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