1
0
mirror of https://github.com/systemd/systemd synced 2026-03-28 09:44:50 +01:00

Compare commits

..

No commits in common. "9a89ab26d6fefe886815c63e148f4140a3da6955" and "ed938716cdbacb6984d774c49d7740d87f8df810" have entirely different histories.

33 changed files with 573 additions and 852 deletions

View File

@ -50,28 +50,6 @@ service manager.
BPF helpers written in C and used by PID 1 can be found under `src/core/bpf/`. BPF helpers written in C and used by PID 1 can be found under `src/core/bpf/`.
### Implementing Unit Settings
The system and session manager supports a large number of unit settings. These can generally
be configured in three ways:
1. Via textual, INI-style configuration files called *unit* *files*
2. Via D-Bus messages to the manager
3. Via the `systemd-run` and `systemctl set-property` commands
From a user's perspective, the third is a wrapper for the second. To implement a new unit
setting, it is necessary to support all three input methods:
1. *unit* *files* are parsed in `src/core/load-fragment.c`, with many simple and fixed-type
unit settings being parsed by common helpers, with the definition in the generator file
`src/core/load-fragment-gperf.gperf.in`
2. D-Bus messages are defined and parsed in `src/core/dbus-*.c`
3. `systemd-run` and `systemctl set-property` do client-side parsing and translating into
D-Bus messages in `src/shared/bus-unit-util.c`
So that they are exercised by the fuzzing CI, new unit settings should also be listed in the
text files under `test/fuzz/fuzz-unit-file/`.
## UDEV ## UDEV
Sources for the udev daemon and command-line tool (single binary) can be found under Sources for the udev daemon and command-line tool (single binary) can be found under

View File

@ -185,16 +185,11 @@
numeric PCR indexes in the range 0…23. If not used, defaults to PCR 7 only. If an empty string is numeric PCR indexes in the range 0…23. If not used, defaults to PCR 7 only. If an empty string is
specified, binds the enrollment to no PCRs at all. PCRs allow binding the enrollment to specific specified, binds the enrollment to no PCRs at all. PCRs allow binding the enrollment to specific
software versions and system state, so that the enrolled unlocking key is only accessible (may be software versions and system state, so that the enrolled unlocking key is only accessible (may be
"unsealed") if specific trusted software and/or configuration is used.</para> "unsealed") if specific trusted software and/or configuration is used.</para></listitem>
<table> <table>
<title>Well-known PCR Definitions</title> <title>Well-known PCR Definitions</title>
<!-- See: https://trustedcomputinggroup.org/resource/pc-client-specific-platform-firmware-profile-specification/ -->
<!-- See: https://github.com/rhboot/shim/blob/main/README.tpm -->
<!-- See: https://www.gnu.org/software/grub/manual/grub/html_node/Measured-Boot.html -->
<!-- See: https://sourceforge.net/p/linux-ima/wiki/Home/ -->
<tgroup cols='2' align='left' colsep='1' rowsep='1'> <tgroup cols='2' align='left' colsep='1' rowsep='1'>
<colspec colname="pcr" /> <colspec colname="pcr" />
<colspec colname="definition" /> <colspec colname="definition" />
@ -229,7 +224,7 @@
<row> <row>
<entry>4</entry> <entry>4</entry>
<entry>Boot loader; changes on boot loader updates. The shim project will measure the PE binary it chain loads into this PCR.</entry> <entry>Boot loader; changes on boot loader updates</entry>
</row> </row>
<row> <row>
@ -244,39 +239,17 @@
<row> <row>
<entry>7</entry> <entry>7</entry>
<entry>Secure boot state; changes when UEFI SecureBoot mode is enabled/disabled, or firmware certificates (PK, KEK, db, dbx, …) changes. The shim project will measure most of its (non-MOK) certificates and SBAT data into this PCR.</entry> <entry>Secure boot state; changes when UEFI SecureBoot mode is enabled/disabled</entry>
</row> </row>
<row> <row>
<entry>8</entry> <entry>8</entry>
<entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line into this PCR.</entry> <entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
<!-- Grub measures all its commands and the kernel command line into PCR 8 too… -->
</row>
<!-- Grub measures all files it reads (including kernel image, initrd, …) into PCR 9… -->
<row>
<entry>10</entry>
<entry>The IMA project measures its runtime state into this PCR.</entry>
</row>
<row>
<entry>14</entry>
<entry>The shim project measures its "MOK" certificates and hashes into this PCR.</entry>
</row> </row>
</tbody> </tbody>
</tgroup> </tgroup>
</table> </table>
<para>For most applications it should be sufficient to bind against PCR 7 (and possibly PCR 14, if
shim/MOK is desired), as this includes measurements of the trusted certificates (and possibly hashes)
that are used to validate all components of the boot process up to and including the OS kernel. In
order to simplify firmware and OS version updates it's typically not advisable to include PCRs such
as 0 and 2 in the binding of the enrollment, since the program code they cover should already be
protected indirectly through the certificates measured into PCR 7. Validation through these
certificates is typically preferable over validation through direct measurements as it is less
brittle in context of OS/firmware updates: the measurements will change on every update, but code
signatures likely will validate against pre-existing certificates.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View File

@ -2111,7 +2111,6 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>RouteMetric=</varname></term>
<term><varname>UseDNS=</varname></term> <term><varname>UseDNS=</varname></term>
<term><varname>UseNTP=</varname></term> <term><varname>UseNTP=</varname></term>
<term><varname>UseHostname=</varname></term> <term><varname>UseHostname=</varname></term>

View File

@ -11,7 +11,7 @@
#include "bus-util.h" #include "bus-util.h"
#include "env-util.h" #include "env-util.h"
#include "format-table.h" #include "format-table.h"
#include "in-addr-prefix-util.h" #include "in-addr-util.h"
#include "locale-util.h" #include "locale-util.h"
#include "macro.h" #include "macro.h"
#include "manager.h" #include "manager.h"
@ -2582,10 +2582,10 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
return log_oom(); return log_oom();
} }
struct in_addr_prefix *i; IPAddressAccessItem *i;
bool deny_ipv4 = false, deny_ipv6 = false; bool deny_ipv4 = false, deny_ipv6 = false;
SET_FOREACH(i, g->ip_address_deny) { LIST_FOREACH(items, i, g->ip_address_deny) {
if (i->family == AF_INET && i->prefixlen == 0) if (i->family == AF_INET && i->prefixlen == 0)
deny_ipv4 = true; deny_ipv4 = true;
else if (i->family == AF_INET6 && i->prefixlen == 0) else if (i->family == AF_INET6 && i->prefixlen == 0)
@ -2594,7 +2594,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
info->ip_address_deny_all = deny_ipv4 && deny_ipv6; info->ip_address_deny_all = deny_ipv4 && deny_ipv6;
info->ip_address_allow_localhost = info->ip_address_allow_other = false; info->ip_address_allow_localhost = info->ip_address_allow_other = false;
SET_FOREACH(i, g->ip_address_allow) { LIST_FOREACH(items, i, g->ip_address_allow) {
if (in_addr_is_localhost(i->family, &i->address)) if (in_addr_is_localhost(i->family, &i->address))
info->ip_address_allow_localhost = true; info->ip_address_allow_localhost = true;
else else

View File

@ -831,6 +831,35 @@ static int in_addr_data_compare_func(const struct in_addr_data *x, const struct
DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func); DEFINE_HASH_OPS(in_addr_data_hash_ops, struct in_addr_data, in_addr_data_hash_func, in_addr_data_compare_func);
static void in_addr_prefix_hash_func(const struct in_addr_prefix *a, struct siphash *state) {
assert(a);
assert(state);
siphash24_compress(&a->family, sizeof(a->family), state);
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
}
static int in_addr_prefix_compare_func(const struct in_addr_prefix *x, const struct in_addr_prefix *y) {
int r;
assert(x);
assert(y);
r = CMP(x->family, y->family);
if (r != 0)
return r;
r = CMP(x->prefixlen, y->prefixlen);
if (r != 0)
return r;
return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
}
DEFINE_HASH_OPS(in_addr_prefix_hash_ops, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(in_addr_prefix_hash_ops_free, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func, free);
void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) { void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state) {
assert(addr); assert(addr);
assert(state); assert(state);

View File

@ -20,6 +20,12 @@ struct in_addr_data {
union in_addr_union address; union in_addr_union address;
}; };
struct in_addr_prefix {
int family;
uint8_t prefixlen;
union in_addr_union address;
};
bool in4_addr_is_null(const struct in_addr *a); bool in4_addr_is_null(const struct in_addr *a);
static inline bool in4_addr_is_set(const struct in_addr *a) { static inline bool in4_addr_is_set(const struct in_addr *a) {
return !in4_addr_is_null(a); return !in4_addr_is_null(a);
@ -118,6 +124,8 @@ void in6_addr_hash_func(const struct in6_addr *addr, struct siphash *state);
int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b); int in6_addr_compare_func(const struct in6_addr *a, const struct in6_addr *b);
extern const struct hash_ops in_addr_data_hash_ops; extern const struct hash_ops in_addr_data_hash_ops;
extern const struct hash_ops in_addr_prefix_hash_ops;
extern const struct hash_ops in_addr_prefix_hash_ops_free;
extern const struct hash_ops in6_addr_hash_ops; extern const struct hash_ops in6_addr_hash_ops;
#define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u" #define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u"

View File

@ -18,7 +18,7 @@
#include "bpf-firewall.h" #include "bpf-firewall.h"
#include "bpf-program.h" #include "bpf-program.h"
#include "fd-util.h" #include "fd-util.h"
#include "in-addr-prefix-util.h" #include "ip-address-access.h"
#include "memory-util.h" #include "memory-util.h"
#include "missing_syscall.h" #include "missing_syscall.h"
#include "unit.h" #include "unit.h"
@ -335,13 +335,13 @@ static int bpf_firewall_compile_bpf(
return 0; return 0;
} }
static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t *n_ipv6) { static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ipv4, size_t *n_ipv6) {
struct in_addr_prefix *a; IPAddressAccessItem *a;
assert(n_ipv4); assert(n_ipv4);
assert(n_ipv6); assert(n_ipv6);
SET_FOREACH(a, prefixes) LIST_FOREACH(items, a, list) {
switch (a->family) { switch (a->family) {
case AF_INET: case AF_INET:
@ -355,25 +355,26 @@ static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t
default: default:
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
}
return 0; return 0;
} }
static int bpf_firewall_add_access_items( static int bpf_firewall_add_access_items(
Set *prefixes, IPAddressAccessItem *list,
int ipv4_map_fd, int ipv4_map_fd,
int ipv6_map_fd, int ipv6_map_fd,
int verdict) { int verdict) {
struct bpf_lpm_trie_key *key_ipv4, *key_ipv6; struct bpf_lpm_trie_key *key_ipv4, *key_ipv6;
struct in_addr_prefix *a;
uint64_t value = verdict; uint64_t value = verdict;
IPAddressAccessItem *a;
int r; int r;
key_ipv4 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t)); key_ipv4 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t));
key_ipv6 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t) * 4); key_ipv6 = alloca0(offsetof(struct bpf_lpm_trie_key, data) + sizeof(uint32_t) * 4);
SET_FOREACH(a, prefixes) LIST_FOREACH(items, a, list) {
switch (a->family) { switch (a->family) {
case AF_INET: case AF_INET:
@ -399,6 +400,7 @@ static int bpf_firewall_add_access_items(
default: default:
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
} }
}
return 0; return 0;
} }
@ -412,6 +414,7 @@ static int bpf_firewall_prepare_access_maps(
_cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1; _cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1;
size_t n_ipv4 = 0, n_ipv6 = 0; size_t n_ipv4 = 0, n_ipv6 = 0;
IPAddressAccessItem *list;
Unit *p; Unit *p;
int r; int r;
@ -421,29 +424,18 @@ static int bpf_firewall_prepare_access_maps(
for (p = u; p; p = UNIT_GET_SLICE(p)) { for (p = u; p; p = UNIT_GET_SLICE(p)) {
CGroupContext *cc; CGroupContext *cc;
Set *prefixes;
bool *reduced;
cc = unit_get_cgroup_context(p); cc = unit_get_cgroup_context(p);
if (!cc) if (!cc)
continue; continue;
prefixes = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny; list = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny;
reduced = verdict == ACCESS_ALLOWED ? &cc->ip_address_allow_reduced : &cc->ip_address_deny_reduced;
if (!*reduced) { bpf_firewall_count_access_items(list, &n_ipv4, &n_ipv6);
r = in_addr_prefixes_reduce(prefixes);
if (r < 0)
return r;
*reduced = true;
}
bpf_firewall_count_access_items(prefixes, &n_ipv4, &n_ipv6);
/* Skip making the LPM trie map in cases where we are using "any" in order to hack around /* Skip making the LPM trie map in cases where we are using "any" in order to hack around
* needing CAP_SYS_ADMIN for allocating LPM trie map. */ * needing CAP_SYS_ADMIN for allocating LPM trie map. */
if (in_addr_prefixes_is_any(prefixes)) { if (ip_address_access_item_is_any(list)) {
*ret_has_any = true; *ret_has_any = true;
return 0; return 0;
} }

View File

@ -19,7 +19,6 @@
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "fs-util.h" #include "fs-util.h"
#include "in-addr-prefix-util.h"
#include "io-util.h" #include "io-util.h"
#include "ip-protocol-list.h" #include "ip-protocol-list.h"
#include "limits-util.h" #include "limits-util.h"
@ -239,8 +238,8 @@ void cgroup_context_done(CGroupContext *c) {
cgroup_context_remove_socket_bind(&c->socket_bind_allow); cgroup_context_remove_socket_bind(&c->socket_bind_allow);
cgroup_context_remove_socket_bind(&c->socket_bind_deny); cgroup_context_remove_socket_bind(&c->socket_bind_deny);
c->ip_address_allow = set_free(c->ip_address_allow); c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
c->ip_address_deny = set_free(c->ip_address_deny); c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
c->ip_filters_ingress = strv_free(c->ip_filters_ingress); c->ip_filters_ingress = strv_free(c->ip_filters_ingress);
c->ip_filters_egress = strv_free(c->ip_filters_egress); c->ip_filters_egress = strv_free(c->ip_filters_egress);
@ -396,7 +395,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
CGroupDeviceAllow *a; CGroupDeviceAllow *a;
CGroupContext *c; CGroupContext *c;
CGroupSocketBindItem *bi; CGroupSocketBindItem *bi;
struct in_addr_prefix *iaai; IPAddressAccessItem *iaai;
char **path; char **path;
char cda[FORMAT_CGROUP_DIFF_MAX]; char cda[FORMAT_CGROUP_DIFF_MAX];
@ -550,18 +549,18 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
FORMAT_BYTES(b->wbps)); FORMAT_BYTES(b->wbps));
} }
SET_FOREACH(iaai, c->ip_address_allow) { LIST_FOREACH(items, iaai, c->ip_address_allow) {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k); (void) in_addr_to_string(iaai->family, &iaai->address, &k);
fprintf(f, "%sIPAddressAllow: %s\n", prefix, strnull(k)); fprintf(f, "%sIPAddressAllow: %s/%u\n", prefix, strnull(k), iaai->prefixlen);
} }
SET_FOREACH(iaai, c->ip_address_deny) { LIST_FOREACH(items, iaai, c->ip_address_deny) {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k); (void) in_addr_to_string(iaai->family, &iaai->address, &k);
fprintf(f, "%sIPAddressDeny: %s\n", prefix, strnull(k)); fprintf(f, "%sIPAddressDeny: %s/%u\n", prefix, strnull(k), iaai->prefixlen);
} }
STRV_FOREACH(path, c->ip_filters_ingress) STRV_FOREACH(path, c->ip_filters_ingress)
@ -1556,8 +1555,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
return false; return false;
if (c->ip_accounting || if (c->ip_accounting ||
!set_isempty(c->ip_address_allow) || c->ip_address_allow ||
!set_isempty(c->ip_address_deny) || c->ip_address_deny ||
c->ip_filters_ingress || c->ip_filters_ingress ||
c->ip_filters_egress) c->ip_filters_egress)
return true; return true;
@ -1568,8 +1567,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
if (!c) if (!c)
return false; return false;
if (!set_isempty(c->ip_address_allow) || if (c->ip_address_allow ||
!set_isempty(c->ip_address_deny)) c->ip_address_deny)
return true; return true;
} }

View File

@ -5,6 +5,7 @@
#include "cgroup-util.h" #include "cgroup-util.h"
#include "cpu-set-util.h" #include "cpu-set-util.h"
#include "ip-address-access.h"
#include "list.h" #include "list.h"
#include "time-util.h" #include "time-util.h"
@ -147,17 +148,13 @@ struct CGroupContext {
uint64_t memory_max; uint64_t memory_max;
uint64_t memory_swap_max; uint64_t memory_swap_max;
bool default_memory_min_set:1; bool default_memory_min_set;
bool default_memory_low_set:1; bool default_memory_low_set;
bool memory_min_set:1; bool memory_min_set;
bool memory_low_set:1; bool memory_low_set;
Set *ip_address_allow; LIST_HEAD(IPAddressAccessItem, ip_address_allow);
Set *ip_address_deny; LIST_HEAD(IPAddressAccessItem, ip_address_deny);
/* These two flags indicate that redundant entries have been removed from
* ip_address_allow/ip_address_deny, i.e. in_addr_prefixes_reduce() has already been called. */
bool ip_address_allow_reduced;
bool ip_address_deny_reduced;
char **ip_filters_ingress; char **ip_filters_ingress;
char **ip_filters_egress; char **ip_filters_egress;

View File

@ -15,7 +15,6 @@
#include "errno-util.h" #include "errno-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "in-addr-prefix-util.h"
#include "ip-protocol-list.h" #include "ip-protocol-list.h"
#include "limits-util.h" #include "limits-util.h"
#include "parse-util.h" #include "parse-util.h"
@ -319,17 +318,14 @@ static int property_get_ip_address_access(
void *userdata, void *userdata,
sd_bus_error *error) { sd_bus_error *error) {
Set **prefixes = userdata; IPAddressAccessItem** items = userdata, *i;
struct in_addr_prefix *i;
int r; int r;
assert(prefixes);
r = sd_bus_message_open_container(reply, 'a', "(iayu)"); r = sd_bus_message_open_container(reply, 'a', "(iayu)");
if (r < 0) if (r < 0)
return r; return r;
SET_FOREACH(i, *prefixes) { LIST_FOREACH(items, i, *items) {
r = sd_bus_message_open_container(reply, 'r', "iayu"); r = sd_bus_message_open_container(reply, 'r', "iayu");
if (r < 0) if (r < 0)
@ -1749,9 +1745,11 @@ int bus_cgroup_set_property(
return 1; return 1;
} else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) { } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
_cleanup_set_free_ Set *new_prefixes = NULL; IPAddressAccessItem **list;
size_t n = 0; size_t n = 0;
list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
r = sd_bus_message_enter_container(message, 'a', "(iayu)"); r = sd_bus_message_enter_container(message, 'a', "(iayu)");
if (r < 0) if (r < 0)
return r; return r;
@ -1791,16 +1789,17 @@ int bus_cgroup_set_property(
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family)); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
struct in_addr_prefix prefix = { IPAddressAccessItem *item;
.family = family,
.prefixlen = prefixlen,
};
memcpy(&prefix.address, ap, an); item = new0(IPAddressAccessItem, 1);
if (!item)
return -ENOMEM;
r = in_addr_prefix_add(&new_prefixes, &prefix); item->family = family;
if (r < 0) item->prefixlen = prefixlen;
return r; memcpy(&item->address, ap, an);
LIST_PREPEND(items, *list, item);
} }
r = sd_bus_message_exit_container(message); r = sd_bus_message_exit_container(message);
@ -1814,46 +1813,33 @@ int bus_cgroup_set_property(
if (r < 0) if (r < 0)
return r; return r;
*list = ip_address_access_reduce(*list);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
IPAddressAccessItem *item;
size_t size = 0; size_t size = 0;
Set **prefixes;
bool *reduced; if (n == 0)
*list = ip_address_access_free_all(*list);
unit_invalidate_cgroup_bpf(u); unit_invalidate_cgroup_bpf(u);
f = open_memstream_unlocked(&buf, &size); f = open_memstream_unlocked(&buf, &size);
if (!f) if (!f)
return -ENOMEM; return -ENOMEM;
prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny; fputs(name, f);
reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced; fputs("=\n", f);
if (n == 0) { LIST_FOREACH(items, item, *list) {
*reduced = true; char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
*prefixes = set_free(*prefixes);
fputs(name, f);
fputs("=\n", f);
} else {
struct in_addr_prefix *p;
*reduced = false; errno = 0;
if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
return errno_or_else(EINVAL);
r = in_addr_prefixes_merge(prefixes, new_prefixes); fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
if (r < 0)
return r;
SET_FOREACH(p, new_prefixes) {
_cleanup_free_ char *buffer = NULL;
r = in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buffer);
if (r == -ENOMEM)
return r;
if (r < 0)
continue;
fprintf(f, "%s=%s\n", name, buffer);
}
} }
r = fflush_and_check(f); r = fflush_and_check(f);

View File

@ -0,0 +1,208 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdio.h>
#include <stdlib.h>
#include "alloc-util.h"
#include "bpf-firewall.h"
#include "extract-word.h"
#include "hostname-util.h"
#include "ip-address-access.h"
#include "parse-util.h"
#include "string-util.h"
int config_parse_ip_address_access(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
IPAddressAccessItem **list = data;
const char *p;
int r;
assert(list);
if (isempty(rvalue)) {
*list = ip_address_access_free_all(*list);
return 0;
}
p = rvalue;
for (;;) {
_cleanup_free_ IPAddressAccessItem *a = NULL;
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == 0)
break;
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
break;
}
a = new0(IPAddressAccessItem, 1);
if (!a)
return log_oom();
if (streq(word, "any")) {
/* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
a->family = AF_INET;
LIST_APPEND(items, *list, a);
a = new0(IPAddressAccessItem, 1);
if (!a)
return log_oom();
a->family = AF_INET6;
} else if (is_localhost(word)) {
/* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
a->family = AF_INET;
a->address.in.s_addr = htobe32(0x7f000000);
a->prefixlen = 8;
LIST_APPEND(items, *list, a);
a = new0(IPAddressAccessItem, 1);
if (!a)
return log_oom();
a->family = AF_INET6;
a->address.in6 = (struct in6_addr) IN6ADDR_LOOPBACK_INIT;
a->prefixlen = 128;
} else if (streq(word, "link-local")) {
/* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
a->family = AF_INET;
a->address.in.s_addr = htobe32((UINT32_C(169) << 24 | UINT32_C(254) << 16));
a->prefixlen = 16;
LIST_APPEND(items, *list, a);
a = new0(IPAddressAccessItem, 1);
if (!a)
return log_oom();
a->family = AF_INET6;
a->address.in6 = (struct in6_addr) {
.s6_addr32[0] = htobe32(0xfe800000)
};
a->prefixlen = 64;
} else if (streq(word, "multicast")) {
/* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
a->family = AF_INET;
a->address.in.s_addr = htobe32((UINT32_C(224) << 24));
a->prefixlen = 4;
LIST_APPEND(items, *list, a);
a = new0(IPAddressAccessItem, 1);
if (!a)
return log_oom();
a->family = AF_INET6;
a->address.in6 = (struct in6_addr) {
.s6_addr32[0] = htobe32(0xff000000)
};
a->prefixlen = 8;
} else {
r = in_addr_prefix_from_string_auto(word, &a->family, &a->address, &a->prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Address prefix is invalid, ignoring assignment: %s", word);
return 0;
}
}
LIST_APPEND(items, *list, a);
a = NULL;
}
*list = ip_address_access_reduce(*list);
return 0;
}
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first) {
IPAddressAccessItem *next, *p = first;
while (p) {
next = p->items_next;
free(p);
p = next;
}
return NULL;
}
IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first) {
IPAddressAccessItem *a, *b, *tmp;
int r;
/* Drops all entries from the list that are covered by another entry in full, thus removing all redundant
* entries. */
LIST_FOREACH_SAFE(items, a, tmp, first) {
/* Drop irrelevant bits */
(void) in_addr_mask(a->family, &a->address, a->prefixlen);
LIST_FOREACH(items, b, first) {
if (a == b)
continue;
if (a->family != b->family)
continue;
if (b->prefixlen > a->prefixlen)
continue;
r = in_addr_prefix_covers(b->family,
&b->address,
b->prefixlen,
&a->address);
if (r > 0) {
/* b covers a fully, then let's drop a */
LIST_REMOVE(items, first, a);
free(a);
break;
}
}
}
return first;
}
bool ip_address_access_item_is_any(IPAddressAccessItem *first) {
/* Check for exactly two entries */
if (!first || !first->items_next || first->items_next->items_next)
return false;
/* Check both entries cover the full range */
if (first->prefixlen != 0 || first->items_next->prefixlen != 0)
return false;
/* Check that one of them is the IPv4 and the other IPv6 */
if (!((first->family == AF_INET && first->items_next->family == AF_INET6) ||
(first->family == AF_INET6 && first->items_next->family == AF_INET)))
return false;
/* No need to check the actual addresses, they don't matter if the prefix is zero */
return true;
}

View File

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
#include "in-addr-util.h"
#include "list.h"
typedef struct IPAddressAccessItem IPAddressAccessItem;
struct IPAddressAccessItem {
int family;
unsigned char prefixlen;
union in_addr_union address;
LIST_FIELDS(IPAddressAccessItem, items);
};
CONFIG_PARSER_PROTOTYPE(config_parse_ip_address_access);
IPAddressAccessItem* ip_address_access_free_all(IPAddressAccessItem *first);
IPAddressAccessItem* ip_address_access_reduce(IPAddressAccessItem *first);
/* Returns true if a list consists of only the two items necessary for "any"
* (0.0.0.0/0 and ::/0). */
bool ip_address_access_item_is_any(IPAddressAccessItem *first);

View File

@ -221,8 +221,8 @@
{{type}}.Delegate, config_parse_delegate, 0, offsetof({{type}}, cgroup_context) {{type}}.Delegate, config_parse_delegate, 0, offsetof({{type}}, cgroup_context)
{{type}}.DisableControllers, config_parse_disable_controllers, 0, offsetof({{type}}, cgroup_context) {{type}}.DisableControllers, config_parse_disable_controllers, 0, offsetof({{type}}, cgroup_context)
{{type}}.IPAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.ip_accounting) {{type}}.IPAccounting, config_parse_bool, 0, offsetof({{type}}, cgroup_context.ip_accounting)
{{type}}.IPAddressAllow, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_allow) {{type}}.IPAddressAllow, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_allow)
{{type}}.IPAddressDeny, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_deny) {{type}}.IPAddressDeny, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_deny)
{{type}}.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_ingress) {{type}}.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_ingress)
{{type}}.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_egress) {{type}}.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof({{type}}, cgroup_context.ip_filters_egress)
{{type}}.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof({{type}}, cgroup_context.moom_swap) {{type}}.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof({{type}}, cgroup_context.moom_swap)
@ -243,7 +243,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#include <stddef.h> #include <stddef.h>
#include "all-units.h" #include "all-units.h"
#include "conf-parser.h" #include "conf-parser.h"
#include "in-addr-prefix-util.h"
#include "load-fragment.h" #include "load-fragment.h"
%} %}
struct ConfigPerfItem; struct ConfigPerfItem;

View File

@ -12,6 +12,7 @@
#include "cgroup.h" #include "cgroup.h"
#include "fdset.h" #include "fdset.h"
#include "hashmap.h" #include "hashmap.h"
#include "ip-address-access.h"
#include "list.h" #include "list.h"
#include "prioq.h" #include "prioq.h"
#include "ratelimit.h" #include "ratelimit.h"

View File

@ -71,6 +71,8 @@ libcore_sources = '''
generator-setup.h generator-setup.h
ima-setup.c ima-setup.c
ima-setup.h ima-setup.h
ip-address-access.c
ip-address-access.h
job.c job.c
job.h job.h
kill.c kill.c

View File

@ -3,7 +3,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "sd-id128.h" #include "sd-id128.h"

View File

@ -9,7 +9,7 @@
#include "dhcp6-internal.h" #include "dhcp6-internal.h"
#include "escape.h" #include "escape.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "in-addr-prefix-util.h" #include "in-addr-util.h"
#include "networkd-dhcp-common.h" #include "networkd-dhcp-common.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
@ -18,44 +18,6 @@
#include "socket-util.h" #include "socket-util.h"
#include "string-table.h" #include "string-table.h"
#include "strv.h" #include "strv.h"
#include "vrf.h"
static uint32_t link_get_vrf_table(Link *link) {
assert(link);
assert(link->network);
return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN;
}
uint32_t link_get_dhcp4_route_table(Link *link) {
assert(link);
assert(link->network);
/* When the interface is part of an VRF use the VRFs routing table, unless
* another table is explicitly specified. */
if (link->network->dhcp_route_table_set)
return link->network->dhcp_route_table;
return link_get_vrf_table(link);
}
uint32_t link_get_dhcp6_route_table(Link *link) {
assert(link);
assert(link->network);
if (link->network->dhcp6_route_table_set)
return link->network->dhcp6_route_table;
return link_get_vrf_table(link);
}
uint32_t link_get_ipv6_accept_ra_route_table(Link *link) {
assert(link);
assert(link->network);
if (link->network->ipv6_accept_ra_route_table_set)
return link->network->ipv6_accept_ra_route_table;
return link_get_vrf_table(link);
}
bool link_dhcp_enabled(Link *link, int family) { bool link_dhcp_enabled(Link *link, int family) {
assert(link); assert(link);
@ -310,7 +272,7 @@ int config_parse_dhcp(
return 0; return 0;
} }
int config_parse_dhcp_or_ra_route_metric( int config_parse_dhcp_route_metric(
const char* unit, const char* unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -328,7 +290,6 @@ int config_parse_dhcp_or_ra_route_metric(
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
assert(rvalue); assert(rvalue);
assert(data); assert(data);
@ -339,24 +300,17 @@ int config_parse_dhcp_or_ra_route_metric(
return 0; return 0;
} }
switch(ltype) { if (streq_ptr(section, "DHCPv4")) {
case AF_INET:
network->dhcp_route_metric = metric; network->dhcp_route_metric = metric;
network->dhcp_route_metric_set = true; network->dhcp_route_metric_set = true;
break; } else if (STRPTR_IN_SET(section, "DHCPv6", "IPv6AcceptRA")) {
case AF_INET6:
network->ipv6_accept_ra_route_metric = metric; network->ipv6_accept_ra_route_metric = metric;
network->ipv6_accept_ra_route_metric_set = true; network->ipv6_accept_ra_route_metric_set = true;
break; } else { /* [DHCP] section */
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_route_metric_set) if (!network->dhcp_route_metric_set)
network->dhcp_route_metric = metric; network->dhcp_route_metric = metric;
if (!network->ipv6_accept_ra_route_metric_set) if (!network->ipv6_accept_ra_route_metric_set)
network->ipv6_accept_ra_route_metric = metric; network->ipv6_accept_ra_route_metric = metric;
break;
default:
assert_not_reached();
} }
return 0; return 0;
@ -379,7 +333,6 @@ int config_parse_dhcp_use_dns(
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
assert(rvalue); assert(rvalue);
assert(data); assert(data);
@ -390,24 +343,17 @@ int config_parse_dhcp_use_dns(
return 0; return 0;
} }
switch(ltype) { if (streq_ptr(section, "DHCPv4")) {
case AF_INET:
network->dhcp_use_dns = r; network->dhcp_use_dns = r;
network->dhcp_use_dns_set = true; network->dhcp_use_dns_set = true;
break; } else if (streq_ptr(section, "DHCPv6")) {
case AF_INET6:
network->dhcp6_use_dns = r; network->dhcp6_use_dns = r;
network->dhcp6_use_dns_set = true; network->dhcp6_use_dns_set = true;
break; } else { /* [DHCP] section */
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_use_dns_set) if (!network->dhcp_use_dns_set)
network->dhcp_use_dns = r; network->dhcp_use_dns = r;
if (!network->dhcp6_use_dns_set) if (!network->dhcp6_use_dns_set)
network->dhcp6_use_dns = r; network->dhcp6_use_dns = r;
break;
default:
assert_not_reached();
} }
return 0; return 0;
@ -430,7 +376,6 @@ int config_parse_dhcp_use_domains(
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
assert(rvalue); assert(rvalue);
assert(data); assert(data);
@ -441,24 +386,17 @@ int config_parse_dhcp_use_domains(
return 0; return 0;
} }
switch(ltype) { if (streq_ptr(section, "DHCPv4")) {
case AF_INET:
network->dhcp_use_domains = d; network->dhcp_use_domains = d;
network->dhcp_use_domains_set = true; network->dhcp_use_domains_set = true;
break; } else if (streq_ptr(section, "DHCPv6")) {
case AF_INET6:
network->dhcp6_use_domains = d; network->dhcp6_use_domains = d;
network->dhcp6_use_domains_set = true; network->dhcp6_use_domains_set = true;
break; } else { /* [DHCP] section */
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_use_domains_set) if (!network->dhcp_use_domains_set)
network->dhcp_use_domains = d; network->dhcp_use_domains = d;
if (!network->dhcp6_use_domains_set) if (!network->dhcp6_use_domains_set)
network->dhcp6_use_domains = d; network->dhcp6_use_domains = d;
break;
default:
assert_not_reached();
} }
return 0; return 0;
@ -481,7 +419,6 @@ int config_parse_dhcp_use_ntp(
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
assert(rvalue); assert(rvalue);
assert(data); assert(data);
@ -492,30 +429,23 @@ int config_parse_dhcp_use_ntp(
return 0; return 0;
} }
switch(ltype) { if (streq_ptr(section, "DHCPv4")) {
case AF_INET:
network->dhcp_use_ntp = r; network->dhcp_use_ntp = r;
network->dhcp_use_ntp_set = true; network->dhcp_use_ntp_set = true;
break; } else if (streq_ptr(section, "DHCPv6")) {
case AF_INET6:
network->dhcp6_use_ntp = r; network->dhcp6_use_ntp = r;
network->dhcp6_use_ntp_set = true; network->dhcp6_use_ntp_set = true;
break; } else { /* [DHCP] section */
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_use_ntp_set) if (!network->dhcp_use_ntp_set)
network->dhcp_use_ntp = r; network->dhcp_use_ntp = r;
if (!network->dhcp6_use_ntp_set) if (!network->dhcp6_use_ntp_set)
network->dhcp6_use_ntp = r; network->dhcp6_use_ntp = r;
break;
default:
assert_not_reached();
} }
return 0; return 0;
} }
int config_parse_dhcp_or_ra_route_table( int config_parse_section_route_table(
const char *unit, const char *unit,
const char *filename, const char *filename,
unsigned line, unsigned line,
@ -533,11 +463,6 @@ int config_parse_dhcp_or_ra_route_table(
assert(filename); assert(filename);
assert(lvalue); assert(lvalue);
assert(IN_SET(ltype,
(RTPROT_DHCP<<16) | AF_UNSPEC,
(RTPROT_DHCP<<16) | AF_INET,
(RTPROT_DHCP<<16) | AF_INET6,
(RTPROT_RA<<16) | AF_INET6));
assert(rvalue); assert(rvalue);
assert(data); assert(data);
@ -548,34 +473,12 @@ int config_parse_dhcp_or_ra_route_table(
return 0; return 0;
} }
switch(ltype) { if (STRPTR_IN_SET(section, "DHCP", "DHCPv4")) {
case (RTPROT_DHCP<<16) | AF_INET:
network->dhcp_route_table = rt; network->dhcp_route_table = rt;
network->dhcp_route_table_set = true; network->dhcp_route_table_set = true;
network->dhcp_route_table_set_explicitly = true; } else { /* section is IPv6AcceptRA */
break;
case (RTPROT_DHCP<<16) | AF_INET6:
network->dhcp6_route_table = rt;
network->dhcp6_route_table_set = true;
network->dhcp6_route_table_set_explicitly = true;
break;
case (RTPROT_DHCP<<16) | AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_route_table_set_explicitly) {
network->dhcp_route_table = rt;
network->dhcp_route_table_set = true;
}
if (!network->dhcp6_route_table_set_explicitly) {
network->dhcp6_route_table = rt;
network->dhcp6_route_table_set = true;
}
break;
case (RTPROT_RA<<16) | AF_INET6:
network->ipv6_accept_ra_route_table = rt; network->ipv6_accept_ra_route_table = rt;
network->ipv6_accept_ra_route_table_set = true; network->ipv6_accept_ra_route_table_set = true;
break;
default:
assert_not_reached();
} }
return 0; return 0;
@ -1265,3 +1168,69 @@ int config_parse_network_duid_rawdata(
/* For backward compatibility, also set DHCPv6 DUID if not specified explicitly. */ /* For backward compatibility, also set DHCPv6 DUID if not specified explicitly. */
return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network); return config_parse_duid_rawdata(unit, filename, line, section, section_line, lvalue, false, rvalue, &network->dhcp6_duid, network);
} }
int config_parse_address_filter(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Set **list = data;
int r;
assert(filename);
assert(lvalue);
assert(IN_SET(ltype, AF_INET, AF_INET6));
assert(rvalue);
assert(data);
if (isempty(rvalue)) {
*list = set_free(*list);
return 0;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *n = NULL;
_cleanup_free_ struct in_addr_prefix *a = NULL;
struct in_addr_prefix prefix;
r = extract_first_word(&p, &n, NULL, 0);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse NDisc %s=, ignoring assignment: %s",
lvalue, rvalue);
return 0;
}
if (r == 0)
return 0;
r = in_addr_prefix_from_string(n, ltype, &prefix.address, &prefix.prefixlen);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"NDisc %s= entry is invalid, ignoring assignment: %s",
lvalue, n);
continue;
}
prefix.family = ltype;
a = newdup(struct in_addr_prefix, &prefix, 1);
if (!a)
return log_oom();
r = set_ensure_consume(list, &in_addr_prefix_hash_ops_free, TAKE_PTR(a));
if (r < 0)
return log_oom();
if (r == 0)
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s %s= entry is duplicated, ignoring assignment: %s",
section, lvalue, n);
}
}

View File

@ -44,10 +44,6 @@ typedef struct DUID {
bool set; bool set;
} DUID; } DUID;
uint32_t link_get_dhcp4_route_table(Link *link);
uint32_t link_get_dhcp6_route_table(Link *link);
uint32_t link_get_ipv6_accept_ra_route_table(Link *link);
bool link_dhcp_enabled(Link *link, int family); bool link_dhcp_enabled(Link *link, int family);
static inline bool link_dhcp4_enabled(Link *link) { static inline bool link_dhcp4_enabled(Link *link) {
return link_dhcp_enabled(link, AF_INET); return link_dhcp_enabled(link, AF_INET);
@ -84,12 +80,12 @@ const char *dhcp_option_data_type_to_string(DHCPOptionDataType d) _const_;
DHCPOptionDataType dhcp_option_data_type_from_string(const char *d) _pure_; DHCPOptionDataType dhcp_option_data_type_from_string(const char *d) _pure_;
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_or_ra_route_metric); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_route_metric);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_dns);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_iaid); CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_or_ra_route_table); CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_or_vendor_class); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_or_vendor_class);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options); CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
@ -99,3 +95,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_type);
CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata); CONFIG_PARSER_PROTOTYPE(config_parse_duid_rawdata);
CONFIG_PARSER_PROTOTYPE(config_parse_manager_duid_rawdata); CONFIG_PARSER_PROTOTYPE(config_parse_manager_duid_rawdata);
CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_rawdata); CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_rawdata);
CONFIG_PARSER_PROTOTYPE(config_parse_address_filter);

View File

@ -135,26 +135,6 @@ static int dhcp4_after_route_configure(Request *req, void *object) {
return 0; return 0;
} }
static int dhcp4_retry(Link *link) {
int r;
assert(link);
r = dhcp4_remove_all(link);
if (r < 0)
return r;
r = link_request_static_nexthops(link, true);
if (r < 0)
return r;
r = link_request_static_routes(link, true);
if (r < 0)
return r;
return dhcp4_request_address_and_routes(link, false);
}
static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
@ -185,7 +165,19 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
link->dhcp4_route_failed = false; link->dhcp4_route_failed = false;
link->dhcp4_route_retrying = true; link->dhcp4_route_retrying = true;
r = dhcp4_retry(link); r = dhcp4_remove_all(link);
if (r < 0)
link_enter_failed(link);
r = link_request_static_nexthops(link, true);
if (r < 0)
link_enter_failed(link);
r = link_request_static_routes(link, true);
if (r < 0)
link_enter_failed(link);
r = dhcp4_request_address_and_routes(link, false);
if (r < 0) if (r < 0)
link_enter_failed(link); link_enter_failed(link);
@ -205,16 +197,6 @@ static int dhcp4_request_route(Route *in, Link *link) {
assert(route); assert(route);
assert(link); assert(link);
route->family = AF_INET;
if (!route->protocol_set)
route->protocol = RTPROT_DHCP;
if (!route->priority_set)
route->priority = link->network->dhcp_route_metric;
if (!route->table_set)
route->table = link_get_dhcp4_route_table(link);
if (route->mtu == 0)
route->mtu = link->network->dhcp_route_mtu;
r = link_has_route(link, route); r = link_has_route(link, route);
if (r < 0) if (r < 0)
return r; return r;
@ -261,10 +243,14 @@ static int dhcp4_request_prefix_route(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
route->family = AF_INET;
route->dst.in.s_addr = address.s_addr & netmask.s_addr; route->dst.in.s_addr = address.s_addr & netmask.s_addr;
route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask); route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
route->prefsrc.in = address; route->prefsrc.in = address;
route->scope = RT_SCOPE_LINK; route->scope = RT_SCOPE_LINK;
route->protocol = RTPROT_DHCP;
route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu;
return dhcp4_request_route(TAKE_PTR(route), link); return dhcp4_request_route(TAKE_PTR(route), link);
} }
@ -286,10 +272,15 @@ static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw)
if (r < 0) if (r < 0)
return r; return r;
route->family = AF_INET;
route->dst.in = *gw; route->dst.in = *gw;
route->dst_prefixlen = 32; route->dst_prefixlen = 32;
route->prefsrc.in = address; route->prefsrc.in = address;
route->scope = RT_SCOPE_LINK; route->scope = RT_SCOPE_LINK;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu;
return dhcp4_request_route(TAKE_PTR(route), link); return dhcp4_request_route(TAKE_PTR(route), link);
} }
@ -463,7 +454,12 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
if (r < 0) if (r < 0)
return r; return r;
route->family = AF_INET;
route->gw_family = AF_INET; route->gw_family = AF_INET;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu;
r = sd_dhcp_route_get_gateway(static_routes[i], &gw); r = sd_dhcp_route_get_gateway(static_routes[i], &gw);
if (r < 0) if (r < 0)
@ -541,9 +537,14 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *gw) {
return r; return r;
/* Next, add a default gateway. */ /* Next, add a default gateway. */
route->family = AF_INET;
route->gw_family = AF_INET; route->gw_family = AF_INET;
route->gw.in = router[0]; route->gw.in = router[0];
route->prefsrc.in = address; route->prefsrc.in = address;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu;
r = dhcp4_request_route(TAKE_PTR(route), link); r = dhcp4_request_route(TAKE_PTR(route), link);
if (r < 0) if (r < 0)
@ -585,6 +586,14 @@ static int dhcp4_request_semi_static_routes(Link *link, const struct in_addr *gw
return r; return r;
route->gw.in = *gw; route->gw.in = *gw;
if (!route->protocol_set)
route->protocol = RTPROT_DHCP;
if (!route->priority_set)
route->priority = link->network->dhcp_route_metric;
if (!route->table_set)
route->table = link_get_dhcp_route_table(link);
if (route->mtu == 0)
route->mtu = link->network->dhcp_route_mtu;
r = dhcp4_request_route(TAKE_PTR(route), link); r = dhcp4_request_route(TAKE_PTR(route), link);
if (r < 0) if (r < 0)
@ -618,8 +627,13 @@ static int dhcp4_request_routes_to_servers(
if (r < 0) if (r < 0)
return r; return r;
route->family = AF_INET;
route->dst.in = servers[i]; route->dst.in = servers[i];
route->dst_prefixlen = 32; route->dst_prefixlen = 32;
route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp_route_metric;
route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu;
r = dhcp4_request_route_auto(TAKE_PTR(route), link, gw); r = dhcp4_request_route_auto(TAKE_PTR(route), link, gw);
if (r < 0) if (r < 0)
@ -909,7 +923,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
static int dhcp4_request_address(Link *link, bool announce) { static int dhcp4_request_address(Link *link, bool announce) {
_cleanup_(address_freep) Address *addr = NULL; _cleanup_(address_freep) Address *addr = NULL;
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
struct in_addr address, netmask, server; struct in_addr address, netmask;
unsigned prefixlen; unsigned prefixlen;
Request *req; Request *req;
int r; int r;
@ -928,10 +942,6 @@ static int dhcp4_request_address(Link *link, bool announce) {
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no netmask: %m"); return log_link_warning_errno(link, r, "DHCP error: no netmask: %m");
r = sd_dhcp_lease_get_server_identifier(link->dhcp_lease, &server);
if (r < 0)
return log_link_debug_errno(link, r, "DHCP error: failed to get DHCP server IP address: %m");
if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) { if (!FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) {
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
if (r < 0) if (r < 0)
@ -950,21 +960,19 @@ static int dhcp4_request_address(Link *link, bool announce) {
if (r > 0 && in4_addr_is_set(&router[0])) if (r > 0 && in4_addr_is_set(&router[0]))
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link), LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u, gateway "IPV4_ADDRESS_FMT_STR" acquired from "IPV4_ADDRESS_FMT_STR, LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u via "IPV4_ADDRESS_FMT_STR,
IPV4_ADDRESS_FMT_VAL(address), IPV4_ADDRESS_FMT_VAL(address),
prefixlen, prefixlen,
IPV4_ADDRESS_FMT_VAL(router[0]), IPV4_ADDRESS_FMT_VAL(router[0])),
IPV4_ADDRESS_FMT_VAL(server)),
"ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address), "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen, "PREFIXLEN=%u", prefixlen,
"GATEWAY="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(router[0])); "GATEWAY="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(router[0]));
else else
log_struct(LOG_INFO, log_struct(LOG_INFO,
LOG_LINK_INTERFACE(link), LOG_LINK_INTERFACE(link),
LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u acquired from "IPV4_ADDRESS_FMT_STR, LOG_LINK_MESSAGE(link, "DHCPv4 address "IPV4_ADDRESS_FMT_STR"/%u",
IPV4_ADDRESS_FMT_VAL(address), IPV4_ADDRESS_FMT_VAL(address),
prefixlen, prefixlen),
IPV4_ADDRESS_FMT_VAL(server)),
"ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address), "ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
"PREFIXLEN=%u", prefixlen); "PREFIXLEN=%u", prefixlen);
} }
@ -984,9 +992,11 @@ static int dhcp4_request_address(Link *link, bool announce) {
addr->route_metric = link->network->dhcp_route_metric; addr->route_metric = link->network->dhcp_route_metric;
addr->duplicate_address_detection = link->network->dhcp_send_decline ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO; addr->duplicate_address_detection = link->network->dhcp_send_decline ? ADDRESS_FAMILY_IPV4 : ADDRESS_FAMILY_NO;
r = free_and_strdup_warn(&addr->label, link->network->dhcp_label); if (link->network->dhcp_label) {
if (r < 0) addr->label = strdup(link->network->dhcp_label);
return r; if (!addr->label)
return log_oom();
}
if (address_get(link, addr, NULL) < 0) if (address_get(link, addr, NULL) < 0)
link->dhcp4_configured = false; link->dhcp4_configured = false;

View File

@ -12,7 +12,6 @@
#include "hashmap.h" #include "hashmap.h"
#include "hostname-setup.h" #include "hostname-setup.h"
#include "hostname-util.h" #include "hostname-util.h"
#include "in-addr-prefix-util.h"
#include "missing_network.h" #include "missing_network.h"
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-dhcp6.h" #include "networkd-dhcp6.h"
@ -875,7 +874,7 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad
route->family = AF_INET6; route->family = AF_INET6;
route->dst.in6 = *addr; route->dst.in6 = *addr;
route->dst_prefixlen = prefixlen; route->dst_prefixlen = prefixlen;
route->table = link_get_dhcp6_route_table(link); route->table = link_get_dhcp_route_table(link);
route->type = RTN_UNREACHABLE; route->type = RTN_UNREACHABLE;
route->protocol = RTPROT_DHCP; route->protocol = RTPROT_DHCP;

View File

@ -403,13 +403,6 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
assert(link); assert(link);
assert(rt); assert(rt);
if (!route->table_set)
route->table = link_get_ipv6_accept_ra_route_table(link);
if (!route->priority_set)
route->priority = link->network->ipv6_accept_ra_route_metric;
if (!route->protocol_set)
route->protocol = RTPROT_RA;
r = link_has_route(link, route); r = link_has_route(link, route);
if (r < 0) if (r < 0)
return r; return r;
@ -543,7 +536,7 @@ static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
struct in6_addr gateway; struct in6_addr gateway;
uint32_t mtu = 0; uint32_t table, mtu = 0;
unsigned preference; unsigned preference;
uint16_t lifetime; uint16_t lifetime;
usec_t time_now; usec_t time_now;
@ -588,11 +581,16 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m"); return log_link_error_errno(link, r, "Failed to get default router MTU from RA: %m");
} }
table = link_get_ipv6_accept_ra_route_table(link);
r = route_new(&route); r = route_new(&route);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
route->family = AF_INET6; route->family = AF_INET6;
route->table = table;
route->priority = link->network->ipv6_accept_ra_route_metric;
route->protocol = RTPROT_RA;
route->pref = preference; route->pref = preference;
route->gw_family = AF_INET6; route->gw_family = AF_INET6;
route->gw.in6 = gateway; route->gw.in6 = gateway;
@ -616,6 +614,12 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
return r; return r;
route->gw.in6 = gateway; route->gw.in6 = gateway;
if (!route->table_set)
route->table = table;
if (!route->priority_set)
route->priority = link->network->ipv6_accept_ra_route_metric;
if (!route->protocol_set)
route->protocol = RTPROT_RA;
if (!route->pref_set) if (!route->pref_set)
route->pref = preference; route->pref = preference;
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
@ -874,6 +878,9 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
return log_oom(); return log_oom();
route->family = AF_INET6; route->family = AF_INET6;
route->table = link_get_ipv6_accept_ra_route_table(link);
route->priority = link->network->ipv6_accept_ra_route_metric;
route->protocol = RTPROT_RA;
route->flags = RTM_F_PREFIX; route->flags = RTM_F_PREFIX;
route->dst_prefixlen = prefixlen; route->dst_prefixlen = prefixlen;
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
@ -954,6 +961,9 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
return log_oom(); return log_oom();
route->family = AF_INET6; route->family = AF_INET6;
route->table = link_get_ipv6_accept_ra_route_table(link);
route->priority = link->network->ipv6_accept_ra_route_metric;
route->protocol = RTPROT_RA;
route->pref = preference; route->pref = preference;
route->gw.in6 = gateway; route->gw.in6 = gateway;
route->gw_family = AF_INET6; route->gw_family = AF_INET6;

View File

@ -5,7 +5,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
#endif #endif
#include <stddef.h> #include <stddef.h>
#include "conf-parser.h" #include "conf-parser.h"
#include "in-addr-prefix-util.h"
#include "netem.h" #include "netem.h"
#include "net-condition.h" #include "net-condition.h"
#include "networkd-address-label.h" #include "networkd-address-label.h"
@ -200,14 +199,14 @@ NextHop.OnLink, config_parse_nexthop_onlink,
NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0 NextHop.Blackhole, config_parse_nexthop_blackhole, 0, 0
NextHop.Group, config_parse_nexthop_group, 0, 0 NextHop.Group, config_parse_nexthop_group, 0, 0
DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCPv4.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
DHCPv4.UseDNS, config_parse_dhcp_use_dns, AF_INET, 0 DHCPv4.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns) DHCPv4.RoutesToDNS, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_dns)
DHCPv4.UseNTP, config_parse_dhcp_use_ntp, AF_INET, 0 DHCPv4.UseNTP, config_parse_dhcp_use_ntp, 0, 0
DHCPv4.RoutesToNTP, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_ntp) DHCPv4.RoutesToNTP, config_parse_bool, 0, offsetof(Network, dhcp_routes_to_ntp)
DHCPv4.UseSIP, config_parse_bool, 0, offsetof(Network, dhcp_use_sip) DHCPv4.UseSIP, config_parse_bool, 0, offsetof(Network, dhcp_use_sip)
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
DHCPv4.UseDomains, config_parse_dhcp_use_domains, AF_INET, 0 DHCPv4.UseDomains, config_parse_dhcp_use_domains, 0, 0
DHCPv4.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) DHCPv4.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes)
DHCPv4.UseGateway, config_parse_tristate, 0, offsetof(Network, dhcp_use_gateway) DHCPv4.UseGateway, config_parse_tristate, 0, offsetof(Network, dhcp_use_gateway)
DHCPv4.RequestOptions, config_parse_dhcp_request_options, AF_INET, 0 DHCPv4.RequestOptions, config_parse_dhcp_request_options, AF_INET, 0
@ -223,24 +222,24 @@ DHCPv4.UserClass, config_parse_dhcp_user_or_vendor_cl
DHCPv4.IAID, config_parse_iaid, AF_INET, 0 DHCPv4.IAID, config_parse_iaid, AF_INET, 0
DHCPv4.DUIDType, config_parse_network_duid_type, 0, 0 DHCPv4.DUIDType, config_parse_network_duid_type, 0, 0
DHCPv4.DUIDRawData, config_parse_network_duid_rawdata, 0, 0 DHCPv4.DUIDRawData, config_parse_network_duid_rawdata, 0, 0
DHCPv4.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET, 0 DHCPv4.RouteMetric, config_parse_dhcp_route_metric, 0, 0
DHCPv4.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET, 0 DHCPv4.RouteTable, config_parse_section_route_table, 0, 0
DHCPv4.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCPv4.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release) DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline) DHCPv4.SendDecline, config_parse_bool, 0, offsetof(Network, dhcp_send_decline)
DHCPv4.DenyList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_deny_listed_ip) DHCPv4.DenyList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_deny_listed_ip)
DHCPv4.AllowList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_allow_listed_ip) DHCPv4.AllowList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_allow_listed_ip)
DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type) DHCPv4.IPServiceType, config_parse_dhcp_ip_service_type, 0, offsetof(Network, dhcp_ip_service_type)
DHCPv4.SendOption, config_parse_dhcp_send_option, AF_INET, 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)
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0 DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address) DHCPv6.UseAddress, config_parse_bool, 0, offsetof(Network, dhcp6_use_address)
DHCPv6.UseDNS, config_parse_dhcp_use_dns, AF_INET6, 0 DHCPv6.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCPv6.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp6_use_hostname) DHCPv6.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp6_use_hostname)
DHCPv6.UseDomains, config_parse_dhcp_use_domains, AF_INET6, 0 DHCPv6.UseDomains, config_parse_dhcp_use_domains, 0, 0
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, AF_INET6, 0 DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit) DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCPv6.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp6_mudurl) DHCPv6.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp6_mudurl)
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0 DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
@ -254,21 +253,20 @@ DHCPv6.SendOption, config_parse_dhcp_send_option,
DHCPv6.IAID, config_parse_iaid, AF_INET6, 0 DHCPv6.IAID, config_parse_iaid, AF_INET6, 0
DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid) DHCPv6.DUIDType, config_parse_duid_type, 0, offsetof(Network, dhcp6_duid)
DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, dhcp6_duid) DHCPv6.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, dhcp6_duid)
DHCPv6.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET6, 0
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)
IPv6AcceptRA.UseDomains, config_parse_ipv6_accept_ra_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) IPv6AcceptRA.UseDomains, config_parse_ipv6_accept_ra_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
IPv6AcceptRA.UseMTU, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_mtu) IPv6AcceptRA.UseMTU, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_mtu)
IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client) IPv6AcceptRA.DHCPv6Client, config_parse_ipv6_accept_ra_start_dhcp6_client, 0, offsetof(Network, ipv6_accept_ra_start_dhcp6_client)
IPv6AcceptRA.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_RA<<16) | AF_INET6, 0 IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0
IPv6AcceptRA.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0 IPv6AcceptRA.RouteMetric, config_parse_dhcp_route_metric, 0, 0
IPv6AcceptRA.RouterAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_router) IPv6AcceptRA.RouterAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_router)
IPv6AcceptRA.RouterDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_router) IPv6AcceptRA.RouterDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_router)
IPv6AcceptRA.PrefixAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix) IPv6AcceptRA.PrefixAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix)
IPv6AcceptRA.PrefixDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) IPv6AcceptRA.PrefixDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
IPv6AcceptRA.RouteAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_route_prefix) IPv6AcceptRA.RouteAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_route_prefix)
IPv6AcceptRA.RouteDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_route_prefix) IPv6AcceptRA.RouteDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_route_prefix)
DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0 DHCPServer.ServerAddress, config_parse_dhcp_server_address, 0, 0
DHCPServer.UplinkInterface, config_parse_uplink, 0, 0 DHCPServer.UplinkInterface, config_parse_uplink, 0, 0
DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target) DHCPServer.RelayTarget, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_relay_target)
@ -501,14 +499,14 @@ IPv6PrefixDelegation.DNS, config_parse_radv_dns,
IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains) IPv6PrefixDelegation.EmitDomains, config_parse_bool, 0, offsetof(Network, router_emit_domains)
IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0 IPv6PrefixDelegation.Domains, config_parse_radv_search_domains, 0, 0
IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec) IPv6PrefixDelegation.DNSLifetimeSec, config_parse_sec, 0, offsetof(Network, router_dns_lifetime_usec)
DHCPv4.BlackList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_deny_listed_ip) DHCPv4.BlackList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_deny_listed_ip)
DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
DHCP.UseDNS, config_parse_dhcp_use_dns, AF_UNSPEC, 0 DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0
DHCP.UseNTP, config_parse_dhcp_use_ntp, AF_UNSPEC, 0 DHCP.UseNTP, config_parse_dhcp_use_ntp, 0, 0
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
DHCP.UseDomains, config_parse_dhcp_use_domains, AF_UNSPEC, 0 DHCP.UseDomains, config_parse_dhcp_use_domains, 0, 0
DHCP.UseDomainName, config_parse_dhcp_use_domains, AF_UNSPEC, 0 DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, 0
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes)
DHCP.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize) DHCP.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize)
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname)
@ -520,17 +518,17 @@ DHCP.UserClass, config_parse_dhcp_user_or_vendor_cl
DHCP.IAID, config_parse_iaid, AF_INET, 0 DHCP.IAID, config_parse_iaid, AF_INET, 0
DHCP.DUIDType, config_parse_network_duid_type, 0, 0 DHCP.DUIDType, config_parse_network_duid_type, 0, 0
DHCP.DUIDRawData, config_parse_network_duid_rawdata, 0, 0 DHCP.DUIDRawData, config_parse_network_duid_rawdata, 0, 0
DHCP.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_UNSPEC, 0 DHCP.RouteMetric, config_parse_dhcp_route_metric, 0, 0
DHCP.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_UNSPEC, 0 DHCP.RouteTable, config_parse_section_route_table, 0, 0
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port) DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit) DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information) DHCP.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
DHCPv4.UseDomainName, config_parse_dhcp_use_domains, AF_INET, 0 DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, 0
DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical) DHCPv4.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
DHCPv6.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0 DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0
IPv6AcceptRA.DenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) IPv6AcceptRA.DenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
IPv6AcceptRA.BlackList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix) IPv6AcceptRA.BlackList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0 TrafficControlQueueingDiscipline.Parent, config_parse_qdisc_parent, _QDISC_KIND_INVALID, 0
TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_network_emulator_delay, 0, 0 TrafficControlQueueingDiscipline.NetworkEmulatorDelaySec, config_parse_network_emulator_delay, 0, 0
TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_network_emulator_delay, 0, 0 TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_network_emulator_delay, 0, 0

View File

@ -135,8 +135,6 @@ struct Network {
uint32_t dhcp_route_metric; uint32_t dhcp_route_metric;
bool dhcp_route_metric_set; bool dhcp_route_metric_set;
uint32_t dhcp_route_table; uint32_t dhcp_route_table;
bool dhcp_route_table_set;
bool dhcp_route_table_set_explicitly;
uint32_t dhcp_fallback_lease_lifetime; uint32_t dhcp_fallback_lease_lifetime;
uint32_t dhcp_route_mtu; uint32_t dhcp_route_mtu;
uint16_t dhcp_client_port; uint16_t dhcp_client_port;
@ -157,6 +155,7 @@ struct Network {
int dhcp_use_gateway; int dhcp_use_gateway;
bool dhcp_use_timezone; bool dhcp_use_timezone;
bool dhcp_use_hostname; bool dhcp_use_hostname;
bool dhcp_route_table_set;
bool dhcp_send_release; bool dhcp_send_release;
bool dhcp_send_decline; bool dhcp_send_decline;
DHCPUseDomains dhcp_use_domains; DHCPUseDomains dhcp_use_domains;
@ -175,9 +174,6 @@ struct Network {
bool dhcp6_use_ntp; bool dhcp6_use_ntp;
bool dhcp6_use_ntp_set; bool dhcp6_use_ntp_set;
bool dhcp6_rapid_commit; bool dhcp6_rapid_commit;
bool dhcp6_route_table;
bool dhcp6_route_table_set;
bool dhcp6_route_table_set_explicitly;
DHCPUseDomains dhcp6_use_domains; DHCPUseDomains dhcp6_use_domains;
bool dhcp6_use_domains_set; bool dhcp6_use_domains_set;
uint32_t dhcp6_iaid; uint32_t dhcp6_iaid;

View File

@ -22,6 +22,24 @@
#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U #define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
static uint32_t link_get_vrf_table(const Link *link) {
return link->network->vrf ? VRF(link->network->vrf)->table : RT_TABLE_MAIN;
}
uint32_t link_get_dhcp_route_table(const Link *link) {
/* When the interface is part of an VRF use the VRFs routing table, unless
* another table is explicitly specified. */
if (link->network->dhcp_route_table_set)
return link->network->dhcp_route_table;
return link_get_vrf_table(link);
}
uint32_t link_get_ipv6_accept_ra_route_table(const Link *link) {
if (link->network->ipv6_accept_ra_route_table_set)
return link->network->ipv6_accept_ra_route_table;
return link_get_vrf_table(link);
}
static const char * const route_type_table[__RTN_MAX] = { static const char * const route_type_table[__RTN_MAX] = {
[RTN_UNICAST] = "unicast", [RTN_UNICAST] = "unicast",
[RTN_LOCAL] = "local", [RTN_LOCAL] = "local",

View File

@ -84,6 +84,9 @@ bool gateway_is_ready(Link *link, int onlink, int family, const union in_addr_un
int link_drop_routes(Link *link); int link_drop_routes(Link *link);
int link_drop_foreign_routes(Link *link); int link_drop_foreign_routes(Link *link);
uint32_t link_get_dhcp_route_table(const Link *link);
uint32_t link_get_ipv6_accept_ra_route_table(const Link *link);
int link_request_route( int link_request_route(
Link *link, Link *link,
Route *route, Route *route,

View File

@ -1,325 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "alloc-util.h"
#include "extract-word.h"
#include "hostname-util.h"
#include "in-addr-prefix-util.h"
#include "string-util.h"
/* 0.0.0.0/0 */
#define IN_ADDR_PREFIX_IPV4_ANY ((struct in_addr_prefix) { .family = AF_INET })
/* ::/0 */
#define IN_ADDR_PREFIX_IPV6_ANY ((struct in_addr_prefix) { .family = AF_INET6 })
/* 127.0.0.0/8 */
#define IN_ADDR_PREFIX_IPV4_LOCALHOST \
((struct in_addr_prefix) { \
.family = AF_INET, \
.address.in.s_addr = htobe32(UINT32_C(127) << 24), \
.prefixlen = 8, \
})
/* ::1/128 */
#define IN_ADDR_PREFIX_IPV6_LOCALHOST \
((struct in_addr_prefix) { \
.family = AF_INET6, \
.address.in6 = IN6ADDR_LOOPBACK_INIT, \
.prefixlen = 128, \
})
/* 169.254.0.0/16 */
#define IN_ADDR_PREFIX_IPV4_LINKLOCAL \
((struct in_addr_prefix) { \
.family = AF_INET, \
.address.in.s_addr = htobe32((UINT32_C(169) << 24) | \
(UINT32_C(254) << 16)), \
.prefixlen = 16, \
})
/* fe80::/64 */
#define IN_ADDR_PREFIX_IPV6_LINKLOCAL \
((struct in_addr_prefix) { \
.family = AF_INET6, \
.address.in6.s6_addr[0] = 0xfe, \
.address.in6.s6_addr[1] = 0x80, \
.prefixlen = 64, \
})
/* 224.0.0.0/4 */
#define IN_ADDR_PREFIX_IPV4_MULTICAST \
((struct in_addr_prefix) { \
.family = AF_INET, \
.address.in.s_addr = htobe32((UINT32_C(224) << 24)), \
.prefixlen = 4, \
})
/* ff00::/8 */
#define IN_ADDR_PREFIX_IPV6_MULTICAST \
((struct in_addr_prefix) { \
.family = AF_INET6, \
.address.in6.s6_addr[0] = 0xff, \
.prefixlen = 8, \
})
static void in_addr_prefix_hash_func(const struct in_addr_prefix *a, struct siphash *state) {
assert(a);
assert(state);
siphash24_compress(&a->family, sizeof(a->family), state);
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
}
static int in_addr_prefix_compare_func(const struct in_addr_prefix *x, const struct in_addr_prefix *y) {
int r;
assert(x);
assert(y);
r = CMP(x->family, y->family);
if (r != 0)
return r;
r = CMP(x->prefixlen, y->prefixlen);
if (r != 0)
return r;
return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
}
DEFINE_HASH_OPS(in_addr_prefix_hash_ops, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func);
DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(in_addr_prefix_hash_ops_free, struct in_addr_prefix, in_addr_prefix_hash_func, in_addr_prefix_compare_func, free);
int in_addr_prefix_add(Set **prefixes, const struct in_addr_prefix *prefix) {
struct in_addr_prefix *copy;
assert(prefixes);
assert(prefix);
assert(IN_SET(prefix->family, AF_INET, AF_INET6));
copy = newdup(struct in_addr_prefix, prefix, 1);
if (!copy)
return -ENOMEM;
(void) in_addr_mask(copy->family, &copy->address, copy->prefixlen);
return set_ensure_consume(prefixes, &in_addr_prefix_hash_ops_free, copy);
}
int in_addr_prefixes_reduce(Set *prefixes) {
uint32_t ipv4_prefixlen_bits = 0;
uint64_t ipv6_prefixlen_bits[128 / sizeof(uint64_t)] = {};
uint8_t ipv4_prefixlens[32] = {}, ipv6_prefixlens[128] = {};
bool ipv4_has_any = false, ipv6_has_any = false;
size_t ipv4_n_prefixlens = 0, ipv6_n_prefixlens = 0;
struct in_addr_prefix *p;
SET_FOREACH(p, prefixes)
switch(p->family) {
case AF_INET:
assert(p->prefixlen <= 32);
if (p->prefixlen == 0)
ipv4_has_any = true;
else
ipv4_prefixlen_bits |= UINT32_C(1) << (p->prefixlen - 1);
break;
case AF_INET6:
assert(p->prefixlen <= 128);
if (p->prefixlen == 0)
ipv6_has_any = true;
else
ipv6_prefixlen_bits[(p->prefixlen - 1) / sizeof(uint64_t)] |=
UINT64_C(1) << ((p->prefixlen - 1) % sizeof(uint64_t));
break;
default:
assert_not_reached();
}
if (!ipv4_has_any)
for (size_t i = 0; i < 32; i++)
if (ipv4_prefixlen_bits & (UINT32_C(1) << i))
ipv4_prefixlens[ipv4_n_prefixlens++] = i + 1;
if (!ipv6_has_any)
for (size_t i = 0; i < 128; i++)
if (ipv6_prefixlen_bits[i / sizeof(uint64_t)] &
(UINT64_C(1) << (i % sizeof(uint64_t))))
ipv6_prefixlens[ipv6_n_prefixlens++] = i + 1;
SET_FOREACH(p, prefixes) {
uint8_t *prefixlens;
bool covered;
size_t *n;
if (p->prefixlen == 0)
continue;
switch(p->family) {
case AF_INET:
prefixlens = ipv4_prefixlens;
n = &ipv4_n_prefixlens;
covered = ipv4_has_any;
break;
case AF_INET6:
prefixlens = ipv6_prefixlens;
n = &ipv6_n_prefixlens;
covered = ipv6_has_any;
break;
default:
assert_not_reached();
}
for (size_t i = 0; i < *n; i++) {
struct in_addr_prefix tmp;
if (covered)
break;
if (prefixlens[i] >= p->prefixlen)
break;
tmp = *p;
tmp.prefixlen = prefixlens[i];
(void) in_addr_mask(tmp.family, &tmp.address, tmp.prefixlen);
covered = set_contains(prefixes, &tmp);
}
if (covered)
free(set_remove(prefixes, p));
}
return 0;
}
int in_addr_prefixes_merge(Set **dest, Set *src) {
struct in_addr_prefix *p;
int r;
assert(dest);
SET_FOREACH(p, src) {
r = in_addr_prefix_add(dest, p);
if (r < 0)
return r;
}
return 0;
}
bool in_addr_prefixes_is_any(Set *prefixes) {
return
set_contains(prefixes, &IN_ADDR_PREFIX_IPV4_ANY) &&
set_contains(prefixes, &IN_ADDR_PREFIX_IPV6_ANY);
}
int config_parse_in_addr_prefixes(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Set **prefixes = data;
int r;
assert(prefixes);
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
if (isempty(rvalue)) {
*prefixes = set_free(*prefixes);
return 0;
}
for (const char *p = rvalue;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
if (r == -ENOMEM)
return log_oom();
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
return 0;
}
if (r == 0)
return 0;
if (streq(word, "any")) {
/* "any" is a shortcut for 0.0.0.0/0 and ::/0 */
if (ltype != AF_INET6) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV4_ANY);
if (r < 0)
return log_oom();
}
if (ltype != AF_INET) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV6_ANY);
if (r < 0)
return log_oom();
}
} else if (is_localhost(word)) {
/* "localhost" is a shortcut for 127.0.0.0/8 and ::1/128 */
if (ltype != AF_INET6) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV4_LOCALHOST);
if (r < 0)
return log_oom();
}
if (ltype != AF_INET) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV6_LOCALHOST);
if (r < 0)
return log_oom();
}
} else if (streq(word, "link-local")) {
/* "link-local" is a shortcut for 169.254.0.0/16 and fe80::/64 */
if (ltype != AF_INET6) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV4_LINKLOCAL);
if (r < 0)
return log_oom();
}
if (ltype != AF_INET) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV6_LINKLOCAL);
if (r < 0)
return log_oom();
}
} else if (streq(word, "multicast")) {
/* "multicast" is a shortcut for 224.0.0.0/4 and ff00::/8 */
if (ltype != AF_INET6) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV4_MULTICAST);
if (r < 0)
return log_oom();
}
if (ltype != AF_INET) {
r = in_addr_prefix_add(prefixes, &IN_ADDR_PREFIX_IPV6_MULTICAST);
if (r < 0)
return log_oom();
}
} else {
struct in_addr_prefix a;
if (ltype == AF_UNSPEC)
r = in_addr_prefix_from_string_auto(word, &a.family, &a.address, &a.prefixlen);
else {
a.family = ltype;
r = in_addr_prefix_from_string(word, a.family, &a.address, &a.prefixlen);
}
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Address prefix is invalid, ignoring assignment: %s", word);
continue;
}
r = in_addr_prefix_add(prefixes, &a);
if (r < 0)
return log_oom();
}
}
}

View File

@ -1,23 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "conf-parser.h"
#include "in-addr-util.h"
#include "set.h"
struct in_addr_prefix {
int family;
uint8_t prefixlen;
union in_addr_union address;
};
int in_addr_prefix_add(Set **prefixes, const struct in_addr_prefix *prefix);
int in_addr_prefixes_reduce(Set *prefixes);
int in_addr_prefixes_merge(Set **dest, Set *src);
/* Returns true if a set contains the two items necessary for "any" (0.0.0.0/0 and ::/0). */
bool in_addr_prefixes_is_any(Set *prefixes);
extern const struct hash_ops in_addr_prefix_hash_ops;
extern const struct hash_ops in_addr_prefix_hash_ops_free;
CONFIG_PARSER_PROTOTYPE(config_parse_in_addr_prefixes);

View File

@ -151,8 +151,6 @@ shared_sources = files('''
ima-util.h ima-util.h
import-util.c import-util.c
import-util.h import-util.h
in-addr-prefix-util.c
in-addr-prefix-util.h
initreq.h initreq.h
install-file.c install-file.c
install-file.h install-file.h

View File

@ -285,8 +285,6 @@ tests += [
[['src/test/test-in-addr-util.c']], [['src/test/test-in-addr-util.c']],
[['src/test/test-in-addr-prefix-util.c']],
[['src/test/test-barrier.c']], [['src/test/test-barrier.c']],
[['src/test/test-tmpfiles.c']], [['src/test/test-tmpfiles.c']],

View File

@ -6,7 +6,6 @@
#include "bpf-firewall.h" #include "bpf-firewall.h"
#include "bpf-program.h" #include "bpf-program.h"
#include "in-addr-prefix-util.h"
#include "load-fragment.h" #include "load-fragment.h"
#include "manager.h" #include "manager.h"
#include "memory-util.h" #include "memory-util.h"
@ -107,39 +106,21 @@ int main(int argc, char *argv[]) {
cc->ip_accounting = true; cc->ip_accounting = true;
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "10.0.1.0/24", &cc->ip_address_allow, NULL) == 0);
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressAllow", 0, "127.0.0.2", &cc->ip_address_allow, NULL) == 0);
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.3", &cc->ip_address_deny, NULL) == 0);
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "10.0.3.2/24", &cc->ip_address_deny, NULL) == 0);
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.1/25", &cc->ip_address_deny, NULL) == 0);
assert_se(config_parse_in_addr_prefixes(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0); assert_se(config_parse_ip_address_access(u->id, "filename", 1, "Service", 1, "IPAddressDeny", 0, "127.0.0.4", &cc->ip_address_deny, NULL) == 0);
assert_se(set_size(cc->ip_address_allow) == 2); assert(cc->ip_address_allow);
assert_se(set_size(cc->ip_address_deny) == 4); assert(cc->ip_address_allow->items_next);
assert(!cc->ip_address_allow->items_next->items_next);
/* The deny list is defined redundantly, let's ensure it will be properly reduced */ /* The deny list is defined redundantly, let's ensure it got properly reduced */
assert_se(in_addr_prefixes_reduce(cc->ip_address_allow) >= 0); assert(cc->ip_address_deny);
assert_se(in_addr_prefixes_reduce(cc->ip_address_deny) >= 0); assert(cc->ip_address_deny->items_next);
assert(!cc->ip_address_deny->items_next->items_next);
assert_se(set_size(cc->ip_address_allow) == 2);
assert_se(set_size(cc->ip_address_deny) == 2);
assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) {
.family = AF_INET,
.address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(1) << 8)),
.prefixlen = 24 }));
assert_se(set_contains(cc->ip_address_allow, &(struct in_addr_prefix) {
.family = AF_INET,
.address.in.s_addr = htobe32(0x7f000002),
.prefixlen = 32 }));
assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) {
.family = AF_INET,
.address.in.s_addr = htobe32(0x7f000000),
.prefixlen = 25 }));
assert_se(set_contains(cc->ip_address_deny, &(struct in_addr_prefix) {
.family = AF_INET,
.address.in.s_addr = htobe32((UINT32_C(10) << 24) | (UINT32_C(3) << 8)),
.prefixlen = 24 }));
assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.2 -W 5", SERVICE(u)->exec_command, u) == 0); assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.2 -W 5", SERVICE(u)->exec_command, u) == 0);
assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.3 -W 5", SERVICE(u)->exec_command, u) == 0); assert_se(config_parse_exec(u->id, "filename", 1, "Service", 1, "ExecStart", SERVICE_EXEC_START, "/bin/ping -c 1 127.0.0.3 -W 5", SERVICE(u)->exec_command, u) == 0);

View File

@ -1,94 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "in-addr-prefix-util.h"
#include "tests.h"
static void test_config_parse_in_addr_prefixes_one(int family, const union in_addr_union *addr, uint8_t prefixlen, Set **prefixes) {
_cleanup_free_ char *str = NULL;
assert_se(in_addr_prefix_to_string(family, addr, prefixlen, &str) >= 0);
assert_se(config_parse_in_addr_prefixes("unit", "filename", 1, "Service", 1, "IPAddressAllow", 0, str, prefixes, NULL) >= 0);
}
static void test_config_parse_in_addr_prefixes(Set **ret) {
_cleanup_set_free_ Set *prefixes = NULL;
log_info("/* %s() */", __func__);
for (uint32_t i = 0; i < 256; i++) {
/* ipv4 link-local address */
test_config_parse_in_addr_prefixes_one(AF_INET, &(union in_addr_union) {
.in.s_addr = htobe32((UINT32_C(169) << 24) |
(UINT32_C(254) << 16) |
(i << 8)),
}, 24, &prefixes);
/* ipv6 multicast address */
test_config_parse_in_addr_prefixes_one(AF_INET6, &(union in_addr_union) {
.in6.s6_addr[0] = 0xff,
.in6.s6_addr[1] = i,
}, 16, &prefixes);
for (uint32_t j = 0; j < 256; j++) {
test_config_parse_in_addr_prefixes_one(AF_INET, &(union in_addr_union) {
.in.s_addr = htobe32((UINT32_C(169) << 24) |
(UINT32_C(254) << 16) |
(i << 8) | j),
}, 32, &prefixes);
test_config_parse_in_addr_prefixes_one(AF_INET6, &(union in_addr_union) {
.in6.s6_addr[0] = 0xff,
.in6.s6_addr[1] = i,
.in6.s6_addr[2] = j,
}, 24, &prefixes);
}
}
*ret = TAKE_PTR(prefixes);
}
static void test_in_addr_prefixes_reduce(Set *prefixes) {
log_info("/* %s() */", __func__);
assert_se(set_size(prefixes) == 2 * 256 * 257);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(in_addr_prefixes_reduce(prefixes) >= 0);
assert_se(set_size(prefixes) == 2 * 256);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(config_parse_in_addr_prefixes("unit", "filename", 1, "Service", 1, "IPAddressAllow", 0, "link-local", &prefixes, NULL) == 0);
assert_se(set_size(prefixes) == 2 * 256 + 2);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(in_addr_prefixes_reduce(prefixes) >= 0);
assert_se(set_size(prefixes) == 256 + 2);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(config_parse_in_addr_prefixes("unit", "filename", 1, "Service", 1, "IPAddressAllow", 0, "multicast", &prefixes, NULL) == 0);
assert_se(set_size(prefixes) == 256 + 4);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(in_addr_prefixes_reduce(prefixes) >= 0);
assert_se(set_size(prefixes) == 4);
assert_se(!in_addr_prefixes_is_any(prefixes));
assert_se(config_parse_in_addr_prefixes("unit", "filename", 1, "Service", 1, "IPAddressAllow", 0, "any", &prefixes, NULL) == 0);
assert_se(set_size(prefixes) == 6);
assert_se(in_addr_prefixes_is_any(prefixes));
assert_se(in_addr_prefixes_reduce(prefixes) >= 0);
assert_se(set_size(prefixes) == 2);
assert_se(in_addr_prefixes_is_any(prefixes));
}
int main(int argc, char *argv[]) {
_cleanup_set_free_ Set *prefixes = NULL;
test_setup_logging(LOG_DEBUG);
test_config_parse_in_addr_prefixes(&prefixes);
test_in_addr_prefixes_reduce(prefixes);
return 0;
}

View File

@ -3,9 +3,9 @@
#include <fnmatch.h> #include <fnmatch.h>
#include <netinet/in.h> #include <netinet/in.h>
#include "in-addr-util.h" #include "log.h"
#include "strv.h" #include "strv.h"
#include "tests.h" #include "in-addr-util.h"
static void test_in_addr_prefix_from_string_one( static void test_in_addr_prefix_from_string_one(
const char *p, const char *p,
@ -238,7 +238,7 @@ static void test_in_addr_prefix_intersect(void) {
static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) { static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigned pl, const char *after) {
union in_addr_union ubefore, uafter, t; union in_addr_union ubefore, uafter, t;
log_debug("/* %s(%s, prefixlen=%u) */", __func__, before, pl); log_info("/* %s(%s, prefixlen=%u) */", __func__, before, pl);
assert_se(in_addr_from_string(f, before, &ubefore) >= 0); assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
@ -252,8 +252,6 @@ static void test_in_addr_prefix_next_one(unsigned f, const char *before, unsigne
} }
static void test_in_addr_prefix_next(void) { static void test_in_addr_prefix_next(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0"); test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 24, "192.168.1.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0"); test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 16, "192.169.0.0");
test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0"); test_in_addr_prefix_next_one(AF_INET, "192.168.0.0", 20, "192.168.16.0");
@ -278,7 +276,7 @@ static void test_in_addr_prefix_next(void) {
static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) { static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned pl, uint64_t nth, const char *after) {
union in_addr_union ubefore, uafter, t; union in_addr_union ubefore, uafter, t;
log_debug("/* %s(%s, prefixlen=%u, nth=%"PRIu64") */", __func__, before, pl, nth); log_info("/* %s(%s, prefixlen=%u, nth=%"PRIu64") */", __func__, before, pl, nth);
assert_se(in_addr_from_string(f, before, &ubefore) >= 0); assert_se(in_addr_from_string(f, before, &ubefore) >= 0);
@ -292,8 +290,6 @@ static void test_in_addr_prefix_nth_one(unsigned f, const char *before, unsigned
} }
static void test_in_addr_prefix_nth(void) { static void test_in_addr_prefix_nth(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0"); test_in_addr_prefix_nth_one(AF_INET, "192.168.0.0", 24, 0, "192.168.0.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 0, "192.168.0.0"); test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 0, "192.168.0.0");
test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 1, "192.168.1.0"); test_in_addr_prefix_nth_one(AF_INET, "192.168.0.123", 24, 1, "192.168.1.0");
@ -327,7 +323,7 @@ static void test_in_addr_prefix_range_one(
union in_addr_union a, s, e; union in_addr_union a, s, e;
log_debug("/* %s(%s, prefixlen=%u) */", __func__, in, prefixlen); log_info("/* %s(%s, prefixlen=%u) */", __func__, in, prefixlen);
assert_se(in_addr_from_string(family, in, &a) >= 0); assert_se(in_addr_from_string(family, in, &a) >= 0);
assert_se((in_addr_prefix_range(family, &a, prefixlen, &s, &e) >= 0) == !!expected_start); assert_se((in_addr_prefix_range(family, &a, prefixlen, &s, &e) >= 0) == !!expected_start);
@ -347,8 +343,6 @@ static void test_in_addr_prefix_range_one(
} }
static void test_in_addr_prefix_range(void) { static void test_in_addr_prefix_range(void) {
log_info("/* %s */", __func__);
test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 24, "192.168.123.0", "192.168.124.0"); test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 24, "192.168.123.0", "192.168.124.0");
test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 16, "192.168.0.0", "192.169.0.0"); test_in_addr_prefix_range_one(AF_INET, "192.168.123.123", 16, "192.168.0.0", "192.169.0.0");
@ -382,8 +376,6 @@ static void test_in_addr_to_string(void) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
test_in_addr_prefix_from_string(); test_in_addr_prefix_from_string();
test_in_addr_random_prefix(); test_in_addr_random_prefix();
test_in_addr_prefix_to_string(); test_in_addr_prefix_to_string();

View File

@ -148,7 +148,6 @@ RouteMetric=
IAID= IAID=
DUIDType= DUIDType=
DUIDRawData= DUIDRawData=
RouteTable=
[DHCPv6PrefixDelegation] [DHCPv6PrefixDelegation]
SubnetId= SubnetId=
Announce= Announce=