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.
9a89ab26d6
...
ed938716cd
@ -50,28 +50,6 @@ service manager.
|
||||
|
||||
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
|
||||
|
||||
Sources for the udev daemon and command-line tool (single binary) can be found under
|
||||
|
||||
@ -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
|
||||
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
|
||||
"unsealed") if specific trusted software and/or configuration is used.</para>
|
||||
"unsealed") if specific trusted software and/or configuration is used.</para></listitem>
|
||||
|
||||
<table>
|
||||
<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'>
|
||||
<colspec colname="pcr" />
|
||||
<colspec colname="definition" />
|
||||
@ -229,7 +224,7 @@
|
||||
|
||||
<row>
|
||||
<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>
|
||||
@ -244,39 +239,17 @@
|
||||
|
||||
<row>
|
||||
<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>
|
||||
<entry>8</entry>
|
||||
<entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line into 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>
|
||||
<entry><citerefentry><refentrytitle>sd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry> measures the kernel command line in this PCR.</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</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>
|
||||
|
||||
@ -2111,7 +2111,6 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RouteMetric=</varname></term>
|
||||
<term><varname>UseDNS=</varname></term>
|
||||
<term><varname>UseNTP=</varname></term>
|
||||
<term><varname>UseHostname=</varname></term>
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#include "bus-util.h"
|
||||
#include "env-util.h"
|
||||
#include "format-table.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "locale-util.h"
|
||||
#include "macro.h"
|
||||
#include "manager.h"
|
||||
@ -2582,10 +2582,10 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
struct in_addr_prefix *i;
|
||||
IPAddressAccessItem *i;
|
||||
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)
|
||||
deny_ipv4 = true;
|
||||
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_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))
|
||||
info->ip_address_allow_localhost = true;
|
||||
else
|
||||
|
||||
@ -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);
|
||||
|
||||
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) {
|
||||
assert(addr);
|
||||
assert(state);
|
||||
|
||||
@ -20,6 +20,12 @@ struct in_addr_data {
|
||||
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);
|
||||
static inline bool in4_addr_is_set(const struct in_addr *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);
|
||||
|
||||
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;
|
||||
|
||||
#define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u"
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
#include "bpf-firewall.h"
|
||||
#include "bpf-program.h"
|
||||
#include "fd-util.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "unit.h"
|
||||
@ -335,13 +335,13 @@ static int bpf_firewall_compile_bpf(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t *n_ipv6) {
|
||||
struct in_addr_prefix *a;
|
||||
static int bpf_firewall_count_access_items(IPAddressAccessItem *list, size_t *n_ipv4, size_t *n_ipv6) {
|
||||
IPAddressAccessItem *a;
|
||||
|
||||
assert(n_ipv4);
|
||||
assert(n_ipv6);
|
||||
|
||||
SET_FOREACH(a, prefixes)
|
||||
LIST_FOREACH(items, a, list) {
|
||||
switch (a->family) {
|
||||
|
||||
case AF_INET:
|
||||
@ -355,25 +355,26 @@ static int bpf_firewall_count_access_items(Set *prefixes, size_t *n_ipv4, size_t
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_firewall_add_access_items(
|
||||
Set *prefixes,
|
||||
IPAddressAccessItem *list,
|
||||
int ipv4_map_fd,
|
||||
int ipv6_map_fd,
|
||||
int verdict) {
|
||||
|
||||
struct bpf_lpm_trie_key *key_ipv4, *key_ipv6;
|
||||
struct in_addr_prefix *a;
|
||||
uint64_t value = verdict;
|
||||
IPAddressAccessItem *a;
|
||||
int r;
|
||||
|
||||
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);
|
||||
|
||||
SET_FOREACH(a, prefixes)
|
||||
LIST_FOREACH(items, a, list) {
|
||||
switch (a->family) {
|
||||
|
||||
case AF_INET:
|
||||
@ -399,6 +400,7 @@ static int bpf_firewall_add_access_items(
|
||||
default:
|
||||
return -EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -412,6 +414,7 @@ static int bpf_firewall_prepare_access_maps(
|
||||
|
||||
_cleanup_close_ int ipv4_map_fd = -1, ipv6_map_fd = -1;
|
||||
size_t n_ipv4 = 0, n_ipv6 = 0;
|
||||
IPAddressAccessItem *list;
|
||||
Unit *p;
|
||||
int r;
|
||||
|
||||
@ -421,29 +424,18 @@ static int bpf_firewall_prepare_access_maps(
|
||||
|
||||
for (p = u; p; p = UNIT_GET_SLICE(p)) {
|
||||
CGroupContext *cc;
|
||||
Set *prefixes;
|
||||
bool *reduced;
|
||||
|
||||
cc = unit_get_cgroup_context(p);
|
||||
if (!cc)
|
||||
continue;
|
||||
|
||||
prefixes = 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;
|
||||
list = verdict == ACCESS_ALLOWED ? cc->ip_address_allow : cc->ip_address_deny;
|
||||
|
||||
if (!*reduced) {
|
||||
r = in_addr_prefixes_reduce(prefixes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*reduced = true;
|
||||
}
|
||||
|
||||
bpf_firewall_count_access_items(prefixes, &n_ipv4, &n_ipv6);
|
||||
bpf_firewall_count_access_items(list, &n_ipv4, &n_ipv6);
|
||||
|
||||
/* 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. */
|
||||
if (in_addr_prefixes_is_any(prefixes)) {
|
||||
if (ip_address_access_item_is_any(list)) {
|
||||
*ret_has_any = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -19,7 +19,6 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "fs-util.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "io-util.h"
|
||||
#include "ip-protocol-list.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_deny);
|
||||
|
||||
c->ip_address_allow = set_free(c->ip_address_allow);
|
||||
c->ip_address_deny = set_free(c->ip_address_deny);
|
||||
c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
|
||||
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_egress = strv_free(c->ip_filters_egress);
|
||||
@ -396,7 +395,7 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
|
||||
CGroupDeviceAllow *a;
|
||||
CGroupContext *c;
|
||||
CGroupSocketBindItem *bi;
|
||||
struct in_addr_prefix *iaai;
|
||||
IPAddressAccessItem *iaai;
|
||||
char **path;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
SET_FOREACH(iaai, c->ip_address_allow) {
|
||||
LIST_FOREACH(items, iaai, c->ip_address_allow) {
|
||||
_cleanup_free_ char *k = NULL;
|
||||
|
||||
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k);
|
||||
fprintf(f, "%sIPAddressAllow: %s\n", prefix, strnull(k));
|
||||
(void) in_addr_to_string(iaai->family, &iaai->address, &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;
|
||||
|
||||
(void) in_addr_prefix_to_string(iaai->family, &iaai->address, iaai->prefixlen, &k);
|
||||
fprintf(f, "%sIPAddressDeny: %s\n", prefix, strnull(k));
|
||||
(void) in_addr_to_string(iaai->family, &iaai->address, &k);
|
||||
fprintf(f, "%sIPAddressDeny: %s/%u\n", prefix, strnull(k), iaai->prefixlen);
|
||||
}
|
||||
|
||||
STRV_FOREACH(path, c->ip_filters_ingress)
|
||||
@ -1556,8 +1555,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
|
||||
return false;
|
||||
|
||||
if (c->ip_accounting ||
|
||||
!set_isempty(c->ip_address_allow) ||
|
||||
!set_isempty(c->ip_address_deny) ||
|
||||
c->ip_address_allow ||
|
||||
c->ip_address_deny ||
|
||||
c->ip_filters_ingress ||
|
||||
c->ip_filters_egress)
|
||||
return true;
|
||||
@ -1568,8 +1567,8 @@ static bool unit_get_needs_bpf_firewall(Unit *u) {
|
||||
if (!c)
|
||||
return false;
|
||||
|
||||
if (!set_isempty(c->ip_address_allow) ||
|
||||
!set_isempty(c->ip_address_deny))
|
||||
if (c->ip_address_allow ||
|
||||
c->ip_address_deny)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "cgroup-util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "list.h"
|
||||
#include "time-util.h"
|
||||
|
||||
@ -147,17 +148,13 @@ struct CGroupContext {
|
||||
uint64_t memory_max;
|
||||
uint64_t memory_swap_max;
|
||||
|
||||
bool default_memory_min_set:1;
|
||||
bool default_memory_low_set:1;
|
||||
bool memory_min_set:1;
|
||||
bool memory_low_set:1;
|
||||
bool default_memory_min_set;
|
||||
bool default_memory_low_set;
|
||||
bool memory_min_set;
|
||||
bool memory_low_set;
|
||||
|
||||
Set *ip_address_allow;
|
||||
Set *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;
|
||||
LIST_HEAD(IPAddressAccessItem, ip_address_allow);
|
||||
LIST_HEAD(IPAddressAccessItem, ip_address_deny);
|
||||
|
||||
char **ip_filters_ingress;
|
||||
char **ip_filters_egress;
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "ip-protocol-list.h"
|
||||
#include "limits-util.h"
|
||||
#include "parse-util.h"
|
||||
@ -319,17 +318,14 @@ static int property_get_ip_address_access(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Set **prefixes = userdata;
|
||||
struct in_addr_prefix *i;
|
||||
IPAddressAccessItem** items = userdata, *i;
|
||||
int r;
|
||||
|
||||
assert(prefixes);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "(iayu)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
SET_FOREACH(i, *prefixes) {
|
||||
LIST_FOREACH(items, i, *items) {
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'r', "iayu");
|
||||
if (r < 0)
|
||||
@ -1749,9 +1745,11 @@ int bus_cgroup_set_property(
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
|
||||
_cleanup_set_free_ Set *new_prefixes = NULL;
|
||||
IPAddressAccessItem **list;
|
||||
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)");
|
||||
if (r < 0)
|
||||
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));
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
struct in_addr_prefix prefix = {
|
||||
.family = family,
|
||||
.prefixlen = prefixlen,
|
||||
};
|
||||
IPAddressAccessItem *item;
|
||||
|
||||
memcpy(&prefix.address, ap, an);
|
||||
item = new0(IPAddressAccessItem, 1);
|
||||
if (!item)
|
||||
return -ENOMEM;
|
||||
|
||||
r = in_addr_prefix_add(&new_prefixes, &prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
item->family = family;
|
||||
item->prefixlen = prefixlen;
|
||||
memcpy(&item->address, ap, an);
|
||||
|
||||
LIST_PREPEND(items, *list, item);
|
||||
}
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
@ -1814,46 +1813,33 @@ int bus_cgroup_set_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*list = ip_address_access_reduce(*list);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
IPAddressAccessItem *item;
|
||||
size_t size = 0;
|
||||
Set **prefixes;
|
||||
bool *reduced;
|
||||
|
||||
if (n == 0)
|
||||
*list = ip_address_access_free_all(*list);
|
||||
|
||||
unit_invalidate_cgroup_bpf(u);
|
||||
f = open_memstream_unlocked(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
prefixes = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
|
||||
reduced = streq(name, "IPAddressAllow") ? &c->ip_address_allow_reduced : &c->ip_address_deny_reduced;
|
||||
|
||||
if (n == 0) {
|
||||
*reduced = true;
|
||||
*prefixes = set_free(*prefixes);
|
||||
fputs(name, f);
|
||||
fputs("=\n", f);
|
||||
} else {
|
||||
struct in_addr_prefix *p;
|
||||
|
||||
*reduced = false;
|
||||
LIST_FOREACH(items, item, *list) {
|
||||
char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
|
||||
|
||||
r = in_addr_prefixes_merge(prefixes, new_prefixes);
|
||||
if (r < 0)
|
||||
return r;
|
||||
errno = 0;
|
||||
if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
|
||||
return errno_or_else(EINVAL);
|
||||
|
||||
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);
|
||||
}
|
||||
fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
|
||||
208
src/core/ip-address-access.c
Normal file
208
src/core/ip-address-access.c
Normal 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;
|
||||
}
|
||||
25
src/core/ip-address-access.h
Normal file
25
src/core/ip-address-access.h
Normal 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);
|
||||
@ -221,8 +221,8 @@
|
||||
{{type}}.Delegate, config_parse_delegate, 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}}.IPAddressAllow, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_allow)
|
||||
{{type}}.IPAddressDeny, config_parse_in_addr_prefixes, AF_UNSPEC, offsetof({{type}}, cgroup_context.ip_address_deny)
|
||||
{{type}}.IPAddressAllow, config_parse_ip_address_access, 0, offsetof({{type}}, cgroup_context.ip_address_allow)
|
||||
{{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}}.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)
|
||||
@ -243,7 +243,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#include <stddef.h>
|
||||
#include "all-units.h"
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "load-fragment.h"
|
||||
%}
|
||||
struct ConfigPerfItem;
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#include "cgroup.h"
|
||||
#include "fdset.h"
|
||||
#include "hashmap.h"
|
||||
#include "ip-address-access.h"
|
||||
#include "list.h"
|
||||
#include "prioq.h"
|
||||
#include "ratelimit.h"
|
||||
|
||||
@ -71,6 +71,8 @@ libcore_sources = '''
|
||||
generator-setup.h
|
||||
ima-setup.c
|
||||
ima-setup.h
|
||||
ip-address-access.c
|
||||
ip-address-access.h
|
||||
job.c
|
||||
job.h
|
||||
kill.c
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
#include "dhcp6-internal.h"
|
||||
#include "escape.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "networkd-dhcp-common.h"
|
||||
#include "networkd-link.h"
|
||||
#include "networkd-manager.h"
|
||||
@ -18,44 +18,6 @@
|
||||
#include "socket-util.h"
|
||||
#include "string-table.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) {
|
||||
assert(link);
|
||||
@ -310,7 +272,7 @@ int config_parse_dhcp(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_or_ra_route_metric(
|
||||
int config_parse_dhcp_route_metric(
|
||||
const char* unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -328,7 +290,6 @@ int config_parse_dhcp_or_ra_route_metric(
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
@ -339,24 +300,17 @@ int config_parse_dhcp_or_ra_route_metric(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
case AF_INET:
|
||||
if (streq_ptr(section, "DHCPv4")) {
|
||||
network->dhcp_route_metric = metric;
|
||||
network->dhcp_route_metric_set = true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
} else if (STRPTR_IN_SET(section, "DHCPv6", "IPv6AcceptRA")) {
|
||||
network->ipv6_accept_ra_route_metric = metric;
|
||||
network->ipv6_accept_ra_route_metric_set = true;
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
/* For backward compatibility. */
|
||||
} else { /* [DHCP] section */
|
||||
if (!network->dhcp_route_metric_set)
|
||||
network->dhcp_route_metric = metric;
|
||||
if (!network->ipv6_accept_ra_route_metric_set)
|
||||
network->ipv6_accept_ra_route_metric = metric;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -379,7 +333,6 @@ int config_parse_dhcp_use_dns(
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
@ -390,24 +343,17 @@ int config_parse_dhcp_use_dns(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
case AF_INET:
|
||||
if (streq_ptr(section, "DHCPv4")) {
|
||||
network->dhcp_use_dns = r;
|
||||
network->dhcp_use_dns_set = true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
} else if (streq_ptr(section, "DHCPv6")) {
|
||||
network->dhcp6_use_dns = r;
|
||||
network->dhcp6_use_dns_set = true;
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
/* For backward compatibility. */
|
||||
} else { /* [DHCP] section */
|
||||
if (!network->dhcp_use_dns_set)
|
||||
network->dhcp_use_dns = r;
|
||||
if (!network->dhcp6_use_dns_set)
|
||||
network->dhcp6_use_dns = r;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -430,7 +376,6 @@ int config_parse_dhcp_use_domains(
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
@ -441,24 +386,17 @@ int config_parse_dhcp_use_domains(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
case AF_INET:
|
||||
if (streq_ptr(section, "DHCPv4")) {
|
||||
network->dhcp_use_domains = d;
|
||||
network->dhcp_use_domains_set = true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
} else if (streq_ptr(section, "DHCPv6")) {
|
||||
network->dhcp6_use_domains = d;
|
||||
network->dhcp6_use_domains_set = true;
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
/* For backward compatibility. */
|
||||
} else { /* [DHCP] section */
|
||||
if (!network->dhcp_use_domains_set)
|
||||
network->dhcp_use_domains = d;
|
||||
if (!network->dhcp6_use_domains_set)
|
||||
network->dhcp6_use_domains = d;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -481,7 +419,6 @@ int config_parse_dhcp_use_ntp(
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
|
||||
assert(rvalue);
|
||||
assert(data);
|
||||
|
||||
@ -492,30 +429,23 @@ int config_parse_dhcp_use_ntp(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
case AF_INET:
|
||||
if (streq_ptr(section, "DHCPv4")) {
|
||||
network->dhcp_use_ntp = r;
|
||||
network->dhcp_use_ntp_set = true;
|
||||
break;
|
||||
case AF_INET6:
|
||||
} else if (streq_ptr(section, "DHCPv6")) {
|
||||
network->dhcp6_use_ntp = r;
|
||||
network->dhcp6_use_ntp_set = true;
|
||||
break;
|
||||
case AF_UNSPEC:
|
||||
/* For backward compatibility. */
|
||||
} else { /* [DHCP] section */
|
||||
if (!network->dhcp_use_ntp_set)
|
||||
network->dhcp_use_ntp = r;
|
||||
if (!network->dhcp6_use_ntp_set)
|
||||
network->dhcp6_use_ntp = r;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_or_ra_route_table(
|
||||
int config_parse_section_route_table(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -533,11 +463,6 @@ int config_parse_dhcp_or_ra_route_table(
|
||||
|
||||
assert(filename);
|
||||
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(data);
|
||||
|
||||
@ -548,34 +473,12 @@ int config_parse_dhcp_or_ra_route_table(
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(ltype) {
|
||||
case (RTPROT_DHCP<<16) | AF_INET:
|
||||
if (STRPTR_IN_SET(section, "DHCP", "DHCPv4")) {
|
||||
network->dhcp_route_table = rt;
|
||||
network->dhcp_route_table_set = true;
|
||||
network->dhcp_route_table_set_explicitly = true;
|
||||
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:
|
||||
} else { /* section is IPv6AcceptRA */
|
||||
network->ipv6_accept_ra_route_table = rt;
|
||||
network->ipv6_accept_ra_route_table_set = true;
|
||||
break;
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1265,3 +1168,69 @@ int config_parse_network_duid_rawdata(
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,10 +44,6 @@ typedef struct DUID {
|
||||
bool set;
|
||||
} 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);
|
||||
static inline bool link_dhcp4_enabled(Link *link) {
|
||||
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_;
|
||||
|
||||
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_domains);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp);
|
||||
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_send_option);
|
||||
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_manager_duid_rawdata);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_network_duid_rawdata);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_address_filter);
|
||||
|
||||
@ -135,26 +135,6 @@ static int dhcp4_after_route_configure(Request *req, void *object) {
|
||||
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) {
|
||||
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_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)
|
||||
link_enter_failed(link);
|
||||
|
||||
@ -205,16 +197,6 @@ static int dhcp4_request_route(Route *in, Link *link) {
|
||||
assert(route);
|
||||
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);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -261,10 +243,14 @@ static int dhcp4_request_prefix_route(Link *link) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route->family = AF_INET;
|
||||
route->dst.in.s_addr = address.s_addr & netmask.s_addr;
|
||||
route->dst_prefixlen = in4_addr_netmask_to_prefixlen(&netmask);
|
||||
route->prefsrc.in = address;
|
||||
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);
|
||||
}
|
||||
@ -286,10 +272,15 @@ static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw)
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route->family = AF_INET;
|
||||
route->dst.in = *gw;
|
||||
route->dst_prefixlen = 32;
|
||||
route->prefsrc.in = address;
|
||||
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);
|
||||
}
|
||||
@ -463,7 +454,12 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route->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);
|
||||
if (r < 0)
|
||||
@ -541,9 +537,14 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *gw) {
|
||||
return r;
|
||||
|
||||
/* Next, add a default gateway. */
|
||||
route->family = AF_INET;
|
||||
route->gw_family = AF_INET;
|
||||
route->gw.in = router[0];
|
||||
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);
|
||||
if (r < 0)
|
||||
@ -585,6 +586,14 @@ static int dhcp4_request_semi_static_routes(Link *link, const struct in_addr *gw
|
||||
return r;
|
||||
|
||||
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);
|
||||
if (r < 0)
|
||||
@ -618,8 +627,13 @@ static int dhcp4_request_routes_to_servers(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
route->family = AF_INET;
|
||||
route->dst.in = servers[i];
|
||||
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);
|
||||
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) {
|
||||
_cleanup_(address_freep) Address *addr = NULL;
|
||||
uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME;
|
||||
struct in_addr address, netmask, server;
|
||||
struct in_addr address, netmask;
|
||||
unsigned prefixlen;
|
||||
Request *req;
|
||||
int r;
|
||||
@ -928,10 +942,6 @@ static int dhcp4_request_address(Link *link, bool announce) {
|
||||
if (r < 0)
|
||||
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)) {
|
||||
r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime);
|
||||
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]))
|
||||
log_struct(LOG_INFO,
|
||||
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),
|
||||
prefixlen,
|
||||
IPV4_ADDRESS_FMT_VAL(router[0]),
|
||||
IPV4_ADDRESS_FMT_VAL(server)),
|
||||
IPV4_ADDRESS_FMT_VAL(router[0])),
|
||||
"ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
|
||||
"PREFIXLEN=%u", prefixlen,
|
||||
"GATEWAY="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(router[0]));
|
||||
else
|
||||
log_struct(LOG_INFO,
|
||||
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),
|
||||
prefixlen,
|
||||
IPV4_ADDRESS_FMT_VAL(server)),
|
||||
prefixlen),
|
||||
"ADDRESS="IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address),
|
||||
"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->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 (r < 0)
|
||||
return r;
|
||||
if (link->network->dhcp_label) {
|
||||
addr->label = strdup(link->network->dhcp_label);
|
||||
if (!addr->label)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (address_get(link, addr, NULL) < 0)
|
||||
link->dhcp4_configured = false;
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#include "hashmap.h"
|
||||
#include "hostname-setup.h"
|
||||
#include "hostname-util.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "missing_network.h"
|
||||
#include "networkd-address.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->dst.in6 = *addr;
|
||||
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->protocol = RTPROT_DHCP;
|
||||
|
||||
|
||||
@ -403,13 +403,6 @@ static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
|
||||
assert(link);
|
||||
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);
|
||||
if (r < 0)
|
||||
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) {
|
||||
_cleanup_(route_freep) Route *route = NULL;
|
||||
struct in6_addr gateway;
|
||||
uint32_t mtu = 0;
|
||||
uint32_t table, mtu = 0;
|
||||
unsigned preference;
|
||||
uint16_t lifetime;
|
||||
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");
|
||||
}
|
||||
|
||||
table = link_get_ipv6_accept_ra_route_table(link);
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
route->family = AF_INET6;
|
||||
route->table = table;
|
||||
route->priority = link->network->ipv6_accept_ra_route_metric;
|
||||
route->protocol = RTPROT_RA;
|
||||
route->pref = preference;
|
||||
route->gw_family = AF_INET6;
|
||||
route->gw.in6 = gateway;
|
||||
@ -616,6 +614,12 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
|
||||
return r;
|
||||
|
||||
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)
|
||||
route->pref = preference;
|
||||
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();
|
||||
|
||||
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->dst_prefixlen = prefixlen;
|
||||
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();
|
||||
|
||||
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->gw.in6 = gateway;
|
||||
route->gw_family = AF_INET6;
|
||||
|
||||
@ -5,7 +5,6 @@ _Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include "conf-parser.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "netem.h"
|
||||
#include "net-condition.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.Group, config_parse_nexthop_group, 0, 0
|
||||
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.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.UseSIP, config_parse_bool, 0, offsetof(Network, dhcp_use_sip)
|
||||
DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
|
||||
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.UseGateway, config_parse_tristate, 0, offsetof(Network, dhcp_use_gateway)
|
||||
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.DUIDType, config_parse_network_duid_type, 0, 0
|
||||
DHCPv4.DUIDRawData, config_parse_network_duid_rawdata, 0, 0
|
||||
DHCPv4.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET, 0
|
||||
DHCPv4.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_INET, 0
|
||||
DHCPv4.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
DHCPv4.RouteTable, config_parse_section_route_table, 0, 0
|
||||
DHCPv4.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
|
||||
DHCPv4.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
|
||||
DHCPv4.SendRelease, config_parse_bool, 0, offsetof(Network, dhcp_send_release)
|
||||
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.AllowList, config_parse_in_addr_prefixes, AF_INET, offsetof(Network, dhcp_allow_listed_ip)
|
||||
DHCPv4.DenyList, config_parse_address_filter, AF_INET, offsetof(Network, dhcp_deny_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.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.RouteMTUBytes, config_parse_mtu, AF_INET, offsetof(Network, dhcp_route_mtu)
|
||||
DHCPv4.FallbackLeaseLifetimeSec, config_parse_dhcp_fallback_lease_lifetime, 0, 0
|
||||
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.UseDomains, config_parse_dhcp_use_domains, AF_INET6, 0
|
||||
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, AF_INET6, 0
|
||||
DHCPv6.UseDomains, config_parse_dhcp_use_domains, 0, 0
|
||||
DHCPv6.UseNTP, config_parse_dhcp_use_ntp, 0, 0
|
||||
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
|
||||
DHCPv6.MUDURL, config_parse_mud_url, 0, offsetof(Network, dhcp6_mudurl)
|
||||
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.DUIDType, config_parse_duid_type, 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.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.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.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.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0
|
||||
IPv6AcceptRA.RouterAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_router)
|
||||
IPv6AcceptRA.RouterDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_router)
|
||||
IPv6AcceptRA.PrefixAllowList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix)
|
||||
IPv6AcceptRA.PrefixDenyList, config_parse_in_addr_prefixes, 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.RouteDenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_route_prefix)
|
||||
IPv6AcceptRA.RouteTable, config_parse_section_route_table, 0, 0
|
||||
IPv6AcceptRA.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
IPv6AcceptRA.RouterAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_router)
|
||||
IPv6AcceptRA.RouterDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_router)
|
||||
IPv6AcceptRA.PrefixAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_listed_prefix)
|
||||
IPv6AcceptRA.PrefixDenyList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
|
||||
IPv6AcceptRA.RouteAllowList, config_parse_address_filter, AF_INET6, offsetof(Network, ndisc_allow_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.UplinkInterface, config_parse_uplink, 0, 0
|
||||
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.Domains, config_parse_radv_search_domains, 0, 0
|
||||
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.UseDNS, config_parse_dhcp_use_dns, AF_UNSPEC, 0
|
||||
DHCP.UseNTP, config_parse_dhcp_use_ntp, AF_UNSPEC, 0
|
||||
DHCP.UseDNS, config_parse_dhcp_use_dns, 0, 0
|
||||
DHCP.UseNTP, config_parse_dhcp_use_ntp, 0, 0
|
||||
DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu)
|
||||
DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname)
|
||||
DHCP.UseDomains, config_parse_dhcp_use_domains, AF_UNSPEC, 0
|
||||
DHCP.UseDomainName, config_parse_dhcp_use_domains, AF_UNSPEC, 0
|
||||
DHCP.UseDomains, config_parse_dhcp_use_domains, 0, 0
|
||||
DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, 0
|
||||
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes)
|
||||
DHCP.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize)
|
||||
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.DUIDType, config_parse_network_duid_type, 0, 0
|
||||
DHCP.DUIDRawData, config_parse_network_duid_rawdata, 0, 0
|
||||
DHCP.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_UNSPEC, 0
|
||||
DHCP.RouteTable, config_parse_dhcp_or_ra_route_table, (RTPROT_DHCP<<16) | AF_UNSPEC, 0
|
||||
DHCP.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
DHCP.RouteTable, config_parse_section_route_table, 0, 0
|
||||
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
|
||||
DHCP.ListenPort, config_parse_uint16, 0, offsetof(Network, dhcp_client_port)
|
||||
DHCP.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
|
||||
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)
|
||||
DHCPv6.RouteMetric, config_parse_dhcp_or_ra_route_metric, AF_INET6, 0
|
||||
IPv6AcceptRA.DenyList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
|
||||
IPv6AcceptRA.BlackList, config_parse_in_addr_prefixes, AF_INET6, offsetof(Network, ndisc_deny_listed_prefix)
|
||||
DHCPv6.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
IPv6AcceptRA.DenyList, config_parse_address_filter, 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.NetworkEmulatorDelaySec, config_parse_network_emulator_delay, 0, 0
|
||||
TrafficControlQueueingDiscipline.NetworkEmulatorDelayJitterSec, config_parse_network_emulator_delay, 0, 0
|
||||
|
||||
@ -135,8 +135,6 @@ struct Network {
|
||||
uint32_t dhcp_route_metric;
|
||||
bool dhcp_route_metric_set;
|
||||
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_route_mtu;
|
||||
uint16_t dhcp_client_port;
|
||||
@ -157,6 +155,7 @@ struct Network {
|
||||
int dhcp_use_gateway;
|
||||
bool dhcp_use_timezone;
|
||||
bool dhcp_use_hostname;
|
||||
bool dhcp_route_table_set;
|
||||
bool dhcp_send_release;
|
||||
bool dhcp_send_decline;
|
||||
DHCPUseDomains dhcp_use_domains;
|
||||
@ -175,9 +174,6 @@ struct Network {
|
||||
bool dhcp6_use_ntp;
|
||||
bool dhcp6_use_ntp_set;
|
||||
bool dhcp6_rapid_commit;
|
||||
bool dhcp6_route_table;
|
||||
bool dhcp6_route_table_set;
|
||||
bool dhcp6_route_table_set_explicitly;
|
||||
DHCPUseDomains dhcp6_use_domains;
|
||||
bool dhcp6_use_domains_set;
|
||||
uint32_t dhcp6_iaid;
|
||||
|
||||
@ -22,6 +22,24 @@
|
||||
|
||||
#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] = {
|
||||
[RTN_UNICAST] = "unicast",
|
||||
[RTN_LOCAL] = "local",
|
||||
|
||||
@ -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_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(
|
||||
Link *link,
|
||||
Route *route,
|
||||
|
||||
@ -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, ©->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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
@ -151,8 +151,6 @@ shared_sources = files('''
|
||||
ima-util.h
|
||||
import-util.c
|
||||
import-util.h
|
||||
in-addr-prefix-util.c
|
||||
in-addr-prefix-util.h
|
||||
initreq.h
|
||||
install-file.c
|
||||
install-file.h
|
||||
|
||||
@ -285,8 +285,6 @@ tests += [
|
||||
|
||||
[['src/test/test-in-addr-util.c']],
|
||||
|
||||
[['src/test/test-in-addr-prefix-util.c']],
|
||||
|
||||
[['src/test/test-barrier.c']],
|
||||
|
||||
[['src/test/test-tmpfiles.c']],
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
|
||||
#include "bpf-firewall.h"
|
||||
#include "bpf-program.h"
|
||||
#include "in-addr-prefix-util.h"
|
||||
#include "load-fragment.h"
|
||||
#include "manager.h"
|
||||
#include "memory-util.h"
|
||||
@ -107,39 +106,21 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
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_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_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_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_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_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, "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, "127.0.0.2", &cc->ip_address_allow, 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_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_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_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_se(set_size(cc->ip_address_deny) == 4);
|
||||
assert(cc->ip_address_allow);
|
||||
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 */
|
||||
assert_se(in_addr_prefixes_reduce(cc->ip_address_allow) >= 0);
|
||||
assert_se(in_addr_prefixes_reduce(cc->ip_address_deny) >= 0);
|
||||
|
||||
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 }));
|
||||
/* The deny list is defined redundantly, let's ensure it got properly reduced */
|
||||
assert(cc->ip_address_deny);
|
||||
assert(cc->ip_address_deny->items_next);
|
||||
assert(!cc->ip_address_deny->items_next->items_next);
|
||||
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -3,9 +3,9 @@
|
||||
#include <fnmatch.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "in-addr-util.h"
|
||||
#include "log.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "in-addr-util.h"
|
||||
|
||||
static void test_in_addr_prefix_from_string_one(
|
||||
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) {
|
||||
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);
|
||||
|
||||
@ -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) {
|
||||
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", 16, "192.169.0.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) {
|
||||
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);
|
||||
|
||||
@ -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) {
|
||||
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.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");
|
||||
@ -327,7 +323,7 @@ static void test_in_addr_prefix_range_one(
|
||||
|
||||
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_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) {
|
||||
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", 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[]) {
|
||||
test_setup_logging(LOG_DEBUG);
|
||||
|
||||
test_in_addr_prefix_from_string();
|
||||
test_in_addr_random_prefix();
|
||||
test_in_addr_prefix_to_string();
|
||||
|
||||
@ -148,7 +148,6 @@ RouteMetric=
|
||||
IAID=
|
||||
DUIDType=
|
||||
DUIDRawData=
|
||||
RouteTable=
|
||||
[DHCPv6PrefixDelegation]
|
||||
SubnetId=
|
||||
Announce=
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user