1
0
mirror of https://github.com/systemd/systemd synced 2026-03-15 09:34:47 +01:00

Compare commits

..

No commits in common. "c799d93cfa8d8202a05b28dc8836d5a29fa0487e" and "5c2e5957678462d871c5c2ea5261becec5f8f80f" have entirely different histories.

81 changed files with 1578 additions and 2593 deletions

View File

@ -13,7 +13,7 @@ account sufficient pam_unix.so
account required pam_permit.so account required pam_permit.so
-password sufficient pam_systemd_home.so -password sufficient pam_systemd_home.so
password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
password required pam_deny.so password required pam_deny.so
-session optional pam_keyinit.so revoke -session optional pam_keyinit.so revoke

View File

@ -318,8 +318,7 @@ account sufficient pam_unix.so
account required pam_permit.so account required pam_permit.so
-password sufficient pam_systemd_home.so -password sufficient pam_systemd_home.so
password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
password required pam_deny.so password required pam_deny.so
-session optional pam_keyinit.so revoke -session optional pam_keyinit.so revoke

View File

@ -139,7 +139,7 @@ account sufficient pam_unix.so
account required pam_permit.so account required pam_permit.so
<command>-password sufficient pam_systemd_home.so</command> <command>-password sufficient pam_systemd_home.so</command>
password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
password required pam_deny.so password required pam_deny.so
-session optional pam_keyinit.so revoke -session optional pam_keyinit.so revoke

View File

@ -775,7 +775,7 @@ BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook
<para><replaceable>bind-rule</replaceable> := [<replaceable>address-family</replaceable><constant>:</constant>]<replaceable>ip-ports</replaceable></para> <para><replaceable>bind-rule</replaceable> := [<replaceable>address-family</replaceable><constant>:</constant>]<replaceable>ip-ports</replaceable></para>
<para><replaceable>address-family</replaceable> := { <constant>ipv4</constant> | <constant>ipv6</constant> }</para> <para><replaceable>address-family</replaceable> := { <constant>IPv4</constant> | <constant>IPv6</constant> }</para>
<para><replaceable>ip-ports</replaceable> := { <replaceable>ip-port</replaceable> | <replaceable>ip-port-range</replaceable> | <para><replaceable>ip-ports</replaceable> := { <replaceable>ip-port</replaceable> | <replaceable>ip-port-range</replaceable> |
<constant>any</constant> }</para> <constant>any</constant> }</para>
@ -812,7 +812,7 @@ BPFProgram=bind6:/sys/fs/bpf/sock-addr-hook
<para>Examples:<programlisting> <para>Examples:<programlisting>
# Allow binding IPv6 socket addresses with a port greater than or equal to 10000. # Allow binding IPv6 socket addresses with a port greater than or equal to 10000.
[Service] [Service]
SocketBindAllow=ipv6:10000-65535 SocketBindAllow=IPv6:10000-65535
SocketBindDeny=any SocketBindDeny=any
# Allow binding IPv4 and IPv6 socket addresses with 1234 and 4321 ports. # Allow binding IPv4 and IPv6 socket addresses with 1234 and 4321 ports.
@ -823,7 +823,7 @@ SocketBindDeny=any
# Deny binding IPv6 socket addresses. # Deny binding IPv6 socket addresses.
[Service] [Service]
SocketBindDeny=ipv6:any SocketBindDeny=IPv6:any
# Deny binding IPv4 and IPv6 socket addresses. # Deny binding IPv4 and IPv6 socket addresses.
[Service] [Service]

View File

@ -38,15 +38,3 @@ int af_from_name(const char *name) {
int af_max(void) { int af_max(void) {
return ELEMENTSOF(af_names); return ELEMENTSOF(af_names);
} }
const char *af_to_ipv4_ipv6(int id) {
/* Pretty often we want to map the address family to the typically used protocol name for IPv4 +
* IPv6. Let's add special helpers for that. */
return id == AF_INET ? "ipv4" :
id == AF_INET6 ? "ipv6" : NULL;
}
int af_from_ipv4_ipv6(const char *af) {
return streq_ptr(af, "ipv4") ? AF_INET :
streq_ptr(af, "ipv6") ? AF_INET6 : AF_UNSPEC;
}

View File

@ -22,7 +22,4 @@ static inline const char* af_to_name_short(int id) {
return f + 3; return f + 3;
} }
const char* af_to_ipv4_ipv6(int id);
int af_from_ipv4_ipv6(const char *af);
int af_max(void); int af_max(void);

View File

@ -5,10 +5,6 @@
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h> #include <sys/types.h>
#include "fd-util.h"
#define CREDENTIAL_NAME_MAX FDNAME_MAX
bool credential_name_valid(const char *s); bool credential_name_valid(const char *s);
int get_credentials_dir(const char **ret); int get_credentials_dir(const char **ret);

View File

@ -454,7 +454,7 @@ bool fdname_is_valid(const char *s) {
return false; return false;
} }
return p - s <= FDNAME_MAX; return p - s < 256;
} }
int fd_get_path(int fd, char **ret) { int fd_get_path(int fd, char **ret) {

View File

@ -8,9 +8,6 @@
#include "macro.h" #include "macro.h"
/* maximum length of fdname */
#define FDNAME_MAX 255
/* Make sure we can distinguish fd 0 and NULL */ /* Make sure we can distinguish fd 0 and NULL */
#define FD_TO_PTR(fd) INT_TO_PTR((fd)+1) #define FD_TO_PTR(fd) INT_TO_PTR((fd)+1)
#define PTR_TO_FD(p) (PTR_TO_INT(p)-1) #define PTR_TO_FD(p) (PTR_TO_INT(p)-1)

View File

@ -371,26 +371,28 @@ static inline void *ordered_hashmap_first_key(OrderedHashmap *h) {
return _hashmap_first_key(HASHMAP_BASE(h), false); return _hashmap_first_key(HASHMAP_BASE(h), false);
} }
#define hashmap_clear_with_destructor(h, f) \ #define hashmap_clear_with_destructor(_s, _f) \
({ \ ({ \
Hashmap *_h = (h); \
void *_item; \ void *_item; \
while ((_item = hashmap_steal_first(_h))) \ while ((_item = hashmap_steal_first(_s))) \
f(_item); \ _f(_item); \
_h; \
}) })
#define hashmap_free_with_destructor(h, f) \ #define hashmap_free_with_destructor(_s, _f) \
hashmap_free(hashmap_clear_with_destructor(h, f)) ({ \
#define ordered_hashmap_clear_with_destructor(h, f) \ hashmap_clear_with_destructor(_s, _f); \
hashmap_free(_s); \
})
#define ordered_hashmap_clear_with_destructor(_s, _f) \
({ \ ({ \
OrderedHashmap *_h = (h); \
void *_item; \ void *_item; \
while ((_item = ordered_hashmap_steal_first(_h))) \ while ((_item = ordered_hashmap_steal_first(_s))) \
f(_item); \ _f(_item); \
_h; \ })
#define ordered_hashmap_free_with_destructor(_s, _f) \
({ \
ordered_hashmap_clear_with_destructor(_s, _f); \
ordered_hashmap_free(_s); \
}) })
#define ordered_hashmap_free_with_destructor(h, f) \
ordered_hashmap_free(ordered_hashmap_clear_with_destructor(h, f))
/* no hashmap_next */ /* no hashmap_next */
void* ordered_hashmap_next(OrderedHashmap *h, const void *key); void* ordered_hashmap_next(OrderedHashmap *h, const void *key);

View File

@ -73,13 +73,7 @@ int in_addr_prefix_range(
union in_addr_union *ret_start, union in_addr_union *ret_start,
union in_addr_union *ret_end); union in_addr_union *ret_end);
int in_addr_to_string(int family, const union in_addr_union *u, char **ret); int in_addr_to_string(int family, const union in_addr_union *u, char **ret);
static inline int in6_addr_to_string(const struct in6_addr *u, char **ret) {
return in_addr_to_string(AF_INET6, (const union in_addr_union*) u, ret);
}
int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret); int in_addr_prefix_to_string(int family, const union in_addr_union *u, unsigned prefixlen, char **ret);
static inline int in6_addr_prefix_to_string(const struct in6_addr *u, unsigned prefixlen, char **ret) {
return in_addr_prefix_to_string(AF_INET6, (const union in_addr_union*) u, prefixlen, ret);
}
int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret); int in_addr_port_ifindex_name_to_string(int family, const union in_addr_union *u, uint16_t port, int ifindex, const char *server_name, char **ret);
static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) { static inline int in_addr_ifindex_to_string(int family, const union in_addr_union *u, int ifindex, char **ret) {
return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret); return in_addr_port_ifindex_name_to_string(family, u, 0, ifindex, NULL, ret);
@ -126,10 +120,3 @@ 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;
extern const struct hash_ops in_addr_prefix_hash_ops_free; 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_VAL(address) \
be32toh((address).s_addr) >> 24, \
(be32toh((address).s_addr) >> 16) & 0xFFu, \
(be32toh((address).s_addr) >> 8) & 0xFFu, \
be32toh((address).s_addr) & 0xFFu

View File

@ -75,17 +75,6 @@ void ordered_set_print(FILE *f, const char *field, OrderedSet *s);
#define ORDERED_SET_FOREACH(e, s) \ #define ORDERED_SET_FOREACH(e, s) \
_ORDERED_SET_FOREACH(e, s, UNIQ_T(i, UNIQ)) _ORDERED_SET_FOREACH(e, s, UNIQ_T(i, UNIQ))
#define ordered_set_clear_with_destructor(s, f) \
({ \
OrderedSet *_s = (s); \
void *_item; \
while ((_item = ordered_set_steal_first(_s))) \
f(_item); \
_s; \
})
#define ordered_set_free_with_destructor(s, f) \
ordered_set_free(ordered_set_clear_with_destructor(s, f))
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free_free);

View File

@ -95,16 +95,17 @@ static inline void *set_steal_first(Set *s) {
return _hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL); return _hashmap_first_key_and_value(HASHMAP_BASE(s), true, NULL);
} }
#define set_clear_with_destructor(s, f) \ #define set_clear_with_destructor(_s, _f) \
({ \ ({ \
Set *_s = (s); \
void *_item; \ void *_item; \
while ((_item = set_steal_first(_s))) \ while ((_item = set_steal_first(_s))) \
f(_item); \ _f(_item); \
_s; \ })
#define set_free_with_destructor(_s, _f) \
({ \
set_clear_with_destructor(_s, _f); \
set_free(_s); \
}) })
#define set_free_with_destructor(s, f) \
set_free(set_clear_with_destructor(s, f))
/* no set_steal_first_key */ /* no set_steal_first_key */
/* no set_first_key */ /* no set_first_key */

View File

@ -224,7 +224,6 @@ if have_gnu_efi
'-Bsymbolic', '-Bsymbolic',
'-nostdlib', '-nostdlib',
'-znocombreloc', '-znocombreloc',
'--build-id=sha1',
'-L', efi_libdir, '-L', efi_libdir,
efi_crt0] efi_crt0]
if ['aarch64', 'arm', 'riscv64'].contains(efi_arch) if ['aarch64', 'arm', 'riscv64'].contains(efi_arch)
@ -255,22 +254,24 @@ if have_gnu_efi
libgcc_file_name = run_command(efi_cc + ['-print-libgcc-file-name']).stdout().strip() libgcc_file_name = run_command(efi_cc + ['-print-libgcc-file-name']).stdout().strip()
systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(EFI_MACHINE_TYPE_NAME) systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(EFI_MACHINE_TYPE_NAME)
stub_elf_name = 'linux@0@.elf.stub'.format(EFI_MACHINE_TYPE_NAME)
stub_efi_name = 'linux@0@.efi.stub'.format(EFI_MACHINE_TYPE_NAME) stub_efi_name = 'linux@0@.efi.stub'.format(EFI_MACHINE_TYPE_NAME)
no_undefined_symbols = find_program('no-undefined-symbols.sh') no_undefined_symbols = find_program('no-undefined-symbols.sh')
efi_stubs = [] foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects],
foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects, false], ['stub.so', stub_efi_name, stub_objects]]
[stub_elf_name, stub_efi_name, stub_objects, true]]
so = custom_target( so = custom_target(
tuple[0], tuple[0],
input : tuple[2], input : tuple[2],
output : tuple[0], output : tuple[0],
command : [efi_ld, '-o', '@OUTPUT@', command : [efi_ld, '-o', '@OUTPUT@'] +
efi_ldflags, tuple[2], efi_ldflags + tuple[2] +
'-lefi', '-lgnuefi', libgcc_file_name], ['-lefi', '-lgnuefi', libgcc_file_name])
install : tuple[3],
install_dir : bootlibdir) if want_tests != 'false'
test('no-undefined-symbols-' + tuple[0],
no_undefined_symbols,
args : [so])
endif
stub = custom_target( stub = custom_target(
tuple[1], tuple[1],
@ -283,26 +284,22 @@ if have_gnu_efi
'-j', '.data', '-j', '.data',
'-j', '.dynamic', '-j', '.dynamic',
'-j', '.dynsym', '-j', '.dynsym',
'-j', '.rel*', '-j', '.rel*']
efi_format, + efi_format +
'@INPUT@', '@OUTPUT@'], ['@INPUT@', '@OUTPUT@'],
install : true, install : true,
install_dir : bootlibdir) install_dir : bootlibdir)
efi_stubs += [[so, stub]] set_variable(tuple[0].underscorify(), so)
set_variable(tuple[0].underscorify() + '_stub', stub)
if want_tests != 'false'
test('no-undefined-symbols-' + tuple[0],
no_undefined_symbols,
args : so)
endif
endforeach endforeach
############################################################ ############################################################
test_efi_disk_img = custom_target( test_efi_disk_img = custom_target(
'test-efi-disk.img', 'test-efi-disk.img',
input : [efi_stubs[0][0], efi_stubs[1][1]], input : [systemd_boot_so, stub_so_stub],
output : 'test-efi-disk.img', output : 'test-efi-disk.img',
command : [test_efi_create_disk_sh, '@OUTPUT@','@INPUT@', splash_bmp]) command : [test_efi_create_disk_sh, '@OUTPUT@',
'@INPUT0@', '@INPUT1@', splash_bmp])
endif endif

View File

@ -4,7 +4,6 @@
#include "sd-messages.h" #include "sd-messages.h"
#include "af-list.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h" #include "blockdev-util.h"
#include "bpf-devices.h" #include "bpf-devices.h"
@ -203,10 +202,12 @@ void cgroup_context_remove_bpf_foreign_program(CGroupContext *c, CGroupBPFForeig
} }
void cgroup_context_remove_socket_bind(CGroupSocketBindItem **head) { void cgroup_context_remove_socket_bind(CGroupSocketBindItem **head) {
CGroupSocketBindItem *h;
assert(head); assert(head);
while (*head) { while (*head) {
CGroupSocketBindItem *h = *head; h = *head;
LIST_REMOVE(socket_bind_items, *head, h); LIST_REMOVE(socket_bind_items, *head, h);
free(h); free(h);
} }
@ -593,18 +594,16 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
} }
void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) { void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f) {
const char *family, *colon; const char *family = item->address_family == AF_INET ? "IPv4:" :
item->address_family == AF_INET6 ? "IPv6:" : "";
family = strempty(af_to_ipv4_ipv6(item->address_family));
colon = isempty(family) ? "" : ":";
if (item->nr_ports == 0) if (item->nr_ports == 0)
fprintf(f, " %s%sany", family, colon); fprintf(f, " %sany", family);
else if (item->nr_ports == 1) else if (item->nr_ports == 1)
fprintf(f, " %s%s%" PRIu16, family, colon, item->port_min); fprintf(f, " %s%" PRIu16, family, item->port_min);
else { else {
uint16_t port_max = item->port_min + item->nr_ports - 1; uint16_t port_max = item->port_min + item->nr_ports - 1;
fprintf(f, " %s%s%" PRIu16 "-%" PRIu16, family, colon, item->port_min, port_max); fprintf(f, " %s%" PRIu16 "-%" PRIu16, family, item->port_min, port_max);
} }
} }
@ -1581,7 +1580,7 @@ static bool unit_get_needs_socket_bind(Unit *u) {
if (!c) if (!c)
return false; return false;
return c->socket_bind_allow || c->socket_bind_deny; return c->socket_bind_allow != NULL || c->socket_bind_deny != NULL;
} }
static CGroupMask unit_get_cgroup_mask(Unit *u) { static CGroupMask unit_get_cgroup_mask(Unit *u) {

View File

@ -475,11 +475,8 @@ int manager_varlink_init(Manager *m) {
void manager_varlink_done(Manager *m) { void manager_varlink_done(Manager *m) {
assert(m); assert(m);
/* Explicitly close the varlink connection to oomd. Note we first take the varlink connection out of /* Send the final message if we still have a subscribe request open. */
* the manager, and only then disconnect it in two steps so that we don't end up accidentally m->managed_oom_varlink_request = varlink_close_unref(m->managed_oom_varlink_request);
* unreffing it twice. After all, closing the connection might cause the disconnect handler we
* installed (vl_disconnect() above) to be called, where we will unref it too. */
varlink_close_unref(TAKE_PTR(m->managed_oom_varlink_request));
m->varlink_server = varlink_server_unref(m->varlink_server); m->varlink_server = varlink_server_unref(m->varlink_server);
} }

View File

@ -293,7 +293,15 @@ int config_parse_unit_path_printf(
assert(rvalue); assert(rvalue);
assert(u); assert(u);
r = unit_path_printf(u, rvalue, &k); /* Let's not bother with anything that is too long */
if (strlen(rvalue) >= PATH_MAX) {
log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, 0,
"%s value too long%s.",
lvalue, fatal ? "" : ", ignoring");
return fatal ? -ENAMETOOLONG : 0;
}
r = unit_full_printf(u, rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, r, log_syntax(unit, fatal ? LOG_ERR : LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s'%s: %m", "Failed to resolve unit specifiers in '%s'%s: %m",
@ -344,7 +352,7 @@ int config_parse_unit_path_strv_printf(
return 0; return 0;
} }
r = unit_path_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", word); "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
@ -425,7 +433,7 @@ int config_parse_socket_listen(
if (ltype != SOCKET_SOCKET) { if (ltype != SOCKET_SOCKET) {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
r = unit_path_printf(UNIT(s), rvalue, &k); r = unit_full_printf(UNIT(s), rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -447,7 +455,7 @@ int config_parse_socket_listen(
} else if (streq(lvalue, "ListenNetlink")) { } else if (streq(lvalue, "ListenNetlink")) {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
r = unit_path_printf(UNIT(s), rvalue, &k); r = unit_full_printf(UNIT(s), rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -464,7 +472,7 @@ int config_parse_socket_listen(
} else { } else {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
r = unit_path_printf(UNIT(s), rvalue, &k); r = unit_full_printf(UNIT(s), rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -761,7 +769,7 @@ int config_parse_exec(
f++; f++;
} }
r = unit_path_printf(u, f, &path); r = unit_full_printf(u, f, &path);
if (r < 0) { if (r < 0) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
"Failed to resolve unit specifiers in '%s'%s: %m", "Failed to resolve unit specifiers in '%s'%s: %m",
@ -848,7 +856,7 @@ int config_parse_exec(
if (r < 0) if (r < 0)
return ignore ? 0 : -ENOEXEC; return ignore ? 0 : -ENOEXEC;
r = unit_path_printf(u, word, &resolved); r = unit_full_printf(u, word, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r, log_syntax(unit, ignore ? LOG_WARNING : LOG_ERR, filename, line, r,
"Failed to resolve unit specifiers in %s%s: %m", "Failed to resolve unit specifiers in %s%s: %m",
@ -948,7 +956,7 @@ int config_parse_exec_input(
if (n) { if (n) {
_cleanup_free_ char *resolved = NULL; _cleanup_free_ char *resolved = NULL;
r = unit_fd_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n);
return 0; return 0;
@ -968,7 +976,7 @@ int config_parse_exec_input(
} else if ((n = startswith(rvalue, "file:"))) { } else if ((n = startswith(rvalue, "file:"))) {
_cleanup_free_ char *resolved = NULL; _cleanup_free_ char *resolved = NULL;
r = unit_path_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", n);
return 0; return 0;
@ -1032,7 +1040,7 @@ int config_parse_exec_input_text(
return 0; return 0;
} }
r = unit_full_printf_full(u, unescaped, EXEC_STDIN_DATA_MAX, &resolved); r = unit_full_printf(u, unescaped, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", unescaped); "Failed to resolve unit specifiers in '%s', ignoring: %m", unescaped);
@ -1147,7 +1155,7 @@ int config_parse_exec_output(
n = startswith(rvalue, "fd:"); n = startswith(rvalue, "fd:");
if (n) { if (n) {
r = unit_fd_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", n);
return 0; return 0;
@ -1172,7 +1180,7 @@ int config_parse_exec_output(
} else if ((n = startswith(rvalue, "file:"))) { } else if ((n = startswith(rvalue, "file:"))) {
r = unit_path_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n);
return 0; return 0;
@ -1186,7 +1194,7 @@ int config_parse_exec_output(
} else if ((n = startswith(rvalue, "append:"))) { } else if ((n = startswith(rvalue, "append:"))) {
r = unit_path_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n);
return 0; return 0;
@ -1200,7 +1208,7 @@ int config_parse_exec_output(
} else if ((n = startswith(rvalue, "truncate:"))) { } else if ((n = startswith(rvalue, "truncate:"))) {
r = unit_path_printf(u, n, &resolved); r = unit_full_printf(u, n, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", n);
return 0; return 0;
@ -2072,7 +2080,7 @@ int config_parse_path_spec(const char *unit,
return 0; return 0;
} }
r = unit_path_printf(UNIT(p), rvalue, &k); r = unit_full_printf(UNIT(p), rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0; return 0;
@ -2167,7 +2175,7 @@ int config_parse_fdname(
return 0; return 0;
} }
r = unit_fd_printf(UNIT(s), rvalue, &p); r = unit_full_printf(UNIT(s), rvalue, &p);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -2256,7 +2264,7 @@ int config_parse_bus_name(
assert(rvalue); assert(rvalue);
assert(u); assert(u);
r = unit_full_printf_full(u, rvalue, SD_BUS_MAXIMUM_NAME_LENGTH, &k); r = unit_full_printf(u, rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0; return 0;
@ -2549,7 +2557,7 @@ int config_parse_working_directory(
} else { } else {
_cleanup_free_ char *k = NULL; _cleanup_free_ char *k = NULL;
r = unit_path_printf(u, rvalue, &k); r = unit_full_printf(u, rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, missing_ok ? LOG_WARNING : LOG_ERR, filename, line, r, log_syntax(unit, missing_ok ? LOG_WARNING : LOG_ERR, filename, line, r,
"Failed to resolve unit specifiers in working directory path '%s'%s: %m", "Failed to resolve unit specifiers in working directory path '%s'%s: %m",
@ -2596,7 +2604,7 @@ int config_parse_unit_env_file(const char *unit,
return 0; return 0;
} }
r = unit_full_printf_full(u, rvalue, PATH_MAX, &n); r = unit_full_printf(u, rvalue, &n);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -2657,7 +2665,7 @@ int config_parse_environ(
return 0; return 0;
if (u) { if (u) {
r = unit_env_printf(u, word, &resolved); r = unit_full_printf(u, word, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in %s, ignoring: %m", word); "Failed to resolve unit specifiers in %s, ignoring: %m", word);
@ -2722,7 +2730,7 @@ int config_parse_pass_environ(
break; break;
if (u) { if (u) {
r = unit_env_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve specifiers in %s, ignoring: %m", word); "Failed to resolve specifiers in %s, ignoring: %m", word);
@ -2797,7 +2805,7 @@ int config_parse_unset_environ(
break; break;
if (u) { if (u) {
r = unit_env_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in %s, ignoring: %m", word); "Failed to resolve unit specifiers in %s, ignoring: %m", word);
@ -2924,7 +2932,7 @@ int config_parse_log_namespace(
return 0; return 0;
} }
r = unit_full_printf_full(u, rvalue, NAME_MAX, &k); r = unit_full_printf(u, rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0; return 0;
@ -2977,7 +2985,7 @@ int config_parse_unit_condition_path(
if (negate) if (negate)
rvalue++; rvalue++;
r = unit_path_printf(u, rvalue, &p); r = unit_full_printf(u, rvalue, &p);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", rvalue);
return 0; return 0;
@ -3082,7 +3090,7 @@ int config_parse_unit_requires_mounts_for(
if (r == 0) if (r == 0)
return 0; return 0;
r = unit_path_printf(u, word, &resolved); r = unit_full_printf(u, word, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", word);
continue; continue;
@ -3952,7 +3960,7 @@ int config_parse_device_allow(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4018,7 +4026,7 @@ int config_parse_io_device_weight(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4087,7 +4095,7 @@ int config_parse_io_device_latency(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4157,7 +4165,7 @@ int config_parse_io_limit(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4243,7 +4251,7 @@ int config_parse_blockio_device_weight(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4316,7 +4324,7 @@ int config_parse_blockio_bandwidth(
return 0; return 0;
} }
r = unit_path_printf(userdata, path, &resolved); r = unit_full_printf(userdata, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in '%s', ignoring: %m", path); "Failed to resolve unit specifiers in '%s', ignoring: %m", path);
@ -4432,7 +4440,7 @@ int config_parse_exec_directories(
if (r == 0) if (r == 0)
return 0; return 0;
r = unit_path_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
@ -4495,7 +4503,7 @@ int config_parse_set_credential(
return 0; return 0;
} }
r = unit_cred_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
return 0; return 0;
@ -4580,7 +4588,7 @@ int config_parse_load_credential(
return 0; return 0;
} }
r = unit_cred_printf(u, word, &k); r = unit_full_printf(u, word, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", word);
return 0; return 0;
@ -4597,7 +4605,7 @@ int config_parse_load_credential(
if (!q) if (!q)
return log_oom(); return log_oom();
} else { } else {
r = unit_path_printf(u, p, &q); r = unit_full_printf(u, p, &q);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in \"%s\", ignoring: %m", p);
return 0; return 0;
@ -4732,7 +4740,7 @@ int config_parse_namespace_path_strv(
w++; w++;
} }
r = unit_path_printf(u, w, &resolved); r = unit_full_printf(u, w, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s: %m", w);
continue; continue;
@ -4812,7 +4820,7 @@ int config_parse_temporary_filesystems(
continue; continue;
} }
r = unit_path_printf(u, path, &resolved); r = unit_full_printf(u, path, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in %s, ignoring: %m", path);
continue; continue;
@ -4873,7 +4881,7 @@ int config_parse_bind_paths(
if (r == 0) if (r == 0)
break; break;
r = unit_full_printf_full(u, source, PATH_MAX, &sresolved); r = unit_full_printf(u, source, &sresolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", source); "Failed to resolve unit specifiers in \"%s\", ignoring: %m", source);
@ -4904,7 +4912,7 @@ int config_parse_bind_paths(
continue; continue;
} }
r = unit_path_printf(u, destination, &dresolved); r = unit_full_printf(u, destination, &dresolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve specifiers in \"%s\", ignoring: %m", destination); "Failed to resolve specifiers in \"%s\", ignoring: %m", destination);
@ -5020,7 +5028,7 @@ int config_parse_mount_images(
s++; s++;
} }
r = unit_path_printf(u, s, &sresolved); r = unit_full_printf(u, s, &sresolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", s); "Failed to resolve unit specifiers in \"%s\", ignoring: %m", s);
@ -5036,7 +5044,7 @@ int config_parse_mount_images(
continue; continue;
} }
r = unit_path_printf(u, second, &dresolved); r = unit_full_printf(u, second, &dresolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve specifiers in \"%s\", ignoring: %m", second); "Failed to resolve specifiers in \"%s\", ignoring: %m", second);
@ -5179,7 +5187,7 @@ int config_parse_extension_images(
s++; s++;
} }
r = unit_path_printf(u, s, &sresolved); r = unit_full_printf(u, s, &sresolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to resolve unit specifiers in \"%s\", ignoring: %m", s); "Failed to resolve unit specifiers in \"%s\", ignoring: %m", s);
@ -5408,7 +5416,7 @@ int config_parse_pid_file(
return 0; return 0;
} }
r = unit_path_printf(u, rvalue, &k); r = unit_full_printf(u, rvalue, &k);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -5529,7 +5537,7 @@ int config_parse_ip_filter_bpf_progs(
return 0; return 0;
} }
r = unit_path_printf(u, rvalue, &resolved); r = unit_full_printf(u, rvalue, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -5603,7 +5611,7 @@ int config_parse_bpf_foreign_program(
return 0; return 0;
} }
r = unit_path_printf(u, rvalue, &resolved); r = unit_full_printf(u, rvalue, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue); log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to resolve unit specifiers in '%s', ignoring: %m", rvalue);
return 0; return 0;
@ -5653,10 +5661,13 @@ int config_parse_cgroup_socket_bind(
} }
if (rvalue) { if (rvalue) {
af = af_from_ipv4_ipv6(word); if (streq(word, "IPv4"))
if (af == AF_UNSPEC) { af = AF_INET;
else if (streq(word, "IPv6"))
af = AF_INET6;
else {
log_syntax(unit, LOG_WARNING, filename, line, 0, log_syntax(unit, LOG_WARNING, filename, line, 0,
"Only \"ipv4\" and \"ipv6\" protocols are supported, ignoring."); "Only IPv4 and IPv6 protocols are supported, ignoring.");
return 0; return 0;
} }

View File

@ -201,10 +201,10 @@ int unit_name_printf(const Unit *u, const char* format, char **ret) {
assert(format); assert(format);
assert(ret); assert(ret);
return specifier_printf(format, UNIT_NAME_MAX, table, u, ret); return specifier_printf(format, table, u, ret);
} }
int unit_full_printf_full(const Unit *u, const char *format, size_t max_length, char **ret) { int unit_full_printf(const Unit *u, const char *format, char **ret) {
/* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes /* This is similar to unit_name_printf() but also supports unescaping. Also, adds a couple of additional codes
* (which are likely not suitable for unescaped inclusion in unit names): * (which are likely not suitable for unescaped inclusion in unit names):
* *
@ -265,5 +265,5 @@ int unit_full_printf_full(const Unit *u, const char *format, size_t max_length,
{} {}
}; };
return specifier_printf(format, max_length, table, u, ret); return specifier_printf(format, table, u, ret);
} }

View File

@ -1,26 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once #pragma once
#include "creds-util.h"
#include "env-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "unit.h" #include "unit.h"
int unit_name_printf(const Unit *u, const char* text, char **ret); int unit_name_printf(const Unit *u, const char* text, char **ret);
int unit_full_printf_full(const Unit *u, const char *text, size_t max_length, char **ret); int unit_full_printf(const Unit *u, const char *text, char **ret);
static inline int unit_full_printf(const Unit *u, const char *text, char **ret) {
return unit_full_printf_full(u, text, LONG_LINE_MAX, ret);
}
static inline int unit_path_printf(const Unit *u, const char *text, char **ret) {
return unit_full_printf_full(u, text, PATH_MAX-1, ret);
}
static inline int unit_fd_printf(const Unit *u, const char *text, char **ret) {
return unit_full_printf_full(u, text, FDNAME_MAX, ret);
}
static inline int unit_cred_printf(const Unit *u, const char *text, char **ret) {
return unit_full_printf_full(u, text, CREDENTIAL_NAME_MAX, ret);
}
static inline int unit_env_printf(const Unit *u, const char *text, char **ret) {
return unit_full_printf_full(u, text, sc_arg_max(), ret);
}

View File

@ -8,7 +8,6 @@
#include "sd-daemon.h" #include "sd-daemon.h"
#include "af-list.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "def.h" #include "def.h"
#include "errno-util.h" #include "errno-util.h"
@ -499,7 +498,7 @@ static int accept_connection(
log_debug("Accepted %s %s connection from %s", log_debug("Accepted %s %s connection from %s",
type, type,
af_to_ipv4_ipv6(socket_address_family(addr)), socket_address_family(addr) == AF_INET ? "IP" : "IPv6",
a); a);
*hostname = b; *hostname = b;

View File

@ -27,5 +27,5 @@ int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t
/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ /* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */
int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size);
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file); int dhcp_lease_save(const sd_dhcp_lease *lease, const char *lease_file);
int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file); int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file);

View File

@ -2052,7 +2052,7 @@ int sd_dhcp_client_send_renew(sd_dhcp_client *client) {
return client_initialize_time_events(client); return client_initialize_time_events(client);
} }
int sd_dhcp_client_is_running(sd_dhcp_client *client) { int sd_dhcp_client_is_running(const sd_dhcp_client *client) {
if (!client) if (!client)
return 0; return 0;

View File

@ -31,7 +31,7 @@
#include "tmpfile-util.h" #include "tmpfile-util.h"
#include "unaligned.h" #include "unaligned.h"
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_address(const sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -42,7 +42,7 @@ int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr) {
return 0; return 0;
} }
int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_broadcast(const sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -53,7 +53,7 @@ int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr) {
return 0; return 0;
} }
int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) { int sd_dhcp_lease_get_lifetime(const sd_dhcp_lease *lease, uint32_t *lifetime) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(lifetime, -EINVAL); assert_return(lifetime, -EINVAL);
@ -64,7 +64,7 @@ int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime) {
return 0; return 0;
} }
int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) { int sd_dhcp_lease_get_t1(const sd_dhcp_lease *lease, uint32_t *t1) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(t1, -EINVAL); assert_return(t1, -EINVAL);
@ -75,7 +75,7 @@ int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1) {
return 0; return 0;
} }
int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) { int sd_dhcp_lease_get_t2(const sd_dhcp_lease *lease, uint32_t *t2) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(t2, -EINVAL); assert_return(t2, -EINVAL);
@ -86,7 +86,7 @@ int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2) {
return 0; return 0;
} }
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) { int sd_dhcp_lease_get_mtu(const sd_dhcp_lease *lease, uint16_t *mtu) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(mtu, -EINVAL); assert_return(mtu, -EINVAL);
@ -98,7 +98,7 @@ int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu) {
} }
int sd_dhcp_lease_get_servers( int sd_dhcp_lease_get_servers(
sd_dhcp_lease *lease, const sd_dhcp_lease *lease,
sd_dhcp_lease_server_type_t what, sd_dhcp_lease_server_type_t what,
const struct in_addr **addr) { const struct in_addr **addr) {
@ -114,26 +114,26 @@ int sd_dhcp_lease_get_servers(
return (int) lease->servers[what].size; return (int) lease->servers[what].size;
} }
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_dns(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_DNS, addr);
} }
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_ntp(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_NTP, addr);
} }
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_sip(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SIP, addr);
} }
int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_pop3(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_POP3, addr);
} }
int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_smtp(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_SMTP, addr);
} }
int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_lpr(const sd_dhcp_lease *lease, const struct in_addr **addr) {
return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr); return sd_dhcp_lease_get_servers(lease, SD_DHCP_LEASE_LPR, addr);
} }
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname) { int sd_dhcp_lease_get_domainname(const sd_dhcp_lease *lease, const char **domainname) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(domainname, -EINVAL); assert_return(domainname, -EINVAL);
@ -144,7 +144,7 @@ int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname)
return 0; return 0;
} }
int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) { int sd_dhcp_lease_get_hostname(const sd_dhcp_lease *lease, const char **hostname) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(hostname, -EINVAL); assert_return(hostname, -EINVAL);
@ -155,7 +155,7 @@ int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname) {
return 0; return 0;
} }
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) { int sd_dhcp_lease_get_root_path(const sd_dhcp_lease *lease, const char **root_path) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(root_path, -EINVAL); assert_return(root_path, -EINVAL);
@ -166,7 +166,7 @@ int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path) {
return 0; return 0;
} }
int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr) { int sd_dhcp_lease_get_router(const sd_dhcp_lease *lease, const struct in_addr **addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -177,7 +177,7 @@ int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr)
return (int) lease->router_size; return (int) lease->router_size;
} }
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_netmask(const sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -188,7 +188,7 @@ int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr) {
return 0; return 0;
} }
int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_server_identifier(const sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -199,7 +199,7 @@ int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *ad
return 0; return 0;
} }
int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) { int sd_dhcp_lease_get_next_server(const sd_dhcp_lease *lease, struct in_addr *addr) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(addr, -EINVAL); assert_return(addr, -EINVAL);
@ -214,7 +214,7 @@ int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr) {
* The returned routes array must be freed by the caller. * The returned routes array must be freed by the caller.
* Route objects have the same lifetime of the lease and must not be freed. * Route objects have the same lifetime of the lease and must not be freed.
*/ */
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) { int sd_dhcp_lease_get_routes(const sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
sd_dhcp_route **ret; sd_dhcp_route **ret;
unsigned i; unsigned i;
@ -235,7 +235,7 @@ int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes) {
return (int) lease->static_route_size; return (int) lease->static_route_size;
} }
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) { int sd_dhcp_lease_get_search_domains(const sd_dhcp_lease *lease, char ***domains) {
size_t r; size_t r;
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
@ -250,7 +250,7 @@ int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains) {
return -ENODATA; return -ENODATA;
} }
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len) { int sd_dhcp_lease_get_vendor_specific(const sd_dhcp_lease *lease, const void **data, size_t *data_len) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(data, -EINVAL); assert_return(data, -EINVAL);
assert_return(data_len, -EINVAL); assert_return(data_len, -EINVAL);
@ -868,7 +868,7 @@ int dhcp_lease_new(sd_dhcp_lease **ret) {
return 0; return 0;
} }
int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) { int dhcp_lease_save(const sd_dhcp_lease *lease, const char *lease_file) {
_cleanup_(unlink_and_freep) char *temp_path = NULL; _cleanup_(unlink_and_freep) char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
struct sd_dhcp_raw_option *option; struct sd_dhcp_raw_option *option;
@ -1313,7 +1313,7 @@ int dhcp_lease_set_default_subnet_mask(sd_dhcp_lease *lease) {
return 0; return 0;
} }
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) { int sd_dhcp_lease_get_client_id(const sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(client_id, -EINVAL); assert_return(client_id, -EINVAL);
assert_return(client_id_len, -EINVAL); assert_return(client_id_len, -EINVAL);
@ -1348,7 +1348,7 @@ int dhcp_lease_set_client_id(sd_dhcp_lease *lease, const void *client_id, size_t
return 0; return 0;
} }
int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) { int sd_dhcp_lease_get_timezone(const sd_dhcp_lease *lease, const char **tz) {
assert_return(lease, -EINVAL); assert_return(lease, -EINVAL);
assert_return(tz, -EINVAL); assert_return(tz, -EINVAL);
@ -1359,7 +1359,7 @@ int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **tz) {
return 0; return 0;
} }
int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination) { int sd_dhcp_route_get_destination(const sd_dhcp_route *route, struct in_addr *destination) {
assert_return(route, -EINVAL); assert_return(route, -EINVAL);
assert_return(destination, -EINVAL); assert_return(destination, -EINVAL);
@ -1367,7 +1367,7 @@ int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destinat
return 0; return 0;
} }
int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length) { int sd_dhcp_route_get_destination_prefix_length(const sd_dhcp_route *route, uint8_t *length) {
assert_return(route, -EINVAL); assert_return(route, -EINVAL);
assert_return(length, -EINVAL); assert_return(length, -EINVAL);
@ -1375,7 +1375,7 @@ int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *l
return 0; return 0;
} }
int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) { int sd_dhcp_route_get_gateway(const sd_dhcp_route *route, struct in_addr *gateway) {
assert_return(route, -EINVAL); assert_return(route, -EINVAL);
assert_return(gateway, -EINVAL); assert_return(gateway, -EINVAL);
@ -1383,7 +1383,7 @@ int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway) {
return 0; return 0;
} }
int sd_dhcp_route_get_option(sd_dhcp_route *route) { int sd_dhcp_route_get_option(const sd_dhcp_route *route) {
assert_return(route, -EINVAL); assert_return(route, -EINVAL);
return route->option; return route->option;

View File

@ -12,7 +12,6 @@
#include "sd-bus.h" #include "sd-bus.h"
#include "af-list.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "bus-container.h" #include "bus-container.h"
#include "bus-control.h" #include "bus-control.h"
@ -822,8 +821,11 @@ static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
return -EINVAL; return -EINVAL;
if (family) { if (family) {
hints.ai_family = af_from_ipv4_ipv6(family); if (streq(family, "ipv4"))
if (hints.ai_family == AF_UNSPEC) hints.ai_family = AF_INET;
else if (streq(family, "ipv6"))
hints.ai_family = AF_INET6;
else
return -EINVAL; return -EINVAL;
} }

View File

@ -152,7 +152,7 @@ int nlmsg_type_to_genl_family(const sd_netlink *nl, uint16_t type, sd_genl_famil
return 0; return 0;
} }
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *family) { int sd_genl_message_get_family(const sd_netlink *nl, const sd_netlink_message *m, sd_genl_family_t *family) {
uint16_t type; uint16_t type;
int r; int r;

View File

@ -114,7 +114,7 @@ sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
return NULL; return NULL;
} }
int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) { int sd_netlink_message_get_type(const sd_netlink_message *m, uint16_t *type) {
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
assert_return(type, -EINVAL); assert_return(type, -EINVAL);
@ -132,7 +132,7 @@ int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) {
return 0; return 0;
} }
int sd_netlink_message_is_broadcast(sd_netlink_message *m) { int sd_netlink_message_is_broadcast(const sd_netlink_message *m) {
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
return m->broadcast; return m->broadcast;
@ -1235,14 +1235,14 @@ uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
return m->hdr->nlmsg_seq; return m->hdr->nlmsg_seq;
} }
int sd_netlink_message_is_error(sd_netlink_message *m) { int sd_netlink_message_is_error(const sd_netlink_message *m) {
assert_return(m, 0); assert_return(m, 0);
assert_return(m->hdr, 0); assert_return(m->hdr, 0);
return m->hdr->nlmsg_type == NLMSG_ERROR; return m->hdr->nlmsg_type == NLMSG_ERROR;
} }
int sd_netlink_message_get_errno(sd_netlink_message *m) { int sd_netlink_message_get_errno(const sd_netlink_message *m) {
struct nlmsgerr *err; struct nlmsgerr *err;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);

View File

@ -142,7 +142,7 @@ void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata) {
return ret; return ret;
} }
int sd_netlink_slot_get_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t *callback) { int sd_netlink_slot_get_destroy_callback(const sd_netlink_slot *slot, sd_netlink_destroy_t *callback) {
assert_return(slot, -EINVAL); assert_return(slot, -EINVAL);
if (callback) if (callback)
@ -158,7 +158,7 @@ int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destr
return 0; return 0;
} }
int sd_netlink_slot_get_floating(sd_netlink_slot *slot) { int sd_netlink_slot_get_floating(const sd_netlink_slot *slot) {
assert_return(slot, -EINVAL); assert_return(slot, -EINVAL);
return slot->floating; return slot->floating;
@ -186,7 +186,7 @@ int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b) {
return 1; return 1;
} }
int sd_netlink_slot_get_description(sd_netlink_slot *slot, const char **description) { int sd_netlink_slot_get_description(const sd_netlink_slot *slot, const char **description) {
assert_return(slot, -EINVAL); assert_return(slot, -EINVAL);
if (description) if (description)

View File

@ -409,44 +409,6 @@ int rtattr_append_attribute(struct rtattr **rta, unsigned short type, const void
return 0; return 0;
} }
MultipathRoute *multipath_route_free(MultipathRoute *m) {
if (!m)
return NULL;
free(m->ifname);
return mfree(m);
}
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret) {
_cleanup_(multipath_route_freep) MultipathRoute *n = NULL;
_cleanup_free_ char *ifname = NULL;
assert(m);
assert(ret);
if (m->ifname) {
ifname = strdup(m->ifname);
if (!ifname)
return -ENOMEM;
}
n = new(MultipathRoute, 1);
if (!n)
return -ENOMEM;
*n = (MultipathRoute) {
.gateway = m->gateway,
.weight = m->weight,
.ifindex = m->ifindex,
.ifname = TAKE_PTR(ifname),
};
*ret = TAKE_PTR(n);
return 0;
}
int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) { int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, OrderedSet **ret) {
_cleanup_ordered_set_free_free_ OrderedSet *set = NULL; _cleanup_ordered_set_free_free_ OrderedSet *set = NULL;
int r; int r;
@ -458,7 +420,7 @@ int rtattr_read_nexthop(const struct rtnexthop *rtnh, size_t size, int family, O
return -EBADMSG; return -EBADMSG;
for (; size >= sizeof(struct rtnexthop); ) { for (; size >= sizeof(struct rtnexthop); ) {
_cleanup_(multipath_route_freep) MultipathRoute *m = NULL; _cleanup_free_ MultipathRoute *m = NULL;
if (NLMSG_ALIGN(rtnh->rtnh_len) > size) if (NLMSG_ALIGN(rtnh->rtnh_len) > size)
return -EBADMSG; return -EBADMSG;

View File

@ -19,16 +19,10 @@ typedef struct RouteVia {
typedef struct MultipathRoute { typedef struct MultipathRoute {
RouteVia gateway; RouteVia gateway;
uint32_t weight;
int ifindex; int ifindex;
char *ifname; uint32_t weight;
} MultipathRoute; } MultipathRoute;
MultipathRoute *multipath_route_free(MultipathRoute *m);
DEFINE_TRIVIAL_CLEANUP_FUNC(MultipathRoute*, multipath_route_free);
int multipath_route_dup(const MultipathRoute *m, MultipathRoute **ret);
int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret); int rtnl_message_new_synthetic_error(sd_netlink *rtnl, int error, uint32_t serial, sd_netlink_message **ret);
uint32_t rtnl_message_get_serial(sd_netlink_message *m); uint32_t rtnl_message_get_serial(sd_netlink_message *m);
void rtnl_message_seal(sd_netlink_message *m); void rtnl_message_seal(sd_netlink_message *m);

View File

@ -81,7 +81,7 @@ int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) {
return 0; return 0;
} }
int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) { int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -110,7 +110,7 @@ int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table)
return 0; return 0;
} }
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) { int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -125,7 +125,7 @@ int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
return 0; return 0;
} }
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type) { int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -154,7 +154,7 @@ int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) {
return 0; return 0;
} }
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) { int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -169,7 +169,7 @@ int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *pro
return 0; return 0;
} }
int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) { int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -184,7 +184,7 @@ int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope)
return 0; return 0;
} }
int sd_rtnl_message_route_get_tos(sd_netlink_message *m, uint8_t *tos) { int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, uint8_t *tos) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -199,7 +199,7 @@ int sd_rtnl_message_route_get_tos(sd_netlink_message *m, uint8_t *tos) {
return 0; return 0;
} }
int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) { int sd_rtnl_message_route_get_table(const sd_netlink_message *m, unsigned char *table) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -214,7 +214,7 @@ int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table)
return 0; return 0;
} }
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) { int sd_rtnl_message_route_get_dst_prefixlen(const sd_netlink_message *m, unsigned char *dst_len) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -229,7 +229,7 @@ int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char
return 0; return 0;
} }
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len) { int sd_rtnl_message_route_get_src_prefixlen(const sd_netlink_message *m, unsigned char *src_len) {
struct rtmsg *rtm; struct rtmsg *rtm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -324,7 +324,7 @@ int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
return 0; return 0;
} }
int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family) { int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) {
struct nhmsg *nhm; struct nhmsg *nhm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -338,7 +338,7 @@ int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family) {
return 0; return 0;
} }
int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol) { int sd_rtnl_message_nexthop_get_protocol(const sd_netlink_message *m, uint8_t *protocol) {
struct nhmsg *nhm; struct nhmsg *nhm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -378,7 +378,7 @@ int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) {
return 0; return 0;
} }
int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) { int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags) {
struct ndmsg *ndm; struct ndmsg *ndm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -391,7 +391,7 @@ int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) {
return 0; return 0;
} }
int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) { int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state) {
struct ndmsg *ndm; struct ndmsg *ndm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -404,7 +404,7 @@ int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) {
return 0; return 0;
} }
int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) { int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family) {
struct ndmsg *ndm; struct ndmsg *ndm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -419,7 +419,7 @@ int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) {
return 0; return 0;
} }
int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index) { int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *index) {
struct ndmsg *ndm; struct ndmsg *ndm;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -572,7 +572,7 @@ int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) {
return 0; return 0;
} }
int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family) { int sd_rtnl_message_addr_get_family(const sd_netlink_message *m, int *family) {
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -587,7 +587,7 @@ int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family) {
return 0; return 0;
} }
int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) { int sd_rtnl_message_addr_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) {
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -602,7 +602,7 @@ int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *pre
return 0; return 0;
} }
int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope) { int sd_rtnl_message_addr_get_scope(const sd_netlink_message *m, unsigned char *scope) {
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -617,7 +617,7 @@ int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope)
return 0; return 0;
} }
int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags) { int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags) {
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -632,7 +632,7 @@ int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags)
return 0; return 0;
} }
int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex) { int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex) {
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -692,7 +692,7 @@ int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret,
return 0; return 0;
} }
int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) { int sd_rtnl_message_link_get_ifindex(const sd_netlink_message *m, int *ifindex) {
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -707,7 +707,7 @@ int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) {
return 0; return 0;
} }
int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) { int sd_rtnl_message_link_get_flags(const sd_netlink_message *m, unsigned *flags) {
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -722,7 +722,7 @@ int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) {
return 0; return 0;
} }
int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type) { int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type) {
struct ifinfomsg *ifi; struct ifinfomsg *ifi;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -737,7 +737,7 @@ int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type) {
return 0; return 0;
} }
int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) { int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family) {
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
assert_return(family, -EINVAL); assert_return(family, -EINVAL);
@ -835,7 +835,7 @@ int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char
return 0; return 0;
} }
int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) { int sd_rtnl_message_addrlabel_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) {
struct ifaddrlblmsg *addrlabel; struct ifaddrlblmsg *addrlabel;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -884,7 +884,7 @@ int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, uint8_t t
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_tos(sd_netlink_message *m, uint8_t *tos) { int sd_rtnl_message_routing_policy_rule_get_tos(const sd_netlink_message *m, uint8_t *tos) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -912,7 +912,7 @@ int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, uint8_t
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, uint8_t *table) { int sd_rtnl_message_routing_policy_rule_get_table(const sd_netlink_message *m, uint8_t *table) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -939,7 +939,7 @@ int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, uint32_
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, uint32_t *flags) { int sd_rtnl_message_routing_policy_rule_get_flags(const sd_netlink_message *m, uint32_t *flags) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -966,7 +966,7 @@ int sd_rtnl_message_routing_policy_rule_set_fib_type(sd_netlink_message *m, uint
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_fib_type(sd_netlink_message *m, uint8_t *type) { int sd_rtnl_message_routing_policy_rule_get_fib_type(const sd_netlink_message *m, uint8_t *type) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -994,7 +994,7 @@ int sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(sd_netlink_message
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(sd_netlink_message *m, uint8_t *len) { int sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(const sd_netlink_message *m, uint8_t *len) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);
@ -1022,7 +1022,7 @@ int sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(sd_netlink_message
return 0; return 0;
} }
int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(sd_netlink_message *m, uint8_t *len) { int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(const sd_netlink_message *m, uint8_t *len) {
struct fib_rule_hdr *frh; struct fib_rule_hdr *frh;
assert_return(m, -EINVAL); assert_return(m, -EINVAL);

View File

@ -742,7 +742,7 @@ int sd_netlink_call(sd_netlink *rtnl,
return sd_netlink_read(rtnl, serial, usec, ret); return sd_netlink_read(rtnl, serial, usec, ret);
} }
int sd_netlink_get_events(sd_netlink *rtnl) { int sd_netlink_get_events(const sd_netlink *rtnl) {
assert_return(rtnl, -EINVAL); assert_return(rtnl, -EINVAL);
assert_return(!rtnl_pid_changed(rtnl), -ECHILD); assert_return(!rtnl_pid_changed(rtnl), -ECHILD);
@ -752,7 +752,7 @@ int sd_netlink_get_events(sd_netlink *rtnl) {
return 0; return 0;
} }
int sd_netlink_get_timeout(sd_netlink *rtnl, uint64_t *timeout_usec) { int sd_netlink_get_timeout(const sd_netlink *rtnl, uint64_t *timeout_usec) {
struct reply_callback *c; struct reply_callback *c;
assert_return(rtnl, -EINVAL); assert_return(rtnl, -EINVAL);

View File

@ -105,8 +105,6 @@ sources = files('''
networkd-network.h networkd-network.h
networkd-nexthop.c networkd-nexthop.c
networkd-nexthop.h networkd-nexthop.h
networkd-queue.c
networkd-queue.h
networkd-route.c networkd-route.c
networkd-route.h networkd-route.h
networkd-routing-policy-rule.c networkd-routing-policy-rule.c

View File

@ -9,9 +9,9 @@
#include "netlink-util.h" #include "netlink-util.h"
#include "networkd-address-pool.h" #include "networkd-address-pool.h"
#include "networkd-address.h" #include "networkd-address.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-queue.h"
#include "parse-util.h" #include "parse-util.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
@ -150,7 +150,7 @@ static bool address_may_have_broadcast(const Address *a) {
* See https://tools.ietf.org/html/rfc3021 */ * See https://tools.ietf.org/html/rfc3021 */
return a->family == AF_INET && return a->family == AF_INET &&
in4_addr_is_null(&a->in_addr_peer.in) && in_addr_is_null(AF_INET, &a->in_addr_peer) &&
a->prefixlen <= 30; a->prefixlen <= 30;
} }
@ -406,7 +406,7 @@ static int address_update(Address *address, const Address *src) {
} }
if (address->family == AF_INET6 && if (address->family == AF_INET6 &&
in6_addr_is_link_local(&address->in_addr.in6) > 0 && in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
in6_addr_is_null(&address->link->ipv6ll_address)) { in6_addr_is_null(&address->link->ipv6ll_address)) {
r = link_ipv6ll_gained(address->link, &address->in_addr.in6); r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
@ -485,63 +485,6 @@ int link_has_ipv6_address(Link *link, const struct in6_addr *address) {
return address_get(link, a, NULL) >= 0; return address_get(link, a, NULL) >= 0;
} }
static int link_get_ipv4_address(Set *addresses, const struct in_addr *address, Address **ret) {
Address *a;
assert(address);
SET_FOREACH(a, addresses) {
if (a->family != AF_INET)
continue;
if (!in4_addr_equal(&a->in_addr.in, address))
continue;
if (ret)
*ret = a;
return 0;
}
return -ENOENT;
}
int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready) {
Link *link;
int r;
assert(manager);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(address);
if (family == AF_INET)
HASHMAP_FOREACH(link, manager->links) {
Address *a;
if (link_get_ipv4_address(link->addresses, &address->in, &a) >= 0)
return !check_ready || address_is_ready(a);
if (link_get_ipv4_address(link->addresses_foreign, &address->in, &a) >= 0)
return !check_ready || address_is_ready(a);
}
else {
_cleanup_(address_freep) Address *tmp = NULL;
Address *a;
r = address_new(&tmp);
if (r < 0)
return r;
tmp->family = family;
tmp->in_addr = *address;
HASHMAP_FOREACH(link, manager->links)
if (address_get(link, tmp, &a) >= 0)
return !check_ready || address_is_ready(a);
}
return false;
}
static void log_address_debug(const Address *address, const char *str, const Link *link) { static void log_address_debug(const Address *address, const char *str, const Link *link) {
_cleanup_free_ char *addr = NULL, *peer = NULL; _cleanup_free_ char *addr = NULL, *peer = NULL;
char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX]; char valid_buf[FORMAT_TIMESPAN_MAX], preferred_buf[FORMAT_TIMESPAN_MAX];
@ -577,6 +520,25 @@ static void log_address_debug(const Address *address, const char *str, const Lin
preferred_str ? "for " : "forever", strempty(preferred_str)); preferred_str ? "for " : "forever", strempty(preferred_str));
} }
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->ifname);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, "Could not drop address");
else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
return 1;
}
static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) { static int address_set_netlink_message(const Address *address, sd_netlink_message *req, Link *link) {
int r; int r;
@ -608,33 +570,6 @@ static int address_set_netlink_message(const Address *address, sd_netlink_messag
return 0; return 0;
} }
int address_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->address_remove_messages > 0);
assert(error_msg);
link->address_remove_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, error_msg);
else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
return 1;
}
static int address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return address_remove_handler_internal(rtnl, m, link, "Could not drop address");
}
int address_remove( int address_remove(
const Address *address, const Address *address,
Link *link, Link *link,
@ -668,7 +603,6 @@ int address_remove(
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);
link->address_remove_messages++;
return 0; return 0;
} }
@ -772,7 +706,7 @@ int link_drop_foreign_addresses(Link *link) {
SET_FOREACH(address, link->addresses_foreign) { SET_FOREACH(address, link->addresses_foreign) {
/* we consider IPv6LL addresses to be managed by the kernel */ /* we consider IPv6LL addresses to be managed by the kernel */
if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6) == 1 && link_ipv6ll_enabled(link)) if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
continue; continue;
if (link_address_is_dynamic(link, address)) { if (link_address_is_dynamic(link, address)) {
@ -798,6 +732,35 @@ int link_drop_foreign_addresses(Link *link) {
return r; return r;
} }
static int remove_static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->ifname);
assert(link->address_remove_messages > 0);
link->address_remove_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, "Could not drop address");
else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->address_remove_messages == 0 && link->request_static_addresses) {
link_set_state(link, LINK_STATE_CONFIGURING);
r = link_set_addresses(link);
if (r < 0)
link_enter_failed(link);
}
return 1;
}
int link_drop_addresses(Link *link) { int link_drop_addresses(Link *link) {
Address *address, *pool_address; Address *address, *pool_address;
int k, r = 0; int k, r = 0;
@ -806,15 +769,17 @@ int link_drop_addresses(Link *link) {
SET_FOREACH(address, link->addresses) { SET_FOREACH(address, link->addresses) {
/* we consider IPv6LL addresses to be managed by the kernel */ /* we consider IPv6LL addresses to be managed by the kernel */
if (address->family == AF_INET6 && in6_addr_is_link_local(&address->in_addr.in6) == 1 && link_ipv6ll_enabled(link)) if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1 && link_ipv6ll_enabled(link))
continue; continue;
k = address_remove(address, link, NULL); k = address_remove(address, link, remove_static_address_handler);
if (k < 0 && r >= 0) { if (k < 0 && r >= 0) {
r = k; r = k;
continue; continue;
} }
link->address_remove_messages++;
SET_FOREACH(pool_address, link->pool_addresses) SET_FOREACH(pool_address, link->pool_addresses)
if (address_equal(address, pool_address)) if (address_equal(address, pool_address))
address_free(set_remove(link->pool_addresses, pool_address)); address_free(set_remove(link->pool_addresses, pool_address));
@ -880,31 +845,9 @@ static int address_acquire(Link *link, const Address *original, Address **ret) {
return 1; return 1;
} }
int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(error_msg);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, error_msg);
link_enter_failed(link);
return 0;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
return 1;
}
static int ipv4_dad_configure(Address *address); static int ipv4_dad_configure(Address *address);
static int address_configure( int address_configure(
const Address *address, const Address *address,
Link *link, Link *link,
link_netlink_message_handler_t callback, link_netlink_message_handler_t callback,
@ -1008,24 +951,78 @@ static int address_configure(
return k; return k;
} }
static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int static_address_ready_callback(Address *address) {
Address *a;
Link *link;
int r; int r;
assert(link); assert(address);
assert(link->static_address_messages > 0); assert(address->link);
link->static_address_messages--; link = address->link;
r = address_configure_handler_internal(rtnl, m, link, "Failed to set static address"); if (!link->addresses_configured)
if (r <= 0) return 0;
SET_FOREACH(a, link->static_addresses)
if (!address_is_ready(a)) {
_cleanup_free_ char *str = NULL;
(void) in_addr_prefix_to_string(a->family, &a->in_addr, a->prefixlen, &str);
log_link_debug(link, "an address %s is not ready", strnull(str));
return 0;
}
/* This should not be called again */
SET_FOREACH(a, link->static_addresses)
a->callback = NULL;
link->addresses_ready = true;
r = link_set_ipv6_proxy_ndp_addresses(link);
if (r < 0)
return r; return r;
if (link->static_address_messages == 0) { return link_set_routes(link);
log_link_debug(link, "Addresses set"); }
link->static_addresses_configured = true;
link_check_ready(link);
r = dhcp4_server_configure(link); static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
assert(link->address_messages > 0);
link->address_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->address_messages == 0) {
Address *a;
log_link_debug(link, "Addresses set");
link->addresses_configured = true;
/* When all static addresses are already ready, then static_address_ready_callback()
* will not be called automatically. So, call it here. */
a = set_first(link->static_addresses);
if (!a) {
log_link_debug(link, "No static address is stored. Already removed?");
return 1;
}
r = static_address_ready_callback(a);
if (r < 0) if (r < 0)
link_enter_failed(link); link_enter_failed(link);
} }
@ -1033,65 +1030,55 @@ static int static_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return 1; return 1;
} }
static int static_address_after_configure(Request *req, void *object) { static int static_address_configure(const Address *address, Link *link) {
Address *address = object; Address *ret;
Link *link;
int r; int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ADDRESS);
assert(address); assert(address);
assert(link);
link = req->link; r = address_configure(address, link, address_handler, &ret);
if (r < 0)
return log_link_warning_errno(link, r, "Could not configure static address: %m");
r = set_ensure_put(&link->static_addresses, &address_hash_ops, address); link->address_messages++;
r = set_ensure_put(&link->static_addresses, &address_hash_ops, ret);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "Failed to store static address: %m"); return log_link_warning_errno(link, r, "Failed to store static address: %m");
ret->callback = static_address_ready_callback;
return 0; return 0;
} }
int link_request_address( int link_set_addresses(Link *link) {
Link *link, Address *ad;
Address *address,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
assert(link);
assert(address);
log_address_debug(address, "Requesting", link);
return link_queue_request(link, REQUEST_TYPE_ADDRESS, address, consume_object,
message_counter, netlink_handler, ret);
}
int link_request_static_addresses(Link *link) {
Address *a;
Prefix *p; Prefix *p;
int r; int r;
assert(link); assert(link);
assert(link->network); assert(link->network);
link->static_addresses_configured = false; if (link->address_remove_messages != 0) {
log_link_debug(link, "Removing old addresses, new addresses will be configured later.");
link->request_static_addresses = true;
return 0;
}
ORDERED_HASHMAP_FOREACH(a, link->network->addresses_by_section) { if (link->address_messages != 0) {
Request *req; log_link_debug(link, "Static addresses are configuring.");
return 0;
}
r = link_request_address(link, a, false, &link->static_address_messages, ORDERED_HASHMAP_FOREACH(ad, link->network->addresses_by_section) {
static_address_handler, &req); r = static_address_configure(ad, link);
if (r < 0) if (r < 0)
return r; return r;
req->after_configure = static_address_after_configure;
} }
HASHMAP_FOREACH(p, link->network->prefixes_by_section) { HASHMAP_FOREACH(p, link->network->prefixes_by_section) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *address = NULL;
Request *req;
if (!p->assign) if (!p->assign)
continue; continue;
@ -1110,18 +1097,22 @@ int link_request_static_addresses(Link *link) {
address->family = AF_INET6; address->family = AF_INET6;
address->route_metric = p->route_metric; address->route_metric = p->route_metric;
r = static_address_configure(address, link);
if (r < 0)
return r;
}
r = link_request_address(link, TAKE_PTR(address), true, &link->static_address_messages, if (link->address_messages == 0) {
static_address_handler, &req); link->addresses_configured = true;
link->addresses_ready = true;
r = link_set_ipv6_proxy_ndp_addresses(link);
if (r < 0) if (r < 0)
return r; return r;
req->after_configure = static_address_after_configure; r = link_set_routes(link);
} if (r < 0)
return r;
if (link->static_address_messages == 0) {
link->static_addresses_configured = true;
link_check_ready(link);
} else { } else {
log_link_debug(link, "Setting addresses"); log_link_debug(link, "Setting addresses");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
@ -1130,34 +1121,6 @@ int link_request_static_addresses(Link *link) {
return 0; return 0;
} }
int request_process_address(Request *req) {
Address *ret = NULL; /* avoid false maybe-uninitialized warning */
int r;
assert(req);
assert(req->link);
assert(req->address);
assert(req->type == REQUEST_TYPE_ADDRESS);
if (!link_is_ready_to_configure(req->link, false))
return 0;
if (req->link->address_remove_messages > 0)
return 0;
r = address_configure(req->address, req->link, req->netlink_handler, &ret);
if (r < 0)
return r;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)
return r;
}
return 1;
}
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(address_freep) Address *tmp = NULL; _cleanup_(address_freep) Address *tmp = NULL;
Link *link = NULL; Link *link = NULL;
@ -1341,6 +1304,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
} }
static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
_cleanup_free_ char *pretty = NULL;
Address *address; Address *address;
Link *link; Link *link;
int r; int r;
@ -1351,26 +1315,22 @@ static void static_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
address = (Address *) userdata; address = (Address *) userdata;
link = address->link; link = address->link;
assert(address->family == AF_INET); (void) in_addr_to_string(address->family, &address->in_addr, &pretty);
switch (event) { switch (event) {
case SD_IPV4ACD_EVENT_STOP: case SD_IPV4ACD_EVENT_STOP:
log_link_debug(link, "Stopping ACD client..."); log_link_debug(link, "Stopping ACD client...");
return; return;
case SD_IPV4ACD_EVENT_BIND: case SD_IPV4ACD_EVENT_BIND:
log_link_debug(link, "Successfully claimed address "IPV4_ADDRESS_FMT_STR, log_link_debug(link, "Successfully claimed address %s", strna(pretty));
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
link_check_ready(link); link_check_ready(link);
break; break;
case SD_IPV4ACD_EVENT_CONFLICT: case SD_IPV4ACD_EVENT_CONFLICT:
log_link_warning(link, "DAD conflict. Dropping address "IPV4_ADDRESS_FMT_STR, log_link_warning(link, "DAD conflict. Dropping address %s", strna(pretty));
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
r = address_remove(address, link, NULL); r = address_remove(address, link, NULL);
if (r < 0) if (r < 0)
log_link_error_errno(link, r, "Failed to drop DAD conflicted address "IPV4_ADDRESS_FMT_STR, log_link_error_errno(link, r, "Failed to drop DAD conflicted address %s", strna(pretty));;
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
link_check_ready(link); link_check_ready(link);
break; break;
@ -1393,7 +1353,12 @@ static int ipv4_dad_configure(Address *address) {
if (address->family != AF_INET) if (address->family != AF_INET)
return 0; return 0;
log_address_debug(address, "Starting IPv4ACD client. Probing", address->link); if (DEBUG_LOGGING) {
_cleanup_free_ char *pretty = NULL;
(void) in_addr_to_string(address->family, &address->in_addr, &pretty);
log_link_debug(address->link, "Starting IPv4ACD client. Probing address %s", strna(pretty));
}
if (!address->acd) { if (!address->acd) {
r = sd_ipv4acd_new(&address->acd); r = sd_ipv4acd_new(&address->acd);

View File

@ -16,7 +16,6 @@
typedef struct Manager Manager; typedef struct Manager Manager;
typedef struct Network Network; typedef struct Network Network;
typedef struct Request Request;
typedef int (*address_ready_callback_t)(Address *address); typedef int (*address_ready_callback_t)(Address *address);
typedef struct Address { typedef struct Address {
@ -52,8 +51,7 @@ typedef struct Address {
int address_new(Address **ret); int address_new(Address **ret);
Address *address_free(Address *address); Address *address_free(Address *address);
int address_get(Link *link, const Address *in, Address **ret); int address_get(Link *link, const Address *in, Address **ret);
int address_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg); int address_configure(const Address *address, Link *link, link_netlink_message_handler_t callback, Address **ret);
int address_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback); int address_remove(const Address *address, Link *link, link_netlink_message_handler_t callback);
bool address_equal(const Address *a1, const Address *a2); bool address_equal(const Address *a1, const Address *a2);
bool address_is_ready(const Address *a); bool address_is_ready(const Address *a);
@ -62,26 +60,16 @@ int generate_ipv6_eui_64_address(const Link *link, struct in6_addr *ret);
DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free); DEFINE_NETWORK_SECTION_FUNCTIONS(Address, address_free);
int link_set_addresses(Link *link);
int link_drop_addresses(Link *link); int link_drop_addresses(Link *link);
int link_drop_foreign_addresses(Link *link); int link_drop_foreign_addresses(Link *link);
bool link_address_is_dynamic(const Link *link, const Address *address); bool link_address_is_dynamic(const Link *link, const Address *address);
int link_has_ipv6_address(Link *link, const struct in6_addr *address); int link_has_ipv6_address(Link *link, const struct in6_addr *address);
int manager_has_address(Manager *manager, int family, const union in_addr_union *address, bool check_ready);
void ipv4_dad_unref(Link *link); void ipv4_dad_unref(Link *link);
int ipv4_dad_stop(Link *link); int ipv4_dad_stop(Link *link);
int ipv4_dad_update_mac(Link *link); int ipv4_dad_update_mac(Link *link);
int link_request_address(
Link *link,
Address *address,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret);
int link_request_static_addresses(Link *link);
int request_process_address(Request *req);
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, Manager *m);
void network_drop_invalid_addresses(Network *network); void network_drop_invalid_addresses(Network *network);
@ -98,3 +86,10 @@ CONFIG_PARSER_PROTOTYPE(config_parse_address_flags);
CONFIG_PARSER_PROTOTYPE(config_parse_address_scope); CONFIG_PARSER_PROTOTYPE(config_parse_address_scope);
CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric); CONFIG_PARSER_PROTOTYPE(config_parse_address_route_metric);
CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection); CONFIG_PARSER_PROTOTYPE(config_parse_duplicate_address_detection);
#define IPV4_ADDRESS_FMT_STR "%u.%u.%u.%u"
#define IPV4_ADDRESS_FMT_VAL(address) \
be32toh((address).s_addr) >> 24, \
(be32toh((address).s_addr) >> 16) & 0xFFu, \
(be32toh((address).s_addr) >> 8) & 0xFFu, \
be32toh((address).s_addr) & 0xFFu

View File

@ -17,16 +17,13 @@
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-nexthop.h"
#include "networkd-queue.h"
#include "networkd-route.h"
#include "networkd-state-file.h" #include "networkd-state-file.h"
#include "string-table.h" #include "string-table.h"
#include "strv.h" #include "strv.h"
#include "sysctl-util.h" #include "sysctl-util.h"
#include "web-util.h" #include "web-util.h"
static int dhcp4_request_address_and_routes(Link *link, bool announce); static int dhcp4_update_address(Link *link, bool announce);
static int dhcp4_remove_all(Link *link); static int dhcp4_remove_all(Link *link);
void network_adjust_dhcp4(Network *network) { void network_adjust_dhcp4(Network *network) {
@ -86,20 +83,8 @@ static void dhcp4_check_ready(Link *link) {
if (link->network->dhcp_send_decline && !link->dhcp4_address_bind) if (link->network->dhcp_send_decline && !link->dhcp4_address_bind)
return; return;
if (link->dhcp4_messages > 0) { if (link->dhcp4_messages > 0)
log_link_debug(link, "%s(): DHCPv4 address and routes are not set.", __func__);
return; return;
}
if (!link->dhcp_address) {
log_link_debug(link, "%s(): DHCPv4 address is not set.", __func__);
return;
}
if (!address_is_ready(link->dhcp_address)) {
log_link_debug(link, "%s(): DHCPv4 address is not ready.", __func__);
return;
}
link->dhcp4_configured = true; link->dhcp4_configured = true;
@ -117,27 +102,6 @@ static void dhcp4_check_ready(Link *link) {
link_check_ready(link); link_check_ready(link);
} }
static int dhcp4_after_route_configure(Request *req, void *object) {
Route *route = object;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ROUTE);
assert(route);
link = req->link;
r = set_ensure_put(&link->dhcp_routes, &route_hash_ops, route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv4 route: %m");
set_remove(link->dhcp_routes_old, route);
return 0;
}
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;
@ -171,15 +135,6 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
r = dhcp4_remove_all(link); r = dhcp4_remove_all(link);
if (r < 0) if (r < 0)
link_enter_failed(link); 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);
return 1; return 1;
} }
@ -188,26 +143,24 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
return 1; return 1;
} }
static int dhcp4_request_route(Route *in, Link *link) { static int dhcp_route_configure(Route *route, Link *link) {
_cleanup_(route_freep) Route *route = in; Route *ret;
Request *req;
int r; int r;
assert(route); assert(route);
assert(link); assert(link);
r = link_has_route(link, route); r = route_configure(route, link, dhcp4_route_handler, &ret);
if (r < 0) if (r < 0)
return r; return log_link_error_errno(link, r, "Failed to set DHCPv4 route: %m");
if (r == 0)
link->dhcp4_configured = false;
r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp4_messages, link->dhcp4_messages++;
dhcp4_route_handler, &req);
r = set_ensure_put(&link->dhcp_routes, &route_hash_ops, ret);
if (r < 0) if (r < 0)
return r; return log_link_error_errno(link, r, "Failed to store DHCPv4 route: %m");
req->after_configure = dhcp4_after_route_configure; (void) set_remove(link->dhcp_routes_old, ret);
return 0; return 0;
} }
@ -218,7 +171,7 @@ static bool link_prefixroute(Link *link) {
link->manager->dhcp4_prefix_root_cannot_set_table; link->manager->dhcp4_prefix_root_cannot_set_table;
} }
static int dhcp4_request_prefix_route(Link *link) { static int link_set_dhcp_prefix_route(Link *link) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
struct in_addr address, netmask; struct in_addr address, netmask;
int r; int r;
@ -251,10 +204,10 @@ static int dhcp4_request_prefix_route(Link *link) {
route->table = link_get_dhcp_route_table(link); route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu; route->mtu = link->network->dhcp_route_mtu;
return dhcp4_request_route(TAKE_PTR(route), link); return dhcp_route_configure(route, link);
} }
static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw) { static int link_set_dhcp_route_to_gateway(Link *link, const struct in_addr *gw) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
struct in_addr address; struct in_addr address;
int r; int r;
@ -281,15 +234,14 @@ static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw)
route->table = link_get_dhcp_route_table(link); route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu; route->mtu = link->network->dhcp_route_mtu;
return dhcp4_request_route(TAKE_PTR(route), link); return dhcp_route_configure(route, link);
} }
static int dhcp4_request_route_auto( static int dhcp_route_configure_auto(
Route *in, Route *route,
Link *link, Link *link,
const struct in_addr *gw) { const struct in_addr *gw) {
_cleanup_(route_freep) Route *route = in;
struct in_addr address, netmask, prefix; struct in_addr address, netmask, prefix;
uint8_t prefixlen; uint8_t prefixlen;
int r; int r;
@ -299,6 +251,8 @@ static int dhcp4_request_route_auto(
assert(link->dhcp_lease); assert(link->dhcp_lease);
assert(gw); assert(gw);
/* The route object may be reused in an iteration. All elements must be set or cleared. */
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0) if (r < 0)
return r; return r;
@ -355,7 +309,7 @@ static int dhcp4_request_route_auto(
return 0; return 0;
} }
r = dhcp4_request_route_to_gateway(link, gw); r = link_set_dhcp_route_to_gateway(link, gw);
if (r < 0) if (r < 0)
return r; return r;
@ -365,12 +319,13 @@ static int dhcp4_request_route_auto(
route->prefsrc.in = address; route->prefsrc.in = address;
} }
return dhcp4_request_route(TAKE_PTR(route), link); return dhcp_route_configure(route, link);
} }
static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_gw) { static int link_set_dhcp_static_routes(Link *link, struct in_addr *ret_default_gw) {
_cleanup_free_ sd_dhcp_route **static_routes = NULL; _cleanup_free_ sd_dhcp_route **static_routes = NULL;
bool classless_route = false, static_route = false; bool classless_route = false, static_route = false;
_cleanup_(route_freep) Route *route = NULL;
struct in_addr default_gw = {}; struct in_addr default_gw = {};
int n, r; int n, r;
@ -405,25 +360,24 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
if (classless_route && static_route) if (classless_route && static_route)
log_link_debug(link, "Classless static routes received from DHCP server: ignoring static-route option"); log_link_debug(link, "Classless static routes received from DHCP server: ignoring static-route option");
r = route_new(&route);
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;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
_cleanup_(route_freep) Route *route = NULL;
struct in_addr gw; struct in_addr gw;
if (sd_dhcp_route_get_option(static_routes[i]) != if (sd_dhcp_route_get_option(static_routes[i]) !=
(classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE)) (classless_route ? SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE : SD_DHCP_OPTION_STATIC_ROUTE))
continue; continue;
r = route_new(&route);
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); r = sd_dhcp_route_get_gateway(static_routes[i], &gw);
if (r < 0) if (r < 0)
return r; return r;
@ -444,7 +398,7 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
in4_addr_is_null(&default_gw)) in4_addr_is_null(&default_gw))
default_gw = gw; default_gw = gw;
r = dhcp4_request_route_auto(TAKE_PTR(route), link, &gw); r = dhcp_route_configure_auto(route, link, &gw);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -453,7 +407,7 @@ static int dhcp4_request_static_routes(Link *link, struct in_addr *ret_default_g
return classless_route; return classless_route;
} }
static int dhcp4_request_gateway(Link *link, struct in_addr *ret_gw) { static int link_set_dhcp_gateway(Link *link, struct in_addr *ret_gw) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
const struct in_addr *router; const struct in_addr *router;
struct in_addr address; struct in_addr address;
@ -485,7 +439,7 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *ret_gw) {
/* The dhcp netmask may mask out the gateway. First, add an explicit route for the gateway host /* The dhcp netmask may mask out the gateway. First, add an explicit route for the gateway host
* so that we can route no matter the netmask or existing kernel route tables. */ * so that we can route no matter the netmask or existing kernel route tables. */
r = dhcp4_request_route_to_gateway(link, &router[0]); r = link_set_dhcp_route_to_gateway(link, &router[0]);
if (r < 0) if (r < 0)
return r; return r;
@ -503,7 +457,7 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *ret_gw) {
route->table = link_get_dhcp_route_table(link); route->table = link_get_dhcp_route_table(link);
route->mtu = link->network->dhcp_route_mtu; route->mtu = link->network->dhcp_route_mtu;
r = dhcp4_request_route(TAKE_PTR(route), link); r = dhcp_route_configure(route, link);
if (r < 0) if (r < 0)
return r; return r;
@ -514,21 +468,17 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *ret_gw) {
if (rt->gw_family != AF_INET) if (rt->gw_family != AF_INET)
continue; continue;
r = route_dup(rt, &route); rt->gw.in = router[0];
if (r < 0) if (!rt->protocol_set)
return r; rt->protocol = RTPROT_DHCP;
if (!rt->priority_set)
rt->priority = link->network->dhcp_route_metric;
if (!rt->table_set)
rt->table = link_get_dhcp_route_table(link);
if (rt->mtu == 0)
rt->mtu = link->network->dhcp_route_mtu;
route->gw.in = router[0]; r = dhcp_route_configure(rt, link);
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) if (r < 0)
return r; return r;
} }
@ -537,12 +487,13 @@ static int dhcp4_request_gateway(Link *link, struct in_addr *ret_gw) {
return 0; return 0;
} }
static int dhcp4_request_routes_to_servers( static int link_set_routes_to_servers(
Link *link, Link *link,
const struct in_addr *servers, const struct in_addr *servers,
size_t n_servers, size_t n_servers,
const struct in_addr *gw) { const struct in_addr *gw) {
_cleanup_(route_freep) Route *route = NULL;
int r; int r;
assert(link); assert(link);
@ -551,25 +502,24 @@ static int dhcp4_request_routes_to_servers(
assert(servers || n_servers == 0); assert(servers || n_servers == 0);
assert(gw); assert(gw);
for (size_t i = 0; i < n_servers; i++) { r = route_new(&route);
_cleanup_(route_freep) Route *route = NULL; if (r < 0)
return r;
route->family = AF_INET;
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;
for (size_t i = 0; i < n_servers; i++) {
if (in4_addr_is_null(&servers[i])) if (in4_addr_is_null(&servers[i]))
continue; continue;
r = route_new(&route);
if (r < 0)
return r;
route->family = AF_INET;
route->dst.in = servers[i]; 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); r = dhcp_route_configure_auto(route, link, gw);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -577,7 +527,7 @@ static int dhcp4_request_routes_to_servers(
return 0; return 0;
} }
static int dhcp4_request_routes_to_dns(Link *link, const struct in_addr *gw) { static int link_set_routes_to_dns(Link *link, const struct in_addr *gw) {
const struct in_addr *dns; const struct in_addr *dns;
int r; int r;
@ -596,10 +546,10 @@ static int dhcp4_request_routes_to_dns(Link *link, const struct in_addr *gw) {
if (r < 0) if (r < 0)
return r; return r;
return dhcp4_request_routes_to_servers(link, dns, r, gw); return link_set_routes_to_servers(link, dns, r, gw);
} }
static int dhcp4_request_routes_to_ntp(Link *link, const struct in_addr *gw) { static int link_set_routes_to_ntp(Link *link, const struct in_addr *gw) {
const struct in_addr *ntp; const struct in_addr *ntp;
int r; int r;
@ -618,17 +568,25 @@ static int dhcp4_request_routes_to_ntp(Link *link, const struct in_addr *gw) {
if (r < 0) if (r < 0)
return r; return r;
return dhcp4_request_routes_to_servers(link, ntp, r, gw); return link_set_routes_to_servers(link, ntp, r, gw);
} }
static int dhcp4_request_routes(Link *link) { static int link_set_dhcp_routes(Link *link) {
struct in_addr gw = {}; struct in_addr gw = {};
Route *rt; Route *rt;
int r; int r;
assert(link); assert(link);
if (!link->dhcp_lease) if (!link->dhcp_lease) /* link went down while we configured the IP addresses? */
return 0;
if (!link->network) /* link went down while we configured the IP addresses? */
return 0;
if (!link_has_carrier(link) && !link->network->configure_without_carrier)
/* During configuring addresses, the link lost its carrier. As networkd is dropping
* the addresses now, let's not configure the routes either. */
return 0; return 0;
while ((rt = set_steal_first(link->dhcp_routes))) { while ((rt = set_steal_first(link->dhcp_routes))) {
@ -637,28 +595,28 @@ static int dhcp4_request_routes(Link *link) {
return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m"); return log_link_error_errno(link, r, "Failed to store old DHCPv4 route: %m");
} }
r = dhcp4_request_prefix_route(link); r = link_set_dhcp_prefix_route(link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: Could not request prefix route: %m"); return log_link_error_errno(link, r, "DHCP error: Could not set prefix route: %m");
r = dhcp4_request_static_routes(link, &gw); r = link_set_dhcp_static_routes(link, &gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: Could not request static routes: %m"); return log_link_error_errno(link, r, "DHCP error: Could not set static routes: %m");
if (r == 0) { if (r == 0) {
/* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and /* According to RFC 3442: If the DHCP server returns both a Classless Static Routes option and
* a Router option, the DHCP client MUST ignore the Router option. */ * a Router option, the DHCP client MUST ignore the Router option. */
r = dhcp4_request_gateway(link, &gw); r = link_set_dhcp_gateway(link, &gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: Could not request gateway: %m"); return log_link_error_errno(link, r, "DHCP error: Could not set gateway: %m");
} }
r = dhcp4_request_routes_to_dns(link, &gw); r = link_set_routes_to_dns(link, &gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: Could not request routes to DNS servers: %m"); return log_link_error_errno(link, r, "DHCP error: Could not set routes to DNS servers: %m");
r = dhcp4_request_routes_to_ntp(link, &gw); r = link_set_routes_to_ntp(link, &gw);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "DHCP error: Could not request routes to NTP servers: %m"); return log_link_error_errno(link, r, "DHCP error: Could not set routes to NTP servers: %m");
return 0; return 0;
} }
@ -712,20 +670,24 @@ static int dhcp_reset_hostname(Link *link) {
return 0; return 0;
} }
static int dhcp4_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp4_remove_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(m);
assert(link); assert(link);
assert(link->dhcp4_remove_messages > 0); assert(link->dhcp4_remove_messages > 0);
link->dhcp4_remove_messages--; link->dhcp4_remove_messages--;
r = link_route_remove_handler_internal(rtnl, m, link, "Failed to remove DHCPv4 route, ignoring"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH)
log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 route, ignoring");
if (link->dhcp4_remove_messages == 0) { if (link->dhcp4_remove_messages == 0) {
r = dhcp4_request_address_and_routes(link, false); r = dhcp4_update_address(link, false);
if (r < 0) if (r < 0)
link_enter_failed(link); link_enter_failed(link);
} }
@ -733,20 +695,26 @@ static int dhcp4_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, L
return 1; return 1;
} }
static int dhcp4_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp4_remove_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(m);
assert(link); assert(link);
assert(link->dhcp4_remove_messages > 0); assert(link->dhcp4_remove_messages > 0);
link->dhcp4_remove_messages--; link->dhcp4_remove_messages--;
r = address_remove_handler_internal(rtnl, m, link, "Failed to remove DHCPv4 address, ignoring"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_message_warning_errno(link, m, r, "Failed to remove DHCPv4 address, ignoring");
else
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp4_remove_messages == 0) { if (link->dhcp4_remove_messages == 0) {
r = dhcp4_request_address_and_routes(link, false); r = dhcp4_update_address(link, false);
if (r < 0) if (r < 0)
link_enter_failed(link); link_enter_failed(link);
} }
@ -761,7 +729,7 @@ static int dhcp4_remove_all(Link *link) {
assert(link); assert(link);
SET_FOREACH(route, link->dhcp_routes) { SET_FOREACH(route, link->dhcp_routes) {
k = route_remove(route, NULL, link, dhcp4_route_remove_handler); k = route_remove(route, NULL, link, dhcp4_remove_route_handler);
if (k < 0) if (k < 0)
r = k; r = k;
else else
@ -769,7 +737,7 @@ static int dhcp4_remove_all(Link *link) {
} }
if (link->dhcp_address) { if (link->dhcp_address) {
k = address_remove(link->dhcp_address, link, dhcp4_address_remove_handler); k = address_remove(link->dhcp_address, link, dhcp4_remove_address_handler);
if (k < 0) if (k < 0)
r = k; r = k;
else else
@ -811,18 +779,12 @@ static int dhcp_lease_lost(Link *link) {
(void) sd_ipv4acd_stop(link->dhcp_acd); (void) sd_ipv4acd_stop(link->dhcp_acd);
if (r < 0) return r;
return r;
r = link_request_static_nexthops(link, true);
if (r < 0)
return r;
return link_request_static_routes(link, true);
} }
static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) { static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
struct in_addr address; _cleanup_free_ char *pretty = NULL;
union in_addr_union address = {};
Link *link; Link *link;
int r; int r;
@ -833,21 +795,23 @@ static void dhcp_address_on_acd(sd_ipv4acd *acd, int event, void *userdata) {
switch (event) { switch (event) {
case SD_IPV4ACD_EVENT_STOP: case SD_IPV4ACD_EVENT_STOP:
log_link_debug(link, "Stopping ACD client for DHCPv4 address."); log_link_debug(link, "Stopping ACD client for DHCP4...");
return; return;
case SD_IPV4ACD_EVENT_BIND: case SD_IPV4ACD_EVENT_BIND:
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
(void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address.in);
log_link_debug(link, "Successfully claimed DHCPv4 address "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address)); (void) in_addr_to_string(AF_INET, &address, &pretty);
log_link_debug(link, "Successfully claimed DHCP4 address %s", strna(pretty));
} }
link->dhcp4_address_bind = true; link->dhcp4_address_bind = true;
dhcp4_check_ready(link); dhcp4_check_ready(link);
break; break;
case SD_IPV4ACD_EVENT_CONFLICT: case SD_IPV4ACD_EVENT_CONFLICT:
(void) sd_dhcp_lease_get_address(link->dhcp_lease, &address); (void) sd_dhcp_lease_get_address(link->dhcp_lease, &address.in);
log_link_warning(link, "DAD conflict. Dropping DHCPv4 address "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(address)); (void) in_addr_to_string(AF_INET, &address, &pretty);
log_link_warning(link, "DAD conflict. Dropping DHCP4 address %s", strna(pretty));
r = sd_dhcp_client_send_decline(link->dhcp_client); r = sd_dhcp_client_send_decline(link->dhcp_client);
if (r < 0) if (r < 0)
@ -929,7 +893,8 @@ static int dhcp4_dad_update_mac(Link *link) {
} }
static int dhcp4_start_acd(Link *link) { static int dhcp4_start_acd(Link *link) {
struct in_addr addr, old; union in_addr_union addr;
struct in_addr old;
int r; int r;
if (!link->network->dhcp_send_decline) if (!link->network->dhcp_send_decline)
@ -942,7 +907,7 @@ static int dhcp4_start_acd(Link *link) {
link->dhcp4_address_bind = false; link->dhcp4_address_bind = false;
r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr); r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr.in);
if (r < 0) if (r < 0)
return r; return r;
@ -950,7 +915,7 @@ static int dhcp4_start_acd(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_ipv4acd_set_address(link->dhcp_acd, &addr); r = sd_ipv4acd_set_address(link->dhcp_acd, &addr.in);
if (r < 0) if (r < 0)
return r; return r;
@ -958,51 +923,45 @@ static int dhcp4_start_acd(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address "IPV4_ADDRESS_FMT_STR, if (DEBUG_LOGGING) {
IPV4_ADDRESS_FMT_VAL(addr)); _cleanup_free_ char *pretty = NULL;
return sd_ipv4acd_start(link->dhcp_acd, !in4_addr_equal(&addr, &old)); (void) in_addr_to_string(AF_INET, &addr, &pretty);
log_link_debug(link, "Starting IPv4ACD client. Probing DHCPv4 address %s", strna(pretty));
}
r = sd_ipv4acd_start(link->dhcp_acd, !in4_addr_equal(&addr.in, &old));
if (r < 0)
return r;
return 1;
} }
static int dhcp4_address_ready_callback(Address *address) { static int dhcp4_address_ready_callback(Address *address) {
Link *link;
int r;
assert(address); assert(address);
link = address->link;
/* Do not call this again. */ /* Do not call this again. */
address->callback = NULL; address->callback = NULL;
dhcp4_check_ready(address->link); r = link_set_dhcp_routes(link);
return 0; if (r < 0)
} return r;
static int dhcp4_after_address_configure(Request *req, void *object) { /* Reconfigure static routes as kernel may remove some routes when lease expires. */
Address *address = object; r = link_set_routes(link);
Link *link; if (r < 0)
int r; return r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ADDRESS);
assert(address);
link = req->link;
if (!address_equal(link->dhcp_address, address)) {
if (link->dhcp_address_old &&
!address_equal(link->dhcp_address_old, link->dhcp_address)) {
/* Still too old address exists? Let's remove it immediately. */
r = address_remove(link->dhcp_address_old, link, NULL);
if (r < 0)
return r;
}
link->dhcp_address_old = link->dhcp_address;
}
link->dhcp_address = address;
r = dhcp4_start_acd(link); r = dhcp4_start_acd(link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCPv4 address: %m"); return log_link_error_errno(link, r, "Failed to start IPv4ACD for DHCP4 address: %m");
dhcp4_check_ready(link);
return 0; return 0;
} }
@ -1010,30 +969,36 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
int r; int r;
assert(link); assert(link);
assert(link->dhcp4_messages > 0);
link->dhcp4_messages--; if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv4 address"); r = sd_netlink_message_get_errno(m);
if (r <= 0) if (r < 0 && r != -EEXIST) {
return r; log_link_message_warning_errno(link, m, r, "Could not set DHCPv4 address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (address_is_ready(link->dhcp_address)) { if (address_is_ready(link->dhcp_address)) {
r = dhcp4_address_ready_callback(link->dhcp_address); r = dhcp4_address_ready_callback(link->dhcp_address);
if (r < 0) if (r < 0) {
link_enter_failed(link); link_enter_failed(link);
return 1;
}
} else } else
link->dhcp_address->callback = dhcp4_address_ready_callback; link->dhcp_address->callback = dhcp4_address_ready_callback;
return 1; return 1;
} }
static int dhcp4_request_address(Link *link, bool announce) { static int dhcp4_update_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; struct in_addr address, netmask;
unsigned prefixlen; unsigned prefixlen;
Request *req; Address *ret;
int r; int r;
assert(link); assert(link);
@ -1042,6 +1007,15 @@ static int dhcp4_request_address(Link *link, bool announce) {
if (!link->dhcp_lease) if (!link->dhcp_lease)
return 0; return 0;
link_set_state(link, LINK_STATE_CONFIGURING);
link->dhcp4_configured = false;
/* address_handler calls link_set_routes() and link_set_nexthop(). Before they are called, the
* related flags must be cleared. Otherwise, the link becomes configured state before routes
* are configured. */
link->static_routes_configured = false;
link->static_nexthops_configured = false;
r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); r = sd_dhcp_lease_get_address(link->dhcp_lease, &address);
if (r < 0) if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: no address: %m"); return log_link_warning_errno(link, r, "DHCP error: no address: %m");
@ -1099,34 +1073,15 @@ static int dhcp4_request_address(Link *link, bool announce) {
SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link)); SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
addr->route_metric = link->network->dhcp_route_metric; addr->route_metric = link->network->dhcp_route_metric;
if (address_get(link, addr, NULL) < 0) /* allow reusing an existing address and simply update its lifetime
link->dhcp4_configured = false; * in case it already exists */
r = address_configure(addr, link, dhcp4_address_handler, &ret);
r = link_request_address(link, TAKE_PTR(addr), true, &link->dhcp4_messages,
dhcp4_address_handler, &req);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCPv4 address: %m"); return log_link_error_errno(link, r, "Failed to set DHCPv4 address: %m");
req->after_configure = dhcp4_after_address_configure; if (!address_equal(link->dhcp_address, ret))
link->dhcp_address_old = link->dhcp_address;
return 0; link->dhcp_address = ret;
}
static int dhcp4_request_address_and_routes(Link *link, bool announce) {
int r;
assert(link);
r = dhcp4_request_address(link, announce);
if (r < 0)
return r;
r = dhcp4_request_routes(link);
if (r < 0)
return r;
link_set_state(link, LINK_STATE_CONFIGURING);
link_check_ready(link);
return 0; return 0;
} }
@ -1146,7 +1101,7 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
link->dhcp_lease = sd_dhcp_lease_ref(lease); link->dhcp_lease = sd_dhcp_lease_ref(lease);
link_dirty(link); link_dirty(link);
return dhcp4_request_address_and_routes(link, false); return dhcp4_update_address(link, false);
} }
static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
@ -1211,7 +1166,16 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
} }
} }
return dhcp4_request_address_and_routes(link, true); if (link->dhcp4_remove_messages == 0) {
r = dhcp4_update_address(link, true);
if (r < 0)
return r;
} else
log_link_debug(link,
"The link has previously assigned DHCPv4 address or routes. "
"The newly assigned address and routes will set up after old ones are removed.");
return 0;
} }
static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) { static int dhcp_lease_ip_change(sd_dhcp_client *client, Link *link) {

View File

@ -18,7 +18,6 @@
#include "networkd-dhcp6.h" #include "networkd-dhcp6.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-queue.h"
#include "networkd-radv.h" #include "networkd-radv.h"
#include "siphash24.h" #include "siphash24.h"
#include "string-table.h" #include "string-table.h"
@ -44,7 +43,7 @@ bool link_dhcp6_pd_is_enabled(Link *link) {
static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) { static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
uint32_t lifetime_preferred, lifetime_valid; uint32_t lifetime_preferred, lifetime_valid;
struct in6_addr pd_prefix; union in_addr_union pd_prefix;
uint8_t pd_prefix_len; uint8_t pd_prefix_len;
if (!lease) if (!lease)
@ -52,7 +51,7 @@ static bool dhcp6_lease_has_pd_prefix(sd_dhcp6_lease *lease) {
sd_dhcp6_lease_reset_pd_prefix_iter(lease); sd_dhcp6_lease_reset_pd_prefix_iter(lease);
return sd_dhcp6_lease_get_pd(lease, &pd_prefix, &pd_prefix_len, &lifetime_preferred, &lifetime_valid) >= 0; return sd_dhcp6_lease_get_pd(lease, &pd_prefix.in6, &pd_prefix_len, &lifetime_preferred, &lifetime_valid) >= 0;
} }
DHCP6DelegatedPrefix *dhcp6_pd_free(DHCP6DelegatedPrefix *p) { DHCP6DelegatedPrefix *dhcp6_pd_free(DHCP6DelegatedPrefix *p) {
@ -87,21 +86,21 @@ static int dhcp6_pd_compare_func(const DHCP6DelegatedPrefix *a, const DHCP6Deleg
DEFINE_HASH_OPS(dhcp6_pd_hash_ops, DHCP6DelegatedPrefix, dhcp6_pd_hash_func, dhcp6_pd_compare_func); DEFINE_HASH_OPS(dhcp6_pd_hash_ops, DHCP6DelegatedPrefix, dhcp6_pd_hash_func, dhcp6_pd_compare_func);
static Link *dhcp6_pd_get_link_by_prefix(Link *link, const struct in6_addr *prefix) { static Link *dhcp6_pd_get_link_by_prefix(Link *link, const union in_addr_union *prefix) {
DHCP6DelegatedPrefix *pd; DHCP6DelegatedPrefix *pd;
assert(link); assert(link);
assert(link->manager); assert(link->manager);
assert(prefix); assert(prefix);
pd = hashmap_get(link->manager->dhcp6_prefixes, prefix); pd = hashmap_get(link->manager->dhcp6_prefixes, &prefix->in6);
if (!pd) if (!pd)
return NULL; return NULL;
return pd->link; return pd->link;
} }
static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_prefix, struct in6_addr *ret_prefix) { static int dhcp6_pd_get_assigned_prefix(Link *link, const union in_addr_union *pd_prefix, union in_addr_union *ret_prefix) {
DHCP6DelegatedPrefix *pd, in; DHCP6DelegatedPrefix *pd, in;
assert(link); assert(link);
@ -110,7 +109,7 @@ static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_pr
assert(ret_prefix); assert(ret_prefix);
in = (DHCP6DelegatedPrefix) { in = (DHCP6DelegatedPrefix) {
.pd_prefix = *pd_prefix, .pd_prefix = pd_prefix->in6,
.link = link, .link = link,
}; };
@ -118,7 +117,7 @@ static int dhcp6_pd_get_assigned_prefix(Link *link, const struct in6_addr *pd_pr
if (!pd) if (!pd)
return -ENOENT; return -ENOENT;
*ret_prefix = pd->prefix; ret_prefix->in6 = pd->prefix;
return 0; return 0;
} }
@ -230,7 +229,7 @@ int dhcp6_pd_remove(Link *link) {
return r; return r;
} }
static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp6_pd_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
@ -238,9 +237,15 @@ static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
link->dhcp6_pd_route_messages--; link->dhcp6_pd_route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Failed to add DHCPv6 Prefix Delegation route"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Failed to add DHCPv6 Prefix Delegation route");
link_enter_failed(link);
return 1;
}
if (link->dhcp6_pd_route_messages == 0) { if (link->dhcp6_pd_route_messages == 0) {
log_link_debug(link, "DHCPv6 prefix delegation routes set"); log_link_debug(link, "DHCPv6 prefix delegation routes set");
@ -259,32 +264,11 @@ static int dhcp6_pd_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
return 1; return 1;
} }
static int dhcp6_pd_after_route_configure(Request *req, void *object) { static int dhcp6_set_pd_route(Link *link, const union in_addr_union *prefix, const union in_addr_union *pd_prefix) {
Route *route = object;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ROUTE);
assert(route);
link = req->link;
r = set_ensure_put(&link->dhcp6_pd_routes, &route_hash_ops, route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 prefix route: %m");
set_remove(link->dhcp6_pd_routes_old, route);
return 0;
}
static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, const struct in6_addr *pd_prefix) {
_cleanup_(dhcp6_pd_freep) DHCP6DelegatedPrefix *pd = NULL; _cleanup_(dhcp6_pd_freep) DHCP6DelegatedPrefix *pd = NULL;
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
Link *assigned_link; Link *assigned_link;
Request *req; Route *ret;
int r; int r;
assert(link); assert(link);
@ -297,23 +281,24 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, con
return r; return r;
route->family = AF_INET6; route->family = AF_INET6;
route->dst.in6 = *prefix; route->dst = *prefix;
route->dst_prefixlen = 64; route->dst_prefixlen = 64;
route->protocol = RTPROT_DHCP; route->protocol = RTPROT_DHCP;
route->priority = link->network->dhcp6_pd_route_metric; route->priority = link->network->dhcp6_pd_route_metric;
r = link_has_route(link, route); r = route_configure(route, link, dhcp6_pd_route_handler, &ret);
if (r < 0) if (r < 0)
return r; return log_link_error_errno(link, r, "Failed to set DHCPv6 prefix route: %m");
if (r == 0) if (r > 0)
link->dhcp6_pd_route_configured = false; link->dhcp6_pd_route_configured = false;
r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp6_pd_route_messages, link->dhcp6_pd_route_messages++;
dhcp6_pd_route_handler, &req);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCPv6 prefix route: %m");
req->after_configure = dhcp6_pd_after_route_configure; r = set_ensure_put(&link->dhcp6_pd_routes, &route_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 prefix route: %m");
(void) set_remove(link->dhcp6_pd_routes_old, ret);
assigned_link = dhcp6_pd_get_link_by_prefix(link, prefix); assigned_link = dhcp6_pd_get_link_by_prefix(link, prefix);
if (assigned_link) { if (assigned_link) {
@ -326,8 +311,8 @@ static int dhcp6_pd_request_route(Link *link, const struct in6_addr *prefix, con
return log_oom(); return log_oom();
*pd = (DHCP6DelegatedPrefix) { *pd = (DHCP6DelegatedPrefix) {
.prefix = *prefix, .prefix = prefix->in6,
.pd_prefix = *pd_prefix, .pd_prefix = pd_prefix->in6,
.link = link_ref(link), .link = link_ref(link),
}; };
@ -353,9 +338,16 @@ static int dhcp6_pd_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Lin
link->dhcp6_pd_address_messages--; link->dhcp6_pd_address_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 delegated prefix address"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 delegated prefix address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp6_pd_address_messages == 0) { if (link->dhcp6_pd_address_messages == 0) {
log_link_debug(link, "DHCPv6 delegated prefix addresses set"); log_link_debug(link, "DHCPv6 delegated prefix addresses set");
@ -378,15 +370,12 @@ static void log_dhcp6_pd_address(Link *link, const Address *address) {
_cleanup_free_ char *buffer = NULL; _cleanup_free_ char *buffer = NULL;
int log_level; int log_level;
assert(address);
assert(address->family == AF_INET6);
log_level = address_get(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO; log_level = address_get(link, address, NULL) >= 0 ? LOG_DEBUG : LOG_INFO;
if (log_level < log_get_max_level()) if (log_level < log_get_max_level())
return; return;
(void) in6_addr_prefix_to_string(&address->in_addr.in6, address->prefixlen, &buffer); (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buffer);
if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
address->cinfo.ifa_valid * USEC_PER_SEC, address->cinfo.ifa_valid * USEC_PER_SEC,
@ -402,35 +391,14 @@ static void log_dhcp6_pd_address(Link *link, const Address *address) {
preferred_str ? "for " : "forever", strempty(preferred_str)); preferred_str ? "for " : "forever", strempty(preferred_str));
} }
static int dhcp6_pd_after_address_configure(Request *req, void *object) { static int dhcp6_set_pd_address(
Address *address = object;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ADDRESS);
assert(address);
link = req->link;
r = set_ensure_put(&link->dhcp6_pd_addresses, &address_hash_ops, address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 delegated prefix address: %m");
set_remove(link->dhcp6_pd_addresses_old, address);
return 0;
}
static int dhcp6_pd_request_address(
Link *link, Link *link,
const struct in6_addr *prefix, const union in_addr_union *prefix,
uint32_t lifetime_preferred, uint32_t lifetime_preferred,
uint32_t lifetime_valid) { uint32_t lifetime_valid) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *address = NULL;
Request *req; Address *ret;
int r; int r;
assert(link); assert(link);
@ -444,10 +412,10 @@ static int dhcp6_pd_request_address(
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to allocate address for DHCPv6 delegated prefix: %m"); return log_link_error_errno(link, r, "Failed to allocate address for DHCPv6 delegated prefix: %m");
address->in_addr.in6 = *prefix; address->in_addr = *prefix;
if (in6_addr_is_set(&link->network->dhcp6_pd_token)) if (in_addr_is_set(AF_INET6, &link->network->dhcp6_pd_token))
memcpy(address->in_addr.in6.s6_addr + 8, link->network->dhcp6_pd_token.s6_addr + 8, 8); memcpy(address->in_addr.in6.s6_addr + 8, link->network->dhcp6_pd_token.in6.s6_addr + 8, 8);
else { else {
r = generate_ipv6_eui_64_address(link, &address->in_addr.in6); r = generate_ipv6_eui_64_address(link, &address->in_addr.in6);
if (r < 0) if (r < 0)
@ -462,24 +430,27 @@ static int dhcp6_pd_request_address(
address->route_metric = link->network->dhcp6_pd_route_metric; address->route_metric = link->network->dhcp6_pd_route_metric;
log_dhcp6_pd_address(link, address); log_dhcp6_pd_address(link, address);
r = address_configure(address, link, dhcp6_pd_address_handler, &ret);
if (address_get(link, address, NULL) < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 delegated prefix address: %m");
if (r > 0)
link->dhcp6_pd_address_configured = false; link->dhcp6_pd_address_configured = false;
r = link_request_address(link, TAKE_PTR(address), true, &link->dhcp6_pd_address_messages, link->dhcp6_pd_address_messages++;
dhcp6_pd_address_handler, &req);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCPv6 delegated prefix address: %m");
req->after_configure = dhcp6_pd_after_address_configure; r = set_ensure_put(&link->dhcp6_pd_addresses, &address_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 delegated prefix address: %m");
(void) set_remove(link->dhcp6_pd_addresses_old, ret);
return 0; return 0;
} }
static int dhcp6_pd_assign_prefix( static int dhcp6_pd_assign_prefix(
Link *link, Link *link,
const struct in6_addr *prefix, const union in_addr_union *prefix,
const struct in6_addr *pd_prefix, const union in_addr_union *pd_prefix,
uint32_t lifetime_preferred, uint32_t lifetime_preferred,
uint32_t lifetime_valid) { uint32_t lifetime_valid) {
@ -490,16 +461,16 @@ static int dhcp6_pd_assign_prefix(
assert(prefix); assert(prefix);
if (link->network->dhcp6_pd_announce) { if (link->network->dhcp6_pd_announce) {
r = radv_add_prefix(link, prefix, 64, lifetime_preferred, lifetime_valid); r = radv_add_prefix(link, &prefix->in6, 64, lifetime_preferred, lifetime_valid);
if (r < 0) if (r < 0)
return r; return r;
} }
r = dhcp6_pd_request_route(link, prefix, pd_prefix); r = dhcp6_set_pd_route(link, prefix, pd_prefix);
if (r < 0) if (r < 0)
return r; return r;
r = dhcp6_pd_request_address(link, prefix, lifetime_preferred, lifetime_valid); r = dhcp6_set_pd_address(link, prefix, lifetime_preferred, lifetime_valid);
if (r < 0) if (r < 0)
return r; return r;
@ -515,9 +486,9 @@ static bool link_has_preferred_subnet_id(Link *link) {
static int dhcp6_get_preferred_delegated_prefix( static int dhcp6_get_preferred_delegated_prefix(
Link *link, Link *link,
const struct in6_addr *masked_pd_prefix, const union in_addr_union *masked_pd_prefix,
uint8_t pd_prefix_len, uint8_t pd_prefix_len,
struct in6_addr *ret) { union in_addr_union *ret) {
/* We start off with the original PD prefix we have been assigned and iterate from there */ /* We start off with the original PD prefix we have been assigned and iterate from there */
union in_addr_union prefix; union in_addr_union prefix;
@ -531,7 +502,7 @@ static int dhcp6_get_preferred_delegated_prefix(
assert(pd_prefix_len <= 64); assert(pd_prefix_len <= 64);
n_prefixes = UINT64_C(1) << (64 - pd_prefix_len); n_prefixes = UINT64_C(1) << (64 - pd_prefix_len);
prefix.in6 = *masked_pd_prefix; prefix = *masked_pd_prefix;
if (link_has_preferred_subnet_id(link)) { if (link_has_preferred_subnet_id(link)) {
uint64_t subnet_id = link->network->dhcp6_pd_subnet_id; uint64_t subnet_id = link->network->dhcp6_pd_subnet_id;
@ -550,28 +521,28 @@ static int dhcp6_get_preferred_delegated_prefix(
/* Verify that the prefix we did calculate fits in the pd prefix. /* Verify that the prefix we did calculate fits in the pd prefix.
* This should not fail as we checked the prefix size beforehand */ * This should not fail as we checked the prefix size beforehand */
assert_se(in_addr_prefix_covers(AF_INET6, (const union in_addr_union*) masked_pd_prefix, pd_prefix_len, &prefix) > 0); assert_se(in_addr_prefix_covers(AF_INET6, masked_pd_prefix, pd_prefix_len, &prefix) > 0);
assigned_link = dhcp6_pd_get_link_by_prefix(link, &prefix.in6); assigned_link = dhcp6_pd_get_link_by_prefix(link, &prefix);
if (assigned_link && assigned_link != link) { if (assigned_link && assigned_link != link) {
_cleanup_free_ char *assigned_buf = NULL; _cleanup_free_ char *assigned_buf = NULL;
(void) in6_addr_to_string(&prefix.in6, &assigned_buf); (void) in_addr_to_string(AF_INET6, &prefix, &assigned_buf);
return log_link_warning_errno(link, SYNTHETIC_ERRNO(EAGAIN), return log_link_warning_errno(link, SYNTHETIC_ERRNO(EAGAIN),
"The requested prefix %s is already assigned to another link.", "The requested prefix %s is already assigned to another link.",
strna(assigned_buf)); strna(assigned_buf));
} }
*ret = prefix.in6; *ret = prefix;
return 0; return 0;
} }
for (uint64_t n = 0; n < n_prefixes; n++) { for (uint64_t n = 0; n < n_prefixes; n++) {
/* If we do not have an allocation preference just iterate /* If we do not have an allocation preference just iterate
* through the address space and return the first free prefix. */ * through the address space and return the first free prefix. */
assigned_link = dhcp6_pd_get_link_by_prefix(link, &prefix.in6); assigned_link = dhcp6_pd_get_link_by_prefix(link, &prefix);
if (!assigned_link || assigned_link == link) { if (!assigned_link || assigned_link == link) {
*ret = prefix.in6; *ret = prefix;
return 0; return 0;
} }
@ -584,7 +555,7 @@ static int dhcp6_get_preferred_delegated_prefix(
} }
static void dhcp6_pd_prefix_distribute(Link *dhcp6_link, static void dhcp6_pd_prefix_distribute(Link *dhcp6_link,
const struct in6_addr *masked_pd_prefix, const union in_addr_union *masked_pd_prefix,
uint8_t pd_prefix_len, uint8_t pd_prefix_len,
uint32_t lifetime_preferred, uint32_t lifetime_preferred,
uint32_t lifetime_valid, uint32_t lifetime_valid,
@ -600,7 +571,7 @@ static void dhcp6_pd_prefix_distribute(Link *dhcp6_link,
HASHMAP_FOREACH(link, dhcp6_link->manager->links) { HASHMAP_FOREACH(link, dhcp6_link->manager->links) {
_cleanup_free_ char *assigned_buf = NULL; _cleanup_free_ char *assigned_buf = NULL;
struct in6_addr assigned_prefix; union in_addr_union assigned_prefix;
if (link == dhcp6_link) if (link == dhcp6_link)
continue; continue;
@ -623,7 +594,7 @@ static void dhcp6_pd_prefix_distribute(Link *dhcp6_link,
} }
} }
(void) in6_addr_to_string(&assigned_prefix, &assigned_buf); (void) in_addr_to_string(AF_INET6, &assigned_prefix, &assigned_buf);
r = dhcp6_pd_assign_prefix(link, &assigned_prefix, masked_pd_prefix, r = dhcp6_pd_assign_prefix(link, &assigned_prefix, masked_pd_prefix,
lifetime_preferred, lifetime_valid); lifetime_preferred, lifetime_valid);
if (r < 0) { if (r < 0) {
@ -688,10 +659,11 @@ static int dhcp6_pd_finalize(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
if (!link->dhcp6_pd_address_configured || !link->dhcp6_pd_route_configured) if (link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured)
link_check_ready(link);
else
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
link_check_ready(link);
return 0; return 0;
} }
@ -809,7 +781,7 @@ static int dhcp6_remove(Link *link) {
return r; return r;
} }
static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int dhcp6_route_handler(sd_netlink *nl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
@ -817,9 +789,15 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
link->dhcp6_route_messages--; link->dhcp6_route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Failed to set unreachable route for DHCPv6 delegated subnet"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Failed to add unreachable route for DHCPv6 delegated subnet");
link_enter_failed(link);
return 1;
}
if (link->dhcp6_route_messages == 0) { if (link->dhcp6_route_messages == 0) {
log_link_debug(link, "Unreachable routes for DHCPv6 delegated subnets set"); log_link_debug(link, "Unreachable routes for DHCPv6 delegated subnets set");
@ -837,37 +815,16 @@ static int dhcp6_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
return 1; return 1;
} }
static int dhcp6_after_route_configure(Request *req, void *object) { static int dhcp6_set_unreachable_route(Link *link, const union in_addr_union *addr, uint8_t prefixlen) {
Route *route = object;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ROUTE);
assert(route);
link = req->link;
r = set_ensure_put(&link->dhcp6_routes, &route_hash_ops, route);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store unreachable route for DHCPv6 delegated subnet: %m");
set_remove(link->dhcp6_routes_old, route);
return 0;
}
static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *addr, uint8_t prefixlen) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
Request *req; Route *ret;
int r; int r;
assert(link); assert(link);
assert(addr); assert(addr);
(void) in6_addr_prefix_to_string(addr, prefixlen, &buf); (void) in_addr_prefix_to_string(AF_INET6, addr, prefixlen, &buf);
if (prefixlen == 64) { if (prefixlen == 64) {
log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated subnet %s since distributed prefix is 64", log_link_debug(link, "Not adding a blocking route for DHCPv6 delegated subnet %s since distributed prefix is 64",
@ -880,30 +837,32 @@ static int dhcp6_request_unreachable_route(Link *link, const struct in6_addr *ad
return log_oom(); return log_oom();
route->family = AF_INET6; route->family = AF_INET6;
route->dst.in6 = *addr; route->dst = *addr;
route->dst_prefixlen = prefixlen; route->dst_prefixlen = prefixlen;
route->table = link_get_dhcp_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;
r = link_has_route(link, route); r = route_configure(route, link, dhcp6_route_handler, &ret);
if (r < 0) if (r < 0)
return r; return log_link_error_errno(link, r, "Failed to set unreachable route for DHCPv6 delegated subnet %s: %m",
if (r == 0) strna(buf));
if (r > 0)
link->dhcp6_route_configured = false; link->dhcp6_route_configured = false;
r = link_request_route(link, TAKE_PTR(route), true, &link->dhcp6_route_messages, link->dhcp6_route_messages++;
dhcp6_route_handler, &req);
r = set_ensure_put(&link->dhcp6_routes, &route_hash_ops, ret);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to request unreachable route for DHCPv6 delegated subnet %s: %m", return log_link_error_errno(link, r, "Failed to store unreachable route for DHCPv6 delegated subnet %s: %m",
strna(buf)); strna(buf));
req->after_configure = dhcp6_after_route_configure; (void) set_remove(link->dhcp6_routes_old, ret);
return 0; return 0;
} }
static int dhcp6_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_t prefixlen) { static int dhcp6_pd_prefix_add(Link *link, const union in_addr_union *prefix, uint8_t prefixlen) {
_cleanup_free_ struct in_addr_prefix *p = NULL; _cleanup_free_ struct in_addr_prefix *p = NULL;
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
int r; int r;
@ -918,10 +877,10 @@ static int dhcp6_pd_prefix_add(Link *link, const struct in6_addr *prefix, uint8_
*p = (struct in_addr_prefix) { *p = (struct in_addr_prefix) {
.family = AF_INET6, .family = AF_INET6,
.prefixlen = prefixlen, .prefixlen = prefixlen,
.address.in6 = *prefix, .address = *prefix,
}; };
(void) in6_addr_prefix_to_string(prefix, prefixlen, &buf); (void) in_addr_prefix_to_string(p->family, &p->address, p->prefixlen, &buf);
log_link_full(link, log_link_full(link,
set_contains(link->dhcp6_pd_prefixes, p) ? LOG_DEBUG : set_contains(link->dhcp6_pd_prefixes, p) ? LOG_DEBUG :
@ -959,11 +918,10 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) { for (sd_dhcp6_lease_reset_pd_prefix_iter(dhcp6_link->dhcp6_lease);;) {
uint32_t lifetime_preferred, lifetime_valid; uint32_t lifetime_preferred, lifetime_valid;
struct in6_addr pd_prefix; union in_addr_union pd_prefix, prefix;
union in_addr_union prefix;
uint8_t pd_prefix_len; uint8_t pd_prefix_len;
r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix, &pd_prefix_len, r = sd_dhcp6_lease_get_pd(dhcp6_link->dhcp6_lease, &pd_prefix.in6, &pd_prefix_len,
&lifetime_preferred, &lifetime_valid); &lifetime_preferred, &lifetime_valid);
if (r < 0) if (r < 0)
break; break;
@ -974,7 +932,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
if (r == 0) if (r == 0)
continue; continue;
r = dhcp6_request_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len); r = dhcp6_set_unreachable_route(dhcp6_link, &pd_prefix, pd_prefix_len);
if (r < 0) if (r < 0)
return r; return r;
@ -989,7 +947,7 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
assert(pd_prefix_len <= 64); assert(pd_prefix_len <= 64);
prefix.in6 = pd_prefix; prefix = pd_prefix;
r = in_addr_mask(AF_INET6, &prefix, pd_prefix_len); r = in_addr_mask(AF_INET6, &prefix, pd_prefix_len);
if (r < 0) if (r < 0)
return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m"); return log_link_error_errno(dhcp6_link, r, "Failed to mask DHCPv6 PD prefix: %m");
@ -998,20 +956,20 @@ static int dhcp6_pd_prefix_acquired(Link *dhcp6_link) {
uint64_t n_prefixes = UINT64_C(1) << (64 - pd_prefix_len); uint64_t n_prefixes = UINT64_C(1) << (64 - pd_prefix_len);
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_prefix_to_string(&prefix.in6, pd_prefix_len, &buf); (void) in_addr_prefix_to_string(AF_INET6, &prefix, pd_prefix_len, &buf);
log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s", log_link_debug(dhcp6_link, "Assigning up to %" PRIu64 " prefixes from %s",
n_prefixes, strna(buf)); n_prefixes, strna(buf));
} }
dhcp6_pd_prefix_distribute(dhcp6_link, dhcp6_pd_prefix_distribute(dhcp6_link,
&prefix.in6, &prefix,
pd_prefix_len, pd_prefix_len,
lifetime_preferred, lifetime_preferred,
lifetime_valid, lifetime_valid,
true); true);
dhcp6_pd_prefix_distribute(dhcp6_link, dhcp6_pd_prefix_distribute(dhcp6_link,
&prefix.in6, &prefix,
pd_prefix_len, pd_prefix_len,
lifetime_preferred, lifetime_preferred,
lifetime_valid, lifetime_valid,
@ -1038,9 +996,16 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
link->dhcp6_address_messages--; link->dhcp6_address_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set DHCPv6 address"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set DHCPv6 address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->dhcp6_address_messages == 0) { if (link->dhcp6_address_messages == 0) {
log_link_debug(link, "DHCPv6 addresses set"); log_link_debug(link, "DHCPv6 addresses set");
@ -1067,9 +1032,8 @@ static void log_dhcp6_address(Link *link, const Address *address, char **ret) {
assert(link); assert(link);
assert(address); assert(address);
assert(address->family == AF_INET6);
(void) in6_addr_prefix_to_string(&address->in_addr.in6, address->prefixlen, &buffer); (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buffer);
if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) if (address->cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
address->cinfo.ifa_valid * USEC_PER_SEC, address->cinfo.ifa_valid * USEC_PER_SEC,
@ -1121,28 +1085,7 @@ finalize:
*ret = TAKE_PTR(buffer); *ret = TAKE_PTR(buffer);
} }
static int dhcp6_after_address_configure(Request *req, void *object) { static int dhcp6_update_address(
Address *address = object;
Link *link;
int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ADDRESS);
assert(address);
link = req->link;
r = set_ensure_put(&link->dhcp6_addresses, &address_hash_ops, address);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 address: %m");
set_remove(link->dhcp6_addresses_old, address);
return 0;
}
static int dhcp6_request_address(
Link *link, Link *link,
const struct in6_addr *ip6_addr, const struct in6_addr *ip6_addr,
uint32_t lifetime_preferred, uint32_t lifetime_preferred,
@ -1150,7 +1093,7 @@ static int dhcp6_request_address(
_cleanup_(address_freep) Address *addr = NULL; _cleanup_(address_freep) Address *addr = NULL;
_cleanup_free_ char *buffer = NULL; _cleanup_free_ char *buffer = NULL;
Request *req; Address *ret;
int r; int r;
r = address_new(&addr); r = address_new(&addr);
@ -1166,15 +1109,19 @@ static int dhcp6_request_address(
log_dhcp6_address(link, addr, &buffer); log_dhcp6_address(link, addr, &buffer);
if (address_get(link, addr, NULL) < 0) r = address_configure(addr, link, dhcp6_address_handler, &ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to set DHCPv6 address %s: %m", strna(buffer));
if (r > 0)
link->dhcp6_address_configured = false; link->dhcp6_address_configured = false;
r = link_request_address(link, TAKE_PTR(addr), true, &link->dhcp6_address_messages, link->dhcp6_address_messages++;
dhcp6_address_handler, &req);
if (r < 0)
return log_link_error_errno(link, r, "Failed to request DHCPv6 address %s: %m", strna(buffer));
req->after_configure = dhcp6_after_address_configure; r = set_ensure_put(&link->dhcp6_addresses, &address_hash_ops, ret);
if (r < 0)
return log_link_error_errno(link, r, "Failed to store DHCPv6 address %s: %m", strna(buffer));
(void) set_remove(link->dhcp6_addresses_old, ret);
return 0; return 0;
} }
@ -1197,7 +1144,7 @@ static int dhcp6_address_acquired(Link *link) {
if (r < 0) if (r < 0)
break; break;
r = dhcp6_request_address(link, &ip6_addr, lifetime_preferred, lifetime_valid); r = dhcp6_update_address(link, &ip6_addr, lifetime_preferred, lifetime_valid);
if (r < 0) if (r < 0)
return r; return r;
} }
@ -1277,10 +1224,11 @@ static int dhcp6_lease_ip_acquired(sd_dhcp6_client *client, Link *link) {
if (r < 0) if (r < 0)
return r; return r;
if (!link->dhcp6_address_configured || !link->dhcp6_route_configured) if (link->dhcp6_address_configured && link->dhcp6_route_configured)
link_check_ready(link);
else
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
link_check_ready(link);
return 0; return 0;
} }
@ -1350,7 +1298,7 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
} }
} }
int dhcp6_request_information(Link *link, int ir) { int dhcp6_request_address(Link *link, int ir) {
int r, inf_req, pd; int r, inf_req, pd;
bool running; bool running;
@ -1428,7 +1376,7 @@ int dhcp6_start(Link *link) {
log_link_debug(link, "Acquiring DHCPv6 lease"); log_link_debug(link, "Acquiring DHCPv6 lease");
return dhcp6_request_information(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST); return dhcp6_request_address(link, link->network->dhcp6_without_ra == DHCP6_CLIENT_START_MODE_INFORMATION_REQUEST);
} }
int dhcp6_request_prefix_delegation(Link *link) { int dhcp6_request_prefix_delegation(Link *link) {
@ -1901,8 +1849,7 @@ int config_parse_dhcp6_pd_token(
void *data, void *data,
void *userdata) { void *userdata) {
struct in6_addr *addr = data; union in_addr_union *addr = data, tmp;
union in_addr_union tmp;
int r; int r;
assert(filename); assert(filename);
@ -1911,7 +1858,7 @@ int config_parse_dhcp6_pd_token(
assert(data); assert(data);
if (isempty(rvalue)) { if (isempty(rvalue)) {
*addr = (struct in6_addr) {}; *addr = IN_ADDR_NULL;
return 0; return 0;
} }
@ -1928,7 +1875,7 @@ int config_parse_dhcp6_pd_token(
return 0; return 0;
} }
*addr = tmp.in6; *addr = tmp;
return 0; return 0;
} }

View File

@ -32,7 +32,7 @@ int dhcp6_pd_remove(Link *link);
int dhcp6_configure(Link *link); int dhcp6_configure(Link *link);
int dhcp6_update_mac(Link *link); int dhcp6_update_mac(Link *link);
int dhcp6_start(Link *link); int dhcp6_start(Link *link);
int dhcp6_request_information(Link *link, int ir); int dhcp6_request_address(Link *link, int ir);
int dhcp6_request_prefix_delegation(Link *link); int dhcp6_request_prefix_delegation(Link *link);
int link_serialize_dhcp6_client(Link *link, FILE *f); int link_serialize_dhcp6_client(Link *link, FILE *f);

View File

@ -8,55 +8,39 @@
#include "networkd-ipv4ll.h" #include "networkd-ipv4ll.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-queue.h"
#include "parse-util.h" #include "parse-util.h"
static int address_new_from_ipv4ll(Link *link, Address **ret) {
_cleanup_(address_freep) Address *address = NULL;
struct in_addr addr;
int r;
assert(link);
assert(link->ipv4ll);
assert(ret);
r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
if (r < 0)
return r;
r = address_new(&address);
if (r < 0)
return -ENOMEM;
address->family = AF_INET;
address->in_addr.in = addr;
address->prefixlen = 16;
address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(UINT32_C(0xffffffff) >> address->prefixlen);
address->scope = RT_SCOPE_LINK;
address->route_metric = IPV4LL_ROUTE_METRIC;
*ret = TAKE_PTR(address);
return 0;
}
static int ipv4ll_address_lost(Link *link) { static int ipv4ll_address_lost(Link *link) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *address = NULL;
struct in_addr addr;
int r; int r;
assert(link); assert(link);
link->ipv4ll_address_configured = false; link->ipv4ll_address_configured = false;
r = address_new_from_ipv4ll(link, &address); r = sd_ipv4ll_get_address(link->ipv4ll, &addr);
if (r == -ENOENT) if (r < 0)
return 0; return 0;
log_link_debug(link, "IPv4 link-local release "IPV4_ADDRESS_FMT_STR, IPV4_ADDRESS_FMT_VAL(addr));
r = address_new(&address);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate address: %m");
address->family = AF_INET;
address->in_addr.in = addr;
address->prefixlen = 16;
address->scope = RT_SCOPE_LINK;
r = address_remove(address, link, NULL);
if (r < 0) if (r < 0)
return r; return r;
log_link_debug(link, "IPv4 link-local release "IPV4_ADDRESS_FMT_STR, link_check_ready(link);
IPV4_ADDRESS_FMT_VAL(address->in_addr.in));
return address_remove(address, link, NULL); return 0;
} }
static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
@ -65,9 +49,13 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
assert(link); assert(link);
assert(!link->ipv4ll_address_configured); assert(!link->ipv4ll_address_configured);
r = address_configure_handler_internal(rtnl, m, link, "Could not set ipv4ll address"); r = sd_netlink_message_get_errno(m);
if (r <= 0) if (r < 0 && r != -EEXIST) {
return r; log_link_message_warning_errno(link, m, r, "could not set ipv4ll address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
link->ipv4ll_address_configured = true; link->ipv4ll_address_configured = true;
link_check_ready(link); link_check_ready(link);
@ -76,7 +64,8 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
} }
static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
_cleanup_(address_freep) Address *address = NULL; _cleanup_(address_freep) Address *ll_addr = NULL;
struct in_addr address;
int r; int r;
assert(ll); assert(ll);
@ -84,16 +73,31 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
link->ipv4ll_address_configured = false; link->ipv4ll_address_configured = false;
r = address_new_from_ipv4ll(link, &address); r = sd_ipv4ll_get_address(ll, &address);
if (r == -ENOENT) if (r == -ENOENT)
return 0; return 0;
if (r < 0) else if (r < 0)
return r; return r;
log_link_debug(link, "IPv4 link-local claim "IPV4_ADDRESS_FMT_STR, log_link_debug(link, "IPv4 link-local claim "IPV4_ADDRESS_FMT_STR,
IPV4_ADDRESS_FMT_VAL(address->in_addr.in)); IPV4_ADDRESS_FMT_VAL(address));
return link_request_address(link, TAKE_PTR(address), true, NULL, ipv4ll_address_handler, NULL); r = address_new(&ll_addr);
if (r < 0)
return r;
ll_addr->family = AF_INET;
ll_addr->in_addr.in = address;
ll_addr->prefixlen = 16;
ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
ll_addr->scope = RT_SCOPE_LINK;
ll_addr->route_metric = IPV4LL_ROUTE_METRIC;
r = address_configure(ll_addr, link, ipv4ll_address_handler, NULL);
if (r < 0)
return r;
return 0;
} }
static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) { static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) {

View File

@ -33,7 +33,6 @@
#include "networkd-dhcp6.h" #include "networkd-dhcp6.h"
#include "networkd-fdb.h" #include "networkd-fdb.h"
#include "networkd-ipv4ll.h" #include "networkd-ipv4ll.h"
#include "networkd-ipv6-proxy-ndp.h"
#include "networkd-link-bus.h" #include "networkd-link-bus.h"
#include "networkd-link.h" #include "networkd-link.h"
#include "networkd-lldp-tx.h" #include "networkd-lldp-tx.h"
@ -42,12 +41,11 @@
#include "networkd-ndisc.h" #include "networkd-ndisc.h"
#include "networkd-neighbor.h" #include "networkd-neighbor.h"
#include "networkd-nexthop.h" #include "networkd-nexthop.h"
#include "networkd-queue.h" #include "networkd-sriov.h"
#include "networkd-sysctl.h"
#include "networkd-radv.h" #include "networkd-radv.h"
#include "networkd-routing-policy-rule.h" #include "networkd-routing-policy-rule.h"
#include "networkd-sriov.h"
#include "networkd-state-file.h" #include "networkd-state-file.h"
#include "networkd-sysctl.h"
#include "networkd-wifi.h" #include "networkd-wifi.h"
#include "set.h" #include "set.h"
#include "socket-util.h" #include "socket-util.h"
@ -135,25 +133,6 @@ bool link_ipv6_enabled(Link *link) {
return false; return false;
} }
bool link_is_ready_to_configure(Link *link, bool allow_unmanaged) {
assert(link);
if (!link->network || link->network->unmanaged) {
if (!allow_unmanaged)
return false;
return link_has_carrier(link);
}
if (!IN_SET(link->state, LINK_STATE_CONFIGURING, LINK_STATE_CONFIGURED))
return false;
if (!link_has_carrier(link) && !link->network->configure_without_carrier)
return false;
return true;
}
static bool link_is_enslaved(Link *link) { static bool link_is_enslaved(Link *link) {
if (link->flags & IFF_SLAVE) if (link->flags & IFF_SLAVE)
/* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */ /* Even if the link is not managed by networkd, honor IFF_SLAVE flag. */
@ -794,9 +773,12 @@ void link_check_ready(Link *link) {
return; return;
} }
if (!link->static_addresses_configured) if (!link->addresses_configured)
return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__); return (void) log_link_debug(link, "%s(): static addresses are not configured.", __func__);
if (!link->neighbors_configured)
return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__);
SET_FOREACH(a, link->addresses) SET_FOREACH(a, link->addresses)
if (!address_is_ready(a)) { if (!address_is_ready(a)) {
_cleanup_free_ char *str = NULL; _cleanup_free_ char *str = NULL;
@ -805,16 +787,13 @@ void link_check_ready(Link *link) {
return (void) log_link_debug(link, "%s(): an address %s is not ready.", __func__, strna(str)); return (void) log_link_debug(link, "%s(): an address %s is not ready.", __func__, strna(str));
} }
if (!link->static_neighbors_configured) if (!link->static_routes_configured)
return (void) log_link_debug(link, "%s(): static neighbors are not configured.", __func__); return (void) log_link_debug(link, "%s(): static routes are not configured.", __func__);
if (!link->static_nexthops_configured) if (!link->static_nexthops_configured)
return (void) log_link_debug(link, "%s(): static nexthops are not configured.", __func__); return (void) log_link_debug(link, "%s(): static nexthops are not configured.", __func__);
if (!link->static_routes_configured) if (!link->routing_policy_rules_configured)
return (void) log_link_debug(link, "%s(): static routes are not configured.", __func__);
if (!link->static_routing_policy_rules_configured)
return (void) log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__); return (void) log_link_debug(link, "%s(): static routing policy rules are not configured.", __func__);
if (!link->tc_configured) if (!link->tc_configured)
@ -878,6 +857,15 @@ static int link_set_static_configs(Link *link) {
assert(link->network); assert(link->network);
assert(link->state != _LINK_STATE_INVALID); assert(link->state != _LINK_STATE_INVALID);
/* Reset all *_configured flags we are configuring. */
link->request_static_addresses = false;
link->addresses_configured = false;
link->addresses_ready = false;
link->neighbors_configured = false;
link->static_routes_configured = false;
link->static_nexthops_configured = false;
link->routing_policy_rules_configured = false;
r = link_set_bridge_fdb(link); r = link_set_bridge_fdb(link);
if (r < 0) if (r < 0)
return r; return r;
@ -886,7 +874,11 @@ static int link_set_static_configs(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
r = link_set_ipv6_proxy_ndp_addresses(link); r = link_set_neighbors(link);
if (r < 0)
return r;
r = link_set_addresses(link);
if (r < 0) if (r < 0)
return r; return r;
@ -894,23 +886,8 @@ static int link_set_static_configs(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
r = link_request_static_addresses(link); /* now that we can figure out a default address for the dhcp server, start it */
if (r < 0) r = dhcp4_server_configure(link);
return r;
r = link_request_static_neighbors(link);
if (r < 0)
return r;
r = link_request_static_nexthops(link, false);
if (r < 0)
return r;
r = link_request_static_routes(link, false);
if (r < 0)
return r;
r = link_request_static_routing_policy_rules(link);
if (r < 0) if (r < 0)
return r; return r;
@ -2051,20 +2028,20 @@ static int link_drop_foreign_config(Link *link) {
assert(link); assert(link);
assert(link->manager); assert(link->manager);
r = link_drop_foreign_routes(link); r = link_drop_foreign_addresses(link);
k = link_drop_foreign_nexthops(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_foreign_addresses(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_foreign_neighbors(link); k = link_drop_foreign_neighbors(link);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
r = k; r = k;
k = link_drop_foreign_routes(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_foreign_nexthops(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_foreign_routing_policy_rules(link->manager); k = manager_drop_foreign_routing_policy_rules(link->manager);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
r = k; r = k;
@ -2078,20 +2055,20 @@ static int link_drop_config(Link *link) {
assert(link); assert(link);
assert(link->manager); assert(link->manager);
r = link_drop_routes(link); r = link_drop_addresses(link);
k = link_drop_nexthops(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_addresses(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_neighbors(link); k = link_drop_neighbors(link);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
r = k; r = k;
k = link_drop_routes(link);
if (k < 0 && r >= 0)
r = k;
k = link_drop_nexthops(link);
if (k < 0 && r >= 0)
r = k;
k = manager_drop_routing_policy_rules(link->manager, link); k = manager_drop_routing_policy_rules(link->manager, link);
if (k < 0 && r >= 0) if (k < 0 && r >= 0)
r = k; r = k;
@ -2101,17 +2078,6 @@ static int link_drop_config(Link *link) {
return r; return r;
} }
static void link_drop_requests(Link *link) {
Request *req;
assert(link);
assert(link->manager);
ORDERED_SET_FOREACH(req, link->manager->request_queue)
if (req->link == link)
request_drop(req);
}
int link_configure(Link *link) { int link_configure(Link *link) {
int r; int r;
@ -2266,8 +2232,6 @@ static int link_reconfigure_internal(Link *link, sd_netlink_message *m, bool for
if (r < 0) if (r < 0)
return r; return r;
link_drop_requests(link);
r = link_drop_config(link); r = link_drop_config(link);
if (r < 0) if (r < 0)
return r; return r;
@ -2700,8 +2664,6 @@ static int link_carrier_lost(Link *link) {
return r; return r;
} }
link_drop_requests(link);
r = link_drop_config(link); r = link_drop_config(link);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -78,16 +78,13 @@ typedef struct Link {
LinkAddressState ipv4_address_state; LinkAddressState ipv4_address_state;
LinkAddressState ipv6_address_state; LinkAddressState ipv6_address_state;
unsigned address_label_messages; unsigned address_messages;
unsigned static_address_messages;
unsigned static_neighbor_messages;
unsigned static_nexthop_messages;
unsigned static_route_messages;
unsigned static_routing_policy_rule_messages;
unsigned address_remove_messages; unsigned address_remove_messages;
unsigned neighbor_remove_messages; unsigned address_label_messages;
unsigned nexthop_remove_messages; unsigned neighbor_messages;
unsigned route_remove_messages; unsigned route_messages;
unsigned nexthop_messages;
unsigned routing_policy_rule_messages;
unsigned tc_messages; unsigned tc_messages;
unsigned sr_iov_messages; unsigned sr_iov_messages;
unsigned enslaving; unsigned enslaving;
@ -121,11 +118,13 @@ typedef struct Link {
sd_ipv4ll *ipv4ll; sd_ipv4ll *ipv4ll;
bool ipv4ll_address_configured:1; bool ipv4ll_address_configured:1;
bool static_addresses_configured:1; bool request_static_addresses:1;
bool static_neighbors_configured:1; bool addresses_configured:1;
bool static_nexthops_configured:1; bool addresses_ready:1;
bool neighbors_configured:1;
bool static_routes_configured:1; bool static_routes_configured:1;
bool static_routing_policy_rules_configured:1; bool static_nexthops_configured:1;
bool routing_policy_rules_configured:1;
bool tc_configured:1; bool tc_configured:1;
bool sr_iov_configured:1; bool sr_iov_configured:1;
bool setting_mtu:1; bool setting_mtu:1;
@ -200,8 +199,6 @@ typedef struct Link {
typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*); typedef int (*link_netlink_message_handler_t)(sd_netlink*, sd_netlink_message*, Link*);
bool link_is_ready_to_configure(Link *link, bool allow_unmanaged);
void link_ntp_settings_clear(Link *link); void link_ntp_settings_clear(Link *link);
void link_dns_settings_clear(Link *link); void link_dns_settings_clear(Link *link);
Link *link_unref(Link *link); Link *link_unref(Link *link);

View File

@ -34,7 +34,6 @@
#include "networkd-neighbor.h" #include "networkd-neighbor.h"
#include "networkd-network-bus.h" #include "networkd-network-bus.h"
#include "networkd-nexthop.h" #include "networkd-nexthop.h"
#include "networkd-queue.h"
#include "networkd-routing-policy-rule.h" #include "networkd-routing-policy-rule.h"
#include "networkd-speed-meter.h" #include "networkd-speed-meter.h"
#include "networkd-state-file.h" #include "networkd-state-file.h"
@ -407,10 +406,6 @@ int manager_new(Manager **ret) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_event_add_post(m->event, NULL, manager_process_requests, m);
if (r < 0)
return r;
r = manager_connect_rtnl(m); r = manager_connect_rtnl(m);
if (r < 0) if (r < 0)
return r; return r;
@ -451,8 +446,6 @@ Manager* manager_free(Manager *m) {
HASHMAP_FOREACH(link, m->links) HASHMAP_FOREACH(link, m->links)
(void) link_stop_engines(link, true); (void) link_stop_engines(link, true);
m->request_queue = ordered_set_free_with_destructor(m->request_queue, request_free);
m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free); m->dhcp6_prefixes = hashmap_free_with_destructor(m->dhcp6_prefixes, dhcp6_pd_free);
m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free); m->dhcp6_pd_prefixes = set_free_with_destructor(m->dhcp6_pd_prefixes, dhcp6_pd_free);

View File

@ -62,7 +62,6 @@ struct Manager {
char* dynamic_hostname; char* dynamic_hostname;
char* dynamic_timezone; char* dynamic_timezone;
unsigned routing_policy_rule_remove_messages;
Set *rules; Set *rules;
Set *rules_foreign; Set *rules_foreign;
@ -70,12 +69,10 @@ struct Manager {
Hashmap *nexthops_by_id; Hashmap *nexthops_by_id;
/* Manager stores nexthops without RTA_OIF attribute. */ /* Manager stores nexthops without RTA_OIF attribute. */
unsigned nexthop_remove_messages;
Set *nexthops; Set *nexthops;
Set *nexthops_foreign; Set *nexthops_foreign;
/* Manager stores routes without RTA_OIF attribute. */ /* Manager stores routes without RTA_OIF attribute. */
unsigned route_remove_messages;
Set *routes; Set *routes;
Set *routes_foreign; Set *routes_foreign;
@ -94,8 +91,6 @@ struct Manager {
bool bridge_mdb_on_master_not_supported; bool bridge_mdb_on_master_not_supported;
FirewallContext *fw_ctx; FirewallContext *fw_ctx;
OrderedSet *request_queue;
}; };
int manager_new(Manager **ret); int manager_new(Manager **ret);

View File

@ -15,7 +15,6 @@
#include "networkd-dhcp6.h" #include "networkd-dhcp6.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-ndisc.h" #include "networkd-ndisc.h"
#include "networkd-queue.h"
#include "networkd-state-file.h" #include "networkd-state-file.h"
#include "string-table.h" #include "string-table.h"
#include "string-util.h" #include "string-util.h"
@ -90,7 +89,6 @@ static int ndisc_address_callback(Address *address) {
assert(address); assert(address);
assert(address->link); assert(address->link);
assert(address->family == AF_INET6);
SET_FOREACH(n, address->link->ndisc_addresses) SET_FOREACH(n, address->link->ndisc_addresses)
if (n->address == address) { if (n->address == address) {
@ -101,7 +99,7 @@ static int ndisc_address_callback(Address *address) {
if (in6_addr_is_null(&router)) { if (in6_addr_is_null(&router)) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_prefix_to_string(&address->in_addr.in6, address->prefixlen, &buf); (void) in_addr_prefix_to_string(address->family, &address->in_addr, address->prefixlen, &buf);
log_link_debug(address->link, "%s is called for %s, but it is already removed, ignoring.", log_link_debug(address->link, "%s is called for %s, but it is already removed, ignoring.",
__func__, strna(buf)); __func__, strna(buf));
return 0; return 0;
@ -109,7 +107,7 @@ static int ndisc_address_callback(Address *address) {
/* Make this called only once */ /* Make this called only once */
SET_FOREACH(n, address->link->ndisc_addresses) SET_FOREACH(n, address->link->ndisc_addresses)
if (in6_addr_equal(&n->router, &router)) if (IN6_ARE_ADDR_EQUAL(&n->router, &router))
n->address->callback = NULL; n->address->callback = NULL;
return ndisc_remove_old_one(address->link, &router, true); return ndisc_remove_old_one(address->link, &router, true);
@ -133,7 +131,7 @@ static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool
return 0; return 0;
SET_FOREACH(na, link->ndisc_addresses) SET_FOREACH(na, link->ndisc_addresses)
if (!na->marked && in6_addr_equal(&na->router, router)) { if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) {
set_callback = true; set_callback = true;
break; break;
} }
@ -147,13 +145,13 @@ static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool
if (set_callback) { if (set_callback) {
SET_FOREACH(na, link->ndisc_addresses) SET_FOREACH(na, link->ndisc_addresses)
if (!na->marked && in6_addr_equal(&na->router, router)) if (!na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router))
na->address->callback = ndisc_address_callback; na->address->callback = ndisc_address_callback;
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_to_string(router, &buf); (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) router, &buf);
log_link_debug(link, "No SLAAC address obtained from %s is ready. " log_link_debug(link, "No SLAAC address obtained from %s is ready. "
"The old NDisc information will be removed later.", "The old NDisc information will be removed later.",
strna(buf)); strna(buf));
@ -165,32 +163,32 @@ static int ndisc_remove_old_one(Link *link, const struct in6_addr *router, bool
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_to_string(router, &buf); (void) in_addr_to_string(AF_INET6, (const union in_addr_union*) router, &buf);
log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf)); log_link_debug(link, "Removing old NDisc information obtained from %s.", strna(buf));
} }
SET_FOREACH(na, link->ndisc_addresses) SET_FOREACH(na, link->ndisc_addresses)
if (na->marked && in6_addr_equal(&na->router, router)) { if (na->marked && IN6_ARE_ADDR_EQUAL(&na->router, router)) {
k = address_remove(na->address, link, NULL); k = address_remove(na->address, link, NULL);
if (k < 0) if (k < 0)
r = k; r = k;
} }
SET_FOREACH(nr, link->ndisc_routes) SET_FOREACH(nr, link->ndisc_routes)
if (nr->marked && in6_addr_equal(&nr->router, router)) { if (nr->marked && IN6_ARE_ADDR_EQUAL(&nr->router, router)) {
k = route_remove(nr->route, NULL, link, NULL); k = route_remove(nr->route, NULL, link, NULL);
if (k < 0) if (k < 0)
r = k; r = k;
} }
SET_FOREACH(rdnss, link->ndisc_rdnss) SET_FOREACH(rdnss, link->ndisc_rdnss)
if (rdnss->marked && in6_addr_equal(&rdnss->router, router)) { if (rdnss->marked && IN6_ARE_ADDR_EQUAL(&rdnss->router, router)) {
free(set_remove(link->ndisc_rdnss, rdnss)); free(set_remove(link->ndisc_rdnss, rdnss));
updated = true; updated = true;
} }
SET_FOREACH(dnssl, link->ndisc_dnssl) SET_FOREACH(dnssl, link->ndisc_dnssl)
if (dnssl->marked && in6_addr_equal(&dnssl->router, router)) { if (dnssl->marked && IN6_ARE_ADDR_EQUAL(&dnssl->router, router)) {
free(set_remove(link->ndisc_dnssl, dnssl)); free(set_remove(link->ndisc_dnssl, dnssl));
updated = true; updated = true;
} }
@ -306,9 +304,15 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
link->ndisc_routes_messages--; link->ndisc_routes_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set NDisc route"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_error_errno(link, m, r, "Could not set NDisc route");
link_enter_failed(link);
return 1;
}
if (link->ndisc_routes_messages == 0) { if (link->ndisc_routes_messages == 0) {
log_link_debug(link, "NDisc routes set."); log_link_debug(link, "NDisc routes set.");
@ -326,23 +330,24 @@ static int ndisc_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *li
return 1; return 1;
} }
static int ndisc_after_route_configure(Request *req, void *object) { static int ndisc_route_configure(Route *route, Link *link, sd_ndisc_router *rt) {
_cleanup_free_ NDiscRoute *nr = NULL; _cleanup_free_ NDiscRoute *nr = NULL;
NDiscRoute *nr_exist; NDiscRoute *nr_exist;
struct in6_addr router; struct in6_addr router;
Route *route = object; Route *ret;
sd_ndisc_router *rt;
Link *link;
int r; int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ROUTE);
assert(req->userdata);
assert(route); assert(route);
assert(link);
assert(rt);
link = req->link; r = route_configure(route, link, ndisc_route_handler, &ret);
rt = req->userdata; if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc route: %m");
if (r > 0)
link->ndisc_routes_configured = false;
link->ndisc_routes_messages++;
r = sd_ndisc_router_get_address(rt, &router); r = sd_ndisc_router_get_address(rt, &router);
if (r < 0) if (r < 0)
@ -354,7 +359,7 @@ static int ndisc_after_route_configure(Request *req, void *object) {
*nr = (NDiscRoute) { *nr = (NDiscRoute) {
.router = router, .router = router,
.route = route, .route = ret,
}; };
nr_exist = set_get(link->ndisc_routes, nr); nr_exist = set_get(link->ndisc_routes, nr);
@ -373,39 +378,6 @@ static int ndisc_after_route_configure(Request *req, void *object) {
return 0; return 0;
} }
static void ndisc_request_on_free(Request *req) {
assert(req);
sd_ndisc_router_unref(req->userdata);
}
static int ndisc_request_route(Route *in, Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = in;
Request *req;
int r;
assert(route);
assert(link);
assert(rt);
r = link_has_route(link, route);
if (r < 0)
return r;
if (r == 0)
link->ndisc_routes_configured = false;
r = link_request_route(link, TAKE_PTR(route), true, &link->ndisc_routes_messages,
ndisc_route_handler, &req);
if (r < 0)
return r;
req->userdata = sd_ndisc_router_ref(rt);
req->after_configure = ndisc_after_route_configure;
req->on_free = ndisc_request_on_free;
return 0;
}
static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) { static void ndisc_address_hash_func(const NDiscAddress *x, struct siphash *state) {
address_hash_func(x->address, state); address_hash_func(x->address, state);
} }
@ -429,9 +401,16 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
link->ndisc_addresses_messages--; link->ndisc_addresses_messages--;
r = address_configure_handler_internal(rtnl, m, link, "Could not set NDisc address"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_error_errno(link, m, r, "Could not set NDisc address");
link_enter_failed(link);
return 1;
} else if (r >= 0)
(void) manager_rtnl_process_address(rtnl, m, link->manager);
if (link->ndisc_addresses_messages == 0) { if (link->ndisc_addresses_messages == 0) {
log_link_debug(link, "NDisc SLAAC addresses set."); log_link_debug(link, "NDisc SLAAC addresses set.");
@ -447,23 +426,24 @@ static int ndisc_address_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *
return 1; return 1;
} }
static int ndisc_after_address_configure(Request *req, void *object) { static int ndisc_address_configure(Address *address, Link *link, sd_ndisc_router *rt) {
_cleanup_free_ NDiscAddress *na = NULL; _cleanup_free_ NDiscAddress *na = NULL;
NDiscAddress *na_exist; NDiscAddress *na_exist;
struct in6_addr router; struct in6_addr router;
sd_ndisc_router *rt; Address *ret;
Address *address = object;
Link *link;
int r; int r;
assert(req);
assert(req->link);
assert(req->type == REQUEST_TYPE_ADDRESS);
assert(req->userdata);
assert(address); assert(address);
assert(link);
assert(rt);
link = req->link; r = address_configure(address, link, ndisc_address_handler, &ret);
rt = req->userdata; if (r < 0)
return log_link_error_errno(link, r, "Failed to set NDisc SLAAC address: %m");
if (r > 0)
link->ndisc_addresses_configured = false;
link->ndisc_addresses_messages++;
r = sd_ndisc_router_get_address(rt, &router); r = sd_ndisc_router_get_address(rt, &router);
if (r < 0) if (r < 0)
@ -475,7 +455,7 @@ static int ndisc_after_address_configure(Request *req, void *object) {
*na = (NDiscAddress) { *na = (NDiscAddress) {
.router = router, .router = router,
.address = address, .address = ret,
}; };
na_exist = set_get(link->ndisc_addresses, na); na_exist = set_get(link->ndisc_addresses, na);
@ -494,33 +474,9 @@ static int ndisc_after_address_configure(Request *req, void *object) {
return 0; return 0;
} }
static int ndisc_request_address(Address *in, Link *link, sd_ndisc_router *rt) {
_cleanup_(address_freep) Address *address = in;
Request *req;
int r;
assert(address);
assert(link);
assert(rt);
if (address_get(link, address, NULL) < 0)
link->ndisc_addresses_configured = false;
r = link_request_address(link, TAKE_PTR(address), true, &link->ndisc_addresses_messages,
ndisc_address_handler, &req);
if (r < 0)
return r;
req->userdata = sd_ndisc_router_ref(rt);
req->after_configure = ndisc_after_address_configure;
req->on_free = ndisc_request_on_free;
return 0;
}
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; union in_addr_union gateway;
uint16_t lifetime; uint16_t lifetime;
unsigned preference; unsigned preference;
uint32_t table, mtu; uint32_t table, mtu;
@ -537,17 +493,17 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
if (lifetime == 0) /* not a default router */ if (lifetime == 0) /* not a default router */
return 0; return 0;
r = sd_ndisc_router_get_address(rt, &gateway); r = sd_ndisc_router_get_address(rt, &gateway.in6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
if (link_has_ipv6_address(link, &gateway) > 0) { if (link_has_ipv6_address(link, &gateway.in6) > 0) {
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buffer = NULL; _cleanup_free_ char *buffer = NULL;
(void) in6_addr_to_string(&gateway, &buffer); (void) in_addr_to_string(AF_INET6, &gateway, &buffer);
log_link_debug(link, "No NDisc route added, gateway %s matches local address", log_link_debug(link, "No NDisc route added, gateway %s matches local address",
strna(buffer)); strnull(buffer));
} }
return 0; return 0;
} }
@ -578,13 +534,13 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
route->protocol = RTPROT_RA; 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 = gateway;
route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC); route->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
route->mtu = mtu; route->mtu = mtu;
r = ndisc_request_route(TAKE_PTR(route), link, rt); r = ndisc_route_configure(route, link, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not request default route: %m"); return log_link_error_errno(link, r, "Could not set default route: %m");
Route *route_gw; Route *route_gw;
HASHMAP_FOREACH(route_gw, link->network->routes_by_section) { HASHMAP_FOREACH(route_gw, link->network->routes_by_section) {
@ -594,26 +550,22 @@ static int ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
if (route_gw->gw_family != AF_INET6) if (route_gw->gw_family != AF_INET6)
continue; continue;
r = route_dup(route_gw, &route); route_gw->gw = gateway;
if (r < 0) if (!route_gw->table_set)
return r; route_gw->table = table;
if (!route_gw->priority_set)
route_gw->priority = link->network->ipv6_accept_ra_route_metric;
if (!route_gw->protocol_set)
route_gw->protocol = RTPROT_RA;
if (!route_gw->pref_set)
route_gw->pref = preference;
route_gw->lifetime = usec_add(time_now, lifetime * USEC_PER_SEC);
if (route_gw->mtu == 0)
route_gw->mtu = mtu;
route->gw.in6 = gateway; r = ndisc_route_configure(route_gw, link, rt);
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);
if (route->mtu == 0)
route->mtu = mtu;
r = ndisc_request_route(TAKE_PTR(route), link, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not request gateway: %m"); return log_link_error_errno(link, r, "Could not set gateway: %m");
} }
return 0; return 0;
@ -698,7 +650,7 @@ static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address,
_cleanup_free_ struct in6_addr *new_address = NULL; _cleanup_free_ struct in6_addr *new_address = NULL;
if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE if (j->address_generation_type == IPV6_TOKEN_ADDRESS_GENERATION_PREFIXSTABLE
&& (in6_addr_is_null(&j->prefix) || in6_addr_equal(&j->prefix, address))) { && (in6_addr_is_null(&j->prefix) || IN6_ARE_ADDR_EQUAL(&j->prefix, address))) {
/* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop /* While this loop uses dad_counter and a retry limit as specified in RFC 7217, the loop
* does not actually attempt Duplicate Address Detection; the counter will be incremented * does not actually attempt Duplicate Address Detection; the counter will be incremented
* only when the address generation algorithm produces an invalid address, and the loop * only when the address generation algorithm produces an invalid address, and the loop
@ -757,6 +709,7 @@ static int ndisc_router_generate_addresses(Link *link, struct in6_addr *address,
static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining; uint32_t lifetime_valid, lifetime_preferred, lifetime_remaining;
_cleanup_set_free_free_ Set *addresses = NULL; _cleanup_set_free_free_ Set *addresses = NULL;
_cleanup_(address_freep) Address *address = NULL;
struct in6_addr addr, *a; struct in6_addr addr, *a;
unsigned prefixlen; unsigned prefixlen;
usec_t time_now; usec_t time_now;
@ -793,18 +746,18 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
if (r < 0) if (r < 0)
return r; return r;
r = address_new(&address);
if (r < 0)
return log_oom();
address->family = AF_INET6;
address->prefixlen = prefixlen;
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
address->cinfo.ifa_prefered = lifetime_preferred;
SET_FOREACH(a, addresses) { SET_FOREACH(a, addresses) {
_cleanup_(address_freep) Address *address = NULL;
Address *existing_address; Address *existing_address;
r = address_new(&address);
if (r < 0)
return log_oom();
address->family = AF_INET6;
address->prefixlen = prefixlen;
address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR;
address->cinfo.ifa_prefered = lifetime_preferred;
address->in_addr.in6 = *a; address->in_addr.in6 = *a;
/* see RFC4862 section 5.5.3.e */ /* see RFC4862 section 5.5.3.e */
@ -825,9 +778,9 @@ static int ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *r
if (address->cinfo.ifa_valid == 0) if (address->cinfo.ifa_valid == 0)
continue; continue;
r = ndisc_request_address(TAKE_PTR(address), link, rt); r = ndisc_address_configure(address, link, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not request SLAAC address: %m"); return log_link_error_errno(link, r, "Could not set SLAAC address: %m");
} }
return 0; return 0;
@ -871,16 +824,16 @@ static int ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m"); return log_link_error_errno(link, r, "Failed to get prefix address: %m");
r = ndisc_request_route(TAKE_PTR(route), link, rt); r = ndisc_route_configure(route, link, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not request prefix route: %m");; return log_link_error_errno(link, r, "Could not set prefix route: %m");;
return 0; return 0;
} }
static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
struct in6_addr gateway, dst; union in_addr_union gateway, dst;
uint32_t lifetime; uint32_t lifetime;
unsigned preference, prefixlen; unsigned preference, prefixlen;
usec_t time_now; usec_t time_now;
@ -895,35 +848,35 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
if (lifetime == 0) if (lifetime == 0)
return 0; return 0;
r = sd_ndisc_router_route_get_address(rt, &dst); r = sd_ndisc_router_route_get_address(rt, &dst.in6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get route address: %m"); return log_link_error_errno(link, r, "Failed to get route address: %m");
if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) && if ((!set_isempty(link->network->ndisc_allow_listed_route_prefix) &&
!set_contains(link->network->ndisc_allow_listed_route_prefix, &dst)) || !set_contains(link->network->ndisc_allow_listed_route_prefix, &dst.in6)) ||
set_contains(link->network->ndisc_deny_listed_route_prefix, &dst)) { set_contains(link->network->ndisc_deny_listed_route_prefix, &dst.in6)) {
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_to_string(&dst, &buf); (void) in_addr_to_string(AF_INET6, &dst, &buf);
if (!set_isempty(link->network->ndisc_allow_listed_route_prefix)) if (!set_isempty(link->network->ndisc_allow_listed_route_prefix))
log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strna(buf)); log_link_debug(link, "Route prefix '%s' is not in allow list, ignoring", strnull(buf));
else else
log_link_debug(link, "Route prefix '%s' is in deny list, ignoring", strna(buf)); log_link_debug(link, "Route prefix '%s' is in deny list, ignoring", strnull(buf));
} }
return 0; return 0;
} }
r = sd_ndisc_router_get_address(rt, &gateway); r = sd_ndisc_router_get_address(rt, &gateway.in6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m"); return log_link_error_errno(link, r, "Failed to get gateway address from RA: %m");
if (link_has_ipv6_address(link, &gateway) > 0) { if (link_has_ipv6_address(link, &gateway.in6) > 0) {
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_to_string(&gateway, &buf); (void) in_addr_to_string(AF_INET6, &gateway, &buf);
log_link_debug(link, "Advertised route gateway %s is local to the link, ignoring route", strna(buf)); log_link_debug(link, "Advertised route gateway, %s, is local to the link, ignoring route", strnull(buf));
} }
return 0; return 0;
} }
@ -949,15 +902,15 @@ static int ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
route->priority = link->network->ipv6_accept_ra_route_metric; route->priority = link->network->ipv6_accept_ra_route_metric;
route->protocol = RTPROT_RA; route->protocol = RTPROT_RA;
route->pref = preference; route->pref = preference;
route->gw.in6 = gateway; route->gw = gateway;
route->gw_family = AF_INET6; route->gw_family = AF_INET6;
route->dst.in6 = dst; route->dst = dst;
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);
r = ndisc_request_route(TAKE_PTR(route), link, rt); r = ndisc_route_configure(route, link, rt);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not request additional route: %m"); return log_link_error_errno(link, r, "Could not set additional route: %m");
return 0; return 0;
} }
@ -1006,7 +959,7 @@ static int ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m"); return log_link_error_errno(link, n, "Failed to get RDNSS addresses: %m");
SET_FOREACH(rdnss, link->ndisc_rdnss) SET_FOREACH(rdnss, link->ndisc_rdnss)
if (in6_addr_equal(&rdnss->router, &router)) if (IN6_ARE_ADDR_EQUAL(&rdnss->router, &router))
rdnss->marked = true; rdnss->marked = true;
if (lifetime == 0) if (lifetime == 0)
@ -1100,7 +1053,7 @@ static int ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m"); return log_link_error_errno(link, r, "Failed to get DNSSL addresses: %m");
SET_FOREACH(dnssl, link->ndisc_dnssl) SET_FOREACH(dnssl, link->ndisc_dnssl)
if (in6_addr_equal(&dnssl->router, &router)) if (IN6_ARE_ADDR_EQUAL(&dnssl->router, &router))
dnssl->marked = true; dnssl->marked = true;
if (lifetime == 0) if (lifetime == 0)
@ -1166,20 +1119,20 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
switch (type) { switch (type) {
case SD_NDISC_OPTION_PREFIX_INFORMATION: { case SD_NDISC_OPTION_PREFIX_INFORMATION: {
struct in6_addr a; union in_addr_union a;
uint8_t flags; uint8_t flags;
r = sd_ndisc_router_prefix_get_address(rt, &a); r = sd_ndisc_router_prefix_get_address(rt, &a.in6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get prefix address: %m"); return log_link_error_errno(link, r, "Failed to get prefix address: %m");
if ((!set_isempty(link->network->ndisc_allow_listed_prefix) && if ((!set_isempty(link->network->ndisc_allow_listed_prefix) &&
!set_contains(link->network->ndisc_allow_listed_prefix, &a)) || !set_contains(link->network->ndisc_allow_listed_prefix, &a.in6)) ||
set_contains(link->network->ndisc_deny_listed_prefix, &a)) { set_contains(link->network->ndisc_deny_listed_prefix, &a.in6)) {
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *b = NULL; _cleanup_free_ char *b = NULL;
(void) in6_addr_to_string(&a, &b); (void) in_addr_to_string(AF_INET6, &a, &b);
if (!set_isempty(link->network->ndisc_allow_listed_prefix)) if (!set_isempty(link->network->ndisc_allow_listed_prefix))
log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b)); log_link_debug(link, "Prefix '%s' is not in allow list, ignoring", strna(b));
else else
@ -1234,7 +1187,7 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
} }
static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) { static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
struct in6_addr router; union in_addr_union router;
uint64_t flags; uint64_t flags;
NDiscAddress *na; NDiscAddress *na;
NDiscRoute *nr; NDiscRoute *nr;
@ -1245,17 +1198,17 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
assert(link->manager); assert(link->manager);
assert(rt); assert(rt);
r = sd_ndisc_router_get_address(rt, &router); r = sd_ndisc_router_get_address(rt, &router.in6);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Failed to get router address from RA: %m"); return log_link_error_errno(link, r, "Failed to get router address from RA: %m");
if ((!set_isempty(link->network->ndisc_allow_listed_router) && if ((!set_isempty(link->network->ndisc_allow_listed_router) &&
!set_contains(link->network->ndisc_allow_listed_router, &router)) || !set_contains(link->network->ndisc_allow_listed_router, &router.in6)) ||
set_contains(link->network->ndisc_deny_listed_router, &router)) { set_contains(link->network->ndisc_deny_listed_router, &router.in6)) {
if (DEBUG_LOGGING) { if (DEBUG_LOGGING) {
_cleanup_free_ char *buf = NULL; _cleanup_free_ char *buf = NULL;
(void) in6_addr_to_string(&router, &buf); (void) in_addr_to_string(AF_INET6, &router, &buf);
if (!set_isempty(link->network->ndisc_allow_listed_router)) if (!set_isempty(link->network->ndisc_allow_listed_router))
log_link_debug(link, "Router '%s' is not in allow list, ignoring", strna(buf)); log_link_debug(link, "Router '%s' is not in allow list, ignoring", strna(buf));
else else
@ -1265,11 +1218,11 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
} }
SET_FOREACH(na, link->ndisc_addresses) SET_FOREACH(na, link->ndisc_addresses)
if (in6_addr_equal(&na->router, &router)) if (IN6_ARE_ADDR_EQUAL(&na->router, &router.in6))
na->marked = true; na->marked = true;
SET_FOREACH(nr, link->ndisc_routes) SET_FOREACH(nr, link->ndisc_routes)
if (in6_addr_equal(&nr->router, &router)) if (IN6_ARE_ADDR_EQUAL(&nr->router, &router.in6))
nr->marked = true; nr->marked = true;
r = sd_ndisc_router_get_flags(rt, &flags); r = sd_ndisc_router_get_flags(rt, &flags);
@ -1282,11 +1235,11 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))
/* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */ /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
r = dhcp6_request_information(link, !(flags & ND_RA_FLAG_MANAGED)); r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
else else
/* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode /* When IPv6AcceptRA.DHCPv6Client=always, start dhcp6 client in managed mode
* even if router does not have M or O flag. */ * even if router does not have M or O flag. */
r = dhcp6_request_information(link, false); r = dhcp6_request_address(link, false);
if (r < 0 && r != -EBUSY) if (r < 0 && r != -EBUSY)
return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); return log_link_error_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
else else
@ -1314,10 +1267,11 @@ static int ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
if (r < 0) if (r < 0)
return r; return r;
if (!link->ndisc_addresses_configured || !link->ndisc_routes_configured) if (link->ndisc_addresses_configured && link->ndisc_routes_configured)
link_check_ready(link);
else
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
link_check_ready(link);
return 0; return 0;
} }

View File

@ -7,7 +7,6 @@
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-neighbor.h" #include "networkd-neighbor.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-queue.h"
#include "set.h" #include "set.h"
Neighbor *neighbor_free(Neighbor *neighbor) { Neighbor *neighbor_free(Neighbor *neighbor) {
@ -236,12 +235,34 @@ static void log_neighbor_debug(const Neighbor *neighbor, const char *str, const
"%s neighbor: lladdr: %s, dst: %s", "%s neighbor: lladdr: %s, dst: %s",
str, strna(lladdr), strna(dst)); str, strna(lladdr), strna(dst));
} }
static int neighbor_configure(
const Neighbor *neighbor,
Link *link,
link_netlink_message_handler_t callback,
Neighbor **ret) {
static int neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(m);
assert(link);
assert(link->neighbor_messages > 0);
link->neighbor_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
/* Neighbor may not exist yet. So, do not enter failed state here. */
log_link_message_warning_errno(link, m, r, "Could not set neighbor, ignoring");
if (link->neighbor_messages == 0) {
log_link_debug(link, "Neighbors set");
link->neighbors_configured = true;
link_check_ready(link);
}
return 1;
}
static int neighbor_configure(Neighbor *neighbor, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r; int r;
@ -250,7 +271,6 @@ static int neighbor_configure(
assert(link->ifindex > 0); assert(link->ifindex > 0);
assert(link->manager); assert(link->manager);
assert(link->manager->rtnl); assert(link->manager->rtnl);
assert(callback);
log_neighbor_debug(neighbor, "Configuring", link); log_neighbor_debug(neighbor, "Configuring", link);
@ -271,65 +291,22 @@ static int neighbor_configure(
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m"); return log_link_error_errno(link, r, "Could not append NDA_DST attribute: %m");
r = neighbor_add(link, neighbor, ret); r = netlink_call_async(link->manager->rtnl, NULL, req, neighbor_configure_handler,
if (r < 0)
return log_link_error_errno(link, r, "Could not add neighbor: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link->neighbor_messages++;
link_ref(link); link_ref(link);
r = neighbor_add(link, neighbor, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not add neighbor: %m");
return r; return r;
} }
static int static_neighbor_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int link_set_neighbors(Link *link) {
int r;
assert(m);
assert(link);
assert(link->static_neighbor_messages > 0);
link->static_neighbor_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set neighbor");
link_enter_failed(link);
return 1;
}
if (link->static_neighbor_messages == 0) {
log_link_debug(link, "Neighbors set");
link->static_neighbors_configured = true;
link_check_ready(link);
}
return 1;
}
static int link_request_neighbor(
Link *link,
Neighbor *neighbor,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
assert(link);
assert(neighbor);
log_neighbor_debug(neighbor, "Requesting", link);
return link_queue_request(link, REQUEST_TYPE_NEIGHBOR, neighbor, consume_object,
message_counter, netlink_handler, ret);
}
int link_request_static_neighbors(Link *link) {
Neighbor *neighbor; Neighbor *neighbor;
int r; int r;
@ -337,20 +314,24 @@ int link_request_static_neighbors(Link *link) {
assert(link->network); assert(link->network);
assert(link->state != _LINK_STATE_INVALID); assert(link->state != _LINK_STATE_INVALID);
link->static_neighbors_configured = false; if (link->neighbor_messages != 0) {
log_link_debug(link, "Neighbors are configuring.");
HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) { return 0;
r = link_request_neighbor(link, neighbor, false, &link->static_neighbor_messages,
static_neighbor_configure_handler, NULL);
if (r < 0)
return log_link_warning_errno(link, r, "Could not request neighbor: %m");
} }
if (link->static_neighbor_messages == 0) { link->neighbors_configured = false;
link->static_neighbors_configured = true;
HASHMAP_FOREACH(neighbor, link->network->neighbors_by_section) {
r = neighbor_configure(neighbor, link);
if (r < 0)
return log_link_warning_errno(link, r, "Could not set neighbor: %m");
}
if (link->neighbor_messages == 0) {
link->neighbors_configured = true;
link_check_ready(link); link_check_ready(link);
} else { } else {
log_link_debug(link, "Requesting neighbors"); log_link_debug(link, "Setting neighbors");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
} }
@ -362,9 +343,6 @@ static int neighbor_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link
assert(m); assert(m);
assert(link); assert(link);
assert(link->neighbor_remove_messages > 0);
link->neighbor_remove_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
@ -404,7 +382,6 @@ static int neighbor_remove(Neighbor *neighbor, Link *link) {
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);
link->neighbor_remove_messages++;
return 0; return 0;
} }
@ -460,34 +437,6 @@ int link_drop_neighbors(Link *link) {
return r; return r;
} }
int request_process_neighbor(Request *req) {
Neighbor *ret;
int r;
assert(req);
assert(req->link);
assert(req->neighbor);
assert(req->type == REQUEST_TYPE_NEIGHBOR);
if (!link_is_ready_to_configure(req->link, false))
return 0;
if (req->link->neighbor_remove_messages > 0)
return 0;
r = neighbor_configure(req->neighbor, req->link, req->netlink_handler, &ret);
if (r < 0)
return r;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)
return r;
}
return 1;
}
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(neighbor_freep) Neighbor *tmp = NULL; _cleanup_(neighbor_freep) Neighbor *tmp = NULL;
_cleanup_free_ void *lladdr = NULL; _cleanup_free_ void *lladdr = NULL;

View File

@ -10,10 +10,9 @@
#include "in-addr-util.h" #include "in-addr-util.h"
#include "networkd-util.h" #include "networkd-util.h"
typedef struct Link Link; typedef Manager Manager;
typedef struct Manager Manager; typedef Network Network;
typedef struct Network Network; typedef Link Link;
typedef struct Request Request;
union lladdr_union { union lladdr_union {
struct ether_addr mac; struct ether_addr mac;
@ -35,12 +34,10 @@ Neighbor *neighbor_free(Neighbor *neighbor);
void network_drop_invalid_neighbors(Network *network); void network_drop_invalid_neighbors(Network *network);
int link_set_neighbors(Link *link);
int link_drop_neighbors(Link *link); int link_drop_neighbors(Link *link);
int link_drop_foreign_neighbors(Link *link); int link_drop_foreign_neighbors(Link *link);
int link_request_static_neighbors(Link *link);
int request_process_neighbor(Request *req);
int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_neighbor(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address); CONFIG_PARSER_PROTOTYPE(config_parse_neighbor_address);

View File

@ -228,7 +228,7 @@ struct Network {
bool dhcp6_pd_manage_temporary_address; bool dhcp6_pd_manage_temporary_address;
int64_t dhcp6_pd_subnet_id; int64_t dhcp6_pd_subnet_id;
uint32_t dhcp6_pd_route_metric; uint32_t dhcp6_pd_route_metric;
struct in6_addr dhcp6_pd_token; union in_addr_union dhcp6_pd_token;
/* Bridge Support */ /* Bridge Support */
int use_bpdu; int use_bpdu;

View File

@ -10,8 +10,6 @@
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-nexthop.h" #include "networkd-nexthop.h"
#include "networkd-queue.h"
#include "networkd-route.h"
#include "parse-util.h" #include "parse-util.h"
#include "set.h" #include "set.h"
#include "string-util.h" #include "string-util.h"
@ -358,16 +356,13 @@ static void log_nexthop_debug(const NextHop *nexthop, uint32_t id, const char *s
str, nexthop->id, id, strna(gw), yes_no(nexthop->blackhole)); str, nexthop->id, id, strna(gw), yes_no(nexthop->blackhole));
} }
static int link_nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(m); assert(m);
assert(link);
assert(link->nexthop_remove_messages > 0);
link->nexthop_remove_messages--; /* Note that link may be NULL. */
if (link && IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1; return 1;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
@ -377,22 +372,6 @@ static int link_nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1; return 1;
} }
static int manager_nexthop_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Manager *manager) {
int r;
assert(m);
assert(manager);
assert(manager->nexthop_remove_messages > 0);
manager->nexthop_remove_messages--;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ENOENT)
log_message_warning_errno(m, r, "Could not drop nexthop, ignoring");
return 1;
}
static int nexthop_remove(const NextHop *nexthop, Manager *manager, Link *link) { static int nexthop_remove(const NextHop *nexthop, Manager *manager, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r; int r;
@ -417,40 +396,55 @@ static int nexthop_remove(const NextHop *nexthop, Manager *manager, Link *link)
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m"); return log_link_error_errno(link, r, "Could not append NHA_ID attribute: %m");
if (link) r = netlink_call_async(manager->rtnl, NULL, req, nexthop_remove_handler,
r = netlink_call_async(manager->rtnl, NULL, req, link_nexthop_remove_handler, link_netlink_destroy_callback, link);
link_netlink_destroy_callback, link);
else
r = netlink_call_async(manager->rtnl, NULL, req, manager_nexthop_remove_handler,
NULL, manager);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); /* link may be NULL, link_ref() is OK with that */ link_ref(link); /* link may be NULL, link_ref() is OK with that */
if (link)
link->nexthop_remove_messages++;
else
manager->nexthop_remove_messages++;
return 0; return 0;
} }
static int nexthop_configure( static int nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
const NextHop *nexthop, int r;
Link *link,
link_netlink_message_handler_t callback,
NextHop **ret) {
assert(link);
assert(link->nexthop_messages > 0);
link->nexthop_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set nexthop");
link_enter_failed(link);
return 1;
}
if (link->nexthop_messages == 0) {
log_link_debug(link, "Nexthops set");
link->static_nexthops_configured = true;
/* Now all nexthops are configured. Let's configure remaining routes. */
r = link_set_routes_with_gateway(link);
if (r < 0)
link_enter_failed(link);
}
return 1;
}
static int nexthop_configure(const NextHop *nexthop, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r, k; int r;
assert(link); assert(link);
assert(link->manager); assert(link->manager);
assert(link->manager->rtnl); assert(link->manager->rtnl);
assert(link->ifindex > 0); assert(link->ifindex > 0);
assert(IN_SET(nexthop->family, AF_INET, AF_INET6)); assert(IN_SET(nexthop->family, AF_INET, AF_INET6));
assert(callback);
log_nexthop_debug(nexthop, nexthop->id, "Configuring", link); log_nexthop_debug(nexthop, nexthop->id, "Configuring", link);
@ -488,90 +482,60 @@ static int nexthop_configure(
} }
} }
k = nexthop_add(link, nexthop, ret); r = netlink_call_async(link->manager->rtnl, NULL, req, nexthop_handler,
if (k < 0)
return log_link_error_errno(link, k, "Could not add nexthop: %m");
r = netlink_call_async(link->manager->rtnl, NULL, req, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);
return k; r = nexthop_add(link, nexthop, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not add nexthop: %m");
return r;
} }
static int static_nexthop_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int link_set_nexthops(Link *link) {
int r; enum {
PHASE_ID, /* First phase: Nexthops with ID */
assert(link); PHASE_WITHOUT_ID, /* Second phase: Nexthops without ID */
assert(link->static_nexthop_messages > 0); _PHASE_MAX,
} phase;
link->static_nexthop_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set nexthop");
link_enter_failed(link);
return 1;
}
if (link->static_nexthop_messages == 0) {
log_link_debug(link, "Nexthops set");
link->static_nexthops_configured = true;
link_check_ready(link);
}
return 1;
}
static int link_request_nexthop(
Link *link,
NextHop *nexthop,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
assert(link);
assert(nexthop);
log_nexthop_debug(nexthop, nexthop->id, "Requesting", link);
return link_queue_request(link, REQUEST_TYPE_NEXTHOP, nexthop, consume_object,
message_counter, netlink_handler, ret);
}
int link_request_static_nexthops(Link *link, bool only_ipv4) {
NextHop *nh; NextHop *nh;
int r; int r;
assert(link); assert(link);
assert(link->network); assert(link->network);
if (link->nexthop_messages != 0) {
log_link_debug(link, "Nexthops are configuring.");
return 0;
}
link->static_nexthops_configured = false; link->static_nexthops_configured = false;
HASHMAP_FOREACH(nh, link->network->nexthops_by_section) { for (phase = PHASE_ID; phase < _PHASE_MAX; phase++)
if (only_ipv4 && nh->family != AF_INET) HASHMAP_FOREACH(nh, link->network->nexthops_by_section) {
continue; if ((nh->id > 0) != (phase == PHASE_ID))
continue;
r = link_request_nexthop(link, nh, false, &link->static_nexthop_messages, r = nexthop_configure(nh, link);
static_nexthop_handler, NULL); if (r < 0)
if (r < 0) return log_link_warning_errno(link, r, "Could not set nexthop: %m");
return log_link_warning_errno(link, r, "Could not request nexthop: %m");
}
if (link->static_nexthop_messages == 0) { link->nexthop_messages++;
}
if (link->nexthop_messages == 0) {
link->static_nexthops_configured = true; link->static_nexthops_configured = true;
link_check_ready(link); /* Finally, configure routes with gateways. */
} else { return link_set_routes_with_gateway(link);
log_link_debug(link, "Requesting nexthops");
link_set_state(link, LINK_STATE_CONFIGURING);
} }
log_link_debug(link, "Setting nexthops");
link_set_state(link, LINK_STATE_CONFIGURING);
return 0; return 0;
} }
@ -693,73 +657,6 @@ int link_drop_nexthops(Link *link) {
return r; return r;
} }
static bool nexthop_is_ready_to_configure(Link *link, const NextHop *nexthop) {
assert(link);
assert(nexthop);
if (nexthop->blackhole) {
if (link->manager->nexthop_remove_messages > 0)
return false;
} else {
Link *l;
HASHMAP_FOREACH(l, link->manager->links) {
if (l->address_remove_messages > 0)
return false;
if (l->nexthop_remove_messages > 0)
return false;
if (l->route_remove_messages > 0)
return false;
}
}
if (nexthop->id == 0) {
Request *req;
ORDERED_SET_FOREACH(req, link->manager->request_queue) {
if (req->type != REQUEST_TYPE_NEXTHOP)
continue;
if (req->nexthop->id != 0)
return false; /* first configure nexthop with id. */
}
}
if (nexthop->onlink <= 0 &&
in_addr_is_set(nexthop->family, &nexthop->gw) &&
!manager_address_is_reachable(link->manager, nexthop->family, &nexthop->gw))
return false;
return true;
}
int request_process_nexthop(Request *req) {
NextHop *ret;
int r;
assert(req);
assert(req->link);
assert(req->nexthop);
assert(req->type == REQUEST_TYPE_NEXTHOP);
if (!link_is_ready_to_configure(req->link, false))
return 0;
if (!nexthop_is_ready_to_configure(req->link, req->nexthop))
return 0;
r = nexthop_configure(req->nexthop, req->link, req->netlink_handler, &ret);
if (r < 0)
return r;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)
return r;
}
return 1;
}
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) { int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m) {
_cleanup_(nexthop_freep) NextHop *tmp = NULL; _cleanup_(nexthop_freep) NextHop *tmp = NULL;
NextHop *nexthop = NULL; NextHop *nexthop = NULL;

View File

@ -15,7 +15,6 @@
typedef struct Link Link; typedef struct Link Link;
typedef struct Manager Manager; typedef struct Manager Manager;
typedef struct Network Network; typedef struct Network Network;
typedef struct Request Request;
typedef struct NextHop { typedef struct NextHop {
Network *network; Network *network;
@ -37,12 +36,10 @@ NextHop *nexthop_free(NextHop *nexthop);
void network_drop_invalid_nexthops(Network *network); void network_drop_invalid_nexthops(Network *network);
int link_set_nexthops(Link *link);
int link_drop_nexthops(Link *link); int link_drop_nexthops(Link *link);
int link_drop_foreign_nexthops(Link *link); int link_drop_foreign_nexthops(Link *link);
int link_request_static_nexthops(Link *link, bool only_ipv4);
int request_process_nexthop(Request *req);
int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret); int manager_get_nexthop_by_id(Manager *manager, uint32_t id, NextHop **ret);
int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_nexthop(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);

View File

@ -1,151 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "networkd-address.h"
#include "networkd-manager.h"
#include "networkd-neighbor.h"
#include "networkd-nexthop.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
#include "networkd-queue.h"
static void request_free_object(RequestType type, void *object) {
switch(type) {
case REQUEST_TYPE_ADDRESS:
address_free(object);
break;
case REQUEST_TYPE_NEIGHBOR:
neighbor_free(object);
break;
case REQUEST_TYPE_NEXTHOP:
nexthop_free(object);
break;
case REQUEST_TYPE_ROUTE:
route_free(object);
break;
case REQUEST_TYPE_ROUTING_POLICY_RULE:
routing_policy_rule_free(object);
break;
default:
assert_not_reached("invalid request type.");
}
}
Request *request_free(Request *req) {
if (!req)
return NULL;
if (req->on_free)
req->on_free(req);
if (req->consume_object)
request_free_object(req->type, req->object);
if (req->link && req->link->manager)
ordered_set_remove(req->link->manager->request_queue, req);
link_unref(req->link);
return mfree(req);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(Request*, request_free);
void request_drop(Request *req) {
if (req->message_counter)
(*req->message_counter)--;
request_free(req);
}
int link_queue_request(
Link *link,
RequestType type,
void *object,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
_cleanup_(request_freep) Request *req = NULL;
int r;
assert(link);
assert(link->manager);
assert(type >= 0 && type < _REQUEST_TYPE_MAX);
assert(object);
assert(netlink_handler);
req = new(Request, 1);
if (!req) {
if (consume_object)
request_free_object(type, object);
return -ENOMEM;
}
*req = (Request) {
.link = link,
.type = type,
.object = object,
.consume_object = consume_object,
.message_counter = message_counter,
.netlink_handler = netlink_handler,
};
link_ref(link);
r = ordered_set_ensure_put(&link->manager->request_queue, NULL, req);
if (r < 0)
return r;
if (req->message_counter)
(*req->message_counter)++;
if (ret)
*ret = req;
TAKE_PTR(req);
return 0;
}
int manager_process_requests(sd_event_source *s, void *userdata) {
Manager *manager = userdata;
int r;
assert(manager);
for (;;) {
bool processed = false;
Request *req;
ORDERED_SET_FOREACH(req, manager->request_queue) {
switch(req->type) {
case REQUEST_TYPE_ADDRESS:
r = request_process_address(req);
break;
case REQUEST_TYPE_NEIGHBOR:
r = request_process_neighbor(req);
break;
case REQUEST_TYPE_NEXTHOP:
r = request_process_nexthop(req);
break;
case REQUEST_TYPE_ROUTE:
r = request_process_route(req);
break;
case REQUEST_TYPE_ROUTING_POLICY_RULE:
r = request_process_routing_policy_rule(req);
break;
default:
return -EINVAL;
}
if (r < 0)
link_enter_failed(req->link);
if (r > 0) {
ordered_set_remove(manager->request_queue, req);
request_free(req);
processed = true;
}
}
if (!processed)
break;
}
return 0;
}

View File

@ -1,60 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-event.h"
#include "networkd-link.h"
typedef struct Address Address;
typedef struct Neighbor Neighbor;
typedef struct NextHop NextHop;
typedef struct Route Route;
typedef struct RoutingPolicyRule RoutingPolicyRule;
typedef struct Request Request;
typedef int (*request_after_configure_handler_t)(Request*, void*);
typedef void (*request_on_free_handler_t)(Request*);
typedef enum RequestType {
REQUEST_TYPE_ADDRESS,
REQUEST_TYPE_NEIGHBOR,
REQUEST_TYPE_NEXTHOP,
REQUEST_TYPE_ROUTE,
REQUEST_TYPE_ROUTING_POLICY_RULE,
_REQUEST_TYPE_MAX,
_REQUEST_TYPE_INVALID = -EINVAL,
} RequestType;
typedef struct Request {
Link *link;
RequestType type;
bool consume_object;
union {
Address *address;
Neighbor *neighbor;
NextHop *nexthop;
Route *route;
RoutingPolicyRule *rule;
void *object;
};
void *userdata;
unsigned *message_counter;
link_netlink_message_handler_t netlink_handler;
request_after_configure_handler_t after_configure;
request_on_free_handler_t on_free;
} Request;
Request *request_free(Request *req);
void request_drop(Request *req);
int link_queue_request(
Link *link,
RequestType type,
void *object,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret);
int manager_process_requests(sd_event_source *s, void *userdata);

View File

@ -9,8 +9,8 @@
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-network.h" #include "networkd-network.h"
#include "networkd-nexthop.h" #include "networkd-nexthop.h"
#include "networkd-queue.h"
#include "networkd-route.h" #include "networkd-route.h"
#include "networkd-routing-policy-rule.h"
#include "parse-util.h" #include "parse-util.h"
#include "socket-netlink.h" #include "socket-netlink.h"
#include "string-table.h" #include "string-table.h"
@ -288,7 +288,7 @@ Route *route_free(Route *route) {
set_remove(route->manager->routes_foreign, route); set_remove(route->manager->routes_foreign, route);
} }
ordered_set_free_with_destructor(route->multipath_routes, multipath_route_free); ordered_set_free_free(route->multipath_routes);
sd_event_source_unref(route->expire); sd_event_source_unref(route->expire);
@ -510,44 +510,6 @@ static void route_copy(Route *dest, const Route *src, const MultipathRoute *m, c
} }
} }
int route_dup(const Route *src, Route **ret) {
_cleanup_(route_freep) Route *dest = NULL;
MultipathRoute *m;
int r;
assert(src);
assert(ret);
dest = newdup(Route, src, 1);
if (!dest)
return -ENOMEM;
/* Unset all pointers */
dest->network = NULL;
dest->section = NULL;
dest->link = NULL;
dest->manager = NULL;
dest->multipath_routes = NULL;
dest->expire = NULL;
ORDERED_SET_FOREACH(m, src->multipath_routes) {
_cleanup_(multipath_route_freep) MultipathRoute *n = NULL;
r = multipath_route_dup(m, &n);
if (r < 0)
return r;
r = ordered_set_ensure_put(&dest->multipath_routes, NULL, n);
if (r < 0)
return r;
TAKE_PTR(n);
}
*ret = TAKE_PTR(dest);
return 0;
}
static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, Route **ret) { static int route_add_internal(Manager *manager, Link *link, Set **routes, const Route *in, Route **ret) {
_cleanup_(route_freep) Route *route = NULL; _cleanup_(route_freep) Route *route = NULL;
int r; int r;
@ -642,115 +604,13 @@ static bool route_type_is_reject(const Route *route) {
return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW); return IN_SET(route->type, RTN_UNREACHABLE, RTN_PROHIBIT, RTN_BLACKHOLE, RTN_THROW);
} }
int link_has_route(Link *link, const Route *route) { static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *m) {
MultipathRoute *m; _cleanup_free_ char *dst = NULL, *src = NULL, *gw = NULL, *prefsrc = NULL,
int r;
assert(link);
assert(route);
if (route->nexthop_id > 0) {
_cleanup_(route_freep) Route *tmp = NULL;
NextHop *nh;
if (manager_get_nexthop_by_id(link->manager, route->nexthop_id, &nh) < 0)
return false;
r = route_new(&tmp);
if (r < 0)
return r;
route_copy(tmp, route, NULL, nh);
if (route_type_is_reject(route) || (nh && nh->blackhole))
return route_get(link->manager, NULL, tmp, NULL) >= 0;
else
return route_get(NULL, link, tmp, NULL) >= 0;
}
if (ordered_set_isempty(route->multipath_routes)) {
if (route_type_is_reject(route))
return route_get(link->manager, NULL, route, NULL) >= 0;
else
return route_get(NULL, link, route, NULL) >= 0;
}
ORDERED_SET_FOREACH(m, route->multipath_routes) {
_cleanup_(route_freep) Route *tmp = NULL;
Link *l;
if (m->ifname) {
r = resolve_interface(&link->manager->rtnl, m->ifname);
if (r < 0)
return false;
m->ifindex = r;
if (link_get(link->manager, m->ifindex, &l) < 0)
return false;
} else
l = link;
r = route_new(&tmp);
if (r < 0)
return r;
route_copy(tmp, route, m, NULL);
if (route_get(NULL, l, tmp, NULL) < 0)
return false;
}
return true;
}
static bool route_address_is_reachable(const Route *route, int family, const union in_addr_union *address) {
assert(route);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(address);
if (route->family != family)
return false;
if (!in_addr_is_set(route->family, &route->dst))
return false;
return in_addr_prefix_intersect(
route->family,
&route->dst,
route->dst_prefixlen,
address,
FAMILY_ADDRESS_SIZE(family) * 8) > 0;
}
bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address) {
Link *link;
assert(manager);
assert(IN_SET(family, AF_INET, AF_INET6));
assert(address);
HASHMAP_FOREACH(link, manager->links) {
Route *route;
SET_FOREACH(route, link->routes)
if (route_address_is_reachable(route, family, address))
return true;
SET_FOREACH(route, link->routes_foreign)
if (route_address_is_reachable(route, family, address))
return true;
}
return false;
}
static void log_route_debug(const Route *route, const char *str, const Link *link, const Manager *manager) {
_cleanup_free_ char *dst = NULL, *src = NULL, *gw_alloc = NULL, *prefsrc = NULL,
*table = NULL, *scope = NULL, *proto = NULL; *table = NULL, *scope = NULL, *proto = NULL;
const char *gw = NULL;
assert(route); assert(route);
assert(str); assert(str);
assert(manager); assert(m);
/* link may be NULL. */ /* link may be NULL. */
@ -761,32 +621,12 @@ static void log_route_debug(const Route *route, const char *str, const Link *lin
(void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst); (void) in_addr_prefix_to_string(route->family, &route->dst, route->dst_prefixlen, &dst);
if (in_addr_is_set(route->family, &route->src)) if (in_addr_is_set(route->family, &route->src))
(void) in_addr_to_string(route->family, &route->src, &src); (void) in_addr_to_string(route->family, &route->src, &src);
if (in_addr_is_set(route->gw_family, &route->gw)) { if (in_addr_is_set(route->gw_family, &route->gw))
(void) in_addr_to_string(route->gw_family, &route->gw, &gw_alloc); (void) in_addr_to_string(route->gw_family, &route->gw, &gw);
gw = gw_alloc;
} else if (route->gateway_from_dhcp_or_ra) {
if (route->gw_family == AF_INET)
gw = "_dhcp4";
else if (route->gw_family == AF_INET6)
gw = "_ipv6ra";
} else {
MultipathRoute *m;
ORDERED_SET_FOREACH(m, route->multipath_routes) {
_cleanup_free_ char *buf = NULL, *joined = NULL;
union in_addr_union a = m->gateway.address;
(void) in_addr_to_string(m->gateway.family, &a, &buf);
joined = strjoin(gw_alloc, gw_alloc ? "," : "", strna(buf), m->ifname ? "@" : "", strempty(m->ifname));
if (joined)
free_and_replace(gw_alloc, joined);
}
gw = gw_alloc;
}
if (in_addr_is_set(route->family, &route->prefsrc)) if (in_addr_is_set(route->family, &route->prefsrc))
(void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc); (void) in_addr_to_string(route->family, &route->prefsrc, &prefsrc);
(void) route_scope_to_string_alloc(route->scope, &scope); (void) route_scope_to_string_alloc(route->scope, &scope);
(void) manager_get_route_table_to_string(manager, route->table, &table); (void) manager_get_route_table_to_string(m, route->table, &table);
(void) route_protocol_full_to_string_alloc(route->protocol, &proto); (void) route_protocol_full_to_string_alloc(route->protocol, &proto);
log_link_debug(link, log_link_debug(link,
@ -903,42 +743,18 @@ static int route_set_netlink_message(const Route *route, sd_netlink_message *req
return 0; return 0;
} }
int link_route_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg) { static int route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(m); assert(m);
assert(link);
assert(link->route_remove_messages > 0);
assert(error_msg);
link->route_remove_messages--; /* Note that link may be NULL. */
if (link && IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return 1;
return 0;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH) if (r < 0 && r != -ESRCH)
log_link_message_warning_errno(link, m, r, error_msg); log_link_message_warning_errno(link, m, r, "Could not drop route, ignoring");
return 1;
}
static int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
return link_route_remove_handler_internal(rtnl, m, link, "Could not drop route, ignoring");
}
static int manager_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Manager *manager) {
int r;
assert(m);
assert(manager);
assert(manager->route_remove_messages > 0);
manager->route_remove_messages--;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH)
log_message_warning_errno(m, r, "Could not drop route, ignoring");
return 1; return 1;
} }
@ -958,6 +774,7 @@ int route_remove(
if (!manager) if (!manager)
manager = link->manager; manager = link->manager;
/* link may be NULL! */
log_route_debug(route, "Removing", link, manager); log_route_debug(route, "Removing", link, manager);
@ -986,29 +803,18 @@ int route_remove(
if (r < 0) if (r < 0)
return r; return r;
if (link) { r = netlink_call_async(manager->rtnl, NULL, req,
r = netlink_call_async(manager->rtnl, NULL, req, callback ?: route_remove_handler,
callback ?: link_route_remove_handler, link_netlink_destroy_callback, link);
link_netlink_destroy_callback, link); if (r < 0)
if (r < 0) return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link); /* link may be NULL, link_ref() is OK with that */
link->route_remove_messages++;
} else {
r = netlink_call_async(manager->rtnl, NULL, req,
manager_route_remove_handler,
NULL, manager);
if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m");
manager->route_remove_messages++;
}
return 0; return 0;
} }
static bool link_has_static_route(const Link *link, const Route *route) { static bool link_has_route(const Link *link, const Route *route) {
Route *net_route; Route *net_route;
assert(link); assert(link);
@ -1024,7 +830,7 @@ static bool link_has_static_route(const Link *link, const Route *route) {
return false; return false;
} }
static bool links_have_static_route(const Manager *manager, const Route *route, const Link *except) { static bool links_have_route(const Manager *manager, const Route *route, const Link *except) {
Link *link; Link *link;
assert(manager); assert(manager);
@ -1033,7 +839,7 @@ static bool links_have_static_route(const Manager *manager, const Route *route,
if (link == except) if (link == except)
continue; continue;
if (link_has_static_route(link, route)) if (link_has_route(link, route))
return true; return true;
} }
@ -1057,7 +863,7 @@ static int manager_drop_routes_internal(Manager *manager, bool foreign, const Li
continue; continue;
/* The route will be configured later, or already configured by a link. */ /* The route will be configured later, or already configured by a link. */
if (links_have_static_route(manager, route, except)) if (links_have_route(manager, route, except))
continue; continue;
/* The existing links do not have the route. Let's drop this now. It may be /* The existing links do not have the route. Let's drop this now. It may be
@ -1109,7 +915,7 @@ int link_drop_foreign_routes(Link *link) {
FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP))
continue; continue;
if (link_has_static_route(link, route)) if (link_has_route(link, route))
k = route_add(NULL, link, route, NULL, NULL, NULL); k = route_add(NULL, link, route, NULL, NULL, NULL);
else else
k = route_remove(route, NULL, link, NULL); k = route_remove(route, NULL, link, NULL);
@ -1288,36 +1094,14 @@ static int append_nexthops(const Route *route, sd_netlink_message *req) {
return 0; return 0;
} }
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg) { int route_configure(
int r;
assert(m);
assert(link);
assert(error_msg);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 0;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set route with gateway");
link_enter_failed(link);
return 0;
}
return 1;
}
static int route_configure(
const Route *route, const Route *route,
Link *link, Link *link,
link_netlink_message_handler_t callback, link_netlink_message_handler_t callback,
unsigned *ret_n_routes, Route **ret) {
Route ***ret_routes) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
_cleanup_free_ Route **routes = NULL; Route *nr;
unsigned n_routes = 0; /* avoid false maybe-uninitialized warning */
int r, k; int r, k;
assert(link); assert(link);
@ -1326,7 +1110,6 @@ static int route_configure(
assert(link->ifindex > 0); assert(link->ifindex > 0);
assert(IN_SET(route->family, AF_INET, AF_INET6)); assert(IN_SET(route->family, AF_INET, AF_INET6));
assert(callback); assert(callback);
assert(!!ret_n_routes == !!ret_routes);
if (route_get(link->manager, link, route, NULL) <= 0 && if (route_get(link->manager, link, route, NULL) <= 0 &&
set_size(link->routes) >= routes_max()) set_size(link->routes) >= routes_max())
@ -1409,36 +1192,21 @@ static int route_configure(
if (route->nexthop_id != 0 || if (route->nexthop_id != 0 ||
in_addr_is_set(route->gw_family, &route->gw) || in_addr_is_set(route->gw_family, &route->gw) ||
ordered_set_isempty(route->multipath_routes)) { ordered_set_isempty(route->multipath_routes)) {
k = route_add_and_setup_timer(link, route, NULL, &nr);
if (ret_routes) {
n_routes = 1;
routes = new(Route*, n_routes);
if (!routes)
return log_oom();
}
k = route_add_and_setup_timer(link, route, NULL, routes);
if (k < 0) if (k < 0)
return k; return k;
} else { } else {
MultipathRoute *m; MultipathRoute *m;
Route **p;
r = append_nexthops(route, req); r = append_nexthops(route, req);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m"); return log_link_error_errno(link, r, "Could not append RTA_MULTIPATH attribute: %m");
if (ret_routes) { assert(!ret);
n_routes = ordered_set_size(route->multipath_routes);
routes = new(Route*, n_routes);
if (!routes)
return log_oom();
}
k = 0; k = 0;
p = routes;
ORDERED_SET_FOREACH(m, route->multipath_routes) { ORDERED_SET_FOREACH(m, route->multipath_routes) {
r = route_add_and_setup_timer(link, route, m, ret_routes ? p++ : NULL); r = route_add_and_setup_timer(link, route, m, NULL);
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
@ -1453,28 +1221,32 @@ static int route_configure(
link_ref(link); link_ref(link);
if (ret_routes) { if (ret)
*ret_n_routes = n_routes; *ret = nr;
*ret_routes = TAKE_PTR(routes);
}
return k; return k;
} }
static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { static int route_handler_with_gateway(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r; int r;
assert(link); assert(link);
assert(link->static_route_messages > 0); assert(link->route_messages > 0);
link->static_route_messages--; link->route_messages--;
r = route_configure_handler_internal(rtnl, m, link, "Could not set route"); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
if (r <= 0) return 1;
return r;
if (link->static_route_messages == 0) { r = sd_netlink_message_get_errno(m);
log_link_debug(link, "Routes set"); if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set route with gateway");
link_enter_failed(link);
return 1;
}
if (link->route_messages == 0) {
log_link_debug(link, "Routes with gateway set");
link->static_routes_configured = true; link->static_routes_configured = true;
link_check_ready(link); link_check_ready(link);
} }
@ -1482,157 +1254,140 @@ static int static_route_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *l
return 1; return 1;
} }
int link_request_route( static int route_handler_without_gateway(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
Link *link, int r;
Route *route,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
assert(link); assert(link);
assert(link->manager); assert(link->route_messages > 0);
assert(route);
log_route_debug(route, "Requesting", link, link->manager); link->route_messages--;
return link_queue_request(link, REQUEST_TYPE_ROUTE, route, consume_object,
message_counter, netlink_handler, ret); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not set route without gateway");
link_enter_failed(link);
return 1;
}
if (link->route_messages == 0) {
log_link_debug(link, "Routes set without gateway");
/* Now, we can talk to gateways, let's configure nexthops. */
r = link_set_nexthops(link);
if (r < 0)
link_enter_failed(link);
}
return 1;
} }
int link_request_static_routes(Link *link, bool only_ipv4) { static bool route_has_gateway(const Route *route) {
Route *route; assert(route);
if (in_addr_is_set(route->gw_family, &route->gw))
return true;
if (!ordered_set_isempty(route->multipath_routes))
return true;
if (route->nexthop_id > 0)
return true;
return false;
}
static int link_set_routes_internal(Link *link, bool with_gateway) {
Route *rt;
int r; int r;
assert(link); assert(link);
assert(link->network); assert(link->network);
link->static_routes_configured = false; HASHMAP_FOREACH(rt, link->network->routes_by_section) {
if (rt->gateway_from_dhcp_or_ra)
HASHMAP_FOREACH(route, link->network->routes_by_section) {
if (route->gateway_from_dhcp_or_ra)
continue; continue;
if (only_ipv4 && route->family != AF_INET) if (route_has_gateway(rt) != with_gateway)
continue; continue;
r = link_request_route(link, route, false, &link->static_route_messages, r = route_configure(rt, link, with_gateway ? route_handler_with_gateway : route_handler_without_gateway, NULL);
static_route_handler, NULL);
if (r < 0) if (r < 0)
return r; return log_link_warning_errno(link, r, "Could not set routes: %m");
link->route_messages++;
} }
if (link->static_route_messages == 0) { return 0;
}
int link_set_routes_with_gateway(Link *link) {
int r;
assert(link);
assert(link->network);
if (!link_has_carrier(link) && !link->network->configure_without_carrier)
/* During configuring addresses, the link lost its carrier. As networkd is dropping
* the addresses now, let's not configure the routes either. */
return 0;
/* Finally, add routes that needs a gateway. */
r = link_set_routes_internal(link, true);
if (r < 0)
return r;
if (link->route_messages == 0) {
link->static_routes_configured = true; link->static_routes_configured = true;
link_check_ready(link); link_check_ready(link);
} else { } else {
log_link_debug(link, "Requesting routes"); log_link_debug(link, "Setting routes with gateway");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
} }
return 0; return 0;
} }
static int route_is_ready_to_configure(const Route *route, Link *link) { int link_set_routes(Link *link) {
MultipathRoute *m;
NextHop *nh = NULL;
int r; int r;
assert(route);
assert(link); assert(link);
assert(link->network);
assert(link->state != _LINK_STATE_INVALID);
if (route->nexthop_id > 0 && link->static_routes_configured = false;
manager_get_nexthop_by_id(link->manager, route->nexthop_id, &nh) < 0)
return false;
if (route_type_is_reject(route) || (nh && nh->blackhole)) { if (!link->addresses_ready)
if (nh && link->manager->nexthop_remove_messages > 0)
return false;
if (link->manager->route_remove_messages > 0)
return false;
} else {
Link *l;
HASHMAP_FOREACH(l, link->manager->links) {
if (l->address_remove_messages > 0)
return false;
if (l->nexthop_remove_messages > 0)
return false;
if (l->route_remove_messages > 0)
return false;
}
}
if (in_addr_is_set(route->family, &route->prefsrc) > 0) {
r = manager_has_address(link->manager, route->family, &route->prefsrc, route->family == AF_INET6);
if (r <= 0)
return r;
}
if (route->gateway_onlink <= 0 &&
in_addr_is_set(route->gw_family, &route->gw) > 0 &&
!manager_address_is_reachable(link->manager, route->gw_family, &route->gw))
return false;
ORDERED_SET_FOREACH(m, route->multipath_routes) {
union in_addr_union a = m->gateway.address;
if (route->gateway_onlink <= 0 &&
!manager_address_is_reachable(link->manager, m->gateway.family, &a))
return false;
if (m->ifname) {
Link *l;
r = resolve_interface(&link->manager->rtnl, m->ifname);
if (r < 0)
return false;
m->ifindex = r;
if (link_get(link->manager, m->ifindex, &l) < 0)
return false;
if (!link_is_ready_to_configure(l, true))
return false;
}
}
return true;
}
int request_process_route(Request *req) {
_cleanup_free_ Route **routes = NULL;
unsigned n_routes;
int r;
assert(req);
assert(req->link);
assert(req->route);
assert(req->type == REQUEST_TYPE_ROUTE);
if (!link_is_ready_to_configure(req->link, false))
return 0; return 0;
r = route_is_ready_to_configure(req->route, req->link); if (!link_has_carrier(link) && !link->network->configure_without_carrier)
if (r <= 0) /* During configuring addresses, the link lost its carrier. As networkd is dropping
return r; * the addresses now, let's not configure the routes either. */
return 0;
r = route_configure(req->route, req->link, req->netlink_handler, if (link->route_messages != 0) {
req->after_configure ? &n_routes : NULL, log_link_debug(link, "Static routes are configuring.");
req->after_configure ? &routes : NULL); return 0;
}
r = link_set_routing_policy_rules(link);
if (r < 0) if (r < 0)
return r; return r;
if (req->after_configure) { /* First, add the routes that enable us to talk to gateways. */
assert(n_routes > 0); r = link_set_routes_internal(link, false);
if (r < 0)
return r;
for (unsigned i = 0; i < n_routes; i++) { if (link->route_messages == 0)
r = req->after_configure(req, routes[i]); /* If no route is configured, then configure nexthops. */
if (r < 0) return link_set_nexthops(link);
return r;
}
}
return 1; log_link_debug(link, "Setting routes without gateway");
link_set_state(link, LINK_STATE_CONFIGURING);
return 0;
} }
static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) { static int process_route_one(Manager *manager, Link *link, uint16_t type, const Route *tmp, const MultipathRoute *m) {
@ -2705,14 +2460,13 @@ int config_parse_multipath_route(
void *data, void *data,
void *userdata) { void *userdata) {
_cleanup_(multipath_route_freep) MultipathRoute *m = NULL;
_cleanup_(route_free_or_set_invalidp) Route *n = NULL; _cleanup_(route_free_or_set_invalidp) Route *n = NULL;
_cleanup_free_ char *word = NULL; _cleanup_free_ char *word = NULL, *buf = NULL;
_cleanup_free_ MultipathRoute *m = NULL;
Network *network = userdata; Network *network = userdata;
const char *p, *ip, *dev;
union in_addr_union a; union in_addr_union a;
int family, r; int family, r;
const char *p;
char *dev;
assert(filename); assert(filename);
assert(section); assert(section);
@ -2730,7 +2484,7 @@ int config_parse_multipath_route(
} }
if (isempty(rvalue)) { if (isempty(rvalue)) {
n->multipath_routes = ordered_set_free_with_destructor(n->multipath_routes, multipath_route_free); n->multipath_routes = ordered_set_free_free(n->multipath_routes);
return 0; return 0;
} }
@ -2750,14 +2504,15 @@ int config_parse_multipath_route(
dev = strchr(word, '@'); dev = strchr(word, '@');
if (dev) { if (dev) {
*dev++ = '\0'; buf = strndup(word, dev - word);
if (!buf)
m->ifname = strdup(dev);
if (!m->ifname)
return log_oom(); return log_oom();
} ip = buf;
dev++;
} else
ip = word;
r = in_addr_from_string_auto(word, &family, &a); r = in_addr_from_string_auto(ip, &family, &a);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue); "Invalid multipath route gateway '%s', ignoring assignment: %m", rvalue);
@ -2766,6 +2521,16 @@ int config_parse_multipath_route(
m->gateway.address = a; m->gateway.address = a;
m->gateway.family = family; m->gateway.family = family;
if (dev) {
r = resolve_interface(NULL, dev);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid interface name or index, ignoring assignment: %s", dev);
return 0;
}
m->ifindex = r;
}
if (!isempty(p)) { if (!isempty(p)) {
r = safe_atou32(p, &m->weight); r = safe_atou32(p, &m->weight);
if (r < 0) { if (r < 0) {

View File

@ -3,6 +3,7 @@
#include <inttypes.h> #include <inttypes.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include "sd-netlink.h" #include "sd-netlink.h"
@ -13,7 +14,6 @@
typedef struct Manager Manager; typedef struct Manager Manager;
typedef struct Network Network; typedef struct Network Network;
typedef struct Request Request;
typedef struct Route { typedef struct Route {
Network *network; Network *network;
@ -71,31 +71,18 @@ extern const struct hash_ops route_hash_ops;
int route_new(Route **ret); int route_new(Route **ret);
Route *route_free(Route *route); Route *route_free(Route *route);
DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free); DEFINE_NETWORK_SECTION_FUNCTIONS(Route, route_free);
int route_dup(const Route *src, Route **ret);
int route_configure_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg); int route_configure(const Route *route, Link *link, link_netlink_message_handler_t callback, Route **ret);
int link_route_remove_handler_internal(sd_netlink *rtnl, sd_netlink_message *m, Link *link, const char *error_msg);
int route_remove(const Route *route, Manager *manager, Link *link, link_netlink_message_handler_t callback); int route_remove(const Route *route, Manager *manager, Link *link, link_netlink_message_handler_t callback);
int link_has_route(Link *link, const Route *route); int link_set_routes(Link *link);
bool manager_address_is_reachable(Manager *manager, int family, const union in_addr_union *address); int link_set_routes_with_gateway(Link *link);
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_dhcp_route_table(const Link *link);
uint32_t link_get_ipv6_accept_ra_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,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret);
int link_request_static_routes(Link *link, bool only_ipv4);
int request_process_route(Request *req);
int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
int network_add_ipv4ll_route(Network *network); int network_add_ipv4ll_route(Network *network);

View File

@ -12,8 +12,6 @@
#include "ip-protocol-list.h" #include "ip-protocol-list.h"
#include "netlink-util.h" #include "netlink-util.h"
#include "networkd-manager.h" #include "networkd-manager.h"
#include "networkd-queue.h"
#include "networkd-route.h"
#include "networkd-routing-policy-rule.h" #include "networkd-routing-policy-rule.h"
#include "networkd-util.h" #include "networkd-util.h"
#include "parse-util.h" #include "parse-util.h"
@ -111,35 +109,45 @@ static int routing_policy_rule_new_static(Network *network, const char *filename
return 0; return 0;
} }
static int routing_policy_rule_dup(const RoutingPolicyRule *src, RoutingPolicyRule **ret) { static int routing_policy_rule_copy(RoutingPolicyRule *dest, const RoutingPolicyRule *src) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *dest = NULL; _cleanup_free_ char *iif = NULL, *oif = NULL;
assert(dest);
assert(src); assert(src);
assert(ret);
dest = newdup(RoutingPolicyRule, src, 1);
if (!dest)
return -ENOMEM;
/* Unset all pointers */
dest->manager = NULL;
dest->network = NULL;
dest->section = NULL;
dest->iif = dest->oif = NULL;
if (src->iif) { if (src->iif) {
dest->iif = strdup(src->iif); iif = strdup(src->iif);
if (!dest->iif) if (!iif)
return -ENOMEM; return -ENOMEM;
} }
if (src->oif) { if (src->oif) {
dest->oif = strdup(src->oif); oif = strdup(src->oif);
if (!dest->oif) if (!oif)
return -ENOMEM; return -ENOMEM;
} }
*ret = TAKE_PTR(dest); dest->family = src->family;
dest->from = src->from;
dest->from_prefixlen = src->from_prefixlen;
dest->to = src->to;
dest->to_prefixlen = src->to_prefixlen;
dest->invert_rule = src->invert_rule;
dest->tos = src->tos;
dest->type = src->type;
dest->fwmark = src->fwmark;
dest->fwmask = src->fwmask;
dest->priority = src->priority;
dest->table = src->table;
dest->iif = TAKE_PTR(iif);
dest->oif = TAKE_PTR(oif);
dest->ipproto = src->ipproto;
dest->protocol = src->protocol;
dest->sport = src->sport;
dest->dport = src->dport;
dest->uid_range = src->uid_range;
dest->suppress_prefixlen = src->suppress_prefixlen;
return 0; return 0;
} }
@ -315,7 +323,7 @@ static int routing_policy_rule_get(Manager *m, const RoutingPolicyRule *rule, Ro
return -ENOENT; return -ENOENT;
} }
static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, RoutingPolicyRule **ret) { static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, int family, RoutingPolicyRule **ret) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL; _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *rule = NULL;
RoutingPolicyRule *existing; RoutingPolicyRule *existing;
bool is_new = false; bool is_new = false;
@ -323,12 +331,19 @@ static int routing_policy_rule_add(Manager *m, const RoutingPolicyRule *in, Rout
assert(m); assert(m);
assert(in); assert(in);
assert(IN_SET(in->family, AF_INET, AF_INET6)); assert(IN_SET(family, AF_INET, AF_INET6));
assert(in->family == AF_UNSPEC || in->family == family);
r = routing_policy_rule_dup(in, &rule); r = routing_policy_rule_new(&rule);
if (r < 0) if (r < 0)
return r; return r;
r = routing_policy_rule_copy(rule, in);
if (r < 0)
return r;
rule->family = family;
r = routing_policy_rule_get(m, rule, &existing); r = routing_policy_rule_get(m, rule, &existing);
if (r == -ENOENT) { if (r == -ENOENT) {
/* Rule does not exist, use a new one. */ /* Rule does not exist, use a new one. */
@ -375,11 +390,11 @@ static int routing_policy_rule_consume_foreign(Manager *m, RoutingPolicyRule *ru
return 1; return 1;
} }
static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const char *str, const Link *link, const Manager *m) { static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, int family, const char *str, const Link *link, const Manager *m) {
_cleanup_free_ char *from = NULL, *to = NULL, *table = NULL; _cleanup_free_ char *from = NULL, *to = NULL, *table = NULL;
assert(rule); assert(rule);
assert(IN_SET(rule->family, AF_INET, AF_INET6)); assert(IN_SET(family, AF_INET, AF_INET6));
assert(str); assert(str);
assert(m); assert(m);
@ -388,8 +403,8 @@ static void log_routing_policy_rule_debug(const RoutingPolicyRule *rule, const c
if (!DEBUG_LOGGING) if (!DEBUG_LOGGING)
return; return;
(void) in_addr_prefix_to_string(rule->family, &rule->from, rule->from_prefixlen, &from); (void) in_addr_prefix_to_string(family, &rule->from, rule->from_prefixlen, &from);
(void) in_addr_prefix_to_string(rule->family, &rule->to, rule->to_prefixlen, &to); (void) in_addr_prefix_to_string(family, &rule->to, rule->to_prefixlen, &to);
(void) manager_get_route_table_to_string(m, rule->table, &table); (void) manager_get_route_table_to_string(m, rule->table, &table);
log_link_debug(link, log_link_debug(link,
@ -519,14 +534,10 @@ static int routing_policy_rule_set_netlink_message(const RoutingPolicyRule *rule
return 0; return 0;
} }
static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, Manager *manager) { static int routing_policy_rule_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int r; int r;
assert(m); assert(m);
assert(manager);
assert(manager->routing_policy_rule_remove_messages > 0);
manager->routing_policy_rule_remove_messages--;
r = sd_netlink_message_get_errno(m); r = sd_netlink_message_get_errno(m);
if (r < 0) if (r < 0)
@ -544,7 +555,7 @@ static int routing_policy_rule_remove(const RoutingPolicyRule *rule, Manager *ma
assert(manager->rtnl); assert(manager->rtnl);
assert(IN_SET(rule->family, AF_INET, AF_INET6)); assert(IN_SET(rule->family, AF_INET, AF_INET6));
log_routing_policy_rule_debug(rule, "Removing", NULL, manager); log_routing_policy_rule_debug(rule, rule->family, "Removing", NULL, manager);
r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family); r = sd_rtnl_message_new_routing_policy_rule(manager->rtnl, &m, RTM_DELRULE, rule->family);
if (r < 0) if (r < 0)
@ -554,37 +565,58 @@ static int routing_policy_rule_remove(const RoutingPolicyRule *rule, Manager *ma
if (r < 0) if (r < 0)
return r; return r;
r = netlink_call_async(manager->rtnl, NULL, m, r = sd_netlink_call_async(manager->rtnl, NULL, m,
routing_policy_rule_remove_handler, routing_policy_rule_remove_handler,
NULL, manager); NULL, NULL, 0, __func__);
if (r < 0) if (r < 0)
return log_error_errno(r, "Could not send rtnetlink message: %m"); return log_error_errno(r, "Could not send rtnetlink message: %m");
manager->routing_policy_rule_remove_messages++;
return 0; return 0;
} }
static int routing_policy_rule_configure( static int routing_policy_rule_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
const RoutingPolicyRule *rule, int r;
Link *link,
link_netlink_message_handler_t callback,
RoutingPolicyRule **ret) {
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
assert(link->routing_policy_rule_messages > 0);
link->routing_policy_rule_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not add routing policy rule");
link_enter_failed(link);
return 1;
}
if (link->routing_policy_rule_messages == 0) {
log_link_debug(link, "Routing policy rule configured");
link->routing_policy_rules_configured = true;
link_check_ready(link);
}
return 1;
}
static int routing_policy_rule_configure_internal(const RoutingPolicyRule *rule, int family, Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int r; int r;
assert(rule); assert(rule);
assert(IN_SET(rule->family, AF_INET, AF_INET6));
assert(link); assert(link);
assert(link->ifindex > 0); assert(link->ifindex > 0);
assert(link->manager); assert(link->manager);
assert(link->manager->rtnl); assert(link->manager->rtnl);
assert(callback);
log_routing_policy_rule_debug(rule, "Configuring", link, link->manager); log_routing_policy_rule_debug(rule, family, "Configuring", link, link->manager);
r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, rule->family); r = sd_rtnl_message_new_routing_policy_rule(link->manager->rtnl, &m, RTM_NEWRULE, family);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m"); return log_link_error_errno(link, r, "Could not allocate RTM_NEWRULE message: %m");
@ -592,20 +624,43 @@ static int routing_policy_rule_configure(
if (r < 0) if (r < 0)
return r; return r;
r = routing_policy_rule_add(link->manager, rule, ret); r = netlink_call_async(link->manager->rtnl, NULL, m,
if (r < 0) routing_policy_rule_handler,
return log_link_error_errno(link, r, "Could not add rule: %m");
r = netlink_call_async(link->manager->rtnl, NULL, m, callback,
link_netlink_destroy_callback, link); link_netlink_destroy_callback, link);
if (r < 0) if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link); link_ref(link);
link->routing_policy_rule_messages++;
r = routing_policy_rule_add(link->manager, rule, family, NULL);
if (r < 0)
return log_link_error_errno(link, r, "Could not add rule: %m");
return r; return r;
} }
static int routing_policy_rule_configure(const RoutingPolicyRule *rule, Link *link) {
int r;
if (IN_SET(rule->family, AF_INET, AF_INET6))
return routing_policy_rule_configure_internal(rule, rule->family, link);
if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) {
r = routing_policy_rule_configure_internal(rule, AF_INET, link);
if (r < 0)
return r;
}
if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) {
r = routing_policy_rule_configure_internal(rule, AF_INET6, link);
if (r < 0)
return r;
}
return 0;
}
static int links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) { static int links_have_routing_policy_rule(const Manager *m, const RoutingPolicyRule *rule, const Link *except) {
Link *link; Link *link;
int r; int r;
@ -630,7 +685,11 @@ static int links_have_routing_policy_rule(const Manager *m, const RoutingPolicyR
/* The case Family=both. */ /* The case Family=both. */
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL; _cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
r = routing_policy_rule_dup(link_rule, &tmp); r = routing_policy_rule_new(&tmp);
if (r < 0)
return r;
r = routing_policy_rule_copy(tmp, link_rule);
if (r < 0) if (r < 0)
return r; return r;
@ -676,153 +735,36 @@ int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const L
return r; return r;
} }
static int static_routing_policy_rule_configure_handler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) { int link_set_routing_policy_rules(Link *link) {
int r;
assert(rtnl);
assert(m);
assert(link);
assert(link->ifname);
assert(link->static_routing_policy_rule_messages > 0);
link->static_routing_policy_rule_messages--;
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_message_warning_errno(link, m, r, "Could not add routing policy rule");
link_enter_failed(link);
return 1;
}
if (link->static_routing_policy_rule_messages == 0) {
log_link_debug(link, "Routing policy rule configured");
link->static_routing_policy_rules_configured = true;
link_check_ready(link);
}
return 1;
}
static int link_request_routing_policy_rule(
Link *link,
RoutingPolicyRule *rule,
bool consume_object,
unsigned *message_counter,
link_netlink_message_handler_t netlink_handler,
Request **ret) {
assert(link);
assert(link->manager);
assert(rule);
log_routing_policy_rule_debug(rule, "Requesting", link, link->manager);
return link_queue_request(link, REQUEST_TYPE_ROUTING_POLICY_RULE, rule, consume_object,
message_counter, netlink_handler, ret);
}
static int link_request_static_routing_policy_rule(Link *link, RoutingPolicyRule *rule) {
int r;
if (IN_SET(rule->family, AF_INET, AF_INET6))
return link_request_routing_policy_rule(link, rule, false,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV4)) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
r = routing_policy_rule_dup(rule, &tmp);
if (r < 0)
return r;
tmp->family = AF_INET;
r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
if (r < 0)
return r;
}
if (FLAGS_SET(rule->address_family, ADDRESS_FAMILY_IPV6)) {
_cleanup_(routing_policy_rule_freep) RoutingPolicyRule *tmp = NULL;
r = routing_policy_rule_dup(rule, &tmp);
if (r < 0)
return r;
tmp->family = AF_INET6;
r = link_request_routing_policy_rule(link, TAKE_PTR(tmp), true,
&link->static_routing_policy_rule_messages,
static_routing_policy_rule_configure_handler,
NULL);
if (r < 0)
return r;
}
return 0;
}
int link_request_static_routing_policy_rules(Link *link) {
RoutingPolicyRule *rule; RoutingPolicyRule *rule;
int r; int r;
assert(link); assert(link);
assert(link->network); assert(link->network);
link->static_routing_policy_rules_configured = false; if (link->routing_policy_rule_messages != 0) {
log_link_debug(link, "Routing policy rules are configuring.");
HASHMAP_FOREACH(rule, link->network->rules_by_section) { return 0;
r = link_request_static_routing_policy_rule(link, rule);
if (r < 0)
return log_link_warning_errno(link, r, "Could not request routing policy rule: %m");
} }
if (link->static_routing_policy_rule_messages == 0) { link->routing_policy_rules_configured = false;
link->static_routing_policy_rules_configured = true;
link_check_ready(link); HASHMAP_FOREACH(rule, link->network->rules_by_section) {
} else { r = routing_policy_rule_configure(rule, link);
log_link_debug(link, "Requesting routing policy rules"); if (r < 0)
return log_link_warning_errno(link, r, "Could not set routing policy rule: %m");
}
if (link->routing_policy_rule_messages == 0)
link->routing_policy_rules_configured = true;
else {
log_link_debug(link, "Setting routing policy rules");
link_set_state(link, LINK_STATE_CONFIGURING); link_set_state(link, LINK_STATE_CONFIGURING);
} }
return 0; return 0;
} }
int request_process_routing_policy_rule(Request *req) {
RoutingPolicyRule *ret = NULL; /* avoid false maybe-uninitialized warning */
int r;
assert(req);
assert(req->link);
assert(req->rule);
assert(req->type == REQUEST_TYPE_ROUTING_POLICY_RULE);
if (!link_is_ready_to_configure(req->link, false))
return 0;
if (req->link->manager->routing_policy_rule_remove_messages > 0)
return 0;
r = routing_policy_rule_configure(req->rule, req->link, req->netlink_handler, &ret);
if (r < 0)
return r;
if (req->after_configure) {
r = req->after_configure(req, ret);
if (r < 0)
return r;
}
return 1;
}
static const RoutingPolicyRule kernel_rules[] = { static const RoutingPolicyRule kernel_rules[] = {
{ .family = AF_INET, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, { .family = AF_INET, .priority = 0, .table = RT_TABLE_LOCAL, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
{ .family = AF_INET, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, }, { .family = AF_INET, .priority = 32766, .table = RT_TABLE_MAIN, .type = FR_ACT_TO_TBL, .uid_range.start = UID_INVALID, .uid_range.end = UID_INVALID, .suppress_prefixlen = -1, },
@ -1035,11 +977,11 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
switch (type) { switch (type) {
case RTM_NEWRULE: case RTM_NEWRULE:
if (rule) if (rule)
log_routing_policy_rule_debug(tmp, "Received remembered", NULL, m); log_routing_policy_rule_debug(tmp, tmp->family, "Received remembered", NULL, m);
else if (!m->manage_foreign_routes) else if (!m->manage_foreign_routes)
log_routing_policy_rule_debug(tmp, "Ignoring received foreign", NULL, m); log_routing_policy_rule_debug(tmp, tmp->family, "Ignoring received foreign", NULL, m);
else { else {
log_routing_policy_rule_debug(tmp, "Remembering foreign", NULL, m); log_routing_policy_rule_debug(tmp, tmp->family, "Remembering foreign", NULL, m);
r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp)); r = routing_policy_rule_consume_foreign(m, TAKE_PTR(tmp));
if (r < 0) if (r < 0)
log_warning_errno(r, "Could not remember foreign rule, ignoring: %m"); log_warning_errno(r, "Could not remember foreign rule, ignoring: %m");
@ -1047,10 +989,10 @@ int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Man
break; break;
case RTM_DELRULE: case RTM_DELRULE:
if (rule) { if (rule) {
log_routing_policy_rule_debug(tmp, "Forgetting", NULL, m); log_routing_policy_rule_debug(tmp, tmp->family, "Forgetting", NULL, m);
routing_policy_rule_free(rule); routing_policy_rule_free(rule);
} else } else
log_routing_policy_rule_debug(tmp, "Kernel removed unknown", NULL, m); log_routing_policy_rule_debug(tmp, tmp->family, "Kernel removed unknown", NULL, m);
break; break;
default: default:

View File

@ -4,15 +4,16 @@
#include <inttypes.h> #include <inttypes.h>
#include <linux/fib_rules.h> #include <linux/fib_rules.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include "conf-parser.h" #include "conf-parser.h"
#include "in-addr-util.h" #include "in-addr-util.h"
#include "networkd-util.h" #include "networkd-util.h"
#include "set.h"
typedef struct Network Network;
typedef struct Link Link; typedef struct Link Link;
typedef struct Manager Manager; typedef struct Manager Manager;
typedef struct Network Network;
typedef struct Request Request;
typedef struct RoutingPolicyRule { typedef struct RoutingPolicyRule {
Manager *manager; Manager *manager;
@ -54,8 +55,7 @@ RoutingPolicyRule *routing_policy_rule_free(RoutingPolicyRule *rule);
void network_drop_invalid_routing_policy_rules(Network *network); void network_drop_invalid_routing_policy_rules(Network *network);
int link_request_static_routing_policy_rules(Link *link); int link_set_routing_policy_rules(Link *link);
int request_process_routing_policy_rule(Request *req);
int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m); int manager_rtnl_process_rule(sd_netlink *rtnl, sd_netlink_message *message, Manager *m);
int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except); int manager_drop_routing_policy_rules_internal(Manager *m, bool foreign, const Link *except);

View File

@ -977,7 +977,7 @@ static int config_parse_label(
/* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of /* Nota bene: the empty label is a totally valid one. Let's hence not follow our usual rule of
* assigning the empty string to reset to default here, but really accept it as label to set. */ * assigning the empty string to reset to default here, but really accept it as label to set. */
r = specifier_printf(rvalue, GPT_LABEL_MAX, specifier_table, NULL, &resolved); r = specifier_printf(rvalue, specifier_table, NULL, &resolved);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in Label=, ignoring: %s", rvalue); "Failed to expand specifiers in Label=, ignoring: %s", rvalue);
@ -1142,7 +1142,7 @@ static int config_parse_copy_files(
if (!isempty(p)) if (!isempty(p))
return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue); return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "Too many arguments: %s", rvalue);
r = specifier_printf(source, PATH_MAX-1, specifier_table, NULL, &resolved_source); r = specifier_printf(source, specifier_table, NULL, &resolved_source);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue); "Failed to expand specifiers in CopyFiles= source, ignoring: %s", rvalue);
@ -1153,7 +1153,7 @@ static int config_parse_copy_files(
if (r < 0) if (r < 0)
return 0; return 0;
r = specifier_printf(target, PATH_MAX-1, specifier_table, NULL, &resolved_target); r = specifier_printf(target, specifier_table, NULL, &resolved_target);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target); "Failed to expand specifiers in CopyFiles= target, ignoring: %s", resolved_target);
@ -1202,7 +1202,7 @@ static int config_parse_copy_blocks(
return 0; return 0;
} }
r = specifier_printf(rvalue, PATH_MAX-1, specifier_table, NULL, &d); r = specifier_printf(rvalue, specifier_table, NULL, &d);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue); "Failed to expand specifiers in CopyBlocks= source path, ignoring: %s", rvalue);
@ -1250,7 +1250,7 @@ static int config_parse_make_dirs(
if (r == 0) if (r == 0)
return 0; return 0;
r = specifier_printf(word, PATH_MAX-1, specifier_table, NULL, &d); r = specifier_printf(word, specifier_table, NULL, &d);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word); "Failed to expand specifiers in MakeDirectories= parameter, ignoring: %s", word);

View File

@ -255,7 +255,7 @@ int config_parse_dnssd_service_name(
return 0; return 0;
} }
r = specifier_printf(rvalue, DNS_LABEL_MAX, specifier_table, NULL, &name); r = specifier_printf(rvalue, specifier_table, NULL, &name);
if (r < 0) { if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, log_syntax(unit, LOG_WARNING, filename, line, r,
"Invalid service instance name template '%s', ignoring assignment: %m", rvalue); "Invalid service instance name template '%s', ignoring assignment: %m", rvalue);

View File

@ -170,7 +170,7 @@ int dnssd_render_instance_name(DnssdService *s, char **ret_name) {
assert(s); assert(s);
assert(s->name_template); assert(s->name_template);
r = specifier_printf(s->name_template, DNS_LABEL_MAX, specifier_table, s, &name); r = specifier_printf(s->name_template, specifier_table, s, &name);
if (r < 0) if (r < 0)
return log_debug_errno(r, "Failed to replace specifiers: %m"); return log_debug_errno(r, "Failed to replace specifiers: %m");

View File

@ -1097,27 +1097,18 @@ uint32_t manager_find_mtu(Manager *m) {
uint32_t mtu = 0; uint32_t mtu = 0;
Link *l; Link *l;
/* If we don't know on which link a DNS packet would be delivered, let's find the largest MTU that /* If we don't know on which link a DNS packet would be
* works on all interfaces we know of that have an IP address asociated */ * delivered, let's find the largest MTU that works on all
* interfaces we know of */
HASHMAP_FOREACH(l, m->links) { HASHMAP_FOREACH(l, m->links) {
/* Let's filter out links without IP addresses (e.g. AF_CAN links and suchlike) */ if (l->mtu <= 0)
if (!l->addresses)
continue;
/* Safety check: MTU shorter than what we need for the absolutely shortest DNS request? Then
* let's ignore this link. */
if (l->mtu < MIN(UDP4_PACKET_HEADER_SIZE + DNS_PACKET_HEADER_SIZE,
UDP6_PACKET_HEADER_SIZE + DNS_PACKET_HEADER_SIZE))
continue; continue;
if (mtu <= 0 || l->mtu < mtu) if (mtu <= 0 || l->mtu < mtu)
mtu = l->mtu; mtu = l->mtu;
} }
if (mtu == 0) /* found nothing? then let's assume the typical Ethernet MTU for lack of anything more precise */
return 1500;
return mtu; return mtu;
} }

View File

@ -18,7 +18,7 @@
# Some examples of DNS servers which may be used for DNS= and FallbackDNS=: # Some examples of DNS servers which may be used for DNS= and FallbackDNS=:
# Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com # Cloudflare: 1.1.1.1#cloudflare-dns.com 1.0.0.1#cloudflare-dns.com 2606:4700:4700::1111#cloudflare-dns.com 2606:4700:4700::1001#cloudflare-dns.com
# Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google # Google: 8.8.8.8#dns.google 8.8.4.4#dns.google 2001:4860:4860::8888#dns.google 2001:4860:4860::8844#dns.google
# Quad9: 9.9.9.9#dns.quad9.net 149.112.112.112#dns.quad9.net 2620:fe::fe#dns.quad9.net 2620:fe::9#dns.quad9.net # Quad9: 9.9.9.9#dns.quad9.net 2620:fe::fe#dns.quad9.net
#DNS= #DNS=
#FallbackDNS=@DNS_SERVERS@ #FallbackDNS=@DNS_SERVERS@
#Domains= #Domains=

View File

@ -1,6 +1,5 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "af-list.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "bus-error.h" #include "bus-error.h"
#include "bus-unit-util.h" #include "bus-unit-util.h"
@ -880,10 +879,14 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
address_family = eq ? word : NULL; address_family = eq ? word : NULL;
if (address_family) { if (address_family) {
family = af_from_ipv4_ipv6(address_family); if (!STR_IN_SET(address_family, "IPv4", "IPv6"))
if (family == AF_UNSPEC)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Only \"ipv4\" and \"ipv6\" protocols are supported"); "Only IPv4 and IPv6 protocols are supported");
if (streq(address_family, "IPv4"))
family = AF_INET;
else
family = AF_INET6;
} }
user_port = eq ? eq : word; user_port = eq ? eq : word;

View File

@ -985,7 +985,7 @@ bool dns_service_name_is_valid(const char *name) {
l = strlen(name); l = strlen(name);
if (l <= 0) if (l <= 0)
return false; return false;
if (l > DNS_LABEL_MAX) if (l > 63)
return false; return false;
return true; return true;

View File

@ -104,7 +104,7 @@ int gpt_partition_label_valid(const char *s) {
if (!recoded) if (!recoded)
return -ENOMEM; return -ENOMEM;
return char16_strlen(recoded) <= GPT_LABEL_MAX; return char16_strlen(recoded) <= 36;
} }
bool gpt_partition_type_is_root(sd_id128_t id) { bool gpt_partition_type_is_root(sd_id128_t id) {

View File

@ -115,9 +115,6 @@
#define GPT_FLAG_NO_AUTO (1ULL << 63) #define GPT_FLAG_NO_AUTO (1ULL << 63)
#define GPT_FLAG_GROWFS (1ULL << 59) #define GPT_FLAG_GROWFS (1ULL << 59)
/* maximum length of gpt label */
#define GPT_LABEL_MAX 36
const char *gpt_partition_type_uuid_to_string(sd_id128_t id); const char *gpt_partition_type_uuid_to_string(sd_id128_t id);
const char *gpt_partition_type_uuid_to_string_harder( const char *gpt_partition_type_uuid_to_string_harder(
sd_id128_t id, sd_id128_t id,

View File

@ -103,7 +103,7 @@ static int specifier_last_component(char specifier, const void *data, const void
return 0; return 0;
} }
int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret) { int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
/* This is similar to unit_name_printf() */ /* This is similar to unit_name_printf() */
const Specifier table[] = { const Specifier table[] = {
@ -123,5 +123,5 @@ int install_full_printf_internal(const UnitFileInstallInfo *i, const char *forma
assert(format); assert(format);
assert(ret); assert(ret);
return specifier_printf(format, max_length, table, i, ret); return specifier_printf(format, table, i, ret);
} }

View File

@ -2,12 +2,5 @@
#pragma once #pragma once
#include "install.h" #include "install.h"
#include "unit-name.h"
int install_full_printf_internal(const UnitFileInstallInfo *i, const char *format, size_t max_length, char **ret); int install_full_printf(const UnitFileInstallInfo *i, const char *format, char **ret);
static inline int install_name_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
return install_full_printf_internal(i, format, UNIT_NAME_MAX, ret);
}
static inline int install_path_printf(const UnitFileInstallInfo *i, const char *format, char **ret) {
return install_full_printf_internal(i, format, PATH_MAX-1, ret);
}

View File

@ -1143,7 +1143,7 @@ static int config_parse_also(
if (r == 0) if (r == 0)
break; break;
r = install_name_printf(info, word, &printed); r = install_full_printf(info, word, &printed);
if (r < 0) if (r < 0)
return r; return r;
@ -1190,7 +1190,7 @@ static int config_parse_default_instance(
return log_syntax(unit, LOG_WARNING, filename, line, 0, return log_syntax(unit, LOG_WARNING, filename, line, 0,
"DefaultInstance= only makes sense for template units, ignoring."); "DefaultInstance= only makes sense for template units, ignoring.");
r = install_name_printf(i, rvalue, &printed); r = install_full_printf(i, rvalue, &printed);
if (r < 0) if (r < 0)
return r; return r;
@ -1816,7 +1816,7 @@ static int install_info_symlink_alias(
STRV_FOREACH(s, i->aliases) { STRV_FOREACH(s, i->aliases) {
_cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL; _cleanup_free_ char *alias_path = NULL, *dst = NULL, *dst_updated = NULL;
q = install_path_printf(i, *s, &dst); q = install_full_printf(i, *s, &dst);
if (q < 0) if (q < 0)
return q; return q;
@ -1891,7 +1891,7 @@ static int install_info_symlink_wants(
STRV_FOREACH(s, list) { STRV_FOREACH(s, list) {
_cleanup_free_ char *path = NULL, *dst = NULL; _cleanup_free_ char *path = NULL, *dst = NULL;
q = install_name_printf(i, *s, &dst); q = install_full_printf(i, *s, &dst);
if (q < 0) if (q < 0)
return q; return q;

View File

@ -29,9 +29,9 @@
* and "%" used for escaping. */ * and "%" used for escaping. */
#define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%" #define POSSIBLE_SPECIFIERS ALPHANUMERICAL "%"
int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret) { int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **_ret) {
size_t l, allocated = 0; size_t l, allocated = 0;
_cleanup_free_ char *result = NULL; _cleanup_free_ char *ret = NULL;
char *t; char *t;
const char *f; const char *f;
bool percent = false; bool percent = false;
@ -41,11 +41,11 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
assert(table); assert(table);
l = strlen(text); l = strlen(text);
if (!GREEDY_REALLOC(result, allocated, l + 1)) if (!GREEDY_REALLOC(ret, allocated, l + 1))
return -ENOMEM; return -ENOMEM;
t = result; t = ret;
for (f = text; *f != '\0'; f++, l--) { for (f = text; *f; f++, l--)
if (percent) { if (percent) {
if (*f == '%') if (*f == '%')
*(t++) = '%'; *(t++) = '%';
@ -64,13 +64,13 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
if (r < 0) if (r < 0)
return r; return r;
j = t - result; j = t - ret;
k = strlen(w); k = strlen(w);
if (!GREEDY_REALLOC(result, allocated, j + k + l + 1)) if (!GREEDY_REALLOC(ret, allocated, j + k + l + 1))
return -ENOMEM; return -ENOMEM;
memcpy(result + j, w, k); memcpy(ret + j, w, k);
t = result + j + k; t = ret + j + k;
} else if (strchr(POSSIBLE_SPECIFIERS, *f)) } else if (strchr(POSSIBLE_SPECIFIERS, *f))
/* Oops, an unknown specifier. */ /* Oops, an unknown specifier. */
return -EBADSLT; return -EBADSLT;
@ -86,26 +86,19 @@ int specifier_printf(const char *text, size_t max_length, const Specifier table[
else else
*(t++) = *f; *(t++) = *f;
if ((size_t) (t - result) > max_length)
return -ENAMETOOLONG;
}
/* If string ended with a stray %, also end with % */ /* If string ended with a stray %, also end with % */
if (percent) { if (percent)
*(t++) = '%'; *(t++) = '%';
if ((size_t) (t - result) > max_length)
return -ENAMETOOLONG;
}
*(t++) = 0; *(t++) = 0;
/* Try to deallocate unused bytes, but don't sweat it too much */ /* Try to deallocate unused bytes, but don't sweat it too much */
if ((size_t)(t - result) < allocated) { if ((size_t)(t - ret) < allocated) {
t = realloc(result, t - result); t = realloc(ret, t - ret);
if (t) if (t)
result = t; ret = t;
} }
*ret = TAKE_PTR(result); *_ret = TAKE_PTR(ret);
return 0; return 0;
} }
@ -131,7 +124,7 @@ int specifier_machine_id(char specifier, const void *data, const void *userdata,
if (r < 0) if (r < 0)
return r; return r;
n = new(char, SD_ID128_STRING_MAX); n = new(char, 33);
if (!n) if (!n)
return -ENOMEM; return -ENOMEM;
@ -148,7 +141,7 @@ int specifier_boot_id(char specifier, const void *data, const void *userdata, ch
if (r < 0) if (r < 0)
return r; return r;
n = new(char, SD_ID128_STRING_MAX); n = new(char, 33);
if (!n) if (!n)
return -ENOMEM; return -ENOMEM;

View File

@ -11,7 +11,7 @@ typedef struct Specifier {
const void *data; const void *data;
} Specifier; } Specifier;
int specifier_printf(const char *text, size_t max_length, const Specifier table[], const void *userdata, char **ret); int specifier_printf(const char *text, const Specifier table[], const void *userdata, char **ret);
int specifier_string(char specifier, const void *data, const void *userdata, char **ret); int specifier_string(char specifier, const void *data, const void *userdata, char **ret);

View File

@ -1210,8 +1210,9 @@ int varlink_close(Varlink *v) {
varlink_set_state(v, VARLINK_DISCONNECTED); varlink_set_state(v, VARLINK_DISCONNECTED);
/* Let's take a reference first, since varlink_detach_server() might drop the final (dangling) ref /* Let's take a reference first, since varlink_detach_server() might drop the final ref from the
* which would destroy us before we can call varlink_clear() */ * disconnect callback, which would invalidate the pointer we are holding before we can call
* varlink_clear(). */
varlink_ref(v); varlink_ref(v);
varlink_detach_server(v); varlink_detach_server(v);
varlink_clear(v); varlink_clear(v);
@ -1224,15 +1225,32 @@ Varlink* varlink_close_unref(Varlink *v) {
if (!v) if (!v)
return NULL; return NULL;
(void) varlink_close(v); /* A reference is given to us to be destroyed. But when calling varlink_close(), a callback might
* also drop a reference. We allow this, and will hold a temporary reference to the object to make
* sure that the object still exists when control returns to us. If there's just one reference
* remaining after varlink_close(), even though there were at least two right before, we'll handle
* that gracefully instead of crashing.
*
* In other words, this call drops the donated reference, but if the internal call to varlink_close()
* dropped a reference to, we don't drop the reference afain. This allows the caller to say:
* global_object->varlink = varlink_close_unref(global_object->varlink);
* even though there is some callback which has access to global_object and may drop the reference
* stored in global_object->varlink. Without this step, the same code would have to be written as:
* Varlink *t = TAKE_PTR(global_object->varlink);
* varlink_close_unref(t);
*/
/* n_ref >= 1 */
varlink_ref(v); /* n_ref >= 2 */
varlink_close(v); /* n_ref >= 1 */
if (v->n_ref > 1)
v->n_ref--; /* n_ref >= 1 */
return varlink_unref(v); return varlink_unref(v);
} }
Varlink* varlink_flush_close_unref(Varlink *v) { Varlink* varlink_flush_close_unref(Varlink *v) {
if (!v) if (v)
return NULL; varlink_flush(v);
(void) varlink_flush(v);
return varlink_close_unref(v); return varlink_close_unref(v);
} }

View File

@ -2,7 +2,6 @@
#include <sys/mount.h> #include <sys/mount.h>
#include "af-list.h"
#include "bus-error.h" #include "bus-error.h"
#include "bus-locator.h" #include "bus-locator.h"
#include "bus-map-properties.h" #include "bus-map-properties.h"
@ -1711,25 +1710,22 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
return 1; return 1;
} else if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) { } else if (STR_IN_SET(name, "SocketBindAllow", "SocketBindDeny")) {
uint16_t nr_ports, port_min; uint16_t nr_ports, port_min;
const char *family;
int af; int af;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(iqq)"); r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(iqq)");
if (r < 0) if (r < 0)
return bus_log_parse_error(r); return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(iqq)", &af, &nr_ports, &port_min)) > 0) { while ((r = sd_bus_message_read(m, "(iqq)", &af, &nr_ports, &port_min)) > 0) {
const char *family, *colon; family = af == AF_INET ? "IPv4:" : af == AF_INET6 ? "IPv6:" : "";
family = strempty(af_to_ipv4_ipv6(af));
colon = isempty(family) ? "" : ":";
if (nr_ports == 0) if (nr_ports == 0)
bus_print_property_valuef(name, expected_value, flags, "%s%sany", family, colon); bus_print_property_valuef(name, expected_value, flags, "%sany", family);
else if (nr_ports == 1) else if (nr_ports == 1)
bus_print_property_valuef( bus_print_property_valuef(
name, expected_value, flags, "%s%s%hu", family, colon, port_min); name, expected_value, flags, "%s%hu", family, port_min);
else else
bus_print_property_valuef( bus_print_property_valuef(
name, expected_value, flags, "%s%s%hu-%hu", family, colon, port_min, name, expected_value, flags, "%s%hu-%hu", family, port_min,
(uint16_t) (port_min + nr_ports - 1)); (uint16_t) (port_min + nr_ports - 1));
} }
if (r < 0) if (r < 0)

View File

@ -206,7 +206,7 @@ int sd_dhcp_client_set_fallback_lease_lifetime(
int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v); int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_is_running(sd_dhcp_client *client); int sd_dhcp_client_is_running(const sd_dhcp_client *client);
int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_stop(sd_dhcp_client *client);
int sd_dhcp_client_start(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client);
int sd_dhcp_client_send_release(sd_dhcp_client *client); int sd_dhcp_client_send_release(sd_dhcp_client *client);

View File

@ -46,36 +46,36 @@ typedef enum sd_dhcp_lease_server_type_t {
_SD_ENUM_FORCE_S64(DHCP_LEASE_SERVER_TYPE), _SD_ENUM_FORCE_S64(DHCP_LEASE_SERVER_TYPE),
} sd_dhcp_lease_server_type_t; } sd_dhcp_lease_server_type_t;
int sd_dhcp_lease_get_address(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_address(const sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_lifetime(sd_dhcp_lease *lease, uint32_t *lifetime); int sd_dhcp_lease_get_lifetime(const sd_dhcp_lease *lease, uint32_t *lifetime);
int sd_dhcp_lease_get_t1(sd_dhcp_lease *lease, uint32_t *t1); int sd_dhcp_lease_get_t1(const sd_dhcp_lease *lease, uint32_t *t1);
int sd_dhcp_lease_get_t2(sd_dhcp_lease *lease, uint32_t *t2); int sd_dhcp_lease_get_t2(const sd_dhcp_lease *lease, uint32_t *t2);
int sd_dhcp_lease_get_broadcast(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_broadcast(const sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_netmask(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_netmask(const sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_router(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_router(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_next_server(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_next_server(const sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_server_identifier(sd_dhcp_lease *lease, struct in_addr *addr); int sd_dhcp_lease_get_server_identifier(const sd_dhcp_lease *lease, struct in_addr *addr);
int sd_dhcp_lease_get_servers(sd_dhcp_lease *lease, sd_dhcp_lease_server_type_t what, const struct in_addr **addr); int sd_dhcp_lease_get_servers(const sd_dhcp_lease *lease, sd_dhcp_lease_server_type_t what, const struct in_addr **addr);
int sd_dhcp_lease_get_dns(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_dns(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_ntp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_ntp(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_sip(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_sip(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_pop3(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_pop3(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_smtp(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_smtp(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_lpr(sd_dhcp_lease *lease, const struct in_addr **addr); int sd_dhcp_lease_get_lpr(const sd_dhcp_lease *lease, const struct in_addr **addr);
int sd_dhcp_lease_get_mtu(sd_dhcp_lease *lease, uint16_t *mtu); int sd_dhcp_lease_get_mtu(const sd_dhcp_lease *lease, uint16_t *mtu);
int sd_dhcp_lease_get_domainname(sd_dhcp_lease *lease, const char **domainname); int sd_dhcp_lease_get_domainname(const sd_dhcp_lease *lease, const char **domainname);
int sd_dhcp_lease_get_search_domains(sd_dhcp_lease *lease, char ***domains); int sd_dhcp_lease_get_search_domains(const sd_dhcp_lease *lease, char ***domains);
int sd_dhcp_lease_get_hostname(sd_dhcp_lease *lease, const char **hostname); int sd_dhcp_lease_get_hostname(const sd_dhcp_lease *lease, const char **hostname);
int sd_dhcp_lease_get_root_path(sd_dhcp_lease *lease, const char **root_path); int sd_dhcp_lease_get_root_path(const sd_dhcp_lease *lease, const char **root_path);
int sd_dhcp_lease_get_routes(sd_dhcp_lease *lease, sd_dhcp_route ***routes); int sd_dhcp_lease_get_routes(const sd_dhcp_lease *lease, sd_dhcp_route ***routes);
int sd_dhcp_lease_get_vendor_specific(sd_dhcp_lease *lease, const void **data, size_t *data_len); int sd_dhcp_lease_get_vendor_specific(const sd_dhcp_lease *lease, const void **data, size_t *data_len);
int sd_dhcp_lease_get_client_id(sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len); int sd_dhcp_lease_get_client_id(const sd_dhcp_lease *lease, const void **client_id, size_t *client_id_len);
int sd_dhcp_lease_get_timezone(sd_dhcp_lease *lease, const char **timezone); int sd_dhcp_lease_get_timezone(const sd_dhcp_lease *lease, const char **timezone);
int sd_dhcp_route_get_destination(sd_dhcp_route *route, struct in_addr *destination); int sd_dhcp_route_get_destination(const sd_dhcp_route *route, struct in_addr *destination);
int sd_dhcp_route_get_destination_prefix_length(sd_dhcp_route *route, uint8_t *length); int sd_dhcp_route_get_destination_prefix_length(const sd_dhcp_route *route, uint8_t *length);
int sd_dhcp_route_get_gateway(sd_dhcp_route *route, struct in_addr *gateway); int sd_dhcp_route_get_gateway(const sd_dhcp_route *route, struct in_addr *gateway);
int sd_dhcp_route_get_option(sd_dhcp_route *route); int sd_dhcp_route_get_option(const sd_dhcp_route *route);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_lease, sd_dhcp_lease_unref);

View File

@ -73,8 +73,8 @@ int sd_netlink_call(sd_netlink *nl, sd_netlink_message *message, uint64_t timeou
sd_netlink_message **reply); sd_netlink_message **reply);
int sd_netlink_read(sd_netlink *nl, uint32_t serial, uint64_t timeout, sd_netlink_message **reply); int sd_netlink_read(sd_netlink *nl, uint32_t serial, uint64_t timeout, sd_netlink_message **reply);
int sd_netlink_get_events(sd_netlink *nl); int sd_netlink_get_events(const sd_netlink *nl);
int sd_netlink_get_timeout(sd_netlink *nl, uint64_t *timeout); int sd_netlink_get_timeout(const sd_netlink *nl, uint64_t *timeout);
int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret); int sd_netlink_process(sd_netlink *nl, sd_netlink_message **ret);
int sd_netlink_wait(sd_netlink *nl, uint64_t timeout); int sd_netlink_wait(sd_netlink *nl, uint64_t timeout);
@ -137,33 +137,33 @@ sd_netlink_message *sd_netlink_message_ref(sd_netlink_message *m);
sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m); sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m);
int sd_netlink_message_request_dump(sd_netlink_message *m, int dump); int sd_netlink_message_request_dump(sd_netlink_message *m, int dump);
int sd_netlink_message_is_error(sd_netlink_message *m); int sd_netlink_message_is_error(const sd_netlink_message *m);
int sd_netlink_message_get_errno(sd_netlink_message *m); int sd_netlink_message_get_errno(const sd_netlink_message *m);
int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type); int sd_netlink_message_get_type(const sd_netlink_message *m, uint16_t *type);
int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags); int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags);
int sd_netlink_message_is_broadcast(sd_netlink_message *m); int sd_netlink_message_is_broadcast(const sd_netlink_message *m);
/* rtnl */ /* rtnl */
int sd_rtnl_message_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family);
int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family); int sd_rtnl_message_new_addr(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int family);
int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family); int sd_rtnl_message_new_addr_update(sd_netlink *nl, sd_netlink_message **ret, int index, int family);
int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope); int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags); int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags);
int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_addr_get_family(const sd_netlink_message *m, int *family);
int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen); int sd_rtnl_message_addr_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen);
int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope); int sd_rtnl_message_addr_get_scope(const sd_netlink_message *m, unsigned char *scope);
int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags); int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags);
int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex); int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex);
int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index); int sd_rtnl_message_new_link(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index);
int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change); int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change);
int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type); int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type);
int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family); int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family);
int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex); int sd_rtnl_message_link_get_ifindex(const sd_netlink_message *m, int *ifindex);
int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags); int sd_rtnl_message_link_get_flags(const sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type); int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type);
int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol); int sd_rtnl_message_new_route(sd_netlink *nl, sd_netlink_message **ret, uint16_t nlmsg_type, int rtm_family, unsigned char rtm_protocol);
int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
@ -172,46 +172,46 @@ int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags); int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags);
int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table); int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table);
int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type); int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type);
int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags); int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags);
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family);
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol); int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol);
int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope); int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope);
int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos); int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, unsigned char *tos);
int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table); int sd_rtnl_message_route_get_table(const sd_netlink_message *m, unsigned char *table);
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len); int sd_rtnl_message_route_get_dst_prefixlen(const sd_netlink_message *m, unsigned char *dst_len);
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len); int sd_rtnl_message_route_get_src_prefixlen(const sd_netlink_message *m, unsigned char *src_len);
int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type); int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type);
int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol); int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nhmsg_type, int nh_family, unsigned char nh_protocol);
int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags); int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family); int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family);
int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol); int sd_rtnl_message_nexthop_get_protocol(const sd_netlink_message *m, uint8_t *protocol);
int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family); int sd_rtnl_message_new_neigh(sd_netlink *nl, sd_netlink_message **ret, uint16_t msg_type, int index, int nda_family);
int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags); int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags);
int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state); int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state);
int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family); int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family);
int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index); int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *index);
int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state); int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state);
int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags); int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags);
int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family); int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family);
int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen); int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen); int sd_rtnl_message_addrlabel_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen);
int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family); int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family);
int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, uint8_t tos); int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, uint8_t tos);
int sd_rtnl_message_routing_policy_rule_get_tos(sd_netlink_message *m, uint8_t *tos); int sd_rtnl_message_routing_policy_rule_get_tos(const sd_netlink_message *m, uint8_t *tos);
int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, uint8_t table); int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, uint8_t table);
int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, uint8_t *table); int sd_rtnl_message_routing_policy_rule_get_table(const sd_netlink_message *m, uint8_t *table);
int sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(sd_netlink_message *m, uint8_t len); int sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(sd_netlink_message *m, uint8_t len);
int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(sd_netlink_message *m, uint8_t *len); int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(const sd_netlink_message *m, uint8_t *len);
int sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(sd_netlink_message *m, uint8_t len); int sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(sd_netlink_message *m, uint8_t len);
int sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(sd_netlink_message *m, uint8_t *len); int sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(const sd_netlink_message *m, uint8_t *len);
int sd_rtnl_message_routing_policy_rule_set_fib_type(sd_netlink_message *m, uint8_t type); int sd_rtnl_message_routing_policy_rule_set_fib_type(sd_netlink_message *m, uint8_t type);
int sd_rtnl_message_routing_policy_rule_get_fib_type(sd_netlink_message *m, uint8_t *type); int sd_rtnl_message_routing_policy_rule_get_fib_type(const sd_netlink_message *m, uint8_t *type);
int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, uint32_t flags); int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, uint32_t flags);
int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, uint32_t *flags); int sd_rtnl_message_routing_policy_rule_get_flags(const sd_netlink_message *m, uint32_t *flags);
int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex); int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex);
int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent); int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent);
@ -252,7 +252,7 @@ int sd_nfnl_nft_message_add_setelem_end(sd_netlink_message *m);
/* genl */ /* genl */
int sd_genl_socket_open(sd_netlink **nl); int sd_genl_socket_open(sd_netlink **nl);
int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **m); int sd_genl_message_new(sd_netlink *nl, sd_genl_family_t family, uint8_t cmd, sd_netlink_message **m);
int sd_genl_message_get_family(sd_netlink *nl, sd_netlink_message *m, sd_genl_family_t *family); int sd_genl_message_get_family(const sd_netlink *nl, const sd_netlink_message *m, sd_genl_family_t *family);
/* slot */ /* slot */
sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl); sd_netlink_slot *sd_netlink_slot_ref(sd_netlink_slot *nl);
@ -261,11 +261,11 @@ sd_netlink_slot *sd_netlink_slot_unref(sd_netlink_slot *nl);
sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot); sd_netlink *sd_netlink_slot_get_netlink(sd_netlink_slot *slot);
void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot); void *sd_netlink_slot_get_userdata(sd_netlink_slot *slot);
void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata); void *sd_netlink_slot_set_userdata(sd_netlink_slot *slot, void *userdata);
int sd_netlink_slot_get_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t *callback); int sd_netlink_slot_get_destroy_callback(const sd_netlink_slot *slot, sd_netlink_destroy_t *callback);
int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t callback); int sd_netlink_slot_set_destroy_callback(sd_netlink_slot *slot, sd_netlink_destroy_t callback);
int sd_netlink_slot_get_floating(sd_netlink_slot *slot); int sd_netlink_slot_get_floating(const sd_netlink_slot *slot);
int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b); int sd_netlink_slot_set_floating(sd_netlink_slot *slot, int b);
int sd_netlink_slot_get_description(sd_netlink_slot *slot, const char **description); int sd_netlink_slot_get_description(const sd_netlink_slot *slot, const char **description);
int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description); int sd_netlink_slot_set_description(sd_netlink_slot *slot, const char *description);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref); _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_netlink, sd_netlink_unref);

View File

@ -1492,7 +1492,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
name = mfree(name); name = mfree(name);
if (name) { if (name) {
r = specifier_printf(name, NAME_MAX, specifier_table, NULL, &resolved_name); r = specifier_printf(name, specifier_table, NULL, &resolved_name);
if (r < 0) if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name); return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", fname, line, name);
@ -1507,7 +1507,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
id = mfree(id); id = mfree(id);
if (id) { if (id) {
r = specifier_printf(id, PATH_MAX-1, specifier_table, NULL, &resolved_id); r = specifier_printf(id, specifier_table, NULL, &resolved_id);
if (r < 0) if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, name); fname, line, name);
@ -1518,7 +1518,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
description = mfree(description); description = mfree(description);
if (description) { if (description) {
r = specifier_printf(description, LONG_LINE_MAX, specifier_table, NULL, &resolved_description); r = specifier_printf(description, specifier_table, NULL, &resolved_description);
if (r < 0) if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, description); fname, line, description);
@ -1534,7 +1534,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
home = mfree(home); home = mfree(home);
if (home) { if (home) {
r = specifier_printf(home, PATH_MAX-1, specifier_table, NULL, &resolved_home); r = specifier_printf(home, specifier_table, NULL, &resolved_home);
if (r < 0) if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, home); fname, line, home);
@ -1550,7 +1550,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
shell = mfree(shell); shell = mfree(shell);
if (shell) { if (shell) {
r = specifier_printf(shell, PATH_MAX-1, specifier_table, NULL, &resolved_shell); r = specifier_printf(shell, specifier_table, NULL, &resolved_shell);
if (r < 0) if (r < 0)
return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m", return log_error_errno(r, "[%s:%u] Failed to replace specifiers in '%s': %m",
fname, line, shell); fname, line, shell);

View File

@ -512,7 +512,7 @@ static void test_install_printf(void) {
_cleanup_free_ char \ _cleanup_free_ char \
*d1 = strdup(i.name), \ *d1 = strdup(i.name), \
*d2 = strdup(i.path); \ *d2 = strdup(i.path); \
assert_se(install_name_printf(&src, pattern, &t) >= 0 || !result); \ assert_se(install_full_printf(&src, pattern, &t) >= 0 || !result); \
memzero(i.name, strlen(i.name)); \ memzero(i.name, strlen(i.name)); \
memzero(i.path, strlen(i.path)); \ memzero(i.path, strlen(i.path)); \
assert_se(d1 && d2); \ assert_se(d1 && d2); \

View File

@ -141,8 +141,8 @@ int main(int argc, char *argv[]) {
assert_se(manager_startup(m, NULL, NULL) >= 0); assert_se(manager_startup(m, NULL, NULL) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("2000"), STRV_MAKE("any")) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("2000"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("ipv6:2001-2002"), STRV_MAKE("any")) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "2000", STRV_MAKE("IPv6:2001-2002"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("ipv4:6666", "6667"), STRV_MAKE("any")) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("IPv4:6666", "6667"), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("6667", "6668", ""), STRV_MAKE("any")) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "6666", STRV_MAKE("6667", "6668", ""), STRV_MAKE("any")) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "7777", STRV_MAKE_EMPTY, STRV_MAKE_EMPTY) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "7777", STRV_MAKE_EMPTY, STRV_MAKE_EMPTY) >= 0);
assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("any"), STRV_MAKE("any")) >= 0); assert_se(test_socket_bind(m, "socket_bind_test.service", netcat_path, "8888", STRV_MAKE("any"), STRV_MAKE("any")) >= 0);

View File

@ -56,38 +56,6 @@ static const Specifier specifier_table[] = {
{} {}
}; };
static void test_specifier_printf(void) {
static const Specifier table[] = {
{ 'X', specifier_string, (char*) "AAAA" },
{ 'Y', specifier_string, (char*) "BBBB" },
COMMON_SYSTEM_SPECIFIERS,
{}
};
_cleanup_free_ char *w = NULL;
int r;
log_info("/* %s */", __func__);
r = specifier_printf("xxx a=%X b=%Y yyy", SIZE_MAX, table, NULL, &w);
assert_se(r >= 0);
assert_se(w);
puts(w);
assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
free(w);
r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", SIZE_MAX, table, NULL, &w);
assert_se(r >= 0);
assert_se(w);
puts(w);
w = mfree(w);
specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", SIZE_MAX, table, NULL, &w);
if (w)
puts(w);
}
static void test_specifiers(void) { static void test_specifiers(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
@ -97,7 +65,7 @@ static void test_specifiers(void) {
xsprintf(spec, "%%%c", s->specifier); xsprintf(spec, "%%%c", s->specifier);
assert_se(specifier_printf(spec, SIZE_MAX, specifier_table, NULL, &resolved) >= 0); assert_se(specifier_printf(spec, specifier_table, NULL, &resolved) >= 0);
log_info("%%%c → %s", s->specifier, resolved); log_info("%%%c → %s", s->specifier, resolved);
} }
@ -108,7 +76,6 @@ int main(int argc, char *argv[]) {
test_specifier_escape(); test_specifier_escape();
test_specifier_escape_strv(); test_specifier_escape_strv();
test_specifier_printf();
test_specifiers(); test_specifiers();
return 0; return 0;

View File

@ -3,9 +3,42 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "escape.h" #include "escape.h"
#include "nulstr-util.h" #include "nulstr-util.h"
#include "specifier.h"
#include "string-util.h" #include "string-util.h"
#include "strv.h" #include "strv.h"
static void test_specifier_printf(void) {
static const Specifier table[] = {
{ 'X', specifier_string, (char*) "AAAA" },
{ 'Y', specifier_string, (char*) "BBBB" },
COMMON_SYSTEM_SPECIFIERS,
{}
};
_cleanup_free_ char *w = NULL;
int r;
log_info("/* %s */", __func__);
r = specifier_printf("xxx a=%X b=%Y yyy", table, NULL, &w);
assert_se(r >= 0);
assert_se(w);
puts(w);
assert_se(streq(w, "xxx a=AAAA b=BBBB yyy"));
free(w);
r = specifier_printf("machine=%m, boot=%b, host=%H, version=%v, arch=%a", table, NULL, &w);
assert_se(r >= 0);
assert_se(w);
puts(w);
w = mfree(w);
specifier_printf("os=%o, os-version=%w, build=%B, variant=%W", table, NULL, &w);
if (w)
puts(w);
}
static void test_str_in_set(void) { static void test_str_in_set(void) {
log_info("/* %s */", __func__); log_info("/* %s */", __func__);
@ -989,6 +1022,7 @@ static void test_strv_fnmatch(void) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
test_specifier_printf();
test_str_in_set(); test_str_in_set();
test_strptr_in_set(); test_strptr_in_set();
test_startswith_set(); test_startswith_set();

View File

@ -2522,7 +2522,7 @@ static int specifier_expansion_from_arg(Item *i) {
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument); return log_error_errno(r, "Failed to unescape parameter to write: %s", i->argument);
r = specifier_printf(unescaped, PATH_MAX-1, specifier_table, NULL, &resolved); r = specifier_printf(unescaped, specifier_table, NULL, &resolved);
if (r < 0) if (r < 0)
return r; return r;
@ -2532,7 +2532,7 @@ static int specifier_expansion_from_arg(Item *i) {
case SET_XATTR: case SET_XATTR:
case RECURSIVE_SET_XATTR: case RECURSIVE_SET_XATTR:
STRV_FOREACH(xattr, i->xattrs) { STRV_FOREACH(xattr, i->xattrs) {
r = specifier_printf(*xattr, SIZE_MAX, specifier_table, NULL, &resolved); r = specifier_printf(*xattr, specifier_table, NULL, &resolved);
if (r < 0) if (r < 0)
return r; return r;
@ -2706,7 +2706,7 @@ static int parse_line(
i.append_or_force = append_or_force; i.append_or_force = append_or_force;
i.allow_failure = allow_failure; i.allow_failure = allow_failure;
r = specifier_printf(path, PATH_MAX-1, specifier_table, NULL, &i.path); r = specifier_printf(path, specifier_table, NULL, &i.path);
if (r == -ENXIO) if (r == -ENXIO)
return log_unresolvable_specifier(fname, line); return log_unresolvable_specifier(fname, line);
if (r < 0) { if (r < 0) {

View File

@ -1,13 +1,13 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -eo pipefail set -e
out="${1:?}" out="$1"
systemd_efi="${2:?}" systemd_efi="$2"
boot_stub="${3:?}" boot_stub="$3"
splash_bmp="${4:?}" splash_bmp="$4"
if [ -z "$out" -o -z "$systemd_efi" -o -z "$boot_stub" -o -z "$splash_bmp" ]; then
efi_dir="$(bootctl -p)" exit 1
entry_dir="${efi_dir}/$(cat /etc/machine-id)/$(uname -r)" fi
# create GPT table with EFI System Partition # create GPT table with EFI System Partition
rm -f "$out" rm -f "$out"
@ -15,17 +15,15 @@ dd if=/dev/null of="$out" bs=1M seek=512 count=1 status=none
parted --script "$out" "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on" parted --script "$out" "mklabel gpt" "mkpart ESP fat32 1MiB 511MiB" "set 1 boot on"
# create FAT32 file system # create FAT32 file system
LOOP="$(losetup --show -f -P "$out")" LOOP=$(losetup --show -f -P "$out")
mkfs.vfat -F32 "${LOOP}p1" mkfs.vfat -F32 ${LOOP}p1
mkdir -p mnt mkdir -p mnt
mount "${LOOP}p1" mnt mount ${LOOP}p1 mnt
mkdir -p mnt/EFI/{BOOT,systemd} mkdir -p mnt/EFI/{BOOT,systemd}
cp "$systemd_efi" mnt/EFI/BOOT/BOOTX64.efi cp "$systemd_efi" mnt/EFI/BOOT/BOOTX64.efi
if [ -e /boot/shellx64.efi ]; then [ -e /boot/shellx64.efi ] && cp /boot/shellx64.efi mnt/
cp /boot/shellx64.efi mnt/
fi
mkdir mnt/EFI/Linux mkdir mnt/EFI/Linux
echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" >mnt/cmdline.txt echo -n "foo=yes bar=no root=/dev/fakeroot debug rd.break=initqueue" >mnt/cmdline.txt
@ -33,8 +31,8 @@ objcopy \
--add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \ --add-section .osrel=/etc/os-release --change-section-vma .osrel=0x20000 \
--add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \ --add-section .cmdline=mnt/cmdline.txt --change-section-vma .cmdline=0x30000 \
--add-section .splash="$splash_bmp" --change-section-vma .splash=0x40000 \ --add-section .splash="$splash_bmp" --change-section-vma .splash=0x40000 \
--add-section .linux="${entry_dir}/linux" --change-section-vma .linux=0x2000000 \ --add-section .linux=/boot/$(cat /etc/machine-id)/$(uname -r)/linux --change-section-vma .linux=0x2000000 \
--add-section .initrd="${entry_dir}/initrd" --change-section-vma .initrd=0x3000000 \ --add-section .initrd=/boot/$(cat /etc/machine-id)/$(uname -r)/initrd --change-section-vma .initrd=0x3000000 \
"$boot_stub" mnt/EFI/Linux/linux-test.efi "$boot_stub" mnt/EFI/Linux/linux-test.efi
# install entries # install entries
@ -50,4 +48,4 @@ echo -e "title Test6\nlinux /test6\n" > mnt/loader/entries/test6.conf
sync sync
umount mnt umount mnt
rmdir mnt rmdir mnt
losetup -d "$LOOP" losetup -d $LOOP

View File

@ -2784,16 +2784,20 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
expect_up = initial_up expect_up = initial_up
next_up = not expect_up next_up = not expect_up
# if initial expected state is down, must wait for setup_state to reach configuring
# so systemd-networkd considers it 'activated'
setup_state = None if initial_up else 'configuring'
for iteration in range(4): for iteration in range(4):
with self.subTest(iteration=iteration, expect_up=expect_up): with self.subTest(iteration=iteration, expect_up=expect_up):
operstate = 'routable' if expect_up else 'off' operstate = 'routable' if expect_up else 'off'
setup_state = 'configured' if expect_up else None
self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20) self.wait_operstate('test1', operstate, setup_state=setup_state, setup_timeout=20)
setup_state = None
if expect_up: if expect_up:
self.assertIn('UP', check_output('ip link show test1')) self.assertIn('UP', check_output('ip link show test1'))
self.assertIn('192.168.10.30/24', check_output('ip address show test1')) self.assertIn('192.168.10.30/24', check_output('ip address show test1'))
self.assertIn('default via 192.168.10.1', check_output('ip route show dev test1')) self.assertIn('default via 192.168.10.1', check_output('ip route show'))
else: else:
self.assertIn('DOWN', check_output('ip link show test1')) self.assertIn('DOWN', check_output('ip link show test1'))
@ -2896,8 +2900,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertEqual(rc, 0) self.assertEqual(rc, 0)
time.sleep(1) time.sleep(1)
self.wait_online(['veth99:routable', 'veth-peer:routable'])
output = check_output('ip nexthop list dev veth99') output = check_output('ip nexthop list dev veth99')
print(output) print(output)
self.assertEqual(output, '') self.assertEqual(output, '')
@ -2911,8 +2913,6 @@ class NetworkdNetworkTests(unittest.TestCase, Utilities):
self.assertEqual(rc, 0) self.assertEqual(rc, 0)
time.sleep(1) time.sleep(1)
self.wait_online(['veth99:routable', 'veth-peer:routable'])
rc = call('ip link del veth99') rc = call('ip link del veth99')
self.assertEqual(rc, 0) self.assertEqual(rc, 0)
time.sleep(2) time.sleep(2)