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