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 /* $FreeBSD: src/sys/net/ppp_tty.c,v 1.43.2.1 2002/02/13 00:43:11 dillon Exp $ */
74 /* $DragonFly: src/sys/net/ppp_layer/ppp_tty.c,v 1.2 2003/06/17 04:28:48 dillon Exp $ */
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/dkstat.h>
85 #include <sys/socket.h>
86 #include <sys/fcntl.h>
90 #include <sys/vnode.h>
93 #include <i386/isa/intr_machdep.h>
99 #include <net/if_ppp.h>
100 #include <net/if_pppvar.h>
102 static int pppopen __P((dev_t dev, struct tty *tp));
103 static int pppclose __P((struct tty *tp, int flag));
104 static int pppread __P((struct tty *tp, struct uio *uio, int flag));
105 static int pppwrite __P((struct tty *tp, struct uio *uio, int flag));
106 static int ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
108 static int pppinput __P((int c, struct tty *tp));
109 static int pppstart __P((struct tty *tp));
111 static u_short pppfcs __P((u_short fcs, u_char *cp, int len));
112 static void pppasyncstart __P((struct ppp_softc *));
113 static void pppasyncctlp __P((struct ppp_softc *));
114 static void pppasyncrelinq __P((struct ppp_softc *));
115 static void pppasyncsetmtu __P((struct ppp_softc *));
116 static void ppp_timeout __P((void *));
117 static void pppgetm __P((struct ppp_softc *sc));
118 static void ppplogchar __P((struct ppp_softc *, int));
120 /* XXX called from if_ppp.c - layering violation */
121 void pppasyncattach __P((void *));
124 * Some useful mbuf macros not in mbuf.h.
126 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
128 #define M_DATASTART(m) \
129 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
130 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
132 #define M_DATASIZE(m) \
133 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
134 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
137 * Does c need to be escaped?
139 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
142 * Procedures for using an async tty interface for PPP.
145 /* This is a FreeBSD-2.X kernel. */
146 #define CCOUNT(q) ((q)->c_cc)
147 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
148 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
151 * Define the PPP line discipline.
154 static struct linesw pppdisc = {
155 pppopen, pppclose, pppread, pppwrite,
156 ppptioctl, pppinput, pppstart, ttymodem,
161 pppasyncattach(dummy)
170 * Make sure that the soft net "engine" cannot run while spltty code is
171 * active. The if_ppp.c code can walk down into b_to_q etc, and it is
172 * bad if the tty system was in the middle of another b_to_q...
174 tty_imask |= softnet_imask; /* spltty() block spl[soft]net() */
175 net_imask |= softtty_imask; /* splimp() block splsofttty() */
176 net_imask |= tty_imask; /* splimp() block spltty() */
181 printf("new masks: bio %x, tty %x, net %x\n",
182 bio_imask, tty_imask, net_imask);
185 /* register line discipline */
186 linesw[PPPDISC] = pppdisc;
190 * Line specific open routine for async tty devices.
191 * Attach the given tty to the first available ppp unit.
192 * Called from device open routine or ttioctl() at >= splsofttty()
198 register struct tty *tp;
200 struct proc *p = curproc; /* XXX */
201 register struct ppp_softc *sc;
204 if ((error = suser(p)) != 0)
209 if (tp->t_line == PPPDISC) {
210 sc = (struct ppp_softc *) tp->t_sc;
211 if (sc != NULL && sc->sc_devp == (void *) tp) {
217 if ((sc = pppalloc(p->p_pid)) == NULL) {
223 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
227 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
228 sc->sc_asyncmap[0] = 0xffffffff;
229 sc->sc_asyncmap[3] = 0x60000000;
230 sc->sc_rasyncmap = 0;
231 sc->sc_devp = (void *) tp;
232 sc->sc_start = pppasyncstart;
233 sc->sc_ctlp = pppasyncctlp;
234 sc->sc_relinq = pppasyncrelinq;
235 sc->sc_setmtu = pppasyncsetmtu;
238 sc->sc_if.if_flags |= IFF_RUNNING;
239 getmicrotime(&sc->sc_if.if_lastchange);
240 sc->sc_if.if_baudrate = tp->t_ospeed;
242 tp->t_sc = (caddr_t) sc;
243 ttyflush(tp, FREAD | FWRITE);
246 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
247 * allocation helps avoid the need for select and/or FIONREAD.
248 * We also pass 1 byte tokens through t_canq...
250 clist_alloc_cblocks(&tp->t_canq, 1, 1);
251 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
252 sc->sc_if.if_mtu + PPP_HIWAT);
253 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
261 * Line specific close routine, called from device close routine
262 * and from ttioctl at >= splsofttty().
263 * Detach the tty from the ppp unit.
264 * Mimics part of ttyclose().
271 register struct ppp_softc *sc;
275 ttyflush(tp, FREAD | FWRITE);
276 clist_free_cblocks(&tp->t_canq);
277 clist_free_cblocks(&tp->t_outq);
279 sc = (struct ppp_softc *) tp->t_sc;
282 if (tp == (struct tty *) sc->sc_devp) {
292 * Relinquish the interface unit to another device.
296 struct ppp_softc *sc;
302 m_freem(sc->sc_outm);
309 if (sc->sc_flags & SC_TIMEOUT) {
310 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
311 sc->sc_flags &= ~SC_TIMEOUT;
317 * This gets called from the upper layer to notify a mtu change
321 register struct ppp_softc *sc;
323 register struct tty *tp = (struct tty *) sc->sc_devp;
328 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
329 sc->sc_if.if_mtu + PPP_HIWAT);
334 * Line specific (tty) read routine.
335 * called at zero spl from the device driver in the response to user-level
336 * reads on the tty file descriptor (ie: pppd).
339 pppread(tp, uio, flag)
340 register struct tty *tp;
344 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
352 * Loop waiting for input, checking that nothing disasterous
353 * happens in the meantime.
357 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
361 if (sc->sc_inq.ifq_head != NULL)
363 if ((tp->t_state & TS_CONNECTED) == 0) {
365 return 0; /* end of file */
367 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
369 return (EWOULDBLOCK);
371 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
378 /* Pull place-holder byte out of canonical queue */
381 /* Get the packet from the input queue */
382 IF_DEQUEUE(&sc->sc_inq, m0);
385 for (m = m0; m && uio->uio_resid; m = m->m_next)
386 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
393 * Line specific (tty) write routine.
394 * called at zero spl from the device driver in the response to user-level
395 * writes on the tty file descriptor (ie: pppd).
398 pppwrite(tp, uio, flag)
399 register struct tty *tp;
403 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
404 struct mbuf *m, *m0, **mp;
408 if ((tp->t_state & TS_CONNECTED) == 0)
409 return 0; /* wrote 0 bytes */
410 if (tp->t_line != PPPDISC)
412 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
414 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
415 uio->uio_resid < PPP_HDRLEN)
419 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
420 MGET(m, M_WAIT, MT_DATA);
421 if ((*mp = m) == NULL) {
427 if (uio->uio_resid >= MCLBYTES / 2)
428 MCLGET(m, M_DONTWAIT);
429 len = M_TRAILINGSPACE(m);
430 if (len > uio->uio_resid)
431 len = uio->uio_resid;
432 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
439 dst.sa_family = AF_UNSPEC;
440 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
441 m0->m_data += PPP_HDRLEN;
442 m0->m_len -= PPP_HDRLEN;
444 /* call the upper layer to "transmit" it... */
445 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
451 * Line specific (tty) ioctl routine.
452 * This discipline requires that tty device drivers call
453 * the line specific l_ioctl routine from their ioctl routines.
457 ppptioctl(tp, cmd, data, flag, p)
464 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
467 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
472 case PPPIOCSASYNCMAP:
473 if ((error = suser(p)) != 0)
475 sc->sc_asyncmap[0] = *(u_int *)data;
478 case PPPIOCGASYNCMAP:
479 *(u_int *)data = sc->sc_asyncmap[0];
482 case PPPIOCSRASYNCMAP:
483 if ((error = suser(p)) != 0)
485 sc->sc_rasyncmap = *(u_int *)data;
488 case PPPIOCGRASYNCMAP:
489 *(u_int *)data = sc->sc_rasyncmap;
492 case PPPIOCSXASYNCMAP:
493 if ((error = suser(p)) != 0)
496 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
497 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
498 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
499 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
503 case PPPIOCGXASYNCMAP:
504 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
508 error = pppioctl(sc, cmd, data, flag, p);
509 if (error == 0 && cmd == PPPIOCSMRU)
517 * FCS lookup table as calculated by genfcstab.
519 static u_short fcstab[256] = {
520 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
521 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
522 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
523 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
524 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
525 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
526 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
527 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
528 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
529 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
530 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
531 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
532 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
533 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
534 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
535 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
536 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
537 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
538 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
539 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
540 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
541 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
542 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
543 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
544 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
545 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
546 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
547 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
548 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
549 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
550 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
551 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
555 * Calculate a new FCS given the current FCS and the new data.
558 pppfcs(u_short fcs, u_char *cp, int len)
561 fcs = PPP_FCS(fcs, *cp++);
566 * This gets called at splsoftnet from if_ppp.c at various times
567 * when there is data ready to be sent.
571 register struct ppp_softc *sc;
573 register struct tty *tp = (struct tty *) sc->sc_devp;
574 register struct mbuf *m;
576 register u_char *start, *stop, *cp;
577 int n, ndone, done, idle;
581 /* XXX assumes atomic access to *tp although we're not at spltty(). */
582 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
584 * See if we have an existing packet partly sent.
585 * If not, get a new packet and start sending it.
590 * Get another packet to be sent.
599 * The extra PPP_FLAG will start up a new packet, and thus
600 * will flush any accumulated garbage. We do this whenever
601 * the line may have been idle for some time.
604 if (CCOUNT(&tp->t_outq) == 0) {
605 ++sc->sc_stats.ppp_obytes;
606 (void) putc(PPP_FLAG, &tp->t_outq);
609 /* Calculate the FCS for the first mbuf's worth. */
610 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
611 getmicrotime(&sc->sc_if.if_lastchange);
615 start = mtod(m, u_char *);
620 * Find out how many bytes in the string we can
621 * handle without doing something special.
623 for (cp = start; cp < stop; cp++)
628 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
629 ndone = n - b_to_q(start, n, &tp->t_outq);
632 sc->sc_stats.ppp_obytes += ndone;
635 break; /* packet doesn't fit */
638 * If there are characters left in the mbuf,
639 * the first one must be special.
640 * Put it out in a different form.
644 if (putc(PPP_ESCAPE, &tp->t_outq)) {
648 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
649 (void) unputc(&tp->t_outq);
654 sc->sc_stats.ppp_obytes += 2;
661 * If we didn't empty this mbuf, remember where we're up to.
662 * If we emptied the last mbuf, try to add the FCS and closing
663 * flag, and if we can't, leave sc_outm pointing to m, but with
664 * m->m_len == 0, to remind us to output the FCS and flag later.
667 if (done && m->m_next == NULL) {
673 * We may have to escape the bytes in the FCS.
676 c = ~sc->sc_outfcs & 0xFF;
679 *p++ = c ^ PPP_TRANS;
682 c = (~sc->sc_outfcs >> 8) & 0xFF;
685 *p++ = c ^ PPP_TRANS;
691 * Try to output the FCS and flag. If the bytes
692 * don't all fit, back out.
695 for (q = endseq; q < p; ++q)
696 if (putc(*q, &tp->t_outq)) {
698 for (; q > endseq; --q)
704 sc->sc_stats.ppp_obytes += q - endseq;
708 /* remember where we got to */
714 /* Finished with this mbuf; free it and move on. */
717 /* Finished a packet */
720 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
724 * If m == NULL, we have finished a packet.
725 * If m != NULL, we've either done as much work this time
726 * as we need to, or else we've filled up the output queue.
733 /* Call pppstart to start output again if necessary. */
738 * This timeout is needed for operation on a pseudo-tty,
739 * because the pty code doesn't call pppstart after it has
740 * drained the t_outq.
742 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
743 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
744 sc->sc_flags |= SC_TIMEOUT;
751 * This gets called when a received packet is placed on
752 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
756 struct ppp_softc *sc;
761 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
763 tp = (struct tty *) sc->sc_devp;
764 putc(0, &tp->t_canq);
770 * Start output on async tty interface. If the transmit queue
771 * has drained sufficiently, arrange for pppasyncstart to be
772 * called later at splsoftnet.
773 * Called at spltty or higher.
777 register struct tty *tp;
779 register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
782 * Call output process whether or not there is any output.
783 * We are being called in lieu of ttstart and must do what it would.
785 if (tp->t_oproc != NULL)
789 * If the transmit queue has drained and the tty has not hung up
790 * or been disconnected from the ppp unit, then tell if_ppp.c that
791 * we need more output.
793 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
794 && !((tp->t_state & TS_CONNECTED) == 0)
795 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
803 * Timeout routine - try to start some more output.
809 struct ppp_softc *sc = (struct ppp_softc *) x;
810 struct tty *tp = (struct tty *) sc->sc_devp;
814 sc->sc_flags &= ~SC_TIMEOUT;
820 * Allocate enough mbuf to handle current MRU.
824 register struct ppp_softc *sc;
826 struct mbuf *m, **mp;
830 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
831 if ((m = *mp) == NULL) {
832 MGETHDR(m, M_DONTWAIT, MT_DATA);
836 MCLGET(m, M_DONTWAIT);
838 len -= M_DATASIZE(m);
844 * tty interface receiver interrupt.
846 static unsigned paritytab[8] = {
847 0x96696996, 0x69969669, 0x69969669, 0x96696996,
848 0x69969669, 0x96696996, 0x96696996, 0x69969669
852 * Called when character is available from device driver.
853 * Only guaranteed to be at splsofttty() or spltty()
854 * This is safe to be called while the upper half's netisr is preempted.
859 register struct tty *tp;
861 register struct ppp_softc *sc;
865 sc = (struct ppp_softc *) tp->t_sc;
866 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
870 ++sc->sc_stats.ppp_ibytes;
872 if ((tp->t_state & TS_CONNECTED) == 0) {
873 if (sc->sc_flags & SC_DEBUG)
874 printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
878 if (c & TTY_ERRORMASK) {
879 /* framing error or overrun on this char - abort packet */
880 if (sc->sc_flags & SC_DEBUG)
881 printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
889 * Handle software flow control of output.
891 if (tp->t_iflag & IXON) {
892 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
893 if ((tp->t_state & TS_TTSTOP) == 0) {
894 tp->t_state |= TS_TTSTOP;
899 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
900 tp->t_state &= ~TS_TTSTOP;
901 if (tp->t_oproc != NULL)
909 sc->sc_flags |= SC_RCV_B7_1;
911 sc->sc_flags |= SC_RCV_B7_0;
912 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
913 sc->sc_flags |= SC_RCV_ODDP;
915 sc->sc_flags |= SC_RCV_EVNP;
918 if (sc->sc_flags & SC_LOG_RAWIN)
925 if (sc->sc_rawin_count > 0)
929 * If SC_ESCAPED is set, then we've seen the packet
930 * abort sequence "}~".
932 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
933 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
935 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
936 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
937 if (sc->sc_flags & SC_DEBUG)
938 printf("ppp%d: bad fcs %x, pkt len %d\n",
939 sc->sc_if.if_unit, sc->sc_fcs, ilen);
940 sc->sc_if.if_ierrors++;
941 sc->sc_stats.ppp_ierrors++;
943 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
948 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
950 if (sc->sc_flags & SC_DEBUG)
951 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
953 sc->sc_if.if_ierrors++;
954 sc->sc_stats.ppp_ierrors++;
955 sc->sc_flags |= SC_PKTLOST;
962 * Remove FCS trailer. Somewhat painful...
965 if (--sc->sc_mc->m_len == 0) {
966 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
972 /* excise this mbuf chain */
974 sc->sc_m = sc->sc_mc->m_next;
975 sc->sc_mc->m_next = NULL;
977 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
978 if (sc->sc_flags & SC_PKTLOST) {
980 sc->sc_flags &= ~SC_PKTLOST;
988 if (sc->sc_flags & SC_FLUSH) {
989 if (sc->sc_flags & SC_LOG_FLUSH)
994 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
998 if (sc->sc_flags & SC_ESCAPED) {
999 sc->sc_flags &= ~SC_ESCAPED;
1001 } else if (c == PPP_ESCAPE) {
1002 sc->sc_flags |= SC_ESCAPED;
1009 * Initialize buffer on first octet received.
1010 * First octet could be address or protocol (when compressing
1012 * Second octet is control.
1013 * Third octet is first or second (when compressing protocol)
1014 * octet of protocol.
1015 * Fourth octet is second octet of protocol.
1017 if (sc->sc_ilen == 0) {
1018 /* reset the first input mbuf */
1019 if (sc->sc_m == NULL) {
1021 if (sc->sc_m == NULL) {
1022 if (sc->sc_flags & SC_DEBUG)
1023 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1029 m->m_data = M_DATASTART(sc->sc_m);
1031 sc->sc_mp = mtod(m, char *);
1032 sc->sc_fcs = PPP_INITFCS;
1033 if (c != PPP_ALLSTATIONS) {
1034 if (sc->sc_flags & SC_REJ_COMP_AC) {
1035 if (sc->sc_flags & SC_DEBUG)
1036 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1037 sc->sc_if.if_unit, c);
1040 *sc->sc_mp++ = PPP_ALLSTATIONS;
1041 *sc->sc_mp++ = PPP_UI;
1046 if (sc->sc_ilen == 1 && c != PPP_UI) {
1047 if (sc->sc_flags & SC_DEBUG)
1048 printf("ppp%d: missing UI (0x3), got 0x%x\n",
1049 sc->sc_if.if_unit, c);
1052 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1053 /* a compressed protocol */
1058 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1059 if (sc->sc_flags & SC_DEBUG)
1060 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1061 (sc->sc_mp[-1] << 8) + c);
1065 /* packet beyond configured mru? */
1066 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1067 if (sc->sc_flags & SC_DEBUG)
1068 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1072 /* is this mbuf full? */
1074 if (M_TRAILINGSPACE(m) <= 0) {
1075 if (m->m_next == NULL) {
1077 if (m->m_next == NULL) {
1078 if (sc->sc_flags & SC_DEBUG)
1079 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1083 sc->sc_mc = m = m->m_next;
1085 m->m_data = M_DATASTART(m);
1086 sc->sc_mp = mtod(m, char *);
1091 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1095 if (!(sc->sc_flags & SC_FLUSH)) {
1097 sc->sc_if.if_ierrors++;
1098 sc->sc_stats.ppp_ierrors++;
1099 sc->sc_flags |= SC_FLUSH;
1101 if (sc->sc_flags & SC_LOG_FLUSH)
1107 #define MAX_DUMP_BYTES 128
1111 struct ppp_softc *sc;
1115 sc->sc_rawin[sc->sc_rawin_count++] = c;
1116 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1117 || (c < 0 && sc->sc_rawin_count > 0)) {
1118 printf("ppp%d input: %*D", sc->sc_if.if_unit,
1119 sc->sc_rawin_count, sc->sc_rawin, " ");
1120 sc->sc_rawin_count = 0;