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