aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRicardo Branco <rbranco@suse.de>2026-04-12 14:08:38 +0000
committerPouria Mousavizadeh Tehrani <pouria@FreeBSD.org>2026-04-17 07:22:39 +0000
commitcaaa7a07fed4a16e753c0064482c0eaa0900607b (patch)
treed933e6dba8d61f121b82ca15543976035bc006d0
parent64e2715f5d8f03ab7e763a49a0e102d755673810 (diff)
linux: Support IPPROTO_RAW socket option translation
Handle Linux IPPROTO_RAW socket options in the Linuxulator for both getsockopt(2) and setsockopt(2). Detect the socket family and remap the level to IPPROTO_IPV6 for AF_INET6, reusing the existing option translators. This fixes IPV6_CHECKSUM for IPv6 raw sockets, which Linux programs set at level IPPROTO_RAW rather than IPPROTO_IPV6. Signed-off-by: Ricardo Branco <rbranco@suse.de> PR: 294434 Reviewed by: pouria Pull-Request: https://github.com/freebsd/freebsd-src/pull/2138
-rw-r--r--sys/compat/linux/linux_socket.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index d971b2a7fbe7..2d20751a41aa 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -30,6 +30,7 @@
#include <sys/param.h>
#include <sys/capsicum.h>
+#include <sys/domain.h>
#include <sys/filedesc.h>
#include <sys/limits.h>
#include <sys/malloc.h>
@@ -2190,6 +2191,26 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
}
break;
#ifdef INET6
+ case IPPROTO_RAW: {
+ struct file *fp;
+ struct socket *so;
+ int family;
+
+ error = getsock(td, args->s, &cap_setsockopt_rights, &fp);
+ if (error != 0)
+ return (error);
+ so = fp->f_data;
+ family = so->so_proto->pr_domain->dom_family;
+ fdrop(fp, td);
+
+ name = -1;
+ if (family == AF_INET6) {
+ name = linux_to_bsd_ip6_sockopt(args->optname);
+ if (name >= 0)
+ level = IPPROTO_IPV6;
+ }
+ break;
+ }
case IPPROTO_ICMPV6: {
struct icmp6_filter f;
int i;
@@ -2473,6 +2494,26 @@ linux_getsockopt(struct thread *td, struct linux_getsockopt_args *args)
}
break;
#ifdef INET6
+ case IPPROTO_RAW: {
+ struct file *fp;
+ struct socket *so;
+ int family;
+
+ error = getsock(td, args->s, &cap_getsockopt_rights, &fp);
+ if (error != 0)
+ return (error);
+ so = fp->f_data;
+ family = so->so_proto->pr_domain->dom_family;
+ fdrop(fp, td);
+
+ name = -1;
+ if (family == AF_INET6) {
+ name = linux_to_bsd_ip6_sockopt(args->optname);
+ if (name >= 0)
+ level = IPPROTO_IPV6;
+ }
+ break;
+ }
case IPPROTO_ICMPV6: {
struct icmp6_filter f;
int i;