if_ppp.c revision 1.85
1/*	$NetBSD: if_ppp.c,v 1.85 2003/09/01 16:51:25 christos Exp $	*/
2/*	Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp 	*/
3
4/*
5 * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
6 *
7 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 *
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
19 *    distribution.
20 *
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
27 *      5000 Forbes Avenue
28 *      Pittsburgh, PA  15213-3890
29 *      (412) 268-4387, fax: (412) 268-7395
30 *      tech-transfer@andrew.cmu.edu
31 *
32 * 4. Redistributions of any form whatsoever must retain the following
33 *    acknowledgment:
34 *    "This product includes software developed by Computing Services
35 *     at Carnegie Mellon University (http://www.cmu.edu/computing/)."
36 *
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.
44 *
45 * Based on:
46 *	@(#)if_sl.c	7.6.1.2 (Berkeley) 2/15/89
47 *
48 * Copyright (c) 1987 Regents of the University of California.
49 * All rights reserved.
50 *
51 * Redistribution and use in source and binary forms are permitted
52 * provided that the above copyright notice and this paragraph are
53 * duplicated in all such forms and that any documentation,
54 * advertising materials, and other materials related to such
55 * distribution and use acknowledge that the software was developed
56 * by the University of California, Berkeley.  The name of the
57 * University may not be used to endorse or promote products derived
58 * from this software without specific prior written permission.
59 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
60 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
61 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
62 *
63 * Serial Line interface
64 *
65 * Rick Adams
66 * Center for Seismic Studies
67 * 1300 N 17th Street, Suite 1450
68 * Arlington, Virginia 22209
69 * (703)276-7900
70 * rick@seismo.ARPA
71 * seismo!rick
72 *
73 * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
74 * Converted to 4.3BSD Beta by Chris Torek.
75 * Other changes made at Berkeley, based in part on code by Kirk Smith.
76 *
77 * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
78 * Added VJ tcp header compression; more unified ioctls
79 *
80 * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
81 * Cleaned up a lot of the mbuf-related code to fix bugs that
82 * caused system crashes and packet corruption.  Changed pppstart
83 * so that it doesn't just give up with a collision if the whole
84 * packet doesn't fit in the output ring buffer.
85 *
86 * Added priority queueing for interactive IP packets, following
87 * the model of if_sl.c, plus hooks for bpf.
88 * Paul Mackerras (paulus@cs.anu.edu.au).
89 */
90
91/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
92/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
93
94/*
95 * XXX IMP ME HARDER
96 *
97 * This is an explanation of that comment.  This code used to use
98 * splimp() to block both network and tty interrupts.  However,
99 * that call is deprecated.  So, we have replaced the uses of
100 * splimp() with splhigh() in order to applomplish what it needs
101 * to accomplish, and added that happy little comment.
102 */
103
104#include <sys/cdefs.h>
105__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.85 2003/09/01 16:51:25 christos Exp $");
106
107#include "ppp.h"
108
109#include "opt_inet.h"
110#include "opt_gateway.h"
111#include "opt_ppp.h"
112
113#ifdef INET
114#define VJC
115#endif
116#define PPP_COMPRESS
117
118#include <sys/param.h>
119#include <sys/proc.h>
120#include <sys/mbuf.h>
121#include <sys/socket.h>
122#include <sys/ioctl.h>
123#include <sys/kernel.h>
124#include <sys/systm.h>
125#include <sys/time.h>
126#include <sys/malloc.h>
127
128#include <net/if.h>
129#include <net/if_types.h>
130#include <net/netisr.h>
131#include <net/route.h>
132#ifdef PPP_FILTER
133#include <net/bpf.h>
134#endif
135
136#include <machine/intr.h>
137
138#include <netinet/in.h>
139#include <netinet/in_systm.h>
140#include <netinet/in_var.h>
141#ifdef INET
142#include <netinet/ip.h>
143#endif
144
145#include "bpfilter.h"
146#if NBPFILTER > 0
147#include <sys/time.h>
148#include <net/bpf.h>
149#endif
150
151#if defined(PPP_FILTER) || NBPFILTER > 0
152#include <net/slip.h>
153#endif
154
155#ifdef VJC
156#include <net/slcompress.h>
157#endif
158
159#include <net/ppp_defs.h>
160#include <net/if_ppp.h>
161#include <net/if_pppvar.h>
162#include <machine/cpu.h>
163
164#ifdef PPP_COMPRESS
165#define PACKETPTR	struct mbuf *
166#include <net/ppp-comp.h>
167#endif
168
169static int	pppsioctl __P((struct ifnet *, u_long, caddr_t));
170static void	ppp_requeue __P((struct ppp_softc *));
171static void	ppp_ccp __P((struct ppp_softc *, struct mbuf *m, int rcvd));
172static void	ppp_ccp_closed __P((struct ppp_softc *));
173static void	ppp_inproc __P((struct ppp_softc *, struct mbuf *));
174static void	pppdumpm __P((struct mbuf *m0));
175#ifdef ALTQ
176static void	ppp_ifstart __P((struct ifnet *ifp));
177#endif
178
179#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
180void		pppnetisr(void);
181#endif
182void		pppintr(void *);
183
184/*
185 * Some useful mbuf macros not in mbuf.h.
186 */
187#define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
188
189#define M_DATASTART(m)	\
190	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
191	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
192
193#define M_DATASIZE(m)	\
194	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
195	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
196
197/*
198 * We define two link layer specific mbuf flags, to mark high-priority
199 * packets for output, and received packets following lost/corrupted
200 * packets.
201 */
202#define	M_HIGHPRI	M_LINK0	/* output packet for sc_fastq */
203#define	M_ERRMARK	M_LINK1	/* rx packet following lost/corrupted pkt */
204
205struct	ppp_softc ppp_softc[NPPP];
206
207#ifdef PPP_COMPRESS
208/*
209 * List of compressors we know about.
210 * We leave some space so maybe we can modload compressors.
211 */
212
213extern struct compressor ppp_bsd_compress;
214extern struct compressor ppp_deflate, ppp_deflate_draft;
215
216struct compressor *ppp_compressors[PPP_COMPRESSORS_MAX] = {
217#if DO_BSD_COMPRESS && defined(PPP_BSDCOMP)
218    &ppp_bsd_compress,
219#endif
220#if DO_DEFLATE && defined(PPP_DEFLATE)
221    &ppp_deflate,
222    &ppp_deflate_draft,
223#endif
224    NULL
225};
226#endif /* PPP_COMPRESS */
227
228
229/*
230 * Called from boot code to establish ppp interfaces.
231 */
232void
233pppattach()
234{
235    struct ppp_softc *sc;
236    int i = 0;
237
238    for (sc = ppp_softc; i < NPPP; sc++) {
239	sc->sc_unit = i;	/* XXX */
240	sprintf(sc->sc_if.if_xname, "ppp%d", i++);
241	callout_init(&sc->sc_timo_ch);
242	sc->sc_if.if_softc = sc;
243	sc->sc_if.if_mtu = PPP_MTU;
244	sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
245	sc->sc_if.if_type = IFT_PPP;
246	sc->sc_if.if_hdrlen = PPP_HDRLEN;
247	sc->sc_if.if_dlt = DLT_NULL;
248	sc->sc_if.if_ioctl = pppsioctl;
249	sc->sc_if.if_output = pppoutput;
250#ifdef ALTQ
251	sc->sc_if.if_start = ppp_ifstart;
252#endif
253	IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
254	sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
255	sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
256	sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
257	IFQ_SET_READY(&sc->sc_if.if_snd);
258	if_attach(&sc->sc_if);
259	if_alloc_sadl(&sc->sc_if);
260#if NBPFILTER > 0
261	bpfattach(&sc->sc_if, DLT_NULL, 0);
262#endif
263    }
264}
265
266/*
267 * Allocate a ppp interface unit and initialize it.
268 */
269struct ppp_softc *
270pppalloc(pid)
271    pid_t pid;
272{
273    int nppp, i;
274    struct ppp_softc *sc;
275
276    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
277	if (sc->sc_xfer == pid) {
278	    sc->sc_xfer = 0;
279	    return sc;
280	}
281    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
282	if (sc->sc_devp == NULL)
283	    break;
284    if (nppp >= NPPP)
285	return NULL;
286
287#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
288    sc->sc_si = softintr_establish(IPL_SOFTNET, pppintr, sc);
289    if (sc->sc_si == NULL) {
290	printf("ppp%d: unable to establish softintr\n", sc->sc_unit);
291	return (NULL);
292    }
293#endif
294
295    sc->sc_flags = 0;
296    sc->sc_mru = PPP_MRU;
297    sc->sc_relinq = NULL;
298    memset((char *)&sc->sc_stats, 0, sizeof(sc->sc_stats));
299#ifdef VJC
300    MALLOC(sc->sc_comp, struct slcompress *, sizeof(struct slcompress),
301	   M_DEVBUF, M_NOWAIT);
302    if (sc->sc_comp)
303	sl_compress_init(sc->sc_comp);
304#endif
305#ifdef PPP_COMPRESS
306    sc->sc_xc_state = NULL;
307    sc->sc_rc_state = NULL;
308#endif /* PPP_COMPRESS */
309    for (i = 0; i < NUM_NP; ++i)
310	sc->sc_npmode[i] = NPMODE_ERROR;
311    sc->sc_npqueue = NULL;
312    sc->sc_npqtail = &sc->sc_npqueue;
313    sc->sc_last_sent = sc->sc_last_recv = time.tv_sec;
314
315    return sc;
316}
317
318/*
319 * Deallocate a ppp unit.  Must be called at splsoftnet or higher.
320 */
321void
322pppdealloc(sc)
323    struct ppp_softc *sc;
324{
325    struct mbuf *m;
326
327#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
328    softintr_disestablish(sc->sc_si);
329#endif
330    if_down(&sc->sc_if);
331    sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
332    sc->sc_devp = NULL;
333    sc->sc_xfer = 0;
334    for (;;) {
335	IF_DEQUEUE(&sc->sc_rawq, m);
336	if (m == NULL)
337	    break;
338	m_freem(m);
339    }
340    for (;;) {
341	IF_DEQUEUE(&sc->sc_inq, m);
342	if (m == NULL)
343	    break;
344	m_freem(m);
345    }
346    for (;;) {
347	IF_DEQUEUE(&sc->sc_fastq, m);
348	if (m == NULL)
349	    break;
350	m_freem(m);
351    }
352    while ((m = sc->sc_npqueue) != NULL) {
353	sc->sc_npqueue = m->m_nextpkt;
354	m_freem(m);
355    }
356    if (sc->sc_togo != NULL) {
357	m_freem(sc->sc_togo);
358	sc->sc_togo = NULL;
359    }
360#ifdef PPP_COMPRESS
361    ppp_ccp_closed(sc);
362    sc->sc_xc_state = NULL;
363    sc->sc_rc_state = NULL;
364#endif /* PPP_COMPRESS */
365#ifdef PPP_FILTER
366    if (sc->sc_pass_filt_in.bf_insns != 0) {
367	FREE(sc->sc_pass_filt_in.bf_insns, M_DEVBUF);
368	sc->sc_pass_filt_in.bf_insns = 0;
369	sc->sc_pass_filt_in.bf_len = 0;
370    }
371    if (sc->sc_pass_filt_out.bf_insns != 0) {
372	FREE(sc->sc_pass_filt_out.bf_insns, M_DEVBUF);
373	sc->sc_pass_filt_out.bf_insns = 0;
374	sc->sc_pass_filt_out.bf_len = 0;
375    }
376    if (sc->sc_active_filt_in.bf_insns != 0) {
377	FREE(sc->sc_active_filt_in.bf_insns, M_DEVBUF);
378	sc->sc_active_filt_in.bf_insns = 0;
379	sc->sc_active_filt_in.bf_len = 0;
380    }
381    if (sc->sc_active_filt_out.bf_insns != 0) {
382	FREE(sc->sc_active_filt_out.bf_insns, M_DEVBUF);
383	sc->sc_active_filt_out.bf_insns = 0;
384	sc->sc_active_filt_out.bf_len = 0;
385    }
386#endif /* PPP_FILTER */
387#ifdef VJC
388    if (sc->sc_comp != 0) {
389	FREE(sc->sc_comp, M_DEVBUF);
390	sc->sc_comp = 0;
391    }
392#endif
393}
394
395/*
396 * Ioctl routine for generic ppp devices.
397 */
398int
399pppioctl(sc, cmd, data, flag, p)
400    struct ppp_softc *sc;
401    u_long cmd;
402    caddr_t data;
403    int flag;
404    struct proc *p;
405{
406    int s, error, flags, mru, npx;
407    u_int nb;
408    struct ppp_option_data *odp;
409    struct compressor **cp;
410    struct npioctl *npi;
411    time_t t;
412#ifdef PPP_FILTER
413    struct bpf_program *bp, *nbp;
414    struct bpf_insn *newcode, *oldcode;
415    int newcodelen;
416#endif /* PPP_FILTER */
417#ifdef	PPP_COMPRESS
418    u_char ccp_option[CCP_MAX_OPTION_LENGTH];
419#endif
420
421    switch (cmd) {
422    case FIONREAD:
423	*(int *)data = sc->sc_inq.ifq_len;
424	break;
425
426    case PPPIOCGUNIT:
427	*(int *)data = sc->sc_unit;	/* XXX */
428	break;
429
430    case PPPIOCGFLAGS:
431	*(u_int *)data = sc->sc_flags;
432	break;
433
434    case PPPIOCGRAWIN:
435	{
436	    struct ppp_rawin *rwin = (struct ppp_rawin *)data;
437	    u_char p, q = 0;
438
439	    for (p = sc->sc_rawin_start; p < sizeof(sc->sc_rawin.buf);)
440		rwin->buf[q++] = sc->sc_rawin.buf[p++];
441
442	    for (p = 0; p < sc->sc_rawin_start;)
443		rwin->buf[q++] = sc->sc_rawin.buf[p++];
444
445	    rwin->count = sc->sc_rawin.count;
446	}
447	break;
448
449    case PPPIOCSFLAGS:
450	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
451	    return (error);
452	flags = *(int *)data & SC_MASK;
453	s = splsoftnet();
454#ifdef PPP_COMPRESS
455	if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
456	    ppp_ccp_closed(sc);
457#endif
458	splhigh();	/* XXX IMP ME HARDER */
459	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
460	splx(s);
461	break;
462
463    case PPPIOCSMRU:
464	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
465	    return (error);
466	mru = *(int *)data;
467	if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU)
468	    sc->sc_mru = mru;
469	break;
470
471    case PPPIOCGMRU:
472	*(int *)data = sc->sc_mru;
473	break;
474
475#ifdef VJC
476    case PPPIOCSMAXCID:
477	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
478	    return (error);
479	if (sc->sc_comp) {
480	    s = splsoftnet();
481	    sl_compress_setup(sc->sc_comp, *(int *)data);
482	    splx(s);
483	}
484	break;
485#endif
486
487    case PPPIOCXFERUNIT:
488	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
489	    return (error);
490	sc->sc_xfer = p->p_pid;
491	break;
492
493#ifdef PPP_COMPRESS
494    case PPPIOCSCOMPRESS:
495	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
496	    return (error);
497	odp = (struct ppp_option_data *) data;
498	nb = odp->length;
499	if (nb > sizeof(ccp_option))
500	    nb = sizeof(ccp_option);
501	if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
502	    return (error);
503	if (ccp_option[1] < 2)	/* preliminary check on the length byte */
504	    return (EINVAL);
505	for (cp = ppp_compressors; *cp != NULL; ++cp)
506	    if ((*cp)->compress_proto == ccp_option[0]) {
507		/*
508		 * Found a handler for the protocol - try to allocate
509		 * a compressor or decompressor.
510		 */
511		error = 0;
512		if (odp->transmit) {
513		    s = splsoftnet();
514		    if (sc->sc_xc_state != NULL)
515			(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
516		    sc->sc_xcomp = *cp;
517		    sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
518		    if (sc->sc_xc_state == NULL) {
519			if (sc->sc_flags & SC_DEBUG)
520			    printf("%s: comp_alloc failed\n",
521				sc->sc_if.if_xname);
522			error = ENOBUFS;
523		    }
524		    splhigh();	/* XXX IMP ME HARDER */
525		    sc->sc_flags &= ~SC_COMP_RUN;
526		    splx(s);
527		} else {
528		    s = splsoftnet();
529		    if (sc->sc_rc_state != NULL)
530			(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
531		    sc->sc_rcomp = *cp;
532		    sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
533		    if (sc->sc_rc_state == NULL) {
534			if (sc->sc_flags & SC_DEBUG)
535			    printf("%s: decomp_alloc failed\n",
536				sc->sc_if.if_xname);
537			error = ENOBUFS;
538		    }
539		    splhigh();	/* XXX IMP ME HARDER */
540		    sc->sc_flags &= ~SC_DECOMP_RUN;
541		    splx(s);
542		}
543		return (error);
544	    }
545	if (sc->sc_flags & SC_DEBUG)
546	    printf("%s: no compressor for [%x %x %x], %x\n",
547		sc->sc_if.if_xname, ccp_option[0], ccp_option[1],
548		ccp_option[2], nb);
549	return (EINVAL);	/* no handler found */
550#endif /* PPP_COMPRESS */
551
552    case PPPIOCGNPMODE:
553    case PPPIOCSNPMODE:
554	npi = (struct npioctl *) data;
555	switch (npi->protocol) {
556	case PPP_IP:
557	    npx = NP_IP;
558	    break;
559	case PPP_IPV6:
560	    npx = NP_IPV6;
561	    break;
562	default:
563	    return EINVAL;
564	}
565	if (cmd == PPPIOCGNPMODE) {
566	    npi->mode = sc->sc_npmode[npx];
567	} else {
568	    if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
569		return (error);
570	    if (npi->mode != sc->sc_npmode[npx]) {
571		s = splnet();
572		sc->sc_npmode[npx] = npi->mode;
573		if (npi->mode != NPMODE_QUEUE) {
574		    ppp_requeue(sc);
575		    ppp_restart(sc);
576		}
577		splx(s);
578	    }
579	}
580	break;
581
582    case PPPIOCGIDLE:
583	s = splsoftnet();
584	t = time.tv_sec;
585	((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
586	((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
587	splx(s);
588	break;
589
590#ifdef PPP_FILTER
591    case PPPIOCSPASS:
592    case PPPIOCSACTIVE:
593	/* These are no longer supported. */
594	return EOPNOTSUPP;
595
596    case PPPIOCSIPASS:
597    case PPPIOCSOPASS:
598    case PPPIOCSIACTIVE:
599    case PPPIOCSOACTIVE:
600	nbp = (struct bpf_program *) data;
601	if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
602	    return EINVAL;
603	newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
604	if (newcodelen != 0) {
605	    newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK);
606	    /* WAITOK -- malloc() never fails. */
607	    if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
608			       newcodelen)) != 0) {
609		free(newcode, M_DEVBUF);
610		return error;
611	    }
612	    if (!bpf_validate(newcode, nbp->bf_len)) {
613		free(newcode, M_DEVBUF);
614		return EINVAL;
615	    }
616	} else
617	    newcode = 0;
618	switch (cmd) {
619	case PPPIOCSIPASS:
620	    bp = &sc->sc_pass_filt_in;
621	    break;
622
623	case PPPIOCSOPASS:
624	    bp = &sc->sc_pass_filt_out;
625	    break;
626
627	case PPPIOCSIACTIVE:
628	    bp = &sc->sc_active_filt_in;
629	    break;
630
631	case PPPIOCSOACTIVE:
632	    bp = &sc->sc_active_filt_out;
633	    break;
634	}
635	oldcode = bp->bf_insns;
636	s = splnet();
637	bp->bf_len = nbp->bf_len;
638	bp->bf_insns = newcode;
639	splx(s);
640	if (oldcode != 0)
641	    free(oldcode, M_DEVBUF);
642	break;
643#endif /* PPP_FILTER */
644
645    default:
646	return (EPASSTHROUGH);
647    }
648    return (0);
649}
650
651/*
652 * Process an ioctl request to the ppp network interface.
653 */
654static int
655pppsioctl(ifp, cmd, data)
656    struct ifnet *ifp;
657    u_long cmd;
658    caddr_t data;
659{
660    struct proc *p = curproc;	/* XXX */
661    struct ppp_softc *sc = ifp->if_softc;
662    struct ifaddr *ifa = (struct ifaddr *)data;
663    struct ifreq *ifr = (struct ifreq *)data;
664    struct ppp_stats *psp;
665#ifdef	PPP_COMPRESS
666    struct ppp_comp_stats *pcp;
667#endif
668    int s = splnet(), error = 0;
669
670    switch (cmd) {
671    case SIOCSIFFLAGS:
672	if ((ifp->if_flags & IFF_RUNNING) == 0)
673	    ifp->if_flags &= ~IFF_UP;
674	break;
675
676    case SIOCSIFADDR:
677	switch (ifa->ifa_addr->sa_family) {
678#ifdef INET
679	case AF_INET:
680	    break;
681#endif
682#ifdef INET6
683	case AF_INET6:
684	    break;
685#endif
686	default:
687	    error = EAFNOSUPPORT;
688	    break;
689	}
690	break;
691
692    case SIOCSIFDSTADDR:
693	switch (ifa->ifa_addr->sa_family) {
694#ifdef INET
695	case AF_INET:
696	    break;
697#endif
698#ifdef INET6
699	case AF_INET6:
700	    break;
701#endif
702	default:
703	    error = EAFNOSUPPORT;
704	    break;
705	}
706	break;
707
708    case SIOCSIFMTU:
709	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
710	    break;
711	sc->sc_if.if_mtu = ifr->ifr_mtu;
712	break;
713
714    case SIOCGIFMTU:
715	ifr->ifr_mtu = sc->sc_if.if_mtu;
716	break;
717
718    case SIOCADDMULTI:
719    case SIOCDELMULTI:
720	if (ifr == 0) {
721	    error = EAFNOSUPPORT;
722	    break;
723	}
724	switch (ifr->ifr_addr.sa_family) {
725#ifdef INET
726	case AF_INET:
727	    break;
728#endif
729#ifdef INET6
730	case AF_INET6:
731	    break;
732#endif
733	default:
734	    error = EAFNOSUPPORT;
735	    break;
736	}
737	break;
738
739    case SIOCGPPPSTATS:
740	psp = &((struct ifpppstatsreq *) data)->stats;
741	memset(psp, 0, sizeof(*psp));
742	psp->p = sc->sc_stats;
743#if defined(VJC) && !defined(SL_NO_STATS)
744	if (sc->sc_comp) {
745	    psp->vj.vjs_packets = sc->sc_comp->sls_packets;
746	    psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
747	    psp->vj.vjs_searches = sc->sc_comp->sls_searches;
748	    psp->vj.vjs_misses = sc->sc_comp->sls_misses;
749	    psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
750	    psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
751	    psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
752	    psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
753	}
754#endif /* VJC */
755	break;
756
757#ifdef PPP_COMPRESS
758    case SIOCGPPPCSTATS:
759	pcp = &((struct ifpppcstatsreq *) data)->stats;
760	memset(pcp, 0, sizeof(*pcp));
761	if (sc->sc_xc_state != NULL)
762	    (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
763	if (sc->sc_rc_state != NULL)
764	    (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
765	break;
766#endif /* PPP_COMPRESS */
767
768    default:
769	error = EINVAL;
770    }
771    splx(s);
772    return (error);
773}
774
775/*
776 * Queue a packet.  Start transmission if not active.
777 * Packet is placed in Information field of PPP frame.
778 */
779int
780pppoutput(ifp, m0, dst, rtp)
781    struct ifnet *ifp;
782    struct mbuf *m0;
783    struct sockaddr *dst;
784    struct rtentry *rtp;
785{
786    struct ppp_softc *sc = ifp->if_softc;
787    int protocol, address, control;
788    u_char *cp;
789    int s, error;
790#ifdef INET
791    struct ip *ip;
792#endif
793    struct ifqueue *ifq;
794    enum NPmode mode;
795    int len;
796    struct mbuf *m;
797    ALTQ_DECL(struct altq_pktattr pktattr;)
798
799    if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
800	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
801	error = ENETDOWN;	/* sort of */
802	goto bad;
803    }
804
805    IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
806
807    /*
808     * Compute PPP header.
809     */
810    m0->m_flags &= ~M_HIGHPRI;
811    switch (dst->sa_family) {
812#ifdef INET
813    case AF_INET:
814	address = PPP_ALLSTATIONS;
815	control = PPP_UI;
816	protocol = PPP_IP;
817	mode = sc->sc_npmode[NP_IP];
818
819	/*
820	 * If this packet has the "low delay" bit set in the IP header,
821	 * put it on the fastq instead.
822	 */
823	ip = mtod(m0, struct ip *);
824	if (ip->ip_tos & IPTOS_LOWDELAY)
825	    m0->m_flags |= M_HIGHPRI;
826	break;
827#endif
828#ifdef INET6
829    case AF_INET6:
830	address = PPP_ALLSTATIONS;	/*XXX*/
831	control = PPP_UI;		/*XXX*/
832	protocol = PPP_IPV6;
833	mode = sc->sc_npmode[NP_IPV6];
834
835#if 0	/* XXX flowinfo/traffic class, maybe? */
836	/*
837	 * If this packet has the "low delay" bit set in the IP header,
838	 * put it on the fastq instead.
839	 */
840	ip = mtod(m0, struct ip *);
841	if (ip->ip_tos & IPTOS_LOWDELAY)
842	    m0->m_flags |= M_HIGHPRI;
843#endif
844	break;
845#endif
846    case AF_UNSPEC:
847	address = PPP_ADDRESS(dst->sa_data);
848	control = PPP_CONTROL(dst->sa_data);
849	protocol = PPP_PROTOCOL(dst->sa_data);
850	mode = NPMODE_PASS;
851	break;
852    default:
853	printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family);
854	error = EAFNOSUPPORT;
855	goto bad;
856    }
857
858    /*
859     * Drop this packet, or return an error, if necessary.
860     */
861    if (mode == NPMODE_ERROR) {
862	error = ENETDOWN;
863	goto bad;
864    }
865    if (mode == NPMODE_DROP) {
866	error = 0;
867	goto bad;
868    }
869
870    /*
871     * Add PPP header.  If no space in first mbuf, allocate another.
872     * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
873     */
874    if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
875	m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
876	if (m0 == 0) {
877	    error = ENOBUFS;
878	    goto bad;
879	}
880	m0->m_len = 0;
881    } else
882	m0->m_data -= PPP_HDRLEN;
883
884    cp = mtod(m0, u_char *);
885    *cp++ = address;
886    *cp++ = control;
887    *cp++ = protocol >> 8;
888    *cp++ = protocol & 0xff;
889    m0->m_len += PPP_HDRLEN;
890
891    len = 0;
892    for (m = m0; m != 0; m = m->m_next)
893	len += m->m_len;
894
895    if (sc->sc_flags & SC_LOG_OUTPKT) {
896	printf("%s output: ", ifp->if_xname);
897	pppdumpm(m0);
898    }
899
900    if ((protocol & 0x8000) == 0) {
901#ifdef PPP_FILTER
902	/*
903	 * Apply the pass and active filters to the packet,
904	 * but only if it is a data packet.
905	 */
906	if (sc->sc_pass_filt_out.bf_insns != 0
907	    && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0,
908			  len, 0) == 0) {
909	    error = 0;		/* drop this packet */
910	    goto bad;
911	}
912
913	/*
914	 * Update the time we sent the most recent packet.
915	 */
916	if (sc->sc_active_filt_out.bf_insns == 0
917	    || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0,
918	    		  len, 0))
919	    sc->sc_last_sent = time.tv_sec;
920#else
921	/*
922	 * Update the time we sent the most recent packet.
923	 */
924	sc->sc_last_sent = time.tv_sec;
925#endif /* PPP_FILTER */
926    }
927
928#if NBPFILTER > 0
929    /*
930     * See if bpf wants to look at the packet.
931     */
932    if (sc->sc_if.if_bpf)
933	bpf_mtap(sc->sc_if.if_bpf, m0);
934#endif
935
936    /*
937     * Put the packet on the appropriate queue.
938     */
939    s = splnet();
940    if (mode == NPMODE_QUEUE) {
941	/* XXX we should limit the number of packets on this queue */
942	*sc->sc_npqtail = m0;
943	m0->m_nextpkt = NULL;
944	sc->sc_npqtail = &m0->m_nextpkt;
945    } else {
946	if ((m0->m_flags & M_HIGHPRI)
947#ifdef ALTQ
948	    && ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
949#endif
950	    ) {
951	    ifq = &sc->sc_fastq;
952	    if (IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
953	        IF_DROP(ifq);
954		splx(s);
955		error = ENOBUFS;
956		goto bad;
957	    } else {
958		IF_ENQUEUE(ifq, m0);
959		error = 0;
960	    }
961	} else
962	    IFQ_ENQUEUE(&sc->sc_if.if_snd, m0, &pktattr, error);
963	if (error) {
964	    splx(s);
965	    sc->sc_if.if_oerrors++;
966	    sc->sc_stats.ppp_oerrors++;
967	    return (error);
968	}
969	ppp_restart(sc);
970    }
971    ifp->if_opackets++;
972    ifp->if_obytes += len;
973
974    splx(s);
975    return (0);
976
977bad:
978    m_freem(m0);
979    return (error);
980}
981
982/*
983 * After a change in the NPmode for some NP, move packets from the
984 * npqueue to the send queue or the fast queue as appropriate.
985 * Should be called at splnet, since we muck with the queues.
986 */
987static void
988ppp_requeue(sc)
989    struct ppp_softc *sc;
990{
991    struct mbuf *m, **mpp;
992    struct ifqueue *ifq;
993    enum NPmode mode;
994    int error;
995
996    for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
997	switch (PPP_PROTOCOL(mtod(m, u_char *))) {
998	case PPP_IP:
999	    mode = sc->sc_npmode[NP_IP];
1000	    break;
1001	case PPP_IPV6:
1002	    mode = sc->sc_npmode[NP_IPV6];
1003	    break;
1004	default:
1005	    mode = NPMODE_PASS;
1006	}
1007
1008	switch (mode) {
1009	case NPMODE_PASS:
1010	    /*
1011	     * This packet can now go on one of the queues to be sent.
1012	     */
1013	    *mpp = m->m_nextpkt;
1014	    m->m_nextpkt = NULL;
1015	    if ((m->m_flags & M_HIGHPRI)
1016#ifdef ALTQ
1017		&& ALTQ_IS_ENABLED(&sc->sc_if.if_snd) == 0
1018#endif
1019		) {
1020		ifq = &sc->sc_fastq;
1021		if (IF_QFULL(ifq)) {
1022		    IF_DROP(ifq);
1023		    m_freem(m);
1024		    error = ENOBUFS;
1025		} else {
1026		    IF_ENQUEUE(ifq, m);
1027		    error = 0;
1028		}
1029	    } else
1030		IFQ_ENQUEUE(&sc->sc_if.if_snd, m, NULL, error);
1031	    if (error) {
1032		sc->sc_if.if_oerrors++;
1033		sc->sc_stats.ppp_oerrors++;
1034	    }
1035	    break;
1036
1037	case NPMODE_DROP:
1038	case NPMODE_ERROR:
1039	    *mpp = m->m_nextpkt;
1040	    m_freem(m);
1041	    break;
1042
1043	case NPMODE_QUEUE:
1044	    mpp = &m->m_nextpkt;
1045	    break;
1046	}
1047    }
1048    sc->sc_npqtail = mpp;
1049}
1050
1051/*
1052 * Transmitter has finished outputting some stuff;
1053 * remember to call sc->sc_start later at splsoftnet.
1054 */
1055void
1056ppp_restart(sc)
1057    struct ppp_softc *sc;
1058{
1059    int s = splhigh();	/* XXX IMP ME HARDER */
1060
1061    sc->sc_flags &= ~SC_TBUSY;
1062#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1063    softintr_schedule(sc->sc_si);
1064#else
1065    schednetisr(NETISR_PPP);
1066#endif
1067    splx(s);
1068}
1069
1070/*
1071 * Get a packet to send.  This procedure is intended to be called at
1072 * splsoftnet, since it may involve time-consuming operations such as
1073 * applying VJ compression, packet compression, address/control and/or
1074 * protocol field compression to the packet.
1075 */
1076struct mbuf *
1077ppp_dequeue(sc)
1078    struct ppp_softc *sc;
1079{
1080    struct mbuf *m, *mp;
1081    u_char *cp;
1082    int address, control, protocol;
1083    int s;
1084
1085    /*
1086     * Grab a packet to send: first try the fast queue, then the
1087     * normal queue.
1088     */
1089    s = splnet();
1090    IF_DEQUEUE(&sc->sc_fastq, m);
1091    if (m == NULL)
1092	IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
1093    splx(s);
1094
1095    if (m == NULL)
1096	return NULL;
1097
1098    ++sc->sc_stats.ppp_opackets;
1099
1100    /*
1101     * Extract the ppp header of the new packet.
1102     * The ppp header will be in one mbuf.
1103     */
1104    cp = mtod(m, u_char *);
1105    address = PPP_ADDRESS(cp);
1106    control = PPP_CONTROL(cp);
1107    protocol = PPP_PROTOCOL(cp);
1108
1109    switch (protocol) {
1110    case PPP_IP:
1111#ifdef VJC
1112	/*
1113	 * If the packet is a TCP/IP packet, see if we can compress it.
1114	 */
1115	if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
1116	    struct ip *ip;
1117	    int type;
1118
1119	    mp = m;
1120	    ip = (struct ip *) (cp + PPP_HDRLEN);
1121	    if (mp->m_len <= PPP_HDRLEN) {
1122		mp = mp->m_next;
1123		if (mp == NULL)
1124		    break;
1125		ip = mtod(mp, struct ip *);
1126	    }
1127	    /* this code assumes the IP/TCP header is in one non-shared mbuf */
1128	    if (ip->ip_p == IPPROTO_TCP) {
1129		type = sl_compress_tcp(mp, ip, sc->sc_comp,
1130				       !(sc->sc_flags & SC_NO_TCP_CCID));
1131		switch (type) {
1132		case TYPE_UNCOMPRESSED_TCP:
1133		    protocol = PPP_VJC_UNCOMP;
1134		    break;
1135		case TYPE_COMPRESSED_TCP:
1136		    protocol = PPP_VJC_COMP;
1137		    cp = mtod(m, u_char *);
1138		    cp[0] = address;	/* header has moved */
1139		    cp[1] = control;
1140		    cp[2] = 0;
1141		    break;
1142		}
1143		cp[3] = protocol;	/* update protocol in PPP header */
1144	    }
1145	}
1146#endif	/* VJC */
1147	break;
1148
1149#ifdef PPP_COMPRESS
1150    case PPP_CCP:
1151	ppp_ccp(sc, m, 0);
1152	break;
1153#endif	/* PPP_COMPRESS */
1154    }
1155
1156#ifdef PPP_COMPRESS
1157    if (protocol != PPP_LCP && protocol != PPP_CCP
1158	&& sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
1159	struct mbuf *mcomp = NULL;
1160	int slen;
1161
1162	slen = 0;
1163	for (mp = m; mp != NULL; mp = mp->m_next)
1164	    slen += mp->m_len;
1165	(*sc->sc_xcomp->compress)
1166	    (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
1167	if (mcomp != NULL) {
1168	    if (sc->sc_flags & SC_CCP_UP) {
1169		/* Send the compressed packet instead of the original. */
1170		m_freem(m);
1171		m = mcomp;
1172		cp = mtod(m, u_char *);
1173		protocol = cp[3];
1174	    } else {
1175		/* Can't transmit compressed packets until CCP is up. */
1176		m_freem(mcomp);
1177	    }
1178	}
1179    }
1180#endif	/* PPP_COMPRESS */
1181
1182    /*
1183     * Compress the address/control and protocol, if possible.
1184     */
1185    if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
1186	control == PPP_UI && protocol != PPP_ALLSTATIONS &&
1187	protocol != PPP_LCP) {
1188	/* can compress address/control */
1189	m->m_data += 2;
1190	m->m_len -= 2;
1191    }
1192    if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
1193	/* can compress protocol */
1194	if (mtod(m, u_char *) == cp) {
1195	    cp[2] = cp[1];	/* move address/control up */
1196	    cp[1] = cp[0];
1197	}
1198	++m->m_data;
1199	--m->m_len;
1200    }
1201
1202    return m;
1203}
1204
1205#ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1206void
1207pppnetisr(void)
1208{
1209	struct ppp_softc *sc;
1210	int i;
1211
1212	for (i = 0; i < NPPP; i++) {
1213		sc = &ppp_softc[i];
1214		pppintr(sc);
1215	}
1216}
1217#endif
1218
1219/*
1220 * Software interrupt routine, called at splsoftnet.
1221 */
1222void
1223pppintr(void *arg)
1224{
1225	struct ppp_softc *sc = arg;
1226	struct mbuf *m;
1227	int s;
1228
1229	if (!(sc->sc_flags & SC_TBUSY)
1230	    && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head
1231		|| sc->sc_outm)) {
1232		s = splhigh();	/* XXX IMP ME HARDER */
1233		sc->sc_flags |= SC_TBUSY;
1234		splx(s);
1235		(*sc->sc_start)(sc);
1236	}
1237	for (;;) {
1238		s = splnet();
1239		IF_DEQUEUE(&sc->sc_rawq, m);
1240		splx(s);
1241		if (m == NULL)
1242			break;
1243		ppp_inproc(sc, m);
1244	}
1245}
1246
1247#ifdef PPP_COMPRESS
1248/*
1249 * Handle a CCP packet.  `rcvd' is 1 if the packet was received,
1250 * 0 if it is about to be transmitted.
1251 */
1252static void
1253ppp_ccp(sc, m, rcvd)
1254    struct ppp_softc *sc;
1255    struct mbuf *m;
1256    int rcvd;
1257{
1258    u_char *dp, *ep;
1259    struct mbuf *mp;
1260    int slen, s;
1261
1262    /*
1263     * Get a pointer to the data after the PPP header.
1264     */
1265    if (m->m_len <= PPP_HDRLEN) {
1266	mp = m->m_next;
1267	if (mp == NULL)
1268	    return;
1269	dp = (mp != NULL)? mtod(mp, u_char *): NULL;
1270    } else {
1271	mp = m;
1272	dp = mtod(mp, u_char *) + PPP_HDRLEN;
1273    }
1274
1275    ep = mtod(mp, u_char *) + mp->m_len;
1276    if (dp + CCP_HDRLEN > ep)
1277	return;
1278    slen = CCP_LENGTH(dp);
1279    if (dp + slen > ep) {
1280	if (sc->sc_flags & SC_DEBUG)
1281	    printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
1282		dp, slen, mtod(mp, u_char *), mp->m_len);
1283	return;
1284    }
1285
1286    switch (CCP_CODE(dp)) {
1287    case CCP_CONFREQ:
1288    case CCP_TERMREQ:
1289    case CCP_TERMACK:
1290	/* CCP must be going down - disable compression */
1291	if (sc->sc_flags & SC_CCP_UP) {
1292	    s = splhigh();	/* XXX IMP ME HARDER */
1293	    sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
1294	    splx(s);
1295	}
1296	break;
1297
1298    case CCP_CONFACK:
1299	if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
1300	    && slen >= CCP_HDRLEN + CCP_OPT_MINLEN
1301	    && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
1302	    if (!rcvd) {
1303		/* we're agreeing to send compressed packets. */
1304		if (sc->sc_xc_state != NULL
1305		    && (*sc->sc_xcomp->comp_init)
1306			(sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1307			 sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) {
1308		    s = splhigh();	/* XXX IMP ME HARDER */
1309		    sc->sc_flags |= SC_COMP_RUN;
1310		    splx(s);
1311		}
1312	    } else {
1313		/* peer is agreeing to send compressed packets. */
1314		if (sc->sc_rc_state != NULL
1315		    && (*sc->sc_rcomp->decomp_init)
1316			(sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1317			 sc->sc_unit, 0, sc->sc_mru,
1318			 sc->sc_flags & SC_DEBUG)) {
1319		    s = splhigh();	/* XXX IMP ME HARDER */
1320		    sc->sc_flags |= SC_DECOMP_RUN;
1321		    sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
1322		    splx(s);
1323		}
1324	    }
1325	}
1326	break;
1327
1328    case CCP_RESETACK:
1329	if (sc->sc_flags & SC_CCP_UP) {
1330	    if (!rcvd) {
1331		if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
1332		    (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
1333	    } else {
1334		if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1335		    (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
1336		    s = splhigh();	/* XXX IMP ME HARDER */
1337		    sc->sc_flags &= ~SC_DC_ERROR;
1338		    splx(s);
1339		}
1340	    }
1341	}
1342	break;
1343    }
1344}
1345
1346/*
1347 * CCP is down; free (de)compressor state if necessary.
1348 */
1349static void
1350ppp_ccp_closed(sc)
1351    struct ppp_softc *sc;
1352{
1353    if (sc->sc_xc_state) {
1354	(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1355	sc->sc_xc_state = NULL;
1356    }
1357    if (sc->sc_rc_state) {
1358	(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1359	sc->sc_rc_state = NULL;
1360    }
1361}
1362#endif /* PPP_COMPRESS */
1363
1364/*
1365 * PPP packet input routine.
1366 * The caller has checked and removed the FCS and has inserted
1367 * the address/control bytes and the protocol high byte if they
1368 * were omitted.
1369 */
1370void
1371ppppktin(sc, m, lost)
1372    struct ppp_softc *sc;
1373    struct mbuf *m;
1374    int lost;
1375{
1376    int s = splhigh();	/* XXX IMP ME HARDER */
1377
1378    if (lost)
1379	m->m_flags |= M_ERRMARK;
1380    IF_ENQUEUE(&sc->sc_rawq, m);
1381#ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1382    softintr_schedule(sc->sc_si);
1383#else
1384    schednetisr(NETISR_PPP);
1385#endif
1386    splx(s);
1387}
1388
1389/*
1390 * Process a received PPP packet, doing decompression as necessary.
1391 * Should be called at splsoftnet.
1392 */
1393#define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1394			 TYPE_UNCOMPRESSED_TCP)
1395
1396static void
1397ppp_inproc(sc, m)
1398    struct ppp_softc *sc;
1399    struct mbuf *m;
1400{
1401    struct ifnet *ifp = &sc->sc_if;
1402    struct ifqueue *inq;
1403    int s, ilen, proto, rv;
1404    u_char *cp, adrs, ctrl;
1405    struct mbuf *mp, *dmp = NULL;
1406#ifdef VJC
1407    int xlen;
1408    u_char *iphdr;
1409    u_int hlen;
1410#endif
1411
1412    sc->sc_stats.ppp_ipackets++;
1413
1414    if (sc->sc_flags & SC_LOG_INPKT) {
1415	ilen = 0;
1416	for (mp = m; mp != NULL; mp = mp->m_next)
1417	    ilen += mp->m_len;
1418	printf("%s: got %d bytes\n", ifp->if_xname, ilen);
1419	pppdumpm(m);
1420    }
1421
1422    cp = mtod(m, u_char *);
1423    adrs = PPP_ADDRESS(cp);
1424    ctrl = PPP_CONTROL(cp);
1425    proto = PPP_PROTOCOL(cp);
1426
1427    if (m->m_flags & M_ERRMARK) {
1428	m->m_flags &= ~M_ERRMARK;
1429	s = splhigh();	/* XXX IMP ME HARDER */
1430	sc->sc_flags |= SC_VJ_RESET;
1431	splx(s);
1432    }
1433
1434#ifdef PPP_COMPRESS
1435    /*
1436     * Decompress this packet if necessary, update the receiver's
1437     * dictionary, or take appropriate action on a CCP packet.
1438     */
1439    if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
1440	&& !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
1441	/* decompress this packet */
1442	rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1443	if (rv == DECOMP_OK) {
1444	    m_freem(m);
1445	    if (dmp == NULL) {
1446		/* no error, but no decompressed packet produced */
1447		return;
1448	    }
1449	    m = dmp;
1450	    cp = mtod(m, u_char *);
1451	    proto = PPP_PROTOCOL(cp);
1452
1453	} else {
1454	    /*
1455	     * An error has occurred in decompression.
1456	     * Pass the compressed packet up to pppd, which may take
1457	     * CCP down or issue a Reset-Req.
1458	     */
1459	    if (sc->sc_flags & SC_DEBUG)
1460		printf("%s: decompress failed %d\n", ifp->if_xname, rv);
1461	    s = splhigh();	/* XXX IMP ME HARDER */
1462	    sc->sc_flags |= SC_VJ_RESET;
1463	    if (rv == DECOMP_ERROR)
1464		sc->sc_flags |= SC_DC_ERROR;
1465	    else
1466		sc->sc_flags |= SC_DC_FERROR;
1467	    splx(s);
1468	}
1469
1470    } else {
1471	if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1472	    (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1473	}
1474	if (proto == PPP_CCP) {
1475	    ppp_ccp(sc, m, 1);
1476	}
1477    }
1478#endif
1479
1480    ilen = 0;
1481    for (mp = m; mp != NULL; mp = mp->m_next)
1482	ilen += mp->m_len;
1483
1484#ifdef VJC
1485    if (sc->sc_flags & SC_VJ_RESET) {
1486	/*
1487	 * If we've missed a packet, we must toss subsequent compressed
1488	 * packets which don't have an explicit connection ID.
1489	 */
1490	if (sc->sc_comp)
1491	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
1492	s = splhigh();	/* XXX IMP ME HARDER */
1493	sc->sc_flags &= ~SC_VJ_RESET;
1494	splx(s);
1495    }
1496
1497    /*
1498     * See if we have a VJ-compressed packet to uncompress.
1499     */
1500    if (proto == PPP_VJC_COMP) {
1501	if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1502	    goto bad;
1503
1504	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1505				      ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
1506				      sc->sc_comp, &iphdr, &hlen);
1507
1508	if (xlen <= 0) {
1509	    if (sc->sc_flags & SC_DEBUG)
1510		printf("%s: VJ uncompress failed on type comp\n",
1511		    ifp->if_xname);
1512	    goto bad;
1513	}
1514
1515	/* Copy the PPP and IP headers into a new mbuf. */
1516	MGETHDR(mp, M_DONTWAIT, MT_DATA);
1517	if (mp == NULL)
1518	    goto bad;
1519	mp->m_len = 0;
1520	mp->m_next = NULL;
1521	if (hlen + PPP_HDRLEN > MHLEN) {
1522	    MCLGET(mp, M_DONTWAIT);
1523	    if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
1524		m_freem(mp);
1525		goto bad;	/* lose if big headers and no clusters */
1526	    }
1527	}
1528	cp = mtod(mp, u_char *);
1529	cp[0] = adrs;
1530	cp[1] = ctrl;
1531	cp[2] = 0;
1532	cp[3] = PPP_IP;
1533	proto = PPP_IP;
1534	bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1535	mp->m_len = hlen + PPP_HDRLEN;
1536
1537	/*
1538	 * Trim the PPP and VJ headers off the old mbuf
1539	 * and stick the new and old mbufs together.
1540	 */
1541	m->m_data += PPP_HDRLEN + xlen;
1542	m->m_len -= PPP_HDRLEN + xlen;
1543	if (m->m_len <= M_TRAILINGSPACE(mp)) {
1544	    bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
1545	    mp->m_len += m->m_len;
1546	    MFREE(m, mp->m_next);
1547	} else
1548	    mp->m_next = m;
1549	m = mp;
1550	ilen += hlen - xlen;
1551
1552    } else if (proto == PPP_VJC_UNCOMP) {
1553	if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1554	    goto bad;
1555
1556	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1557				      ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
1558				      sc->sc_comp, &iphdr, &hlen);
1559
1560	if (xlen < 0) {
1561	    if (sc->sc_flags & SC_DEBUG)
1562		printf("%s: VJ uncompress failed on type uncomp\n",
1563		    ifp->if_xname);
1564	    goto bad;
1565	}
1566
1567	proto = PPP_IP;
1568	cp[3] = PPP_IP;
1569    }
1570#endif /* VJC */
1571
1572    /*
1573     * If the packet will fit in a header mbuf, don't waste a
1574     * whole cluster on it.
1575     */
1576    if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
1577	MGETHDR(mp, M_DONTWAIT, MT_DATA);
1578	if (mp != NULL) {
1579	    m_copydata(m, 0, ilen, mtod(mp, caddr_t));
1580	    m_freem(m);
1581	    m = mp;
1582	    m->m_len = ilen;
1583	}
1584    }
1585    m->m_pkthdr.len = ilen;
1586    m->m_pkthdr.rcvif = ifp;
1587
1588    if ((proto & 0x8000) == 0) {
1589#ifdef PPP_FILTER
1590	/*
1591	 * See whether we want to pass this packet, and
1592	 * if it counts as link activity.
1593	 */
1594	if (sc->sc_pass_filt_in.bf_insns != 0
1595	    && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m,
1596			  ilen, 0) == 0) {
1597	    /* drop this packet */
1598	    m_freem(m);
1599	    return;
1600	}
1601	if (sc->sc_active_filt_in.bf_insns == 0
1602	    || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m,
1603	    		  ilen, 0))
1604	    sc->sc_last_recv = time.tv_sec;
1605#else
1606	/*
1607	 * Record the time that we received this packet.
1608	 */
1609	sc->sc_last_recv = time.tv_sec;
1610#endif /* PPP_FILTER */
1611    }
1612
1613#if NBPFILTER > 0
1614    /* See if bpf wants to look at the packet. */
1615    if (sc->sc_if.if_bpf)
1616	bpf_mtap(sc->sc_if.if_bpf, m);
1617#endif
1618
1619    rv = 0;
1620    switch (proto) {
1621#ifdef INET
1622    case PPP_IP:
1623	/*
1624	 * IP packet - take off the ppp header and pass it up to IP.
1625	 */
1626	if ((ifp->if_flags & IFF_UP) == 0
1627	    || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1628	    /* interface is down - drop the packet. */
1629	    m_freem(m);
1630	    return;
1631	}
1632	m->m_pkthdr.len -= PPP_HDRLEN;
1633	m->m_data += PPP_HDRLEN;
1634	m->m_len -= PPP_HDRLEN;
1635#ifdef GATEWAY
1636	if (ipflow_fastforward(m))
1637		return;
1638#endif
1639	schednetisr(NETISR_IP);
1640	inq = &ipintrq;
1641	break;
1642#endif
1643
1644#ifdef INET6
1645    case PPP_IPV6:
1646	/*
1647	 * IPv6 packet - take off the ppp header and pass it up to IPv6.
1648	 */
1649	if ((ifp->if_flags & IFF_UP) == 0
1650	    || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) {
1651	    /* interface is down - drop the packet. */
1652	    m_freem(m);
1653	    return;
1654	}
1655	m->m_pkthdr.len -= PPP_HDRLEN;
1656	m->m_data += PPP_HDRLEN;
1657	m->m_len -= PPP_HDRLEN;
1658	schednetisr(NETISR_IPV6);
1659	inq = &ip6intrq;
1660	break;
1661#endif
1662
1663    default:
1664	/*
1665	 * Some other protocol - place on input queue for read().
1666	 */
1667	inq = &sc->sc_inq;
1668	rv = 1;
1669	break;
1670    }
1671
1672    /*
1673     * Put the packet on the appropriate input queue.
1674     */
1675    s = splnet();
1676    if (IF_QFULL(inq)) {
1677	IF_DROP(inq);
1678	splx(s);
1679	if (sc->sc_flags & SC_DEBUG)
1680	    printf("%s: input queue full\n", ifp->if_xname);
1681	ifp->if_iqdrops++;
1682	goto bad;
1683    }
1684    IF_ENQUEUE(inq, m);
1685    splx(s);
1686    ifp->if_ipackets++;
1687    ifp->if_ibytes += ilen;
1688
1689    if (rv)
1690	(*sc->sc_ctlp)(sc);
1691
1692    return;
1693
1694 bad:
1695    m_freem(m);
1696    sc->sc_if.if_ierrors++;
1697    sc->sc_stats.ppp_ierrors++;
1698}
1699
1700#define MAX_DUMP_BYTES	128
1701
1702static void
1703pppdumpm(m0)
1704    struct mbuf *m0;
1705{
1706    char buf[3*MAX_DUMP_BYTES+4];
1707    char *bp = buf;
1708    struct mbuf *m;
1709    static char digits[] = "0123456789abcdef";
1710
1711    for (m = m0; m; m = m->m_next) {
1712	int l = m->m_len;
1713	u_char *rptr = (u_char *)m->m_data;
1714
1715	while (l--) {
1716	    if (bp > buf + sizeof(buf) - 4)
1717		goto done;
1718	    *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
1719	    *bp++ = digits[*rptr++ & 0xf];
1720	}
1721
1722	if (m->m_next) {
1723	    if (bp > buf + sizeof(buf) - 3)
1724		goto done;
1725	    *bp++ = '|';
1726	} else
1727	    *bp++ = ' ';
1728    }
1729done:
1730    if (m)
1731	*bp++ = '>';
1732    *bp = 0;
1733    printf("%s\n", buf);
1734}
1735
1736#ifdef ALTQ
1737/*
1738 * a wrapper to transmit a packet from if_start since ALTQ uses
1739 * if_start to send a packet.
1740 */
1741static void
1742ppp_ifstart(ifp)
1743	struct ifnet *ifp;
1744{
1745	struct ppp_softc *sc;
1746
1747	sc = ifp->if_softc;
1748	(*sc->sc_start)(sc);
1749}
1750#endif
1751