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