1/*	$NetBSD$	*/
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$");
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#include <sys/module.h>
128#include <sys/mutex.h>
129#include <sys/once.h>
130#include <sys/conf.h>
131#include <sys/kauth.h>
132#include <sys/intr.h>
133#include <sys/socketvar.h>
134
135#include <net/if.h>
136#include <net/if_types.h>
137#include <net/netisr.h>
138#include <net/route.h>
139#ifdef PPP_FILTER
140#include <net/bpf.h>
141#endif
142
143#include <netinet/in.h>
144#include <netinet/in_systm.h>
145#include <netinet/in_var.h>
146#ifdef INET
147#include <netinet/ip.h>
148#endif
149
150#include <net/bpf.h>
151
152#include <net/slip.h>
153
154#ifdef VJC
155#include <net/slcompress.h>
156#endif
157
158#include <net/ppp_defs.h>
159#include <net/if_ppp.h>
160#include <net/if_pppvar.h>
161#include <sys/cpu.h>
162
163#ifdef PPP_COMPRESS
164#define PACKETPTR	struct mbuf *
165#include <net/ppp-comp.h>
166#endif
167
168static int	pppsioctl(struct ifnet *, u_long, void *);
169static void	ppp_requeue(struct ppp_softc *);
170static void	ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
171static void	ppp_ccp_closed(struct ppp_softc *);
172static void	ppp_inproc(struct ppp_softc *, struct mbuf *);
173static void	pppdumpm(struct mbuf *m0);
174#ifdef ALTQ
175static void	ppp_ifstart(struct ifnet *ifp);
176#endif
177
178static void	pppintr(void *);
179
180/*
181 * Some useful mbuf macros not in mbuf.h.
182 */
183#define M_IS_CLUSTER(m)	((m)->m_flags & M_EXT)
184
185#define M_DATASTART(m)	\
186	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
187	    (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
188
189#define M_DATASIZE(m)	\
190	(M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
191	    (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
192
193/*
194 * We define two link layer specific mbuf flags, to mark high-priority
195 * packets for output, and received packets following lost/corrupted
196 * packets.
197 */
198#define	M_HIGHPRI	M_LINK0	/* output packet for sc_fastq */
199#define	M_ERRMARK	M_LINK1	/* rx packet following lost/corrupted pkt */
200
201static int		ppp_clone_create(struct if_clone *, int);
202static int		ppp_clone_destroy(struct ifnet *);
203
204static struct ppp_softc *ppp_create(const char *, int);
205
206static LIST_HEAD(, ppp_softc) ppp_softc_list;
207static kmutex_t ppp_list_lock;
208
209struct if_clone ppp_cloner =
210    IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy);
211
212#ifdef PPP_COMPRESS
213ONCE_DECL(ppp_compressor_mtx_init);
214static LIST_HEAD(, compressor) ppp_compressors = { NULL };
215static kmutex_t ppp_compressors_mtx;
216
217static int ppp_compressor_init(void);
218static struct compressor *ppp_get_compressor(uint8_t);
219static void ppp_compressor_rele(struct compressor *);
220#endif /* PPP_COMPRESS */
221
222
223/*
224 * Called from boot code to establish ppp interfaces.
225 */
226void
227pppattach(void)
228{
229    extern struct linesw ppp_disc;
230
231    if (ttyldisc_attach(&ppp_disc) != 0)
232    	panic("pppattach");
233
234    mutex_init(&ppp_list_lock, MUTEX_DEFAULT, IPL_NONE);
235    LIST_INIT(&ppp_softc_list);
236    if_clone_attach(&ppp_cloner);
237    RUN_ONCE(&ppp_compressor_mtx_init, ppp_compressor_init);
238}
239
240static struct ppp_softc *
241ppp_create(const char *name, int unit)
242{
243    struct ppp_softc *sc, *sci, *scl = NULL;
244
245    sc = malloc(sizeof(*sc), M_DEVBUF, M_WAIT|M_ZERO);
246
247    mutex_enter(&ppp_list_lock);
248    if (unit == -1) {
249	int i = 0;
250	LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) {
251	    scl = sci;
252	    if (i < sci->sc_unit) {
253		unit = i;
254		break;
255	    } else {
256#ifdef DIAGNOSTIC
257		KASSERT(i == sci->sc_unit);
258#endif
259		i++;
260	    }
261	}
262	if (unit == -1)
263	    unit = i;
264    } else {
265	LIST_FOREACH(sci, &ppp_softc_list, sc_iflist) {
266	    scl = sci;
267	    if (unit < sci->sc_unit)
268		break;
269	    else if (unit == sci->sc_unit) {
270		free(sc, M_DEVBUF);
271		return NULL;
272	    }
273	}
274    }
275
276    if (sci != NULL)
277	LIST_INSERT_BEFORE(sci, sc, sc_iflist);
278    else if (scl != NULL)
279	LIST_INSERT_AFTER(scl, sc, sc_iflist);
280    else
281	LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_iflist);
282
283    mutex_exit(&ppp_list_lock);
284
285    if_initname(&sc->sc_if, name, sc->sc_unit = unit);
286    callout_init(&sc->sc_timo_ch, 0);
287    sc->sc_if.if_softc = sc;
288    sc->sc_if.if_mtu = PPP_MTU;
289    sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
290    sc->sc_if.if_type = IFT_PPP;
291    sc->sc_if.if_hdrlen = PPP_HDRLEN;
292    sc->sc_if.if_dlt = DLT_NULL;
293    sc->sc_if.if_ioctl = pppsioctl;
294    sc->sc_if.if_output = pppoutput;
295#ifdef ALTQ
296    sc->sc_if.if_start = ppp_ifstart;
297#endif
298    IFQ_SET_MAXLEN(&sc->sc_if.if_snd, IFQ_MAXLEN);
299    sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
300    sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
301    sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
302    /* Ratio of 1:2 packets between the regular and the fast queue */
303    sc->sc_maxfastq = 2;
304    IFQ_SET_READY(&sc->sc_if.if_snd);
305    if_attach(&sc->sc_if);
306    if_alloc_sadl(&sc->sc_if);
307    bpf_attach(&sc->sc_if, DLT_NULL, 0);
308    return sc;
309}
310
311static int
312ppp_clone_create(struct if_clone *ifc, int unit)
313{
314    return ppp_create(ifc->ifc_name, unit) == NULL ? EEXIST : 0;
315}
316
317static int
318ppp_clone_destroy(struct ifnet *ifp)
319{
320    struct ppp_softc *sc = (struct ppp_softc *)ifp->if_softc;
321
322    if (sc->sc_devp != NULL)
323	return EBUSY; /* Not removing it */
324
325    mutex_enter(&ppp_list_lock);
326    LIST_REMOVE(sc, sc_iflist);
327    mutex_exit(&ppp_list_lock);
328
329    bpf_detach(ifp);
330    if_detach(ifp);
331
332    free(sc, M_DEVBUF);
333    return 0;
334}
335
336/*
337 * Allocate a ppp interface unit and initialize it.
338 */
339struct ppp_softc *
340pppalloc(pid_t pid)
341{
342    struct ppp_softc *sc = NULL, *scf;
343    int i;
344
345    mutex_enter(&ppp_list_lock);
346    LIST_FOREACH(scf, &ppp_softc_list, sc_iflist) {
347	if (scf->sc_xfer == pid) {
348	    scf->sc_xfer = 0;
349	    mutex_exit(&ppp_list_lock);
350	    return scf;
351	}
352	if (scf->sc_devp == NULL && sc == NULL)
353	    sc = scf;
354    }
355    mutex_exit(&ppp_list_lock);
356
357    if (sc == NULL)
358	sc = ppp_create(ppp_cloner.ifc_name, -1);
359
360    sc->sc_si = softint_establish(SOFTINT_NET, pppintr, sc);
361    if (sc->sc_si == NULL) {
362	printf("%s: unable to establish softintr\n", sc->sc_if.if_xname);
363	return (NULL);
364    }
365    sc->sc_flags = 0;
366    sc->sc_mru = PPP_MRU;
367    sc->sc_relinq = NULL;
368    (void)memset(&sc->sc_stats, 0, sizeof(sc->sc_stats));
369#ifdef VJC
370    sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT);
371    if (sc->sc_comp)
372	sl_compress_init(sc->sc_comp);
373#endif
374#ifdef PPP_COMPRESS
375    sc->sc_xc_state = NULL;
376    sc->sc_rc_state = NULL;
377#endif /* PPP_COMPRESS */
378    for (i = 0; i < NUM_NP; ++i)
379	sc->sc_npmode[i] = NPMODE_ERROR;
380    sc->sc_npqueue = NULL;
381    sc->sc_npqtail = &sc->sc_npqueue;
382    sc->sc_last_sent = sc->sc_last_recv = time_second;
383
384    return sc;
385}
386
387/*
388 * Deallocate a ppp unit.  Must be called at splsoftnet or higher.
389 */
390void
391pppdealloc(struct ppp_softc *sc)
392{
393    struct mbuf *m;
394
395    softint_disestablish(sc->sc_si);
396    if_down(&sc->sc_if);
397    sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
398    sc->sc_devp = NULL;
399    sc->sc_xfer = 0;
400    for (;;) {
401	IF_DEQUEUE(&sc->sc_rawq, m);
402	if (m == NULL)
403	    break;
404	m_freem(m);
405    }
406    for (;;) {
407	IF_DEQUEUE(&sc->sc_inq, m);
408	if (m == NULL)
409	    break;
410	m_freem(m);
411    }
412    for (;;) {
413	IF_DEQUEUE(&sc->sc_fastq, m);
414	if (m == NULL)
415	    break;
416	m_freem(m);
417    }
418    while ((m = sc->sc_npqueue) != NULL) {
419	sc->sc_npqueue = m->m_nextpkt;
420	m_freem(m);
421    }
422    if (sc->sc_togo != NULL) {
423	m_freem(sc->sc_togo);
424	sc->sc_togo = NULL;
425    }
426#ifdef PPP_COMPRESS
427    ppp_ccp_closed(sc);
428    sc->sc_xc_state = NULL;
429    sc->sc_rc_state = NULL;
430#endif /* PPP_COMPRESS */
431#ifdef PPP_FILTER
432    if (sc->sc_pass_filt_in.bf_insns != 0) {
433	free(sc->sc_pass_filt_in.bf_insns, M_DEVBUF);
434	sc->sc_pass_filt_in.bf_insns = 0;
435	sc->sc_pass_filt_in.bf_len = 0;
436    }
437    if (sc->sc_pass_filt_out.bf_insns != 0) {
438	free(sc->sc_pass_filt_out.bf_insns, M_DEVBUF);
439	sc->sc_pass_filt_out.bf_insns = 0;
440	sc->sc_pass_filt_out.bf_len = 0;
441    }
442    if (sc->sc_active_filt_in.bf_insns != 0) {
443	free(sc->sc_active_filt_in.bf_insns, M_DEVBUF);
444	sc->sc_active_filt_in.bf_insns = 0;
445	sc->sc_active_filt_in.bf_len = 0;
446    }
447    if (sc->sc_active_filt_out.bf_insns != 0) {
448	free(sc->sc_active_filt_out.bf_insns, M_DEVBUF);
449	sc->sc_active_filt_out.bf_insns = 0;
450	sc->sc_active_filt_out.bf_len = 0;
451    }
452#endif /* PPP_FILTER */
453#ifdef VJC
454    if (sc->sc_comp != 0) {
455	free(sc->sc_comp, M_DEVBUF);
456	sc->sc_comp = 0;
457    }
458#endif
459    (void)ppp_clone_destroy(&sc->sc_if);
460}
461
462/*
463 * Ioctl routine for generic ppp devices.
464 */
465int
466pppioctl(struct ppp_softc *sc, u_long cmd, void *data, int flag,
467    struct lwp *l)
468{
469    int s, error, flags, mru, npx;
470    u_int nb;
471    struct ppp_option_data *odp;
472    struct compressor *cp;
473    struct npioctl *npi;
474    time_t t;
475#ifdef PPP_FILTER
476    struct bpf_program *bp, *nbp;
477    struct bpf_insn *newcode, *oldcode;
478    int newcodelen;
479#endif /* PPP_FILTER */
480#ifdef	PPP_COMPRESS
481    u_char ccp_option[CCP_MAX_OPTION_LENGTH];
482#endif
483
484    switch (cmd) {
485    case PPPIOCSFLAGS:
486    case PPPIOCSMRU:
487    case PPPIOCSMAXCID:
488    case PPPIOCSCOMPRESS:
489    case PPPIOCSNPMODE:
490	if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
491	    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, &sc->sc_if, KAUTH_ARG(cmd),
492	    NULL) != 0)
493		return (EPERM);
494	break;
495    case PPPIOCXFERUNIT:
496	/* XXX: Why is this privileged?! */
497	if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
498	    KAUTH_REQ_NETWORK_INTERFACE_GETPRIV, &sc->sc_if, KAUTH_ARG(cmd),
499	    NULL) != 0)
500		return (EPERM);
501	break;
502    default:
503	break;
504    }
505
506    switch (cmd) {
507    case FIONREAD:
508	*(int *)data = sc->sc_inq.ifq_len;
509	break;
510
511    case PPPIOCGUNIT:
512	*(int *)data = sc->sc_unit;
513	break;
514
515    case PPPIOCGFLAGS:
516	*(u_int *)data = sc->sc_flags;
517	break;
518
519    case PPPIOCGRAWIN:
520	{
521	    struct ppp_rawin *rwin = (struct ppp_rawin *)data;
522	    u_char c, q = 0;
523
524	    for (c = sc->sc_rawin_start; c < sizeof(sc->sc_rawin.buf);)
525		rwin->buf[q++] = sc->sc_rawin.buf[c++];
526
527	    for (c = 0; c < sc->sc_rawin_start;)
528		rwin->buf[q++] = sc->sc_rawin.buf[c++];
529
530	    rwin->count = sc->sc_rawin.count;
531	}
532	break;
533
534    case PPPIOCSFLAGS:
535	flags = *(int *)data & SC_MASK;
536	s = splsoftnet();
537#ifdef PPP_COMPRESS
538	if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
539	    ppp_ccp_closed(sc);
540#endif
541	splhigh();	/* XXX IMP ME HARDER */
542	sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
543	splx(s);
544	break;
545
546    case PPPIOCSMRU:
547	mru = *(int *)data;
548	if (mru >= PPP_MINMRU && mru <= PPP_MAXMRU)
549	    sc->sc_mru = mru;
550	break;
551
552    case PPPIOCGMRU:
553	*(int *)data = sc->sc_mru;
554	break;
555
556#ifdef VJC
557    case PPPIOCSMAXCID:
558	if (sc->sc_comp) {
559	    s = splsoftnet();
560	    sl_compress_setup(sc->sc_comp, *(int *)data);
561	    splx(s);
562	}
563	break;
564#endif
565
566    case PPPIOCXFERUNIT:
567	sc->sc_xfer = l->l_proc->p_pid;
568	break;
569
570#ifdef PPP_COMPRESS
571    case PPPIOCSCOMPRESS:
572	odp = (struct ppp_option_data *) data;
573	nb = odp->length;
574	if (nb > sizeof(ccp_option))
575	    nb = sizeof(ccp_option);
576	if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
577	    return (error);
578	if (ccp_option[1] < 2)	/* preliminary check on the length byte */
579	    return (EINVAL);
580	cp = ppp_get_compressor(ccp_option[0]);
581	if (cp == NULL) {
582		if (sc->sc_flags & SC_DEBUG)
583		    printf("%s: no compressor for [%x %x %x], %x\n",
584			sc->sc_if.if_xname, ccp_option[0], ccp_option[1],
585			ccp_option[2], nb);
586		return (EINVAL);	/* no handler found */
587	}
588	/*
589	 * Found a handler for the protocol - try to allocate
590	 * a compressor or decompressor.
591	 */
592	error = 0;
593	if (odp->transmit) {
594	    s = splsoftnet();
595	    if (sc->sc_xc_state != NULL) {
596		(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
597		ppp_compressor_rele(sc->sc_xcomp);
598	    }
599	    sc->sc_xcomp = cp;
600	    sc->sc_xc_state = cp->comp_alloc(ccp_option, nb);
601	    if (sc->sc_xc_state == NULL) {
602		if (sc->sc_flags & SC_DEBUG)
603		    printf("%s: comp_alloc failed\n",
604			sc->sc_if.if_xname);
605		error = ENOBUFS;
606	    }
607	    splhigh();	/* XXX IMP ME HARDER */
608	    sc->sc_flags &= ~SC_COMP_RUN;
609	    splx(s);
610	} else {
611	    s = splsoftnet();
612	    if (sc->sc_rc_state != NULL) {
613		(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
614		ppp_compressor_rele(sc->sc_rcomp);
615	    }
616	    sc->sc_rcomp = cp;
617	    sc->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
618	    if (sc->sc_rc_state == NULL) {
619		if (sc->sc_flags & SC_DEBUG)
620		    printf("%s: decomp_alloc failed\n",
621			sc->sc_if.if_xname);
622		error = ENOBUFS;
623	    }
624	    splhigh();	/* XXX IMP ME HARDER */
625	    sc->sc_flags &= ~SC_DECOMP_RUN;
626	    splx(s);
627	}
628	return (error);
629#endif /* PPP_COMPRESS */
630
631    case PPPIOCGNPMODE:
632    case PPPIOCSNPMODE:
633	npi = (struct npioctl *) data;
634	switch (npi->protocol) {
635	case PPP_IP:
636	    npx = NP_IP;
637	    break;
638	case PPP_IPV6:
639	    npx = NP_IPV6;
640	    break;
641	default:
642	    return EINVAL;
643	}
644	if (cmd == PPPIOCGNPMODE) {
645	    npi->mode = sc->sc_npmode[npx];
646	} else {
647	    if (npi->mode != sc->sc_npmode[npx]) {
648		s = splnet();
649		sc->sc_npmode[npx] = npi->mode;
650		if (npi->mode != NPMODE_QUEUE) {
651		    ppp_requeue(sc);
652		    ppp_restart(sc);
653		}
654		splx(s);
655	    }
656	}
657	break;
658
659    case PPPIOCGIDLE:
660	s = splsoftnet();
661	t = time_second;
662	((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
663	((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
664	splx(s);
665	break;
666
667#ifdef PPP_FILTER
668    case PPPIOCSPASS:
669    case PPPIOCSACTIVE:
670	/* These are no longer supported. */
671	return EOPNOTSUPP;
672
673    case PPPIOCSIPASS:
674    case PPPIOCSOPASS:
675    case PPPIOCSIACTIVE:
676    case PPPIOCSOACTIVE:
677	nbp = (struct bpf_program *) data;
678	if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
679	    return EINVAL;
680	newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
681	if (newcodelen != 0) {
682	    newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK);
683	    /* WAITOK -- malloc() never fails. */
684	    if ((error = copyin((void *)nbp->bf_insns, (void *)newcode,
685			       newcodelen)) != 0) {
686		free(newcode, M_DEVBUF);
687		return error;
688	    }
689	    if (!bpf_validate(newcode, nbp->bf_len)) {
690		free(newcode, M_DEVBUF);
691		return EINVAL;
692	    }
693	} else
694	    newcode = 0;
695	switch (cmd) {
696	case PPPIOCSIPASS:
697	    bp = &sc->sc_pass_filt_in;
698	    break;
699
700	case PPPIOCSOPASS:
701	    bp = &sc->sc_pass_filt_out;
702	    break;
703
704	case PPPIOCSIACTIVE:
705	    bp = &sc->sc_active_filt_in;
706	    break;
707
708	case PPPIOCSOACTIVE:
709	    bp = &sc->sc_active_filt_out;
710	    break;
711	default:
712	    free(newcode, M_DEVBUF);
713	    return (EPASSTHROUGH);
714	}
715	oldcode = bp->bf_insns;
716	s = splnet();
717	bp->bf_len = nbp->bf_len;
718	bp->bf_insns = newcode;
719	splx(s);
720	if (oldcode != 0)
721	    free(oldcode, M_DEVBUF);
722	break;
723#endif /* PPP_FILTER */
724
725    default:
726	return (EPASSTHROUGH);
727    }
728    return (0);
729}
730
731/*
732 * Process an ioctl request to the ppp network interface.
733 */
734static int
735pppsioctl(struct ifnet *ifp, u_long cmd, void *data)
736{
737    struct ppp_softc *sc = ifp->if_softc;
738    struct ifaddr *ifa = (struct ifaddr *)data;
739    struct ifreq *ifr = (struct ifreq *)data;
740    struct ppp_stats *psp;
741#ifdef	PPP_COMPRESS
742    struct ppp_comp_stats *pcp;
743#endif
744    int s = splnet(), error = 0;
745
746    switch (cmd) {
747    case SIOCSIFFLAGS:
748	if ((error = ifioctl_common(ifp, cmd, data)) != 0)
749		break;
750	if ((ifp->if_flags & IFF_RUNNING) == 0)
751	    ifp->if_flags &= ~IFF_UP;
752	break;
753
754    case SIOCINITIFADDR:
755	switch (ifa->ifa_addr->sa_family) {
756#ifdef INET
757	case AF_INET:
758	    break;
759#endif
760#ifdef INET6
761	case AF_INET6:
762	    break;
763#endif
764	default:
765	    error = EAFNOSUPPORT;
766	    break;
767	}
768	break;
769
770    case SIOCADDMULTI:
771    case SIOCDELMULTI:
772	if (ifr == NULL) {
773	    error = EAFNOSUPPORT;
774	    break;
775	}
776	switch (ifreq_getaddr(cmd, ifr)->sa_family) {
777#ifdef INET
778	case AF_INET:
779	    break;
780#endif
781#ifdef INET6
782	case AF_INET6:
783	    break;
784#endif
785	default:
786	    error = EAFNOSUPPORT;
787	    break;
788	}
789	break;
790
791    case SIOCGPPPSTATS:
792	psp = &((struct ifpppstatsreq *) data)->stats;
793	memset(psp, 0, sizeof(*psp));
794	psp->p = sc->sc_stats;
795#if defined(VJC) && !defined(SL_NO_STATS)
796	if (sc->sc_comp) {
797	    psp->vj.vjs_packets = sc->sc_comp->sls_packets;
798	    psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
799	    psp->vj.vjs_searches = sc->sc_comp->sls_searches;
800	    psp->vj.vjs_misses = sc->sc_comp->sls_misses;
801	    psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
802	    psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
803	    psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
804	    psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
805	}
806#endif /* VJC */
807	break;
808
809#ifdef PPP_COMPRESS
810    case SIOCGPPPCSTATS:
811	pcp = &((struct ifpppcstatsreq *) data)->stats;
812	memset(pcp, 0, sizeof(*pcp));
813	if (sc->sc_xc_state != NULL)
814	    (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
815	if (sc->sc_rc_state != NULL)
816	    (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
817	break;
818#endif /* PPP_COMPRESS */
819
820    default:
821	if ((error = ifioctl_common(&sc->sc_if, cmd, data)) == ENETRESET)
822		error = 0;
823	break;
824    }
825    splx(s);
826    return (error);
827}
828
829/*
830 * Queue a packet.  Start transmission if not active.
831 * Packet is placed in Information field of PPP frame.
832 */
833int
834pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
835    struct rtentry *rtp)
836{
837    struct ppp_softc *sc = ifp->if_softc;
838    int protocol, address, control;
839    u_char *cp;
840    int s, error;
841#ifdef INET
842    struct ip *ip;
843#endif
844    struct ifqueue *ifq;
845    enum NPmode mode;
846    int len;
847    ALTQ_DECL(struct altq_pktattr pktattr;)
848
849    if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
850	|| ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
851	error = ENETDOWN;	/* sort of */
852	goto bad;
853    }
854
855    IFQ_CLASSIFY(&ifp->if_snd, m0, dst->sa_family, &pktattr);
856
857    /*
858     * Compute PPP header.
859     */
860    m0->m_flags &= ~M_HIGHPRI;
861    switch (dst->sa_family) {
862#ifdef INET
863    case AF_INET:
864	address = PPP_ALLSTATIONS;
865	control = PPP_UI;
866	protocol = PPP_IP;
867	mode = sc->sc_npmode[NP_IP];
868
869	/*
870	 * If this packet has the "low delay" bit set in the IP header,
871	 * put it on the fastq instead.
872	 */
873	ip = mtod(m0, struct ip *);
874	if (ip->ip_tos & IPTOS_LOWDELAY)
875	    m0->m_flags |= M_HIGHPRI;
876	break;
877#endif
878#ifdef INET6
879    case AF_INET6:
880	address = PPP_ALLSTATIONS;	/*XXX*/
881	control = PPP_UI;		/*XXX*/
882	protocol = PPP_IPV6;
883	mode = sc->sc_npmode[NP_IPV6];
884
885#if 0	/* XXX flowinfo/traffic class, maybe? */
886	/*
887	 * If this packet has the "low delay" bit set in the IP header,
888	 * put it on the fastq instead.
889	 */
890	ip = mtod(m0, struct ip *);
891	if (ip->ip_tos & IPTOS_LOWDELAY)
892	    m0->m_flags |= M_HIGHPRI;
893#endif
894	break;
895#endif
896    case AF_UNSPEC:
897	address = PPP_ADDRESS(dst->sa_data);
898	control = PPP_CONTROL(dst->sa_data);
899	protocol = PPP_PROTOCOL(dst->sa_data);
900	mode = NPMODE_PASS;
901	break;
902    default:
903	printf("%s: af%d not supported\n", ifp->if_xname, dst->sa_family);
904	error = EAFNOSUPPORT;
905	goto bad;
906    }
907
908    /*
909     * Drop this packet, or return an error, if necessary.
910     */
911    if (mode == NPMODE_ERROR) {
912	error = ENETDOWN;
913	goto bad;
914    }
915    if (mode == NPMODE_DROP) {
916	error = 0;
917	goto bad;
918    }
919
920    /*
921     * Add PPP header.
922     */
923    M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT);
924    if (m0 == NULL) {
925	error = ENOBUFS;
926	goto bad;
927    }
928
929    cp = mtod(m0, u_char *);
930    *cp++ = address;
931    *cp++ = control;
932    *cp++ = protocol >> 8;
933    *cp++ = protocol & 0xff;
934
935    len = m_length(m0);
936
937    if (sc->sc_flags & SC_LOG_OUTPKT) {
938	printf("%s output: ", ifp->if_xname);
939	pppdumpm(m0);
940    }
941
942    if ((protocol & 0x8000) == 0) {
943#ifdef PPP_FILTER
944	/*
945	 * Apply the pass and active filters to the packet,
946	 * but only if it is a data packet.
947	 */
948	if (sc->sc_pass_filt_out.bf_insns != 0
949	    && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0,
950			  len, 0) == 0) {
951	    error = 0;		/* drop this packet */
952	    goto bad;
953	}
954
955	/*
956	 * Update the time we sent the most recent packet.
957	 */
958	if (sc->sc_active_filt_out.bf_insns == 0
959	    || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0,
960	    		  len, 0))
961	    sc->sc_last_sent = time_second;
962#else
963	/*
964	 * Update the time we sent the most recent packet.
965	 */
966	sc->sc_last_sent = time_second;
967#endif /* PPP_FILTER */
968    }
969
970    /*
971     * See if bpf wants to look at the packet.
972     */
973    bpf_mtap(&sc->sc_if, m0);
974
975    /*
976     * Put the packet on the appropriate queue.
977     */
978    s = splnet();
979    if (mode == NPMODE_QUEUE) {
980	/* XXX we should limit the number of packets on this queue */
981	*sc->sc_npqtail = m0;
982	m0->m_nextpkt = NULL;
983	sc->sc_npqtail = &m0->m_nextpkt;
984    } else {
985	ifq = (m0->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL;
986	if ((error = ifq_enqueue2(&sc->sc_if, ifq, m0
987		ALTQ_COMMA ALTQ_DECL(&pktattr))) != 0) {
988	    splx(s);
989	    sc->sc_if.if_oerrors++;
990	    sc->sc_stats.ppp_oerrors++;
991	    return (error);
992	}
993	ppp_restart(sc);
994    }
995    ifp->if_opackets++;
996    ifp->if_obytes += len;
997
998    splx(s);
999    return (0);
1000
1001bad:
1002    m_freem(m0);
1003    return (error);
1004}
1005
1006/*
1007 * After a change in the NPmode for some NP, move packets from the
1008 * npqueue to the send queue or the fast queue as appropriate.
1009 * Should be called at splnet, since we muck with the queues.
1010 */
1011static void
1012ppp_requeue(struct ppp_softc *sc)
1013{
1014    struct mbuf *m, **mpp;
1015    struct ifqueue *ifq;
1016    enum NPmode mode;
1017    int error;
1018
1019    for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
1020	switch (PPP_PROTOCOL(mtod(m, u_char *))) {
1021	case PPP_IP:
1022	    mode = sc->sc_npmode[NP_IP];
1023	    break;
1024	case PPP_IPV6:
1025	    mode = sc->sc_npmode[NP_IPV6];
1026	    break;
1027	default:
1028	    mode = NPMODE_PASS;
1029	}
1030
1031	switch (mode) {
1032	case NPMODE_PASS:
1033	    /*
1034	     * This packet can now go on one of the queues to be sent.
1035	     */
1036	    *mpp = m->m_nextpkt;
1037	    m->m_nextpkt = NULL;
1038	    ifq = (m->m_flags & M_HIGHPRI) ? &sc->sc_fastq : NULL;
1039	    if ((error = ifq_enqueue2(&sc->sc_if, ifq, m ALTQ_COMMA
1040		ALTQ_DECL(NULL))) != 0) {
1041		sc->sc_if.if_oerrors++;
1042		sc->sc_stats.ppp_oerrors++;
1043	    }
1044	    break;
1045
1046	case NPMODE_DROP:
1047	case NPMODE_ERROR:
1048	    *mpp = m->m_nextpkt;
1049	    m_freem(m);
1050	    break;
1051
1052	case NPMODE_QUEUE:
1053	    mpp = &m->m_nextpkt;
1054	    break;
1055	}
1056    }
1057    sc->sc_npqtail = mpp;
1058}
1059
1060/*
1061 * Transmitter has finished outputting some stuff;
1062 * remember to call sc->sc_start later at splsoftnet.
1063 */
1064void
1065ppp_restart(struct ppp_softc *sc)
1066{
1067    int s = splhigh();	/* XXX IMP ME HARDER */
1068
1069    sc->sc_flags &= ~SC_TBUSY;
1070    softint_schedule(sc->sc_si);
1071    splx(s);
1072}
1073
1074/*
1075 * Get a packet to send.  This procedure is intended to be called at
1076 * splsoftnet, since it may involve time-consuming operations such as
1077 * applying VJ compression, packet compression, address/control and/or
1078 * protocol field compression to the packet.
1079 */
1080struct mbuf *
1081ppp_dequeue(struct ppp_softc *sc)
1082{
1083    struct mbuf *m, *mp;
1084    u_char *cp;
1085    int address, control, protocol;
1086    int s;
1087
1088    /*
1089     * Grab a packet to send: first try the fast queue, then the
1090     * normal queue.
1091     */
1092    s = splnet();
1093    if (sc->sc_nfastq < sc->sc_maxfastq) {
1094	IF_DEQUEUE(&sc->sc_fastq, m);
1095	if (m != NULL)
1096	    sc->sc_nfastq++;
1097	else
1098	    IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
1099    } else {
1100	sc->sc_nfastq = 0;
1101	IFQ_DEQUEUE(&sc->sc_if.if_snd, m);
1102	if (m == NULL) {
1103	    IF_DEQUEUE(&sc->sc_fastq, m);
1104	    if (m != NULL)
1105		sc->sc_nfastq++;
1106	}
1107    }
1108    splx(s);
1109
1110    if (m == NULL)
1111	return NULL;
1112
1113    ++sc->sc_stats.ppp_opackets;
1114
1115    /*
1116     * Extract the ppp header of the new packet.
1117     * The ppp header will be in one mbuf.
1118     */
1119    cp = mtod(m, u_char *);
1120    address = PPP_ADDRESS(cp);
1121    control = PPP_CONTROL(cp);
1122    protocol = PPP_PROTOCOL(cp);
1123
1124    switch (protocol) {
1125    case PPP_IP:
1126#ifdef VJC
1127	/*
1128	 * If the packet is a TCP/IP packet, see if we can compress it.
1129	 */
1130	if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
1131	    struct ip *ip;
1132	    int type;
1133
1134	    mp = m;
1135	    ip = (struct ip *) (cp + PPP_HDRLEN);
1136	    if (mp->m_len <= PPP_HDRLEN) {
1137		mp = mp->m_next;
1138		if (mp == NULL)
1139		    break;
1140		ip = mtod(mp, struct ip *);
1141	    }
1142	    /* this code assumes the IP/TCP header is in one non-shared mbuf */
1143	    if (ip->ip_p == IPPROTO_TCP) {
1144		type = sl_compress_tcp(mp, ip, sc->sc_comp,
1145				       !(sc->sc_flags & SC_NO_TCP_CCID));
1146		switch (type) {
1147		case TYPE_UNCOMPRESSED_TCP:
1148		    protocol = PPP_VJC_UNCOMP;
1149		    break;
1150		case TYPE_COMPRESSED_TCP:
1151		    protocol = PPP_VJC_COMP;
1152		    cp = mtod(m, u_char *);
1153		    cp[0] = address;	/* header has moved */
1154		    cp[1] = control;
1155		    cp[2] = 0;
1156		    break;
1157		}
1158		cp[3] = protocol;	/* update protocol in PPP header */
1159	    }
1160	}
1161#endif	/* VJC */
1162	break;
1163
1164#ifdef PPP_COMPRESS
1165    case PPP_CCP:
1166	ppp_ccp(sc, m, 0);
1167	break;
1168#endif	/* PPP_COMPRESS */
1169    }
1170
1171#ifdef PPP_COMPRESS
1172    if (protocol != PPP_LCP && protocol != PPP_CCP
1173	&& sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
1174	struct mbuf *mcomp = NULL;
1175	int slen;
1176
1177	slen = 0;
1178	for (mp = m; mp != NULL; mp = mp->m_next)
1179	    slen += mp->m_len;
1180	(*sc->sc_xcomp->compress)
1181	    (sc->sc_xc_state, &mcomp, m, slen, sc->sc_if.if_mtu + PPP_HDRLEN);
1182	if (mcomp != NULL) {
1183	    if (sc->sc_flags & SC_CCP_UP) {
1184		/* Send the compressed packet instead of the original. */
1185		m_freem(m);
1186		m = mcomp;
1187		cp = mtod(m, u_char *);
1188		protocol = cp[3];
1189	    } else {
1190		/* Can't transmit compressed packets until CCP is up. */
1191		m_freem(mcomp);
1192	    }
1193	}
1194    }
1195#endif	/* PPP_COMPRESS */
1196
1197    /*
1198     * Compress the address/control and protocol, if possible.
1199     */
1200    if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
1201	control == PPP_UI && protocol != PPP_ALLSTATIONS &&
1202	protocol != PPP_LCP) {
1203	/* can compress address/control */
1204	m->m_data += 2;
1205	m->m_len -= 2;
1206    }
1207    if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
1208	/* can compress protocol */
1209	if (mtod(m, u_char *) == cp) {
1210	    cp[2] = cp[1];	/* move address/control up */
1211	    cp[1] = cp[0];
1212	}
1213	++m->m_data;
1214	--m->m_len;
1215    }
1216
1217    return m;
1218}
1219
1220/*
1221 * Software interrupt routine, called at splsoftnet.
1222 */
1223static void
1224pppintr(void *arg)
1225{
1226	struct ppp_softc *sc = arg;
1227	struct mbuf *m;
1228	int s;
1229
1230	mutex_enter(softnet_lock);
1231	if (!(sc->sc_flags & SC_TBUSY)
1232	    && (IFQ_IS_EMPTY(&sc->sc_if.if_snd) == 0 || sc->sc_fastq.ifq_head
1233		|| sc->sc_outm)) {
1234		s = splhigh();	/* XXX IMP ME HARDER */
1235		sc->sc_flags |= SC_TBUSY;
1236		splx(s);
1237		(*sc->sc_start)(sc);
1238	}
1239	for (;;) {
1240		s = splnet();
1241		IF_DEQUEUE(&sc->sc_rawq, m);
1242		splx(s);
1243		if (m == NULL)
1244			break;
1245		ppp_inproc(sc, m);
1246	}
1247	mutex_exit(softnet_lock);
1248}
1249
1250#ifdef PPP_COMPRESS
1251/*
1252 * Handle a CCP packet.  `rcvd' is 1 if the packet was received,
1253 * 0 if it is about to be transmitted.
1254 */
1255static void
1256ppp_ccp(struct ppp_softc *sc, struct mbuf *m, 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(struct ppp_softc *sc)
1351{
1352    if (sc->sc_xc_state) {
1353	(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1354	ppp_compressor_rele(sc->sc_xcomp);
1355	sc->sc_xc_state = NULL;
1356    }
1357    if (sc->sc_rc_state) {
1358	(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1359	ppp_compressor_rele(sc->sc_rcomp);
1360	sc->sc_rc_state = NULL;
1361    }
1362}
1363#endif /* PPP_COMPRESS */
1364
1365/*
1366 * PPP packet input routine.
1367 * The caller has checked and removed the FCS and has inserted
1368 * the address/control bytes and the protocol high byte if they
1369 * were omitted.
1370 */
1371void
1372ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost)
1373{
1374    int s = splhigh();	/* XXX IMP ME HARDER */
1375
1376    if (lost)
1377	m->m_flags |= M_ERRMARK;
1378    IF_ENQUEUE(&sc->sc_rawq, m);
1379    softint_schedule(sc->sc_si);
1380    splx(s);
1381}
1382
1383/*
1384 * Process a received PPP packet, doing decompression as necessary.
1385 * Should be called at splsoftnet.
1386 */
1387#define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1388			 TYPE_UNCOMPRESSED_TCP)
1389
1390static void
1391ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
1392{
1393    struct ifnet *ifp = &sc->sc_if;
1394    struct ifqueue *inq;
1395    int s, ilen, proto, rv;
1396    u_char *cp, adrs, ctrl;
1397    struct mbuf *mp, *dmp = NULL;
1398#ifdef VJC
1399    int xlen;
1400    u_char *iphdr;
1401    u_int hlen;
1402#endif
1403
1404    sc->sc_stats.ppp_ipackets++;
1405
1406    if (sc->sc_flags & SC_LOG_INPKT) {
1407	ilen = 0;
1408	for (mp = m; mp != NULL; mp = mp->m_next)
1409	    ilen += mp->m_len;
1410	printf("%s: got %d bytes\n", ifp->if_xname, ilen);
1411	pppdumpm(m);
1412    }
1413
1414    cp = mtod(m, u_char *);
1415    adrs = PPP_ADDRESS(cp);
1416    ctrl = PPP_CONTROL(cp);
1417    proto = PPP_PROTOCOL(cp);
1418
1419    if (m->m_flags & M_ERRMARK) {
1420	m->m_flags &= ~M_ERRMARK;
1421	s = splhigh();	/* XXX IMP ME HARDER */
1422	sc->sc_flags |= SC_VJ_RESET;
1423	splx(s);
1424    }
1425
1426#ifdef PPP_COMPRESS
1427    /*
1428     * Decompress this packet if necessary, update the receiver's
1429     * dictionary, or take appropriate action on a CCP packet.
1430     */
1431    if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
1432	&& !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
1433	/* decompress this packet */
1434	rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1435	if (rv == DECOMP_OK) {
1436	    m_freem(m);
1437	    if (dmp == NULL) {
1438		/* no error, but no decompressed packet produced */
1439		return;
1440	    }
1441	    m = dmp;
1442	    cp = mtod(m, u_char *);
1443	    proto = PPP_PROTOCOL(cp);
1444
1445	} else {
1446	    /*
1447	     * An error has occurred in decompression.
1448	     * Pass the compressed packet up to pppd, which may take
1449	     * CCP down or issue a Reset-Req.
1450	     */
1451	    if (sc->sc_flags & SC_DEBUG)
1452		printf("%s: decompress failed %d\n", ifp->if_xname, rv);
1453	    s = splhigh();	/* XXX IMP ME HARDER */
1454	    sc->sc_flags |= SC_VJ_RESET;
1455	    if (rv == DECOMP_ERROR)
1456		sc->sc_flags |= SC_DC_ERROR;
1457	    else
1458		sc->sc_flags |= SC_DC_FERROR;
1459	    splx(s);
1460	}
1461
1462    } else {
1463	if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1464	    (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1465	}
1466	if (proto == PPP_CCP) {
1467	    ppp_ccp(sc, m, 1);
1468	}
1469    }
1470#endif
1471
1472    ilen = 0;
1473    for (mp = m; mp != NULL; mp = mp->m_next)
1474	ilen += mp->m_len;
1475
1476#ifdef VJC
1477    if (sc->sc_flags & SC_VJ_RESET) {
1478	/*
1479	 * If we've missed a packet, we must toss subsequent compressed
1480	 * packets which don't have an explicit connection ID.
1481	 */
1482	if (sc->sc_comp)
1483	    sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
1484	s = splhigh();	/* XXX IMP ME HARDER */
1485	sc->sc_flags &= ~SC_VJ_RESET;
1486	splx(s);
1487    }
1488
1489    /*
1490     * See if we have a VJ-compressed packet to uncompress.
1491     */
1492    if (proto == PPP_VJC_COMP) {
1493	if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1494	    goto bad;
1495
1496	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1497				      ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
1498				      sc->sc_comp, &iphdr, &hlen);
1499
1500	if (xlen <= 0) {
1501	    if (sc->sc_flags & SC_DEBUG)
1502		printf("%s: VJ uncompress failed on type comp\n",
1503		    ifp->if_xname);
1504	    goto bad;
1505	}
1506
1507	/* Copy the PPP and IP headers into a new mbuf. */
1508	MGETHDR(mp, M_DONTWAIT, MT_DATA);
1509	if (mp == NULL)
1510	    goto bad;
1511	mp->m_len = 0;
1512	mp->m_next = NULL;
1513	if (hlen + PPP_HDRLEN > MHLEN) {
1514	    MCLGET(mp, M_DONTWAIT);
1515	    if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
1516		m_freem(mp);
1517		goto bad;	/* lose if big headers and no clusters */
1518	    }
1519	}
1520	cp = mtod(mp, u_char *);
1521	cp[0] = adrs;
1522	cp[1] = ctrl;
1523	cp[2] = 0;
1524	cp[3] = PPP_IP;
1525	proto = PPP_IP;
1526	bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1527	mp->m_len = hlen + PPP_HDRLEN;
1528
1529	/*
1530	 * Trim the PPP and VJ headers off the old mbuf
1531	 * and stick the new and old mbufs together.
1532	 */
1533	m->m_data += PPP_HDRLEN + xlen;
1534	m->m_len -= PPP_HDRLEN + xlen;
1535	if (m->m_len <= M_TRAILINGSPACE(mp)) {
1536	    bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
1537	    mp->m_len += m->m_len;
1538	    MFREE(m, mp->m_next);
1539	} else
1540	    mp->m_next = m;
1541	m = mp;
1542	ilen += hlen - xlen;
1543
1544    } else if (proto == PPP_VJC_UNCOMP) {
1545	if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1546	    goto bad;
1547
1548	xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
1549				      ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
1550				      sc->sc_comp, &iphdr, &hlen);
1551
1552	if (xlen < 0) {
1553	    if (sc->sc_flags & SC_DEBUG)
1554		printf("%s: VJ uncompress failed on type uncomp\n",
1555		    ifp->if_xname);
1556	    goto bad;
1557	}
1558
1559	proto = PPP_IP;
1560	cp[3] = PPP_IP;
1561    }
1562#endif /* VJC */
1563
1564    /*
1565     * If the packet will fit in a header mbuf, don't waste a
1566     * whole cluster on it.
1567     */
1568    if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
1569	MGETHDR(mp, M_DONTWAIT, MT_DATA);
1570	if (mp != NULL) {
1571	    m_copydata(m, 0, ilen, mtod(mp, void *));
1572	    m_freem(m);
1573	    m = mp;
1574	    m->m_len = ilen;
1575	}
1576    }
1577    m->m_pkthdr.len = ilen;
1578    m->m_pkthdr.rcvif = ifp;
1579
1580    if ((proto & 0x8000) == 0) {
1581#ifdef PPP_FILTER
1582	/*
1583	 * See whether we want to pass this packet, and
1584	 * if it counts as link activity.
1585	 */
1586	if (sc->sc_pass_filt_in.bf_insns != 0
1587	    && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m,
1588			  ilen, 0) == 0) {
1589	    /* drop this packet */
1590	    m_freem(m);
1591	    return;
1592	}
1593	if (sc->sc_active_filt_in.bf_insns == 0
1594	    || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m,
1595	    		  ilen, 0))
1596	    sc->sc_last_recv = time_second;
1597#else
1598	/*
1599	 * Record the time that we received this packet.
1600	 */
1601	sc->sc_last_recv = time_second;
1602#endif /* PPP_FILTER */
1603    }
1604
1605    /* See if bpf wants to look at the packet. */
1606    bpf_mtap(&sc->sc_if, m);
1607
1608    rv = 0;
1609    switch (proto) {
1610#ifdef INET
1611    case PPP_IP:
1612	/*
1613	 * IP packet - take off the ppp header and pass it up to IP.
1614	 */
1615	if ((ifp->if_flags & IFF_UP) == 0
1616	    || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1617	    /* interface is down - drop the packet. */
1618	    m_freem(m);
1619	    return;
1620	}
1621	m->m_pkthdr.len -= PPP_HDRLEN;
1622	m->m_data += PPP_HDRLEN;
1623	m->m_len -= PPP_HDRLEN;
1624#ifdef GATEWAY
1625	if (ipflow_fastforward(m))
1626		return;
1627#endif
1628	schednetisr(NETISR_IP);
1629	inq = &ipintrq;
1630	break;
1631#endif
1632
1633#ifdef INET6
1634    case PPP_IPV6:
1635	/*
1636	 * IPv6 packet - take off the ppp header and pass it up to IPv6.
1637	 */
1638	if ((ifp->if_flags & IFF_UP) == 0
1639	    || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) {
1640	    /* interface is down - drop the packet. */
1641	    m_freem(m);
1642	    return;
1643	}
1644	m->m_pkthdr.len -= PPP_HDRLEN;
1645	m->m_data += PPP_HDRLEN;
1646	m->m_len -= PPP_HDRLEN;
1647#ifdef GATEWAY
1648	if (ip6flow_fastforward(&m))
1649		return;
1650#endif
1651	schednetisr(NETISR_IPV6);
1652	inq = &ip6intrq;
1653	break;
1654#endif
1655
1656    default:
1657	/*
1658	 * Some other protocol - place on input queue for read().
1659	 */
1660	inq = &sc->sc_inq;
1661	rv = 1;
1662	break;
1663    }
1664
1665    /*
1666     * Put the packet on the appropriate input queue.
1667     */
1668    s = splnet();
1669    if (IF_QFULL(inq)) {
1670	IF_DROP(inq);
1671	splx(s);
1672	if (sc->sc_flags & SC_DEBUG)
1673	    printf("%s: input queue full\n", ifp->if_xname);
1674	ifp->if_iqdrops++;
1675	goto bad;
1676    }
1677    IF_ENQUEUE(inq, m);
1678    splx(s);
1679    ifp->if_ipackets++;
1680    ifp->if_ibytes += ilen;
1681
1682    if (rv)
1683	(*sc->sc_ctlp)(sc);
1684
1685    return;
1686
1687 bad:
1688    m_freem(m);
1689    sc->sc_if.if_ierrors++;
1690    sc->sc_stats.ppp_ierrors++;
1691}
1692
1693#define MAX_DUMP_BYTES	128
1694
1695static void
1696pppdumpm(struct mbuf *m0)
1697{
1698    char buf[3*MAX_DUMP_BYTES+4];
1699    char *bp = buf;
1700    struct mbuf *m;
1701
1702    for (m = m0; m; m = m->m_next) {
1703	int l = m->m_len;
1704	u_char *rptr = (u_char *)m->m_data;
1705
1706	while (l--) {
1707	    if (bp > buf + sizeof(buf) - 4)
1708		goto done;
1709	    *bp++ = hexdigits[*rptr >> 4]; /* convert byte to ascii hex */
1710	    *bp++ = hexdigits[*rptr++ & 0xf];
1711	}
1712
1713	if (m->m_next) {
1714	    if (bp > buf + sizeof(buf) - 3)
1715		goto done;
1716	    *bp++ = '|';
1717	} else
1718	    *bp++ = ' ';
1719    }
1720done:
1721    if (m)
1722	*bp++ = '>';
1723    *bp = 0;
1724    printf("%s\n", buf);
1725}
1726
1727#ifdef ALTQ
1728/*
1729 * a wrapper to transmit a packet from if_start since ALTQ uses
1730 * if_start to send a packet.
1731 */
1732static void
1733ppp_ifstart(struct ifnet *ifp)
1734{
1735	struct ppp_softc *sc;
1736
1737	sc = ifp->if_softc;
1738	(*sc->sc_start)(sc);
1739}
1740#endif
1741
1742static const struct ppp_known_compressor {
1743	uint8_t code;
1744	const char *module;
1745} ppp_known_compressors[] = {
1746	{ CI_DEFLATE, "ppp_deflate" },
1747	{ CI_DEFLATE_DRAFT, "ppp_deflate" },
1748	{ CI_BSD_COMPRESS, "ppp_bsdcomp" },
1749	{ CI_MPPE, "ppp_mppe" },
1750	{ 0, NULL }
1751};
1752
1753static int
1754ppp_compressor_init(void)
1755{
1756
1757	mutex_init(&ppp_compressors_mtx, MUTEX_DEFAULT, IPL_NONE);
1758	return 0;
1759}
1760
1761static void
1762ppp_compressor_rele(struct compressor *cp)
1763{
1764
1765	mutex_enter(&ppp_compressors_mtx);
1766	--cp->comp_refcnt;
1767	mutex_exit(&ppp_compressors_mtx);
1768}
1769
1770static struct compressor *
1771ppp_get_compressor_noload(uint8_t ci, bool hold)
1772{
1773	struct compressor *cp;
1774
1775	KASSERT(mutex_owned(&ppp_compressors_mtx));
1776	LIST_FOREACH(cp, &ppp_compressors, comp_list) {
1777		if (cp->compress_proto == ci) {
1778			if (hold)
1779				++cp->comp_refcnt;
1780			return cp;
1781		}
1782	}
1783
1784	return NULL;
1785}
1786
1787static struct compressor *
1788ppp_get_compressor(uint8_t ci)
1789{
1790	struct compressor *cp = NULL;
1791	const struct ppp_known_compressor *pkc;
1792
1793	mutex_enter(&ppp_compressors_mtx);
1794	cp = ppp_get_compressor_noload(ci, true);
1795	mutex_exit(&ppp_compressors_mtx);
1796	if (cp != NULL)
1797		return cp;
1798
1799	kernconfig_lock();
1800	mutex_enter(&ppp_compressors_mtx);
1801	cp = ppp_get_compressor_noload(ci, true);
1802	mutex_exit(&ppp_compressors_mtx);
1803	if (cp == NULL) {
1804		/* Not found, so try to autoload a module */
1805		for (pkc = ppp_known_compressors; pkc->module != NULL; pkc++) {
1806			if (pkc->code == ci) {
1807				if (module_autoload(pkc->module,
1808				    MODULE_CLASS_MISC) != 0)
1809					break;
1810				mutex_enter(&ppp_compressors_mtx);
1811				cp = ppp_get_compressor_noload(ci, true);
1812				mutex_exit(&ppp_compressors_mtx);
1813				break;
1814			}
1815		}
1816	}
1817	kernconfig_unlock();
1818
1819	return cp;
1820}
1821
1822int
1823ppp_register_compressor(struct compressor *pc, size_t ncomp)
1824{
1825	int error = 0;
1826	size_t i;
1827
1828	RUN_ONCE(&ppp_compressor_mtx_init, ppp_compressor_init);
1829
1830	mutex_enter(&ppp_compressors_mtx);
1831	for (i = 0; i < ncomp; i++) {
1832		if (ppp_get_compressor_noload(pc[i].compress_proto,
1833		    false) != NULL)
1834			error = EEXIST;
1835	}
1836	if (!error) {
1837		for (i = 0; i < ncomp; i++) {
1838			pc[i].comp_refcnt = 0;
1839			LIST_INSERT_HEAD(&ppp_compressors, &pc[i], comp_list);
1840		}
1841	}
1842	mutex_exit(&ppp_compressors_mtx);
1843
1844	return error;
1845}
1846
1847int
1848ppp_unregister_compressor(struct compressor *pc, size_t ncomp)
1849{
1850	int error = 0;
1851	size_t i;
1852
1853	mutex_enter(&ppp_compressors_mtx);
1854	for (i = 0; i < ncomp; i++) {
1855		if (ppp_get_compressor_noload(pc[i].compress_proto,
1856		    false) != &pc[i])
1857			error = ENOENT;
1858		else if (pc[i].comp_refcnt != 0)
1859			error = EBUSY;
1860	}
1861	if (!error) {
1862		for (i = 0; i < ncomp; i++) {
1863			LIST_REMOVE(&pc[i], comp_list);
1864		}
1865	}
1866	mutex_exit(&ppp_compressors_mtx);
1867
1868	return error;
1869}
1870