1 /* $Id: ppp_tty.c,v 1.3 1996/07/01 01:04:11 paulus Exp $ */
4 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
7 * Copyright (c) 1989 Carnegie Mellon University.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Carnegie Mellon University. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * Carnegie Mellon University
25 * Pittsburgh, PA 15213
30 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
32 * Copyright (c) 1987 Regents of the University of California.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms are permitted
36 * provided that the above copyright notice and this paragraph are
37 * duplicated in all such forms and that any documentation,
38 * advertising materials, and other materials related to such
39 * distribution and use acknowledge that the software was developed
40 * by the University of California, Berkeley. The name of the
41 * University may not be used to endorse or promote products derived
42 * from this software without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
47 * Serial Line interface
50 * Center for Seismic Studies
51 * 1300 N 17th Street, Suite 1450
52 * Arlington, Virginia 22209
57 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
58 * Converted to 4.3BSD Beta by Chris Torek.
59 * Other changes made at Berkeley, based in part on code by Kirk Smith.
61 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
62 * Added VJ tcp header compression; more unified ioctls
64 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
65 * Cleaned up a lot of the mbuf-related code to fix bugs that
66 * caused system crashes and packet corruption. Changed pppstart
67 * so that it doesn't just give up with a "collision" if the whole
68 * packet doesn't fit in the output ring buffer.
70 * Added priority queueing for interactive IP packets, following
71 * the model of if_sl.c, plus hooks for bpf.
72 * Paul Mackerras (paulus@cs.anu.edu.au).
75 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
76 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
84 #include <sys/param.h>
87 #include <sys/dkstat.h>
88 #include <sys/socket.h>
89 #include <sys/ioctl.h>
92 #include <sys/kernel.h>
94 #include <sys/vnode.h>
95 #include <sys/systm.h>
98 #include <net/if_types.h>
101 #include <netinet/in.h>
102 #include <netinet/in_systm.h>
103 #include <netinet/ip.h>
104 #include <net/slcompress.h>
107 #include <net/ppp_defs.h>
108 #include <net/if_ppp.h>
109 #include <net/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, u_long 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_int16_t pppfcs __P((u_int16_t 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 pppasyncrelinq __P((struct ppp_softc *));
124 static void ppp_timeout __P((void *));
125 static void pppgetm __P((struct ppp_softc *sc));
126 static void pppdumpb __P((u_char *b, int l));
127 static void ppplogchar __P((struct ppp_softc *, int));
130 * Some useful mbuf macros not in mbuf.h.
132 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
134 #define M_DATASTART(m) \
135 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
136 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
138 #define M_DATASIZE(m) \
139 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
140 (m)->m_flags & M_PKTHDR ? MHLEN: 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.
151 /* This is a NetBSD-1.0 or later kernel. */
152 #define CCOUNT(q) ((q)->c_cc)
154 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
155 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
158 * Line specific open routine for async tty devices.
159 * Attach the given tty to the first available ppp unit.
160 * Called from device open routine or ttioctl.
166 register struct tty *tp;
168 struct proc *p = curproc; /* XXX */
169 register struct ppp_softc *sc;
172 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
177 if (tp->t_line == PPPDISC) {
178 sc = (struct ppp_softc *) tp->t_sc;
179 if (sc != NULL && sc->sc_devp == (void *) tp) {
185 if ((sc = pppalloc(p->p_pid)) == NULL) {
191 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
195 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
196 sc->sc_asyncmap[0] = 0xffffffff;
197 sc->sc_asyncmap[3] = 0x60000000;
198 sc->sc_rasyncmap = 0;
199 sc->sc_devp = (void *) tp;
200 sc->sc_start = pppasyncstart;
201 sc->sc_ctlp = pppasyncctlp;
202 sc->sc_relinq = pppasyncrelinq;
205 sc->sc_if.if_flags |= IFF_RUNNING;
206 sc->sc_if.if_baudrate = tp->t_ospeed;
208 tp->t_sc = (caddr_t) sc;
209 ttyflush(tp, FREAD | FWRITE);
216 * Line specific close routine, called from device close routine
218 * Detach the tty from the ppp unit.
219 * Mimics part of ttyclose().
226 register struct ppp_softc *sc;
230 ttyflush(tp, FREAD|FWRITE);
232 sc = (struct ppp_softc *) tp->t_sc;
235 if (tp == (struct tty *) sc->sc_devp) {
245 * Relinquish the interface unit to another device.
249 struct ppp_softc *sc;
255 m_freem(sc->sc_outm);
262 if (sc->sc_flags & SC_TIMEOUT) {
263 untimeout(ppp_timeout, (void *) sc);
264 sc->sc_flags &= ~SC_TIMEOUT;
270 * Line specific (tty) read routine.
273 pppread(tp, uio, flag)
274 register struct tty *tp;
278 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
286 * Loop waiting for input, checking that nothing disasterous
287 * happens in the meantime.
291 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
295 if (sc->sc_inq.ifq_head != NULL)
297 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0
298 && (tp->t_state & TS_ISOPEN)) {
300 return 0; /* end of file */
302 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
304 return (EWOULDBLOCK);
306 error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
313 /* Pull place-holder byte out of canonical queue */
316 /* Get the packet from the input queue */
317 IF_DEQUEUE(&sc->sc_inq, m0);
320 for (m = m0; m && uio->uio_resid; m = m->m_next)
321 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
328 * Line specific (tty) write routine.
331 pppwrite(tp, uio, flag)
332 register struct tty *tp;
336 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
337 struct mbuf *m, *m0, **mp;
341 if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
342 return 0; /* wrote 0 bytes */
343 if (tp->t_line != PPPDISC)
345 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
347 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
348 uio->uio_resid < PPP_HDRLEN)
350 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
351 MGET(m, M_WAIT, MT_DATA);
352 if ((*mp = m) == NULL) {
357 if (uio->uio_resid >= MCLBYTES / 2)
358 MCLGET(m, M_DONTWAIT);
359 len = M_TRAILINGSPACE(m);
360 if (len > uio->uio_resid)
361 len = uio->uio_resid;
362 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
368 dst.sa_family = AF_UNSPEC;
369 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
370 m0->m_data += PPP_HDRLEN;
371 m0->m_len -= PPP_HDRLEN;
372 return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
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, p)
389 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
392 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
397 case PPPIOCSASYNCMAP:
398 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
400 sc->sc_asyncmap[0] = *(u_int *)data;
403 case PPPIOCGASYNCMAP:
404 *(u_int *)data = sc->sc_asyncmap[0];
407 case PPPIOCSRASYNCMAP:
408 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
410 sc->sc_rasyncmap = *(u_int *)data;
413 case PPPIOCGRASYNCMAP:
414 *(u_int *)data = sc->sc_rasyncmap;
417 case PPPIOCSXASYNCMAP:
418 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
421 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
422 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
423 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
424 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
428 case PPPIOCGXASYNCMAP:
429 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
433 error = pppioctl(sc, cmd, data, flag, p);
434 if (error == 0 && cmd == PPPIOCSMRU)
442 * FCS lookup table as calculated by genfcstab.
444 static u_int16_t fcstab[256] = {
445 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
446 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
447 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
448 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
449 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
450 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
451 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
452 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
453 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
454 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
455 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
456 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
457 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
458 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
459 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
460 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
461 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
462 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
463 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
464 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
465 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
466 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
467 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
468 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
469 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
470 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
471 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
472 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
473 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
474 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
475 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
476 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
480 * Calculate a new FCS given the current FCS and the new data.
484 register u_int16_t fcs;
489 fcs = PPP_FCS(fcs, *cp++);
494 * This gets called at splsoftnet from if_ppp.c at various times
495 * when there is data ready to be sent.
499 register struct ppp_softc *sc;
501 register struct tty *tp = (struct tty *) sc->sc_devp;
502 register struct mbuf *m;
504 register u_char *start, *stop, *cp;
505 int n, ndone, done, idle;
510 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
512 * See if we have an existing packet partly sent.
513 * If not, get a new packet and start sending it.
518 * Get another packet to be sent.
527 * The extra PPP_FLAG will start up a new packet, and thus
528 * will flush any accumulated garbage. We do this whenever
529 * the line may have been idle for some time.
531 if (CCOUNT(&tp->t_outq) == 0) {
532 ++sc->sc_stats.ppp_obytes;
533 (void) putc(PPP_FLAG, &tp->t_outq);
536 /* Calculate the FCS for the first mbuf's worth. */
537 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
538 sc->sc_if.if_lastchange = time;
542 start = mtod(m, u_char *);
547 * Find out how many bytes in the string we can
548 * handle without doing something special.
550 for (cp = start; cp < stop; cp++)
555 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
556 ndone = n - b_to_q(start, n, &tp->t_outq);
559 sc->sc_stats.ppp_obytes += ndone;
562 break; /* packet doesn't fit */
565 * If there are characters left in the mbuf,
566 * the first one must be special.
567 * Put it out in a different form.
571 if (putc(PPP_ESCAPE, &tp->t_outq))
573 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
574 (void) unputc(&tp->t_outq);
579 sc->sc_stats.ppp_obytes += 2;
586 * If we didn't empty this mbuf, remember where we're up to.
587 * If we emptied the last mbuf, try to add the FCS and closing
588 * flag, and if we can't, leave sc_outm pointing to m, but with
589 * m->m_len == 0, to remind us to output the FCS and flag later.
592 if (done && m->m_next == NULL) {
598 * We may have to escape the bytes in the FCS.
601 c = ~sc->sc_outfcs & 0xFF;
604 *p++ = c ^ PPP_TRANS;
607 c = (~sc->sc_outfcs >> 8) & 0xFF;
610 *p++ = c ^ PPP_TRANS;
616 * Try to output the FCS and flag. If the bytes
617 * don't all fit, back out.
620 for (q = endseq; q < p; ++q)
621 if (putc(*q, &tp->t_outq)) {
623 for (; q > endseq; --q)
629 sc->sc_stats.ppp_obytes += q - endseq;
633 /* remember where we got to */
639 /* Finished with this mbuf; free it and move on. */
643 /* Finished a packet */
646 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
650 * If m == NULL, we have finished a packet.
651 * If m != NULL, we've either done as much work this time
652 * as we need to, or else we've filled up the output queue.
659 /* Call pppstart to start output again if necessary. */
664 * This timeout is needed for operation on a pseudo-tty,
665 * because the pty code doesn't call pppstart after it has
666 * drained the t_outq.
668 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
669 timeout(ppp_timeout, (void *) sc, 1);
670 sc->sc_flags |= SC_TIMEOUT;
677 * This gets called when a received packet is placed on
678 * the inq, at splsoftnet.
682 struct ppp_softc *sc;
687 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
689 tp = (struct tty *) sc->sc_devp;
690 putc(0, &tp->t_canq);
696 * Start output on async tty interface. If the transmit queue
697 * has drained sufficiently, arrange for pppasyncstart to be
698 * called later at splsoftnet.
699 * Called at spltty or higher.
703 register struct tty *tp;
705 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
708 * If there is stuff in the output queue, send it now.
709 * We are being called in lieu of ttstart and must do what it would.
711 if (tp->t_oproc != NULL)
715 * If the transmit queue has drained and the tty has not hung up
716 * or been disconnected from the ppp unit, then tell if_ppp.c that
717 * we need more output.
719 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
720 && !((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
721 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
729 * Timeout routine - try to start some more output.
735 struct ppp_softc *sc = (struct ppp_softc *) x;
736 struct tty *tp = (struct tty *) sc->sc_devp;
740 sc->sc_flags &= ~SC_TIMEOUT;
746 * Allocate enough mbuf to handle current MRU.
750 register struct ppp_softc *sc;
752 struct mbuf *m, **mp;
756 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
757 if ((m = *mp) == NULL) {
758 MGETHDR(m, M_DONTWAIT, MT_DATA);
762 MCLGET(m, M_DONTWAIT);
764 len -= M_DATASIZE(m);
770 * tty interface receiver interrupt.
772 static unsigned paritytab[8] = {
773 0x96696996, 0x69969669, 0x69969669, 0x96696996,
774 0x69969669, 0x96696996, 0x96696996, 0x69969669
780 register struct tty *tp;
782 register struct ppp_softc *sc;
786 sc = (struct ppp_softc *) tp->t_sc;
787 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
791 ++sc->sc_stats.ppp_ibytes;
794 /* framing error or overrun on this char - abort packet */
795 if (sc->sc_flags & SC_DEBUG)
796 printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
803 * Handle software flow control of output.
805 if (tp->t_iflag & IXON) {
806 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
807 if ((tp->t_state & TS_TTSTOP) == 0) {
808 tp->t_state |= TS_TTSTOP;
809 (*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
813 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
814 tp->t_state &= ~TS_TTSTOP;
815 if (tp->t_oproc != NULL)
823 sc->sc_flags |= SC_RCV_B7_1;
825 sc->sc_flags |= SC_RCV_B7_0;
826 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
827 sc->sc_flags |= SC_RCV_ODDP;
829 sc->sc_flags |= SC_RCV_EVNP;
832 if (sc->sc_flags & SC_LOG_RAWIN)
839 if (sc->sc_rawin_count > 0)
843 * If SC_ESCAPED is set, then we've seen the packet
844 * abort sequence "}~".
846 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
847 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
849 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
850 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
851 if (sc->sc_flags & SC_DEBUG)
852 printf("ppp%d: bad fcs %x, pkt len %d\n",
853 sc->sc_if.if_unit, sc->sc_fcs, ilen);
854 sc->sc_if.if_ierrors++;
855 sc->sc_stats.ppp_ierrors++;
857 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
862 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
864 if (sc->sc_flags & SC_DEBUG)
865 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
867 sc->sc_if.if_ierrors++;
868 sc->sc_stats.ppp_ierrors++;
869 sc->sc_flags |= SC_PKTLOST;
876 * Remove FCS trailer. Somewhat painful...
879 if (--sc->sc_mc->m_len == 0) {
880 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
886 /* excise this mbuf chain */
888 sc->sc_m = sc->sc_mc->m_next;
889 sc->sc_mc->m_next = NULL;
891 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
892 if (sc->sc_flags & SC_PKTLOST) {
894 sc->sc_flags &= ~SC_PKTLOST;
902 if (sc->sc_flags & SC_FLUSH) {
903 if (sc->sc_flags & SC_LOG_FLUSH)
908 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
912 if (sc->sc_flags & SC_ESCAPED) {
913 sc->sc_flags &= ~SC_ESCAPED;
915 } else if (c == PPP_ESCAPE) {
916 sc->sc_flags |= SC_ESCAPED;
923 * Initialize buffer on first octet received.
924 * First octet could be address or protocol (when compressing
926 * Second octet is control.
927 * Third octet is first or second (when compressing protocol)
929 * Fourth octet is second octet of protocol.
931 if (sc->sc_ilen == 0) {
932 /* reset the first input mbuf */
933 if (sc->sc_m == NULL) {
935 if (sc->sc_m == NULL) {
936 if (sc->sc_flags & SC_DEBUG)
937 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
943 m->m_data = M_DATASTART(sc->sc_m);
945 sc->sc_mp = mtod(m, char *);
946 sc->sc_fcs = PPP_INITFCS;
947 if (c != PPP_ALLSTATIONS) {
948 if (sc->sc_flags & SC_REJ_COMP_AC) {
949 if (sc->sc_flags & SC_DEBUG)
950 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
951 sc->sc_if.if_unit, c);
954 *sc->sc_mp++ = PPP_ALLSTATIONS;
955 *sc->sc_mp++ = PPP_UI;
960 if (sc->sc_ilen == 1 && c != PPP_UI) {
961 if (sc->sc_flags & SC_DEBUG)
962 printf("ppp%d: missing UI (0x3), got 0x%x\n",
963 sc->sc_if.if_unit, c);
966 if (sc->sc_ilen == 2 && (c & 1) == 1) {
967 /* a compressed protocol */
972 if (sc->sc_ilen == 3 && (c & 1) == 0) {
973 if (sc->sc_flags & SC_DEBUG)
974 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
975 (sc->sc_mp[-1] << 8) + c);
979 /* packet beyond configured mru? */
980 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
981 if (sc->sc_flags & SC_DEBUG)
982 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
986 /* is this mbuf full? */
988 if (M_TRAILINGSPACE(m) <= 0) {
989 if (m->m_next == NULL) {
991 if (m->m_next == NULL) {
992 if (sc->sc_flags & SC_DEBUG)
993 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
997 sc->sc_mc = m = m->m_next;
999 m->m_data = M_DATASTART(m);
1000 sc->sc_mp = mtod(m, char *);
1005 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1009 if (!(sc->sc_flags & SC_FLUSH)) {
1011 sc->sc_if.if_ierrors++;
1012 sc->sc_stats.ppp_ierrors++;
1013 sc->sc_flags |= SC_FLUSH;
1015 if (sc->sc_flags & SC_LOG_FLUSH)
1021 #define MAX_DUMP_BYTES 128
1025 struct ppp_softc *sc;
1029 sc->sc_rawin[sc->sc_rawin_count++] = c;
1030 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1031 || (c < 0 && sc->sc_rawin_count > 0)) {
1032 printf("ppp%d input: ", sc->sc_if.if_unit);
1033 pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1034 sc->sc_rawin_count = 0;
1043 char buf[3*MAX_DUMP_BYTES+4];
1045 static char digits[] = "0123456789abcdef";
1048 if (bp >= buf + sizeof(buf) - 3) {
1052 *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1053 *bp++ = digits[*b++ & 0xf];
1058 printf("%s\n", buf);
1061 #endif /* NPPP > 0 */