]> git.ozlabs.org Git - ppp.git/blobdiff - modules/if_ppp.c
Update README to fix an error
[ppp.git] / modules / if_ppp.c
diff --git a/modules/if_ppp.c b/modules/if_ppp.c
deleted file mode 100644 (file)
index e150923..0000000
+++ /dev/null
@@ -1,873 +0,0 @@
-/*
- * if_ppp.c - a network interface connected to a STREAMS module.
- *
- * Copyright (c) 1994 Paul Mackerras. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. The name(s) of the authors of this software must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission.
- *
- * 4. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by Paul Mackerras
- *     <paulus@samba.org>".
- *
- * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
- * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
- * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * $Id: if_ppp.c,v 1.18 2002/12/06 09:49:15 paulus Exp $
- */
-
-/*
- * This file is used under SunOS 4 and Digital UNIX.
- *
- * This file provides the glue between PPP and IP.
- */
-
-#define INET   1
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/errno.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/netisr.h>
-#include <net/ppp_defs.h>
-#include <net/pppio.h>
-#include <netinet/in.h>
-#include <netinet/in_var.h>
-#ifdef __osf__
-#include <sys/ioctl.h>
-#include <net/if_types.h>
-#else
-#include <sys/sockio.h>
-#endif
-#include "ppp_mod.h"
-
-#include <sys/stream.h>
-
-#ifdef SNIT_SUPPORT
-#include <sys/time.h>
-#include <net/nit_if.h>
-#include <netinet/if_ether.h>
-#endif
-
-#ifdef __osf__
-#define SIOCSIFMTU SIOCSIPMTU
-#define SIOCGIFMTU SIOCRIPMTU
-#define IFA_ADDR(ifa)   (*(ifa)->ifa_addr)
-#else
-#define IFA_ADDR(ifa)   ((ifa)->ifa_addr)
-#endif
-
-#define ifr_mtu                ifr_metric
-
-static int if_ppp_open(queue_t *, int, int, int);
-static int if_ppp_close(queue_t *, int);
-static int if_ppp_wput(queue_t *, mblk_t *);
-static int if_ppp_rput(queue_t *, mblk_t *);
-
-#define PPP_IF_ID 0x8021
-static struct module_info minfo = {
-    PPP_IF_ID, "if_ppp", 0, INFPSZ, 4096, 128
-};
-
-static struct qinit rinit = {
-    if_ppp_rput, NULL, if_ppp_open, if_ppp_close, NULL, &minfo, NULL
-};
-
-static struct qinit winit = {
-    if_ppp_wput, NULL, NULL, NULL, NULL, &minfo, NULL
-};
-
-struct streamtab if_pppinfo = {
-    &rinit, &winit, NULL, NULL
-};
-
-typedef struct if_ppp_state {
-    int unit;
-    queue_t *q;
-    int flags;
-} if_ppp_t;
-
-/* Values for flags */
-#define DBGLOG         1
-
-static int if_ppp_count;       /* Number of currently-active streams */
-
-static int ppp_nalloc;         /* Number of elements of ifs and states */
-static struct ifnet **ifs;     /* Array of pointers to interface structs */
-static if_ppp_t **states;      /* Array of pointers to state structs */
-
-static int if_ppp_output(struct ifnet *, struct mbuf *,
-                        struct sockaddr *);
-static int if_ppp_ioctl(struct ifnet *, u_int, caddr_t);
-static struct mbuf *make_mbufs(mblk_t *, int);
-static mblk_t *make_message(struct mbuf *, int);
-
-#ifdef SNIT_SUPPORT
-/* Fake ether header for SNIT */
-static struct ether_header snit_ehdr = {{0}, {0}, ETHERTYPE_IP};
-#endif
-
-#ifndef __osf__
-static void ppp_if_detach(struct ifnet *);
-
-/*
- * Detach all the interfaces before unloading.
- * Not sure this works.
- */
-int
-if_ppp_unload()
-{
-    int i;
-
-    if (if_ppp_count > 0)
-       return EBUSY;
-    for (i = 0; i < ppp_nalloc; ++i)
-       if (ifs[i] != 0)
-           ppp_if_detach(ifs[i]);
-    if (ifs) {
-       FREE(ifs, ppp_nalloc * sizeof (struct ifnet *));
-       FREE(states, ppp_nalloc * sizeof (struct if_ppp_t *));
-    }
-    ppp_nalloc = 0;
-    return 0;
-}
-#endif /* __osf__ */
-
-/*
- * STREAMS module entry points.
- */
-static int
-if_ppp_open(q, dev, flag, sflag)
-    queue_t *q;
-    int dev;
-    int flag, sflag;
-{
-    if_ppp_t *sp;
-
-    if (q->q_ptr == 0) {
-       sp = (if_ppp_t *) ALLOC_SLEEP(sizeof (if_ppp_t));
-       if (sp == 0)
-           return OPENFAIL;
-       bzero(sp, sizeof (if_ppp_t));
-       q->q_ptr = (caddr_t) sp;
-       WR(q)->q_ptr = (caddr_t) sp;
-       sp->unit = -1;          /* no interface unit attached at present */
-       sp->q = WR(q);
-       sp->flags = 0;
-       ++if_ppp_count;
-    }
-    return 0;
-}
-
-static int
-if_ppp_close(q, flag)
-    queue_t *q;
-    int flag;
-{
-    if_ppp_t *sp;
-    struct ifnet *ifp;
-
-    sp = (if_ppp_t *) q->q_ptr;
-    if (sp != 0) {
-       if (sp->flags & DBGLOG)
-           printf("if_ppp closed, q=%x sp=%x\n", q, sp);
-       if (sp->unit >= 0) {
-           if (sp->unit < ppp_nalloc) {
-               states[sp->unit] = 0;
-               ifp = ifs[sp->unit];
-               if (ifp != 0)
-                   ifp->if_flags &= ~(IFF_UP | IFF_RUNNING);
-#ifdef DEBUG
-           } else {
-               printf("if_ppp: unit %d nonexistent!\n", sp->unit);
-#endif
-           }
-       }
-       FREE(sp, sizeof (if_ppp_t));
-       --if_ppp_count;
-    }
-    return 0;
-}
-
-static int
-if_ppp_wput(q, mp)
-    queue_t *q;
-    mblk_t *mp;
-{
-    if_ppp_t *sp;
-    struct iocblk *iop;
-    int error, unit;
-    struct ifnet *ifp;
-
-    sp = (if_ppp_t *) q->q_ptr;
-    switch (mp->b_datap->db_type) {
-    case M_DATA:
-       /*
-        * Now why would we be getting data coming in here??
-        */
-       if (sp->flags & DBGLOG)
-           printf("if_ppp: got M_DATA len=%d\n", msgdsize(mp));
-       freemsg(mp);
-       break;
-
-    case M_IOCTL:
-       iop = (struct iocblk *) mp->b_rptr;
-       error = EINVAL;
-
-       if (sp->flags & DBGLOG)
-           printf("if_ppp: got ioctl cmd=%x count=%d\n",
-                  iop->ioc_cmd, iop->ioc_count);
-
-       switch (iop->ioc_cmd) {
-       case PPPIO_NEWPPA:              /* well almost */
-           if (iop->ioc_count != sizeof(int) || sp->unit >= 0)
-               break;
-           if ((error = NOTSUSER()) != 0)
-               break;
-           unit = *(int *)mp->b_cont->b_rptr;
-
-           /* Check that this unit isn't already in use */
-           if (unit < ppp_nalloc && states[unit] != 0) {
-               error = EADDRINUSE;
-               break;
-           }
-
-           /* Extend ifs and states arrays if necessary. */
-           error = ENOSR;
-           if (unit >= ppp_nalloc) {
-               int newn;
-               struct ifnet **newifs;
-               if_ppp_t **newstates;
-
-               newn = unit + 4;
-               if (sp->flags & DBGLOG)
-                   printf("if_ppp: extending ifs to %d\n", newn);
-               newifs = (struct ifnet **)
-                   ALLOC_NOSLEEP(newn * sizeof (struct ifnet *));
-               if (newifs == 0)
-                   break;
-               bzero(newifs, newn * sizeof (struct ifnet *));
-               newstates = (if_ppp_t **)
-                   ALLOC_NOSLEEP(newn * sizeof (struct if_ppp_t *));
-               if (newstates == 0) {
-                   FREE(newifs, newn * sizeof (struct ifnet *));
-                   break;
-               }
-               bzero(newstates, newn * sizeof (struct if_ppp_t *));
-               bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *));
-               bcopy(states, newstates, ppp_nalloc * sizeof(if_ppp_t *));
-               if (ifs) {
-                   FREE(ifs, ppp_nalloc * sizeof(struct ifnet *));
-                   FREE(states, ppp_nalloc * sizeof(if_ppp_t *));
-               }
-               ifs = newifs;
-               states = newstates;
-               ppp_nalloc = newn;
-           }
-
-           /* Allocate a new ifnet struct if necessary. */
-           ifp = ifs[unit];
-           if (ifp == 0) {
-               ifp = (struct ifnet *) ALLOC_NOSLEEP(sizeof (struct ifnet));
-               if (ifp == 0)
-                   break;
-               bzero(ifp, sizeof (struct ifnet));
-               ifs[unit] = ifp;
-               ifp->if_name = "ppp";
-               ifp->if_unit = unit;
-               ifp->if_mtu = PPP_MTU;
-               ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;
-#ifndef __osf__
-#ifdef IFF_MULTICAST
-               ifp->if_flags |= IFF_MULTICAST;
-#endif
-#endif /* __osf__ */
-               ifp->if_output = if_ppp_output;
-#ifdef __osf__
-               ifp->if_version = "Point-to-Point Protocol, version 2.3.11";
-               ifp->if_mediamtu = PPP_MTU;
-               ifp->if_type = IFT_PPP;
-               ifp->if_hdrlen = PPP_HDRLEN;
-               ifp->if_addrlen = 0;
-               ifp->if_flags |= IFF_NOARP | IFF_SIMPLEX | IFF_NOTRAILERS;
-#ifdef IFF_VAR_MTU
-               ifp->if_flags |= IFF_VAR_MTU;
-#endif
-#ifdef NETMASTERCPU
-               ifp->if_affinity = NETMASTERCPU;
-#endif
-#endif
-               ifp->if_ioctl = if_ppp_ioctl;
-               ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
-               if_attach(ifp);
-               if (sp->flags & DBGLOG)
-                   printf("if_ppp: created unit %d\n", unit);
-           } else {
-               ifp->if_mtu = PPP_MTU;
-               ifp->if_flags |= IFF_RUNNING;
-           }
-
-           states[unit] = sp;
-           sp->unit = unit;
-
-           error = 0;
-           iop->ioc_count = 0;
-           if (sp->flags & DBGLOG)
-               printf("if_ppp: attached unit %d, sp=%x q=%x\n", unit,
-                      sp, sp->q);
-           break;
-
-       case PPPIO_DEBUG:
-           error = -1;
-           if (iop->ioc_count == sizeof(int)) {
-               if (*(int *)mp->b_cont->b_rptr == PPPDBG_LOG + PPPDBG_IF) {
-                   printf("if_ppp: debug log enabled, q=%x sp=%x\n", q, sp);
-                   sp->flags |= DBGLOG;
-                   error = 0;
-                   iop->ioc_count = 0;
-               }
-           }
-           break;
-
-       default:
-           error = -1;
-           break;
-       }
-
-       if (sp->flags & DBGLOG)
-           printf("if_ppp: ioctl result %d\n", error);
-       if (error < 0)
-           putnext(q, mp);
-       else if (error == 0) {
-           mp->b_datap->db_type = M_IOCACK;
-           qreply(q, mp);
-       } else {
-           mp->b_datap->db_type = M_IOCNAK;
-           iop->ioc_count = 0;
-           iop->ioc_error = error;
-           qreply(q, mp);
-       }
-       break;
-
-    default:
-       putnext(q, mp);
-    }
-    return 0;
-}
-
-static int
-if_ppp_rput(q, mp)
-    queue_t *q;
-    mblk_t *mp;
-{
-    if_ppp_t *sp;
-    int proto, s;
-    struct mbuf *mb;
-    struct ifqueue *inq;
-    struct ifnet *ifp;
-    int len;
-
-    sp = (if_ppp_t *) q->q_ptr;
-    switch (mp->b_datap->db_type) {
-    case M_DATA:
-       /*
-        * Convert the message into an mbuf chain
-        * and inject it into the network code.
-        */
-       if (sp->flags & DBGLOG)
-           printf("if_ppp: rput pkt len %d data %x %x %x %x %x %x %x %x\n",
-                  msgdsize(mp), mp->b_rptr[0], mp->b_rptr[1], mp->b_rptr[2],
-                  mp->b_rptr[3], mp->b_rptr[4], mp->b_rptr[5], mp->b_rptr[6],
-                  mp->b_rptr[7]);
-
-       if (sp->unit < 0) {
-           freemsg(mp);
-           break;
-       }
-       if (sp->unit >= ppp_nalloc || (ifp = ifs[sp->unit]) == 0) {
-#ifdef DEBUG
-           printf("if_ppp: no unit %d!\n", sp->unit);
-#endif
-           freemsg(mp);
-           break;
-       }
-
-       if ((ifp->if_flags & IFF_UP) == 0) {
-           freemsg(mp);
-           break;
-       }
-       ++ifp->if_ipackets;
-
-       proto = PPP_PROTOCOL(mp->b_rptr);
-       adjmsg(mp, PPP_HDRLEN);
-       len = msgdsize(mp);
-       mb = make_mbufs(mp, sizeof(struct ifnet *));
-       freemsg(mp);
-       if (mb == NULL) {
-           if (sp->flags & DBGLOG)
-               printf("if_ppp%d: make_mbufs failed\n", ifp->if_unit);
-           ++ifp->if_ierrors;
-           break;
-       }
-
-#ifdef SNIT_SUPPORT
-       if (proto == PPP_IP && (ifp->if_flags & IFF_PROMISC)) {
-           struct nit_if nif;
-
-           nif.nif_header = (caddr_t) &snit_ehdr;
-           nif.nif_hdrlen = sizeof(snit_ehdr);
-           nif.nif_bodylen = len;
-           nif.nif_promisc = 0;
-           snit_intr(ifp, mb, &nif);
-       }
-#endif
-
-/*
- * For Digital UNIX, there's space set aside in the header mbuf
- * for the interface info.
- *
- * For Sun it's smuggled around via a pointer at the front of the mbuf.
- */
-#ifdef __osf__
-        mb->m_pkthdr.rcvif = ifp;
-        mb->m_pkthdr.len = len;
-#else
-       mb->m_off -= sizeof(struct ifnet *);
-       mb->m_len += sizeof(struct ifnet *);
-       *mtod(mb, struct ifnet **) = ifp;
-#endif
-
-       inq = 0;
-       switch (proto) {
-       case PPP_IP:
-           inq = &ipintrq;
-           schednetisr(NETISR_IP);
-       }
-
-       if (inq != 0) {
-           s = splhigh();
-           if (IF_QFULL(inq)) {
-               IF_DROP(inq);
-               ++ifp->if_ierrors;
-               if (sp->flags & DBGLOG)
-                   printf("if_ppp: inq full, proto=%x\n", proto);
-               m_freem(mb);
-           } else {
-               IF_ENQUEUE(inq, mb);
-           }
-           splx(s);
-       } else {
-           if (sp->flags & DBGLOG)
-               printf("if_ppp%d: proto=%x?\n", ifp->if_unit, proto);
-           ++ifp->if_ierrors;
-           m_freem(mb);
-       }
-       break;
-
-    default:
-       putnext(q, mp);
-    }
-    return 0;
-}
-
-/*
- * Network code wants to output a packet.
- * Turn it into a STREAMS message and send it down.
- */
-static int
-if_ppp_output(ifp, m0, dst)
-    struct ifnet *ifp;
-    struct mbuf *m0;
-    struct sockaddr *dst;
-{
-    mblk_t *mp;
-    int proto, s;
-    if_ppp_t *sp;
-    u_char *p;
-
-    if ((ifp->if_flags & IFF_UP) == 0) {
-       m_freem(m0);
-       return ENETDOWN;
-    }
-
-    if ((unsigned)ifp->if_unit >= ppp_nalloc) {
-#ifdef DEBUG
-       printf("if_ppp_output: unit %d?\n", ifp->if_unit);
-#endif
-       m_freem(m0);
-       return EINVAL;
-    }
-    sp = states[ifp->if_unit];
-    if (sp == 0) {
-#ifdef DEBUG
-       printf("if_ppp_output: no queue?\n");
-#endif
-       m_freem(m0);
-       return ENETDOWN;
-    }
-
-    if (sp->flags & DBGLOG) {
-       p = mtod(m0, u_char *);
-       printf("if_ppp_output%d: af=%d data=%x %x %x %x %x %x %x %x q=%x\n",
-              ifp->if_unit, dst->sa_family, p[0], p[1], p[2], p[3], p[4],
-              p[5], p[6], p[7], sp->q);
-    }
-
-    switch (dst->sa_family) {
-    case AF_INET:
-       proto = PPP_IP;
-#ifdef SNIT_SUPPORT
-       if (ifp->if_flags & IFF_PROMISC) {
-           struct nit_if nif;
-           struct mbuf *m;
-           int len;
-
-           for (len = 0, m = m0; m != NULL; m = m->m_next)
-               len += m->m_len;
-           nif.nif_header = (caddr_t) &snit_ehdr;
-           nif.nif_hdrlen = sizeof(snit_ehdr);
-           nif.nif_bodylen = len;
-           nif.nif_promisc = 0;
-           snit_intr(ifp, m0, &nif);
-       }
-#endif
-       break;
-
-    default:
-       m_freem(m0);
-       return EAFNOSUPPORT;
-    }
-
-    ++ifp->if_opackets;
-    mp = make_message(m0, PPP_HDRLEN);
-    m_freem(m0);
-    if (mp == 0) {
-       ++ifp->if_oerrors;
-       return ENOBUFS;
-    }
-    mp->b_rptr -= PPP_HDRLEN;
-    mp->b_rptr[0] = PPP_ALLSTATIONS;
-    mp->b_rptr[1] = PPP_UI;
-    mp->b_rptr[2] = proto >> 8;
-    mp->b_rptr[3] = proto;
-
-    s = splstr();
-    if (sp->flags & DBGLOG)
-       printf("if_ppp: putnext(%x, %x), r=%x w=%x p=%x\n",
-              sp->q, mp, mp->b_rptr, mp->b_wptr, proto);
-    putnext(sp->q, mp);
-    splx(s);
-
-    return 0;
-}
-
-/*
- * Socket ioctl routine for ppp interfaces.
- */
-static int
-if_ppp_ioctl(ifp, cmd, data)
-    struct ifnet *ifp;
-    u_int cmd;
-    caddr_t data;
-{
-    int s, error;
-    struct ifreq *ifr = (struct ifreq *) data;
-    struct ifaddr *ifa = (struct ifaddr *) data;
-    u_short mtu;
-
-    error = 0;
-    s = splimp();
-    switch (cmd) {
-    case SIOCSIFFLAGS:
-       if ((ifp->if_flags & IFF_RUNNING) == 0)
-           ifp->if_flags &= ~IFF_UP;
-       break;
-
-    case SIOCSIFADDR:
-       if (IFA_ADDR(ifa).sa_family != AF_INET)
-           error = EAFNOSUPPORT;
-       break;
-
-    case SIOCSIFDSTADDR:
-       if (IFA_ADDR(ifa).sa_family != AF_INET)
-           error = EAFNOSUPPORT;
-       break;
-
-    case SIOCSIFMTU:
-       if ((error = NOTSUSER()) != 0)
-           break;
-#ifdef __osf__
-       /* this hack is necessary because ifioctl checks ifr_data
-        * in 4.0 and 5.0, but ifr_data and ifr_metric overlay each 
-        * other in the definition of struct ifreq so pppd can't set both.
-        */
-        bcopy(ifr->ifr_data, &mtu, sizeof (u_short));
-        ifr->ifr_mtu = mtu;
-#endif
-
-       if (ifr->ifr_mtu < PPP_MINMTU || ifr->ifr_mtu > PPP_MAXMTU) {
-           error = EINVAL;
-           break;
-       }
-       ifp->if_mtu = ifr->ifr_mtu;
-       break;
-
-    case SIOCGIFMTU:
-       ifr->ifr_mtu = ifp->if_mtu;
-       break;
-
-    case SIOCADDMULTI:
-    case SIOCDELMULTI:
-       switch(ifr->ifr_addr.sa_family) {
-       case AF_INET:
-           break;
-       default:
-           error = EAFNOSUPPORT;
-           break;
-       }
-       break;
-
-    default:
-       error = EINVAL;
-    }
-    splx(s);
-    return (error);
-}
-
-/*
- * Turn a STREAMS message into an mbuf chain.
- */
-static struct mbuf *
-make_mbufs(mp, off)
-    mblk_t *mp;
-    int off;
-{
-    struct mbuf *head, **prevp, *m;
-    int len, space, n;
-    unsigned char *cp, *dp;
-
-    len = msgdsize(mp);
-    if (len == 0)
-       return 0;
-    prevp = &head;
-    space = 0;
-    cp = mp->b_rptr;
-#ifdef __osf__
-    MGETHDR(m, M_DONTWAIT, MT_DATA);
-    m->m_len = 0;
-    space = MHLEN;
-    *prevp = m;
-    prevp = &m->m_next;
-    dp = mtod(m, unsigned char *);
-    len -= space;
-    off = 0;
-#endif
-    for (;;) {
-       while (cp >= mp->b_wptr) {
-           mp = mp->b_cont;
-           if (mp == 0) {
-               *prevp = 0;
-               return head;
-           }
-           cp = mp->b_rptr;
-       }
-       n = mp->b_wptr - cp;
-       if (space == 0) {
-           MGET(m, M_DONTWAIT, MT_DATA);
-           *prevp = m;
-           if (m == 0) {
-               if (head != 0)
-                   m_freem(head);
-               return 0;
-           }
-           if (len + off > 2 * MLEN) {
-#ifdef __osf__
-               MCLGET(m, M_DONTWAIT);
-#else
-               MCLGET(m);
-#endif
-           }
-#ifdef __osf__
-           space = ((m->m_flags & M_EXT) ? MCLBYTES : MLEN);
-#else
-           space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
-           m->m_off += off;
-#endif
-           m->m_len = 0;
-           len -= space;
-           dp = mtod(m, unsigned char *);
-           off = 0;
-           prevp = &m->m_next;
-       }
-       if (n > space)
-           n = space;
-       bcopy(cp, dp, n);
-       cp += n;
-       dp += n;
-       space -= n;
-       m->m_len += n;
-    }
-}
-
-/*
- * Turn an mbuf chain into a STREAMS message.
- */
-#define ALLOCB_MAX     4096
-
-static mblk_t *
-make_message(m, off)
-    struct mbuf *m;
-    int off;
-{
-    mblk_t *head, **prevp, *mp;
-    int len, space, n, nb;
-    unsigned char *cp, *dp;
-    struct mbuf *nm;
-
-    len = 0;
-    for (nm = m; nm != 0; nm = nm->m_next)
-       len += nm->m_len;
-    prevp = &head;
-    space = 0;
-    cp = mtod(m, unsigned char *);
-    nb = m->m_len;
-    for (;;) {
-       while (nb <= 0) {
-           m = m->m_next;
-           if (m == 0) {
-               *prevp = 0;
-               return head;
-           }
-           cp = mtod(m, unsigned char *);
-           nb = m->m_len;
-       }
-       if (space == 0) {
-           space = len + off;
-           if (space > ALLOCB_MAX)
-               space = ALLOCB_MAX;
-           mp = allocb(space, BPRI_LO);
-           *prevp = mp;
-           if (mp == 0) {
-               if (head != 0)
-                   freemsg(head);
-               return 0;
-           }
-           dp = mp->b_rptr += off;
-           space -= off;
-           len -= space;
-           off = 0;
-           prevp = &mp->b_cont;
-       }
-       n = nb < space? nb: space;
-       bcopy(cp, dp, n);
-       cp += n;
-       dp += n;
-       nb -= n;
-       space -= n;
-       mp->b_wptr = dp;
-    }
-}
-
-/*
- * Digital UNIX doesn't allow for removing ifnet structures
- * from the list.  But then we're not using this as a loadable
- * module anyway, so that's OK.
- *
- * Under SunOS, this should allow the module to be unloaded.
- * Unfortunately, it doesn't seem to detach all the references,
- * so your system may well crash after you unload this module :-(
- */
-#ifndef __osf__
-
-/*
- * Remove an interface from the system.
- * This routine contains magic.
- */
-#include <net/route.h>
-#include <netinet/in_pcb.h>
-#include <netinet/ip_var.h>
-#include <netinet/tcp.h>
-#include <netinet/tcp_timer.h>
-#include <netinet/tcp_var.h>
-#include <netinet/udp.h>
-#include <netinet/udp_var.h>
-
-static void
-ppp_if_detach(ifp)
-    struct ifnet *ifp;
-{
-    int s;
-    struct inpcb *pcb;
-    struct ifaddr *ifa;
-    struct in_ifaddr **inap;
-    struct ifnet **ifpp;
-
-    s = splhigh();
-
-    /*
-     * Clear the interface from any routes currently cached in
-     * TCP or UDP protocol control blocks.
-     */
-    for (pcb = tcb.inp_next; pcb != &tcb; pcb = pcb->inp_next)
-       if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
-           in_losing(pcb);
-    for (pcb = udb.inp_next; pcb != &udb; pcb = pcb->inp_next)
-       if (pcb->inp_route.ro_rt && pcb->inp_route.ro_rt->rt_ifp == ifp)
-           in_losing(pcb);
-
-    /*
-     * Delete routes through all addresses of the interface.
-     */
-    for (ifa = ifp->if_addrlist; ifa != 0; ifa = ifa->ifa_next) {
-       rtinit(ifa, ifa, SIOCDELRT, RTF_HOST);
-       rtinit(ifa, ifa, SIOCDELRT, 0);
-    }
-
-    /*
-     * Unlink the interface's address(es) from the in_ifaddr list.
-     */
-    for (inap = &in_ifaddr; *inap != 0; ) {
-       if ((*inap)->ia_ifa.ifa_ifp == ifp)
-           *inap = (*inap)->ia_next;
-       else
-           inap = &(*inap)->ia_next;
-    }
-
-    /*
-     * Delete the interface from the ifnet list.
-     */
-    for (ifpp = &ifnet; (*ifpp) != 0; ) {
-       if (*ifpp == ifp)
-           break;
-       ifpp = &(*ifpp)->if_next;
-    }
-    if (*ifpp == 0)
-       printf("couldn't find interface ppp%d in ifnet list\n", ifp->if_unit);
-    else
-       *ifpp = ifp->if_next;
-
-    splx(s);
-}
-
-#endif /* __osf__ */