Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Feb 2025 01:57:14 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 062ca7e887e3 - stable/14 - inpcb: Imbue in(6)_pcblookup_local() with a FIB parameter
Message-ID:  <202502210157.51L1vEvA067351@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=062ca7e887e33267c85c698a6c318d5f29c3d786

commit 062ca7e887e33267c85c698a6c318d5f29c3d786
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-02-06 14:14:09 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-02-21 01:04:49 +0000

    inpcb: Imbue in(6)_pcblookup_local() with a FIB parameter
    
    This is to enable a mode where duplicate inpcb bindings are permitted,
    and we want to look up an inpcb with a particular FIB.  Thus, add a
    "fib" parameter to in_pcblookup() and related functions, and plumb it
    through.
    
    A fib value of RT_ALL_FIBS indicates that the lookup should ignore FIB
    numbers when searching.  Otherwise, it should refer to a valid FIB
    number, and the returned inpcb should belong to the specific FIB.  For
    now, just add the fib parameter where needed, as there are several
    layers to plumb through.
    
    No functional change intended.
    
    Reviewed by:    glebius
    MFC after:      2 weeks
    Sponsored by:   Klara, Inc.
    Sponsored by:   Stormshield
    Differential Revision:  https://reviews.freebsd.org/D48660
    
    (cherry picked from commit 9a4131629bb3083ddc02a32950e4eb4806a07710)
---
 sys/netinet/in_pcb.c     | 23 ++++++++++++++++-------
 sys/netinet/in_pcb_var.h |  4 ++--
 sys/netinet6/in6_pcb.c   | 20 +++++++++++++-------
 sys/netinet6/in6_pcb.h   |  2 +-
 4 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 32b7f1f96492..84229ce39eb2 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -818,12 +818,14 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
 #ifdef INET6
 			if ((inp->inp_vflag & INP_IPV6) != 0) {
 				tmpinp = in6_pcblookup_local(pcbinfo,
-				    &inp->in6p_laddr, lport, lookupflags, cred);
+				    &inp->in6p_laddr, lport, RT_ALL_FIBS,
+				    lookupflags, cred);
 #ifdef INET
 				if (tmpinp == NULL &&
 				    (inp->inp_vflag & INP_IPV4))
 					tmpinp = in_pcblookup_local(pcbinfo,
-					    laddr, lport, lookupflags, cred);
+					    laddr, lport, RT_ALL_FIBS,
+					    lookupflags, cred);
 #endif
 			}
 #endif
@@ -832,7 +834,7 @@ in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa, u_short *lportp,
 #endif
 #ifdef INET
 				tmpinp = in_pcblookup_local(pcbinfo, laddr,
-				    lport, lookupflags, cred);
+				    lport, RT_ALL_FIBS, lookupflags, cred);
 #endif
 		}
 	} while (tmpinp != NULL);
@@ -931,7 +933,7 @@ in_pcbbind_avail(struct inpcb *inp, const struct in_addr laddr,
 			 * which has a unique 4-tuple.
 			 */
 			t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
-			    INPLOOKUP_WILDCARD, cred);
+			    RT_ALL_FIBS, INPLOOKUP_WILDCARD, cred);
 			if (t != NULL &&
 			    (inp->inp_socket->so_type != SOCK_STREAM ||
 			     in_nullhost(t->inp_faddr)) &&
@@ -939,7 +941,7 @@ in_pcbbind_avail(struct inpcb *inp, const struct in_addr laddr,
 				return (EADDRINUSE);
 		}
 		t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
-		    lookupflags, cred);
+		    RT_ALL_FIBS, lookupflags, cred);
 		if (t != NULL && ((reuseport | reuseport_lb) &
 		    t->inp_socket->so_options) == 0) {
 #ifdef INET6
@@ -1991,7 +1993,7 @@ restart:
 #define INP_LOOKUP_MAPPED_PCB_COST	3
 struct inpcb *
 in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
-    u_short lport, int lookupflags, struct ucred *cred)
+    u_short lport, int fib, int lookupflags, struct ucred *cred)
 {
 	struct inpcb *inp;
 #ifdef INET6
@@ -2003,6 +2005,9 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
 
 	KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
 	    ("%s: invalid lookup flags %d", __func__, lookupflags));
+	KASSERT(fib == RT_ALL_FIBS || (fib >= 0 && fib < V_rt_numfibs),
+	    ("%s: invalid fib %d", __func__, fib));
+
 	INP_HASH_LOCK_ASSERT(pcbinfo);
 
 	if ((lookupflags & INPLOOKUP_WILDCARD) == 0) {
@@ -2021,7 +2026,8 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
 #endif
 			if (inp->inp_faddr.s_addr == INADDR_ANY &&
 			    inp->inp_laddr.s_addr == laddr.s_addr &&
-			    inp->inp_lport == lport) {
+			    inp->inp_lport == lport && (fib == RT_ALL_FIBS ||
+			    inp->inp_inc.inc_fibnum == fib)) {
 				/*
 				 * Found?
 				 */
@@ -2060,6 +2066,9 @@ in_pcblookup_local(struct inpcbinfo *pcbinfo, struct in_addr laddr,
 				if (!prison_equal_ip4(inp->inp_cred->cr_prison,
 				    cred->cr_prison))
 					continue;
+				if (fib != RT_ALL_FIBS &&
+				    inp->inp_inc.inc_fibnum != fib)
+					continue;
 #ifdef INET6
 				/* XXX inp locking */
 				if ((inp->inp_vflag & INP_IPV4) == 0)
diff --git a/sys/netinet/in_pcb_var.h b/sys/netinet/in_pcb_var.h
index f2191cf73386..1780a9859f5f 100644
--- a/sys/netinet/in_pcb_var.h
+++ b/sys/netinet/in_pcb_var.h
@@ -55,8 +55,8 @@ int	in_pcb_lport(struct inpcb *, struct in_addr *, u_short *,
 int	in_pcb_lport_dest(struct inpcb *inp, struct sockaddr *lsa,
             u_short *lportp, struct sockaddr *fsa, u_short fport,
             struct ucred *cred, int lookupflags);
-struct inpcb *	in_pcblookup_local(struct inpcbinfo *, struct in_addr, u_short,
-	    int, struct ucred *);
+struct inpcb *in_pcblookup_local(struct inpcbinfo *, struct in_addr, u_short,
+	    int, int, struct ucred *);
 
 struct inpcbport {
 	struct inpcbhead phd_pcblist;
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index c2cf856d0dfd..9584dcf7474c 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -251,7 +251,7 @@ in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
 			 * which has a unique 4-tuple.
 			 */
 			t = in6_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
-			    INPLOOKUP_WILDCARD, cred);
+			    RT_ALL_FIBS, INPLOOKUP_WILDCARD, cred);
 			if (t != NULL &&
 			    (inp->inp_socket->so_type != SOCK_STREAM ||
 			     IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
@@ -265,8 +265,8 @@ in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
 
 				in6_sin6_2_sin(&sin, sin6);
 				t = in_pcblookup_local(inp->inp_pcbinfo,
-				    sin.sin_addr, lport, INPLOOKUP_WILDCARD,
-				    cred);
+				    sin.sin_addr, lport, RT_ALL_FIBS,
+				    INPLOOKUP_WILDCARD, cred);
 				if (t != NULL &&
 				    (inp->inp_socket->so_type != SOCK_STREAM ||
 				     in_nullhost(t->inp_faddr)) &&
@@ -277,7 +277,7 @@ in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
 #endif
 		}
 		t = in6_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
-		    lookupflags, cred);
+		    RT_ALL_FIBS, lookupflags, cred);
 		if (t != NULL && ((reuseport | reuseport_lb) &
 		    t->inp_socket->so_options) == 0)
 			return (EADDRINUSE);
@@ -288,7 +288,7 @@ in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
 
 			in6_sin6_2_sin(&sin, sin6);
 			t = in_pcblookup_local(inp->inp_pcbinfo, sin.sin_addr,
-			   lport, lookupflags, cred);
+			   lport, RT_ALL_FIBS, lookupflags, cred);
 			if (t != NULL && ((reuseport | reuseport_lb) &
 			    t->inp_socket->so_options) == 0 &&
 			    (!in_nullhost(t->inp_laddr) ||
@@ -751,13 +751,15 @@ in6_pcbnotify(struct inpcbinfo *pcbinfo, struct sockaddr_in6 *sa6_dst,
  */
 struct inpcb *
 in6_pcblookup_local(struct inpcbinfo *pcbinfo, const struct in6_addr *laddr,
-    u_short lport, int lookupflags, struct ucred *cred)
+    u_short lport, int fib, int lookupflags, struct ucred *cred)
 {
 	struct inpcb *inp;
 	int matchwild = 3, wildcard;
 
 	KASSERT((lookupflags & ~(INPLOOKUP_WILDCARD)) == 0,
 	    ("%s: invalid lookup flags %d", __func__, lookupflags));
+	KASSERT(fib == RT_ALL_FIBS || (fib >= 0 && fib < V_rt_numfibs),
+	    ("%s: invalid fib %d", __func__, fib));
 
 	INP_HASH_LOCK_ASSERT(pcbinfo);
 
@@ -775,7 +777,8 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, const struct in6_addr *laddr,
 				continue;
 			if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) &&
 			    IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr) &&
-			    inp->inp_lport == lport) {
+			    inp->inp_lport == lport && (fib == RT_ALL_FIBS ||
+			    inp->inp_inc.inc_fibnum == fib)) {
 				/* Found. */
 				if (prison_equal_ip6(cred->cr_prison,
 				    inp->inp_cred->cr_prison))
@@ -815,6 +818,9 @@ in6_pcblookup_local(struct inpcbinfo *pcbinfo, const struct in6_addr *laddr,
 				/* XXX inp locking */
 				if ((inp->inp_vflag & INP_IPV6) == 0)
 					continue;
+				if (fib != RT_ALL_FIBS &&
+				    inp->inp_inc.inc_fibnum != fib)
+					continue;
 				if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr))
 					wildcard++;
 				if (!IN6_IS_ADDR_UNSPECIFIED(
diff --git a/sys/netinet6/in6_pcb.h b/sys/netinet6/in6_pcb.h
index edf7023747bb..5118b4b412a4 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -77,7 +77,7 @@ int	in6_pcbconnect(struct inpcb *, struct sockaddr_in6 *, struct ucred *,
 	    bool);
 void	in6_pcbdisconnect(struct inpcb *);
 struct inpcb *in6_pcblookup_local(struct inpcbinfo *, const struct in6_addr *,
-	    u_short, int, struct ucred *);
+	    u_short, int, int, struct ucred *);
 struct inpcb *in6_pcblookup_hash_locked(struct inpcbinfo *pcbinfo,
 	    const struct in6_addr *faddr, u_int fport_arg,
 	    const struct in6_addr *laddr, u_int lport_arg,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202502210157.51L1vEvA067351>