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.12 2005/02/11 22:25:57 joerg 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>
97 #include <net/ifq_var.h>
102 #include <net/ppp/if_ppp.h>
103 #include <net/ppp/if_pppvar.h>
105 static int pppopen (dev_t dev, struct tty *tp);
106 static int pppclose (struct tty *tp, int flag);
107 static int pppread (struct tty *tp, struct uio *uio, int flag);
108 static int pppwrite (struct tty *tp, struct uio *uio, int flag);
109 static int ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
110 int flag, struct thread *);
111 static int pppinput (int c, struct tty *tp);
112 static int pppstart (struct tty *tp);
114 static u_short pppfcs (u_short fcs, u_char *cp, int len);
115 static void pppasyncstart (struct ppp_softc *);
116 static void pppasyncctlp (struct ppp_softc *);
117 static void pppasyncrelinq (struct ppp_softc *);
118 static void pppasyncsetmtu (struct ppp_softc *);
119 static void ppp_timeout (void *);
120 static void pppgetm (struct ppp_softc *sc);
121 static void ppplogchar (struct ppp_softc *, int);
123 /* XXX called from if_ppp.c - layering violation */
124 void pppasyncattach (void *);
127 * Some useful mbuf macros not in mbuf.h.
129 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
131 #define M_DATASTART(m) \
132 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
133 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
135 #define M_DATASIZE(m) \
136 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
137 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
140 * Does c need to be escaped?
142 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
145 * Procedures for using an async tty interface for PPP.
148 /* This is a FreeBSD-2.X kernel. */
149 #define CCOUNT(q) ((q)->c_cc)
150 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
151 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
154 * Define the PPP line discipline.
157 static struct linesw pppdisc = {
158 pppopen, pppclose, pppread, pppwrite,
159 ppptioctl, pppinput, pppstart, ttymodem,
164 pppasyncattach(dummy)
173 * Make sure that the soft net "engine" cannot run while spltty code is
174 * active. The if_ppp.c code can walk down into b_to_q etc, and it is
175 * bad if the tty system was in the middle of another b_to_q...
177 tty_imask |= softnet_imask; /* spltty() block spl[soft]net() */
178 net_imask |= softtty_imask; /* splimp() block splsofttty() */
179 net_imask |= tty_imask; /* splimp() block spltty() */
184 printf("new masks: bio %x, tty %x, net %x\n",
185 bio_imask, tty_imask, net_imask);
188 /* register line discipline */
189 linesw[PPPDISC] = pppdisc;
193 * Line specific open routine for async tty devices.
194 * Attach the given tty to the first available ppp unit.
195 * Called from device open routine or ttioctl() at >= splsofttty()
199 pppopen(dev_t dev, struct tty *tp)
201 struct thread *td = curthread; /* XXX */
202 struct ppp_softc *sc;
205 if ((error = suser(td)) != 0)
210 if (tp->t_line == PPPDISC) {
211 sc = (struct ppp_softc *) tp->t_sc;
212 if (sc != NULL && sc->sc_devp == (void *) tp) {
218 if ((sc = pppalloc(td)) == NULL) {
224 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
228 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
229 sc->sc_asyncmap[0] = 0xffffffff;
230 sc->sc_asyncmap[3] = 0x60000000;
231 sc->sc_rasyncmap = 0;
232 sc->sc_devp = (void *) tp;
233 sc->sc_start = pppasyncstart;
234 sc->sc_ctlp = pppasyncctlp;
235 sc->sc_relinq = pppasyncrelinq;
236 sc->sc_setmtu = pppasyncsetmtu;
239 sc->sc_if.if_flags |= IFF_RUNNING;
240 getmicrotime(&sc->sc_if.if_lastchange);
241 sc->sc_if.if_baudrate = tp->t_ospeed;
243 tp->t_sc = (caddr_t) sc;
244 ttyflush(tp, FREAD | FWRITE);
247 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
248 * allocation helps avoid the need for select and/or FIONREAD.
249 * We also pass 1 byte tokens through t_canq...
251 clist_alloc_cblocks(&tp->t_canq, 1, 1);
252 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
253 sc->sc_if.if_mtu + PPP_HIWAT);
254 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
262 * Line specific close routine, called from device close routine
263 * and from ttioctl at >= splsofttty().
264 * Detach the tty from the ppp unit.
265 * Mimics part of ttyclose().
272 struct ppp_softc *sc;
276 ttyflush(tp, FREAD | FWRITE);
277 clist_free_cblocks(&tp->t_canq);
278 clist_free_cblocks(&tp->t_outq);
280 sc = (struct ppp_softc *) tp->t_sc;
283 if (tp == (struct tty *) sc->sc_devp) {
293 * Relinquish the interface unit to another device.
297 struct ppp_softc *sc;
303 m_freem(sc->sc_outm);
310 if (sc->sc_flags & SC_TIMEOUT) {
311 callout_stop(&sc->sc_timeout);
312 sc->sc_flags &= ~SC_TIMEOUT;
318 * This gets called from the upper layer to notify a mtu change
322 struct ppp_softc *sc;
324 struct tty *tp = (struct tty *) sc->sc_devp;
329 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
330 sc->sc_if.if_mtu + PPP_HIWAT);
335 * Line specific (tty) read routine.
336 * called at zero spl from the device driver in the response to user-level
337 * reads on the tty file descriptor (ie: pppd).
340 pppread(tp, uio, flag)
345 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
353 * Loop waiting for input, checking that nothing disasterous
354 * happens in the meantime.
358 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
362 if (sc->sc_inq.ifq_head != NULL)
364 if ((tp->t_state & TS_CONNECTED) == 0) {
366 return 0; /* end of file */
368 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
370 return (EWOULDBLOCK);
372 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
379 /* Pull place-holder byte out of canonical queue */
382 /* Get the packet from the input queue */
383 IF_DEQUEUE(&sc->sc_inq, m0);
386 for (m = m0; m && uio->uio_resid; m = m->m_next)
387 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
394 * Line specific (tty) write routine.
395 * called at zero spl from the device driver in the response to user-level
396 * writes on the tty file descriptor (ie: pppd).
399 pppwrite(tp, uio, flag)
404 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
405 struct mbuf *m, *m0, **mp;
409 if ((tp->t_state & TS_CONNECTED) == 0)
410 return 0; /* wrote 0 bytes */
411 if (tp->t_line != PPPDISC)
413 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
415 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
416 uio->uio_resid < PPP_HDRLEN)
420 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
421 MGET(m, MB_WAIT, MT_DATA);
422 if ((*mp = m) == NULL) {
428 if (uio->uio_resid >= MCLBYTES / 2)
429 MCLGET(m, MB_DONTWAIT);
430 len = M_TRAILINGSPACE(m);
431 if (len > uio->uio_resid)
432 len = uio->uio_resid;
433 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
440 dst.sa_family = AF_UNSPEC;
441 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
442 m0->m_data += PPP_HDRLEN;
443 m0->m_len -= PPP_HDRLEN;
445 /* call the upper layer to "transmit" it... */
446 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
452 * Line specific (tty) ioctl routine.
453 * This discipline requires that tty device drivers call
454 * the line specific l_ioctl routine from their ioctl routines.
458 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
460 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
463 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
468 case PPPIOCSASYNCMAP:
469 if ((error = suser(td)) != 0)
471 sc->sc_asyncmap[0] = *(u_int *)data;
474 case PPPIOCGASYNCMAP:
475 *(u_int *)data = sc->sc_asyncmap[0];
478 case PPPIOCSRASYNCMAP:
479 if ((error = suser(td)) != 0)
481 sc->sc_rasyncmap = *(u_int *)data;
484 case PPPIOCGRASYNCMAP:
485 *(u_int *)data = sc->sc_rasyncmap;
488 case PPPIOCSXASYNCMAP:
489 if ((error = suser(td)) != 0)
492 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
493 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
494 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
495 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
499 case PPPIOCGXASYNCMAP:
500 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
504 error = pppioctl(sc, cmd, data, flag, td);
505 if (error == 0 && cmd == PPPIOCSMRU)
513 * FCS lookup table as calculated by genfcstab.
515 static u_short fcstab[256] = {
516 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
517 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
518 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
519 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
520 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
521 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
522 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
523 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
524 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
525 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
526 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
527 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
528 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
529 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
530 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
531 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
532 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
533 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
534 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
535 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
536 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
537 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
538 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
539 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
540 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
541 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
542 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
543 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
544 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
545 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
546 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
547 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
551 * Calculate a new FCS given the current FCS and the new data.
554 pppfcs(u_short fcs, u_char *cp, int len)
557 fcs = PPP_FCS(fcs, *cp++);
562 * This gets called at splsoftnet from if_ppp.c at various times
563 * when there is data ready to be sent.
567 struct ppp_softc *sc;
569 struct tty *tp = (struct tty *) sc->sc_devp;
572 u_char *start, *stop, *cp;
573 int n, ndone, done, idle;
577 /* XXX assumes atomic access to *tp although we're not at spltty(). */
578 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
580 * See if we have an existing packet partly sent.
581 * If not, get a new packet and start sending it.
586 * Get another packet to be sent.
595 * The extra PPP_FLAG will start up a new packet, and thus
596 * will flush any accumulated garbage. We do this whenever
597 * the line may have been idle for some time.
600 if (CCOUNT(&tp->t_outq) == 0) {
601 ++sc->sc_stats.ppp_obytes;
602 (void) putc(PPP_FLAG, &tp->t_outq);
605 /* Calculate the FCS for the first mbuf's worth. */
606 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
607 getmicrotime(&sc->sc_if.if_lastchange);
611 start = mtod(m, u_char *);
616 * Find out how many bytes in the string we can
617 * handle without doing something special.
619 for (cp = start; cp < stop; cp++)
624 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
625 ndone = n - b_to_q(start, n, &tp->t_outq);
628 sc->sc_stats.ppp_obytes += ndone;
631 break; /* packet doesn't fit */
634 * If there are characters left in the mbuf,
635 * the first one must be special.
636 * Put it out in a different form.
640 if (putc(PPP_ESCAPE, &tp->t_outq)) {
644 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
645 (void) unputc(&tp->t_outq);
650 sc->sc_stats.ppp_obytes += 2;
657 * If we didn't empty this mbuf, remember where we're up to.
658 * If we emptied the last mbuf, try to add the FCS and closing
659 * flag, and if we can't, leave sc_outm pointing to m, but with
660 * m->m_len == 0, to remind us to output the FCS and flag later.
663 if (done && m->m_next == NULL) {
669 * We may have to escape the bytes in the FCS.
672 c = ~sc->sc_outfcs & 0xFF;
675 *p++ = c ^ PPP_TRANS;
678 c = (~sc->sc_outfcs >> 8) & 0xFF;
681 *p++ = c ^ PPP_TRANS;
687 * Try to output the FCS and flag. If the bytes
688 * don't all fit, back out.
691 for (q = endseq; q < p; ++q)
692 if (putc(*q, &tp->t_outq)) {
694 for (; q > endseq; --q)
700 sc->sc_stats.ppp_obytes += q - endseq;
704 /* remember where we got to */
710 /* Finished with this mbuf; free it and move on. */
713 /* Finished a packet */
716 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
720 * If m == NULL, we have finished a packet.
721 * If m != NULL, we've either done as much work this time
722 * as we need to, or else we've filled up the output queue.
729 /* Call pppstart to start output again if necessary. */
734 * This timeout is needed for operation on a pseudo-tty,
735 * because the pty code doesn't call pppstart after it has
736 * drained the t_outq.
738 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
739 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
740 sc->sc_flags |= SC_TIMEOUT;
747 * This gets called when a received packet is placed on
748 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
752 struct ppp_softc *sc;
757 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
759 tp = (struct tty *) sc->sc_devp;
760 putc(0, &tp->t_canq);
766 * Start output on async tty interface. If the transmit queue
767 * has drained sufficiently, arrange for pppasyncstart to be
768 * called later at splsoftnet.
769 * Called at spltty or higher.
775 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
778 * Call output process whether or not there is any output.
779 * We are being called in lieu of ttstart and must do what it would.
781 if (tp->t_oproc != NULL)
785 * If ALTQ is enabled, don't invoke NETISR_PPP.
786 * pppintr() could loop without doing anything useful
787 * under rate-limiting.
789 if (ifq_is_enabled(&sc->sc_if.if_snd))
793 * If the transmit queue has drained and the tty has not hung up
794 * or been disconnected from the ppp unit, then tell if_ppp.c that
795 * we need more output.
797 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
798 && !((tp->t_state & TS_CONNECTED) == 0)
799 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
807 * Timeout routine - try to start some more output.
813 struct ppp_softc *sc = (struct ppp_softc *) x;
814 struct tty *tp = (struct tty *) sc->sc_devp;
818 sc->sc_flags &= ~SC_TIMEOUT;
824 * Allocate enough mbuf to handle current MRU.
828 struct ppp_softc *sc;
830 struct mbuf *m, **mp;
834 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
835 if ((m = *mp) == NULL) {
836 MGETHDR(m, MB_DONTWAIT, MT_DATA);
840 MCLGET(m, MB_DONTWAIT);
842 len -= M_DATASIZE(m);
848 * tty interface receiver interrupt.
850 static unsigned paritytab[8] = {
851 0x96696996, 0x69969669, 0x69969669, 0x96696996,
852 0x69969669, 0x96696996, 0x96696996, 0x69969669
856 * Called when character is available from device driver.
857 * Only guaranteed to be at splsofttty() or spltty()
858 * This is safe to be called while the upper half's netisr is preempted.
865 struct ppp_softc *sc;
869 sc = (struct ppp_softc *) tp->t_sc;
870 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
874 ++sc->sc_stats.ppp_ibytes;
876 if ((tp->t_state & TS_CONNECTED) == 0) {
877 if (sc->sc_flags & SC_DEBUG)
878 printf("%s: no carrier\n", sc->sc_if.if_xname);
882 if (c & TTY_ERRORMASK) {
883 /* framing error or overrun on this char - abort packet */
884 if (sc->sc_flags & SC_DEBUG)
885 printf("%s: line error %x\n", sc->sc_if.if_xname,
893 * Handle software flow control of output.
895 if (tp->t_iflag & IXON) {
896 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
897 if ((tp->t_state & TS_TTSTOP) == 0) {
898 tp->t_state |= TS_TTSTOP;
903 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
904 tp->t_state &= ~TS_TTSTOP;
905 if (tp->t_oproc != NULL)
913 sc->sc_flags |= SC_RCV_B7_1;
915 sc->sc_flags |= SC_RCV_B7_0;
916 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
917 sc->sc_flags |= SC_RCV_ODDP;
919 sc->sc_flags |= SC_RCV_EVNP;
922 if (sc->sc_flags & SC_LOG_RAWIN)
929 if (sc->sc_rawin_count > 0)
933 * If SC_ESCAPED is set, then we've seen the packet
934 * abort sequence "}~".
936 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
937 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
939 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
940 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
941 if (sc->sc_flags & SC_DEBUG)
942 printf("%s: bad fcs %x, pkt len %d\n",
943 sc->sc_if.if_xname, sc->sc_fcs, ilen);
944 sc->sc_if.if_ierrors++;
945 sc->sc_stats.ppp_ierrors++;
947 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
952 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
954 if (sc->sc_flags & SC_DEBUG)
955 printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
957 sc->sc_if.if_ierrors++;
958 sc->sc_stats.ppp_ierrors++;
959 sc->sc_flags |= SC_PKTLOST;
966 * Remove FCS trailer. Somewhat painful...
969 if (--sc->sc_mc->m_len == 0) {
970 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
976 /* excise this mbuf chain */
978 sc->sc_m = sc->sc_mc->m_next;
979 sc->sc_mc->m_next = NULL;
981 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
982 if (sc->sc_flags & SC_PKTLOST) {
984 sc->sc_flags &= ~SC_PKTLOST;
992 if (sc->sc_flags & SC_FLUSH) {
993 if (sc->sc_flags & SC_LOG_FLUSH)
998 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1002 if (sc->sc_flags & SC_ESCAPED) {
1003 sc->sc_flags &= ~SC_ESCAPED;
1005 } else if (c == PPP_ESCAPE) {
1006 sc->sc_flags |= SC_ESCAPED;
1013 * Initialize buffer on first octet received.
1014 * First octet could be address or protocol (when compressing
1016 * Second octet is control.
1017 * Third octet is first or second (when compressing protocol)
1018 * octet of protocol.
1019 * Fourth octet is second octet of protocol.
1021 if (sc->sc_ilen == 0) {
1022 /* reset the first input mbuf */
1023 if (sc->sc_m == NULL) {
1025 if (sc->sc_m == NULL) {
1026 if (sc->sc_flags & SC_DEBUG)
1027 printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1033 m->m_data = M_DATASTART(sc->sc_m);
1035 sc->sc_mp = mtod(m, char *);
1036 sc->sc_fcs = PPP_INITFCS;
1037 if (c != PPP_ALLSTATIONS) {
1038 if (sc->sc_flags & SC_REJ_COMP_AC) {
1039 if (sc->sc_flags & SC_DEBUG)
1040 printf("%s: garbage received: 0x%x (need 0xFF)\n",
1041 sc->sc_if.if_xname, c);
1044 *sc->sc_mp++ = PPP_ALLSTATIONS;
1045 *sc->sc_mp++ = PPP_UI;
1050 if (sc->sc_ilen == 1 && c != PPP_UI) {
1051 if (sc->sc_flags & SC_DEBUG)
1052 printf("%s: missing UI (0x3), got 0x%x\n",
1053 sc->sc_if.if_xname, c);
1056 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1057 /* a compressed protocol */
1062 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1063 if (sc->sc_flags & SC_DEBUG)
1064 printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1065 (sc->sc_mp[-1] << 8) + c);
1069 /* packet beyond configured mru? */
1070 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1071 if (sc->sc_flags & SC_DEBUG)
1072 printf("%s: packet too big\n", sc->sc_if.if_xname);
1076 /* is this mbuf full? */
1078 if (M_TRAILINGSPACE(m) <= 0) {
1079 if (m->m_next == NULL) {
1081 if (m->m_next == NULL) {
1082 if (sc->sc_flags & SC_DEBUG)
1083 printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1087 sc->sc_mc = m = m->m_next;
1089 m->m_data = M_DATASTART(m);
1090 sc->sc_mp = mtod(m, char *);
1095 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1099 if (!(sc->sc_flags & SC_FLUSH)) {
1101 sc->sc_if.if_ierrors++;
1102 sc->sc_stats.ppp_ierrors++;
1103 sc->sc_flags |= SC_FLUSH;
1105 if (sc->sc_flags & SC_LOG_FLUSH)
1111 #define MAX_DUMP_BYTES 128
1115 struct ppp_softc *sc;
1119 sc->sc_rawin[sc->sc_rawin_count++] = c;
1120 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1121 || (c < 0 && sc->sc_rawin_count > 0)) {
1122 printf("%s input: %*D", sc->sc_if.if_xname,
1123 sc->sc_rawin_count, sc->sc_rawin, " ");
1124 sc->sc_rawin_count = 0;