4 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
7 * Copyright (c) 1989 Carnegie Mellon University.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by Carnegie Mellon University. The name of the
16 * University may not be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * Carnegie Mellon University
25 * Pittsburgh, PA 15213
30 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
32 * Copyright (c) 1987 Regents of the University of California.
33 * All rights reserved.
35 * Redistribution and use in source and binary forms are permitted
36 * provided that the above copyright notice and this paragraph are
37 * duplicated in all such forms and that any documentation,
38 * advertising materials, and other materials related to such
39 * distribution and use acknowledge that the software was developed
40 * by the University of California, Berkeley. The name of the
41 * University may not be used to endorse or promote products derived
42 * from this software without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
44 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
45 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
47 * Serial Line interface
50 * Center for Seismic Studies
51 * 1300 N 17th Street, Suite 1450
52 * Arlington, Virginia 22209
57 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
58 * Converted to 4.3BSD Beta by Chris Torek.
59 * Other changes made at Berkeley, based in part on code by Kirk Smith.
61 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
62 * Added VJ tcp header compression; more unified ioctls
64 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
65 * Cleaned up a lot of the mbuf-related code to fix bugs that
66 * caused system crashes and packet corruption. Changed pppstart
67 * so that it doesn't just give up with a "collision" if the whole
68 * packet doesn't fit in the output ring buffer.
70 * Added priority queueing for interactive IP packets, following
71 * the model of if_sl.c, plus hooks for bpf.
72 * Paul Mackerras (paulus@cs.anu.edu.au).
75 /* $FreeBSD: src/sys/net/ppp_tty.c,v 1.43.2.1 2002/02/13 00:43:11 dillon Exp $ */
76 /* $DragonFly: src/sys/net/ppp_layer/ppp_tty.c,v 1.25 2008/05/14 11:59:23 sephe Exp $ */
78 #include "opt_ppp.h" /* XXX for ppp_defs.h */
80 #define VJC /* XXX for ppp_defs.h */
82 #include <sys/param.h>
83 #include <sys/systm.h>
87 #include <sys/dkstat.h>
88 #include <sys/socket.h>
89 #include <sys/fcntl.h>
90 #include <sys/thread2.h>
94 #include <sys/vnode.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 (cdev_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 ucred *);
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(void *dummy)
166 /* register line discipline */
167 linesw[PPPDISC] = pppdisc;
171 * Line specific open routine for async tty devices.
172 * Attach the given tty to the first available ppp unit.
173 * Called from device open routine or ttioctl() at >= splsofttty()
177 pppopen(cdev_t dev, struct tty *tp)
179 struct thread *td = curthread; /* XXX */
180 struct ppp_softc *sc;
183 if ((error = priv_check(td, PRIV_ROOT)) != 0)
187 lwkt_gettoken(&tty_token);
189 if (tp->t_line == PPPDISC) {
190 sc = (struct ppp_softc *) tp->t_sc;
191 if (sc != NULL && sc->sc_devp == (void *) tp) {
192 lwkt_reltoken(&tty_token);
198 if ((sc = pppalloc(td)) == NULL) {
199 lwkt_reltoken(&tty_token);
205 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
209 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
210 sc->sc_asyncmap[0] = 0xffffffff;
211 sc->sc_asyncmap[3] = 0x60000000;
212 sc->sc_rasyncmap = 0;
213 sc->sc_devp = (void *) tp;
214 sc->sc_start = pppasyncstart;
215 sc->sc_ctlp = pppasyncctlp;
216 sc->sc_relinq = pppasyncrelinq;
217 sc->sc_setmtu = pppasyncsetmtu;
220 sc->sc_if.if_flags |= IFF_RUNNING;
221 getmicrotime(&sc->sc_if.if_lastchange);
222 sc->sc_if.if_baudrate = tp->t_ospeed;
224 tp->t_sc = (caddr_t) sc;
225 ttyflush(tp, FREAD | FWRITE);
228 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
229 * allocation helps avoid the need for select and/or FIONREAD.
230 * We also pass 1 byte tokens through t_canq...
232 clist_alloc_cblocks(&tp->t_canq, 1, 1);
233 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
234 sc->sc_if.if_mtu + PPP_HIWAT);
235 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
237 lwkt_reltoken(&tty_token);
244 * Line specific close routine, called from device close routine
245 * and from ttioctl at >= splsofttty().
246 * Detach the tty from the ppp unit.
247 * Mimics part of ttyclose().
250 pppclose(struct tty *tp, int flag)
252 struct ppp_softc *sc;
255 lwkt_gettoken(&tty_token);
256 ttyflush(tp, FREAD | FWRITE);
257 clist_free_cblocks(&tp->t_canq);
258 clist_free_cblocks(&tp->t_outq);
260 sc = (struct ppp_softc *) tp->t_sc;
263 if (tp == (struct tty *) sc->sc_devp) {
268 lwkt_reltoken(&tty_token);
274 * Relinquish the interface unit to another device.
277 pppasyncrelinq(struct ppp_softc *sc)
280 lwkt_gettoken(&tty_token);
283 m_freem(sc->sc_outm);
290 if (sc->sc_flags & SC_TIMEOUT) {
291 callout_stop(&sc->sc_timeout);
292 sc->sc_flags &= ~SC_TIMEOUT;
295 lwkt_reltoken(&tty_token);
300 * This gets called from the upper layer to notify a mtu change
303 pppasyncsetmtu(struct ppp_softc *sc)
305 struct tty *tp = (struct tty *) sc->sc_devp;
308 lwkt_gettoken(&tty_token);
310 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
311 sc->sc_if.if_mtu + PPP_HIWAT);
312 lwkt_reltoken(&tty_token);
317 * Line specific (tty) read routine.
318 * called at zero spl from the device driver in the response to user-level
319 * reads on the tty file descriptor (ie: pppd).
322 pppread(struct tty *tp, struct uio *uio, int flag)
324 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
331 * Loop waiting for input, checking that nothing disasterous
332 * happens in the meantime.
335 lwkt_gettoken(&tty_token);
337 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
338 lwkt_reltoken(&tty_token);
342 if (sc->sc_inq.ifq_head != NULL)
344 if ((tp->t_state & TS_CONNECTED) == 0) {
345 lwkt_reltoken(&tty_token);
347 return 0; /* end of file */
349 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
350 lwkt_reltoken(&tty_token);
352 return (EWOULDBLOCK);
354 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
356 lwkt_reltoken(&tty_token);
362 /* Pull place-holder byte out of canonical queue */
363 clist_getc(&tp->t_canq);
365 /* Get the packet from the input queue */
366 IF_DEQUEUE(&sc->sc_inq, m0);
367 lwkt_reltoken(&tty_token);
370 for (m = m0; m && uio->uio_resid; m = m->m_next)
371 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
378 * Line specific (tty) write routine.
379 * called at zero spl from the device driver in the response to user-level
380 * writes on the tty file descriptor (ie: pppd).
383 pppwrite(struct tty *tp, struct uio *uio, int flag)
385 struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
386 struct mbuf *m, *m0, **mp;
390 lwkt_gettoken(&tty_token);
391 if ((tp->t_state & TS_CONNECTED) == 0) {
392 lwkt_reltoken(&tty_token);
393 return 0; /* wrote 0 bytes */
395 if (tp->t_line != PPPDISC) {
396 lwkt_reltoken(&tty_token);
399 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
400 lwkt_reltoken(&tty_token);
403 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
404 uio->uio_resid < PPP_HDRLEN) {
405 lwkt_reltoken(&tty_token);
410 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
412 MGETHDR(m, MB_WAIT, MT_DATA);
413 m->m_pkthdr.len = uio->uio_resid - PPP_HDRLEN;
414 m->m_pkthdr.rcvif = NULL;
416 MGET(m, MB_WAIT, MT_DATA);
418 if ((*mp = m) == NULL) {
421 lwkt_reltoken(&tty_token);
425 if (uio->uio_resid >= MCLBYTES / 2)
426 MCLGET(m, MB_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) {
433 lwkt_reltoken(&tty_token);
438 dst.sa_family = AF_UNSPEC;
439 bcopy(mtod(m0, u_char *), dst.sa_data, PPP_HDRLEN);
440 m0->m_data += PPP_HDRLEN;
441 m0->m_len -= PPP_HDRLEN;
443 /* call the upper layer to "transmit" it... */
444 error = pppoutput(&sc->sc_if, m0, &dst, NULL);
446 lwkt_reltoken(&tty_token);
451 * Line specific (tty) ioctl routine.
452 * This discipline requires that tty device drivers call
453 * the line specific l_ioctl routine from their ioctl routines.
457 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cr)
459 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
462 lwkt_gettoken(&tty_token);
463 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
464 lwkt_reltoken(&tty_token);
470 case PPPIOCSASYNCMAP:
471 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
473 sc->sc_asyncmap[0] = *(u_int *)data;
476 case PPPIOCGASYNCMAP:
477 *(u_int *)data = sc->sc_asyncmap[0];
480 case PPPIOCSRASYNCMAP:
481 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
483 sc->sc_rasyncmap = *(u_int *)data;
486 case PPPIOCGRASYNCMAP:
487 *(u_int *)data = sc->sc_rasyncmap;
490 case PPPIOCSXASYNCMAP:
491 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
494 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
495 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
496 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
497 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
501 case PPPIOCGXASYNCMAP:
502 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
506 error = pppioctl(sc, cmd, data, flag, cr);
507 if (error == 0 && cmd == PPPIOCSMRU)
511 lwkt_reltoken(&tty_token);
516 * FCS lookup table as calculated by genfcstab.
518 static u_short fcstab[256] = {
519 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
520 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
521 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
522 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
523 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
524 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
525 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
526 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
527 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
528 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
529 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
530 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
531 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
532 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
533 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
534 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
535 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
536 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
537 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
538 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
539 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
540 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
541 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
542 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
543 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
544 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
545 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
546 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
547 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
548 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
549 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
550 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
554 * Calculate a new FCS given the current FCS and the new data.
557 pppfcs(u_short fcs, u_char *cp, int len)
560 fcs = PPP_FCS(fcs, *cp++);
565 * This gets called at splsoftnet from if_ppp.c at various times
566 * when there is data ready to be sent.
569 pppasyncstart(struct ppp_softc *sc)
571 struct tty *tp = (struct tty *) sc->sc_devp;
574 u_char *start, *stop, *cp;
575 int n, ndone, done, idle;
578 lwkt_gettoken(&tty_token);
579 /* XXX assumes atomic access to *tp although we're not at spltty(). */
580 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
582 * See if we have an existing packet partly sent.
583 * If not, get a new packet and start sending it.
588 * Get another packet to be sent.
597 * The extra PPP_FLAG will start up a new packet, and thus
598 * will flush any accumulated garbage. We do this whenever
599 * the line may have been idle for some time.
602 if (CCOUNT(&tp->t_outq) == 0) {
603 ++sc->sc_stats.ppp_obytes;
604 clist_putc(PPP_FLAG, &tp->t_outq);
607 /* Calculate the FCS for the first mbuf's worth. */
608 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
609 getmicrotime(&sc->sc_if.if_lastchange);
613 start = mtod(m, u_char *);
618 * Find out how many bytes in the string we can
619 * handle without doing something special.
621 for (cp = start; cp < stop; cp++)
626 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
627 ndone = n - b_to_q(start, n, &tp->t_outq);
630 sc->sc_stats.ppp_obytes += ndone;
633 break; /* packet doesn't fit */
636 * If there are characters left in the mbuf,
637 * the first one must be special.
638 * Put it out in a different form.
642 if (clist_putc(PPP_ESCAPE, &tp->t_outq)) {
646 if (clist_putc(*start ^ PPP_TRANS, &tp->t_outq)) {
647 clist_unputc(&tp->t_outq);
652 sc->sc_stats.ppp_obytes += 2;
659 * If we didn't empty this mbuf, remember where we're up to.
660 * If we emptied the last mbuf, try to add the FCS and closing
661 * flag, and if we can't, leave sc_outm pointing to m, but with
662 * m->m_len == 0, to remind us to output the FCS and flag later.
665 if (done && m->m_next == NULL) {
671 * We may have to escape the bytes in the FCS.
674 c = ~sc->sc_outfcs & 0xFF;
677 *p++ = c ^ PPP_TRANS;
680 c = (~sc->sc_outfcs >> 8) & 0xFF;
683 *p++ = c ^ PPP_TRANS;
689 * Try to output the FCS and flag. If the bytes
690 * don't all fit, back out.
693 for (q = endseq; q < p; ++q)
694 if (clist_putc(*q, &tp->t_outq)) {
696 for (; q > endseq; --q)
697 clist_unputc(&tp->t_outq);
702 sc->sc_stats.ppp_obytes += q - endseq;
706 /* remember where we got to */
712 /* Finished with this mbuf; free it and move on. */
715 /* Finished a packet */
718 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
722 * If m == NULL, we have finished a packet.
723 * If m != NULL, we've either done as much work this time
724 * as we need to, or else we've filled up the output queue.
731 /* Call pppstart to start output again if necessary. */
736 * This timeout is needed for operation on a pseudo-tty,
737 * because the pty code doesn't call pppstart after it has
738 * drained the t_outq.
740 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
741 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
742 sc->sc_flags |= SC_TIMEOUT;
746 lwkt_reltoken(&tty_token);
750 * This gets called when a received packet is placed on
751 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
754 pppasyncctlp(struct ppp_softc *sc)
758 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
760 lwkt_gettoken(&tty_token);
761 tp = (struct tty *) sc->sc_devp;
762 clist_putc(0, &tp->t_canq);
764 lwkt_reltoken(&tty_token);
769 * Start output on async tty interface. If the transmit queue
770 * has drained sufficiently, arrange for pppasyncstart to be
771 * called later at splsoftnet.
772 * Called at spltty or higher.
775 pppstart(struct tty *tp)
777 struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
779 lwkt_gettoken(&tty_token);
781 * Call output process whether or not there is any output.
782 * We are being called in lieu of ttstart and must do what it would.
784 if (tp->t_oproc != NULL)
788 * If ALTQ is enabled, don't invoke NETISR_PPP.
789 * pppintr() could loop without doing anything useful
790 * under rate-limiting.
792 if (ifq_is_enabled(&sc->sc_if.if_snd)) {
793 lwkt_reltoken(&tty_token);
798 * If the transmit queue has drained and the tty has not hung up
799 * or been disconnected from the ppp unit, then tell if_ppp.c that
800 * we need more output.
802 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
803 && !((tp->t_state & TS_CONNECTED) == 0)
804 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
808 lwkt_reltoken(&tty_token);
813 * Timeout routine - try to start some more output.
818 struct ppp_softc *sc = (struct ppp_softc *) x;
819 struct tty *tp = (struct tty *) sc->sc_devp;
822 lwkt_gettoken(&tty_token);
823 sc->sc_flags &= ~SC_TIMEOUT;
825 lwkt_reltoken(&tty_token);
830 * Allocate enough mbuf to handle current MRU.
833 pppgetm(struct ppp_softc *sc)
835 struct mbuf *m, **mp;
839 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
840 if ((m = *mp) == NULL) {
841 MGETHDR(m, MB_DONTWAIT, MT_DATA);
845 MCLGET(m, MB_DONTWAIT);
847 len -= M_DATASIZE(m);
853 * tty interface receiver interrupt.
855 static unsigned paritytab[8] = {
856 0x96696996, 0x69969669, 0x69969669, 0x96696996,
857 0x69969669, 0x96696996, 0x96696996, 0x69969669
861 * Called when character is available from device driver.
862 * Only guaranteed to be at splsofttty() or spltty()
863 * This is safe to be called while the upper half's netisr is preempted.
866 pppinput(int c, struct tty *tp)
868 struct ppp_softc *sc;
872 lwkt_gettoken(&tty_token);
873 sc = (struct ppp_softc *) tp->t_sc;
874 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
875 lwkt_reltoken(&tty_token);
880 ++sc->sc_stats.ppp_ibytes;
882 if ((tp->t_state & TS_CONNECTED) == 0) {
883 if (sc->sc_flags & SC_DEBUG)
884 kprintf("%s: no carrier\n", sc->sc_if.if_xname);
888 if (c & TTY_ERRORMASK) {
889 /* framing error or overrun on this char - abort packet */
890 if (sc->sc_flags & SC_DEBUG)
891 kprintf("%s: line error %x\n", sc->sc_if.if_xname,
899 * Handle software flow control of output.
901 if (tp->t_iflag & IXON) {
902 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
903 if ((tp->t_state & TS_TTSTOP) == 0) {
904 tp->t_state |= TS_TTSTOP;
907 lwkt_reltoken(&tty_token);
910 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
911 tp->t_state &= ~TS_TTSTOP;
912 if (tp->t_oproc != NULL)
914 lwkt_reltoken(&tty_token);
921 sc->sc_flags |= SC_RCV_B7_1;
923 sc->sc_flags |= SC_RCV_B7_0;
924 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
925 sc->sc_flags |= SC_RCV_ODDP;
927 sc->sc_flags |= SC_RCV_EVNP;
930 if (sc->sc_flags & SC_LOG_RAWIN)
937 if (sc->sc_rawin_count > 0)
941 * If SC_ESCAPED is set, then we've seen the packet
942 * abort sequence "}~".
944 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
945 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
947 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
948 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
949 if (sc->sc_flags & SC_DEBUG)
950 kprintf("%s: bad fcs %x, pkt len %d\n",
951 sc->sc_if.if_xname, sc->sc_fcs, ilen);
952 sc->sc_if.if_ierrors++;
953 sc->sc_stats.ppp_ierrors++;
955 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
957 lwkt_reltoken(&tty_token);
961 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
963 if (sc->sc_flags & SC_DEBUG)
964 kprintf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
966 sc->sc_if.if_ierrors++;
967 sc->sc_stats.ppp_ierrors++;
968 sc->sc_flags |= SC_PKTLOST;
971 lwkt_reltoken(&tty_token);
976 * Remove FCS trailer. Somewhat painful...
979 if (--sc->sc_mc->m_len == 0) {
980 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
986 /* excise this mbuf chain */
988 sc->sc_m = sc->sc_mc->m_next;
989 sc->sc_mc->m_next = NULL;
991 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
992 if (sc->sc_flags & SC_PKTLOST) {
994 sc->sc_flags &= ~SC_PKTLOST;
999 lwkt_reltoken(&tty_token);
1003 if (sc->sc_flags & SC_FLUSH) {
1004 if (sc->sc_flags & SC_LOG_FLUSH)
1006 lwkt_reltoken(&tty_token);
1010 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
1011 lwkt_reltoken(&tty_token);
1016 if (sc->sc_flags & SC_ESCAPED) {
1017 sc->sc_flags &= ~SC_ESCAPED;
1019 } else if (c == PPP_ESCAPE) {
1020 sc->sc_flags |= SC_ESCAPED;
1022 lwkt_reltoken(&tty_token);
1028 * Initialize buffer on first octet received.
1029 * First octet could be address or protocol (when compressing
1031 * Second octet is control.
1032 * Third octet is first or second (when compressing protocol)
1033 * octet of protocol.
1034 * Fourth octet is second octet of protocol.
1036 if (sc->sc_ilen == 0) {
1037 /* reset the first input mbuf */
1038 if (sc->sc_m == NULL) {
1040 if (sc->sc_m == NULL) {
1041 if (sc->sc_flags & SC_DEBUG)
1042 kprintf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1048 m->m_data = M_DATASTART(sc->sc_m);
1050 sc->sc_mp = mtod(m, char *);
1051 sc->sc_fcs = PPP_INITFCS;
1052 if (c != PPP_ALLSTATIONS) {
1053 if (sc->sc_flags & SC_REJ_COMP_AC) {
1054 if (sc->sc_flags & SC_DEBUG)
1055 kprintf("%s: garbage received: 0x%x (need 0xFF)\n",
1056 sc->sc_if.if_xname, c);
1059 *sc->sc_mp++ = PPP_ALLSTATIONS;
1060 *sc->sc_mp++ = PPP_UI;
1065 if (sc->sc_ilen == 1 && c != PPP_UI) {
1066 if (sc->sc_flags & SC_DEBUG)
1067 kprintf("%s: missing UI (0x3), got 0x%x\n",
1068 sc->sc_if.if_xname, c);
1071 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1072 /* a compressed protocol */
1077 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1078 if (sc->sc_flags & SC_DEBUG)
1079 kprintf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1080 (sc->sc_mp[-1] << 8) + c);
1084 /* packet beyond configured mru? */
1085 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1086 if (sc->sc_flags & SC_DEBUG)
1087 kprintf("%s: packet too big\n", sc->sc_if.if_xname);
1091 /* is this mbuf full? */
1093 if (M_TRAILINGSPACE(m) <= 0) {
1094 if (m->m_next == NULL) {
1096 if (m->m_next == NULL) {
1097 if (sc->sc_flags & SC_DEBUG)
1098 kprintf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1102 sc->sc_mc = m = m->m_next;
1104 m->m_data = M_DATASTART(m);
1105 sc->sc_mp = mtod(m, char *);
1110 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1111 lwkt_reltoken(&tty_token);
1115 if (!(sc->sc_flags & SC_FLUSH)) {
1117 sc->sc_if.if_ierrors++;
1118 sc->sc_stats.ppp_ierrors++;
1119 sc->sc_flags |= SC_FLUSH;
1121 if (sc->sc_flags & SC_LOG_FLUSH)
1124 lwkt_reltoken(&tty_token);
1128 #define MAX_DUMP_BYTES 128
1131 ppplogchar(struct ppp_softc *sc, int c)
1134 sc->sc_rawin[sc->sc_rawin_count++] = c;
1135 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1136 || (c < 0 && sc->sc_rawin_count > 0)) {
1137 kprintf("%s input: %*D", sc->sc_if.if_xname,
1138 sc->sc_rawin_count, sc->sc_rawin, " ");
1139 sc->sc_rawin_count = 0;