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 /* $Id: ppp_tty.c,v 1.7 1997/03/04 03:27:28 paulus Exp $ */
74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
75 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
83 #include <sys/param.h>
84 #include <sys/systm.h>
87 #include <sys/dkstat.h>
88 #include <sys/socket.h>
89 #include <sys/ioctl.h>
92 #include <sys/kernel.h>
94 #include <sys/vnode.h>
97 #include <net/if_types.h>
100 #include <netinet/in.h>
101 #include <netinet/in_systm.h>
102 #include <netinet/ip.h>
103 #include <net/pppcompress.h>
106 #include <net/ppp_defs.h>
107 #include <net/if_ppp.h>
108 #include <net/if_pppvar.h>
110 void pppasyncattach __P((void));
111 int pppopen __P((dev_t dev, struct tty *tp));
112 int pppclose __P((struct tty *tp, int flag));
113 int pppread __P((struct tty *tp, struct uio *uio, int flag));
114 int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
115 int ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
117 int pppinput __P((int c, struct tty *tp));
118 int pppstart __P((struct tty *tp));
120 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
121 static void pppasyncstart __P((struct ppp_softc *));
122 static void pppasyncctlp __P((struct ppp_softc *));
123 static void pppasyncrelinq __P((struct ppp_softc *));
124 static void ppp_timeout __P((void *));
125 static void pppgetm __P((struct ppp_softc *sc));
126 static void pppdumpb __P((u_char *b, int l));
127 static void ppplogchar __P((struct ppp_softc *, int));
130 * Some useful mbuf macros not in mbuf.h.
132 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
134 #define M_DATASTART(m) \
135 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
136 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
138 #define M_DATASIZE(m) \
139 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
140 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
143 * Does c need to be escaped?
145 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
148 * Procedures for using an async tty interface for PPP.
151 /* This is a FreeBSD-2.0 kernel. */
152 #define CCOUNT(q) ((q)->c_cc)
153 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
154 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
157 * Define the PPP line discipline.
160 static struct linesw pppdisc = {
161 pppopen, pppclose, pppread, pppwrite, ppptioctl,
162 pppinput, pppstart, ttymodem
168 linesw[PPPDISC] = pppdisc;
171 TEXT_SET(pseudo_set, pppasyncattach);
174 * Line specific open routine for async tty devices.
175 * Attach the given tty to the first available ppp unit.
176 * Called from device open routine or ttioctl.
182 register struct tty *tp;
184 struct proc *p = curproc; /* XXX */
185 register struct ppp_softc *sc;
188 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
193 if (tp->t_line == PPPDISC) {
194 sc = (struct ppp_softc *) tp->t_sc;
195 if (sc != NULL && sc->sc_devp == (void *) tp) {
201 if ((sc = pppalloc(p->p_pid)) == NULL) {
207 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
211 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
212 sc->sc_asyncmap[0] = 0xffffffff;
213 sc->sc_asyncmap[3] = 0x60000000;
214 sc->sc_rasyncmap = 0;
215 sc->sc_devp = (void *) tp;
216 sc->sc_start = pppasyncstart;
217 sc->sc_ctlp = pppasyncctlp;
218 sc->sc_relinq = pppasyncrelinq;
221 sc->sc_if.if_flags |= IFF_RUNNING;
222 sc->sc_if.if_baudrate = tp->t_ospeed;
224 tp->t_sc = (caddr_t) sc;
225 ttyflush(tp, FREAD | FWRITE);
232 * Line specific close routine, called from device close routine
234 * Detach the tty from the ppp unit.
235 * Mimics part of ttyclose().
242 register struct ppp_softc *sc;
246 ttyflush(tp, FREAD|FWRITE);
248 sc = (struct ppp_softc *) tp->t_sc;
251 if (tp == (struct tty *) sc->sc_devp) {
261 * Relinquish the interface unit to another device.
265 struct ppp_softc *sc;
271 m_freem(sc->sc_outm);
278 if (sc->sc_flags & SC_TIMEOUT) {
279 untimeout(ppp_timeout, (void *) sc);
280 sc->sc_flags &= ~SC_TIMEOUT;
286 * Line specific (tty) read routine.
289 pppread(tp, uio, flag)
290 register struct tty *tp;
294 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
302 * Loop waiting for input, checking that nothing disasterous
303 * happens in the meantime.
307 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
311 if (sc->sc_inq.ifq_head != NULL)
313 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
314 && (tp->t_state & TS_ISOPEN)) {
316 return 0; /* end of file */
318 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
320 return (EWOULDBLOCK);
322 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, "ttyin", 0);
329 /* Pull place-holder byte out of canonical queue */
332 /* Get the packet from the input queue */
333 IF_DEQUEUE(&sc->sc_inq, m0);
336 for (m = m0; m && uio->uio_resid; m = m->m_next)
337 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
344 * Line specific (tty) write routine.
347 pppwrite(tp, uio, flag)
348 register struct tty *tp;
352 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
353 struct mbuf *m, *m0, **mp;
357 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
358 return 0; /* wrote 0 bytes */
359 if (tp->t_line != PPPDISC)
361 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
363 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
364 uio->uio_resid < PPP_HDRLEN)
366 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
367 MGET(m, M_WAIT, MT_DATA);
368 if ((*mp = m) == NULL) {
373 if (uio->uio_resid >= MCLBYTES / 2)
374 MCLGET(m, M_DONTWAIT);
375 len = M_TRAILINGSPACE(m);
376 if (len > uio->uio_resid)
377 len = uio->uio_resid;
378 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
384 dst.sa_family = AF_UNSPEC;
385 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
386 m0->m_data += PPP_HDRLEN;
387 m0->m_len -= PPP_HDRLEN;
388 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
392 * Line specific (tty) ioctl routine.
393 * This discipline requires that tty device drivers call
394 * the line specific l_ioctl routine from their ioctl routines.
398 ppptioctl(tp, cmd, data, flag, p)
405 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
408 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
413 case PPPIOCSASYNCMAP:
414 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
416 sc->sc_asyncmap[0] = *(u_int *)data;
419 case PPPIOCGASYNCMAP:
420 *(u_int *)data = sc->sc_asyncmap[0];
423 case PPPIOCSRASYNCMAP:
424 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
426 sc->sc_rasyncmap = *(u_int *)data;
429 case PPPIOCGRASYNCMAP:
430 *(u_int *)data = sc->sc_rasyncmap;
433 case PPPIOCSXASYNCMAP:
434 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
437 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
438 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
439 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
440 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
444 case PPPIOCGXASYNCMAP:
445 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
449 error = pppioctl(sc, cmd, data, flag, p);
450 if (error == 0 && cmd == PPPIOCSMRU)
458 * FCS lookup table as calculated by genfcstab.
460 static u_short fcstab[256] = {
461 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
462 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
463 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
464 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
465 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
466 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
467 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
468 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
469 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
470 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
471 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
472 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
473 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
474 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
475 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
476 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
477 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
478 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
479 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
480 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
481 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
482 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
483 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
484 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
485 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
486 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
487 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
488 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
489 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
490 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
491 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
492 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
496 * Calculate a new FCS given the current FCS and the new data.
500 register u_short fcs;
505 fcs = PPP_FCS(fcs, *cp++);
510 * This gets called at splsoftnet from if_ppp.c at various times
511 * when there is data ready to be sent.
515 register struct ppp_softc *sc;
517 register struct tty *tp = (struct tty *) sc->sc_devp;
518 register struct mbuf *m;
520 register u_char *start, *stop, *cp;
521 int n, ndone, done, idle;
526 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
528 * See if we have an existing packet partly sent.
529 * If not, get a new packet and start sending it.
534 * Get another packet to be sent.
543 * The extra PPP_FLAG will start up a new packet, and thus
544 * will flush any accumulated garbage. We do this whenever
545 * the line may have been idle for some time.
547 if (CCOUNT(&tp->t_outq) == 0) {
548 ++sc->sc_stats.ppp_obytes;
549 (void) putc(PPP_FLAG, &tp->t_outq);
552 /* Calculate the FCS for the first mbuf's worth. */
553 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
554 sc->sc_if.if_lastchange = time;
558 start = mtod(m, u_char *);
563 * Find out how many bytes in the string we can
564 * handle without doing something special.
566 for (cp = start; cp < stop; cp++)
571 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
572 ndone = n - b_to_q(start, n, &tp->t_outq);
575 sc->sc_stats.ppp_obytes += ndone;
578 break; /* packet doesn't fit */
581 * If there are characters left in the mbuf,
582 * the first one must be special.
583 * Put it out in a different form.
587 if (putc(PPP_ESCAPE, &tp->t_outq))
589 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
590 (void) unputc(&tp->t_outq);
595 sc->sc_stats.ppp_obytes += 2;
602 * If we didn't empty this mbuf, remember where we're up to.
603 * If we emptied the last mbuf, try to add the FCS and closing
604 * flag, and if we can't, leave sc_outm pointing to m, but with
605 * m->m_len == 0, to remind us to output the FCS and flag later.
608 if (done && m->m_next == NULL) {
614 * We may have to escape the bytes in the FCS.
617 c = ~sc->sc_outfcs & 0xFF;
620 *p++ = c ^ PPP_TRANS;
623 c = (~sc->sc_outfcs >> 8) & 0xFF;
626 *p++ = c ^ PPP_TRANS;
632 * Try to output the FCS and flag. If the bytes
633 * don't all fit, back out.
636 for (q = endseq; q < p; ++q)
637 if (putc(*q, &tp->t_outq)) {
639 for (; q > endseq; --q)
645 sc->sc_stats.ppp_obytes += q - endseq;
649 /* remember where we got to */
655 /* Finished with this mbuf; free it and move on. */
659 /* Finished a packet */
662 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
666 * If m == NULL, we have finished a packet.
667 * If m != NULL, we've either done as much work this time
668 * as we need to, or else we've filled up the output queue.
675 /* Call pppstart to start output again if necessary. */
680 * This timeout is needed for operation on a pseudo-tty,
681 * because the pty code doesn't call pppstart after it has
682 * drained the t_outq.
684 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
685 timeout(ppp_timeout, (void *) sc, 1);
686 sc->sc_flags |= SC_TIMEOUT;
693 * This gets called when a received packet is placed on
694 * the inq, at splsoftnet.
698 struct ppp_softc *sc;
703 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
705 tp = (struct tty *) sc->sc_devp;
706 putc(0, &tp->t_canq);
712 * Start output on async tty interface. If the transmit queue
713 * has drained sufficiently, arrange for pppasyncstart to be
714 * called later at splsoftnet.
715 * Called at spltty or higher.
719 register struct tty *tp;
721 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
724 * If there is stuff in the output queue, send it now.
725 * We are being called in lieu of ttstart and must do what it would.
727 if (tp->t_oproc != NULL)
731 * If the transmit queue has drained and the tty has not hung up
732 * or been disconnected from the ppp unit, then tell if_ppp.c that
733 * we need more output.
735 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
736 && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
737 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
745 * Timeout routine - try to start some more output.
751 struct ppp_softc *sc = (struct ppp_softc *) x;
752 struct tty *tp = (struct tty *) sc->sc_devp;
756 sc->sc_flags &= ~SC_TIMEOUT;
762 * Allocate enough mbuf to handle current MRU.
766 register struct ppp_softc *sc;
768 struct mbuf *m, **mp;
772 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
773 if ((m = *mp) == NULL) {
774 MGETHDR(m, M_DONTWAIT, MT_DATA);
778 MCLGET(m, M_DONTWAIT);
780 len -= M_DATASIZE(m);
786 * tty interface receiver interrupt.
788 static unsigned paritytab[8] = {
789 0x96696996, 0x69969669, 0x69969669, 0x96696996,
790 0x69969669, 0x96696996, 0x96696996, 0x69969669
796 register struct tty *tp;
798 register struct ppp_softc *sc;
802 sc = (struct ppp_softc *) tp->t_sc;
803 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
807 ++sc->sc_stats.ppp_ibytes;
810 /* framing error or overrun on this char - abort packet */
811 if (sc->sc_flags & SC_DEBUG)
812 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
819 * Handle software flow control of output.
821 if (tp->t_iflag & IXON) {
822 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
823 if ((tp->t_state & TS_TTSTOP) == 0) {
824 tp->t_state |= TS_TTSTOP;
825 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
829 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
830 tp->t_state &= ~TS_TTSTOP;
831 if (tp->t_oproc != NULL)
839 sc->sc_flags |= SC_RCV_B7_1;
841 sc->sc_flags |= SC_RCV_B7_0;
842 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
843 sc->sc_flags |= SC_RCV_ODDP;
845 sc->sc_flags |= SC_RCV_EVNP;
848 if (sc->sc_flags & SC_LOG_RAWIN)
855 if (sc->sc_rawin_count > 0)
859 * If SC_ESCAPED is set, then we've seen the packet
860 * abort sequence "}~".
862 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
863 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
865 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
866 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
867 if (sc->sc_flags & SC_DEBUG)
868 printf("ppp%d: bad fcs %x, pkt len %d\n",
869 sc->sc_if.if_unit, sc->sc_fcs, ilen);
870 sc->sc_if.if_ierrors++;
871 sc->sc_stats.ppp_ierrors++;
873 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
878 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
880 if (sc->sc_flags & SC_DEBUG)
881 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
883 sc->sc_if.if_ierrors++;
884 sc->sc_stats.ppp_ierrors++;
885 sc->sc_flags |= SC_PKTLOST;
892 * Remove FCS trailer. Somewhat painful...
895 if (--sc->sc_mc->m_len == 0) {
896 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
902 /* excise this mbuf chain */
904 sc->sc_m = sc->sc_mc->m_next;
905 sc->sc_mc->m_next = NULL;
907 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
908 if (sc->sc_flags & SC_PKTLOST) {
910 sc->sc_flags &= ~SC_PKTLOST;
918 if (sc->sc_flags & SC_FLUSH) {
919 if (sc->sc_flags & SC_LOG_FLUSH)
924 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
928 if (sc->sc_flags & SC_ESCAPED) {
929 sc->sc_flags &= ~SC_ESCAPED;
931 } else if (c == PPP_ESCAPE) {
932 sc->sc_flags |= SC_ESCAPED;
939 * Initialize buffer on first octet received.
940 * First octet could be address or protocol (when compressing
942 * Second octet is control.
943 * Third octet is first or second (when compressing protocol)
945 * Fourth octet is second octet of protocol.
947 if (sc->sc_ilen == 0) {
948 /* reset the first input mbuf */
949 if (sc->sc_m == NULL) {
951 if (sc->sc_m == NULL) {
952 if (sc->sc_flags & SC_DEBUG)
953 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
959 m->m_data = M_DATASTART(sc->sc_m);
961 sc->sc_mp = mtod(m, char *);
962 sc->sc_fcs = PPP_INITFCS;
963 if (c != PPP_ALLSTATIONS) {
964 if (sc->sc_flags & SC_REJ_COMP_AC) {
965 if (sc->sc_flags & SC_DEBUG)
966 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
967 sc->sc_if.if_unit, c);
970 *sc->sc_mp++ = PPP_ALLSTATIONS;
971 *sc->sc_mp++ = PPP_UI;
976 if (sc->sc_ilen == 1 && c != PPP_UI) {
977 if (sc->sc_flags & SC_DEBUG)
978 printf("ppp%d: missing UI (0x3), got 0x%x\n",
979 sc->sc_if.if_unit, c);
982 if (sc->sc_ilen == 2 && (c & 1) == 1) {
983 /* a compressed protocol */
988 if (sc->sc_ilen == 3 && (c & 1) == 0) {
989 if (sc->sc_flags & SC_DEBUG)
990 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
991 (sc->sc_mp[-1] << 8) + c);
995 /* packet beyond configured mru? */
996 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
997 if (sc->sc_flags & SC_DEBUG)
998 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1002 /* is this mbuf full? */
1004 if (M_TRAILINGSPACE(m) <= 0) {
1005 if (m->m_next == NULL) {
1007 if (m->m_next == NULL) {
1008 if (sc->sc_flags & SC_DEBUG)
1009 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1013 sc->sc_mc = m = m->m_next;
1015 m->m_data = M_DATASTART(m);
1016 sc->sc_mp = mtod(m, char *);
1021 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1025 if (!(sc->sc_flags & SC_FLUSH)) {
1027 sc->sc_if.if_ierrors++;
1028 sc->sc_stats.ppp_ierrors++;
1029 sc->sc_flags |= SC_FLUSH;
1031 if (sc->sc_flags & SC_LOG_FLUSH)
1037 #define MAX_DUMP_BYTES 128
1041 struct ppp_softc *sc;
1045 sc->sc_rawin[sc->sc_rawin_count++] = c;
1046 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1047 || (c < 0 && sc->sc_rawin_count > 0)) {
1048 printf("ppp%d input: ", sc->sc_if.if_unit);
1049 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1050 sc->sc_rawin_count = 0;
1059 char buf[3*MAX_DUMP_BYTES+4];
1061 static char digits[] = "0123456789abcdef";
1064 if (bp >= buf + sizeof(buf) - 3) {
1068 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1069 *bp++ = digits[*b++ & 0xf];
1074 printf("%s\n", buf);
1077 #endif /* NPPP > 0 */