source: rtems/c/src/libnetworking/modem/ppp.c @ 85a0f07

4.104.114.84.95
Last change on this file since 85a0f07 was 85a0f07, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 25, 2000 at 10:10:01 PM

2000-11-25 Antti P Miettinen <antti.p.miettinen@…>

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