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