Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 Apr 2026 07:22:52 +0000
From:      Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Cc:        Ricardo Branco <rbranco@suse.de>
Subject:   git: 64e2715f5d8f - main - linux: Support ICMP6_FILTER socket option translation
Message-ID:  <69e1dfcc.4525b.76faacf@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by pouria:

URL: https://cgit.FreeBSD.org/src/commit/?id=64e2715f5d8f03ab7e763a49a0e102d755673810

commit 64e2715f5d8f03ab7e763a49a0e102d755673810
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2026-04-12 11:01:47 +0000
Commit:     Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org>
CommitDate: 2026-04-17 07:22:36 +0000

    linux: Support ICMP6_FILTER socket option translation
    
    Handle Linux IPPROTO_ICMPV6 socket options in the Linuxulator and map
    ICMP6_FILTER for both getsockopt(2) and setsockopt(2).
    
    Linux and FreeBSD use inverted bit semantics for struct icmp6_filter, so
    invert the filter contents before/after calling setsockopt/getsockopt.
    
    Signed-off-by:  Ricardo Branco <rbranco@suse.de>
    PR:             294434
    Reviewed by:    pouria
    Pull-Request:   https://github.com/freebsd/freebsd-src/pull/2138
---
 sys/compat/linux/linux_socket.c | 67 +++++++++++++++++++++++++++++++++++++++++
 sys/compat/linux/linux_socket.h |  2 ++
 2 files changed, 69 insertions(+)

diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 023be1e6b885..d971b2a7fbe7 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -52,6 +52,7 @@
 #include <netinet/ip.h>
 #include <netinet/tcp.h>
 #ifdef INET6
+#include <netinet/icmp6.h>
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
 #endif
@@ -622,6 +623,19 @@ bsd_to_linux_tcp_user_timeout(u_int bsd_timeout)
 	return (bsd_timeout * 1000U);
 }
 
+#ifdef INET6
+static int
+linux_to_bsd_icmp6_sockopt(int opt)
+{
+
+	switch (opt) {
+	case LINUX_ICMP6_FILTER:
+		return (ICMP6_FILTER);
+	}
+	return (-1);
+}
+#endif
+
 static int
 linux_to_bsd_msg_flags(int flags)
 {
@@ -2175,6 +2189,29 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
 			break;
 		}
 		break;
+#ifdef INET6
+	case IPPROTO_ICMPV6: {
+		struct icmp6_filter f;
+		int i;
+
+		name = linux_to_bsd_icmp6_sockopt(args->optname);
+		if (name != ICMP6_FILTER)
+			break;
+
+		if (args->optlen != sizeof(f))
+			return (EINVAL);
+
+		error = copyin(PTRIN(args->optval), &f, sizeof(f));
+		if (error)
+			return (error);
+
+		/* Linux uses opposite values for pass/block in ICMPv6 */
+		for (i = 0; i < nitems(f.icmp6_filt); i++)
+			f.icmp6_filt[i] = ~f.icmp6_filt[i];
+		return (kern_setsockopt(td, args->s, IPPROTO_ICMPV6,
+		    ICMP6_FILTER, &f, UIO_SYSSPACE, sizeof(f)));
+	}
+#endif
 	case SOL_NETLINK:
 		name = args->optname;
 		break;
@@ -2435,6 +2472,36 @@ linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
 			break;
 		}
 		break;
+#ifdef INET6
+	case IPPROTO_ICMPV6: {
+		struct icmp6_filter f;
+		int i;
+
+		name = linux_to_bsd_icmp6_sockopt(args->optname);
+		if (name != ICMP6_FILTER)
+			break;
+
+		error = copyin(PTRIN(args->optlen), &len, sizeof(len));
+		if (error)
+			return (error);
+		if (len != sizeof(f))
+			return (EINVAL);
+
+		error = kern_getsockopt(td, args->s, IPPROTO_ICMPV6,
+		    ICMP6_FILTER, &f, UIO_SYSSPACE, &len);
+		if (error)
+			return (error);
+
+		/* Linux uses opposite values for pass/block in ICMPv6 */
+		for (i = 0; i < nitems(f.icmp6_filt); i++)
+			f.icmp6_filt[i] = ~f.icmp6_filt[i];
+		error = copyout(&f, PTRIN(args->optval), len);
+		if (error)
+			return (error);
+
+		return (copyout(&len, PTRIN(args->optlen), sizeof(socklen_t)));
+	}
+#endif
 	default:
 		name = -1;
 		break;
diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h
index f2a96b3e7dcb..d30d68409496 100644
--- a/sys/compat/linux/linux_socket.h
+++ b/sys/compat/linux/linux_socket.h
@@ -324,6 +324,8 @@ int linux_accept(struct thread *td, struct linux_accept_args *args);
 #define	LINUX_TCP_MD5SIG	14
 #define	LINUX_TCP_USER_TIMEOUT	18
 
+#define	LINUX_ICMP6_FILTER	1
+
 struct l_ifmap {
 	l_ulong		mem_start;
 	l_ulong		mem_end;


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e1dfcc.4525b.76faacf>