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 /* $Id: ppp_tty.c,v 1.8 1997/04/30 05:42:08 paulus Exp $ */
74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
75 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
83 #include <sys/param.h>
84 #include <sys/systm.h>
87 #include <sys/dkstat.h>
88 #include <sys/socket.h>
89 #include <sys/ioctl.h>
92 #include <sys/kernel.h>
94 #include <sys/vnode.h>
97 #include <net/if_types.h>
100 #include <netinet/in.h>
101 #include <netinet/in_systm.h>
102 #include <netinet/ip.h>
103 #include <net/pppcompress.h>
109 #include <net/ppp_defs.h>
110 #include <net/if_ppp.h>
111 #include <net/if_pppvar.h>
113 void pppasyncattach
__P((void));
114 int pppopen
__P((dev_t dev
, struct tty
*tp
));
115 int pppclose
__P((struct tty
*tp
, int flag
));
116 int pppread
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
117 int pppwrite
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
118 int ppptioctl
__P((struct tty
*tp
, int cmd
, caddr_t data
, int flag
,
120 int pppinput
__P((int c
, struct tty
*tp
));
121 int pppstart
__P((struct tty
*tp
));
123 static u_short pppfcs
__P((u_short fcs
, u_char
*cp
, int len
));
124 static void pppasyncstart
__P((struct ppp_softc
*));
125 static void pppasyncctlp
__P((struct ppp_softc
*));
126 static void pppasyncrelinq
__P((struct ppp_softc
*));
127 static void ppp_timeout
__P((void *));
128 static void pppgetm
__P((struct ppp_softc
*sc
));
129 static void pppdumpb
__P((u_char
*b
, int l
));
130 static void ppplogchar
__P((struct ppp_softc
*, int));
133 * Some useful mbuf macros not in mbuf.h.
135 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
137 #define M_DATASTART(m) \
138 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
139 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
141 #define M_DATASIZE(m) \
142 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
143 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
146 * Does c need to be escaped?
148 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
151 * Procedures for using an async tty interface for PPP.
154 /* This is a FreeBSD-2.0 kernel. */
155 #define CCOUNT(q) ((q)->c_cc)
156 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
157 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
160 * Define the PPP line discipline.
163 static struct linesw pppdisc
= {
164 pppopen
, pppclose
, pppread
, pppwrite
, ppptioctl
,
165 pppinput
, pppstart
, ttymodem
171 linesw
[PPPDISC
] = pppdisc
;
174 TEXT_SET(pseudo_set
, pppasyncattach
);
177 * Line specific open routine for async tty devices.
178 * Attach the given tty to the first available ppp unit.
179 * Called from device open routine or ttioctl.
185 register struct tty
*tp
;
187 struct proc
*p
= curproc
; /* XXX */
188 register struct ppp_softc
*sc
;
191 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
196 if (tp
->t_line
== PPPDISC
) {
197 sc
= (struct ppp_softc
*) tp
->t_sc
;
198 if (sc
!= NULL
&& sc
->sc_devp
== (void *) tp
) {
204 if ((sc
= pppalloc(p
->p_pid
)) == NULL
) {
210 (*sc
->sc_relinq
)(sc
); /* get previous owner to relinquish the unit */
214 bzero(sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
215 sc
->sc_asyncmap
[0] = 0xffffffff;
216 sc
->sc_asyncmap
[3] = 0x60000000;
217 sc
->sc_rasyncmap
= 0;
218 sc
->sc_devp
= (void *) tp
;
219 sc
->sc_start
= pppasyncstart
;
220 sc
->sc_ctlp
= pppasyncctlp
;
221 sc
->sc_relinq
= pppasyncrelinq
;
224 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
225 sc
->sc_if
.if_baudrate
= tp
->t_ospeed
;
227 tp
->t_sc
= (caddr_t
) sc
;
228 ttyflush(tp
, FREAD
| FWRITE
);
235 * Line specific close routine, called from device close routine
237 * Detach the tty from the ppp unit.
238 * Mimics part of ttyclose().
245 register struct ppp_softc
*sc
;
249 ttyflush(tp
, FREAD
|FWRITE
);
251 sc
= (struct ppp_softc
*) tp
->t_sc
;
254 if (tp
== (struct tty
*) sc
->sc_devp
) {
264 * Relinquish the interface unit to another device.
268 struct ppp_softc
*sc
;
274 m_freem(sc
->sc_outm
);
281 if (sc
->sc_flags
& SC_TIMEOUT
) {
282 untimeout(ppp_timeout
, (void *) sc
);
283 sc
->sc_flags
&= ~SC_TIMEOUT
;
289 * Line specific (tty) read routine.
292 pppread(tp
, uio
, flag
)
293 register struct tty
*tp
;
297 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
305 * Loop waiting for input, checking that nothing disasterous
306 * happens in the meantime.
310 if (tp
!= (struct tty
*) sc
->sc_devp
|| tp
->t_line
!= PPPDISC
) {
314 if (sc
->sc_inq
.ifq_head
!= NULL
)
316 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0
317 && (tp
->t_state
& TS_ISOPEN
)) {
319 return 0; /* end of file */
321 if (tp
->t_state
& TS_ASYNC
|| flag
& IO_NDELAY
) {
323 return (EWOULDBLOCK
);
325 error
= ttysleep(tp
, (caddr_t
)&tp
->t_rawq
, TTIPRI
| PCATCH
, "ttyin", 0);
332 /* Pull place-holder byte out of canonical queue */
335 /* Get the packet from the input queue */
336 IF_DEQUEUE(&sc
->sc_inq
, m0
);
339 for (m
= m0
; m
&& uio
->uio_resid
; m
= m
->m_next
)
340 if ((error
= uiomove(mtod(m
, u_char
*), m
->m_len
, uio
)) != 0)
347 * Line specific (tty) write routine.
350 pppwrite(tp
, uio
, flag
)
351 register struct tty
*tp
;
355 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
356 struct mbuf
*m
, *m0
, **mp
;
360 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
361 return 0; /* wrote 0 bytes */
362 if (tp
->t_line
!= PPPDISC
)
364 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
366 if (uio
->uio_resid
> sc
->sc_if
.if_mtu
+ PPP_HDRLEN
||
367 uio
->uio_resid
< PPP_HDRLEN
)
369 for (mp
= &m0
; uio
->uio_resid
; mp
= &m
->m_next
) {
370 MGET(m
, M_WAIT
, MT_DATA
);
371 if ((*mp
= m
) == NULL
) {
376 if (uio
->uio_resid
>= MCLBYTES
/ 2)
377 MCLGET(m
, M_DONTWAIT
);
378 len
= M_TRAILINGSPACE(m
);
379 if (len
> uio
->uio_resid
)
380 len
= uio
->uio_resid
;
381 if ((error
= uiomove(mtod(m
, u_char
*), len
, uio
)) != 0) {
387 dst
.sa_family
= AF_UNSPEC
;
388 bcopy(mtod(m0
, u_char
*), dst
.sa_data
, PPP_HDRLEN
);
389 m0
->m_data
+= PPP_HDRLEN
;
390 m0
->m_len
-= PPP_HDRLEN
;
391 return (pppoutput(&sc
->sc_if
, m0
, &dst
, (struct rtentry
*)0));
395 * Line specific (tty) ioctl routine.
396 * This discipline requires that tty device drivers call
397 * the line specific l_ioctl routine from their ioctl routines.
401 ppptioctl(tp
, cmd
, data
, flag
, p
)
408 struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
411 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
416 case PPPIOCSASYNCMAP
:
417 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
419 sc
->sc_asyncmap
[0] = *(u_int
*)data
;
422 case PPPIOCGASYNCMAP
:
423 *(u_int
*)data
= sc
->sc_asyncmap
[0];
426 case PPPIOCSRASYNCMAP
:
427 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
429 sc
->sc_rasyncmap
= *(u_int
*)data
;
432 case PPPIOCGRASYNCMAP
:
433 *(u_int
*)data
= sc
->sc_rasyncmap
;
436 case PPPIOCSXASYNCMAP
:
437 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
440 bcopy(data
, sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
441 sc
->sc_asyncmap
[1] = 0; /* mustn't escape 0x20 - 0x3f */
442 sc
->sc_asyncmap
[2] &= ~0x40000000; /* mustn't escape 0x5e */
443 sc
->sc_asyncmap
[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
447 case PPPIOCGXASYNCMAP
:
448 bcopy(sc
->sc_asyncmap
, data
, sizeof(sc
->sc_asyncmap
));
452 error
= pppioctl(sc
, cmd
, data
, flag
, p
);
453 if (error
== 0 && cmd
== PPPIOCSMRU
)
461 * FCS lookup table as calculated by genfcstab.
463 static u_short fcstab
[256] = {
464 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
465 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
466 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
467 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
468 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
469 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
470 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
471 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
472 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
473 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
474 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
475 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
476 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
477 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
478 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
479 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
480 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
481 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
482 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
483 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
484 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
485 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
486 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
487 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
488 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
489 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
490 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
491 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
492 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
493 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
494 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
495 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
499 * Calculate a new FCS given the current FCS and the new data.
503 register u_short fcs
;
508 fcs
= PPP_FCS(fcs
, *cp
++);
513 * This gets called at splsoftnet from if_ppp.c at various times
514 * when there is data ready to be sent.
518 register struct ppp_softc
*sc
;
520 register struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
521 register struct mbuf
*m
;
523 register u_char
*start
, *stop
, *cp
;
524 int n
, ndone
, done
, idle
;
529 while (CCOUNT(&tp
->t_outq
) < PPP_HIWAT
) {
531 * See if we have an existing packet partly sent.
532 * If not, get a new packet and start sending it.
537 * Get another packet to be sent.
546 * The extra PPP_FLAG will start up a new packet, and thus
547 * will flush any accumulated garbage. We do this whenever
548 * the line may have been idle for some time.
550 if (CCOUNT(&tp
->t_outq
) == 0) {
551 ++sc
->sc_stats
.ppp_obytes
;
552 (void) putc(PPP_FLAG
, &tp
->t_outq
);
555 /* Calculate the FCS for the first mbuf's worth. */
556 sc
->sc_outfcs
= pppfcs(PPP_INITFCS
, mtod(m
, u_char
*), m
->m_len
);
557 sc
->sc_if
.if_lastchange
= time
;
561 start
= mtod(m
, u_char
*);
566 * Find out how many bytes in the string we can
567 * handle without doing something special.
569 for (cp
= start
; cp
< stop
; cp
++)
574 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
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 /* remember where we got to */
658 /* Finished with this mbuf; free it and move on. */
662 /* Finished a packet */
665 sc
->sc_outfcs
= pppfcs(sc
->sc_outfcs
, mtod(m
, u_char
*), m
->m_len
);
669 * If m == NULL, we have finished a packet.
670 * If m != NULL, we've either done as much work this time
671 * as we need to, or else we've filled up the output queue.
678 /* Call pppstart to start output again if necessary. */
683 * This timeout is needed for operation on a pseudo-tty,
684 * because the pty code doesn't call pppstart after it has
685 * drained the t_outq.
687 if (!idle
&& (sc
->sc_flags
& SC_TIMEOUT
) == 0) {
688 timeout(ppp_timeout
, (void *) sc
, 1);
689 sc
->sc_flags
|= SC_TIMEOUT
;
696 * This gets called when a received packet is placed on
697 * the inq, at splsoftnet.
701 struct ppp_softc
*sc
;
706 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
708 tp
= (struct tty
*) sc
->sc_devp
;
709 putc(0, &tp
->t_canq
);
715 * Start output on async tty interface. If the transmit queue
716 * has drained sufficiently, arrange for pppasyncstart to be
717 * called later at splsoftnet.
718 * Called at spltty or higher.
722 register struct tty
*tp
;
724 register struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
727 * If there is stuff in the output queue, send it now.
728 * We are being called in lieu of ttstart and must do what it would.
730 if (tp
->t_oproc
!= NULL
)
734 * If the transmit queue has drained and the tty has not hung up
735 * or been disconnected from the ppp unit, then tell if_ppp.c that
736 * we need more output.
738 if (CCOUNT(&tp
->t_outq
) < PPP_LOWAT
739 && !((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
740 && sc
!= NULL
&& tp
== (struct tty
*) sc
->sc_devp
) {
748 * Timeout routine - try to start some more output.
754 struct ppp_softc
*sc
= (struct ppp_softc
*) x
;
755 struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
759 sc
->sc_flags
&= ~SC_TIMEOUT
;
765 * Allocate enough mbuf to handle current MRU.
769 register struct ppp_softc
*sc
;
771 struct mbuf
*m
, **mp
;
775 for (len
= sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
; len
> 0; ){
776 if ((m
= *mp
) == NULL
) {
777 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
781 MCLGET(m
, M_DONTWAIT
);
783 len
-= M_DATASIZE(m
);
789 * tty interface receiver interrupt.
791 static unsigned paritytab
[8] = {
792 0x96696996, 0x69969669, 0x69969669, 0x96696996,
793 0x69969669, 0x96696996, 0x96696996, 0x69969669
799 register struct tty
*tp
;
801 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
;
813 /* framing error or overrun on this char - abort packet */
814 if (sc
->sc_flags
& SC_DEBUG
)
815 printf("ppp%d: bad char %x\n", sc
->sc_if
.if_unit
, c
);
822 * Handle software flow control of output.
824 if (tp
->t_iflag
& IXON
) {
825 if (c
== tp
->t_cc
[VSTOP
] && tp
->t_cc
[VSTOP
] != _POSIX_VDISABLE
) {
826 if ((tp
->t_state
& TS_TTSTOP
) == 0) {
827 tp
->t_state
|= TS_TTSTOP
;
828 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
832 if (c
== tp
->t_cc
[VSTART
] && tp
->t_cc
[VSTART
] != _POSIX_VDISABLE
) {
833 tp
->t_state
&= ~TS_TTSTOP
;
834 if (tp
->t_oproc
!= NULL
)
842 sc
->sc_flags
|= SC_RCV_B7_1
;
844 sc
->sc_flags
|= SC_RCV_B7_0
;
845 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
846 sc
->sc_flags
|= SC_RCV_ODDP
;
848 sc
->sc_flags
|= SC_RCV_EVNP
;
851 if (sc
->sc_flags
& SC_LOG_RAWIN
)
858 if (sc
->sc_rawin_count
> 0)
862 * If SC_ESCAPED is set, then we've seen the packet
863 * abort sequence "}~".
865 if (sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)
866 || (ilen
> 0 && sc
->sc_fcs
!= PPP_GOODFCS
)) {
868 sc
->sc_flags
|= SC_PKTLOST
; /* note the dropped packet */
869 if ((sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)) == 0){
870 if (sc
->sc_flags
& SC_DEBUG
)
871 printf("ppp%d: bad fcs %x, pkt len %d\n",
872 sc
->sc_if
.if_unit
, sc
->sc_fcs
, ilen
);
873 sc
->sc_if
.if_ierrors
++;
874 sc
->sc_stats
.ppp_ierrors
++;
876 sc
->sc_flags
&= ~(SC_FLUSH
| SC_ESCAPED
);
881 if (ilen
< PPP_HDRLEN
+ PPP_FCSLEN
) {
883 if (sc
->sc_flags
& SC_DEBUG
)
884 printf("ppp%d: too short (%d)\n", sc
->sc_if
.if_unit
, ilen
);
886 sc
->sc_if
.if_ierrors
++;
887 sc
->sc_stats
.ppp_ierrors
++;
888 sc
->sc_flags
|= SC_PKTLOST
;
895 * Remove FCS trailer. Somewhat painful...
898 if (--sc
->sc_mc
->m_len
== 0) {
899 for (m
= sc
->sc_m
; m
->m_next
!= sc
->sc_mc
; m
= m
->m_next
)
905 /* excise this mbuf chain */
907 sc
->sc_m
= sc
->sc_mc
->m_next
;
908 sc
->sc_mc
->m_next
= NULL
;
910 ppppktin(sc
, m
, sc
->sc_flags
& SC_PKTLOST
);
911 if (sc
->sc_flags
& SC_PKTLOST
) {
913 sc
->sc_flags
&= ~SC_PKTLOST
;
921 if (sc
->sc_flags
& SC_FLUSH
) {
922 if (sc
->sc_flags
& SC_LOG_FLUSH
)
927 if (c
< 0x20 && (sc
->sc_rasyncmap
& (1 << c
)))
931 if (sc
->sc_flags
& SC_ESCAPED
) {
932 sc
->sc_flags
&= ~SC_ESCAPED
;
934 } else if (c
== PPP_ESCAPE
) {
935 sc
->sc_flags
|= SC_ESCAPED
;
942 * Initialize buffer on first octet received.
943 * First octet could be address or protocol (when compressing
945 * Second octet is control.
946 * Third octet is first or second (when compressing protocol)
948 * Fourth octet is second octet of protocol.
950 if (sc
->sc_ilen
== 0) {
951 /* reset the first input mbuf */
952 if (sc
->sc_m
== NULL
) {
954 if (sc
->sc_m
== NULL
) {
955 if (sc
->sc_flags
& SC_DEBUG
)
956 printf("ppp%d: no input mbufs!\n", sc
->sc_if
.if_unit
);
962 m
->m_data
= M_DATASTART(sc
->sc_m
);
964 sc
->sc_mp
= mtod(m
, char *);
965 sc
->sc_fcs
= PPP_INITFCS
;
966 if (c
!= PPP_ALLSTATIONS
) {
967 if (sc
->sc_flags
& SC_REJ_COMP_AC
) {
968 if (sc
->sc_flags
& SC_DEBUG
)
969 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
970 sc
->sc_if
.if_unit
, c
);
973 *sc
->sc_mp
++ = PPP_ALLSTATIONS
;
974 *sc
->sc_mp
++ = PPP_UI
;
979 if (sc
->sc_ilen
== 1 && c
!= PPP_UI
) {
980 if (sc
->sc_flags
& SC_DEBUG
)
981 printf("ppp%d: missing UI (0x3), got 0x%x\n",
982 sc
->sc_if
.if_unit
, c
);
985 if (sc
->sc_ilen
== 2 && (c
& 1) == 1) {
986 /* a compressed protocol */
991 if (sc
->sc_ilen
== 3 && (c
& 1) == 0) {
992 if (sc
->sc_flags
& SC_DEBUG
)
993 printf("ppp%d: bad protocol %x\n", sc
->sc_if
.if_unit
,
994 (sc
->sc_mp
[-1] << 8) + c
);
998 /* packet beyond configured mru? */
999 if (++sc
->sc_ilen
> sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
) {
1000 if (sc
->sc_flags
& SC_DEBUG
)
1001 printf("ppp%d: packet too big\n", sc
->sc_if
.if_unit
);
1005 /* is this mbuf full? */
1007 if (M_TRAILINGSPACE(m
) <= 0) {
1008 if (m
->m_next
== NULL
) {
1010 if (m
->m_next
== NULL
) {
1011 if (sc
->sc_flags
& SC_DEBUG
)
1012 printf("ppp%d: too few input mbufs!\n", sc
->sc_if
.if_unit
);
1016 sc
->sc_mc
= m
= m
->m_next
;
1018 m
->m_data
= M_DATASTART(m
);
1019 sc
->sc_mp
= mtod(m
, char *);
1024 sc
->sc_fcs
= PPP_FCS(sc
->sc_fcs
, c
);
1028 if (!(sc
->sc_flags
& SC_FLUSH
)) {
1030 sc
->sc_if
.if_ierrors
++;
1031 sc
->sc_stats
.ppp_ierrors
++;
1032 sc
->sc_flags
|= SC_FLUSH
;
1034 if (sc
->sc_flags
& SC_LOG_FLUSH
)
1040 #define MAX_DUMP_BYTES 128
1044 struct ppp_softc
*sc
;
1048 sc
->sc_rawin
[sc
->sc_rawin_count
++] = c
;
1049 if (sc
->sc_rawin_count
>= sizeof(sc
->sc_rawin
)
1050 || (c
< 0 && sc
->sc_rawin_count
> 0)) {
1051 printf("ppp%d input: ", sc
->sc_if
.if_unit
);
1052 pppdumpb(sc
->sc_rawin
, sc
->sc_rawin_count
);
1053 sc
->sc_rawin_count
= 0;
1062 char buf
[3*MAX_DUMP_BYTES
+4];
1064 static char digits
[] = "0123456789abcdef";
1067 if (bp
>= buf
+ sizeof(buf
) - 3) {
1071 *bp
++ = digits
[*b
>> 4]; /* convert byte to ascii hex */
1072 *bp
++ = digits
[*b
++ & 0xf];
1077 printf("%s\n", buf
);
1080 #endif /* NPPP > 0 */