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.15 2006/01/14 11:05:18 swildner 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>
87 #include <sys/thread2.h>
91 #include <sys/vnode.h>
94 #include <i386/isa/intr_machdep.h>
98 #include <net/ifq_var.h>
103 #include <net/ppp/if_ppp.h>
104 #include <net/ppp/if_pppvar.h>
106 static int pppopen (dev_t dev, struct tty *tp);
107 static int pppclose (struct tty *tp, int flag);
108 static int pppread (struct tty *tp, struct uio *uio, int flag);
109 static int pppwrite (struct tty *tp, struct uio *uio, int flag);
110 static int ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
111 int flag, struct thread *);
112 static int pppinput (int c, struct tty *tp);
113 static int pppstart (struct tty *tp);
115 static u_short pppfcs (u_short fcs, u_char *cp, int len);
116 static void pppasyncstart (struct ppp_softc *);
117 static void pppasyncctlp (struct ppp_softc *);
118 static void pppasyncrelinq (struct ppp_softc *);
119 static void pppasyncsetmtu (struct ppp_softc *);
120 static void ppp_timeout (void *);
121 static void pppgetm (struct ppp_softc *sc);
122 static void ppplogchar (struct ppp_softc *, int);
124 /* XXX called from if_ppp.c - layering violation */
125 void pppasyncattach (void *);
128 * Some useful mbuf macros not in mbuf.h.
130 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
132 #define M_DATASTART(m) \
133 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
134 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
136 #define M_DATASIZE(m) \
137 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
138 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
141 * Does c need to be escaped?
143 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
146 * Procedures for using an async tty interface for PPP.
149 /* This is a FreeBSD-2.X kernel. */
150 #define CCOUNT(q) ((q)->c_cc)
151 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
152 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
155 * Define the PPP line discipline.
158 static struct linesw pppdisc = {
159 pppopen, pppclose, pppread, pppwrite,
160 ppptioctl, pppinput, pppstart, ttymodem,
165 pppasyncattach(void *dummy)
167 /* register line discipline */
168 linesw[PPPDISC] = pppdisc;
172 * Line specific open routine for async tty devices.
173 * Attach the given tty to the first available ppp unit.
174 * Called from device open routine or ttioctl() at >= splsofttty()
178 pppopen(dev_t dev, struct tty *tp)
180 struct thread *td = curthread; /* XXX */
181 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)) == 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().
247 pppclose(struct tty *tp, int flag)
249 struct ppp_softc *sc;
252 ttyflush(tp, FREAD | FWRITE);
253 clist_free_cblocks(&tp->t_canq);
254 clist_free_cblocks(&tp->t_outq);
256 sc = (struct ppp_softc *) tp->t_sc;
259 if (tp == (struct tty *) sc->sc_devp) {
269 * Relinquish the interface unit to another device.
272 pppasyncrelinq(struct ppp_softc *sc)
277 m_freem(sc->sc_outm);
284 if (sc->sc_flags & SC_TIMEOUT) {
285 callout_stop(&sc->sc_timeout);
286 sc->sc_flags &= ~SC_TIMEOUT;
293 * This gets called from the upper layer to notify a mtu change
296 pppasyncsetmtu(struct ppp_softc *sc)
298 struct tty *tp = (struct tty *) sc->sc_devp;
302 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
303 sc->sc_if.if_mtu + PPP_HIWAT);
308 * Line specific (tty) read routine.
309 * called at zero spl from the device driver in the response to user-level
310 * reads on the tty file descriptor (ie: pppd).
313 pppread(struct tty *tp, struct uio *uio, int flag)
315 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
322 * Loop waiting for input, checking that nothing disasterous
323 * happens in the meantime.
327 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
331 if (sc->sc_inq.ifq_head != NULL)
333 if ((tp->t_state & TS_CONNECTED) == 0) {
335 return 0; /* end of file */
337 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
339 return (EWOULDBLOCK);
341 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
348 /* Pull place-holder byte out of canonical queue */
351 /* Get the packet from the input queue */
352 IF_DEQUEUE(&sc->sc_inq, m0);
355 for (m = m0; m && uio->uio_resid; m = m->m_next)
356 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
363 * Line specific (tty) write routine.
364 * called at zero spl from the device driver in the response to user-level
365 * writes on the tty file descriptor (ie: pppd).
368 pppwrite(struct tty *tp, struct uio *uio, int flag)
370 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
371 struct mbuf *m, *m0, **mp;
375 if ((tp->t_state & TS_CONNECTED) == 0)
376 return 0; /* wrote 0 bytes */
377 if (tp->t_line != PPPDISC)
379 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
381 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
382 uio->uio_resid < PPP_HDRLEN)
386 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
387 MGET(m, MB_WAIT, MT_DATA);
388 if ((*mp = m) == NULL) {
394 if (uio->uio_resid >= MCLBYTES / 2)
395 MCLGET(m, MB_DONTWAIT);
396 len = M_TRAILINGSPACE(m);
397 if (len > uio->uio_resid)
398 len = uio->uio_resid;
399 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
406 dst.sa_family = AF_UNSPEC;
407 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
408 m0->m_data += PPP_HDRLEN;
409 m0->m_len -= PPP_HDRLEN;
411 /* call the upper layer to "transmit" it... */
412 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
418 * Line specific (tty) ioctl routine.
419 * This discipline requires that tty device drivers call
420 * the line specific l_ioctl routine from their ioctl routines.
424 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
426 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
429 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
434 case PPPIOCSASYNCMAP:
435 if ((error = suser(td)) != 0)
437 sc->sc_asyncmap[0] = *(u_int *)data;
440 case PPPIOCGASYNCMAP:
441 *(u_int *)data = sc->sc_asyncmap[0];
444 case PPPIOCSRASYNCMAP:
445 if ((error = suser(td)) != 0)
447 sc->sc_rasyncmap = *(u_int *)data;
450 case PPPIOCGRASYNCMAP:
451 *(u_int *)data = sc->sc_rasyncmap;
454 case PPPIOCSXASYNCMAP:
455 if ((error = suser(td)) != 0)
458 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
459 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
460 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
461 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
465 case PPPIOCGXASYNCMAP:
466 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
470 error = pppioctl(sc, cmd, data, flag, td);
471 if (error == 0 && cmd == PPPIOCSMRU)
479 * FCS lookup table as calculated by genfcstab.
481 static u_short fcstab[256] = {
482 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
483 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
484 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
485 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
486 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
487 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
488 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
489 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
490 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
491 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
492 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
493 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
494 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
495 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
496 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
497 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
498 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
499 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
500 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
501 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
502 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
503 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
504 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
505 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
506 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
507 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
508 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
509 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
510 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
511 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
512 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
513 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
517 * Calculate a new FCS given the current FCS and the new data.
520 pppfcs(u_short fcs, u_char *cp, int len)
523 fcs = PPP_FCS(fcs, *cp++);
528 * This gets called at splsoftnet from if_ppp.c at various times
529 * when there is data ready to be sent.
532 pppasyncstart(struct ppp_softc *sc)
534 struct tty *tp = (struct tty *) sc->sc_devp;
537 u_char *start, *stop, *cp;
538 int n, ndone, done, idle;
541 /* XXX assumes atomic access to *tp although we're not at spltty(). */
542 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
544 * See if we have an existing packet partly sent.
545 * If not, get a new packet and start sending it.
550 * Get another packet to be sent.
559 * The extra PPP_FLAG will start up a new packet, and thus
560 * will flush any accumulated garbage. We do this whenever
561 * the line may have been idle for some time.
564 if (CCOUNT(&tp->t_outq) == 0) {
565 ++sc->sc_stats.ppp_obytes;
566 putc(PPP_FLAG, &tp->t_outq);
569 /* Calculate the FCS for the first mbuf's worth. */
570 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
571 getmicrotime(&sc->sc_if.if_lastchange);
575 start = mtod(m, u_char *);
580 * Find out how many bytes in the string we can
581 * handle without doing something special.
583 for (cp = start; cp < stop; cp++)
588 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
589 ndone = n - b_to_q(start, n, &tp->t_outq);
592 sc->sc_stats.ppp_obytes += ndone;
595 break; /* packet doesn't fit */
598 * If there are characters left in the mbuf,
599 * the first one must be special.
600 * Put it out in a different form.
604 if (putc(PPP_ESCAPE, &tp->t_outq)) {
608 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
614 sc->sc_stats.ppp_obytes += 2;
621 * If we didn't empty this mbuf, remember where we're up to.
622 * If we emptied the last mbuf, try to add the FCS and closing
623 * flag, and if we can't, leave sc_outm pointing to m, but with
624 * m->m_len == 0, to remind us to output the FCS and flag later.
627 if (done && m->m_next == NULL) {
633 * We may have to escape the bytes in the FCS.
636 c = ~sc->sc_outfcs & 0xFF;
639 *p++ = c ^ PPP_TRANS;
642 c = (~sc->sc_outfcs >> 8) & 0xFF;
645 *p++ = c ^ PPP_TRANS;
651 * Try to output the FCS and flag. If the bytes
652 * don't all fit, back out.
655 for (q = endseq; q < p; ++q)
656 if (putc(*q, &tp->t_outq)) {
658 for (; q > endseq; --q)
664 sc->sc_stats.ppp_obytes += q - endseq;
668 /* remember where we got to */
674 /* Finished with this mbuf; free it and move on. */
677 /* Finished a packet */
680 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
684 * If m == NULL, we have finished a packet.
685 * If m != NULL, we've either done as much work this time
686 * as we need to, or else we've filled up the output queue.
693 /* Call pppstart to start output again if necessary. */
698 * This timeout is needed for operation on a pseudo-tty,
699 * because the pty code doesn't call pppstart after it has
700 * drained the t_outq.
702 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
703 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
704 sc->sc_flags |= SC_TIMEOUT;
711 * This gets called when a received packet is placed on
712 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
715 pppasyncctlp(struct ppp_softc *sc)
719 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
721 tp = (struct tty *) sc->sc_devp;
722 putc(0, &tp->t_canq);
728 * Start output on async tty interface. If the transmit queue
729 * has drained sufficiently, arrange for pppasyncstart to be
730 * called later at splsoftnet.
731 * Called at spltty or higher.
734 pppstart(struct tty *tp)
736 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
739 * Call output process whether or not there is any output.
740 * We are being called in lieu of ttstart and must do what it would.
742 if (tp->t_oproc != NULL)
746 * If ALTQ is enabled, don't invoke NETISR_PPP.
747 * pppintr() could loop without doing anything useful
748 * under rate-limiting.
750 if (ifq_is_enabled(&sc->sc_if.if_snd))
754 * If the transmit queue has drained and the tty has not hung up
755 * or been disconnected from the ppp unit, then tell if_ppp.c that
756 * we need more output.
758 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
759 && !((tp->t_state & TS_CONNECTED) == 0)
760 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
768 * Timeout routine - try to start some more output.
773 struct ppp_softc *sc = (struct ppp_softc *) x;
774 struct tty *tp = (struct tty *) sc->sc_devp;
777 sc->sc_flags &= ~SC_TIMEOUT;
783 * Allocate enough mbuf to handle current MRU.
786 pppgetm(struct ppp_softc *sc)
788 struct mbuf *m, **mp;
792 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
793 if ((m = *mp) == NULL) {
794 MGETHDR(m, MB_DONTWAIT, MT_DATA);
798 MCLGET(m, MB_DONTWAIT);
800 len -= M_DATASIZE(m);
806 * tty interface receiver interrupt.
808 static unsigned paritytab[8] = {
809 0x96696996, 0x69969669, 0x69969669, 0x96696996,
810 0x69969669, 0x96696996, 0x96696996, 0x69969669
814 * Called when character is available from device driver.
815 * Only guaranteed to be at splsofttty() or spltty()
816 * This is safe to be called while the upper half's netisr is preempted.
819 pppinput(int c, struct tty *tp)
821 struct ppp_softc *sc;
825 sc = (struct ppp_softc *) tp->t_sc;
826 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
830 ++sc->sc_stats.ppp_ibytes;
832 if ((tp->t_state & TS_CONNECTED) == 0) {
833 if (sc->sc_flags & SC_DEBUG)
834 printf("%s: no carrier\n", sc->sc_if.if_xname);
838 if (c & TTY_ERRORMASK) {
839 /* framing error or overrun on this char - abort packet */
840 if (sc->sc_flags & SC_DEBUG)
841 printf("%s: line error %x\n", sc->sc_if.if_xname,
849 * Handle software flow control of output.
851 if (tp->t_iflag & IXON) {
852 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
853 if ((tp->t_state & TS_TTSTOP) == 0) {
854 tp->t_state |= TS_TTSTOP;
859 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
860 tp->t_state &= ~TS_TTSTOP;
861 if (tp->t_oproc != NULL)
869 sc->sc_flags |= SC_RCV_B7_1;
871 sc->sc_flags |= SC_RCV_B7_0;
872 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
873 sc->sc_flags |= SC_RCV_ODDP;
875 sc->sc_flags |= SC_RCV_EVNP;
878 if (sc->sc_flags & SC_LOG_RAWIN)
885 if (sc->sc_rawin_count > 0)
889 * If SC_ESCAPED is set, then we've seen the packet
890 * abort sequence "}~".
892 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
893 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
895 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
896 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
897 if (sc->sc_flags & SC_DEBUG)
898 printf("%s: bad fcs %x, pkt len %d\n",
899 sc->sc_if.if_xname, sc->sc_fcs, ilen);
900 sc->sc_if.if_ierrors++;
901 sc->sc_stats.ppp_ierrors++;
903 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
908 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
910 if (sc->sc_flags & SC_DEBUG)
911 printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
913 sc->sc_if.if_ierrors++;
914 sc->sc_stats.ppp_ierrors++;
915 sc->sc_flags |= SC_PKTLOST;
922 * Remove FCS trailer. Somewhat painful...
925 if (--sc->sc_mc->m_len == 0) {
926 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
932 /* excise this mbuf chain */
934 sc->sc_m = sc->sc_mc->m_next;
935 sc->sc_mc->m_next = NULL;
937 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
938 if (sc->sc_flags & SC_PKTLOST) {
940 sc->sc_flags &= ~SC_PKTLOST;
948 if (sc->sc_flags & SC_FLUSH) {
949 if (sc->sc_flags & SC_LOG_FLUSH)
954 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
958 if (sc->sc_flags & SC_ESCAPED) {
959 sc->sc_flags &= ~SC_ESCAPED;
961 } else if (c == PPP_ESCAPE) {
962 sc->sc_flags |= SC_ESCAPED;
969 * Initialize buffer on first octet received.
970 * First octet could be address or protocol (when compressing
972 * Second octet is control.
973 * Third octet is first or second (when compressing protocol)
975 * Fourth octet is second octet of protocol.
977 if (sc->sc_ilen == 0) {
978 /* reset the first input mbuf */
979 if (sc->sc_m == NULL) {
981 if (sc->sc_m == NULL) {
982 if (sc->sc_flags & SC_DEBUG)
983 printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
989 m->m_data = M_DATASTART(sc->sc_m);
991 sc->sc_mp = mtod(m, char *);
992 sc->sc_fcs = PPP_INITFCS;
993 if (c != PPP_ALLSTATIONS) {
994 if (sc->sc_flags & SC_REJ_COMP_AC) {
995 if (sc->sc_flags & SC_DEBUG)
996 printf("%s: garbage received: 0x%x (need 0xFF)\n",
997 sc->sc_if.if_xname, c);
1000 *sc->sc_mp++ = PPP_ALLSTATIONS;
1001 *sc->sc_mp++ = PPP_UI;
1006 if (sc->sc_ilen == 1 && c != PPP_UI) {
1007 if (sc->sc_flags & SC_DEBUG)
1008 printf("%s: missing UI (0x3), got 0x%x\n",
1009 sc->sc_if.if_xname, c);
1012 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1013 /* a compressed protocol */
1018 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1019 if (sc->sc_flags & SC_DEBUG)
1020 printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1021 (sc->sc_mp[-1] << 8) + c);
1025 /* packet beyond configured mru? */
1026 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1027 if (sc->sc_flags & SC_DEBUG)
1028 printf("%s: packet too big\n", sc->sc_if.if_xname);
1032 /* is this mbuf full? */
1034 if (M_TRAILINGSPACE(m) <= 0) {
1035 if (m->m_next == NULL) {
1037 if (m->m_next == NULL) {
1038 if (sc->sc_flags & SC_DEBUG)
1039 printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1043 sc->sc_mc = m = m->m_next;
1045 m->m_data = M_DATASTART(m);
1046 sc->sc_mp = mtod(m, char *);
1051 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1055 if (!(sc->sc_flags & SC_FLUSH)) {
1057 sc->sc_if.if_ierrors++;
1058 sc->sc_stats.ppp_ierrors++;
1059 sc->sc_flags |= SC_FLUSH;
1061 if (sc->sc_flags & SC_LOG_FLUSH)
1067 #define MAX_DUMP_BYTES 128
1070 ppplogchar(struct ppp_softc *sc, int c)
1073 sc->sc_rawin[sc->sc_rawin_count++] = c;
1074 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1075 || (c < 0 && sc->sc_rawin_count > 0)) {
1076 printf("%s input: %*D", sc->sc_if.if_xname,
1077 sc->sc_rawin_count, sc->sc_rawin, " ");
1078 sc->sc_rawin_count = 0;