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