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(dev_t dev, struct tty *tp);
98 static int pppclose(struct tty *tp, int flag);
99 static int pppread(struct tty *tp, struct uio *uio, int flag);
100 static int pppwrite(struct tty *tp, struct uio *uio, int flag);
101 static int ppptioctl(struct tty *tp, u_long cmd, caddr_t data,
102 int flag, struct thread *td);
103 static int pppinput(int c, struct tty *tp);
104 static int pppstart(struct tty *tp);
106 static u_short pppfcs(u_short fcs, u_char *cp, int len);
107 static void pppasyncstart(struct ppp_softc *);
108 static void pppasyncctlp(struct ppp_softc *);
109 static void pppasyncrelinq(struct ppp_softc *);
110 static void pppasyncsetmtu(struct ppp_softc *);
111 static void ppp_timeout(void *);
112 static void pppgetm(struct ppp_softc *sc);
113 static void ppplogchar(struct ppp_softc *, int);
115 /* XXX called from if_ppp.c - layering violation */
116 void pppasyncattach(void *);
117 void pppasyncdetach(void);
120 * Some useful mbuf macros not in mbuf.h.
122 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
124 #define M_DATASTART(m) \
125 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
126 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
128 #define M_DATASIZE(m) \
129 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
130 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
133 * Does c need to be escaped?
135 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
138 * Procedures for using an async tty interface for PPP.
141 /* This is a FreeBSD-2.X kernel. */
142 #define CCOUNT(q) ((q)->c_cc)
143 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
144 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
147 * Define the PPP line discipline.
150 static struct linesw pppdisc = {
151 pppopen, pppclose, pppread, pppwrite,
152 ppptioctl, pppinput, pppstart, ttymodem,
157 pppasyncattach(dummy)
160 ldisc_register(PPPDISC, &pppdisc);
166 ldisc_deregister(PPPDISC);
170 * Line specific open routine for async tty devices.
171 * Attach the given tty to the first available ppp unit.
172 * Called from device open routine or ttioctl() at >= splsofttty()
178 register struct tty *tp;
180 struct thread *td = curthread; /* XXX */
181 register struct ppp_softc *sc;
184 if ((error = suser(td)) != 0)
189 if (tp->t_line == PPPDISC) {
190 sc = (struct ppp_softc *) tp->t_sc;
191 if (sc != NULL && sc->sc_devp == (void *) tp) {
197 if ((sc = pppalloc(td->td_proc->p_pid)) == NULL) {
203 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
207 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
208 sc->sc_asyncmap[0] = 0xffffffff;
209 sc->sc_asyncmap[3] = 0x60000000;
210 sc->sc_rasyncmap = 0;
211 sc->sc_devp = (void *) tp;
212 sc->sc_start = pppasyncstart;
213 sc->sc_ctlp = pppasyncctlp;
214 sc->sc_relinq = pppasyncrelinq;
215 sc->sc_setmtu = pppasyncsetmtu;
218 sc->sc_if.if_flags |= IFF_RUNNING;
219 getmicrotime(&sc->sc_if.if_lastchange);
220 sc->sc_if.if_baudrate = tp->t_ospeed;
222 tp->t_sc = (caddr_t) sc;
223 ttyflush(tp, FREAD | FWRITE);
226 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
227 * allocation helps avoid the need for select and/or FIONREAD.
228 * We also pass 1 byte tokens through t_canq...
230 clist_alloc_cblocks(&tp->t_canq, 1, 1);
231 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
232 sc->sc_if.if_mtu + PPP_HIWAT);
233 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
241 * Line specific close routine, called from device close routine
242 * and from ttioctl at >= splsofttty().
243 * Detach the tty from the ppp unit.
244 * Mimics part of ttyclose().
251 register struct ppp_softc *sc;
255 ttyflush(tp, FREAD | FWRITE);
256 clist_free_cblocks(&tp->t_canq);
257 clist_free_cblocks(&tp->t_outq);
259 sc = (struct ppp_softc *) tp->t_sc;
262 if (tp == (struct tty *) sc->sc_devp) {
272 * Relinquish the interface unit to another device.
276 struct ppp_softc *sc;
282 m_freem(sc->sc_outm);
289 if (sc->sc_flags & SC_TIMEOUT) {
290 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
291 sc->sc_flags &= ~SC_TIMEOUT;
297 * This gets called from the upper layer to notify a mtu change
301 register struct ppp_softc *sc;
303 register struct tty *tp = (struct tty *) sc->sc_devp;
308 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
309 sc->sc_if.if_mtu + PPP_HIWAT);
314 * Line specific (tty) read routine.
315 * called at zero spl from the device driver in the response to user-level
316 * reads on the tty file descriptor (ie: pppd).
319 pppread(tp, uio, flag)
320 register struct tty *tp;
324 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
332 * Loop waiting for input, checking that nothing disasterous
333 * happens in the meantime.
337 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
341 if (sc->sc_inq.ifq_head != NULL)
343 if ((tp->t_state & TS_CONNECTED) == 0) {
345 return 0; /* end of file */
347 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
349 return (EWOULDBLOCK);
351 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
358 /* Pull place-holder byte out of canonical queue */
361 /* Get the packet from the input queue */
362 IF_DEQUEUE(&sc->sc_inq, m0);
365 for (m = m0; m && uio->uio_resid; m = m->m_next)
366 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
373 * Line specific (tty) write routine.
374 * called at zero spl from the device driver in the response to user-level
375 * writes on the tty file descriptor (ie: pppd).
378 pppwrite(tp, uio, flag)
379 register struct tty *tp;
383 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
384 struct mbuf *m, *m0, **mp;
388 if ((tp->t_state & TS_CONNECTED) == 0)
389 return 0; /* wrote 0 bytes */
390 if (tp->t_line != PPPDISC)
392 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
394 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
395 uio->uio_resid < PPP_HDRLEN)
399 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
400 MGET(m, M_TRYWAIT, MT_DATA);
401 if ((*mp = m) == NULL) {
407 if (uio->uio_resid >= MCLBYTES / 2)
408 MCLGET(m, M_DONTWAIT);
409 len = M_TRAILINGSPACE(m);
410 if (len > uio->uio_resid)
411 len = uio->uio_resid;
412 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
419 dst.sa_family = AF_UNSPEC;
420 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
421 m0->m_data += PPP_HDRLEN;
422 m0->m_len -= PPP_HDRLEN;
424 /* call the upper layer to "transmit" it... */
425 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
431 * Line specific (tty) ioctl routine.
432 * This discipline requires that tty device drivers call
433 * the line specific l_ioctl routine from their ioctl routines.
437 ppptioctl(tp, cmd, data, flag, td)
444 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
447 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
452 case PPPIOCSASYNCMAP:
453 if ((error = suser(td)) != 0)
455 sc->sc_asyncmap[0] = *(u_int *)data;
458 case PPPIOCGASYNCMAP:
459 *(u_int *)data = sc->sc_asyncmap[0];
462 case PPPIOCSRASYNCMAP:
463 if ((error = suser(td)) != 0)
465 sc->sc_rasyncmap = *(u_int *)data;
468 case PPPIOCGRASYNCMAP:
469 *(u_int *)data = sc->sc_rasyncmap;
472 case PPPIOCSXASYNCMAP:
473 if ((error = suser(td)) != 0)
476 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
477 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
478 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
479 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
483 case PPPIOCGXASYNCMAP:
484 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
488 error = pppioctl(sc, cmd, data, flag, td);
489 if (error == 0 && cmd == PPPIOCSMRU)
497 * FCS lookup table as calculated by genfcstab.
499 static u_short fcstab[256] = {
500 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
501 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
502 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
503 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
504 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
505 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
506 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
507 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
508 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
509 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
510 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
511 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
512 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
513 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
514 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
515 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
516 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
517 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
518 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
519 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
520 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
521 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
522 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
523 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
524 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
525 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
526 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
527 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
528 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
529 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
530 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
531 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
535 * Calculate a new FCS given the current FCS and the new data.
538 pppfcs(u_short fcs, u_char *cp, int len)
541 fcs = PPP_FCS(fcs, *cp++);
546 * This gets called at splsoftnet from if_ppp.c at various times
547 * when there is data ready to be sent.
551 register struct ppp_softc *sc;
553 register struct tty *tp = (struct tty *) sc->sc_devp;
554 register struct mbuf *m;
556 register u_char *start, *stop, *cp;
557 int n, ndone, done, idle;
561 /* XXX assumes atomic access to *tp although we're not at spltty(). */
562 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
564 * See if we have an existing packet partly sent.
565 * If not, get a new packet and start sending it.
570 * Get another packet to be sent.
579 * The extra PPP_FLAG will start up a new packet, and thus
580 * will flush any accumulated garbage. We do this whenever
581 * the line may have been idle for some time.
584 if (CCOUNT(&tp->t_outq) == 0) {
585 ++sc->sc_stats.ppp_obytes;
586 (void) putc(PPP_FLAG, &tp->t_outq);
589 /* Calculate the FCS for the first mbuf's worth. */
590 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
591 getmicrotime(&sc->sc_if.if_lastchange);
595 start = mtod(m, u_char *);
600 * Find out how many bytes in the string we can
601 * handle without doing something special.
603 for (cp = start; cp < stop; cp++)
608 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
609 ndone = n - b_to_q(start, n, &tp->t_outq);
612 sc->sc_stats.ppp_obytes += ndone;
615 break; /* packet doesn't fit */
618 * If there are characters left in the mbuf,
619 * the first one must be special.
620 * Put it out in a different form.
624 if (putc(PPP_ESCAPE, &tp->t_outq)) {
628 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
629 (void) unputc(&tp->t_outq);
634 sc->sc_stats.ppp_obytes += 2;
641 * If we didn't empty this mbuf, remember where we're up to.
642 * If we emptied the last mbuf, try to add the FCS and closing
643 * flag, and if we can't, leave sc_outm pointing to m, but with
644 * m->m_len == 0, to remind us to output the FCS and flag later.
647 if (done && m->m_next == NULL) {
653 * We may have to escape the bytes in the FCS.
656 c = ~sc->sc_outfcs & 0xFF;
659 *p++ = c ^ PPP_TRANS;
662 c = (~sc->sc_outfcs >> 8) & 0xFF;
665 *p++ = c ^ PPP_TRANS;
671 * Try to output the FCS and flag. If the bytes
672 * don't all fit, back out.
675 for (q = endseq; q < p; ++q)
676 if (putc(*q, &tp->t_outq)) {
678 for (; q > endseq; --q)
684 sc->sc_stats.ppp_obytes += q - endseq;
688 /* remember where we got to */
694 /* Finished with this mbuf; free it and move on. */
697 /* Finished a packet */
700 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
704 * If m == NULL, we have finished a packet.
705 * If m != NULL, we've either done as much work this time
706 * as we need to, or else we've filled up the output queue.
713 /* Call pppstart to start output again if necessary. */
718 * This timeout is needed for operation on a pseudo-tty,
719 * because the pty code doesn't call pppstart after it has
720 * drained the t_outq.
722 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
723 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
724 sc->sc_flags |= SC_TIMEOUT;
731 * This gets called when a received packet is placed on
732 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
736 struct ppp_softc *sc;
741 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
743 tp = (struct tty *) sc->sc_devp;
744 putc(0, &tp->t_canq);
750 * Start output on async tty interface. If the transmit queue
751 * has drained sufficiently, arrange for pppasyncstart to be
752 * called later at splsoftnet.
753 * Called at spltty or higher.
757 register struct tty *tp;
759 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
762 * Call output process whether or not there is any output.
763 * We are being called in lieu of ttstart and must do what it would.
765 if (tp->t_oproc != NULL)
769 * If the transmit queue has drained and the tty has not hung up
770 * or been disconnected from the ppp unit, then tell if_ppp.c that
771 * we need more output.
773 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
774 && !((tp->t_state & TS_CONNECTED) == 0)
775 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
783 * Timeout routine - try to start some more output.
789 struct ppp_softc *sc = (struct ppp_softc *) x;
790 struct tty *tp = (struct tty *) sc->sc_devp;
794 sc->sc_flags &= ~SC_TIMEOUT;
800 * Allocate enough mbuf to handle current MRU.
804 register struct ppp_softc *sc;
806 struct mbuf *m, **mp;
810 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
811 if ((m = *mp) == NULL) {
812 MGETHDR(m, M_DONTWAIT, MT_DATA);
816 MCLGET(m, M_DONTWAIT);
818 len -= M_DATASIZE(m);
824 * tty interface receiver interrupt.
826 static unsigned paritytab[8] = {
827 0x96696996, 0x69969669, 0x69969669, 0x96696996,
828 0x69969669, 0x96696996, 0x96696996, 0x69969669
832 * Called when character is available from device driver.
833 * Only guaranteed to be at splsofttty() or spltty()
834 * This is safe to be called while the upper half's netisr is preempted.
839 register struct tty *tp;
841 register struct ppp_softc *sc;
845 sc = (struct ppp_softc *) tp->t_sc;
846 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
850 ++sc->sc_stats.ppp_ibytes;
852 if ((tp->t_state & TS_CONNECTED) == 0) {
853 if (sc->sc_flags & SC_DEBUG)
854 printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
858 if (c & TTY_ERRORMASK) {
859 /* framing error or overrun on this char - abort packet */
860 if (sc->sc_flags & SC_DEBUG)
861 printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
869 * Handle software flow control of output.
871 if (tp->t_iflag & IXON) {
872 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
873 if ((tp->t_state & TS_TTSTOP) == 0) {
874 tp->t_state |= TS_TTSTOP;
879 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
880 tp->t_state &= ~TS_TTSTOP;
881 if (tp->t_oproc != NULL)
889 sc->sc_flags |= SC_RCV_B7_1;
891 sc->sc_flags |= SC_RCV_B7_0;
892 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
893 sc->sc_flags |= SC_RCV_ODDP;
895 sc->sc_flags |= SC_RCV_EVNP;
898 if (sc->sc_flags & SC_LOG_RAWIN)
905 if (sc->sc_rawin_count > 0)
909 * If SC_ESCAPED is set, then we've seen the packet
910 * abort sequence "}~".
912 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
913 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
915 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
916 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
917 if (sc->sc_flags & SC_DEBUG)
918 printf("ppp%d: bad fcs %x, pkt len %d\n",
919 sc->sc_if.if_unit, sc->sc_fcs, ilen);
920 sc->sc_if.if_ierrors++;
921 sc->sc_stats.ppp_ierrors++;
923 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
928 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
930 if (sc->sc_flags & SC_DEBUG)
931 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
933 sc->sc_if.if_ierrors++;
934 sc->sc_stats.ppp_ierrors++;
935 sc->sc_flags |= SC_PKTLOST;
942 * Remove FCS trailer. Somewhat painful...
945 if (--sc->sc_mc->m_len == 0) {
946 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
952 /* excise this mbuf chain */
954 sc->sc_m = sc->sc_mc->m_next;
955 sc->sc_mc->m_next = NULL;
957 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
958 if (sc->sc_flags & SC_PKTLOST) {
960 sc->sc_flags &= ~SC_PKTLOST;
968 if (sc->sc_flags & SC_FLUSH) {
969 if (sc->sc_flags & SC_LOG_FLUSH)
974 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
978 if (sc->sc_flags & SC_ESCAPED) {
979 sc->sc_flags &= ~SC_ESCAPED;
981 } else if (c == PPP_ESCAPE) {
982 sc->sc_flags |= SC_ESCAPED;
989 * Initialize buffer on first octet received.
990 * First octet could be address or protocol (when compressing
992 * Second octet is control.
993 * Third octet is first or second (when compressing protocol)
995 * Fourth octet is second octet of protocol.
997 if (sc->sc_ilen == 0) {
998 /* reset the first input mbuf */
999 if (sc->sc_m == NULL) {
1001 if (sc->sc_m == NULL) {
1002 if (sc->sc_flags & SC_DEBUG)
1003 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1009 m->m_data = M_DATASTART(sc->sc_m);
1011 sc->sc_mp = mtod(m, char *);
1012 sc->sc_fcs = PPP_INITFCS;
1013 if (c != PPP_ALLSTATIONS) {
1014 if (sc->sc_flags & SC_REJ_COMP_AC) {
1015 if (sc->sc_flags & SC_DEBUG)
1016 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1017 sc->sc_if.if_unit, c);
1020 *sc->sc_mp++ = PPP_ALLSTATIONS;
1021 *sc->sc_mp++ = PPP_UI;
1026 if (sc->sc_ilen == 1 && c != PPP_UI) {
1027 if (sc->sc_flags & SC_DEBUG)
1028 printf("ppp%d: missing UI (0x3), got 0x%x\n",
1029 sc->sc_if.if_unit, c);
1032 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1033 /* a compressed protocol */
1038 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1039 if (sc->sc_flags & SC_DEBUG)
1040 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1041 (sc->sc_mp[-1] << 8) + c);
1045 /* packet beyond configured mru? */
1046 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1047 if (sc->sc_flags & SC_DEBUG)
1048 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1052 /* is this mbuf full? */
1054 if (M_TRAILINGSPACE(m) <= 0) {
1055 if (m->m_next == NULL) {
1057 if (m->m_next == NULL) {
1058 if (sc->sc_flags & SC_DEBUG)
1059 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1063 sc->sc_mc = m = m->m_next;
1065 m->m_data = M_DATASTART(m);
1066 sc->sc_mp = mtod(m, char *);
1071 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1075 if (!(sc->sc_flags & SC_FLUSH)) {
1077 sc->sc_if.if_ierrors++;
1078 sc->sc_stats.ppp_ierrors++;
1079 sc->sc_flags |= SC_FLUSH;
1081 if (sc->sc_flags & SC_LOG_FLUSH)
1087 #define MAX_DUMP_BYTES 128
1091 struct ppp_softc *sc;
1095 sc->sc_rawin[sc->sc_rawin_count++] = c;
1096 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1097 || (c < 0 && sc->sc_rawin_count > 0)) {
1098 printf("ppp%d input: %*D", sc->sc_if.if_unit,
1099 sc->sc_rawin_count, sc->sc_rawin, " ");
1100 sc->sc_rawin_count = 0;