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