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 $ */
77 #include "opt_ppp.h" /* XXX for ppp_defs.h */
79 #define VJC /* XXX for ppp_defs.h */
81 #include <sys/param.h>
82 #include <sys/systm.h>
86 #include <sys/dkstat.h>
87 #include <sys/socket.h>
88 #include <sys/fcntl.h>
89 #include <sys/thread2.h>
93 #include <sys/vnode.h>
96 #include <net/ifq_var.h>
101 #include <net/ppp/if_ppp.h>
102 #include <net/ppp/if_pppvar.h>
104 static int pppopen (cdev_t dev, struct tty *tp);
105 static int pppclose (struct tty *tp, int flag);
106 static int pppread (struct tty *tp, struct uio *uio, int flag);
107 static int pppwrite (struct tty *tp, struct uio *uio, int flag);
108 static int ppptioctl (struct tty *tp, u_long cmd, caddr_t data,
109 int flag, struct ucred *);
110 static int pppinput (int c, struct tty *tp);
111 static int pppstart (struct tty *tp);
113 static u_short pppfcs (u_short fcs, u_char *cp, int len);
114 static void pppasyncstart (struct ppp_softc *);
115 static void pppasyncctlp (struct ppp_softc *);
116 static void pppasyncrelinq (struct ppp_softc *);
117 static void pppasyncsetmtu (struct ppp_softc *);
118 static void ppp_timeout (void *);
119 static void pppgetm (struct ppp_softc *sc);
120 static void ppplogchar (struct ppp_softc *, int);
122 /* XXX called from if_ppp.c - layering violation */
123 void pppasyncattach (void *);
126 * Some useful mbuf macros not in mbuf.h.
128 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
130 #define M_DATASTART(m) \
131 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
132 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
134 #define M_DATASIZE(m) \
135 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
136 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
139 * Does c need to be escaped?
141 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
144 * Procedures for using an async tty interface for PPP.
147 /* This is a FreeBSD-2.X kernel. */
148 #define CCOUNT(q) ((q)->c_cc)
149 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
150 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
153 * Define the PPP line discipline.
156 static struct linesw pppdisc = {
157 pppopen, pppclose, pppread, pppwrite,
158 ppptioctl, pppinput, pppstart, ttymodem,
163 pppasyncattach(void *dummy)
165 /* register line discipline */
166 linesw[PPPDISC] = pppdisc;
170 * Line specific open routine for async tty devices.
171 * Attach the given tty to the first available ppp unit.
172 * Called from device open routine or ttioctl() at >= splsofttty()
176 pppopen(cdev_t dev, struct tty *tp)
178 struct thread *td = curthread; /* XXX */
179 struct ppp_softc *sc;
182 if ((error = priv_check(td, PRIV_ROOT)) != 0)
186 lwkt_gettoken(&tty_token);
188 if (tp->t_line == PPPDISC) {
189 sc = (struct ppp_softc *) tp->t_slsc;
190 if (sc != NULL && sc->sc_devp == (void *) tp) {
191 lwkt_reltoken(&tty_token);
197 if ((sc = pppalloc(td)) == NULL) {
198 lwkt_reltoken(&tty_token);
204 (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
208 bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
209 sc->sc_asyncmap[0] = 0xffffffff;
210 sc->sc_asyncmap[3] = 0x60000000;
211 sc->sc_rasyncmap = 0;
212 sc->sc_devp = (void *) tp;
213 sc->sc_start = pppasyncstart;
214 sc->sc_ctlp = pppasyncctlp;
215 sc->sc_relinq = pppasyncrelinq;
216 sc->sc_setmtu = pppasyncsetmtu;
219 sc->sc_if.if_flags |= IFF_RUNNING;
220 getmicrotime(&sc->sc_if.if_lastchange);
221 sc->sc_if.if_baudrate = tp->t_ospeed;
223 tp->t_slsc = (caddr_t) sc;
224 ttyflush(tp, FREAD | FWRITE);
227 * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
228 * allocation helps avoid the need for select and/or FIONREAD.
229 * We also pass 1 byte tokens through t_canq...
231 clist_alloc_cblocks(&tp->t_canq, 1, 1);
232 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
233 sc->sc_if.if_mtu + PPP_HIWAT);
234 clist_alloc_cblocks(&tp->t_rawq, 0, 0);
236 lwkt_reltoken(&tty_token);
243 * Line specific close routine, called from device close routine
244 * and from ttioctl at >= splsofttty().
245 * Detach the tty from the ppp unit.
246 * Mimics part of ttyclose().
249 pppclose(struct tty *tp, int flag)
251 struct ppp_softc *sc;
254 lwkt_gettoken(&tty_token);
255 ttyflush(tp, FREAD | FWRITE);
256 clist_free_cblocks(&tp->t_canq);
257 clist_free_cblocks(&tp->t_outq);
259 sc = (struct ppp_softc *) tp->t_slsc;
262 if (tp == (struct tty *) sc->sc_devp) {
267 lwkt_reltoken(&tty_token);
273 * Relinquish the interface unit to another device.
276 pppasyncrelinq(struct ppp_softc *sc)
279 lwkt_gettoken(&tty_token);
282 m_freem(sc->sc_outm);
289 if (sc->sc_flags & SC_TIMEOUT) {
290 callout_stop(&sc->sc_timeout);
291 sc->sc_flags &= ~SC_TIMEOUT;
294 lwkt_reltoken(&tty_token);
299 * This gets called from the upper layer to notify a mtu change
302 pppasyncsetmtu(struct ppp_softc *sc)
304 struct tty *tp = (struct tty *) sc->sc_devp;
307 lwkt_gettoken(&tty_token);
309 clist_alloc_cblocks(&tp->t_outq, sc->sc_if.if_mtu + PPP_HIWAT,
310 sc->sc_if.if_mtu + PPP_HIWAT);
311 lwkt_reltoken(&tty_token);
316 * Line specific (tty) read routine.
317 * called at zero spl from the device driver in the response to user-level
318 * reads on the tty file descriptor (ie: pppd).
321 pppread(struct tty *tp, struct uio *uio, int flag)
323 struct ppp_softc *sc = (struct ppp_softc *)tp->t_slsc;
330 * Loop waiting for input, checking that nothing disasterous
331 * happens in the meantime.
334 lwkt_gettoken(&tty_token);
336 if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
337 lwkt_reltoken(&tty_token);
341 if (sc->sc_inq.ifq_head != NULL)
343 if ((tp->t_state & TS_CONNECTED) == 0) {
344 lwkt_reltoken(&tty_token);
346 return 0; /* end of file */
348 if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
349 lwkt_reltoken(&tty_token);
351 return (EWOULDBLOCK);
353 error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), PCATCH, "pppin", 0);
355 lwkt_reltoken(&tty_token);
361 /* Pull place-holder byte out of canonical queue */
362 clist_getc(&tp->t_canq);
364 /* Get the packet from the input queue */
365 IF_DEQUEUE(&sc->sc_inq, m0);
366 lwkt_reltoken(&tty_token);
369 for (m = m0; m && uio->uio_resid; m = m->m_next)
370 if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
377 * Line specific (tty) write routine.
378 * called at zero spl from the device driver in the response to user-level
379 * writes on the tty file descriptor (ie: pppd).
382 pppwrite(struct tty *tp, struct uio *uio, int flag)
384 struct ppp_softc *sc = (struct ppp_softc *)tp->t_slsc;
385 struct mbuf *m, *m0, **mp;
389 lwkt_gettoken(&tty_token);
390 if ((tp->t_state & TS_CONNECTED) == 0) {
391 lwkt_reltoken(&tty_token);
392 return 0; /* wrote 0 bytes */
394 if (tp->t_line != PPPDISC) {
395 lwkt_reltoken(&tty_token);
398 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
399 lwkt_reltoken(&tty_token);
402 if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
403 uio->uio_resid < PPP_HDRLEN) {
404 lwkt_reltoken(&tty_token);
409 for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
411 MGETHDR(m, M_WAITOK, MT_DATA);
412 m->m_pkthdr.len = uio->uio_resid - PPP_HDRLEN;
413 m->m_pkthdr.rcvif = NULL;
415 MGET(m, M_WAITOK, MT_DATA);
417 if ((*mp = m) == NULL) {
420 lwkt_reltoken(&tty_token);
424 if (uio->uio_resid >= MCLBYTES / 2)
426 len = M_TRAILINGSPACE(m);
427 if (len > uio->uio_resid)
428 len = uio->uio_resid;
429 if ((error = uiomove(mtod(m, u_char *), len, uio)) != 0) {
432 lwkt_reltoken(&tty_token);
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, NULL);
445 lwkt_reltoken(&tty_token);
450 * Line specific (tty) ioctl routine.
451 * This discipline requires that tty device drivers call
452 * the line specific l_ioctl routine from their ioctl routines.
456 ppptioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct ucred *cr)
458 struct ppp_softc *sc = (struct ppp_softc *) tp->t_slsc;
461 lwkt_gettoken(&tty_token);
462 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
463 lwkt_reltoken(&tty_token);
469 case PPPIOCSASYNCMAP:
470 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
472 sc->sc_asyncmap[0] = *(u_int *)data;
475 case PPPIOCGASYNCMAP:
476 *(u_int *)data = sc->sc_asyncmap[0];
479 case PPPIOCSRASYNCMAP:
480 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
482 sc->sc_rasyncmap = *(u_int *)data;
485 case PPPIOCGRASYNCMAP:
486 *(u_int *)data = sc->sc_rasyncmap;
489 case PPPIOCSXASYNCMAP:
490 if ((error = priv_check_cred(cr, PRIV_ROOT, 0)) != 0)
493 bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
494 sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
495 sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
496 sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
500 case PPPIOCGXASYNCMAP:
501 bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
505 error = pppioctl(sc, cmd, data, flag, cr);
506 if (error == 0 && cmd == PPPIOCSMRU)
510 lwkt_reltoken(&tty_token);
515 * FCS lookup table as calculated by genfcstab.
517 static u_short fcstab[256] = {
518 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
519 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
520 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
521 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
522 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
523 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
524 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
525 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
526 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
527 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
528 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
529 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
530 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
531 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
532 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
533 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
534 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
535 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
536 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
537 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
538 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
539 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
540 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
541 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
542 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
543 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
544 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
545 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
546 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
547 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
548 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
549 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
553 * Calculate a new FCS given the current FCS and the new data.
556 pppfcs(u_short fcs, u_char *cp, int len)
559 fcs = PPP_FCS(fcs, *cp++);
564 * This gets called at splsoftnet from if_ppp.c at various times
565 * when there is data ready to be sent.
568 pppasyncstart(struct ppp_softc *sc)
570 struct tty *tp = (struct tty *) sc->sc_devp;
573 u_char *start, *stop, *cp;
574 int n, ndone, done, idle;
577 lwkt_gettoken(&tty_token);
578 /* XXX assumes atomic access to *tp although we're not at spltty(). */
579 while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
581 * See if we have an existing packet partly sent.
582 * If not, get a new packet and start sending it.
587 * Get another packet to be sent.
596 * The extra PPP_FLAG will start up a new packet, and thus
597 * will flush any accumulated garbage. We do this whenever
598 * the line may have been idle for some time.
601 if (CCOUNT(&tp->t_outq) == 0) {
602 ++sc->sc_stats.ppp_obytes;
603 clist_putc(PPP_FLAG, &tp->t_outq);
606 /* Calculate the FCS for the first mbuf's worth. */
607 sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
608 getmicrotime(&sc->sc_if.if_lastchange);
612 start = mtod(m, u_char *);
617 * Find out how many bytes in the string we can
618 * handle without doing something special.
620 for (cp = start; cp < stop; cp++)
625 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
626 ndone = n - b_to_q(start, n, &tp->t_outq);
629 sc->sc_stats.ppp_obytes += ndone;
632 break; /* packet doesn't fit */
635 * If there are characters left in the mbuf,
636 * the first one must be special.
637 * Put it out in a different form.
641 if (clist_putc(PPP_ESCAPE, &tp->t_outq)) {
645 if (clist_putc(*start ^ PPP_TRANS, &tp->t_outq)) {
646 clist_unputc(&tp->t_outq);
651 sc->sc_stats.ppp_obytes += 2;
658 * If we didn't empty this mbuf, remember where we're up to.
659 * If we emptied the last mbuf, try to add the FCS and closing
660 * flag, and if we can't, leave sc_outm pointing to m, but with
661 * m->m_len == 0, to remind us to output the FCS and flag later.
664 if (done && m->m_next == NULL) {
670 * We may have to escape the bytes in the FCS.
673 c = ~sc->sc_outfcs & 0xFF;
676 *p++ = c ^ PPP_TRANS;
679 c = (~sc->sc_outfcs >> 8) & 0xFF;
682 *p++ = c ^ PPP_TRANS;
688 * Try to output the FCS and flag. If the bytes
689 * don't all fit, back out.
692 for (q = endseq; q < p; ++q)
693 if (clist_putc(*q, &tp->t_outq)) {
695 for (; q > endseq; --q)
696 clist_unputc(&tp->t_outq);
701 sc->sc_stats.ppp_obytes += q - endseq;
705 /* remember where we got to */
711 /* Finished with this mbuf; free it and move on. */
714 /* Finished a packet */
717 sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
721 * If m == NULL, we have finished a packet.
722 * If m != NULL, we've either done as much work this time
723 * as we need to, or else we've filled up the output queue.
730 /* Call pppstart to start output again if necessary. */
735 * This timeout is needed for operation on a pseudo-tty,
736 * because the pty code doesn't call pppstart after it has
737 * drained the t_outq.
739 if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
740 callout_reset(&sc->sc_timeout, 1, ppp_timeout, sc);
741 sc->sc_flags |= SC_TIMEOUT;
745 lwkt_reltoken(&tty_token);
749 * This gets called when a received packet is placed on
750 * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
753 pppasyncctlp(struct ppp_softc *sc)
757 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
759 lwkt_gettoken(&tty_token);
760 tp = (struct tty *) sc->sc_devp;
761 clist_putc(0, &tp->t_canq);
763 lwkt_reltoken(&tty_token);
768 * Start output on async tty interface. If the transmit queue
769 * has drained sufficiently, arrange for pppasyncstart to be
770 * called later at splsoftnet.
771 * Called at spltty or higher.
774 pppstart(struct tty *tp)
776 struct ppp_softc *sc = (struct ppp_softc *) tp->t_slsc;
778 lwkt_gettoken(&tty_token);
780 * Call output process whether or not there is any output.
781 * We are being called in lieu of ttstart and must do what it would.
783 if (tp->t_oproc != NULL)
787 * If ALTQ is enabled, don't invoke NETISR_PPP.
788 * pppintr() could loop without doing anything useful
789 * under rate-limiting.
791 if (ifq_is_enabled(&sc->sc_if.if_snd)) {
792 lwkt_reltoken(&tty_token);
797 * If the transmit queue has drained and the tty has not hung up
798 * or been disconnected from the ppp unit, then tell if_ppp.c that
799 * we need more output.
801 if (CCOUNT(&tp->t_outq) < PPP_LOWAT
802 && !((tp->t_state & TS_CONNECTED) == 0)
803 && sc != NULL && tp == (struct tty *) sc->sc_devp) {
807 lwkt_reltoken(&tty_token);
812 * Timeout routine - try to start some more output.
817 struct ppp_softc *sc = (struct ppp_softc *) x;
818 struct tty *tp = (struct tty *) sc->sc_devp;
821 lwkt_gettoken(&tty_token);
822 sc->sc_flags &= ~SC_TIMEOUT;
824 lwkt_reltoken(&tty_token);
829 * Allocate enough mbuf to handle current MRU.
832 pppgetm(struct ppp_softc *sc)
834 struct mbuf *m, **mp;
838 for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
839 if ((m = *mp) == NULL) {
840 MGETHDR(m, M_NOWAIT, MT_DATA);
846 len -= M_DATASIZE(m);
852 * tty interface receiver interrupt.
854 static unsigned paritytab[8] = {
855 0x96696996, 0x69969669, 0x69969669, 0x96696996,
856 0x69969669, 0x96696996, 0x96696996, 0x69969669
860 * Called when character is available from device driver.
861 * Only guaranteed to be at splsofttty() or spltty()
862 * This is safe to be called while the upper half's netisr is preempted.
865 pppinput(int c, struct tty *tp)
867 struct ppp_softc *sc;
871 lwkt_gettoken(&tty_token);
872 sc = (struct ppp_softc *) tp->t_slsc;
873 if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
874 lwkt_reltoken(&tty_token);
879 ++sc->sc_stats.ppp_ibytes;
881 if ((tp->t_state & TS_CONNECTED) == 0) {
882 if (sc->sc_flags & SC_DEBUG)
883 kprintf("%s: no carrier\n", sc->sc_if.if_xname);
887 if (c & TTY_ERRORMASK) {
888 /* framing error or overrun on this char - abort packet */
889 if (sc->sc_flags & SC_DEBUG)
890 kprintf("%s: line error %x\n", sc->sc_if.if_xname,
898 * Handle software flow control of output.
900 if (tp->t_iflag & IXON) {
901 if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
902 if ((tp->t_state & TS_TTSTOP) == 0) {
903 tp->t_state |= TS_TTSTOP;
906 lwkt_reltoken(&tty_token);
909 if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
910 tp->t_state &= ~TS_TTSTOP;
911 if (tp->t_oproc != NULL)
913 lwkt_reltoken(&tty_token);
920 sc->sc_flags |= SC_RCV_B7_1;
922 sc->sc_flags |= SC_RCV_B7_0;
923 if (paritytab[c >> 5] & (1 << (c & 0x1F)))
924 sc->sc_flags |= SC_RCV_ODDP;
926 sc->sc_flags |= SC_RCV_EVNP;
929 if (sc->sc_flags & SC_LOG_RAWIN)
936 if (sc->sc_rawin_count > 0)
940 * If SC_ESCAPED is set, then we've seen the packet
941 * abort sequence "}~".
943 if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
944 || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
946 sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
947 if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
948 if (sc->sc_flags & SC_DEBUG)
949 kprintf("%s: bad fcs %x, pkt len %d\n",
950 sc->sc_if.if_xname, sc->sc_fcs, ilen);
951 IFNET_STAT_INC(&sc->sc_if, ierrors, 1);
952 sc->sc_stats.ppp_ierrors++;
954 sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
956 lwkt_reltoken(&tty_token);
960 if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
962 if (sc->sc_flags & SC_DEBUG)
963 kprintf("%s: too short (%d)\n", sc->sc_if.if_xname, ilen);
965 IFNET_STAT_INC(&sc->sc_if, ierrors, 1);
966 sc->sc_stats.ppp_ierrors++;
967 sc->sc_flags |= SC_PKTLOST;
970 lwkt_reltoken(&tty_token);
975 * Remove FCS trailer. Somewhat painful...
978 if (--sc->sc_mc->m_len == 0) {
979 for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
985 /* excise this mbuf chain */
987 sc->sc_m = sc->sc_mc->m_next;
988 sc->sc_mc->m_next = NULL;
990 ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
991 if (sc->sc_flags & SC_PKTLOST) {
993 sc->sc_flags &= ~SC_PKTLOST;
998 lwkt_reltoken(&tty_token);
1002 if (sc->sc_flags & SC_FLUSH) {
1003 if (sc->sc_flags & SC_LOG_FLUSH)
1005 lwkt_reltoken(&tty_token);
1009 if (c < 0x20 && (sc->sc_rasyncmap & (1 << c))) {
1010 lwkt_reltoken(&tty_token);
1015 if (sc->sc_flags & SC_ESCAPED) {
1016 sc->sc_flags &= ~SC_ESCAPED;
1018 } else if (c == PPP_ESCAPE) {
1019 sc->sc_flags |= SC_ESCAPED;
1021 lwkt_reltoken(&tty_token);
1027 * Initialize buffer on first octet received.
1028 * First octet could be address or protocol (when compressing
1030 * Second octet is control.
1031 * Third octet is first or second (when compressing protocol)
1032 * octet of protocol.
1033 * Fourth octet is second octet of protocol.
1035 if (sc->sc_ilen == 0) {
1036 /* reset the first input mbuf */
1037 if (sc->sc_m == NULL) {
1039 if (sc->sc_m == NULL) {
1040 if (sc->sc_flags & SC_DEBUG)
1041 kprintf("%s: no input mbufs!\n", sc->sc_if.if_xname);
1047 m->m_data = M_DATASTART(sc->sc_m);
1049 sc->sc_mp = mtod(m, char *);
1050 sc->sc_fcs = PPP_INITFCS;
1051 if (c != PPP_ALLSTATIONS) {
1052 if (sc->sc_flags & SC_REJ_COMP_AC) {
1053 if (sc->sc_flags & SC_DEBUG)
1054 kprintf("%s: garbage received: 0x%x (need 0xFF)\n",
1055 sc->sc_if.if_xname, c);
1058 *sc->sc_mp++ = PPP_ALLSTATIONS;
1059 *sc->sc_mp++ = PPP_UI;
1064 if (sc->sc_ilen == 1 && c != PPP_UI) {
1065 if (sc->sc_flags & SC_DEBUG)
1066 kprintf("%s: missing UI (0x3), got 0x%x\n",
1067 sc->sc_if.if_xname, c);
1070 if (sc->sc_ilen == 2 && (c & 1) == 1) {
1071 /* a compressed protocol */
1076 if (sc->sc_ilen == 3 && (c & 1) == 0) {
1077 if (sc->sc_flags & SC_DEBUG)
1078 kprintf("%s: bad protocol %x\n", sc->sc_if.if_xname,
1079 (sc->sc_mp[-1] << 8) + c);
1083 /* packet beyond configured mru? */
1084 if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1085 if (sc->sc_flags & SC_DEBUG)
1086 kprintf("%s: packet too big\n", sc->sc_if.if_xname);
1090 /* is this mbuf full? */
1092 if (M_TRAILINGSPACE(m) <= 0) {
1093 if (m->m_next == NULL) {
1095 if (m->m_next == NULL) {
1096 if (sc->sc_flags & SC_DEBUG)
1097 kprintf("%s: too few input mbufs!\n", sc->sc_if.if_xname);
1101 sc->sc_mc = m = m->m_next;
1103 m->m_data = M_DATASTART(m);
1104 sc->sc_mp = mtod(m, char *);
1109 sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1110 lwkt_reltoken(&tty_token);
1114 if (!(sc->sc_flags & SC_FLUSH)) {
1116 IFNET_STAT_INC(&sc->sc_if, ierrors, 1);
1117 sc->sc_stats.ppp_ierrors++;
1118 sc->sc_flags |= SC_FLUSH;
1120 if (sc->sc_flags & SC_LOG_FLUSH)
1123 lwkt_reltoken(&tty_token);
1127 #define MAX_DUMP_BYTES 128
1130 ppplogchar(struct ppp_softc *sc, int c)
1135 sc->sc_rawin[sc->sc_rawin_count++] = c;
1136 if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1137 || (c < 0 && sc->sc_rawin_count > 0)) {
1138 hexstr = kmalloc(HEX_NCPYLEN(sc->sc_rawin_count), M_TEMP, M_WAITOK | M_ZERO);
1139 kprintf("%s input: %s", sc->sc_if.if_xname, hexncpy(sc->sc_rawin,
1140 sc->sc_rawin_count, hexstr, HEX_NCPYLEN(sc->sc_rawin_count), " "));
1141 sc->sc_rawin_count = 0;
1142 kfree(hexstr, M_TEMP);