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