]> git.ozlabs.org Git - ppp.git/commitdiff
new modules for SunOS 4
authorPaul Mackerras <paulus@samba.org>
Tue, 19 Dec 1995 00:06:06 +0000 (00:06 +0000)
committerPaul Mackerras <paulus@samba.org>
Tue, 19 Dec 1995 00:06:06 +0000 (00:06 +0000)
sunos4/Makefile [new file with mode: 0644]
sunos4/Makefile.top [new file with mode: 0644]
sunos4/if_ppp.c [new file with mode: 0644]
sunos4/if_ppp_vdcmd.c [new file with mode: 0644]
sunos4/ppp.INSTALL [new file with mode: 0755]
sunos4/ppp_ahdlc_vdcmd.c [new file with mode: 0644]
sunos4/ppp_comp_vdcmd.c [new file with mode: 0644]
sunos4/ppp_vdcmd.c [new file with mode: 0644]

diff --git a/sunos4/Makefile b/sunos4/Makefile
new file mode 100644 (file)
index 0000000..6259e2e
--- /dev/null
@@ -0,0 +1,49 @@
+#
+# Makefile for STREAMS modules for SunOS 4.
+#
+# $Id: Makefile,v 1.1 1995/12/19 00:05:55 paulus Exp $
+#
+
+ARCH:sh = /bin/arch -k
+#CC = gcc
+
+BINDIR = /usr/local/etc
+INSTALL = install -o root -g daemon
+
+# Defining __$(ARCH)__ is for gcc's broken version of sun/vddrv.h.
+CFLAGS= -DKERNEL -I.. -O -DSUNOS4 -D$(ARCH) -D__$(ARCH)__ -DDEBUG -DNO_DLPI
+
+MODULES= ppp_mod.o ppp_ahdl_mod.o ppp_comp_mod.o if_ppp_mod.o
+
+all:   $(MODULES)
+
+ppp_mod.o:     ppp.o ppp_vdcmd.o
+       ld -r -o ppp_mod.o ppp.o ppp_vdcmd.o
+
+ppp_ahdl_mod.o: ppp_ahdlc.o ppp_ahdlc_vdcmd.o
+       ld -r -o ppp_ahdl_mod.o ppp_ahdlc.o ppp_ahdlc_vdcmd.o
+
+ppp_comp_mod.o: ppp_comp.o bsd-comp.o vjcompress.o ppp_comp_vdcmd.o
+       ld -r -o ppp_comp_mod.o ppp_comp.o bsd-comp.o vjcompress.o \
+        ppp_comp_vdcmd.o
+
+bsd-comp.o: ../modules/bsd-comp.c
+       $(CC) $(CFLAGS) -c $?
+ppp.o: ../modules/ppp.c
+       $(CC) $(CFLAGS) -c $?
+ppp_ahdlc.o: ../modules/ppp_ahdlc.c
+       $(CC) $(CFLAGS) -c $?
+ppp_comp.o: ../modules/ppp_comp.c
+       $(CC) $(CFLAGS) -c $?
+vjcompress.o: ../modules/vjcompress.c
+       $(CC) $(CFLAGS) -c $?
+
+if_ppp_mod.o:  if_ppp.o if_ppp_vdcmd.o
+       ld -r -o if_ppp_mod.o if_ppp.o if_ppp_vdcmd.o
+
+install: all
+       $(INSTALL) $(MODULES) $(BINDIR)
+       ./ppp.INSTALL
+
+clean:
+       rm -f ppp ppp_comp ppp_ahdl *.o *~ core
diff --git a/sunos4/Makefile.top b/sunos4/Makefile.top
new file mode 100644 (file)
index 0000000..b63276c
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# ppp top level makefile
+#
+
+BINDIR = /usr/local/etc
+MANDIR = /usr/local/man
+ETCDIR = /etc/ppp
+
+INSTALL= install -o root -g daemon
+
+all:
+       cd chat; $(MAKE) all
+       cd pppd; $(MAKE) all
+       cd pppstats; $(MAKE) all
+       cd sunos4; $(MAKE) all
+
+install: $(BINDIR) $(MANDIR)/man8 install-progs install-etcppp
+
+install-progs:
+       cd chat; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) install
+       cd pppd; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) install
+       cd pppstats; $(MAKE) BINDIR=$(BINDIR) MANDIR=$(MANDIR) install
+       cd sunos4; $(MAKE) BINDIR=$(BINDIR) install
+
+install-etcppp: $(ETCDIR) $(ETCDIR)/options $(ETCDIR)/pap-secrets \
+       $(ETCDIR)/chap-secrets
+
+$(ETCDIR)/options:
+       if netstat -rn | grep default >/dev/null; then \
+         $(INSTALL) -c -m 644 etc.ppp/options $@; \
+       else $(INSTALL) -c -m 644 etc.ppp/options.leaf $@; fi
+$(ETCDIR)/pap-secrets:
+       $(INSTALL) -c -m 600 etc.ppp/pap-secrets $@
+$(ETCDIR)/chap-secrets:
+       $(INSTALL) -c -m 600 etc.ppp/chap-secrets $@
+
+$(BINDIR):
+       $(INSTALL) -d -m 755 $@
+$(MANDIR)/man8:
+       $(INSTALL) -d -m 755 $@
+$(ETCDIR):
+       $(INSTALL) -d -m 755 $@
+
+clean:
+       rm -f *~
+       cd chat; $(MAKE) clean
+       cd pppd; $(MAKE) clean
+       cd pppstats; $(MAKE) clean
+       cd sunos4; $(MAKE) clean
+
diff --git a/sunos4/if_ppp.c b/sunos4/if_ppp.c
new file mode 100644 (file)
index 0000000..1b8eed5
--- /dev/null
@@ -0,0 +1,733 @@
+/*
+ * if_ppp.c - a network interface connected to a STREAMS module.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: if_ppp.c,v 1.1 1995/12/19 00:05:59 paulus Exp $
+ */
+
+/*
+ * This file is used under SunOS 4.
+ */
+
+#define INET   1
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stream.h>
+#include <sys/errno.h>
+#include <sys/kmem_alloc.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.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>
+
+#define NOTSUSER()     (suser()? 0: EPERM)
+#define ifr_mtu                ifr_metric
+
+#define ZALLOC(n, t, how)      ((t *) kmem_zalloc((n) * sizeof(t), (how)))
+#define ZFREE(p, n, t)         kmem_free((void *)(p), (n) * sizeof(t))
+
+#define PPP_MINMTU     64
+#define PPP_MAXMTU     65536
+
+typedef unsigned char uchar_t;
+typedef unsigned short ushort_t;
+
+static int if_ppp_open __P((queue_t *, int, int, int));
+static int if_ppp_close __P((queue_t *, int));
+static int if_ppp_wput __P((queue_t *, mblk_t *));
+static int if_ppp_rput __P((queue_t *, mblk_t *));
+
+static struct module_info minfo = {
+    0x8021, "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 __P((struct ifnet *, struct mbuf *,
+                             struct sockaddr *));
+static int if_ppp_ioctl __P((struct ifnet *, u_long, caddr_t));
+static struct mbuf *make_mbufs __P((mblk_t *, int));
+static mblk_t *make_message __P((struct mbuf *, int));
+static void ppp_if_detach __P((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]);
+    ZFREE(ifs, ppp_nalloc, struct ifnet *);
+    ZFREE(states, ppp_nalloc, if_ppp_t *);
+    ppp_nalloc = 0;
+    return 0;
+}
+
+/*
+ * 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 = ZALLOC(1, if_ppp_t, KMEM_SLEEP);
+       if (sp == 0)
+           return OPENFAIL;
+       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
+           }
+       }
+       ZFREE(sp, 1, 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 = ZALLOC(newn, struct ifnet *, KMEM_NOSLEEP);
+               if (newifs == 0)
+                   break;
+               newstates = ZALLOC(newn, if_ppp_t *, KMEM_NOSLEEP);
+               if (newstates == 0) {
+                   ZFREE(newifs, newn, struct ifnet *);
+                   break;
+               }
+               bcopy(ifs, newifs, ppp_nalloc * sizeof(struct ifnet *));
+               bcopy(states, newstates, 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 = ZALLOC(1, struct ifnet, KMEM_NOSLEEP);
+               if (ifp == 0)
+                   break;
+               ifs[unit] = ifp;
+               ifp->if_name = "ppp";
+               ifp->if_unit = unit;
+               ifp->if_mtu = PPP_MRU;
+               ifp->if_flags = IFF_POINTOPOINT | IFF_RUNNING;
+#ifdef IFF_MULTICAST
+               ifp->if_flags |= IFF_MULTICAST;
+#endif
+               ifp->if_output = if_ppp_output;
+               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_MRU;
+               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;
+
+    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);
+       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;
+       }
+       mb->m_off -= sizeof(struct ifnet *);
+       mb->m_len += sizeof(struct ifnet *);
+       *mtod(mb, struct ifnet **) = ifp;
+
+       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;
+       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_long cmd;
+    caddr_t data;
+{
+    int s, error;
+    struct ifreq *ifr = (struct ifreq *) data;
+    struct ifaddr *ifa = (struct ifaddr *) data;
+
+    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->ifa_addr.sa_family != AF_INET)
+           error = EAFNOSUPPORT;
+       break;
+
+    case SIOCSIFDSTADDR:
+       if (ifa->ifa_addr.sa_family != AF_INET)
+           error = EAFNOSUPPORT;
+       break;
+
+    case SIOCSIFMTU:
+       if ((error = NOTSUSER()) != 0)
+           break;
+       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;
+    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) {
+               MCLGET(m);
+           }
+           space = (m->m_off > MMAXOFF? MCLBYTES: MLEN) - off;
+           m->m_off += off;
+           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;
+    }
+}
+
+/*
+ * 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);
+}
diff --git a/sunos4/if_ppp_vdcmd.c b/sunos4/if_ppp_vdcmd.c
new file mode 100644 (file)
index 0000000..2bf9710
--- /dev/null
@@ -0,0 +1,57 @@
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/conf.h>
+#include <sun/vddrv.h>
+
+extern struct streamtab if_pppinfo;
+
+static struct vdldrv vd = {
+    VDMAGIC_USER,
+    "if_ppp"
+};
+
+static int fmodsw_index = -1;
+
+int
+if_ppp_vdcmd(fun, vdp, vdi, vds)
+    unsigned int fun;
+    struct vddrv *vdp;
+    addr_t vdi;
+    struct vdstat *vds;
+{
+    int n, error;
+
+    switch (fun) {
+    case VDLOAD:
+       vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+       if (fmodsw_index >= 0)
+           return EBUSY;
+       for (n = 0; n < fmodcnt; ++n)
+           if (fmodsw[n].f_str == 0)
+               break;
+       if (n >= fmodcnt)
+           return ENODEV;
+       strncpy(fmodsw[n].f_name, vd.Drv_name, FMNAMESZ+1);
+       fmodsw[n].f_str = &if_pppinfo;
+       fmodsw_index = n;
+       break;
+
+    case VDUNLOAD:
+       if (fmodsw_index <= 0)
+           return EINVAL;
+       error = if_ppp_unload();
+       if (error != 0)
+           return error;
+       fmodsw[fmodsw_index].f_name[0] = 0;
+       fmodsw[fmodsw_index].f_str = 0;
+       fmodsw_index = -1;
+       break;
+
+    case VDSTAT:
+       break;
+
+    default:
+       return EIO;
+    }
+    return 0;
+}
diff --git a/sunos4/ppp.INSTALL b/sunos4/ppp.INSTALL
new file mode 100755 (executable)
index 0000000..aa55a5d
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/sh
+
+# Script for loading, unloading, etc. ppp modules.
+
+moddir=/usr/local/etc
+etcppp=/etc/ppp
+
+PATH=/usr/etc:/usr/bin
+
+# Check that we're superuser
+touch /tmp/su$$
+if chown root /tmp/su$$ >/dev/null; then :
+else
+    echo "$0: must be root."
+    rm -f /tmp/su$$
+    exit 1
+fi
+rm -f /tmp/su$$
+
+case "$0" in
+*ppp.INSTALL)
+    if [ ! -f ppp.INSTALL ]; then
+       echo "ppp.INSTALL: not found"
+       exit 1
+    fi
+    for n in INSTALL LOAD UNLOAD MKDEV RMDEV; do
+       if [ -h /dev/ppp.$n -o -f /dev/ppp.$n ]; then
+           rm /dev/ppp.$n
+       fi
+    done
+    cp ppp.INSTALL /dev
+    for n in LOAD UNLOAD MKDEV RMDEV; do
+       ln -s ppp.INSTALL /dev/ppp.$n
+    done
+    ;;
+
+*ppp.LOAD)
+    if modstat | grep -w ppp >/dev/null; then
+       echo "ppp driver is already loaded."
+       exit 1
+    fi
+    if modstat | grep -w if_ppp >/dev/null; then
+       echo "if_ppp module already loaded: not reloading."
+    else
+       echo -n "if_ppp: "
+       modload $moddir/if_ppp_mod.o -sym -entry _if_ppp_vdcmd \
+           -o $etcppp/if_ppp_mod
+    fi
+    echo -n "ppp: "
+    modload $moddir/ppp_mod.o -sym -entry _ppp_vdcmd -exec /dev/ppp.MKDEV \
+       -o $etcppp/ppp_mod
+    echo -n "ppp_comp: "
+    modload $moddir/ppp_comp_mod.o -sym -entry _ppp_comp_vdcmd \
+       -o $etcppp/ppp_comp
+    echo -n "ppp_ahdl: "
+    modload $moddir/ppp_ahdl_mod.o -sym -entry _ppp_ahdlc_vdcmd \
+       -o $etcppp/ppp_ahdl
+    exit 0
+    ;;
+
+*ppp.MKDEV)
+    # args: module number, type, b-major, c-major
+    if [ $# -ne 4 ]; then
+       echo "Usage: $0 module-id module-type b-major c-major"
+       exit 1
+    fi
+    if [ "$2" -ne "12345607" ]; then
+       echo "$0: $2: bad module type"
+       exit 1
+    fi
+    rm -f /dev/ppp
+    # we "just know" that 37 is the major number of the clone driver
+    mknod /dev/ppp c 37 $3
+    chmod 644 /dev/ppp
+    exit 0
+    ;;
+
+*ppp.UNLOAD)
+    stat=0
+    if modstat | grep -w if_ppp >/dev/null; then
+       echo "$0: not unloading if_ppp module."
+    fi
+    for mod in ppp ppp_comp ppp_ahdl; do
+       id=`modstat | grep -w $mod | awk '{print $1}'`
+       if [ x$id = x ]; then
+           echo "$mod is not loaded."
+           stat = 1
+       else
+           modunload -id $id
+       fi
+    done
+    exit $stat
+    ;;
+
+*ppp.RMDEV)
+    echo "$# args: $*"
+    exit 0
+    ;;
+
+*)
+    echo "Invocation names: ppp.INSTALL ppp.LOAD ppp.UNLOAD ppp.MKDEV ppp.RMDEV"
+    exit 1
+    ;;
+esac
diff --git a/sunos4/ppp_ahdlc_vdcmd.c b/sunos4/ppp_ahdlc_vdcmd.c
new file mode 100644 (file)
index 0000000..2dbe826
--- /dev/null
@@ -0,0 +1,57 @@
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/conf.h>
+#include <sun/vddrv.h>
+
+extern struct streamtab ppp_ahdlcinfo;
+extern int ppp_ahdlc_count;
+
+static struct vdldrv vd = {
+    VDMAGIC_USER,
+    "ppp_ahdl"
+};
+
+static int fmodsw_index = -1;
+
+int
+ppp_ahdlc_vdcmd(fun, vdp, vdi, vds)
+    unsigned int fun;
+    struct vddrv *vdp;
+    addr_t vdi;
+    struct vdstat *vds;
+{
+    int n;
+
+    switch (fun) {
+    case VDLOAD:
+       vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+       if (fmodsw_index >= 0)
+           return EBUSY;
+       for (n = 0; n < fmodcnt; ++n)
+           if (fmodsw[n].f_str == 0)
+               break;
+       if (n >= fmodcnt)
+           return ENODEV;
+       strncpy(fmodsw[n].f_name, vd.Drv_name, FMNAMESZ+1);
+       fmodsw[n].f_str = &ppp_ahdlcinfo;
+       fmodsw_index = n;
+       break;
+
+    case VDUNLOAD:
+       if (ppp_ahdlc_count > 0)
+           return EBUSY;
+       if (fmodsw_index <= 0)
+           return EINVAL;
+       fmodsw[fmodsw_index].f_name[0] = 0;
+       fmodsw[fmodsw_index].f_str = 0;
+       fmodsw_index = -1;
+       break;
+
+    case VDSTAT:
+       break;
+
+    default:
+       return EIO;
+    }
+    return 0;
+}
diff --git a/sunos4/ppp_comp_vdcmd.c b/sunos4/ppp_comp_vdcmd.c
new file mode 100644 (file)
index 0000000..b81bc47
--- /dev/null
@@ -0,0 +1,57 @@
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/conf.h>
+#include <sun/vddrv.h>
+
+extern struct streamtab ppp_compinfo;
+extern int ppp_comp_count;
+
+static struct vdldrv vd = {
+    VDMAGIC_USER,
+    "ppp_comp"
+};
+
+static int fmodsw_index = -1;
+
+int
+ppp_comp_vdcmd(fun, vdp, vdi, vds)
+    unsigned int fun;
+    struct vddrv *vdp;
+    addr_t vdi;
+    struct vdstat *vds;
+{
+    int n;
+
+    switch (fun) {
+    case VDLOAD:
+       vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+       if (fmodsw_index >= 0)
+           return EBUSY;
+       for (n = 0; n < fmodcnt; ++n)
+           if (fmodsw[n].f_str == 0)
+               break;
+       if (n >= fmodcnt)
+           return ENODEV;
+       strncpy(fmodsw[n].f_name, vd.Drv_name, FMNAMESZ+1);
+       fmodsw[n].f_str = &ppp_compinfo;
+       fmodsw_index = n;
+       break;
+
+    case VDUNLOAD:
+       if (ppp_comp_count > 0)
+           return EBUSY;
+       if (fmodsw_index <= 0)
+           return EINVAL;
+       fmodsw[fmodsw_index].f_name[0] = 0;
+       fmodsw[fmodsw_index].f_str = 0;
+       fmodsw_index = -1;
+       break;
+
+    case VDSTAT:
+       break;
+
+    default:
+       return EIO;
+    }
+    return 0;
+}
diff --git a/sunos4/ppp_vdcmd.c b/sunos4/ppp_vdcmd.c
new file mode 100644 (file)
index 0000000..eeaa039
--- /dev/null
@@ -0,0 +1,65 @@
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/conf.h>
+#include <sun/vddrv.h>
+
+extern struct streamtab pppinfo;
+extern int ppp_count;
+extern int nchrdev;
+
+static struct vdldrv vd = {
+    VDMAGIC_PSEUDO,
+    "ppp"
+};
+
+extern int nodev();
+
+static struct cdevsw ppp_cdevsw = {
+    nodev, nodev, nodev, nodev, nodev, nodev, nodev, 0,
+    &pppinfo
+};
+
+static struct cdevsw old_entry;
+
+int
+ppp_vdcmd(fun, vdp, vdi, vds)
+    unsigned int fun;
+    struct vddrv *vdp;
+    addr_t vdi;
+    struct vdstat *vds;
+{
+    int n, maj;
+
+    switch (fun) {
+    case VDLOAD:
+       /*
+        * It seems like modload doesn't install the cdevsw entry
+        * for us.  Oh well...
+        */
+       for (maj = 1; maj < nchrdev; ++maj)
+           if (cdevsw[maj].d_open == &vd_unuseddev)
+               break;
+       if (maj >= nchrdev)
+           return ENODEV;
+       vd.Drv_charmajor = maj;
+       old_entry = cdevsw[maj];
+       cdevsw[maj] = ppp_cdevsw;
+       vd.Drv_cdevsw = &ppp_cdevsw;
+       vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+       break;
+
+    case VDUNLOAD:
+       if (ppp_count > 0)
+           return EBUSY;
+       if (vd.Drv_charmajor > 0)
+           cdevsw[vd.Drv_charmajor] = old_entry;
+       break;
+
+    case VDSTAT:
+       break;
+
+    default:
+       return EIO;
+    }
+    return 0;
+}