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.13 2005/06/15 12:27:20 joerg 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>
84 #include <sys/dkstat.h>
85 #include <sys/socket.h>
86 #include <sys/fcntl.h>
87 #include <sys/thread2.h>
91 #include <sys/vnode.h>
94 #include <i386/isa/intr_machdep.h>
98 #include <net/ifq_var.h>
103 #include <net/ppp/if_ppp.h>
104 #include <net/ppp/if_pppvar.h>
106 static int pppopen (dev_t dev, struct tty *tp);
107 static int pppclose (struct tty *tp, int flag);
108 static int pppread (struct tty *tp, struct uio *uio, int flag);
109 static int pppwrite (struct tty *tp, struct uio *uio, int flag);
110 static int ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
111 int flag, struct thread *);
112 static int pppinput (int c, struct tty *tp);
113 static int pppstart (struct tty *tp);
115 static u_short pppfcs (u_short fcs, u_char *cp, int len);
116 static void pppasyncstart (struct ppp_softc *);
117 static void pppasyncctlp (struct ppp_softc *);
118 static void pppasyncrelinq (struct ppp_softc *);
119 static void pppasyncsetmtu (struct ppp_softc *);
120 static void ppp_timeout (void *);
121 static void pppgetm (struct ppp_softc *sc);
122 static void ppplogchar (struct ppp_softc *, int);
124 /* XXX called from if_ppp.c - layering violation */
125 void pppasyncattach (void *);
128 * Some useful mbuf macros not in mbuf.h.
130 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
132 #define M_DATASTART(m) \
133 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
134 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
136 #define M_DATASIZE(m) \
137 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
138 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
141 * Does c need to be escaped?
143 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
146 * Procedures for using an async tty interface for PPP.
149 /* This is a FreeBSD-2.X kernel. */
150 #define CCOUNT(q) ((q)->c_cc)
151 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
152 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
155 * Define the PPP line discipline.
158 static struct linesw pppdisc = {
159 pppopen, pppclose, pppread, pppwrite,
160 ppptioctl, pppinput, pppstart, ttymodem,
165 pppasyncattach(dummy)
168 /* register line discipline */
169 linesw[PPPDISC] = pppdisc;
173 * Line specific open routine for async tty devices.
174 * Attach the given tty to the first available ppp unit.
175 * Called from device open routine or ttioctl() at >= splsofttty()
179 pppopen(dev_t dev, struct tty *tp)
181 struct thread *td = curthread; /* XXX */
182 struct ppp_softc *sc;
185 if ((error = suser(td)) != 0)
190 if (tp->t_line == PPPDISC) {
191 sc = (struct ppp_softc *) tp->t_sc;
192 if (sc != NULL && sc->sc_devp == (void *) tp) {
198 if ((sc = pppalloc(td)) == NULL) {
204 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
208 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
209 sc->sc_asyncmap[0] = 0xffffffff;
210 sc->sc_asyncmap[3] = 0x60000000;
211 sc->sc_rasyncmap = 0;
212 sc->sc_devp = (void *) tp;
213 sc->sc_start = pppasyncstart;
214 sc->sc_ctlp = pppasyncctlp;
215 sc->sc_relinq = pppasyncrelinq;
216 sc->sc_setmtu = pppasyncsetmtu;
219 sc->sc_if.if_flags |= IFF_RUNNING;
220 getmicrotime(&sc->sc_if.if_lastchange);
221 sc->sc_if.if_baudrate = tp->t_ospeed;
223 tp->t_sc = (caddr_t) sc;
224 ttyflush(tp, FREAD | FWRITE);
227 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
228 * allocation helps avoid the need for select and/or FIONREAD.
229 * We also pass 1 byte tokens through t_canq...
231 clist_alloc_cblocks(&tp->t_canq, 1, 1);
232 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
233 sc->sc_if.if_mtu + PPP_HIWAT);
234 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
242 * Line specific close routine, called from device close routine
243 * and from ttioctl at >= splsofttty().
244 * Detach the tty from the ppp unit.
245 * Mimics part of ttyclose().
252 struct ppp_softc *sc;
255 ttyflush(tp, FREAD | FWRITE);
256 clist_free_cblocks(&tp->t_canq);
257 clist_free_cblocks(&tp->t_outq);
259 sc = (struct ppp_softc *) tp->t_sc;
262 if (tp == (struct tty *) sc->sc_devp) {
272 * Relinquish the interface unit to another device.
276 struct ppp_softc *sc;
281 m_freem(sc->sc_outm);
288 if (sc->sc_flags & SC_TIMEOUT) {
289 callout_stop(&sc->sc_timeout);
290 sc->sc_flags &= ~SC_TIMEOUT;
297 * This gets called from the upper layer to notify a mtu change
301 struct ppp_softc *sc;
303 struct tty *tp = (struct tty *) sc->sc_devp;
307 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
308 sc->sc_if.if_mtu + PPP_HIWAT);
313 * Line specific (tty) read routine.
314 * called at zero spl from the device driver in the response to user-level
315 * reads on the tty file descriptor (ie: pppd).
318 pppread(tp, uio, flag)
323 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
330 * Loop waiting for input, checking that nothing disasterous
331 * happens in the meantime.
335 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
339 if (sc->sc_inq.ifq_head != NULL)
341 if ((tp->t_state & TS_CONNECTED) == 0) {
343 return 0; /* end of file */
345 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
347 return (EWOULDBLOCK);
349 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
356 /* Pull place-holder byte out of canonical queue */
359 /* Get the packet from the input queue */
360 IF_DEQUEUE(&sc->sc_inq, m0);
363 for (m = m0; m && uio->uio_resid; m = m->m_next)
364 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
371 * Line specific (tty) write routine.
372 * called at zero spl from the device driver in the response to user-level
373 * writes on the tty file descriptor (ie: pppd).
376 pppwrite(tp, uio, flag)
381 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
382 struct mbuf *m, *m0, **mp;
386 if ((tp->t_state & TS_CONNECTED) == 0)
387 return 0; /* wrote 0 bytes */
388 if (tp->t_line != PPPDISC)
390 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
392 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
393 uio->uio_resid < PPP_HDRLEN)
397 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
398 MGET(m, MB_WAIT, MT_DATA);
399 if ((*mp = m) == NULL) {
405 if (uio->uio_resid >= MCLBYTES / 2)
406 MCLGET(m, MB_DONTWAIT);
407 len = M_TRAILINGSPACE(m);
408 if (len > uio->uio_resid)
409 len = uio->uio_resid;
410 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
417 dst.sa_family = AF_UNSPEC;
418 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
419 m0->m_data += PPP_HDRLEN;
420 m0->m_len -= PPP_HDRLEN;
422 /* call the upper layer to "transmit" it... */
423 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
429 * Line specific (tty) ioctl routine.
430 * This discipline requires that tty device drivers call
431 * the line specific l_ioctl routine from their ioctl routines.
435 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
437 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
440 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
445 case PPPIOCSASYNCMAP:
446 if ((error = suser(td)) != 0)
448 sc->sc_asyncmap[0] = *(u_int *)data;
451 case PPPIOCGASYNCMAP:
452 *(u_int *)data = sc->sc_asyncmap[0];
455 case PPPIOCSRASYNCMAP:
456 if ((error = suser(td)) != 0)
458 sc->sc_rasyncmap = *(u_int *)data;
461 case PPPIOCGRASYNCMAP:
462 *(u_int *)data = sc->sc_rasyncmap;
465 case PPPIOCSXASYNCMAP:
466 if ((error = suser(td)) != 0)
469 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
470 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
471 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
472 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
476 case PPPIOCGXASYNCMAP:
477 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
481 error = pppioctl(sc, cmd, data, flag, td);
482 if (error == 0 && cmd == PPPIOCSMRU)
490 * FCS lookup table as calculated by genfcstab.
492 static u_short fcstab[256] = {
493 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
494 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
495 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
496 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
497 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
498 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
499 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
500 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
501 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
502 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
503 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
504 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
505 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
506 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
507 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
508 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
509 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
510 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
511 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
512 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
513 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
514 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
515 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
516 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
517 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
518 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
519 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
520 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
521 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
522 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
523 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
524 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
528 * Calculate a new FCS given the current FCS and the new data.
531 pppfcs(u_short fcs, u_char *cp, int len)
534 fcs = PPP_FCS(fcs, *cp++);
539 * This gets called at splsoftnet from if_ppp.c at various times
540 * when there is data ready to be sent.
544 struct ppp_softc *sc;
546 struct tty *tp = (struct tty *) sc->sc_devp;
549 u_char *start, *stop, *cp;
550 int n, ndone, done, idle;
553 /* XXX assumes atomic access to *tp although we're not at spltty(). */
554 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
556 * See if we have an existing packet partly sent.
557 * If not, get a new packet and start sending it.
562 * Get another packet to be sent.
571 * The extra PPP_FLAG will start up a new packet, and thus
572 * will flush any accumulated garbage. We do this whenever
573 * the line may have been idle for some time.
576 if (CCOUNT(&tp->t_outq) == 0) {
577 ++sc->sc_stats.ppp_obytes;
578 (void) putc(PPP_FLAG, &tp->t_outq);
581 /* Calculate the FCS for the first mbuf's worth. */
582 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
583 getmicrotime(&sc->sc_if.if_lastchange);
587 start = mtod(m, u_char *);
592 * Find out how many bytes in the string we can
593 * handle without doing something special.
595 for (cp = start; cp < stop; cp++)
600 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
601 ndone = n - b_to_q(start, n, &tp->t_outq);
604 sc->sc_stats.ppp_obytes += ndone;
607 break; /* packet doesn't fit */
610 * If there are characters left in the mbuf,
611 * the first one must be special.
612 * Put it out in a different form.
616 if (putc(PPP_ESCAPE, &tp->t_outq)) {
620 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
621 (void) unputc(&tp->t_outq);
626 sc->sc_stats.ppp_obytes += 2;
633 * If we didn't empty this mbuf, remember where we're up to.
634 * If we emptied the last mbuf, try to add the FCS and closing
635 * flag, and if we can't, leave sc_outm pointing to m, but with
636 * m->m_len == 0, to remind us to output the FCS and flag later.
639 if (done && m->m_next == NULL) {
645 * We may have to escape the bytes in the FCS.
648 c = ~sc->sc_outfcs & 0xFF;
651 *p++ = c ^ PPP_TRANS;
654 c = (~sc->sc_outfcs >> 8) & 0xFF;
657 *p++ = c ^ PPP_TRANS;
663 * Try to output the FCS and flag. If the bytes
664 * don't all fit, back out.
667 for (q = endseq; q < p; ++q)
668 if (putc(*q, &tp->t_outq)) {
670 for (; q > endseq; --q)
676 sc->sc_stats.ppp_obytes += q - endseq;
680 /* remember where we got to */
686 /* Finished with this mbuf; free it and move on. */
689 /* Finished a packet */
692 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
696 * If m == NULL, we have finished a packet.
697 * If m != NULL, we've either done as much work this time
698 * as we need to, or else we've filled up the output queue.
705 /* Call pppstart to start output again if necessary. */
710 * This timeout is needed for operation on a pseudo-tty,
711 * because the pty code doesn't call pppstart after it has
712 * drained the t_outq.
714 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
715 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
716 sc->sc_flags |= SC_TIMEOUT;
723 * This gets called when a received packet is placed on
724 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
728 struct ppp_softc *sc;
732 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
734 tp = (struct tty *) sc->sc_devp;
735 putc(0, &tp->t_canq);
741 * Start output on async tty interface. If the transmit queue
742 * has drained sufficiently, arrange for pppasyncstart to be
743 * called later at splsoftnet.
744 * Called at spltty or higher.
750 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
753 * Call output process whether or not there is any output.
754 * We are being called in lieu of ttstart and must do what it would.
756 if (tp->t_oproc != NULL)
760 * If ALTQ is enabled, don't invoke NETISR_PPP.
761 * pppintr() could loop without doing anything useful
762 * under rate-limiting.
764 if (ifq_is_enabled(&sc->sc_if.if_snd))
768 * If the transmit queue has drained and the tty has not hung up
769 * or been disconnected from the ppp unit, then tell if_ppp.c that
770 * we need more output.
772 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
773 && !((tp->t_state & TS_CONNECTED) == 0)
774 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
782 * Timeout routine - try to start some more output.
788 struct ppp_softc *sc = (struct ppp_softc *) x;
789 struct tty *tp = (struct tty *) sc->sc_devp;
792 sc->sc_flags &= ~SC_TIMEOUT;
798 * Allocate enough mbuf to handle current MRU.
802 struct ppp_softc *sc;
804 struct mbuf *m, **mp;
808 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
809 if ((m = *mp) == NULL) {
810 MGETHDR(m, MB_DONTWAIT, MT_DATA);
814 MCLGET(m, MB_DONTWAIT);
816 len -= M_DATASIZE(m);
822 * tty interface receiver interrupt.
824 static unsigned paritytab[8] = {
825 0x96696996, 0x69969669, 0x69969669, 0x96696996,
826 0x69969669, 0x96696996, 0x96696996, 0x69969669
830 * Called when character is available from device driver.
831 * Only guaranteed to be at splsofttty() or spltty()
832 * This is safe to be called while the upper half's netisr is preempted.
839 struct ppp_softc *sc;
843 sc = (struct ppp_softc *) tp->t_sc;
844 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
848 ++sc->sc_stats.ppp_ibytes;
850 if ((tp->t_state & TS_CONNECTED) == 0) {
851 if (sc->sc_flags & SC_DEBUG)
852 printf("%s: no carrier\n", sc->sc_if.if_xname);
856 if (c & TTY_ERRORMASK) {
857 /* framing error or overrun on this char - abort packet */
858 if (sc->sc_flags & SC_DEBUG)
859 printf("%s: line error %x\n", sc->sc_if.if_xname,
867 * Handle software flow control of output.
869 if (tp->t_iflag & IXON) {
870 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
871 if ((tp->t_state & TS_TTSTOP) == 0) {
872 tp->t_state |= TS_TTSTOP;
877 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
878 tp->t_state &= ~TS_TTSTOP;
879 if (tp->t_oproc != NULL)
887 sc->sc_flags |= SC_RCV_B7_1;
889 sc->sc_flags |= SC_RCV_B7_0;
890 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
891 sc->sc_flags |= SC_RCV_ODDP;
893 sc->sc_flags |= SC_RCV_EVNP;
896 if (sc->sc_flags & SC_LOG_RAWIN)
903 if (sc->sc_rawin_count > 0)
907 * If SC_ESCAPED is set, then we've seen the packet
908 * abort sequence "}~".
910 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
911 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
913 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
914 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
915 if (sc->sc_flags & SC_DEBUG)
916 printf("%s: bad fcs %x, pkt len %d\n",
917 sc->sc_if.if_xname, sc->sc_fcs, ilen);
918 sc->sc_if.if_ierrors++;
919 sc->sc_stats.ppp_ierrors++;
921 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
926 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
928 if (sc->sc_flags & SC_DEBUG)
929 printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
931 sc->sc_if.if_ierrors++;
932 sc->sc_stats.ppp_ierrors++;
933 sc->sc_flags |= SC_PKTLOST;
940 * Remove FCS trailer. Somewhat painful...
943 if (--sc->sc_mc->m_len == 0) {
944 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
950 /* excise this mbuf chain */
952 sc->sc_m = sc->sc_mc->m_next;
953 sc->sc_mc->m_next = NULL;
955 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
956 if (sc->sc_flags & SC_PKTLOST) {
958 sc->sc_flags &= ~SC_PKTLOST;
966 if (sc->sc_flags & SC_FLUSH) {
967 if (sc->sc_flags & SC_LOG_FLUSH)
972 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
976 if (sc->sc_flags & SC_ESCAPED) {
977 sc->sc_flags &= ~SC_ESCAPED;
979 } else if (c == PPP_ESCAPE) {
980 sc->sc_flags |= SC_ESCAPED;
987 * Initialize buffer on first octet received.
988 * First octet could be address or protocol (when compressing
990 * Second octet is control.
991 * Third octet is first or second (when compressing protocol)
993 * Fourth octet is second octet of protocol.
995 if (sc->sc_ilen == 0) {
996 /* reset the first input mbuf */
997 if (sc->sc_m == NULL) {
999 if (sc->sc_m == NULL) {
1000 if (sc->sc_flags & SC_DEBUG)
1001 printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1007 m->m_data = M_DATASTART(sc->sc_m);
1009 sc->sc_mp = mtod(m, char *);
1010 sc->sc_fcs = PPP_INITFCS;
1011 if (c != PPP_ALLSTATIONS) {
1012 if (sc->sc_flags & SC_REJ_COMP_AC) {
1013 if (sc->sc_flags & SC_DEBUG)
1014 printf("%s: garbage received: 0x%x (need 0xFF)\n",
1015 sc->sc_if.if_xname, c);
1018 *sc->sc_mp++ = PPP_ALLSTATIONS;
1019 *sc->sc_mp++ = PPP_UI;
1024 if (sc->sc_ilen == 1 && c != PPP_UI) {
1025 if (sc->sc_flags & SC_DEBUG)
1026 printf("%s: missing UI (0x3), got 0x%x\n",
1027 sc->sc_if.if_xname, c);
1030 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1031 /* a compressed protocol */
1036 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1037 if (sc->sc_flags & SC_DEBUG)
1038 printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1039 (sc->sc_mp[-1] << 8) + c);
1043 /* packet beyond configured mru? */
1044 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1045 if (sc->sc_flags & SC_DEBUG)
1046 printf("%s: packet too big\n", sc->sc_if.if_xname);
1050 /* is this mbuf full? */
1052 if (M_TRAILINGSPACE(m) <= 0) {
1053 if (m->m_next == NULL) {
1055 if (m->m_next == NULL) {
1056 if (sc->sc_flags & SC_DEBUG)
1057 printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1061 sc->sc_mc = m = m->m_next;
1063 m->m_data = M_DATASTART(m);
1064 sc->sc_mp = mtod(m, char *);
1069 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1073 if (!(sc->sc_flags & SC_FLUSH)) {
1075 sc->sc_if.if_ierrors++;
1076 sc->sc_stats.ppp_ierrors++;
1077 sc->sc_flags |= SC_FLUSH;
1079 if (sc->sc_flags & SC_LOG_FLUSH)
1085 #define MAX_DUMP_BYTES 128
1089 struct ppp_softc *sc;
1093 sc->sc_rawin[sc->sc_rawin_count++] = c;
1094 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1095 || (c < 0 && sc->sc_rawin_count > 0)) {
1096 printf("%s input: %*D", sc->sc_if.if_xname,
1097 sc->sc_rawin_count, sc->sc_rawin, " ");
1098 sc->sc_rawin_count = 0;