diff options
Diffstat (limited to 'src/network')
36 files changed, 1573 insertions, 1031 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c index aa83f32f53..3454394977 100644 --- a/src/network/networkctl.c +++ b/src/network/networkctl.c @@ -26,7 +26,7 @@ #include "sd-network.h" #include "sd-rtnl.h" #include "sd-hwdb.h" -#include "libudev.h" +#include "sd-device.h" #include "strv.h" #include "build.h" @@ -34,13 +34,14 @@ #include "pager.h" #include "lldp.h" #include "rtnl-util.h" -#include "udev-util.h" +#include "device-util.h" #include "hwdb-util.h" #include "arphrd-list.h" #include "local-addresses.h" #include "socket-util.h" #include "ether-addr-util.h" #include "verbs.h" +#include "terminal-util.h" static bool arg_no_pager = false; static bool arg_legend = true; @@ -54,17 +55,20 @@ static void pager_open_if_enabled(void) { pager_open(false); } -static int link_get_type_string(int iftype, struct udev_device *d, char **ret) { +static int link_get_type_string(int iftype, sd_device *d, char **ret) { const char *t; char *p; + assert(ret); + if (iftype == ARPHRD_ETHER && d) { - const char *devtype, *id = NULL; + const char *devtype = NULL, *id = NULL; /* WLANs have iftype ARPHRD_ETHER, but we want * to show a more useful type string for * them */ - devtype = udev_device_get_devtype(d); + (void)sd_device_get_devtype(d, &devtype); + if (streq_ptr(devtype, "wlan")) id = "wlan"; else if (streq_ptr(devtype, "wwan")) @@ -189,7 +193,6 @@ static void setup_state_to_color(const char *state, const char **on, const char static int list_links(int argc, char *argv[], void *userdata) { _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; - _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; _cleanup_free_ LinkInfo *links = NULL; int r, c, i; @@ -200,10 +203,6 @@ static int list_links(int argc, char *argv[], void *userdata) { if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); - udev = udev_new(); - if (!udev) - return log_error_errno(errno, "Failed to connect to udev: %m"); - r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); if (r < 0) return rtnl_log_create_error(r); @@ -225,7 +224,7 @@ static int list_links(int argc, char *argv[], void *userdata) { for (i = 0; i < c; i++) { _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_device_unref_ sd_device *d = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; char devid[2 + DECIMAL_STR_MAX(int)]; @@ -238,7 +237,7 @@ static int list_links(int argc, char *argv[], void *userdata) { setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); sprintf(devid, "n%i", links[i].ifindex); - d = udev_device_new_from_device_id(udev, devid); + (void)sd_device_new_from_device_id(&d, devid); link_get_type_string(links[i].iftype, d, &t); @@ -495,19 +494,19 @@ static void dump_list(const char *prefix, char **l) { static int link_status_one( sd_rtnl *rtnl, - struct udev *udev, sd_hwdb *hwdb, const char *name) { - _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL; _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; - _cleanup_udev_device_unref_ struct udev_device *d = NULL; + _cleanup_device_unref_ sd_device *d = NULL; char devid[2 + DECIMAL_STR_MAX(int)]; _cleanup_free_ char *t = NULL, *network = NULL; const char *driver = NULL, *path = NULL, *vendor = NULL, *model = NULL, *link = NULL; const char *on_color_operational, *off_color_operational, *on_color_setup, *off_color_setup; + _cleanup_strv_free_ char **carrier_bound_to = NULL; + _cleanup_strv_free_ char **carrier_bound_by = NULL; struct ether_addr e; unsigned iftype; int r, ifindex; @@ -515,7 +514,6 @@ static int link_status_one( uint32_t mtu; assert(rtnl); - assert(udev); assert(name); if (safe_atoi(name, &ifindex) >= 0 && ifindex > 0) @@ -587,31 +585,36 @@ static int link_status_one( } sprintf(devid, "n%i", ifindex); - d = udev_device_new_from_device_id(udev, devid); + + (void)sd_device_new_from_device_id(&d, devid); + if (d) { - link = udev_device_get_property_value(d, "ID_NET_LINK_FILE"); - driver = udev_device_get_property_value(d, "ID_NET_DRIVER"); - path = udev_device_get_property_value(d, "ID_PATH"); + (void)sd_device_get_property_value(d, "ID_NET_LINK_FILE", &link); + (void)sd_device_get_property_value(d, "ID_NET_DRIVER", &driver); + (void)sd_device_get_property_value(d, "ID_PATH", &path); - vendor = udev_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE"); - if (!vendor) - vendor = udev_device_get_property_value(d, "ID_VENDOR"); + r = sd_device_get_property_value(d, "ID_VENDOR_FROM_DATABASE", &vendor); + if (r < 0) + (void)sd_device_get_property_value(d, "ID_VENDOR", &vendor); - model = udev_device_get_property_value(d, "ID_MODEL_FROM_DATABASE"); - if (!model) - model = udev_device_get_property_value(d, "ID_MODEL"); + r = sd_device_get_property_value(d, "ID_MODEL_FROM_DATABASE", &model); + if (r < 0) + (void)sd_device_get_property_value(d, "ID_MODEL", &model); } link_get_type_string(iftype, d, &t); sd_network_link_get_network_file(ifindex, &network); + sd_network_link_get_carrier_bound_to(ifindex, &carrier_bound_to); + sd_network_link_get_carrier_bound_by(ifindex, &carrier_bound_by); + printf("%s%s%s %i: %s\n", on_color_operational, draw_special_char(DRAW_BLACK_CIRCLE), off_color_operational, ifindex, name); - printf(" Link File: %s\n" - "Network File: %s\n" - " Type: %s\n" - " State: %s%s%s (%s%s%s)\n", + printf(" Link File: %s\n" + " Network File: %s\n" + " Type: %s\n" + " State: %s%s%s (%s%s%s)\n", strna(link), strna(network), strna(t), @@ -619,13 +622,13 @@ static int link_status_one( on_color_setup, strna(setup_state), off_color_setup); if (path) - printf(" Path: %s\n", path); + printf(" Path: %s\n", path); if (driver) - printf(" Driver: %s\n", driver); + printf(" Driver: %s\n", driver); if (vendor) - printf(" Vendor: %s\n", vendor); + printf(" Vendor: %s\n", vendor); if (model) - printf(" Model: %s\n", model); + printf(" Model: %s\n", model); if (have_mac) { _cleanup_free_ char *description = NULL; @@ -634,30 +637,35 @@ static int link_status_one( ieee_oui(hwdb, &e, &description); if (description) - printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description); + printf(" HW Address: %s (%s)\n", ether_addr_to_string(&e, ea), description); else - printf(" HW Address: %s\n", ether_addr_to_string(&e, ea)); + printf(" HW Address: %s\n", ether_addr_to_string(&e, ea)); } if (mtu > 0) - printf(" MTU: %u\n", mtu); + printf(" MTU: %u\n", mtu); - dump_addresses(rtnl, " Address: ", ifindex); - dump_gateways(rtnl, hwdb, " Gateway: ", ifindex); + dump_addresses(rtnl, " Address: ", ifindex); + dump_gateways(rtnl, hwdb, " Gateway: ", ifindex); if (!strv_isempty(dns)) - dump_list(" DNS: ", dns); + dump_list(" DNS: ", dns); if (!strv_isempty(domains)) - dump_list(" Domain: ", domains); + dump_list(" Domain: ", domains); if (!strv_isempty(ntp)) - dump_list(" NTP: ", ntp); + dump_list(" NTP: ", ntp); + + if (!strv_isempty(carrier_bound_to)) + dump_list("Carrier Bound To: ", carrier_bound_to); + + if (!strv_isempty(carrier_bound_by)) + dump_list("Carrier Bound By: ", carrier_bound_by); return 0; } static int link_status(int argc, char *argv[], void *userdata) { _cleanup_hwdb_unref_ sd_hwdb *hwdb = NULL; - _cleanup_udev_unref_ struct udev *udev = NULL; _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; char **name; int r; @@ -666,10 +674,6 @@ static int link_status(int argc, char *argv[], void *userdata) { if (r < 0) return log_error_errno(r, "Failed to connect to netlink: %m"); - udev = udev_new(); - if (!udev) - return log_error_errno(errno, "Failed to connect to udev: %m"); - r = sd_hwdb_new(&hwdb); if (r < 0) log_debug_errno(r, "Failed to open hardware database: %m"); @@ -731,14 +735,14 @@ static int link_status(int argc, char *argv[], void *userdata) { if (i > 0) fputc('\n', stdout); - link_status_one(rtnl, udev, hwdb, links[i].name); + link_status_one(rtnl, hwdb, links[i].name); } } else { STRV_FOREACH(name, argv + 1) { if (name != argv + 1) fputc('\n', stdout); - link_status_one(rtnl, udev, hwdb, *name); + link_status_one(rtnl, hwdb, *name); } } @@ -954,17 +958,17 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) { continue; if (streq(a, "_Chassis")) { - chassis = strdup(b); - if (!chassis) - return -ENOMEM; + r = free_and_strdup(&chassis, b); + if (r < 0) + return r; } else if (streq(a, "_Port")) { - port = strdup(b); - if (!port) - return -ENOMEM; + r = free_and_strdup(&port, b); + if (r < 0) + return r; } else if (streq(a, "_TTL")) { - long long unsigned x; + long long unsigned x = 0; usec_t time; r = safe_atollu(b, &x); diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c index 7ad11c6177..584a956a7e 100644 --- a/src/network/networkd-address-pool.c +++ b/src/network/networkd-address-pool.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <arpa/inet.h> #include "networkd.h" #include "networkd-link.h" diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c index 47033acde4..069ba3eccb 100644 --- a/src/network/networkd-address.c +++ b/src/network/networkd-address.c @@ -25,7 +25,6 @@ #include "util.h" #include "conf-parser.h" #include "fw-util.h" -#include "network-internal.h" #include "networkd.h" #include "networkd-link.h" @@ -210,10 +209,18 @@ int address_update(Address *address, Link *link, if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); - r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + address->flags |= IFA_F_PERMANENT; + + r = sd_rtnl_message_addr_set_flags(req, address->flags & 0xff); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); + if (address->flags & ~0xff && link->rtnl_extended_attrs) { + r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags); + if (r < 0) + return log_error_errno(r, "Could not set extended flags: %m"); + } + r = sd_rtnl_message_addr_set_scope(req, address->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); @@ -267,10 +274,8 @@ static int address_acquire(Link *link, Address *original, Address **ret) { /* The address is configured to be 0.0.0.0 or [::] by the user? * Then let's acquire something more useful from the pool. */ r = manager_address_pool_acquire(link->manager, original->family, original->prefixlen, &in_addr); - if (r < 0) { - log_link_error(link, "Failed to acquire address from pool: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Failed to acquire address from pool: %m"); if (r == 0) { log_link_error(link, "Couldn't find free address for interface, all taken."); return -EBUSY; @@ -336,10 +341,18 @@ int address_configure(Address *address, Link *link, if (r < 0) return log_error_errno(r, "Could not set prefixlen: %m"); - r = sd_rtnl_message_addr_set_flags(req, IFA_F_PERMANENT); + address->flags |= IFA_F_PERMANENT; + + r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff)); if (r < 0) return log_error_errno(r, "Could not set flags: %m"); + if (address->flags & ~0xff) { + r = sd_rtnl_message_append_u32(req, IFA_FLAGS, address->flags); + if (r < 0) + return log_error_errno(r, "Could not set extended flags: %m"); + } + r = sd_rtnl_message_addr_set_scope(req, address->scope); if (r < 0) return log_error_errno(r, "Could not set scope: %m"); diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index c3d0e3d39d..20aee53d6e 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -22,6 +22,7 @@ #include <netinet/ether.h> #include <linux/if.h> +#include "hostname-util.h" #include "networkd-link.h" #include "network-internal.h" #include "dhcp-lease-internal.h" @@ -409,62 +410,43 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { assert(link); r = sd_dhcp_client_get_lease(client, &lease); - if (r < 0) { - log_link_warning(link, "DHCP error: no lease: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: no lease: %m"); r = sd_dhcp_lease_get_address(lease, &address); - if (r < 0) { - log_link_warning(link, "DHCP error: no address: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: no address: %m"); r = sd_dhcp_lease_get_netmask(lease, &netmask); - if (r < 0) { - log_link_warning(link, "DHCP error: no netmask: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "DHCP error: no netmask: %m"); prefixlen = in_addr_netmask_to_prefixlen(&netmask); r = sd_dhcp_lease_get_router(lease, &gateway); - if (r < 0 && r != -ENOENT) { - log_link_warning(link, "DHCP error: could not get gateway: %s", - strerror(-r)); - return r; - } + if (r < 0 && r != -ENOENT) + return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m"); if (r >= 0) - log_link_struct(link, LOG_INFO, - "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", - IFNAMSIZ, - link->ifname, - ADDRESS_FMT_VAL(address), - prefixlen, - ADDRESS_FMT_VAL(gateway), - "ADDRESS=%u.%u.%u.%u", - ADDRESS_FMT_VAL(address), - "PREFIXLEN=%u", - prefixlen, - "GATEWAY=%u.%u.%u.%u", - ADDRESS_FMT_VAL(gateway), - NULL); + log_struct(LOG_INFO, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u via %u.%u.%u.%u", + ADDRESS_FMT_VAL(address), + prefixlen, + ADDRESS_FMT_VAL(gateway)), + "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), + "PREFIXLEN=%u", prefixlen, + "GATEWAY=%u.%u.%u.%u", ADDRESS_FMT_VAL(gateway), + NULL); else - log_link_struct(link, LOG_INFO, - "MESSAGE=%-*s: DHCPv4 address %u.%u.%u.%u/%u", - IFNAMSIZ, - link->ifname, - ADDRESS_FMT_VAL(address), - prefixlen, - "ADDRESS=%u.%u.%u.%u", - ADDRESS_FMT_VAL(address), - "PREFIXLEN=%u", - prefixlen, - NULL); + log_struct(LOG_INFO, + LOG_LINK_INTERFACE(link), + LOG_LINK_MESSAGE(link, "DHCPv4 address %u.%u.%u.%u/%u", + ADDRESS_FMT_VAL(address), + prefixlen), + "ADDRESS=%u.%u.%u.%u", ADDRESS_FMT_VAL(address), + "PREFIXLEN=%u", prefixlen, + NULL); link->dhcp_lease = lease; @@ -475,8 +457,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { if (r >= 0) { r = link_set_mtu(link, mtu); if (r < 0) - log_link_error(link, "Failed to set MTU " - "to %" PRIu16, mtu); + log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu); } } @@ -487,27 +468,21 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { if (r >= 0) { r = link_set_hostname(link, hostname); if (r < 0) - log_link_error(link, - "Failed to set transient hostname to '%s'", - hostname); + log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname); } } if (!link->network->dhcp_critical) { - r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, - &lifetime); + r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); if (r < 0) { - log_link_warning(link, - "DHCP error: no lifetime: %s", - strerror(-r)); + log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); return r; } } r = dhcp4_update_address(link, &address, &netmask, lifetime); if (r < 0) { - log_link_warning(link, "could not update IP address: %s", - strerror(-r)); + log_link_warning_errno(link, r, "Could not update IP address: %m"); link_enter_failed(link); return r; } @@ -661,5 +636,21 @@ int dhcp4_configure(Link *link) { return r; } + switch (link->network->dhcp_client_identifier) { + case DHCP_CLIENT_ID_DUID: + /* Library defaults to this. */ + break; + case DHCP_CLIENT_ID_MAC: + r = sd_dhcp_client_set_client_id(link->dhcp_client, + ARPHRD_ETHER, + (const uint8_t *) &link->mac, + sizeof (link->mac)); + if (r < 0) + return r; + break; + default: + assert_not_reached("Unknown client identifier type."); + } + return 0; } diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index bcfad4c03f..33e18137d2 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -28,6 +28,8 @@ #include "sd-icmp6-nd.h" #include "sd-dhcp6-client.h" +static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link); + static int dhcp6_lease_information_acquired(sd_dhcp6_client *client, Link *link) { return 0; @@ -42,6 +44,15 @@ static int dhcp6_address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) { + if (link->rtnl_extended_attrs) { + log_link_warning(link, "Could not set extended netlink attributes, reverting to fallback mechanism"); + + link->rtnl_extended_attrs = false; + dhcp6_lease_address_acquired(link->dhcp6_client, link); + + return 1; + } + log_link_error(link, "Could not set DHCPv6 address: %s", strerror(-r)); @@ -65,61 +76,25 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr, addr->family = AF_INET6; memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); + + addr->flags = IFA_F_NOPREFIXROUTE; addr->prefixlen = prefixlen; addr->cinfo.ifa_prefered = lifetime_preferred; addr->cinfo.ifa_valid = lifetime_valid; - log_link_struct(link, LOG_INFO, "MESSAGE=%-*s: DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d", - IFNAMSIZ, - link->ifname, SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6), - addr->prefixlen, lifetime_preferred, lifetime_valid, - NULL); + log_link_info(link, + "DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d", + SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6), + addr->prefixlen, lifetime_preferred, lifetime_valid); r = address_update(addr, link, dhcp6_address_handler); if (r < 0) - log_link_warning(link, "Could not assign DHCPv6 address: %s", - strerror(-r)); + log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); return r; } -static int dhcp6_prefix_expired(Link *link) { - int r; - sd_dhcp6_lease *lease; - struct in6_addr *expired_prefix, ip6_addr; - uint8_t expired_prefixlen; - uint32_t lifetime_preferred, lifetime_valid; - - r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery, - &expired_prefix, &expired_prefixlen); - if (r < 0) - return r; - - r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease); - if (r < 0) - return r; - - sd_dhcp6_lease_reset_address_iter(lease); - - while (sd_dhcp6_lease_get_address(lease, &ip6_addr, - &lifetime_preferred, - &lifetime_valid) >= 0) { - - r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen, - &ip6_addr); - if (r >= 0) { - r = dhcp6_address_update(link, &ip6_addr, 128, - lifetime_preferred, - lifetime_valid); - - return r; - } - } - - return 0; -} - static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { int r; sd_dhcp6_lease *lease; @@ -296,6 +271,45 @@ static int dhcp6_configure(Link *link, int event) { return r; } +static int dhcp6_prefix_expired(Link *link) { + int r; + sd_dhcp6_lease *lease; + struct in6_addr *expired_prefix, ip6_addr; + uint8_t expired_prefixlen; + uint32_t lifetime_preferred, lifetime_valid; + + r = sd_icmp6_ra_get_expired_prefix(link->icmp6_router_discovery, + &expired_prefix, &expired_prefixlen); + if (r < 0) + return r; + + r = sd_dhcp6_client_get_lease(link->dhcp6_client, &lease); + if (r < 0) + return r; + + log_link_info(link, "IPv6 prefix "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired", + SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix), + expired_prefixlen); + + sd_dhcp6_lease_reset_address_iter(lease); + + while (sd_dhcp6_lease_get_address(lease, &ip6_addr, + &lifetime_preferred, + &lifetime_valid) >= 0) { + + r = sd_icmp6_prefix_match(expired_prefix, expired_prefixlen, + &ip6_addr); + if (r < 0) + continue; + + log_link_info(link, "IPv6 prefix length updated "SD_ICMP6_ADDRESS_FORMAT_STR"/%d", SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128); + + dhcp6_address_update(link, &ip6_addr, 128, lifetime_preferred, lifetime_valid); + } + + return 0; +} + static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { Link *link = userdata; @@ -318,7 +332,8 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) { break; case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED: - dhcp6_prefix_expired(link); + if (!link->rtnl_extended_attrs) + dhcp6_prefix_expired(link); break; diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c index feab8d421e..796d1117b6 100644 --- a/src/network/networkd-fdb.c +++ b/src/network/networkd-fdb.c @@ -19,16 +19,11 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <ctype.h> #include <net/if.h> #include <net/ethernet.h> #include "networkd.h" -#include "networkd-netdev.h" #include "networkd-link.h" -#include "network-internal.h" -#include "path-util.h" -#include "conf-files.h" #include "conf-parser.h" #include "util.h" @@ -93,7 +88,7 @@ static int set_fdb_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) - log_link_error(link, "Could not add FDB entry: %s", strerror(-r)); + log_link_error_errno(link, r, "Could not add FDB entry: %m"); return 1; } @@ -138,10 +133,8 @@ int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) { /* send message to the kernel to update its internal static MAC table. */ r = sd_rtnl_call_async(rtnl, req, set_fdb_handler, link, 0, NULL); - if (r < 0) { - log_link_error(link, "Could not send rtnetlink message: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); return 0; } @@ -155,9 +148,9 @@ void fdb_entry_free(FdbEntry *fdb_entry) { LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); - if(fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, - UINT_TO_PTR(fdb_entry->section)); + if (fdb_entry->section) + hashmap_remove(fdb_entry->network->fdb_entries_by_section, + UINT_TO_PTR(fdb_entry->section)); } free(fdb_entry->mac_addr); @@ -166,16 +159,18 @@ void fdb_entry_free(FdbEntry *fdb_entry) { } /* parse the HW address from config files. */ -int config_parse_fdb_hwaddr(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_fdb_hwaddr( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; int r; @@ -187,10 +182,8 @@ int config_parse_fdb_hwaddr(const char *unit, assert(data); r = fdb_entry_new_static(network, section_line, &fdb_entry); - if (r < 0) { - log_error("Failed to allocate a new FDB entry: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_oom(); /* read in the MAC address for the FDB table. */ r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", @@ -201,9 +194,8 @@ int config_parse_fdb_hwaddr(const char *unit, &fdb_entry->mac_addr->ether_addr_octet[4], &fdb_entry->mac_addr->ether_addr_octet[5]); - if (ETHER_ADDR_LEN != r) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Not a valid MAC address, ignoring assignment: %s", rvalue); + if (ETHER_ADDR_LEN != r) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not a valid MAC address, ignoring assignment: %s", rvalue); return 0; } @@ -213,16 +205,18 @@ int config_parse_fdb_hwaddr(const char *unit, } /* parse the VLAN Id from config files. */ -int config_parse_fdb_vlan_id(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_fdb_vlan_id( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Network *network = userdata; _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; int r; @@ -234,18 +228,14 @@ int config_parse_fdb_vlan_id(const char *unit, assert(data); r = fdb_entry_new_static(network, section_line, &fdb_entry); - if (r < 0) { - log_error("Failed to allocate a new FDB entry: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_oom(); r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &fdb_entry->vlan_id, userdata); - if (r < 0) { - log_error("Failed to parse the unsigned integer: %s", strerror(-r)); + if (r < 0) return r; - } fdb_entry = NULL; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index f716e8231a..b30fd7ae89 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -26,14 +26,12 @@ #include "util.h" #include "virt.h" #include "fileio.h" +#include "socket-util.h" #include "bus-util.h" #include "udev-util.h" -#include "libudev-private.h" #include "network-internal.h" #include "networkd-link.h" #include "networkd-netdev.h" -#include "conf-parser.h" -#include "dhcp-lease-internal.h" bool link_dhcp6_enabled(Link *link) { if (link->flags & IFF_LOOPBACK) @@ -131,10 +129,8 @@ static int link_update_flags(Link *link, sd_rtnl_message *m) { assert(link); r = sd_rtnl_message_link_get_flags(m, &flags); - if (r < 0) { - log_link_warning(link, "Could not get link flags"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not get link flags: %m"); r = sd_rtnl_message_read_u8(m, IFLA_OPERSTATE, &operstate); if (r < 0) @@ -146,7 +142,7 @@ static int link_update_flags(Link *link, sd_rtnl_message *m) { return 0; if (link->flags != flags) { - log_link_debug(link, "flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + log_link_debug(link, "Flags change:%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags), FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags), FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags), @@ -180,12 +176,12 @@ static int link_update_flags(Link *link, sd_rtnl_message *m) { * printing 20 */ if (unknown_flags_added) log_link_debug(link, - "unknown link flags gained: %#.5x (ignoring)", + "Unknown link flags gained: %#.5x (ignoring)", unknown_flags_added); if (unknown_flags_removed) log_link_debug(link, - "unknown link flags lost: %#.5x (ignoring)", + "Unknown link flags lost: %#.5x (ignoring)", unknown_flags_removed); } @@ -230,6 +226,7 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { link->n_ref = 1; link->manager = manager; link->state = LINK_STATE_PENDING; + link->rtnl_extended_attrs = true; link->ifindex = ifindex; link->ifname = strdup(ifname); if (!link->ifname) @@ -275,6 +272,8 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) { static void link_free(Link *link) { Address *address; + Iterator i; + Link *carrier; if (!link) return; @@ -312,6 +311,14 @@ static void link_free(Link *link) { udev_device_unref(link->udev_device); + HASHMAP_FOREACH (carrier, link->bound_to_links, i) + hashmap_remove(link->bound_to_links, INT_TO_PTR(carrier->ifindex)); + hashmap_free(link->bound_to_links); + + HASHMAP_FOREACH (carrier, link->bound_by_links, i) + hashmap_remove(link->bound_by_links, INT_TO_PTR(carrier->ifindex)); + hashmap_free(link->bound_by_links); + free(link); } @@ -358,23 +365,10 @@ static void link_set_state(Link *link, LinkState state) { return; } -void link_drop(Link *link) { - if (!link || link->state == LINK_STATE_LINGER) - return; - - link_set_state(link, LINK_STATE_LINGER); - - log_link_debug(link, "link removed"); - - link_unref(link); - - return; -} - static void link_enter_unmanaged(Link *link) { assert(link); - log_link_debug(link, "unmanaged"); + log_link_debug(link, "Unmanaged"); link_set_state(link, LINK_STATE_UNMANAGED); @@ -393,50 +387,32 @@ static int link_stop_clients(Link *link) { if (link->dhcp_client) { k = sd_dhcp_client_stop(link->dhcp_client); - if (k < 0) { - log_link_warning(link, "Could not stop DHCPv4 client: %s", - strerror(-r)); - r = k; - } + if (k < 0) + r = log_link_warning_errno(link, r, "Could not stop DHCPv4 client: %m"); } if (link->ipv4ll) { k = sd_ipv4ll_stop(link->ipv4ll); - if (k < 0) { - log_link_warning(link, "Could not stop IPv4 link-local: %s", - strerror(-r)); - r = k; - } + if (k < 0) + r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m"); } if(link->icmp6_router_discovery) { - if (link->dhcp6_client) { k = sd_dhcp6_client_stop(link->dhcp6_client); - if (k < 0) { - log_link_warning(link, "Could not stop DHCPv6 client: %s", - strerror(-r)); - r = k; - } + if (k < 0) + r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m"); } k = sd_icmp6_nd_stop(link->icmp6_router_discovery); - if (k < 0) { - log_link_warning(link, - "Could not stop ICMPv6 router discovery: %s", - strerror(-r)); - r = k; - } + if (k < 0) + r = log_link_warning_errno(link, r, "Could not stop ICMPv6 router discovery: %m"); } if (link->lldp) { - k = sd_lldp_stop(link->lldp); - if (k < 0) { - log_link_warning(link, "Could not stop LLDP : %s", - strerror(-r)); - r = k; - } + if (k < 0) + r = log_link_warning_errno(link, r, "Could not stop LLDP: %m"); } return r; @@ -448,7 +424,7 @@ void link_enter_failed(Link *link) { if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) return; - log_link_warning(link, "failed"); + log_link_warning(link, "Failed"); link_set_state(link, LINK_STATE_FAILED); @@ -491,7 +467,7 @@ static int link_enter_configured(Link *link) { assert(link->network); assert(link->state == LINK_STATE_SETTING_ROUTES); - log_link_info(link, "link configured"); + log_link_info(link, "Configured"); link_set_state(link, LINK_STATE_CONFIGURED); @@ -537,10 +513,10 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, -r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname); if (link->link_messages == 0) { - log_link_debug(link, "routes set"); + log_link_debug(link, "Routes set"); link->static_configured = true; link_client_handler(link); } @@ -561,9 +537,7 @@ static int link_enter_set_routes(Link *link) { LIST_FOREACH(routes, rt, link->network->static_routes) { r = route_configure(rt, link, &route_handler); if (r < 0) { - log_link_warning(link, - "could not set routes: %s", - strerror(-r)); + log_link_warning_errno(link, r, "Could not set routes: %m"); link_enter_failed(link); return r; } @@ -575,7 +549,7 @@ static int link_enter_set_routes(Link *link) { link->static_configured = true; link_client_handler(link); } else - log_link_debug(link, "setting routes"); + log_link_debug(link, "Setting routes"); return 0; } @@ -593,7 +567,7 @@ int link_route_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -ESRCH) - log_link_warning_errno(link, -r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname); return 1; } @@ -617,12 +591,12 @@ static int address_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, -r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname); else if (r >= 0) link_rtnl_process_address(rtnl, m, link->manager); if (link->link_messages == 0) { - log_link_debug(link, "addresses set"); + log_link_debug(link, "Addresses set"); link_enter_set_routes(link); } @@ -658,8 +632,7 @@ static int link_enter_set_addresses(Link *link) { address = link_find_dhcp_server_address(link); if (!address) { - log_link_warning(link, - "Failed to find suitable address for DHCPv4 server instance."); + log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance."); link_enter_failed(link); return 0; } @@ -691,21 +664,20 @@ static int link_enter_set_addresses(Link *link) { r = sd_dhcp_server_start(link->dhcp_server); if (r < 0) { - log_link_warning(link, "could not start DHCPv4 server " - "instance: %s", strerror(-r)); + log_link_warning_errno(link, r, "Could not start DHCPv4 server instance: %m"); link_enter_failed(link); return 0; } - log_link_debug(link, "offering DHCPv4 leases"); + log_link_debug(link, "Offering DHCPv4 leases"); } - if (link->link_messages == 0) { + if (link->link_messages == 0) link_enter_set_routes(link); - } else - log_link_debug(link, "setting addresses"); + else + log_link_debug(link, "Setting addresses"); return 0; } @@ -723,7 +695,7 @@ int link_address_drop_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EADDRNOTAVAIL) - log_link_warning_errno(link, -r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname); return 1; } @@ -735,7 +707,7 @@ static int link_set_bridge_fdb(Link *const link) { LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { r = fdb_entry_configure(link, fdb_entry); if(r < 0) { - log_link_error(link, "Failed to add MAC entry to static MAC table: %s", strerror(-r)); + log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); break; } } @@ -747,16 +719,11 @@ static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { _cleanup_link_unref_ Link *link = userdata; int r; - log_link_debug(link, "set link"); + log_link_debug(link, "Set link"); r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_struct(link, LOG_ERR, - "MESSAGE=%-*s: could not join netdev: %s", - IFNAMSIZ, - link->ifname, strerror(-r), - "ERRNO=%d", -r, - NULL); + log_link_error_errno(link, r, "Could not join netdev: %m"); link_enter_failed(link); return 1; } @@ -764,11 +731,11 @@ static int link_set_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { return 0; } -static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, - sd_bus_error *ret_error) { +static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { _cleanup_link_unref_ Link *link = userdata; int r; + assert(m); assert(link); if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) @@ -776,8 +743,7 @@ static int set_hostname_handler(sd_bus *bus, sd_bus_message *m, void *userdata, r = sd_bus_message_get_errno(m); if (r > 0) - log_link_warning(link, "Could not set hostname: %s", - strerror(r)); + log_link_warning_errno(link, r, "Could not set hostname: %m"); return 1; } @@ -794,8 +760,7 @@ int link_set_hostname(Link *link, const char *hostname) { if (!link->manager->bus) { /* TODO: replace by assert when we can rely on kdbus */ - log_link_info(link, - "Not connected to system bus, ignoring transient hostname."); + log_link_info(link, "Not connected to system bus, ignoring transient hostname."); return 0; } @@ -815,11 +780,8 @@ int link_set_hostname(Link *link, const char *hostname) { r = sd_bus_call_async(link->manager->bus, NULL, m, set_hostname_handler, link, 0); - if (r < 0) { - log_link_error(link, "Could not set transient hostname: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not set transient hostname: %m"); link_ref(link); @@ -839,7 +801,7 @@ static int set_mtu_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { r = sd_rtnl_message_get_errno(m); if (r < 0) - log_link_warning_errno(link, -r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname); + log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname); return 1; } @@ -852,29 +814,19 @@ int link_set_mtu(Link *link, uint32_t mtu) { assert(link->manager); assert(link->manager->rtnl); - log_link_debug(link, "setting MTU: %" PRIu32, mtu); + log_link_debug(link, "Setting MTU: %" PRIu32, mtu); - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, - RTM_SETLINK, link->ifindex); - if (r < 0) { - log_link_error(link, "Could not allocate RTM_SETLINK message"); - return r; - } + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_append_u32(req, IFLA_MTU, mtu); - if (r < 0) { - log_link_error(link, "Could not append MTU: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not append MTU: %m"); - r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, - 0, NULL); - if (r < 0) { - log_link_error(link, - "Could not send rtnetlink message: %s", - strerror(-r)); - return r; - } + r = sd_rtnl_call_async(link->manager->rtnl, req, set_mtu_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); @@ -891,53 +843,31 @@ static int link_set_bridge(Link *link) { if(link->network->cost == 0) return 0; - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, - RTM_SETLINK, link->ifindex); - if (r < 0) { - log_link_error(link, "Could not allocate RTM_SETLINK message"); - return r; - } + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_link_set_family(req, PF_BRIDGE); - if (r < 0) { - log_link_error(link, - "Could not set message family %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not set message family: %m"); r = sd_rtnl_message_open_container(req, IFLA_PROTINFO); - if (r < 0) { - log_link_error(link, - "Could not append IFLA_PROTINFO attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); if(link->network->cost != 0) { r = sd_rtnl_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); - if (r < 0) { - log_link_error(link, - "Could not append IFLA_BRPORT_COST attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); } r = sd_rtnl_message_close_container(req); - if (r < 0) { - log_link_error(link, - "Could not append IFLA_LINKINFO attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_rtnl_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL); - if (r < 0) { - log_link_error(link, - "Could not send rtnetlink message: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); link_ref(link); @@ -957,7 +887,7 @@ static void lldp_handler(sd_lldp *lldp, int event, void *userdata) { r = sd_lldp_save(link->lldp, link->lldp_file); if (r < 0) - log_link_warning(link, "could not save LLDP"); + log_link_warning_errno(link, r, "Could not save LLDP: %m"); } @@ -972,40 +902,31 @@ static int link_acquire_conf(Link *link) { if (link_ipv4ll_enabled(link)) { assert(link->ipv4ll); - log_link_debug(link, "acquiring IPv4 link-local address"); + log_link_debug(link, "Acquiring IPv4 link-local address"); r = sd_ipv4ll_start(link->ipv4ll); - if (r < 0) { - log_link_warning(link, "could not acquire IPv4 " - "link-local address"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m"); } if (link_dhcp4_enabled(link)) { assert(link->dhcp_client); - log_link_debug(link, "acquiring DHCPv4 lease"); + log_link_debug(link, "Acquiring DHCPv4 lease"); r = sd_dhcp_client_start(link->dhcp_client); - if (r < 0) { - log_link_warning(link, "could not acquire DHCPv4 " - "lease"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m"); } if (link_dhcp6_enabled(link)) { assert(link->icmp6_router_discovery); - log_link_debug(link, "discovering IPv6 routers"); + log_link_debug(link, "Discovering IPv6 routers"); r = sd_icmp6_router_solicitation_start(link->icmp6_router_discovery); - if (r < 0) { - log_link_warning(link, - "could not start IPv6 router discovery"); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not start IPv6 router discovery: %m"); } if (link_lldp_enabled(link)) { @@ -1014,10 +935,8 @@ static int link_acquire_conf(Link *link) { log_link_debug(link, "Starting LLDP"); r = sd_lldp_start(link->lldp); - if (r < 0) { - log_link_warning(link, "could not start LLDP "); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not start LLDP: %m"); } return 0; @@ -1047,11 +966,10 @@ static int link_up_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { return 1; r = sd_rtnl_message_get_errno(m); - if (r < 0) { - /* we warn but don't fail the link, as it may - be brought up later */ - log_link_warning_errno(link, -r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname); - } + if (r < 0) + /* we warn but don't fail the link, as it may be + brought up later */ + log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname); return 1; } @@ -1066,98 +984,370 @@ static int link_up(Link *link) { assert(link->manager); assert(link->manager->rtnl); - log_link_debug(link, "bringing link up"); + log_link_debug(link, "Bringing link up"); - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, - RTM_SETLINK, link->ifindex); - if (r < 0) { - log_link_error(link, "Could not allocate RTM_SETLINK message"); - return r; - } + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); - if (r < 0) { - log_link_error(link, "Could not set link flags: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); if (link->network->mac) { r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac); - if (r < 0) { - log_link_error(link, "Could not set MAC address: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not set MAC address: %m"); } if (link->network->mtu) { r = sd_rtnl_message_append_u32(req, IFLA_MTU, link->network->mtu); - if (r < 0) { - log_link_error(link, "Could not set MTU: %s", strerror(-r)); - return r; - } + if (r < 0) + return log_link_error_errno(link, r, "Could not set MTU: %m"); } r = sd_rtnl_message_open_container(req, IFLA_AF_SPEC); - if (r < 0) { - log_link_error(link, "Could not open IFLA_AF_SPEC container: %s", strerror(-r)); - return r; + if (r < 0) + return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); + + if (socket_ipv6_is_supported()) { + /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */ + r = sd_rtnl_message_open_container(req, AF_INET6); + if (r < 0) + return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m"); + + ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE; + r = sd_rtnl_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m"); + + if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) { + r = sd_rtnl_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6); + if (r < 0) + return log_link_error_errno(link, r, "Could not append IFLA_INET6_TOKEN: %m"); + } + + r = sd_rtnl_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m"); } - r = sd_rtnl_message_open_container(req, AF_INET6); - if (r < 0) { - log_link_error(link, "Could not open AF_INET6 container: %s", strerror(-r)); - return r; + r = sd_rtnl_message_close_container(req); + if (r < 0) + return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); + + r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_down_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) { + _cleanup_link_unref_ Link *link = userdata; + int r; + + assert(link); + + if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) + return 1; + + r = sd_rtnl_message_get_errno(m); + if (r < 0) + log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname); + + return 1; +} + +static int link_down(Link *link) { + _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL; + int r; + + assert(link); + assert(link->manager); + assert(link->manager->rtnl); + + log_link_debug(link, "Bringing link down"); + + r = sd_rtnl_message_new_link(link->manager->rtnl, &req, + RTM_SETLINK, link->ifindex); + if (r < 0) + return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); + + r = sd_rtnl_message_link_set_flags(req, 0, IFF_UP); + if (r < 0) + return log_link_error_errno(link, r, "Could not set link flags: %m"); + + r = sd_rtnl_call_async(link->manager->rtnl, req, link_down_handler, link, 0, NULL); + if (r < 0) + return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); + + link_ref(link); + + return 0; +} + +static int link_handle_bound_to_list(Link *link) { + Link *l; + Iterator i; + int r; + bool required_up = false; + bool link_is_up = false; + + assert(link); + + if (hashmap_isempty(link->bound_to_links)) + return 0; + + if (link->flags & IFF_UP) + link_is_up = true; + + HASHMAP_FOREACH (l, link->bound_to_links, i) + if (link_has_carrier(l)) { + required_up = true; + break; + } + + if (!required_up && link_is_up) { + r = link_down(link); + if (r < 0) + return r; + } else if (required_up && !link_is_up) { + r = link_up(link); + if (r < 0) + return r; } - ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE; - r = sd_rtnl_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode); - if (r < 0) { - log_link_error(link, "Could not append IFLA_INET6_ADDR_GEN_MODE: %s", strerror(-r)); + return 0; +} + +static int link_handle_bound_by_list(Link *link) { + Iterator i; + Link *l; + int r; + + assert(link); + + if (hashmap_isempty(link->bound_by_links)) + return 0; + + HASHMAP_FOREACH (l, link->bound_by_links, i) { + r = link_handle_bound_to_list(l); + if (r < 0) + return r; + } + + return 0; +} + +static int link_put_carrier(Link *link, Link *carrier, Hashmap **h) { + int r; + + assert(link); + assert(carrier); + + if (link == carrier) + return 0; + + if (hashmap_get(*h, INT_TO_PTR(carrier->ifindex))) + return 0; + + r = hashmap_ensure_allocated(h, NULL); + if (r < 0) + return r; + + r = hashmap_put(*h, INT_TO_PTR(carrier->ifindex), carrier); + if (r < 0) return r; + + return 0; +} + +static int link_new_bound_by_list(Link *link) { + Manager *m; + Link *carrier; + Iterator i; + int r; + bool list_updated = false; + + assert(link); + assert(link->manager); + + m = link->manager; + + HASHMAP_FOREACH (carrier, m->links, i) { + if (!carrier->network) + continue; + + if (strv_isempty(carrier->network->bind_carrier)) + continue; + + if (strv_fnmatch(carrier->network->bind_carrier, link->ifname, 0)) { + r = link_put_carrier(link, carrier, &link->bound_by_links); + if (r < 0) + return r; + + list_updated = true; + } } - if (!in_addr_is_null(AF_INET6, &link->network->ipv6_token)) { - r = sd_rtnl_message_append_in6_addr(req, IFLA_INET6_TOKEN, &link->network->ipv6_token.in6); - if (r < 0) { - log_link_error(link, "Could not append IFLA_INET6_TOKEN: %s", strerror(-r)); + if (list_updated) + link_save(link); + + HASHMAP_FOREACH (carrier, link->bound_by_links, i) { + r = link_put_carrier(carrier, link, &carrier->bound_to_links); + if (r < 0) return r; + + link_save(carrier); + } + + return 0; +} + +static int link_new_bound_to_list(Link *link) { + Manager *m; + Link *carrier; + Iterator i; + int r; + bool list_updated = false; + + assert(link); + assert(link->manager); + + if (!link->network) + return 0; + + if (strv_isempty(link->network->bind_carrier)) + return 0; + + m = link->manager; + + HASHMAP_FOREACH (carrier, m->links, i) { + if (strv_fnmatch(link->network->bind_carrier, carrier->ifname, 0)) { + r = link_put_carrier(link, carrier, &link->bound_to_links); + if (r < 0) + return r; + + list_updated = true; } } - r = sd_rtnl_message_close_container(req); - if (r < 0) { - log_link_error(link, "Could not close AF_INET6 container: %s", strerror(-r)); - return r; + if (list_updated) + link_save(link); + + HASHMAP_FOREACH (carrier, link->bound_to_links, i) { + r = link_put_carrier(carrier, link, &carrier->bound_by_links); + if (r < 0) + return r; + + link_save(carrier); } - r = sd_rtnl_message_close_container(req); - if (r < 0) { - log_link_error(link, "Could not close IFLA_AF_SPEC container: %s", strerror(-r)); + return 0; +} + +static int link_new_carrier_maps(Link *link) { + int r; + + r = link_new_bound_by_list(link); + if (r < 0) return r; - } - r = sd_rtnl_call_async(link->manager->rtnl, req, link_up_handler, link, - 0, NULL); - if (r < 0) { - log_link_error(link, - "Could not send rtnetlink message: %s", - strerror(-r)); + r = link_handle_bound_by_list(link); + if (r < 0) return r; - } - link_ref(link); + r = link_new_bound_to_list(link); + if (r < 0) + return r; + + r = link_handle_bound_to_list(link); + if (r < 0) + return r; return 0; } +static void link_free_bound_to_list(Link *link) { + Link *bound_to; + Iterator i; + + HASHMAP_FOREACH (bound_to, link->bound_to_links, i) { + hashmap_remove(link->bound_to_links, INT_TO_PTR(bound_to->ifindex)); + + if (hashmap_remove(bound_to->bound_by_links, INT_TO_PTR(link->ifindex))) + link_save(bound_to); + } + + return; +} + +static void link_free_bound_by_list(Link *link) { + Link *bound_by; + Iterator i; + + HASHMAP_FOREACH (bound_by, link->bound_by_links, i) { + hashmap_remove(link->bound_by_links, INT_TO_PTR(bound_by->ifindex)); + + if (hashmap_remove(bound_by->bound_to_links, INT_TO_PTR(link->ifindex))) { + link_save(bound_by); + link_handle_bound_to_list(bound_by); + } + } + + return; +} + +static void link_free_carrier_maps(Link *link) { + bool list_updated = false; + + assert(link); + + if (!hashmap_isempty(link->bound_to_links)) { + link_free_bound_to_list(link); + list_updated = true; + } + + if (!hashmap_isempty(link->bound_by_links)) { + link_free_bound_by_list(link); + list_updated = true; + } + + if (list_updated) + link_save(link); + + return; +} + +void link_drop(Link *link) { + if (!link || link->state == LINK_STATE_LINGER) + return; + + link_set_state(link, LINK_STATE_LINGER); + + link_free_carrier_maps(link); + + log_link_debug(link, "Link removed"); + + link_unref(link); + + return; +} + static int link_joined(Link *link) { int r; assert(link); assert(link->network); - if (!(link->flags & IFF_UP)) { + if (!hashmap_isempty(link->bound_to_links)) { + r = link_handle_bound_to_list(link); + if (r < 0) + return r; + } else if (!(link->flags & IFF_UP)) { r = link_up(link); if (r < 0) { link_enter_failed(link); @@ -1167,11 +1357,8 @@ static int link_joined(Link *link) { if(link->network->bridge) { r = link_set_bridge(link); - if (r < 0) { - log_link_error(link, - "Could not set bridge message: %s", - strerror(-r)); - } + if (r < 0) + log_link_error_errno(link, r, "Could not set bridge message: %m"); } return link_enter_set_addresses(link); @@ -1192,11 +1379,11 @@ static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m, r = sd_rtnl_message_get_errno(m); if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, -r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname); + log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname); link_enter_failed(link); return 1; } else - log_link_debug(link, "joined netdev"); + log_link_debug(link, "Joined netdev"); if (link->enslaving <= 0) link_joined(link); @@ -1223,22 +1410,20 @@ static int link_enter_join_netdev(Link *link) { return link_joined(link); if (link->network->bond) { - log_link_struct(link, LOG_DEBUG, - "MESSAGE=%-*s: enslaving by '%s'", - IFNAMSIZ, - link->ifname, link->network->bond->ifname, - NETDEVIF(link->network->bond), - NULL); - - r = netdev_join(link->network->bond, link, &netdev_join_handler); + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bond), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bond->ifname), + NULL); + + r = netdev_join(link->network->bond, link, netdev_join_handler); if (r < 0) { - log_link_struct(link, LOG_WARNING, - "MESSAGE=%-*s: could not join netdev '%s': %s", - IFNAMSIZ, - link->ifname, link->network->bond->ifname, - strerror(-r), - NETDEVIF(link->network->bond), - NULL); + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bond), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bond->ifname), + NULL); + link_enter_failed(link); return r; } @@ -1247,23 +1432,19 @@ static int link_enter_join_netdev(Link *link) { } if (link->network->bridge) { - log_link_struct(link, LOG_DEBUG, - "MESSAGE=%-*s: enslaving by '%s'", - IFNAMSIZ, - link->ifname, link->network->bridge->ifname, - NETDEVIF(link->network->bridge), - NULL); - - r = netdev_join(link->network->bridge, link, - &netdev_join_handler); + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bridge), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->bridge->ifname), + NULL); + + r = netdev_join(link->network->bridge, link, netdev_join_handler); if (r < 0) { - log_link_struct(link, LOG_WARNING, - "MESSAGE=%-*s: could not join netdev '%s': %s", - IFNAMSIZ, - link->ifname, link->network->bridge->ifname, - strerror(-r), - NETDEVIF(link->network->bridge), - NULL); + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(link->network->bridge), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->bridge->ifname), + NULL), link_enter_failed(link); return r; } @@ -1272,20 +1453,20 @@ static int link_enter_join_netdev(Link *link) { } HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { - log_link_struct(link, LOG_DEBUG, - "MESSAGE=%-*s: enslaving by '%s'", - IFNAMSIZ, - link->ifname, netdev->ifname, NETDEVIF(netdev), - NULL); - r = netdev_join(netdev, link, &netdev_join_handler); + log_struct(LOG_DEBUG, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Enslaving by '%s'", netdev->ifname), + NULL); + + r = netdev_join(netdev, link, netdev_join_handler); if (r < 0) { - log_link_struct(link, LOG_WARNING, - "MESSAGE=%-*s: could not join netdev '%s': %s", - IFNAMSIZ, - link->ifname, netdev->ifname, - strerror(-r), - NETDEVIF(netdev), NULL); + log_struct_errno(LOG_WARNING, r, + LOG_LINK_INTERFACE(link), + LOG_NETDEV_INTERFACE(netdev), + LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", netdev->ifname), + NULL); link_enter_failed(link); return r; } @@ -1298,39 +1479,16 @@ static int link_enter_join_netdev(Link *link) { static int link_set_ipv4_forward(Link *link) { const char *p = NULL; - bool b; int r; - b = link_ipv4_forward_enabled(link); + if (link->network->ip_forward == ADDRESS_FAMILY_KERNEL) + return 0; p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/forwarding"); - r = write_string_file_no_create(p, one_zero(b)); + r = write_string_file_no_create(p, one_zero(link_ipv4_forward_enabled(link))); if (r < 0) log_link_warning_errno(link, r, "Cannot configure IPv4 forwarding for interface %s: %m", link->ifname); - if (b) { - _cleanup_free_ char *buf = NULL; - - /* If IP forwarding is turned on for this interface, - * then propagate this to the global setting. Given - * that turning this on has side-effects on other - * fields, we'll try to avoid doing this unless - * necessary, hence check the previous value - * first. Note that we never turn this option off - * again, since all interfaces we manage do not do - * forwarding anyway by default, and ownership rules - * of this control are so unclear. */ - - r = read_one_line_file("/proc/sys/net/ipv4/ip_forward", &buf); - if (r < 0) - log_link_warning_errno(link, r, "Cannot read /proc/sys/net/ipv4/ip_forward: %m"); - else if (!streq(buf, "1")) { - r = write_string_file_no_create("/proc/sys/net/ipv4/ip_forward", "1"); - if (r < 0) - log_link_warning_errno(link, r, "Cannot write /proc/sys/net/ipv4/ip_forward: %m"); - } - } - return 0; } @@ -1338,6 +1496,13 @@ static int link_set_ipv6_forward(Link *link) { const char *p = NULL; int r; + /* Make this a NOP if IPv6 is not available */ + if (!socket_ipv6_is_supported()) + return 0; + + if (link->network->ip_forward == ADDRESS_FAMILY_KERNEL) + return 0; + p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/forwarding"); r = write_string_file_no_create(p, one_zero(link_ipv6_forward_enabled(link))); if (r < 0) @@ -1430,7 +1595,15 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, if (link->state != LINK_STATE_PENDING) return 1; - log_link_debug(link, "link state is up-to-date"); + log_link_debug(link, "Link state is up-to-date"); + + r = link_new_bound_by_list(link); + if (r < 0) + return r; + + r = link_handle_bound_by_list(link); + if (r < 0) + return r; r = network_get(link->manager, link->udev_device, link->ifname, &link->mac, &network); @@ -1442,19 +1615,23 @@ static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, if (link->flags & IFF_LOOPBACK) { if (network->link_local != ADDRESS_FAMILY_NO) - log_link_debug(link, "ignoring link-local autoconfiguration for loopback link"); + log_link_debug(link, "Ignoring link-local autoconfiguration for loopback link"); if (network->dhcp != ADDRESS_FAMILY_NO) - log_link_debug(link, "ignoring DHCP clients for loopback link"); + log_link_debug(link, "Ignoring DHCP clients for loopback link"); if (network->dhcp_server) - log_link_debug(link, "ignoring DHCP server for loopback link"); + log_link_debug(link, "Ignoring DHCP server for loopback link"); } r = network_apply(link->manager, network, link); if (r < 0) return r; + r = link_new_bound_to_list(link); + if (r < 0) + return r; + r = link_configure(link); if (r < 0) return r; @@ -1519,6 +1696,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use Link *link = NULL; uint16_t type; _cleanup_address_free_ Address *address = NULL; + unsigned char flags; Address *existing; char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; const char *valid_str = NULL; @@ -1538,13 +1716,16 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use r = sd_rtnl_message_get_type(message, &type); if (r < 0) { - log_warning("rtnl: could not get message type"); + log_warning_errno(r, "rtnl: could not get message type: %m"); + return 0; + } else if (type != RTM_NEWADDR && type != RTM_DELADDR) { + log_warning("rtnl: received unexpected message type when processing address"); return 0; } r = sd_rtnl_message_addr_get_ifindex(message, &ifindex); if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex: %m"); + log_warning_errno(r, "rtnl: could not get ifindex from address: %m"); return 0; } else if (ifindex <= 0) { log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); @@ -1566,33 +1747,34 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use r = sd_rtnl_message_addr_get_family(message, &address->family); if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received address with invalid family, ignoring"); + log_link_warning(link, "rtnl: received address with invalid family, ignoring."); return 0; } r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen); if (r < 0) { - log_link_warning(link, "rtnl: received address with invalid prefixlen, ignoring"); + log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); return 0; } r = sd_rtnl_message_addr_get_scope(message, &address->scope); if (r < 0) { - log_link_warning(link, "rtnl: received address with invalid scope, ignoring"); + log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); return 0; } - r = sd_rtnl_message_addr_get_flags(message, &address->flags); + r = sd_rtnl_message_addr_get_flags(message, &flags); if (r < 0) { - log_link_warning(link, "rtnl: received address with invalid flags, ignoring"); + log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); return 0; } + address->flags = flags; switch (address->family) { case AF_INET: r = sd_rtnl_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in); if (r < 0) { - log_link_warning(link, "rtnl: received address without valid address, ignoring"); + log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; } @@ -1601,7 +1783,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use case AF_INET6: r = sd_rtnl_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6); if (r < 0) { - log_link_warning(link, "rtnl: received address without valid address, ignoring"); + log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); return 0; } @@ -1612,7 +1794,7 @@ int link_rtnl_process_address(sd_rtnl *rtnl, sd_rtnl_message *message, void *use } if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) { - log_link_warning(link, "could not print address"); + log_link_warning(link, "Could not print address"); return 0; } @@ -1686,17 +1868,14 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) { link = *ret; - log_link_debug(link, "link %d added", link->ifindex); + log_link_debug(link, "Link %d added", link->ifindex); if (detect_container(NULL) <= 0) { /* not in a container, udev will be around */ sprintf(ifindex_str, "n%d", link->ifindex); device = udev_device_new_from_device_id(m->udev, ifindex_str); - if (!device) { - log_link_warning(link, - "could not find udev device: %m"); - return -errno; - } + if (!device) + return log_link_warning_errno(link, errno, "Could not find udev device: %m"); if (udev_device_get_is_initialized(device) <= 0) { /* not yet ready */ @@ -1732,6 +1911,10 @@ static int link_carrier_gained(Link *link) { } } + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + return 0; } @@ -1746,6 +1929,10 @@ static int link_carrier_lost(Link *link) { return r; } + r = link_handle_bound_by_list(link); + if (r < 0) + return r; + return 0; } @@ -1763,7 +1950,7 @@ int link_carrier_reset(Link *link) { if (r < 0) return r; - log_link_info(link, "reset carrier"); + log_link_info(link, "Reset carrier"); } return 0; @@ -1783,18 +1970,28 @@ int link_update(Link *link, sd_rtnl_message *m) { if (link->state == LINK_STATE_LINGER) { link_ref(link); - log_link_info(link, "link readded"); + log_link_info(link, "Link readded"); link_set_state(link, LINK_STATE_ENSLAVING); + + r = link_new_carrier_maps(link); + if (r < 0) + return r; } r = sd_rtnl_message_read_string(m, IFLA_IFNAME, &ifname); if (r >= 0 && !streq(ifname, link->ifname)) { - log_link_info(link, "renamed to %s", ifname); + log_link_info(link, "Renamed to %s", ifname); + + link_free_carrier_maps(link); free(link->ifname); link->ifname = strdup(ifname); if (!link->ifname) return -ENOMEM; + + r = link_new_carrier_maps(link); + if (r < 0) + return r; } r = sd_rtnl_message_read_u32(m, IFLA_MTU, &mtu); @@ -1802,17 +1999,14 @@ int link_update(Link *link, sd_rtnl_message *m) { link->mtu = mtu; if (!link->original_mtu) { link->original_mtu = mtu; - log_link_debug(link, "saved original MTU: %" - PRIu32, link->original_mtu); + log_link_debug(link, "Saved original MTU: %" PRIu32, link->original_mtu); } if (link->dhcp_client) { r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); if (r < 0) { - log_link_warning(link, - "Could not update MTU in DHCP client: %s", - strerror(-r)); + log_link_warning_errno(link, r, "Could not update MTU in DHCP client: %m"); return r; } } @@ -1839,12 +2033,8 @@ int link_update(Link *link, sd_rtnl_message *m) { if (link->ipv4ll) { r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); - if (r < 0) { - log_link_warning(link, - "Could not update MAC address in IPv4LL client: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); } if (link->dhcp_client) { @@ -1852,12 +2042,8 @@ int link_update(Link *link, sd_rtnl_message *m) { (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); - if (r < 0) { - log_link_warning(link, - "Could not update MAC address in DHCP client: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); } if (link->dhcp6_client) { @@ -1865,12 +2051,8 @@ int link_update(Link *link, sd_rtnl_message *m) { (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); - if (r < 0) { - log_link_warning(link, - "Could not update MAC address in DHCPv6 client: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); } } } @@ -1885,13 +2067,13 @@ int link_update(Link *link, sd_rtnl_message *m) { carrier_lost = had_carrier && !link_has_carrier(link); if (carrier_gained) { - log_link_info(link, "gained carrier"); + log_link_info(link, "Gained carrier"); r = link_carrier_gained(link); if (r < 0) return r; } else if (carrier_lost) { - log_link_info(link, "lost carrier"); + log_link_info(link, "Lost carrier"); r = link_carrier_lost(link); if (r < 0) @@ -1971,7 +2153,7 @@ int link_save(Link *link) { r = fopen_temporary(link->state_file, &f, &temp_path); if (r < 0) - return r; + goto fail; fchmod(fileno(f), 0644); @@ -2063,6 +2245,38 @@ int link_save(Link *link) { llmnr_support_to_string(link->network->llmnr)); } + if (!hashmap_isempty(link->bound_to_links)) { + Link *carrier; + Iterator i; + bool space = false; + + fputs("CARRIER_BOUND_TO=", f); + HASHMAP_FOREACH(carrier, link->bound_to_links, i) { + if (space) + fputc(' ', f); + fputs(carrier->ifname, f); + space = true; + } + + fputs("\n", f); + } + + if (!hashmap_isempty(link->bound_by_links)) { + Link *carrier; + Iterator i; + bool space = false; + + fputs("CARRIER_BOUND_BY=", f); + HASHMAP_FOREACH(carrier, link->bound_by_links, i) { + if (space) + fputc(' ', f); + fputs(carrier->ifname, f); + space = true; + } + + fputs("\n", f); + } + if (link->dhcp_lease) { assert(link->network); @@ -2100,9 +2314,12 @@ int link_save(Link *link) { return 0; fail: - log_link_error(link, "Failed to save link data to %s: %s", link->state_file, strerror(-r)); - unlink(link->state_file); - unlink(temp_path); + log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file); + (void) unlink(link->state_file); + + if (temp_path) + (void) unlink(temp_path); + return r; } diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index cec158e47d..c599952c45 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -82,9 +82,13 @@ struct Link { sd_icmp6_nd *icmp6_router_discovery; sd_dhcp6_client *dhcp6_client; + bool rtnl_extended_attrs; sd_lldp *lldp; char *lldp_file; + + Hashmap *bound_by_links; + Hashmap *bound_to_links; }; Link *link_unref(Link *link); @@ -137,14 +141,18 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); /* Macros which append INTERFACE= to the message */ -#define log_link_full(link, level, error, fmt, ...) \ - log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", link->ifname, "%-*s: " fmt, IFNAMSIZ, link->ifname, ##__VA_ARGS__) +#define log_link_full(link, level, error, ...) \ + ({ \ + Link *_l = (link); \ + _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \ + log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + }) \ -#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) -#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) -#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) -#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) -#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) +#define log_link_debug(link, ...) log_link_full(link, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_link_info(link, ...) log_link_full(link, LOG_INFO, 0, ##__VA_ARGS__) +#define log_link_notice(link, ...) log_link_full(link, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_link_warning(link, ...) log_link_full(link, LOG_WARNING, 0, ##__VA_ARGS__) +#define log_link_error(link, ...) log_link_full(link, LOG_ERR, 0, ##__VA_ARGS__) #define log_link_debug_errno(link, error, ...) log_link_full(link, LOG_DEBUG, error, ##__VA_ARGS__) #define log_link_info_errno(link, error, ...) log_link_full(link, LOG_INFO, error, ##__VA_ARGS__) @@ -152,7 +160,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); #define log_link_warning_errno(link, error, ...) log_link_full(link, LOG_WARNING, error, ##__VA_ARGS__) #define log_link_error_errno(link, error, ...) log_link_full(link, LOG_ERR, error, ##__VA_ARGS__) -#define log_link_struct(link, level, ...) log_struct(level, "INTERFACE=%s", link->ifname, __VA_ARGS__) +#define LOG_LINK_MESSAGE(link, fmt, ...) "MESSAGE=%s: " fmt, (link)->ifname, ##__VA_ARGS__ +#define LOG_LINK_INTERFACE(link) "INTERFACE=%s", (link)->ifname #define ADDRESS_FMT_VAL(address) \ be32toh((address).s_addr) >> 24, \ diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index ce97ac0778..2cc53df4b1 100644 --- a/src/network/networkd-manager.c +++ b/src/network/networkd-manager.c @@ -27,13 +27,11 @@ #include "networkd.h" #include "networkd-netdev.h" #include "networkd-link.h" -#include "network-internal.h" #include "libudev-private.h" #include "udev-util.h" #include "rtnl-util.h" #include "bus-util.h" #include "def.h" -#include "mkdir.h" #include "virt.h" #include "sd-rtnl.h" @@ -107,12 +105,11 @@ static int manager_reset_all(Manager *m) { return 0; } -static int match_prepare_for_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { +static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { Manager *m = userdata; int b, r; - assert(bus); - assert(bus); + assert(message); r = sd_bus_message_read(message, "b", &b); if (r < 0) { @@ -301,11 +298,14 @@ static int manager_rtnl_process_link(sd_rtnl *rtnl, sd_rtnl_message *message, vo if (r < 0) { log_warning_errno(r, "rtnl: could not get message type: %m"); return 0; + } else if (type != RTM_NEWLINK && type != RTM_DELLINK) { + log_warning("rtnl: received unexpected message type when processing link"); + return 0; } r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex: %m"); + log_warning_errno(r, "rtnl: could not get ifindex from link: %m"); return 0; } else if (ifindex <= 0) { log_warning("rtnl: received link message with invalid ifindex: %d", ifindex); @@ -853,6 +853,8 @@ const char *address_family_boolean_to_string(AddressFamilyBoolean b) { return "ipv4"; if (b == ADDRESS_FAMILY_IPV6) return "ipv6"; + if (b == ADDRESS_FAMILY_KERNEL) + return "kernel"; return NULL; } @@ -872,6 +874,8 @@ AddressFamilyBoolean address_family_boolean_from_string(const char *s) { return ADDRESS_FAMILY_IPV4; if (streq(s, "ipv6")) return ADDRESS_FAMILY_IPV6; + if (streq(s, "kernel")) + return ADDRESS_FAMILY_KERNEL; return _ADDRESS_FAMILY_BOOLEAN_INVALID; } diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index 88321ef84c..70df08a5e1 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -21,14 +21,45 @@ ***/ #include <netinet/ether.h> -#include <arpa/inet.h> #include <linux/if_bonding.h> #include "conf-parser.h" #include "sd-rtnl.h" +#include "rtnl-types.h" #include "networkd-netdev-bond.h" #include "missing.h" +/* + * Number of seconds between instances where the bonding + * driver sends learning packets to each slaves peer switch + */ +#define LEARNING_PACKETS_INTERVAL_MIN_SEC (1 * USEC_PER_SEC) +#define LEARNING_PACKETS_INTERVAL_MAX_SEC (0x7fffffff * USEC_PER_SEC) + +/* Number of IGMP membership reports to be issued after + * a failover event. + */ +#define RESEND_IGMP_MIN 0 +#define RESEND_IGMP_MAX 255 +#define RESEND_IGMP_DEFAULT 1 + +/* + * Number of packets to transmit through a slave before + * moving to the next one. + */ +#define PACKETS_PER_SLAVE_MIN 0 +#define PACKETS_PER_SLAVE_MAX 65535 +#define PACKETS_PER_SLAVE_DEFAULT 1 + +/* + * Number of peer notifications (gratuitous ARPs and + * unsolicited IPv6 Neighbor Advertisements) to be issued after a + * failover event. + */ +#define GRATUITOUS_ARP_MIN 0 +#define GRATUITOUS_ARP_MAX 255 +#define GRATUITOUS_ARP_DEFAULT 1 + static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = { [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr", [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup", @@ -42,7 +73,6 @@ static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode"); - static const char* const bond_xmit_hash_policy_table[_NETDEV_BOND_XMIT_HASH_POLICY_MAX] = { [NETDEV_BOND_XMIT_HASH_POLICY_LAYER2] = "layer2", [NETDEV_BOND_XMIT_HASH_POLICY_LAYER34] = "layer3+4", @@ -65,6 +95,51 @@ static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = { DEFINE_STRING_TABLE_LOOKUP(bond_lacp_rate, BondLacpRate); DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_lacp_rate, bond_lacp_rate, BondLacpRate, "Failed to parse bond lacp rate") +static const char* const bond_ad_select_table[_NETDEV_BOND_AD_SELECT_MAX] = { + [NETDEV_BOND_AD_SELECT_STABLE] = "stable", + [NETDEV_BOND_AD_SELECT_BANDWIDTH] = "bandwidth", + [NETDEV_BOND_AD_SELECT_COUNT] = "count", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_ad_select, BondAdSelect); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_ad_select, bond_ad_select, BondAdSelect, "Failed to parse bond AD select"); + +static const char* const bond_fail_over_mac_table[_NETDEV_BOND_FAIL_OVER_MAC_MAX] = { + [NETDEV_BOND_FAIL_OVER_MAC_NONE] = "none", + [NETDEV_BOND_FAIL_OVER_MAC_ACTIVE] = "active", + [NETDEV_BOND_FAIL_OVER_MAC_FOLLOW] = "follow", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_fail_over_mac, BondFailOverMac); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_fail_over_mac, bond_fail_over_mac, BondFailOverMac, "Failed to parse bond fail over MAC"); + +static const char *const bond_arp_validate_table[_NETDEV_BOND_ARP_VALIDATE_MAX] = { + [NETDEV_BOND_ARP_VALIDATE_NONE] = "none", + [NETDEV_BOND_ARP_VALIDATE_ACTIVE]= "active", + [NETDEV_BOND_ARP_VALIDATE_BACKUP]= "backup", + [NETDEV_BOND_ARP_VALIDATE_ALL]= "all", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_arp_validate, BondArpValidate); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_validate, bond_arp_validate, BondArpValidate, "Failed to parse bond arp validate"); + +static const char *const bond_arp_all_targets_table[_NETDEV_BOND_ARP_ALL_TARGETS_MAX] = { + [NETDEV_BOND_ARP_ALL_TARGETS_ANY] = "any", + [NETDEV_BOND_ARP_ALL_TARGETS_ALL] = "all", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_arp_all_targets, BondArpAllTargets); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_arp_all_targets, bond_arp_all_targets, BondArpAllTargets, "Failed to parse bond Arp all targets"); + +static const char *bond_primary_reselect_table[_NETDEV_BOND_PRIMARY_RESELECT_MAX] = { + [NETDEV_BOND_PRIMARY_RESELECT_ALWAYS] = "always", + [NETDEV_BOND_PRIMARY_RESELECT_BETTER]= "better", + [NETDEV_BOND_PRIMARY_RESELECT_FAILURE]= "failure", +}; + +DEFINE_STRING_TABLE_LOOKUP(bond_primary_reselect, BondPrimaryReselect); +DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_primary_reselect, bond_primary_reselect, BondPrimaryReselect, "Failed to parse bond primary reselect"); + static uint8_t bond_mode_to_kernel(BondMode mode) { switch (mode) { case NETDEV_BOND_MODE_BALANCE_RR: @@ -105,7 +180,8 @@ static uint8_t bond_xmit_hash_policy_to_kernel(BondXmitHashPolicy policy) { static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { Bond *b = BOND(netdev); - int r; + ArpIpTarget *target = NULL; + int r, i = 0; assert(netdev); assert(!link); @@ -175,9 +251,230 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m } } + if (b->arp_interval != 0) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ARP_INTERVAL attribute: %s", + strerror(-r)); + return r; + } + } + + if ((b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC) && + (b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC)) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_LP_INTERVAL attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID && + b->mode == BOND_MODE_8023AD) { + r = sd_rtnl_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_AD_SELECT attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID && + b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) { + r = sd_rtnl_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ARP_VALIDATE attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ARP_VALIDATE attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->primary_reselect); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->resend_igmp <= RESEND_IGMP_MAX) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_RESEND_IGMP attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) { + r = sd_rtnl_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %s", + strerror(-r)); + return r; + } + } + + if (b->min_links != 0) { + r = sd_rtnl_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_MIN_LINKS attribute: %s", + strerror(-r)); + return r; + } + } + + r = sd_rtnl_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %s", + strerror(-r)); + return r; + } + + if (b->arp_interval > 0) { + if (b->n_arp_ip_targets > 0) { + + r = sd_rtnl_message_open_container(m, IFLA_BOND_ARP_IP_TARGET); + if (r < 0) { + log_netdev_error(netdev, + "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %s", + strerror(-r)); + return r; + } + + LIST_FOREACH(arp_ip_target, target, b->arp_ip_targets) { + r = sd_rtnl_message_append_u32(m, i++, target->ip.in.s_addr); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %s", + strerror(-r)); + return r; + } + } + + r = sd_rtnl_message_close_container(m); + if (r < 0) { + log_netdev_error(netdev, + "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %s", + strerror(-r)); + return r; + } + } + } + return 0; } +int config_parse_arp_ip_target_address(const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { + Bond *b = userdata; + const char *word, *state; + size_t l; + int r; + + assert(filename); + assert(lvalue); + assert(rvalue); + assert(data); + + FOREACH_WORD_QUOTED(word, l, rvalue, state) { + _cleanup_free_ ArpIpTarget *buffer = NULL; + _cleanup_free_ char *n = NULL; + int f; + + n = strndup(word, l); + if (!n) + return -ENOMEM; + + buffer = new0(ArpIpTarget, 1); + if (!buffer) + return -ENOMEM; + + r = in_addr_from_string_auto(n, &f, &buffer->ip); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Bond ARP ip target address is invalid, ignoring assignment: %s", n); + return 0; + } + + if (f != AF_INET) { + log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Bond ARP ip target address is invalid, ignoring assignment: %s", n); + return 0; + } + + LIST_PREPEND(arp_ip_target, b->arp_ip_targets, buffer); + b->n_arp_ip_targets ++; + + buffer = NULL; + + if (b->n_arp_ip_targets > BOND_ARP_TARGETS_MAX) + break; + } + + return 0; +} + +static void bond_done(NetDev *netdev) { + ArpIpTarget *t = NULL, *n = NULL; + Bond *b = BOND(netdev); + + assert(netdev); + assert(b); + + LIST_FOREACH_SAFE(arp_ip_target, t, n, b->arp_ip_targets) + free(t); + + b->arp_ip_targets = NULL; +} + static void bond_init(NetDev *netdev) { Bond *b = BOND(netdev); @@ -187,11 +484,27 @@ static void bond_init(NetDev *netdev) { b->mode = _NETDEV_BOND_MODE_INVALID; b->xmit_hash_policy = _NETDEV_BOND_XMIT_HASH_POLICY_INVALID; b->lacp_rate = _NETDEV_BOND_LACP_RATE_INVALID; + b->ad_select = _NETDEV_BOND_AD_SELECT_INVALID; + b->fail_over_mac = _NETDEV_BOND_FAIL_OVER_MAC_INVALID; + b->arp_validate = _NETDEV_BOND_ARP_VALIDATE_INVALID; + b->arp_all_targets = _NETDEV_BOND_ARP_ALL_TARGETS_INVALID; + b->primary_reselect = _NETDEV_BOND_PRIMARY_RESELECT_INVALID; + + b->all_slaves_active = false; + + b->resend_igmp = RESEND_IGMP_DEFAULT; + b->packets_per_slave = PACKETS_PER_SLAVE_DEFAULT; + b->num_grat_arp = GRATUITOUS_ARP_DEFAULT; + b->lp_interval = LEARNING_PACKETS_INTERVAL_MIN_SEC; + + LIST_HEAD_INIT(b->arp_ip_targets); + b->n_arp_ip_targets = 0; } const NetDevVTable bond_vtable = { .object_size = sizeof(Bond), .init = bond_init, + .done = bond_done, .sections = "Match\0NetDev\0Bond\0", .fill_message_create = netdev_bond_fill_message_create, .create_type = NETDEV_CREATE_MASTER, diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h index c09af5fa52..32d1702d58 100644 --- a/src/network/networkd-netdev-bond.h +++ b/src/network/networkd-netdev-bond.h @@ -47,7 +47,6 @@ typedef enum BondXmitHashPolicy { _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1 } BondXmitHashPolicy; - typedef enum BondLacpRate { NETDEV_BOND_LACP_RATE_SLOW, NETDEV_BOND_LACP_RATE_FAST, @@ -55,16 +54,79 @@ typedef enum BondLacpRate { _NETDEV_BOND_LACP_RATE_INVALID = -1, } BondLacpRate; +typedef enum BondAdSelect { + NETDEV_BOND_AD_SELECT_STABLE, + NETDEV_BOND_AD_SELECT_BANDWIDTH, + NETDEV_BOND_AD_SELECT_COUNT, + _NETDEV_BOND_AD_SELECT_MAX, + _NETDEV_BOND_AD_SELECT_INVALID = -1, +} BondAdSelect; + +typedef enum BondFailOverMac { + NETDEV_BOND_FAIL_OVER_MAC_NONE, + NETDEV_BOND_FAIL_OVER_MAC_ACTIVE, + NETDEV_BOND_FAIL_OVER_MAC_FOLLOW, + _NETDEV_BOND_FAIL_OVER_MAC_MAX, + _NETDEV_BOND_FAIL_OVER_MAC_INVALID = -1, +} BondFailOverMac; + +typedef enum BondArpValidate { + NETDEV_BOND_ARP_VALIDATE_NONE, + NETDEV_BOND_ARP_VALIDATE_ACTIVE, + NETDEV_BOND_ARP_VALIDATE_BACKUP, + NETDEV_BOND_ARP_VALIDATE_ALL, + _NETDEV_BOND_ARP_VALIDATE_MAX, + _NETDEV_BOND_ARP_VALIDATE_INVALID = -1, +} BondArpValidate; + +typedef enum BondArpAllTargets { + NETDEV_BOND_ARP_ALL_TARGETS_ANY, + NETDEV_BOND_ARP_ALL_TARGETS_ALL, + _NETDEV_BOND_ARP_ALL_TARGETS_MAX, + _NETDEV_BOND_ARP_ALL_TARGETS_INVALID = -1, +} BondArpAllTargets; + +typedef enum BondPrimaryReselect { + NETDEV_BOND_PRIMARY_RESELECT_ALWAYS, + NETDEV_BOND_PRIMARY_RESELECT_BETTER, + NETDEV_BOND_PRIMARY_RESELECT_FAILURE, + _NETDEV_BOND_PRIMARY_RESELECT_MAX, + _NETDEV_BOND_PRIMARY_RESELECT_INVALID = -1, +} BondPrimaryReselect; + +typedef struct ArpIpTarget { + union in_addr_union ip; + + LIST_FIELDS(struct ArpIpTarget, arp_ip_target); +} ArpIpTarget; + struct Bond { NetDev meta; BondMode mode; BondXmitHashPolicy xmit_hash_policy; BondLacpRate lacp_rate; + BondAdSelect ad_select; + BondFailOverMac fail_over_mac; + BondArpValidate arp_validate; + BondArpAllTargets arp_all_targets; + BondPrimaryReselect primary_reselect; + + bool all_slaves_active; + + unsigned resend_igmp; + unsigned packets_per_slave; + unsigned num_grat_arp; + unsigned min_links; usec_t miimon; usec_t updelay; usec_t downdelay; + usec_t arp_interval; + usec_t lp_interval; + + int n_arp_ip_targets; + ArpIpTarget *arp_ip_targets; }; extern const NetDevVTable bond_vtable; @@ -78,6 +140,27 @@ BondXmitHashPolicy bond_xmit_hash_policy_from_string(const char *d) _pure_; const char *bond_lacp_rate_to_string(BondLacpRate d) _const_; BondLacpRate bond_lacp_rate_from_string(const char *d) _pure_; +const char *bond_fail_over_mac_to_string(BondFailOverMac d) _const_; +BondFailOverMac bond_fail_over_mac_from_string(const char *d) _pure_; + +const char *bond_ad_select_to_string(BondAdSelect d) _const_; +BondAdSelect bond_ad_select_from_string(const char *d) _pure_; + +const char *bond_arp_validate_to_string(BondArpValidate d) _const_; +BondArpValidate bond_arp_validate_from_string(const char *d) _pure_; + +const char *bond_arp_all_targets_to_string(BondArpAllTargets d) _const_; +BondArpAllTargets bond_arp_all_targets_from_string(const char *d) _pure_; + +const char *bond_primary_reselect_to_string(BondPrimaryReselect d) _const_; +BondPrimaryReselect bond_primary_reselect_from_string(const char *d) _pure_; + int config_parse_bond_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_xmit_hash_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_bond_lacp_rate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bond_ad_select(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bond_fail_over_mac(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bond_arp_validate(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bond_arp_all_targets(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_bond_primary_reselect(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_arp_ip_target_address(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c index 91b7051a06..fd6af7e99b 100644 --- a/src/network/networkd-netdev-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -20,11 +20,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <netinet/ether.h> -#include <arpa/inet.h> -#include <net/if.h> -#include "sd-rtnl.h" #include "networkd-netdev-bridge.h" #include "missing.h" diff --git a/src/network/networkd-netdev-dummy.c b/src/network/networkd-netdev-dummy.c index 01c10a2d73..bb246a2be0 100644 --- a/src/network/networkd-netdev-dummy.c +++ b/src/network/networkd-netdev-dummy.c @@ -20,12 +20,7 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <netinet/ether.h> -#include <arpa/inet.h> -#include <net/if.h> -#include <linux/veth.h> -#include "sd-rtnl.h" #include "networkd-netdev-dummy.h" const NetDevVTable dummy_vtable = { diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 963c47c3e5..66ed2e013c 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -18,49 +18,65 @@ struct ConfigPerfItem; %struct-type %includes %% -Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, match_host) -Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel) -Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, match_arch) -NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) -NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) -NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) -NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu) -NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) -VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id) -MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) -IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) -Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local) -Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote) -Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) -Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) -Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) -Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) -Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) -Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) -VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) -VXLAN.Group, config_parse_vxlan_group_address, 0, offsetof(VxLan, group) -VXLAN.TOS, config_parse_unsigned, 0, offsetof(VxLan, tos) -VXLAN.TTL, config_parse_unsigned, 0, offsetof(VxLan, ttl) -VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning) -VXLAN.ARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy) -VXLAN.L2MissNotification, config_parse_bool, 0, offsetof(VxLan, l2miss) -VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss) -VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit) -VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) -Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) -Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) -Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) -Tun.User, config_parse_string, 0, offsetof(TunTap, user_name) -Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name) -Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) -Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) -Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) -Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) -Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) -Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) -Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy) -Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate) -Bond.MIIMonitorSec, config_parse_sec, 0, offsetof(Bond, miimon) -Bond.UpDelaySec, config_parse_sec, 0, offsetof(Bond, updelay) -Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) +Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(NetDev, match_host) +Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(NetDev, match_virt) +Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(NetDev, match_kernel) +Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(NetDev, match_arch) +NetDev.Description, config_parse_string, 0, offsetof(NetDev, description) +NetDev.Name, config_parse_ifname, 0, offsetof(NetDev, ifname) +NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) +NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu) +NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) +VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id) +MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) +IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode) +Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local) +Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote) +Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) +Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) +Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) +Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) +Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) +Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) +VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) +VXLAN.Group, config_parse_vxlan_group_address, 0, offsetof(VxLan, group) +VXLAN.TOS, config_parse_unsigned, 0, offsetof(VxLan, tos) +VXLAN.TTL, config_parse_unsigned, 0, offsetof(VxLan, ttl) +VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning) +VXLAN.ARPProxy, config_parse_bool, 0, offsetof(VxLan, arp_proxy) +VXLAN.L2MissNotification, config_parse_bool, 0, offsetof(VxLan, l2miss) +VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss) +VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit) +VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum) +VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) +VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) +VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) +Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) +Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tun.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) +Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) +Bond.TransmitHashPolicy, config_parse_bond_xmit_hash_policy, 0, offsetof(Bond, xmit_hash_policy) +Bond.LACPTransmitRate, config_parse_bond_lacp_rate, 0, offsetof(Bond, lacp_rate) +Bond.AdSelect, config_parse_bond_ad_select, 0, offsetof(Bond, ad_select) +Bond.FailOverMACPolicy, config_parse_bond_fail_over_mac, 0, offsetof(Bond, fail_over_mac) +Bond.ARPIPTargets, config_parse_arp_ip_target_address, 0, 0 +Bond.ARPValidate, config_parse_bond_arp_validate, 0, offsetof(Bond, arp_validate) +Bond.ARPAllTargets, config_parse_bond_arp_all_targets, 0, offsetof(Bond, arp_all_targets) +Bond.PrimaryReselectPolicy, config_parse_bond_primary_reselect, 0, offsetof(Bond, primary_reselect) +Bond.ResendIGMP, config_parse_unsigned, 0, offsetof(Bond, resend_igmp) +Bond.PacketsPerSlave, config_parse_unsigned, 0, offsetof(Bond, packets_per_slave) +Bond.GratuitousARP, config_parse_unsigned, 0, offsetof(Bond, num_grat_arp) +Bond.AllSlavesActive, config_parse_unsigned, 0, offsetof(Bond, all_slaves_active) +Bond.MinLinks, config_parse_unsigned, 0, offsetof(Bond, min_links) +Bond.MIIMonitorSec, config_parse_sec, 0, offsetof(Bond, miimon) +Bond.UpDelaySec, config_parse_sec, 0, offsetof(Bond, updelay) +Bond.DownDelaySec, config_parse_sec, 0, offsetof(Bond, downdelay) +Bond.ARPIntervalSec, config_parse_sec, 0, offsetof(Bond, arp_interval) +Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval) diff --git a/src/network/networkd-netdev-ipvlan.c b/src/network/networkd-netdev-ipvlan.c index 9a7c280c6b..5189000c1f 100644 --- a/src/network/networkd-netdev-ipvlan.c +++ b/src/network/networkd-netdev-ipvlan.c @@ -20,12 +20,9 @@ ***/ #include <net/if.h> -#include <linux/if_link.h> #include "networkd-netdev-ipvlan.h" -#include "network-internal.h" #include "conf-parser.h" -#include "list.h" static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = { [NETDEV_IPVLAN_MODE_L2] = "L2", diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c index 198fb575ee..5f41f1c865 100644 --- a/src/network/networkd-netdev-macvlan.c +++ b/src/network/networkd-netdev-macvlan.c @@ -22,9 +22,7 @@ #include <net/if.h> #include "networkd-netdev-macvlan.h" -#include "network-internal.h" #include "conf-parser.h" -#include "list.h" static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { [NETDEV_MACVLAN_MODE_PRIVATE] = "private", diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index e95082d119..8af4be4974 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -19,7 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <netinet/ether.h> #include <arpa/inet.h> #include <net/if.h> #include <linux/ip.h> @@ -29,7 +28,6 @@ #include "sd-rtnl.h" #include "networkd-netdev-tunnel.h" #include "networkd-link.h" -#include "network-internal.h" #include "util.h" #include "missing.h" #include "conf-parser.h" @@ -56,44 +54,24 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_PMTUDISC attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); return r; } @@ -109,44 +87,24 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_PMTUDISC attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); return r; } @@ -158,9 +116,9 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me assert(netdev); if (netdev->kind == NETDEV_KIND_GRE) - t = GRE(netdev); + t = GRE(netdev); else - t = GRETAP(netdev); + t = GRETAP(netdev); assert(t); assert(t->family == AF_INET); @@ -168,52 +126,28 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me assert(m); r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_TOS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_PMTUDISC attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m"); return r; } @@ -225,9 +159,9 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl assert(netdev); if (netdev->kind == NETDEV_KIND_IP6GRE) - t = IP6GRE(netdev); + t = IP6GRE(netdev); else - t = IP6GRETAP(netdev); + t = IP6GRETAP(netdev); assert(t); assert(t->family == AF_INET6); @@ -235,36 +169,20 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl assert(m); r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_GRE_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); return r; } @@ -280,28 +198,41 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); + + return r; +} + +static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { + Tunnel *t = VTI6(netdev); + int r; + + assert(netdev); + assert(link); + assert(m); + assert(t); + assert(t->family == AF_INET6); + + r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); + + r = sd_rtnl_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); + + r = sd_rtnl_message_append_in6_addr(m, IFLA_VTI_REMOTE, &t->remote.in6); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); return r; } @@ -318,36 +249,20 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl assert(t->family == AF_INET6); r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_LOCAL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_REMOTE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_TTL attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); switch (t->ip6tnl_mode) { case NETDEV_IP6_TNL_MODE_IP6IP6: @@ -363,12 +278,8 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl } r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PROTO, proto); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IPTUN_MODE attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m"); return r; } @@ -401,6 +312,9 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { case NETDEV_KIND_VTI: t = VTI(netdev); break; + case NETDEV_KIND_VTI6: + t = VTI6(netdev); + break; case NETDEV_KIND_IP6TNL: t = IP6TNL(netdev); break; @@ -411,13 +325,13 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { assert(t); if (t->remote.in.s_addr == INADDR_ANY) { - log_warning("Tunnel without remote address configured in %s. Ignoring", filename); - return -EINVAL; + log_warning("Tunnel without remote address configured in %s. Ignoring", filename); + return -EINVAL; } if (t->family != AF_INET && t->family != AF_INET6) { - log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); - return -EINVAL; + log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); + return -EINVAL; } if (netdev->kind == NETDEV_KIND_IP6TNL) { @@ -485,9 +399,15 @@ static void sit_init(NetDev *n) { } static void vti_init(NetDev *n) { - Tunnel *t = VTI(n); + Tunnel *t; assert(n); + + if (n->kind == NETDEV_KIND_VTI) + t = VTI(n); + else + t = VTI6(n); + assert(t); t->pmtudisc = true; @@ -561,6 +481,15 @@ const NetDevVTable vti_vtable = { .config_verify = netdev_tunnel_verify, }; +const NetDevVTable vti6_vtable = { + .object_size = sizeof(Tunnel), + .init = vti_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_vti6_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, + .config_verify = netdev_tunnel_verify, +}; + const NetDevVTable gre_vtable = { .object_size = sizeof(Tunnel), .init = gre_init, diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h index 453d73c596..88f57ac105 100644 --- a/src/network/networkd-netdev-tunnel.h +++ b/src/network/networkd-netdev-tunnel.h @@ -55,6 +55,7 @@ struct Tunnel { extern const NetDevVTable ipip_vtable; extern const NetDevVTable sit_vtable; extern const NetDevVTable vti_vtable; +extern const NetDevVTable vti6_vtable; extern const NetDevVTable gre_vtable; extern const NetDevVTable gretap_vtable; extern const NetDevVTable ip6gre_vtable; diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c index 4f449aea48..4e974927cb 100644 --- a/src/network/networkd-netdev-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -108,7 +108,7 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { } } - if(t->group_name) { + if (t->group_name) { group = t->group_name; @@ -173,15 +173,11 @@ static void tuntap_done(NetDev *netdev) { static int tuntap_verify(NetDev *netdev, const char *filename) { assert(netdev); - if (netdev->mtu) { - log_warning_netdev(netdev, "MTU configured for %s, ignoring", - netdev_kind_to_string(netdev->kind)); - } + if (netdev->mtu) + log_netdev_warning(netdev, "MTU configured for %s, ignoring", netdev_kind_to_string(netdev->kind)); - if (netdev->mac) { - log_warning_netdev(netdev, "MAC configured for %s, ignoring", - netdev_kind_to_string(netdev->kind)); - } + if (netdev->mac) + log_netdev_warning(netdev, "MAC configured for %s, ignoring", netdev_kind_to_string(netdev->kind)); return 0; } diff --git a/src/network/networkd-netdev-veth.c b/src/network/networkd-netdev-veth.c index 251cf92aec..9e9e1225e7 100644 --- a/src/network/networkd-netdev-veth.c +++ b/src/network/networkd-netdev-veth.c @@ -19,8 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <netinet/ether.h> -#include <arpa/inet.h> #include <net/if.h> #include <linux/veth.h> diff --git a/src/network/networkd-netdev-vlan.c b/src/network/networkd-netdev-vlan.c index 665559f895..0ed024b41d 100644 --- a/src/network/networkd-netdev-vlan.c +++ b/src/network/networkd-netdev-vlan.c @@ -22,8 +22,6 @@ #include <net/if.h> #include "networkd-netdev-vlan.h" -#include "network-internal.h" -#include "list.h" static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *req) { VLan *v = VLAN(netdev); diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c index d5128cb7c0..e2c2b108b9 100644 --- a/src/network/networkd-netdev-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -19,8 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <netinet/ether.h> -#include <arpa/inet.h> #include <net/if.h> #include "sd-rtnl.h" @@ -135,6 +133,30 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ } } + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_CSUM, v->udpcsum); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_VXLAN_UDP_CSUM attribute: %s", + strerror(-r)); + return r; + } + + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %s", + strerror(-r)); + return r; + } + + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); + if (r < 0) { + log_netdev_error(netdev, + "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %s", + strerror(-r)); + return r; + } + return r; } @@ -199,6 +221,9 @@ static void vxlan_init(NetDev *netdev) { v->id = VXLAN_VID_MAX + 1; v->learning = true; + v->udpcsum = false; + v->udp6zerocsumtx = false; + v->udp6zerocsumrx = false; } const NetDevVTable vxlan_vtable = { diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h index 6339af9add..fe5254e91f 100644 --- a/src/network/networkd-netdev-vxlan.h +++ b/src/network/networkd-netdev-vxlan.h @@ -47,6 +47,9 @@ struct VxLan { bool route_short_circuit; bool l2miss; bool l3miss; + bool udpcsum; + bool udp6zerocsumtx; + bool udp6zerocsumrx; }; extern const NetDevVTable vxlan_vtable; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index 8119205dde..66fd0fac0a 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -24,7 +24,6 @@ #include "networkd-netdev.h" #include "networkd-link.h" #include "network-internal.h" -#include "path-util.h" #include "conf-files.h" #include "conf-parser.h" #include "list.h" @@ -44,6 +43,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable, [NETDEV_KIND_SIT] = &sit_vtable, [NETDEV_KIND_VTI] = &vti_vtable, + [NETDEV_KIND_VTI6] = &vti6_vtable, [NETDEV_KIND_VETH] = &veth_vtable, [NETDEV_KIND_DUMMY] = &dummy_vtable, [NETDEV_KIND_TUN] = &tun_vtable, @@ -66,6 +66,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_SIT] = "sit", [NETDEV_KIND_VETH] = "veth", [NETDEV_KIND_VTI] = "vti", + [NETDEV_KIND_VTI6] = "vti6", [NETDEV_KIND_DUMMY] = "dummy", [NETDEV_KIND_TUN] = "tun", [NETDEV_KIND_TAP] = "tap", @@ -191,34 +192,21 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_hand assert(link); assert(callback); - r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, - RTM_SETLINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not allocate RTM_SETLINK message: %s", - strerror(-r)); - return r; - } + r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_SETLINK, link->ifindex); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); r = sd_rtnl_message_append_u32(req, IFLA_MASTER, netdev->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_MASTER attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m"); r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL); - if (r < 0) { - log_netdev_error(netdev, - "Could not send rtnetlink message: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error(netdev, "Could not send rtnetlink message: %m"); link_ref(link); - log_netdev_debug(netdev, "enslaving link '%s'", link->ifname); + log_netdev_debug(netdev, "Enslaving link '%s'", link->ifname); return 0; } @@ -235,7 +223,7 @@ static int netdev_enter_ready(NetDev *netdev) { netdev->state = NETDEV_STATE_READY; - log_info_netdev(netdev, "netdev ready"); + log_netdev_info(netdev, "netdev ready"); LIST_FOREACH_SAFE(callbacks, callback, callback_next, netdev->callbacks) { /* enslave the links that were attempted to be enslaved before the @@ -261,15 +249,15 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda r = sd_rtnl_message_get_errno(m); if (r == -EEXIST) - log_netdev_debug(netdev, "netdev exists, using existing"); + log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); else if (r < 0) { - log_warning_netdev(netdev, "netdev could not be created: %s", strerror(-r)); + log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); netdev_drop(netdev); return 1; } - log_netdev_debug(netdev, "created"); + log_netdev_debug(netdev, "Created"); return 1; } @@ -298,8 +286,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callbac LIST_PREPEND(callbacks, netdev->callbacks, cb); - log_netdev_debug(netdev, "will enslave '%s', when reday", - link->ifname); + log_netdev_debug(netdev, "Will enslave '%s', when ready", link->ifname); } return 0; @@ -316,25 +303,23 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) { assert(message); r = sd_rtnl_message_get_type(message, &type); - if (r < 0) { - log_netdev_error(netdev, "Could not get rtnl message type"); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get rtnl message type: %m"); if (type != RTM_NEWLINK) { - log_netdev_error(netdev, "Can not set ifindex from unexpected rtnl message type"); + log_netdev_error(netdev, "Cannot set ifindex from unexpected rtnl message type."); return -EINVAL; } r = sd_rtnl_message_link_get_ifindex(message, &ifindex); if (r < 0) { - log_netdev_error(netdev, "Could not get ifindex: %s", strerror(-r)); + log_netdev_error_errno(netdev, r, "Could not get ifindex: %m"); netdev_enter_failed(netdev); return r; } else if (ifindex <= 0) { log_netdev_error(netdev, "Got invalid ifindex: %d", ifindex); netdev_enter_failed(netdev); - return r; + return -EINVAL; } if (netdev->ifindex > 0) { @@ -349,35 +334,26 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) { } r = sd_rtnl_message_read_string(message, IFLA_IFNAME, &received_name); - if (r < 0) { - log_netdev_error(netdev, "Could not get IFNAME"); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get IFNAME: %m"); if (!streq(netdev->ifname, received_name)) { - log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", - received_name); + log_netdev_error(netdev, "Received newlink with wrong IFNAME %s", received_name); netdev_enter_failed(netdev); return r; } r = sd_rtnl_message_enter_container(message, IFLA_LINKINFO); - if (r < 0) { - log_netdev_error(netdev, "Could not get LINKINFO"); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m"); r = sd_rtnl_message_read_string(message, IFLA_INFO_KIND, &received_kind); - if (r < 0) { - log_netdev_error(netdev, "Could not get KIND"); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not get KIND: %m"); r = sd_rtnl_message_exit_container(message); - if (r < 0) { - log_netdev_error(netdev, "Could not exit container"); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not exit container: %m"); if (netdev->kind == NETDEV_KIND_TAP) /* the kernel does not distinguish between tun and tap */ @@ -469,72 +445,43 @@ static int netdev_create(NetDev *netdev, Link *link, if (r < 0) return r; - log_netdev_debug(netdev, "created"); + log_netdev_debug(netdev, "Created"); } else { _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); - if (r < 0) { - log_netdev_error(netdev, - "Could not allocate RTM_NEWLINK message: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m"); r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_IFNAME, attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m"); if (netdev->mac) { r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_ADDRESS attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); } if (netdev->mtu) { r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_MTU attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m"); } if (link) { r = sd_rtnl_message_append_u32(m, IFLA_LINK, link->ifindex); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_LINK attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINK attribute: %m"); } r = sd_rtnl_message_open_container(m, IFLA_LINKINFO); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_LINKINFO attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); - r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, - netdev_kind_to_string(netdev->kind)); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_INFO_DATA attribute: %s", - strerror(-r)); - return r; - } + r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, netdev_kind_to_string(netdev->kind)); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); if (NETDEV_VTABLE(netdev)->fill_message_create) { r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m); @@ -543,50 +490,30 @@ static int netdev_create(NetDev *netdev, Link *link, } r = sd_rtnl_message_close_container(m); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_LINKINFO attribute: %s", - strerror(-r)); - return r; - } + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); r = sd_rtnl_message_close_container(m); - if (r < 0) { - log_netdev_error(netdev, - "Could not append IFLA_LINKINFO attribute: %s", - strerror(-r)); - return r; - } - + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); if (link) { - r = sd_rtnl_call_async(netdev->manager->rtnl, m, - callback, link, 0, NULL); - if (r < 0) { - log_netdev_error(netdev, - "Could not send rtnetlink message: %s", - strerror(-r)); - return r; - } + r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); link_ref(link); } else { - r = sd_rtnl_call_async(netdev->manager->rtnl, m, - netdev_create_handler, netdev, 0, - NULL); - if (r < 0) { - log_netdev_error(netdev, - "Could not send rtnetlink message: %s", - strerror(-r)); - return r; - } + r = sd_rtnl_call_async(netdev->manager->rtnl, m, netdev_create_handler, netdev, 0, NULL); + if (r < 0) + return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); netdev_ref(netdev); } netdev->state = NETDEV_STATE_CREATING; - log_netdev_debug(netdev, "creating"); + log_netdev_debug(netdev, "Creating"); } return 0; @@ -710,11 +637,8 @@ static int netdev_load_one(Manager *manager, const char *filename) { if (!netdev->mac) { r = netdev_get_mac(netdev->ifname, &netdev->mac); - if (r < 0) { - log_error("Failed to generate predictable MAC address for %s", - netdev->ifname); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to generate predictable MAC address for %s: %m", netdev->ifname); } r = hashmap_put(netdev->manager->netdevs, netdev->ifname, netdev); @@ -743,8 +667,9 @@ static int netdev_load_one(Manager *manager, const char *filename) { } int netdev_load(Manager *manager) { + _cleanup_strv_free_ char **files = NULL; NetDev *netdev; - char **files, **f; + char **f; int r; assert(manager); @@ -762,7 +687,5 @@ int netdev_load(Manager *manager) { return r; } - strv_free(files); - return 0; } diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 3756b1e5a7..1ded495e4a 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -22,10 +22,7 @@ #pragma once #include "networkd.h" -#include "hashmap.h" #include "list.h" -#include "set.h" -#include "in-addr-util.h" typedef struct NetDevVTable NetDevVTable; @@ -53,6 +50,7 @@ typedef enum NetDevKind { NETDEV_KIND_SIT, NETDEV_KIND_VETH, NETDEV_KIND_VTI, + NETDEV_KIND_VTI6, NETDEV_KIND_IP6TNL, NETDEV_KIND_DUMMY, NETDEV_KIND_TUN, @@ -172,6 +170,7 @@ DEFINE_CAST(IP6GRE, Tunnel); DEFINE_CAST(IP6GRETAP, Tunnel); DEFINE_CAST(SIT, Tunnel); DEFINE_CAST(VTI, Tunnel); +DEFINE_CAST(VTI6, Tunnel); DEFINE_CAST(IP6TNL, Tunnel); DEFINE_CAST(VETH, Veth); DEFINE_CAST(DUMMY, Dummy); @@ -203,13 +202,24 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign /* Macros which append INTERFACE= to the message */ -#define log_full_netdev(level, netdev, fmt, ...) log_object_internal(level, 0, __FILE__, __LINE__, __func__, "INTERFACE=", netdev->ifname, "%-*s: " fmt, IFNAMSIZ, netdev->ifname, ##__VA_ARGS__) -#define log_netdev_debug(netdev, ...) log_full_netdev(LOG_DEBUG, netdev, ##__VA_ARGS__) -#define log_info_netdev(netdev, ...) log_full_netdev(LOG_INFO, netdev, ##__VA_ARGS__) -#define log_notice_netdev(netdev, ...) log_full_netdev(LOG_NOTICE, netdev, ##__VA_ARGS__) -#define log_warning_netdev(netdev, ...) log_full_netdev(LOG_WARNING, netdev,## __VA_ARGS__) -#define log_netdev_error(netdev, ...) log_full_netdev(LOG_ERR, netdev, ##__VA_ARGS__) - -#define log_struct_netdev(level, netdev, ...) log_struct(level, "INTERFACE=%s", netdev->ifname, __VA_ARGS__) - -#define NETDEVIF(netdev) "INTERFACE=%s", netdev->ifname +#define log_netdev_full(netdev, level, error, ...) \ + ({ \ + NetDev *_n = (netdev); \ + _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \ + log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + }) + +#define log_netdev_debug(netdev, ...) log_netdev_full(netdev, LOG_DEBUG, 0, ##__VA_ARGS__) +#define log_netdev_info(netdev, ...) log_netdev_full(netdev, LOG_INFO, 0, ##__VA_ARGS__) +#define log_netdev_notice(netdev, ...) log_netdev_full(netdev, LOG_NOTICE, 0, ##__VA_ARGS__) +#define log_netdev_warning(netdev, ...) log_netdev_full(netdev, LOG_WARNING, 0, ## __VA_ARGS__) +#define log_netdev_error(netdev, ...) log_netdev_full(netdev, LOG_ERR, 0, ##__VA_ARGS__) + +#define log_netdev_debug_errno(netdev, error, ...) log_netdev_full(netdev, LOG_DEBUG, error, ##__VA_ARGS__) +#define log_netdev_info_errno(netdev, error, ...) log_netdev_full(netdev, LOG_INFO, error, ##__VA_ARGS__) +#define log_netdev_notice_errno(netdev, error, ...) log_netdev_full(netdev, LOG_NOTICE, error, ##__VA_ARGS__) +#define log_netdev_warning_errno(netdev, error, ...) log_netdev_full(netdev, LOG_WARNING, error, ##__VA_ARGS__) +#define log_netdev_error_errno(netdev, error, ...) log_netdev_full(netdev, LOG_ERR, error, ##__VA_ARGS__) + +#define LOG_NETDEV_MESSAGE(netdev, fmt, ...) "MESSAGE=%s: " fmt, (netdev)->ifname, ##__VA_ARGS__ +#define LOG_NETDEV_INTERFACE(netdev) "INTERFACE=%s", (netdev)->ifname diff --git a/src/network/networkd-network-bus.c b/src/network/networkd-network-bus.c index 36b40d32b9..b5f8f5cfb2 100644 --- a/src/network/networkd-network-bus.c +++ b/src/network/networkd-network-bus.c @@ -19,8 +19,6 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "bus-util.h" -#include "bus-label.h" #include "strv.h" #include "networkd.h" diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index fc277df949..8abf5bcf2e 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -48,6 +48,7 @@ Network.LLMNR, config_parse_llmnr, 0, Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) Network.IPForward, config_parse_address_family_boolean,0, offsetof(Network, ip_forward) Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) +Network.BindCarrier, config_parse_strv, 0, offsetof(Network, bind_carrier) Address.Address, config_parse_address, 0, 0 Address.Peer, config_parse_address, 0, 0 Address.Broadcast, config_parse_broadcast, 0, 0 @@ -57,7 +58,9 @@ Route.Destination, config_parse_destination, 0, Route.Source, config_parse_destination, 0, 0 Route.Metric, config_parse_route_priority, 0, 0 Route.Scope, config_parse_route_scope, 0, 0 +DHCP.ClientIdentifier, config_parse_dhcp_client_identifier,0, offsetof(Network, dhcp_client_identifier) DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns) +DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp) DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu) DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname) DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 35ac064cf6..5947084106 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -22,10 +22,10 @@ #include <ctype.h> #include <net/if.h> -#include "path-util.h" #include "conf-files.h" #include "conf-parser.h" #include "util.h" +#include "hostname-util.h" #include "networkd.h" #include "networkd-netdev.h" #include "networkd-link.h" @@ -104,6 +104,7 @@ static int network_load_one(Manager *manager, const char *filename) { network->dhcp_routes = true; network->dhcp_sendhost = true; network->dhcp_route_metric = DHCP_ROUTE_METRIC; + network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; network->llmnr = LLMNR_SUPPORT_YES; @@ -209,6 +210,7 @@ void network_free(Network *network) { strv_free(network->ntp); strv_free(network->dns); strv_free(network->domains); + strv_free(network->bind_carrier); netdev_unref(network->bridge); @@ -271,29 +273,39 @@ int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *address, Network **ret) { Network *network; + struct udev_device *parent; + const char *path = NULL, *parent_driver = NULL, *driver = NULL, *devtype = NULL; assert(manager); assert(ret); + if (device) { + path = udev_device_get_property_value(device, "ID_PATH"); + + parent = udev_device_get_parent(device); + if (parent) + parent_driver = udev_device_get_driver(parent); + + driver = udev_device_get_property_value(device, "ID_NET_DRIVER"); + + devtype = udev_device_get_devtype(device); + } + LIST_FOREACH(networks, network, manager->networks) { if (net_match_config(network->match_mac, network->match_path, network->match_driver, network->match_type, network->match_name, network->match_host, network->match_virt, network->match_kernel, network->match_arch, - address, - udev_device_get_property_value(device, "ID_PATH"), - udev_device_get_driver(udev_device_get_parent(device)), - udev_device_get_property_value(device, "ID_NET_DRIVER"), - udev_device_get_devtype(device), - ifname)) { - if (network->match_name) { + address, path, parent_driver, driver, + devtype, ifname)) { + if (network->match_name && device) { const char *attr; uint8_t name_assign_type = NET_NAME_UNKNOWN; attr = udev_device_get_sysattr_value(device, "name_assign_type"); if (attr) - (void)safe_atou8(attr, &name_assign_type); + (void) safe_atou8(attr, &name_assign_type); if (name_assign_type == NET_NAME_ENUM) log_warning("%-*s: found matching network '%s', based on potentially unpredictable ifname", @@ -413,8 +425,8 @@ int config_parse_netdev(const char *unit, r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Can not add VLAN '%s' to network: %s", - rvalue, strerror(-r)); + "Can not add VLAN '%s' to network: %m", + rvalue); return 0; } @@ -490,8 +502,7 @@ int config_parse_tunnel(const char *unit, r = netdev_get(network->manager, rvalue, &netdev); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Tunnel is invalid, ignoring assignment: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue); return 0; } @@ -502,6 +513,7 @@ int config_parse_tunnel(const char *unit, netdev->kind != NETDEV_KIND_IP6GRE && netdev->kind != NETDEV_KIND_IP6GRETAP && netdev->kind != NETDEV_KIND_VTI && + netdev->kind != NETDEV_KIND_VTI6 && netdev->kind != NETDEV_KIND_IP6TNL ) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, @@ -511,9 +523,7 @@ int config_parse_tunnel(const char *unit, r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Can not add VLAN '%s' to network: %s", - rvalue, strerror(-r)); + log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue); return 0; } @@ -600,6 +610,14 @@ int config_parse_dhcp( return 0; } +static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = { + [DHCP_CLIENT_ID_MAC] = "mac", + [DHCP_CLIENT_ID_DUID] = "duid" +}; + +DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier); +DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type"); + static const char* const llmnr_support_table[_LLMNR_SUPPORT_MAX] = { [LLMNR_SUPPORT_NO] = "no", [LLMNR_SUPPORT_YES] = "yes", @@ -674,13 +692,13 @@ int config_parse_ipv6token( r = in_addr_from_string(AF_INET6, rvalue, &buffer); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to parse IPv6 token, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue); return 0; } r = in_addr_is_null(AF_INET6, &buffer); if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, -r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue); + log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue); return 0; } diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index c2d1ffca25..7f110a5217 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -19,15 +19,12 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <net/if.h> #include "networkd.h" #include "networkd-link.h" -#include "utf8.h" #include "util.h" #include "conf-parser.h" -#include "network-internal.h" int route_new_static(Network *network, unsigned section, Route **ret) { _cleanup_route_free_ Route *route = NULL; diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c index e091b20ed9..341bcae3fb 100644 --- a/src/network/networkd-wait-online-link.c +++ b/src/network/networkd-wait-online-link.c @@ -20,10 +20,8 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <net/if.h> #include "sd-network.h" -#include "strv.h" #include "networkd-wait-online-link.h" diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c index cafe110e50..1c997a50a4 100644 --- a/src/network/networkd-wait-online-manager.c +++ b/src/network/networkd-wait-online-manager.c @@ -25,7 +25,6 @@ #include "rtnl-util.h" -#include "network-util.h" #include "network-internal.h" #include "networkd-wait-online-link.h" #include "networkd-wait-online.h" diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c index f0ca6def87..6a96f1de55 100644 --- a/src/network/networkd-wait-online.c +++ b/src/network/networkd-wait-online.c @@ -21,11 +21,10 @@ #include <getopt.h> #include "sd-daemon.h" - -#include "networkd-wait-online.h" - #include "strv.h" #include "build.h" +#include "signal-util.h" +#include "networkd-wait-online.h" static bool arg_quiet = false; static usec_t arg_timeout = 120 * USEC_PER_SEC; diff --git a/src/network/networkd-wait-online.h b/src/network/networkd-wait-online.h index 66b865cfe2..73d129699d 100644 --- a/src/network/networkd-wait-online.h +++ b/src/network/networkd-wait-online.h @@ -25,7 +25,6 @@ #include "sd-rtnl.h" #include "sd-network.h" -#include "util.h" #include "hashmap.h" typedef struct Manager Manager; diff --git a/src/network/networkd.c b/src/network/networkd.c index 7319276c53..41ec7cf904 100644 --- a/src/network/networkd.c +++ b/src/network/networkd.c @@ -19,10 +19,9 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include "capability.h" -#include "sd-event.h" #include "sd-daemon.h" - +#include "capability.h" +#include "signal-util.h" #include "networkd.h" int main(int argc, char *argv[]) { @@ -54,21 +53,19 @@ int main(int argc, char *argv[]) { * watches in. */ r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid); if (r < 0) - log_error_errno(r, "Could not create runtime directory: %m"); + log_warning_errno(r, "Could not create runtime directory: %m"); r = mkdir_safe_label("/run/systemd/netif/links", 0755, uid, gid); if (r < 0) - log_error_errno(r, "Could not create runtime directory 'links': %m"); + log_warning_errno(r, "Could not create runtime directory 'links': %m"); r = mkdir_safe_label("/run/systemd/netif/leases", 0755, uid, gid); if (r < 0) - log_error_errno(r, "Could not create runtime directory 'leases': %m"); + log_warning_errno(r, "Could not create runtime directory 'leases': %m"); r = mkdir_safe_label("/run/systemd/netif/lldp", 0755, uid, gid); if (r < 0) - log_error("Could not create runtime directory 'lldp': %s", - strerror(-r)); - + log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); r = drop_privileges(uid, gid, (1ULL << CAP_NET_ADMIN) | diff --git a/src/network/networkd.h b/src/network/networkd.h index bdb2f20e2f..49afeffe81 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -60,6 +60,7 @@ typedef enum AddressFamilyBoolean { ADDRESS_FAMILY_IPV4 = 1, ADDRESS_FAMILY_IPV6 = 2, ADDRESS_FAMILY_YES = 3, + ADDRESS_FAMILY_KERNEL = 4, _ADDRESS_FAMILY_BOOLEAN_MAX, _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, } AddressFamilyBoolean; @@ -83,6 +84,13 @@ typedef enum LinkOperationalState { _LINK_OPERSTATE_INVALID = -1 } LinkOperationalState; +typedef enum DCHPClientIdentifier { + DHCP_CLIENT_ID_MAC, + DHCP_CLIENT_ID_DUID, + _DHCP_CLIENT_ID_MAX, + _DHCP_CLIENT_ID_INVALID = -1, +} DCHPClientIdentifier; + struct FdbEntry { Network *network; unsigned section; @@ -115,6 +123,7 @@ struct Network { NetDev *bond; Hashmap *stacked_netdevs; AddressFamilyBoolean dhcp; + DCHPClientIdentifier dhcp_client_identifier; char *dhcp_vendor_class_identifier; bool dhcp_dns; bool dhcp_ntp; @@ -151,7 +160,7 @@ struct Network { Hashmap *fdb_entries_by_section; bool wildcard_domain; - char **domains, **dns, **ntp; + char **domains, **dns, **ntp, **bind_carrier; LLMNRSupport llmnr; @@ -165,7 +174,7 @@ struct Address { int family; unsigned char prefixlen; unsigned char scope; - unsigned char flags; + uint32_t flags; char *label; struct in_addr broadcast; @@ -403,6 +412,9 @@ int config_parse_fdb_vlan_id(const char *unit, const char *filename, unsigned li int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, + const char *section, unsigned section_line, const char *lvalue, + int ltype, const char *rvalue, void *data, void *userdata); /* IPv4LL support (legacy) */ @@ -437,7 +449,7 @@ AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); -/* Opeartional State */ +/* Operational State */ const char* link_operstate_to_string(LinkOperationalState s) _const_; LinkOperationalState link_operstate_from_string(const char *s) _pure_; diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c index 6709ab0957..67fcca2ac0 100644 --- a/src/network/test-network-tables.c +++ b/src/network/test-network-tables.c @@ -1,5 +1,4 @@ #include "networkd.h" -#include "networkd-link.h" #include "networkd-netdev-bond.h" #include "networkd-netdev-macvlan.h" #include "dhcp6-internal.h" |