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