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.18 2006/07/28 02:17:40 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>
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 ucred *);
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 lwkt_serialize_enter(sc->sc_if.if_serializer);
413 error = pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0);
414 lwkt_serialize_exit(sc->sc_if.if_serializer);
420 * Line specific (tty) ioctl routine.
421 * This discipline requires that tty device drivers call
422 * the line specific l_ioctl routine from their ioctl routines.
426 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cr)
428 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
431 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
436 case PPPIOCSASYNCMAP:
437 if ((error = suser_cred(cr, 0)) != 0)
439 sc->sc_asyncmap[0] = *(u_int *)data;
442 case PPPIOCGASYNCMAP:
443 *(u_int *)data = sc->sc_asyncmap[0];
446 case PPPIOCSRASYNCMAP:
447 if ((error = suser_cred(cr, 0)) != 0)
449 sc->sc_rasyncmap = *(u_int *)data;
452 case PPPIOCGRASYNCMAP:
453 *(u_int *)data = sc->sc_rasyncmap;
456 case PPPIOCSXASYNCMAP:
457 if ((error = suser_cred(cr, 0)) != 0)
460 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
461 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
462 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
463 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
467 case PPPIOCGXASYNCMAP:
468 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
472 error = pppioctl(sc, cmd, data, flag, cr);
473 if (error == 0 && cmd == PPPIOCSMRU)
481 * FCS lookup table as calculated by genfcstab.
483 static u_short fcstab[256] = {
484 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
485 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
486 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
487 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
488 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
489 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
490 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
491 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
492 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
493 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
494 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
495 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
496 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
497 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
498 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
499 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
500 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
501 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
502 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
503 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
504 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
505 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
506 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
507 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
508 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
509 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
510 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
511 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
512 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
513 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
514 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
515 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
519 * Calculate a new FCS given the current FCS and the new data.
522 pppfcs(u_short fcs, u_char *cp, int len)
525 fcs = PPP_FCS(fcs, *cp++);
530 * This gets called at splsoftnet from if_ppp.c at various times
531 * when there is data ready to be sent.
534 pppasyncstart(struct ppp_softc *sc)
536 struct tty *tp = (struct tty *) sc->sc_devp;
539 u_char *start, *stop, *cp;
540 int n, ndone, done, idle;
543 /* XXX assumes atomic access to *tp although we're not at spltty(). */
544 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
546 * See if we have an existing packet partly sent.
547 * If not, get a new packet and start sending it.
552 * Get another packet to be sent.
561 * The extra PPP_FLAG will start up a new packet, and thus
562 * will flush any accumulated garbage. We do this whenever
563 * the line may have been idle for some time.
566 if (CCOUNT(&tp->t_outq) == 0) {
567 ++sc->sc_stats.ppp_obytes;
568 putc(PPP_FLAG, &tp->t_outq);
571 /* Calculate the FCS for the first mbuf's worth. */
572 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
573 getmicrotime(&sc->sc_if.if_lastchange);
577 start = mtod(m, u_char *);
582 * Find out how many bytes in the string we can
583 * handle without doing something special.
585 for (cp = start; cp < stop; cp++)
590 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
591 ndone = n - b_to_q(start, n, &tp->t_outq);
594 sc->sc_stats.ppp_obytes += ndone;
597 break; /* packet doesn't fit */
600 * If there are characters left in the mbuf,
601 * the first one must be special.
602 * Put it out in a different form.
606 if (putc(PPP_ESCAPE, &tp->t_outq)) {
610 if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
616 sc->sc_stats.ppp_obytes += 2;
623 * If we didn't empty this mbuf, remember where we're up to.
624 * If we emptied the last mbuf, try to add the FCS and closing
625 * flag, and if we can't, leave sc_outm pointing to m, but with
626 * m->m_len == 0, to remind us to output the FCS and flag later.
629 if (done && m->m_next == NULL) {
635 * We may have to escape the bytes in the FCS.
638 c = ~sc->sc_outfcs & 0xFF;
641 *p++ = c ^ PPP_TRANS;
644 c = (~sc->sc_outfcs >> 8) & 0xFF;
647 *p++ = c ^ PPP_TRANS;
653 * Try to output the FCS and flag. If the bytes
654 * don't all fit, back out.
657 for (q = endseq; q < p; ++q)
658 if (putc(*q, &tp->t_outq)) {
660 for (; q > endseq; --q)
666 sc->sc_stats.ppp_obytes += q - endseq;
670 /* remember where we got to */
676 /* Finished with this mbuf; free it and move on. */
679 /* Finished a packet */
682 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
686 * If m == NULL, we have finished a packet.
687 * If m != NULL, we've either done as much work this time
688 * as we need to, or else we've filled up the output queue.
695 /* Call pppstart to start output again if necessary. */
700 * This timeout is needed for operation on a pseudo-tty,
701 * because the pty code doesn't call pppstart after it has
702 * drained the t_outq.
704 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
705 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
706 sc->sc_flags |= SC_TIMEOUT;
713 * This gets called when a received packet is placed on
714 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
717 pppasyncctlp(struct ppp_softc *sc)
721 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
723 tp = (struct tty *) sc->sc_devp;
724 putc(0, &tp->t_canq);
730 * Start output on async tty interface. If the transmit queue
731 * has drained sufficiently, arrange for pppasyncstart to be
732 * called later at splsoftnet.
733 * Called at spltty or higher.
736 pppstart(struct tty *tp)
738 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
741 * Call output process whether or not there is any output.
742 * We are being called in lieu of ttstart and must do what it would.
744 if (tp->t_oproc != NULL)
748 * If ALTQ is enabled, don't invoke NETISR_PPP.
749 * pppintr() could loop without doing anything useful
750 * under rate-limiting.
752 if (ifq_is_enabled(&sc->sc_if.if_snd))
756 * If the transmit queue has drained and the tty has not hung up
757 * or been disconnected from the ppp unit, then tell if_ppp.c that
758 * we need more output.
760 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
761 && !((tp->t_state & TS_CONNECTED) == 0)
762 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
770 * Timeout routine - try to start some more output.
775 struct ppp_softc *sc = (struct ppp_softc *) x;
776 struct tty *tp = (struct tty *) sc->sc_devp;
779 sc->sc_flags &= ~SC_TIMEOUT;
785 * Allocate enough mbuf to handle current MRU.
788 pppgetm(struct ppp_softc *sc)
790 struct mbuf *m, **mp;
794 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
795 if ((m = *mp) == NULL) {
796 MGETHDR(m, MB_DONTWAIT, MT_DATA);
800 MCLGET(m, MB_DONTWAIT);
802 len -= M_DATASIZE(m);
808 * tty interface receiver interrupt.
810 static unsigned paritytab[8] = {
811 0x96696996, 0x69969669, 0x69969669, 0x96696996,
812 0x69969669, 0x96696996, 0x96696996, 0x69969669
816 * Called when character is available from device driver.
817 * Only guaranteed to be at splsofttty() or spltty()
818 * This is safe to be called while the upper half's netisr is preempted.
821 pppinput(int c, struct tty *tp)
823 struct ppp_softc *sc;
827 sc = (struct ppp_softc *) tp->t_sc;
828 if (sc == NULL || tp != (struct tty *) sc->sc_devp)
832 ++sc->sc_stats.ppp_ibytes;
834 if ((tp->t_state & TS_CONNECTED) == 0) {
835 if (sc->sc_flags & SC_DEBUG)
836 printf("%s: no carrier\n", sc->sc_if.if_xname);
840 if (c & TTY_ERRORMASK) {
841 /* framing error or overrun on this char - abort packet */
842 if (sc->sc_flags & SC_DEBUG)
843 printf("%s: line error %x\n", sc->sc_if.if_xname,
851 * Handle software flow control of output.
853 if (tp->t_iflag & IXON) {
854 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
855 if ((tp->t_state & TS_TTSTOP) == 0) {
856 tp->t_state |= TS_TTSTOP;
861 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
862 tp->t_state &= ~TS_TTSTOP;
863 if (tp->t_oproc != NULL)
871 sc->sc_flags |= SC_RCV_B7_1;
873 sc->sc_flags |= SC_RCV_B7_0;
874 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
875 sc->sc_flags |= SC_RCV_ODDP;
877 sc->sc_flags |= SC_RCV_EVNP;
880 if (sc->sc_flags & SC_LOG_RAWIN)
887 if (sc->sc_rawin_count > 0)
891 * If SC_ESCAPED is set, then we've seen the packet
892 * abort sequence "}~".
894 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
895 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
897 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
898 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
899 if (sc->sc_flags & SC_DEBUG)
900 printf("%s: bad fcs %x, pkt len %d\n",
901 sc->sc_if.if_xname, sc->sc_fcs, ilen);
902 sc->sc_if.if_ierrors++;
903 sc->sc_stats.ppp_ierrors++;
905 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
910 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
912 if (sc->sc_flags & SC_DEBUG)
913 printf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
915 sc->sc_if.if_ierrors++;
916 sc->sc_stats.ppp_ierrors++;
917 sc->sc_flags |= SC_PKTLOST;
924 * Remove FCS trailer. Somewhat painful...
927 if (--sc->sc_mc->m_len == 0) {
928 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
934 /* excise this mbuf chain */
936 sc->sc_m = sc->sc_mc->m_next;
937 sc->sc_mc->m_next = NULL;
939 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
940 if (sc->sc_flags & SC_PKTLOST) {
942 sc->sc_flags &= ~SC_PKTLOST;
950 if (sc->sc_flags & SC_FLUSH) {
951 if (sc->sc_flags & SC_LOG_FLUSH)
956 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
960 if (sc->sc_flags & SC_ESCAPED) {
961 sc->sc_flags &= ~SC_ESCAPED;
963 } else if (c == PPP_ESCAPE) {
964 sc->sc_flags |= SC_ESCAPED;
971 * Initialize buffer on first octet received.
972 * First octet could be address or protocol (when compressing
974 * Second octet is control.
975 * Third octet is first or second (when compressing protocol)
977 * Fourth octet is second octet of protocol.
979 if (sc->sc_ilen == 0) {
980 /* reset the first input mbuf */
981 if (sc->sc_m == NULL) {
983 if (sc->sc_m == NULL) {
984 if (sc->sc_flags & SC_DEBUG)
985 printf("%s: no input mbufs!\n", sc->sc_if.if_xname);
991 m->m_data = M_DATASTART(sc->sc_m);
993 sc->sc_mp = mtod(m, char *);
994 sc->sc_fcs = PPP_INITFCS;
995 if (c != PPP_ALLSTATIONS) {
996 if (sc->sc_flags & SC_REJ_COMP_AC) {
997 if (sc->sc_flags & SC_DEBUG)
998 printf("%s: garbage received: 0x%x (need 0xFF)\n",
999 sc->sc_if.if_xname, c);
1002 *sc->sc_mp++ = PPP_ALLSTATIONS;
1003 *sc->sc_mp++ = PPP_UI;
1008 if (sc->sc_ilen == 1 && c != PPP_UI) {
1009 if (sc->sc_flags & SC_DEBUG)
1010 printf("%s: missing UI (0x3), got 0x%x\n",
1011 sc->sc_if.if_xname, c);
1014 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1015 /* a compressed protocol */
1020 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1021 if (sc->sc_flags & SC_DEBUG)
1022 printf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1023 (sc->sc_mp[-1] << 8) + c);
1027 /* packet beyond configured mru? */
1028 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1029 if (sc->sc_flags & SC_DEBUG)
1030 printf("%s: packet too big\n", sc->sc_if.if_xname);
1034 /* is this mbuf full? */
1036 if (M_TRAILINGSPACE(m) <= 0) {
1037 if (m->m_next == NULL) {
1039 if (m->m_next == NULL) {
1040 if (sc->sc_flags & SC_DEBUG)
1041 printf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1045 sc->sc_mc = m = m->m_next;
1047 m->m_data = M_DATASTART(m);
1048 sc->sc_mp = mtod(m, char *);
1053 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1057 if (!(sc->sc_flags & SC_FLUSH)) {
1059 sc->sc_if.if_ierrors++;
1060 sc->sc_stats.ppp_ierrors++;
1061 sc->sc_flags |= SC_FLUSH;
1063 if (sc->sc_flags & SC_LOG_FLUSH)
1069 #define MAX_DUMP_BYTES 128
1072 ppplogchar(struct ppp_softc *sc, int c)
1075 sc->sc_rawin[sc->sc_rawin_count++] = c;
1076 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1077 || (c < 0 && sc->sc_rawin_count > 0)) {
1078 printf("%s input: %*D", sc->sc_if.if_xname,
1079 sc->sc_rawin_count, sc->sc_rawin, " ");
1080 sc->sc_rawin_count = 0;