linux: ignore setsockopt(IPV6_RECVERR)

Under Linux, the socket options IP_RECVERR and IPV6_RECVERR are used to
receive socket errors via a dedicated 'error queue' which can be
retrieved via recvmsg().  FreeBSD does not support this functionality.

For IPv4, the sysctl compat.linux.ignore_ip_recverr can be set to 1 to
silently ignore attempts to set IP_RECVERR and return success to the
application, which is wrong, but is required for (among other things)
a functional DNS client in recent versions of glibc.

Add support for ignoring IPV6_RECVERR, controlled by the same sysctl.
This fixes DNS in Linux when using IPv6 resolvers.

Reviewed by: imp, Jose Luis Duran
Pull Request: https://github.com/freebsd/freebsd-src/pull/1118
This commit is contained in:
Lexi Winter 2024-04-22 15:58:11 -06:00 committed by Warner Losh
parent 50ecbc5142
commit ca63710d36

View file

@ -501,6 +501,11 @@ linux_to_bsd_ip6_sockopt(int opt)
"unsupported IPv6 socket option IPV6_RECVFRAGSIZE (%d)",
opt);
return (-2);
case LINUX_IPV6_RECVERR:
LINUX_RATELIMIT_MSG_OPT1(
"unsupported IPv6 socket option IPV6_RECVERR (%d), you can not get extended reliability info in linux programs",
opt);
return (-2);
/* unknown sockopts */
default:
@ -2112,6 +2117,14 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args)
name = linux_to_bsd_ip_sockopt(args->optname);
break;
case IPPROTO_IPV6:
if (args->optname == LINUX_IPV6_RECVERR &&
linux_ignore_ip_recverr) {
/*
* XXX: This is a hack to unbreak DNS resolution
* with glibc 2.30 and above.
*/
return (0);
}
name = linux_to_bsd_ip6_sockopt(args->optname);
break;
case IPPROTO_TCP: