2 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
4 * Copyright (c) 1989 Carnegie Mellon University.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 * Carnegie Mellon University
22 * Pittsburgh, PA 15213
27 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
29 * Copyright (c) 1987 Regents of the University of California.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms are permitted
33 * provided that the above copyright notice and this paragraph are
34 * duplicated in all such forms and that any documentation,
35 * advertising materials, and other materials related to such
36 * distribution and use acknowledge that the software was developed
37 * by the University of California, Berkeley. The name of the
38 * University may not be used to endorse or promote products derived
39 * from this software without specific prior written permission.
40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
41 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
42 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
44 * Serial Line interface
47 * Center for Seismic Studies
48 * 1300 N 17th Street, Suite 1450
49 * Arlington, Virginia 22209
54 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
55 * Converted to 4.3BSD Beta by Chris Torek.
56 * Other changes made at Berkeley, based in part on code by Kirk Smith.
58 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
59 * Added VJ tcp header compression; more unified ioctls
61 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
62 * Cleaned up a lot of the mbuf-related code to fix bugs that
63 * caused system crashes and packet corruption. Changed pppstart
64 * so that it doesn't just give up with a collision if the whole
65 * packet doesn't fit in the output ring buffer.
67 * Added priority queueing for interactive IP packets, following
68 * the model of if_sl.c, plus hooks for bpf.
69 * Paul Mackerras (paulus@cs.anu.edu.au).
71 * Ultrix port by Per Sundstrom <sundstrom@stkhlm.enet.dec.com>,
72 * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
75 /* $Id: ppp_tty.c,v 1.1 1994/11/21 04:50:36 paulus Exp $ */
76 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
84 #include "../h/param.h"
85 #include "../h/user.h"
86 #include "../h/proc.h"
87 #include "../h/mbuf.h"
89 #include "../h/socket.h"
90 #include "../h/ioctl.h"
91 #include "../h/file.h"
93 #include "../h/kernel.h"
94 #include "../h/conf.h"
96 #include "../h/systm.h"
98 #include "../net/net/if.h"
101 #include "../net/netinet/in.h"
102 #include "../net/netinet/in_systm.h"
103 #include "../net/netinet/ip.h"
104 #include "slcompress.h"
107 #include "ppp_defs.h"
109 #include "if_pppvar.h"
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 pppgetm __P((struct ppp_softc *sc));
124 static void pppdumpb __P((u_char *b, int l));
125 static void ppplogchar __P((struct ppp_softc *, int));
128 * Some useful mbuf macros not in mbuf.h.
130 #define M_IS_CLUSTER(m) ((m)->m_off > MMAXOFF)
132 #define M_TRAILINGSPACE(m) \
133 ((M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr + M_CLUSTERSZ : MSIZE) \
134 - ((m)->m_off + (m)->m_len))
136 #define M_OFFSTART(m) \
137 (M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr : MMINOFF)
139 #define M_DATASIZE(m) \
140 (M_IS_CLUSTER(m) ? M_CLUSTERSZ : 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.
152 * This is an Ultrix kernel, we've got clists.
154 #define CCOUNT(q) ((q)->c_cc)
157 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
160 * Line specific open routine for async tty devices.
161 * Attach the given tty to the first available ppp unit.
167 register struct tty *tp;
169 register struct ppp_softc *sc;
171 struct proc *p = u.u_procp;
176 if (tp->t_line == PPPDISC) {
177 sc = (struct ppp_softc *) tp->t_sc;
178 if (sc != NULL && sc->sc_devp == (void *) tp)
182 if ((sc = pppalloc(p->p_pid)) == NULL)
185 if (sc->sc_outm != NULL) {
186 m_freem(sc->sc_outm);
193 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
194 sc->sc_asyncmap[0] = 0xffffffff;
195 sc->sc_asyncmap[3] = 0x60000000;
196 sc->sc_rasyncmap = 0;
197 sc->sc_devp = (void *) tp;
198 sc->sc_start = pppasyncstart;
199 sc->sc_ctlp = pppasyncctlp;
201 tp->t_sc = (caddr_t) sc;
202 ttyflush(tp, FREAD | FWRITE);
208 * Line specific close routine.
209 * Detach the tty from the ppp unit.
210 * Mimics part of ttyclose().
217 register struct ppp_softc *sc;
222 s = splimp(); /* paranoid; splnet probably ok */
224 sc = (struct ppp_softc *)tp->t_sc;
227 if (tp == (struct tty *) sc->sc_devp) {
228 m_freem(sc->sc_outm);
240 * Line specific (tty) read routine.
243 pppread(tp, uio, flag)
244 register struct tty *tp;
248 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
253 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
254 return 0; /* end of file */
255 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
258 while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
259 if (tp->t_state & (TS_ASYNC | TS_NBIO)) {
261 return (EWOULDBLOCK);
263 sleep((caddr_t) &tp->t_rawq, TTIPRI);
265 if (tp->t_line != PPPDISC) {
270 /* Pull place-holder byte out of canonical queue */
273 /* Get the packet from the input queue */
274 IF_DEQUEUE(&sc->sc_inq, m0);
277 for (m = m0; m && uio->uio_resid; m = m->m_next)
278 if (error = uiomove(mtod(m, u_char *), m->m_len, UIO_READ, uio))
285 * Line specific (tty) write routine.
288 pppwrite(tp, uio, flag)
289 register struct tty *tp;
293 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
294 struct mbuf *m, *m0, **mp, *p;
298 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
299 return 0; /* wrote 0 bytes */
300 if (tp->t_line != PPPDISC)
302 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
304 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
305 uio->uio_resid < PPP_HDRLEN)
307 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
308 MGET(m, M_WAIT, MT_DATA);
309 if ((*mp = m) == NULL) {
313 if (uio->uio_resid >= CLBYTES / 2) {
317 len = MIN(m->m_len, uio->uio_resid);
318 if (error = uiomove(mtod(m, u_char *), len, UIO_WRITE, uio)) {
324 dst.sa_family = AF_UNSPEC;
325 *(u_int32_t *)dst.sa_data = *mtod(m0, u_int32_t *);
326 m0->m_off += PPP_HDRLEN;
327 m0->m_len -= PPP_HDRLEN;
328 return (pppoutput(&sc->sc_if, m0, &dst));
332 * Line specific (tty) ioctl routine.
333 * This discipline requires that tty device drivers call
334 * the line specific l_ioctl routine from their ioctl routines.
338 ppptioctl(tp, cmd, data, flag)
343 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
346 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
351 case PPPIOCSASYNCMAP:
354 sc->sc_asyncmap[0] = *(u_int *)data;
357 case PPPIOCGASYNCMAP:
358 *(u_int *)data = sc->sc_asyncmap[0];
361 case PPPIOCSRASYNCMAP:
364 sc->sc_rasyncmap = *(u_int *)data;
367 case PPPIOCGRASYNCMAP:
368 *(u_int *)data = sc->sc_rasyncmap;
371 case PPPIOCSXASYNCMAP:
374 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
375 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
376 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
377 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
380 case PPPIOCGXASYNCMAP:
381 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
385 error = pppioctl(sc, cmd, data, flag);
386 if (error == 0 && cmd == PPPIOCSMRU)
394 * FCS lookup table as calculated by genfcstab.
396 static u_short fcstab[256] = {
397 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
398 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
399 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
400 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
401 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
402 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
403 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
404 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
405 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
406 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
407 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
408 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
409 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
410 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
411 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
412 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
413 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
414 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
415 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
416 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
417 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
418 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
419 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
420 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
421 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
422 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
423 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
424 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
425 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
426 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
427 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
428 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
432 * Calculate a new FCS given the current FCS and the new data.
436 register u_short fcs;
441 fcs = PPP_FCS(fcs, *cp++);
446 * This gets called from pppoutput when a new packet is
451 register struct ppp_softc *sc;
453 register struct tty *tp = (struct tty *) sc->sc_devp;
459 * This gets called when a received packet is placed on
464 struct ppp_softc *sc;
468 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
469 tp = (struct tty *) sc->sc_devp;
470 putc(0, &tp->t_canq);
475 * Start output on async tty interface. Get another datagram
476 * to send from the interface queue and start sending it.
480 register struct tty *tp;
482 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
483 register struct mbuf *m;
485 register u_char *start, *stop, *cp;
486 int n, s, ndone, done;
489 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
490 /* sorry, I can't talk now */
493 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
500 * If there is more in the output queue, just send it now.
501 * We are being called in lieu of ttstart and must do what
504 if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
506 if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
511 * See if we have an existing packet partly sent.
512 * If not, get a new packet and start sending it.
517 * Get another packet to be sent.
524 * The extra PPP_FLAG will start up a new packet, and thus
525 * will flush any accumulated garbage. We do this whenever
526 * the line may have been idle for some time.
528 if (CCOUNT(&tp->t_outq) == 0) {
530 (void) putc(PPP_FLAG, &tp->t_outq);
533 /* Calculate the FCS for the first mbuf's worth. */
534 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
538 start = mtod(m, u_char *);
543 * Find out how many bytes in the string we can
544 * handle without doing something special.
546 for (cp = start; cp < stop; cp++)
551 ndone = n - b_to_q(start, n, &tp->t_outq);
554 sc->sc_bytessent += ndone;
557 break; /* packet doesn't fit */
560 * If there are characters left in the mbuf,
561 * the first one must be special..
562 * Put it out in a different form.
565 if (putc(PPP_ESCAPE, &tp->t_outq))
567 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
568 (void) unputc(&tp->t_outq);
571 sc->sc_bytessent += 2;
577 * If we didn't empty this mbuf, remember where we're up to.
578 * If we emptied the last mbuf, try to add the FCS and closing
579 * flag, and if we can't, leave sc_outm pointing to m, but with
580 * m->m_len == 0, to remind us to output the FCS and flag later.
583 if (done && m->m_next == NULL) {
589 * We may have to escape the bytes in the FCS.
592 c = ~sc->sc_outfcs & 0xFF;
595 *p++ = c ^ PPP_TRANS;
598 c = (~sc->sc_outfcs >> 8) & 0xFF;
601 *p++ = c ^ PPP_TRANS;
607 * Try to output the FCS and flag. If the bytes
608 * don't all fit, back out.
610 for (q = endseq; q < p; ++q)
611 if (putc(*q, &tp->t_outq)) {
613 for (; q > endseq; --q)
620 m->m_off += m->m_len - len;
623 if (tp->t_oproc != NULL)
625 return; /* can't do any more at the moment */
628 /* Finished with this mbuf; free it and move on. */
634 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
637 /* Finished a packet */
639 sc->sc_bytessent++; /* account for closing flag */
640 sc->sc_if.if_opackets++;
645 * Allocate enough mbuf to handle current MRU.
649 register struct ppp_softc *sc;
651 struct mbuf *m, **mp, *p;
657 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
658 if ((m = *mp) == NULL) {
659 MGET(m, M_DONTWAIT, MT_DATA);
665 len -= M_DATASIZE(m);
672 * tty interface receiver interrupt.
674 static unsigned paritytab[8] = {
675 0x96696996, 0x69969669, 0x69969669, 0x96696996,
676 0x69969669, 0x96696996, 0x96696996, 0x69969669
682 register struct tty *tp;
684 register struct ppp_softc *sc;
689 sc = (struct ppp_softc *) tp->t_sc;
690 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
698 sc->sc_flags |= SC_RCV_B7_1;
700 sc->sc_flags |= SC_RCV_B7_0;
701 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
702 sc->sc_flags |= SC_RCV_ODDP;
704 sc->sc_flags |= SC_RCV_EVNP;
706 if (sc->sc_flags & SC_LOG_RAWIN)
713 if (sc->sc_rawin_count > 0)
717 * If SC_ESCAPED is set, then we've seen the packet
718 * abort sequence "}~".
720 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
721 || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
722 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
723 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
724 if (sc->sc_flags & SC_DEBUG)
725 printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
727 sc->sc_if.if_ierrors++;
729 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
733 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
735 if (sc->sc_flags & SC_DEBUG)
736 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
737 sc->sc_if.if_ierrors++;
738 sc->sc_flags |= SC_PKTLOST;
744 * Remove FCS trailer. Somewhat painful...
747 if (--sc->sc_mc->m_len == 0) {
748 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
754 /* excise this mbuf chain */
756 sc->sc_m = sc->sc_mc->m_next;
757 sc->sc_mc->m_next = NULL;
759 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
760 sc->sc_flags &= ~SC_PKTLOST;
766 if (sc->sc_flags & SC_FLUSH) {
767 if (sc->sc_flags & SC_LOG_FLUSH)
772 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
775 if (sc->sc_flags & SC_ESCAPED) {
776 sc->sc_flags &= ~SC_ESCAPED;
778 } else if (c == PPP_ESCAPE) {
779 sc->sc_flags |= SC_ESCAPED;
784 * Initialize buffer on first octet received.
785 * First octet could be address or protocol (when compressing
787 * Second octet is control.
788 * Third octet is first or second (when compressing protocol)
790 * Fourth octet is second octet of protocol.
792 if (sc->sc_ilen == 0) {
793 /* reset the first input mbuf */
794 if (sc->sc_m == NULL) {
796 if (sc->sc_m == NULL) {
797 if (sc->sc_flags & SC_DEBUG)
798 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
804 m->m_off = M_OFFSTART(m);
806 sc->sc_mp = mtod(m, char *);
807 sc->sc_fcs = PPP_INITFCS;
808 if (c != PPP_ALLSTATIONS) {
809 if (sc->sc_flags & SC_REJ_COMP_AC) {
810 if (sc->sc_flags & SC_DEBUG)
811 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
812 sc->sc_if.if_unit, c);
815 *sc->sc_mp++ = PPP_ALLSTATIONS;
816 *sc->sc_mp++ = PPP_UI;
821 if (sc->sc_ilen == 1 && c != PPP_UI) {
822 if (sc->sc_flags & SC_DEBUG)
823 printf("ppp%d: missing UI (0x3), got 0x%x\n",
824 sc->sc_if.if_unit, c);
827 if (sc->sc_ilen == 2 && (c & 1) == 1) {
828 /* a compressed protocol */
833 if (sc->sc_ilen == 3 && (c & 1) == 0) {
834 if (sc->sc_flags & SC_DEBUG)
835 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
836 (sc->sc_mp[-1] << 8) + c);
840 /* packet beyond configured mru? */
841 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
842 if (sc->sc_flags & SC_DEBUG)
843 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
847 /* is this mbuf full? */
849 if (M_TRAILINGSPACE(m) <= 0) {
850 if (m->m_next == NULL) {
852 if (m->m_next == NULL) {
853 if (sc->sc_flags & SC_DEBUG)
854 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
858 sc->sc_mc = m = m->m_next;
860 m->m_off = M_OFFSTART(m);
861 sc->sc_mp = mtod(m, char *);
866 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
870 if (!(sc->sc_flags & SC_FLUSH)) {
871 sc->sc_if.if_ierrors++;
872 sc->sc_flags |= SC_FLUSH;
873 if (sc->sc_flags & SC_LOG_FLUSH)
878 #define MAX_DUMP_BYTES 128
882 struct ppp_softc *sc;
886 sc->sc_rawin[sc->sc_rawin_count++] = c;
887 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
888 || c < 0 && sc->sc_rawin_count > 0) {
889 printf("ppp%d input: ", sc->sc_if.if_unit);
890 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
891 sc->sc_rawin_count = 0;
900 char buf[3*MAX_DUMP_BYTES+4];
902 static char digits[] = "0123456789abcdef";
905 if (bp >= buf + sizeof(buf) - 3) {
909 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
910 *bp++ = digits[*b++ & 0xf];
918 #endif /* NPPP > 0 */