Compare commits
6 Commits
f8bff7805e
...
2ac4d1d45b
Author | SHA1 | Date |
---|---|---|
Lennart Poettering | 2ac4d1d45b | |
Lennart Poettering | 965cccae8b | |
Lennart Poettering | c6a7924513 | |
Lennart Poettering | 5d0fe4233b | |
Lennart Poettering | 00df39a56a | |
lichangze | 7c5c59d4b1 |
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 (sa.sa.sa_family == AF_INET) {
|
|
||||||
r = setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_be, sizeof(ifindex_be));
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return -errno;
|
return r;
|
||||||
} 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) {
|
|
||||||
r = setsockopt_int(fd, IPPROTO_IP, IP_TTL, 1);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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 (sa.sa.sa_family == AF_INET) {
|
|
||||||
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);
|
r = socket_set_recvpktinfo(fd, sa.sa.sa_family, true);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
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)
|
||||||
|
|
|
@ -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: %m");
|
log_debug_errno(errno, "Failed to invoke IP_UNICAST_IF/IPV6_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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -647,6 +647,7 @@ static int manager_listen_setup(Manager *m) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (addr.sa.sa_family == AF_INET)
|
||||||
(void) setsockopt_int(m->server_socket, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY);
|
(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);
|
||||||
|
|
Loading…
Reference in New Issue