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