From f6e6f8e73459654c7f56d30d63f5c188622ec57b Mon Sep 17 00:00:00 2001 From: mvs Date: Sun, 26 Jun 2022 15:50:21 +0000 Subject: [PATCH] The "ifq_set_maxlen(..., 1);" hack we use to enforce pipex(4) related (*if_qstart)() be always called with netlock held doesn't work anymore with PPPOE sessions. Introduce `pipex_list_mtx' mutex(9) and use it to protect global pipex(4) lists and radix trees. Protect pipex(4) `session' dereference with reference counters, because we could sleep when accessing pipex(4) from ioctl(2) path, and this is not possible with mutex(9) held. ok bluhm@ --- sys/net/if_ethersubr.c | 4 +- sys/net/if_gre.c | 14 ++- sys/net/if_pppx.c | 17 ++-- sys/net/pipex.c | 194 ++++++++++++++++++++++++++++++--------- sys/net/pipex.h | 3 +- sys/net/pipex_local.h | 32 ++++--- sys/netinet/ip_gre.c | 18 ++-- sys/netinet/udp_usrreq.c | 21 +++-- 8 files changed, 222 insertions(+), 81 deletions(-) diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 45dbd6c4d2d..b460036bc0e 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.279 2022/04/22 12:10:57 bluhm Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.280 2022/06/26 15:50:21 mvs Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -547,9 +547,11 @@ ether_input(struct ifnet *ifp, struct mbuf *m) if ((session = pipex_pppoe_lookup_session(m)) != NULL) { pipex_pppoe_input(m, session); + pipex_rele_session(session); KERNEL_UNLOCK(); return; } + pipex_rele_session(session); } #endif if (etype == ETHERTYPE_PPPOEDISC) diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index d2f6524dd26..40441489b75 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_gre.c,v 1.171 2021/03/10 10:21:47 jsg Exp $ */ +/* $OpenBSD: if_gre.c,v 1.172 2022/06/26 15:50:21 mvs Exp $ */ /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -974,9 +974,15 @@ gre_input_1(struct gre_tunnel *key, struct mbuf *m, struct pipex_session *session; session = pipex_pptp_lookup_session(m); - if (session != NULL && - pipex_pptp_input(m, session) == NULL) - return (NULL); + if (session != NULL) { + struct mbuf *m0; + + m0 = pipex_pptp_input(m, session); + pipex_rele_session(session); + + if (m0 == NULL) + return (NULL); + } } #endif break; diff --git a/sys/net/if_pppx.c b/sys/net/if_pppx.c index 36aa942222c..0aaaedc038f 100644 --- a/sys/net/if_pppx.c +++ b/sys/net/if_pppx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pppx.c,v 1.115 2022/06/26 13:14:37 mvs Exp $ */ +/* $OpenBSD: if_pppx.c,v 1.116 2022/06/26 15:50:21 mvs Exp $ */ /* * Copyright (c) 2010 Claudio Jeker @@ -1322,9 +1322,7 @@ pppacclose(dev_t dev, int flags, int mode, struct proc *p) splx(s); pool_put(&pipex_session_pool, sc->sc_multicast_session); - NET_LOCK(); pipex_destroy_all_sessions(sc); - NET_UNLOCK(); LIST_REMOVE(sc, sc_entry); free(sc, M_DEVBUF, sizeof(*sc)); @@ -1384,13 +1382,19 @@ pppac_del_session(struct pppac_softc *sc, struct pipex_session_close_req *req) { struct pipex_session *session; - session = pipex_lookup_by_session_id(req->pcr_protocol, + mtx_enter(&pipex_list_mtx); + + session = pipex_lookup_by_session_id_locked(req->pcr_protocol, req->pcr_session_id); - if (session == NULL || session->ownersc != sc) + if (session == NULL || session->ownersc != sc) { + mtx_leave(&pipex_list_mtx); return (EINVAL); - pipex_unlink_session(session); + } + pipex_unlink_session_locked(session); pipex_rele_session(session); + mtx_leave(&pipex_list_mtx); + return (0); } @@ -1461,6 +1465,7 @@ pppac_qstart(struct ifqueue *ifq) session = pipex_lookup_by_ip_address(ip.ip_dst); if (session != NULL) { pipex_ip_output(m, session); + pipex_rele_session(session); m = NULL; } } diff --git a/sys/net/pipex.c b/sys/net/pipex.c index 66737529b1b..cef23c856da 100644 --- a/sys/net/pipex.c +++ b/sys/net/pipex.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex.c,v 1.137 2022/06/26 13:14:37 mvs Exp $ */ +/* $OpenBSD: pipex.c,v 1.138 2022/06/26 15:50:21 mvs Exp $ */ /*- * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -79,6 +80,8 @@ #include #include "pipex_local.h" +struct mutex pipex_list_mtx = MUTEX_INITIALIZER(IPL_SOFTNET); + struct pool pipex_session_pool; struct pool mppe_key_pool; @@ -88,17 +91,18 @@ struct pool mppe_key_pool; * A atomic operation * I immutable after creation * N net lock + * L pipex_list_mtx */ int pipex_enable = 0; /* [N] */ struct pipex_hash_head - pipex_session_list, /* [N] master session list */ - pipex_close_wait_list, /* [N] expired session list */ - pipex_peer_addr_hashtable[PIPEX_HASH_SIZE], /* [N] peer's address hash */ - pipex_id_hashtable[PIPEX_HASH_SIZE]; /* [N] peer id hash */ + pipex_session_list, /* [L] master session list */ + pipex_close_wait_list, /* [L] expired session list */ + pipex_peer_addr_hashtable[PIPEX_HASH_SIZE], /* [L] peer's address hash */ + pipex_id_hashtable[PIPEX_HASH_SIZE]; /* [L] peer id hash */ -struct radix_node_head *pipex_rd_head4 = NULL; /* [N] */ -struct radix_node_head *pipex_rd_head6 = NULL; /* [N] */ +struct radix_node_head *pipex_rd_head4 = NULL; /* [L] */ +struct radix_node_head *pipex_rd_head6 = NULL; /* [L] */ struct timeout pipex_timer_ch; /* callout timer context */ int pipex_prune = 1; /* [I] walk list every seconds */ @@ -145,16 +149,18 @@ pipex_destroy_all_sessions(void *ownersc) { struct pipex_session *session, *session_tmp; - NET_ASSERT_LOCKED(); + mtx_enter(&pipex_list_mtx); LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { if (session->ownersc == ownersc) { KASSERT((session->flags & PIPEX_SFLAGS_PPPX) == 0); - pipex_unlink_session(session); + pipex_unlink_session_locked(session); pipex_rele_session(session); } } + + mtx_leave(&pipex_list_mtx); } int @@ -263,6 +269,7 @@ pipex_init_session(struct pipex_session **rsession, /* prepare a new session */ session = pool_get(&pipex_session_pool, PR_WAITOK | PR_ZERO); + refcnt_init(&session->pxs_refcnt); mtx_init(&session->pxs_mtx, IPL_SOFTNET); session->state = PIPEX_STATE_INITIAL; session->protocol = req->pr_protocol; @@ -363,6 +370,9 @@ pipex_init_session(struct pipex_session **rsession, void pipex_rele_session(struct pipex_session *session) { + if (refcnt_rele(&session->pxs_refcnt) == 0) + return; + if (session->mppe_recv.old_session_keys) pool_put(&mppe_key_pool, session->mppe_recv.old_session_keys); counters_free(session->stat_counters, pxc_ncounters); @@ -375,8 +385,9 @@ pipex_link_session(struct pipex_session *session, struct ifnet *ifp, { struct pipex_hash_head *chain; struct radix_node *rn; + int error = 0; - NET_ASSERT_LOCKED(); + mtx_enter(&pipex_list_mtx); if (pipex_rd_head4 == NULL) { if (!rn_inithead((void **)&pipex_rd_head4, @@ -388,9 +399,11 @@ pipex_link_session(struct pipex_session *session, struct ifnet *ifp, offsetof(struct sockaddr_in6, sin6_addr))) panic("rn_inithead() failed on pipex_link_session()"); } - if (pipex_lookup_by_session_id(session->protocol, - session->session_id)) - return (EEXIST); + if (pipex_lookup_by_session_id_locked(session->protocol, + session->session_id)) { + error = EEXIST; + goto out; + } session->ownersc = ownersc; session->ifindex = ifp->if_index; @@ -399,13 +412,17 @@ pipex_link_session(struct pipex_session *session, struct ifnet *ifp, if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 && !in_nullhost(session->ip_address.sin_addr)) { - if (pipex_lookup_by_ip_address(session->ip_address.sin_addr) - != NULL) - return (EADDRINUSE); + if (pipex_lookup_by_ip_address_locked( + session->ip_address.sin_addr) != NULL) { + error = EADDRINUSE; + goto out; + } rn = rn_addroute(&session->ip_address, &session->ip_netmask, pipex_rd_head4, session->ps4_rn, RTP_STATIC); - if (rn == NULL) - return (ENOMEM); + if (rn == NULL) { + error = ENOMEM; + goto out; + } } LIST_INSERT_HEAD(&pipex_session_list, session, session_list); @@ -426,17 +443,21 @@ pipex_link_session(struct pipex_session *session, struct ifnet *ifp, pipex_timer_start(); session->state = PIPEX_STATE_OPENED; - return (0); +out: + mtx_leave(&pipex_list_mtx); + + return error; } void -pipex_unlink_session(struct pipex_session *session) +pipex_unlink_session_locked(struct pipex_session *session) { struct radix_node *rn; + MUTEX_ASSERT_LOCKED(&pipex_list_mtx); + session->ifindex = 0; - NET_ASSERT_LOCKED(); if (session->state == PIPEX_STATE_CLOSED) return; if ((session->flags & PIPEX_SFLAGS_PPPX) == 0 && @@ -466,10 +487,19 @@ pipex_unlink_session(struct pipex_session *session) pipex_timer_stop(); } +void +pipex_unlink_session(struct pipex_session *session) +{ + mtx_enter(&pipex_list_mtx); + pipex_unlink_session_locked(session); + mtx_leave(&pipex_list_mtx); +} + int pipex_notify_close_session(struct pipex_session *session) { - NET_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&pipex_list_mtx); + session->state = PIPEX_STATE_CLOSE_WAIT; session->idle_time = 0; LIST_INSERT_HEAD(&pipex_close_wait_list, session, state_list); @@ -499,38 +529,49 @@ Static int pipex_config_session(struct pipex_session_config_req *req, void *ownersc) { struct pipex_session *session; + int error = 0; NET_ASSERT_LOCKED(); + session = pipex_lookup_by_session_id(req->pcr_protocol, req->pcr_session_id); if (session == NULL) return (EINVAL); - if (session->ownersc != ownersc) - return (EINVAL); - if (req->pcr_ip_forward != 0) - session->flags |= PIPEX_SFLAGS_IP_FORWARD; - else - session->flags &= ~PIPEX_SFLAGS_IP_FORWARD; + if (session->ownersc == ownersc) { + if (req->pcr_ip_forward != 0) + session->flags |= PIPEX_SFLAGS_IP_FORWARD; + else + session->flags &= ~PIPEX_SFLAGS_IP_FORWARD; + } else + error = EINVAL; - return (0); + pipex_rele_session(session); + + return error; } Static int pipex_get_stat(struct pipex_session_stat_req *req, void *ownersc) { struct pipex_session *session; + int error = 0; NET_ASSERT_LOCKED(); + session = pipex_lookup_by_session_id(req->psr_protocol, req->psr_session_id); if (session == NULL) return (EINVAL); - if (session->ownersc != ownersc) - return (EINVAL); - pipex_export_session_stats(session, &req->psr_stat); - return (0); + if (session->ownersc == ownersc) + pipex_export_session_stats(session, &req->psr_stat); + else + error = EINVAL; + + pipex_rele_session(session); + + return error; } Static int @@ -538,8 +579,10 @@ pipex_get_closed(struct pipex_session_list_req *req, void *ownersc) { struct pipex_session *session, *session_tmp; - NET_ASSERT_LOCKED(); bzero(req, sizeof(*req)); + + mtx_enter(&pipex_list_mtx); + LIST_FOREACH_SAFE(session, &pipex_close_wait_list, state_list, session_tmp) { if (session->ownersc != ownersc) @@ -554,15 +597,19 @@ pipex_get_closed(struct pipex_session_list_req *req, void *ownersc) } } + mtx_leave(&pipex_list_mtx); + return (0); } Static struct pipex_session * -pipex_lookup_by_ip_address(struct in_addr addr) +pipex_lookup_by_ip_address_locked(struct in_addr addr) { struct pipex_session *session; struct sockaddr_in pipex_in4, pipex_in4mask; + MUTEX_ASSERT_LOCKED(&pipex_list_mtx); + if (pipex_rd_head4 == NULL) return (NULL); bzero(&pipex_in4, sizeof(pipex_in4)); @@ -590,13 +637,31 @@ pipex_lookup_by_ip_address(struct in_addr addr) return (session); } +struct pipex_session * +pipex_lookup_by_ip_address(struct in_addr addr) +{ + struct pipex_session *session; + + mtx_enter(&pipex_list_mtx); + + session = pipex_lookup_by_ip_address_locked(addr); + if (session != NULL) + refcnt_take(&session->pxs_refcnt); + + mtx_leave(&pipex_list_mtx); + + return (session); +} + + Static struct pipex_session * -pipex_lookup_by_session_id(int protocol, int session_id) +pipex_lookup_by_session_id_locked(int protocol, int session_id) { struct pipex_hash_head *list; struct pipex_session *session; - NET_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&pipex_list_mtx); + list = PIPEX_ID_HASHTABLE(session_id); LIST_FOREACH(session, list, id_chain) { if (session->protocol == protocol && @@ -614,6 +679,22 @@ pipex_lookup_by_session_id(int protocol, int session_id) return (session); } +struct pipex_session * +pipex_lookup_by_session_id(int protocol, int session_id) +{ + struct pipex_session *session; + + mtx_enter(&pipex_list_mtx); + + session = pipex_lookup_by_session_id_locked(protocol, session_id); + if (session != NULL) + refcnt_take(&session->pxs_refcnt); + + mtx_leave(&pipex_list_mtx); + + return (session); +} + /*********************************************************************** * Timer functions ***********************************************************************/ @@ -637,7 +718,7 @@ pipex_timer(void *ignored_arg) timeout_add_sec(&pipex_timer_ch, pipex_prune); - NET_LOCK(); + mtx_enter(&pipex_list_mtx); /* walk through */ LIST_FOREACH_SAFE(session, &pipex_session_list, session_list, session_tmp) { @@ -660,7 +741,7 @@ pipex_timer(void *ignored_arg) if (session->idle_time < PIPEX_CLOSE_TIMEOUT) continue; /* Release the sessions when timeout */ - pipex_unlink_session(session); + pipex_unlink_session_locked(session); KASSERTMSG((session->flags & PIPEX_SFLAGS_PPPX) == 0, "FIXME session must not be released when pppx"); pipex_rele_session(session); @@ -671,7 +752,7 @@ pipex_timer(void *ignored_arg) } } - NET_UNLOCK(); + mtx_leave(&pipex_list_mtx); } /*********************************************************************** @@ -695,9 +776,12 @@ pipex_ip_output(struct mbuf *m0, struct pipex_session *session) m0 = ip_is_idle_packet(m0, &is_idle); if (m0 == NULL) goto dropped; - if (is_idle == 0) + if (is_idle == 0) { + mtx_enter(&pipex_list_mtx); /* update expire time */ session->idle_time = 0; + mtx_leave(&pipex_list_mtx); + } } /* adjust tcpmss */ @@ -914,9 +998,12 @@ pipex_ip_input(struct mbuf *m0, struct pipex_session *session) m0 = ip_is_idle_packet(m0, &is_idle); if (m0 == NULL) goto drop; - if (is_idle == 0) + if (is_idle == 0) { /* update expire time */ + mtx_enter(&pipex_list_mtx); session->idle_time = 0; + mtx_leave(&pipex_list_mtx); + } } /* adjust tcpmss */ @@ -1132,8 +1219,11 @@ pipex_pppoe_lookup_session(struct mbuf *m0) 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_ifidx != + m0->m_pkthdr.ph_ifidx) { + pipex_rele_session(session); session = NULL; + } return (session); } @@ -1144,7 +1234,6 @@ pipex_pppoe_input(struct mbuf *m0, struct pipex_session *session) int hlen; struct pipex_pppoe_header pppoe; - NET_ASSERT_LOCKED(); /* already checked at pipex_pppoe_lookup_session */ KASSERT(m0->m_pkthdr.len >= (sizeof(struct ether_header) + sizeof(pppoe))); @@ -1568,6 +1657,8 @@ pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) /* lookup pipex session table */ id = ntohs(gre.call_id); + mtx_enter(&pipex_list_mtx); + list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa)); LIST_FOREACH(session, list, peer_addr_chain) { if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0) @@ -1575,6 +1666,12 @@ pipex_pptp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) if (session->peer_session_id == id) break; } + + if (session != NULL) + refcnt_take(&session->pxs_refcnt); + + mtx_leave(&pipex_list_mtx); + #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, @@ -1834,6 +1931,7 @@ pipex_l2tp_input(struct mbuf *m0, int off0, struct pipex_session *session, int rewind = 0; NET_ASSERT_LOCKED(); + length = offset = ns = nr = 0; l2tp_session = &session->proto.l2tp; l2tp_session->ipsecflowinfo = ipsecflowinfo; @@ -2010,6 +2108,8 @@ pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) session_id = ntohs(l2tp.session_id); tunnel_id = ntohs(l2tp.tunnel_id); + mtx_enter(&pipex_list_mtx); + list = PIPEX_PEER_ADDR_HASHTABLE(pipex_sockaddr_hash_key(sa)); LIST_FOREACH(session, list, peer_addr_chain) { if (pipex_sockaddr_compar_addr(&session->peer.sa, sa) != 0) @@ -2019,6 +2119,12 @@ pipex_l2tp_userland_lookup_session(struct mbuf *m0, struct sockaddr *sa) if (session->peer_session_id == session_id) break; } + + if (session != NULL) + refcnt_take(&session->pxs_refcnt); + + mtx_leave(&pipex_list_mtx); + #ifdef PIPEX_DEBUG if (session == NULL) { PIPEX_DBG((NULL, LOG_DEBUG, "<%s> session not found " diff --git a/sys/net/pipex.h b/sys/net/pipex.h index a71f914826e..1f15f6bf8c9 100644 --- a/sys/net/pipex.h +++ b/sys/net/pipex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex.h,v 1.31 2022/01/02 22:36:04 jsg Exp $ */ +/* $OpenBSD: pipex.h,v 1.32 2022/06/26 15:50:21 mvs Exp $ */ /* * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -193,6 +193,7 @@ struct mbuf *pipex_l2tp_input (struct mbuf *, int off, struct pipex_se struct pipex_session *pipex_l2tp_userland_lookup_session_ipv4 (struct mbuf *, struct in_addr); struct pipex_session *pipex_l2tp_userland_lookup_session_ipv6 (struct mbuf *, struct in6_addr); struct mbuf *pipex_l2tp_userland_output (struct mbuf *, struct pipex_session *); +void pipex_rele_session(struct pipex_session *); int pipex_ioctl (void *, u_long, caddr_t); void pipex_session_init_mppe_recv(struct pipex_session *, int, int, u_char *); diff --git a/sys/net/pipex_local.h b/sys/net/pipex_local.h index 7431f44487c..8959e21759d 100644 --- a/sys/net/pipex_local.h +++ b/sys/net/pipex_local.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pipex_local.h,v 1.46 2022/06/26 13:14:37 mvs Exp $ */ +/* $OpenBSD: pipex_local.h,v 1.47 2022/06/26 15:50:21 mvs Exp $ */ /* * Copyright (c) 2009 Internet Initiative Japan Inc. @@ -26,6 +26,11 @@ * SUCH DAMAGE. */ +#include +#include + +extern struct mutex pipex_list_mtx; + #define PIPEX_PPTP 1 #define PIPEX_L2TP 1 #define PIPEX_PPPOE 1 @@ -53,6 +58,7 @@ * Locks used to protect struct members: * I immutable after creation * N net lock + * L pipex_list_mtx * s this pipex_session' `pxs_mtx' * m this pipex_mppe' `pxm_mtx' */ @@ -153,26 +159,28 @@ struct cpumem; /* pppac ip-extension session table */ struct pipex_session { struct radix_node ps4_rn[2]; - /* [N] tree glue, and other values */ + /* [L] tree glue, and other values */ struct radix_node ps6_rn[2]; - /* [N] tree glue, and other values */ + /* [L] tree glue, and other values */ + + struct refcnt pxs_refcnt; struct mutex pxs_mtx; - LIST_ENTRY(pipex_session) session_list; /* [N] all session chain */ - LIST_ENTRY(pipex_session) state_list; /* [N] state list chain */ - LIST_ENTRY(pipex_session) id_chain; /* [N] id hash chain */ + LIST_ENTRY(pipex_session) session_list; /* [L] all session chain */ + LIST_ENTRY(pipex_session) state_list; /* [L] state list chain */ + LIST_ENTRY(pipex_session) id_chain; /* [L] id hash chain */ LIST_ENTRY(pipex_session) peer_addr_chain; - /* [N] peer's address hash chain */ - uint16_t state; /* [N] pipex session state */ + /* [L] peer's address hash chain */ + u_int state; /* [L] pipex session state */ #define PIPEX_STATE_INITIAL 0x0000 #define PIPEX_STATE_OPENED 0x0001 #define PIPEX_STATE_CLOSE_WAIT 0x0002 #define PIPEX_STATE_CLOSE_WAIT2 0x0003 #define PIPEX_STATE_CLOSED 0x0004 - uint32_t idle_time; /* [N] idle time in seconds */ + uint32_t idle_time; /* [L] idle time in seconds */ - u_int flags; /* [N] flags, see below */ + u_int flags; /* [N] flags, see below */ #define PIPEX_SFLAGS_IP_FORWARD 0x01 /* [N] enable IP forwarding */ #define PIPEX_SFLAGS_IP6_FORWARD 0x02 /* [N] enable IPv6 forwarding */ #define PIPEX_SFLAGS_MULTICAST 0x04 /* [I] virtual entry for @@ -401,10 +409,10 @@ extern struct pool pipex_session_pool; void pipex_destroy_all_sessions (void *); int pipex_init_session(struct pipex_session **, struct pipex_session_req *); -void pipex_rele_session(struct pipex_session *); int pipex_link_session(struct pipex_session *, struct ifnet *, void *); void pipex_unlink_session(struct pipex_session *); +void pipex_unlink_session_locked(struct pipex_session *); void pipex_export_session_stats(struct pipex_session *, struct pipex_statistics *); int pipex_config_session (struct pipex_session_config_req *, @@ -413,7 +421,9 @@ int pipex_get_stat (struct pipex_session_stat_req *, void *); int pipex_get_closed (struct pipex_session_list_req *, void *); +struct pipex_session *pipex_lookup_by_ip_address_locked (struct in_addr); struct pipex_session *pipex_lookup_by_ip_address (struct in_addr); +struct pipex_session *pipex_lookup_by_session_id_locked (int, int); struct pipex_session *pipex_lookup_by_session_id (int, int); void pipex_ip_output (struct mbuf *, struct pipex_session *); void pipex_ppp_output (struct mbuf *, struct pipex_session *, int); diff --git a/sys/netinet/ip_gre.c b/sys/netinet/ip_gre.c index eb68cb0b752..3e630221a18 100644 --- a/sys/netinet/ip_gre.c +++ b/sys/netinet/ip_gre.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_gre.c,v 1.73 2022/02/25 23:51:03 guenther Exp $ */ +/* $OpenBSD: ip_gre.c,v 1.74 2022/06/26 15:50:21 mvs Exp $ */ /* $NetBSD: ip_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */ /* @@ -70,7 +70,6 @@ gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, if (inp != NULL && inp->inp_pipex && req == PRU_SEND) { struct sockaddr_in *sin4; struct in_addr *ina_dst; - struct pipex_session *session; ina_dst = NULL; if ((so->so_state & SS_ISCONNECTED) != 0) { @@ -81,10 +80,17 @@ gre_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam, if (in_nam2sin(nam, &sin4) == 0) ina_dst = &sin4->sin_addr; } - if (ina_dst != NULL && - (session = pipex_pptp_userland_lookup_session_ipv4(m, - *ina_dst))) - m = pipex_pptp_userland_output(m, session); + if (ina_dst != NULL) { + struct pipex_session *session; + + session = pipex_pptp_userland_lookup_session_ipv4(m, + *ina_dst); + + if(session != NULL) { + m = pipex_pptp_userland_output(m, session); + pipex_rele_session(session); + } + } if (m == NULL) return (ENOMEM); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 84592f9afb9..d0ef04a2b54 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.278 2022/05/15 09:12:20 dlg Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.279 2022/06/26 15:50:21 mvs Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -565,12 +565,14 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af) if (pipex_enable && inp->inp_pipex) { struct pipex_session *session; int off = iphlen + sizeof(struct udphdr); + if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) { - if ((m = *mp = pipex_l2tp_input(m, off, session, - ipsecflowinfo)) == NULL) { - /* the packet is handled by PIPEX */ + m = *mp = pipex_l2tp_input(m, off, session, + ipsecflowinfo); + pipex_rele_session(session); + + if (m == NULL) return IPPROTO_DONE; - } } } #endif @@ -1150,12 +1152,15 @@ udp_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *addr, session = pipex_l2tp_userland_lookup_session_ipv4( m, inp->inp_faddr); - if (session != NULL) - if ((m = pipex_l2tp_userland_output( - m, session)) == NULL) { + if (session != NULL) { + m = pipex_l2tp_userland_output(m, session); + pipex_rele_session(session); + + if (m == NULL) { error = ENOMEM; goto release; } + } } #endif -- 2.20.1