Below is a patch which does the important parts of making kernel ppp
devices clonable and making the module unloadable.  It combines both
"ifconfig <if> create" style cloning and the sl(4) create on attach
method.  This was done to allow interfaces to be pre-created so things
like firewall rules would work, but also to let things "just work" when
some tried to run pppd on a tty.

Since I've never used pppd, this patch hasn't been extensivly tested so
any testing would be appreciated.

Once this is commited, we'll have eliminated all compile time
specification of the number of pseudo network devices.

-- Brooks

Index: conf/files
===================================================================
RCS file: /usr/cvs/src/sys/conf/files,v
retrieving revision 1.642
diff -u -p -r1.642 files
--- conf/files  30 May 2002 17:37:34 -0000      1.642
+++ conf/files  30 May 2002 20:46:42 -0000
@@ -984,7 +984,7 @@ net/if_iso88025subr.c       optional token
 net/if_loop.c          optional loop
 net/if_media.c         standard
 net/if_mib.c           standard
-net/if_ppp.c           count ppp
+net/if_ppp.c           optional ppp
 net/if_sl.c            optional sl
 net/if_spppsubr.c      optional sppp
 net/if_spppsubr.c      optional i4bisppp
Index: net/if_ppp.c
===================================================================
RCS file: /usr/cvs/src/sys/net/if_ppp.c,v
retrieving revision 1.79
diff -u -p -r1.79 if_ppp.c
--- net/if_ppp.c        4 Apr 2002 21:03:28 -0000       1.79
+++ net/if_ppp.c        28 Apr 2002 17:11:41 -0000
@@ -73,8 +73,6 @@
 /* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
 /* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
 
-#include "ppp.h"
-
 #include "opt_inet.h"
 #include "opt_ipx.h"
 #include "opt_ppp.h"
@@ -130,10 +128,13 @@
 #include <net/ppp_comp.h>
 #endif
 
-static struct ppp_softc ppp_softc[NPPP];
+#define PPPNAME                "ppp"
+static MALLOC_DEFINE(M_PPP, PPPNAME, "PPP interface");
+static LIST_HEAD(, ppp_softc) ppp_softc_list;
 
 /* XXX layering violation */
 extern void    pppasyncattach(void *);
+extern void    pppasyncdetach(void);
 
 static int     pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
 static void    pppintr(void);
@@ -143,6 +144,11 @@ static void        ppp_ccp(struct ppp_softc *, 
 static void    ppp_ccp_closed(struct ppp_softc *);
 static void    ppp_inproc(struct ppp_softc *, struct mbuf *);
 static void    pppdumpm(struct mbuf *m0);
+static int     ppp_clone_create(struct if_clone *, int);
+static void    ppp_clone_destroy(struct ifnet *);
+
+static struct if_clone ppp_cloner = IF_CLONE_INITIALIZER(PPPNAME,
+    ppp_clone_create, ppp_clone_destroy, 0, IF_MAXUNIT);
 
 /*
  * Some useful mbuf macros not in mbuf.h.
@@ -186,18 +192,15 @@ static struct compressor *ppp_compressor
 };
 #endif /* PPP_COMPRESS */
 
-/*
- * Called from boot code to establish ppp interfaces.
- */
-static void
-pppattach(void)
+static int
+ppp_clone_create(struct if_clone *ifc, int unit)
 {
-    register struct ppp_softc *sc;
-    register int i = 0;
+       struct ppp_softc        *sc;
 
-    for (sc = ppp_softc; i < NPPP; sc++) {
-       sc->sc_if.if_name = "ppp";
-       sc->sc_if.if_unit = i++;
+       sc = malloc(sizeof(struct ppp_softc), M_PPP, M_WAITOK | M_ZERO);
+       sc->sc_if.if_softc = sc;
+       sc->sc_if.if_name = PPPNAME;
+       sc->sc_if.if_unit = unit;
        sc->sc_if.if_mtu = PPP_MTU;
        sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
        sc->sc_if.if_type = IFT_PPP;
@@ -208,18 +211,29 @@ pppattach(void)
        sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
        sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
        sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
-        mtx_init(&sc->sc_inq.ifq_mtx, "ppp_inq", NULL, MTX_DEF);
-        mtx_init(&sc->sc_fastq.ifq_mtx, "ppp_fastq", NULL, MTX_DEF);
-        mtx_init(&sc->sc_rawq.ifq_mtx, "ppp_rawq", NULL, MTX_DEF);
+       mtx_init(&sc->sc_inq.ifq_mtx, "ppp_inq", NULL, MTX_DEF);
+       mtx_init(&sc->sc_fastq.ifq_mtx, "ppp_fastq", NULL, MTX_DEF);
+       mtx_init(&sc->sc_rawq.ifq_mtx, "ppp_rawq", NULL, MTX_DEF);
        if_attach(&sc->sc_if);
        bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN);
-    }
-    register_netisr(NETISR_PPP, pppintr);
-    /*
-     * XXX layering violation - if_ppp can work over any lower level
-     * transport that cares to attach to it.
-     */
-    pppasyncattach(NULL);
+       LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list);
+
+       return 1;
+}
+
+static void
+ppp_clone_destroy(struct ifnet *ifp)
+{
+       struct ppp_softc        *sc;
+
+       sc = ifp->if_softc;
+
+       LIST_REMOVE(sc, sc_list);
+       bpfdetach(ifp);
+       if_detach(ifp);
+       mtx_destroy(&sc->sc_rawq.ifq_mtx);
+       mtx_destroy(&sc->sc_fastq.ifq_mtx);
+       mtx_destroy(&sc->sc_inq.ifq_mtx);
 }
 
 static int
@@ -227,10 +241,27 @@ ppp_modevent(module_t mod, int type, voi
 { 
        switch (type) { 
        case MOD_LOAD: 
-               pppattach();
+               if_clone_attach(&ppp_cloner);
+
+               register_netisr(NETISR_PPP, pppintr);
+               /*
+                * XXX layering violation - if_ppp can work over any lower
+                * level transport that cares to attach to it.
+                */
+               pppasyncattach(NULL);
                break; 
        case MOD_UNLOAD: 
-               printf("if_ppp module unload - not possible for this module type\n"); 
+               /* XXX: layering violation */
+               pppasyncdetach();
+
+               unregister_netisr(NETISR_PPP);
+
+               if_clone_detach(&ppp_cloner);
+
+               while (!LIST_EMPTY(&ppp_softc_list))
+                       ppp_clone_destroy(
+                           &LIST_FIRST(&ppp_softc_list)->sc_if);
+
                return EINVAL; 
        } 
        return 0; 
@@ -251,18 +282,32 @@ struct ppp_softc *
 pppalloc(pid)
     pid_t pid;
 {
-    int nppp, i;
+    int i;
+    char tmpname[IFNAMSIZ];
+    struct ifnet *ifp;
     struct ppp_softc *sc;
 
-    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
+    LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
        if (sc->sc_xfer == pid) {
            sc->sc_xfer = 0;
            return sc;
        }
-    for (nppp = 0, sc = ppp_softc; nppp < NPPP; nppp++, sc++)
+    }
+    LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
        if (sc->sc_devp == NULL)
            break;
-    if (nppp >= NPPP)
+    }
+    /* Try to clone an interface if we don't have a free one */
+    if (sc == NULL) {
+       strcpy(tmpname, PPPNAME);
+       if (if_clone_create(tmpname, sizeof(tmpname)) != 0)
+           return NULL;
+       ifp = ifunit(tmpname);
+       if (ifp == NULL)
+           return NULL;
+       sc = ifp->if_softc;
+    }
+    if (sc == NULL || sc->sc_devp != NULL)
        return NULL;
 
     sc->sc_flags = 0;
@@ -574,7 +619,7 @@ pppsioctl(ifp, cmd, data)
     caddr_t data;
 {
     struct thread *td = curthread;     /* XXX */
-    register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
+    register struct ppp_softc *sc = ifp->if_softc;
     register struct ifaddr *ifa = (struct ifaddr *)data;
     register struct ifreq *ifr = (struct ifreq *)data;
     struct ppp_stats *psp;
@@ -704,7 +749,7 @@ pppoutput(ifp, m0, dst, rtp)
     struct sockaddr *dst;
     struct rtentry *rtp;
 {
-    register struct ppp_softc *sc = &ppp_softc[ifp->if_unit];
+    register struct ppp_softc *sc = ifp->if_softc;
     int protocol, address, control;
     u_char *cp;
     int s, error;
@@ -1085,11 +1130,10 @@ static void
 pppintr()
 {
     struct ppp_softc *sc;
-    int i, s;
+    int s;
     struct mbuf *m;
 
-    sc = ppp_softc;
-    for (i = 0; i < NPPP; ++i, ++sc) {
+    LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
        s = splimp();
        if (!(sc->sc_flags & SC_TBUSY)
            && (sc->sc_if.if_snd.ifq_head || sc->sc_fastq.ifq_head)) {
Index: net/if_pppvar.h
===================================================================
RCS file: /usr/cvs/src/sys/net/if_pppvar.h,v
retrieving revision 1.19
diff -u -p -r1.19 if_pppvar.h
--- net/if_pppvar.h     24 Mar 2002 09:34:04 -0000      1.19
+++ net/if_pppvar.h     13 Apr 2002 03:36:14 -0000
@@ -96,6 +96,7 @@ struct ppp_softc {
        u_short sc_outfcs;              /* FCS so far for output packet */
        u_char  sc_rawin[16];           /* chars as received */
        int     sc_rawin_count;         /* # in sc_rawin */
+       LIST_ENTRY(ppp_softc) sc_list;
 };
 
 struct ppp_softc *pppalloc(pid_t pid);
Index: net/ppp_tty.c
===================================================================
RCS file: /usr/cvs/src/sys/net/ppp_tty.c,v
retrieving revision 1.50
diff -u -p -r1.50 ppp_tty.c
--- net/ppp_tty.c       1 Apr 2002 21:31:03 -0000       1.50
+++ net/ppp_tty.c       25 May 2002 21:15:47 -0000
@@ -114,6 +114,7 @@ static void ppplogchar(struct ppp_softc 
 
 /* XXX called from if_ppp.c - layering violation */
 void           pppasyncattach(void *);
+void           pppasyncdetach(void);
 
 /*
  * Some useful mbuf macros not in mbuf.h.
@@ -146,6 +147,7 @@ void                pppasyncattach(void *);
  * Define the PPP line discipline.
  */
 
+static struct linesw pppnodisc;
 static struct linesw pppdisc = {
        pppopen,        pppclose,       pppread,        pppwrite,
        ppptioctl,      pppinput,       pppstart,       ttymodem,
@@ -156,8 +158,17 @@ void
 pppasyncattach(dummy)
     void *dummy;
 {
+    /* save previous entry for detach */
+    pppnodisc = linesw[PPPDISC];
     /* register line discipline */
     linesw[PPPDISC] = pppdisc;
+}
+
+void
+pppasyncdetach()
+{
+       /* deregister line discipline */
+       linesw[PPPDISC] = pppnodisc;
 }
 
 /*

-- 
Any statement of the form "X is the one, true Y" is FALSE.
PGP fingerprint 655D 519C 26A7 82E7 2529  9BF0 5D8E 8BE9 F238 1AD4

Attachment: msg06162/pgp00000.pgp
Description: PGP signature

Reply via email to