Interface index 0 is never associated with interface descriptor. So
we can assign this value to session's interface index before destroy
corresponding `ifnet'. It's safe to use indexes instead of pointers to
`ifnet' in pipex(4).

Index: sys/net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.96
diff -u -p -r1.96 if_pppx.c
--- sys/net/if_pppx.c   15 Jul 2020 13:02:44 -0000      1.96
+++ sys/net/if_pppx.c   16 Jul 2020 11:19:21 -0000
@@ -652,9 +652,6 @@ pppx_add_session(struct pppx_dev *pxd, s
        ifp = &pxi->pxi_if;
 
        pxi->pxi_session = session;
-       /* fake a pipex interface context */
-       pxi->pxi_ifcontext.ifnet_this = ifp;
-       pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED;
 
        /* try to set the interface up */
        unit = pppx_if_next_unit();
@@ -687,10 +684,6 @@ pppx_add_session(struct pppx_dev *pxd, s
        ifp->if_softc = pxi;
        /* ifp->if_rdomain = req->pr_rdomain; */
 
-       error = pipex_link_session(session, &pxi->pxi_ifcontext);
-       if (error)
-               goto remove;
-
        /* XXXSMP breaks atomicity */
        NET_UNLOCK();
        if_attach(ifp);
@@ -702,7 +695,6 @@ pppx_add_session(struct pppx_dev *pxd, s
 #if NBPFILTER > 0
        bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(u_int32_t));
 #endif
-       SET(ifp->if_flags, IFF_RUNNING);
 
        /* XXX ipv6 support?  how does the caller indicate it wants ipv6
         * instead of ipv4?
@@ -740,11 +732,26 @@ pppx_add_session(struct pppx_dev *pxd, s
        } else {
                if_addrhooks_run(ifp);
        }
+
+       /* fake a pipex interface context */
+       pxi->pxi_ifcontext.ifindex = ifp->if_index;
+       pxi->pxi_ifcontext.pipexmode = PIPEX_ENABLED;
+
+       error = pipex_link_session(session, &pxi->pxi_ifcontext);
+       if (error)
+               goto detach;
+
+       SET(ifp->if_flags, IFF_RUNNING);
        pxi->pxi_ready = 1;
 
        return (error);
 
-remove:
+detach:
+       /* XXXSMP breaks atomicity */
+       NET_UNLOCK();
+       if_detach(ifp);
+       NET_LOCK();
+
        if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL)
                panic("%s: inconsistent RB tree", __func__);
        LIST_REMOVE(pxi, pxi_list);
@@ -1100,7 +1107,7 @@ pppacopen(dev_t dev, int flags, int mode
        bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t));
 #endif
 
-       pipex_iface_init(&sc->sc_pipex_iface, ifp);
+       pipex_iface_init(&sc->sc_pipex_iface, ifp->if_index);
 
        return (0);
 }
Index: sys/net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.119
diff -u -p -r1.119 pipex.c
--- sys/net/pipex.c     6 Jul 2020 20:37:51 -0000       1.119
+++ sys/net/pipex.c     16 Jul 2020 11:19:21 -0000
@@ -140,12 +140,12 @@ pipex_init(void)
 }
 
 void
-pipex_iface_init(struct pipex_iface_context *pipex_iface, struct ifnet *ifp)
+pipex_iface_init(struct pipex_iface_context *pipex_iface, int ifindex)
 {
        struct pipex_session *session;
 
        pipex_iface->pipexmode = 0;
-       pipex_iface->ifnet_this = ifp;
+       pipex_iface->ifindex = ifindex;
 
        if (pipex_rd_head4 == NULL) {
                if (!rn_inithead((void **)&pipex_rd_head4,
@@ -162,6 +162,7 @@ pipex_iface_init(struct pipex_iface_cont
        session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO);
        session->is_multicast = 1;
        session->pipex_iface = pipex_iface;
+       session->ifindex = ifindex;
        pipex_iface->multicast_session = session;
 }
 
@@ -436,6 +437,7 @@ pipex_link_session(struct pipex_session 
                return (EEXIST);
 
        session->pipex_iface = iface;
+       session->ifindex = iface->ifindex;
 
        LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
        chain = PIPEX_ID_HASHTABLE(session->session_id);
@@ -461,6 +463,8 @@ pipex_link_session(struct pipex_session 
 void
 pipex_unlink_session(struct pipex_session *session)
 {
+       session->ifindex = 0;
+
        LIST_REMOVE(session, id_chain);
 #if defined(PIPEX_PPTP) || defined(PIPEX_L2TP)
        switch (session->protocol) {
@@ -916,10 +920,12 @@ pipex_ip_output(struct mbuf *m0, struct 
        int is_idle;
        struct ifnet *ifp;
 
-       /* output succeed here as a interface */
-       ifp = session->pipex_iface->ifnet_this;
-       ifp->if_opackets++;
-       ifp->if_obytes+=m0->m_pkthdr.len;
+       if ((ifp = if_get(session->ifindex)) != NULL) {
+               /* output succeed here as a interface */
+               ifp->if_opackets++;
+               ifp->if_obytes+=m0->m_pkthdr.len;
+       }
+       if_put(ifp);
 
        if (session->is_multicast == 0) {
                /*
@@ -1038,9 +1044,13 @@ pipex_ppp_input(struct mbuf *m0, struct 
 
 #if NBPFILTER > 0
            {
-               struct ifnet *ifp = session->pipex_iface->ifnet_this;
-               if (ifp->if_bpf && ifp->if_type == IFT_PPP)
-                       bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
+               struct ifnet *ifp;
+               
+               if ((ifp = if_get(session->ifindex)) != NULL) {
+                       if (ifp->if_bpf && ifp->if_type == IFT_PPP)
+                               bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
+               }
+               if_put(ifp);
            }
 #endif
                m_adj(m0, hlen);
@@ -1105,8 +1115,7 @@ pipex_ip_input(struct mbuf *m0, struct p
        int is_idle;
 
        /* change recvif */
-       ifp = session->pipex_iface->ifnet_this;
-       m0->m_pkthdr.ph_ifidx = ifp->if_index;
+       m0->m_pkthdr.ph_ifidx = session->ifindex;
 
        if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) {
                PIPEX_PULLUP(m0, sizeof(struct ip));
@@ -1149,6 +1158,9 @@ pipex_ip_input(struct mbuf *m0, struct p
 
        len = m0->m_pkthdr.len;
 
+       if ((ifp = if_get(session->ifindex)) == NULL)
+               goto drop;
+
 #if NBPFILTER > 0
        if (ifp->if_bpf)
                bpf_mtap_af(ifp->if_bpf, AF_INET, m0, BPF_DIRECTION_IN);
@@ -1160,6 +1172,8 @@ pipex_ip_input(struct mbuf *m0, struct p
        session->stat.ibytes += len;
        ipv4_input(ifp, m0);
 
+       if_put(ifp);
+
        return;
 drop:
        m_freem(m0);
@@ -1174,8 +1188,7 @@ pipex_ip6_input(struct mbuf *m0, struct 
        int len;
 
        /* change recvif */
-       ifp = session->pipex_iface->ifnet_this;
-       m0->m_pkthdr.ph_ifidx = ifp->if_index;
+       m0->m_pkthdr.ph_ifidx = session->ifindex;
 
        /*
         * XXX: what is reasonable ingress filter ???
@@ -1195,6 +1208,9 @@ pipex_ip6_input(struct mbuf *m0, struct 
 
        len = m0->m_pkthdr.len;
 
+       if ((ifp = if_get(session->ifindex)) == NULL)
+               goto drop;
+
 #if NBPFILTER > 0
        if (ifp->if_bpf)
                bpf_mtap_af(ifp->if_bpf, AF_INET6, m0, BPF_DIRECTION_IN);
@@ -1205,6 +1221,13 @@ pipex_ip6_input(struct mbuf *m0, struct 
        session->stat.ipackets++;
        session->stat.ibytes += len;
        ipv6_input(ifp, m0);
+
+       if_put(ifp);
+
+       return;
+drop:
+       m_freem(m0);
+       session->stat.ierrors++;
 }
 #endif
 
@@ -1498,7 +1521,7 @@ pipex_pptp_output(struct mbuf *m0, struc
        }
        gre->flags = htons(gre->flags);
 
-       m0->m_pkthdr.ph_ifidx = session->pipex_iface->ifnet_this->if_index;
+       m0->m_pkthdr.ph_ifidx = session->ifindex;
        ip_send(m0);
        if (len > 0) {  /* network layer only */
                /* countup statistics */
@@ -1930,7 +1953,7 @@ pipex_l2tp_output(struct mbuf *m0, struc
        udp->uh_sum = 0;
 
        m0->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
-       m0->m_pkthdr.ph_ifidx = session->pipex_iface->ifnet_this->if_index;
+       m0->m_pkthdr.ph_ifidx = session->ifindex;
 #if NPF > 0
        pf_pkt_addr_changed(m0);
 #endif
@@ -2949,12 +2972,17 @@ pipex_session_log(struct pipex_session *
 
        logpri(prio);
        if (session != NULL) {
+               struct ifnet *ifp;
+
+               ifp = if_get(session->ifindex);
                addlog("pipex: ppp=%d iface=%s protocol=%s id=%d ",
-                   session->ppp_id, session->pipex_iface->ifnet_this->if_xname,
+                   session->ppp_id,
+                   ifp? ifp->if_xname : "Unknown",
                    (session->protocol == PIPEX_PROTO_PPPOE)? "PPPoE" :
                    (session->protocol == PIPEX_PROTO_PPTP)? "PPTP" :
                    (session->protocol == PIPEX_PROTO_L2TP) ? "L2TP" :
                    "Unknown", session->session_id);
+               if_put(ifp);
        } else
                addlog("pipex: ");
 
Index: sys/net/pipex.h
===================================================================
RCS file: /cvs/src/sys/net/pipex.h,v
retrieving revision 1.24
diff -u -p -r1.24 pipex.h
--- sys/net/pipex.h     6 Jul 2020 20:37:51 -0000       1.24
+++ sys/net/pipex.h     16 Jul 2020 11:19:21 -0000
@@ -190,7 +190,7 @@ struct pipex_session;
  *      N       net lock
  */
 struct pipex_iface_context {
-       struct  ifnet *ifnet_this;      /* [I] outer interface */
+       int     ifindex;                /* [I] outer interface index */
        u_int   pipexmode;              /* [N] pipex mode */
        /* [I] virtual pipex_session entry for multicast routing */
        struct pipex_session *multicast_session;
@@ -198,7 +198,7 @@ struct pipex_iface_context {
 
 __BEGIN_DECLS
 void                  pipex_init (void);
-void                  pipex_iface_init (struct pipex_iface_context *, struct 
ifnet *);
+void                  pipex_iface_init (struct pipex_iface_context *, int);
 void                  pipex_iface_fini (struct pipex_iface_context *);
 
 int                   pipex_notify_close_session(struct pipex_session 
*session);
Index: sys/net/pipex_local.h
===================================================================
RCS file: /cvs/src/sys/net/pipex_local.h,v
retrieving revision 1.36
diff -u -p -r1.36 pipex_local.h
--- sys/net/pipex_local.h       6 Jul 2020 20:37:51 -0000       1.36
+++ sys/net/pipex_local.h       16 Jul 2020 11:19:21 -0000
@@ -183,6 +183,7 @@ struct pipex_session {
        int             ip6_prefixlen;   /* [I] remote IPv6 prefixlen */
 
        struct pipex_iface_context* pipex_iface; /* [N] context for interface */
+       int             ifindex;                /* [N] interface index */
 
        uint32_t        ppp_flags;              /* [I] configure flags */
 #ifdef PIPEX_MPPE

Reply via email to