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).
75 #include "opt_ppp.h" /* XXX for ppp_defs.h */
77 #define VJC /* XXX for ppp_defs.h */
79 #include <sys/param.h>
80 #include <sys/systm.h>
83 #include <sys/dkstat.h>
84 #include <sys/socket.h>
85 #include <sys/fcntl.h>
89 #include <sys/vnode.h>
94 #include <net/if_ppp.h>
95 #include <net/if_pppvar.h>
97 static int pppopen __P((dev_t dev, struct tty *tp));
98 static int pppclose __P((struct tty *tp, int flag));
99 static int pppread __P((struct tty *tp, struct uio *uio, int flag));
100 static int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
101 static int ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
103 static int pppinput __P((int c, struct tty *tp));
104 static int pppstart __P((struct tty *tp));
106 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
107 static void pppasyncstart __P((struct ppp_softc *));
108 static void pppasyncctlp __P((struct ppp_softc *));
109 static void pppasyncrelinq __P((struct ppp_softc *));
110 static void pppasyncsetmtu __P((struct ppp_softc *));
111 static void ppp_timeout __P((void *));
112 static void pppgetm __P((struct ppp_softc *sc));
113 static void ppplogchar __P((struct ppp_softc *, int));
115 /* XXX called from if_ppp.c - layering violation */
116 void pppasyncattach __P((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,
156 pppasyncattach(dummy)
159 /* register line discipline */
160 linesw[PPPDISC] = pppdisc;
164 * Line specific open routine for async tty devices.
165 * Attach the given tty to the first available ppp unit.
166 * Called from device open routine or ttioctl() at >= splsofttty()
172 register struct tty *tp;
174 struct proc *p = curproc; /* XXX */
175 register struct ppp_softc *sc;
178 if ((error = suser(p)) != 0)
183 if (tp->t_line == PPPDISC) {
184 sc = (struct ppp_softc *) tp->t_sc;
185 if (sc != NULL && sc->sc_devp == (void *) tp) {
191 if ((sc = pppalloc(p->p_pid)) == NULL) {
197 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
201 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
202 sc->sc_asyncmap[0] = 0xffffffff;
203 sc->sc_asyncmap[3] = 0x60000000;
204 sc->sc_rasyncmap = 0;
205 sc->sc_devp = (void *) tp;
206 sc->sc_start = pppasyncstart;
207 sc->sc_ctlp = pppasyncctlp;
208 sc->sc_relinq = pppasyncrelinq;
209 sc->sc_setmtu = pppasyncsetmtu;
212 sc->sc_if.if_flags |= IFF_RUNNING;
213 getmicrotime(&sc->sc_if.if_lastchange);
214 sc->sc_if.if_baudrate = tp->t_ospeed;
216 tp->t_sc = (caddr_t) sc;
217 ttyflush(tp, FREAD | FWRITE);
220 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
221 * allocation helps avoid the need for select and/or FIONREAD.
222 * We also pass 1 byte tokens through t_canq...
224 clist_alloc_cblocks(&tp->t_canq, 1, 1);
225 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
226 sc->sc_if.if_mtu + PPP_HIWAT);
227 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
235 * Line specific close routine, called from device close routine
236 * and from ttioctl at >= splsofttty().
237 * Detach the tty from the ppp unit.
238 * Mimics part of ttyclose().
245 register struct ppp_softc *sc;
249 ttyflush(tp, FREAD | FWRITE);
250 clist_free_cblocks(&tp->t_canq);
251 clist_free_cblocks(&tp->t_outq);
253 sc = (struct ppp_softc *) tp->t_sc;
256 if (tp == (struct tty *) sc->sc_devp) {
266 * Relinquish the interface unit to another device.
270 struct ppp_softc *sc;
276 m_freem(sc->sc_outm);
283 if (sc->sc_flags & SC_TIMEOUT) {
284 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
285 sc->sc_flags &= ~SC_TIMEOUT;
291 * This gets called from the upper layer to notify a mtu change
295 register struct ppp_softc *sc;
297 register struct tty *tp = (struct tty *) sc->sc_devp;
302 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
303 sc->sc_if.if_mtu + PPP_HIWAT);
308 * Line specific (tty) read routine.
309 * called at zero spl from the device driver in the response to user-level
310 * reads on the tty file descriptor (ie: pppd).
313 pppread(tp, uio, flag)
314 register struct tty *tp;
318 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
326 * Loop waiting for input, checking that nothing disasterous
327 * happens in the meantime.
331 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
335 if (sc->sc_inq.ifq_head != NULL)
337 if ((tp->t_state & TS_CONNECTED) == 0) {
339 return 0; /* end of file */
341 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
343 return (EWOULDBLOCK);
345 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
352 /* Pull place-holder byte out of canonical queue */
355 /* Get the packet from the input queue */
356 IF_DEQUEUE(&sc->sc_inq, m0);
359 for (m = m0; m && uio->uio_resid; m = m->m_next)
360 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
367 * Line specific (tty) write routine.
368 * called at zero spl from the device driver in the response to user-level
369 * writes on the tty file descriptor (ie: pppd).
372 pppwrite(tp, uio, flag)
373 register struct tty *tp;
377 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
378 struct mbuf *m, *m0, **mp;
382 if ((tp->t_state & TS_CONNECTED) == 0)
383 return 0; /* wrote 0 bytes */
384 if (tp->t_line != PPPDISC)
386 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
388 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
389 uio->uio_resid < PPP_HDRLEN)
393 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
394 MGET(m, M_TRYWAIT, MT_DATA);
395 if ((*mp = m) == NULL) {
401 if (uio->uio_resid >= MCLBYTES / 2)
402 MCLGET(m, M_DONTWAIT);
403 len = M_TRAILINGSPACE(m);
404 if (len > uio->uio_resid)
405 len = uio->uio_resid;
406 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
413 dst.sa_family = AF_UNSPEC;
414 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
415 m0->m_data += PPP_HDRLEN;
416 m0->m_len -= PPP_HDRLEN;
418 /* call the upper layer to "transmit" it... */
419 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
425 * Line specific (tty) ioctl routine.
426 * This discipline requires that tty device drivers call
427 * the line specific l_ioctl routine from their ioctl routines.
431 ppptioctl(tp, cmd, data, flag, p)
438 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
441 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
446 case PPPIOCSASYNCMAP:
447 if ((error = suser(p)) != 0)
449 sc->sc_asyncmap[0] = *(u_int *)data;
452 case PPPIOCGASYNCMAP:
453 *(u_int *)data = sc->sc_asyncmap[0];
456 case PPPIOCSRASYNCMAP:
457 if ((error = suser(p)) != 0)
459 sc->sc_rasyncmap = *(u_int *)data;
462 case PPPIOCGRASYNCMAP:
463 *(u_int *)data = sc->sc_rasyncmap;
466 case PPPIOCSXASYNCMAP:
467 if ((error = suser(p)) != 0)
470 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
471 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
472 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
473 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
477 case PPPIOCGXASYNCMAP:
478 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
482 error = pppioctl(sc, cmd, data, flag, p);
483 if (error == 0 && cmd == PPPIOCSMRU)
491 * FCS lookup table as calculated by genfcstab.
493 static u_short fcstab[256] = {
494 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
495 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
496 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
497 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
498 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
499 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
500 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
501 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
502 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
503 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
504 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
505 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
506 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
507 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
508 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
509 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
510 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
511 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
512 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
513 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
514 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
515 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
516 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
517 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
518 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
519 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
520 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
521 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
522 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
523 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
524 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
525 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
529 * Calculate a new FCS given the current FCS and the new data.
532 pppfcs(u_short fcs, u_char *cp, int len)
535 fcs = PPP_FCS(fcs, *cp++);
540 * This gets called at splsoftnet from if_ppp.c at various times
541 * when there is data ready to be sent.
545 register struct ppp_softc *sc;
547 register struct tty *tp = (struct tty *) sc->sc_devp;
548 register struct mbuf *m;
550 register u_char *start, *stop, *cp;
551 int n, ndone, done, idle;
556 /* XXX assumes atomic access to *tp although we're not at spltty(). */
557 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
559 * See if we have an existing packet partly sent.
560 * If not, get a new packet and start sending it.
565 * Get another packet to be sent.
574 * The extra PPP_FLAG will start up a new packet, and thus
575 * will flush any accumulated garbage. We do this whenever
576 * the line may have been idle for some time.
579 if (CCOUNT(&tp->t_outq) == 0) {
580 ++sc->sc_stats.ppp_obytes;
581 (void) putc(PPP_FLAG, &tp->t_outq);
584 /* Calculate the FCS for the first mbuf's worth. */
585 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
586 getmicrotime(&sc->sc_if.if_lastchange);
590 start = mtod(m, u_char *);
595 * Find out how many bytes in the string we can
596 * handle without doing something special.
598 for (cp = start; cp < stop; cp++)
603 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
604 ndone = n - b_to_q(start, n, &tp->t_outq);
607 sc->sc_stats.ppp_obytes += ndone;
610 break; /* packet doesn't fit */
613 * If there are characters left in the mbuf,
614 * the first one must be special.
615 * Put it out in a different form.
619 if (putc(PPP_ESCAPE, &tp->t_outq)) {
623 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
624 (void) unputc(&tp->t_outq);
629 sc->sc_stats.ppp_obytes += 2;
636 * If we didn't empty this mbuf, remember where we're up to.
637 * If we emptied the last mbuf, try to add the FCS and closing
638 * flag, and if we can't, leave sc_outm pointing to m, but with
639 * m->m_len == 0, to remind us to output the FCS and flag later.
642 if (done && m->m_next == NULL) {
648 * We may have to escape the bytes in the FCS.
651 c = ~sc->sc_outfcs & 0xFF;
654 *p++ = c ^ PPP_TRANS;
657 c = (~sc->sc_outfcs >> 8) & 0xFF;
660 *p++ = c ^ PPP_TRANS;
666 * Try to output the FCS and flag. If the bytes
667 * don't all fit, back out.
670 for (q = endseq; q < p; ++q)
671 if (putc(*q, &tp->t_outq)) {
673 for (; q > endseq; --q)
679 sc->sc_stats.ppp_obytes += q - endseq;
683 /* remember where we got to */
689 /* Finished with this mbuf; free it and move on. */
693 /* Finished a packet */
696 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
700 * If m == NULL, we have finished a packet.
701 * If m != NULL, we've either done as much work this time
702 * as we need to, or else we've filled up the output queue.
709 /* Call pppstart to start output again if necessary. */
714 * This timeout is needed for operation on a pseudo-tty,
715 * because the pty code doesn't call pppstart after it has
716 * drained the t_outq.
718 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
719 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
720 sc->sc_flags |= SC_TIMEOUT;
727 * This gets called when a received packet is placed on
728 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
732 struct ppp_softc *sc;
737 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
739 tp = (struct tty *) sc->sc_devp;
740 putc(0, &tp->t_canq);
746 * Start output on async tty interface. If the transmit queue
747 * has drained sufficiently, arrange for pppasyncstart to be
748 * called later at splsoftnet.
749 * Called at spltty or higher.
753 register struct tty *tp;
755 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
758 * Call output process whether or not there is any output.
759 * We are being called in lieu of ttstart and must do what it would.
761 if (tp->t_oproc != NULL)
765 * If the transmit queue has drained and the tty has not hung up
766 * or been disconnected from the ppp unit, then tell if_ppp.c that
767 * we need more output.
769 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
770 && !((tp->t_state & TS_CONNECTED) == 0)
771 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
779 * Timeout routine - try to start some more output.
785 struct ppp_softc *sc = (struct ppp_softc *) x;
786 struct tty *tp = (struct tty *) sc->sc_devp;
790 sc->sc_flags &= ~SC_TIMEOUT;
796 * Allocate enough mbuf to handle current MRU.
800 register struct ppp_softc *sc;
802 struct mbuf *m, **mp;
806 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
807 if ((m = *mp) == NULL) {
808 MGETHDR(m, M_DONTWAIT, MT_DATA);
812 MCLGET(m, M_DONTWAIT);
814 len -= M_DATASIZE(m);
820 * tty interface receiver interrupt.
822 static unsigned paritytab[8] = {
823 0x96696996, 0x69969669, 0x69969669, 0x96696996,
824 0x69969669, 0x96696996, 0x96696996, 0x69969669
828 * Called when character is available from device driver.
829 * Only guaranteed to be at splsofttty() or spltty()
830 * This is safe to be called while the upper half's netisr is preempted.
835 register struct tty *tp;
837 register struct ppp_softc *sc;
841 sc = (struct ppp_softc *) tp->t_sc;
842 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
846 ++sc->sc_stats.ppp_ibytes;
848 if ((tp->t_state & TS_CONNECTED) == 0) {
849 if (sc->sc_flags & SC_DEBUG)
850 printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
854 if (c & TTY_ERRORMASK) {
855 /* framing error or overrun on this char - abort packet */
856 if (sc->sc_flags & SC_DEBUG)
857 printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
865 * Handle software flow control of output.
867 if (tp->t_iflag & IXON) {
868 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
869 if ((tp->t_state & TS_TTSTOP) == 0) {
870 tp->t_state |= TS_TTSTOP;
875 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
876 tp->t_state &= ~TS_TTSTOP;
877 if (tp->t_oproc != NULL)
885 sc->sc_flags |= SC_RCV_B7_1;
887 sc->sc_flags |= SC_RCV_B7_0;
888 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
889 sc->sc_flags |= SC_RCV_ODDP;
891 sc->sc_flags |= SC_RCV_EVNP;
894 if (sc->sc_flags & SC_LOG_RAWIN)
901 if (sc->sc_rawin_count > 0)
905 * If SC_ESCAPED is set, then we've seen the packet
906 * abort sequence "}~".
908 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
909 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
911 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
912 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
913 if (sc->sc_flags & SC_DEBUG)
914 printf("ppp%d: bad fcs %x, pkt len %d\n",
915 sc->sc_if.if_unit, sc->sc_fcs, ilen);
916 sc->sc_if.if_ierrors++;
917 sc->sc_stats.ppp_ierrors++;
919 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
924 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
926 if (sc->sc_flags & SC_DEBUG)
927 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
929 sc->sc_if.if_ierrors++;
930 sc->sc_stats.ppp_ierrors++;
931 sc->sc_flags |= SC_PKTLOST;
938 * Remove FCS trailer. Somewhat painful...
941 if (--sc->sc_mc->m_len == 0) {
942 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
948 /* excise this mbuf chain */
950 sc->sc_m = sc->sc_mc->m_next;
951 sc->sc_mc->m_next = NULL;
953 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
954 if (sc->sc_flags & SC_PKTLOST) {
956 sc->sc_flags &= ~SC_PKTLOST;
964 if (sc->sc_flags & SC_FLUSH) {
965 if (sc->sc_flags & SC_LOG_FLUSH)
970 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
974 if (sc->sc_flags & SC_ESCAPED) {
975 sc->sc_flags &= ~SC_ESCAPED;
977 } else if (c == PPP_ESCAPE) {
978 sc->sc_flags |= SC_ESCAPED;
985 * Initialize buffer on first octet received.
986 * First octet could be address or protocol (when compressing
988 * Second octet is control.
989 * Third octet is first or second (when compressing protocol)
991 * Fourth octet is second octet of protocol.
993 if (sc->sc_ilen == 0) {
994 /* reset the first input mbuf */
995 if (sc->sc_m == NULL) {
997 if (sc->sc_m == NULL) {
998 if (sc->sc_flags & SC_DEBUG)
999 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1005 m->m_data = M_DATASTART(sc->sc_m);
1007 sc->sc_mp = mtod(m, char *);
1008 sc->sc_fcs = PPP_INITFCS;
1009 if (c != PPP_ALLSTATIONS) {
1010 if (sc->sc_flags & SC_REJ_COMP_AC) {
1011 if (sc->sc_flags & SC_DEBUG)
1012 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1013 sc->sc_if.if_unit, c);
1016 *sc->sc_mp++ = PPP_ALLSTATIONS;
1017 *sc->sc_mp++ = PPP_UI;
1022 if (sc->sc_ilen == 1 && c != PPP_UI) {
1023 if (sc->sc_flags & SC_DEBUG)
1024 printf("ppp%d: missing UI (0x3), got 0x%x\n",
1025 sc->sc_if.if_unit, c);
1028 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1029 /* a compressed protocol */
1034 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1035 if (sc->sc_flags & SC_DEBUG)
1036 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1037 (sc->sc_mp[-1] << 8) + c);
1041 /* packet beyond configured mru? */
1042 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1043 if (sc->sc_flags & SC_DEBUG)
1044 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1048 /* is this mbuf full? */
1050 if (M_TRAILINGSPACE(m) <= 0) {
1051 if (m->m_next == NULL) {
1053 if (m->m_next == NULL) {
1054 if (sc->sc_flags & SC_DEBUG)
1055 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1059 sc->sc_mc = m = m->m_next;
1061 m->m_data = M_DATASTART(m);
1062 sc->sc_mp = mtod(m, char *);
1067 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1071 if (!(sc->sc_flags & SC_FLUSH)) {
1073 sc->sc_if.if_ierrors++;
1074 sc->sc_stats.ppp_ierrors++;
1075 sc->sc_flags |= SC_FLUSH;
1077 if (sc->sc_flags & SC_LOG_FLUSH)
1083 #define MAX_DUMP_BYTES 128
1087 struct ppp_softc *sc;
1091 sc->sc_rawin[sc->sc_rawin_count++] = c;
1092 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1093 || (c < 0 && sc->sc_rawin_count > 0)) {
1094 printf("ppp%d input: %*D", sc->sc_if.if_unit,
1095 sc->sc_rawin_count, sc->sc_rawin, " ");
1096 sc->sc_rawin_count = 0;