network: set link ifindex when multi-path routes specified without interface name
mentioned in the specifications. We are simply trying to make the boot and
installation processes of Linux a bit more robust and self-descriptive.
-### Why did you only define the root partition for x86, x86-64, ARM, ARM64, ia64?
+### Why did you only define the root partition for x86, x86-64, ARM, ARM64, ia64, riscv32, riscv64?
The automatic discovery of the root partition is defined to operate on the disk
containing the current EFI System Partition (ESP). Since EFI only exists on
-x86, x86-64, ia64, and ARM so far, we only defined root partition UUIDs for
+x86, x86-64, ia64, ARM and RISC-V so far, we only defined root partition UUIDs for
these architectures. Should EFI become more common on other architectures, we
can define additional UUIDs for them.
<listitem><para>SSL CA certificate.</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>NetworkTimeoutSec=</varname></term>
+
+ <listitem><para>When network connectivity to the server is lost, this option
+ configures the time to wait for the connectivity to get restored. If the server is
+ not reachable over the network for the configured time, <command>systemd-journal-upload</command>
+ exits. Takes a value in seconds (or in other time units if suffixed with "ms", "min", "h", etc).
+ For details, see <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+ </para></listitem>
+ </varlistentry>
+
</variablelist>
</refsect1>
static bool arg_merge = false;
static int arg_follow = -1;
static const char *arg_save_state = NULL;
+static usec_t arg_network_timeout_usec = USEC_INFINITY;
static void close_fd_input(Uploader *u);
return log_error_errno(SYNTHETIC_ERRNO(ENOSR),
"Call to curl_easy_init failed.");
+ /* If configured, set a timeout for the curl operation. */
+ if (arg_network_timeout_usec != USEC_INFINITY)
+ easy_setopt(curl, CURLOPT_TIMEOUT,
+ (long) DIV_ROUND_UP(arg_network_timeout_usec, USEC_PER_SEC),
+ LOG_ERR, return -EXFULL);
+
/* tell it to POST to the URL */
easy_setopt(curl, CURLOPT_POST, 1L,
LOG_ERR, return -EXFULL);
static int parse_config(void) {
const ConfigTableItem items[] = {
- { "Upload", "URL", config_parse_string, 0, &arg_url },
- { "Upload", "ServerKeyFile", config_parse_path_or_ignore, 0, &arg_key },
- { "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
- { "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
+ { "Upload", "URL", config_parse_string, 0, &arg_url },
+ { "Upload", "ServerKeyFile", config_parse_path_or_ignore, 0, &arg_key },
+ { "Upload", "ServerCertificateFile", config_parse_path_or_ignore, 0, &arg_cert },
+ { "Upload", "TrustedCertificateFile", config_parse_path_or_ignore, 0, &arg_trust },
+ { "Upload", "NetworkTimeoutSec", config_parse_sec, 0, &arg_network_timeout_usec },
{}
};
#include "network-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
+#include "stat-util.h"
#include "stdio-util.h"
#include "udev-util.h"
#include "virt.h"
const uint8_t *mac,
size_t mac_len,
bool legacy_unstable_byteorder,
+ bool use_mac,
void *_id) {
+
/* name is a pointer to memory in the sd_device struct, so must
* have the same scope */
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
- uint64_t id;
uint32_t id32;
+ uint64_t id;
+ int r;
+
+ if (path_is_read_only_fs("/sys") <= 0 && !use_mac) {
+ /* udev should be around */
+
+ r = sd_device_new_from_ifindex(&device, ifindex);
+ if (r < 0)
+ return r;
+
+ r = sd_device_get_is_initialized(device);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ /* not yet ready */
+ return -EBUSY;
+
+ r = device_is_renaming(device);
+ if (r < 0)
+ return r;
+ if (r > 0)
+ /* device is under renaming */
+ return -EBUSY;
- if (detect_container() <= 0) {
- /* not in a container, udev will be around */
- char ifindex_str[1 + DECIMAL_STR_MAX(int)];
- int r;
-
- xsprintf(ifindex_str, "n%d", ifindex);
- if (sd_device_new_from_device_id(&device, ifindex_str) >= 0) {
- r = sd_device_get_is_initialized(device);
- if (r < 0)
- return r;
- if (r == 0)
- /* not yet ready */
- return -EBUSY;
-
- r = device_is_renaming(device);
- if (r < 0)
- return r;
- if (r > 0)
- /* device is under renaming */
- return -EBUSY;
-
- name = net_get_name_persistent(device);
- }
+ name = net_get_name_persistent(device);
}
if (name)
int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len);
int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len);
int dhcp_identifier_set_duid_uuid(struct duid *duid, size_t *len);
-int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, void *_id);
+int dhcp_identifier_set_iaid(int ifindex, const uint8_t *mac, size_t mac_len, bool legacy_unstable_byteorder, bool use_mac, void *_id);
extern const struct hash_ops dhcp_option_hash_ops;
+typedef struct sd_dhcp_client sd_dhcp_client;
+
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
const uint8_t *mac_addr, size_t mac_addr_len,
const uint8_t *bcast_addr, size_t bcast_addr_len,
int dhcp_packet_verify_headers(DHCPPacket *packet, size_t len, bool checksum, uint16_t port);
+void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode);
+
/* If we are invoking callbacks of a dhcp-client, ensure unreffing the
* client from the callback doesn't destroy the object we are working
* on */
LIST_HEAD(DHCP6Address, addresses);
} DHCP6IA;
+typedef struct sd_dhcp6_client sd_dhcp6_client;
+
int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
size_t optlen, const void *optval);
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
const char *dhcp6_message_status_to_string(int s) _const_;
int dhcp6_message_status_from_string(const char *s) _pure_;
+void dhcp6_client_set_test_mode(sd_dhcp6_client *client, bool test_mode);
+
#define log_dhcp6_client_errno(client, error, fmt, ...) \
log_interface_prefix_full_errno( \
"DHCPv6 client: ", \
assert_se(sd_dhcp6_client_set_ifindex(client, 42) == 0);
assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
assert_se(sd_dhcp6_client_set_information_request(client, is_information_request_enabled) == 0);
+ dhcp6_client_set_test_mode(client, true);
assert_se(sd_dhcp6_client_start(client) >= 0);
sd_dhcp_lease *lease;
usec_t start_delay;
int ip_service_type;
+
+ /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
+ bool test_mode;
};
static const uint8_t default_req_opts[] = {
else {
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr,
client->mac_addr_len,
- true,
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to set IAID: %m");
return dhcp_client_set_iaid_duid_internal(client, false, false, 0, DUID_TYPE_LLT, NULL, 0, llt_time);
}
+void dhcp_client_set_test_mode(sd_dhcp_client *client, bool test_mode) {
+ assert(client);
+
+ client->test_mode = test_mode;
+}
+
int sd_dhcp_client_set_hostname(
sd_dhcp_client *client,
const char *hostname) {
client->client_id.type = 255;
r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
- true, &client->client_id.ns.iaid);
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
+ &client->client_id.ns.iaid);
if (r < 0)
return r;
usec_t information_refresh_time_usec;
OrderedHashmap *extra_options;
OrderedHashmap *vendor_options;
+
+ /* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
+ bool test_mode;
};
static const uint16_t default_req_opts[] = {
return 0;
}
+void dhcp6_client_set_test_mode(sd_dhcp6_client *client, bool test_mode) {
+ assert(client);
+
+ client->test_mode = test_mode;
+}
+
int sd_dhcp6_client_get_iaid(sd_dhcp6_client *client, uint32_t *iaid) {
assert_return(client, -EINVAL);
assert_return(iaid, -EINVAL);
if (client->iaid_set)
return 0;
- r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len, true, &iaid);
+ r = dhcp_identifier_set_iaid(client->ifindex, client->mac_addr, client->mac_addr_len,
+ /* legacy_unstable_byteorder = */ true,
+ /* use_mac = */ client->test_mode,
+ &iaid);
if (r < 0)
return r;
static void test_dhcp_identifier_set_iaid(void) {
uint32_t iaid_legacy;
be32_t iaid;
- int ifindex;
- for (;;) {
- char ifname[IFNAMSIZ];
-
- /* try to find an ifindex which does not exist. I causes dhcp_identifier_set_iaid()
- * to hash the MAC address. */
- pseudo_random_bytes(&ifindex, sizeof(ifindex));
- if (ifindex > 0 && !if_indextoname(ifindex, ifname))
- break;
- }
-
- assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), true, &iaid_legacy) >= 0);
- assert_se(dhcp_identifier_set_iaid(ifindex, mac_addr, sizeof(mac_addr), false, &iaid) >= 0);
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, sizeof(mac_addr), /* legacy = */ true,
+ /* use_mac = */ true, &iaid_legacy) >= 0);
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, sizeof(mac_addr), /* legacy = */ false,
+ /* use_mac = */ true, &iaid) >= 0);
/* we expect, that the MAC address was hashed. The legacy value is in native
* endianness. */
size_t duid_len;
assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
- assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, &iaid) >= 0);
+ assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, true, /* use_mac = */ true, &iaid) >= 0);
assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
assert_se(len == 19);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
+ dhcp_client_set_test_mode(client, true);
assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, mac_addr, bcast_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
+ dhcp_client_set_test_mode(client, true);
assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
#include "sd-dhcp6-client.h"
#include "sd-event.h"
+#include "dhcp-identifier.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
#include "dhcp6-protocol.h"
#include "strv.h"
#include "tests.h"
#include "time-util.h"
-#include "virt.h"
static struct ether_addr mac_addr = {
.ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
sizeof (mac_addr),
ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1);
+ dhcp6_client_set_test_mode(client, true);
assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
assert_se(val == 0);
sd_device_get_usec_initialized;
sd_device_trigger_with_uuid;
sd_device_get_trigger_uuid;
+ sd_device_new_from_ifname;
+ sd_device_new_from_ifindex;
} LIBSYSTEMD_248;
#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
+#include "format-util.h"
#include "fs-util.h"
#include "hashmap.h"
#include "id128-util.h"
#include "macro.h"
+#include "netlink-util.h"
#include "parse-util.h"
#include "path-util.h"
#include "set.h"
return sd_device_new_from_syspath(ret, syspath);
}
+static int device_new_from_main_ifname(sd_device **ret, const char *ifname) {
+ const char *syspath;
+
+ assert(ret);
+ assert(ifname);
+
+ syspath = strjoina("/sys/class/net/", ifname);
+ return sd_device_new_from_syspath(ret, syspath);
+}
+
+_public_ int sd_device_new_from_ifname(sd_device **ret, const char *ifname) {
+ _cleanup_free_ char *main_name = NULL;
+ int r;
+
+ assert_return(ret, -EINVAL);
+ assert_return(ifname, -EINVAL);
+
+ r = parse_ifindex(ifname);
+ if (r > 0)
+ return sd_device_new_from_ifindex(ret, r);
+
+ if (ifname_valid(ifname)) {
+ r = device_new_from_main_ifname(ret, ifname);
+ if (r >= 0)
+ return r;
+ }
+
+ r = rtnl_resolve_link_alternative_name(NULL, ifname, &main_name);
+ if (r < 0)
+ return r;
+
+ return device_new_from_main_ifname(ret, main_name);
+}
+
+_public_ int sd_device_new_from_ifindex(sd_device **ret, int ifindex) {
+ char ifname[IF_NAMESIZE + 1];
+
+ assert_return(ret, -EINVAL);
+ assert_return(ifindex > 0, -EINVAL);
+
+ if (!format_ifname(ifindex, ifname))
+ return -ENODEV;
+
+ return device_new_from_main_ifname(ret, ifname);
+}
+
static int device_strjoin_new(
const char *a,
const char *b,
}
case 'n': {
- _cleanup_(sd_device_unrefp) sd_device *device = NULL;
- _cleanup_close_ int sk = -1;
- struct ifreq ifr = {};
int ifindex;
- r = ifr.ifr_ifindex = parse_ifindex(id + 1);
- if (r < 0)
- return r;
+ ifindex = parse_ifindex(id + 1);
+ if (ifindex < 0)
+ return ifindex;
- sk = socket_ioctl_fd();
- if (sk < 0)
- return sk;
-
- r = ioctl(sk, SIOCGIFNAME, &ifr);
- if (r < 0)
- return -errno;
-
- r = sd_device_new_from_subsystem_sysname(&device, "net", ifr.ifr_name);
- if (r < 0)
- return r;
-
- r = sd_device_get_ifindex(device, &ifindex);
- if (r < 0)
- return r;
-
- /* this is racey, so we might end up with the wrong device */
- if (ifr.ifr_ifindex != ifindex)
- return -ENODEV;
-
- *ret = TAKE_PTR(device);
- return 0;
+ return sd_device_new_from_ifindex(ret, ifindex);
}
case '+': {
#include "memory-util.h"
#include "netlink-internal.h"
#include "netlink-util.h"
+#include "parse-util.h"
#include "strv.h"
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
return 0;
}
-int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name) {
+int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret) {
_cleanup_(sd_netlink_unrefp) sd_netlink *our_rtnl = NULL;
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL, *reply = NULL;
- int r, ret;
+ int r, ifindex;
assert(name);
+ /* This returns ifindex and the main interface name. */
+
+ if (!ifname_valid_full(name, IFNAME_VALID_ALTERNATIVE))
+ return -EINVAL;
+
if (!rtnl)
rtnl = &our_rtnl;
if (!*rtnl) {
if (r < 0)
return r;
- r = sd_rtnl_message_link_get_ifindex(reply, &ret);
+ r = sd_rtnl_message_link_get_ifindex(reply, &ifindex);
if (r < 0)
return r;
- assert(ret > 0);
- return ret;
+ assert(ifindex > 0);
+
+ if (ret) {
+ r = sd_netlink_message_read_string_strdup(message, IFLA_IFNAME, ret);
+ if (r < 0)
+ return r;
+ }
+
+ return ifindex;
+}
+
+int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name) {
+ int r;
+
+ /* Like if_nametoindex, but resolves "alternative names" too. */
+
+ assert(name);
+
+ r = if_nametoindex(name);
+ if (r > 0)
+ return r;
+
+ return rtnl_resolve_link_alternative_name(rtnl, name, NULL);
+}
+
+int rtnl_resolve_interface(sd_netlink **rtnl, const char *name) {
+ int r;
+
+ /* Like rtnl_resolve_ifname, but resolves interface numbers too. */
+
+ assert(name);
+
+ r = parse_ifindex(name);
+ if (r > 0)
+ return r;
+ assert(r < 0);
+
+ return rtnl_resolve_ifname(rtnl, name);
+}
+
+int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name) {
+ int r;
+
+ r = rtnl_resolve_interface(rtnl, name);
+ if (r < 0)
+ return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name);
+ return r;
}
int rtnl_get_link_info(sd_netlink **rtnl, int ifindex, unsigned short *ret_iftype, unsigned *ret_flags) {
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);
int rtnl_delete_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
-int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name);
+int rtnl_resolve_link_alternative_name(sd_netlink **rtnl, const char *name, char **ret);
+int rtnl_resolve_ifname(sd_netlink **rtnl, const char *name);
+int rtnl_resolve_interface(sd_netlink **rtnl, const char *name);
+int rtnl_resolve_interface_or_warn(sd_netlink **rtnl, const char *name);
int rtnl_get_link_info(sd_netlink **rtnl, int ifindex, unsigned short *ret_iftype, unsigned *ret_flags);
int rtnl_log_parse_error(int r);
links[c].needs_freeing = true;
- char devid[2 + DECIMAL_STR_MAX(int)];
- xsprintf(devid, "n%i", links[c].ifindex);
- (void) sd_device_new_from_device_id(&links[c].sd_device, devid);
+ (void) sd_device_new_from_ifindex(&links[c].sd_device, links[c].ifindex);
acquire_ether_link_info(&fd, &links[c]);
acquire_wlan_link_info(&links[c]);
return log_oom();
for (int i = 1; i < argc; i++) {
- index = resolve_interface_or_warn(&rtnl, argv[i]);
+ index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0)
return index;
return log_oom();
for (int i = 1; i < argc; i++) {
- index = resolve_interface_or_warn(&rtnl, argv[i]);
+ index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0)
return index;
return log_error_errno(r, "Failed to connect system bus: %m");
for (int i = 1; i < argc; i++) {
- index = resolve_interface_or_warn(&rtnl, argv[i]);
+ index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0)
return index;
return log_error_errno(r, "Failed to connect system bus: %m");
for (int i = 1; i < argc; i++) {
- int index = resolve_interface_or_warn(&rtnl, argv[i]);
+ int index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0)
return index;
return log_oom();
for (int i = 1; i < argc; i++) {
- index = resolve_interface_or_warn(&rtnl, argv[i]);
+ index = rtnl_resolve_interface_or_warn(&rtnl, argv[i]);
if (index < 0)
return index;
if (!link->sr_iov_configured)
return (void) log_link_debug(link, "%s(): SR-IOV is not configured.", __func__);
- if (link_has_carrier(link) || !link->network->configure_without_carrier) {
- bool has_ndisc_address = false;
- NDiscAddress *n;
-
- if (link_ipv6ll_enabled(link) && !in6_addr_is_set(&link->ipv6ll_address))
- return (void) log_link_debug(link, "%s(): IPv6LL is not configured yet.", __func__);
-
- SET_FOREACH(n, link->ndisc_addresses)
- if (!n->marked) {
- has_ndisc_address = true;
- break;
- }
+ /* IPv6LL is assigned after the link gains its carrier. */
+ if (!link->network->configure_without_carrier &&
+ link_ipv6ll_enabled(link) &&
+ !in6_addr_is_set(&link->ipv6ll_address))
+ return (void) log_link_debug(link, "%s(): IPv6LL is not configured yet.", __func__);
+
+ bool has_ndisc_address = false;
+ NDiscAddress *n;
+ SET_FOREACH(n, link->ndisc_addresses)
+ if (!n->marked) {
+ has_ndisc_address = true;
+ break;
+ }
- if ((link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) || link_ipv4ll_enabled(link)) &&
- !link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
+ if ((link_dhcp4_enabled(link) || link_dhcp6_with_address_enabled(link) || link_ipv4ll_enabled(link)) &&
+ !link->dhcp_address && set_isempty(link->dhcp6_addresses) && !has_ndisc_address &&
+ !link->ipv4ll_address_configured)
+ /* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
+ return (void) log_link_debug(link, "%s(): DHCP4, DHCP6 or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
+
+ /* Ignore NDisc when ConfigureWithoutCarrier= is enabled, as IPv6AcceptRA= is enabled by default. */
+ if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
+ (!link->network->configure_without_carrier && link_ipv6_accept_ra_enabled(link)) ||
+ link_ipv4ll_enabled(link)) {
+
+ if (!link->dhcp4_configured &&
+ !(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
+ !(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
+ !(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
!link->ipv4ll_address_configured)
- /* When DHCP[46] or IPv4LL is enabled, at least one address is acquired by them. */
- return (void) log_link_debug(link, "%s(): DHCP4, DHCP6 or IPv4LL is enabled but no dynamic address is assigned yet.", __func__);
-
- if (link_dhcp4_enabled(link) || link_dhcp6_enabled(link) || link_dhcp6_pd_is_enabled(link) ||
- link_ipv6_accept_ra_enabled(link) || link_ipv4ll_enabled(link)) {
- if (!link->dhcp4_configured &&
- !(link->dhcp6_address_configured && link->dhcp6_route_configured) &&
- !(link->dhcp6_pd_address_configured && link->dhcp6_pd_route_configured) &&
- !(link->ndisc_addresses_configured && link->ndisc_routes_configured) &&
- !link->ipv4ll_address_configured)
- /* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
- return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
-
- log_link_debug(link, "%s(): dhcp4:%s ipv4ll:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
- __func__,
- yes_no(link->dhcp4_configured),
- yes_no(link->ipv4ll_address_configured),
- yes_no(link->dhcp6_address_configured),
- yes_no(link->dhcp6_route_configured),
- yes_no(link->dhcp6_pd_address_configured),
- yes_no(link->dhcp6_pd_route_configured),
- yes_no(link->ndisc_addresses_configured),
- yes_no(link->ndisc_routes_configured));
- }
+ /* When DHCP[46], NDisc, or IPv4LL is enabled, at least one protocol must be finished. */
+ return (void) log_link_debug(link, "%s(): dynamic addresses or routes are not configured.", __func__);
+
+ log_link_debug(link, "%s(): dhcp4:%s ipv4ll:%s dhcp6_addresses:%s dhcp_routes:%s dhcp_pd_addresses:%s dhcp_pd_routes:%s ndisc_addresses:%s ndisc_routes:%s",
+ __func__,
+ yes_no(link->dhcp4_configured),
+ yes_no(link->ipv4ll_address_configured),
+ yes_no(link->dhcp6_address_configured),
+ yes_no(link->dhcp6_route_configured),
+ yes_no(link->dhcp6_pd_address_configured),
+ yes_no(link->dhcp6_pd_route_configured),
+ yes_no(link->ndisc_addresses_configured),
+ yes_no(link->ndisc_routes_configured));
}
link_set_state(link, LINK_STATE_CONFIGURED);
static int link_check_initialized(Link *link) {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
- char ifindex_str[2 + DECIMAL_STR_MAX(int)];
int r;
assert(link);
return link_initialized_and_synced(link);
/* udev should be around */
- xsprintf(ifindex_str, "n%d", link->ifindex);
- r = sd_device_new_from_device_id(&device, ifindex_str);
+ r = sd_device_new_from_ifindex(&device, link->ifindex);
if (r < 0) {
log_link_debug_errno(link, r, "Could not find device, waiting for device initialization: %m");
return 0;
return 0;
if (r < 0)
return log_link_debug_errno(link, r, "rtnl: failed to read MTU in RTM_NEWLINK message: %m");
+ if (mtu == 0)
+ return 0;
r = sd_netlink_message_read_u32(message, IFLA_MIN_MTU, &min_mtu);
if (r < 0 && r != -ENODATA)
if (r < 0 && r != -ENODATA)
return log_link_debug_errno(link, r, "rtnl: failed to read maximum MTU in RTM_NEWLINK message: %m");
- if (mtu == 0)
- return 0;
-
if (max_mtu == 0)
max_mtu = UINT32_MAX;
if (link->mtu == mtu)
return 0;
- log_link_debug(link, "MTU is changed: %"PRIu32" → %"PRIu32" (min: %"PRIu32", max: %"PRIu32")",
- link->mtu, mtu, link->min_mtu, link->max_mtu);
+ if (link->mtu != 0)
+ log_link_debug(link, "MTU is changed: %"PRIu32" → %"PRIu32" (min: %"PRIu32", max: %"PRIu32")",
+ link->mtu, mtu, link->min_mtu, link->max_mtu);
link->mtu = mtu;
#include "networkd-manager-bus.h"
#include "networkd-manager.h"
#include "path-util.h"
-#include "socket-netlink.h"
#include "strv.h"
#include "user-util.h"
_cleanup_free_ char *path = NULL;
Manager *manager = userdata;
const char *name;
- int index, r;
Link *link;
+ int r;
r = sd_bus_message_read(message, "s", &name);
if (r < 0)
return r;
- index = resolve_ifname(&manager->rtnl, name);
- if (index < 0)
- return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %s cannot be resolved", name);
-
- link = hashmap_get(manager->links, INT_TO_PTR(index));
- if (!link)
+ if (link_get_by_name(manager, name, &link) < 0)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_LINK, "Link %s not known", name);
r = sd_bus_message_new_method_return(message, &reply);
#include "networkd-queue.h"
#include "networkd-route.h"
#include "parse-util.h"
-#include "socket-netlink.h"
#include "string-table.h"
#include "string-util.h"
#include "strv.h"
Link *l;
if (m->ifname) {
- r = resolve_interface(&link->manager->rtnl, m->ifname);
- if (r < 0)
+ if (link_get_by_name(link->manager, m->ifname, &l) < 0)
return false;
- m->ifindex = r;
- if (link_get(link->manager, m->ifindex, &l) < 0)
- return false;
+ m->ifindex = l->ifindex;
} else
l = link;
if (r < 0)
return r;
- u = if_nametoindex(n); /* We don't need to use resolve_ifname() here because the
+ u = if_nametoindex(n); /* We don't need to use rtnl_resolve_ifname() here because the
* name we assigned is always the main name. */
if (u == 0)
return log_error_errno(errno, "Failed to resolve interface %s: %m", n);
assert(veth_name);
assert(bridge_name);
- bridge_ifi = resolve_interface(&rtnl, bridge_name);
+ bridge_ifi = rtnl_resolve_interface(&rtnl, bridge_name);
if (bridge_ifi < 0)
return bridge_ifi;
int test_network_interface_initialized(const char *name) {
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
- int ifi, r;
- char ifi_str[2 + DECIMAL_STR_MAX(int)];
+ int r;
- if (path_is_read_only_fs("/sys"))
+ if (path_is_read_only_fs("/sys") > 0)
return 0;
/* udev should be around. */
- ifi = resolve_interface_or_warn(NULL, name);
- if (ifi < 0)
- return ifi;
-
- sprintf(ifi_str, "n%i", ifi);
- r = sd_device_new_from_device_id(&d, ifi_str);
+ r = sd_device_new_from_ifname(&d, name);
if (r < 0)
return log_error_errno(r, "Failed to get device %s: %m", name);
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
int ifi;
- ifi = resolve_interface_or_warn(&rtnl, *i);
+ ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
if (ifi < 0)
return ifi;
struct ether_addr mac;
int ifi;
- ifi = resolve_interface_or_warn(&rtnl, *i);
+ ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
if (ifi < 0)
return ifi;
_cleanup_free_ char *n = NULL, *a = NULL;
int ifi;
- ifi = resolve_interface_or_warn(&rtnl, *i);
+ ifi = rtnl_resolve_interface_or_warn(&rtnl, *i);
if (ifi < 0)
return ifi;
if (!iface)
return log_oom();
- ifi = resolve_interface(NULL, iface);
+ ifi = rtnl_resolve_interface(NULL, iface);
if (ifi < 0) {
if (ifi == -ENODEV && arg_ifindex_permissive) {
log_debug("Interface '%s' not found, but -f specified, ignoring.", iface);
STRV_FOREACH(ifname, argv + 1) {
int ifindex, q;
- ifindex = resolve_interface(&rtnl, *ifname);
+ ifindex = rtnl_resolve_interface(&rtnl, *ifname);
if (ifindex < 0) {
log_warning_errno(ifindex, "Failed to resolve interface \"%s\", ignoring: %m", *ifname);
continue;
#include "socket-util.h"
#include "string-util.h"
-int resolve_ifname(sd_netlink **rtnl, const char *name) {
- int r;
-
- /* Like if_nametoindex, but resolves "alternative names" too. */
-
- assert(name);
-
- r = if_nametoindex(name);
- if (r > 0)
- return r;
-
- return rtnl_resolve_link_alternative_name(rtnl, name);
-}
-
-int resolve_interface(sd_netlink **rtnl, const char *name) {
- int r;
-
- /* Like resolve_ifname, but resolves interface numbers too. */
-
- assert(name);
-
- r = parse_ifindex(name);
- if (r > 0)
- return r;
- assert(r < 0);
-
- return resolve_ifname(rtnl, name);
-}
-
-int resolve_interface_or_warn(sd_netlink **rtnl, const char *name) {
- int r;
-
- r = resolve_interface(rtnl, name);
- if (r < 0)
- return log_error_errno(r, "Failed to resolve interface \"%s\": %m", name);
- return r;
-}
-
int socket_address_parse(SocketAddress *a, const char *s) {
_cleanup_free_ char *n = NULL;
char *e;
return -EINVAL; /* We want to return -EINVAL for syntactically invalid names,
* and -ENODEV for valid but nonexistent interfaces. */
- ifindex = resolve_interface(NULL, m + 1);
+ ifindex = rtnl_resolve_interface(NULL, m + 1);
if (ifindex < 0)
return ifindex;
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
-#include "sd-netlink.h"
-
#include "in-addr-util.h"
#include "macro.h"
#include "socket-util.h"
-int resolve_ifname(sd_netlink **rtnl, const char *name);
-int resolve_interface(sd_netlink **rtnl, const char *name);
-int resolve_interface_or_warn(sd_netlink **rtnl, const char *name);
-
int make_socket_fd(int log_level, const char* address, int type, int flags);
int socket_address_parse(SocketAddress *a, const char *s);
int sd_device_new_from_subsystem_sysname(sd_device **ret, const char *subsystem, const char *sysname);
int sd_device_new_from_device_id(sd_device **ret, const char *id);
int sd_device_new_from_stat_rdev(sd_device **ret, const struct stat *st);
+int sd_device_new_from_ifname(sd_device **ret, const char *ifname);
+int sd_device_new_from_ifindex(sd_device **ret, int ifindex);
int sd_device_get_parent(sd_device *child, sd_device **ret);
int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret);
set -e
TEST_DESCRIPTION="UDEV"
-IMAGE_NAME="udev"
+IMAGE_NAME="default"
TEST_NO_NSPAWN=1
# shellcheck source=test/test-functions
QEMU_TIMEOUT=800
-test_append_files() {
- (
- instmods dummy
- generate_module_dependencies
- )
-}
-
do_test "$@"
instmods loop
instmods vfat
+ instmods dummy
if [[ "$LOOKS_LIKE_SUSE" ]]; then
instmods ext4
Name=bridge99
[Network]
-LinkLocalAddressing=yes
IPv6AcceptRA=no
ConfigureWithoutCarrier=yes
[Network]
Address=192.168.0.15/24
Gateway=192.168.0.1
+IPv6AcceptRA=no
with self.subTest(carrier=carrier):
if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
check_output(f'ip link set dev test1 carrier {carrier}')
- self.wait_online([f'test1:{routable_map[carrier]}'])
+ self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
print(output)
with self.subTest(carrier=carrier, have_config=have_config):
if carrier_map[carrier] != read_link_attr('test1', 'carrier'):
check_output(f'ip link set dev test1 carrier {carrier}')
- self.wait_online([f'test1:{routable_map[carrier]}'])
+ self.wait_online([f'test1:{routable_map[carrier]}:{routable_map[carrier]}'])
output = check_output(*networkctl_cmd, '-n', '0', 'status', 'test1', env=env)
print(output)