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.3 1995/08/16 01:36:40 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, ttymodem
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_CONNECTED) == 0 && (tp->t_state & TS_ISOPEN)) {
306 return 0; /* end of file */
308 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
310 return (EWOULDBLOCK);
312 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
319 /* Pull place-holder byte out of canonical queue */
322 /* Get the packet from the input queue */
323 IF_DEQUEUE(&sc->sc_inq, m0);
326 for (m = m0; m && uio->uio_resid; m = m->m_next)
327 if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
334 * Line specific (tty) write routine.
337 pppwrite(tp, uio, flag)
338 register struct tty *tp;
342 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
343 struct mbuf *m, *m0, **mp;
347 if ((tp->t_state & TS_CONNECTED) == 0)
348 return 0; /* wrote 0 bytes */
349 if (tp->t_line != PPPDISC)
351 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
353 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
354 uio->uio_resid < PPP_HDRLEN)
356 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
357 MGET(m, M_WAIT, MT_DATA);
358 if ((*mp = m) == NULL) {
363 if (uio->uio_resid >= MCLBYTES / 2)
364 MCLGET(m, M_DONTWAIT);
365 len = M_TRAILINGSPACE(m);
366 if (len > uio->uio_resid)
367 len = uio->uio_resid;
368 if (error = uiomove(mtod(m, u_char *), len, uio)) {
374 dst.sa_family = AF_UNSPEC;
375 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
376 m0->m_data += PPP_HDRLEN;
377 m0->m_len -= PPP_HDRLEN;
378 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
382 * Line specific (tty) ioctl routine.
383 * This discipline requires that tty device drivers call
384 * the line specific l_ioctl routine from their ioctl routines.
388 ppptioctl(tp, cmd, data, flag, p)
394 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
397 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
402 case PPPIOCSASYNCMAP:
403 if (error = suser(p->p_ucred, &p->p_acflag))
405 sc->sc_asyncmap[0] = *(u_int *)data;
408 case PPPIOCGASYNCMAP:
409 *(u_int *)data = sc->sc_asyncmap[0];
412 case PPPIOCSRASYNCMAP:
413 if (error = suser(p->p_ucred, &p->p_acflag))
415 sc->sc_rasyncmap = *(u_int *)data;
418 case PPPIOCGRASYNCMAP:
419 *(u_int *)data = sc->sc_rasyncmap;
422 case PPPIOCSXASYNCMAP:
423 if (error = suser(p->p_ucred, &p->p_acflag))
426 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
427 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
428 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
429 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
433 case PPPIOCGXASYNCMAP:
434 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
438 error = pppioctl(sc, cmd, data, flag, p);
439 if (error == 0 && cmd == PPPIOCSMRU)
447 * FCS lookup table as calculated by genfcstab.
449 static u_short fcstab[256] = {
450 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
451 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
452 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
453 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
454 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
455 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
456 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
457 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
458 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
459 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
460 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
461 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
462 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
463 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
464 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
465 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
466 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
467 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
468 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
469 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
470 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
471 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
472 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
473 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
474 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
475 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
476 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
477 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
478 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
479 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
480 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
481 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
485 * Calculate a new FCS given the current FCS and the new data.
489 register u_short fcs;
494 fcs = PPP_FCS(fcs, *cp++);
499 * This gets called from pppoutput when a new packet is
504 register struct ppp_softc *sc;
506 register struct tty *tp = (struct tty *) sc->sc_devp;
515 * This gets called when a received packet is placed on
520 struct ppp_softc *sc;
524 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
525 tp = (struct tty *) sc->sc_devp;
526 putc(0, &tp->t_canq);
531 * Start output on async tty interface. Get another datagram
532 * to send from the interface queue and start sending it.
536 register struct tty *tp;
538 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
539 register struct mbuf *m;
541 register u_char *start, *stop, *cp;
542 int n, s, ndone, done, idle;
545 if ((tp->t_state & TS_CONNECTED) == 0
546 || sc == NULL || tp != (struct tty *) sc->sc_devp) {
547 if (tp->t_oproc != NULL)
553 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
555 * See if we have an existing packet partly sent.
556 * If not, get a new packet and start sending it.
561 * Get another packet to be sent.
570 * The extra PPP_FLAG will start up a new packet, and thus
571 * will flush any accumulated garbage. We do this whenever
572 * the line may have been idle for some time.
574 if (CCOUNT(&tp->t_outq) == 0) {
576 (void) putc(PPP_FLAG, &tp->t_outq);
579 /* Calculate the FCS for the first mbuf's worth. */
580 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
584 start = mtod(m, u_char *);
589 * Find out how many bytes in the string we can
590 * handle without doing something special.
592 for (cp = start; cp < stop; cp++)
597 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
598 ndone = n - b_to_q(start, n, &tp->t_outq);
601 sc->sc_bytessent += ndone;
604 break; /* packet doesn't fit */
607 * If there are characters left in the mbuf,
608 * the first one must be special..
609 * Put it out in a different form.
612 if (putc(PPP_ESCAPE, &tp->t_outq))
614 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
615 (void) unputc(&tp->t_outq);
618 sc->sc_bytessent += 2;
625 * If we didn't empty this mbuf, remember where we're up to.
626 * If we emptied the last mbuf, try to add the FCS and closing
627 * flag, and if we can't, leave sc_outm pointing to m, but with
628 * m->m_len == 0, to remind us to output the FCS and flag later.
631 if (done && m->m_next == NULL) {
637 * We may have to escape the bytes in the FCS.
640 c = ~sc->sc_outfcs & 0xFF;
643 *p++ = c ^ PPP_TRANS;
646 c = (~sc->sc_outfcs >> 8) & 0xFF;
649 *p++ = c ^ PPP_TRANS;
655 * Try to output the FCS and flag. If the bytes
656 * don't all fit, back out.
658 for (q = endseq; q < p; ++q)
659 if (putc(*q, &tp->t_outq)) {
661 for (; q > endseq; --q)
665 sc->sc_bytessent += q - endseq;
669 /* remember where we got to */
675 /* Finished with this mbuf; free it and move on. */
679 /* Finished a packet */
680 sc->sc_if.if_opackets++;
681 sc->sc_if.if_obytes = sc->sc_bytessent;
684 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
688 * Here we have either finished a packet (m == NULL)
689 * or filled up the output queue (m != NULL).
697 * Send anything that may be in the output queue.
698 * We are being called in lieu of ttstart and must do what it would.
700 if (tp->t_oproc != NULL)
704 * This timeout is needed for operation on a pseudo-tty,
705 * because the pty code doesn't call pppstart after it has
706 * drained the t_outq.
708 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
709 timeout(ppp_timeout, (void *) sc, 1);
710 sc->sc_flags |= SC_TIMEOUT;
717 * Timeout routine - try to start some more output.
723 struct ppp_softc *sc = (struct ppp_softc *) x;
724 struct tty *tp = (struct tty *) sc->sc_devp;
728 sc->sc_flags &= ~SC_TIMEOUT;
734 * Allocate enough mbuf to handle current MRU.
738 register struct ppp_softc *sc;
740 struct mbuf *m, **mp;
746 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
747 if ((m = *mp) == NULL) {
748 MGETHDR(m, M_DONTWAIT, MT_DATA);
752 MCLGET(m, M_DONTWAIT);
754 len -= M_DATASIZE(m);
761 * tty interface receiver interrupt.
763 static unsigned paritytab[8] = {
764 0x96696996, 0x69969669, 0x69969669, 0x96696996,
765 0x69969669, 0x96696996, 0x96696996, 0x69969669
771 register struct tty *tp;
773 register struct ppp_softc *sc;
777 sc = (struct ppp_softc *) tp->t_sc;
778 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
786 /* framing error or overrun on this char - abort packet */
787 if (sc->sc_flags & SC_DEBUG)
788 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
795 sc->sc_flags |= SC_RCV_B7_1;
797 sc->sc_flags |= SC_RCV_B7_0;
798 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
799 sc->sc_flags |= SC_RCV_ODDP;
801 sc->sc_flags |= SC_RCV_EVNP;
803 if (sc->sc_flags & SC_LOG_RAWIN)
809 sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
811 if (sc->sc_rawin_count > 0)
815 * If SC_ESCAPED is set, then we've seen the packet
816 * abort sequence "}~".
818 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
819 || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
820 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
821 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
822 if (sc->sc_flags & SC_DEBUG)
823 printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
825 sc->sc_if.if_ierrors++;
827 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
832 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
834 if (sc->sc_flags & SC_DEBUG)
835 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
836 sc->sc_if.if_ierrors++;
837 sc->sc_flags |= SC_PKTLOST;
844 * Remove FCS trailer. Somewhat painful...
847 if (--sc->sc_mc->m_len == 0) {
848 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
854 /* excise this mbuf chain */
856 sc->sc_m = sc->sc_mc->m_next;
857 sc->sc_mc->m_next = NULL;
859 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
860 sc->sc_flags &= ~SC_PKTLOST;
867 if (sc->sc_flags & SC_FLUSH) {
868 if (sc->sc_flags & SC_LOG_FLUSH)
874 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
879 if (sc->sc_flags & SC_ESCAPED) {
880 sc->sc_flags &= ~SC_ESCAPED;
882 } else if (c == PPP_ESCAPE) {
883 sc->sc_flags |= SC_ESCAPED;
889 * Initialize buffer on first octet received.
890 * First octet could be address or protocol (when compressing
892 * Second octet is control.
893 * Third octet is first or second (when compressing protocol)
895 * Fourth octet is second octet of protocol.
897 if (sc->sc_ilen == 0) {
898 /* reset the first input mbuf */
899 if (sc->sc_m == NULL) {
901 if (sc->sc_m == NULL) {
902 if (sc->sc_flags & SC_DEBUG)
903 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
909 m->m_data = M_DATASTART(sc->sc_m);
911 sc->sc_mp = mtod(m, char *);
912 sc->sc_fcs = PPP_INITFCS;
913 if (c != PPP_ALLSTATIONS) {
914 if (sc->sc_flags & SC_REJ_COMP_AC) {
915 if (sc->sc_flags & SC_DEBUG)
916 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
917 sc->sc_if.if_unit, c);
920 *sc->sc_mp++ = PPP_ALLSTATIONS;
921 *sc->sc_mp++ = PPP_UI;
926 if (sc->sc_ilen == 1 && c != PPP_UI) {
927 if (sc->sc_flags & SC_DEBUG)
928 printf("ppp%d: missing UI (0x3), got 0x%x\n",
929 sc->sc_if.if_unit, c);
932 if (sc->sc_ilen == 2 && (c & 1) == 1) {
933 /* a compressed protocol */
938 if (sc->sc_ilen == 3 && (c & 1) == 0) {
939 if (sc->sc_flags & SC_DEBUG)
940 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
941 (sc->sc_mp[-1] << 8) + c);
945 /* packet beyond configured mru? */
946 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
947 if (sc->sc_flags & SC_DEBUG)
948 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
952 /* is this mbuf full? */
954 if (M_TRAILINGSPACE(m) <= 0) {
955 if (m->m_next == NULL) {
957 if (m->m_next == NULL) {
958 if (sc->sc_flags & SC_DEBUG)
959 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
963 sc->sc_mc = m = m->m_next;
965 m->m_data = M_DATASTART(m);
966 sc->sc_mp = mtod(m, char *);
971 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
976 if (!(sc->sc_flags & SC_FLUSH)) {
977 sc->sc_if.if_ierrors++;
978 sc->sc_flags |= SC_FLUSH;
979 if (sc->sc_flags & SC_LOG_FLUSH)
986 #define MAX_DUMP_BYTES 128
990 struct ppp_softc *sc;
994 sc->sc_rawin[sc->sc_rawin_count++] = c;
995 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
996 || c < 0 && sc->sc_rawin_count > 0) {
997 printf("ppp%d input: ", sc->sc_if.if_unit);
998 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
999 sc->sc_rawin_count = 0;
1008 char buf[3*MAX_DUMP_BYTES+4];
1010 static char digits[] = "0123456789abcdef";
1013 if (bp >= buf + sizeof(buf) - 3) {
1017 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1018 *bp++ = digits[*b++ & 0xf];
1023 printf("%s\n", buf);
1026 #endif /* NPPP > 0 */