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