git: 01f8ce83242d - main - inpcb: Factor out parts of in6_pcbbind() and in_pcbbind_setup()

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Thu, 05 Dec 2024 15:20:48 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=01f8ce83242d7a8e599cf6a78b6277161d79edd4

commit 01f8ce83242d7a8e599cf6a78b6277161d79edd4
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2024-12-05 15:00:13 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-12-05 15:19:57 +0000

    inpcb: Factor out parts of in6_pcbbind() and in_pcbbind_setup()
    
    A large portion of these functions just determines whether the inpcb can
    bind to the address/port.  This portion has no side effects, so is a
    good candidate to move into its own helper function.  This patch does
    so, making the callers less complicated and reducing indentation.
    
    While moving this code, also make some changes:
    - Load socket options (SO_REUSEADDR etc.) only once.  There is nothing
      preventing another thread from toggling the socket options, so make
      this function easier to reason about by avoiding races.
    - When checking whether the bind address is an interface address, make a
      separate sockaddr rather than temporarily modifying the one passed to
      in_pcbbind().
    
    Reviewed by:    ae, glebius
    MFC after:      1 month
    Sponsored by:   Klara, Inc.
    Sponsored by:   Stormshield
    Differential Revision:  https://reviews.freebsd.org/D47590
---
 sys/netinet/in_pcb.c   | 172 ++++++++++++++++++--------------
 sys/netinet6/in6_pcb.c | 262 +++++++++++++++++++++++++++----------------------
 2 files changed, 242 insertions(+), 192 deletions(-)

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 7c881817ac6e..94fb406bcd2b 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -861,6 +861,93 @@ in_pcb_lport(struct inpcb *inp, struct in_addr *laddrp, u_short *lportp,
 #endif /* INET || INET6 */
 
 #ifdef INET
+/*
+ * Determine whether the inpcb can be bound to the specified address/port tuple.
+ */
+static int
+in_pcbbind_avail(struct inpcb *inp, const struct in_addr laddr,
+    const u_short lport, int sooptions, int lookupflags, struct ucred *cred)
+{
+	int reuseport, reuseport_lb;
+
+	INP_LOCK_ASSERT(inp);
+	INP_HASH_LOCK_ASSERT(inp->inp_pcbinfo);
+
+	reuseport = (sooptions & SO_REUSEPORT);
+	reuseport_lb = (sooptions & SO_REUSEPORT_LB);
+
+	if (IN_MULTICAST(ntohl(laddr.s_addr))) {
+		/*
+		 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
+		 * allow complete duplication of binding if
+		 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
+		 * and a multicast address is bound on both
+		 * new and duplicated sockets.
+		 */
+		if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT)) != 0)
+			reuseport = SO_REUSEADDR | SO_REUSEPORT;
+		/*
+		 * XXX: How to deal with SO_REUSEPORT_LB here?
+		 * Treat same as SO_REUSEPORT for now.
+		 */
+		if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT_LB)) != 0)
+			reuseport_lb = SO_REUSEADDR | SO_REUSEPORT_LB;
+	} else if (!in_nullhost(laddr)) {
+		struct sockaddr_in sin;
+
+		memset(&sin, 0, sizeof(sin));
+		sin.sin_family = AF_INET;
+		sin.sin_len = sizeof(sin);
+		sin.sin_addr = laddr;
+
+		/*
+		 * Is the address a local IP address?
+		 * If INP_BINDANY is set, then the socket may be bound
+		 * to any endpoint address, local or not.
+		 */
+		if ((inp->inp_flags & INP_BINDANY) == 0 &&
+		    ifa_ifwithaddr_check((const struct sockaddr *)&sin) == 0)
+			return (EADDRNOTAVAIL);
+	}
+
+	if (lport != 0) {
+		struct inpcb *t;
+
+		if (ntohs(lport) <= V_ipport_reservedhigh &&
+		    ntohs(lport) >= V_ipport_reservedlow &&
+		    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT))
+			return (EACCES);
+
+		if (!IN_MULTICAST(ntohl(laddr.s_addr)) &&
+		    priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) {
+			t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
+			    INPLOOKUP_WILDCARD, cred);
+			if (t != NULL &&
+			    (inp->inp_socket->so_type != SOCK_STREAM ||
+			     in_nullhost(t->inp_faddr)) &&
+			    (!in_nullhost(laddr) ||
+			     !in_nullhost(t->inp_laddr) ||
+			     (t->inp_socket->so_options & SO_REUSEPORT) ||
+			     (t->inp_socket->so_options & SO_REUSEPORT_LB) == 0) &&
+			    (inp->inp_cred->cr_uid != t->inp_cred->cr_uid))
+				return (EADDRINUSE);
+		}
+		t = in_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
+		    lookupflags, cred);
+		if (t != NULL && ((reuseport | reuseport_lb) &
+		    t->inp_socket->so_options) == 0) {
+#ifdef INET6
+			if (!in_nullhost(laddr) ||
+			    !in_nullhost(t->inp_laddr) ||
+			    (inp->inp_vflag & INP_IPV6PROTO) == 0 ||
+			    (t->inp_vflag & INP_IPV6PROTO) == 0)
+#endif
+				return (EADDRINUSE);
+		}
+	}
+	return (0);
+}
+
 /*
  * Set up a bind operation on a PCB, performing port allocation
  * as required, but do not actually modify the PCB. Callers can
@@ -878,15 +965,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	struct in_addr laddr;
 	u_short lport = 0;
-	int lookupflags = 0, reuseport = (so->so_options & SO_REUSEPORT);
+	int lookupflags, sooptions;
 	int error;
 
-	/*
-	 * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here
-	 * so that we don't have to add to the (already messy) code below.
-	 */
-	int reuseport_lb = (so->so_options & SO_REUSEPORT_LB);
-
 	/*
 	 * No state changes, so read locks are sufficient here.
 	 */
@@ -896,7 +977,10 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
 	laddr.s_addr = *laddrp;
 	if (sin != NULL && laddr.s_addr != INADDR_ANY)
 		return (EINVAL);
-	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0)
+
+	lookupflags = 0;
+	sooptions = atomic_load_int(&so->so_options);
+	if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT | SO_REUSEPORT_LB)) == 0)
 		lookupflags = INPLOOKUP_WILDCARD;
 	if (sin == NULL) {
 		if ((error = prison_local_ip4(cred, &laddr)) != 0)
@@ -918,73 +1002,11 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr_in *sin, in_addr_t *laddrp,
 		}
 		laddr = sin->sin_addr;
 
-		/* NB: lport is left as 0 if the port isn't being changed. */
-		if (IN_MULTICAST(ntohl(laddr.s_addr))) {
-			/*
-			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
-			 * allow complete duplication of binding if
-			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
-			 * and a multicast address is bound on both
-			 * new and duplicated sockets.
-			 */
-			if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
-				reuseport = SO_REUSEADDR|SO_REUSEPORT;
-			/*
-			 * XXX: How to deal with SO_REUSEPORT_LB here?
-			 * Treat same as SO_REUSEPORT for now.
-			 */
-			if ((so->so_options &
-			    (SO_REUSEADDR|SO_REUSEPORT_LB)) != 0)
-				reuseport_lb = SO_REUSEADDR|SO_REUSEPORT_LB;
-		} else if (!in_nullhost(laddr)) {
-			sin->sin_port = 0;		/* yech... */
-			bzero(&sin->sin_zero, sizeof(sin->sin_zero));
-			/*
-			 * Is the address a local IP address?
-			 * If INP_BINDANY is set, then the socket may be bound
-			 * to any endpoint address, local or not.
-			 */
-			if ((inp->inp_flags & INP_BINDANY) == 0 &&
-			    ifa_ifwithaddr_check(
-			    (const struct sockaddr *)sin) == 0)
-				return (EADDRNOTAVAIL);
-		}
-		if (lport) {
-			struct inpcb *t;
-
-			if (ntohs(lport) <= V_ipport_reservedhigh &&
-			    ntohs(lport) >= V_ipport_reservedlow &&
-			    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT))
-				return (EACCES);
-
-			if (!IN_MULTICAST(ntohl(laddr.s_addr)) &&
-			    priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) {
-				t = in_pcblookup_local(pcbinfo, laddr, lport,
-				    INPLOOKUP_WILDCARD, cred);
-				if (t != NULL &&
-				    (so->so_type != SOCK_STREAM ||
-				     in_nullhost(t->inp_faddr)) &&
-				    (!in_nullhost(laddr) ||
-				     !in_nullhost(t->inp_laddr) ||
-				     (t->inp_socket->so_options & SO_REUSEPORT) ||
-				     (t->inp_socket->so_options & SO_REUSEPORT_LB) == 0) &&
-				    (inp->inp_cred->cr_uid !=
-				     t->inp_cred->cr_uid))
-					return (EADDRINUSE);
-			}
-			t = in_pcblookup_local(pcbinfo, laddr, lport,
-			    lookupflags, cred);
-			if (t != NULL && ((reuseport | reuseport_lb) &
-			    t->inp_socket->so_options) == 0) {
-#ifdef INET6
-				if (!in_nullhost(laddr) ||
-				    !in_nullhost(t->inp_laddr) ||
-				    (inp->inp_vflag & INP_IPV6PROTO) == 0 ||
-				    (t->inp_vflag & INP_IPV6PROTO) == 0)
-#endif
-					return (EADDRINUSE);
-			}
-		}
+		/* See if this address/port combo is available. */
+		error = in_pcbbind_avail(inp, laddr, lport, sooptions,
+		    lookupflags, cred);
+		if (error != 0)
+			return (error);
 	}
 	if (*lportp != 0)
 		lport = *lportp;
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 639ec68e19e2..6b5a9d3706be 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -160,27 +160,157 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
 	return (0);
 }
 
+/*
+ * Determine whether the inpcb can be bound to the specified address/port tuple.
+ */
+static int
+in6_pcbbind_avail(struct inpcb *inp, const struct sockaddr_in6 *sin6,
+    int sooptions, int lookupflags, struct ucred *cred)
+{
+	const struct in6_addr *laddr;
+	int reuseport, reuseport_lb;
+	u_short lport;
+
+	INP_LOCK_ASSERT(inp);
+	INP_HASH_LOCK_ASSERT(inp->inp_pcbinfo);
+
+	laddr = &sin6->sin6_addr;
+	lport = sin6->sin6_port;
+
+	reuseport = (sooptions & SO_REUSEPORT);
+	reuseport_lb = (sooptions & SO_REUSEPORT_LB);
+
+	if (IN6_IS_ADDR_MULTICAST(laddr)) {
+		/*
+		 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
+		 * allow compepte duplication of binding if
+		 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
+		 * and a multicast address is bound on both
+		 * new and duplicated sockets.
+		 */
+		if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT)) != 0)
+			reuseport = SO_REUSEADDR | SO_REUSEPORT;
+		/*
+		 * XXX: How to deal with SO_REUSEPORT_LB here?
+		 * Treat same as SO_REUSEPORT for now.
+		 */
+		if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT_LB)) != 0)
+			reuseport_lb = SO_REUSEADDR | SO_REUSEPORT_LB;
+	} else if (!IN6_IS_ADDR_UNSPECIFIED(laddr)) {
+		struct sockaddr_in6 sin6;
+		struct epoch_tracker et;
+		struct ifaddr *ifa;
+
+		memset(&sin6, 0, sizeof(sin6));
+		sin6.sin6_family = AF_INET6;
+		sin6.sin6_len = sizeof(sin6);
+		sin6.sin6_addr = *laddr;
+
+		NET_EPOCH_ENTER(et);
+		if ((ifa = ifa_ifwithaddr((const struct sockaddr *)&sin6)) ==
+		    NULL && (inp->inp_flags & INP_BINDANY) == 0) {
+			NET_EPOCH_EXIT(et);
+			return (EADDRNOTAVAIL);
+		}
+
+		/*
+		 * XXX: bind to an anycast address might accidentally
+		 * cause sending a packet with anycast source address.
+		 * We should allow to bind to a deprecated address, since
+		 * the application dares to use it.
+		 */
+		if (ifa != NULL &&
+		    ((struct in6_ifaddr *)ifa)->ia6_flags &
+		    (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_DETACHED)) {
+			NET_EPOCH_EXIT(et);
+			return (EADDRNOTAVAIL);
+		}
+		NET_EPOCH_EXIT(et);
+	}
+
+	if (lport != 0) {
+		struct inpcb *t;
+
+		if (ntohs(lport) <= V_ipport_reservedhigh &&
+		    ntohs(lport) >= V_ipport_reservedlow &&
+		    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT))
+			return (EACCES);
+
+		if (!IN6_IS_ADDR_MULTICAST(laddr) &&
+		    priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) !=
+		    0) {
+			t = in6_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
+			    INPLOOKUP_WILDCARD, cred);
+			if (t != NULL &&
+			    (inp->inp_socket->so_type != SOCK_STREAM ||
+			     IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
+			    (!IN6_IS_ADDR_UNSPECIFIED(laddr) ||
+			     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
+			     (t->inp_socket->so_options & SO_REUSEPORT) ||
+			     (t->inp_socket->so_options & SO_REUSEPORT_LB) == 0) &&
+			    (inp->inp_cred->cr_uid != t->inp_cred->cr_uid))
+				return (EADDRINUSE);
+
+#ifdef INET
+			if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
+			    IN6_IS_ADDR_UNSPECIFIED(laddr)) {
+				struct sockaddr_in sin;
+
+				in6_sin6_2_sin(&sin, sin6);
+				t = in_pcblookup_local(inp->inp_pcbinfo,
+				    sin.sin_addr, lport, INPLOOKUP_WILDCARD,
+				    cred);
+				if (t != NULL &&
+				    (inp->inp_socket->so_type != SOCK_STREAM ||
+				     in_nullhost(t->inp_faddr)) &&
+				    (inp->inp_cred->cr_uid !=
+				     t->inp_cred->cr_uid))
+					return (EADDRINUSE);
+			}
+#endif
+		}
+		t = in6_pcblookup_local(inp->inp_pcbinfo, laddr, lport,
+		    lookupflags, cred);
+		if (t != NULL && ((reuseport | reuseport_lb) &
+		    t->inp_socket->so_options) == 0)
+			return (EADDRINUSE);
+#ifdef INET
+		if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
+		    IN6_IS_ADDR_UNSPECIFIED(laddr)) {
+			struct sockaddr_in sin;
+
+			in6_sin6_2_sin(&sin, sin6);
+			t = in_pcblookup_local(inp->inp_pcbinfo, sin.sin_addr,
+			   lport, lookupflags, cred);
+			if (t != NULL && ((reuseport | reuseport_lb) &
+			    t->inp_socket->so_options) == 0 &&
+			    (!in_nullhost(t->inp_laddr) ||
+			     (t->inp_vflag & INP_IPV6PROTO) != 0)) {
+				return (EADDRINUSE);
+			}
+		}
+#endif
+	}
+	return (0);
+}
+
 int
 in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
 {
 	struct socket *so = inp->inp_socket;
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 	u_short	lport = 0;
-	int error, lookupflags = 0;
-	int reuseport = (so->so_options & SO_REUSEPORT);
-
-	/*
-	 * XXX: Maybe we could let SO_REUSEPORT_LB set SO_REUSEPORT bit here
-	 * so that we don't have to add to the (already messy) code below.
-	 */
-	int reuseport_lb = (so->so_options & SO_REUSEPORT_LB);
+	int error, lookupflags, sooptions;
 
 	INP_WLOCK_ASSERT(inp);
 	INP_HASH_WLOCK_ASSERT(pcbinfo);
 
 	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
 		return (EINVAL);
-	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT|SO_REUSEPORT_LB)) == 0)
+
+	lookupflags = 0;
+	sooptions = atomic_load_int(&so->so_options);
+	if ((sooptions & (SO_REUSEADDR | SO_REUSEPORT | SO_REUSEPORT_LB)) == 0)
 		lookupflags = INPLOOKUP_WILDCARD;
 	if (sin6 == NULL) {
 		if ((error = prison_local_ip6(cred, &inp->in6p_laddr,
@@ -199,115 +329,13 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr_in6 *sin6, struct ucred *cred)
 		    ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
 			return (error);
 
-		lport = sin6->sin6_port;
-		if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
-			/*
-			 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
-			 * allow compepte duplication of binding if
-			 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
-			 * and a multicast address is bound on both
-			 * new and duplicated sockets.
-			 */
-			if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) != 0)
-				reuseport = SO_REUSEADDR|SO_REUSEPORT;
-			/*
-			 * XXX: How to deal with SO_REUSEPORT_LB here?
-			 * Treat same as SO_REUSEPORT for now.
-			 */
-			if ((so->so_options &
-			    (SO_REUSEADDR|SO_REUSEPORT_LB)) != 0)
-				reuseport_lb = SO_REUSEADDR|SO_REUSEPORT_LB;
-		} else if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
-			struct epoch_tracker et;
-			struct ifaddr *ifa;
-
-			sin6->sin6_port = 0;		/* yech... */
-			NET_EPOCH_ENTER(et);
-			if ((ifa = ifa_ifwithaddr((struct sockaddr *)sin6)) ==
-			    NULL &&
-			    (inp->inp_flags & INP_BINDANY) == 0) {
-				NET_EPOCH_EXIT(et);
-				return (EADDRNOTAVAIL);
-			}
-
-			/*
-			 * XXX: bind to an anycast address might accidentally
-			 * cause sending a packet with anycast source address.
-			 * We should allow to bind to a deprecated address, since
-			 * the application dares to use it.
-			 */
-			if (ifa != NULL &&
-			    ((struct in6_ifaddr *)ifa)->ia6_flags &
-			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|IN6_IFF_DETACHED)) {
-				NET_EPOCH_EXIT(et);
-				return (EADDRNOTAVAIL);
-			}
-			NET_EPOCH_EXIT(et);
-		}
-		if (lport) {
-			struct inpcb *t;
-
-			if (ntohs(lport) <= V_ipport_reservedhigh &&
-			    ntohs(lport) >= V_ipport_reservedlow &&
-			    priv_check_cred(cred, PRIV_NETINET_RESERVEDPORT))
-				return (EACCES);
-
-			if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
-			    priv_check_cred(inp->inp_cred, PRIV_NETINET_REUSEPORT) != 0) {
-				t = in6_pcblookup_local(pcbinfo,
-				    &sin6->sin6_addr, lport,
-				    INPLOOKUP_WILDCARD, cred);
-				if (t != NULL &&
-				    (so->so_type != SOCK_STREAM ||
-				     IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
-				    (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
-				     !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
-				     (t->inp_socket->so_options & SO_REUSEPORT) ||
-				     (t->inp_socket->so_options & SO_REUSEPORT_LB) == 0) &&
-				    (inp->inp_cred->cr_uid !=
-				     t->inp_cred->cr_uid))
-					return (EADDRINUSE);
-
-#ifdef INET
-				if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
-				    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
-					struct sockaddr_in sin;
-
-					in6_sin6_2_sin(&sin, sin6);
-					t = in_pcblookup_local(pcbinfo,
-					    sin.sin_addr, lport,
-					    INPLOOKUP_WILDCARD, cred);
-					if (t != NULL &&
-					    (so->so_type != SOCK_STREAM ||
-					     in_nullhost(t->inp_faddr)) &&
-					    (inp->inp_cred->cr_uid !=
-					     t->inp_cred->cr_uid))
-						return (EADDRINUSE);
-				}
-#endif
-			}
-			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
-			    lport, lookupflags, cred);
-			if (t != NULL && ((reuseport | reuseport_lb) &
-			    t->inp_socket->so_options) == 0)
-				return (EADDRINUSE);
-#ifdef INET
-			if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0 &&
-			    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
-				struct sockaddr_in sin;
+		/* See if this address/port combo is available. */
+		error = in6_pcbbind_avail(inp, sin6, sooptions, lookupflags,
+		    cred);
+		if (error != 0)
+			return (error);
 
-				in6_sin6_2_sin(&sin, sin6);
-				t = in_pcblookup_local(pcbinfo, sin.sin_addr,
-				   lport, lookupflags, cred);
-				if (t != NULL && ((reuseport | reuseport_lb) &
-				    t->inp_socket->so_options) == 0 &&
-				    (!in_nullhost(t->inp_laddr) ||
-				     (t->inp_vflag & INP_IPV6PROTO) != 0)) {
-					return (EADDRINUSE);
-				}
-			}
-#endif
-		}
+		lport = sin6->sin6_port;
 		inp->in6p_laddr = sin6->sin6_addr;
 	}
 	if (lport == 0) {