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.1 1994/12/15 22:28:09 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;
290 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
291 return 0; /* end of file */
292 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
295 while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
296 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
298 return (EWOULDBLOCK);
300 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
306 if (tp->t_line != PPPDISC) {
311 /* Pull place-holder byte out of canonical queue */
314 /* Get the packet from the input queue */
315 IF_DEQUEUE(&sc->sc_inq, m0);
318 for (m = m0; m && uio->uio_resid; m = m->m_next)
319 if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
326 * Line specific (tty) write routine.
329 pppwrite(tp, uio, flag)
330 register struct tty *tp;
334 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
335 struct mbuf *m, *m0, **mp;
339 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
340 return 0; /* wrote 0 bytes */
341 if (tp->t_line != PPPDISC)
343 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
345 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
346 uio->uio_resid < PPP_HDRLEN)
348 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
349 MGET(m, M_WAIT, MT_DATA);
350 if ((*mp = m) == NULL) {
355 if (uio->uio_resid >= MCLBYTES / 2)
356 MCLGET(m, M_DONTWAIT);
357 len = M_TRAILINGSPACE(m);
358 if (len > uio->uio_resid)
359 len = uio->uio_resid;
360 if (error = uiomove(mtod(m, u_char *), len, uio)) {
366 dst.sa_family = AF_UNSPEC;
367 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
368 m0->m_data += PPP_HDRLEN;
369 m0->m_len -= PPP_HDRLEN;
370 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
374 * Line specific (tty) ioctl routine.
375 * This discipline requires that tty device drivers call
376 * the line specific l_ioctl routine from their ioctl routines.
380 ppptioctl(tp, cmd, data, flag, p)
386 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
389 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
394 case PPPIOCSASYNCMAP:
395 if (error = suser(p->p_ucred, &p->p_acflag))
397 sc->sc_asyncmap[0] = *(u_int *)data;
400 case PPPIOCGASYNCMAP:
401 *(u_int *)data = sc->sc_asyncmap[0];
404 case PPPIOCSRASYNCMAP:
405 if (error = suser(p->p_ucred, &p->p_acflag))
407 sc->sc_rasyncmap = *(u_int *)data;
410 case PPPIOCGRASYNCMAP:
411 *(u_int *)data = sc->sc_rasyncmap;
414 case PPPIOCSXASYNCMAP:
415 if (error = suser(p->p_ucred, &p->p_acflag))
418 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
419 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
420 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
421 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
425 case PPPIOCGXASYNCMAP:
426 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
430 error = pppioctl(sc, cmd, data, flag, p);
431 if (error == 0 && cmd == PPPIOCSMRU)
439 * FCS lookup table as calculated by genfcstab.
441 static u_short fcstab[256] = {
442 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
443 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
444 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
445 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
446 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
447 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
448 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
449 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
450 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
451 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
452 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
453 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
454 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
455 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
456 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
457 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
458 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
459 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
460 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
461 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
462 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
463 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
464 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
465 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
466 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
467 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
468 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
469 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
470 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
471 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
472 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
473 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
477 * Calculate a new FCS given the current FCS and the new data.
481 register u_short fcs;
486 fcs = PPP_FCS(fcs, *cp++);
491 * This gets called from pppoutput when a new packet is
496 register struct ppp_softc *sc;
498 register struct tty *tp = (struct tty *) sc->sc_devp;
507 * This gets called when a received packet is placed on
512 struct ppp_softc *sc;
516 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
517 tp = (struct tty *) sc->sc_devp;
518 putc(0, &tp->t_canq);
523 * Start output on async tty interface. Get another datagram
524 * to send from the interface queue and start sending it.
528 register struct tty *tp;
530 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
531 register struct mbuf *m;
533 register u_char *start, *stop, *cp;
534 int n, s, ndone, done, idle;
537 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
538 || sc == NULL || tp != (struct tty *) sc->sc_devp) {
539 if (tp->t_oproc != NULL)
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.
566 if (CCOUNT(&tp->t_outq) == 0) {
568 (void) putc(PPP_FLAG, &tp->t_outq);
571 /* Calculate the FCS for the first mbuf's worth. */
572 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
576 start = mtod(m, u_char *);
581 * Find out how many bytes in the string we can
582 * handle without doing something special.
584 for (cp = start; cp < stop; cp++)
589 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
590 ndone = n - b_to_q(start, n, &tp->t_outq);
593 sc->sc_bytessent += ndone;
596 break; /* packet doesn't fit */
599 * If there are characters left in the mbuf,
600 * the first one must be special..
601 * Put it out in a different form.
604 if (putc(PPP_ESCAPE, &tp->t_outq))
606 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
607 (void) unputc(&tp->t_outq);
610 sc->sc_bytessent += 2;
617 * If we didn't empty this mbuf, remember where we're up to.
618 * If we emptied the last mbuf, try to add the FCS and closing
619 * flag, and if we can't, leave sc_outm pointing to m, but with
620 * m->m_len == 0, to remind us to output the FCS and flag later.
623 if (done && m->m_next == NULL) {
629 * We may have to escape the bytes in the FCS.
632 c = ~sc->sc_outfcs & 0xFF;
635 *p++ = c ^ PPP_TRANS;
638 c = (~sc->sc_outfcs >> 8) & 0xFF;
641 *p++ = c ^ PPP_TRANS;
647 * Try to output the FCS and flag. If the bytes
648 * don't all fit, back out.
650 for (q = endseq; q < p; ++q)
651 if (putc(*q, &tp->t_outq)) {
653 for (; q > endseq; --q)
657 sc->sc_bytessent += q - endseq;
661 /* remember where we got to */
667 /* Finished with this mbuf; free it and move on. */
671 /* Finished a packet */
672 sc->sc_if.if_opackets++;
673 sc->sc_if.if_obytes = sc->sc_bytessent;
676 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
680 * Here we have either finished a packet (m == NULL)
681 * or filled up the output queue (m != NULL).
689 * If there is stuff in the output queue, send it now.
690 * We are being called in lieu of ttstart and must do what it would.
692 if (tp->t_oproc != NULL)
696 * This timeout is needed for operation on a pseudo-tty,
697 * because the pty code doesn't call pppstart after it has
698 * drained the t_outq.
700 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
701 timeout(ppp_timeout, (void *) sc, 1);
702 sc->sc_flags |= SC_TIMEOUT;
709 * Timeout routine - try to start some more output.
715 struct ppp_softc *sc = (struct ppp_softc *) x;
716 struct tty *tp = (struct tty *) sc->sc_devp;
720 sc->sc_flags &= ~SC_TIMEOUT;
726 * Allocate enough mbuf to handle current MRU.
730 register struct ppp_softc *sc;
732 struct mbuf *m, **mp;
738 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
739 if ((m = *mp) == NULL) {
740 MGETHDR(m, M_DONTWAIT, MT_DATA);
744 MCLGET(m, M_DONTWAIT);
746 len -= M_DATASIZE(m);
753 * tty interface receiver interrupt.
755 static unsigned paritytab[8] = {
756 0x96696996, 0x69969669, 0x69969669, 0x96696996,
757 0x69969669, 0x96696996, 0x96696996, 0x69969669
763 register struct tty *tp;
765 register struct ppp_softc *sc;
769 sc = (struct ppp_softc *) tp->t_sc;
770 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
778 /* framing error or overrun on this char - abort packet */
779 if (sc->sc_flags & SC_DEBUG)
780 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
787 sc->sc_flags |= SC_RCV_B7_1;
789 sc->sc_flags |= SC_RCV_B7_0;
790 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
791 sc->sc_flags |= SC_RCV_ODDP;
793 sc->sc_flags |= SC_RCV_EVNP;
795 if (sc->sc_flags & SC_LOG_RAWIN)
801 sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
803 if (sc->sc_rawin_count > 0)
807 * If SC_ESCAPED is set, then we've seen the packet
808 * abort sequence "}~".
810 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
811 || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
812 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
813 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
814 if (sc->sc_flags & SC_DEBUG)
815 printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
817 sc->sc_if.if_ierrors++;
819 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
824 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
826 if (sc->sc_flags & SC_DEBUG)
827 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
828 sc->sc_if.if_ierrors++;
829 sc->sc_flags |= SC_PKTLOST;
836 * Remove FCS trailer. Somewhat painful...
839 if (--sc->sc_mc->m_len == 0) {
840 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
846 /* excise this mbuf chain */
848 sc->sc_m = sc->sc_mc->m_next;
849 sc->sc_mc->m_next = NULL;
851 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
852 sc->sc_flags &= ~SC_PKTLOST;
859 if (sc->sc_flags & SC_FLUSH) {
860 if (sc->sc_flags & SC_LOG_FLUSH)
866 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
871 if (sc->sc_flags & SC_ESCAPED) {
872 sc->sc_flags &= ~SC_ESCAPED;
874 } else if (c == PPP_ESCAPE) {
875 sc->sc_flags |= SC_ESCAPED;
881 * Initialize buffer on first octet received.
882 * First octet could be address or protocol (when compressing
884 * Second octet is control.
885 * Third octet is first or second (when compressing protocol)
887 * Fourth octet is second octet of protocol.
889 if (sc->sc_ilen == 0) {
890 /* reset the first input mbuf */
891 if (sc->sc_m == NULL) {
893 if (sc->sc_m == NULL) {
894 if (sc->sc_flags & SC_DEBUG)
895 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
901 m->m_data = M_DATASTART(sc->sc_m);
903 sc->sc_mp = mtod(m, char *);
904 sc->sc_fcs = PPP_INITFCS;
905 if (c != PPP_ALLSTATIONS) {
906 if (sc->sc_flags & SC_REJ_COMP_AC) {
907 if (sc->sc_flags & SC_DEBUG)
908 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
909 sc->sc_if.if_unit, c);
912 *sc->sc_mp++ = PPP_ALLSTATIONS;
913 *sc->sc_mp++ = PPP_UI;
918 if (sc->sc_ilen == 1 && c != PPP_UI) {
919 if (sc->sc_flags & SC_DEBUG)
920 printf("ppp%d: missing UI (0x3), got 0x%x\n",
921 sc->sc_if.if_unit, c);
924 if (sc->sc_ilen == 2 && (c & 1) == 1) {
925 /* a compressed protocol */
930 if (sc->sc_ilen == 3 && (c & 1) == 0) {
931 if (sc->sc_flags & SC_DEBUG)
932 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
933 (sc->sc_mp[-1] << 8) + c);
937 /* packet beyond configured mru? */
938 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
939 if (sc->sc_flags & SC_DEBUG)
940 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
944 /* is this mbuf full? */
946 if (M_TRAILINGSPACE(m) <= 0) {
947 if (m->m_next == NULL) {
949 if (m->m_next == NULL) {
950 if (sc->sc_flags & SC_DEBUG)
951 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
955 sc->sc_mc = m = m->m_next;
957 m->m_data = M_DATASTART(m);
958 sc->sc_mp = mtod(m, char *);
963 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
968 if (!(sc->sc_flags & SC_FLUSH)) {
969 sc->sc_if.if_ierrors++;
970 sc->sc_flags |= SC_FLUSH;
971 if (sc->sc_flags & SC_LOG_FLUSH)
978 #define MAX_DUMP_BYTES 128
982 struct ppp_softc *sc;
986 sc->sc_rawin[sc->sc_rawin_count++] = c;
987 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
988 || c < 0 && sc->sc_rawin_count > 0) {
989 printf("ppp%d input: ", sc->sc_if.if_unit);
990 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
991 sc->sc_rawin_count = 0;
1000 char buf[3*MAX_DUMP_BYTES+4];
1002 static char digits[] = "0123456789abcdef";
1005 if (bp >= buf + sizeof(buf) - 3) {
1009 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1010 *bp++ = digits[*b++ & 0xf];
1015 printf("%s\n", buf);
1018 #endif /* NPPP > 0 */