Compare commits
No commits in common. "2ac4d1d45b952b9d675ae7911de3fef0874d65a8" and "f8bff7805ea1252c2421d07a92bf5b19f4f16aa7" have entirely different histories.
2ac4d1d45b
...
f8bff7805e
|
@ -448,27 +448,37 @@
|
|||
<refsect2>
|
||||
<title>Other Forms of Activation</title>
|
||||
|
||||
<para>Other forms of activation have been suggested and implemented in some systems. However, there are
|
||||
often simpler or better alternatives, or they can be put together of combinations of the schemes
|
||||
above. Example: Sometimes, it appears useful to start daemons or <filename>.socket</filename> units
|
||||
when a specific IP address is configured on a network interface, because network sockets shall be bound
|
||||
to the address. However, an alternative to implement this is by utilizing the Linux
|
||||
<constant>IP_FREEBIND</constant>/<constant>IPV6_FREEBIND</constant> socket option, as accessible via
|
||||
<varname>FreeBind=yes</varname> in systemd socket files (see
|
||||
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details). This option, when enabled, allows sockets to be bound to a non-local, not configured IP
|
||||
address, and hence allows bindings to a particular IP address before it actually becomes available,
|
||||
making such an explicit dependency to the configured address redundant. Another often suggested trigger
|
||||
for service activation is low system load. However, here too, a 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
|
||||
<para>Other forms of activation have been suggested and
|
||||
implemented in some systems. However, there are often simpler or
|
||||
better alternatives, or they can be put together of combinations
|
||||
of the schemes above. Example: Sometimes, it appears useful to
|
||||
start daemons or <filename>.socket</filename> units when a
|
||||
specific IP address is configured on a network interface,
|
||||
because network sockets shall be bound to the address. However,
|
||||
an alternative to implement this is by utilizing the Linux
|
||||
<constant>IP_FREEBIND</constant> socket option, as accessible
|
||||
via <varname>FreeBind=yes</varname> in systemd socket files (see
|
||||
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details). This option, when enabled, allows sockets to be
|
||||
bound to a non-local, not configured IP address, and hence
|
||||
allows bindings to a particular IP address before it actually
|
||||
becomes available, making such an explicit dependency to the
|
||||
configured address redundant. Another often suggested trigger
|
||||
for service activation is low system load. However, here too, a
|
||||
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>IOSchedulingClass=idle</varname>. Optionally, this may be combined with timer-based activation
|
||||
to schedule background jobs during runtime and with minimal impact on the system, and remove it from
|
||||
the boot phase itself.</para>
|
||||
<varname>IOSchedulingClass=idle</varname>. Optionally, this may
|
||||
be combined with timer-based activation to schedule background
|
||||
jobs during runtime and with minimal impact on the system, and
|
||||
remove it from the boot phase itself.</para>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
|
|
|
@ -568,23 +568,26 @@
|
|||
|
||||
<varlistentry>
|
||||
<term><varname>IPTOS=</varname></term>
|
||||
<listitem><para>Takes an integer argument controlling the IP Type-Of-Service field for packets
|
||||
generated from this socket. This controls the <constant>IP_TOS</constant> socket option (see
|
||||
<citerefentry
|
||||
project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
details.). Either a numeric string or one of <option>low-delay</option>, <option>throughput</option>,
|
||||
<option>reliability</option> or <option>low-cost</option> may be specified.</para></listitem>
|
||||
<listitem><para>Takes an integer argument controlling the IP
|
||||
Type-Of-Service field for packets generated from this socket.
|
||||
This controls the IP_TOS socket option (see
|
||||
<citerefentry project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details.). Either a numeric string or one of
|
||||
<option>low-delay</option>, <option>throughput</option>,
|
||||
<option>reliability</option> or <option>low-cost</option> may
|
||||
be specified.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>IPTTL=</varname></term>
|
||||
<listitem><para>Takes an integer argument controlling the IPv4 Time-To-Live/IPv6 Hop-Count field for
|
||||
packets generated from this socket. This sets the
|
||||
<constant>IP_TTL</constant>/<constant>IPV6_UNICAST_HOPS</constant> socket options (see <citerefentry
|
||||
project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry> and
|
||||
<citerefentry
|
||||
project='die-net'><refentrytitle>ipv6</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
details.)</para></listitem>
|
||||
<listitem><para>Takes an integer argument controlling the IPv4
|
||||
Time-To-Live/IPv6 Hop-Count field for packets generated from
|
||||
this socket. This sets the IP_TTL/IPV6_UNICAST_HOPS socket
|
||||
options (see
|
||||
<citerefentry project='die-net'><refentrytitle>ip</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
and
|
||||
<citerefentry project='die-net'><refentrytitle>ipv6</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for details.)</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -659,18 +662,20 @@
|
|||
|
||||
<varlistentry>
|
||||
<term><varname>FreeBind=</varname></term>
|
||||
<listitem><para>Takes a boolean value. Controls whether the socket can be bound to non-local IP
|
||||
addresses. This is useful to configure sockets listening on specific IP addresses before those IP
|
||||
addresses are successfully configured on a network interface. This sets the
|
||||
<constant>IP_FREEBIND</constant>/<constant>IPV6_FREEBIND</constant> socket option. For robustness
|
||||
reasons it is recommended to use this option whenever you bind a socket to a specific IP
|
||||
address. Defaults to <option>false</option>.</para></listitem>
|
||||
<listitem><para>Takes a boolean value. Controls whether the
|
||||
socket can be bound to non-local IP addresses. This is useful
|
||||
to configure sockets listening on specific IP addresses before
|
||||
those IP addresses are successfully configured on a network
|
||||
interface. This sets the IP_FREEBIND socket option. For
|
||||
robustness reasons it is recommended to use this option
|
||||
whenever you bind a socket to a specific IP address. Defaults
|
||||
to <option>false</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Transparent=</varname></term>
|
||||
<listitem><para>Takes a boolean value. Controls the
|
||||
<constant>IP_TRANSPARENT</constant>/<constant>IPV6_TRANSPARENT</constant> socket option. Defaults to
|
||||
IP_TRANSPARENT socket option. Defaults to
|
||||
<option>false</option>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
|
|
@ -6,11 +6,6 @@
|
|||
#define IPV6_UNICAST_IF 76
|
||||
#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 */
|
||||
#ifndef IPV4_MIN_MTU
|
||||
#define IPV4_MIN_MTU 68
|
||||
|
|
|
@ -80,15 +80,15 @@ int socket_address_listen(
|
|||
}
|
||||
|
||||
if (free_bind) {
|
||||
r = socket_set_freebind(fd, socket_address_family(a), true);
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "IP_FREEBIND/IPV6_FREEBIND failed: %m");
|
||||
log_warning_errno(r, "IP_FREEBIND failed: %m");
|
||||
}
|
||||
|
||||
if (transparent) {
|
||||
r = socket_set_transparent(fd, socket_address_family(a), true);
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_TRANSPARENT, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "IP_TRANSPARENT/IPV6_TRANSPARENT failed: %m");
|
||||
log_warning_errno(r, "IP_TRANSPARENT failed: %m");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "macro.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_socket.h"
|
||||
#include "missing_network.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
|
@ -1205,28 +1204,13 @@ ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
|
|||
return n;
|
||||
}
|
||||
|
||||
int socket_get_family(int fd, int *ret) {
|
||||
int socket_pass_pktinfo(int fd, bool b) {
|
||||
int af;
|
||||
socklen_t sl = sizeof(af);
|
||||
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &af, &sl) < 0)
|
||||
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) {
|
||||
|
||||
case AF_INET:
|
||||
|
@ -1242,142 +1226,3 @@ int socket_set_recvpktinfo(int fd, int af, bool b) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -261,11 +261,4 @@ int socket_bind_to_ifindex(int fd, int ifindex);
|
|||
|
||||
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
|
||||
|
||||
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);
|
||||
int socket_pass_pktinfo(int fd, bool b);
|
||||
|
|
|
@ -979,11 +979,10 @@ static void socket_close_fds(Socket *s) {
|
|||
(void) unlink(*i);
|
||||
}
|
||||
|
||||
static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
|
||||
static void socket_apply_socket_options(Socket *s, int fd) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(p);
|
||||
assert(fd >= 0);
|
||||
|
||||
if (s->keep_alive) {
|
||||
|
@ -1047,7 +1046,7 @@ static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
|
|||
}
|
||||
|
||||
if (s->pass_pktinfo) {
|
||||
r = socket_set_recvpktinfo(fd, socket_address_family(&p->address), true);
|
||||
r = socket_pass_pktinfo(fd, true);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m");
|
||||
}
|
||||
|
@ -1083,8 +1082,16 @@ static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
|
|||
}
|
||||
|
||||
if (s->ip_ttl >= 0) {
|
||||
r = socket_set_ttl(fd, socket_address_family(&p->address), s->ip_ttl);
|
||||
if (r < 0)
|
||||
int x;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -1657,7 +1664,7 @@ static int socket_open_fds(Socket *_s) {
|
|||
if (p->fd < 0)
|
||||
return p->fd;
|
||||
|
||||
socket_apply_socket_options(s, p, p->fd);
|
||||
socket_apply_socket_options(s, p->fd);
|
||||
socket_symlink(s);
|
||||
break;
|
||||
|
||||
|
@ -2997,7 +3004,7 @@ static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
|||
if (cfd < 0)
|
||||
goto fail;
|
||||
|
||||
socket_apply_socket_options(p->socket, p, cfd);
|
||||
socket_apply_socket_options(p->socket, cfd);
|
||||
}
|
||||
|
||||
socket_enter_running(p->socket, cfd);
|
||||
|
|
|
@ -189,25 +189,19 @@ static const char* fallback_chassis(void) {
|
|||
int v, r;
|
||||
|
||||
v = detect_virtualization();
|
||||
if (v < 0)
|
||||
log_debug_errno(v, "Failed to detect virtualization, ignoring: %m");
|
||||
else if (VIRTUALIZATION_IS_VM(v))
|
||||
if (VIRTUALIZATION_IS_VM(v))
|
||||
return "vm";
|
||||
else if (VIRTUALIZATION_IS_CONTAINER(v))
|
||||
if (VIRTUALIZATION_IS_CONTAINER(v))
|
||||
return "container";
|
||||
|
||||
r = read_one_line_file("/sys/class/dmi/id/chassis_type", &type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(v, "Failed to read DMI chassis type, ignoring: %m");
|
||||
if (r < 0)
|
||||
goto try_acpi;
|
||||
}
|
||||
|
||||
r = safe_atou(type, &t);
|
||||
free(type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(v, "Failed to parse DMI chassis type, ignoring: %m");
|
||||
if (r < 0)
|
||||
goto try_acpi;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
|
@ -223,7 +217,6 @@ static const char* fallback_chassis(void) {
|
|||
case 0x4: /* Low Profile Desktop */
|
||||
case 0x6: /* Mini Tower */
|
||||
case 0x7: /* Tower */
|
||||
case 0xD: /* All in one (i.e. PC built into monitor) */
|
||||
return "desktop";
|
||||
|
||||
case 0x8: /* Portable */
|
||||
|
@ -246,24 +239,17 @@ static const char* fallback_chassis(void) {
|
|||
case 0x1F: /* Convertible */
|
||||
case 0x20: /* Detachable */
|
||||
return "convertible";
|
||||
|
||||
default:
|
||||
log_debug("Unhandled DMI chassis type 0x%02x, ignoring.", t);
|
||||
}
|
||||
|
||||
try_acpi:
|
||||
r = read_one_line_file("/sys/firmware/acpi/pm_profile", &type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(v, "Failed read ACPI PM profile, ignoring: %m");
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = safe_atou(type, &t);
|
||||
free(type);
|
||||
if (r < 0) {
|
||||
log_debug_errno(v, "Failed parse ACPI PM profile, ignoring: %m");
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We only list the really obvious cases here as the ACPI data is not really super reliable.
|
||||
*
|
||||
|
@ -289,9 +275,6 @@ try_acpi:
|
|||
|
||||
case 8: /* Tablet */
|
||||
return "tablet";
|
||||
|
||||
default:
|
||||
log_debug("Unhandled ACPI PM profile 0x%02x, ignoring.", t);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -927,13 +910,13 @@ static const BusObjectImplementation manager_object = {
|
|||
.vtables = BUS_VTABLES(hostname_vtable),
|
||||
};
|
||||
|
||||
static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
|
||||
static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
assert(event);
|
||||
assert(ret);
|
||||
assert(_bus);
|
||||
|
||||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
|
@ -955,7 +938,8 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **ret) {
|
|||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to attach bus to event loop: %m");
|
||||
|
||||
*ret = TAKE_PTR(bus);
|
||||
*_bus = TAKE_PTR(bus);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -386,27 +386,54 @@ static int dns_scope_socket(
|
|||
}
|
||||
|
||||
if (s->link) {
|
||||
r = socket_set_unicast_if(fd, sa.sa.sa_family, ifindex);
|
||||
be32_t ifindex_be = htobe32(ifindex);
|
||||
|
||||
if (sa.sa.sa_family == AF_INET) {
|
||||
r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
|
||||
if (r < 0)
|
||||
return r;
|
||||
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) {
|
||||
/* 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) {
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1);
|
||||
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) {
|
||||
/* 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 (sa.sa.sa_family == AF_INET) {
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVERR, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = socket_set_recvpktinfo(fd, sa.sa.sa_family, true);
|
||||
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)
|
||||
|
|
|
@ -190,10 +190,18 @@ 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);
|
||||
|
||||
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 */
|
||||
r = socket_set_unicast_if(s->fd, s->local.sa.sa_family, s->ifindex);
|
||||
if (s->local.sa.sa_family == AF_INET) {
|
||||
r = setsockopt(s->fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex, sizeof(ifindex));
|
||||
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;
|
||||
|
|
|
@ -543,13 +543,23 @@ static int set_dns_stub_common_socket_options(int fd, int family) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = socket_set_recvpktinfo(fd, family, true);
|
||||
if (family == AF_INET) {
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_PKTINFO, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = socket_set_recvttl(fd, family, true);
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_RECVTTL, true);
|
||||
if (r < 0)
|
||||
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;
|
||||
}
|
||||
|
@ -651,7 +661,10 @@ 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
|
||||
* people may want ttl > 1. */
|
||||
|
||||
r = socket_set_freebind(fd, l->family, true);
|
||||
if (l->family == AF_INET)
|
||||
r = setsockopt_int(fd, IPPROTO_IP, IP_FREEBIND, true);
|
||||
else
|
||||
r = setsockopt_int(fd, IPPROTO_IPV6, IPV6_FREEBIND, true);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -647,7 +647,6 @@ static int manager_listen_setup(Manager *m) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue