Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Feb 2025 16:27:24 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 9a4131629bb3 - main - inpcb: Imbue in(6)_pcblookup_local() with a FIB parameter
Message-ID:  <202502061627.516GROTT095097@gitrepo.freebsd.org>

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

URL: https://cgit.FreeBSD.org/src/commit/?id=9a4131629bb3083ddc02a32950e4eb4806a07710

commit 9a4131629bb3083ddc02a32950e4eb4806a07710
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2025-02-06 14:14:09 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2025-02-06 14:14:09 +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
---
 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 f9eac96acd5b..9a22fa0d9fa4 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -852,12 +852,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
@@ -866,7 +868,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);
@@ -965,7 +967,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)) &&
@@ -973,7 +975,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
@@ -2000,7 +2002,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
@@ -2012,6 +2014,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) {
@@ -2030,7 +2035,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?
 				 */
@@ -2069,6 +2075,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 655fd03ee9ba..90239cbb98cd 100644
--- a/sys/netinet/in_pcb_var.h
+++ b/sys/netinet/in_pcb_var.h
@@ -53,8 +53,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 b44fe5ed3553..82ddd7ebad8c 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -249,7 +249,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)) &&
@@ -263,8 +263,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)) &&
@@ -275,7 +275,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);
@@ -286,7 +286,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) ||
@@ -720,13 +720,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);
 
@@ -744,7 +746,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))
@@ -784,6 +787,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 98a4d27ddb35..eab095780a19 100644
--- a/sys/netinet6/in6_pcb.h
+++ b/sys/netinet6/in6_pcb.h
@@ -75,7 +75,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?202502061627.516GROTT095097>