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).
72 * Ultrix port by Per Sundstrom <sundstrom@stkhlm.enet.dec.com>,
73 * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
76 /* $Id: ppp_tty.c,v 1.8 1996/09/26 06:19:26 paulus Exp $ */
77 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
78 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
86 #include "../h/param.h"
87 #include "../h/user.h"
88 #include "../h/proc.h"
89 #include "../h/mbuf.h"
91 #include "../h/socket.h"
92 #include "../h/ioctl.h"
93 #include "../h/file.h"
95 #include "../h/kernel.h"
96 #include "../h/conf.h"
98 #include "../h/systm.h"
100 #include "../net/net/if.h"
101 #include "ppp_defs.h"
104 #include "../net/netinet/in.h"
105 #include "../net/netinet/in_systm.h"
106 #include "../net/netinet/ip.h"
107 #include "slcompress.h"
111 #include "if_pppvar.h"
113 int pppopen __P((dev_t dev, struct tty *tp));
114 int pppclose __P((struct tty *tp, int flag));
115 int pppread __P((struct tty *tp, struct uio *uio, int flag));
116 int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
117 int ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag));
118 int pppinput __P((int c, struct tty *tp));
119 int pppstart __P((struct tty *tp));
121 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
122 static void pppasyncstart __P((struct ppp_softc *));
123 static void pppasyncctlp __P((struct ppp_softc *));
124 static void pppasyncrelinq __P((struct ppp_softc *));
125 static void ppp_timeout __P((void *));
126 static void pppgetm __P((struct ppp_softc *sc));
127 static void pppdumpb __P((u_char *b, int l));
128 static void ppplogchar __P((struct ppp_softc *, int));
131 * Some useful mbuf macros not in mbuf.h.
133 #define M_IS_CLUSTER(m) ((m)->m_off > MMAXOFF)
135 #define M_TRAILINGSPACE(m) \
136 ((M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr + M_CLUSTERSZ : MSIZE) \
137 - ((m)->m_off + (m)->m_len))
139 #define M_OFFSTART(m) \
140 (M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr : MMINOFF)
142 #define M_DATASIZE(m) \
143 (M_IS_CLUSTER(m) ? M_CLUSTERSZ : MLEN)
146 * Does c need to be escaped?
148 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
151 * Procedures for using an async tty interface for PPP.
155 * This is an Ultrix kernel, we've got clists.
157 #define CCOUNT(q) ((q)->c_cc)
160 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
161 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
164 * Line specific open routine for async tty devices.
165 * Attach the given tty to the first available ppp unit.
166 * Called from device open routine or ttioctl.
172 register struct tty *tp;
174 register struct ppp_softc *sc;
176 struct proc *p = u.u_procp;
183 if (tp->t_line == PPPDISC) {
184 sc = (struct ppp_softc *) tp->t_sc;
185 if (sc != NULL && sc->sc_devp == (void *) tp) {
191 if ((sc = pppalloc(p->p_pid)) == NULL) {
197 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
201 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
202 sc->sc_asyncmap[0] = 0xffffffff;
203 sc->sc_asyncmap[3] = 0x60000000;
204 sc->sc_rasyncmap = 0;
205 sc->sc_devp = (void *) tp;
206 sc->sc_start = pppasyncstart;
207 sc->sc_ctlp = pppasyncctlp;
208 sc->sc_relinq = pppasyncrelinq;
211 sc->sc_if.if_flags |= IFF_RUNNING;
213 tp->t_sc = (caddr_t) sc;
214 ttyflush(tp, FREAD | FWRITE);
221 * Line specific close routine, called from device close routine
223 * Detach the tty from the ppp unit.
224 * Mimics part of ttyclose().
231 register struct ppp_softc *sc;
235 ttyflush(tp, FREAD|FWRITE);
237 sc = (struct ppp_softc *) tp->t_sc;
240 if (tp == (struct tty *) sc->sc_devp) {
250 * Relinquish the interface unit to another device.
254 struct ppp_softc *sc;
260 m_freem(sc->sc_outm);
267 if (sc->sc_flags & SC_TIMEOUT) {
268 untimeout(ppp_timeout, (void *) sc);
269 sc->sc_flags &= ~SC_TIMEOUT;
275 * Line specific (tty) read routine.
278 pppread(tp, uio, flag)
279 register struct tty *tp;
283 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
291 * Loop waiting for input, checking that nothing disasterous
292 * happens in the meantime.
296 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
300 if (sc->sc_inq.ifq_head != NULL)
302 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
303 && (tp->t_state & TS_ISOPEN)) {
305 return 0; /* end of file */
307 if (tp->t_state & (TS_ASYNC | TS_NBIO)) {
309 return (EWOULDBLOCK);
311 sleep((caddr_t) &tp->t_rawq, TTIPRI);
314 /* Pull place-holder byte out of canonical queue */
317 /* Get the packet from the input queue */
318 IF_DEQUEUE(&sc->sc_inq, m0);
321 for (m = m0; m && uio->uio_resid; m = m->m_next)
322 if (error = uiomove(mtod(m, u_char *), m->m_len, UIO_READ, uio))
329 * Line specific (tty) write routine.
332 pppwrite(tp, uio, flag)
333 register struct tty *tp;
337 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
338 struct mbuf *m, *m0, **mp, *p;
342 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
343 return 0; /* wrote 0 bytes */
344 if (tp->t_line != PPPDISC)
346 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
348 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
349 uio->uio_resid < PPP_HDRLEN)
351 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
352 MGET(m, M_WAIT, MT_DATA);
353 if ((*mp = m) == NULL) {
357 if (uio->uio_resid >= CLBYTES / 2) {
361 len = MIN(m->m_len, uio->uio_resid);
362 if (error = uiomove(mtod(m, u_char *), len, UIO_WRITE, uio)) {
368 dst.sa_family = AF_UNSPEC;
369 bcopy(mtod(m0, caddr_t), dst.sa_data, PPP_HDRLEN);
370 m0->m_off += PPP_HDRLEN;
371 m0->m_len -= PPP_HDRLEN;
372 return (pppoutput(&sc->sc_if, m0, &dst));
376 * Line specific (tty) ioctl routine.
377 * This discipline requires that tty device drivers call
378 * the line specific l_ioctl routine from their ioctl routines.
382 ppptioctl(tp, cmd, data, flag)
387 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
390 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
395 case PPPIOCSASYNCMAP:
398 sc->sc_asyncmap[0] = *(u_int *)data;
401 case PPPIOCGASYNCMAP:
402 *(u_int *)data = sc->sc_asyncmap[0];
405 case PPPIOCSRASYNCMAP:
408 sc->sc_rasyncmap = *(u_int *)data;
411 case PPPIOCGRASYNCMAP:
412 *(u_int *)data = sc->sc_rasyncmap;
415 case PPPIOCSXASYNCMAP:
419 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
420 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
421 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
422 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
426 case PPPIOCGXASYNCMAP:
427 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
431 error = pppioctl(sc, cmd, data, flag);
432 if (error == 0 && cmd == PPPIOCSMRU)
440 * FCS lookup table as calculated by genfcstab.
442 static u_short fcstab[256] = {
443 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
444 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
445 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
446 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
447 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
448 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
449 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
450 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
451 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
452 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
453 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
454 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
455 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
456 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
457 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
458 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
459 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
460 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
461 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
462 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
463 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
464 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
465 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
466 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
467 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
468 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
469 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
470 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
471 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
472 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
473 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
474 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
478 * Calculate a new FCS given the current FCS and the new data.
482 register u_short fcs;
487 fcs = PPP_FCS(fcs, *cp++);
492 * This gets called at splnet from if_ppp.c at various times
493 * when there is data ready to be sent.
497 register struct ppp_softc *sc;
499 register struct tty *tp = (struct tty *) sc->sc_devp;
500 register struct mbuf *m;
502 register u_char *start, *stop, *cp;
503 int n, ndone, done, idle;
508 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
510 * See if we have an existing packet partly sent.
511 * If not, get a new packet and start sending it.
516 * Get another packet to be sent.
525 * The extra PPP_FLAG will start up a new packet, and thus
526 * will flush any accumulated garbage. We do this whenever
527 * the line may have been idle for some time.
529 if (CCOUNT(&tp->t_outq) == 0) {
530 ++sc->sc_stats.ppp_obytes;
531 (void) putc(PPP_FLAG, &tp->t_outq);
534 /* Calculate the FCS for the first mbuf's worth. */
535 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
539 start = mtod(m, u_char *);
544 * Find out how many bytes in the string we can
545 * handle without doing something special.
547 for (cp = start; cp < stop; cp++)
552 ndone = n - b_to_q(start, n, &tp->t_outq);
555 sc->sc_stats.ppp_obytes += ndone;
558 break; /* packet doesn't fit */
561 * If there are characters left in the mbuf,
562 * the first one must be special.
563 * Put it out in a different form.
567 if (putc(PPP_ESCAPE, &tp->t_outq))
569 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
570 (void) unputc(&tp->t_outq);
575 sc->sc_stats.ppp_obytes += 2;
582 * If we didn't empty this mbuf, remember where we're up to.
583 * If we emptied the last mbuf, try to add the FCS and closing
584 * flag, and if we can't, leave sc_outm pointing to m, but with
585 * m->m_len == 0, to remind us to output the FCS and flag later.
588 if (done && m->m_next == NULL) {
594 * We may have to escape the bytes in the FCS.
597 c = ~sc->sc_outfcs & 0xFF;
600 *p++ = c ^ PPP_TRANS;
603 c = (~sc->sc_outfcs >> 8) & 0xFF;
606 *p++ = c ^ PPP_TRANS;
612 * Try to output the FCS and flag. If the bytes
613 * don't all fit, back out.
616 for (q = endseq; q < p; ++q)
617 if (putc(*q, &tp->t_outq)) {
619 for (; q > endseq; --q)
625 sc->sc_stats.ppp_obytes += q - endseq;
629 m->m_off += m->m_len - len;
634 /* Finished with this mbuf; free it and move on. */
638 /* Finished a packet */
641 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
645 * If m == NULL, we have finished a packet.
646 * If m != NULL, we've either done as much work this time
647 * as we need to, or else we've filled up the output queue.
654 /* Call pppstart to start output again if necessary. */
659 * This timeout is needed for operation on a pseudo-tty,
660 * because the pty code doesn't call pppstart after it has
661 * drained the t_outq.
663 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
664 timeout(ppp_timeout, (void *) sc, 1);
665 sc->sc_flags |= SC_TIMEOUT;
672 * This gets called when a received packet is placed on
673 * the inq, at splnet.
677 struct ppp_softc *sc;
682 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
684 tp = (struct tty *) sc->sc_devp;
685 putc(0, &tp->t_canq);
691 * Start output on async tty interface. If the transmit queue
692 * has drained sufficiently, arrange for pppasyncstart to be
693 * called later at splnet.
694 * Called at spltty or higher.
698 register struct tty *tp;
700 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
703 * If there is stuff in the output queue, send it now.
704 * We are being called in lieu of ttstart and must do what it would.
706 if (tp->t_oproc != NULL)
710 * If the transmit queue has drained and the tty has not hung up
711 * or been disconnected from the ppp unit, then tell if_ppp.c that
712 * we need more output.
714 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
715 && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
716 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
724 * Timeout routine - try to start some more output.
730 struct ppp_softc *sc = (struct ppp_softc *) x;
731 struct tty *tp = (struct tty *) sc->sc_devp;
735 sc->sc_flags &= ~SC_TIMEOUT;
741 * Allocate enough mbuf to handle current MRU.
745 register struct ppp_softc *sc;
747 struct mbuf *m, **mp, *p;
751 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
752 if ((m = *mp) == NULL) {
753 MGET(m, M_DONTWAIT, MT_DATA);
759 len -= M_DATASIZE(m);
765 * tty interface receiver interrupt.
767 static unsigned paritytab[8] = {
768 0x96696996, 0x69969669, 0x69969669, 0x96696996,
769 0x69969669, 0x96696996, 0x96696996, 0x69969669
775 register struct tty *tp;
777 register struct ppp_softc *sc;
782 sc = (struct ppp_softc *) tp->t_sc;
783 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
787 ++sc->sc_stats.ppp_ibytes;
792 * Handle software flow control of output.
794 if (tp->t_iflag & IXON) {
795 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != 0) {
796 if ((tp->t_state & TS_TTSTOP) == 0) {
797 tp->t_state |= TS_TTSTOP;
798 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
802 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != 0) {
803 tp->t_state &= ~TS_TTSTOP;
804 if (tp->t_oproc != NULL)
812 sc->sc_flags |= SC_RCV_B7_1;
814 sc->sc_flags |= SC_RCV_B7_0;
815 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
816 sc->sc_flags |= SC_RCV_ODDP;
818 sc->sc_flags |= SC_RCV_EVNP;
821 if (sc->sc_flags & SC_LOG_RAWIN)
828 if (sc->sc_rawin_count > 0)
832 * If SC_ESCAPED is set, then we've seen the packet
833 * abort sequence "}~".
835 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
836 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
838 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
839 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
840 if (sc->sc_flags & SC_DEBUG)
841 printf("ppp%d: bad fcs %x, pkt len %d\n",
842 sc->sc_if.if_unit, sc->sc_fcs, ilen);
843 sc->sc_if.if_ierrors++;
844 sc->sc_stats.ppp_ierrors++;
846 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
851 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
853 if (sc->sc_flags & SC_DEBUG)
854 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
856 sc->sc_if.if_ierrors++;
857 sc->sc_stats.ppp_ierrors++;
858 sc->sc_flags |= SC_PKTLOST;
865 * Remove FCS trailer. Somewhat painful...
868 if (--sc->sc_mc->m_len == 0) {
869 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
875 /* excise this mbuf chain */
877 sc->sc_m = sc->sc_mc->m_next;
878 sc->sc_mc->m_next = NULL;
880 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
881 if (sc->sc_flags & SC_PKTLOST) {
883 sc->sc_flags &= ~SC_PKTLOST;
891 if (sc->sc_flags & SC_FLUSH) {
892 if (sc->sc_flags & SC_LOG_FLUSH)
897 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
901 if (sc->sc_flags & SC_ESCAPED) {
902 sc->sc_flags &= ~SC_ESCAPED;
904 } else if (c == PPP_ESCAPE) {
905 sc->sc_flags |= SC_ESCAPED;
912 * Initialize buffer on first octet received.
913 * First octet could be address or protocol (when compressing
915 * Second octet is control.
916 * Third octet is first or second (when compressing protocol)
918 * Fourth octet is second octet of protocol.
920 if (sc->sc_ilen == 0) {
921 /* reset the first input mbuf */
922 if (sc->sc_m == NULL) {
924 if (sc->sc_m == NULL) {
925 if (sc->sc_flags & SC_DEBUG)
926 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
932 m->m_off = M_OFFSTART(m);
934 sc->sc_mp = mtod(m, char *);
935 sc->sc_fcs = PPP_INITFCS;
936 if (c != PPP_ALLSTATIONS) {
937 if (sc->sc_flags & SC_REJ_COMP_AC) {
938 if (sc->sc_flags & SC_DEBUG)
939 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
940 sc->sc_if.if_unit, c);
943 *sc->sc_mp++ = PPP_ALLSTATIONS;
944 *sc->sc_mp++ = PPP_UI;
949 if (sc->sc_ilen == 1 && c != PPP_UI) {
950 if (sc->sc_flags & SC_DEBUG)
951 printf("ppp%d: missing UI (0x3), got 0x%x\n",
952 sc->sc_if.if_unit, c);
955 if (sc->sc_ilen == 2 && (c & 1) == 1) {
956 /* a compressed protocol */
961 if (sc->sc_ilen == 3 && (c & 1) == 0) {
962 if (sc->sc_flags & SC_DEBUG)
963 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
964 (sc->sc_mp[-1] << 8) + c);
968 /* packet beyond configured mru? */
969 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
970 if (sc->sc_flags & SC_DEBUG)
971 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
975 /* is this mbuf full? */
977 if (M_TRAILINGSPACE(m) <= 0) {
978 if (m->m_next == NULL) {
980 if (m->m_next == NULL) {
981 if (sc->sc_flags & SC_DEBUG)
982 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
986 sc->sc_mc = m = m->m_next;
988 m->m_off = M_OFFSTART(m);
989 sc->sc_mp = mtod(m, char *);
994 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
998 if (!(sc->sc_flags & SC_FLUSH)) {
1000 sc->sc_if.if_ierrors++;
1001 sc->sc_stats.ppp_ierrors++;
1002 sc->sc_flags |= SC_FLUSH;
1004 if (sc->sc_flags & SC_LOG_FLUSH)
1010 #define MAX_DUMP_BYTES 128
1014 struct ppp_softc *sc;
1018 sc->sc_rawin[sc->sc_rawin_count++] = c;
1019 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1020 || (c < 0 && sc->sc_rawin_count > 0)) {
1021 printf("ppp%d input: ", sc->sc_if.if_unit);
1022 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1023 sc->sc_rawin_count = 0;
1032 char buf[3*MAX_DUMP_BYTES+4];
1034 static char digits[] = "0123456789abcdef";
1037 if (bp >= buf + sizeof(buf) - 3) {
1041 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1042 *bp++ = digits[*b++ & 0xf];
1047 printf("%s\n", buf);
1050 #endif /* NPPP > 0 */