2 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
5 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The name "Carnegie Mellon University" must not be used to
20 * endorse or promote products derived from this software without
21 * prior written permission. For permission or any legal
22 * details, please contact
23 * Office of Technology Transfer
24 * Carnegie Mellon University
26 * Pittsburgh, PA 15213-3890
27 * (412) 268-4387, fax: (412) 268-7395
28 * tech-transfer@andrew.cmu.edu
30 * 4. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by Computing Services
33 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
35 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
36 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
37 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
38 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
40 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
41 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
44 * Carnegie Mellon University
46 * Pittsburgh, PA 15213
51 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
53 * Copyright (c) 1987 Regents of the University of California.
54 * All rights reserved.
56 * Redistribution and use in source and binary forms are permitted
57 * provided that the above copyright notice and this paragraph are
58 * duplicated in all such forms and that any documentation,
59 * advertising materials, and other materials related to such
60 * distribution and use acknowledge that the software was developed
61 * by the University of California, Berkeley. The name of the
62 * University may not be used to endorse or promote products derived
63 * from this software without specific prior written permission.
64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
65 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
66 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
68 * Serial Line interface
71 * Center for Seismic Studies
72 * 1300 N 17th Street, Suite 1450
73 * Arlington, Virginia 22209
78 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
79 * Converted to 4.3BSD Beta by Chris Torek.
80 * Other changes made at Berkeley, based in part on code by Kirk Smith.
82 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
83 * Added VJ tcp header compression; more unified ioctls
85 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
86 * Cleaned up a lot of the mbuf-related code to fix bugs that
87 * caused system crashes and packet corruption. Changed pppstart
88 * so that it doesn't just give up with a "collision" if the whole
89 * packet doesn't fit in the output ring buffer.
91 * Added priority queueing for interactive IP packets, following
92 * the model of if_sl.c, plus hooks for bpf.
93 * Paul Mackerras (paulus@cs.anu.edu.au).
95 * Ultrix port by Per Sundstrom <sundstrom@stkhlm.enet.dec.com>,
96 * Robert Olsson <robert@robur.slu.se> and Paul Mackerras.
99 /* $Id: ppp_tty.c,v 1.9 2002/12/06 09:49:16 paulus Exp $ */
100 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
101 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
109 #include "../h/param.h"
110 #include "../h/user.h"
111 #include "../h/proc.h"
112 #include "../h/mbuf.h"
113 #include "../h/buf.h"
114 #include "../h/socket.h"
115 #include "../h/ioctl.h"
116 #include "../h/file.h"
117 #include "../h/tty.h"
118 #include "../h/kernel.h"
119 #include "../h/conf.h"
120 #include "../h/uio.h"
121 #include "../h/systm.h"
123 #include "../net/net/if.h"
124 #include "ppp_defs.h"
127 #include "../net/netinet/in.h"
128 #include "../net/netinet/in_systm.h"
129 #include "../net/netinet/ip.h"
130 #include "slcompress.h"
134 #include "if_pppvar.h"
136 int pppopen
__P((dev_t dev
, struct tty
*tp
));
137 int pppclose
__P((struct tty
*tp
, int flag
));
138 int pppread
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
139 int pppwrite
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
140 int ppptioctl
__P((struct tty
*tp
, int cmd
, caddr_t data
, int flag
));
141 int pppinput
__P((int c
, struct tty
*tp
));
142 int pppstart
__P((struct tty
*tp
));
144 static u_short pppfcs
__P((u_short fcs
, u_char
*cp
, int len
));
145 static void pppasyncstart
__P((struct ppp_softc
*));
146 static void pppasyncctlp
__P((struct ppp_softc
*));
147 static void pppasyncrelinq
__P((struct ppp_softc
*));
148 static void ppp_timeout
__P((void *));
149 static void pppgetm
__P((struct ppp_softc
*sc
));
150 static void pppdumpb
__P((u_char
*b
, int l
));
151 static void ppplogchar
__P((struct ppp_softc
*, int));
154 * Some useful mbuf macros not in mbuf.h.
156 #define M_IS_CLUSTER(m) ((m)->m_off > MMAXOFF)
158 #define M_TRAILINGSPACE(m) \
159 ((M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr + M_CLUSTERSZ : MSIZE) \
160 - ((m)->m_off + (m)->m_len))
162 #define M_OFFSTART(m) \
163 (M_IS_CLUSTER(m) ? (u_int)(m)->m_clptr : MMINOFF)
165 #define M_DATASIZE(m) \
166 (M_IS_CLUSTER(m) ? M_CLUSTERSZ : MLEN)
169 * Does c need to be escaped?
171 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
174 * Procedures for using an async tty interface for PPP.
178 * This is an Ultrix kernel, we've got clists.
180 #define CCOUNT(q) ((q)->c_cc)
183 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
184 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
187 * Line specific open routine for async tty devices.
188 * Attach the given tty to the first available ppp unit.
189 * Called from device open routine or ttioctl.
195 register struct tty
*tp
;
197 register struct ppp_softc
*sc
;
199 struct proc
*p
= u
.u_procp
;
206 if (tp
->t_line
== PPPDISC
) {
207 sc
= (struct ppp_softc
*) tp
->t_sc
;
208 if (sc
!= NULL
&& sc
->sc_devp
== (void *) tp
) {
214 if ((sc
= pppalloc(p
->p_pid
)) == NULL
) {
220 (*sc
->sc_relinq
)(sc
); /* get previous owner to relinquish the unit */
224 bzero(sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
225 sc
->sc_asyncmap
[0] = 0xffffffff;
226 sc
->sc_asyncmap
[3] = 0x60000000;
227 sc
->sc_rasyncmap
= 0;
228 sc
->sc_devp
= (void *) tp
;
229 sc
->sc_start
= pppasyncstart
;
230 sc
->sc_ctlp
= pppasyncctlp
;
231 sc
->sc_relinq
= pppasyncrelinq
;
234 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
236 tp
->t_sc
= (caddr_t
) sc
;
237 ttyflush(tp
, FREAD
| FWRITE
);
244 * Line specific close routine, called from device close routine
246 * Detach the tty from the ppp unit.
247 * Mimics part of ttyclose().
254 register struct ppp_softc
*sc
;
258 ttyflush(tp
, FREAD
|FWRITE
);
260 sc
= (struct ppp_softc
*) tp
->t_sc
;
263 if (tp
== (struct tty
*) sc
->sc_devp
) {
273 * Relinquish the interface unit to another device.
277 struct ppp_softc
*sc
;
283 m_freem(sc
->sc_outm
);
290 if (sc
->sc_flags
& SC_TIMEOUT
) {
291 untimeout(ppp_timeout
, (void *) sc
);
292 sc
->sc_flags
&= ~SC_TIMEOUT
;
298 * Line specific (tty) read routine.
301 pppread(tp
, uio
, flag
)
302 register struct tty
*tp
;
306 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
314 * Loop waiting for input, checking that nothing disasterous
315 * happens in the meantime.
319 if (tp
!= (struct tty
*) sc
->sc_devp
|| tp
->t_line
!= PPPDISC
) {
323 if (sc
->sc_inq
.ifq_head
!= NULL
)
325 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0
326 && (tp
->t_state
& TS_ISOPEN
)) {
328 return 0; /* end of file */
330 if (tp
->t_state
& (TS_ASYNC
| TS_NBIO
)) {
332 return (EWOULDBLOCK
);
334 sleep((caddr_t
) &tp
->t_rawq
, TTIPRI
);
337 /* Pull place-holder byte out of canonical queue */
340 /* Get the packet from the input queue */
341 IF_DEQUEUE(&sc
->sc_inq
, m0
);
344 for (m
= m0
; m
&& uio
->uio_resid
; m
= m
->m_next
)
345 if (error
= uiomove(mtod(m
, u_char
*), m
->m_len
, UIO_READ
, uio
))
352 * Line specific (tty) write routine.
355 pppwrite(tp
, uio
, flag
)
356 register struct tty
*tp
;
360 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
361 struct mbuf
*m
, *m0
, **mp
, *p
;
365 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
366 return 0; /* wrote 0 bytes */
367 if (tp
->t_line
!= PPPDISC
)
369 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
371 if (uio
->uio_resid
> sc
->sc_if
.if_mtu
+ PPP_HDRLEN
||
372 uio
->uio_resid
< PPP_HDRLEN
)
374 for (mp
= &m0
; uio
->uio_resid
; mp
= &m
->m_next
) {
375 MGET(m
, M_WAIT
, MT_DATA
);
376 if ((*mp
= m
) == NULL
) {
380 if (uio
->uio_resid
>= CLBYTES
/ 2) {
384 len
= MIN(m
->m_len
, uio
->uio_resid
);
385 if (error
= uiomove(mtod(m
, u_char
*), len
, UIO_WRITE
, uio
)) {
391 dst
.sa_family
= AF_UNSPEC
;
392 bcopy(mtod(m0
, caddr_t
), dst
.sa_data
, PPP_HDRLEN
);
393 m0
->m_off
+= PPP_HDRLEN
;
394 m0
->m_len
-= PPP_HDRLEN
;
395 return (pppoutput(&sc
->sc_if
, m0
, &dst
));
399 * Line specific (tty) ioctl routine.
400 * This discipline requires that tty device drivers call
401 * the line specific l_ioctl routine from their ioctl routines.
405 ppptioctl(tp
, cmd
, data
, flag
)
410 struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
413 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
418 case PPPIOCSASYNCMAP
:
421 sc
->sc_asyncmap
[0] = *(u_int
*)data
;
424 case PPPIOCGASYNCMAP
:
425 *(u_int
*)data
= sc
->sc_asyncmap
[0];
428 case PPPIOCSRASYNCMAP
:
431 sc
->sc_rasyncmap
= *(u_int
*)data
;
434 case PPPIOCGRASYNCMAP
:
435 *(u_int
*)data
= sc
->sc_rasyncmap
;
438 case PPPIOCSXASYNCMAP
:
442 bcopy(data
, sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
443 sc
->sc_asyncmap
[1] = 0; /* mustn't escape 0x20 - 0x3f */
444 sc
->sc_asyncmap
[2] &= ~0x40000000; /* mustn't escape 0x5e */
445 sc
->sc_asyncmap
[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
449 case PPPIOCGXASYNCMAP
:
450 bcopy(sc
->sc_asyncmap
, data
, sizeof(sc
->sc_asyncmap
));
454 error
= pppioctl(sc
, cmd
, data
, flag
);
455 if (error
== 0 && cmd
== PPPIOCSMRU
)
463 * FCS lookup table as calculated by genfcstab.
465 static u_short fcstab
[256] = {
466 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
467 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
468 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
469 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
470 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
471 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
472 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
473 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
474 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
475 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
476 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
477 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
478 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
479 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
480 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
481 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
482 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
483 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
484 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
485 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
486 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
487 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
488 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
489 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
490 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
491 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
492 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
493 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
494 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
495 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
496 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
497 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
501 * Calculate a new FCS given the current FCS and the new data.
505 register u_short fcs
;
510 fcs
= PPP_FCS(fcs
, *cp
++);
515 * This gets called at splnet from if_ppp.c at various times
516 * when there is data ready to be sent.
520 register struct ppp_softc
*sc
;
522 register struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
523 register struct mbuf
*m
;
525 register u_char
*start
, *stop
, *cp
;
526 int n
, ndone
, done
, idle
;
531 while (CCOUNT(&tp
->t_outq
) < PPP_HIWAT
) {
533 * See if we have an existing packet partly sent.
534 * If not, get a new packet and start sending it.
539 * Get another packet to be sent.
548 * The extra PPP_FLAG will start up a new packet, and thus
549 * will flush any accumulated garbage. We do this whenever
550 * the line may have been idle for some time.
552 if (CCOUNT(&tp
->t_outq
) == 0) {
553 ++sc
->sc_stats
.ppp_obytes
;
554 (void) putc(PPP_FLAG
, &tp
->t_outq
);
557 /* Calculate the FCS for the first mbuf's worth. */
558 sc
->sc_outfcs
= pppfcs(PPP_INITFCS
, mtod(m
, u_char
*), m
->m_len
);
562 start
= mtod(m
, u_char
*);
567 * Find out how many bytes in the string we can
568 * handle without doing something special.
570 for (cp
= start
; cp
< stop
; cp
++)
575 ndone
= n
- b_to_q(start
, n
, &tp
->t_outq
);
578 sc
->sc_stats
.ppp_obytes
+= ndone
;
581 break; /* packet doesn't fit */
584 * If there are characters left in the mbuf,
585 * the first one must be special.
586 * Put it out in a different form.
590 if (putc(PPP_ESCAPE
, &tp
->t_outq
))
592 if (putc(*start
^ PPP_TRANS
, &tp
->t_outq
)) {
593 (void) unputc(&tp
->t_outq
);
598 sc
->sc_stats
.ppp_obytes
+= 2;
605 * If we didn't empty this mbuf, remember where we're up to.
606 * If we emptied the last mbuf, try to add the FCS and closing
607 * flag, and if we can't, leave sc_outm pointing to m, but with
608 * m->m_len == 0, to remind us to output the FCS and flag later.
611 if (done
&& m
->m_next
== NULL
) {
617 * We may have to escape the bytes in the FCS.
620 c
= ~sc
->sc_outfcs
& 0xFF;
623 *p
++ = c
^ PPP_TRANS
;
626 c
= (~sc
->sc_outfcs
>> 8) & 0xFF;
629 *p
++ = c
^ PPP_TRANS
;
635 * Try to output the FCS and flag. If the bytes
636 * don't all fit, back out.
639 for (q
= endseq
; q
< p
; ++q
)
640 if (putc(*q
, &tp
->t_outq
)) {
642 for (; q
> endseq
; --q
)
648 sc
->sc_stats
.ppp_obytes
+= q
- endseq
;
652 m
->m_off
+= m
->m_len
- len
;
657 /* Finished with this mbuf; free it and move on. */
661 /* Finished a packet */
664 sc
->sc_outfcs
= pppfcs(sc
->sc_outfcs
, mtod(m
, u_char
*), m
->m_len
);
668 * If m == NULL, we have finished a packet.
669 * If m != NULL, we've either done as much work this time
670 * as we need to, or else we've filled up the output queue.
677 /* Call pppstart to start output again if necessary. */
682 * This timeout is needed for operation on a pseudo-tty,
683 * because the pty code doesn't call pppstart after it has
684 * drained the t_outq.
686 if (!idle
&& (sc
->sc_flags
& SC_TIMEOUT
) == 0) {
687 timeout(ppp_timeout
, (void *) sc
, 1);
688 sc
->sc_flags
|= SC_TIMEOUT
;
695 * This gets called when a received packet is placed on
696 * the inq, at splnet.
700 struct ppp_softc
*sc
;
705 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
707 tp
= (struct tty
*) sc
->sc_devp
;
708 putc(0, &tp
->t_canq
);
714 * Start output on async tty interface. If the transmit queue
715 * has drained sufficiently, arrange for pppasyncstart to be
716 * called later at splnet.
717 * Called at spltty or higher.
721 register struct tty
*tp
;
723 register struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
726 * If there is stuff in the output queue, send it now.
727 * We are being called in lieu of ttstart and must do what it would.
729 if (tp
->t_oproc
!= NULL
)
733 * If the transmit queue has drained and the tty has not hung up
734 * or been disconnected from the ppp unit, then tell if_ppp.c that
735 * we need more output.
737 if (CCOUNT(&tp
->t_outq
) < PPP_LOWAT
738 && !((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
739 && sc
!= NULL
&& tp
== (struct tty
*) sc
->sc_devp
) {
747 * Timeout routine - try to start some more output.
753 struct ppp_softc
*sc
= (struct ppp_softc
*) x
;
754 struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
758 sc
->sc_flags
&= ~SC_TIMEOUT
;
764 * Allocate enough mbuf to handle current MRU.
768 register struct ppp_softc
*sc
;
770 struct mbuf
*m
, **mp
, *p
;
774 for (len
= sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
; len
> 0; ){
775 if ((m
= *mp
) == NULL
) {
776 MGET(m
, M_DONTWAIT
, MT_DATA
);
782 len
-= M_DATASIZE(m
);
788 * tty interface receiver interrupt.
790 static unsigned paritytab
[8] = {
791 0x96696996, 0x69969669, 0x69969669, 0x96696996,
792 0x69969669, 0x96696996, 0x96696996, 0x69969669
798 register struct tty
*tp
;
800 register struct ppp_softc
*sc
;
805 sc
= (struct ppp_softc
*) tp
->t_sc
;
806 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
810 ++sc
->sc_stats
.ppp_ibytes
;
815 * Handle software flow control of output.
817 if (tp
->t_iflag
& IXON
) {
818 if (c
== tp
->t_cc
[VSTOP
] && tp
->t_cc
[VSTOP
] != 0) {
819 if ((tp
->t_state
& TS_TTSTOP
) == 0) {
820 tp
->t_state
|= TS_TTSTOP
;
821 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
825 if (c
== tp
->t_cc
[VSTART
] && tp
->t_cc
[VSTART
] != 0) {
826 tp
->t_state
&= ~TS_TTSTOP
;
827 if (tp
->t_oproc
!= NULL
)
835 sc
->sc_flags
|= SC_RCV_B7_1
;
837 sc
->sc_flags
|= SC_RCV_B7_0
;
838 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
839 sc
->sc_flags
|= SC_RCV_ODDP
;
841 sc
->sc_flags
|= SC_RCV_EVNP
;
844 if (sc
->sc_flags
& SC_LOG_RAWIN
)
851 if (sc
->sc_rawin_count
> 0)
855 * If SC_ESCAPED is set, then we've seen the packet
856 * abort sequence "}~".
858 if (sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)
859 || (ilen
> 0 && sc
->sc_fcs
!= PPP_GOODFCS
)) {
861 sc
->sc_flags
|= SC_PKTLOST
; /* note the dropped packet */
862 if ((sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)) == 0){
863 if (sc
->sc_flags
& SC_DEBUG
)
864 printf("ppp%d: bad fcs %x, pkt len %d\n",
865 sc
->sc_if
.if_unit
, sc
->sc_fcs
, ilen
);
866 sc
->sc_if
.if_ierrors
++;
867 sc
->sc_stats
.ppp_ierrors
++;
869 sc
->sc_flags
&= ~(SC_FLUSH
| SC_ESCAPED
);
874 if (ilen
< PPP_HDRLEN
+ PPP_FCSLEN
) {
876 if (sc
->sc_flags
& SC_DEBUG
)
877 printf("ppp%d: too short (%d)\n", sc
->sc_if
.if_unit
, ilen
);
879 sc
->sc_if
.if_ierrors
++;
880 sc
->sc_stats
.ppp_ierrors
++;
881 sc
->sc_flags
|= SC_PKTLOST
;
888 * Remove FCS trailer. Somewhat painful...
891 if (--sc
->sc_mc
->m_len
== 0) {
892 for (m
= sc
->sc_m
; m
->m_next
!= sc
->sc_mc
; m
= m
->m_next
)
898 /* excise this mbuf chain */
900 sc
->sc_m
= sc
->sc_mc
->m_next
;
901 sc
->sc_mc
->m_next
= NULL
;
903 ppppktin(sc
, m
, sc
->sc_flags
& SC_PKTLOST
);
904 if (sc
->sc_flags
& SC_PKTLOST
) {
906 sc
->sc_flags
&= ~SC_PKTLOST
;
914 if (sc
->sc_flags
& SC_FLUSH
) {
915 if (sc
->sc_flags
& SC_LOG_FLUSH
)
920 if (c
< 0x20 && (sc
->sc_rasyncmap
& (1 << c
)))
924 if (sc
->sc_flags
& SC_ESCAPED
) {
925 sc
->sc_flags
&= ~SC_ESCAPED
;
927 } else if (c
== PPP_ESCAPE
) {
928 sc
->sc_flags
|= SC_ESCAPED
;
935 * Initialize buffer on first octet received.
936 * First octet could be address or protocol (when compressing
938 * Second octet is control.
939 * Third octet is first or second (when compressing protocol)
941 * Fourth octet is second octet of protocol.
943 if (sc
->sc_ilen
== 0) {
944 /* reset the first input mbuf */
945 if (sc
->sc_m
== NULL
) {
947 if (sc
->sc_m
== NULL
) {
948 if (sc
->sc_flags
& SC_DEBUG
)
949 printf("ppp%d: no input mbufs!\n", sc
->sc_if
.if_unit
);
955 m
->m_off
= M_OFFSTART(m
);
957 sc
->sc_mp
= mtod(m
, char *);
958 sc
->sc_fcs
= PPP_INITFCS
;
959 if (c
!= PPP_ALLSTATIONS
) {
960 if (sc
->sc_flags
& SC_REJ_COMP_AC
) {
961 if (sc
->sc_flags
& SC_DEBUG
)
962 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
963 sc
->sc_if
.if_unit
, c
);
966 *sc
->sc_mp
++ = PPP_ALLSTATIONS
;
967 *sc
->sc_mp
++ = PPP_UI
;
972 if (sc
->sc_ilen
== 1 && c
!= PPP_UI
) {
973 if (sc
->sc_flags
& SC_DEBUG
)
974 printf("ppp%d: missing UI (0x3), got 0x%x\n",
975 sc
->sc_if
.if_unit
, c
);
978 if (sc
->sc_ilen
== 2 && (c
& 1) == 1) {
979 /* a compressed protocol */
984 if (sc
->sc_ilen
== 3 && (c
& 1) == 0) {
985 if (sc
->sc_flags
& SC_DEBUG
)
986 printf("ppp%d: bad protocol %x\n", sc
->sc_if
.if_unit
,
987 (sc
->sc_mp
[-1] << 8) + c
);
991 /* packet beyond configured mru? */
992 if (++sc
->sc_ilen
> sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
) {
993 if (sc
->sc_flags
& SC_DEBUG
)
994 printf("ppp%d: packet too big\n", sc
->sc_if
.if_unit
);
998 /* is this mbuf full? */
1000 if (M_TRAILINGSPACE(m
) <= 0) {
1001 if (m
->m_next
== NULL
) {
1003 if (m
->m_next
== NULL
) {
1004 if (sc
->sc_flags
& SC_DEBUG
)
1005 printf("ppp%d: too few input mbufs!\n", sc
->sc_if
.if_unit
);
1009 sc
->sc_mc
= m
= m
->m_next
;
1011 m
->m_off
= M_OFFSTART(m
);
1012 sc
->sc_mp
= mtod(m
, char *);
1017 sc
->sc_fcs
= PPP_FCS(sc
->sc_fcs
, c
);
1021 if (!(sc
->sc_flags
& SC_FLUSH
)) {
1023 sc
->sc_if
.if_ierrors
++;
1024 sc
->sc_stats
.ppp_ierrors
++;
1025 sc
->sc_flags
|= SC_FLUSH
;
1027 if (sc
->sc_flags
& SC_LOG_FLUSH
)
1033 #define MAX_DUMP_BYTES 128
1037 struct ppp_softc
*sc
;
1041 sc
->sc_rawin
[sc
->sc_rawin_count
++] = c
;
1042 if (sc
->sc_rawin_count
>= sizeof(sc
->sc_rawin
)
1043 || (c
< 0 && sc
->sc_rawin_count
> 0)) {
1044 printf("ppp%d input: ", sc
->sc_if
.if_unit
);
1045 pppdumpb(sc
->sc_rawin
, sc
->sc_rawin_count
);
1046 sc
->sc_rawin_count
= 0;
1055 char buf
[3*MAX_DUMP_BYTES
+4];
1057 static char digits
[] = "0123456789abcdef";
1060 if (bp
>= buf
+ sizeof(buf
) - 3) {
1064 *bp
++ = digits
[*b
>> 4]; /* convert byte to ascii hex */
1065 *bp
++ = digits
[*b
++ & 0xf];
1070 printf("%s\n", buf
);
1073 #endif /* NPPP > 0 */