Page MenuHomeFreeBSD

D58281.id.diff
No OneTemporary

D58281.id.diff

diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -925,7 +925,7 @@
* to any endpoint address, local or not.
*/
if ((inp->inp_flags & INP_BINDANY) == 0 &&
- ifa_ifwithaddr_check((const struct sockaddr *)&sin) == 0)
+ ifa_ifwithaddr_fib_check((const struct sockaddr *)&sin, fib) == 0)
return (EADDRNOTAVAIL);
}
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -860,7 +860,7 @@
{
struct sockaddr_in *addr = (struct sockaddr_in *)nam;
struct inpcb *inp;
- int error;
+ int fib, error;
if (nam->sa_family != AF_INET)
return (EAFNOSUPPORT);
@@ -874,11 +874,14 @@
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip_bind: inp == NULL"));
+ fib = V_rip_bind_all_fibs == 0 ? inp->inp_inc.inc_fibnum :
+ RT_ALL_FIBS;
+
if (CK_STAILQ_EMPTY(&V_ifnet) ||
(addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
(addr->sin_addr.s_addr &&
(inp->inp_flags & INP_BINDANY) == 0 &&
- ifa_ifwithaddr_check((struct sockaddr *)addr) == 0))
+ ifa_ifwithaddr_fib_check((struct sockaddr *)addr, fib) == 0))
return (EADDRNOTAVAIL);
INP_WLOCK(inp);
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -208,7 +208,7 @@
sin6.sin6_addr = *laddr;
NET_EPOCH_ENTER(et);
- if ((ifa = ifa_ifwithaddr((const struct sockaddr *)&sin6)) ==
+ if ((ifa = ifa_ifwithaddr_fib((const struct sockaddr *)&sin6, fib)) ==
NULL && (inp->inp_flags & INP_BINDANY) == 0) {
NET_EPOCH_EXIT(et);
return (EADDRNOTAVAIL);
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -743,7 +743,7 @@
struct inpcb *inp;
struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
struct ifaddr *ifa = NULL;
- int error = 0;
+ int fib, error = 0;
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
@@ -759,9 +759,12 @@
if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
return (error);
+ fib = V_rip_bind_all_fibs == 0 ? inp->inp_inc.inc_fibnum :
+ RT_ALL_FIBS;
+
NET_EPOCH_ENTER(et);
if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
- (ifa = ifa_ifwithaddr((struct sockaddr *)addr)) == NULL) {
+ (ifa = ifa_ifwithaddr_fib((struct sockaddr *)addr, fib)) == NULL) {
NET_EPOCH_EXIT(et);
return (EADDRNOTAVAIL);
}
diff --git a/tests/sys/netinet/Makefile b/tests/sys/netinet/Makefile
--- a/tests/sys/netinet/Makefile
+++ b/tests/sys/netinet/Makefile
@@ -30,6 +30,7 @@
redirect
ATF_TESTS_PYTEST+= carp.py \
+ fib_bind.py \
igmp.py \
ip_mroute.py \
tcp_hpts_test.py
diff --git a/tests/sys/netinet/fib_bind.py b/tests/sys/netinet/fib_bind.py
new file mode 100644
--- /dev/null
+++ b/tests/sys/netinet/fib_bind.py
@@ -0,0 +1,100 @@
+#
+# Copyright (c) 2026 Stormshield
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+
+import pytest
+import errno
+import os
+import socket
+import struct
+import sys
+import logging
+
+from atf_python.sys.net.vnet import VnetTestTemplate
+from atf_python.sys.net.tools import ToolsHelper
+
+def _common(tunable, addr, domain, type, proto):
+ """
+ Test what happens when we try to bind a socket to an
+ address that is not present in the current FIB.
+ """
+ sysctl_output = ToolsHelper.get_output(f"sysctl {tunable}")
+ tunable_val = int(sysctl_output.split(":")[1])
+ if tunable_val != 0:
+ pytest.skip(f"{tunable} must be set to 0")
+
+ port = 12345 if type != socket.SOCK_RAW else 0
+ s = socket.socket(domain, type, proto)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_SETFIB, 0)
+
+ failed = False
+ try:
+ s.bind((addr, port))
+ except OSError as e:
+ assert e.errno == errno.EADDRNOTAVAIL
+ failed = True
+ assert failed
+
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_SETFIB, 1)
+
+ failed = False
+ try:
+ s.bind((addr, port))
+ except OSError:
+ failed = True
+ assert not failed
+ s.close()
+
+class TestFibBind(VnetTestTemplate):
+ REQUIRED_MODULES = []
+ TOPOLOGY = {
+ "vnet1": { "ifaces": [ "if1", "if2" ] },
+ "if1": {
+ "prefixes4": [("192.168.1.1/24", "192.168.1.2/24")],
+ "fib": (0, 0),
+ },
+ "if2": {
+ "prefixes4": [("192.168.2.1/24", "192.168.2.2/24")],
+ "fib": (1, 0),
+ },
+ }
+
+ def setup_method(self, method):
+ super().setup_method(method)
+
+ def test_TCP(self):
+ _common("net.inet.tcp.bind_all_fibs", "192.168.2.1", socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)
+
+ def test_UDP(self):
+ _common("net.inet.udp.bind_all_fibs", "192.168.2.1", socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+
+ def test_RAW(self):
+ _common("net.inet.raw.bind_all_fibs", "192.168.2.1", socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
+
+class TestFibBind6(VnetTestTemplate):
+ REQUIRED_MODULES = []
+ TOPOLOGY = {
+ "vnet1": { "ifaces": [ "if1", "if2" ] },
+ "if1": {
+ "prefixes6": [("2001:db8:0:1::1/64", "2001:db8:0:1::2/64")],
+ "fib": (0, 0),
+ },
+ "if2": {
+ "prefixes6": [("2001:db8:0:2::1/64", "2001:db8:0:2::2/64")],
+ "fib": (1, 0),
+ },
+ }
+
+ def setup_method(self, method):
+ super().setup_method(method)
+
+ def test_TCP(self):
+ _common("net.inet.tcp.bind_all_fibs", "2001:db8:0:2::1", socket.AF_INET6, socket.SOCK_STREAM, socket.IPPROTO_TCP)
+
+ def test_UDP(self):
+ _common("net.inet.udp.bind_all_fibs", "2001:db8:0:2::1", socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
+
+ def test_RAW(self):
+ _common("net.inet.raw.bind_all_fibs", "2001:db8:0:2::1", socket.AF_INET6, socket.SOCK_RAW, socket.IPPROTO_IPV6)

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 24, 5:13 AM (2 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35431881
Default Alt Text
D58281.id.diff (5 KB)

Event Timeline