Annotation of XNU/bsd/net/if_ppp.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.