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.2 1995/05/02 01:00:44 paulus Exp $ */
74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
82 #include <sys/param.h>
83 #include <sys/systm.h>
86 #include <sys/dkstat.h>
87 #include <sys/socket.h>
88 #include <sys/ioctl.h>
91 #include <sys/kernel.h>
93 #include <sys/vnode.h>
96 #include <net/if_types.h>
99 #include <netinet/in.h>
100 #include <netinet/in_systm.h>
101 #include <netinet/ip.h>
102 #include <net/pppcompress.h>
105 #include <net/ppp_defs.h>
106 #include <net/if_ppp.h>
107 #include <net/if_pppvar.h>
109 void pppasyncattach __P((void));
110 int pppopen __P((dev_t dev, struct tty *tp));
111 int pppclose __P((struct tty *tp, int flag));
112 int pppread __P((struct tty *tp, struct uio *uio, int flag));
113 int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
114 int ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
116 int pppinput __P((int c, struct tty *tp));
117 int pppstart __P((struct tty *tp));
119 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
120 static void pppasyncstart __P((struct ppp_softc *));
121 static void pppasyncctlp __P((struct ppp_softc *));
122 static void pppasyncrelinq __P((struct ppp_softc *));
123 static void ppp_timeout __P((void *));
124 static void pppgetm __P((struct ppp_softc *sc));
125 static void pppdumpb __P((u_char *b, int l));
126 static void ppplogchar __P((struct ppp_softc *, int));
129 * Some useful mbuf macros not in mbuf.h.
131 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
133 #define M_DATASTART(m) \
134 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
135 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
137 #define M_DATASIZE(m) \
138 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
139 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
142 * Does c need to be escaped?
144 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
147 * Procedures for using an async tty interface for PPP.
150 /* This is a FreeBSD-2.0 kernel. */
151 #define CCOUNT(q) ((q)->c_cc)
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, ppptioctl,
160 pppinput, pppstart, nullmodem
166 linesw[PPPDISC] = pppdisc;
169 TEXT_SET(pseudo_set, pppasyncattach);
172 * Line specific open routine for async tty devices.
173 * Attach the given tty to the first available ppp unit.
179 register struct tty *tp;
181 struct proc *p = curproc; /* XXX */
182 register struct ppp_softc *sc;
185 if (error = suser(p->p_ucred, &p->p_acflag))
188 if (tp->t_line == PPPDISC) {
189 sc = (struct ppp_softc *) tp->t_sc;
190 if (sc != NULL && sc->sc_devp == (void *) tp)
194 if ((sc = pppalloc(p->p_pid)) == NULL)
198 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
203 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
204 sc->sc_asyncmap[0] = 0xffffffff;
205 sc->sc_asyncmap[3] = 0x60000000;
206 sc->sc_rasyncmap = 0;
207 sc->sc_devp = (void *) tp;
208 sc->sc_start = pppasyncstart;
209 sc->sc_ctlp = pppasyncctlp;
210 sc->sc_relinq = pppasyncrelinq;
213 sc->sc_if.if_flags |= IFF_RUNNING;
215 tp->t_sc = (caddr_t) sc;
216 ttyflush(tp, FREAD | FWRITE);
223 * Line specific close routine.
224 * Detach the tty from the ppp unit.
225 * Mimics part of ttyclose().
232 register struct ppp_softc *sc;
237 s = splimp(); /* paranoid; splnet probably ok */
239 sc = (struct ppp_softc *) tp->t_sc;
242 if (tp == (struct tty *) sc->sc_devp) {
252 * Relinquish the interface unit to another device.
256 struct ppp_softc *sc;
262 m_freem(sc->sc_outm);
269 if (sc->sc_flags & SC_TIMEOUT) {
270 untimeout(ppp_timeout, (void *) sc);
271 sc->sc_flags &= ~SC_TIMEOUT;
277 * Line specific (tty) read routine.
280 pppread(tp, uio, flag)
281 register struct tty *tp;
285 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
293 * Loop waiting for input, checking that nothing disasterous
294 * happens in the meantime.
298 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
302 if (sc->sc_inq.ifq_head != NULL)
304 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
305 && (tp->t_state & TS_ISOPEN)) {
307 return 0; /* end of file */
309 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
311 return (EWOULDBLOCK);
313 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
320 /* Pull place-holder byte out of canonical queue */
323 /* Get the packet from the input queue */
324 IF_DEQUEUE(&sc->sc_inq, m0);
327 for (m = m0; m && uio->uio_resid; m = m->m_next)
328 if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
335 * Line specific (tty) write routine.
338 pppwrite(tp, uio, flag)
339 register struct tty *tp;
343 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
344 struct mbuf *m, *m0, **mp;
348 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
349 return 0; /* wrote 0 bytes */
350 if (tp->t_line != PPPDISC)
352 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
354 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
355 uio->uio_resid < PPP_HDRLEN)
357 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
358 MGET(m, M_WAIT, MT_DATA);
359 if ((*mp = m) == NULL) {
364 if (uio->uio_resid >= MCLBYTES / 2)
365 MCLGET(m, M_DONTWAIT);
366 len = M_TRAILINGSPACE(m);
367 if (len > uio->uio_resid)
368 len = uio->uio_resid;
369 if (error = uiomove(mtod(m, u_char *), len, uio)) {
375 dst.sa_family = AF_UNSPEC;
376 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
377 m0->m_data += PPP_HDRLEN;
378 m0->m_len -= PPP_HDRLEN;
379 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
383 * Line specific (tty) ioctl routine.
384 * This discipline requires that tty device drivers call
385 * the line specific l_ioctl routine from their ioctl routines.
389 ppptioctl(tp, cmd, data, flag, p)
395 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
398 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
403 case PPPIOCSASYNCMAP:
404 if (error = suser(p->p_ucred, &p->p_acflag))
406 sc->sc_asyncmap[0] = *(u_int *)data;
409 case PPPIOCGASYNCMAP:
410 *(u_int *)data = sc->sc_asyncmap[0];
413 case PPPIOCSRASYNCMAP:
414 if (error = suser(p->p_ucred, &p->p_acflag))
416 sc->sc_rasyncmap = *(u_int *)data;
419 case PPPIOCGRASYNCMAP:
420 *(u_int *)data = sc->sc_rasyncmap;
423 case PPPIOCSXASYNCMAP:
424 if (error = suser(p->p_ucred, &p->p_acflag))
427 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
428 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
429 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
430 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
434 case PPPIOCGXASYNCMAP:
435 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
439 error = pppioctl(sc, cmd, data, flag, p);
440 if (error == 0 && cmd == PPPIOCSMRU)
448 * FCS lookup table as calculated by genfcstab.
450 static u_short fcstab[256] = {
451 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
452 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
453 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
454 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
455 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
456 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
457 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
458 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
459 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
460 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
461 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
462 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
463 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
464 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
465 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
466 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
467 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
468 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
469 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
470 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
471 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
472 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
473 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
474 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
475 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
476 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
477 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
478 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
479 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
480 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
481 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
482 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
486 * Calculate a new FCS given the current FCS and the new data.
490 register u_short fcs;
495 fcs = PPP_FCS(fcs, *cp++);
500 * This gets called from pppoutput when a new packet is
505 register struct ppp_softc *sc;
507 register struct tty *tp = (struct tty *) sc->sc_devp;
516 * This gets called when a received packet is placed on
521 struct ppp_softc *sc;
525 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
526 tp = (struct tty *) sc->sc_devp;
527 putc(0, &tp->t_canq);
532 * Start output on async tty interface. Get another datagram
533 * to send from the interface queue and start sending it.
537 register struct tty *tp;
539 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
540 register struct mbuf *m;
542 register u_char *start, *stop, *cp;
543 int n, s, ndone, done, idle;
546 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
547 || sc == NULL || tp != (struct tty *) sc->sc_devp) {
548 if (tp->t_oproc != NULL)
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.
575 if (CCOUNT(&tp->t_outq) == 0) {
577 (void) putc(PPP_FLAG, &tp->t_outq);
580 /* Calculate the FCS for the first mbuf's worth. */
581 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
585 start = mtod(m, u_char *);
590 * Find out how many bytes in the string we can
591 * handle without doing something special.
593 for (cp = start; cp < stop; cp++)
598 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
599 ndone = n - b_to_q(start, n, &tp->t_outq);
602 sc->sc_bytessent += ndone;
605 break; /* packet doesn't fit */
608 * If there are characters left in the mbuf,
609 * the first one must be special..
610 * Put it out in a different form.
613 if (putc(PPP_ESCAPE, &tp->t_outq))
615 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
616 (void) unputc(&tp->t_outq);
619 sc->sc_bytessent += 2;
626 * If we didn't empty this mbuf, remember where we're up to.
627 * If we emptied the last mbuf, try to add the FCS and closing
628 * flag, and if we can't, leave sc_outm pointing to m, but with
629 * m->m_len == 0, to remind us to output the FCS and flag later.
632 if (done && m->m_next == NULL) {
638 * We may have to escape the bytes in the FCS.
641 c = ~sc->sc_outfcs & 0xFF;
644 *p++ = c ^ PPP_TRANS;
647 c = (~sc->sc_outfcs >> 8) & 0xFF;
650 *p++ = c ^ PPP_TRANS;
656 * Try to output the FCS and flag. If the bytes
657 * don't all fit, back out.
659 for (q = endseq; q < p; ++q)
660 if (putc(*q, &tp->t_outq)) {
662 for (; q > endseq; --q)
666 sc->sc_bytessent += q - endseq;
670 /* remember where we got to */
676 /* Finished with this mbuf; free it and move on. */
680 /* Finished a packet */
681 sc->sc_if.if_opackets++;
682 sc->sc_if.if_obytes = sc->sc_bytessent;
685 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
689 * Here we have either finished a packet (m == NULL)
690 * or filled up the output queue (m != NULL).
698 * If there is stuff in the output queue, send it now.
699 * We are being called in lieu of ttstart and must do what it would.
701 if (tp->t_oproc != NULL)
705 * This timeout is needed for operation on a pseudo-tty,
706 * because the pty code doesn't call pppstart after it has
707 * drained the t_outq.
709 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
710 timeout(ppp_timeout, (void *) sc, 1);
711 sc->sc_flags |= SC_TIMEOUT;
718 * Timeout routine - try to start some more output.
724 struct ppp_softc *sc = (struct ppp_softc *) x;
725 struct tty *tp = (struct tty *) sc->sc_devp;
729 sc->sc_flags &= ~SC_TIMEOUT;
735 * Allocate enough mbuf to handle current MRU.
739 register struct ppp_softc *sc;
741 struct mbuf *m, **mp;
747 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
748 if ((m = *mp) == NULL) {
749 MGETHDR(m, M_DONTWAIT, MT_DATA);
753 MCLGET(m, M_DONTWAIT);
755 len -= M_DATASIZE(m);
762 * tty interface receiver interrupt.
764 static unsigned paritytab[8] = {
765 0x96696996, 0x69969669, 0x69969669, 0x96696996,
766 0x69969669, 0x96696996, 0x96696996, 0x69969669
772 register struct tty *tp;
774 register struct ppp_softc *sc;
778 sc = (struct ppp_softc *) tp->t_sc;
779 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
787 /* framing error or overrun on this char - abort packet */
788 if (sc->sc_flags & SC_DEBUG)
789 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
796 sc->sc_flags |= SC_RCV_B7_1;
798 sc->sc_flags |= SC_RCV_B7_0;
799 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
800 sc->sc_flags |= SC_RCV_ODDP;
802 sc->sc_flags |= SC_RCV_EVNP;
804 if (sc->sc_flags & SC_LOG_RAWIN)
810 sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
812 if (sc->sc_rawin_count > 0)
816 * If SC_ESCAPED is set, then we've seen the packet
817 * abort sequence "}~".
819 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
820 || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
821 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
822 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
823 if (sc->sc_flags & SC_DEBUG)
824 printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
826 sc->sc_if.if_ierrors++;
828 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
833 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
835 if (sc->sc_flags & SC_DEBUG)
836 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
837 sc->sc_if.if_ierrors++;
838 sc->sc_flags |= SC_PKTLOST;
845 * Remove FCS trailer. Somewhat painful...
848 if (--sc->sc_mc->m_len == 0) {
849 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
855 /* excise this mbuf chain */
857 sc->sc_m = sc->sc_mc->m_next;
858 sc->sc_mc->m_next = NULL;
860 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
861 sc->sc_flags &= ~SC_PKTLOST;
868 if (sc->sc_flags & SC_FLUSH) {
869 if (sc->sc_flags & SC_LOG_FLUSH)
875 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
880 if (sc->sc_flags & SC_ESCAPED) {
881 sc->sc_flags &= ~SC_ESCAPED;
883 } else if (c == PPP_ESCAPE) {
884 sc->sc_flags |= SC_ESCAPED;
890 * Initialize buffer on first octet received.
891 * First octet could be address or protocol (when compressing
893 * Second octet is control.
894 * Third octet is first or second (when compressing protocol)
896 * Fourth octet is second octet of protocol.
898 if (sc->sc_ilen == 0) {
899 /* reset the first input mbuf */
900 if (sc->sc_m == NULL) {
902 if (sc->sc_m == NULL) {
903 if (sc->sc_flags & SC_DEBUG)
904 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
910 m->m_data = M_DATASTART(sc->sc_m);
912 sc->sc_mp = mtod(m, char *);
913 sc->sc_fcs = PPP_INITFCS;
914 if (c != PPP_ALLSTATIONS) {
915 if (sc->sc_flags & SC_REJ_COMP_AC) {
916 if (sc->sc_flags & SC_DEBUG)
917 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
918 sc->sc_if.if_unit, c);
921 *sc->sc_mp++ = PPP_ALLSTATIONS;
922 *sc->sc_mp++ = PPP_UI;
927 if (sc->sc_ilen == 1 && c != PPP_UI) {
928 if (sc->sc_flags & SC_DEBUG)
929 printf("ppp%d: missing UI (0x3), got 0x%x\n",
930 sc->sc_if.if_unit, c);
933 if (sc->sc_ilen == 2 && (c & 1) == 1) {
934 /* a compressed protocol */
939 if (sc->sc_ilen == 3 && (c & 1) == 0) {
940 if (sc->sc_flags & SC_DEBUG)
941 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
942 (sc->sc_mp[-1] << 8) + c);
946 /* packet beyond configured mru? */
947 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
948 if (sc->sc_flags & SC_DEBUG)
949 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
953 /* is this mbuf full? */
955 if (M_TRAILINGSPACE(m) <= 0) {
956 if (m->m_next == NULL) {
958 if (m->m_next == NULL) {
959 if (sc->sc_flags & SC_DEBUG)
960 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
964 sc->sc_mc = m = m->m_next;
966 m->m_data = M_DATASTART(m);
967 sc->sc_mp = mtod(m, char *);
972 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
977 if (!(sc->sc_flags & SC_FLUSH)) {
978 sc->sc_if.if_ierrors++;
979 sc->sc_flags |= SC_FLUSH;
980 if (sc->sc_flags & SC_LOG_FLUSH)
987 #define MAX_DUMP_BYTES 128
991 struct ppp_softc *sc;
995 sc->sc_rawin[sc->sc_rawin_count++] = c;
996 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
997 || c < 0 && sc->sc_rawin_count > 0) {
998 printf("ppp%d input: ", sc->sc_if.if_unit);
999 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1000 sc->sc_rawin_count = 0;
1009 char buf[3*MAX_DUMP_BYTES+4];
1011 static char digits[] = "0123456789abcdef";
1014 if (bp >= buf + sizeof(buf) - 3) {
1018 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1019 *bp++ = digits[*b++ & 0xf];
1024 printf("%s\n", buf);
1027 #endif /* NPPP > 0 */