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.3 2003/06/23 17:55:45 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,
107 int flag, struct thread *));
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()
196 pppopen(dev_t dev, struct tty *tp)
198 struct proc *p = curproc; /* XXX */
199 struct ppp_softc *sc;
202 if ((error = suser_xxx(p->p_ucred, 0)) != 0)
207 if (tp->t_line == PPPDISC) {
208 sc = (struct ppp_softc *) tp->t_sc;
209 if (sc != NULL && sc->sc_devp == (void *) tp) {
215 if ((sc = pppalloc(p->p_pid)) == NULL) {
221 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
225 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
226 sc->sc_asyncmap[0] = 0xffffffff;
227 sc->sc_asyncmap[3] = 0x60000000;
228 sc->sc_rasyncmap = 0;
229 sc->sc_devp = (void *) tp;
230 sc->sc_start = pppasyncstart;
231 sc->sc_ctlp = pppasyncctlp;
232 sc->sc_relinq = pppasyncrelinq;
233 sc->sc_setmtu = pppasyncsetmtu;
236 sc->sc_if.if_flags |= IFF_RUNNING;
237 getmicrotime(&sc->sc_if.if_lastchange);
238 sc->sc_if.if_baudrate = tp->t_ospeed;
240 tp->t_sc = (caddr_t) sc;
241 ttyflush(tp, FREAD | FWRITE);
244 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
245 * allocation helps avoid the need for select and/or FIONREAD.
246 * We also pass 1 byte tokens through t_canq...
248 clist_alloc_cblocks(&tp->t_canq, 1, 1);
249 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
250 sc->sc_if.if_mtu + PPP_HIWAT);
251 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
259 * Line specific close routine, called from device close routine
260 * and from ttioctl at >= splsofttty().
261 * Detach the tty from the ppp unit.
262 * Mimics part of ttyclose().
269 register struct ppp_softc *sc;
273 ttyflush(tp, FREAD | FWRITE);
274 clist_free_cblocks(&tp->t_canq);
275 clist_free_cblocks(&tp->t_outq);
277 sc = (struct ppp_softc *) tp->t_sc;
280 if (tp == (struct tty *) sc->sc_devp) {
290 * Relinquish the interface unit to another device.
294 struct ppp_softc *sc;
300 m_freem(sc->sc_outm);
307 if (sc->sc_flags & SC_TIMEOUT) {
308 untimeout(ppp_timeout, (void *) sc, sc->sc_ch);
309 sc->sc_flags &= ~SC_TIMEOUT;
315 * This gets called from the upper layer to notify a mtu change
319 register struct ppp_softc *sc;
321 register struct tty *tp = (struct tty *) sc->sc_devp;
326 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
327 sc->sc_if.if_mtu + PPP_HIWAT);
332 * Line specific (tty) read routine.
333 * called at zero spl from the device driver in the response to user-level
334 * reads on the tty file descriptor (ie: pppd).
337 pppread(tp, uio, flag)
338 register struct tty *tp;
342 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
350 * Loop waiting for input, checking that nothing disasterous
351 * happens in the meantime.
355 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
359 if (sc->sc_inq.ifq_head != NULL)
361 if ((tp->t_state & TS_CONNECTED) == 0) {
363 return 0; /* end of file */
365 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
367 return (EWOULDBLOCK);
369 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
376 /* Pull place-holder byte out of canonical queue */
379 /* Get the packet from the input queue */
380 IF_DEQUEUE(&sc->sc_inq, m0);
383 for (m = m0; m && uio->uio_resid; m = m->m_next)
384 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
391 * Line specific (tty) write routine.
392 * called at zero spl from the device driver in the response to user-level
393 * writes on the tty file descriptor (ie: pppd).
396 pppwrite(tp, uio, flag)
397 register struct tty *tp;
401 register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
402 struct mbuf *m, *m0, **mp;
406 if ((tp->t_state & TS_CONNECTED) == 0)
407 return 0; /* wrote 0 bytes */
408 if (tp->t_line != PPPDISC)
410 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
412 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
413 uio->uio_resid < PPP_HDRLEN)
417 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
418 MGET(m, M_WAIT, MT_DATA);
419 if ((*mp = m) == NULL) {
425 if (uio->uio_resid >= MCLBYTES / 2)
426 MCLGET(m, M_DONTWAIT);
427 len = M_TRAILINGSPACE(m);
428 if (len > uio->uio_resid)
429 len = uio->uio_resid;
430 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
437 dst.sa_family = AF_UNSPEC;
438 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
439 m0->m_data += PPP_HDRLEN;
440 m0->m_len -= PPP_HDRLEN;
442 /* call the upper layer to "transmit" it... */
443 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
449 * Line specific (tty) ioctl routine.
450 * This discipline requires that tty device drivers call
451 * the line specific l_ioctl routine from their ioctl routines.
455 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
457 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
458 struct proc *p = td->td_proc;
463 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
468 case PPPIOCSASYNCMAP:
469 if ((error = suser_xxx(p->p_ucred, 0)) != 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_xxx(p->p_ucred, 0)) != 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_xxx(p->p_ucred, 0)) != 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, p);
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 register struct ppp_softc *sc;
569 register struct tty *tp = (struct tty *) sc->sc_devp;
570 register struct mbuf *m;
572 register 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 sc->sc_ch = timeout(ppp_timeout, (void *) sc, 1);
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.
773 register struct tty *tp;
775 register 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 the transmit queue has drained and the tty has not hung up
786 * or been disconnected from the ppp unit, then tell if_ppp.c that
787 * we need more output.
789 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
790 && !((tp->t_state & TS_CONNECTED) == 0)
791 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
799 * Timeout routine - try to start some more output.
805 struct ppp_softc *sc = (struct ppp_softc *) x;
806 struct tty *tp = (struct tty *) sc->sc_devp;
810 sc->sc_flags &= ~SC_TIMEOUT;
816 * Allocate enough mbuf to handle current MRU.
820 register struct ppp_softc *sc;
822 struct mbuf *m, **mp;
826 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
827 if ((m = *mp) == NULL) {
828 MGETHDR(m, M_DONTWAIT, MT_DATA);
832 MCLGET(m, M_DONTWAIT);
834 len -= M_DATASIZE(m);
840 * tty interface receiver interrupt.
842 static unsigned paritytab[8] = {
843 0x96696996, 0x69969669, 0x69969669, 0x96696996,
844 0x69969669, 0x96696996, 0x96696996, 0x69969669
848 * Called when character is available from device driver.
849 * Only guaranteed to be at splsofttty() or spltty()
850 * This is safe to be called while the upper half's netisr is preempted.
855 register struct tty *tp;
857 register struct ppp_softc *sc;
861 sc = (struct ppp_softc *) tp->t_sc;
862 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
866 ++sc->sc_stats.ppp_ibytes;
868 if ((tp->t_state & TS_CONNECTED) == 0) {
869 if (sc->sc_flags & SC_DEBUG)
870 printf("ppp%d: no carrier\n", sc->sc_if.if_unit);
874 if (c & TTY_ERRORMASK) {
875 /* framing error or overrun on this char - abort packet */
876 if (sc->sc_flags & SC_DEBUG)
877 printf("ppp%d: line error %x\n", sc->sc_if.if_unit,
885 * Handle software flow control of output.
887 if (tp->t_iflag & IXON) {
888 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
889 if ((tp->t_state & TS_TTSTOP) == 0) {
890 tp->t_state |= TS_TTSTOP;
895 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
896 tp->t_state &= ~TS_TTSTOP;
897 if (tp->t_oproc != NULL)
905 sc->sc_flags |= SC_RCV_B7_1;
907 sc->sc_flags |= SC_RCV_B7_0;
908 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
909 sc->sc_flags |= SC_RCV_ODDP;
911 sc->sc_flags |= SC_RCV_EVNP;
914 if (sc->sc_flags & SC_LOG_RAWIN)
921 if (sc->sc_rawin_count > 0)
925 * If SC_ESCAPED is set, then we've seen the packet
926 * abort sequence "}~".
928 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
929 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
931 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
932 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
933 if (sc->sc_flags & SC_DEBUG)
934 printf("ppp%d: bad fcs %x, pkt len %d\n",
935 sc->sc_if.if_unit, sc->sc_fcs, ilen);
936 sc->sc_if.if_ierrors++;
937 sc->sc_stats.ppp_ierrors++;
939 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
944 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
946 if (sc->sc_flags & SC_DEBUG)
947 printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
949 sc->sc_if.if_ierrors++;
950 sc->sc_stats.ppp_ierrors++;
951 sc->sc_flags |= SC_PKTLOST;
958 * Remove FCS trailer. Somewhat painful...
961 if (--sc->sc_mc->m_len == 0) {
962 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
968 /* excise this mbuf chain */
970 sc->sc_m = sc->sc_mc->m_next;
971 sc->sc_mc->m_next = NULL;
973 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
974 if (sc->sc_flags & SC_PKTLOST) {
976 sc->sc_flags &= ~SC_PKTLOST;
984 if (sc->sc_flags & SC_FLUSH) {
985 if (sc->sc_flags & SC_LOG_FLUSH)
990 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
994 if (sc->sc_flags & SC_ESCAPED) {
995 sc->sc_flags &= ~SC_ESCAPED;
997 } else if (c == PPP_ESCAPE) {
998 sc->sc_flags |= SC_ESCAPED;
1005 * Initialize buffer on first octet received.
1006 * First octet could be address or protocol (when compressing
1008 * Second octet is control.
1009 * Third octet is first or second (when compressing protocol)
1010 * octet of protocol.
1011 * Fourth octet is second octet of protocol.
1013 if (sc->sc_ilen == 0) {
1014 /* reset the first input mbuf */
1015 if (sc->sc_m == NULL) {
1017 if (sc->sc_m == NULL) {
1018 if (sc->sc_flags & SC_DEBUG)
1019 printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1025 m->m_data = M_DATASTART(sc->sc_m);
1027 sc->sc_mp = mtod(m, char *);
1028 sc->sc_fcs = PPP_INITFCS;
1029 if (c != PPP_ALLSTATIONS) {
1030 if (sc->sc_flags & SC_REJ_COMP_AC) {
1031 if (sc->sc_flags & SC_DEBUG)
1032 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1033 sc->sc_if.if_unit, c);
1036 *sc->sc_mp++ = PPP_ALLSTATIONS;
1037 *sc->sc_mp++ = PPP_UI;
1042 if (sc->sc_ilen == 1 && c != PPP_UI) {
1043 if (sc->sc_flags & SC_DEBUG)
1044 printf("ppp%d: missing UI (0x3), got 0x%x\n",
1045 sc->sc_if.if_unit, c);
1048 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1049 /* a compressed protocol */
1054 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1055 if (sc->sc_flags & SC_DEBUG)
1056 printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1057 (sc->sc_mp[-1] << 8) + c);
1061 /* packet beyond configured mru? */
1062 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1063 if (sc->sc_flags & SC_DEBUG)
1064 printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1068 /* is this mbuf full? */
1070 if (M_TRAILINGSPACE(m) <= 0) {
1071 if (m->m_next == NULL) {
1073 if (m->m_next == NULL) {
1074 if (sc->sc_flags & SC_DEBUG)
1075 printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1079 sc->sc_mc = m = m->m_next;
1081 m->m_data = M_DATASTART(m);
1082 sc->sc_mp = mtod(m, char *);
1087 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1091 if (!(sc->sc_flags & SC_FLUSH)) {
1093 sc->sc_if.if_ierrors++;
1094 sc->sc_stats.ppp_ierrors++;
1095 sc->sc_flags |= SC_FLUSH;
1097 if (sc->sc_flags & SC_LOG_FLUSH)
1103 #define MAX_DUMP_BYTES 128
1107 struct ppp_softc *sc;
1111 sc->sc_rawin[sc->sc_rawin_count++] = c;
1112 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1113 || (c < 0 && sc->sc_rawin_count > 0)) {
1114 printf("ppp%d input: %*D", sc->sc_if.if_unit,
1115 sc->sc_rawin_count, sc->sc_rawin, " ");
1116 sc->sc_rawin_count = 0;