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