Compare commits
14 Commits
8270e3d8ed
...
e7d5fe17db
Author | SHA1 | Date |
---|---|---|
Andrew Doran | e7d5fe17db | |
Lennart Poettering | 2d5996c175 | |
Zbigniew Jędrzejewski-Szmek | 6b726e602e | |
Zbigniew Jędrzejewski-Szmek | f1f7b08805 | |
Lennart Poettering | 1e0d5eebf1 | |
Benjamin Dahlhoff | 13c829c1bd | |
Lennart Poettering | ead2a4a231 | |
Lennart Poettering | f742f9d317 | |
Lennart Poettering | 82c8bda1f1 | |
Lennart Poettering | 0497c4c28a | |
Lennart Poettering | e2b5546452 | |
Lennart Poettering | 57ee010ff2 | |
Marc-André Lureau | dd1d306058 | |
Marc-André Lureau | 2d95d81f7b |
2
TODO
2
TODO
|
@ -22,8 +22,6 @@ Janitorial Clean-ups:
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
* random-util: make user of new GRND_INSECURE flag wherever possible
|
|
||||||
|
|
||||||
* nspawn: support time namespaces
|
* nspawn: support time namespaces
|
||||||
|
|
||||||
* pid1: Move to tracking of main pid/control pid of units per pidfd
|
* pid1: Move to tracking of main pid/control pid of units per pidfd
|
||||||
|
|
|
@ -193,6 +193,10 @@ sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/07/201
|
||||||
sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
|
sensor:modalias:acpi:BOSC0200*:dmi:bvnAmericanMegatrendsInc.:bvr5.11:bd05/28/2016:svnDefaultstring:pnDefaultstring:pvrDefaultstring:rvnHampoo:rnCherryTrailCR:rvrDefaultstring:cvnDefaultstring:ct3:cvrDefaultstring:
|
||||||
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
||||||
|
|
||||||
|
# Chuwi HiBook Pro (CWI526)
|
||||||
|
sensor:modalias:acpi:BOSC0200*:dmi:*:svnHampoo*:pnP1D6_C109K:*
|
||||||
|
ACCEL_MOUNT_MATRIX=1, 0, 0; 0, -1, 0; 0, 0, 1
|
||||||
|
|
||||||
# Chuwi CoreBook
|
# Chuwi CoreBook
|
||||||
# Chuwi CoreBook does not have its product name filled, so we
|
# Chuwi CoreBook does not have its product name filled, so we
|
||||||
# match the entire dmi-alias
|
# match the entire dmi-alias
|
||||||
|
|
|
@ -1748,6 +1748,14 @@
|
||||||
Defaults to false.</para>
|
Defaults to false.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>SendOption=</varname></term>
|
||||||
|
<listitem>
|
||||||
|
<para>As in the <literal>[DHCPv4]</literal> section, however because DHCPv6 uses 16-bit fields to store
|
||||||
|
option numbers, the option number is an integer in the range 1..65536.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -1985,7 +1993,7 @@
|
||||||
<para>Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type
|
<para>Send a raw option with value via DHCPv4 server. Takes a DHCP option number, data type
|
||||||
and data (<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
|
and data (<literal><replaceable>option</replaceable>:<replaceable>type</replaceable>:<replaceable>value</replaceable></literal>).
|
||||||
The option number is an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
|
The option number is an integer in the range 1..254. The type takes one of <literal>uint8</literal>,
|
||||||
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, or
|
<literal>uint16</literal>, <literal>uint32</literal>, <literal>ipv4address</literal>, <literal>ipv6address</literal>, or
|
||||||
<literal>string</literal>. Special characters in the data string may be escaped using
|
<literal>string</literal>. Special characters in the data string may be escaped using
|
||||||
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
|
<ulink url="https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences">C-style
|
||||||
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
|
escapes</ulink>. This setting can be specified multiple times. If an empty string is specified,
|
||||||
|
|
|
@ -845,35 +845,41 @@
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>SuccessExitStatus=</varname></term>
|
<term><varname>SuccessExitStatus=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Takes a list of exit status definitions that, when returned by the main service
|
<listitem><para>Takes a list of exit status definitions that, when returned by the main service
|
||||||
process, will be considered successful termination, in addition to the normal successful exit code 0
|
process, will be considered successful termination, in addition to the normal successful exit status
|
||||||
and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
|
0 and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
|
||||||
<constant>SIGTERM</constant>, and <constant>SIGPIPE</constant>. Exit status definitions can be
|
<constant>SIGTERM</constant>, and <constant>SIGPIPE</constant>. Exit status definitions can be
|
||||||
numeric exit codes, termination code names, or termination signal names, separated by spaces. See the
|
numeric termination statuses, termination status names, or termination signal names, separated by
|
||||||
Process Exit Codes section in
|
spaces. See the Process Exit Codes section in
|
||||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||||
a list of termination codes names (for this setting only the part without the
|
a list of termination status names (for this setting only the part without the
|
||||||
<literal>EXIT_</literal> or <literal>EX_</literal> prefix should be used). See
|
<literal>EXIT_</literal> or <literal>EX_</literal> prefix should be used). See <citerefentry
|
||||||
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||||
a list of signal names.</para>
|
a list of signal names.</para>
|
||||||
|
|
||||||
<para>This option may appear more than once, in which case the
|
<para>Note that this setting does not change the the mapping between numeric exit statuses and their
|
||||||
list of successful exit statuses is merged. If the empty
|
names, i.e. regardless how this setting is used 0 will still be mapped to <literal>SUCCESS</literal>
|
||||||
string is assigned to this option, the list is reset, all
|
(and thus typically shown as <literal>0/SUCCESS</literal> in tool outputs) and 1 to
|
||||||
prior assignments of this option will have no
|
<literal>FAILURE</literal> (and thus typically shown as <literal>1/FAILURE</literal>), and so on. It
|
||||||
effect.</para>
|
only controls what happens as effect of these exit statuses, and how it propagates to the state of
|
||||||
|
the service as a whole.</para>
|
||||||
|
|
||||||
|
<para>This option may appear more than once, in which case the list of successful exit statuses is
|
||||||
|
merged. If the empty string is assigned to this option, the list is reset, all prior assignments of
|
||||||
|
this option will have no effect.</para>
|
||||||
|
|
||||||
<example>
|
<example>
|
||||||
<title>A service with with the <varname>SuccessExitStatus=</varname> setting</title>
|
<title>A service with with the <varname>SuccessExitStatus=</varname> setting</title>
|
||||||
|
|
||||||
<programlisting>SuccessExitStatus=TEMPFAIL 250 SIGUSR1</programlisting>
|
<programlisting>SuccessExitStatus=TEMPFAIL 250 SIGUSR1</programlisting>
|
||||||
|
|
||||||
<para>Exit codes 75 (<constant>TEMPFAIL</constant>), 250, and the termination signal
|
<para>Exit status 75 (<constant>TEMPFAIL</constant>), 250, and the termination signal
|
||||||
<constant>SIGKILL</constant> are considered clean service terminations.</para>
|
<constant>SIGKILL</constant> are considered clean service terminations.</para>
|
||||||
</example>
|
</example>
|
||||||
|
|
||||||
<para>Note: <command>systemd-analyze exit-status</command> may be used to list exit
|
<para>Note: <command>systemd-analyze exit-status</command> may be used to list exit statuses and
|
||||||
codes and translate between numerical code values and names.</para></listitem>
|
translate between numerical status values and names.</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -121,16 +121,19 @@ A+ /path-or-glob/to/append/acls/recursively - - - - POSIX
|
||||||
<filename>/usr/lib/tmpfiles.d</filename> and <filename>/run/tmpfiles.d</filename>. Files in
|
<filename>/usr/lib/tmpfiles.d</filename> and <filename>/run/tmpfiles.d</filename>. Files in
|
||||||
<filename>/run/tmpfiles.d</filename> override files with the same name in
|
<filename>/run/tmpfiles.d</filename> override files with the same name in
|
||||||
<filename>/usr/lib/tmpfiles.d</filename>. Packages should install their configuration files in
|
<filename>/usr/lib/tmpfiles.d</filename>. Packages should install their configuration files in
|
||||||
<filename>/usr/lib/tmpfiles.d</filename>. Files in <filename>/etc/tmpfiles.d</filename> are reserved for the local
|
<filename>/usr/lib/tmpfiles.d</filename>. Files in <filename>/etc/tmpfiles.d</filename> are reserved for
|
||||||
administrator, who may use this logic to override the configuration files installed by vendor packages. All
|
the local administrator, who may use this logic to override the configuration files installed by vendor
|
||||||
configuration files are sorted by their filename in lexicographic order, regardless of which of the directories
|
packages. All configuration files are sorted by their filename in lexicographic order, regardless of
|
||||||
they reside in. If multiple files specify the same path, the entry in the file with the lexicographically earliest
|
which of the directories they reside in. If multiple files specify the same path, the entry in the file
|
||||||
name will be applied. All other conflicting entries will be logged as errors. When two lines are prefix path and
|
with the lexicographically earliest name will be applied (note that lines suppressed due to the
|
||||||
suffix path of each other, then the prefix line is always created first, the suffix later (and if removal applies
|
<literal>!</literal> are filtered before application, meaning that if an early line carries the
|
||||||
to the line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are
|
exclamation mark and is suppressed because of that, a later line matching in path will be applied). All
|
||||||
applied after those accepting no globs. If multiple operations shall be applied on the same file (such as ACL,
|
other conflicting entries will be logged as errors. When two lines are prefix path and suffix path of
|
||||||
xattr, file attribute adjustments), these are always done in the same fixed order. Except for those cases, the
|
each other, then the prefix line is always created first, the suffix later (and if removal applies to the
|
||||||
files/directories are processed in the order they are listed.</para>
|
line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are
|
||||||
|
applied after those accepting no globs. If multiple operations shall be applied on the same file (such as
|
||||||
|
ACL, xattr, file attribute adjustments), these are always done in the same fixed order. Except for those
|
||||||
|
cases, the files/directories are processed in the order they are listed.</para>
|
||||||
|
|
||||||
<para>If the administrator wants to disable a configuration file
|
<para>If the administrator wants to disable a configuration file
|
||||||
supplied by the vendor, the recommended way is to place a symlink
|
supplied by the vendor, the recommended way is to place a symlink
|
||||||
|
@ -154,8 +157,8 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||||
<refsect2>
|
<refsect2>
|
||||||
<title>Type</title>
|
<title>Type</title>
|
||||||
|
|
||||||
<para>The type consists of a single letter and optionally an
|
<para>The type consists of a single letter and optionally an exclamation mark (<literal>!</literal>)
|
||||||
exclamation mark and/or minus sign.</para>
|
and/or minus sign (<literal>-</literal>).</para>
|
||||||
|
|
||||||
<para>The following line types are understood:</para>
|
<para>The following line types are understood:</para>
|
||||||
|
|
||||||
|
@ -453,13 +456,10 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>If the exclamation mark is used, this line is only safe to
|
<para>If the exclamation mark (<literal>!</literal>) is used, this line is only safe to execute during
|
||||||
execute during boot, and can break a running system. Lines
|
boot, and can break a running system. Lines without the exclamation mark are presumed to be safe to
|
||||||
without the exclamation mark are presumed to be safe to execute
|
execute at any time, e.g. on package upgrades. <command>systemd-tmpfiles</command> will take lines with
|
||||||
at any time, e.g. on package upgrades.
|
an exclamation mark only into consideration, if the <option>--boot</option> option is given.</para>
|
||||||
<command>systemd-tmpfiles</command> will execute line with an
|
|
||||||
exclamation mark only if option <option>--boot</option> is
|
|
||||||
given.</para>
|
|
||||||
|
|
||||||
<para>For example:
|
<para>For example:
|
||||||
<programlisting># Make sure these are created by default so that nobody else can
|
<programlisting># Make sure these are created by default so that nobody else can
|
||||||
|
@ -471,9 +471,8 @@ r! /tmp/.X[0-9]*-lock</programlisting>
|
||||||
running system, and will only be executed with
|
running system, and will only be executed with
|
||||||
<option>--boot</option>.</para>
|
<option>--boot</option>.</para>
|
||||||
|
|
||||||
<para>If the minus sign is used, this line failing to run
|
<para>If the minus sign (<literal>-</literal>) is used, this line failing to run successfully during
|
||||||
successfully during create (and only create) will not cause
|
create (and only create) will not cause the execution of <command>systemd-tmpfiles</command> to return
|
||||||
the execution of <command>systemd-tmpfiles</command> to return
|
|
||||||
an error.</para>
|
an error.</para>
|
||||||
|
|
||||||
<para>For example:
|
<para>For example:
|
||||||
|
|
|
@ -14,3 +14,7 @@
|
||||||
#ifndef GRND_RANDOM
|
#ifndef GRND_RANDOM
|
||||||
#define GRND_RANDOM 0x0002
|
#define GRND_RANDOM 0x0002
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef GRND_INSECURE
|
||||||
|
#define GRND_INSECURE 0x0004
|
||||||
|
#endif
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
|
#include "errno-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
#include "fileio.h"
|
#include "fileio.h"
|
||||||
#include "io-util.h"
|
#include "io-util.h"
|
||||||
|
@ -207,7 +208,9 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||||
if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
|
if (have_syscall != 0 && !HAS_FEATURE_MEMORY_SANITIZER) {
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
r = getrandom(p, n, FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK);
|
r = getrandom(p, n,
|
||||||
|
(FLAGS_SET(flags, RANDOM_BLOCK) ? 0 : GRND_NONBLOCK) |
|
||||||
|
(FLAGS_SET(flags, RANDOM_ALLOW_INSECURE) ? GRND_INSECURE : 0));
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
have_syscall = true;
|
have_syscall = true;
|
||||||
|
|
||||||
|
@ -237,7 +240,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||||
have_syscall = true;
|
have_syscall = true;
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
} else if (errno == ENOSYS) {
|
} else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
||||||
/* We lack the syscall, continue with reading from /dev/urandom. */
|
/* We lack the syscall, continue with reading from /dev/urandom. */
|
||||||
have_syscall = false;
|
have_syscall = false;
|
||||||
break;
|
break;
|
||||||
|
@ -263,6 +266,18 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||||
|
|
||||||
/* Use /dev/urandom instead */
|
/* Use /dev/urandom instead */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
} else if (errno == EINVAL) {
|
||||||
|
|
||||||
|
/* Most likely: unknown flag. We know that GRND_INSECURE might cause this,
|
||||||
|
* hence try without. */
|
||||||
|
|
||||||
|
if (FLAGS_SET(flags, RANDOM_ALLOW_INSECURE)) {
|
||||||
|
flags = flags &~ RANDOM_ALLOW_INSECURE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -errno;
|
||||||
} else
|
} else
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
@ -325,9 +340,11 @@ void initialize_srand(void) {
|
||||||
|
|
||||||
/* INT_MAX gives us only 31 bits, so use 24 out of that. */
|
/* INT_MAX gives us only 31 bits, so use 24 out of that. */
|
||||||
#if RAND_MAX >= INT_MAX
|
#if RAND_MAX >= INT_MAX
|
||||||
|
assert_cc(RAND_MAX >= 16777215);
|
||||||
# define RAND_STEP 3
|
# define RAND_STEP 3
|
||||||
#else
|
#else
|
||||||
/* SHORT_INT_MAX or lower gives at most 15 bits, we just just 8 out of that. */
|
/* SHORT_INT_MAX or lower gives at most 15 bits, we just use 8 out of that. */
|
||||||
|
assert_cc(RAND_MAX >= 255);
|
||||||
# define RAND_STEP 1
|
# define RAND_STEP 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -392,7 +409,7 @@ void random_bytes(void *p, size_t n) {
|
||||||
* This function is hence not useful for generating UUIDs or cryptographic key material.
|
* This function is hence not useful for generating UUIDs or cryptographic key material.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
|
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND|RANDOM_ALLOW_INSECURE) >= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */
|
||||||
|
|
|
@ -10,6 +10,7 @@ typedef enum RandomFlags {
|
||||||
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
|
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
|
||||||
RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
|
RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
|
||||||
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
|
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
|
||||||
|
RANDOM_ALLOW_INSECURE = 1 << 4, /* Allow usage of GRND_INSECURE flag to kernel's getrandom() API */
|
||||||
} RandomFlags;
|
} RandomFlags;
|
||||||
|
|
||||||
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
|
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
|
||||||
|
|
|
@ -19,6 +19,7 @@ typedef enum DHCPRawOption {
|
||||||
DHCP_RAW_OPTION_DATA_UINT32,
|
DHCP_RAW_OPTION_DATA_UINT32,
|
||||||
DHCP_RAW_OPTION_DATA_STRING,
|
DHCP_RAW_OPTION_DATA_STRING,
|
||||||
DHCP_RAW_OPTION_DATA_IPV4ADDRESS,
|
DHCP_RAW_OPTION_DATA_IPV4ADDRESS,
|
||||||
|
DHCP_RAW_OPTION_DATA_IPV6ADDRESS,
|
||||||
_DHCP_RAW_OPTION_DATA_MAX,
|
_DHCP_RAW_OPTION_DATA_MAX,
|
||||||
_DHCP_RAW_OPTION_DATA_INVALID,
|
_DHCP_RAW_OPTION_DATA_INVALID,
|
||||||
} DHCPRawOption;
|
} DHCPRawOption;
|
||||||
|
|
|
@ -14,6 +14,16 @@
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "sparse-endian.h"
|
#include "sparse-endian.h"
|
||||||
|
|
||||||
|
typedef struct sd_dhcp6_option {
|
||||||
|
unsigned n_ref;
|
||||||
|
|
||||||
|
uint16_t option;
|
||||||
|
void *data;
|
||||||
|
size_t length;
|
||||||
|
} sd_dhcp6_option;
|
||||||
|
|
||||||
|
extern const struct hash_ops dhcp6_option_hash_ops;
|
||||||
|
|
||||||
/* Common option header */
|
/* Common option header */
|
||||||
typedef struct DHCP6Option {
|
typedef struct DHCP6Option {
|
||||||
be16_t code;
|
be16_t code;
|
||||||
|
|
|
@ -597,3 +597,43 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char *
|
||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sd_dhcp6_option* dhcp6_option_free(sd_dhcp6_option *i) {
|
||||||
|
if (!i)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
free(i->data);
|
||||||
|
return mfree(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, sd_dhcp6_option **ret) {
|
||||||
|
assert_return(ret, -EINVAL);
|
||||||
|
assert_return(length == 0 || data, -EINVAL);
|
||||||
|
|
||||||
|
_cleanup_free_ void *q = memdup(data, length);
|
||||||
|
if (!q)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
sd_dhcp6_option *p = new(sd_dhcp6_option, 1);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
*p = (sd_dhcp6_option) {
|
||||||
|
.n_ref = 1,
|
||||||
|
.option = option,
|
||||||
|
.length = length,
|
||||||
|
.data = TAKE_PTR(q),
|
||||||
|
};
|
||||||
|
|
||||||
|
*ret = p;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_TRIVIAL_REF_UNREF_FUNC(sd_dhcp6_option, sd_dhcp6_option, dhcp6_option_free);
|
||||||
|
DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||||
|
dhcp6_option_hash_ops,
|
||||||
|
void,
|
||||||
|
trivial_hash_func,
|
||||||
|
trivial_compare_func,
|
||||||
|
sd_dhcp6_option,
|
||||||
|
sd_dhcp6_option_unref);
|
||||||
|
|
|
@ -78,6 +78,7 @@ struct sd_dhcp6_client {
|
||||||
size_t duid_len;
|
size_t duid_len;
|
||||||
usec_t information_request_time_usec;
|
usec_t information_request_time_usec;
|
||||||
usec_t information_refresh_time_usec;
|
usec_t information_refresh_time_usec;
|
||||||
|
OrderedHashmap *extra_options;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint16_t default_req_opts[] = {
|
static const uint16_t default_req_opts[] = {
|
||||||
|
@ -447,6 +448,24 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v) {
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert_return(client, -EINVAL);
|
||||||
|
assert_return(v, -EINVAL);
|
||||||
|
|
||||||
|
r = ordered_hashmap_ensure_allocated(&client->extra_options, &dhcp6_option_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = ordered_hashmap_put(client->extra_options, UINT_TO_PTR(v->option), v);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
sd_dhcp6_option_ref(v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void client_notify(sd_dhcp6_client *client, int event) {
|
static void client_notify(sd_dhcp6_client *client, int event) {
|
||||||
assert(client);
|
assert(client);
|
||||||
|
|
||||||
|
@ -492,7 +511,9 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||||
_cleanup_free_ DHCP6Message *message = NULL;
|
_cleanup_free_ DHCP6Message *message = NULL;
|
||||||
struct in6_addr all_servers =
|
struct in6_addr all_servers =
|
||||||
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
|
IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
|
||||||
|
struct sd_dhcp6_option *j;
|
||||||
size_t len, optlen = 512;
|
size_t len, optlen = 512;
|
||||||
|
Iterator i;
|
||||||
uint8_t *opt;
|
uint8_t *opt;
|
||||||
int r;
|
int r;
|
||||||
usec_t elapsed_usec;
|
usec_t elapsed_usec;
|
||||||
|
@ -672,6 +693,12 @@ static int client_send_message(sd_dhcp6_client *client, usec_t time_now) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
ORDERED_HASHMAP_FOREACH(j, client->extra_options, i) {
|
||||||
|
r = dhcp6_option_append(&opt, &optlen, j->option, j->length, j->data);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
|
r = dhcp6_network_send_udp_socket(client->fd, &all_servers, message,
|
||||||
len - optlen);
|
len - optlen);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
@ -1584,6 +1611,7 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
|
||||||
free(client->req_opts);
|
free(client->req_opts);
|
||||||
free(client->fqdn);
|
free(client->fqdn);
|
||||||
free(client->mudurl);
|
free(client->mudurl);
|
||||||
|
ordered_hashmap_free(client->extra_options);
|
||||||
return mfree(client);
|
return mfree(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
|
||||||
#include "dhcp-internal.h"
|
#include "dhcp-internal.h"
|
||||||
|
#include "dhcp6-internal.h"
|
||||||
#include "escape.h"
|
#include "escape.h"
|
||||||
#include "in-addr-util.h"
|
#include "in-addr-util.h"
|
||||||
#include "networkd-dhcp-common.h"
|
#include "networkd-dhcp-common.h"
|
||||||
|
@ -320,13 +321,14 @@ int config_parse_dhcp_send_option(
|
||||||
void *data,
|
void *data,
|
||||||
void *userdata) {
|
void *userdata) {
|
||||||
|
|
||||||
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt = NULL, *old = NULL;
|
_cleanup_(sd_dhcp_option_unrefp) sd_dhcp_option *opt4 = NULL, *old4 = NULL;
|
||||||
|
_cleanup_(sd_dhcp6_option_unrefp) sd_dhcp6_option *opt6 = NULL, *old6 = NULL;
|
||||||
_cleanup_free_ char *word = NULL, *q = NULL;
|
_cleanup_free_ char *word = NULL, *q = NULL;
|
||||||
OrderedHashmap **options = data;
|
OrderedHashmap **options = data;
|
||||||
union in_addr_union addr;
|
union in_addr_union addr;
|
||||||
DHCPOptionDataType type;
|
DHCPOptionDataType type;
|
||||||
uint8_t u, uint8_data;
|
uint8_t u8, uint8_data;
|
||||||
uint16_t uint16_data;
|
uint16_t u16, uint16_data;
|
||||||
uint32_t uint32_data;
|
uint32_t uint32_data;
|
||||||
const void *udata;
|
const void *udata;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
@ -353,16 +355,30 @@ int config_parse_dhcp_send_option(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = safe_atou8(word, &u);
|
if (ltype == AF_INET6) {
|
||||||
if (r < 0) {
|
r = safe_atou16(word, &u16);
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
if (r < 0) {
|
||||||
"Invalid DHCP option, ignoring assignment: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
return 0;
|
"Invalid DHCP option, ignoring assignment: %s", rvalue);
|
||||||
}
|
return 0;
|
||||||
if (u < 1 || u >= 255) {
|
}
|
||||||
log_syntax(unit, LOG_ERR, filename, line, 0,
|
if (u16 < 1 || u16 >= 65535) {
|
||||||
"Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||||
return 0;
|
"Invalid DHCP option, valid range is 1-65535, ignoring assignment: %s", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r = safe_atou8(word, &u8);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Invalid DHCP option, ignoring assignment: %s", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (u8 < 1 || u8 >= 255) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0,
|
||||||
|
"Invalid DHCP option, valid range is 1-254, ignoring assignment: %s", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
word = mfree(word);
|
word = mfree(word);
|
||||||
|
@ -387,7 +403,7 @@ int config_parse_dhcp_send_option(
|
||||||
r = safe_atou8(p, &uint8_data);
|
r = safe_atou8(p, &uint8_data);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
"Failed to parse DHCPv4 uint8 data, ignoring assignment: %s", p);
|
"Failed to parse DHCP uint8 data, ignoring assignment: %s", p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +415,7 @@ int config_parse_dhcp_send_option(
|
||||||
r = safe_atou16(p, &uint16_data);
|
r = safe_atou16(p, &uint16_data);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
"Failed to parse DHCPv4 uint16 data, ignoring assignment: %s", p);
|
"Failed to parse DHCP uint16 data, ignoring assignment: %s", p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -411,7 +427,7 @@ int config_parse_dhcp_send_option(
|
||||||
r = safe_atou32(p, &uint32_data);
|
r = safe_atou32(p, &uint32_data);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
"Failed to parse DHCPv4 uint32 data, ignoring assignment: %s", p);
|
"Failed to parse DHCP uint32 data, ignoring assignment: %s", p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +440,7 @@ int config_parse_dhcp_send_option(
|
||||||
r = in_addr_from_string(AF_INET, p, &addr);
|
r = in_addr_from_string(AF_INET, p, &addr);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
"Failed to parse DHCPv4 ipv4address data, ignoring assignment: %s", p);
|
"Failed to parse DHCP ipv4address data, ignoring assignment: %s", p);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,11 +448,23 @@ int config_parse_dhcp_send_option(
|
||||||
sz = sizeof(addr.in.s_addr);
|
sz = sizeof(addr.in.s_addr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DHCP_OPTION_DATA_IPV6ADDRESS: {
|
||||||
|
r = in_addr_from_string(AF_INET6, p, &addr);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Failed to parse DHCP ipv6address data, ignoring assignment: %s", p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
udata = &addr.in6;
|
||||||
|
sz = sizeof(addr.in6.s6_addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DHCP_OPTION_DATA_STRING:
|
case DHCP_OPTION_DATA_STRING:
|
||||||
sz = cunescape(p, UNESCAPE_ACCEPT_NUL, &q);
|
sz = cunescape(p, UNESCAPE_ACCEPT_NUL, &q);
|
||||||
if (sz < 0) {
|
if (sz < 0) {
|
||||||
log_syntax(unit, LOG_ERR, filename, line, sz,
|
log_syntax(unit, LOG_ERR, filename, line, sz,
|
||||||
"Failed to decode DHCPv4 option data, ignoring assignment: %s", p);
|
"Failed to decode DHCP option data, ignoring assignment: %s", p);
|
||||||
}
|
}
|
||||||
|
|
||||||
udata = q;
|
udata = q;
|
||||||
|
@ -445,27 +473,49 @@ int config_parse_dhcp_send_option(
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_dhcp_option_new(u, udata, sz, &opt);
|
if (ltype == AF_INET6) {
|
||||||
if (r < 0) {
|
r = sd_dhcp6_option_new(u16, udata, sz, &opt6);
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
if (r < 0) {
|
||||||
"Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
return 0;
|
"Failed to store DHCP option '%s', ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = ordered_hashmap_ensure_allocated(options, &dhcp6_option_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
/* Overwrite existing option */
|
||||||
|
old6 = ordered_hashmap_get(*options, UINT_TO_PTR(u16));
|
||||||
|
r = ordered_hashmap_replace(*options, UINT_TO_PTR(u16), opt6);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Failed to store DHCP option '%s', ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TAKE_PTR(opt6);
|
||||||
|
} else {
|
||||||
|
r = sd_dhcp_option_new(u8, udata, sz, &opt4);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Failed to store DHCP option '%s', ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = ordered_hashmap_ensure_allocated(options, &dhcp_option_hash_ops);
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
/* Overwrite existing option */
|
||||||
|
old4 = ordered_hashmap_get(*options, UINT_TO_PTR(u8));
|
||||||
|
r = ordered_hashmap_replace(*options, UINT_TO_PTR(u8), opt4);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r,
|
||||||
|
"Failed to store DHCP option '%s', ignoring assignment: %m", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
TAKE_PTR(opt4);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = ordered_hashmap_ensure_allocated(options, &dhcp_option_hash_ops);
|
|
||||||
if (r < 0)
|
|
||||||
return log_oom();
|
|
||||||
|
|
||||||
/* Overwrite existing option */
|
|
||||||
old = ordered_hashmap_remove(*options, UINT_TO_PTR(u));
|
|
||||||
r = ordered_hashmap_put(*options, UINT_TO_PTR(u), opt);
|
|
||||||
if (r < 0) {
|
|
||||||
log_syntax(unit, LOG_ERR, filename, line, r,
|
|
||||||
"Failed to store DHCPv4 option '%s', ignoring assignment: %m", rvalue);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
TAKE_PTR(opt);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,6 +536,7 @@ static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = {
|
||||||
[DHCP_OPTION_DATA_UINT32] = "uint32",
|
[DHCP_OPTION_DATA_UINT32] = "uint32",
|
||||||
[DHCP_OPTION_DATA_STRING] = "string",
|
[DHCP_OPTION_DATA_STRING] = "string",
|
||||||
[DHCP_OPTION_DATA_IPV4ADDRESS] = "ipv4address",
|
[DHCP_OPTION_DATA_IPV4ADDRESS] = "ipv4address",
|
||||||
|
[DHCP_OPTION_DATA_IPV6ADDRESS] = "ipv6address",
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType);
|
DEFINE_STRING_TABLE_LOOKUP(dhcp_option_data_type, DHCPOptionDataType);
|
||||||
|
|
|
@ -21,6 +21,7 @@ typedef enum DHCPOptionDataType {
|
||||||
DHCP_OPTION_DATA_UINT32,
|
DHCP_OPTION_DATA_UINT32,
|
||||||
DHCP_OPTION_DATA_STRING,
|
DHCP_OPTION_DATA_STRING,
|
||||||
DHCP_OPTION_DATA_IPV4ADDRESS,
|
DHCP_OPTION_DATA_IPV4ADDRESS,
|
||||||
|
DHCP_OPTION_DATA_IPV6ADDRESS,
|
||||||
_DHCP_OPTION_DATA_MAX,
|
_DHCP_OPTION_DATA_MAX,
|
||||||
_DHCP_OPTION_DATA_INVALID,
|
_DHCP_OPTION_DATA_INVALID,
|
||||||
} DHCPOptionDataType;
|
} DHCPOptionDataType;
|
||||||
|
|
|
@ -2,14 +2,17 @@
|
||||||
|
|
||||||
#include "sd-dhcp-server.h"
|
#include "sd-dhcp-server.h"
|
||||||
|
|
||||||
|
#include "fd-util.h"
|
||||||
|
#include "fileio.h"
|
||||||
#include "networkd-dhcp-server.h"
|
#include "networkd-dhcp-server.h"
|
||||||
#include "networkd-link.h"
|
#include "networkd-link.h"
|
||||||
#include "networkd-manager.h"
|
#include "networkd-manager.h"
|
||||||
#include "networkd-network.h"
|
#include "networkd-network.h"
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "strv.h"
|
#include "socket-netlink.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
#include "strv.h"
|
||||||
|
|
||||||
static Address* link_find_dhcp_server_address(Link *link) {
|
static Address* link_find_dhcp_server_address(Link *link) {
|
||||||
Address *address;
|
Address *address;
|
||||||
|
@ -174,6 +177,87 @@ static int link_push_uplink_to_dhcp_server(
|
||||||
return sd_dhcp_server_set_servers(s, what, addresses, n_addresses);
|
return sd_dhcp_server_set_servers(s, what, addresses, n_addresses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dhcp4_server_parse_dns_server_string_and_warn(Link *l, const char *string, struct in_addr **addresses, size_t *n_allocated, size_t *n_addresses) {
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *word = NULL, *server_name = NULL;
|
||||||
|
union in_addr_union address;
|
||||||
|
int family, r, ifindex = 0;
|
||||||
|
|
||||||
|
r = extract_first_word(&string, &word, NULL, 0);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = in_addr_ifindex_name_from_string_auto(word, &family, &address, &ifindex, &server_name);
|
||||||
|
if (r < 0) {
|
||||||
|
log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring: %m", word);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Only look for IPv4 addresses */
|
||||||
|
if (family != AF_INET)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Never propagate obviously borked data */
|
||||||
|
if (in4_addr_is_null(&address.in) || in4_addr_is_localhost(&address.in))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!GREEDY_REALLOC(*addresses, *n_allocated, *n_addresses + 1))
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
(*addresses)[(*n_addresses)++] = address.in;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dhcp4_server_set_dns_from_resolve_conf(Link *link) {
|
||||||
|
_cleanup_free_ struct in_addr *addresses = NULL;
|
||||||
|
size_t n_addresses = 0, n_allocated = 0;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
int n = 0, r;
|
||||||
|
|
||||||
|
f = fopen(PRIVATE_UPLINK_RESOLV_CONF, "re");
|
||||||
|
if (!f) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return log_warning_errno(errno, "Failed to open " PRIVATE_UPLINK_RESOLV_CONF ": %m");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
_cleanup_free_ char *line = NULL;
|
||||||
|
const char *a;
|
||||||
|
char *l;
|
||||||
|
|
||||||
|
r = read_line(f, LONG_LINE_MAX, &line);
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to read " PRIVATE_UPLINK_RESOLV_CONF ": %m");
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n++;
|
||||||
|
|
||||||
|
l = strstrip(line);
|
||||||
|
if (IN_SET(*l, '#', ';', 0))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
a = first_word(l, "nameserver");
|
||||||
|
if (!a)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r = dhcp4_server_parse_dns_server_string_and_warn(link, a, &addresses, &n_allocated, &n_addresses);
|
||||||
|
if (r < 0)
|
||||||
|
log_warning_errno(r, "Failed to parse DNS server address '%s', ignoring.", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_addresses <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return sd_dhcp_server_set_dns(link->dhcp_server, addresses, n_addresses);
|
||||||
|
}
|
||||||
|
|
||||||
int dhcp4_server_configure(Link *link) {
|
int dhcp4_server_configure(Link *link) {
|
||||||
bool acquired_uplink = false;
|
bool acquired_uplink = false;
|
||||||
sd_dhcp_option *p;
|
sd_dhcp_option *p;
|
||||||
|
@ -267,8 +351,10 @@ int dhcp4_server_configure(Link *link) {
|
||||||
"Not emitting %s on link, couldn't find suitable uplink.",
|
"Not emitting %s on link, couldn't find suitable uplink.",
|
||||||
dhcp_lease_info_to_string(n));
|
dhcp_lease_info_to_string(n));
|
||||||
r = 0;
|
r = 0;
|
||||||
} else
|
} else if (uplink->network)
|
||||||
r = link_push_uplink_to_dhcp_server(uplink, n, link->dhcp_server);
|
r = link_push_uplink_to_dhcp_server(uplink, n, link->dhcp_server);
|
||||||
|
else if (n == SD_DHCP_LEASE_DNS_SERVERS)
|
||||||
|
r = dhcp4_server_set_dns_from_resolve_conf(link);
|
||||||
}
|
}
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
log_link_warning_errno(link, r,
|
log_link_warning_errno(link, r,
|
||||||
|
|
|
@ -620,7 +620,9 @@ static int dhcp6_set_hostname(sd_dhcp6_client *client, Link *link) {
|
||||||
|
|
||||||
int dhcp6_configure(Link *link) {
|
int dhcp6_configure(Link *link) {
|
||||||
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
|
_cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
|
||||||
|
sd_dhcp6_option *send_option;
|
||||||
const DUID *duid;
|
const DUID *duid;
|
||||||
|
Iterator i;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(link);
|
assert(link);
|
||||||
|
@ -662,6 +664,14 @@ int dhcp6_configure(Link *link) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m");
|
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set DUID: %m");
|
||||||
|
|
||||||
|
ORDERED_HASHMAP_FOREACH(send_option, link->network->dhcp6_client_send_options, i) {
|
||||||
|
r = sd_dhcp6_client_add_option(client, send_option);
|
||||||
|
if (r == -EEXIST)
|
||||||
|
continue;
|
||||||
|
if (r < 0)
|
||||||
|
return log_link_error_errno(link, r, "DHCP6 CLIENT: Failed to set option: %m");
|
||||||
|
}
|
||||||
|
|
||||||
r = dhcp6_set_hostname(client, link);
|
r = dhcp6_set_hostname(client, link);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -185,7 +185,7 @@ DHCPv4.SendRelease, config_parse_bool,
|
||||||
DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline)
|
DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline)
|
||||||
DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0
|
DHCPv4.BlackList, config_parse_dhcp_black_listed_ip_address, 0, 0
|
||||||
DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, ip_service_type)
|
DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, ip_service_type)
|
||||||
DHCPv4.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_options)
|
DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, offsetof(Network, dhcp_client_send_options)
|
||||||
DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options)
|
DHCPv4.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_client_send_vendor_options)
|
||||||
DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
|
DHCPv4.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
|
||||||
DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns)
|
DHCPv6.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp6_use_dns)
|
||||||
|
@ -195,6 +195,7 @@ DHCPv6.MUDURL, config_parse_dhcp6_mud_url,
|
||||||
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
||||||
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
||||||
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
|
DHCPv6.WithoutRA, config_parse_bool, 0, offsetof(Network, dhcp6_without_ra)
|
||||||
|
DHCPv6.SendOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_options)
|
||||||
IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
|
IPv6AcceptRA.UseAutonomousPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_autonomous_prefix)
|
||||||
IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
|
IPv6AcceptRA.UseOnLinkPrefix, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_onlink_prefix)
|
||||||
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
|
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
|
||||||
|
|
|
@ -133,6 +133,7 @@ struct Network {
|
||||||
uint8_t dhcp6_pd_length;
|
uint8_t dhcp6_pd_length;
|
||||||
char *dhcp6_mudurl;
|
char *dhcp6_mudurl;
|
||||||
struct in6_addr dhcp6_pd_address;
|
struct in6_addr dhcp6_pd_address;
|
||||||
|
OrderedHashmap *dhcp6_client_send_options;
|
||||||
|
|
||||||
/* DHCP Server Support */
|
/* DHCP Server Support */
|
||||||
bool dhcp_server;
|
bool dhcp_server;
|
||||||
|
|
|
@ -64,8 +64,6 @@ systemd_resolved_sources = files('''
|
||||||
resolved-etc-hosts.h
|
resolved-etc-hosts.h
|
||||||
resolved-etc-hosts.c
|
resolved-etc-hosts.c
|
||||||
resolved-dnstls.h
|
resolved-dnstls.h
|
||||||
resolved-util.c
|
|
||||||
resolved-util.h
|
|
||||||
'''.split())
|
'''.split())
|
||||||
|
|
||||||
resolvectl_sources = files('''
|
resolvectl_sources = files('''
|
||||||
|
@ -230,10 +228,4 @@ tests += [
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
'ENABLE_RESOLVE', 'manual'],
|
'ENABLE_RESOLVE', 'manual'],
|
||||||
|
|
||||||
[['src/resolve/test-resolved-util.c',
|
|
||||||
'src/resolve/resolved-util.c',
|
|
||||||
'src/resolve/resolved-util.h'],
|
|
||||||
[],
|
|
||||||
[]],
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
#include "parse-util.h"
|
#include "parse-util.h"
|
||||||
#include "resolved-conf.h"
|
#include "resolved-conf.h"
|
||||||
#include "resolved-dnssd.h"
|
#include "resolved-dnssd.h"
|
||||||
#include "resolved-util.h"
|
|
||||||
#include "resolved-manager.h"
|
#include "resolved-manager.h"
|
||||||
#include "resolved-dns-search-domain.h"
|
#include "resolved-dns-search-domain.h"
|
||||||
#include "dns-domain.h"
|
#include "dns-domain.h"
|
||||||
|
#include "socket-netlink.h"
|
||||||
#include "specifier.h"
|
#include "specifier.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
||||||
|
|
||||||
#include "alloc-util.h"
|
|
||||||
#include "macro.h"
|
|
||||||
#include "resolved-util.h"
|
|
||||||
#include "socket-netlink.h"
|
|
||||||
|
|
||||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) {
|
|
||||||
_cleanup_free_ char *buf = NULL, *name = NULL;
|
|
||||||
const char *m;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
assert(s);
|
|
||||||
|
|
||||||
m = strchr(s, '#');
|
|
||||||
if (m) {
|
|
||||||
name = strdup(m+1);
|
|
||||||
if (!name)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
buf = strndup(s, m - s);
|
|
||||||
if (!buf)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
s = buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex);
|
|
||||||
if (r < 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (server_name)
|
|
||||||
*server_name = TAKE_PTR(name);
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "in-addr-util.h"
|
|
||||||
|
|
||||||
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name);
|
|
|
@ -1,32 +0,0 @@
|
||||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
|
||||||
|
|
||||||
#include "log.h"
|
|
||||||
#include "resolved-util.h"
|
|
||||||
#include "string-util.h"
|
|
||||||
#include "tests.h"
|
|
||||||
|
|
||||||
|
|
||||||
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
|
|
||||||
int family, ifindex;
|
|
||||||
union in_addr_union ua;
|
|
||||||
_cleanup_free_ char *server_name = NULL;
|
|
||||||
|
|
||||||
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
|
|
||||||
assert_se(streq_ptr(server_name, expected));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_in_addr_ifindex_name_from_string_auto(void) {
|
|
||||||
log_info("/* %s */", __func__);
|
|
||||||
|
|
||||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
|
|
||||||
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
|
|
||||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
|
|
||||||
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
test_setup_logging(LOG_DEBUG);
|
|
||||||
|
|
||||||
test_in_addr_ifindex_name_from_string_auto();
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -362,3 +362,33 @@ int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_u
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) {
|
||||||
|
_cleanup_free_ char *buf = NULL, *name = NULL;
|
||||||
|
const char *m;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
m = strchr(s, '#');
|
||||||
|
if (m) {
|
||||||
|
name = strdup(m+1);
|
||||||
|
if (!name)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
buf = strndup(s, m - s);
|
||||||
|
if (!buf)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
s = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (server_name)
|
||||||
|
*server_name = TAKE_PTR(name);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -21,3 +21,4 @@ bool socket_address_is(const SocketAddress *a, const char *s, int type);
|
||||||
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
|
bool socket_address_is_netlink(const SocketAddress *a, const char *s);
|
||||||
|
|
||||||
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
|
int in_addr_ifindex_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex);
|
||||||
|
int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "sd-dhcp6-lease.h"
|
#include "sd-dhcp6-lease.h"
|
||||||
|
#include "sd-dhcp6-option.h"
|
||||||
#include "sd-event.h"
|
#include "sd-event.h"
|
||||||
|
|
||||||
#include "_sd-common.h"
|
#include "_sd-common.h"
|
||||||
|
@ -142,6 +143,8 @@ int sd_dhcp6_client_get_lease(
|
||||||
sd_dhcp6_client *client,
|
sd_dhcp6_client *client,
|
||||||
sd_dhcp6_lease **ret);
|
sd_dhcp6_lease **ret);
|
||||||
|
|
||||||
|
int sd_dhcp6_client_add_option(sd_dhcp6_client *client, sd_dhcp6_option *v);
|
||||||
|
|
||||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
|
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
|
||||||
int sd_dhcp6_client_start(sd_dhcp6_client *client);
|
int sd_dhcp6_client_start(sd_dhcp6_client *client);
|
||||||
int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
|
int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||||
|
#ifndef foosddhcp6optionhfoo
|
||||||
|
#define foosddhcp6optionhfoo
|
||||||
|
|
||||||
|
/***
|
||||||
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
systemd is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include "_sd-common.h"
|
||||||
|
|
||||||
|
_SD_BEGIN_DECLARATIONS;
|
||||||
|
|
||||||
|
typedef struct sd_dhcp6_option sd_dhcp6_option;
|
||||||
|
|
||||||
|
int sd_dhcp6_option_new(uint16_t option, const void *data, size_t length, sd_dhcp6_option **ret);
|
||||||
|
sd_dhcp6_option *sd_dhcp6_option_ref(sd_dhcp6_option *ra);
|
||||||
|
sd_dhcp6_option *sd_dhcp6_option_unref(sd_dhcp6_option *ra);
|
||||||
|
|
||||||
|
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp6_option, sd_dhcp6_option_unref);
|
||||||
|
|
||||||
|
_SD_END_DECLARATIONS;
|
||||||
|
|
||||||
|
#endif
|
|
@ -58,6 +58,7 @@ int main(int argc, char **argv) {
|
||||||
test_genuine_random_bytes(0);
|
test_genuine_random_bytes(0);
|
||||||
test_genuine_random_bytes(RANDOM_BLOCK);
|
test_genuine_random_bytes(RANDOM_BLOCK);
|
||||||
test_genuine_random_bytes(RANDOM_ALLOW_RDRAND);
|
test_genuine_random_bytes(RANDOM_ALLOW_RDRAND);
|
||||||
|
test_genuine_random_bytes(RANDOM_ALLOW_INSECURE);
|
||||||
|
|
||||||
test_pseudo_random_bytes();
|
test_pseudo_random_bytes();
|
||||||
|
|
||||||
|
|
|
@ -245,6 +245,24 @@ static void test_in_addr_ifindex_from_string_auto(void) {
|
||||||
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
|
assert_se(in_addr_ifindex_from_string_auto("fe80::19%thisinterfacecantexist", &family, &ua, &ifindex) == -ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) {
|
||||||
|
int family, ifindex;
|
||||||
|
union in_addr_union ua;
|
||||||
|
_cleanup_free_ char *server_name = NULL;
|
||||||
|
|
||||||
|
assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0);
|
||||||
|
assert_se(streq_ptr(server_name, expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_in_addr_ifindex_name_from_string_auto(void) {
|
||||||
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
|
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL);
|
||||||
|
test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com");
|
||||||
|
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL);
|
||||||
|
test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com");
|
||||||
|
}
|
||||||
|
|
||||||
static void test_sockaddr_equal(void) {
|
static void test_sockaddr_equal(void) {
|
||||||
union sockaddr_union a = {
|
union sockaddr_union a = {
|
||||||
.in.sin_family = AF_INET,
|
.in.sin_family = AF_INET,
|
||||||
|
@ -676,6 +694,7 @@ int main(int argc, char *argv[]) {
|
||||||
test_in_addr_to_string();
|
test_in_addr_to_string();
|
||||||
test_in_addr_ifindex_to_string();
|
test_in_addr_ifindex_to_string();
|
||||||
test_in_addr_ifindex_from_string_auto();
|
test_in_addr_ifindex_from_string_auto();
|
||||||
|
test_in_addr_ifindex_name_from_string_auto();
|
||||||
|
|
||||||
test_sockaddr_equal();
|
test_sockaddr_equal();
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,7 @@ ForceDHCPv6PDOtherInformation=
|
||||||
PrefixDelegationHint=
|
PrefixDelegationHint=
|
||||||
WithoutRA=
|
WithoutRA=
|
||||||
MUDURL=
|
MUDURL=
|
||||||
|
SendOption=
|
||||||
[Route]
|
[Route]
|
||||||
Destination=
|
Destination=
|
||||||
Protocol=
|
Protocol=
|
||||||
|
|
Loading…
Reference in New Issue