Compare commits

...

6 Commits

Author SHA1 Message Date
Lennart Poettering 2ac4d1d45b hostnamed: add various debugging log messages when we determine chassis type
No actual code flow changes, just a bunch of debug messages.
2020-09-11 13:14:05 +02:00
Lennart Poettering 965cccae8b
Merge pull request #17005 from poettering/sockopt-ipv4-ipv6
rework how we call per-ipv4/per-ipv6 sockopts that conceptually exist on both
2020-09-11 13:13:41 +02:00
Lennart Poettering c6a7924513 man: always document both the ipv4 and the ipv6 sockopt 2020-09-11 10:33:13 +02:00
Lennart Poettering 5d0fe4233b tree-wide: add helper for IPv4/IPv6 sockopts
A variety of sockopts exist both for IPv4 and IPv6 but require a
different pair of sockopt level/option number. Let's add helpers for
these that internally determine the right sockopt to call.

This should shorten code that generically wants to support both ipv4 +
ipv6 and for the first time adds correct support for some cases where we
only called the ipv4 versions, and not the ipv6 options.
2020-09-11 10:33:13 +02:00
Lennart Poettering 00df39a56a timesyncd: don't attempt to call IP_TOS sockopt on IPv6 sockets 2020-09-11 10:16:39 +02:00
lichangze 7c5c59d4b1 hostnamed: map 'all-in-one' DMI chassis type to desktop 2020-09-11 09:55:44 +02:00
12 changed files with 270 additions and 156 deletions

View File

@ -448,37 +448,27 @@
<refsect2> <refsect2>
<title>Other Forms of Activation</title> <title>Other Forms of Activation</title>
<para>Other forms of activation have been suggested and <para>Other forms of activation have been suggested and implemented in some systems. However, there are
implemented in some systems. However, there are often simpler or often simpler or better alternatives, or they can be put together of combinations of the schemes
better alternatives, or they can be put together of combinations above. Example: Sometimes, it appears useful to start daemons or <filename>.socket</filename> units
of the schemes above. Example: Sometimes, it appears useful to when a specific IP address is configured on a network interface, because network sockets shall be bound
start daemons or <filename>.socket</filename> units when a to the address. However, an alternative to implement this is by utilizing the Linux
specific IP address is configured on a network interface, <constant>IP_FREEBIND</constant>/<constant>IPV6_FREEBIND</constant> socket option, as accessible via
because network sockets shall be bound to the address. However, <varname>FreeBind=yes</varname> in systemd socket files (see
an alternative to implement this is by utilizing the Linux <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
<constant>IP_FREEBIND</constant> socket option, as accessible details). This option, when enabled, allows sockets to be bound to a non-local, not configured IP
via <varname>FreeBind=yes</varname> in systemd socket files (see address, and hence allows bindings to a particular IP address before it actually becomes available,
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> making such an explicit dependency to the configured address redundant. Another often suggested trigger
for details). This option, when enabled, allows sockets to be for service activation is low system load. However, here too, a more convincing approach might be to
bound to a non-local, not configured IP address, and hence make proper use of features of the operating system, in particular, the CPU or I/O scheduler of
allows bindings to a particular IP address before it actually Linux. Instead of scheduling jobs from userspace based on monitoring the OS scheduler, it is advisable
becomes available, making such an explicit dependency to the to leave the scheduling of processes to the OS scheduler itself. systemd provides fine-grained access
configured address redundant. Another often suggested trigger to the CPU and I/O schedulers. If a process executed by the init system shall not negatively impact the
for service activation is low system load. However, here too, a amount of CPU or I/O bandwidth available to other processes, it should be configured with
more convincing approach might be to make proper use of features
of the operating system, in particular, the CPU or I/O scheduler
of Linux. Instead of scheduling jobs from userspace based on
monitoring the OS scheduler, it is advisable to leave the
scheduling of processes to the OS scheduler itself. systemd
provides fine-grained access to the CPU and I/O schedulers. If a
process executed by the init system shall not negatively impact
the amount of CPU or I/O bandwidth available to other processes,
it should be configured with
<varname>CPUSchedulingPolicy=idle</varname> and/or <varname>CPUSchedulingPolicy=idle</varname> and/or
<varname>IOSchedulingClass=idle</varname>. Optionally, this may <varname>IOSchedulingClass=idle</varname>. Optionally, this may be combined with timer-based activation
be combined with timer-based activation to schedule background to schedule background jobs during runtime and with minimal impact on the system, and remove it from
jobs during runtime and with minimal impact on the system, and the boot phase itself.</para>
remove it from the boot phase itself.</para>
</refsect2> </refsect2>
</refsect1> </refsect1>

View File

@ -568,26 +568,23 @@
<varlistentry> <varlistentry>
<term><varname>IPTOS=</varname></term> <term><varname>IPTOS=</varname></term>
<listitem><para>Takes an integer argument controlling the IP <listitem><para>Takes an integer argument controlling the IP Type-Of-Service field for packets
Type-Of-Service field for packets generated from this socket. generated from this socket. This controls the <constant>IP_TOS</constant> socket option (see
This controls the IP_TOS socket option (see <citerefentry
<citerefentry project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
for details.). Either a numeric string or one of details.). Either a numeric string or one of <option>low-delay</option>, <option>throughput</option>,
<option>low-delay</option>, <option>throughput</option>, <option>reliability</option> or <option>low-cost</option> may be specified.</para></listitem>
<option>reliability</option> or <option>low-cost</option> may
be specified.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>IPTTL=</varname></term> <term><varname>IPTTL=</varname></term>
<listitem><para>Takes an integer argument controlling the IPv4 <listitem><para>Takes an integer argument controlling the IPv4 Time-To-Live/IPv6 Hop-Count field for
Time-To-Live/IPv6 Hop-Count field for packets generated from packets generated from this socket. This sets the
this socket. This sets the IP_TTL/IPV6_UNICAST_HOPS socket <constant>IP_TTL</constant>/<constant>IPV6_UNICAST_HOPS</constant> socket options (see <citerefentry
options (see project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> and
<citerefentry project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> <citerefentry
and project='die-net'><refentrytitle>ipv6</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
<citerefentry project='die-net'><refentrytitle>ipv6</refentrytitle><manvolnum>7</manvolnum></citerefentry> details.)</para></listitem>
for details.)</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
@ -662,20 +659,18 @@
<varlistentry> <varlistentry>
<term><varname>FreeBind=</varname></term> <term><varname>FreeBind=</varname></term>
<listitem><para>Takes a boolean value. Controls whether the <listitem><para>Takes a boolean value. Controls whether the socket can be bound to non-local IP
socket can be bound to non-local IP addresses. This is useful addresses. This is useful to configure sockets listening on specific IP addresses before those IP
to configure sockets listening on specific IP addresses before addresses are successfully configured on a network interface. This sets the
those IP addresses are successfully configured on a network <constant>IP_FREEBIND</constant>/<constant>IPV6_FREEBIND</constant> socket option. For robustness
interface. This sets the IP_FREEBIND socket option. For reasons it is recommended to use this option whenever you bind a socket to a specific IP
robustness reasons it is recommended to use this option address. Defaults to <option>false</option>.</para></listitem>
whenever you bind a socket to a specific IP address. Defaults
to <option>false</option>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>Transparent=</varname></term> <term><varname>Transparent=</varname></term>
<listitem><para>Takes a boolean value. Controls the <listitem><para>Takes a boolean value. Controls the
IP_TRANSPARENT socket option. Defaults to <constant>IP_TRANSPARENT</constant>/<constant>IPV6_TRANSPARENT</constant> socket option. Defaults to
<option>false</option>.</para></listitem> <option>false</option>.</para></listitem>
</varlistentry> </varlistentry>

View File

@ -6,6 +6,11 @@
#define IPV6_UNICAST_IF 76 #define IPV6_UNICAST_IF 76
#endif #endif
/* linux/in6.h or netinet/in.h */
#ifndef IPV6_TRANSPARENT
#define IPV6_TRANSPARENT 75
#endif
/* Not exposed but defined at include/net/ip.h */ /* Not exposed but defined at include/net/ip.h */
#ifndef IPV4_MIN_MTU #ifndef IPV4_MIN_MTU
#define IPV4_MIN_MTU 68 #define IPV4_MIN_MTU 68

View File

@ -80,15 +80,15 @@ int socket_address_listen(
} }
if (free_bind) { if (free_bind) {
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true); r = socket_set_freebind(fd, socket_address_family(a), true);
if (r < 0) if (r < 0)
log_warning_errno(r, "IP_FREEBIND failed: %m"); log_warning_errno(r, "IP_FREEBIND/IPV6_FREEBIND failed: %m");
} }
if (transparent) { if (transparent) {
r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true); r = socket_set_transparent(fd, socket_address_family(a), true);
if (r < 0) if (r < 0)
log_warning_errno(r, "IP_TRANSPARENT failed: %m"); log_warning_errno(r, "IP_TRANSPARENT/IPV6_TRANSPARENT failed: %m");
} }
} }

View File

@ -26,6 +26,7 @@
#include "macro.h" #include "macro.h"
#include "memory-util.h" #include "memory-util.h"
#include "missing_socket.h" #include "missing_socket.h"
#include "missing_network.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
@ -1204,13 +1205,28 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
return n; return n;
} }
int socket_pass_pktinfo(int fd, bool b) { int socket_get_family(int fd, int *ret) {
int af; int af;
socklen_t sl = sizeof(af); socklen_t sl = sizeof(af);
if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0) if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
return -errno; return -errno;
if (sl != sizeof(af))
return -EINVAL;
return af;
}
int socket_set_recvpktinfo(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) { switch (af) {
case AF_INET: case AF_INET:
@ -1226,3 +1242,142 @@ int socket_pass_pktinfo(int fd, bool b) {
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
} }
int socket_set_recverr(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_recvttl(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_ttl(int fd, int af, int ttl) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_TTL, ttl);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, ttl);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_unicast_if(int fd, int af, int ifi) {
be32_t ifindex_be = htobe32(ifi);
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
if (setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0)
return -errno;
return 0;
case AF_INET6:
if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be)) < 0)
return -errno;
return 0;
default:
return -EAFNOSUPPORT;
}
}
int socket_set_freebind(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, b);
default:
return -EAFNOSUPPORT;
}
}
int socket_set_transparent(int fd, int af, bool b) {
int r;
if (af == AF_UNSPEC) {
r = socket_get_family(fd, &af);
if (r < 0)
return r;
}
switch (af) {
case AF_INET:
return setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, b);
case AF_INET6:
return setsockopt_int(fd, IPPROTO_IPV6, IPV6_TRANSPARENT, b);
default:
return -EAFNOSUPPORT;
}
}

View File

@ -261,4 +261,11 @@ int socket_bind_to_ifindex(int fd, int ifindex);
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags); ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
int socket_pass_pktinfo(int fd, bool b); int socket_get_family(int fd, int *ret);
int socket_set_recvpktinfo(int fd, int af, bool b);
int socket_set_recverr(int fd, int af, bool b);
int socket_set_recvttl(int fd, int af, bool b);
int socket_set_ttl(int fd, int af, int ttl);
int socket_set_unicast_if(int fd, int af, int ifi);
int socket_set_freebind(int fd, int af, bool b);
int socket_set_transparent(int fd, int af, bool b);

View File

@ -979,10 +979,11 @@ static void socket_close_fds(Socket *s) {
(void) unlink(*i); (void) unlink(*i);
} }
static void socket_apply_socket_options(Socket *s, int fd) { static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
int r; int r;
assert(s); assert(s);
assert(p);
assert(fd >= 0); assert(fd >= 0);
if (s->keep_alive) { if (s->keep_alive) {
@ -1046,7 +1047,7 @@ static void socket_apply_socket_options(Socket *s, int fd) {
} }
if (s->pass_pktinfo) { if (s->pass_pktinfo) {
r = socket_pass_pktinfo(fd, true); r = socket_set_recvpktinfo(fd, socket_address_family(&p->address), true);
if (r < 0) if (r < 0)
log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m"); log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m");
} }
@ -1082,16 +1083,8 @@ static void socket_apply_socket_options(Socket *s, int fd) {
} }
if (s->ip_ttl >= 0) { if (s->ip_ttl >= 0) {
int x; r = socket_set_ttl(fd, socket_address_family(&p->address), s->ip_ttl);
if (r < 0)
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, s->ip_ttl);
if (socket_ipv6_is_supported())
x = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, s->ip_ttl);
else
x = -EAFNOSUPPORT;
if (r < 0 && x < 0)
log_unit_warning_errno(UNIT(s), r, "IP_TTL/IPV6_UNICAST_HOPS failed: %m"); log_unit_warning_errno(UNIT(s), r, "IP_TTL/IPV6_UNICAST_HOPS failed: %m");
} }
@ -1664,7 +1657,7 @@ static int socket_open_fds(Socket *_s) {
if (p->fd < 0) if (p->fd < 0)
return p->fd; return p->fd;
socket_apply_socket_options(s, p->fd); socket_apply_socket_options(s, p, p->fd);
socket_symlink(s); socket_symlink(s);
break; break;
@ -3004,7 +2997,7 @@ static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
if (cfd < 0) if (cfd < 0)
goto fail; goto fail;
socket_apply_socket_options(p->socket, cfd); socket_apply_socket_options(p->socket, p, cfd);
} }
socket_enter_running(p->socket, cfd); socket_enter_running(p->socket, cfd);

View File

@ -189,19 +189,25 @@ static const char* fallback_chassis(void) {
int v, r; int v, r;
v = detect_virtualization(); v = detect_virtualization();
if (VIRTUALIZATION_IS_VM(v)) if (v < 0)
log_debug_errno(v, "Failed to detect virtualization, ignoring: %m");
else if (VIRTUALIZATION_IS_VM(v))
return "vm"; return "vm";
if (VIRTUALIZATION_IS_CONTAINER(v)) else if (VIRTUALIZATION_IS_CONTAINER(v))
return "container"; return "container";
r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type); r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
if (r < 0) if (r < 0) {
log_debug_errno(v, "Failed to read DMI chassis type, ignoring: %m");
goto try_acpi; goto try_acpi;
}
r = safe_atou(type, &t); r = safe_atou(type, &t);
free(type); free(type);
if (r < 0) if (r < 0) {
log_debug_errno(v, "Failed to parse DMI chassis type, ignoring: %m");
goto try_acpi; goto try_acpi;
}
/* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any /* We only list the really obvious cases here. The DMI data is unreliable enough, so let's not do any
additional guesswork on top of that. additional guesswork on top of that.
@ -217,6 +223,7 @@ static const char* fallback_chassis(void) {
case 0x4: /* Low Profile Desktop */ case 0x4: /* Low Profile Desktop */
case 0x6: /* Mini Tower */ case 0x6: /* Mini Tower */
case 0x7: /* Tower */ case 0x7: /* Tower */
case 0xD: /* All in one (i.e. PC built into monitor) */
return "desktop"; return "desktop";
case 0x8: /* Portable */ case 0x8: /* Portable */
@ -239,17 +246,24 @@ static const char* fallback_chassis(void) {
case 0x1F: /* Convertible */ case 0x1F: /* Convertible */
case 0x20: /* Detachable */ case 0x20: /* Detachable */
return "convertible"; return "convertible";
default:
log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t);
} }
try_acpi: try_acpi:
r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type); r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
if (r < 0) if (r < 0) {
log_debug_errno(v, "Failed read ACPI PM profile, ignoring: %m");
return NULL; return NULL;
}
r = safe_atou(type, &t); r = safe_atou(type, &t);
free(type); free(type);
if (r < 0) if (r < 0) {
log_debug_errno(v, "Failed parse ACPI PM profile, ignoring: %m");
return NULL; return NULL;
}
/* We only list the really obvious cases here as the ACPI data is not really super reliable. /* We only list the really obvious cases here as the ACPI data is not really super reliable.
* *
@ -275,6 +289,9 @@ try_acpi:
case 8: /* Tablet */ case 8: /* Tablet */
return "tablet"; return "tablet";
default:
log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t);
} }
return NULL; return NULL;
@ -910,13 +927,13 @@ static const BusObjectImplementation manager_object = {
.vtables = BUS_VTABLES(hostname_vtable), .vtables = BUS_VTABLES(hostname_vtable),
}; };
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) { static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
int r; int r;
assert(c); assert(c);
assert(event); assert(event);
assert(_bus); assert(ret);
r = sd_bus_default_system(&bus); r = sd_bus_default_system(&bus);
if (r < 0) if (r < 0)
@ -938,8 +955,7 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to attach bus to event loop: %m"); return log_error_errno(r, "Failed to attach bus to event loop: %m");
*_bus = TAKE_PTR(bus); *ret = TAKE_PTR(bus);
return 0; return 0;
} }

View File

@ -386,54 +386,27 @@ static int dns_scope_socket(
} }
if (s->link) { if (s->link) {
be32_t ifindex_be = htobe32(ifindex); r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
if (r < 0)
if (sa.sa.sa_family == AF_INET) { return r;
r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
if (r < 0)
return -errno;
} else if (sa.sa.sa_family == AF_INET6) {
r = setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
if (r < 0)
return -errno;
}
} }
if (s->protocol == DNS_PROTOCOL_LLMNR) { if (s->protocol == DNS_PROTOCOL_LLMNR) {
/* RFC 4795, section 2.5 requires the TTL to be set to 1 */ /* RFC 4795, section 2.5 requires the TTL to be set to 1 */
r = socket_set_ttl(fd, sa.sa.sa_family, 1);
if (sa.sa.sa_family == AF_INET) { if (r < 0)
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1); return r;
if (r < 0)
return r;
} else if (sa.sa.sa_family == AF_INET6) {
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, 1);
if (r < 0)
return r;
}
} }
if (type == SOCK_DGRAM) { if (type == SOCK_DGRAM) {
/* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */ /* Set IP_RECVERR or IPV6_RECVERR to get ICMP error feedback. See discussion in #10345. */
r = socket_set_recverr(fd, sa.sa.sa_family, true);
if (r < 0)
return r;
if (sa.sa.sa_family == AF_INET) { r = socket_set_recvpktinfo(fd, sa.sa.sa_family, true);
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true); if (r < 0)
if (r < 0) return r;
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
if (r < 0)
return r;
} else if (sa.sa.sa_family == AF_INET6) {
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVERR, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0)
return r;
}
} }
if (ret_socket_address) if (ret_socket_address)

View File

@ -190,18 +190,10 @@ static int dns_stream_identify(DnsStream *s) {
s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr); s->ifindex = manager_find_ifindex(s->manager, s->local.sa.sa_family, s->local.sa.sa_family == AF_INET ? (union in_addr_union*) &s->local.in.sin_addr : (union in_addr_union*) &s->local.in6.sin6_addr);
if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) { if (s->protocol == DNS_PROTOCOL_LLMNR && s->ifindex > 0) {
be32_t ifindex = htobe32(s->ifindex);
/* Make sure all packets for this connection are sent on the same interface */ /* Make sure all packets for this connection are sent on the same interface */
if (s->local.sa.sa_family == AF_INET) { r = socket_set_unicast_if(s->fd, s->local.sa.sa_family, s->ifindex);
r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex)); if (r < 0)
if (r < 0) log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF/IPV6_UNICAST_IF: %m");
log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF: %m");
} else if (s->local.sa.sa_family == AF_INET6) {
r = setsockopt(s->fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex, sizeof(ifindex));
if (r < 0)
log_debug_errno(errno, "Failed to invoke IPV6_UNICAST_IF: %m");
}
} }
s->identified = true; s->identified = true;

View File

@ -543,23 +543,13 @@ static int set_dns_stub_common_socket_options(int fd, int family) {
if (r < 0) if (r < 0)
return r; return r;
if (family == AF_INET) { r = socket_set_recvpktinfo(fd, family, true);
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true); if (r < 0)
if (r < 0) return r;
return r;
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true); r = socket_set_recvttl(fd, family, true);
if (r < 0) if (r < 0)
return r; return r;
} else {
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, true);
if (r < 0)
return r;
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, true);
if (r < 0)
return r;
}
return 0; return 0;
} }
@ -661,10 +651,7 @@ static int manager_dns_stub_fd_extra(Manager *m, DnsStubListenerExtra *l, int ty
/* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that case /* Do not set IP_TTL for extra DNS stub listners, as the address may not be local and in that case
* people may want ttl > 1. */ * people may want ttl > 1. */
if (l->family == AF_INET) r = socket_set_freebind(fd, l->family, true);
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
else
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, true);
if (r < 0) if (r < 0)
goto fail; goto fail;

View File

@ -647,7 +647,8 @@ static int manager_listen_setup(Manager *m) {
if (r < 0) if (r < 0)
return r; return r;
(void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); if (addr.sa.sa_family == AF_INET)
(void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m); return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
} }