if_ppp.c revision 1.19
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
130struct ppp_softc ppp_softc[NPPP];
131
132void	pppattach __P((void));
133int	pppopen __P((dev_t dev, struct tty *tp));
134void	pppclose __P((struct tty *tp, int flag));
135int	pppread __P((struct tty *tp, struct uio *uio, int flag));
136int	pppwrite __P((struct tty *tp, struct uio *uio, int flag));
137int	ppptioctl __P((struct tty *tp, int cmd, caddr_t data, int flag,
138		       struct proc *));
139int	pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
140		       struct sockaddr *dst, struct rtentry *rtp));
141void	pppinput __P((int c, struct tty *tp));
142int	pppioctl __P((struct ifnet *ifp, int cmd, caddr_t data));
143void	pppstart __P((struct tty *tp));
144
145static int	pppasyncstart __P((struct ppp_softc *));
146static u_short	pppfcs __P((u_short fcs, u_char *cp, int len));
147static int	pppgetm __P((struct ppp_softc *sc));
148static void	pppdumpm __P((struct mbuf *m0, int pktlen));
149static void	pppdumpb __P((u_char *b, int l));
150static 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 */
169static 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 */
183void
184pppattach()
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 */
211struct ppp_softc *
212pppalloc(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 */
243pppdealloc(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 */
271int
272pppopen(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 */
318void
319pppclose(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 */
347int
348pppread(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 */
396int
397pppwrite(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 */
451int
452ppptioctl(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 */
556static 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 */
594static u_short
595pppfcs(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 */
609int
610pppoutput(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
726bad:
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 */
735struct mbuf *
736ppp_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 */
828static
829pppasyncstart(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 */
841void
842pppstart(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 */
1014static int
1015pppgetm(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
1051int
1052ppppktin(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 */
1209static unsigned paritytab[8] = {
1210    0x96696996, 0x69969669, 0x69969669, 0x96696996,
1211    0x69969669, 0x96696996, 0x96696996, 0x69969669
1212};
1213
1214void
1215pppinput(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 */
1439pppioctl(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
1486static void
1487pppdumpm(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    }
1519done:
1520    if (m && pktlen)
1521	*bp++ = '>';
1522    *bp = 0;
1523    printf("%s\n", buf);
1524}
1525
1526static void
1527ppplogchar(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
1541static void
1542pppdumpb(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