1 /* $Id: ppp_tty.c,v 1.4 1997/04/30 05:47:38 paulus Exp $ */
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 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
76 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
84 #include <sys/param.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>
95 #include <sys/systm.h>
98 #include <net/if_types.h>
101 #include <netinet/in.h>
102 #include <netinet/in_systm.h>
103 #include <netinet/ip.h>
104 #include <net/slcompress.h>
110 #include <net/ppp_defs.h>
111 #include <net/if_ppp.h>
112 #include <net/if_pppvar.h>
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
, u_long cmd
, caddr_t data
, int flag
,
120 int pppinput
__P((int c
, struct tty
*tp
));
121 int pppstart
__P((struct tty
*tp
, int));
123 static u_int16_t pppfcs
__P((u_int16_t 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 NetBSD-1.0 or later kernel. */
155 #define CCOUNT(q) ((q)->c_cc)
157 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
158 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
161 * Line specific open routine for async tty devices.
162 * Attach the given tty to the first available ppp unit.
163 * Called from device open routine or ttioctl.
169 register struct tty
*tp
;
171 struct proc
*p
= curproc
; /* XXX */
172 register struct ppp_softc
*sc
;
175 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
180 if (tp
->t_line
== PPPDISC
) {
181 sc
= (struct ppp_softc
*) tp
->t_sc
;
182 if (sc
!= NULL
&& sc
->sc_devp
== (void *) tp
) {
188 if ((sc
= pppalloc(p
->p_pid
)) == NULL
) {
194 (*sc
->sc_relinq
)(sc
); /* get previous owner to relinquish the unit */
198 bzero(sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
199 sc
->sc_asyncmap
[0] = 0xffffffff;
200 sc
->sc_asyncmap
[3] = 0x60000000;
201 sc
->sc_rasyncmap
= 0;
202 sc
->sc_devp
= (void *) tp
;
203 sc
->sc_start
= pppasyncstart
;
204 sc
->sc_ctlp
= pppasyncctlp
;
205 sc
->sc_relinq
= pppasyncrelinq
;
208 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
209 sc
->sc_if
.if_baudrate
= tp
->t_ospeed
;
211 tp
->t_sc
= (caddr_t
) sc
;
212 ttyflush(tp
, FREAD
| FWRITE
);
219 * Line specific close routine, called from device close routine
221 * Detach the tty from the ppp unit.
222 * Mimics part of ttyclose().
229 register struct ppp_softc
*sc
;
233 ttyflush(tp
, FREAD
|FWRITE
);
235 sc
= (struct ppp_softc
*) tp
->t_sc
;
238 if (tp
== (struct tty
*) sc
->sc_devp
) {
248 * Relinquish the interface unit to another device.
252 struct ppp_softc
*sc
;
258 m_freem(sc
->sc_outm
);
265 if (sc
->sc_flags
& SC_TIMEOUT
) {
266 untimeout(ppp_timeout
, (void *) sc
);
267 sc
->sc_flags
&= ~SC_TIMEOUT
;
273 * Line specific (tty) read routine.
276 pppread(tp
, uio
, flag
)
277 register struct tty
*tp
;
281 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
289 * Loop waiting for input, checking that nothing disasterous
290 * happens in the meantime.
294 if (tp
!= (struct tty
*) sc
->sc_devp
|| tp
->t_line
!= PPPDISC
) {
298 if (sc
->sc_inq
.ifq_head
!= NULL
)
300 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0
301 && (tp
->t_state
& TS_ISOPEN
)) {
303 return 0; /* end of file */
305 if (tp
->t_state
& TS_ASYNC
|| flag
& IO_NDELAY
) {
307 return (EWOULDBLOCK
);
309 error
= ttysleep(tp
, (caddr_t
)&tp
->t_rawq
, TTIPRI
|PCATCH
, ttyin
, 0);
316 /* Pull place-holder byte out of canonical queue */
319 /* Get the packet from the input queue */
320 IF_DEQUEUE(&sc
->sc_inq
, m0
);
323 for (m
= m0
; m
&& uio
->uio_resid
; m
= m
->m_next
)
324 if ((error
= uiomove(mtod(m
, u_char
*), m
->m_len
, uio
)) != 0)
331 * Line specific (tty) write routine.
334 pppwrite(tp
, uio
, flag
)
335 register struct tty
*tp
;
339 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
340 struct mbuf
*m
, *m0
, **mp
;
344 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
345 return 0; /* wrote 0 bytes */
346 if (tp
->t_line
!= PPPDISC
)
348 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
350 if (uio
->uio_resid
> sc
->sc_if
.if_mtu
+ PPP_HDRLEN
||
351 uio
->uio_resid
< PPP_HDRLEN
)
353 for (mp
= &m0
; uio
->uio_resid
; mp
= &m
->m_next
) {
354 MGET(m
, M_WAIT
, MT_DATA
);
355 if ((*mp
= m
) == NULL
) {
360 if (uio
->uio_resid
>= MCLBYTES
/ 2)
361 MCLGET(m
, M_DONTWAIT
);
362 len
= M_TRAILINGSPACE(m
);
363 if (len
> uio
->uio_resid
)
364 len
= uio
->uio_resid
;
365 if ((error
= uiomove(mtod(m
, u_char
*), len
, uio
)) != 0) {
371 dst
.sa_family
= AF_UNSPEC
;
372 bcopy(mtod(m0
, u_char
*), dst
.sa_data
, PPP_HDRLEN
);
373 m0
->m_data
+= PPP_HDRLEN
;
374 m0
->m_len
-= PPP_HDRLEN
;
375 return (pppoutput(&sc
->sc_if
, m0
, &dst
, (struct rtentry
*)0));
379 * Line specific (tty) ioctl routine.
380 * This discipline requires that tty device drivers call
381 * the line specific l_ioctl routine from their ioctl routines.
385 ppptioctl(tp
, cmd
, data
, flag
, p
)
392 struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
395 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
400 case PPPIOCSASYNCMAP
:
401 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
403 sc
->sc_asyncmap
[0] = *(u_int
*)data
;
406 case PPPIOCGASYNCMAP
:
407 *(u_int
*)data
= sc
->sc_asyncmap
[0];
410 case PPPIOCSRASYNCMAP
:
411 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
413 sc
->sc_rasyncmap
= *(u_int
*)data
;
416 case PPPIOCGRASYNCMAP
:
417 *(u_int
*)data
= sc
->sc_rasyncmap
;
420 case PPPIOCSXASYNCMAP
:
421 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
424 bcopy(data
, sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
425 sc
->sc_asyncmap
[1] = 0; /* mustn't escape 0x20 - 0x3f */
426 sc
->sc_asyncmap
[2] &= ~0x40000000; /* mustn't escape 0x5e */
427 sc
->sc_asyncmap
[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
431 case PPPIOCGXASYNCMAP
:
432 bcopy(sc
->sc_asyncmap
, data
, sizeof(sc
->sc_asyncmap
));
436 error
= pppioctl(sc
, cmd
, data
, flag
, p
);
437 if (error
== 0 && cmd
== PPPIOCSMRU
)
445 * FCS lookup table as calculated by genfcstab.
447 static u_int16_t fcstab
[256] = {
448 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
449 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
450 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
451 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
452 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
453 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
454 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
455 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
456 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
457 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
458 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
459 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
460 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
461 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
462 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
463 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
464 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
465 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
466 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
467 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
468 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
469 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
470 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
471 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
472 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
473 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
474 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
475 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
476 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
477 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
478 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
479 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
483 * Calculate a new FCS given the current FCS and the new data.
487 register u_int16_t fcs
;
492 fcs
= PPP_FCS(fcs
, *cp
++);
497 * This gets called at splsoftnet from if_ppp.c at various times
498 * when there is data ready to be sent.
502 register struct ppp_softc
*sc
;
504 register struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
505 register struct mbuf
*m
;
507 register u_char
*start
, *stop
, *cp
;
508 int n
, ndone
, done
, idle
;
513 while (CCOUNT(&tp
->t_outq
) < PPP_HIWAT
) {
515 * See if we have an existing packet partly sent.
516 * If not, get a new packet and start sending it.
521 * Get another packet to be sent.
530 * The extra PPP_FLAG will start up a new packet, and thus
531 * will flush any accumulated garbage. We do this whenever
532 * the line may have been idle for some time.
534 if (CCOUNT(&tp
->t_outq
) == 0) {
535 ++sc
->sc_stats
.ppp_obytes
;
536 (void) putc(PPP_FLAG
, &tp
->t_outq
);
539 /* Calculate the FCS for the first mbuf's worth. */
540 sc
->sc_outfcs
= pppfcs(PPP_INITFCS
, mtod(m
, u_char
*), m
->m_len
);
541 sc
->sc_if
.if_lastchange
= time
;
545 start
= mtod(m
, u_char
*);
550 * Find out how many bytes in the string we can
551 * handle without doing something special.
553 for (cp
= start
; cp
< stop
; cp
++)
558 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
559 ndone
= n
- b_to_q(start
, n
, &tp
->t_outq
);
562 sc
->sc_stats
.ppp_obytes
+= ndone
;
565 break; /* packet doesn't fit */
568 * If there are characters left in the mbuf,
569 * the first one must be special.
570 * Put it out in a different form.
574 if (putc(PPP_ESCAPE
, &tp
->t_outq
)) {
578 if (putc(*start
^ PPP_TRANS
, &tp
->t_outq
)) {
579 (void) unputc(&tp
->t_outq
);
584 sc
->sc_stats
.ppp_obytes
+= 2;
591 * If we didn't empty this mbuf, remember where we're up to.
592 * If we emptied the last mbuf, try to add the FCS and closing
593 * flag, and if we can't, leave sc_outm pointing to m, but with
594 * m->m_len == 0, to remind us to output the FCS and flag later.
597 if (done
&& m
->m_next
== NULL
) {
603 * We may have to escape the bytes in the FCS.
606 c
= ~sc
->sc_outfcs
& 0xFF;
609 *p
++ = c
^ PPP_TRANS
;
612 c
= (~sc
->sc_outfcs
>> 8) & 0xFF;
615 *p
++ = c
^ PPP_TRANS
;
621 * Try to output the FCS and flag. If the bytes
622 * don't all fit, back out.
625 for (q
= endseq
; q
< p
; ++q
)
626 if (putc(*q
, &tp
->t_outq
)) {
628 for (; q
> endseq
; --q
)
634 sc
->sc_stats
.ppp_obytes
+= q
- endseq
;
638 /* remember where we got to */
644 /* Finished with this mbuf; free it and move on. */
648 /* Finished a packet */
651 sc
->sc_outfcs
= pppfcs(sc
->sc_outfcs
, mtod(m
, u_char
*), m
->m_len
);
655 * If m == NULL, we have finished a packet.
656 * If m != NULL, we've either done as much work this time
657 * as we need to, or else we've filled up the output queue.
664 /* Call pppstart to start output again if necessary. */
669 * This timeout is needed for operation on a pseudo-tty,
670 * because the pty code doesn't call pppstart after it has
671 * drained the t_outq.
673 if (!idle
&& (sc
->sc_flags
& SC_TIMEOUT
) == 0) {
674 timeout(ppp_timeout
, (void *) sc
, 1);
675 sc
->sc_flags
|= SC_TIMEOUT
;
682 * This gets called when a received packet is placed on
683 * the inq, at splsoftnet.
687 struct ppp_softc
*sc
;
692 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
694 tp
= (struct tty
*) sc
->sc_devp
;
695 putc(0, &tp
->t_canq
);
701 * Start output on async tty interface. If the transmit queue
702 * has drained sufficiently, arrange for pppasyncstart to be
703 * called later at splsoftnet.
704 * Called at spltty or higher.
708 register struct tty
*tp
;
711 register struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
714 * If there is stuff in the output queue, send it now.
715 * We are being called in lieu of ttstart and must do what it would.
717 if (tp
->t_oproc
!= NULL
)
721 * If the transmit queue has drained and the tty has not hung up
722 * or been disconnected from the ppp unit, then tell if_ppp.c that
723 * we need more output.
725 if (CCOUNT(&tp
->t_outq
) >= PPP_LOWAT
&& !force
)
727 if (!((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
728 && sc
!= NULL
&& tp
== (struct tty
*) sc
->sc_devp
) {
736 * Timeout routine - try to start some more output.
742 struct ppp_softc
*sc
= (struct ppp_softc
*) x
;
743 struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
747 sc
->sc_flags
&= ~SC_TIMEOUT
;
753 * Allocate enough mbuf to handle current MRU.
757 register struct ppp_softc
*sc
;
759 struct mbuf
*m
, **mp
;
763 for (len
= sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
; len
> 0; ){
764 if ((m
= *mp
) == NULL
) {
765 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
769 MCLGET(m
, M_DONTWAIT
);
771 len
-= M_DATASIZE(m
);
777 * tty interface receiver interrupt.
779 static unsigned paritytab
[8] = {
780 0x96696996, 0x69969669, 0x69969669, 0x96696996,
781 0x69969669, 0x96696996, 0x96696996, 0x69969669
787 register struct tty
*tp
;
789 register struct ppp_softc
*sc
;
793 sc
= (struct ppp_softc
*) tp
->t_sc
;
794 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
798 ++sc
->sc_stats
.ppp_ibytes
;
801 /* framing error or overrun on this char - abort packet */
802 if (sc
->sc_flags
& SC_DEBUG
)
803 printf("ppp%d: bad char %x\n", sc
->sc_if
.if_unit
, c
);
810 * Handle software flow control of output.
812 if (tp
->t_iflag
& IXON
) {
813 if (c
== tp
->t_cc
[VSTOP
] && tp
->t_cc
[VSTOP
] != _POSIX_VDISABLE
) {
814 if ((tp
->t_state
& TS_TTSTOP
) == 0) {
815 tp
->t_state
|= TS_TTSTOP
;
816 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
820 if (c
== tp
->t_cc
[VSTART
] && tp
->t_cc
[VSTART
] != _POSIX_VDISABLE
) {
821 tp
->t_state
&= ~TS_TTSTOP
;
822 if (tp
->t_oproc
!= NULL
)
830 sc
->sc_flags
|= SC_RCV_B7_1
;
832 sc
->sc_flags
|= SC_RCV_B7_0
;
833 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
834 sc
->sc_flags
|= SC_RCV_ODDP
;
836 sc
->sc_flags
|= SC_RCV_EVNP
;
839 if (sc
->sc_flags
& SC_LOG_RAWIN
)
846 if (sc
->sc_rawin_count
> 0)
850 * If SC_ESCAPED is set, then we've seen the packet
851 * abort sequence "}~".
853 if (sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)
854 || (ilen
> 0 && sc
->sc_fcs
!= PPP_GOODFCS
)) {
856 sc
->sc_flags
|= SC_PKTLOST
; /* note the dropped packet */
857 if ((sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)) == 0){
858 if (sc
->sc_flags
& SC_DEBUG
)
859 printf("ppp%d: bad fcs %x, pkt len %d\n",
860 sc
->sc_if
.if_unit
, sc
->sc_fcs
, ilen
);
861 sc
->sc_if
.if_ierrors
++;
862 sc
->sc_stats
.ppp_ierrors
++;
864 sc
->sc_flags
&= ~(SC_FLUSH
| SC_ESCAPED
);
869 if (ilen
< PPP_HDRLEN
+ PPP_FCSLEN
) {
871 if (sc
->sc_flags
& SC_DEBUG
)
872 printf("ppp%d: too short (%d)\n", sc
->sc_if
.if_unit
, ilen
);
874 sc
->sc_if
.if_ierrors
++;
875 sc
->sc_stats
.ppp_ierrors
++;
876 sc
->sc_flags
|= SC_PKTLOST
;
883 * Remove FCS trailer. Somewhat painful...
886 if (--sc
->sc_mc
->m_len
== 0) {
887 for (m
= sc
->sc_m
; m
->m_next
!= sc
->sc_mc
; m
= m
->m_next
)
893 /* excise this mbuf chain */
895 sc
->sc_m
= sc
->sc_mc
->m_next
;
896 sc
->sc_mc
->m_next
= NULL
;
898 ppppktin(sc
, m
, sc
->sc_flags
& SC_PKTLOST
);
899 if (sc
->sc_flags
& SC_PKTLOST
) {
901 sc
->sc_flags
&= ~SC_PKTLOST
;
909 if (sc
->sc_flags
& SC_FLUSH
) {
910 if (sc
->sc_flags
& SC_LOG_FLUSH
)
915 if (c
< 0x20 && (sc
->sc_rasyncmap
& (1 << c
)))
919 if (sc
->sc_flags
& SC_ESCAPED
) {
920 sc
->sc_flags
&= ~SC_ESCAPED
;
922 } else if (c
== PPP_ESCAPE
) {
923 sc
->sc_flags
|= SC_ESCAPED
;
930 * Initialize buffer on first octet received.
931 * First octet could be address or protocol (when compressing
933 * Second octet is control.
934 * Third octet is first or second (when compressing protocol)
936 * Fourth octet is second octet of protocol.
938 if (sc
->sc_ilen
== 0) {
939 /* reset the first input mbuf */
940 if (sc
->sc_m
== NULL
) {
942 if (sc
->sc_m
== NULL
) {
943 if (sc
->sc_flags
& SC_DEBUG
)
944 printf("ppp%d: no input mbufs!\n", sc
->sc_if
.if_unit
);
950 m
->m_data
= M_DATASTART(sc
->sc_m
);
952 sc
->sc_mp
= mtod(m
, char *);
953 sc
->sc_fcs
= PPP_INITFCS
;
954 if (c
!= PPP_ALLSTATIONS
) {
955 if (sc
->sc_flags
& SC_REJ_COMP_AC
) {
956 if (sc
->sc_flags
& SC_DEBUG
)
957 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
958 sc
->sc_if
.if_unit
, c
);
961 *sc
->sc_mp
++ = PPP_ALLSTATIONS
;
962 *sc
->sc_mp
++ = PPP_UI
;
967 if (sc
->sc_ilen
== 1 && c
!= PPP_UI
) {
968 if (sc
->sc_flags
& SC_DEBUG
)
969 printf("ppp%d: missing UI (0x3), got 0x%x\n",
970 sc
->sc_if
.if_unit
, c
);
973 if (sc
->sc_ilen
== 2 && (c
& 1) == 1) {
974 /* a compressed protocol */
979 if (sc
->sc_ilen
== 3 && (c
& 1) == 0) {
980 if (sc
->sc_flags
& SC_DEBUG
)
981 printf("ppp%d: bad protocol %x\n", sc
->sc_if
.if_unit
,
982 (sc
->sc_mp
[-1] << 8) + c
);
986 /* packet beyond configured mru? */
987 if (++sc
->sc_ilen
> sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
) {
988 if (sc
->sc_flags
& SC_DEBUG
)
989 printf("ppp%d: packet too big\n", sc
->sc_if
.if_unit
);
993 /* is this mbuf full? */
995 if (M_TRAILINGSPACE(m
) <= 0) {
996 if (m
->m_next
== NULL
) {
998 if (m
->m_next
== NULL
) {
999 if (sc
->sc_flags
& SC_DEBUG
)
1000 printf("ppp%d: too few input mbufs!\n", sc
->sc_if
.if_unit
);
1004 sc
->sc_mc
= m
= m
->m_next
;
1006 m
->m_data
= M_DATASTART(m
);
1007 sc
->sc_mp
= mtod(m
, char *);
1012 sc
->sc_fcs
= PPP_FCS(sc
->sc_fcs
, c
);
1016 if (!(sc
->sc_flags
& SC_FLUSH
)) {
1018 sc
->sc_if
.if_ierrors
++;
1019 sc
->sc_stats
.ppp_ierrors
++;
1020 sc
->sc_flags
|= SC_FLUSH
;
1022 if (sc
->sc_flags
& SC_LOG_FLUSH
)
1028 #define MAX_DUMP_BYTES 128
1032 struct ppp_softc
*sc
;
1036 sc
->sc_rawin
[sc
->sc_rawin_count
++] = c
;
1037 if (sc
->sc_rawin_count
>= sizeof(sc
->sc_rawin
)
1038 || (c
< 0 && sc
->sc_rawin_count
> 0)) {
1039 printf("ppp%d input: ", sc
->sc_if
.if_unit
);
1040 pppdumpb(sc
->sc_rawin
, sc
->sc_rawin_count
);
1041 sc
->sc_rawin_count
= 0;
1050 char buf
[3*MAX_DUMP_BYTES
+4];
1052 static char digits
[] = "0123456789abcdef";
1055 if (bp
>= buf
+ sizeof(buf
) - 3) {
1059 *bp
++ = digits
[*b
>> 4]; /* convert byte to ascii hex */
1060 *bp
++ = digits
[*b
++ & 0xf];
1065 printf("%s\n", buf
);
1068 #endif /* NPPP > 0 */