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