diff --git a/sys/netgraph7/ng_sppp.c b/sys/netgraph7/ng_sppp.c --- a/sys/netgraph7/ng_sppp.c +++ b/sys/netgraph7/ng_sppp.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include @@ -42,6 +42,13 @@ #include "ng_parse.h" #include "ng_sppp.h" +/* DF-0720: DragonFly's struct sppp (net/sppp/if_sppp.h) nests the ifnet as + * pp_arpcom.ac_if, so IFP2SP must offset back to the enclosing struct sppp. + * (These macros were undefined, which is why this file did not compile.) */ +#define IFP2SP(ifp) \ + ((struct sppp *)((char *)(ifp) - offsetof(struct sppp, pp_arpcom.ac_if))) +#define SP2IFP(sp) (&(sp)->pp_arpcom.ac_if) + #ifdef NG_SEPARATE_MALLOC MALLOC_DEFINE(M_NETGRAPH_SPPP, "netgraph_sppp", "netgraph sppp node "); #else @@ -246,12 +253,17 @@ if (priv == NULL) return (ENOMEM); - ifp = if_alloc(IFT_PPP); - if (ifp == NULL) { + /* DF-0720: sppp_attach()/IFP2SP treat ifp as the pp_arpcom.ac_if member + * of a struct sppp and write ~1KB of PPP state past the ifnet. Allocate + * a full struct sppp here (NOT if_alloc(IFT_PPP), which only returns + * sizeof(struct ifnet) and would be overflowed by sppp_attach). */ + pp = kmalloc(sizeof(struct sppp), M_NETGRAPH_SPPP, M_WAITOK | M_ZERO); + if (pp == NULL) { kfree(priv, M_NETGRAPH_SPPP); return (ENOSPC); } - pp = IFP2SP(ifp); + ifp = SP2IFP(pp); + ifp->if_type = IFT_PPP; /* Link them together */ ifp->if_softc = priv; @@ -393,7 +405,10 @@ bpfdetach (priv->ifp); sppp_detach (priv->ifp); if_detach (priv->ifp); - if_free(priv->ifp); + /* DF-0720: free the struct sppp we allocated (of which ifp is a member). */ + if (priv->ifp->if_description != NULL) + kfree(priv->ifp->if_description, M_IFDESCR); + kfree(IFP2SP(priv->ifp), M_NETGRAPH_SPPP); ng_sppp_free_unit (priv->unit); kfree(priv, M_NETGRAPH_SPPP); NG_NODE_SET_PRIVATE (node, NULL);