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