1 /* $NetBSD: ppp_tty.c,v 1.12 1997/03/24 21:23:10 christos Exp $ */
2 /* Id: ppp_tty.c,v 1.3 1996/07/01 01:04:11 paulus Exp */
5 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
8 * Copyright (c) 1989 Carnegie Mellon University.
11 * Redistribution and use in source and binary forms are permitted
12 * provided that the above copyright notice and this paragraph are
13 * duplicated in all such forms and that any documentation,
14 * advertising materials, and other materials related to such
15 * distribution and use acknowledge that the software was developed
16 * by Carnegie Mellon University. The name of the
17 * University may not be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 * Carnegie Mellon University
26 * Pittsburgh, PA 15213
31 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
33 * Copyright (c) 1987 Regents of the University of California.
34 * All rights reserved.
36 * Redistribution and use in source and binary forms are permitted
37 * provided that the above copyright notice and this paragraph are
38 * duplicated in all such forms and that any documentation,
39 * advertising materials, and other materials related to such
40 * distribution and use acknowledge that the software was developed
41 * by the University of California, Berkeley. The name of the
42 * University may not be used to endorse or promote products derived
43 * from this software without specific prior written permission.
44 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
46 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
48 * Serial Line interface
51 * Center for Seismic Studies
52 * 1300 N 17th Street, Suite 1450
53 * Arlington, Virginia 22209
58 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
59 * Converted to 4.3BSD Beta by Chris Torek.
60 * Other changes made at Berkeley, based in part on code by Kirk Smith.
62 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
63 * Added VJ tcp header compression; more unified ioctls
65 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
66 * Cleaned up a lot of the mbuf-related code to fix bugs that
67 * caused system crashes and packet corruption. Changed pppstart
68 * so that it doesn't just give up with a "collision" if the whole
69 * packet doesn't fit in the output ring buffer.
71 * Added priority queueing for interactive IP packets, following
72 * the model of if_sl.c, plus hooks for bpf.
73 * Paul Mackerras (paulus@cs.anu.edu.au).
76 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
77 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
85 #include <sys/param.h>
88 #include <sys/dkstat.h>
89 #include <sys/socket.h>
90 #include <sys/ioctl.h>
93 #include <sys/kernel.h>
95 #include <sys/vnode.h>
96 #include <sys/systm.h>
99 #include <net/if_types.h>
102 #include <netinet/in.h>
103 #include <netinet/in_systm.h>
104 #include <netinet/ip.h>
105 #include <net/slcompress.h>
111 #include <net/ppp_defs.h>
112 #include <net/if_ppp.h>
113 #include <net/if_pppvar.h>
115 int pppopen
__P((dev_t dev
, struct tty
*tp
));
116 int pppclose
__P((struct tty
*tp
, int flag
));
117 int pppread
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
118 int pppwrite
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
119 int ppptioctl
__P((struct tty
*tp
, u_long cmd
, caddr_t data
, int flag
,
121 int pppinput
__P((int c
, struct tty
*tp
));
122 int pppstart
__P((struct tty
*tp
, int));
124 static u_int16_t pppfcs
__P((u_int16_t fcs
, u_char
*cp
, int len
));
125 static void pppasyncstart
__P((struct ppp_softc
*));
126 static void pppasyncctlp
__P((struct ppp_softc
*));
127 static void pppasyncrelinq
__P((struct ppp_softc
*));
128 static void ppp_timeout
__P((void *));
129 static void pppgetm
__P((struct ppp_softc
*sc
));
130 static void pppdumpb
__P((u_char
*b
, int l
));
131 static void ppplogchar
__P((struct ppp_softc
*, int));
134 * Some useful mbuf macros not in mbuf.h.
136 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
138 #define M_DATASTART(m) \
139 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
140 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
142 #define M_DATASIZE(m) \
143 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
144 (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
147 * Does c need to be escaped?
149 #define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
152 * Procedures for using an async tty interface for PPP.
155 /* This is a NetBSD-1.0 or later kernel. */
156 #define CCOUNT(q) ((q)->c_cc)
158 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
159 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
162 * Line specific open routine for async tty devices.
163 * Attach the given tty to the first available ppp unit.
164 * Called from device open routine or ttioctl.
170 register struct tty
*tp
;
172 struct proc
*p
= curproc
; /* XXX */
173 register struct ppp_softc
*sc
;
176 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
181 if (tp
->t_line
== PPPDISC
) {
182 sc
= (struct ppp_softc
*) tp
->t_sc
;
183 if (sc
!= NULL
&& sc
->sc_devp
== (void *) tp
) {
189 if ((sc
= pppalloc(p
->p_pid
)) == NULL
) {
195 (*sc
->sc_relinq
)(sc
); /* get previous owner to relinquish the unit */
199 bzero(sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
200 sc
->sc_asyncmap
[0] = 0xffffffff;
201 sc
->sc_asyncmap
[3] = 0x60000000;
202 sc
->sc_rasyncmap
= 0;
203 sc
->sc_devp
= (void *) tp
;
204 sc
->sc_start
= pppasyncstart
;
205 sc
->sc_ctlp
= pppasyncctlp
;
206 sc
->sc_relinq
= pppasyncrelinq
;
209 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
210 sc
->sc_if
.if_baudrate
= tp
->t_ospeed
;
212 tp
->t_sc
= (caddr_t
) sc
;
213 ttyflush(tp
, FREAD
| FWRITE
);
220 * Line specific close routine, called from device close routine
222 * Detach the tty from the ppp unit.
223 * Mimics part of ttyclose().
230 register struct ppp_softc
*sc
;
234 ttyflush(tp
, FREAD
|FWRITE
);
236 sc
= (struct ppp_softc
*) tp
->t_sc
;
239 if (tp
== (struct tty
*) sc
->sc_devp
) {
249 * Relinquish the interface unit to another device.
253 struct ppp_softc
*sc
;
259 m_freem(sc
->sc_outm
);
266 if (sc
->sc_flags
& SC_TIMEOUT
) {
267 untimeout(ppp_timeout
, (void *) sc
);
268 sc
->sc_flags
&= ~SC_TIMEOUT
;
274 * Line specific (tty) read routine.
277 pppread(tp
, uio
, flag
)
278 register struct tty
*tp
;
282 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
290 * Loop waiting for input, checking that nothing disasterous
291 * happens in the meantime.
295 if (tp
!= (struct tty
*) sc
->sc_devp
|| tp
->t_line
!= PPPDISC
) {
299 if (sc
->sc_inq
.ifq_head
!= NULL
)
301 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0
302 && (tp
->t_state
& TS_ISOPEN
)) {
304 return 0; /* end of file */
306 if (tp
->t_state
& TS_ASYNC
|| flag
& IO_NDELAY
) {
308 return (EWOULDBLOCK
);
310 error
= ttysleep(tp
, (caddr_t
)&tp
->t_rawq
, TTIPRI
|PCATCH
, ttyin
, 0);
317 /* Pull place-holder byte out of canonical queue */
320 /* Get the packet from the input queue */
321 IF_DEQUEUE(&sc
->sc_inq
, m0
);
324 for (m
= m0
; m
&& uio
->uio_resid
; m
= m
->m_next
)
325 if ((error
= uiomove(mtod(m
, u_char
*), m
->m_len
, uio
)) != 0)
332 * Line specific (tty) write routine.
335 pppwrite(tp
, uio
, flag
)
336 register struct tty
*tp
;
340 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
341 struct mbuf
*m
, *m0
, **mp
;
345 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
346 return 0; /* wrote 0 bytes */
347 if (tp
->t_line
!= PPPDISC
)
349 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
351 if (uio
->uio_resid
> sc
->sc_if
.if_mtu
+ PPP_HDRLEN
||
352 uio
->uio_resid
< PPP_HDRLEN
)
354 for (mp
= &m0
; uio
->uio_resid
; mp
= &m
->m_next
) {
355 MGET(m
, M_WAIT
, MT_DATA
);
356 if ((*mp
= m
) == NULL
) {
361 if (uio
->uio_resid
>= MCLBYTES
/ 2)
362 MCLGET(m
, M_DONTWAIT
);
363 len
= M_TRAILINGSPACE(m
);
364 if (len
> uio
->uio_resid
)
365 len
= uio
->uio_resid
;
366 if ((error
= uiomove(mtod(m
, u_char
*), len
, uio
)) != 0) {
372 dst
.sa_family
= AF_UNSPEC
;
373 bcopy(mtod(m0
, u_char
*), dst
.sa_data
, PPP_HDRLEN
);
374 m0
->m_data
+= PPP_HDRLEN
;
375 m0
->m_len
-= PPP_HDRLEN
;
376 return ((*sc
->sc_if
.if_output
)(&sc
->sc_if
, m0
, &dst
, (struct rtentry
*)0));
380 * Line specific (tty) ioctl routine.
381 * This discipline requires that tty device drivers call
382 * the line specific l_ioctl routine from their ioctl routines.
386 ppptioctl(tp
, cmd
, data
, flag
, p
)
393 struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
396 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
401 case PPPIOCSASYNCMAP
:
402 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
404 sc
->sc_asyncmap
[0] = *(u_int
*)data
;
407 case PPPIOCGASYNCMAP
:
408 *(u_int
*)data
= sc
->sc_asyncmap
[0];
411 case PPPIOCSRASYNCMAP
:
412 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
414 sc
->sc_rasyncmap
= *(u_int
*)data
;
417 case PPPIOCGRASYNCMAP
:
418 *(u_int
*)data
= sc
->sc_rasyncmap
;
421 case PPPIOCSXASYNCMAP
:
422 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
425 bcopy(data
, sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
426 sc
->sc_asyncmap
[1] = 0; /* mustn't escape 0x20 - 0x3f */
427 sc
->sc_asyncmap
[2] &= ~0x40000000; /* mustn't escape 0x5e */
428 sc
->sc_asyncmap
[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
432 case PPPIOCGXASYNCMAP
:
433 bcopy(sc
->sc_asyncmap
, data
, sizeof(sc
->sc_asyncmap
));
437 error
= pppioctl(sc
, cmd
, data
, flag
, p
);
438 if (error
== 0 && cmd
== PPPIOCSMRU
)
446 * FCS lookup table as calculated by genfcstab.
448 static u_int16_t fcstab
[256] = {
449 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
450 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
451 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
452 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
453 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
454 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
455 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
456 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
457 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
458 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
459 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
460 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
461 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
462 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
463 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
464 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
465 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
466 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
467 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
468 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
469 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
470 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
471 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
472 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
473 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
474 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
475 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
476 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
477 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
478 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
479 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
480 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
484 * Calculate a new FCS given the current FCS and the new data.
488 register u_int16_t fcs
;
493 fcs
= PPP_FCS(fcs
, *cp
++);
498 * This gets called at splsoftnet from if_ppp.c at various times
499 * when there is data ready to be sent.
503 register struct ppp_softc
*sc
;
505 register struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
506 register struct mbuf
*m
;
508 register u_char
*start
, *stop
, *cp
;
509 int n
, ndone
, done
, idle
;
514 while (CCOUNT(&tp
->t_outq
) < PPP_HIWAT
) {
516 * See if we have an existing packet partly sent.
517 * If not, get a new packet and start sending it.
522 * Get another packet to be sent.
531 * The extra PPP_FLAG will start up a new packet, and thus
532 * will flush any accumulated garbage. We do this whenever
533 * the line may have been idle for some time.
535 if (CCOUNT(&tp
->t_outq
) == 0) {
536 ++sc
->sc_stats
.ppp_obytes
;
537 (void) putc(PPP_FLAG
, &tp
->t_outq
);
540 /* Calculate the FCS for the first mbuf's worth. */
541 sc
->sc_outfcs
= pppfcs(PPP_INITFCS
, mtod(m
, u_char
*), m
->m_len
);
542 sc
->sc_if
.if_lastchange
= time
;
546 start
= mtod(m
, u_char
*);
551 * Find out how many bytes in the string we can
552 * handle without doing something special.
554 for (cp
= start
; cp
< stop
; cp
++)
559 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
560 ndone
= n
- b_to_q(start
, n
, &tp
->t_outq
);
563 sc
->sc_stats
.ppp_obytes
+= ndone
;
566 break; /* packet doesn't fit */
569 * If there are characters left in the mbuf,
570 * the first one must be special.
571 * Put it out in a different form.
575 if (putc(PPP_ESCAPE
, &tp
->t_outq
)) {
579 if (putc(*start
^ PPP_TRANS
, &tp
->t_outq
)) {
580 (void) unputc(&tp
->t_outq
);
585 sc
->sc_stats
.ppp_obytes
+= 2;
592 * If we didn't empty this mbuf, remember where we're up to.
593 * If we emptied the last mbuf, try to add the FCS and closing
594 * flag, and if we can't, leave sc_outm pointing to m, but with
595 * m->m_len == 0, to remind us to output the FCS and flag later.
598 if (done
&& m
->m_next
== NULL
) {
604 * We may have to escape the bytes in the FCS.
607 c
= ~sc
->sc_outfcs
& 0xFF;
610 *p
++ = c
^ PPP_TRANS
;
613 c
= (~sc
->sc_outfcs
>> 8) & 0xFF;
616 *p
++ = c
^ PPP_TRANS
;
622 * Try to output the FCS and flag. If the bytes
623 * don't all fit, back out.
626 for (q
= endseq
; q
< p
; ++q
)
627 if (putc(*q
, &tp
->t_outq
)) {
629 for (; q
> endseq
; --q
)
635 sc
->sc_stats
.ppp_obytes
+= q
- endseq
;
639 /* remember where we got to */
645 /* Finished with this mbuf; free it and move on. */
649 /* Finished a packet */
652 sc
->sc_outfcs
= pppfcs(sc
->sc_outfcs
, mtod(m
, u_char
*), m
->m_len
);
656 * If m == NULL, we have finished a packet.
657 * If m != NULL, we've either done as much work this time
658 * as we need to, or else we've filled up the output queue.
665 /* Call pppstart to start output again if necessary. */
670 * This timeout is needed for operation on a pseudo-tty,
671 * because the pty code doesn't call pppstart after it has
672 * drained the t_outq.
674 if (!idle
&& (sc
->sc_flags
& SC_TIMEOUT
) == 0) {
675 timeout(ppp_timeout
, (void *) sc
, 1);
676 sc
->sc_flags
|= SC_TIMEOUT
;
683 * This gets called when a received packet is placed on
684 * the inq, at splsoftnet.
688 struct ppp_softc
*sc
;
693 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
695 tp
= (struct tty
*) sc
->sc_devp
;
696 putc(0, &tp
->t_canq
);
702 * Start output on async tty interface. If the transmit queue
703 * has drained sufficiently, arrange for pppasyncstart to be
704 * called later at splsoftnet.
705 * Called at spltty or higher.
709 register struct tty
*tp
;
712 register struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
715 * If there is stuff in the output queue, send it now.
716 * We are being called in lieu of ttstart and must do what it would.
718 if (tp
->t_oproc
!= NULL
)
722 * If the transmit queue has drained and the tty has not hung up
723 * or been disconnected from the ppp unit, then tell if_ppp.c that
724 * we need more output.
726 if (CCOUNT(&tp
->t_outq
) >= PPP_LOWAT
&& !force
)
728 if (!((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
729 && sc
!= NULL
&& tp
== (struct tty
*) sc
->sc_devp
) {
737 * Timeout routine - try to start some more output.
743 struct ppp_softc
*sc
= (struct ppp_softc
*) x
;
744 struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
748 sc
->sc_flags
&= ~SC_TIMEOUT
;
754 * Allocate enough mbuf to handle current MRU.
758 register struct ppp_softc
*sc
;
760 struct mbuf
*m
, **mp
;
764 for (len
= sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
; len
> 0; ){
765 if ((m
= *mp
) == NULL
) {
766 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
770 MCLGET(m
, M_DONTWAIT
);
772 len
-= M_DATASIZE(m
);
778 * tty interface receiver interrupt.
780 static unsigned paritytab
[8] = {
781 0x96696996, 0x69969669, 0x69969669, 0x96696996,
782 0x69969669, 0x96696996, 0x96696996, 0x69969669
788 register struct tty
*tp
;
790 register struct ppp_softc
*sc
;
794 sc
= (struct ppp_softc
*) tp
->t_sc
;
795 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
799 ++sc
->sc_stats
.ppp_ibytes
;
802 /* framing error or overrun on this char - abort packet */
803 if (sc
->sc_flags
& SC_DEBUG
)
804 printf("%s: bad char %x\n", sc
->sc_if
.if_xname
, c
);
811 * Handle software flow control of output.
813 if (tp
->t_iflag
& IXON
) {
814 if (c
== tp
->t_cc
[VSTOP
] && tp
->t_cc
[VSTOP
] != _POSIX_VDISABLE
) {
815 if ((tp
->t_state
& TS_TTSTOP
) == 0) {
816 tp
->t_state
|= TS_TTSTOP
;
817 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
821 if (c
== tp
->t_cc
[VSTART
] && tp
->t_cc
[VSTART
] != _POSIX_VDISABLE
) {
822 tp
->t_state
&= ~TS_TTSTOP
;
823 if (tp
->t_oproc
!= NULL
)
831 sc
->sc_flags
|= SC_RCV_B7_1
;
833 sc
->sc_flags
|= SC_RCV_B7_0
;
834 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
835 sc
->sc_flags
|= SC_RCV_ODDP
;
837 sc
->sc_flags
|= SC_RCV_EVNP
;
840 if (sc
->sc_flags
& SC_LOG_RAWIN
)
847 if (sc
->sc_rawin_count
> 0)
851 * If SC_ESCAPED is set, then we've seen the packet
852 * abort sequence "}~".
854 if (sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)
855 || (ilen
> 0 && sc
->sc_fcs
!= PPP_GOODFCS
)) {
857 sc
->sc_flags
|= SC_PKTLOST
; /* note the dropped packet */
858 if ((sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)) == 0){
859 if (sc
->sc_flags
& SC_DEBUG
)
860 printf("%s: bad fcs %x\n", sc
->sc_if
.if_xname
,
862 sc
->sc_if
.if_ierrors
++;
863 sc
->sc_stats
.ppp_ierrors
++;
865 sc
->sc_flags
&= ~(SC_FLUSH
| SC_ESCAPED
);
870 if (ilen
< PPP_HDRLEN
+ PPP_FCSLEN
) {
872 if (sc
->sc_flags
& SC_DEBUG
)
873 printf("%s: too short (%d)\n", sc
->sc_if
.if_xname
, ilen
);
875 sc
->sc_if
.if_ierrors
++;
876 sc
->sc_stats
.ppp_ierrors
++;
877 sc
->sc_flags
|= SC_PKTLOST
;
884 * Remove FCS trailer. Somewhat painful...
887 if (--sc
->sc_mc
->m_len
== 0) {
888 for (m
= sc
->sc_m
; m
->m_next
!= sc
->sc_mc
; m
= m
->m_next
)
894 /* excise this mbuf chain */
896 sc
->sc_m
= sc
->sc_mc
->m_next
;
897 sc
->sc_mc
->m_next
= NULL
;
899 ppppktin(sc
, m
, sc
->sc_flags
& SC_PKTLOST
);
900 if (sc
->sc_flags
& SC_PKTLOST
) {
902 sc
->sc_flags
&= ~SC_PKTLOST
;
910 if (sc
->sc_flags
& SC_FLUSH
) {
911 if (sc
->sc_flags
& SC_LOG_FLUSH
)
916 if (c
< 0x20 && (sc
->sc_rasyncmap
& (1 << c
)))
920 if (sc
->sc_flags
& SC_ESCAPED
) {
921 sc
->sc_flags
&= ~SC_ESCAPED
;
923 } else if (c
== PPP_ESCAPE
) {
924 sc
->sc_flags
|= SC_ESCAPED
;
931 * Initialize buffer on first octet received.
932 * First octet could be address or protocol (when compressing
934 * Second octet is control.
935 * Third octet is first or second (when compressing protocol)
937 * Fourth octet is second octet of protocol.
939 if (sc
->sc_ilen
== 0) {
940 /* reset the first input mbuf */
941 if (sc
->sc_m
== NULL
) {
943 if (sc
->sc_m
== NULL
) {
944 if (sc
->sc_flags
& SC_DEBUG
)
945 printf("%s: no input mbufs!\n", sc
->sc_if
.if_xname
);
951 m
->m_data
= M_DATASTART(sc
->sc_m
);
953 sc
->sc_mp
= mtod(m
, char *);
954 sc
->sc_fcs
= PPP_INITFCS
;
955 if (c
!= PPP_ALLSTATIONS
) {
956 if (sc
->sc_flags
& SC_REJ_COMP_AC
) {
957 if (sc
->sc_flags
& SC_DEBUG
)
958 printf("%s: garbage received: 0x%x (need 0xFF)\n",
959 sc
->sc_if
.if_xname
, c
);
962 *sc
->sc_mp
++ = PPP_ALLSTATIONS
;
963 *sc
->sc_mp
++ = PPP_UI
;
968 if (sc
->sc_ilen
== 1 && c
!= PPP_UI
) {
969 if (sc
->sc_flags
& SC_DEBUG
)
970 printf("%s: missing UI (0x3), got 0x%x\n",
971 sc
->sc_if
.if_xname
, c
);
974 if (sc
->sc_ilen
== 2 && (c
& 1) == 1) {
975 /* a compressed protocol */
980 if (sc
->sc_ilen
== 3 && (c
& 1) == 0) {
981 if (sc
->sc_flags
& SC_DEBUG
)
982 printf("%s: bad protocol %x\n", sc
->sc_if
.if_xname
,
983 (sc
->sc_mp
[-1] << 8) + c
);
987 /* packet beyond configured mru? */
988 if (++sc
->sc_ilen
> sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
) {
989 if (sc
->sc_flags
& SC_DEBUG
)
990 printf("%s: packet too big\n", sc
->sc_if
.if_xname
);
994 /* is this mbuf full? */
996 if (M_TRAILINGSPACE(m
) <= 0) {
997 if (m
->m_next
== NULL
) {
999 if (m
->m_next
== NULL
) {
1000 if (sc
->sc_flags
& SC_DEBUG
)
1001 printf("%s: too few input mbufs!\n", sc
->sc_if
.if_xname
);
1005 sc
->sc_mc
= m
= m
->m_next
;
1007 m
->m_data
= M_DATASTART(m
);
1008 sc
->sc_mp
= mtod(m
, char *);
1013 sc
->sc_fcs
= PPP_FCS(sc
->sc_fcs
, c
);
1017 if (!(sc
->sc_flags
& SC_FLUSH
)) {
1019 sc
->sc_if
.if_ierrors
++;
1020 sc
->sc_stats
.ppp_ierrors
++;
1021 sc
->sc_flags
|= SC_FLUSH
;
1023 if (sc
->sc_flags
& SC_LOG_FLUSH
)
1029 #define MAX_DUMP_BYTES 128
1033 struct ppp_softc
*sc
;
1037 sc
->sc_rawin
[sc
->sc_rawin_count
++] = c
;
1038 if (sc
->sc_rawin_count
>= sizeof(sc
->sc_rawin
)
1039 || (c
< 0 && sc
->sc_rawin_count
> 0)) {
1040 printf("%s input: ", sc
->sc_if
.if_xname
);
1041 pppdumpb(sc
->sc_rawin
, sc
->sc_rawin_count
);
1042 sc
->sc_rawin_count
= 0;
1051 char buf
[3*MAX_DUMP_BYTES
+4];
1053 static char digits
[] = "0123456789abcdef";
1056 if (bp
>= buf
+ sizeof(buf
) - 3) {
1060 *bp
++ = digits
[*b
>> 4]; /* convert byte to ascii hex */
1061 *bp
++ = digits
[*b
++ & 0xf];
1066 printf("%s\n", buf
);
1069 #endif /* NPPP > 0 */