xref: /netbsd-src/sys/net/if_ppp.c (revision 6ea46cb5e46c49111a6ecf3bcbe3c7e2730fe9f6)
1 /*	$NetBSD: if_ppp.c,v 1.19 1994/07/27 09:05:33 deraadt Exp $	*/
2 
3 /*
4  * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
5  *
6  * Copyright (c) 1989 Carnegie Mellon University.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms are permitted
10  * provided that the above copyright notice and this paragraph are
11  * duplicated in all such forms and that any documentation,
12  * advertising materials, and other materials related to such
13  * distribution and use acknowledge that the software was developed
14  * by Carnegie Mellon University.  The name of the
15  * University may not be used to endorse or promote products derived
16  * from this software without specific prior written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Drew D. Perkins
22  * Carnegie Mellon University
23  * 4910 Forbes Ave.
24  * Pittsburgh, PA 15213
25  * (412) 268-8576
26  * ddp@andrew.cmu.edu
27  *
28  * Based on:
29  *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
30  *
31  * Copyright (c) 1987 Regents of the University of California.
32  * All rights reserved.
33  *
34  * Redistribution and use in source and binary forms are permitted
35  * provided that the above copyright notice and this paragraph are
36  * duplicated in all such forms and that any documentation,
37  * advertising materials, and other materials related to such
38  * distribution and use acknowledge that the software was developed
39  * by the University of California, Berkeley.  The name of the
40  * University may not be used to endorse or promote products derived
41  * from this software without specific prior written permission.
42  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
43  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
44  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
45  *
46  * Serial Line interface
47  *
48  * Rick Adams
49  * Center for Seismic Studies
50  * 1300 N 17th Street, Suite 1450
51  * Arlington, Virginia 22209
52  * (703)276-7900
53  * rick@seismo.ARPA
54  * seismo!rick
55  *
56  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
57  * Converted to 4.3BSD Beta by Chris Torek.
58  * Other changes made at Berkeley, based in part on code by Kirk Smith.
59  *
60  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
61  * Added VJ tcp header compression; more unified ioctls
62  *
63  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
64  * Cleaned up a lot of the mbuf-related code to fix bugs that
65  * caused system crashes and packet corruption.  Changed pppstart
66  * so that it doesn't just give up with a collision if the whole
67  * packet doesn't fit in the output ring buffer.
68  *
69  * Added priority queueing for interactive IP packets, following
70  * the model of if_sl.c, plus hooks for bpf.
71  * Paul Mackerras (paulus@cs.anu.edu.au).
72  */
73 
74 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
75 
76 #include "ppp.h"
77 #if NPPP > 0
78 
79 #define VJC
80 
81 #include <sys/param.h>
82 #include <sys/proc.h>
83 #include <sys/mbuf.h>
84 #include <sys/buf.h>
85 #include <sys/dkstat.h>
86 #include <sys/socket.h>
87 #include <sys/ioctl.h>
88 #include <sys/file.h>
89 #include <sys/tty.h>
90 #include <sys/kernel.h>
91 #include <sys/conf.h>
92 #include <sys/vnode.h>
93 
94 #include <net/if.h>
95 #include <net/if_types.h>
96 #include <net/netisr.h>
97 #include <net/route.h>
98 
99 #if INET
100 #include <netinet/in.h>
101 #include <netinet/in_systm.h>
102 #include <netinet/in_var.h>
103 #include <netinet/ip.h>
104 #endif
105 
106 #include "bpfilter.h"
107 #if NBPFILTER > 0
108 #include <sys/time.h>
109 #include <net/bpf.h>
110 #endif
111 
112 #ifdef VJC
113 #include <net/slcompress.h>
114 #define HDROFF	MAX_HDR
115 /* HDROFF should really be 128, but other parts of the system will
116    panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */
117 
118 #else
119 #define	HDROFF	(0)
120 #endif
121 
122 #include <net/if_ppp.h>
123 #include <machine/cpu.h>
124 
125 /* This is a NetBSD-current kernel. */
126 #define CCOUNT(q)	((q)->c_cc)
127 
128 #define	PPP_HIWAT	400	/* Don't start a new packet if HIWAT on que */
129 
130 struct ppp_softc ppp_softc[NPPP];
131 
132 void	pppattach __P((void));
133 int	pppopen __P((dev_t dev, struct tty *tp));
134 void	pppclose __P((struct tty *tp, int flag));
135 int	pppread __P((struct tty *tp, struct uio *uio, int flag));
136 int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
137 int	ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
138 		       struct proc *));
139 int	pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
140 		       struct sockaddr *dst, struct rtentry *rtp));
141 void	pppinput __P((int c, struct tty *tp));
142 int	pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
143 void	pppstart __P((struct tty *tp));
144 
145 static int	pppasyncstart __P((struct ppp_softc *));
146 static u_short	pppfcs __P((u_short fcs, u_char *cp, int len));
147 static int	pppgetm __P((struct ppp_softc *sc));
148 static void	pppdumpm __P((struct mbuf *m0, int pktlen));
149 static void	pppdumpb __P((u_char *b, int l));
150 static void	ppplogchar __P((struct ppp_softc *, int));
151 
152 /*
153  * Some useful mbuf macros not in mbuf.h.
154  */
155 #define M_DATASTART(m)	\
156 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_buf : \
157 	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
158 
159 #define M_DATASIZE(m)	\
160 	((m)->m_flags & M_EXT ? (m)->m_ext.ext_size : \
161 	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
162 
163 /*
164  * The following disgusting hack gets around the problem that IP TOS
165  * can't be set yet.  We want to put "interactive" traffic on a high
166  * priority queue.  To decide if traffic is interactive, we check that
167  * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
168  */
169 static u_short interactive_ports[8] = {
170 	0,	513,	0,	0,
171 	0,	21,	0,	23,
172 };
173 #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
174 
175 /*
176  * Does c need to be escaped?
177  */
178 #define ESCAPE_P(c)	(sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
179 
180 /*
181  * Called from boot code to establish ppp interfaces.
182  */
183 void
184 pppattach()
185 {
186     register struct ppp_softc *sc;
187     register int i = 0;
188 
189     for (sc = ppp_softc; i < NPPP; sc++) {
190 	sc->sc_if.if_name = "ppp";
191 	sc->sc_if.if_unit = i++;
192 	sc->sc_if.if_mtu = PPP_MTU;
193 	sc->sc_if.if_flags = IFF_POINTOPOINT;
194 	sc->sc_if.if_type = IFT_PPP;
195 	sc->sc_if.if_hdrlen = PPP_HDRLEN;
196 	sc->sc_if.if_ioctl = pppioctl;
197 	sc->sc_if.if_output = pppoutput;
198 	sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
199 	sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
200 	sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
201 	if_attach(&sc->sc_if);
202 #if NBPFILTER > 0
203 	bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
204 #endif
205     }
206 }
207 
208 /*
209  * Allocate a ppp interface unit and initialize it.
210  */
211 struct ppp_softc *
212 pppalloc(pid)
213     pid_t pid;
214 {
215     int nppp;
216     struct ppp_softc *sc;
217 
218     for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
219 	if (sc->sc_xfer == pid) {
220 	    sc->sc_xfer = 0;
221 	    break;
222 	}
223     if (nppp >= NPPP)
224 	for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
225 	    if (sc->sc_devp == NULL)
226 		break;
227     if (nppp >= NPPP)
228 	return NULL;
229 
230     sc->sc_flags = 0;
231     sc->sc_mru = PPP_MRU;
232 #ifdef VJC
233     sl_compress_init(&sc->sc_comp, -1);
234 #endif
235     sc->sc_if.if_flags |= IFF_RUNNING;
236 
237     return sc;
238 }
239 
240 /*
241  * Deallocate a ppp unit.
242  */
243 pppdealloc(sc)
244     struct ppp_softc *sc;
245 {
246     struct mbuf *m;
247 
248     if_down(&sc->sc_if);
249     sc->sc_devp = NULL;
250     sc->sc_xfer = 0;
251     for (;;) {
252 	IF_DEQUEUE(&sc->sc_inq, m);
253 	if (m == NULL)
254 	    break;
255 	m_freem(m);
256     }
257     for (;;) {
258 	IF_DEQUEUE(&sc->sc_fastq, m);
259 	if (m == NULL)
260 	    break;
261 	m_freem(m);
262     }
263     sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
264 }
265 
266 /*
267  * Line specific open routine for async tty devices.
268  * Attach the given tty to the first available ppp unit.
269  */
270 /* ARGSUSED */
271 int
272 pppopen(dev, tp)
273     dev_t dev;
274     register struct tty *tp;
275 {
276     struct proc *p = curproc;		/* XXX */
277     register struct ppp_softc *sc;
278     int error, s, i;
279 
280     if (error = suser(p->p_ucred, &p->p_acflag))
281 	return (error);
282 
283     if (tp->t_line == PPPDISC) {
284 	sc = (struct ppp_softc *) tp->t_sc;
285 	if (sc != NULL && sc->sc_devp == (void *) tp)
286 	    return (0);
287     }
288 
289     if ((sc = pppalloc(p->p_pid)) == NULL)
290 	return ENXIO;
291 
292     if (sc->sc_outm != NULL) {
293 	m_freem(sc->sc_outm);
294 	sc->sc_outm = NULL;
295     }
296 
297     pppgetm(sc);
298 
299     sc->sc_ilen = 0;
300     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
301     sc->sc_asyncmap[0] = 0xffffffff;
302     sc->sc_asyncmap[3] = 0x60000000;
303     sc->sc_rasyncmap = 0;
304     sc->sc_devp = (void *) tp;
305     sc->sc_start = pppasyncstart;
306 
307     tp->t_sc = (caddr_t) sc;
308     ttyflush(tp, FREAD | FWRITE);
309 
310     return (0);
311 }
312 
313 /*
314  * Line specific close routine.
315  * Detach the tty from the ppp unit.
316  * Mimics part of ttyclose().
317  */
318 void
319 pppclose(tp, flag)
320     struct tty *tp;
321     int flag;
322 {
323     register struct ppp_softc *sc;
324     struct mbuf *m;
325     int s;
326 
327     ttywflush(tp);
328     s = splimp();		/* paranoid; splnet probably ok */
329     tp->t_line = 0;
330     sc = (struct ppp_softc *)tp->t_sc;
331     if (sc != NULL) {
332 	tp->t_sc = NULL;
333 	if (tp == (struct tty *) sc->sc_devp) {
334 	    m_freem(sc->sc_outm);
335 	    sc->sc_outm = NULL;
336 	    m_freem(sc->sc_m);
337 	    sc->sc_m = NULL;
338 	    pppdealloc(sc);
339 	}
340     }
341     splx(s);
342 }
343 
344 /*
345  * Line specific (tty) read routine.
346  */
347 int
348 pppread(tp, uio, flag)
349     register struct tty *tp;
350     struct uio *uio;
351     int flag;
352 {
353     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
354     struct mbuf *m, *m0;
355     register int s;
356     int error = 0;
357 
358     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
359 	return 0;		/* end of file */
360     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
361 	return 0;
362     s = splimp();
363     while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
364 	if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
365 	    splx(s);
366 	    return (EWOULDBLOCK);
367 	}
368 	error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
369 	if (error) {
370 	    splx(s);
371 	    return error;
372 	}
373     }
374     if (tp->t_line != PPPDISC) {
375 	splx(s);
376 	return (-1);
377     }
378 
379     /* Pull place-holder byte out of canonical queue */
380     getc(&tp->t_canq);
381 
382     /* Get the packet from the input queue */
383     IF_DEQUEUE(&sc->sc_inq, m0);
384     splx(s);
385 
386     for (m = m0; m && uio->uio_resid; m = m->m_next)
387 	if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
388 	    break;
389     m_freem(m0);
390     return (error);
391 }
392 
393 /*
394  * Line specific (tty) write routine.
395  */
396 int
397 pppwrite(tp, uio, flag)
398     register struct tty *tp;
399     struct uio *uio;
400     int flag;
401 {
402     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
403     struct mbuf *m, *m0, **mp;
404     struct sockaddr dst;
405     struct ppp_header *ph1, *ph2;
406     int len, error;
407 
408     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
409 	return 0;		/* wrote 0 bytes */
410     if (tp->t_line != PPPDISC)
411 	return (EINVAL);
412     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
413 	return EIO;
414     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
415 	uio->uio_resid < PPP_HDRLEN)
416 	return (EMSGSIZE);
417     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
418 	MGET(m, M_WAIT, MT_DATA);
419 	if ((*mp = m) == NULL) {
420 	    m_freem(m0);
421 	    return (ENOBUFS);
422 	}
423 	m->m_len = 0;
424 	if (uio->uio_resid >= MCLBYTES / 2)
425 	    MCLGET(m, M_DONTWAIT);
426 	len = M_TRAILINGSPACE(m);
427 	if (len > uio->uio_resid)
428 	    len = uio->uio_resid;
429 	if (error = uiomove(mtod(m, u_char *), len, uio)) {
430 	    m_freem(m0);
431 	    return (error);
432 	}
433 	m->m_len = len;
434     }
435     dst.sa_family = AF_UNSPEC;
436     ph1 = (struct ppp_header *) &dst.sa_data;
437     ph2 = mtod(m0, struct ppp_header *);
438     *ph1 = *ph2;
439     m0->m_data += PPP_HDRLEN;
440     m0->m_len -= PPP_HDRLEN;
441     return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
442 }
443 
444 /*
445  * Line specific (tty) ioctl routine.
446  * Provide a way to get the ppp unit number.
447  * This discipline requires that tty device drivers call
448  * the line specific l_ioctl routine from their ioctl routines.
449  */
450 /* ARGSUSED */
451 int
452 ppptioctl(tp, cmd, data, flag, p)
453     struct tty *tp;
454     caddr_t data;
455     int cmd, flag;
456     struct proc *p;
457 {
458     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
459     int s, error, flags, mru;
460 
461     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
462 	return -1;
463 
464     switch (cmd) {
465     case FIONREAD:
466 	*(int *)data = sc->sc_inq.ifq_len;
467 	break;
468 
469     case PPPIOCGUNIT:
470 	*(int *)data = sc->sc_if.if_unit;
471 	break;
472 
473     case PPPIOCGFLAGS:
474 	*(u_int *)data = sc->sc_flags;
475 	break;
476 
477     case PPPIOCSFLAGS:
478 	if (error = suser(p->p_ucred, &p->p_acflag))
479 	    return (error);
480 	flags = *(int *)data & SC_MASK;
481 	s = splimp();
482 	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
483 	splx(s);
484 	break;
485 
486     case PPPIOCSASYNCMAP:
487 	if (error = suser(p->p_ucred, &p->p_acflag))
488 	    return (error);
489 	sc->sc_asyncmap[0] = *(u_int *)data;
490 	break;
491 
492     case PPPIOCGASYNCMAP:
493 	*(u_int *)data = sc->sc_asyncmap[0];
494 	break;
495 
496     case PPPIOCSRASYNCMAP:
497 	if (error = suser(p->p_ucred, &p->p_acflag))
498 	    return (error);
499 	sc->sc_rasyncmap = *(u_int *)data;
500 	break;
501 
502     case PPPIOCGRASYNCMAP:
503 	*(u_int *)data = sc->sc_rasyncmap;
504 	break;
505 
506     case PPPIOCSXASYNCMAP:
507 	if (error = suser(p->p_ucred, &p->p_acflag))
508 	    return (error);
509 	bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
510 	sc->sc_asyncmap[1] = 0;		    /* mustn't escape 0x20 - 0x3f */
511 	sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
512 	sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
513 	break;
514 
515     case PPPIOCGXASYNCMAP:
516 	bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
517 	break;
518 
519     case PPPIOCSMRU:
520 	if (error = suser(p->p_ucred, &p->p_acflag))
521 	    return (error);
522 	mru = *(int *)data;
523 	if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {
524 	    sc->sc_mru = mru;
525 	    pppgetm(sc);
526 	}
527 	break;
528 
529     case PPPIOCGMRU:
530 	*(int *)data = sc->sc_mru;
531 	break;
532 
533 #ifdef VJC
534     case PPPIOCSMAXCID:
535 	if (error = suser(p->p_ucred, &p->p_acflag))
536 	    return (error);
537 	sl_compress_init(&sc->sc_comp, *(int *)data);
538 	break;
539 #endif
540 
541     case PPPIOCXFERUNIT:
542 	if (error = suser(p->p_ucred, &p->p_acflag))
543 	    return (error);
544 	sc->sc_xfer = p->p_pid;
545 	break;
546 
547     default:
548 	return (-1);
549     }
550     return (0);
551 }
552 
553 /*
554  * FCS lookup table as calculated by genfcstab.
555  */
556 static u_short fcstab[256] = {
557 	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
558 	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
559 	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
560 	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
561 	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
562 	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
563 	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
564 	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
565 	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
566 	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
567 	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
568 	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
569 	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
570 	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
571 	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
572 	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
573 	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
574 	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
575 	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
576 	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
577 	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
578 	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
579 	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
580 	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
581 	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
582 	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
583 	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
584 	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
585 	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
586 	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
587 	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
588 	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
589 };
590 
591 /*
592  * Calculate a new FCS given the current FCS and the new data.
593  */
594 static u_short
595 pppfcs(fcs, cp, len)
596     register u_short fcs;
597     register u_char *cp;
598     register int len;
599 {
600     while (len--)
601 	fcs = PPP_FCS(fcs, *cp++);
602     return (fcs);
603 }
604 
605 /*
606  * Queue a packet.  Start transmission if not active.
607  * Packet is placed in Information field of PPP frame.
608  */
609 int
610 pppoutput(ifp, m0, dst, rtp)
611     struct ifnet *ifp;
612     struct mbuf *m0;
613     struct sockaddr *dst;
614     struct rtentry *rtp;
615 {
616     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
617     struct ppp_header *ph;
618     int protocol, address, control;
619     u_char *cp;
620     int s, error;
621     struct ip *ip;
622     struct ifqueue *ifq;
623 
624     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
625 	|| (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
626 	error = ENETDOWN;	/* sort of */
627 	goto bad;
628     }
629 
630     /*
631      * Compute PPP header.
632      */
633     address = PPP_ALLSTATIONS;
634     control = PPP_UI;
635     ifq = &ifp->if_snd;
636     switch (dst->sa_family) {
637 #ifdef INET
638     case AF_INET:
639 	protocol = PPP_IP;
640 	if ((sc->sc_flags & SC_ENABLE_IP) == 0) {
641 	    error = ENETDOWN;
642 	    goto bad;
643 	}
644 
645 	/*
646 	 * If this is a TCP packet to or from an "interactive" port,
647 	 * put the packet on the fastq instead.
648 	 */
649 	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
650 	    register int p = ntohl(((int *)ip)[ip->ip_hl]);
651 	    if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
652 		ifq = &sc->sc_fastq;
653 	}
654 	break;
655 #endif
656 #ifdef NS
657     case AF_NS:
658 	protocol = PPP_XNS;
659 	break;
660 #endif
661     case AF_UNSPEC:
662 	ph = (struct ppp_header *) dst->sa_data;
663 	address = ph->ph_address;
664 	control = ph->ph_control;
665 	protocol = ntohs(ph->ph_protocol);
666 	break;
667     default:
668 	printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
669 	error = EAFNOSUPPORT;
670 	goto bad;
671     }
672 
673     /*
674      * Add PPP header.  If no space in first mbuf, allocate another.
675      * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
676      */
677     if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
678 	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
679 	if (m0 == 0) {
680 	    error = ENOBUFS;
681 	    goto bad;
682 	}
683 	m0->m_len = 0;
684     } else
685 	m0->m_data -= PPP_HDRLEN;
686 
687     cp = mtod(m0, u_char *);
688     *cp++ = address;
689     *cp++ = control;
690     *cp++ = protocol >> 8;
691     *cp++ = protocol & 0xff;
692     m0->m_len += PPP_HDRLEN;
693 
694     if (sc->sc_flags & SC_LOG_OUTPKT) {
695 	printf("ppp%d output: ", ifp->if_unit);
696 	pppdumpm(m0, -1);
697     }
698 
699 #if NBPFILTER > 0
700     /* See if bpf wants to look at the packet. */
701     if (sc->sc_bpf)
702 	bpf_mtap(sc->sc_bpf, m0);
703 #endif
704 
705     /*
706      * Put the packet on the appropriate queue.
707      */
708     s = splimp();
709     if (IF_QFULL(ifq)) {
710 	IF_DROP(ifq);
711 	splx(s);
712 	sc->sc_if.if_oerrors++;
713 	error = ENOBUFS;
714 	goto bad;
715     }
716     IF_ENQUEUE(ifq, m0);
717 
718     /*
719      * Tell the device to send it out.
720      */
721     (*sc->sc_start)(sc);
722 
723     splx(s);
724     return (0);
725 
726 bad:
727     m_freem(m0);
728     return (error);
729 }
730 
731 /*
732  * Grab another packet off a queue and apply VJ compression,
733  * address/control and/or protocol compression if appropriate.
734  */
735 struct mbuf *
736 ppp_dequeue(sc)
737     struct ppp_softc *sc;
738 {
739     int s;
740     struct mbuf *m, *mp;
741     u_char *cp;
742     int address, control, protocol;
743 
744     s = splimp();
745     IF_DEQUEUE(&sc->sc_fastq, m);
746     if (m == NULL)
747 	IF_DEQUEUE(&sc->sc_if.if_snd, m);
748     splx(s);
749     if (m == NULL)
750 	return NULL;
751 
752     /*
753      * Extract the ppp header of the new packet.
754      * The ppp header will be in one mbuf.
755      */
756     cp = mtod(m, u_char *);
757     address = cp[0];
758     control = cp[1];
759     protocol = (cp[2] << 8) + cp[3];
760 
761     switch (protocol) {
762 #ifdef VJC
763     case PPP_IP:
764 	/*
765 	 * If the packet is a TCP/IP packet, see if we can compress it.
766 	 */
767 	if (sc->sc_flags & SC_COMP_TCP) {
768 	    struct ip *ip;
769 	    int type;
770 
771 	    mp = m;
772 	    ip = (struct ip *) (cp + PPP_HDRLEN);
773 	    if (mp->m_len <= PPP_HDRLEN) {
774 		mp = mp->m_next;
775 		if (mp == NULL)
776 		    break;
777 		ip = mtod(mp, struct ip *);
778 	    }
779 	    /* this code assumes the IP/TCP header is in one non-shared mbuf */
780 	    if (ip->ip_p == IPPROTO_TCP) {
781 		type = sl_compress_tcp(mp, ip, &sc->sc_comp,
782 				       !(sc->sc_flags & SC_NO_TCP_CCID));
783 		switch (type) {
784 		case TYPE_UNCOMPRESSED_TCP:
785 		    protocol = PPP_VJC_UNCOMP;
786 		    break;
787 		case TYPE_COMPRESSED_TCP:
788 		    protocol = PPP_VJC_COMP;
789 		    cp = mtod(m, u_char *);
790 		    cp[0] = address;	/* header has moved */
791 		    cp[1] = control;
792 		    cp[2] = 0;
793 		    break;
794 		}
795 		cp[3] = protocol;	/* update protocol in PPP header */
796 	    }
797 	}
798 #endif	/* VJC */
799     }
800 
801     /*
802      * Compress the address/control and protocol, if possible.
803      */
804     if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
805 	control == PPP_UI && protocol != PPP_ALLSTATIONS &&
806 	protocol != PPP_LCP) {
807 	/* can compress address/control */
808 	m->m_data += 2;
809 	m->m_len -= 2;
810     }
811     if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
812 	/* can compress protocol */
813 	if (mtod(m, u_char *) == cp) {
814 	    cp[2] = cp[1];	/* move address/control up */
815 	    cp[1] = cp[0];
816 	}
817 	++m->m_data;
818 	--m->m_len;
819     }
820 
821     return m;
822 }
823 
824 /*
825  * This gets called from pppoutput when a new packet is
826  * put on a queue.
827  */
828 static
829 pppasyncstart(sc)
830     register struct ppp_softc *sc;
831 {
832     register struct tty *tp = (struct tty *) sc->sc_devp;
833 
834     pppstart(tp);
835 }
836 
837 /*
838  * Start output on async tty interface.  Get another datagram
839  * to send from the interface queue and start sending it.
840  */
841 void
842 pppstart(tp)
843     register struct tty *tp;
844 {
845     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
846     register struct mbuf *m;
847     register int len;
848     register u_char *start, *stop, *cp;
849     int n, s, ndone, done;
850     struct mbuf *m2;
851 
852     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
853 	/* sorry, I can't talk now */
854 	return;
855     }
856     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
857 	(*tp->t_oproc)(tp);
858 	return;
859     }
860 
861     for (;;) {
862 	/*
863 	 * If there is more in the output queue, just send it now.
864 	 * We are being called in lieu of ttstart and must do what
865 	 * it would.
866 	 */
867 	if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
868 	    (*tp->t_oproc)(tp);
869 	    if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
870 		return;
871 	}
872 
873 	/*
874 	 * See if we have an existing packet partly sent.
875 	 * If not, get a new packet and start sending it.
876 	 * We take packets on the priority queue ahead of those
877 	 * on the normal queue.
878 	 */
879 	m = sc->sc_outm;
880 	if (m == NULL) {
881 	    /*
882 	     * Get another packet to be sent
883 	     */
884 	    m = ppp_dequeue(sc);
885 	    if (m == NULL)
886 		return;
887 
888 	    /*
889 	     * The extra PPP_FLAG will start up a new packet, and thus
890 	     * will flush any accumulated garbage.  We do this whenever
891 	     * the line may have been idle for some time.
892 	     */
893 	    if (CCOUNT(&tp->t_outq) == 0) {
894 		++sc->sc_bytessent;
895 		(void) putc(PPP_FLAG, &tp->t_outq);
896 	    }
897 
898 	    /* Calculate the FCS for the first mbuf's worth. */
899 	    sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
900 	}
901 
902 	for (;;) {
903 	    start = mtod(m, u_char *);
904 	    len = m->m_len;
905 	    stop = start + len;
906 	    while (len > 0) {
907 		/*
908 		 * Find out how many bytes in the string we can
909 		 * handle without doing something special.
910 		 */
911 		for (cp = start; cp < stop; cp++)
912 		    if (ESCAPE_P(*cp))
913 			break;
914 		n = cp - start;
915 		if (n) {
916 		    /* NetBSD (0.9 or later), 4.3-Reno or similar. */
917 		    ndone = n - b_to_q(start, n, &tp->t_outq);
918 		    len -= ndone;
919 		    start += ndone;
920 		    sc->sc_bytessent += ndone;
921 
922 		    if (ndone < n)
923 			break;	/* packet doesn't fit */
924 		}
925 		/*
926 		 * If there are characters left in the mbuf,
927 		 * the first one must be special..
928 		 * Put it out in a different form.
929 		 */
930 		if (len) {
931 		    if (putc(PPP_ESCAPE, &tp->t_outq))
932 			break;
933 		    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
934 			(void) unputc(&tp->t_outq);
935 			break;
936 		    }
937 		    sc->sc_bytessent += 2;
938 		    start++;
939 		    len--;
940 		}
941 	    }
942 	    /*
943 	     * If we didn't empty this mbuf, remember where we're up to.
944 	     * If we emptied the last mbuf, try to add the FCS and closing
945 	     * flag, and if we can't, leave sc_outm pointing to m, but with
946 	     * m->m_len == 0, to remind us to output the FCS and flag later.
947 	     */
948 	    done = len == 0;
949 	    if (done && m->m_next == NULL) {
950 		u_char *p, *q;
951 		int c;
952 		u_char endseq[8];
953 
954 		/*
955 		 * We may have to escape the bytes in the FCS.
956 		 */
957 		p = endseq;
958 		c = ~sc->sc_outfcs & 0xFF;
959 		if (ESCAPE_P(c)) {
960 		    *p++ = PPP_ESCAPE;
961 		    *p++ = c ^ PPP_TRANS;
962 		} else
963 		    *p++ = c;
964 		c = (~sc->sc_outfcs >> 8) & 0xFF;
965 		if (ESCAPE_P(c)) {
966 		    *p++ = PPP_ESCAPE;
967 		    *p++ = c ^ PPP_TRANS;
968 		} else
969 		    *p++ = c;
970 		*p++ = PPP_FLAG;
971 
972 		/*
973 		 * Try to output the FCS and flag.  If the bytes
974 		 * don't all fit, back out.
975 		 */
976 		for (q = endseq; q < p; ++q)
977 		    if (putc(*q, &tp->t_outq)) {
978 			done = 0;
979 			for (; q > endseq; --q)
980 			    unputc(&tp->t_outq);
981 			break;
982 		    }
983 	    }
984 
985 	    if (!done) {
986 		m->m_data = start;
987 		m->m_len = len;
988 		sc->sc_outm = m;
989 		if (tp->t_oproc != NULL)
990 		    (*tp->t_oproc)(tp);
991 		return;		/* can't do any more at the moment */
992 	    }
993 
994 	    /* Finished with this mbuf; free it and move on. */
995 	    MFREE(m, m2);
996 	    if (m2 == NULL)
997 		break;
998 
999 	    m = m2;
1000 	    sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
1001 	}
1002 
1003 	/* Finished a packet */
1004 	sc->sc_outm = NULL;
1005 	sc->sc_bytessent++;	/* account for closing flag */
1006 	sc->sc_if.if_opackets++;
1007 	sc->sc_if.if_obytes = sc->sc_bytessent;
1008     }
1009 }
1010 
1011 /*
1012  * Allocate enough mbuf to handle current MRU.
1013  */
1014 static int
1015 pppgetm(sc)
1016     register struct ppp_softc *sc;
1017 {
1018     struct mbuf *m, **mp;
1019     int len;
1020     int s;
1021 
1022     s = splimp();
1023     mp = &sc->sc_m;
1024     for (len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
1025 	if ((m = *mp) == NULL) {
1026 	    MGETHDR(m, M_DONTWAIT, MT_DATA);
1027 	    if (m == NULL)
1028 		break;
1029 	    *mp = m;
1030 	    MCLGET(m, M_DONTWAIT);
1031 	}
1032 	len -= M_DATASIZE(m);
1033 	mp = &m->m_next;
1034     }
1035     splx(s);
1036     return len <= 0;
1037 }
1038 
1039 /*
1040  * PPP packet input routine.
1041  * The caller has checked and removed the FCS and has inserted
1042  * the address/control bytes and the protocol high byte if they
1043  * were omitted.  The data in the first mbuf should start HDROFF
1044  * bytes from the beginning of the mbuf data storage area.
1045  * The return value is 1 if the packet was put on sc->sc_inq,
1046  * 0 otherwise.
1047  */
1048 #define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1049 			 TYPE_UNCOMPRESSED_TCP)
1050 
1051 int
1052 ppppktin(sc, m)
1053     struct ppp_softc *sc;
1054     struct mbuf *m;
1055 {
1056     struct ifqueue *inq;
1057     int s, ilen, xlen, proto, rv;
1058     u_char *cp, adrs, ctrl;
1059     struct mbuf *mp;
1060 
1061     sc->sc_if.if_ipackets++;
1062     rv = 0;
1063 
1064     cp = mtod(m, u_char *);
1065     adrs = cp[0];
1066     ctrl = cp[1];
1067     proto = (cp[2] << 8) + cp[3];
1068 
1069     ilen = 0;
1070     for (mp = m; mp != NULL; mp = mp->m_next)
1071 	ilen += mp->m_len;
1072 
1073 #ifdef VJC
1074     /*
1075      * See if we have a VJ-compressed packet to uncompress.
1076      */
1077     if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
1078 	char *pkttype = proto == PPP_VJC_COMP? "": "un";
1079 
1080 	if (sc->sc_flags & SC_REJ_COMP_TCP) {
1081 	    if (sc->sc_flags & SC_DEBUG)
1082 		printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
1083 			sc->sc_if.if_unit, pkttype, sc->sc_flags);
1084 	    m_freem(m);
1085 	    sc->sc_if.if_ierrors++;
1086 	    return 0;
1087 	}
1088 
1089 	if (proto == PPP_VJC_COMP && m->m_data - M_DATASTART(m) < MAX_HDR) {
1090 	    /*
1091 	     * We don't have room in the mbuf to decompress this packet.
1092 	     * XXX For now we just drop the packet.
1093 	     */
1094 	    if (sc->sc_flags & SC_DEBUG)
1095 		printf("ppp%d: no room to VJ-decompress packet\n",
1096 		       sc->sc_if.if_unit);
1097 	    m_freem(m);
1098 	    sc->sc_if.if_ierrors++;
1099 	    return 0;
1100 	}
1101 
1102 	m->m_data += PPP_HDRLEN;
1103 	m->m_len -= PPP_HDRLEN;
1104 	ilen -= PPP_HDRLEN;
1105 	xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
1106 					m->m_len, ilen,
1107 					COMPTYPE(proto), &sc->sc_comp);
1108 
1109 	if (xlen == 0) {
1110 	    if (sc->sc_flags & SC_DEBUG)
1111 		printf("ppp%d: sl_uncompress failed on type %scomp\n",
1112 			sc->sc_if.if_unit, pkttype);
1113 	    m_freem(m);
1114 	    sc->sc_if.if_ierrors++;
1115 	    return 0;
1116 	}
1117 
1118 	/* adjust the first mbuf by the decompressed amt */
1119 	xlen += PPP_HDRLEN;
1120 	m->m_len += xlen - ilen;
1121 	ilen = xlen;
1122 	m->m_data -= PPP_HDRLEN;
1123 	proto = PPP_IP;
1124 
1125 	/* put the ppp header back in place */
1126 	if (cp != mtod(m, u_char *)) {
1127 	    cp = mtod(m, u_char *);
1128 	    cp[0] = adrs;
1129 	    cp[1] = ctrl;
1130 	    cp[2] = 0;
1131 	}
1132 	cp[3] = PPP_IP;
1133     }
1134 #endif /* VJC */
1135 
1136     /*
1137      * If the packet will fit in a header mbuf, don't waste a
1138      * whole cluster on it.
1139      */
1140     if (ilen <= MHLEN) {
1141 	MGETHDR(mp, M_DONTWAIT, MT_DATA);
1142 	if (mp != NULL) {
1143 	    m_copydata(m, 0, ilen, mtod(mp, caddr_t));
1144 	    m_freem(m);
1145 	    m = mp;
1146 	    m->m_len = ilen;
1147 	}
1148     }
1149     m->m_pkthdr.len = ilen;
1150     m->m_pkthdr.rcvif = &sc->sc_if;
1151 
1152 #if NBPFILTER > 0
1153     /* See if bpf wants to look at the packet. */
1154     if (sc->sc_bpf)
1155 	bpf_mtap(sc->sc_bpf, m);
1156 #endif
1157 
1158     switch (proto) {
1159 #ifdef INET
1160     case PPP_IP:
1161 	/*
1162 	 * IP packet - take off the ppp header and pass it up to IP.
1163 	 */
1164 	if ((sc->sc_if.if_flags & IFF_UP) == 0
1165 	    || (sc->sc_flags & SC_ENABLE_IP) == 0) {
1166 	    /* interface is down - drop the packet. */
1167 	    m_freem(m);
1168 	    return 0;
1169 	}
1170 	m->m_pkthdr.len -= PPP_HDRLEN;
1171 	m->m_data += PPP_HDRLEN;
1172 	m->m_len -= PPP_HDRLEN;
1173 	schednetisr(NETISR_IP);
1174 	inq = &ipintrq;
1175 	break;
1176 #endif
1177 
1178     default:
1179 	/*
1180 	 * Some other protocol - place on input queue for read().
1181 	 */
1182 	inq = &sc->sc_inq;
1183 	rv = 1;
1184 	break;
1185     }
1186 
1187     /*
1188      * Put the packet on the appropriate input queue.
1189      */
1190     s = splimp();
1191     if (IF_QFULL(inq)) {
1192 	IF_DROP(inq);
1193 	if (sc->sc_flags & SC_DEBUG)
1194 	    printf("ppp%d: queue full\n", sc->sc_if.if_unit);
1195 	sc->sc_if.if_ierrors++;
1196 	sc->sc_if.if_iqdrops++;
1197 	m_freem(m);
1198 	rv = 0;
1199     } else
1200 	IF_ENQUEUE(inq, m);
1201 
1202     splx(s);
1203     return rv;
1204 }
1205 
1206 /*
1207  * tty interface receiver interrupt.
1208  */
1209 static unsigned paritytab[8] = {
1210     0x96696996, 0x69969669, 0x69969669, 0x96696996,
1211     0x69969669, 0x96696996, 0x96696996, 0x69969669
1212 };
1213 
1214 void
1215 pppinput(c, tp)
1216     int c;
1217     register struct tty *tp;
1218 {
1219     register struct ppp_softc *sc;
1220     struct mbuf *m;
1221     int ilen;
1222 
1223     tk_nin++;
1224     sc = (struct ppp_softc *) tp->t_sc;
1225     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
1226 	return;
1227 
1228     ++sc->sc_bytesrcvd;
1229 
1230     if (c & TTY_FE) {
1231 	/* framing error or overrun on this char - abort packet */
1232 	if (sc->sc_flags & SC_DEBUG)
1233 	    printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
1234 	goto flush;
1235     }
1236 
1237     c &= 0xff;
1238 
1239     if (c & 0x80)
1240 	sc->sc_flags |= SC_RCV_B7_1;
1241     else
1242 	sc->sc_flags |= SC_RCV_B7_0;
1243     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
1244 	sc->sc_flags |= SC_RCV_ODDP;
1245     else
1246 	sc->sc_flags |= SC_RCV_EVNP;
1247 
1248     if (sc->sc_flags & SC_LOG_RAWIN)
1249 	ppplogchar(sc, c);
1250 
1251     if (c == PPP_FLAG) {
1252 	ilen = sc->sc_ilen;
1253 	sc->sc_ilen = 0;
1254 	sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
1255 
1256 	if (sc->sc_rawin_count > 0)
1257 	    ppplogchar(sc, -1);
1258 
1259 	/*
1260 	 * If SC_ESCAPED is set, then we've seen the packet
1261 	 * abort sequence "}~".
1262 	 */
1263 	if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
1264 	    || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
1265 #ifdef VJC
1266 	    /*
1267 	     * If we've missed a packet, we must toss subsequent compressed
1268 	     * packets which don't have an explicit connection ID.
1269 	     */
1270 	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
1271 #endif
1272 	    if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
1273 		if (sc->sc_flags & SC_DEBUG)
1274 		    printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
1275 			   sc->sc_fcs);
1276 		sc->sc_if.if_ierrors++;
1277 	    } else
1278 		sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
1279 	    return;
1280 	}
1281 
1282 	if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
1283 	    if (ilen) {
1284 		if (sc->sc_flags & SC_DEBUG)
1285 		    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
1286 		sc->sc_if.if_ierrors++;
1287 	    }
1288 	    return;
1289 	}
1290 
1291 	/*
1292 	 * Remove FCS trailer.  Somewhat painful...
1293 	 */
1294 	ilen -= 2;
1295 	if (--sc->sc_mc->m_len == 0) {
1296 	    for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
1297 		;
1298 	    sc->sc_mc = m;
1299 	}
1300 	sc->sc_mc->m_len--;
1301 
1302 	/* excise this mbuf chain */
1303 	m = sc->sc_m;
1304 	sc->sc_m = sc->sc_mc->m_next;
1305 	sc->sc_mc->m_next = NULL;
1306 
1307 	if (sc->sc_flags & SC_LOG_INPKT) {
1308 	    printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
1309 	    pppdumpm(m, ilen);
1310 	}
1311 
1312 	if (ppppktin(sc, m)) {
1313 	    /* Put a placeholder byte in canq for ttselect()/ttnread(). */
1314 	    putc(0, &tp->t_canq);
1315 	    ttwakeup(tp);
1316 	}
1317 
1318 	pppgetm(sc);
1319 	return;
1320     }
1321 
1322     if (sc->sc_flags & SC_FLUSH) {
1323 	if (sc->sc_flags & SC_LOG_FLUSH)
1324 	    ppplogchar(sc, c);
1325 	return;
1326     }
1327 
1328     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
1329 	return;
1330 
1331     if (sc->sc_flags & SC_ESCAPED) {
1332 	sc->sc_flags &= ~SC_ESCAPED;
1333 	c ^= PPP_TRANS;
1334     } else if (c == PPP_ESCAPE) {
1335 	sc->sc_flags |= SC_ESCAPED;
1336 	return;
1337     }
1338 
1339     /*
1340      * Initialize buffer on first octet received.
1341      * First octet could be address or protocol (when compressing
1342      * address/control).
1343      * Second octet is control.
1344      * Third octet is first or second (when compressing protocol)
1345      * octet of protocol.
1346      * Fourth octet is second octet of protocol.
1347      */
1348     if (sc->sc_ilen == 0) {
1349 	/* reset the first input mbuf */
1350 	if (sc->sc_m == NULL) {
1351 	    pppgetm(sc);
1352 	    if (sc->sc_m == NULL) {
1353 		if (sc->sc_flags & SC_DEBUG)
1354 		    printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
1355 		goto flush;
1356 	    }
1357 	}
1358 	m = sc->sc_m;
1359 	m->m_len = 0;
1360 	m->m_data = M_DATASTART(sc->sc_m);
1361 	if (M_DATASIZE(sc->sc_m) >= HDROFF + PPP_HDRLEN)
1362 	    m->m_data += HDROFF;	/* allow room for VJ decompression */
1363 	sc->sc_mc = m;
1364 	sc->sc_mp = mtod(m, char *);
1365 	sc->sc_fcs = PPP_INITFCS;
1366 	if (c != PPP_ALLSTATIONS) {
1367 	    if (sc->sc_flags & SC_REJ_COMP_AC) {
1368 		if (sc->sc_flags & SC_DEBUG)
1369 		    printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
1370 			   sc->sc_if.if_unit, c);
1371 		goto flush;
1372 	    }
1373 	    *sc->sc_mp++ = PPP_ALLSTATIONS;
1374 	    *sc->sc_mp++ = PPP_UI;
1375 	    sc->sc_ilen += 2;
1376 	    m->m_len += 2;
1377 	}
1378     }
1379     if (sc->sc_ilen == 1 && c != PPP_UI) {
1380 	if (sc->sc_flags & SC_DEBUG)
1381 	    printf("ppp%d: missing UI (0x3), got 0x%x\n",
1382 		   sc->sc_if.if_unit, c);
1383 	goto flush;
1384     }
1385     if (sc->sc_ilen == 2 && (c & 1) == 1) {
1386 	/* a compressed protocol */
1387 	*sc->sc_mp++ = 0;
1388 	sc->sc_ilen++;
1389 	sc->sc_mc->m_len++;
1390     }
1391     if (sc->sc_ilen == 3 && (c & 1) == 0) {
1392 	if (sc->sc_flags & SC_DEBUG)
1393 	    printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
1394 		   (sc->sc_mp[-1] << 8) + c);
1395 	goto flush;
1396     }
1397 
1398     /* packet beyond configured mru? */
1399     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
1400 	if (sc->sc_flags & SC_DEBUG)
1401 	    printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
1402 	goto flush;
1403     }
1404 
1405     /* is this mbuf full? */
1406     m = sc->sc_mc;
1407     if (M_TRAILINGSPACE(m) <= 0) {
1408 	if (m->m_next == NULL) {
1409 	    pppgetm(sc);
1410 	    if (m->m_next == NULL) {
1411 		if (sc->sc_flags & SC_DEBUG)
1412 		    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
1413 		goto flush;
1414 	    }
1415 	}
1416 	sc->sc_mc = m = m->m_next;
1417 	m->m_len = 0;
1418 	m->m_data = M_DATASTART(m);
1419 	sc->sc_mp = mtod(m, char *);
1420     }
1421 
1422     ++m->m_len;
1423     *sc->sc_mp++ = c;
1424     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
1425     return;
1426 
1427  flush:
1428     if (!(sc->sc_flags & SC_FLUSH)) {
1429 	sc->sc_if.if_ierrors++;
1430 	sc->sc_flags |= SC_FLUSH;
1431 	if (sc->sc_flags & SC_LOG_FLUSH)
1432 	    ppplogchar(sc, c);
1433     }
1434 }
1435 
1436 /*
1437  * Process an ioctl request to interface.
1438  */
1439 pppioctl(ifp, cmd, data)
1440     register struct ifnet *ifp;
1441     int cmd;
1442     caddr_t data;
1443 {
1444     struct proc *p = curproc;	/* XXX */
1445     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
1446     register struct ifaddr *ifa = (struct ifaddr *)data;
1447     register struct ifreq *ifr = (struct ifreq *)data;
1448     int s = splimp(), error = 0;
1449 
1450 
1451     switch (cmd) {
1452     case SIOCSIFFLAGS:
1453 	if ((ifp->if_flags & IFF_RUNNING) == 0)
1454 	    ifp->if_flags &= ~IFF_UP;
1455 	break;
1456 
1457     case SIOCSIFADDR:
1458 	if (ifa->ifa_addr->sa_family != AF_INET)
1459 	    error = EAFNOSUPPORT;
1460 	break;
1461 
1462     case SIOCSIFDSTADDR:
1463 	if (ifa->ifa_addr->sa_family != AF_INET)
1464 	    error = EAFNOSUPPORT;
1465 	break;
1466 
1467     case SIOCSIFMTU:
1468 	if (error = suser(p->p_ucred, &p->p_acflag))
1469 	    break;
1470 	sc->sc_if.if_mtu = ifr->ifr_mtu;
1471 	break;
1472 
1473     case SIOCGIFMTU:
1474 	ifr->ifr_mtu = sc->sc_if.if_mtu;
1475 	break;
1476 
1477     default:
1478 	error = EINVAL;
1479     }
1480     splx(s);
1481     return (error);
1482 }
1483 
1484 #define MAX_DUMP_BYTES	128
1485 
1486 static void
1487 pppdumpm(m0, pktlen)
1488     struct mbuf *m0;
1489     int pktlen;
1490 {
1491     char buf[3*MAX_DUMP_BYTES+4];
1492     char *bp = buf;
1493     struct mbuf *m;
1494     static char digits[] = "0123456789abcdef";
1495 
1496     for (m = m0; m && pktlen; m = m->m_next) {
1497 	int l = m->m_len;
1498 	u_char *rptr = (u_char *)m->m_data;
1499 
1500 	if (pktlen > 0) {
1501 	    if (l > pktlen)
1502 		l = pktlen;
1503 	    pktlen -= l;
1504 	}
1505 	while (l--) {
1506 	    if (bp > buf + sizeof(buf) - 4)
1507 		goto done;
1508 	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
1509 	    *bp++ = digits[*rptr++ & 0xf];
1510 	}
1511 
1512 	if (m->m_next) {
1513 	    if (bp > buf + sizeof(buf) - 3)
1514 		goto done;
1515 	    *bp++ = '|';
1516 	} else
1517 	    *bp++ = ' ';
1518     }
1519 done:
1520     if (m && pktlen)
1521 	*bp++ = '>';
1522     *bp = 0;
1523     printf("%s\n", buf);
1524 }
1525 
1526 static void
1527 ppplogchar(sc, c)
1528     struct ppp_softc *sc;
1529     int c;
1530 {
1531     if (c >= 0)
1532 	sc->sc_rawin[sc->sc_rawin_count++] = c;
1533     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
1534 	|| c < 0 && sc->sc_rawin_count > 0) {
1535 	printf("ppp%d input: ", sc->sc_if.if_unit);
1536 	pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
1537 	sc->sc_rawin_count = 0;
1538     }
1539 }
1540 
1541 static void
1542 pppdumpb(b, l)
1543     u_char *b;
1544     int l;
1545 {
1546     char buf[3*MAX_DUMP_BYTES+4];
1547     char *bp = buf;
1548     static char digits[] = "0123456789abcdef";
1549 
1550     while (l--) {
1551 	if (bp >= buf + sizeof(buf) - 3) {
1552 	    *bp++ = '>';
1553 	    break;
1554 	}
1555 	*bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
1556 	*bp++ = digits[*b++ & 0xf];
1557 	*bp++ = ' ';
1558     }
1559 
1560     *bp = 0;
1561     printf("%s\n", buf);
1562 }
1563 
1564 
1565 #endif	/* NPPP > 0 */
1566