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

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
                     28:  *
                     29:  * Copyright (c) 1989 Carnegie Mellon University.
                     30:  * All rights reserved.
                     31:  *
                     32:  * Redistribution and use in source and binary forms are permitted
                     33:  * provided that the above copyright notice and this paragraph are
                     34:  * duplicated in all such forms and that any documentation,
                     35:  * advertising materials, and other materials related to such
                     36:  * distribution and use acknowledge that the software was developed
                     37:  * by Carnegie Mellon University.  The name of the
                     38:  * University may not be used to endorse or promote products derived
                     39:  * from this software without specific prior written permission.
                     40:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     41:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     42:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     43:  *
                     44:  * Drew D. Perkins
                     45:  * Carnegie Mellon University
                     46:  * 4910 Forbes Ave.
                     47:  * Pittsburgh, PA 15213
                     48:  * (412) 268-8576
                     49:  * [email protected]
                     50:  *
                     51:  * Based on:
                     52:  *     @(#)if_sl.c     7.6.1.2 (Berkeley) 2/15/89
                     53:  *
                     54:  * Copyright (c) 1987 Regents of the University of California.
                     55:  * All rights reserved.
                     56:  *
                     57:  * Redistribution and use in source and binary forms are permitted
                     58:  * provided that the above copyright notice and this paragraph are
                     59:  * duplicated in all such forms and that any documentation,
                     60:  * advertising materials, and other materials related to such
                     61:  * distribution and use acknowledge that the software was developed
                     62:  * by the University of California, Berkeley.  The name of the
                     63:  * University may not be used to endorse or promote products derived
                     64:  * from this software without specific prior written permission.
                     65:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     66:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     67:  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     68:  *
                     69:  * Serial Line interface
                     70:  *
                     71:  * Rick Adams
                     72:  * Center for Seismic Studies
                     73:  * 1300 N 17th Street, Suite 1450
                     74:  * Arlington, Virginia 22209
                     75:  * (703)276-7900
                     76:  * [email protected]
                     77:  * seismo!rick
                     78:  *
                     79:  * Pounded on heavily by Chris Torek ([email protected], umcp-cs!chris).
                     80:  * Converted to 4.3BSD Beta by Chris Torek.
                     81:  * Other changes made at Berkeley, based in part on code by Kirk Smith.
                     82:  *
                     83:  * Converted to 4.3BSD+ 386BSD by Brad Parker ([email protected])
                     84:  * Added VJ tcp header compression; more unified ioctls
                     85:  *
                     86:  * Extensively modified by Paul Mackerras ([email protected]).
                     87:  * Cleaned up a lot of the mbuf-related code to fix bugs that
                     88:  * caused system crashes and packet corruption.  Changed pppstart
                     89:  * so that it doesn't just give up with a collision if the whole
                     90:  * packet doesn't fit in the output ring buffer.
                     91:  *
                     92:  * Added priority queueing for interactive IP packets, following
                     93:  * the model of if_sl.c, plus hooks for bpf.
                     94:  * Paul Mackerras ([email protected]).
                     95:  */
                     96: 
                     97: /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
                     98: 
                     99: #include "ppp.h"
                    100: #if NPPP > 0
                    101: 
                    102: #define VJC
                    103: 
                    104: #include <sys/param.h>
                    105: #include <sys/proc.h>
                    106: #include <sys/mbuf.h>
                    107: #include <sys/buf.h>
                    108: #include <sys/dkstat.h>
                    109: #include <sys/socket.h>
                    110: #include <sys/ioctl.h>
                    111: #include <sys/file.h>
                    112: #include <sys/tty.h>
                    113: #include <sys/kernel.h>
                    114: #include <sys/conf.h>
                    115: #include <sys/vnode.h>
                    116: 
                    117: #include <net/if.h>
                    118: #include <net/if_types.h>
                    119: #include <net/netisr.h>
                    120: #include <net/route.h>
                    121: 
                    122: #if INET
                    123: #include <netinet/in.h>
                    124: #include <netinet/in_systm.h>
                    125: #include <netinet/in_var.h>
                    126: #include <netinet/ip.h>
                    127: #endif
                    128: 
                    129: #include "bpfilter.h"
                    130: #if NBPFILTER > 0
                    131: #include <sys/time.h>
                    132: #include <net/bpf.h>
                    133: #endif
                    134: 
                    135: #ifdef VJC
                    136: #include <net/slcompress.h>
                    137: #define HDROFF MAX_HDR
                    138: /* HDROFF should really be 128, but other parts of the system will
                    139:    panic on TCP+IP headers bigger than MAX_HDR = MHLEN (100). */
                    140: 
                    141: #else
                    142: #define        HDROFF  (0)
                    143: #endif
                    144: 
                    145: #include <net/if_ppp.h>
                    146: #include <machine/cpu.h>
                    147: 
                    148: #define CCOUNT(q)      ((q)->c_cc)
                    149: 
                    150: #define        PPP_HIWAT       400     /* Don't start a new packet if HIWAT on que */
                    151: 
                    152: struct ppp_softc ppp_softc[NPPP];
                    153: 
                    154: void   pppattach __P((void));
                    155: int    pppopen __P((dev_t dev, struct tty *tp));
                    156: void   pppclose __P((struct tty *tp, int flag));
                    157: int    pppread __P((struct tty *tp, struct uio *uio, int flag));
                    158: int    pppwrite __P((struct tty *tp, struct uio *uio, int flag));
                    159: int    ppptioctl __P((struct tty *tp, u_long cmd, caddr_t data, int flag,
                    160:                       struct proc *));
                    161: int    pppoutput __P((struct ifnet *ifp, struct mbuf *m0,
                    162:                       struct sockaddr *dst, struct rtentry *rtp));
                    163: void   pppinput __P((int c, struct tty *tp));
                    164: int    pppioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data));
                    165: void   pppstart __P((struct tty *tp));
                    166: 
                    167: static int     pppasyncstart __P((struct ppp_softc *));
                    168: static u_int16_t pppfcs __P((u_int fcs, u_char *cp, int len));
                    169: static int     pppgetm __P((struct ppp_softc *sc));
                    170: static void    pppdumpm __P((struct mbuf *m0, int pktlen));
                    171: static void    pppdumpb __P((u_char *b, int l));
                    172: static void    ppplogchar __P((struct ppp_softc *, int));
                    173: 
                    174: /*
                    175:  * Some useful mbuf macros not in mbuf.h.
                    176:  */
                    177: #define M_DATASTART(m) \
                    178:        ((m)->m_flags & M_EXT ? (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)->m_flags & M_EXT ? (m)->m_ext.ext_size : \
                    183:            (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
                    184: 
                    185: /*
                    186:  * The following disgusting hack gets around the problem that IP TOS
                    187:  * can't be set yet.  We want to put "interactive" traffic on a high
                    188:  * priority queue.  To decide if traffic is interactive, we check that
                    189:  * a) it is TCP and b) one of its ports is telnet, rlogin or ftp control.
                    190:  */
                    191: static u_int16_t interactive_ports[8] = {
                    192:        0,      513,    0,      0,
                    193:        0,      21,     0,      23,
                    194: };
                    195: #define INTERACTIVE(p) (interactive_ports[(p) & 7] == (p))
                    196: 
                    197: /*
                    198:  * Does c need to be escaped?
                    199:  */
                    200: #define ESCAPE_P(c)    (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
                    201: 
                    202: /*
                    203:  * Called from boot code to establish ppp interfaces.
                    204:  */
                    205: void
                    206: pppattach()
                    207: {
                    208:     register struct ppp_softc *sc;
                    209:     register int i = 0;
                    210: 
                    211:     for (sc = ppp_softc; i < NPPP; sc++) {
                    212:        sc->sc_if.if_name = "ppp";
                    213:        sc->sc_if.if_unit = i++;
                    214:        sc->sc_if.if_mtu = PPP_MTU;
                    215:        sc->sc_if.if_flags = IFF_POINTOPOINT;
                    216:        sc->sc_if.if_type = IFT_PPP;
                    217:        sc->sc_if.if_hdrlen = PPP_HDRLEN;
                    218:        sc->sc_if.if_ioctl = pppioctl;
                    219:        sc->sc_if.if_output = pppoutput;
                    220:        sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
                    221:        sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
                    222:        sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
                    223:        if_attach(&sc->sc_if);
                    224: #if NBPFILTER > 0
                    225:        bpfattach(&sc->sc_bpf, &sc->sc_if, DLT_PPP, PPP_HDRLEN);
                    226: #endif
                    227:     }
                    228: }
                    229: 
                    230: /*
                    231:  * Allocate a ppp interface unit and initialize it.
                    232:  */
                    233: struct ppp_softc *
                    234: pppalloc(pid)
                    235:     pid_t pid;
                    236: {
                    237:     int nppp;
                    238:     struct ppp_softc *sc;
                    239: 
                    240:     for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
                    241:        if (sc->sc_xfer == pid) {
                    242:            sc->sc_xfer = 0;
                    243:            break;
                    244:        }
                    245:     if (nppp >= NPPP)
                    246:        for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
                    247:            if (sc->sc_devp == NULL)
                    248:                break;
                    249:     if (nppp >= NPPP)
                    250:        return NULL;
                    251: 
                    252:     sc->sc_flags = 0;
                    253:     sc->sc_mru = PPP_MRU;
                    254: #ifdef VJC
                    255:     sl_compress_init(&sc->sc_comp, -1);
                    256: #endif
                    257:     sc->sc_if.if_flags |= IFF_RUNNING;
                    258: 
                    259:     return sc;
                    260: }
                    261: 
                    262: /*
                    263:  * Deallocate a ppp unit.
                    264:  */
                    265: pppdealloc(sc)
                    266:     struct ppp_softc *sc;
                    267: {
                    268:     struct mbuf *m;
                    269: 
                    270:     if_down(&sc->sc_if);
                    271:     sc->sc_devp = NULL;
                    272:     sc->sc_xfer = 0;
                    273:     for (;;) {
                    274:        IF_DEQUEUE(&sc->sc_inq, m);
                    275:        if (m == NULL)
                    276:            break;
                    277:        m_freem(m);
                    278:     }
                    279:     for (;;) {
                    280:        IF_DEQUEUE(&sc->sc_fastq, m);
                    281:        if (m == NULL)
                    282:            break;
                    283:        m_freem(m);
                    284:     }
                    285:     sc->sc_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
                    286: }
                    287:     
                    288: /*
                    289:  * Line specific open routine for async tty devices.
                    290:  * Attach the given tty to the first available ppp unit.
                    291:  */
                    292: /* ARGSUSED */
                    293: int
                    294: pppopen(dev, tp)
                    295:     dev_t dev;
                    296:     register struct tty *tp;
                    297: {
                    298:     struct proc *p = current_proc();           /* XXX */
                    299:     register struct ppp_softc *sc;
                    300:     int error, s, i;
                    301: 
                    302:     if (error = suser(p->p_ucred, &p->p_acflag))
                    303:        return (error);
                    304: 
                    305:     if (tp->t_line == PPPDISC) {
                    306:        sc = (struct ppp_softc *) tp->t_sc;
                    307:        if (sc != NULL && sc->sc_devp == (void *) tp)
                    308:            return (0);
                    309:     }
                    310: 
                    311:     if ((sc = pppalloc(p->p_pid)) == NULL)
                    312:        return ENXIO;
                    313: 
                    314:     if (sc->sc_outm != NULL) {
                    315:        m_freem(sc->sc_outm);
                    316:        sc->sc_outm = NULL;
                    317:     }
                    318:        
                    319:     pppgetm(sc);
                    320: 
                    321:     sc->sc_ilen = 0;
                    322:     bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
                    323:     sc->sc_asyncmap[0] = 0xffffffff;
                    324:     sc->sc_asyncmap[3] = 0x60000000;
                    325:     sc->sc_rasyncmap = 0;
                    326:     sc->sc_devp = (void *) tp;
                    327:     sc->sc_start = pppasyncstart;
                    328: 
                    329:     tp->t_sc = (caddr_t) sc;
                    330:     ttyflush(tp, FREAD | FWRITE);
                    331: 
                    332:     return (0);
                    333: }
                    334: 
                    335: /*
                    336:  * Line specific close routine.
                    337:  * Detach the tty from the ppp unit.
                    338:  * Mimics part of ttyclose().
                    339:  */
                    340: void
                    341: pppclose(tp, flag)
                    342:     struct tty *tp;
                    343:     int flag;
                    344: {
                    345:     register struct ppp_softc *sc;
                    346:     struct mbuf *m;
                    347:     int s;
                    348: 
                    349:     ttywflush(tp);
                    350:     s = splimp();              /* paranoid; splnet probably ok */
                    351:     tp->t_line = 0;
                    352:     sc = (struct ppp_softc *)tp->t_sc;
                    353:     if (sc != NULL) {
                    354:        tp->t_sc = NULL;
                    355:        if (tp == (struct tty *) sc->sc_devp) {
                    356:            m_freem(sc->sc_outm);
                    357:            sc->sc_outm = NULL;
                    358:            m_freem(sc->sc_m);
                    359:            sc->sc_m = NULL;
                    360:            pppdealloc(sc);
                    361:        }
                    362:     }
                    363:     splx(s);
                    364: }
                    365: 
                    366: /*
                    367:  * Line specific (tty) read routine.
                    368:  */
                    369: int
                    370: pppread(tp, uio, flag)
                    371:     register struct tty *tp;
                    372:     struct uio *uio;
                    373:     int flag;
                    374: {
                    375:     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
                    376:     struct mbuf *m, *m0;
                    377:     register int s;
                    378:     int error = 0;
                    379: 
                    380:     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
                    381:        return 0;               /* end of file */
                    382:     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
                    383:        return 0;
                    384:     s = splimp();
                    385:     while (sc->sc_inq.ifq_head == NULL && tp->t_line == PPPDISC) {
                    386:        if (tp->t_state & TS_ASYNC || flag & IO_NDELAY) {
                    387:            splx(s);
                    388:            return (EWOULDBLOCK);
                    389:        }
                    390:        error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI|PCATCH, ttyin, 0);
                    391:        if (error) {
                    392:            splx(s);
                    393:            return error;
                    394:        }
                    395:     }
                    396:     if (tp->t_line != PPPDISC) {
                    397:        splx(s);
                    398:        return (-1);
                    399:     }
                    400: 
                    401:     /* Pull place-holder byte out of canonical queue */
                    402:     getc(&tp->t_canq);
                    403: 
                    404:     /* Get the packet from the input queue */
                    405:     IF_DEQUEUE(&sc->sc_inq, m0);
                    406:     splx(s);
                    407: 
                    408:     for (m = m0; m && uio->uio_resid; m = m->m_next)
                    409:        if (error = uiomove(mtod(m, u_char *), m->m_len, uio))
                    410:            break;
                    411:     m_freem(m0);
                    412:     return (error);
                    413: }
                    414: 
                    415: /*
                    416:  * Line specific (tty) write routine.
                    417:  */
                    418: int
                    419: pppwrite(tp, uio, flag)
                    420:     register struct tty *tp;
                    421:     struct uio *uio;
                    422:     int flag;
                    423: {
                    424:     register struct ppp_softc *sc = (struct ppp_softc *)tp->t_sc;
                    425:     struct mbuf *m, *m0, **mp;
                    426:     struct sockaddr dst;
                    427:     struct ppp_header *ph1, *ph2;
                    428:     int len, error;
                    429: 
                    430:     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0)
                    431:        return 0;               /* wrote 0 bytes */
                    432:     if (tp->t_line != PPPDISC)
                    433:        return (EINVAL);
                    434:     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
                    435:        return EIO;
                    436:     if (uio->uio_resid > sc->sc_if.if_mtu + PPP_HDRLEN ||
                    437:        uio->uio_resid < PPP_HDRLEN)
                    438:        return (EMSGSIZE);
                    439:     for (mp = &m0; uio->uio_resid; mp = &m->m_next) {
                    440:        MGET(m, M_WAIT, MT_DATA);
                    441:        if ((*mp = m) == NULL) {
                    442:            m_freem(m0);
                    443:            return (ENOBUFS);
                    444:        }
                    445:        m->m_len = 0;
                    446:        if (uio->uio_resid >= MCLBYTES / 2)
                    447:            MCLGET(m, M_DONTWAIT);
                    448:        len = M_TRAILINGSPACE(m);
                    449:        if (len > uio->uio_resid)
                    450:            len = uio->uio_resid;
                    451:        if (error = uiomove(mtod(m, u_char *), len, uio)) {
                    452:            m_freem(m0);
                    453:            return (error);
                    454:        }
                    455:        m->m_len = len;
                    456:     }
                    457:     dst.sa_family = AF_UNSPEC;
                    458:     ph1 = (struct ppp_header *) &dst.sa_data;
                    459:     ph2 = mtod(m0, struct ppp_header *);
                    460:     *ph1 = *ph2;
                    461:     m0->m_data += PPP_HDRLEN;
                    462:     m0->m_len -= PPP_HDRLEN;
                    463:     return (pppoutput(&sc->sc_if, m0, &dst, (struct rtentry *)0));
                    464: }
                    465: 
                    466: /*
                    467:  * Line specific (tty) ioctl routine.
                    468:  * Provide a way to get the ppp unit number.
                    469:  * This discipline requires that tty device drivers call
                    470:  * the line specific l_ioctl routine from their ioctl routines.
                    471:  */
                    472: /* ARGSUSED */
                    473: int
                    474: ppptioctl(tp, cmd, data, flag, p)
                    475:     struct tty *tp;
                    476:     u_long cmd;
                    477:     caddr_t data;
                    478:     int flag;
                    479:     struct proc *p;
                    480: {
                    481:     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
                    482:     int s, error, flags, mru;
                    483: 
                    484:     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
                    485:        return -1;
                    486: 
                    487:     switch (cmd) {
                    488:     case FIONREAD:
                    489:        *(int *)data = sc->sc_inq.ifq_len;
                    490:        break;
                    491: 
                    492:     case PPPIOCGUNIT:
                    493:        *(int *)data = sc->sc_if.if_unit;
                    494:        break;
                    495: 
                    496:     case PPPIOCGFLAGS:
                    497:        *(u_int *)data = sc->sc_flags;
                    498:        break;
                    499: 
                    500:     case PPPIOCSFLAGS:
                    501:        if (error = suser(p->p_ucred, &p->p_acflag))
                    502:            return (error);
                    503:        flags = *(int *)data & SC_MASK;
                    504:        s = splimp();
                    505:        sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
                    506:        splx(s);
                    507:        break;
                    508: 
                    509:     case PPPIOCSASYNCMAP:
                    510:        if (error = suser(p->p_ucred, &p->p_acflag))
                    511:            return (error);
                    512:        sc->sc_asyncmap[0] = *(u_int32_t *)data;
                    513:        break;
                    514: 
                    515:     case PPPIOCGASYNCMAP:
                    516:        *(u_int32_t *)data = sc->sc_asyncmap[0];
                    517:        break;
                    518: 
                    519:     case PPPIOCSRASYNCMAP:
                    520:        if (error = suser(p->p_ucred, &p->p_acflag))
                    521:            return (error);
                    522:        sc->sc_rasyncmap = *(u_int32_t *)data;
                    523:        break;
                    524: 
                    525:     case PPPIOCGRASYNCMAP:
                    526:        *(u_int32_t *)data = sc->sc_rasyncmap;
                    527:        break;
                    528: 
                    529:     case PPPIOCSXASYNCMAP:
                    530:        if (error = suser(p->p_ucred, &p->p_acflag))
                    531:            return (error);
                    532:        bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
                    533:        sc->sc_asyncmap[1] = 0;             /* mustn't escape 0x20 - 0x3f */
                    534:        sc->sc_asyncmap[2] &= ~0x40000000;  /* mustn't escape 0x5e */
                    535:        sc->sc_asyncmap[3] |= 0x60000000;   /* must escape 0x7d, 0x7e */
                    536:        break;
                    537: 
                    538:     case PPPIOCGXASYNCMAP:
                    539:        bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
                    540:        break;
                    541: 
                    542:     case PPPIOCSMRU:
                    543:        if (error = suser(p->p_ucred, &p->p_acflag))
                    544:            return (error);
                    545:        mru = *(int *)data;
                    546:        if (mru >= PPP_MRU && mru <= PPP_MAXMRU) {
                    547:            sc->sc_mru = mru;
                    548:            pppgetm(sc);
                    549:        }
                    550:        break;
                    551: 
                    552:     case PPPIOCGMRU:
                    553:        *(int *)data = sc->sc_mru;
                    554:        break;
                    555: 
                    556: #ifdef VJC
                    557:     case PPPIOCSMAXCID:
                    558:        if (error = suser(p->p_ucred, &p->p_acflag))
                    559:            return (error);
                    560:        sl_compress_init(&sc->sc_comp, *(int *)data);
                    561:        break;
                    562: #endif
                    563: 
                    564:     case PPPIOCXFERUNIT:
                    565:        if (error = suser(p->p_ucred, &p->p_acflag))
                    566:            return (error);
                    567:        sc->sc_xfer = p->p_pid;
                    568:        break;
                    569: 
                    570:     default:
                    571:        return (-1);
                    572:     }
                    573:     return (0);
                    574: }
                    575: 
                    576: /*
                    577:  * FCS lookup table as calculated by genfcstab.
                    578:  */
                    579: static u_int16_t fcstab[256] = {
                    580:        0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
                    581:        0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
                    582:        0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
                    583:        0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
                    584:        0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
                    585:        0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
                    586:        0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
                    587:        0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
                    588:        0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
                    589:        0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
                    590:        0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
                    591:        0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
                    592:        0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
                    593:        0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
                    594:        0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
                    595:        0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
                    596:        0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
                    597:        0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
                    598:        0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
                    599:        0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
                    600:        0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
                    601:        0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
                    602:        0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
                    603:        0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
                    604:        0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
                    605:        0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
                    606:        0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
                    607:        0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
                    608:        0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
                    609:        0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
                    610:        0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
                    611:        0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
                    612: };
                    613: 
                    614: /*
                    615:  * Calculate a new FCS given the current FCS and the new data.
                    616:  */
                    617: static u_int16_t
                    618: pppfcs(fcs, cp, len)
                    619:     register u_int fcs;
                    620:     register u_char *cp;
                    621:     register int len;
                    622: {
                    623:     while (len--)
                    624:        fcs = PPP_FCS(fcs, *cp++);
                    625:     return (fcs);
                    626: }
                    627: 
                    628: /*
                    629:  * Queue a packet.  Start transmission if not active.
                    630:  * Packet is placed in Information field of PPP frame.
                    631:  */
                    632: int
                    633: pppoutput(ifp, m0, dst, rtp)
                    634:     struct ifnet *ifp;
                    635:     struct mbuf *m0;
                    636:     struct sockaddr *dst;
                    637:     struct rtentry *rtp;
                    638: {
                    639:     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
                    640:     struct ppp_header *ph;
                    641:     int protocol, address, control;
                    642:     u_char *cp;
                    643:     int s, error;
                    644:     struct ip *ip;
                    645:     struct ifqueue *ifq;
                    646: 
                    647:     if (sc->sc_devp == NULL || (ifp->if_flags & IFF_RUNNING) == 0
                    648:        || (ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC) {
                    649:        error = ENETDOWN;       /* sort of */
                    650:        goto bad;
                    651:     }
                    652: 
                    653:     /*
                    654:      * Compute PPP header.
                    655:      */
                    656:     address = PPP_ALLSTATIONS;
                    657:     control = PPP_UI;
                    658:     ifq = &ifp->if_snd;
                    659:     switch (dst->sa_family) {
                    660: #if INET
                    661:     case AF_INET:
                    662:        protocol = PPP_IP;
                    663:        if ((sc->sc_flags & SC_ENABLE_IP) == 0) {
                    664:            error = ENETDOWN;
                    665:            goto bad;
                    666:        }
                    667:        
                    668:        /*
                    669:         * If this is a TCP packet to or from an "interactive" port,
                    670:         * put the packet on the fastq instead.
                    671:         */
                    672:        if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
                    673:            register int32_t p = ntohl(((int32_t *)ip)[ip->ip_hl]);
                    674:            if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
                    675:                ifq = &sc->sc_fastq;
                    676:        }
                    677:        break;
                    678: #endif
                    679: #if NS
                    680:     case AF_NS:
                    681:        protocol = PPP_XNS;
                    682:        break;
                    683: #endif
                    684:     case AF_UNSPEC:
                    685:        ph = (struct ppp_header *) dst->sa_data;
                    686:        address = ph->ph_address;
                    687:        control = ph->ph_control;
                    688:        protocol = ntohs(ph->ph_protocol);
                    689:        break;
                    690:     default:
                    691:        printf("ppp%d: af%d not supported\n", ifp->if_unit, dst->sa_family);
                    692:        error = EAFNOSUPPORT;
                    693:        goto bad;
                    694:     }
                    695: 
                    696:     /*
                    697:      * Add PPP header.  If no space in first mbuf, allocate another.
                    698:      * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
                    699:      */
                    700:     if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
                    701:        m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
                    702:        if (m0 == 0) {
                    703:            error = ENOBUFS;
                    704:            goto bad;
                    705:        }
                    706:        m0->m_len = 0;
                    707:     } else
                    708:        m0->m_data -= PPP_HDRLEN;
                    709: 
                    710:     cp = mtod(m0, u_char *);
                    711:     *cp++ = address;
                    712:     *cp++ = control;
                    713:     *cp++ = protocol >> 8;
                    714:     *cp++ = protocol & 0xff;
                    715:     m0->m_len += PPP_HDRLEN;
                    716: 
                    717:     if (sc->sc_flags & SC_LOG_OUTPKT) {
                    718:        printf("ppp%d output: ", ifp->if_unit);
                    719:        pppdumpm(m0, -1);
                    720:     }
                    721: 
                    722: #if NBPFILTER > 0
                    723:     /* See if bpf wants to look at the packet. */
                    724:     if (sc->sc_bpf)
                    725:        BPF_MTAP(sc->sc_bpf, m0);
                    726: #endif
                    727: 
                    728:     /*
                    729:      * Put the packet on the appropriate queue.
                    730:      */
                    731:     s = splimp();
                    732:     if (IF_QFULL(ifq)) {
                    733:        IF_DROP(ifq);
                    734:        splx(s);
                    735:        sc->sc_if.if_oerrors++;
                    736:        error = ENOBUFS;
                    737:        goto bad;
                    738:     }
                    739:     IF_ENQUEUE(ifq, m0);
                    740: 
                    741:     /*
                    742:      * Tell the device to send it out.
                    743:      */
                    744:     (*sc->sc_start)(sc);
                    745: 
                    746:     splx(s);
                    747:     return (0);
                    748: 
                    749: bad:
                    750:     m_freem(m0);
                    751:     return (error);
                    752: }
                    753: 
                    754: /*
                    755:  * Grab another packet off a queue and apply VJ compression,
                    756:  * address/control and/or protocol compression if appropriate.
                    757:  */
                    758: struct mbuf *
                    759: ppp_dequeue(sc)
                    760:     struct ppp_softc *sc;
                    761: {
                    762:     int s;
                    763:     struct mbuf *m, *mp;
                    764:     u_char *cp;
                    765:     int address, control, protocol;
                    766: 
                    767:     s = splimp();
                    768:     IF_DEQUEUE(&sc->sc_fastq, m);
                    769:     if (m == NULL)
                    770:        IF_DEQUEUE(&sc->sc_if.if_snd, m);
                    771:     splx(s);
                    772:     if (m == NULL)
                    773:        return NULL;
                    774: 
                    775:     /*
                    776:      * Extract the ppp header of the new packet.
                    777:      * The ppp header will be in one mbuf.
                    778:      */
                    779:     cp = mtod(m, u_char *);
                    780:     address = cp[0];
                    781:     control = cp[1];
                    782:     protocol = (cp[2] << 8) + cp[3];
                    783: 
                    784:     switch (protocol) {
                    785: #ifdef VJC
                    786:     case PPP_IP:
                    787:        /*
                    788:         * If the packet is a TCP/IP packet, see if we can compress it.
                    789:         */
                    790:        if (sc->sc_flags & SC_COMP_TCP) {
                    791:            struct ip *ip;
                    792:            int type;
                    793: 
                    794:            mp = m;
                    795:            ip = (struct ip *) (cp + PPP_HDRLEN);
                    796:            if (mp->m_len <= PPP_HDRLEN) {
                    797:                mp = mp->m_next;
                    798:                if (mp == NULL)
                    799:                    break;
                    800:                ip = mtod(mp, struct ip *);
                    801:            }
                    802:            /* this code assumes the IP/TCP header is in one non-shared mbuf */
                    803:            if (ip->ip_p == IPPROTO_TCP) {
                    804:                type = sl_compress_tcp(mp, ip, &sc->sc_comp,
                    805:                                       !(sc->sc_flags & SC_NO_TCP_CCID));
                    806:                switch (type) {
                    807:                case TYPE_UNCOMPRESSED_TCP:
                    808:                    protocol = PPP_VJC_UNCOMP;
                    809:                    break;
                    810:                case TYPE_COMPRESSED_TCP:
                    811:                    protocol = PPP_VJC_COMP;
                    812:                    cp = mtod(m, u_char *);
                    813:                    cp[0] = address;    /* header has moved */
                    814:                    cp[1] = control;
                    815:                    cp[2] = 0;
                    816:                    break;
                    817:                }
                    818:                cp[3] = protocol;       /* update protocol in PPP header */
                    819:            }
                    820:        }
                    821: #endif /* VJC */
                    822:     }
                    823: 
                    824:     /*
                    825:      * Compress the address/control and protocol, if possible.
                    826:      */
                    827:     if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
                    828:        control == PPP_UI && protocol != PPP_ALLSTATIONS &&
                    829:        protocol != PPP_LCP) {
                    830:        /* can compress address/control */
                    831:        m->m_data += 2;
                    832:        m->m_len -= 2;
                    833:     }
                    834:     if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
                    835:        /* can compress protocol */
                    836:        if (mtod(m, u_char *) == cp) {
                    837:            cp[2] = cp[1];      /* move address/control up */
                    838:            cp[1] = cp[0];
                    839:        }
                    840:        ++m->m_data;
                    841:        --m->m_len;
                    842:     }
                    843: 
                    844:     return m;
                    845: }
                    846: 
                    847: /*
                    848:  * This gets called from pppoutput when a new packet is
                    849:  * put on a queue.
                    850:  */
                    851: static
                    852: pppasyncstart(sc)
                    853:     register struct ppp_softc *sc;
                    854: {
                    855:     register struct tty *tp = (struct tty *) sc->sc_devp;
                    856: 
                    857:     pppstart(tp);
                    858: }
                    859: 
                    860: /*
                    861:  * Start output on async tty interface.  Get another datagram
                    862:  * to send from the interface queue and start sending it.
                    863:  */
                    864: void
                    865: pppstart(tp)
                    866:     register struct tty *tp;
                    867: {
                    868:     register struct ppp_softc *sc = (struct ppp_softc *) tp->t_sc;
                    869:     register struct mbuf *m;
                    870:     register int len;
                    871:     register u_char *start, *stop, *cp;
                    872:     int n, s, ndone, done;
                    873:     struct mbuf *m2;
                    874: 
                    875:     if ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
                    876:        /* sorry, I can't talk now */
                    877:        return;
                    878:     }
                    879:     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
                    880:        (*tp->t_oproc)(tp);
                    881:        return;
                    882:     }
                    883: 
                    884:     for (;;) {
                    885:        /*
                    886:         * If there is more in the output queue, just send it now.
                    887:         * We are being called in lieu of ttstart and must do what
                    888:         * it would.
                    889:         */
                    890:        if (CCOUNT(&tp->t_outq) != 0 && tp->t_oproc != NULL) {
                    891:            (*tp->t_oproc)(tp);
                    892:            if (CCOUNT(&tp->t_outq) > PPP_HIWAT)
                    893:                return;
                    894:        }
                    895: 
                    896:        /*
                    897:         * See if we have an existing packet partly sent.
                    898:         * If not, get a new packet and start sending it.
                    899:         * We take packets on the priority queue ahead of those
                    900:         * on the normal queue.
                    901:         */
                    902:        m = sc->sc_outm;
                    903:        if (m == NULL) {
                    904:            /*
                    905:             * Get another packet to be sent
                    906:             */
                    907:            m = ppp_dequeue(sc);
                    908:            if (m == NULL)
                    909:                return;
                    910: 
                    911:            /*
                    912:             * The extra PPP_FLAG will start up a new packet, and thus
                    913:             * will flush any accumulated garbage.  We do this whenever
                    914:             * the line may have been idle for some time.
                    915:             */
                    916:            if (CCOUNT(&tp->t_outq) == 0) {
                    917:                ++sc->sc_bytessent;
                    918:                (void) putc(PPP_FLAG, &tp->t_outq);
                    919:            }
                    920: 
                    921:            /* Calculate the FCS for the first mbuf's worth. */
                    922:            sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
                    923:        }
                    924: 
                    925:        for (;;) {
                    926:            start = mtod(m, u_char *);
                    927:            len = m->m_len;
                    928:            stop = start + len;
                    929:            while (len > 0) {
                    930:                /*
                    931:                 * Find out how many bytes in the string we can
                    932:                 * handle without doing something special.
                    933:                 */
                    934:                for (cp = start; cp < stop; cp++)
                    935:                    if (ESCAPE_P(*cp))
                    936:                        break;
                    937:                n = cp - start;
                    938:                if (n) {
                    939:                    ndone = n - b_to_q(start, n, &tp->t_outq);
                    940:                    len -= ndone;
                    941:                    start += ndone;
                    942:                    sc->sc_bytessent += ndone;
                    943: 
                    944:                    if (ndone < n)
                    945:                        break;  /* packet doesn't fit */
                    946:                }
                    947:                /*
                    948:                 * If there are characters left in the mbuf,
                    949:                 * the first one must be special..
                    950:                 * Put it out in a different form.
                    951:                 */
                    952:                if (len) {
                    953:                    if (putc(PPP_ESCAPE, &tp->t_outq))
                    954:                        break;
                    955:                    if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
                    956:                        (void) unputc(&tp->t_outq);
                    957:                        break;
                    958:                    }
                    959:                    sc->sc_bytessent += 2;
                    960:                    start++;
                    961:                    len--;
                    962:                }
                    963:            }
                    964:            /*
                    965:             * If we didn't empty this mbuf, remember where we're up to.
                    966:             * If we emptied the last mbuf, try to add the FCS and closing
                    967:             * flag, and if we can't, leave sc_outm pointing to m, but with
                    968:             * m->m_len == 0, to remind us to output the FCS and flag later.
                    969:             */
                    970:            done = len == 0;
                    971:            if (done && m->m_next == NULL) {
                    972:                u_char *p, *q;
                    973:                int c;
                    974:                u_char endseq[8];
                    975: 
                    976:                /*
                    977:                 * We may have to escape the bytes in the FCS.
                    978:                 */
                    979:                p = endseq;
                    980:                c = ~sc->sc_outfcs & 0xFF;
                    981:                if (ESCAPE_P(c)) {
                    982:                    *p++ = PPP_ESCAPE;
                    983:                    *p++ = c ^ PPP_TRANS;
                    984:                } else
                    985:                    *p++ = c;
                    986:                c = (~sc->sc_outfcs >> 8) & 0xFF;
                    987:                if (ESCAPE_P(c)) {
                    988:                    *p++ = PPP_ESCAPE;
                    989:                    *p++ = c ^ PPP_TRANS;
                    990:                } else
                    991:                    *p++ = c;
                    992:                *p++ = PPP_FLAG;
                    993: 
                    994:                /*
                    995:                 * Try to output the FCS and flag.  If the bytes
                    996:                 * don't all fit, back out.
                    997:                 */
                    998:                for (q = endseq; q < p; ++q)
                    999:                    if (putc(*q, &tp->t_outq)) {
                   1000:                        done = 0;
                   1001:                        for (; q > endseq; --q)
                   1002:                            unputc(&tp->t_outq);
                   1003:                        break;
                   1004:                    }
                   1005:            }
                   1006: 
                   1007:            if (!done) {
                   1008:                m->m_data = start;
                   1009:                m->m_len = len;
                   1010:                sc->sc_outm = m;
                   1011:                if (tp->t_oproc != NULL)
                   1012:                    (*tp->t_oproc)(tp);
                   1013:                return;         /* can't do any more at the moment */
                   1014:            }
                   1015: 
                   1016:            /* Finished with this mbuf; free it and move on. */
                   1017:            MFREE(m, m2);
                   1018:            if (m2 == NULL)
                   1019:                break;
                   1020: 
                   1021:            m = m2;
                   1022:            sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
                   1023:        }
                   1024: 
                   1025:        /* Finished a packet */
                   1026:        sc->sc_outm = NULL;
                   1027:        sc->sc_bytessent++;     /* account for closing flag */
                   1028:        sc->sc_if.if_opackets++;
                   1029:        sc->sc_if.if_obytes = sc->sc_bytessent;
                   1030:     }
                   1031: }
                   1032: 
                   1033: /*
                   1034:  * Allocate enough mbuf to handle current MRU.
                   1035:  */
                   1036: static int
                   1037: pppgetm(sc)
                   1038:     register struct ppp_softc *sc;
                   1039: {
                   1040:     struct mbuf *m, **mp;
                   1041:     int len;
                   1042:     int s;
                   1043: 
                   1044:     s = splimp();
                   1045:     mp = &sc->sc_m;
                   1046:     for (len = HDROFF + sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
                   1047:        if ((m = *mp) == NULL) {
                   1048:            MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1049:            if (m == NULL)
                   1050:                break;
                   1051:            *mp = m;
                   1052:            MCLGET(m, M_DONTWAIT);
                   1053:        }
                   1054:        len -= M_DATASIZE(m);
                   1055:        mp = &m->m_next;
                   1056:     }
                   1057:     splx(s);
                   1058:     return len <= 0;
                   1059: }
                   1060: 
                   1061: /*
                   1062:  * PPP packet input routine.
                   1063:  * The caller has checked and removed the FCS and has inserted
                   1064:  * the address/control bytes and the protocol high byte if they
                   1065:  * were omitted.  The data in the first mbuf should start HDROFF
                   1066:  * bytes from the beginning of the mbuf data storage area.
                   1067:  * The return value is 1 if the packet was put on sc->sc_inq,
                   1068:  * 0 otherwise.
                   1069:  */
                   1070: #define COMPTYPE(proto)        ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
                   1071:                         TYPE_UNCOMPRESSED_TCP)
                   1072: 
                   1073: int
                   1074: ppppktin(sc, m)
                   1075:     struct ppp_softc *sc;
                   1076:     struct mbuf *m;
                   1077: {
                   1078:     struct ifqueue *inq;
                   1079:     int s, ilen, xlen, proto, rv;
                   1080:     u_char *cp, adrs, ctrl;
                   1081:     struct mbuf *mp;
                   1082: 
                   1083:     sc->sc_if.if_ipackets++;
                   1084:     rv = 0;
                   1085: 
                   1086:     cp = mtod(m, u_char *);
                   1087:     adrs = cp[0];
                   1088:     ctrl = cp[1];
                   1089:     proto = (cp[2] << 8) + cp[3];
                   1090: 
                   1091:     ilen = 0;
                   1092:     for (mp = m; mp != NULL; mp = mp->m_next)
                   1093:        ilen += mp->m_len;
                   1094: 
                   1095: #ifdef VJC
                   1096:     /*
                   1097:      * See if we have a VJ-compressed packet to uncompress.
                   1098:      */
                   1099:     if (proto == PPP_VJC_COMP || proto == PPP_VJC_UNCOMP) {
                   1100:        char *pkttype = proto == PPP_VJC_COMP? "": "un";
                   1101: 
                   1102:        if (sc->sc_flags & SC_REJ_COMP_TCP) {
                   1103:            if (sc->sc_flags & SC_DEBUG)
                   1104:                printf("ppp%d: %scomp pkt w/o compression; flags 0x%x\n",
                   1105:                        sc->sc_if.if_unit, pkttype, sc->sc_flags);
                   1106:            m_freem(m);
                   1107:            sc->sc_if.if_ierrors++;
                   1108:            return 0;
                   1109:        }
                   1110: 
                   1111:        if (proto == PPP_VJC_COMP && m->m_data - M_DATASTART(m) < MAX_HDR) {
                   1112:            /*
                   1113:             * We don't have room in the mbuf to decompress this packet.
                   1114:             * XXX For now we just drop the packet.
                   1115:             */
                   1116:            if (sc->sc_flags & SC_DEBUG)
                   1117:                printf("ppp%d: no room to VJ-decompress packet\n",
                   1118:                       sc->sc_if.if_unit);
                   1119:            m_freem(m);
                   1120:            sc->sc_if.if_ierrors++;
                   1121:            return 0;
                   1122:        }
                   1123: 
                   1124:        m->m_data += PPP_HDRLEN;
                   1125:        m->m_len -= PPP_HDRLEN;
                   1126:        ilen -= PPP_HDRLEN;
                   1127:        xlen = sl_uncompress_tcp_part((u_char **)(&m->m_data),
                   1128:                                        m->m_len, ilen,
                   1129:                                        COMPTYPE(proto), &sc->sc_comp);
                   1130: 
                   1131:        if (xlen == 0) {
                   1132:            if (sc->sc_flags & SC_DEBUG)
                   1133:                printf("ppp%d: sl_uncompress failed on type %scomp\n",
                   1134:                        sc->sc_if.if_unit, pkttype);
                   1135:            m_freem(m);
                   1136:            sc->sc_if.if_ierrors++;
                   1137:            return 0;
                   1138:        }
                   1139: 
                   1140:        /* adjust the first mbuf by the decompressed amt */
                   1141:        xlen += PPP_HDRLEN;
                   1142:        m->m_len += xlen - ilen;
                   1143:        ilen = xlen;
                   1144:        m->m_data -= PPP_HDRLEN;
                   1145:        proto = PPP_IP;
                   1146: 
                   1147:        /* put the ppp header back in place */
                   1148:        if (cp != mtod(m, u_char *)) {
                   1149:            cp = mtod(m, u_char *);
                   1150:            cp[0] = adrs;
                   1151:            cp[1] = ctrl;
                   1152:            cp[2] = 0;
                   1153:        }
                   1154:        cp[3] = PPP_IP;
                   1155:     }
                   1156: #endif /* VJC */
                   1157: 
                   1158:     /*
                   1159:      * If the packet will fit in a header mbuf, don't waste a
                   1160:      * whole cluster on it.
                   1161:      */
                   1162:     if (ilen <= MHLEN) {
                   1163:        MGETHDR(mp, M_DONTWAIT, MT_DATA);
                   1164:        if (mp != NULL) {
                   1165:            m_copydata(m, 0, ilen, mtod(mp, caddr_t));
                   1166:            m_freem(m);
                   1167:            m = mp;
                   1168:            m->m_len = ilen;
                   1169:        }
                   1170:     }
                   1171:     m->m_pkthdr.len = ilen;
                   1172:     m->m_pkthdr.rcvif = &sc->sc_if;
                   1173: 
                   1174: #if NBPFILTER > 0
                   1175:     /* See if bpf wants to look at the packet. */
                   1176:     if (sc->sc_bpf)
                   1177:        BPF_MTAP(sc->sc_bpf, m);
                   1178: #endif
                   1179: 
                   1180:     switch (proto) {
                   1181: #if INET
                   1182:     case PPP_IP:
                   1183:        /*
                   1184:         * IP packet - take off the ppp header and pass it up to IP.
                   1185:         */
                   1186:        if ((sc->sc_if.if_flags & IFF_UP) == 0
                   1187:            || (sc->sc_flags & SC_ENABLE_IP) == 0) {
                   1188:            /* interface is down - drop the packet. */
                   1189:            m_freem(m);
                   1190:            return 0;
                   1191:        }
                   1192:        m->m_pkthdr.len -= PPP_HDRLEN;
                   1193:        m->m_data += PPP_HDRLEN;
                   1194:        m->m_len -= PPP_HDRLEN;
                   1195:        schednetisr(NETISR_IP);
                   1196:        inq = &ipintrq;
                   1197:        break;
                   1198: #endif
                   1199: 
                   1200:     default:
                   1201:        /*
                   1202:         * Some other protocol - place on input queue for read().
                   1203:         */
                   1204:        inq = &sc->sc_inq;
                   1205:        rv = 1;
                   1206:        break;
                   1207:     }
                   1208: 
                   1209:     /*
                   1210:      * Put the packet on the appropriate input queue.
                   1211:      */
                   1212:     s = splimp();
                   1213:     if (IF_QFULL(inq)) {
                   1214:        IF_DROP(inq);
                   1215:        if (sc->sc_flags & SC_DEBUG)
                   1216:            printf("ppp%d: queue full\n", sc->sc_if.if_unit);
                   1217:        sc->sc_if.if_ierrors++;
                   1218:        sc->sc_if.if_iqdrops++;
                   1219:        m_freem(m);
                   1220:        rv = 0;
                   1221:     } else
                   1222:        IF_ENQUEUE(inq, m);
                   1223: 
                   1224:     splx(s);
                   1225:     return rv;
                   1226: }
                   1227: 
                   1228: /*
                   1229:  * tty interface receiver interrupt.
                   1230:  */
                   1231: static unsigned paritytab[8] = {
                   1232:     0x96696996, 0x69969669, 0x69969669, 0x96696996,
                   1233:     0x69969669, 0x96696996, 0x96696996, 0x69969669
                   1234: };
                   1235: 
                   1236: void
                   1237: pppinput(c, tp)
                   1238:     int c;
                   1239:     register struct tty *tp;
                   1240: {
                   1241:     register struct ppp_softc *sc;
                   1242:     struct mbuf *m;
                   1243:     int ilen;
                   1244: 
                   1245:     tk_nin++;
                   1246:     sc = (struct ppp_softc *) tp->t_sc;
                   1247:     if (sc == NULL || tp != (struct tty *) sc->sc_devp)
                   1248:        return;
                   1249: 
                   1250:     ++sc->sc_bytesrcvd;
                   1251: 
                   1252:     if (c & TTY_FE) {
                   1253:        /* framing error or overrun on this char - abort packet */
                   1254:        if (sc->sc_flags & SC_DEBUG)
                   1255:            printf("ppp%d: bad char %x\n", sc->sc_if.if_unit, c);
                   1256:        goto flush;
                   1257:     }
                   1258: 
                   1259:     c &= 0xff;
                   1260: 
                   1261:     if (c & 0x80)
                   1262:        sc->sc_flags |= SC_RCV_B7_1;
                   1263:     else
                   1264:        sc->sc_flags |= SC_RCV_B7_0;
                   1265:     if (paritytab[c >> 5] & (1 << (c & 0x1F)))
                   1266:        sc->sc_flags |= SC_RCV_ODDP;
                   1267:     else
                   1268:        sc->sc_flags |= SC_RCV_EVNP;
                   1269: 
                   1270:     if (sc->sc_flags & SC_LOG_RAWIN)
                   1271:        ppplogchar(sc, c);
                   1272: 
                   1273:     if (c == PPP_FLAG) {
                   1274:        ilen = sc->sc_ilen;
                   1275:        sc->sc_ilen = 0;
                   1276:        sc->sc_if.if_ibytes = sc->sc_bytesrcvd;
                   1277: 
                   1278:        if (sc->sc_rawin_count > 0) 
                   1279:            ppplogchar(sc, -1);
                   1280: 
                   1281:        /*
                   1282:         * If SC_ESCAPED is set, then we've seen the packet
                   1283:         * abort sequence "}~".
                   1284:         */
                   1285:        if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
                   1286:            || ilen > 0 && sc->sc_fcs != PPP_GOODFCS) {
                   1287: #ifdef VJC
                   1288:            /*
                   1289:             * If we've missed a packet, we must toss subsequent compressed
                   1290:             * packets which don't have an explicit connection ID.
                   1291:             */
                   1292:            sl_uncompress_tcp(NULL, 0, TYPE_ERROR, &sc->sc_comp);
                   1293: #endif
                   1294:            if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
                   1295:                if (sc->sc_flags & SC_DEBUG)
                   1296:                    printf("ppp%d: bad fcs %x\n", sc->sc_if.if_unit,
                   1297:                           sc->sc_fcs);
                   1298:                sc->sc_if.if_ierrors++;
                   1299:            } else
                   1300:                sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
                   1301:            return;
                   1302:        }
                   1303: 
                   1304:        if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
                   1305:            if (ilen) {
                   1306:                if (sc->sc_flags & SC_DEBUG)
                   1307:                    printf("ppp%d: too short (%d)\n", sc->sc_if.if_unit, ilen);
                   1308:                sc->sc_if.if_ierrors++;
                   1309:            }
                   1310:            return;
                   1311:        }
                   1312: 
                   1313:        /*
                   1314:         * Remove FCS trailer.  Somewhat painful...
                   1315:         */
                   1316:        ilen -= 2;
                   1317:        if (--sc->sc_mc->m_len == 0) {
                   1318:            for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
                   1319:                ;
                   1320:            sc->sc_mc = m;
                   1321:        }
                   1322:        sc->sc_mc->m_len--;
                   1323: 
                   1324:        /* excise this mbuf chain */
                   1325:        m = sc->sc_m;
                   1326:        sc->sc_m = sc->sc_mc->m_next;
                   1327:        sc->sc_mc->m_next = NULL;
                   1328: 
                   1329:        if (sc->sc_flags & SC_LOG_INPKT) {
                   1330:            printf("ppp%d: got %d bytes\n", sc->sc_if.if_unit, ilen);
                   1331:            pppdumpm(m, ilen);
                   1332:        }
                   1333: 
                   1334:        if (ppppktin(sc, m)) {
                   1335:            /* Put a placeholder byte in canq for ttselect()/ttnread(). */
                   1336:            putc(0, &tp->t_canq);
                   1337:            ttwakeup(tp);
                   1338:        }
                   1339: 
                   1340:        pppgetm(sc);
                   1341:        return;
                   1342:     }
                   1343: 
                   1344:     if (sc->sc_flags & SC_FLUSH) {
                   1345:        if (sc->sc_flags & SC_LOG_FLUSH)
                   1346:            ppplogchar(sc, c);
                   1347:        return;
                   1348:     }
                   1349: 
                   1350:     if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
                   1351:        return;
                   1352: 
                   1353:     if (sc->sc_flags & SC_ESCAPED) {
                   1354:        sc->sc_flags &= ~SC_ESCAPED;
                   1355:        c ^= PPP_TRANS;
                   1356:     } else if (c == PPP_ESCAPE) {
                   1357:        sc->sc_flags |= SC_ESCAPED;
                   1358:        return;
                   1359:     }
                   1360: 
                   1361:     /*
                   1362:      * Initialize buffer on first octet received.
                   1363:      * First octet could be address or protocol (when compressing
                   1364:      * address/control).
                   1365:      * Second octet is control.
                   1366:      * Third octet is first or second (when compressing protocol)
                   1367:      * octet of protocol.
                   1368:      * Fourth octet is second octet of protocol.
                   1369:      */
                   1370:     if (sc->sc_ilen == 0) {
                   1371:        /* reset the first input mbuf */
                   1372:        if (sc->sc_m == NULL) {
                   1373:            pppgetm(sc);
                   1374:            if (sc->sc_m == NULL) {
                   1375:                if (sc->sc_flags & SC_DEBUG)
                   1376:                    printf("ppp%d: no input mbufs!\n", sc->sc_if.if_unit);
                   1377:                goto flush;
                   1378:            }
                   1379:        }
                   1380:        m = sc->sc_m;
                   1381:        m->m_len = 0;
                   1382:        m->m_data = M_DATASTART(sc->sc_m);
                   1383:        if (M_DATASIZE(sc->sc_m) >= HDROFF + PPP_HDRLEN)
                   1384:            m->m_data += HDROFF;        /* allow room for VJ decompression */
                   1385:        sc->sc_mc = m;
                   1386:        sc->sc_mp = mtod(m, char *);
                   1387:        sc->sc_fcs = PPP_INITFCS;
                   1388:        if (c != PPP_ALLSTATIONS) {
                   1389:            if (sc->sc_flags & SC_REJ_COMP_AC) {
                   1390:                if (sc->sc_flags & SC_DEBUG)
                   1391:                    printf("ppp%d: garbage received: 0x%x (need 0xFF)\n",
                   1392:                           sc->sc_if.if_unit, c);
                   1393:                goto flush;
                   1394:            }
                   1395:            *sc->sc_mp++ = PPP_ALLSTATIONS;
                   1396:            *sc->sc_mp++ = PPP_UI;
                   1397:            sc->sc_ilen += 2;
                   1398:            m->m_len += 2;
                   1399:        }
                   1400:     }
                   1401:     if (sc->sc_ilen == 1 && c != PPP_UI) {
                   1402:        if (sc->sc_flags & SC_DEBUG)
                   1403:            printf("ppp%d: missing UI (0x3), got 0x%x\n",
                   1404:                   sc->sc_if.if_unit, c);
                   1405:        goto flush;
                   1406:     }
                   1407:     if (sc->sc_ilen == 2 && (c & 1) == 1) {
                   1408:        /* a compressed protocol */
                   1409:        *sc->sc_mp++ = 0;
                   1410:        sc->sc_ilen++;
                   1411:        sc->sc_mc->m_len++;
                   1412:     }
                   1413:     if (sc->sc_ilen == 3 && (c & 1) == 0) {
                   1414:        if (sc->sc_flags & SC_DEBUG)
                   1415:            printf("ppp%d: bad protocol %x\n", sc->sc_if.if_unit,
                   1416:                   (sc->sc_mp[-1] << 8) + c);
                   1417:        goto flush;
                   1418:     }
                   1419: 
                   1420:     /* packet beyond configured mru? */
                   1421:     if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
                   1422:        if (sc->sc_flags & SC_DEBUG)
                   1423:            printf("ppp%d: packet too big\n", sc->sc_if.if_unit);
                   1424:        goto flush;
                   1425:     }
                   1426: 
                   1427:     /* is this mbuf full? */
                   1428:     m = sc->sc_mc;
                   1429:     if (M_TRAILINGSPACE(m) <= 0) {
                   1430:        if (m->m_next == NULL) {
                   1431:            pppgetm(sc);
                   1432:            if (m->m_next == NULL) {
                   1433:                if (sc->sc_flags & SC_DEBUG)
                   1434:                    printf("ppp%d: too few input mbufs!\n", sc->sc_if.if_unit);
                   1435:                goto flush;
                   1436:            }
                   1437:        }
                   1438:        sc->sc_mc = m = m->m_next;
                   1439:        m->m_len = 0;
                   1440:        m->m_data = M_DATASTART(m);
                   1441:        sc->sc_mp = mtod(m, char *);
                   1442:     }
                   1443: 
                   1444:     ++m->m_len;
                   1445:     *sc->sc_mp++ = c;
                   1446:     sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
                   1447:     return;
                   1448: 
                   1449:  flush:
                   1450:     if (!(sc->sc_flags & SC_FLUSH)) {
                   1451:        sc->sc_if.if_ierrors++;
                   1452:        sc->sc_flags |= SC_FLUSH;
                   1453:        if (sc->sc_flags & SC_LOG_FLUSH)
                   1454:            ppplogchar(sc, c);
                   1455:     }
                   1456: }
                   1457: 
                   1458: /*
                   1459:  * Process an ioctl request to interface.
                   1460:  */
                   1461: pppioctl(ifp, cmd, data)
                   1462:     register struct ifnet *ifp;
                   1463:     u_long cmd;
                   1464:     caddr_t data;
                   1465: {
                   1466:     struct proc *p = current_proc();   /* XXX */
                   1467:     register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
                   1468:     register struct ifaddr *ifa = (struct ifaddr *)data;
                   1469:     register struct ifreq *ifr = (struct ifreq *)data;
                   1470:     int s = splimp(), error = 0;
                   1471: 
                   1472: 
                   1473:     switch (cmd) {
                   1474:     case SIOCSIFFLAGS:
                   1475:        if ((ifp->if_flags & IFF_RUNNING) == 0)
                   1476:            ifp->if_flags &= ~IFF_UP;
                   1477:        break;
                   1478: 
                   1479:     case SIOCSIFADDR:
                   1480:        if (ifa->ifa_addr->sa_family != AF_INET)
                   1481:            error = EAFNOSUPPORT;
                   1482:        break;
                   1483: 
                   1484:     case SIOCSIFDSTADDR:
                   1485:        if (ifa->ifa_addr->sa_family != AF_INET)
                   1486:            error = EAFNOSUPPORT;
                   1487:        break;
                   1488: 
                   1489:     case SIOCSIFMTU:
                   1490:        if (error = suser(p->p_ucred, &p->p_acflag))
                   1491:            break;
                   1492:        sc->sc_if.if_mtu = ifr->ifr_mtu;
                   1493:        break;
                   1494: 
                   1495:     case SIOCGIFMTU:
                   1496:        ifr->ifr_mtu = sc->sc_if.if_mtu;
                   1497:        break;
                   1498: 
                   1499:     default:
                   1500:        error = EINVAL;
                   1501:     }
                   1502:     splx(s);
                   1503:     return (error);
                   1504: }
                   1505: 
                   1506: #define MAX_DUMP_BYTES 128
                   1507: 
                   1508: static void
                   1509: pppdumpm(m0, pktlen)
                   1510:     struct mbuf *m0;
                   1511:     int pktlen;
                   1512: {
                   1513:     char buf[3*MAX_DUMP_BYTES+4];
                   1514:     char *bp = buf;
                   1515:     struct mbuf *m;
                   1516:     static char digits[] = "0123456789abcdef";
                   1517: 
                   1518:     for (m = m0; m && pktlen; m = m->m_next) {
                   1519:        int l = m->m_len;
                   1520:        u_char *rptr = (u_char *)m->m_data;
                   1521: 
                   1522:        if (pktlen > 0) {
                   1523:            if (l > pktlen)
                   1524:                l = pktlen;
                   1525:            pktlen -= l;
                   1526:        }
                   1527:        while (l--) {
                   1528:            if (bp > buf + sizeof(buf) - 4)
                   1529:                goto done;
                   1530:            *bp++ = digits[*rptr >> 4]; /* convert byte to ascii hex */
                   1531:            *bp++ = digits[*rptr++ & 0xf];
                   1532:        }
                   1533: 
                   1534:        if (m->m_next) {
                   1535:            if (bp > buf + sizeof(buf) - 3)
                   1536:                goto done;
                   1537:            *bp++ = '|';
                   1538:        } else
                   1539:            *bp++ = ' ';
                   1540:     }
                   1541: done:
                   1542:     if (m && pktlen)
                   1543:        *bp++ = '>';
                   1544:     *bp = 0;
                   1545:     printf("%s\n", buf);
                   1546: }
                   1547: 
                   1548: static void
                   1549: ppplogchar(sc, c)
                   1550:     struct ppp_softc *sc;
                   1551:     int c;
                   1552: {
                   1553:     if (c >= 0)
                   1554:        sc->sc_rawin[sc->sc_rawin_count++] = c;
                   1555:     if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
                   1556:        || c < 0 && sc->sc_rawin_count > 0) {
                   1557:        printf("ppp%d input: ", sc->sc_if.if_unit);
                   1558:        pppdumpb(sc->sc_rawin, sc->sc_rawin_count);
                   1559:        sc->sc_rawin_count = 0;
                   1560:     }
                   1561: }
                   1562: 
                   1563: static void
                   1564: pppdumpb(b, l)
                   1565:     u_char *b;
                   1566:     int l;
                   1567: {
                   1568:     char buf[3*MAX_DUMP_BYTES+4];
                   1569:     char *bp = buf;
                   1570:     static char digits[] = "0123456789abcdef";
                   1571: 
                   1572:     while (l--) {
                   1573:        if (bp >= buf + sizeof(buf) - 3) {
                   1574:            *bp++ = '>';
                   1575:            break;
                   1576:        }
                   1577:        *bp++ = digits[*b >> 4]; /* convert byte to ascii hex */
                   1578:        *bp++ = digits[*b++ & 0xf];
                   1579:        *bp++ = ' ';
                   1580:     }
                   1581: 
                   1582:     *bp = 0;
                   1583:     printf("%s\n", buf);
                   1584: }
                   1585: 
                   1586: 
                   1587: #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.