Updated diff.
OpenBSD uses 16 bit counter for allocate interface indexes. So we can't
store index in session and be sure if_get(9) returned `ifnet' is our
original `ifnet'.
Now each pipex(4) session has it's own reference to `ifnet'. Also pppoe
related sessions has the reference to it's ethernet interface.
All `ifnet's are obtained by if_get(9) and we use `if_index' from stored
reference to `ifnet'.
Index: net/if_pppx.c
===================================================================
RCS file: /cvs/src/sys/net/if_pppx.c,v
retrieving revision 1.90
diff -u -p -r1.90 if_pppx.c
--- net/if_pppx.c 24 Jun 2020 08:52:53 -0000 1.90
+++ net/if_pppx.c 25 Jun 2020 16:41:25 -0000
@@ -714,15 +714,15 @@ 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);
NET_LOCK();
+ error = pipex_link_session(session, &pxi->pxi_ifcontext);
+ if (error)
+ goto detach;
+
if_addgroup(ifp, "pppx");
if_alloc_sadl(ifp);
@@ -771,7 +771,12 @@ pppx_add_session(struct pppx_dev *pxd, s
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);
@@ -860,13 +865,13 @@ pppx_if_destroy(struct pppx_dev *pxd, st
CLR(ifp->if_flags, IFF_RUNNING);
pipex_unlink_session(session);
+ pipex_rele_session(session);
/* XXXSMP breaks atomicity */
NET_UNLOCK();
if_detach(ifp);
NET_LOCK();
- pipex_rele_session(session);
if (RBT_REMOVE(pppx_ifs, &pppx_ifs, pxi) == NULL)
panic("%s: inconsistent RB tree", __func__);
LIST_REMOVE(pxi, pxi_list);
Index: net/pipex.c
===================================================================
RCS file: /cvs/src/sys/net/pipex.c,v
retrieving revision 1.116
diff -u -p -r1.116 pipex.c
--- net/pipex.c 22 Jun 2020 09:38:15 -0000 1.116
+++ net/pipex.c 25 Jun 2020 16:41:25 -0000
@@ -148,7 +148,7 @@ pipex_iface_init(struct pipex_iface_cont
struct pipex_session *session;
pipex_iface->pipexmode = 0;
- pipex_iface->ifnet_this = ifp;
+ pipex_iface->ifnet_this = if_get(ifp->if_index);
if (pipex_rd_head4 == NULL) {
if (!rn_inithead((void **)&pipex_rd_head4,
@@ -165,6 +165,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->ifnet_this = if_get(ifp->if_index);
pipex_iface->multicast_session = session;
}
@@ -194,10 +195,11 @@ pipex_iface_stop(struct pipex_iface_cont
void
pipex_iface_fini(struct pipex_iface_context *pipex_iface)
{
- pool_put(&pipex_session_pool, pipex_iface->multicast_session);
NET_LOCK();
pipex_iface_stop(pipex_iface);
NET_UNLOCK();
+ pipex_rele_session(pipex_iface->multicast_session);
+ if_put(pipex_iface->ifnet_this);
}
int
@@ -358,7 +360,7 @@ pipex_init_session(struct pipex_session
MIN(req->pr_local_address.ss_len, sizeof(session->local)));
#ifdef PIPEX_PPPOE
if (req->pr_protocol == PIPEX_PROTO_PPPOE)
- session->proto.pppoe.over_ifidx = over_ifp->if_index;
+ session->proto.pppoe.over_iface = if_get(over_ifp->if_index);
#endif
#ifdef PIPEX_PPTP
if (req->pr_protocol == PIPEX_PROTO_PPTP) {
@@ -421,6 +423,13 @@ pipex_init_session(struct pipex_session
void
pipex_rele_session(struct pipex_session *session)
{
+#ifdef PIPEX_PPPOE
+ if (session->protocol == PIPEX_PROTO_PPPOE)
+ if_put(session->proto.pppoe.over_iface);
+#endif
+ if (session->ifnet_this) {
+ if_put(session->ifnet_this);
+ }
if (session->mppe_recv.old_session_keys)
pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys);
pool_put(&pipex_session_pool, session);
@@ -439,6 +448,7 @@ pipex_link_session(struct pipex_session
return (EEXIST);
session->pipex_iface = iface;
+ session->ifnet_this = if_get(iface->ifnet_this->if_index);
LIST_INSERT_HEAD(&pipex_session_list, session, session_list);
chain = PIPEX_ID_HASHTABLE(session->session_id);
@@ -655,7 +665,7 @@ pipex_destroy_session(struct pipex_sessi
}
pipex_unlink_session(session);
- pool_put(&pipex_session_pool, session);
+ pipex_rele_session(session);
return (0);
}
@@ -919,7 +929,7 @@ pipex_ip_output(struct mbuf *m0, struct
struct ifnet *ifp;
/* output succeed here as a interface */
- ifp = session->pipex_iface->ifnet_this;
+ ifp = session->ifnet_this;
ifp->if_opackets++;
ifp->if_obytes+=m0->m_pkthdr.len;
@@ -1038,7 +1048,7 @@ pipex_ppp_input(struct mbuf *m0, struct
#if NBPFILTER > 0
{
- struct ifnet *ifp = session->pipex_iface->ifnet_this;
+ struct ifnet *ifp = session->ifnet_this;
if (ifp->if_bpf && ifp->if_type == IFT_PPP)
bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_IN);
}
@@ -1105,7 +1115,7 @@ pipex_ip_input(struct mbuf *m0, struct p
int is_idle;
/* change recvif */
- ifp = session->pipex_iface->ifnet_this;
+ ifp = session->ifnet_this;
m0->m_pkthdr.ph_ifidx = ifp->if_index;
if (ISSET(session->ppp_flags, PIPEX_PPP_INGRESS_FILTER)) {
@@ -1174,7 +1184,7 @@ pipex_ip6_input(struct mbuf *m0, struct
int len;
/* change recvif */
- ifp = session->pipex_iface->ifnet_this;
+ ifp = session->ifnet_this;
m0->m_pkthdr.ph_ifidx = ifp->if_index;
/*
@@ -1346,7 +1356,8 @@ pipex_pppoe_lookup_session(struct mbuf *
PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found (id=%d)",
__func__, pppoe.session_id));
#endif
- if (session && session->proto.pppoe.over_ifidx != m0->m_pkthdr.ph_ifidx)
+ if (session && session->proto.pppoe.over_iface->if_index !=
+ m0->m_pkthdr.ph_ifidx)
session = NULL;
return (session);
@@ -1407,19 +1418,12 @@ pipex_pppoe_output(struct mbuf *m0, stru
pppoe->session_id = htons(session->session_id);
pppoe->length = htons(len);
- m0->m_pkthdr.ph_ifidx = session->proto.pppoe.over_ifidx;
+ ifp = session->proto.pppoe.over_iface;
+ m0->m_pkthdr.ph_ifidx = ifp->if_index;
m0->m_flags &= ~(M_BCAST|M_MCAST);
-
- ifp = if_get(session->proto.pppoe.over_ifidx);
- if (ifp != NULL) {
- ifp->if_output(ifp, m0, &session->peer.sa, NULL);
- session->stat.opackets++;
- session->stat.obytes += len;
- } else {
- m_freem(m0);
- session->stat.oerrors++;
- }
- if_put(ifp);
+ ifp->if_output(ifp, m0, &session->peer.sa, NULL);
+ session->stat.opackets++;
+ session->stat.obytes += len;
}
#endif /* PIPEX_PPPOE */
Index: net/pipex_local.h
===================================================================
RCS file: /cvs/src/sys/net/pipex_local.h,v
retrieving revision 1.35
diff -u -p -r1.35 pipex_local.h
--- net/pipex_local.h 18 Jun 2020 14:20:12 -0000 1.35
+++ net/pipex_local.h 25 Jun 2020 16:41:25 -0000
@@ -78,7 +78,7 @@ struct pipex_mppe {
#ifdef PIPEX_PPPOE
struct pipex_pppoe_session {
- u_int over_ifidx; /* [I] ether interface */
+ struct ifnet *over_iface; /* [I] ether interface */
};
#endif /* PIPEX_PPPOE */
@@ -183,6 +183,7 @@ struct pipex_session {
int ip6_prefixlen; /* [I] remote IPv6 prefixlen */
struct pipex_iface_context* pipex_iface; /* [I] context for interface */
+ struct ifnet *ifnet_this; /* [k] outer interface */
uint32_t ppp_flags; /* [I] configure flags */
#ifdef PIPEX_MPPE