1 /* $Id: ppp_tty.c,v 1.5 2002/12/06 12:03:44 paulus Exp $ */
4 * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
21 * 3. The name "Carnegie Mellon University" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For permission or any legal
24 * details, please contact
25 * Office of Technology Transfer
26 * Carnegie Mellon University
28 * Pittsburgh, PA 15213-3890
29 * (412) 268-4387, fax: (412) 268-7395
30 * tech-transfer@andrew.cmu.edu
32 * 4. Redistributions of any form whatsoever must retain the following
34 * "This product includes software developed by Computing Services
35 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
37 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
38 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
39 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
40 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
41 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
42 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
43 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
46 * Carnegie Mellon University
48 * Pittsburgh, PA 15213
53 * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
55 * Copyright (c) 1987 Regents of the University of California.
56 * All rights reserved.
58 * Redistribution and use in source and binary forms are permitted
59 * provided that the above copyright notice and this paragraph are
60 * duplicated in all such forms and that any documentation,
61 * advertising materials, and other materials related to such
62 * distribution and use acknowledge that the software was developed
63 * by the University of California, Berkeley. The name of the
64 * University may not be used to endorse or promote products derived
65 * from this software without specific prior written permission.
66 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
67 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
68 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
70 * Serial Line interface
73 * Center for Seismic Studies
74 * 1300 N 17th Street, Suite 1450
75 * Arlington, Virginia 22209
80 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
81 * Converted to 4.3BSD Beta by Chris Torek.
82 * Other changes made at Berkeley, based in part on code by Kirk Smith.
84 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
85 * Added VJ tcp header compression; more unified ioctls
87 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
88 * Cleaned up a lot of the mbuf-related code to fix bugs that
89 * caused system crashes and packet corruption. Changed pppstart
90 * so that it doesn't just give up with a "collision" if the whole
91 * packet doesn't fit in the output ring buffer.
93 * Added priority queueing for interactive IP packets, following
94 * the model of if_sl.c, plus hooks for bpf.
95 * Paul Mackerras (paulus@cs.anu.edu.au).
98 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
99 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
107 #include <sys/param.h>
108 #include <sys/proc.h>
109 #include <sys/mbuf.h>
110 #include <sys/dkstat.h>
111 #include <sys/socket.h>
112 #include <sys/ioctl.h>
113 #include <sys/file.h>
115 #include <sys/kernel.h>
116 #include <sys/conf.h>
117 #include <sys/vnode.h>
118 #include <sys/systm.h>
121 #include <net/if_types.h>
124 #include <netinet/in.h>
125 #include <netinet/in_systm.h>
126 #include <netinet/ip.h>
127 #include <net/slcompress.h>
133 #include <net/ppp_defs.h>
134 #include <net/if_ppp.h>
135 #include <net/if_pppvar.h>
137 int pppopen
__P((dev_t dev
, struct tty
*tp
));
138 int pppclose
__P((struct tty
*tp
, int flag
));
139 int pppread
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
140 int pppwrite
__P((struct tty
*tp
, struct uio
*uio
, int flag
));
141 int ppptioctl
__P((struct tty
*tp
, u_long cmd
, caddr_t data
, int flag
,
143 int pppinput
__P((int c
, struct tty
*tp
));
144 int pppstart
__P((struct tty
*tp
, int));
146 static u_int16_t pppfcs
__P((u_int16_t fcs
, u_char
*cp
, int len
));
147 static void pppasyncstart
__P((struct ppp_softc
*));
148 static void pppasyncctlp
__P((struct ppp_softc
*));
149 static void pppasyncrelinq
__P((struct ppp_softc
*));
150 static void ppp_timeout
__P((void *));
151 static void pppgetm
__P((struct ppp_softc
*sc
));
152 static void pppdumpb
__P((u_char
*b
, int l
));
153 static void ppplogchar
__P((struct ppp_softc
*, int));
156 * Some useful mbuf macros not in mbuf.h.
158 #define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
160 #define M_DATASTART(m) \
161 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
162 (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
164 #define M_DATASIZE(m) \
165 (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
166 (m)->m_flags & M_PKTHDR ? MHLEN: 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.
177 /* This is a NetBSD-1.0 or later kernel. */
178 #define CCOUNT(q) ((q)->c_cc)
180 #define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
181 #define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
184 * Line specific open routine for async tty devices.
185 * Attach the given tty to the first available ppp unit.
186 * Called from device open routine or ttioctl.
192 register struct tty
*tp
;
194 struct proc
*p
= curproc
; /* XXX */
195 register struct ppp_softc
*sc
;
198 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
203 if (tp
->t_line
== PPPDISC
) {
204 sc
= (struct ppp_softc
*) tp
->t_sc
;
205 if (sc
!= NULL
&& sc
->sc_devp
== (void *) tp
) {
211 if ((sc
= pppalloc(p
->p_pid
)) == NULL
) {
217 (*sc
->sc_relinq
)(sc
); /* get previous owner to relinquish the unit */
221 bzero(sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
222 sc
->sc_asyncmap
[0] = 0xffffffff;
223 sc
->sc_asyncmap
[3] = 0x60000000;
224 sc
->sc_rasyncmap
= 0;
225 sc
->sc_devp
= (void *) tp
;
226 sc
->sc_start
= pppasyncstart
;
227 sc
->sc_ctlp
= pppasyncctlp
;
228 sc
->sc_relinq
= pppasyncrelinq
;
231 sc
->sc_if
.if_flags
|= IFF_RUNNING
;
232 sc
->sc_if
.if_baudrate
= tp
->t_ospeed
;
234 tp
->t_sc
= (caddr_t
) sc
;
235 ttyflush(tp
, FREAD
| FWRITE
);
242 * Line specific close routine, called from device close routine
244 * Detach the tty from the ppp unit.
245 * Mimics part of ttyclose().
252 register struct ppp_softc
*sc
;
256 ttyflush(tp
, FREAD
|FWRITE
);
258 sc
= (struct ppp_softc
*) tp
->t_sc
;
261 if (tp
== (struct tty
*) sc
->sc_devp
) {
271 * Relinquish the interface unit to another device.
275 struct ppp_softc
*sc
;
281 m_freem(sc
->sc_outm
);
288 if (sc
->sc_flags
& SC_TIMEOUT
) {
289 untimeout(ppp_timeout
, (void *) sc
);
290 sc
->sc_flags
&= ~SC_TIMEOUT
;
296 * Line specific (tty) read routine.
299 pppread(tp
, uio
, flag
)
300 register struct tty
*tp
;
304 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
312 * Loop waiting for input, checking that nothing disasterous
313 * happens in the meantime.
317 if (tp
!= (struct tty
*) sc
->sc_devp
|| tp
->t_line
!= PPPDISC
) {
321 if (sc
->sc_inq
.ifq_head
!= NULL
)
323 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0
324 && (tp
->t_state
& TS_ISOPEN
)) {
326 return 0; /* end of file */
328 if (tp
->t_state
& TS_ASYNC
|| flag
& IO_NDELAY
) {
330 return (EWOULDBLOCK
);
332 error
= ttysleep(tp
, (caddr_t
)&tp
->t_rawq
, TTIPRI
|PCATCH
, ttyin
, 0);
339 /* Pull place-holder byte out of canonical queue */
342 /* Get the packet from the input queue */
343 IF_DEQUEUE(&sc
->sc_inq
, m0
);
346 for (m
= m0
; m
&& uio
->uio_resid
; m
= m
->m_next
)
347 if ((error
= uiomove(mtod(m
, u_char
*), m
->m_len
, uio
)) != 0)
354 * Line specific (tty) write routine.
357 pppwrite(tp
, uio
, flag
)
358 register struct tty
*tp
;
362 register struct ppp_softc
*sc
= (struct ppp_softc
*)tp
->t_sc
;
363 struct mbuf
*m
, *m0
, **mp
;
367 if ((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
368 return 0; /* wrote 0 bytes */
369 if (tp
->t_line
!= PPPDISC
)
371 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
373 if (uio
->uio_resid
> sc
->sc_if
.if_mtu
+ PPP_HDRLEN
||
374 uio
->uio_resid
< PPP_HDRLEN
)
376 for (mp
= &m0
; uio
->uio_resid
; mp
= &m
->m_next
) {
377 MGET(m
, M_WAIT
, MT_DATA
);
378 if ((*mp
= m
) == NULL
) {
383 if (uio
->uio_resid
>= MCLBYTES
/ 2)
384 MCLGET(m
, M_DONTWAIT
);
385 len
= M_TRAILINGSPACE(m
);
386 if (len
> uio
->uio_resid
)
387 len
= uio
->uio_resid
;
388 if ((error
= uiomove(mtod(m
, u_char
*), len
, uio
)) != 0) {
394 dst
.sa_family
= AF_UNSPEC
;
395 bcopy(mtod(m0
, u_char
*), dst
.sa_data
, PPP_HDRLEN
);
396 m0
->m_data
+= PPP_HDRLEN
;
397 m0
->m_len
-= PPP_HDRLEN
;
398 return (pppoutput(&sc
->sc_if
, m0
, &dst
, (struct rtentry
*)0));
402 * Line specific (tty) ioctl routine.
403 * This discipline requires that tty device drivers call
404 * the line specific l_ioctl routine from their ioctl routines.
408 ppptioctl(tp
, cmd
, data
, flag
, p
)
415 struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
418 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
423 case PPPIOCSASYNCMAP
:
424 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
426 sc
->sc_asyncmap
[0] = *(u_int
*)data
;
429 case PPPIOCGASYNCMAP
:
430 *(u_int
*)data
= sc
->sc_asyncmap
[0];
433 case PPPIOCSRASYNCMAP
:
434 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
436 sc
->sc_rasyncmap
= *(u_int
*)data
;
439 case PPPIOCGRASYNCMAP
:
440 *(u_int
*)data
= sc
->sc_rasyncmap
;
443 case PPPIOCSXASYNCMAP
:
444 if ((error
= suser(p
->p_ucred
, &p
->p_acflag
)) != 0)
447 bcopy(data
, sc
->sc_asyncmap
, sizeof(sc
->sc_asyncmap
));
448 sc
->sc_asyncmap
[1] = 0; /* mustn't escape 0x20 - 0x3f */
449 sc
->sc_asyncmap
[2] &= ~0x40000000; /* mustn't escape 0x5e */
450 sc
->sc_asyncmap
[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
454 case PPPIOCGXASYNCMAP
:
455 bcopy(sc
->sc_asyncmap
, data
, sizeof(sc
->sc_asyncmap
));
459 error
= pppioctl(sc
, cmd
, data
, flag
, p
);
460 if (error
== 0 && cmd
== PPPIOCSMRU
)
468 * FCS lookup table as calculated by genfcstab.
470 static u_int16_t fcstab
[256] = {
471 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
472 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
473 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
474 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
475 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
476 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
477 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
478 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
479 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
480 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
481 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
482 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
483 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
484 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
485 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
486 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
487 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
488 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
489 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
490 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
491 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
492 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
493 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
494 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
495 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
496 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
497 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
498 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
499 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
500 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
501 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
502 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
506 * Calculate a new FCS given the current FCS and the new data.
510 register u_int16_t fcs
;
515 fcs
= PPP_FCS(fcs
, *cp
++);
520 * This gets called at splsoftnet from if_ppp.c at various times
521 * when there is data ready to be sent.
525 register struct ppp_softc
*sc
;
527 register struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
528 register struct mbuf
*m
;
530 register u_char
*start
, *stop
, *cp
;
531 int n
, ndone
, done
, idle
;
536 while (CCOUNT(&tp
->t_outq
) < PPP_HIWAT
) {
538 * See if we have an existing packet partly sent.
539 * If not, get a new packet and start sending it.
544 * Get another packet to be sent.
553 * The extra PPP_FLAG will start up a new packet, and thus
554 * will flush any accumulated garbage. We do this whenever
555 * the line may have been idle for some time.
557 if (CCOUNT(&tp
->t_outq
) == 0) {
558 ++sc
->sc_stats
.ppp_obytes
;
559 (void) putc(PPP_FLAG
, &tp
->t_outq
);
562 /* Calculate the FCS for the first mbuf's worth. */
563 sc
->sc_outfcs
= pppfcs(PPP_INITFCS
, mtod(m
, u_char
*), m
->m_len
);
564 sc
->sc_if
.if_lastchange
= time
;
568 start
= mtod(m
, u_char
*);
573 * Find out how many bytes in the string we can
574 * handle without doing something special.
576 for (cp
= start
; cp
< stop
; cp
++)
581 /* NetBSD (0.9 or later), 4.3-Reno or similar. */
582 ndone
= n
- b_to_q(start
, n
, &tp
->t_outq
);
585 sc
->sc_stats
.ppp_obytes
+= ndone
;
588 break; /* packet doesn't fit */
591 * If there are characters left in the mbuf,
592 * the first one must be special.
593 * Put it out in a different form.
597 if (putc(PPP_ESCAPE
, &tp
->t_outq
)) {
601 if (putc(*start
^ PPP_TRANS
, &tp
->t_outq
)) {
602 (void) unputc(&tp
->t_outq
);
607 sc
->sc_stats
.ppp_obytes
+= 2;
614 * If we didn't empty this mbuf, remember where we're up to.
615 * If we emptied the last mbuf, try to add the FCS and closing
616 * flag, and if we can't, leave sc_outm pointing to m, but with
617 * m->m_len == 0, to remind us to output the FCS and flag later.
620 if (done
&& m
->m_next
== NULL
) {
626 * We may have to escape the bytes in the FCS.
629 c
= ~sc
->sc_outfcs
& 0xFF;
632 *p
++ = c
^ PPP_TRANS
;
635 c
= (~sc
->sc_outfcs
>> 8) & 0xFF;
638 *p
++ = c
^ PPP_TRANS
;
644 * Try to output the FCS and flag. If the bytes
645 * don't all fit, back out.
648 for (q
= endseq
; q
< p
; ++q
)
649 if (putc(*q
, &tp
->t_outq
)) {
651 for (; q
> endseq
; --q
)
657 sc
->sc_stats
.ppp_obytes
+= q
- endseq
;
661 /* remember where we got to */
667 /* Finished with this mbuf; free it and move on. */
671 /* Finished a packet */
674 sc
->sc_outfcs
= pppfcs(sc
->sc_outfcs
, mtod(m
, u_char
*), m
->m_len
);
678 * If m == NULL, we have finished a packet.
679 * If m != NULL, we've either done as much work this time
680 * as we need to, or else we've filled up the output queue.
687 /* Call pppstart to start output again if necessary. */
692 * This timeout is needed for operation on a pseudo-tty,
693 * because the pty code doesn't call pppstart after it has
694 * drained the t_outq.
696 if (!idle
&& (sc
->sc_flags
& SC_TIMEOUT
) == 0) {
697 timeout(ppp_timeout
, (void *) sc
, 1);
698 sc
->sc_flags
|= SC_TIMEOUT
;
705 * This gets called when a received packet is placed on
706 * the inq, at splsoftnet.
710 struct ppp_softc
*sc
;
715 /* Put a placeholder byte in canq for ttselect()/ttnread(). */
717 tp
= (struct tty
*) sc
->sc_devp
;
718 putc(0, &tp
->t_canq
);
724 * Start output on async tty interface. If the transmit queue
725 * has drained sufficiently, arrange for pppasyncstart to be
726 * called later at splsoftnet.
727 * Called at spltty or higher.
731 register struct tty
*tp
;
734 register struct ppp_softc
*sc
= (struct ppp_softc
*) tp
->t_sc
;
737 * If there is stuff in the output queue, send it now.
738 * We are being called in lieu of ttstart and must do what it would.
740 if (tp
->t_oproc
!= NULL
)
744 * If the transmit queue has drained and the tty has not hung up
745 * or been disconnected from the ppp unit, then tell if_ppp.c that
746 * we need more output.
748 if (CCOUNT(&tp
->t_outq
) >= PPP_LOWAT
&& !force
)
750 if (!((tp
->t_state
& TS_CARR_ON
) == 0 && (tp
->t_cflag
& CLOCAL
) == 0)
751 && sc
!= NULL
&& tp
== (struct tty
*) sc
->sc_devp
) {
759 * Timeout routine - try to start some more output.
765 struct ppp_softc
*sc
= (struct ppp_softc
*) x
;
766 struct tty
*tp
= (struct tty
*) sc
->sc_devp
;
770 sc
->sc_flags
&= ~SC_TIMEOUT
;
776 * Allocate enough mbuf to handle current MRU.
780 register struct ppp_softc
*sc
;
782 struct mbuf
*m
, **mp
;
786 for (len
= sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
; len
> 0; ){
787 if ((m
= *mp
) == NULL
) {
788 MGETHDR(m
, M_DONTWAIT
, MT_DATA
);
792 MCLGET(m
, M_DONTWAIT
);
794 len
-= M_DATASIZE(m
);
800 * tty interface receiver interrupt.
802 static unsigned paritytab
[8] = {
803 0x96696996, 0x69969669, 0x69969669, 0x96696996,
804 0x69969669, 0x96696996, 0x96696996, 0x69969669
810 register struct tty
*tp
;
812 register struct ppp_softc
*sc
;
816 sc
= (struct ppp_softc
*) tp
->t_sc
;
817 if (sc
== NULL
|| tp
!= (struct tty
*) sc
->sc_devp
)
821 ++sc
->sc_stats
.ppp_ibytes
;
824 /* framing error or overrun on this char - abort packet */
825 if (sc
->sc_flags
& SC_DEBUG
)
826 printf("ppp%d: bad char %x\n", sc
->sc_if
.if_unit
, c
);
833 * Handle software flow control of output.
835 if (tp
->t_iflag
& IXON
) {
836 if (c
== tp
->t_cc
[VSTOP
] && tp
->t_cc
[VSTOP
] != _POSIX_VDISABLE
) {
837 if ((tp
->t_state
& TS_TTSTOP
) == 0) {
838 tp
->t_state
|= TS_TTSTOP
;
839 (*cdevsw
[major(tp
->t_dev
)].d_stop
)(tp
, 0);
843 if (c
== tp
->t_cc
[VSTART
] && tp
->t_cc
[VSTART
] != _POSIX_VDISABLE
) {
844 tp
->t_state
&= ~TS_TTSTOP
;
845 if (tp
->t_oproc
!= NULL
)
853 sc
->sc_flags
|= SC_RCV_B7_1
;
855 sc
->sc_flags
|= SC_RCV_B7_0
;
856 if (paritytab
[c
>> 5] & (1 << (c
& 0x1F)))
857 sc
->sc_flags
|= SC_RCV_ODDP
;
859 sc
->sc_flags
|= SC_RCV_EVNP
;
862 if (sc
->sc_flags
& SC_LOG_RAWIN
)
869 if (sc
->sc_rawin_count
> 0)
873 * If SC_ESCAPED is set, then we've seen the packet
874 * abort sequence "}~".
876 if (sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)
877 || (ilen
> 0 && sc
->sc_fcs
!= PPP_GOODFCS
)) {
879 sc
->sc_flags
|= SC_PKTLOST
; /* note the dropped packet */
880 if ((sc
->sc_flags
& (SC_FLUSH
| SC_ESCAPED
)) == 0){
881 if (sc
->sc_flags
& SC_DEBUG
)
882 printf("ppp%d: bad fcs %x, pkt len %d\n",
883 sc
->sc_if
.if_unit
, sc
->sc_fcs
, ilen
);
884 sc
->sc_if
.if_ierrors
++;
885 sc
->sc_stats
.ppp_ierrors
++;
887 sc
->sc_flags
&= ~(SC_FLUSH
| SC_ESCAPED
);
892 if (ilen
< PPP_HDRLEN
+ PPP_FCSLEN
) {
894 if (sc
->sc_flags
& SC_DEBUG
)
895 printf("ppp%d: too short (%d)\n", sc
->sc_if
.if_unit
, ilen
);
897 sc
->sc_if
.if_ierrors
++;
898 sc
->sc_stats
.ppp_ierrors
++;
899 sc
->sc_flags
|= SC_PKTLOST
;
906 * Remove FCS trailer. Somewhat painful...
909 if (--sc
->sc_mc
->m_len
== 0) {
910 for (m
= sc
->sc_m
; m
->m_next
!= sc
->sc_mc
; m
= m
->m_next
)
916 /* excise this mbuf chain */
918 sc
->sc_m
= sc
->sc_mc
->m_next
;
919 sc
->sc_mc
->m_next
= NULL
;
921 ppppktin(sc
, m
, sc
->sc_flags
& SC_PKTLOST
);
922 if (sc
->sc_flags
& SC_PKTLOST
) {
924 sc
->sc_flags
&= ~SC_PKTLOST
;
932 if (sc
->sc_flags
& SC_FLUSH
) {
933 if (sc
->sc_flags
& SC_LOG_FLUSH
)
938 if (c
< 0x20 && (sc
->sc_rasyncmap
& (1 << c
)))
942 if (sc
->sc_flags
& SC_ESCAPED
) {
943 sc
->sc_flags
&= ~SC_ESCAPED
;
945 } else if (c
== PPP_ESCAPE
) {
946 sc
->sc_flags
|= SC_ESCAPED
;
953 * Initialize buffer on first octet received.
954 * First octet could be address or protocol (when compressing
956 * Second octet is control.
957 * Third octet is first or second (when compressing protocol)
959 * Fourth octet is second octet of protocol.
961 if (sc
->sc_ilen
== 0) {
962 /* reset the first input mbuf */
963 if (sc
->sc_m
== NULL
) {
965 if (sc
->sc_m
== NULL
) {
966 if (sc
->sc_flags
& SC_DEBUG
)
967 printf("ppp%d: no input mbufs!\n", sc
->sc_if
.if_unit
);
973 m
->m_data
= M_DATASTART(sc
->sc_m
);
975 sc
->sc_mp
= mtod(m
, char *);
976 sc
->sc_fcs
= PPP_INITFCS
;
977 if (c
!= PPP_ALLSTATIONS
) {
978 if (sc
->sc_flags
& SC_REJ_COMP_AC
) {
979 if (sc
->sc_flags
& SC_DEBUG
)
980 printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
981 sc
->sc_if
.if_unit
, c
);
984 *sc
->sc_mp
++ = PPP_ALLSTATIONS
;
985 *sc
->sc_mp
++ = PPP_UI
;
990 if (sc
->sc_ilen
== 1 && c
!= PPP_UI
) {
991 if (sc
->sc_flags
& SC_DEBUG
)
992 printf("ppp%d: missing UI (0x3), got 0x%x\n",
993 sc
->sc_if
.if_unit
, c
);
996 if (sc
->sc_ilen
== 2 && (c
& 1) == 1) {
997 /* a compressed protocol */
1002 if (sc
->sc_ilen
== 3 && (c
& 1) == 0) {
1003 if (sc
->sc_flags
& SC_DEBUG
)
1004 printf("ppp%d: bad protocol %x\n", sc
->sc_if
.if_unit
,
1005 (sc
->sc_mp
[-1] << 8) + c
);
1009 /* packet beyond configured mru? */
1010 if (++sc
->sc_ilen
> sc
->sc_mru
+ PPP_HDRLEN
+ PPP_FCSLEN
) {
1011 if (sc
->sc_flags
& SC_DEBUG
)
1012 printf("ppp%d: packet too big\n", sc
->sc_if
.if_unit
);
1016 /* is this mbuf full? */
1018 if (M_TRAILINGSPACE(m
) <= 0) {
1019 if (m
->m_next
== NULL
) {
1021 if (m
->m_next
== NULL
) {
1022 if (sc
->sc_flags
& SC_DEBUG
)
1023 printf("ppp%d: too few input mbufs!\n", sc
->sc_if
.if_unit
);
1027 sc
->sc_mc
= m
= m
->m_next
;
1029 m
->m_data
= M_DATASTART(m
);
1030 sc
->sc_mp
= mtod(m
, char *);
1035 sc
->sc_fcs
= PPP_FCS(sc
->sc_fcs
, c
);
1039 if (!(sc
->sc_flags
& SC_FLUSH
)) {
1041 sc
->sc_if
.if_ierrors
++;
1042 sc
->sc_stats
.ppp_ierrors
++;
1043 sc
->sc_flags
|= SC_FLUSH
;
1045 if (sc
->sc_flags
& SC_LOG_FLUSH
)
1051 #define MAX_DUMP_BYTES 128
1055 struct ppp_softc
*sc
;
1059 sc
->sc_rawin
[sc
->sc_rawin_count
++] = c
;
1060 if (sc
->sc_rawin_count
>= sizeof(sc
->sc_rawin
)
1061 || (c
< 0 && sc
->sc_rawin_count
> 0)) {
1062 printf("ppp%d input: ", sc
->sc_if
.if_unit
);
1063 pppdumpb(sc
->sc_rawin
, sc
->sc_rawin_count
);
1064 sc
->sc_rawin_count
= 0;
1073 char buf
[3*MAX_DUMP_BYTES
+4];
1075 static char digits
[] = "0123456789abcdef";
1078 if (bp
>= buf
+ sizeof(buf
) - 3) {
1082 *bp
++ = digits
[*b
>> 4]; /* convert byte to ascii hex */
1083 *bp
++ = digits
[*b
++ & 0xf];
1088 printf("%s\n", buf
);
1091 #endif /* NPPP > 0 */