root/net/if_ppp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pppattach
  2. ppp_clone_create
  3. ppp_clone_destroy
  4. pppalloc
  5. pppdealloc
  6. pppioctl
  7. pppsioctl
  8. pppoutput
  9. ppp_requeue
  10. ppp_restart
  11. ppp_dequeue
  12. pppintr
  13. ppp_ccp
  14. ppp_ccp_closed
  15. ppppktin
  16. ppp_inproc
  17. pppdumpm
  18. ppp_ifstart

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

/* [<][>][^][v][top][bottom][index][help] */