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