2 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
5 * Copyright (c) 1989 Carnegie Mellon University.
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by Carnegie Mellon University. The name of the
14 * University may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 * Carnegie Mellon University
23 * Pittsburgh, PA 15213
28 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
30 * Copyright (c) 1987 Regents of the University of California.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms are permitted
34 * provided that the above copyright notice and this paragraph are
35 * duplicated in all such forms and that any documentation,
36 * advertising materials, and other materials related to such
37 * distribution and use acknowledge that the software was developed
38 * by the University of California, Berkeley. The name of the
39 * University may not be used to endorse or promote products derived
40 * from this software without specific prior written permission.
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
42 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
43 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
45 * Serial Line interface
48 * Center for Seismic Studies
49 * 1300 N 17th Street, Suite 1450
50 * Arlington, Virginia 22209
55 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
56 * Converted to 4.3BSD Beta by Chris Torek.
57 * Other changes made at Berkeley, based in part on code by Kirk Smith.
59 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
60 * Added VJ tcp header compression; more unified ioctls
62 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
63 * Cleaned up a lot of the mbuf-related code to fix bugs that
64 * caused system crashes and packet corruption. Changed pppstart
65 * so that it doesn't just give up with a "collision" if the whole
66 * packet doesn't fit in the output ring buffer.
68 * Added priority queueing for interactive IP packets, following
69 * the model of if_sl.c, plus hooks for bpf.
70 * Paul Mackerras (paulus@cs.anu.edu.au).
73 /* $FreeBSD: src/sys/net/ppp_tty.c,v 1.43.2.1 2002/02/13 00:43:11 dillon Exp $ */
74 /* $DragonFly: src/sys/net/ppp_layer/ppp_tty.c,v 1.25 2008/05/14 11:59:23 sephe Exp $ */
76 #include "opt_ppp.h" /* XXX for ppp_defs.h */
78 #define VJC /* XXX for ppp_defs.h */
80 #include <sys/param.h>
81 #include <sys/systm.h>
85 #include <sys/dkstat.h>
86 #include <sys/socket.h>
87 #include <sys/fcntl.h>
88 #include <sys/thread2.h>
92 #include <sys/vnode.h>
95 #include <net/ifq_var.h>
100 #include <net/ppp/if_ppp.h>
101 #include <net/ppp/if_pppvar.h>
103 static int pppopen (cdev_t dev, struct tty *tp);
104 static int pppclose (struct tty *tp, int flag);
105 static int pppread (struct tty *tp, struct uio *uio, int flag);
106 static int pppwrite (struct tty *tp, struct uio *uio, int flag);
107 static int ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
108 int flag, struct ucred *);
109 static int pppinput (int c, struct tty *tp);
110 static int pppstart (struct tty *tp);
112 static u_short pppfcs (u_short fcs, u_char *cp, int len);
113 static void pppasyncstart (struct ppp_softc *);
114 static void pppasyncctlp (struct ppp_softc *);
115 static void pppasyncrelinq (struct ppp_softc *);
116 static void pppasyncsetmtu (struct ppp_softc *);
117 static void ppp_timeout (void *);
118 static void pppgetm (struct ppp_softc *sc);
119 static void ppplogchar (struct ppp_softc *, int);
121 /* XXX called from if_ppp.c - layering violation */
122 void pppasyncattach (void *);
125 * Some useful mbuf macros not in mbuf.h.
127 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
129 #define M_DATASTART(m) \
130 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
131 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
133 #define M_DATASIZE(m) \
134 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
135 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
138 * Does c need to be escaped?
140 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
143 * Procedures for using an async tty interface for PPP.
146 /* This is a FreeBSD-2.X kernel. */
147 #define CCOUNT(q) ((q)->c_cc)
148 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
149 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
152 * Define the PPP line discipline.
155 static struct linesw pppdisc = {
156 pppopen, pppclose, pppread, pppwrite,
157 ppptioctl, pppinput, pppstart, ttymodem,
162 pppasyncattach(void *dummy)
164 /* register line discipline */
165 linesw[PPPDISC] = pppdisc;
169 * Line specific open routine for async tty devices.
170 * Attach the given tty to the first available ppp unit.
171 * Called from device open routine or ttioctl() at >= splsofttty()
175 pppopen(cdev_t dev, struct tty *tp)
177 struct thread *td = curthread; /* XXX */
178 struct ppp_softc *sc;
181 if ((error = priv_check(td, PRIV_ROOT)) != 0)
186 if (tp->t_line == PPPDISC) {
187 sc = (struct ppp_softc *) tp->t_sc;
188 if (sc != NULL && sc->sc_devp == (void *) tp) {
194 if ((sc = pppalloc(td)) == NULL) {
200 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
204 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
205 sc->sc_asyncmap[0] = 0xffffffff;
206 sc->sc_asyncmap[3] = 0x60000000;
207 sc->sc_rasyncmap = 0;
208 sc->sc_devp = (void *) tp;
209 sc->sc_start = pppasyncstart;
210 sc->sc_ctlp = pppasyncctlp;
211 sc->sc_relinq = pppasyncrelinq;
212 sc->sc_setmtu = pppasyncsetmtu;
215 sc->sc_if.if_flags |= IFF_RUNNING;
216 getmicrotime(&sc->sc_if.if_lastchange);
217 sc->sc_if.if_baudrate = tp->t_ospeed;
219 tp->t_sc = (caddr_t) sc;
220 ttyflush(tp, FREAD | FWRITE);
223 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
224 * allocation helps avoid the need for select and/or FIONREAD.
225 * We also pass 1 byte tokens through t_canq...
227 clist_alloc_cblocks(&tp->t_canq, 1, 1);
228 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
229 sc->sc_if.if_mtu + PPP_HIWAT);
230 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
238 * Line specific close routine, called from device close routine
239 * and from ttioctl at >= splsofttty().
240 * Detach the tty from the ppp unit.
241 * Mimics part of ttyclose().
244 pppclose(struct tty *tp, int flag)
246 struct ppp_softc *sc;
249 ttyflush(tp, FREAD | FWRITE);
250 clist_free_cblocks(&tp->t_canq);
251 clist_free_cblocks(&tp->t_outq);
253 sc = (struct ppp_softc *) tp->t_sc;
256 if (tp == (struct tty *) sc->sc_devp) {
266 * Relinquish the interface unit to another device.
269 pppasyncrelinq(struct ppp_softc *sc)
274 m_freem(sc->sc_outm);
281 if (sc->sc_flags & SC_TIMEOUT) {
282 callout_stop(&sc->sc_timeout);
283 sc->sc_flags &= ~SC_TIMEOUT;
290 * This gets called from the upper layer to notify a mtu change
293 pppasyncsetmtu(struct ppp_softc *sc)
295 struct tty *tp = (struct tty *) sc->sc_devp;
299 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
300 sc->sc_if.if_mtu + PPP_HIWAT);
305 * Line specific (tty) read routine.
306 * called at zero spl from the device driver in the response to user-level
307 * reads on the tty file descriptor (ie: pppd).
310 pppread(struct tty *tp, struct uio *uio, int flag)
312 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
319 * Loop waiting for input, checking that nothing disasterous
320 * happens in the meantime.
324 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
328 if (sc->sc_inq.ifq_head != NULL)
330 if ((tp->t_state & TS_CONNECTED) == 0) {
332 return 0; /* end of file */
334 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
336 return (EWOULDBLOCK);
338 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
345 /* Pull place-holder byte out of canonical queue */
346 clist_getc(&tp->t_canq);
348 /* Get the packet from the input queue */
349 IF_DEQUEUE(&sc->sc_inq, m0);
352 for (m = m0; m && uio->uio_resid; m = m->m_next)
353 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
360 * Line specific (tty) write routine.
361 * called at zero spl from the device driver in the response to user-level
362 * writes on the tty file descriptor (ie: pppd).
365 pppwrite(struct tty *tp, struct uio *uio, int flag)
367 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
368 struct mbuf *m, *m0, **mp;
372 if ((tp->t_state & TS_CONNECTED) == 0)
373 return 0; /* wrote 0 bytes */
374 if (tp->t_line != PPPDISC)
376 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
378 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
379 uio->uio_resid < PPP_HDRLEN)
383 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
385 MGETHDR(m, MB_WAIT, MT_DATA);
386 m->m_pkthdr.len = uio->uio_resid - PPP_HDRLEN;
387 m->m_pkthdr.rcvif = NULL;
389 MGET(m, MB_WAIT, MT_DATA);
391 if ((*mp = m) == NULL) {
397 if (uio->uio_resid >= MCLBYTES / 2)
398 MCLGET(m, MB_DONTWAIT);
399 len = M_TRAILINGSPACE(m);
400 if (len > uio->uio_resid)
401 len = uio->uio_resid;
402 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
409 dst.sa_family = AF_UNSPEC;
410 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
411 m0->m_data += PPP_HDRLEN;
412 m0->m_len -= PPP_HDRLEN;
414 /* call the upper layer to "transmit" it... */
415 error = pppoutput(&sc->sc_if, m0, &dst, NULL);
421 * Line specific (tty) ioctl routine.
422 * This discipline requires that tty device drivers call
423 * the line specific l_ioctl routine from their ioctl routines.
427 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cr)
429 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
432 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
437 case PPPIOCSASYNCMAP:
438 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
440 sc->sc_asyncmap[0] = *(u_int *)data;
443 case PPPIOCGASYNCMAP:
444 *(u_int *)data = sc->sc_asyncmap[0];
447 case PPPIOCSRASYNCMAP:
448 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
450 sc->sc_rasyncmap = *(u_int *)data;
453 case PPPIOCGRASYNCMAP:
454 *(u_int *)data = sc->sc_rasyncmap;
457 case PPPIOCSXASYNCMAP:
458 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
461 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
462 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
463 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
464 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
468 case PPPIOCGXASYNCMAP:
469 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
473 error = pppioctl(sc, cmd, data, flag, cr);
474 if (error == 0 && cmd == PPPIOCSMRU)
482 * FCS lookup table as calculated by genfcstab.
484 static u_short fcstab[256] = {
485 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
486 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
487 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
488 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
489 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
490 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
491 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
492 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
493 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
494 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
495 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
496 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
497 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
498 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
499 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
500 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
501 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
502 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
503 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
504 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
505 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
506 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
507 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
508 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
509 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
510 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
511 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
512 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
513 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
514 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
515 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
516 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
520 * Calculate a new FCS given the current FCS and the new data.
523 pppfcs(u_short fcs, u_char *cp, int len)
526 fcs = PPP_FCS(fcs, *cp++);
531 * This gets called at splsoftnet from if_ppp.c at various times
532 * when there is data ready to be sent.
535 pppasyncstart(struct ppp_softc *sc)
537 struct tty *tp = (struct tty *) sc->sc_devp;
540 u_char *start, *stop, *cp;
541 int n, ndone, done, idle;
544 /* XXX assumes atomic access to *tp although we're not at spltty(). */
545 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
547 * See if we have an existing packet partly sent.
548 * If not, get a new packet and start sending it.
553 * Get another packet to be sent.
562 * The extra PPP_FLAG will start up a new packet, and thus
563 * will flush any accumulated garbage. We do this whenever
564 * the line may have been idle for some time.
567 if (CCOUNT(&tp->t_outq) == 0) {
568 ++sc->sc_stats.ppp_obytes;
569 clist_putc(PPP_FLAG, &tp->t_outq);
572 /* Calculate the FCS for the first mbuf's worth. */
573 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
574 getmicrotime(&sc->sc_if.if_lastchange);
578 start = mtod(m, u_char *);
583 * Find out how many bytes in the string we can
584 * handle without doing something special.
586 for (cp = start; cp < stop; cp++)
591 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
592 ndone = n - b_to_q(start, n, &tp->t_outq);
595 sc->sc_stats.ppp_obytes += ndone;
598 break; /* packet doesn't fit */
601 * If there are characters left in the mbuf,
602 * the first one must be special.
603 * Put it out in a different form.
607 if (clist_putc(PPP_ESCAPE, &tp->t_outq)) {
611 if (clist_putc(*start ^ PPP_TRANS, &tp->t_outq)) {
612 clist_unputc(&tp->t_outq);
617 sc->sc_stats.ppp_obytes += 2;
624 * If we didn't empty this mbuf, remember where we're up to.
625 * If we emptied the last mbuf, try to add the FCS and closing
626 * flag, and if we can't, leave sc_outm pointing to m, but with
627 * m->m_len == 0, to remind us to output the FCS and flag later.
630 if (done && m->m_next == NULL) {
636 * We may have to escape the bytes in the FCS.
639 c = ~sc->sc_outfcs & 0xFF;
642 *p++ = c ^ PPP_TRANS;
645 c = (~sc->sc_outfcs >> 8) & 0xFF;
648 *p++ = c ^ PPP_TRANS;
654 * Try to output the FCS and flag. If the bytes
655 * don't all fit, back out.
658 for (q = endseq; q < p; ++q)
659 if (clist_putc(*q, &tp->t_outq)) {
661 for (; q > endseq; --q)
662 clist_unputc(&tp->t_outq);
667 sc->sc_stats.ppp_obytes += q - endseq;
671 /* remember where we got to */
677 /* Finished with this mbuf; free it and move on. */
680 /* Finished a packet */
683 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
687 * If m == NULL, we have finished a packet.
688 * If m != NULL, we've either done as much work this time
689 * as we need to, or else we've filled up the output queue.
696 /* Call pppstart to start output again if necessary. */
701 * This timeout is needed for operation on a pseudo-tty,
702 * because the pty code doesn't call pppstart after it has
703 * drained the t_outq.
705 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
706 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
707 sc->sc_flags |= SC_TIMEOUT;
714 * This gets called when a received packet is placed on
715 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
718 pppasyncctlp(struct ppp_softc *sc)
722 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
724 tp = (struct tty *) sc->sc_devp;
725 clist_putc(0, &tp->t_canq);
731 * Start output on async tty interface. If the transmit queue
732 * has drained sufficiently, arrange for pppasyncstart to be
733 * called later at splsoftnet.
734 * Called at spltty or higher.
737 pppstart(struct tty *tp)
739 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
742 * Call output process whether or not there is any output.
743 * We are being called in lieu of ttstart and must do what it would.
745 if (tp->t_oproc != NULL)
749 * If ALTQ is enabled, don't invoke NETISR_PPP.
750 * pppintr() could loop without doing anything useful
751 * under rate-limiting.
753 if (ifq_is_enabled(&sc->sc_if.if_snd))
757 * If the transmit queue has drained and the tty has not hung up
758 * or been disconnected from the ppp unit, then tell if_ppp.c that
759 * we need more output.
761 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
762 && !((tp->t_state & TS_CONNECTED) == 0)
763 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
771 * Timeout routine - try to start some more output.
776 struct ppp_softc *sc = (struct ppp_softc *) x;
777 struct tty *tp = (struct tty *) sc->sc_devp;
780 sc->sc_flags &= ~SC_TIMEOUT;
786 * Allocate enough mbuf to handle current MRU.
789 pppgetm(struct ppp_softc *sc)
791 struct mbuf *m, **mp;
795 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
796 if ((m = *mp) == NULL) {
797 MGETHDR(m, MB_DONTWAIT, MT_DATA);
801 MCLGET(m, MB_DONTWAIT);
803 len -= M_DATASIZE(m);
809 * tty interface receiver interrupt.
811 static unsigned paritytab[8] = {
812 0x96696996, 0x69969669, 0x69969669, 0x96696996,
813 0x69969669, 0x96696996, 0x96696996, 0x69969669
817 * Called when character is available from device driver.
818 * Only guaranteed to be at splsofttty() or spltty()
819 * This is safe to be called while the upper half's netisr is preempted.
822 pppinput(int c, struct tty *tp)
824 struct ppp_softc *sc;
828 sc = (struct ppp_softc *) tp->t_sc;
829 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
833 ++sc->sc_stats.ppp_ibytes;
835 if ((tp->t_state & TS_CONNECTED) == 0) {
836 if (sc->sc_flags & SC_DEBUG)
837 kprintf("%s: no carrier\n", sc->sc_if.if_xname);
841 if (c & TTY_ERRORMASK) {
842 /* framing error or overrun on this char - abort packet */
843 if (sc->sc_flags & SC_DEBUG)
844 kprintf("%s: line error %x\n", sc->sc_if.if_xname,
852 * Handle software flow control of output.
854 if (tp->t_iflag & IXON) {
855 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
856 if ((tp->t_state & TS_TTSTOP) == 0) {
857 tp->t_state |= TS_TTSTOP;
862 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
863 tp->t_state &= ~TS_TTSTOP;
864 if (tp->t_oproc != NULL)
872 sc->sc_flags |= SC_RCV_B7_1;
874 sc->sc_flags |= SC_RCV_B7_0;
875 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
876 sc->sc_flags |= SC_RCV_ODDP;
878 sc->sc_flags |= SC_RCV_EVNP;
881 if (sc->sc_flags & SC_LOG_RAWIN)
888 if (sc->sc_rawin_count > 0)
892 * If SC_ESCAPED is set, then we've seen the packet
893 * abort sequence "}~".
895 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
896 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
898 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
899 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
900 if (sc->sc_flags & SC_DEBUG)
901 kprintf("%s: bad fcs %x, pkt len %d\n",
902 sc->sc_if.if_xname, sc->sc_fcs, ilen);
903 sc->sc_if.if_ierrors++;
904 sc->sc_stats.ppp_ierrors++;
906 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
911 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
913 if (sc->sc_flags & SC_DEBUG)
914 kprintf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
916 sc->sc_if.if_ierrors++;
917 sc->sc_stats.ppp_ierrors++;
918 sc->sc_flags |= SC_PKTLOST;
925 * Remove FCS trailer. Somewhat painful...
928 if (--sc->sc_mc->m_len == 0) {
929 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
935 /* excise this mbuf chain */
937 sc->sc_m = sc->sc_mc->m_next;
938 sc->sc_mc->m_next = NULL;
940 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
941 if (sc->sc_flags & SC_PKTLOST) {
943 sc->sc_flags &= ~SC_PKTLOST;
951 if (sc->sc_flags & SC_FLUSH) {
952 if (sc->sc_flags & SC_LOG_FLUSH)
957 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
961 if (sc->sc_flags & SC_ESCAPED) {
962 sc->sc_flags &= ~SC_ESCAPED;
964 } else if (c == PPP_ESCAPE) {
965 sc->sc_flags |= SC_ESCAPED;
972 * Initialize buffer on first octet received.
973 * First octet could be address or protocol (when compressing
975 * Second octet is control.
976 * Third octet is first or second (when compressing protocol)
978 * Fourth octet is second octet of protocol.
980 if (sc->sc_ilen == 0) {
981 /* reset the first input mbuf */
982 if (sc->sc_m == NULL) {
984 if (sc->sc_m == NULL) {
985 if (sc->sc_flags & SC_DEBUG)
986 kprintf("%s: no input mbufs!\n", sc->sc_if.if_xname);
992 m->m_data = M_DATASTART(sc->sc_m);
994 sc->sc_mp = mtod(m, char *);
995 sc->sc_fcs = PPP_INITFCS;
996 if (c != PPP_ALLSTATIONS) {
997 if (sc->sc_flags & SC_REJ_COMP_AC) {
998 if (sc->sc_flags & SC_DEBUG)
999 kprintf("%s: garbage received: 0x%x (need 0xFF)\n",
1000 sc->sc_if.if_xname, c);
1003 *sc->sc_mp++ = PPP_ALLSTATIONS;
1004 *sc->sc_mp++ = PPP_UI;
1009 if (sc->sc_ilen == 1 && c != PPP_UI) {
1010 if (sc->sc_flags & SC_DEBUG)
1011 kprintf("%s: missing UI (0x3), got 0x%x\n",
1012 sc->sc_if.if_xname, c);
1015 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1016 /* a compressed protocol */
1021 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1022 if (sc->sc_flags & SC_DEBUG)
1023 kprintf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1024 (sc->sc_mp[-1] << 8) + c);
1028 /* packet beyond configured mru? */
1029 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1030 if (sc->sc_flags & SC_DEBUG)
1031 kprintf("%s: packet too big\n", sc->sc_if.if_xname);
1035 /* is this mbuf full? */
1037 if (M_TRAILINGSPACE(m) <= 0) {
1038 if (m->m_next == NULL) {
1040 if (m->m_next == NULL) {
1041 if (sc->sc_flags & SC_DEBUG)
1042 kprintf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1046 sc->sc_mc = m = m->m_next;
1048 m->m_data = M_DATASTART(m);
1049 sc->sc_mp = mtod(m, char *);
1054 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1058 if (!(sc->sc_flags & SC_FLUSH)) {
1060 sc->sc_if.if_ierrors++;
1061 sc->sc_stats.ppp_ierrors++;
1062 sc->sc_flags |= SC_FLUSH;
1064 if (sc->sc_flags & SC_LOG_FLUSH)
1070 #define MAX_DUMP_BYTES 128
1073 ppplogchar(struct ppp_softc *sc, int c)
1076 sc->sc_rawin[sc->sc_rawin_count++] = c;
1077 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1078 || (c < 0 && sc->sc_rawin_count > 0)) {
1079 kprintf("%s input: %*D", sc->sc_if.if_xname,
1080 sc->sc_rawin_count, sc->sc_rawin, " ");
1081 sc->sc_rawin_count = 0;