xref: /openbsd/sys/net/if_ppp.c (revision 09467b48)
1 /*	$OpenBSD: if_ppp.c,v 1.116 2020/07/10 13:26:42 patrick Exp $	*/
2 /*	$NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos 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, 1989, 1992, 1993
49  *	The Regents of the University of California.  All rights reserved.
50  *
51  * Redistribution and use in source and binary forms, with or without
52  * modification, are permitted provided that the following conditions
53  * are met:
54  * 1. Redistributions of source code must retain the above copyright
55  *    notice, this list of conditions and the following disclaimer.
56  * 2. Redistributions in binary form must reproduce the above copyright
57  *    notice, this list of conditions and the following disclaimer in the
58  *    documentation and/or other materials provided with the distribution.
59  * 3. Neither the name of the University nor the names of its contributors
60  *    may be used to endorse or promote products derived from this software
61  *    without specific prior written permission.
62  *
63  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
64  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
65  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
66  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
67  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
68  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
69  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
70  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
71  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
72  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
73  * SUCH DAMAGE.
74  *
75  * Serial Line interface
76  *
77  * Rick Adams
78  * Center for Seismic Studies
79  * 1300 N 17th Street, Suite 1450
80  * Arlington, Virginia 22209
81  * (703)276-7900
82  * rick@seismo.ARPA
83  * seismo!rick
84  *
85  * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
86  * Converted to 4.3BSD Beta by Chris Torek.
87  * Other changes made at Berkeley, based in part on code by Kirk Smith.
88  *
89  * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
90  * Added VJ tcp header compression; more unified ioctls
91  *
92  * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
93  * Cleaned up a lot of the mbuf-related code to fix bugs that
94  * caused system crashes and packet corruption.  Changed pppstart
95  * so that it doesn't just give up with a collision if the whole
96  * packet doesn't fit in the output ring buffer.
97  *
98  * Added priority queueing for interactive IP packets, following
99  * the model of if_sl.c, plus hooks for bpf.
100  * Paul Mackerras (paulus@cs.anu.edu.au).
101  */
102 
103 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
104 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
105 
106 #include "ppp.h"
107 #if NPPP > 0
108 
109 #define VJC
110 #define PPP_COMPRESS
111 
112 #include <sys/param.h>
113 #include <sys/proc.h>
114 #include <sys/mbuf.h>
115 #include <sys/socket.h>
116 #include <sys/ioctl.h>
117 #include <sys/kernel.h>
118 #include <sys/systm.h>
119 #include <sys/time.h>
120 #include <sys/malloc.h>
121 
122 #include <net/if.h>
123 #include <net/if_var.h>
124 #include <net/if_types.h>
125 #include <net/netisr.h>
126 #include <net/route.h>
127 #include <net/bpf.h>
128 
129 #include <netinet/in.h>
130 #include <netinet/ip.h>
131 
132 #include "bpfilter.h"
133 
134 #ifdef VJC
135 #include <net/slcompress.h>
136 #endif
137 
138 #include <net/ppp_defs.h>
139 #include <net/if_ppp.h>
140 #include <net/if_pppvar.h>
141 
142 #ifdef PPP_COMPRESS
143 #define PACKETPTR	struct mbuf *
144 #include <net/ppp-comp.h>
145 #endif
146 
147 static int	 pppsioctl(struct ifnet *, u_long, caddr_t);
148 static void	 ppp_requeue(struct ppp_softc *);
149 static void	 ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
150 static void	 ppp_ccp_closed(struct ppp_softc *);
151 static void	 ppp_inproc(struct ppp_softc *, struct mbuf *);
152 static void	 pppdumpm(struct mbuf *m0);
153 static void	 ppp_ifstart(struct ifnet *ifp);
154 int		 ppp_clone_create(struct if_clone *, int);
155 int		 ppp_clone_destroy(struct ifnet *);
156 
157 void		 ppp_pkt_list_init(struct ppp_pkt_list *, u_int);
158 int		 ppp_pkt_enqueue(struct ppp_pkt_list *, struct ppp_pkt *);
159 struct ppp_pkt	*ppp_pkt_dequeue(struct ppp_pkt_list *);
160 struct mbuf	*ppp_pkt_mbuf(struct ppp_pkt *);
161 
162 /*
163  * We steal two bits in the mbuf m_flags, to mark high-priority packets
164  * for output, and received packets following lost/corrupted packets.
165  */
166 #define M_ERRMARK	M_LINK0		/* steal a bit in mbuf m_flags */
167 
168 
169 #ifdef PPP_COMPRESS
170 /*
171  * List of compressors we know about.
172  */
173 
174 extern struct compressor ppp_bsd_compress;
175 extern struct compressor ppp_deflate, ppp_deflate_draft;
176 
177 struct compressor *ppp_compressors[] = {
178 #if DO_BSD_COMPRESS && defined(PPP_BSDCOMP)
179 	&ppp_bsd_compress,
180 #endif
181 #if DO_DEFLATE && defined(PPP_DEFLATE)
182 	&ppp_deflate,
183 	&ppp_deflate_draft,
184 #endif
185 	NULL
186 };
187 #endif /* PPP_COMPRESS */
188 
189 LIST_HEAD(, ppp_softc) ppp_softc_list;
190 struct if_clone ppp_cloner =
191     IF_CLONE_INITIALIZER("ppp", ppp_clone_create, ppp_clone_destroy);
192 
193 /*
194  * Called from boot code to establish ppp interfaces.
195  */
196 void
197 pppattach(void)
198 {
199 	LIST_INIT(&ppp_softc_list);
200 	if_clone_attach(&ppp_cloner);
201 }
202 
203 int
204 ppp_clone_create(struct if_clone *ifc, int unit)
205 {
206 	struct ppp_softc *sc;
207 	struct ifnet *ifp;
208 
209 	sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
210 	sc->sc_unit = unit;
211 	ifp = &sc->sc_if;
212 	snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
213 	    ifc->ifc_name, unit);
214 	sc->sc_if.if_softc = sc;
215 	sc->sc_if.if_mtu = PPP_MTU;
216 	sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
217 	sc->sc_if.if_type = IFT_PPP;
218 	sc->sc_if.if_hdrlen = PPP_HDRLEN;
219 	sc->sc_if.if_ioctl = pppsioctl;
220 	sc->sc_if.if_output = pppoutput;
221 	sc->sc_if.if_start = ppp_ifstart;
222 	sc->sc_if.if_rtrequest = p2p_rtrequest;
223 	ifq_set_maxlen(&sc->sc_if.if_snd, IFQ_MAXLEN);
224 	mq_init(&sc->sc_inq, IFQ_MAXLEN, IPL_NET);
225 	ppp_pkt_list_init(&sc->sc_rawq, IFQ_MAXLEN);
226 	if_attach(&sc->sc_if);
227 	if_alloc_sadl(&sc->sc_if);
228 #if NBPFILTER > 0
229 	bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HDRLEN);
230 #endif
231 	NET_LOCK();
232 	LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list);
233 	NET_UNLOCK();
234 
235 	return (0);
236 }
237 
238 int
239 ppp_clone_destroy(struct ifnet *ifp)
240 {
241 	struct ppp_softc *sc = ifp->if_softc;
242 
243 	if (sc->sc_devp != NULL)
244 		return (EBUSY);
245 
246 	NET_LOCK();
247 	LIST_REMOVE(sc, sc_list);
248 	NET_UNLOCK();
249 
250 	if_detach(ifp);
251 
252 	free(sc, M_DEVBUF, 0);
253 	return (0);
254 }
255 
256 /*
257  * Allocate a ppp interface unit and initialize it.
258  */
259 struct ppp_softc *
260 pppalloc(pid_t pid)
261 {
262 	int i;
263 	struct ppp_softc *sc;
264 
265 	NET_LOCK();
266 	LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
267 		if (sc->sc_xfer == pid) {
268 			sc->sc_xfer = 0;
269 			NET_UNLOCK();
270 			return sc;
271 		}
272 	}
273 	LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
274 		if (sc->sc_devp == NULL)
275 			break;
276 	}
277 	NET_UNLOCK();
278 	if (sc == NULL)
279 		return NULL;
280 
281 	sc->sc_flags = 0;
282 	sc->sc_mru = PPP_MRU;
283 	sc->sc_relinq = NULL;
284 	bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
285 #ifdef VJC
286 	sc->sc_comp = malloc(sizeof(struct slcompress), M_DEVBUF, M_NOWAIT);
287 	if (sc->sc_comp)
288 		sl_compress_init(sc->sc_comp);
289 #endif
290 #ifdef PPP_COMPRESS
291 	sc->sc_xc_state = NULL;
292 	sc->sc_rc_state = NULL;
293 #endif /* PPP_COMPRESS */
294 	for (i = 0; i < NUM_NP; ++i)
295 		sc->sc_npmode[i] = NPMODE_ERROR;
296 	ml_init(&sc->sc_npqueue);
297 	sc->sc_last_sent = sc->sc_last_recv = getuptime();
298 
299 	return sc;
300 }
301 
302 /*
303  * Deallocate a ppp unit.
304  */
305 void
306 pppdealloc(struct ppp_softc *sc)
307 {
308 	struct ppp_pkt *pkt;
309 
310 	NET_LOCK();
311 	if_down(&sc->sc_if);
312 	sc->sc_if.if_flags &= ~IFF_RUNNING;
313 	sc->sc_devp = NULL;
314 	sc->sc_xfer = 0;
315 	while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL)
316 		ppp_pkt_free(pkt);
317 	mq_purge(&sc->sc_inq);
318 	ml_purge(&sc->sc_npqueue);
319 	m_freem(sc->sc_togo);
320 	sc->sc_togo = NULL;
321 
322 #ifdef PPP_COMPRESS
323 	ppp_ccp_closed(sc);
324 	sc->sc_xc_state = NULL;
325 	sc->sc_rc_state = NULL;
326 #endif /* PPP_COMPRESS */
327 #if NBPFILTER > 0
328 	if (sc->sc_pass_filt.bf_insns != 0) {
329 		free(sc->sc_pass_filt.bf_insns, M_DEVBUF, 0);
330 		sc->sc_pass_filt.bf_insns = 0;
331 		sc->sc_pass_filt.bf_len = 0;
332 	}
333 	if (sc->sc_active_filt.bf_insns != 0) {
334 		free(sc->sc_active_filt.bf_insns, M_DEVBUF, 0);
335 		sc->sc_active_filt.bf_insns = 0;
336 		sc->sc_active_filt.bf_len = 0;
337 	}
338 #endif
339 #ifdef VJC
340 	if (sc->sc_comp != 0) {
341 		free(sc->sc_comp, M_DEVBUF, 0);
342 		sc->sc_comp = 0;
343 	}
344 #endif
345 	NET_UNLOCK();
346 }
347 
348 /*
349  * Ioctl routine for generic ppp devices.
350  */
351 int
352 pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag,
353     struct proc *p)
354 {
355 	int s, error, flags, mru, npx;
356 	u_int nb;
357 	struct ppp_option_data *odp;
358 	struct compressor **cp;
359 	struct npioctl *npi;
360 	time_t t;
361 #if NBPFILTER > 0
362 	struct bpf_program *bp, *nbp;
363 	struct bpf_insn *newcode, *oldcode;
364 	int newcodelen;
365 #endif
366 #ifdef	PPP_COMPRESS
367 	u_char ccp_option[CCP_MAX_OPTION_LENGTH];
368 #endif
369 
370 	switch (cmd) {
371 	case FIONREAD:
372 		*(int *)data = mq_len(&sc->sc_inq);
373 		break;
374 
375 	case PPPIOCGUNIT:
376 		*(int *)data = sc->sc_unit;	/* XXX */
377 		break;
378 
379 	case PPPIOCGFLAGS:
380 		*(u_int *)data = sc->sc_flags;
381 		break;
382 
383 	case PPPIOCSFLAGS:
384 		if ((error = suser(p)) != 0)
385 			return (error);
386 		flags = *(int *)data & SC_MASK;
387 #ifdef PPP_COMPRESS
388 		if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
389 			ppp_ccp_closed(sc);
390 #endif
391 		s = splnet();
392 		sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
393 		splx(s);
394 		break;
395 
396 	case PPPIOCSMRU:
397 		if ((error = suser(p)) != 0)
398 			return (error);
399 		mru = *(int *)data;
400 		if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
401 			sc->sc_mru = mru;
402 		break;
403 
404 	case PPPIOCGMRU:
405 		*(int *)data = sc->sc_mru;
406 		break;
407 
408 #ifdef VJC
409 	case PPPIOCSMAXCID:
410 		if ((error = suser(p)) != 0)
411 			return (error);
412 		if (sc->sc_comp)
413 			sl_compress_setup(sc->sc_comp, *(int *)data);
414 		break;
415 #endif
416 
417 	case PPPIOCXFERUNIT:
418 		if ((error = suser(p)) != 0)
419 			return (error);
420 		sc->sc_xfer = p->p_p->ps_pid;
421 		break;
422 
423 #ifdef PPP_COMPRESS
424 	case PPPIOCSCOMPRESS:
425 		if ((error = suser(p)) != 0)
426 			return (error);
427 		odp = (struct ppp_option_data *) data;
428 		nb = odp->length;
429 		if (nb > sizeof(ccp_option))
430 			nb = sizeof(ccp_option);
431 		if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
432 			return (error);
433 		 /* preliminary check on the length byte */
434 		if (ccp_option[1] < 2)
435 			return (EINVAL);
436 		for (cp = ppp_compressors; *cp != NULL; ++cp)
437 			if ((*cp)->compress_proto == ccp_option[0]) {
438 			/*
439 			 * Found a handler for the protocol - try to allocate
440 			 * a compressor or decompressor.
441 			 */
442 			error = 0;
443 			if (odp->transmit) {
444 				if (sc->sc_xc_state != NULL) {
445 					(*sc->sc_xcomp->comp_free)(
446 					    sc->sc_xc_state);
447 				}
448 				sc->sc_xcomp = *cp;
449 				sc->sc_xc_state = (*cp)->comp_alloc(ccp_option,
450 				    nb);
451 				if (sc->sc_xc_state == NULL) {
452 					if (sc->sc_flags & SC_DEBUG)
453 						printf(
454 						    "%s: comp_alloc failed\n",
455 						    sc->sc_if.if_xname);
456 					error = ENOBUFS;
457 				}
458 				s = splnet();
459 				sc->sc_flags &= ~SC_COMP_RUN;
460 				splx(s);
461 			} else {
462 				if (sc->sc_rc_state != NULL) {
463 					(*sc->sc_rcomp->decomp_free)(
464 					    sc->sc_rc_state);
465 				}
466 				sc->sc_rcomp = *cp;
467 				sc->sc_rc_state = (*cp)->decomp_alloc(
468 				    ccp_option, nb);
469 				if (sc->sc_rc_state == NULL) {
470 					if (sc->sc_flags & SC_DEBUG) {
471 						printf(
472 						    "%s: decomp_alloc failed\n",
473 						    sc->sc_if.if_xname);
474 					}
475 					error = ENOBUFS;
476 				}
477 				s = splnet();
478 				sc->sc_flags &= ~SC_DECOMP_RUN;
479 				splx(s);
480 			}
481 			return (error);
482 		}
483 		if (sc->sc_flags & SC_DEBUG) {
484 			printf("%s: no compressor for [%x %x %x], %x\n",
485 			    sc->sc_if.if_xname, ccp_option[0], ccp_option[1],
486 			    ccp_option[2], nb);
487 		}
488 		return (EINVAL);	/* no handler found */
489 #endif /* PPP_COMPRESS */
490 
491 	case PPPIOCGNPMODE:
492 	case PPPIOCSNPMODE:
493 		npi = (struct npioctl *)data;
494 		switch (npi->protocol) {
495 		case PPP_IP:
496 			npx = NP_IP;
497 			break;
498 		default:
499 			return EINVAL;
500 		}
501 		if (cmd == PPPIOCGNPMODE) {
502 			npi->mode = sc->sc_npmode[npx];
503 		} else {
504 			if ((error = suser(p)) != 0)
505 				return (error);
506 			if (npi->mode != sc->sc_npmode[npx]) {
507 				sc->sc_npmode[npx] = npi->mode;
508 				if (npi->mode != NPMODE_QUEUE) {
509 					ppp_requeue(sc);
510 					(*sc->sc_start)(sc);
511 				}
512 			}
513 		}
514 		break;
515 
516 	case PPPIOCGIDLE:
517 		t = getuptime();
518 		((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
519 		((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
520 		break;
521 
522 #if NBPFILTER > 0
523 	case PPPIOCSPASS:
524 	case PPPIOCSACTIVE:
525 		nbp = (struct bpf_program *) data;
526 		if ((unsigned) nbp->bf_len > BPF_MAXINSNS)
527 			return EINVAL;
528 		newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
529 		if (nbp->bf_len != 0) {
530 			newcode = mallocarray(nbp->bf_len,
531 			    sizeof(struct bpf_insn), M_DEVBUF, M_WAITOK);
532 			if ((error = copyin((caddr_t)nbp->bf_insns,
533 			    (caddr_t)newcode, newcodelen)) != 0) {
534 				free(newcode, M_DEVBUF, 0);
535 				return error;
536 			}
537 			if (!bpf_validate(newcode, nbp->bf_len)) {
538 				free(newcode, M_DEVBUF, 0);
539 				return EINVAL;
540 			}
541 		} else
542 			newcode = 0;
543 		bp = (cmd == PPPIOCSPASS) ?
544 		    &sc->sc_pass_filt : &sc->sc_active_filt;
545 		oldcode = bp->bf_insns;
546 		s = splnet();
547 		bp->bf_len = nbp->bf_len;
548 		bp->bf_insns = newcode;
549 		splx(s);
550 		if (oldcode != 0)
551 			free(oldcode, M_DEVBUF, 0);
552 		break;
553 #endif
554 
555 	default:
556 		return (-1);
557 	}
558 	return (0);
559 }
560 
561 /*
562  * Process an ioctl request to the ppp network interface.
563  */
564 static int
565 pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
566 {
567 	struct ppp_softc *sc = ifp->if_softc;
568 	struct ifaddr *ifa = (struct ifaddr *)data;
569 	struct ifreq *ifr = (struct ifreq *)data;
570 	struct ppp_stats *psp;
571 #ifdef	PPP_COMPRESS
572 	struct ppp_comp_stats *pcp;
573 #endif
574 	int s = splnet(), error = 0;
575 
576 	switch (cmd) {
577 	case SIOCSIFFLAGS:
578 		if ((ifp->if_flags & IFF_RUNNING) == 0)
579 			ifp->if_flags &= ~IFF_UP;
580 		break;
581 
582 	case SIOCSIFADDR:
583 		if (ifa->ifa_addr->sa_family != AF_INET)
584 			error = EAFNOSUPPORT;
585 		break;
586 
587 	case SIOCSIFDSTADDR:
588 		if (ifa->ifa_addr->sa_family != AF_INET)
589 			error = EAFNOSUPPORT;
590 		break;
591 
592 	case SIOCSIFMTU:
593 		sc->sc_if.if_mtu = ifr->ifr_mtu;
594 		break;
595 
596 	case SIOCADDMULTI:
597 	case SIOCDELMULTI:
598 		break;
599 
600 	case SIOCGPPPSTATS:
601 		psp = &((struct ifpppstatsreq *) data)->stats;
602 		bzero(psp, sizeof(*psp));
603 		psp->p = sc->sc_stats;
604 #if defined(VJC) && !defined(SL_NO_STATS)
605 		if (sc->sc_comp) {
606 			psp->vj.vjs_packets = sc->sc_comp->sls_packets;
607 			psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
608 			psp->vj.vjs_searches = sc->sc_comp->sls_searches;
609 			psp->vj.vjs_misses = sc->sc_comp->sls_misses;
610 			psp->vj.vjs_uncompressedin =
611 			    sc->sc_comp->sls_uncompressedin;
612 			psp->vj.vjs_compressedin =
613 			    sc->sc_comp->sls_compressedin;
614 			psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
615 			psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
616 		}
617 #endif /* VJC */
618 		break;
619 
620 #ifdef PPP_COMPRESS
621 	case SIOCGPPPCSTATS:
622 		pcp = &((struct ifpppcstatsreq *) data)->stats;
623 		bzero(pcp, sizeof(*pcp));
624 		if (sc->sc_xc_state != NULL)
625 			(*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
626 		if (sc->sc_rc_state != NULL)
627 			(*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
628 		break;
629 #endif /* PPP_COMPRESS */
630 
631 	default:
632 		error = ENOTTY;
633 	}
634 	splx(s);
635 	return (error);
636 }
637 
638 /*
639  * Queue a packet.  Start transmission if not active.
640  * Packet is placed in Information field of PPP frame.
641  */
642 int
643 pppoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
644     struct rtentry *rtp)
645 {
646 	struct ppp_softc *sc = ifp->if_softc;
647 	int protocol, address, control;
648 	u_char *cp;
649 	int error;
650 	enum NPmode mode;
651 	int len;
652 
653 	if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
654 	    || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
655 		error = ENETDOWN;	/* sort of */
656 		goto bad;
657 	}
658 
659 #ifdef DIAGNOSTIC
660 	if (ifp->if_rdomain != rtable_l2(m0->m_pkthdr.ph_rtableid)) {
661 		printf("%s: trying to send packet on wrong domain. "
662 		    "if %d vs. mbuf %d, AF %d\n", ifp->if_xname,
663 		    ifp->if_rdomain, rtable_l2(m0->m_pkthdr.ph_rtableid),
664 		    dst->sa_family);
665 	}
666 #endif
667 
668 	/*
669 	 * Compute PPP header.
670 	 */
671 	switch (dst->sa_family) {
672 	case AF_INET:
673 		address = PPP_ALLSTATIONS;
674 		control = PPP_UI;
675 		protocol = PPP_IP;
676 		mode = sc->sc_npmode[NP_IP];
677 		break;
678 	case AF_UNSPEC:
679 		address = PPP_ADDRESS(dst->sa_data);
680 		control = PPP_CONTROL(dst->sa_data);
681 		protocol = PPP_PROTOCOL(dst->sa_data);
682 		mode = NPMODE_PASS;
683 		break;
684 	default:
685 		printf("%s: af%d not supported\n", ifp->if_xname,
686 		    dst->sa_family);
687 		error = EAFNOSUPPORT;
688 		goto bad;
689 	}
690 
691 	/*
692 	 * Drop this packet, or return an error, if necessary.
693 	 */
694 	if (mode == NPMODE_ERROR) {
695 		error = ENETDOWN;
696 		goto bad;
697 	}
698 	if (mode == NPMODE_DROP) {
699 		error = 0;
700 		goto bad;
701 	}
702 
703 	/*
704 	 * Add PPP header.  If no space in first mbuf, allocate another.
705 	 */
706 	M_PREPEND(m0, PPP_HDRLEN, M_DONTWAIT);
707 	if (m0 == NULL) {
708 		error = ENOBUFS;
709 		goto bad;
710 	}
711 
712 	cp = mtod(m0, u_char *);
713 	*cp++ = address;
714 	*cp++ = control;
715 	*cp++ = protocol >> 8;
716 	*cp++ = protocol & 0xff;
717 
718 	if ((m0->m_flags & M_PKTHDR) == 0)
719 		panic("mbuf packet without packet header!");
720 	len = m0->m_pkthdr.len;
721 
722 	if (sc->sc_flags & SC_LOG_OUTPKT) {
723 		printf("%s output: ", ifp->if_xname);
724 		pppdumpm(m0);
725 	}
726 
727 	if ((protocol & 0x8000) == 0) {
728 #if NBPFILTER > 0
729 		/*
730 		 * Apply the pass and active filters to the packet,
731 		 * but only if it is a data packet.
732 		 */
733 		*mtod(m0, u_char *) = 1;	/* indicates outbound */
734 		if (sc->sc_pass_filt.bf_insns != 0 &&
735 		    bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *)m0,
736 		    len, 0) == 0) {
737 			error = 0; /* drop this packet */
738 			goto bad;
739 		}
740 
741 		/*
742 		 * Update the time we sent the most recent packet.
743 		 */
744 		if (sc->sc_active_filt.bf_insns == 0 ||
745 		    bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m0,
746 		    len, 0))
747 			sc->sc_last_sent = getuptime();
748 
749 		*mtod(m0, u_char *) = address;
750 #else
751 		/*
752 		 * Update the time we sent the most recent packet.
753 		 */
754 		sc->sc_last_sent = getuptime();
755 #endif
756 	}
757 
758 #if NBPFILTER > 0
759 	/* See if bpf wants to look at the packet. */
760 	if (ifp->if_bpf)
761 		bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
762 #endif
763 
764 	/*
765 	 * Put the packet on the appropriate queue.
766 	 */
767 	if (mode == NPMODE_QUEUE) {
768 		/* XXX we should limit the number of packets on this queue */
769 		ml_enqueue(&sc->sc_npqueue, m0);
770 	} else {
771 		error = ifq_enqueue(&sc->sc_if.if_snd, m0);
772 		if (error) {
773 			sc->sc_if.if_oerrors++;
774 			sc->sc_stats.ppp_oerrors++;
775 			return (error);
776 		}
777 		(*sc->sc_start)(sc);
778 	}
779 	ifp->if_opackets++;
780 	ifp->if_obytes += len;
781 
782 	return (0);
783 
784 bad:
785 	m_freem(m0);
786 	return (error);
787 }
788 
789 
790 
791 /*
792  * After a change in the NPmode for some NP, move packets from the
793  * npqueue to the send queue or the fast queue as appropriate.
794  */
795 static void
796 ppp_requeue(struct ppp_softc *sc)
797 {
798 	struct mbuf_list ml = MBUF_LIST_INITIALIZER();
799 	struct mbuf *m;
800 	enum NPmode mode;
801 	int error;
802 
803 	while ((m = ml_dequeue(&sc->sc_npqueue)) != NULL) {
804 		switch (PPP_PROTOCOL(mtod(m, u_char *))) {
805 		case PPP_IP:
806 			mode = sc->sc_npmode[NP_IP];
807 			break;
808 		default:
809 			mode = NPMODE_PASS;
810 		}
811 
812 		switch (mode) {
813 		case NPMODE_PASS:
814 			error = ifq_enqueue(&sc->sc_if.if_snd, m);
815 			if (error) {
816 				sc->sc_if.if_oerrors++;
817 				sc->sc_stats.ppp_oerrors++;
818 			}
819 			break;
820 
821 		case NPMODE_DROP:
822 		case NPMODE_ERROR:
823 			m_freem(m);
824 			break;
825 
826 		case NPMODE_QUEUE:
827 			ml_enqueue(&ml, m);
828 			break;
829 		}
830 	}
831 	sc->sc_npqueue = ml;
832 }
833 
834 /*
835  * Transmitter has finished outputting some stuff;
836  */
837 void
838 ppp_restart(struct ppp_softc *sc)
839 {
840 	int s = splnet();
841 
842 	sc->sc_flags &= ~SC_TBUSY;
843 	schednetisr(NETISR_PPP);
844 	splx(s);
845 }
846 
847 /*
848  * Get a packet to send.
849  */
850 struct mbuf *
851 ppp_dequeue(struct ppp_softc *sc)
852 {
853 	struct mbuf *m, *mp;
854 	u_char *cp;
855 	int address, control, protocol;
856 
857 	/*
858 	 * Grab a packet to send: first try the fast queue, then the
859 	 * normal queue.
860 	 */
861 	m = ifq_dequeue(&sc->sc_if.if_snd);
862 	if (m == NULL)
863 		return NULL;
864 
865 	++sc->sc_stats.ppp_opackets;
866 
867 	/*
868 	 * Extract the ppp header of the new packet.
869 	 * The ppp header will be in one mbuf.
870 	 */
871 	cp = mtod(m, u_char *);
872 	address = PPP_ADDRESS(cp);
873 	control = PPP_CONTROL(cp);
874 	protocol = PPP_PROTOCOL(cp);
875 
876 	switch (protocol) {
877 	case PPP_IP:
878 #ifdef VJC
879 		/*
880 		 * If the packet is a TCP/IP packet, see if we can compress it.
881 		 */
882 		if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
883 			struct ip *ip;
884 			int type;
885 
886 			mp = m;
887 			ip = (struct ip *)(cp + PPP_HDRLEN);
888 			if (mp->m_len <= PPP_HDRLEN) {
889 				mp = mp->m_next;
890 				if (mp == NULL)
891 					break;
892 				ip = mtod(mp, struct ip *);
893 			}
894 			/*
895 			 * this code assumes the IP/TCP header is in one
896 			 * non-shared mbuf.
897 			 */
898 			if (ip->ip_p == IPPROTO_TCP) {
899 				type = sl_compress_tcp(mp, ip, sc->sc_comp,
900 				    !(sc->sc_flags & SC_NO_TCP_CCID));
901 				switch (type) {
902 				case TYPE_UNCOMPRESSED_TCP:
903 					protocol = PPP_VJC_UNCOMP;
904 					break;
905 				case TYPE_COMPRESSED_TCP:
906 					protocol = PPP_VJC_COMP;
907 					cp = mtod(m, u_char *);
908 					cp[0] = address; /* header has moved */
909 					cp[1] = control;
910 					cp[2] = 0;
911 					break;
912 				}
913 				/* update protocol in PPP header */
914 				cp[3] = protocol;
915 			}
916 		}
917 #endif	/* VJC */
918 		break;
919 
920 #ifdef PPP_COMPRESS
921 	case PPP_CCP:
922 		ppp_ccp(sc, m, 0);
923 		break;
924 #endif	/* PPP_COMPRESS */
925 	}
926 
927 #ifdef PPP_COMPRESS
928 	if (protocol != PPP_LCP && protocol != PPP_CCP &&
929 	    sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
930 		struct mbuf *mcomp = NULL;
931 		int slen;
932 
933 		slen = 0;
934 		for (mp = m; mp != NULL; mp = mp->m_next)
935 			slen += mp->m_len;
936 		(*sc->sc_xcomp->compress)(sc->sc_xc_state, &mcomp, m, slen,
937 		    (sc->sc_flags & SC_CCP_UP ?
938 		    sc->sc_if.if_mtu + PPP_HDRLEN : 0));
939 		if (mcomp != NULL) {
940 			if (sc->sc_flags & SC_CCP_UP) {
941 				/* Send the compressed packet instead. */
942 				m_freem(m);
943 				m = mcomp;
944 				cp = mtod(m, u_char *);
945 				protocol = cp[3];
946 			} else {
947 				/*
948 				 * Can't transmit compressed packets until
949 				 * CCP is up.
950 				 */
951 				m_freem(mcomp);
952 			}
953 		}
954 	}
955 #endif	/* PPP_COMPRESS */
956 
957 	/*
958 	 * Compress the address/control and protocol, if possible.
959 	 */
960 	if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
961 	    control == PPP_UI && protocol != PPP_ALLSTATIONS &&
962 	    protocol != PPP_LCP) {
963 		/* can compress address/control */
964 		m->m_data += 2;
965 		m->m_len -= 2;
966 	}
967 	if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
968 		/* can compress protocol */
969 		if (mtod(m, u_char *) == cp) {
970 			cp[2] = cp[1];	/* move address/control up */
971 			cp[1] = cp[0];
972 		}
973 		++m->m_data;
974 		--m->m_len;
975 	}
976 
977 	return m;
978 }
979 
980 /*
981  * Software interrupt routine.
982  */
983 void
984 pppintr(void)
985 {
986 	struct ppp_softc *sc;
987 	int s;
988 	struct ppp_pkt *pkt;
989 	struct mbuf *m;
990 
991 	NET_ASSERT_LOCKED();
992 
993 	LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
994 		if (!(sc->sc_flags & SC_TBUSY) &&
995 		    (!ifq_empty(&sc->sc_if.if_snd))) {
996 			s = splnet();
997 			sc->sc_flags |= SC_TBUSY;
998 			splx(s);
999 			(*sc->sc_start)(sc);
1000 		}
1001 		while ((pkt = ppp_pkt_dequeue(&sc->sc_rawq)) != NULL) {
1002 			m = ppp_pkt_mbuf(pkt);
1003 			if (m == NULL)
1004 				continue;
1005 			ppp_inproc(sc, m);
1006 		}
1007 	}
1008 }
1009 
1010 #ifdef PPP_COMPRESS
1011 /*
1012  * Handle a CCP packet.  `rcvd' is 1 if the packet was received,
1013  * 0 if it is about to be transmitted.
1014  */
1015 static void
1016 ppp_ccp(struct ppp_softc *sc, struct mbuf *m, int rcvd)
1017 {
1018 	u_char *dp, *ep;
1019 	struct mbuf *mp;
1020 	int slen, s;
1021 
1022 	/*
1023 	 * Get a pointer to the data after the PPP header.
1024 	 */
1025 	if (m->m_len <= PPP_HDRLEN) {
1026 		mp = m->m_next;
1027 		if (mp == NULL)
1028 			return;
1029 		dp = mtod(mp, u_char *);
1030 	} else {
1031 		mp = m;
1032 		dp = mtod(mp, u_char *) + PPP_HDRLEN;
1033 	}
1034 
1035 	ep = mtod(mp, u_char *) + mp->m_len;
1036 	if (dp + CCP_HDRLEN > ep)
1037 		return;
1038 	slen = CCP_LENGTH(dp);
1039 	if (dp + slen > ep) {
1040 		if (sc->sc_flags & SC_DEBUG) {
1041 			printf("if_ppp/ccp: not enough data in mbuf"
1042 			    " (%p+%x > %p+%x)\n", dp, slen,
1043 			    mtod(mp, u_char *), mp->m_len);
1044 		}
1045 		return;
1046 	}
1047 
1048 	switch (CCP_CODE(dp)) {
1049 	case CCP_CONFREQ:
1050 	case CCP_TERMREQ:
1051 	case CCP_TERMACK:
1052 		/* CCP must be going down - disable compression */
1053 		if (sc->sc_flags & SC_CCP_UP) {
1054 			s = splnet();
1055 			sc->sc_flags &=
1056 			    ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
1057 			splx(s);
1058 		}
1059 		break;
1060 
1061 	case CCP_CONFACK:
1062 		if (sc->sc_flags & SC_CCP_OPEN &&
1063 		    !(sc->sc_flags & SC_CCP_UP) &&
1064 		    slen >= CCP_HDRLEN + CCP_OPT_MINLEN &&
1065 		    slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
1066 			if (!rcvd) {
1067 				/* we're agreeing to send compressed packets. */
1068 				if (sc->sc_xc_state != NULL &&
1069 				    (*sc->sc_xcomp->comp_init)(sc->sc_xc_state,
1070 				    dp + CCP_HDRLEN, slen - CCP_HDRLEN,
1071 				    sc->sc_unit, 0, sc->sc_flags & SC_DEBUG)) {
1072 					s = splnet();
1073 					sc->sc_flags |= SC_COMP_RUN;
1074 					splx(s);
1075 				}
1076 			} else {
1077 				/* peer agrees to send compressed packets */
1078 				if (sc->sc_rc_state != NULL &&
1079 				    (*sc->sc_rcomp->decomp_init)(
1080 				     sc->sc_rc_state, dp + CCP_HDRLEN,
1081 				     slen - CCP_HDRLEN, sc->sc_unit, 0,
1082 				     sc->sc_mru, sc->sc_flags & SC_DEBUG)) {
1083 					s = splnet();
1084 					sc->sc_flags |= SC_DECOMP_RUN;
1085 					sc->sc_flags &=
1086 					    ~(SC_DC_ERROR | SC_DC_FERROR);
1087 					splx(s);
1088 				}
1089 			}
1090 		}
1091 		break;
1092 
1093 	case CCP_RESETACK:
1094 		if (sc->sc_flags & SC_CCP_UP) {
1095 			if (!rcvd) {
1096 				if (sc->sc_xc_state &&
1097 				    (sc->sc_flags & SC_COMP_RUN)) {
1098 					(*sc->sc_xcomp->comp_reset)(
1099 					    sc->sc_xc_state);
1100 				}
1101 			} else {
1102 				if (sc->sc_rc_state &&
1103 				    (sc->sc_flags & SC_DECOMP_RUN)) {
1104 					(*sc->sc_rcomp->decomp_reset)(
1105 					    sc->sc_rc_state);
1106 					s = splnet();
1107 					sc->sc_flags &= ~SC_DC_ERROR;
1108 					splx(s);
1109 				}
1110 			}
1111 		}
1112 		break;
1113 	}
1114 }
1115 
1116 /*
1117  * CCP is down; free (de)compressor state if necessary.
1118  */
1119 static void
1120 ppp_ccp_closed(struct ppp_softc *sc)
1121 {
1122 	if (sc->sc_xc_state) {
1123 		(*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
1124 		sc->sc_xc_state = NULL;
1125 	}
1126 	if (sc->sc_rc_state) {
1127 		(*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
1128 		sc->sc_rc_state = NULL;
1129 	}
1130 }
1131 #endif /* PPP_COMPRESS */
1132 
1133 /*
1134  * PPP packet input routine.
1135  * The caller has checked and removed the FCS and has inserted
1136  * the address/control bytes and the protocol high byte if they
1137  * were omitted.
1138  */
1139 void
1140 ppppktin(struct ppp_softc *sc, struct ppp_pkt *pkt, int lost)
1141 {
1142 	pkt->p_hdr.ph_errmark = lost;
1143 	if (ppp_pkt_enqueue(&sc->sc_rawq, pkt) == 0)
1144 		schednetisr(NETISR_PPP);
1145 }
1146 
1147 /*
1148  * Process a received PPP packet, doing decompression as necessary.
1149  */
1150 #define COMPTYPE(proto)	((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
1151 			 TYPE_UNCOMPRESSED_TCP)
1152 
1153 static void
1154 ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
1155 {
1156 	struct ifnet *ifp = &sc->sc_if;
1157 	int s, ilen, xlen, proto, rv;
1158 	u_char *cp, adrs, ctrl;
1159 	struct mbuf *mp, *dmp = NULL;
1160 	u_char *iphdr;
1161 	u_int hlen;
1162 
1163 	sc->sc_stats.ppp_ipackets++;
1164 
1165 	if (sc->sc_flags & SC_LOG_INPKT) {
1166 		ilen = 0;
1167 		for (mp = m; mp != NULL; mp = mp->m_next)
1168 			ilen += mp->m_len;
1169 		printf("%s: got %d bytes\n", ifp->if_xname, ilen);
1170 		pppdumpm(m);
1171 	}
1172 
1173 	cp = mtod(m, u_char *);
1174 	adrs = PPP_ADDRESS(cp);
1175 	ctrl = PPP_CONTROL(cp);
1176 	proto = PPP_PROTOCOL(cp);
1177 
1178 	if (m->m_flags & M_ERRMARK) {
1179 		m->m_flags &= ~M_ERRMARK;
1180 		s = splnet();
1181 		sc->sc_flags |= SC_VJ_RESET;
1182 		splx(s);
1183 	}
1184 
1185 #ifdef PPP_COMPRESS
1186 	/*
1187 	 * Decompress this packet if necessary, update the receiver's
1188 	 * dictionary, or take appropriate action on a CCP packet.
1189 	 */
1190 	if (proto == PPP_COMP && sc->sc_rc_state &&
1191 	    (sc->sc_flags & SC_DECOMP_RUN) && !(sc->sc_flags & SC_DC_ERROR) &&
1192 	    !(sc->sc_flags & SC_DC_FERROR)) {
1193 		/* decompress this packet */
1194 		rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
1195 		if (rv == DECOMP_OK) {
1196 			m_freem(m);
1197 			if (dmp == NULL) {
1198 				/*
1199 				 * no error, but no decompressed packet
1200 				 * produced
1201 				 */
1202 				return;
1203 			}
1204 			m = dmp;
1205 			cp = mtod(m, u_char *);
1206 			proto = PPP_PROTOCOL(cp);
1207 
1208 		} else {
1209 			/*
1210 			 * An error has occurred in decompression.
1211 			 * Pass the compressed packet up to pppd, which may
1212 			 * take CCP down or issue a Reset-Req.
1213 			 */
1214 			if (sc->sc_flags & SC_DEBUG) {
1215 				printf("%s: decompress failed %d\n",
1216 				    ifp->if_xname, rv);
1217 			}
1218 			s = splnet();
1219 			sc->sc_flags |= SC_VJ_RESET;
1220 			if (rv == DECOMP_ERROR)
1221 				sc->sc_flags |= SC_DC_ERROR;
1222 			else
1223 				sc->sc_flags |= SC_DC_FERROR;
1224 			splx(s);
1225 		}
1226 
1227 	} else {
1228 		if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
1229 			(*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
1230 		}
1231 		if (proto == PPP_CCP) {
1232 			ppp_ccp(sc, m, 1);
1233 		}
1234 	}
1235 #endif
1236 
1237 	ilen = 0;
1238 	for (mp = m; mp != NULL; mp = mp->m_next)
1239 		ilen += mp->m_len;
1240 
1241 #ifdef VJC
1242 	if (sc->sc_flags & SC_VJ_RESET) {
1243 		/*
1244 		* If we've missed a packet, we must toss subsequent compressed
1245 		* packets which don't have an explicit connection ID.
1246 		*/
1247 		if (sc->sc_comp)
1248 			sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
1249 		s = splnet();
1250 		sc->sc_flags &= ~SC_VJ_RESET;
1251 		splx(s);
1252 	}
1253 
1254 	/*
1255 	 * See if we have a VJ-compressed packet to uncompress.
1256 	 */
1257 	if (proto == PPP_VJC_COMP) {
1258 		if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1259 			goto bad;
1260 
1261 		xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
1262 		    m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
1263 		    TYPE_COMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
1264 
1265 		if (xlen <= 0) {
1266 			if (sc->sc_flags & SC_DEBUG) {
1267 				printf("%s: VJ uncompress failed "
1268 				    "on type comp\n", ifp->if_xname);
1269 			}
1270 			goto bad;
1271 		}
1272 
1273 		/* Copy the PPP and IP headers into a new mbuf. */
1274 		MGETHDR(mp, M_DONTWAIT, MT_DATA);
1275 		if (mp == NULL)
1276 			goto bad;
1277 		mp->m_len = 0;
1278 		mp->m_next = NULL;
1279 		if (hlen + PPP_HDRLEN > MHLEN) {
1280 			MCLGET(mp, M_DONTWAIT);
1281 			if (m_trailingspace(mp) < hlen + PPP_HDRLEN) {
1282 				m_freem(mp);
1283 				/* lose if big headers and no clusters */
1284 				goto bad;
1285 			}
1286 		}
1287 		if (m->m_flags & M_PKTHDR)
1288 			M_MOVE_HDR(mp, m);
1289 		cp = mtod(mp, u_char *);
1290 		cp[0] = adrs;
1291 		cp[1] = ctrl;
1292 		cp[2] = 0;
1293 		cp[3] = PPP_IP;
1294 		proto = PPP_IP;
1295 		bcopy(iphdr, cp + PPP_HDRLEN, hlen);
1296 		mp->m_len = hlen + PPP_HDRLEN;
1297 
1298 		/*
1299 		 * Trim the PPP and VJ headers off the old mbuf
1300 		 * and stick the new and old mbufs together.
1301 		 */
1302 		m->m_data += PPP_HDRLEN + xlen;
1303 		m->m_len -= PPP_HDRLEN + xlen;
1304 		if (m->m_len <= m_trailingspace(mp)) {
1305 			bcopy(mtod(m, u_char *),
1306 			    mtod(mp, u_char *) + mp->m_len, m->m_len);
1307 			mp->m_len += m->m_len;
1308 			mp->m_next = m_free(m);
1309 		} else
1310 			mp->m_next = m;
1311 		m = mp;
1312 		ilen += hlen - xlen;
1313 
1314 	} else if (proto == PPP_VJC_UNCOMP) {
1315 		if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
1316 			goto bad;
1317 
1318 		xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN,
1319 		    m->m_len - PPP_HDRLEN, ilen - PPP_HDRLEN,
1320 		    TYPE_UNCOMPRESSED_TCP, sc->sc_comp, &iphdr, &hlen);
1321 
1322 		if (xlen < 0) {
1323 			if (sc->sc_flags & SC_DEBUG) {
1324 				printf("%s: VJ uncompress failed "
1325 				    "on type uncomp\n", ifp->if_xname);
1326 			}
1327 			goto bad;
1328 		}
1329 
1330 		proto = PPP_IP;
1331 		cp[3] = PPP_IP;
1332 	}
1333 #endif /* VJC */
1334 
1335 	m->m_pkthdr.len = ilen;
1336 	m->m_pkthdr.ph_ifidx = ifp->if_index;
1337 
1338 	/* mark incoming routing table */
1339 	m->m_pkthdr.ph_rtableid = ifp->if_rdomain;
1340 
1341 	if ((proto & 0x8000) == 0) {
1342 #if NBPFILTER > 0
1343 		/*
1344 		 * See whether we want to pass this packet, and
1345 		 * if it counts as link activity.
1346 		 */
1347 		adrs = *mtod(m, u_char *);	/* save address field */
1348 		*mtod(m, u_char *) = 0;		/* indicate inbound */
1349 		if (sc->sc_pass_filt.bf_insns != 0 &&
1350 		    bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
1351 		     ilen, 0) == 0) {
1352 			/* drop this packet */
1353 			m_freem(m);
1354 			return;
1355 		}
1356 		if (sc->sc_active_filt.bf_insns == 0 ||
1357 		    bpf_filter(sc->sc_active_filt.bf_insns, (u_char *)m,
1358 		     ilen, 0))
1359 			sc->sc_last_recv = getuptime();
1360 
1361 		*mtod(m, u_char *) = adrs;
1362 #else
1363 		/*
1364 		 * Record the time that we received this packet.
1365 		 */
1366 		sc->sc_last_recv = getuptime();
1367 #endif
1368 	}
1369 
1370 #if NBPFILTER > 0
1371 	/* See if bpf wants to look at the packet. */
1372 	if (ifp->if_bpf)
1373 		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1374 #endif
1375 
1376 	rv = 0;
1377 	switch (proto) {
1378 	case PPP_IP:
1379 		/*
1380 		 * IP packet - take off the ppp header and pass it up to IP.
1381 		 */
1382 		if ((ifp->if_flags & IFF_UP) == 0 ||
1383 		    sc->sc_npmode[NP_IP] != NPMODE_PASS) {
1384 			/* interface is down - drop the packet. */
1385 			m_freem(m);
1386 			return;
1387 		}
1388 		m->m_pkthdr.len -= PPP_HDRLEN;
1389 		m->m_data += PPP_HDRLEN;
1390 		m->m_len -= PPP_HDRLEN;
1391 
1392 		ipv4_input(ifp, m);
1393 		rv = 1;
1394 		break;
1395 
1396 	default:
1397 		/*
1398 		 * Some other protocol - place on input queue for read().
1399 		 */
1400 		if (mq_enqueue(&sc->sc_inq, m) != 0) {
1401 			if_congestion();
1402 			rv = 0; /* failure */
1403 		} else
1404 			rv = 2; /* input queue */
1405 		break;
1406 	}
1407 
1408 	if (rv == 0) {
1409 		/* failure */
1410 		if (sc->sc_flags & SC_DEBUG)
1411 			printf("%s: input queue full\n", ifp->if_xname);
1412 		ifp->if_iqdrops++;
1413 		goto dropped;
1414 	}
1415 
1416 	ifp->if_ipackets++;
1417 	ifp->if_ibytes += ilen;
1418 
1419 	if (rv == 2)
1420 		(*sc->sc_ctlp)(sc);
1421 
1422 	return;
1423 
1424 bad:
1425 	m_freem(m);
1426 dropped:
1427 	sc->sc_if.if_ierrors++;
1428 	sc->sc_stats.ppp_ierrors++;
1429 }
1430 
1431 #define MAX_DUMP_BYTES	128
1432 
1433 static void
1434 pppdumpm(struct mbuf *m0)
1435 {
1436 	char buf[3*MAX_DUMP_BYTES+4];
1437 	char *bp = buf;
1438 	struct mbuf *m;
1439 	static char digits[] = "0123456789abcdef";
1440 
1441 	for (m = m0; m; m = m->m_next) {
1442 		int l = m->m_len;
1443 		u_char *rptr = mtod(m, u_char *);
1444 
1445 		while (l--) {
1446 			if (bp > buf + sizeof(buf) - 4)
1447 				goto done;
1448 
1449 			/* convert byte to ascii hex */
1450 			*bp++ = digits[*rptr >> 4];
1451 			*bp++ = digits[*rptr++ & 0xf];
1452 		}
1453 
1454 		if (m->m_next) {
1455 			if (bp > buf + sizeof(buf) - 3)
1456 				goto done;
1457 			*bp++ = '|';
1458 		} else
1459 			*bp++ = ' ';
1460 	}
1461 done:
1462 	if (m)
1463 		*bp++ = '>';
1464 	*bp = 0;
1465 	printf("%s\n", buf);
1466 }
1467 
1468 static void
1469 ppp_ifstart(struct ifnet *ifp)
1470 {
1471 	struct ppp_softc *sc;
1472 
1473 	sc = ifp->if_softc;
1474 	(*sc->sc_start)(sc);
1475 }
1476 
1477 void
1478 ppp_pkt_list_init(struct ppp_pkt_list *pl, u_int limit)
1479 {
1480 	mtx_init(&pl->pl_mtx, IPL_TTY);
1481 	pl->pl_head = pl->pl_tail = NULL;
1482 	pl->pl_count = 0;
1483 	pl->pl_limit = limit;
1484 }
1485 
1486 int
1487 ppp_pkt_enqueue(struct ppp_pkt_list *pl, struct ppp_pkt *pkt)
1488 {
1489 	int drop = 0;
1490 
1491 	mtx_enter(&pl->pl_mtx);
1492 	if (pl->pl_count < pl->pl_limit) {
1493 		if (pl->pl_tail == NULL)
1494 			pl->pl_head = pl->pl_tail = pkt;
1495 		else {
1496 			PKT_NEXTPKT(pl->pl_tail) = pkt;
1497 			pl->pl_tail = pkt;
1498 		}
1499 		PKT_NEXTPKT(pkt) = NULL;
1500 		pl->pl_count++;
1501 	} else
1502 		drop = 1;
1503 	mtx_leave(&pl->pl_mtx);
1504 
1505 	if (drop)
1506 		ppp_pkt_free(pkt);
1507 
1508 	return (drop);
1509 }
1510 
1511 struct ppp_pkt *
1512 ppp_pkt_dequeue(struct ppp_pkt_list *pl)
1513 {
1514 	struct ppp_pkt *pkt;
1515 
1516 	mtx_enter(&pl->pl_mtx);
1517 	pkt = pl->pl_head;
1518 	if (pkt != NULL) {
1519 		pl->pl_head = PKT_NEXTPKT(pkt);
1520 		if (pl->pl_head == NULL)
1521 			pl->pl_tail = NULL;
1522 
1523 		pl->pl_count--;
1524 	}
1525 	mtx_leave(&pl->pl_mtx);
1526 
1527 	return (pkt);
1528 }
1529 
1530 struct mbuf *
1531 ppp_pkt_mbuf(struct ppp_pkt *pkt0)
1532 {
1533 	extern struct pool ppp_pkts;
1534 	struct mbuf *m0 = NULL, **mp = &m0, *m;
1535 	struct ppp_pkt *pkt = pkt0;
1536 	size_t len = 0;
1537 
1538 	do {
1539 		MGETHDR(m, M_DONTWAIT, MT_DATA);
1540 		if (m == NULL)
1541 			goto fail;
1542 
1543 		MEXTADD(m, pkt, sizeof(*pkt), M_EXTWR,
1544 		    MEXTFREE_POOL, &ppp_pkts);
1545 		m->m_data += sizeof(pkt->p_hdr);
1546 		m->m_len = PKT_LEN(pkt);
1547 
1548 		len += m->m_len;
1549 
1550 		*mp = m;
1551 		mp = &m->m_next;
1552 
1553 		pkt = PKT_NEXT(pkt);
1554 	} while (pkt != NULL);
1555 
1556 	m0->m_pkthdr.len = len;
1557 	if (pkt0->p_hdr.ph_errmark)
1558 		m0->m_flags |= M_ERRMARK;
1559 
1560 	return (m0);
1561 
1562 fail:
1563 	m_freem(m0);
1564 	ppp_pkt_free(pkt0);
1565 	return (NULL);
1566 }
1567 
1568 #endif	/* NPPP > 0 */
1569