source: rtems/c/src/libnetworking/pppd/modem_example/ppp.c @ 6fa6367

4.104.114.84.95
Last change on this file since 6fa6367 was 6fa6367, checked in by Joel Sherrill <joel.sherrill@…>, on 04/20/01 at 20:32:08

2001-04-20 Radzislaw Galler <rgaller@…>

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