2 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
6 * Copyright (c) 1989 Carnegie Mellon University.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by Carnegie Mellon University. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 * Carnegie Mellon University
24 * Pittsburgh, PA 15213
29 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
31 * Copyright (c) 1987 Regents of the University of California.
32 * All rights reserved.
34 * Redistribution and use in source and binary forms are permitted
35 * provided that the above copyright notice and this paragraph are
36 * duplicated in all such forms and that any documentation,
37 * advertising materials, and other materials related to such
38 * distribution and use acknowledge that the software was developed
39 * by the University of California, Berkeley. The name of the
40 * University may not be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
43 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
44 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
46 * Serial Line interface
49 * Center for Seismic Studies
50 * 1300 N 17th Street, Suite 1450
51 * Arlington, Virginia 22209
56 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
57 * Converted to 4.3BSD Beta by Chris Torek.
58 * Other changes made at Berkeley, based in part on code by Kirk Smith.
60 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
61 * Added VJ tcp header compression; more unified ioctls
63 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
64 * Cleaned up a lot of the mbuf-related code to fix bugs that
65 * caused system crashes and packet corruption. Changed pppstart
66 * so that it doesn't just give up with a "collision" if the whole
67 * packet doesn't fit in the output ring buffer.
69 * Added priority queueing for interactive IP packets, following
70 * the model of if_sl.c, plus hooks for bpf.
71 * Paul Mackerras (paulus@cs.anu.edu.au).
76 #include "opt_ppp.h" /* XXX for ppp_defs.h */
78 #define VJC /* XXX for ppp_defs.h */
80 #include <sys/param.h>
81 #include <sys/systm.h>
84 #include <sys/socket.h>
85 #include <sys/fcntl.h>
93 #include <net/if_ppp.h>
94 #include <net/if_pppvar.h>
96 static int pppopen(struct cdev *dev, struct tty *tp);
97 static int pppclose(struct tty *tp, int flag);
98 static int pppread(struct tty *tp, struct uio *uio, int flag);
99 static int pppwrite(struct tty *tp, struct uio *uio, int flag);
100 static int ppptioctl(struct tty *tp, u_long cmd, caddr_t data,
101 int flag, struct thread *td);
102 static int pppinput(int c, struct tty *tp);
103 static int pppstart(struct tty *tp);
105 static u_short pppfcs(u_short fcs, u_char *cp, int len);
106 static void pppasyncstart(struct ppp_softc *);
107 static void pppasyncctlp(struct ppp_softc *);
108 static void pppasyncrelinq(struct ppp_softc *);
109 static void pppasyncsetmtu(struct ppp_softc *);
110 static void ppp_timeout(void *);
111 static void pppgetm(struct ppp_softc *sc);
112 static void ppplogchar(struct ppp_softc *, int);
114 /* XXX called from if_ppp.c - layering violation */
115 void pppasyncattach(void *);
116 void pppasyncdetach(void);
119 * Some useful mbuf macros not in mbuf.h.
121 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
123 #define M_DATASTART(m) \
124 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
125 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
127 #define M_DATASIZE(m) \
128 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
129 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
132 * Does c need to be escaped?
134 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
137 * Procedures for using an async tty interface for PPP.
140 /* This is a FreeBSD-2.X kernel. */
141 #define CCOUNT(q) ((q)->c_cc)
142 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
143 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
146 * Define the PPP line discipline.
149 static struct linesw pppdisc = {
150 pppopen, pppclose, pppread, pppwrite,
151 ppptioctl, pppinput, pppstart, ttymodem
155 pppasyncattach(dummy)
158 ldisc_register(PPPDISC, &pppdisc);
164 ldisc_deregister(PPPDISC);
168 * Line specific open routine for async tty devices.
169 * Attach the given tty to the first available ppp unit.
170 * Called from device open routine or ttioctl() at >= splsofttty()
176 register struct tty *tp;
178 struct thread *td = curthread; /* XXX */
179 register struct ppp_softc *sc;
182 if ((error = suser(td)) != 0)
187 tp->t_hotchar = PPP_FLAG;
189 if ((sc = pppalloc(td->td_proc->p_pid)) == NULL) {
195 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
199 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
200 sc->sc_asyncmap[0] = 0xffffffff;
201 sc->sc_asyncmap[3] = 0x60000000;
202 sc->sc_rasyncmap = 0;
203 sc->sc_devp = (void *) tp;
204 sc->sc_start = pppasyncstart;
205 sc->sc_ctlp = pppasyncctlp;
206 sc->sc_relinq = pppasyncrelinq;
207 sc->sc_setmtu = pppasyncsetmtu;
210 PPP2IFP(sc)->if_drv_flags |= IFF_DRV_RUNNING;
211 getmicrotime(&PPP2IFP(sc)->if_lastchange);
212 PPP2IFP(sc)->if_baudrate = tp->t_ospeed;
214 tp->t_hotchar = PPP_FLAG;
216 ttyflush(tp, FREAD | FWRITE);
219 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
220 * allocation helps avoid the need for select and/or FIONREAD.
221 * We also pass 1 byte tokens through t_canq...
223 clist_alloc_cblocks(&tp->t_canq, 1, 1);
224 clist_alloc_cblocks(&tp->t_outq, PPP2IFP(sc)->if_mtu + PPP_HIWAT,
225 PPP2IFP(sc)->if_mtu + PPP_HIWAT);
226 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
234 * Line specific close routine, called from device close routine
235 * and from ttioctl at >= splsofttty().
236 * Detach the tty from the ppp unit.
237 * Mimics part of tty_close().
244 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
248 ttyflush(tp, FREAD | FWRITE);
249 clist_free_cblocks(&tp->t_canq);
250 clist_free_cblocks(&tp->t_outq);
260 * Relinquish the interface unit to another device.
264 struct ppp_softc *sc;
270 m_freem(sc->sc_outm);
277 if (sc->sc_flags & SC_TIMEOUT) {
278 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
279 sc->sc_flags &= ~SC_TIMEOUT;
285 * This gets called from the upper layer to notify a mtu change
289 register struct ppp_softc *sc;
291 register struct tty *tp = (struct tty *) sc->sc_devp;
296 clist_alloc_cblocks(&tp->t_outq, PPP2IFP(sc)->if_mtu + PPP_HIWAT,
297 PPP2IFP(sc)->if_mtu + PPP_HIWAT);
302 * Line specific (tty) read routine.
303 * called at zero spl from the device driver in the response to user-level
304 * reads on the tty file descriptor (ie: pppd).
307 pppread(tp, uio, flag)
308 register struct tty *tp;
312 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
320 * Loop waiting for input, checking that nothing disasterous
321 * happens in the meantime.
325 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
329 if (sc->sc_inq.ifq_head != NULL)
331 if ((tp->t_state & TS_CONNECTED) == 0) {
333 return 0; /* end of file */
335 if (tp->t_state & TS_ASYNC || flag & O_NONBLOCK) {
337 return (EWOULDBLOCK);
339 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
346 /* Pull place-holder byte out of canonical queue */
349 /* Get the packet from the input queue */
350 IF_DEQUEUE(&sc->sc_inq, m0);
353 for (m = m0; m && uio->uio_resid; m = m->m_next)
354 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
361 * Line specific (tty) write routine.
362 * called at zero spl from the device driver in the response to user-level
363 * writes on the tty file descriptor (ie: pppd).
366 pppwrite(tp, uio, flag)
367 register struct tty *tp;
371 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
376 if ((tp->t_state & TS_CONNECTED) == 0)
377 return 0; /* wrote 0 bytes */
378 if (tp->t_line != PPPDISC)
382 if (uio->uio_resid > PPP2IFP(sc)->if_mtu + PPP_HDRLEN ||
383 uio->uio_resid < PPP_HDRLEN)
387 if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) {
392 dst.sa_family = AF_UNSPEC;
393 bcopy(mtod(m, u_char *), dst.sa_data, PPP_HDRLEN);
394 m->m_data += PPP_HDRLEN;
395 m->m_len -= PPP_HDRLEN;
397 /* call the upper layer to "transmit" it... */
398 error = pppoutput(PPP2IFP(sc), m, &dst, NULL);
404 * Line specific (tty) ioctl routine.
405 * This discipline requires that tty device drivers call
406 * the line specific l_ioctl routine from their ioctl routines.
410 ppptioctl(tp, cmd, data, flag, td)
417 struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
420 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
425 case PPPIOCSASYNCMAP:
426 if ((error = suser(td)) != 0)
428 sc->sc_asyncmap[0] = *(u_int *)data;
431 case PPPIOCGASYNCMAP:
432 *(u_int *)data = sc->sc_asyncmap[0];
435 case PPPIOCSRASYNCMAP:
436 if ((error = suser(td)) != 0)
438 sc->sc_rasyncmap = *(u_int *)data;
441 case PPPIOCGRASYNCMAP:
442 *(u_int *)data = sc->sc_rasyncmap;
445 case PPPIOCSXASYNCMAP:
446 if ((error = suser(td)) != 0)
449 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
450 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
451 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
452 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
456 case PPPIOCGXASYNCMAP:
457 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
461 error = pppioctl(sc, cmd, data, flag, td);
462 if (error == 0 && cmd == PPPIOCSMRU)
470 * FCS lookup table as calculated by genfcstab.
472 static u_short fcstab[256] = {
473 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
474 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
475 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
476 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
477 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
478 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
479 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
480 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
481 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
482 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
483 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
484 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
485 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
486 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
487 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
488 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
489 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
490 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
491 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
492 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
493 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
494 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
495 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
496 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
497 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
498 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
499 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
500 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
501 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
502 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
503 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
504 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
508 * Calculate a new FCS given the current FCS and the new data.
511 pppfcs(u_short fcs, u_char *cp, int len)
514 fcs = PPP_FCS(fcs, *cp++);
519 * This gets called at splsoftnet from if_ppp.c at various times
520 * when there is data ready to be sent.
524 register struct ppp_softc *sc;
526 register struct tty *tp = (struct tty *) sc->sc_devp;
527 register struct mbuf *m;
529 register u_char *start, *stop, *cp;
530 int n, ndone, done, idle;
534 /* XXX assumes atomic access to *tp although we're not at spltty(). */
535 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
537 * See if we have an existing packet partly sent.
538 * If not, get a new packet and start sending it.
543 * Get another packet to be sent.
552 * The extra PPP_FLAG will start up a new packet, and thus
553 * will flush any accumulated garbage. We do this whenever
554 * the line may have been idle for some time.
557 if (CCOUNT(&tp->t_outq) == 0) {
558 ++sc->sc_stats.ppp_obytes;
559 (void) putc(PPP_FLAG, &tp->t_outq);
562 /* Calculate the FCS for the first mbuf's worth. */
563 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
564 getmicrotime(&PPP2IFP(sc)->if_lastchange);
568 start = mtod(m, u_char *);
573 * Find out how many bytes in the string we can
574 * handle without doing something special.
576 for (cp = start; cp < stop; cp++)
581 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
582 ndone = n - b_to_q(start, n, &tp->t_outq);
585 sc->sc_stats.ppp_obytes += ndone;
588 break; /* packet doesn't fit */
591 * If there are characters left in the mbuf,
592 * the first one must be special.
593 * Put it out in a different form.
597 if (putc(PPP_ESCAPE, &tp->t_outq)) {
601 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
602 (void) unputc(&tp->t_outq);
607 sc->sc_stats.ppp_obytes += 2;
614 * If we didn't empty this mbuf, remember where we're up to.
615 * If we emptied the last mbuf, try to add the FCS and closing
616 * flag, and if we can't, leave sc_outm pointing to m, but with
617 * m->m_len == 0, to remind us to output the FCS and flag later.
620 if (done && m->m_next == NULL) {
626 * We may have to escape the bytes in the FCS.
629 c = ~sc->sc_outfcs & 0xFF;
632 *p++ = c ^ PPP_TRANS;
635 c = (~sc->sc_outfcs >> 8) & 0xFF;
638 *p++ = c ^ PPP_TRANS;
644 * Try to output the FCS and flag. If the bytes
645 * don't all fit, back out.
648 for (q = endseq; q < p; ++q)
649 if (putc(*q, &tp->t_outq)) {
651 for (; q > endseq; --q)
657 sc->sc_stats.ppp_obytes += q - endseq;
661 /* remember where we got to */
667 /* Finished with this mbuf; free it and move on. */
670 /* Finished a packet */
673 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
677 * If m == NULL, we have finished a packet.
678 * If m != NULL, we've either done as much work this time
679 * as we need to, or else we've filled up the output queue.
686 /* Call pppstart to start output again if necessary. */
691 * This timeout is needed for operation on a pseudo-tty,
692 * because the pty code doesn't call pppstart after it has
693 * drained the t_outq.
695 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
696 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
697 sc->sc_flags |= SC_TIMEOUT;
704 * This gets called when a received packet is placed on
705 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
709 struct ppp_softc *sc;
714 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
716 tp = (struct tty *) sc->sc_devp;
717 putc(0, &tp->t_canq);
723 * Start output on async tty interface. If the transmit queue
724 * has drained sufficiently, arrange for pppasyncstart to be
725 * called later at splsoftnet.
726 * Called at spltty or higher.
730 register struct tty *tp;
732 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
735 * Call output process whether or not there is any output.
736 * We are being called in lieu of ttstart and must do what it would.
741 * If the transmit queue has drained and the tty has not hung up
742 * or been disconnected from the ppp unit, then tell if_ppp.c that
743 * we need more output.
745 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
746 && !((tp->t_state & TS_CONNECTED) == 0)
755 * Timeout routine - try to start some more output.
761 struct ppp_softc *sc = (struct ppp_softc *) x;
762 struct tty *tp = (struct tty *) sc->sc_devp;
766 sc->sc_flags &= ~SC_TIMEOUT;
772 * Allocate enough mbuf to handle current MRU.
776 register struct ppp_softc *sc;
778 struct mbuf *m, **mp;
782 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
783 if ((m = *mp) == NULL) {
784 MGETHDR(m, M_DONTWAIT, MT_DATA);
788 MCLGET(m, M_DONTWAIT);
790 len -= M_DATASIZE(m);
796 * tty interface receiver interrupt.
798 static unsigned paritytab[8] = {
799 0x96696996, 0x69969669, 0x69969669, 0x96696996,
800 0x69969669, 0x96696996, 0x96696996, 0x69969669
804 * Called when character is available from device driver.
805 * Only guaranteed to be at splsofttty() or spltty()
806 * This is safe to be called while the upper half's netisr is preempted.
811 register struct tty *tp;
813 register struct ppp_softc *sc;
817 sc = (struct ppp_softc *)tp->t_lsc;
822 ++sc->sc_stats.ppp_ibytes;
824 if ((tp->t_state & TS_CONNECTED) == 0) {
825 if (sc->sc_flags & SC_DEBUG)
826 if_printf(PPP2IFP(sc), "no carrier\n");
830 if (c & TTY_ERRORMASK) {
831 /* framing error or overrun on this char - abort packet */
832 if (sc->sc_flags & SC_DEBUG)
833 if_printf(PPP2IFP(sc), "line error %x\n", c & TTY_ERRORMASK);
840 * Handle software flow control of output.
842 if (tp->t_iflag & IXON) {
843 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
844 if ((tp->t_state & TS_TTSTOP) == 0) {
845 tp->t_state |= TS_TTSTOP;
850 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
851 tp->t_state &= ~TS_TTSTOP;
859 sc->sc_flags |= SC_RCV_B7_1;
861 sc->sc_flags |= SC_RCV_B7_0;
862 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
863 sc->sc_flags |= SC_RCV_ODDP;
865 sc->sc_flags |= SC_RCV_EVNP;
868 if (sc->sc_flags & SC_LOG_RAWIN)
875 if (sc->sc_rawin_count > 0)
879 * If SC_ESCAPED is set, then we've seen the packet
880 * abort sequence "}~".
882 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
883 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
885 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
886 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
887 if (sc->sc_flags & SC_DEBUG)
888 if_printf(PPP2IFP(sc), "bad fcs %x, pkt len %d\n",
890 PPP2IFP(sc)->if_ierrors++;
891 sc->sc_stats.ppp_ierrors++;
893 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
898 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
900 if (sc->sc_flags & SC_DEBUG)
901 if_printf(PPP2IFP(sc), "too short (%d)\n", ilen);
903 PPP2IFP(sc)->if_ierrors++;
904 sc->sc_stats.ppp_ierrors++;
905 sc->sc_flags |= SC_PKTLOST;
912 * Remove FCS trailer. Somewhat painful...
915 if (--sc->sc_mc->m_len == 0) {
916 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
922 /* excise this mbuf chain */
924 sc->sc_m = sc->sc_mc->m_next;
925 sc->sc_mc->m_next = NULL;
927 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
928 if (sc->sc_flags & SC_PKTLOST) {
930 sc->sc_flags &= ~SC_PKTLOST;
938 if (sc->sc_flags & SC_FLUSH) {
939 if (sc->sc_flags & SC_LOG_FLUSH)
944 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
948 if (sc->sc_flags & SC_ESCAPED) {
949 sc->sc_flags &= ~SC_ESCAPED;
951 } else if (c == PPP_ESCAPE) {
952 sc->sc_flags |= SC_ESCAPED;
959 * Initialize buffer on first octet received.
960 * First octet could be address or protocol (when compressing
962 * Second octet is control.
963 * Third octet is first or second (when compressing protocol)
965 * Fourth octet is second octet of protocol.
967 if (sc->sc_ilen == 0) {
968 /* reset the first input mbuf */
969 if (sc->sc_m == NULL) {
971 if (sc->sc_m == NULL) {
972 if (sc->sc_flags & SC_DEBUG)
973 if_printf(PPP2IFP(sc), "no input mbufs!\n");
979 m->m_data = M_DATASTART(sc->sc_m);
981 sc->sc_mp = mtod(m, char *);
982 sc->sc_fcs = PPP_INITFCS;
983 if (c != PPP_ALLSTATIONS) {
984 if (sc->sc_flags & SC_REJ_COMP_AC) {
985 if (sc->sc_flags & SC_DEBUG)
986 if_printf(PPP2IFP(sc),
987 "garbage received: 0x%x (need 0xFF)\n", c);
990 *sc->sc_mp++ = PPP_ALLSTATIONS;
991 *sc->sc_mp++ = PPP_UI;
996 if (sc->sc_ilen == 1 && c != PPP_UI) {
997 if (sc->sc_flags & SC_DEBUG)
998 if_printf(PPP2IFP(sc), "missing UI (0x3), got 0x%x\n", c);
1001 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1002 /* a compressed protocol */
1007 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1008 if (sc->sc_flags & SC_DEBUG)
1009 if_printf(PPP2IFP(sc), "bad protocol %x\n",
1010 (sc->sc_mp[-1] << 8) + c);
1014 /* packet beyond configured mru? */
1015 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1016 if (sc->sc_flags & SC_DEBUG)
1017 if_printf(PPP2IFP(sc), "packet too big\n");
1021 /* is this mbuf full? */
1023 if (M_TRAILINGSPACE(m) <= 0) {
1024 if (m->m_next == NULL) {
1026 if (m->m_next == NULL) {
1027 if (sc->sc_flags & SC_DEBUG)
1028 if_printf(PPP2IFP(sc), "too few input mbufs!\n");
1032 sc->sc_mc = m = m->m_next;
1034 m->m_data = M_DATASTART(m);
1035 sc->sc_mp = mtod(m, char *);
1040 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1044 if (!(sc->sc_flags & SC_FLUSH)) {
1046 PPP2IFP(sc)->if_ierrors++;
1047 sc->sc_stats.ppp_ierrors++;
1048 sc->sc_flags |= SC_FLUSH;
1050 if (sc->sc_flags & SC_LOG_FLUSH)
1056 #define MAX_DUMP_BYTES 128
1060 struct ppp_softc *sc;
1064 sc->sc_rawin[sc->sc_rawin_count++] = c;
1065 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1066 || (c < 0 && sc->sc_rawin_count > 0)) {
1067 printf("%s input: %*D", PPP2IFP(sc)->if_xname,
1068 sc->sc_rawin_count, sc->sc_rawin, " ");
1069 sc->sc_rawin_count = 0;