diff options
Diffstat (limited to 'src/network')
73 files changed, 0 insertions, 19137 deletions
diff --git a/src/network/.gitignore b/src/network/.gitignore deleted file mode 100644 index aca55206b7..0000000000 --- a/src/network/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/networkd-network-gperf.c -/networkd-netdev-gperf.c -/networkd-gperf.c diff --git a/src/network/Makefile b/src/network/Makefile deleted file mode 120000 index d0b0e8e008..0000000000 --- a/src/network/Makefile +++ /dev/null @@ -1 +0,0 @@ -../Makefile
\ No newline at end of file diff --git a/src/network/networkctl.c b/src/network/networkctl.c deleted file mode 100644 index 6f7f41bf7d..0000000000 --- a/src/network/networkctl.c +++ /dev/null @@ -1,1142 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <getopt.h> -#include <net/if.h> -#include <stdbool.h> - -#include "sd-device.h" -#include "sd-hwdb.h" -#include "sd-lldp.h" -#include "sd-netlink.h" -#include "sd-network.h" - -#include "alloc-util.h" -#include "arphrd-list.h" -#include "device-util.h" -#include "ether-addr-util.h" -#include "fd-util.h" -#include "hwdb-util.h" -#include "local-addresses.h" -#include "locale-util.h" -#include "netlink-util.h" -#include "pager.h" -#include "parse-util.h" -#include "socket-util.h" -#include "sparse-endian.h" -#include "stdio-util.h" -#include "string-table.h" -#include "string-util.h" -#include "strv.h" -#include "strxcpyx.h" -#include "terminal-util.h" -#include "util.h" -#include "verbs.h" - -static bool arg_no_pager = false; -static bool arg_legend = true; -static bool arg_all = false; - -static int link_get_type_string(unsigned short iftype, sd_device *d, char **ret) { - const char *t; - char *p; - - assert(ret); - - if (iftype == ARPHRD_ETHER && d) { - const char *devtype = NULL, *id = NULL; - /* WLANs have iftype ARPHRD_ETHER, but we want - * to show a more useful type string for - * them */ - - (void) sd_device_get_devtype(d, &devtype); - - if (streq_ptr(devtype, "wlan")) - id = "wlan"; - else if (streq_ptr(devtype, "wwan")) - id = "wwan"; - - if (id) { - p = strdup(id); - if (!p) - return -ENOMEM; - - *ret = p; - return 1; - } - } - - t = arphrd_to_name(iftype); - if (!t) { - *ret = NULL; - return 0; - } - - p = strdup(t); - if (!p) - return -ENOMEM; - - ascii_strlower(p); - *ret = p; - - return 0; -} - -static void operational_state_to_color(const char *state, const char **on, const char **off) { - assert(on); - assert(off); - - if (streq_ptr(state, "routable")) { - *on = ansi_highlight_green(); - *off = ansi_normal(); - } else if (streq_ptr(state, "degraded")) { - *on = ansi_highlight_yellow(); - *off = ansi_normal(); - } else - *on = *off = ""; -} - -static void setup_state_to_color(const char *state, const char **on, const char **off) { - assert(on); - assert(off); - - if (streq_ptr(state, "configured")) { - *on = ansi_highlight_green(); - *off = ansi_normal(); - } else if (streq_ptr(state, "configuring")) { - *on = ansi_highlight_yellow(); - *off = ansi_normal(); - } else if (STRPTR_IN_SET(state, "failed", "linger")) { - *on = ansi_highlight_red(); - *off = ansi_normal(); - } else - *on = *off = ""; -} - -typedef struct LinkInfo { - char name[IFNAMSIZ+1]; - int ifindex; - unsigned short iftype; - struct ether_addr mac_address; - uint32_t mtu; - - bool has_mac_address:1; - bool has_mtu:1; -} LinkInfo; - -static int link_info_compare(const void *a, const void *b) { - const LinkInfo *x = a, *y = b; - - return x->ifindex - y->ifindex; -} - -static int decode_link(sd_netlink_message *m, LinkInfo *info) { - const char *name; - uint16_t type; - int r; - - assert(m); - assert(info); - - r = sd_netlink_message_get_type(m, &type); - if (r < 0) - return r; - - if (type != RTM_NEWLINK) - return 0; - - r = sd_rtnl_message_link_get_ifindex(m, &info->ifindex); - if (r < 0) - return r; - - r = sd_netlink_message_read_string(m, IFLA_IFNAME, &name); - if (r < 0) - return r; - - r = sd_rtnl_message_link_get_type(m, &info->iftype); - if (r < 0) - return r; - - strscpy(info->name, sizeof info->name, name); - - info->has_mac_address = - sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &info->mac_address) >= 0 && - memcmp(&info->mac_address, ÐER_ADDR_NULL, sizeof(struct ether_addr)) != 0; - - info->has_mtu = - sd_netlink_message_read_u32(m, IFLA_MTU, &info->mtu) && - info->mtu > 0; - - return 1; -} - -static int acquire_link_info_strv(sd_netlink *rtnl, char **l, LinkInfo **ret) { - _cleanup_free_ LinkInfo *links = NULL; - char **i; - size_t c = 0; - int r; - - assert(rtnl); - assert(ret); - - links = new(LinkInfo, strv_length(l)); - if (!links) - return log_oom(); - - STRV_FOREACH(i, l) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - int ifindex; - - if (parse_ifindex(*i, &ifindex) >= 0) - r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, ifindex); - else { - r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_message_append_string(req, IFLA_IFNAME, *i); - } - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_call(rtnl, req, 0, &reply); - if (r < 0) - return log_error_errno(r, "Failed to request link: %m"); - - r = decode_link(reply, links + c); - if (r < 0) - return r; - if (r > 0) - c++; - } - - qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); - - *ret = links; - links = NULL; - - return (int) c; -} - -static int acquire_link_info_all(sd_netlink *rtnl, LinkInfo **ret) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - _cleanup_free_ LinkInfo *links = NULL; - size_t allocated = 0, c = 0; - sd_netlink_message *i; - int r; - - assert(rtnl); - assert(ret); - - r = sd_rtnl_message_new_link(rtnl, &req, RTM_GETLINK, 0); - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_call(rtnl, req, 0, &reply); - if (r < 0) - return log_error_errno(r, "Failed to enumerate links: %m"); - - for (i = reply; i; i = sd_netlink_message_next(i)) { - if (!GREEDY_REALLOC(links, allocated, c+1)) - return -ENOMEM; - - r = decode_link(i, links + c); - if (r < 0) - return r; - if (r > 0) - c++; - } - - qsort_safe(links, c, sizeof(LinkInfo), link_info_compare); - - *ret = links; - links = NULL; - - return (int) c; -} - -static int list_links(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_free_ LinkInfo *links = NULL; - int c, i, r; - - r = sd_netlink_open(&rtnl); - if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); - - if (argc > 1) - c = acquire_link_info_strv(rtnl, argv + 1, &links); - else - c = acquire_link_info_all(rtnl, &links); - if (c < 0) - return c; - - pager_open(arg_no_pager, false); - - if (arg_legend) - printf("%3s %-16s %-18s %-11s %-10s\n", - "IDX", - "LINK", - "TYPE", - "OPERATIONAL", - "SETUP"); - - for (i = 0; i < c; i++) { - _cleanup_free_ char *setup_state = NULL, *operational_state = NULL; - _cleanup_(sd_device_unrefp) 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)]; - _cleanup_free_ char *t = NULL; - - (void) sd_network_link_get_operational_state(links[i].ifindex, &operational_state); - operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); - - r = sd_network_link_get_setup_state(links[i].ifindex, &setup_state); - if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */ - setup_state = strdup("unmanaged"); - setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); - - xsprintf(devid, "n%i", links[i].ifindex); - (void) sd_device_new_from_device_id(&d, devid); - - (void) link_get_type_string(links[i].iftype, d, &t); - - printf("%3i %-16s %-18s %s%-11s%s %s%-10s%s\n", - links[i].ifindex, links[i].name, strna(t), - on_color_operational, strna(operational_state), off_color_operational, - on_color_setup, strna(setup_state), off_color_setup); - } - - if (arg_legend) - printf("\n%i links listed.\n", c); - - return 0; -} - -/* IEEE Organizationally Unique Identifier vendor string */ -static int ieee_oui(sd_hwdb *hwdb, const struct ether_addr *mac, char **ret) { - const char *description; - char modalias[strlen("OUI:XXYYXXYYXXYY") + 1], *desc; - int r; - - assert(ret); - - if (!hwdb) - return -EINVAL; - - if (!mac) - return -EINVAL; - - /* skip commonly misused 00:00:00 (Xerox) prefix */ - if (memcmp(mac, "\0\0\0", 3) == 0) - return -EINVAL; - - xsprintf(modalias, "OUI:" ETHER_ADDR_FORMAT_STR, - ETHER_ADDR_FORMAT_VAL(*mac)); - - r = sd_hwdb_get(hwdb, modalias, "ID_OUI_FROM_DATABASE", &description); - if (r < 0) - return r; - - desc = strdup(description); - if (!desc) - return -ENOMEM; - - *ret = desc; - - return 0; -} - -static int get_gateway_description( - sd_netlink *rtnl, - sd_hwdb *hwdb, - int ifindex, - int family, - union in_addr_union *gateway, - char **gateway_description) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *m; - int r; - - assert(rtnl); - assert(ifindex >= 0); - assert(family == AF_INET || family == AF_INET6); - assert(gateway); - assert(gateway_description); - - r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_GETNEIGH, ifindex, family); - if (r < 0) - return r; - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (m = reply; m; m = sd_netlink_message_next(m)) { - union in_addr_union gw = {}; - struct ether_addr mac = {}; - uint16_t type; - int ifi, fam; - - r = sd_netlink_message_get_errno(m); - if (r < 0) { - log_error_errno(r, "got error: %m"); - continue; - } - - r = sd_netlink_message_get_type(m, &type); - if (r < 0) { - log_error_errno(r, "could not get type: %m"); - continue; - } - - if (type != RTM_NEWNEIGH) { - log_error("type is not RTM_NEWNEIGH"); - continue; - } - - r = sd_rtnl_message_neigh_get_family(m, &fam); - if (r < 0) { - log_error_errno(r, "could not get family: %m"); - continue; - } - - if (fam != family) { - log_error("family is not correct"); - continue; - } - - r = sd_rtnl_message_neigh_get_ifindex(m, &ifi); - if (r < 0) { - log_error_errno(r, "could not get ifindex: %m"); - continue; - } - - if (ifindex > 0 && ifi != ifindex) - continue; - - switch (fam) { - case AF_INET: - r = sd_netlink_message_read_in_addr(m, NDA_DST, &gw.in); - if (r < 0) - continue; - - break; - case AF_INET6: - r = sd_netlink_message_read_in6_addr(m, NDA_DST, &gw.in6); - if (r < 0) - continue; - - break; - default: - continue; - } - - if (!in_addr_equal(fam, &gw, gateway)) - continue; - - r = sd_netlink_message_read_ether_addr(m, NDA_LLADDR, &mac); - if (r < 0) - continue; - - r = ieee_oui(hwdb, &mac, gateway_description); - if (r < 0) - continue; - - return 0; - } - - return -ENODATA; -} - -static int dump_gateways( - sd_netlink *rtnl, - sd_hwdb *hwdb, - const char *prefix, - int ifindex) { - _cleanup_free_ struct local_address *local = NULL; - int r, n, i; - - assert(rtnl); - assert(prefix); - - n = local_gateways(rtnl, ifindex, AF_UNSPEC, &local); - if (n < 0) - return n; - - for (i = 0; i < n; i++) { - _cleanup_free_ char *gateway = NULL, *description = NULL; - - r = in_addr_to_string(local[i].family, &local[i].address, &gateway); - if (r < 0) - return r; - - r = get_gateway_description(rtnl, hwdb, local[i].ifindex, local[i].family, &local[i].address, &description); - if (r < 0) - log_debug_errno(r, "Could not get description of gateway: %m"); - - printf("%*s%s", - (int) strlen(prefix), - i == 0 ? prefix : "", - gateway); - - if (description) - printf(" (%s)", description); - - /* Show interface name for the entry if we show - * entries for all interfaces */ - if (ifindex <= 0) { - char name[IF_NAMESIZE+1]; - - if (if_indextoname(local[i].ifindex, name)) { - fputs(" on ", stdout); - fputs(name, stdout); - } else - printf(" on %%%i", local[i].ifindex); - } - - fputc('\n', stdout); - } - - return 0; -} - -static int dump_addresses( - sd_netlink *rtnl, - const char *prefix, - int ifindex) { - - _cleanup_free_ struct local_address *local = NULL; - int r, n, i; - - assert(rtnl); - assert(prefix); - - n = local_addresses(rtnl, ifindex, AF_UNSPEC, &local); - if (n < 0) - return n; - - for (i = 0; i < n; i++) { - _cleanup_free_ char *pretty = NULL; - - r = in_addr_to_string(local[i].family, &local[i].address, &pretty); - if (r < 0) - return r; - - printf("%*s%s", - (int) strlen(prefix), - i == 0 ? prefix : "", - pretty); - - if (ifindex <= 0) { - char name[IF_NAMESIZE+1]; - - if (if_indextoname(local[i].ifindex, name)) { - fputs(" on ", stdout); - fputs(name, stdout); - } else - printf(" on %%%i", local[i].ifindex); - } - - fputc('\n', stdout); - } - - return 0; -} - -static int open_lldp_neighbors(int ifindex, FILE **ret) { - _cleanup_free_ char *p = NULL; - FILE *f; - - if (asprintf(&p, "/run/systemd/netif/lldp/%i", ifindex) < 0) - return -ENOMEM; - - f = fopen(p, "re"); - if (!f) - return -errno; - - *ret = f; - return 0; -} - -static int next_lldp_neighbor(FILE *f, sd_lldp_neighbor **ret) { - _cleanup_free_ void *raw = NULL; - size_t l; - le64_t u; - int r; - - assert(f); - assert(ret); - - l = fread(&u, 1, sizeof(u), f); - if (l == 0 && feof(f)) - return 0; - if (l != sizeof(u)) - return -EBADMSG; - - raw = new(uint8_t, le64toh(u)); - if (!raw) - return -ENOMEM; - - if (fread(raw, 1, le64toh(u), f) != le64toh(u)) - return -EBADMSG; - - r = sd_lldp_neighbor_from_raw(ret, raw, le64toh(u)); - if (r < 0) - return r; - - return 1; -} - -static int dump_lldp_neighbors(const char *prefix, int ifindex) { - _cleanup_fclose_ FILE *f = NULL; - int r, c = 0; - - assert(prefix); - assert(ifindex > 0); - - r = open_lldp_neighbors(ifindex, &f); - if (r < 0) - return r; - - for (;;) { - const char *system_name = NULL, *port_id = NULL, *port_description = NULL; - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - - r = next_lldp_neighbor(f, &n); - if (r < 0) - return r; - if (r == 0) - break; - - printf("%*s", - (int) strlen(prefix), - c == 0 ? prefix : ""); - - (void) sd_lldp_neighbor_get_system_name(n, &system_name); - (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); - (void) sd_lldp_neighbor_get_port_description(n, &port_description); - - printf("%s on port %s", strna(system_name), strna(port_id)); - - if (!isempty(port_description)) - printf(" (%s)", port_description); - - putchar('\n'); - - c++; - } - - return c; -} - -static void dump_ifindexes(const char *prefix, const int *ifindexes) { - unsigned c; - - assert(prefix); - - if (!ifindexes || ifindexes[0] <= 0) - return; - - for (c = 0; ifindexes[c] > 0; c++) { - char name[IF_NAMESIZE+1]; - - printf("%*s", - (int) strlen(prefix), - c == 0 ? prefix : ""); - - if (if_indextoname(ifindexes[c], name)) - fputs(name, stdout); - else - printf("%i", ifindexes[c]); - - fputc('\n', stdout); - } -} - -static void dump_list(const char *prefix, char **l) { - char **i; - - if (strv_isempty(l)) - return; - - STRV_FOREACH(i, l) { - printf("%*s%s\n", - (int) strlen(prefix), - i == l ? prefix : "", - *i); - } -} - -static int link_status_one( - sd_netlink *rtnl, - sd_hwdb *hwdb, - const LinkInfo *info) { - - _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; - _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL; - _cleanup_(sd_device_unrefp) 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_free_ int *carrier_bound_to = NULL, *carrier_bound_by = NULL; - int r; - - assert(rtnl); - assert(info); - - (void) sd_network_link_get_operational_state(info->ifindex, &operational_state); - operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); - - r = sd_network_link_get_setup_state(info->ifindex, &setup_state); - if (r == -ENODATA) /* If there's no info available about this iface, it's unmanaged by networkd */ - setup_state = strdup("unmanaged"); - setup_state_to_color(setup_state, &on_color_setup, &off_color_setup); - - (void) sd_network_link_get_dns(info->ifindex, &dns); - (void) sd_network_link_get_search_domains(info->ifindex, &search_domains); - (void) sd_network_link_get_route_domains(info->ifindex, &route_domains); - (void) sd_network_link_get_ntp(info->ifindex, &ntp); - - xsprintf(devid, "n%i", info->ifindex); - - (void) sd_device_new_from_device_id(&d, devid); - - if (d) { - (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); - - 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); - - 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); - } - - (void) link_get_type_string(info->iftype, d, &t); - - (void) sd_network_link_get_network_file(info->ifindex, &network); - - (void) sd_network_link_get_carrier_bound_to(info->ifindex, &carrier_bound_to); - (void) sd_network_link_get_carrier_bound_by(info->ifindex, &carrier_bound_by); - - printf("%s%s%s %i: %s\n", on_color_operational, special_glyph(BLACK_CIRCLE), off_color_operational, info->ifindex, info->name); - - 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), - on_color_operational, strna(operational_state), off_color_operational, - on_color_setup, strna(setup_state), off_color_setup); - - if (path) - printf(" Path: %s\n", path); - if (driver) - printf(" Driver: %s\n", driver); - if (vendor) - printf(" Vendor: %s\n", vendor); - if (model) - printf(" Model: %s\n", model); - - if (info->has_mac_address) { - _cleanup_free_ char *description = NULL; - char ea[ETHER_ADDR_TO_STRING_MAX]; - - (void) ieee_oui(hwdb, &info->mac_address, &description); - - if (description) - printf(" HW Address: %s (%s)\n", ether_addr_to_string(&info->mac_address, ea), description); - else - printf(" HW Address: %s\n", ether_addr_to_string(&info->mac_address, ea)); - } - - if (info->has_mtu) - printf(" MTU: %u\n", info->mtu); - - (void) dump_addresses(rtnl, " Address: ", info->ifindex); - (void) dump_gateways(rtnl, hwdb, " Gateway: ", info->ifindex); - - dump_list(" DNS: ", dns); - dump_list(" Search Domains: ", search_domains); - dump_list(" Route Domains: ", route_domains); - - dump_list(" NTP: ", ntp); - - dump_ifindexes("Carrier Bound To: ", carrier_bound_to); - dump_ifindexes("Carrier Bound By: ", carrier_bound_by); - - (void) sd_network_link_get_timezone(info->ifindex, &tz); - if (tz) - printf(" Time Zone: %s\n", tz); - - (void) dump_lldp_neighbors(" Connected To: ", info->ifindex); - - return 0; -} - -static int system_status(sd_netlink *rtnl, sd_hwdb *hwdb) { - _cleanup_free_ char *operational_state = NULL; - _cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **search_domains = NULL, **route_domains = NULL; - const char *on_color_operational, *off_color_operational; - - assert(rtnl); - - (void) sd_network_get_operational_state(&operational_state); - operational_state_to_color(operational_state, &on_color_operational, &off_color_operational); - - printf("%s%s%s State: %s%s%s\n", - on_color_operational, special_glyph(BLACK_CIRCLE), off_color_operational, - on_color_operational, strna(operational_state), off_color_operational); - - (void) dump_addresses(rtnl, " Address: ", 0); - (void) dump_gateways(rtnl, hwdb, " Gateway: ", 0); - - (void) sd_network_get_dns(&dns); - dump_list(" DNS: ", dns); - - (void) sd_network_get_search_domains(&search_domains); - dump_list("Search Domains: ", search_domains); - - (void) sd_network_get_route_domains(&route_domains); - dump_list(" Route Domains: ", route_domains); - - (void) sd_network_get_ntp(&ntp); - dump_list(" NTP: ", ntp); - - return 0; -} - -static int link_status(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL; - _cleanup_free_ LinkInfo *links = NULL; - int r, c, i; - - pager_open(arg_no_pager, false); - - r = sd_netlink_open(&rtnl); - if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); - - r = sd_hwdb_new(&hwdb); - if (r < 0) - log_debug_errno(r, "Failed to open hardware database: %m"); - - if (arg_all) - c = acquire_link_info_all(rtnl, &links); - else if (argc <= 1) - return system_status(rtnl, hwdb); - else - c = acquire_link_info_strv(rtnl, argv + 1, &links); - if (c < 0) - return c; - - for (i = 0; i < c; i++) { - if (i > 0) - fputc('\n', stdout); - - link_status_one(rtnl, hwdb, links + i); - } - - return 0; -} - -static char *lldp_capabilities_to_string(uint16_t x) { - static const char characters[] = { - 'o', 'p', 'b', 'w', 'r', 't', 'd', 'a', 'c', 's', 'm', - }; - char *ret; - unsigned i; - - ret = new(char, ELEMENTSOF(characters) + 1); - if (!ret) - return NULL; - - for (i = 0; i < ELEMENTSOF(characters); i++) - ret[i] = (x & (1U << i)) ? characters[i] : '.'; - - ret[i] = 0; - return ret; -} - -static void lldp_capabilities_legend(uint16_t x) { - unsigned w, i, cols = columns(); - static const char* const table[] = { - "o - Other", - "p - Repeater", - "b - Bridge", - "w - WLAN Access Point", - "r - Router", - "t - Telephone", - "d - DOCSIS cable device", - "a - Station", - "c - Customer VLAN", - "s - Service VLAN", - "m - Two-port MAC Relay (TPMR)", - }; - - if (x == 0) - return; - - printf("\nCapability Flags:\n"); - for (w = 0, i = 0; i < ELEMENTSOF(table); i++) - if (x & (1U << i) || arg_all) { - bool newline; - - newline = w + strlen(table[i]) + (w == 0 ? 0 : 2) > cols; - if (newline) - w = 0; - w += printf("%s%s%s", newline ? "\n" : "", w == 0 ? "" : "; ", table[i]); - } - puts(""); -} - -static int link_lldp_status(int argc, char *argv[], void *userdata) { - _cleanup_(sd_netlink_unrefp) sd_netlink *rtnl = NULL; - _cleanup_free_ LinkInfo *links = NULL; - int i, r, c, m = 0; - uint16_t all = 0; - - r = sd_netlink_open(&rtnl); - if (r < 0) - return log_error_errno(r, "Failed to connect to netlink: %m"); - - if (argc > 1) - c = acquire_link_info_strv(rtnl, argv + 1, &links); - else - c = acquire_link_info_all(rtnl, &links); - if (c < 0) - return c; - - pager_open(arg_no_pager, false); - - if (arg_legend) - printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", - "LINK", - "CHASSIS ID", - "SYSTEM NAME", - "CAPS", - "PORT ID", - "PORT DESCRIPTION"); - - for (i = 0; i < c; i++) { - _cleanup_fclose_ FILE *f = NULL; - - r = open_lldp_neighbors(links[i].ifindex, &f); - if (r == -ENOENT) - continue; - if (r < 0) { - log_warning_errno(r, "Failed to open LLDP data for %i, ignoring: %m", links[i].ifindex); - continue; - } - - for (;;) { - _cleanup_free_ char *cid = NULL, *pid = NULL, *sname = NULL, *pdesc = NULL; - const char *chassis_id = NULL, *port_id = NULL, *system_name = NULL, *port_description = NULL, *capabilities = NULL; - _cleanup_(sd_lldp_neighbor_unrefp) sd_lldp_neighbor *n = NULL; - uint16_t cc; - - r = next_lldp_neighbor(f, &n); - if (r < 0) { - log_warning_errno(r, "Failed to read neighbor data: %m"); - break; - } - if (r == 0) - break; - - (void) sd_lldp_neighbor_get_chassis_id_as_string(n, &chassis_id); - (void) sd_lldp_neighbor_get_port_id_as_string(n, &port_id); - (void) sd_lldp_neighbor_get_system_name(n, &system_name); - (void) sd_lldp_neighbor_get_port_description(n, &port_description); - - if (chassis_id) { - cid = ellipsize(chassis_id, 17, 100); - if (cid) - chassis_id = cid; - } - - if (port_id) { - pid = ellipsize(port_id, 17, 100); - if (pid) - port_id = pid; - } - - if (system_name) { - sname = ellipsize(system_name, 16, 100); - if (sname) - system_name = sname; - } - - if (port_description) { - pdesc = ellipsize(port_description, 16, 100); - if (pdesc) - port_description = pdesc; - } - - if (sd_lldp_neighbor_get_enabled_capabilities(n, &cc) >= 0) { - capabilities = lldp_capabilities_to_string(cc); - all |= cc; - } - - printf("%-16s %-17s %-16s %-11s %-17s %-16s\n", - links[i].name, - strna(chassis_id), - strna(system_name), - strna(capabilities), - strna(port_id), - strna(port_description)); - - m++; - } - } - - if (arg_legend) { - lldp_capabilities_legend(all); - printf("\n%i neighbors listed.\n", m); - } - - return 0; -} - -static void help(void) { - printf("%s [OPTIONS...]\n\n" - "Query and control the networking subsystem.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --no-pager Do not pipe output into a pager\n" - " --no-legend Do not show the headers and footers\n" - " -a --all Show status for all links\n\n" - "Commands:\n" - " list [LINK...] List links\n" - " status [LINK...] Show link status\n" - " lldp [LINK...] Show LLDP neighbors\n" - , program_invocation_short_name); -} - -static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_VERSION = 0x100, - ARG_NO_PAGER, - ARG_NO_LEGEND, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "no-pager", no_argument, NULL, ARG_NO_PAGER }, - { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, - { "all", no_argument, NULL, 'a' }, - {} - }; - - int c; - - assert(argc >= 0); - assert(argv); - - while ((c = getopt_long(argc, argv, "ha", options, NULL)) >= 0) { - - switch (c) { - - case 'h': - help(); - return 0; - - case ARG_VERSION: - return version(); - - case ARG_NO_PAGER: - arg_no_pager = true; - break; - - case ARG_NO_LEGEND: - arg_legend = false; - break; - - case 'a': - arg_all = true; - break; - - case '?': - return -EINVAL; - - default: - assert_not_reached("Unhandled option"); - } - } - - return 1; -} - -static int networkctl_main(int argc, char *argv[]) { - const Verb verbs[] = { - { "list", VERB_ANY, VERB_ANY, VERB_DEFAULT, list_links }, - { "status", VERB_ANY, VERB_ANY, 0, link_status }, - { "lldp", VERB_ANY, VERB_ANY, 0, link_lldp_status }, - {} - }; - - return dispatch_verb(argc, argv, verbs, NULL); -} - -static void warn_networkd_missing(void) { - - if (access("/run/systemd/netif/state", F_OK) >= 0) - return; - - fprintf(stderr, "WARNING: systemd-networkd is not running, output will be incomplete.\n\n"); -} - -int main(int argc, char* argv[]) { - int r; - - log_parse_environment(); - log_open(); - - r = parse_argv(argc, argv); - if (r <= 0) - goto finish; - - warn_networkd_missing(); - - r = networkctl_main(argc, argv); - -finish: - pager_close(); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c deleted file mode 100644 index ebc6c9eb9e..0000000000 --- a/src/network/networkd-address-pool.c +++ /dev/null @@ -1,171 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "networkd-address-pool.h" -#include "networkd.h" -#include "set.h" -#include "string-util.h" - -int address_pool_new( - Manager *m, - AddressPool **ret, - int family, - const union in_addr_union *u, - unsigned prefixlen) { - - AddressPool *p; - - assert(m); - assert(ret); - assert(u); - - p = new0(AddressPool, 1); - if (!p) - return -ENOMEM; - - p->manager = m; - p->family = family; - p->prefixlen = prefixlen; - p->in_addr = *u; - - LIST_PREPEND(address_pools, m->address_pools, p); - - *ret = p; - return 0; -} - -int address_pool_new_from_string( - Manager *m, - AddressPool **ret, - int family, - const char *p, - unsigned prefixlen) { - - union in_addr_union u; - int r; - - assert(m); - assert(ret); - assert(p); - - r = in_addr_from_string(family, p, &u); - if (r < 0) - return r; - - return address_pool_new(m, ret, family, &u, prefixlen); -} - -void address_pool_free(AddressPool *p) { - - if (!p) - return; - - if (p->manager) - LIST_REMOVE(address_pools, p->manager->address_pools, p); - - free(p); -} - -static bool address_pool_prefix_is_taken( - AddressPool *p, - const union in_addr_union *u, - unsigned prefixlen) { - - Iterator i; - Link *l; - Network *n; - - assert(p); - assert(u); - - HASHMAP_FOREACH(l, p->manager->links, i) { - Address *a; - Iterator j; - - /* Don't clash with assigned addresses */ - SET_FOREACH(a, l->addresses, j) { - if (a->family != p->family) - continue; - - if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) - return true; - } - - /* Don't clash with addresses already pulled from the pool, but not assigned yet */ - LIST_FOREACH(addresses, a, l->pool_addresses) { - if (a->family != p->family) - continue; - - if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) - return true; - } - } - - /* And don't clash with configured but un-assigned addresses either */ - LIST_FOREACH(networks, n, p->manager->networks) { - Address *a; - - LIST_FOREACH(addresses, a, n->static_addresses) { - if (a->family != p->family) - continue; - - if (in_addr_prefix_intersect(p->family, u, prefixlen, &a->in_addr, a->prefixlen)) - return true; - } - } - - return false; -} - -int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found) { - union in_addr_union u; - - assert(p); - assert(prefixlen > 0); - assert(found); - - if (p->prefixlen > prefixlen) - return 0; - - u = p->in_addr; - for (;;) { - if (!address_pool_prefix_is_taken(p, &u, prefixlen)) { - _cleanup_free_ char *s = NULL; - int r; - - r = in_addr_to_string(p->family, &u, &s); - if (r < 0) - return r; - - log_debug("Found range %s/%u", strna(s), prefixlen); - - *found = u; - return 1; - } - - if (!in_addr_prefix_next(p->family, &u, prefixlen)) - return 0; - - if (!in_addr_prefix_intersect(p->family, &p->in_addr, p->prefixlen, &u, prefixlen)) - return 0; - } - - return 0; -} diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h deleted file mode 100644 index af30decfe0..0000000000 --- a/src/network/networkd-address-pool.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct AddressPool AddressPool; - -#include "in-addr-util.h" -#include "list.h" - -typedef struct Manager Manager; - -struct AddressPool { - Manager *manager; - - int family; - unsigned prefixlen; - - union in_addr_union in_addr; - - LIST_FIELDS(AddressPool, address_pools); -}; - -int address_pool_new(Manager *m, AddressPool **ret, int family, const union in_addr_union *u, unsigned prefixlen); -int address_pool_new_from_string(Manager *m, AddressPool **ret, int family, const char *p, unsigned prefixlen); -void address_pool_free(AddressPool *p); - -int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union *found); diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c deleted file mode 100644 index ed52d5e42d..0000000000 --- a/src/network/networkd-address.c +++ /dev/null @@ -1,922 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "alloc-util.h" -#include "conf-parser.h" -#include "firewall-util.h" -#include "netlink-util.h" -#include "networkd-address.h" -#include "networkd.h" -#include "parse-util.h" -#include "set.h" -#include "socket-util.h" -#include "string-util.h" -#include "utf8.h" -#include "util.h" - -#define ADDRESSES_PER_LINK_MAX 2048U -#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U - -int address_new(Address **ret) { - _cleanup_address_free_ Address *address = NULL; - - address = new0(Address, 1); - if (!address) - return -ENOMEM; - - address->family = AF_UNSPEC; - address->scope = RT_SCOPE_UNIVERSE; - address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME; - address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME; - - *ret = address; - address = NULL; - - return 0; -} - -int address_new_static(Network *network, unsigned section, Address **ret) { - _cleanup_address_free_ Address *address = NULL; - int r; - - assert(network); - assert(ret); - - if (section) { - address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section)); - if (address) { - *ret = address; - address = NULL; - - return 0; - } - } - - if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX) - return -E2BIG; - - r = address_new(&address); - if (r < 0) - return r; - - if (section) { - address->section = section; - hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address); - } - - address->network = network; - LIST_APPEND(addresses, network->static_addresses, address); - network->n_static_addresses++; - - *ret = address; - address = NULL; - - return 0; -} - -void address_free(Address *address) { - if (!address) - return; - - if (address->network) { - LIST_REMOVE(addresses, address->network->static_addresses, address); - assert(address->network->n_static_addresses > 0); - address->network->n_static_addresses--; - - if (address->section) - hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section)); - } - - if (address->link) { - set_remove(address->link->addresses, address); - set_remove(address->link->addresses_foreign, address); - - if (in_addr_equal(AF_INET6, &address->in_addr, (const union in_addr_union *) &address->link->ipv6ll_address)) - memzero(&address->link->ipv6ll_address, sizeof(struct in6_addr)); - } - - free(address); -} - -static void address_hash_func(const void *b, struct siphash *state) { - const Address *a = b; - - assert(a); - - siphash24_compress(&a->family, sizeof(a->family), state); - - switch (a->family) { - case AF_INET: - siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state); - - /* peer prefix */ - if (a->prefixlen != 0) { - uint32_t prefix; - - if (a->in_addr_peer.in.s_addr != 0) - prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen); - else - prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen); - - siphash24_compress(&prefix, sizeof(prefix), state); - } - - /* fallthrough */ - case AF_INET6: - /* local address */ - siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state); - - break; - default: - /* treat any other address family as AF_UNSPEC */ - break; - } -} - -static int address_compare_func(const void *c1, const void *c2) { - const Address *a1 = c1, *a2 = c2; - - if (a1->family < a2->family) - return -1; - if (a1->family > a2->family) - return 1; - - switch (a1->family) { - /* use the same notion of equality as the kernel does */ - case AF_INET: - if (a1->prefixlen < a2->prefixlen) - return -1; - if (a1->prefixlen > a2->prefixlen) - return 1; - - /* compare the peer prefixes */ - if (a1->prefixlen != 0) { - /* make sure we don't try to shift by 32. - * See ISO/IEC 9899:TC3 § 6.5.7.3. */ - uint32_t b1, b2; - - if (a1->in_addr_peer.in.s_addr != 0) - b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); - else - b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen); - - if (a2->in_addr_peer.in.s_addr != 0) - b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen); - else - b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen); - - if (b1 < b2) - return -1; - if (b1 > b2) - return 1; - } - - /* fall-through */ - case AF_INET6: - return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family)); - default: - /* treat any other address family as AF_UNSPEC */ - return 0; - } -} - -static const struct hash_ops address_hash_ops = { - .hash = address_hash_func, - .compare = address_compare_func -}; - -bool address_equal(Address *a1, Address *a2) { - if (a1 == a2) - return true; - - if (!a1 || !a2) - return false; - - return address_compare_func(a1, a2) == 0; -} - -static int address_establish(Address *address, Link *link) { - bool masq; - int r; - - assert(address); - assert(link); - - masq = link->network && - link->network->ip_masquerade && - address->family == AF_INET && - address->scope < RT_SCOPE_LINK; - - /* Add firewall entry if this is requested */ - if (address->ip_masquerade_done != masq) { - union in_addr_union masked = address->in_addr; - in_addr_mask(address->family, &masked, address->prefixlen); - - r = fw_add_masquerade(masq, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); - if (r < 0) - log_link_warning_errno(link, r, "Could not enable IP masquerading: %m"); - - address->ip_masquerade_done = masq; - } - - return 0; -} - -static int address_add_internal(Link *link, Set **addresses, - int family, - const union in_addr_union *in_addr, - unsigned char prefixlen, - Address **ret) { - _cleanup_address_free_ Address *address = NULL; - int r; - - assert(link); - assert(addresses); - assert(in_addr); - - r = address_new(&address); - if (r < 0) - return r; - - address->family = family; - address->in_addr = *in_addr; - address->prefixlen = prefixlen; - /* Consider address tentative until we get the real flags from the kernel */ - address->flags = IFA_F_TENTATIVE; - - r = set_ensure_allocated(addresses, &address_hash_ops); - if (r < 0) - return r; - - r = set_put(*addresses, address); - if (r < 0) - return r; - - address->link = link; - - if (ret) - *ret = address; - - address = NULL; - - return 0; -} - -int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { - return address_add_internal(link, &link->addresses_foreign, family, in_addr, prefixlen, ret); -} - -int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) { - Address *address; - int r; - - r = address_get(link, family, in_addr, prefixlen, &address); - if (r == -ENOENT) { - /* Address does not exist, create a new one */ - r = address_add_internal(link, &link->addresses, family, in_addr, prefixlen, &address); - if (r < 0) - return r; - } else if (r == 0) { - /* Take over a foreign address */ - r = set_ensure_allocated(&link->addresses, &address_hash_ops); - if (r < 0) - return r; - - r = set_put(link->addresses, address); - if (r < 0) - return r; - - set_remove(link->addresses_foreign, address); - } else if (r == 1) { - /* Already exists, do nothing */ - ; - } else - return r; - - if (ret) - *ret = address; - - return 0; -} - -static int address_release(Address *address) { - int r; - - assert(address); - assert(address->link); - - /* Remove masquerading firewall entry if it was added */ - if (address->ip_masquerade_done) { - union in_addr_union masked = address->in_addr; - in_addr_mask(address->family, &masked, address->prefixlen); - - r = fw_add_masquerade(false, AF_INET, 0, &masked, address->prefixlen, NULL, NULL, 0); - if (r < 0) - log_link_warning_errno(address->link, r, "Failed to disable IP masquerading: %m"); - - address->ip_masquerade_done = false; - } - - return 0; -} - -int address_update( - Address *address, - unsigned char flags, - unsigned char scope, - const struct ifa_cacheinfo *cinfo) { - - bool ready; - int r; - - assert(address); - assert(cinfo); - assert_return(address->link, 1); - - if (IN_SET(address->link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - ready = address_is_ready(address); - - address->flags = flags; - address->scope = scope; - address->cinfo = *cinfo; - - link_update_operstate(address->link); - - if (!ready && address_is_ready(address)) { - link_check_ready(address->link); - - if (address->family == AF_INET6 && - in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 && - in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) { - - r = link_ipv6ll_gained(address->link, &address->in_addr.in6); - if (r < 0) - return r; - } - } - - return 0; -} - -int address_drop(Address *address) { - Link *link; - bool ready; - - assert(address); - - ready = address_is_ready(address); - link = address->link; - - address_release(address); - address_free(address); - - link_update_operstate(link); - - if (link && !ready) - link_check_ready(link); - - return 0; -} - -int address_get(Link *link, - int family, - const union in_addr_union *in_addr, - unsigned char prefixlen, - Address **ret) { - - Address address, *existing; - - assert(link); - assert(in_addr); - - address = (Address) { - .family = family, - .in_addr = *in_addr, - .prefixlen = prefixlen, - }; - - existing = set_get(link->addresses, &address); - if (existing) { - if (ret) - *ret = existing; - return 1; - } - - existing = set_get(link->addresses_foreign, &address); - if (existing) { - if (ret) - *ret = existing; - return 0; - } - - return -ENOENT; -} - -int address_remove( - Address *address, - Link *link, - sd_netlink_message_handler_t callback) { - - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(address); - assert(address->family == AF_INET || address->family == AF_INET6); - assert(link); - assert(link->ifindex > 0); - assert(link->manager); - assert(link->manager->rtnl); - - r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_DELADDR, - link->ifindex, address->family); - if (r < 0) - return log_error_errno(r, "Could not allocate RTM_DELADDR message: %m"); - - r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set prefixlen: %m"); - - if (address->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); - else if (address->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); - if (r < 0) - return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m"); - - r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); - if (r < 0) - return log_error_errno(r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return 0; -} - -static int address_acquire(Link *link, Address *original, Address **ret) { - union in_addr_union in_addr = {}; - struct in_addr broadcast = {}; - _cleanup_address_free_ Address *na = NULL; - int r; - - assert(link); - assert(original); - assert(ret); - - /* Something useful was configured? just use it */ - if (in_addr_is_null(original->family, &original->in_addr) <= 0) - return 0; - - /* 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) - 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; - } - - if (original->family == AF_INET) { - /* Pick first address in range for ourselves ... */ - in_addr.in.s_addr = in_addr.in.s_addr | htobe32(1); - - /* .. and use last as broadcast address */ - broadcast.s_addr = in_addr.in.s_addr | htobe32(0xFFFFFFFFUL >> original->prefixlen); - } else if (original->family == AF_INET6) - in_addr.in6.s6_addr[15] |= 1; - - r = address_new(&na); - if (r < 0) - return r; - - na->family = original->family; - na->prefixlen = original->prefixlen; - na->scope = original->scope; - na->cinfo = original->cinfo; - - if (original->label) { - na->label = strdup(original->label); - if (!na->label) - return -ENOMEM; - } - - na->broadcast = broadcast; - na->in_addr = in_addr; - - LIST_PREPEND(addresses, link->pool_addresses, na); - - *ret = na; - na = NULL; - - return 0; -} - -int address_configure( - Address *address, - Link *link, - sd_netlink_message_handler_t callback, - bool update) { - - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(address); - assert(address->family == AF_INET || address->family == AF_INET6); - assert(link); - assert(link->ifindex > 0); - assert(link->manager); - assert(link->manager->rtnl); - - /* If this is a new address, then refuse adding more than the limit */ - if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 && - set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX) - return -E2BIG; - - r = address_acquire(link, address, &address); - if (r < 0) - return r; - - if (update) - r = sd_rtnl_message_new_addr_update(link->manager->rtnl, &req, - link->ifindex, address->family); - else - r = sd_rtnl_message_new_addr(link->manager->rtnl, &req, RTM_NEWADDR, - link->ifindex, address->family); - if (r < 0) - return log_error_errno(r, "Could not allocate RTM_NEWADDR message: %m"); - - r = sd_rtnl_message_addr_set_prefixlen(req, address->prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set prefixlen: %m"); - - address->flags |= IFA_F_PERMANENT; - - if (address->home_address) - address->flags |= IFA_F_HOMEADDRESS; - - if (address->duplicate_address_detection) - address->flags |= IFA_F_NODAD; - - if (address->manage_temporary_address) - address->flags |= IFA_F_MANAGETEMPADDR; - - if (address->prefix_route) - address->flags |= IFA_F_NOPREFIXROUTE; - - if (address->autojoin) - address->flags |= IFA_F_MCAUTOJOIN; - - 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_netlink_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"); - - if (address->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, IFA_LOCAL, &address->in_addr.in); - else if (address->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, IFA_LOCAL, &address->in_addr.in6); - if (r < 0) - return log_error_errno(r, "Could not append IFA_LOCAL attribute: %m"); - - if (!in_addr_is_null(address->family, &address->in_addr_peer)) { - if (address->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, IFA_ADDRESS, &address->in_addr_peer.in); - else if (address->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, IFA_ADDRESS, &address->in_addr_peer.in6); - if (r < 0) - return log_error_errno(r, "Could not append IFA_ADDRESS attribute: %m"); - } else { - if (address->family == AF_INET) { - r = sd_netlink_message_append_in_addr(req, IFA_BROADCAST, &address->broadcast); - if (r < 0) - return log_error_errno(r, "Could not append IFA_BROADCAST attribute: %m"); - } - } - - if (address->label) { - r = sd_netlink_message_append_string(req, IFA_LABEL, address->label); - if (r < 0) - return log_error_errno(r, "Could not append IFA_LABEL attribute: %m"); - } - - r = sd_netlink_message_append_cache_info(req, IFA_CACHEINFO, - &address->cinfo); - if (r < 0) - return log_error_errno(r, "Could not append IFA_CACHEINFO attribute: %m"); - - r = address_establish(address, link); - if (r < 0) - return r; - - r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); - if (r < 0) { - address_release(address); - return log_error_errno(r, "Could not send rtnetlink message: %m"); - } - - link_ref(link); - - r = address_add(link, address->family, &address->in_addr, address->prefixlen, NULL); - if (r < 0) { - address_release(address); - return log_error_errno(r, "Could not add address: %m"); - } - - return 0; -} - -int config_parse_broadcast( - 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_address_free_ Address *n = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = address_new_static(network, section_line, &n); - if (r < 0) - return r; - - if (n->family == AF_INET6) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue); - return 0; - } - - r = in_addr_from_string(AF_INET, rvalue, (union in_addr_union*) &n->broadcast); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Broadcast is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - n->family = AF_INET; - n = NULL; - - return 0; -} - -int config_parse_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) { - - Network *network = userdata; - _cleanup_address_free_ Address *n = NULL; - const char *address, *e; - union in_addr_union buffer; - int r, f; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - if (streq(section, "Network")) { - /* we are not in an Address section, so treat - * this as the special '0' section */ - section_line = 0; - } - - r = address_new_static(network, section_line, &n); - if (r < 0) - return r; - - /* Address=address/prefixlen */ - - /* prefixlen */ - e = strchr(rvalue, '/'); - if (e) { - unsigned i; - - r = safe_atou(e + 1, &i); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1); - return 0; - } - - n->prefixlen = (unsigned char) i; - - address = strndupa(rvalue, e - rvalue); - } else - address = rvalue; - - r = in_addr_from_string_auto(address, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Address is invalid, ignoring assignment: %s", address); - return 0; - } - - if (!e && f == AF_INET) { - r = in_addr_default_prefixlen(&buffer.in, &n->prefixlen); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address); - return 0; - } - } - - if (n->family != AF_UNSPEC && f != n->family) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", address); - return 0; - } - - n->family = f; - - if (streq(lvalue, "Address")) - n->in_addr = buffer; - else - n->in_addr_peer = buffer; - - if (n->family == AF_INET && n->broadcast.s_addr == 0) - n->broadcast.s_addr = n->in_addr.in.s_addr | htonl(0xfffffffflu >> n->prefixlen); - - n = NULL; - - return 0; -} - -int config_parse_label( - 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) { - - _cleanup_address_free_ Address *n = NULL; - Network *network = userdata; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = address_new_static(network, section_line, &n); - if (r < 0) - return r; - - if (!ifname_valid(rvalue)) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not valid or too long, ignoring assignment: %s", rvalue); - return 0; - } - - r = free_and_strdup(&n->label, rvalue); - if (r < 0) - return log_oom(); - - n = NULL; - - return 0; -} - -int config_parse_lifetime(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_address_free_ Address *n = NULL; - unsigned k; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = address_new_static(network, section_line, &n); - if (r < 0) - return r; - - if (STR_IN_SET(rvalue, "forever", "infinity")) { - n->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME; - n = NULL; - - return 0; - } - - r = safe_atou(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse PreferredLifetime, ignoring: %s", rvalue); - return 0; - } - - if (k != 0) - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid PreferredLifetime value, ignoring: %d", k); - else { - n->cinfo.ifa_prefered = k; - n = NULL; - } - - return 0; -} - -int config_parse_address_flags(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_address_free_ Address *n = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = address_new_static(network, section_line, &n); - if (r < 0) - return r; - - r = parse_boolean(rvalue); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue); - return 0; - } - - if (streq(lvalue, "HomeAddress")) - n->home_address = r; - else if (streq(lvalue, "DuplicateAddressDetection")) - n->duplicate_address_detection = r; - else if (streq(lvalue, "ManageTemporaryAddress")) - n->manage_temporary_address = r; - else if (streq(lvalue, "PrefixRoute")) - n->prefix_route = r; - else if (streq(lvalue, "AutoJoin")) - n->autojoin = r; - - return 0; -} - -bool address_is_ready(const Address *a) { - assert(a); - - return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED)); -} diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h deleted file mode 100644 index bc3b4fc7f3..0000000000 --- a/src/network/networkd-address.h +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <inttypes.h> -#include <stdbool.h> - -#include "in-addr-util.h" - -typedef struct Address Address; - -#include "networkd-link.h" -#include "networkd-network.h" - -#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU - -typedef struct Network Network; -typedef struct Link Link; - -struct Address { - Network *network; - unsigned section; - - Link *link; - - int family; - unsigned char prefixlen; - unsigned char scope; - uint32_t flags; - char *label; - - struct in_addr broadcast; - struct ifa_cacheinfo cinfo; - - union in_addr_union in_addr; - union in_addr_union in_addr_peer; - - bool ip_masquerade_done:1; - bool duplicate_address_detection; - bool manage_temporary_address; - bool home_address; - bool prefix_route; - bool autojoin; - - LIST_FIELDS(Address, addresses); -}; - -int address_new_static(Network *network, unsigned section, Address **ret); -int address_new(Address **ret); -void address_free(Address *address); -int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); -int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); -int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret); -int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo); -int address_drop(Address *address); -int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update); -int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback); -bool address_equal(Address *a1, Address *a2); -bool address_is_ready(const Address *a); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free); -#define _cleanup_address_free_ _cleanup_(address_freep) - -int config_parse_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); -int config_parse_broadcast(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_label(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_lifetime(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_address_flags(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-brvlan.c b/src/network/networkd-brvlan.c deleted file mode 100644 index 18ecd86858..0000000000 --- a/src/network/networkd-brvlan.c +++ /dev/null @@ -1,349 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2016 BISDN GmbH. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/in.h> -#include <linux/if_bridge.h> -#include <stdbool.h> - -#include "alloc-util.h" -#include "conf-parser.h" -#include "netlink-util.h" -#include "networkd-brvlan.h" -#include "networkd.h" -#include "parse-util.h" -#include "vlan-util.h" - -static bool is_bit_set(unsigned bit, uint32_t scope) { - assert(bit < sizeof(scope)*8); - return scope & (1 << bit); -} - -static inline void set_bit(unsigned nr, uint32_t *addr) { - if (nr < BRIDGE_VLAN_BITMAP_MAX) - addr[nr / 32] |= (((uint32_t) 1) << (nr % 32)); -} - -static int find_next_bit(int i, uint32_t x) { - int j; - - if (i >= 32) - return -1; - - /* find first bit */ - if (i < 0) - return BUILTIN_FFS_U32(x); - - /* mask off prior finds to get next */ - j = __builtin_ffs(x >> i); - return j ? j + i : 0; -} - -static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) { - struct bridge_vlan_info br_vlan; - int i, j, k, r, done, cnt; - uint16_t begin, end; - bool untagged = false; - - assert(link); - assert(req); - assert(br_vid_bitmap); - assert(br_untagged_bitmap); - - i = cnt = -1; - - begin = end = UINT16_MAX; - for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) { - unsigned base_bit; - uint32_t vid_map = br_vid_bitmap[k]; - uint32_t untagged_map = br_untagged_bitmap[k]; - - base_bit = k * 32; - i = -1; - done = 0; - do { - j = find_next_bit(i, vid_map); - if (j > 0) { - /* first hit of any bit */ - if (begin == UINT16_MAX && end == UINT16_MAX) { - begin = end = j - 1 + base_bit; - untagged = is_bit_set(j - 1, untagged_map); - goto next; - } - - /* this bit is a continuation of prior bits */ - if (j - 2 + base_bit == end && untagged == is_bit_set(j - 1, untagged_map) && (uint16_t)j - 1 + base_bit != pvid && (uint16_t)begin != pvid) { - end++; - goto next; - } - } else - done = 1; - - if (begin != UINT16_MAX) { - cnt++; - if (done && k < BRIDGE_VLAN_BITMAP_LEN - 1) - break; - - br_vlan.flags = 0; - if (untagged) - br_vlan.flags |= BRIDGE_VLAN_INFO_UNTAGGED; - - if (begin == end) { - br_vlan.vid = begin; - - if (begin == pvid) - br_vlan.flags |= BRIDGE_VLAN_INFO_PVID; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - } else { - br_vlan.vid = begin; - br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - - br_vlan.vid = end; - br_vlan.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN; - br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_END; - - r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan)); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m"); - } - - if (done) - break; - } - if (j > 0) { - begin = end = j - 1 + base_bit; - untagged = is_bit_set(j - 1, untagged_map); - } - - next: - i = j; - } while(!done); - } - if (!cnt) - return -EINVAL; - - return cnt; -} - -static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - Link *link = userdata; - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_error_errno(link, r, "Could not add VLAN to bridge port: %m"); - - return 1; -} - -int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - uint16_t flags; - sd_netlink *rtnl; - - assert(link); - assert(link->manager); - assert(br_vid_bitmap); - assert(br_untagged_bitmap); - assert(link->network); - - /* pvid might not be in br_vid_bitmap yet */ - if (pvid) - set_bit(pvid, br_vid_bitmap); - - rtnl = link->manager->rtnl; - - /* create new RTM message */ - r = sd_rtnl_message_new_link(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) - return log_link_error_errno(link, r, "Could not set message family: %m"); - - r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); - if (r < 0) - return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); - - /* master needs flag self */ - if (!link->network->bridge) { - flags = BRIDGE_FLAGS_SELF; - sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t)); - } - - /* add vlan info */ - r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap); - if (r < 0) - return log_link_error_errno(link, r, "Could not append VLANs: %m"); - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); - - /* send message to the kernel */ - r = sd_netlink_call_async(rtnl, req, set_brvlan_handler, link, 0, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - return 0; -} - -static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) { - int r; - char *p; - char *_rvalue = NULL; - uint16_t _vid = UINT16_MAX; - uint16_t _vid_end = UINT16_MAX; - - assert(rvalue); - assert(vid); - assert(vid_end); - - _rvalue = strdupa(rvalue); - p = strchr(_rvalue, '-'); - if (p) { - *p = '\0'; - p++; - r = parse_vlanid(_rvalue, &_vid); - if (r < 0) - return r; - - if (_vid == 0) - return -ERANGE; - - r = parse_vlanid(p, &_vid_end); - if (r < 0) - return r; - - if (_vid_end == 0) - return -ERANGE; - } else { - r = parse_vlanid(_rvalue, &_vid); - if (r < 0) - return r; - - if (_vid == 0) - return -ERANGE; - } - - *vid = _vid; - *vid_end = _vid_end; - return r; -} - -int config_parse_brvlan_pvid(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; - int r; - uint16_t pvid; - r = parse_vlanid(rvalue, &pvid); - if (r < 0) - return r; - - network->pvid = pvid; - network->use_br_vlan = true; - - return 0; -} - -int config_parse_brvlan_vlan(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; - int r; - uint16_t vid, vid_end; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = parse_vid_range(rvalue, &vid, &vid_end); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN, ignoring: %s", rvalue); - return 0; - } - - if (UINT16_MAX == vid_end) - set_bit(vid++, network->br_vid_bitmap); - else { - if (vid >= vid_end) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue); - return 0; - } - for (; vid <= vid_end; vid++) - set_bit(vid, network->br_vid_bitmap); - } - network->use_br_vlan = true; - return 0; -} - -int config_parse_brvlan_untagged(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; - int r; - uint16_t vid, vid_end; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = parse_vid_range(rvalue, &vid, &vid_end); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse VLAN: %s", rvalue); - return 0; - } - - if (UINT16_MAX == vid_end) { - set_bit(vid, network->br_vid_bitmap); - set_bit(vid, network->br_untagged_bitmap); - } else { - if (vid >= vid_end) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue); - return 0; - } - for (; vid <= vid_end; vid++) { - set_bit(vid, network->br_vid_bitmap); - set_bit(vid, network->br_untagged_bitmap); - } - } - network->use_br_vlan = true; - return 0; -} diff --git a/src/network/networkd-brvlan.h b/src/network/networkd-brvlan.h deleted file mode 100644 index b37633f94f..0000000000 --- a/src/network/networkd-brvlan.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright (C) 2016 BISDN GmbH. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <stdint.h> - -typedef struct Link Link; - -int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap); - -int config_parse_brvlan_pvid(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_brvlan_vlan(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_brvlan_untagged(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-conf.c b/src/network/networkd-conf.c deleted file mode 100644 index 49bb8c18f6..0000000000 --- a/src/network/networkd-conf.c +++ /dev/null @@ -1,111 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. - ***/ - -#include <ctype.h> - -#include "conf-parser.h" -#include "def.h" -#include "dhcp-identifier.h" -#include "hexdecoct.h" -#include "networkd-conf.h" -#include "string-table.h" - -int manager_parse_config_file(Manager *m) { - assert(m); - - return config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf", - CONF_PATHS_NULSTR("systemd/networkd.conf.d"), - "DHCP\0", - config_item_perf_lookup, networkd_gperf_lookup, - false, m); -} - -static const char* const duid_type_table[_DUID_TYPE_MAX] = { - [DUID_TYPE_LLT] = "link-layer-time", - [DUID_TYPE_EN] = "vendor", - [DUID_TYPE_LL] = "link-layer", - [DUID_TYPE_UUID] = "uuid", -}; -DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(duid_type, DUIDType); -DEFINE_CONFIG_PARSE_ENUM(config_parse_duid_type, duid_type, DUIDType, "Failed to parse DUID type"); - -int config_parse_duid_rawdata( - 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) { - - DUID *ret = data; - uint8_t raw_data[MAX_DUID_LEN]; - unsigned count = 0; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ret); - - /* RawData contains DUID in format "NN:NN:NN..." */ - for (;;) { - int n1, n2, len, r; - uint32_t byte; - _cleanup_free_ char *cbyte = NULL; - - r = extract_first_word(&rvalue, &cbyte, ":", 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to read DUID, ignoring assignment: %s.", rvalue); - return 0; - } - if (r == 0) - break; - if (count >= MAX_DUID_LEN) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue); - return 0; - } - - len = strlen(cbyte); - if (len != 1 && len != 2) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid length - DUID byte: %s, ignoring assignment: %s.", cbyte, rvalue); - return 0; - } - n1 = unhexchar(cbyte[0]); - if (len == 2) - n2 = unhexchar(cbyte[1]); - else - n2 = 0; - - if (n1 < 0 || n2 < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid DUID byte: %s. Ignoring assignment: %s.", cbyte, rvalue); - return 0; - } - - byte = ((uint8_t) n1 << (4 * (len-1))) | (uint8_t) n2; - raw_data[count++] = byte; - } - - assert_cc(sizeof(raw_data) == sizeof(ret->raw_data)); - memcpy(ret->raw_data, raw_data, count); - ret->raw_data_len = count; - return 0; -} diff --git a/src/network/networkd-conf.h b/src/network/networkd-conf.h deleted file mode 100644 index 00ddb7672a..0000000000 --- a/src/network/networkd-conf.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Vinay Kulkarni <kulkarniv@vmware.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd.h" - -int manager_parse_config_file(Manager *m); - -const struct ConfigPerfItem* networkd_gperf_lookup(const char *key, GPERF_LEN_TYPE length); - -int config_parse_duid_type( - 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_duid_rawdata( - 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-dhcp4.c b/src/network/networkd-dhcp4.c deleted file mode 100644 index 76d3d132ea..0000000000 --- a/src/network/networkd-dhcp4.c +++ /dev/null @@ -1,660 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013-2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if.h> - -#include "alloc-util.h" -#include "dhcp-lease-internal.h" -#include "hostname-util.h" -#include "network-internal.h" -#include "networkd.h" - -static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - assert(link->dhcp4_messages > 0); - - link->dhcp4_messages--; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "Could not set DHCPv4 route: %m"); - link_enter_failed(link); - } - - if (link->dhcp4_messages == 0) { - link->dhcp4_configured = true; - link_check_ready(link); - } - - return 1; -} - -static int link_set_dhcp_routes(Link *link) { - struct in_addr gateway; - _cleanup_free_ sd_dhcp_route **static_routes = NULL; - int r, n, i; - - assert(link); - assert(link->dhcp_lease); - assert(link->network); - - if (!link->network->dhcp_use_routes) - return 0; - - r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); - if (r < 0 && r != -ENODATA) - return log_link_warning_errno(link, r, "DHCP error: could not get gateway: %m"); - - if (r >= 0) { - struct in_addr address; - _cleanup_route_free_ Route *route = NULL; - _cleanup_route_free_ Route *route_gw = NULL; - - r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP error: could not get address: %m"); - - r = route_new(&route); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate route: %m"); - - route->protocol = RTPROT_DHCP; - - r = route_new(&route_gw); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate route: %m"); - - /* The dhcp netmask may mask out the gateway. Add an explicit - * route for the gw host so that we can route no matter the - * netmask or existing kernel route tables. */ - route_gw->family = AF_INET; - route_gw->dst.in = gateway; - route_gw->dst_prefixlen = 32; - route_gw->prefsrc.in = address; - route_gw->scope = RT_SCOPE_LINK; - route_gw->protocol = RTPROT_DHCP; - route_gw->priority = link->network->dhcp_route_metric; - route_gw->table = link->network->dhcp_route_table; - - r = route_configure(route_gw, link, dhcp4_route_handler); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set host route: %m"); - - link->dhcp4_messages++; - - route->family = AF_INET; - route->gw.in = gateway; - route->prefsrc.in = address; - route->priority = link->network->dhcp_route_metric; - route->table = link->network->dhcp_route_table; - - r = route_configure(route, link, dhcp4_route_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set routes: %m"); - link_enter_failed(link); - return r; - } - - link->dhcp4_messages++; - } - - n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes); - if (n == -ENODATA) - return 0; - if (n < 0) - return log_link_warning_errno(link, n, "DHCP error: could not get routes: %m"); - - for (i = 0; i < n; i++) { - _cleanup_route_free_ Route *route = NULL; - - r = route_new(&route); - if (r < 0) - return log_link_error_errno(link, r, "Could not allocate route: %m"); - - route->family = AF_INET; - route->protocol = RTPROT_DHCP; - assert_se(sd_dhcp_route_get_gateway(static_routes[i], &route->gw.in) >= 0); - assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0); - assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0); - route->priority = link->network->dhcp_route_metric; - route->table = link->network->dhcp_route_table; - - r = route_configure(route, link, dhcp4_route_handler); - if (r < 0) - return log_link_warning_errno(link, r, "Could not set host route: %m"); - - link->dhcp4_messages++; - } - - return 0; -} - -static int dhcp_lease_lost(Link *link) { - _cleanup_address_free_ Address *address = NULL; - struct in_addr addr; - struct in_addr netmask; - struct in_addr gateway; - unsigned prefixlen = 0; - int r; - - assert(link); - assert(link->dhcp_lease); - - log_link_warning(link, "DHCP lease lost"); - - if (link->network->dhcp_use_routes) { - _cleanup_free_ sd_dhcp_route **routes = NULL; - int n, i; - - n = sd_dhcp_lease_get_routes(link->dhcp_lease, &routes); - if (n >= 0) { - for (i = 0; i < n; i++) { - _cleanup_route_free_ Route *route = NULL; - - r = route_new(&route); - if (r >= 0) { - route->family = AF_INET; - assert_se(sd_dhcp_route_get_gateway(routes[i], &route->gw.in) >= 0); - assert_se(sd_dhcp_route_get_destination(routes[i], &route->dst.in) >= 0); - assert_se(sd_dhcp_route_get_destination_prefix_length(routes[i], &route->dst_prefixlen) >= 0); - - route_remove(route, link, - link_route_remove_handler); - } - } - } - } - - r = address_new(&address); - if (r >= 0) { - r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway); - if (r >= 0) { - _cleanup_route_free_ Route *route_gw = NULL; - _cleanup_route_free_ Route *route = NULL; - - r = route_new(&route_gw); - if (r >= 0) { - route_gw->family = AF_INET; - route_gw->dst.in = gateway; - route_gw->dst_prefixlen = 32; - route_gw->scope = RT_SCOPE_LINK; - - route_remove(route_gw, link, - link_route_remove_handler); - } - - r = route_new(&route); - if (r >= 0) { - route->family = AF_INET; - route->gw.in = gateway; - - route_remove(route, link, - link_route_remove_handler); - } - } - - r = sd_dhcp_lease_get_address(link->dhcp_lease, &addr); - if (r >= 0) { - r = sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask); - if (r >= 0) - prefixlen = in_addr_netmask_to_prefixlen(&netmask); - - address->family = AF_INET; - address->in_addr.in = addr; - address->prefixlen = prefixlen; - - address_remove(address, link, link_address_remove_handler); - } - } - - if (link->network->dhcp_use_mtu) { - uint16_t mtu; - - r = sd_dhcp_lease_get_mtu(link->dhcp_lease, &mtu); - if (r >= 0 && link->original_mtu != mtu) { - r = link_set_mtu(link, link->original_mtu); - if (r < 0) { - log_link_warning(link, - "DHCP error: could not reset MTU"); - link_enter_failed(link); - return r; - } - } - } - - if (link->network->dhcp_use_hostname) { - const char *hostname = NULL; - - if (link->network->dhcp_hostname) - hostname = link->network->dhcp_hostname; - else - (void) sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname); - - if (hostname) { - /* If a hostname was set due to the lease, then unset it now. */ - r = link_set_hostname(link, NULL); - if (r < 0) - log_link_warning_errno(link, r, "Failed to reset transient hostname: %m"); - } - } - - link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease); - link_dirty(link); - link->dhcp4_configured = false; - - return 0; -} - -static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "Could not set DHCPv4 address: %m"); - link_enter_failed(link); - } else if (r >= 0) - manager_rtnl_process_address(rtnl, m, link->manager); - - link_set_dhcp_routes(link); - - return 1; -} - -static int dhcp4_update_address(Link *link, - struct in_addr *address, - struct in_addr *netmask, - uint32_t lifetime) { - _cleanup_address_free_ Address *addr = NULL; - unsigned prefixlen; - int r; - - assert(address); - assert(netmask); - assert(lifetime); - - prefixlen = in_addr_netmask_to_prefixlen(netmask); - - r = address_new(&addr); - if (r < 0) - return r; - - addr->family = AF_INET; - addr->in_addr.in.s_addr = address->s_addr; - addr->cinfo.ifa_prefered = lifetime; - addr->cinfo.ifa_valid = lifetime; - addr->prefixlen = prefixlen; - addr->broadcast.s_addr = address->s_addr | ~netmask->s_addr; - - /* allow reusing an existing address and simply update its lifetime - * in case it already exists */ - r = address_configure(addr, link, dhcp4_address_handler, true); - if (r < 0) - return r; - - return 0; -} - -static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) { - sd_dhcp_lease *lease; - struct in_addr address; - struct in_addr netmask; - uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; - int r; - - assert(link); - assert(client); - assert(link->network); - - r = sd_dhcp_client_get_lease(client, &lease); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP error: no lease: %m"); - - sd_dhcp_lease_unref(link->dhcp_lease); - link->dhcp4_configured = false; - link->dhcp_lease = sd_dhcp_lease_ref(lease); - link_dirty(link); - - r = sd_dhcp_lease_get_address(lease, &address); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP error: no address: %m"); - - r = sd_dhcp_lease_get_netmask(lease, &netmask); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP error: no netmask: %m"); - - if (!link->network->dhcp_critical) { - r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); - if (r < 0) - return log_link_warning_errno(link, r, "DHCP error: no lifetime: %m"); - } - - r = dhcp4_update_address(link, &address, &netmask, lifetime); - if (r < 0) { - log_link_warning_errno(link, r, "Could not update IP address: %m"); - link_enter_failed(link); - return r; - } - - return 0; -} - -static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) { - sd_dhcp_lease *lease; - struct in_addr address; - struct in_addr netmask; - struct in_addr gateway; - unsigned prefixlen; - uint32_t lifetime = CACHE_INFO_INFINITY_LIFE_TIME; - int r; - - assert(client); - assert(link); - - r = sd_dhcp_client_get_lease(client, &lease); - 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) - return log_link_error_errno(link, r, "DHCP error: No address: %m"); - - r = sd_dhcp_lease_get_netmask(lease, &netmask); - 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 != -ENODATA) - return log_link_error_errno(link, r, "DHCP error: Could not get gateway: %m"); - - if (r >= 0) - 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_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 = sd_dhcp_lease_ref(lease); - link_dirty(link); - - if (link->network->dhcp_use_mtu) { - uint16_t mtu; - - r = sd_dhcp_lease_get_mtu(lease, &mtu); - if (r >= 0) { - r = link_set_mtu(link, mtu); - if (r < 0) - log_link_error_errno(link, r, "Failed to set MTU to %" PRIu16 ": %m", mtu); - } - } - - if (link->network->dhcp_use_hostname) { - const char *hostname = NULL; - - if (link->network->dhcp_hostname) - hostname = link->network->dhcp_hostname; - else - (void) sd_dhcp_lease_get_hostname(lease, &hostname); - - if (hostname) { - r = link_set_hostname(link, hostname); - if (r < 0) - log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname); - } - } - - if (link->network->dhcp_use_timezone) { - const char *tz = NULL; - - (void) sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); - - if (tz) { - r = link_set_timezone(link, tz); - if (r < 0) - log_link_error_errno(link, r, "Failed to set timezone to '%s': %m", tz); - } - } - - if (!link->network->dhcp_critical) { - r = sd_dhcp_lease_get_lifetime(link->dhcp_lease, &lifetime); - if (r < 0) { - 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_errno(link, r, "Could not update IP address: %m"); - link_enter_failed(link); - return r; - } - - return 0; -} -static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) { - Link *link = userdata; - int r = 0; - - assert(link); - assert(link->network); - assert(link->manager); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - switch (event) { - case SD_DHCP_CLIENT_EVENT_EXPIRED: - case SD_DHCP_CLIENT_EVENT_STOP: - case SD_DHCP_CLIENT_EVENT_IP_CHANGE: - if (link->network->dhcp_critical) { - log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it."); - return; - } - - if (link->dhcp_lease) { - r = dhcp_lease_lost(link); - if (r < 0) { - link_enter_failed(link); - return; - } - } - - if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) { - r = dhcp_lease_acquired(client, link); - if (r < 0) { - link_enter_failed(link); - return; - } - } - - break; - case SD_DHCP_CLIENT_EVENT_RENEW: - r = dhcp_lease_renew(client, link); - if (r < 0) { - link_enter_failed(link); - return; - } - break; - case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE: - r = dhcp_lease_acquired(client, link); - if (r < 0) { - link_enter_failed(link); - return; - } - break; - default: - if (event < 0) - log_link_warning_errno(link, event, "DHCP error: Client failed: %m"); - else - log_link_warning(link, "DHCP unknown event: %i", event); - break; - } - - return; -} - -int dhcp4_configure(Link *link) { - int r; - - assert(link); - assert(link->network); - assert(link->network->dhcp & ADDRESS_FAMILY_IPV4); - - if (!link->dhcp_client) { - r = sd_dhcp_client_new(&link->dhcp_client); - if (r < 0) - return r; - } - - r = sd_dhcp_client_attach_event(link->dhcp_client, NULL, 0); - if (r < 0) - return r; - - r = sd_dhcp_client_set_mac(link->dhcp_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), ARPHRD_ETHER); - if (r < 0) - return r; - - r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex); - if (r < 0) - return r; - - r = sd_dhcp_client_set_callback(link->dhcp_client, dhcp4_handler, link); - if (r < 0) - return r; - - r = sd_dhcp_client_set_request_broadcast(link->dhcp_client, - link->network->dhcp_broadcast); - if (r < 0) - return r; - - if (link->mtu) { - r = sd_dhcp_client_set_mtu(link->dhcp_client, link->mtu); - if (r < 0) - return r; - } - - if (link->network->dhcp_use_mtu) { - r = sd_dhcp_client_set_request_option(link->dhcp_client, - SD_DHCP_OPTION_INTERFACE_MTU); - if (r < 0) - return r; - } - - if (link->network->dhcp_use_routes) { - r = sd_dhcp_client_set_request_option(link->dhcp_client, - SD_DHCP_OPTION_STATIC_ROUTE); - if (r < 0) - return r; - r = sd_dhcp_client_set_request_option(link->dhcp_client, - SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE); - if (r < 0) - return r; - } - - /* Always acquire the timezone and NTP */ - r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NTP_SERVER); - if (r < 0) - return r; - - r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_NEW_TZDB_TIMEZONE); - if (r < 0) - return r; - - if (link->network->dhcp_send_hostname) { - _cleanup_free_ char *hostname = NULL; - const char *hn = NULL; - - if (!link->network->dhcp_hostname) { - hostname = gethostname_malloc(); - if (!hostname) - return -ENOMEM; - - hn = hostname; - } else - hn = link->network->dhcp_hostname; - - if (!is_localhost(hn)) { - r = sd_dhcp_client_set_hostname(link->dhcp_client, hn); - if (r < 0) - return r; - } - } - - if (link->network->dhcp_vendor_class_identifier) { - r = sd_dhcp_client_set_vendor_class_identifier(link->dhcp_client, - link->network->dhcp_vendor_class_identifier); - if (r < 0) - return r; - } - - switch (link->network->dhcp_client_identifier) { - case DHCP_CLIENT_ID_DUID: { - /* If configured, apply user specified DUID and/or IAID */ - const DUID *duid = link_duid(link); - - r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, - link->network->iaid, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return r; - 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 deleted file mode 100644 index 15acf56a5f..0000000000 --- a/src/network/networkd-dhcp6.c +++ /dev/null @@ -1,265 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if.h> - -#include "sd-dhcp6-client.h" - -#include "network-internal.h" -#include "networkd.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; -} - -static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - - r = sd_netlink_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_errno(link, r, "Could not set DHCPv6 address: %m"); - - link_enter_failed(link); - - } else if (r >= 0) - manager_rtnl_process_address(rtnl, m, link->manager); - - return 1; -} - -static int dhcp6_address_change( - Link *link, - struct in6_addr *ip6_addr, - uint32_t lifetime_preferred, - uint32_t lifetime_valid) { - - _cleanup_address_free_ Address *addr = NULL; - char buffer[INET6_ADDRSTRLEN]; - int r; - - r = address_new(&addr); - if (r < 0) - return r; - - addr->family = AF_INET6; - memcpy(&addr->in_addr.in6, ip6_addr, sizeof(*ip6_addr)); - - addr->flags = IFA_F_NOPREFIXROUTE; - addr->prefixlen = 128; - - addr->cinfo.ifa_prefered = lifetime_preferred; - addr->cinfo.ifa_valid = lifetime_valid; - - log_link_info(link, - "DHCPv6 address %s/%d timeout preferred %d valid %d", - inet_ntop(AF_INET6, &addr->in_addr.in6, buffer, sizeof(buffer)), - addr->prefixlen, lifetime_preferred, lifetime_valid); - - r = address_configure(addr, link, dhcp6_address_handler, true); - if (r < 0) - log_link_warning_errno(link, r, "Could not assign DHCPv6 address: %m"); - - return r; -} - -static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) { - int r; - sd_dhcp6_lease *lease; - struct in6_addr ip6_addr; - uint32_t lifetime_preferred, lifetime_valid; - - r = sd_dhcp6_client_get_lease(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 = dhcp6_address_change(link, &ip6_addr, lifetime_preferred, lifetime_valid); - if (r < 0) - return r; - } - - return 0; -} - -static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) { - int r; - Link *link = userdata; - - assert(link); - assert(link->network); - assert(link->manager); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - switch(event) { - case SD_DHCP6_CLIENT_EVENT_STOP: - case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE: - case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX: - if (sd_dhcp6_client_get_lease(client, NULL) >= 0) - log_link_warning(link, "DHCPv6 lease lost"); - - link->dhcp6_configured = false; - break; - - case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: - r = dhcp6_lease_address_acquired(client, link); - if (r < 0) { - link_enter_failed(link); - return; - } - - /* fall through */ - case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: - r = dhcp6_lease_information_acquired(client, link); - if (r < 0) { - link_enter_failed(link); - return; - } - - link->dhcp6_configured = true; - break; - - default: - if (event < 0) - log_link_warning_errno(link, event, "DHCPv6 error: %m"); - else - log_link_warning(link, "DHCPv6 unknown event: %d", event); - return; - } - - link_check_ready(link); -} - -int dhcp6_request_address(Link *link, int ir) { - int r, inf_req; - bool running; - - assert(link); - assert(link->dhcp6_client); - assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); - - r = sd_dhcp6_client_is_running(link->dhcp6_client); - if (r < 0) - return r; - else - running = !!r; - - if (running) { - r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); - if (r < 0) - return r; - - if (inf_req == ir) - return 0; - - r = sd_dhcp6_client_stop(link->dhcp6_client); - if (r < 0) - return r; - } else { - r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address); - if (r < 0) - return r; - } - - r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir); - if (r < 0) - return r; - - r = sd_dhcp6_client_start(link->dhcp6_client); - if (r < 0) - return r; - - return 0; -} - -int dhcp6_configure(Link *link) { - sd_dhcp6_client *client = NULL; - int r; - const DUID *duid; - - assert(link); - - if (link->dhcp6_client) - return 0; - - r = sd_dhcp6_client_new(&client); - if (r < 0) - return r; - - r = sd_dhcp6_client_attach_event(client, NULL, 0); - if (r < 0) - goto error; - - r = sd_dhcp6_client_set_mac(client, - (const uint8_t *) &link->mac, - sizeof (link->mac), ARPHRD_ETHER); - if (r < 0) - goto error; - - r = sd_dhcp6_client_set_iaid(client, link->network->iaid); - if (r < 0) - goto error; - - duid = link_duid(link); - r = sd_dhcp6_client_set_duid(client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - goto error; - - r = sd_dhcp6_client_set_ifindex(client, link->ifindex); - if (r < 0) - goto error; - - r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link); - if (r < 0) - goto error; - - link->dhcp6_client = client; - - return 0; - -error: - sd_dhcp6_client_unref(client); - return r; -} diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c deleted file mode 100644 index ed5a47589e..0000000000 --- a/src/network/networkd-fdb.c +++ /dev/null @@ -1,261 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/ethernet.h> -#include <net/if.h> - -#include "alloc-util.h" -#include "conf-parser.h" -#include "netlink-util.h" -#include "networkd-fdb.h" -#include "networkd.h" -#include "util.h" -#include "vlan-util.h" - -#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U - -/* create a new FDB entry or get an existing one. */ -int fdb_entry_new_static( - Network *network, - unsigned section, - FdbEntry **ret) { - - _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; - struct ether_addr *mac_addr = NULL; - - assert(network); - assert(ret); - - /* search entry in hashmap first. */ - if (section) { - fdb_entry = hashmap_get(network->fdb_entries_by_section, UINT_TO_PTR(section)); - if (fdb_entry) { - *ret = fdb_entry; - fdb_entry = NULL; - - return 0; - } - } - - if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX) - return -E2BIG; - - /* allocate space for MAC address. */ - mac_addr = new0(struct ether_addr, 1); - if (!mac_addr) - return -ENOMEM; - - /* allocate space for and FDB entry. */ - fdb_entry = new0(FdbEntry, 1); - if (!fdb_entry) { - /* free previously allocated space for mac_addr. */ - free(mac_addr); - return -ENOMEM; - } - - /* init FDB structure. */ - fdb_entry->network = network; - fdb_entry->mac_addr = mac_addr; - - LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry); - network->n_static_fdb_entries++; - - if (section) { - fdb_entry->section = section; - hashmap_put(network->fdb_entries_by_section, - UINT_TO_PTR(fdb_entry->section), fdb_entry); - } - - /* return allocated FDB structure. */ - *ret = fdb_entry; - fdb_entry = NULL; - - return 0; -} - -static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - Link *link = userdata; - int r; - - assert(link); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_error_errno(link, r, "Could not add FDB entry: %m"); - - return 1; -} - -/* send a request to the kernel to add a FDB entry in its static MAC table. */ -int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - sd_netlink *rtnl; - int r; - uint8_t flags; - Bridge *bridge; - - assert(link); - assert(link->network); - assert(link->manager); - assert(fdb_entry); - - rtnl = link->manager->rtnl; - bridge = BRIDGE(link->network->bridge); - - /* create new RTM message */ - r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE); - if (r < 0) - return rtnl_log_create_error(r); - - if (bridge) - flags = NTF_MASTER; - else - flags = NTF_SELF; - - r = sd_rtnl_message_neigh_set_flags(req, flags); - if (r < 0) - return rtnl_log_create_error(r); - - /* only NUD_PERMANENT state supported. */ - r = sd_rtnl_message_neigh_set_state(req, NUD_NOARP | NUD_PERMANENT); - if (r < 0) - return rtnl_log_create_error(r); - - r = sd_netlink_message_append_ether_addr(req, NDA_LLADDR, fdb_entry->mac_addr); - if (r < 0) - return rtnl_log_create_error(r); - - /* VLAN Id is optional. We'll add VLAN Id only if it's specified. */ - if (0 != fdb_entry->vlan_id) { - r = sd_netlink_message_append_u16(req, NDA_VLAN, fdb_entry->vlan_id); - if (r < 0) - return rtnl_log_create_error(r); - } - - /* send message to the kernel to update its internal static MAC table. */ - r = sd_netlink_call_async(rtnl, req, set_fdb_handler, link, 0, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - return 0; -} - -/* remove and FDB entry. */ -void fdb_entry_free(FdbEntry *fdb_entry) { - if (!fdb_entry) - return; - - if (fdb_entry->network) { - LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry); - - assert(fdb_entry->network->n_static_fdb_entries > 0); - fdb_entry->network->n_static_fdb_entries--; - - if (fdb_entry->section) - hashmap_remove(fdb_entry->network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section)); - } - - free(fdb_entry->mac_addr); - - free(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) { - - Network *network = userdata; - _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = fdb_entry_new_static(network, section_line, &fdb_entry); - if (r < 0) - return log_oom(); - - /* read in the MAC address for the FDB table. */ - r = sscanf(rvalue, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - &fdb_entry->mac_addr->ether_addr_octet[0], - &fdb_entry->mac_addr->ether_addr_octet[1], - &fdb_entry->mac_addr->ether_addr_octet[2], - &fdb_entry->mac_addr->ether_addr_octet[3], - &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, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue); - return 0; - } - - fdb_entry = NULL; - - return 0; -} - -/* 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) { - - Network *network = userdata; - _cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = fdb_entry_new_static(network, section_line, &fdb_entry); - if (r < 0) - return log_oom(); - - r = config_parse_vlanid(unit, filename, line, section, - section_line, lvalue, ltype, - rvalue, &fdb_entry->vlan_id, userdata); - if (r < 0) - return r; - - fdb_entry = NULL; - - return 0; -} diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h deleted file mode 100644 index 2d7d28735c..0000000000 --- a/src/network/networkd-fdb.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright (C) 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "list.h" -#include "macro.h" - -typedef struct Network Network; -typedef struct FdbEntry FdbEntry; -typedef struct Link Link; - -struct FdbEntry { - Network *network; - unsigned section; - - struct ether_addr *mac_addr; - uint16_t vlan_id; - - LIST_FIELDS(FdbEntry, static_fdb_entries); -}; - -int fdb_entry_new_static(Network *network, unsigned section, FdbEntry **ret); -void fdb_entry_free(FdbEntry *fdb_entry); -int fdb_entry_configure(Link *link, FdbEntry *fdb_entry); - -DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free); -#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep) - -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_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); diff --git a/src/network/networkd-gperf.gperf b/src/network/networkd-gperf.gperf deleted file mode 100644 index 3fdfe74955..0000000000 --- a/src/network/networkd-gperf.gperf +++ /dev/null @@ -1,18 +0,0 @@ -%{ -#include <stddef.h> -#include "conf-parser.h" -#include "networkd-conf.h" -%} -struct ConfigPerfItem; -%null_strings -%language=ANSI-C -%define slot-name section_and_lvalue -%define hash-function-name networkd_gperf_hash -%define lookup-function-name networkd_gperf_lookup -%readonly-tables -%omit-struct-type -%struct-type -%includes -%% -DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Manager, duid.type) -DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Manager, duid) diff --git a/src/network/networkd-ipv4ll.c b/src/network/networkd-ipv4ll.c deleted file mode 100644 index 2d81311e81..0000000000 --- a/src/network/networkd-ipv4ll.c +++ /dev/null @@ -1,241 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013-2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if.h> - -#include "network-internal.h" -#include "networkd.h" - -static int ipv4ll_address_lost(Link *link) { - _cleanup_address_free_ Address *address = NULL; - _cleanup_route_free_ Route *route = NULL; - struct in_addr addr; - int r; - - assert(link); - - link->ipv4ll_route = false; - link->ipv4ll_address = false; - - r = sd_ipv4ll_get_address(link->ipv4ll, &addr); - if (r < 0) - return 0; - - log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr)); - - r = address_new(&address); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate address: %m"); - return r; - } - - address->family = AF_INET; - address->in_addr.in = addr; - address->prefixlen = 16; - address->scope = RT_SCOPE_LINK; - - address_remove(address, link, link_address_remove_handler); - - r = route_new(&route); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate route: %m"); - return r; - } - - route->family = AF_INET; - route->scope = RT_SCOPE_LINK; - route->priority = IPV4LL_ROUTE_METRIC; - - route_remove(route, link, link_route_remove_handler); - - link_check_ready(link); - - return 0; -} - -static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - assert(!link->ipv4ll_route); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "could not set ipv4ll route: %m"); - link_enter_failed(link); - } - - link->ipv4ll_route = true; - - if (link->ipv4ll_address == true) - link_check_ready(link); - - return 1; -} - -static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - assert(!link->ipv4ll_address); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "could not set ipv4ll address: %m"); - link_enter_failed(link); - } else if (r >= 0) - manager_rtnl_process_address(rtnl, m, link->manager); - - link->ipv4ll_address = true; - - if (link->ipv4ll_route == true) - link_check_ready(link); - - return 1; -} - -static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) { - _cleanup_address_free_ Address *ll_addr = NULL; - _cleanup_route_free_ Route *route = NULL; - struct in_addr address; - int r; - - assert(ll); - assert(link); - - r = sd_ipv4ll_get_address(ll, &address); - if (r == -ENOENT) - return 0; - else if (r < 0) - return r; - - log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u", - ADDRESS_FMT_VAL(address)); - - r = address_new(&ll_addr); - if (r < 0) - return r; - - ll_addr->family = AF_INET; - ll_addr->in_addr.in = address; - ll_addr->prefixlen = 16; - ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen); - ll_addr->scope = RT_SCOPE_LINK; - - r = address_configure(ll_addr, link, ipv4ll_address_handler, false); - if (r < 0) - return r; - - link->ipv4ll_address = false; - - r = route_new(&route); - if (r < 0) - return r; - - route->family = AF_INET; - route->scope = RT_SCOPE_LINK; - route->protocol = RTPROT_STATIC; - route->priority = IPV4LL_ROUTE_METRIC; - - r = route_configure(route, link, ipv4ll_route_handler); - if (r < 0) - return r; - - link->ipv4ll_route = false; - - return 0; -} - -static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata) { - Link *link = userdata; - int r; - - assert(link); - assert(link->network); - assert(link->manager); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - switch(event) { - case SD_IPV4LL_EVENT_STOP: - case SD_IPV4LL_EVENT_CONFLICT: - r = ipv4ll_address_lost(link); - if (r < 0) { - link_enter_failed(link); - return; - } - break; - case SD_IPV4LL_EVENT_BIND: - r = ipv4ll_address_claimed(ll, link); - if (r < 0) { - link_enter_failed(link); - return; - } - break; - default: - log_link_warning(link, "IPv4 link-local unknown event: %d", event); - break; - } -} - -int ipv4ll_configure(Link *link) { - uint64_t seed; - int r; - - assert(link); - assert(link->network); - assert(link->network->link_local & ADDRESS_FAMILY_IPV4); - - if (!link->ipv4ll) { - r = sd_ipv4ll_new(&link->ipv4ll); - if (r < 0) - return r; - } - - if (link->udev_device) { - r = net_get_unique_predictable_data(link->udev_device, &seed); - if (r >= 0) { - r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed); - if (r < 0) - return r; - } - } - - r = sd_ipv4ll_attach_event(link->ipv4ll, NULL, 0); - if (r < 0) - return r; - - r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); - if (r < 0) - return r; - - r = sd_ipv4ll_set_ifindex(link->ipv4ll, link->ifindex); - if (r < 0) - return r; - - r = sd_ipv4ll_set_callback(link->ipv4ll, ipv4ll_handler, link); - if (r < 0) - return r; - - return 0; -} diff --git a/src/network/networkd-link-bus.c b/src/network/networkd-link-bus.c deleted file mode 100644 index 532557ed6c..0000000000 --- a/src/network/networkd-link-bus.c +++ /dev/null @@ -1,140 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "bus-util.h" -#include "networkd-link.h" -#include "networkd.h" -#include "parse-util.h" -#include "strv.h" - -static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); -static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_administrative_state, link_state, LinkState); - -const sd_bus_vtable link_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Link, operstate), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("AdministrativeState", "s", property_get_administrative_state, offsetof(Link, state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - - SD_BUS_VTABLE_END -}; - -static char *link_bus_path(Link *link) { - _cleanup_free_ char *ifindex = NULL; - char *p; - int r; - - assert(link); - assert(link->ifindex > 0); - - if (asprintf(&ifindex, "%d", link->ifindex) < 0) - return NULL; - - r = sd_bus_path_encode("/org/freedesktop/network1/link", ifindex, &p); - if (r < 0) - return NULL; - - return p; -} - -int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - unsigned c = 0; - Link *link; - Iterator i; - - assert(bus); - assert(path); - assert(m); - assert(nodes); - - l = new0(char*, hashmap_size(m->links) + 1); - if (!l) - return -ENOMEM; - - HASHMAP_FOREACH(link, m->links, i) { - char *p; - - p = link_bus_path(link); - if (!p) - return -ENOMEM; - - l[c++] = p; - } - - l[c] = NULL; - *nodes = l; - l = NULL; - - return 1; -} - -int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - _cleanup_free_ char *identifier = NULL; - Manager *m = userdata; - Link *link; - int ifindex, r; - - assert(bus); - assert(path); - assert(interface); - assert(m); - assert(found); - - r = sd_bus_path_decode(path, "/org/freedesktop/network1/link", &identifier); - if (r <= 0) - return 0; - - r = parse_ifindex(identifier, &ifindex); - if (r < 0) - return 0; - - r = link_get(m, ifindex, &link); - if (r < 0) - return 0; - - *found = link; - - return 1; -} - -int link_send_changed(Link *link, const char *property, ...) { - _cleanup_free_ char *p = NULL; - char **l; - - assert(link); - assert(link->manager); - - if (!link->manager->bus) - return 0; /* replace with assert when we have kdbus */ - - l = strv_from_stdarg_alloca(property); - - p = link_bus_path(link); - if (!p) - return -ENOMEM; - - return sd_bus_emit_properties_changed_strv( - link->manager->bus, - p, - "org.freedesktop.network1.Link", - l); -} diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c deleted file mode 100644 index aefe7335b9..0000000000 --- a/src/network/networkd-link.c +++ /dev/null @@ -1,3547 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if.h> -#include <unistd.h> - -#include "alloc-util.h" -#include "bus-util.h" -#include "dhcp-lease-internal.h" -#include "fd-util.h" -#include "fileio.h" -#include "netlink-util.h" -#include "network-internal.h" -#include "networkd-lldp-tx.h" -#include "networkd-ndisc.h" -#include "networkd.h" -#include "set.h" -#include "socket-util.h" -#include "stdio-util.h" -#include "string-table.h" -#include "udev-util.h" -#include "util.h" -#include "virt.h" - -static bool link_dhcp6_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->dhcp & ADDRESS_FAMILY_IPV6; -} - -static bool link_dhcp4_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->dhcp & ADDRESS_FAMILY_IPV4; -} - -static bool link_dhcp4_server_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->dhcp_server; -} - -static bool link_ipv4ll_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->link_local & ADDRESS_FAMILY_IPV4; -} - -static bool link_ipv6ll_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - return link->network->link_local & ADDRESS_FAMILY_IPV6; -} - -static bool link_ipv6_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->network->bridge) - return false; - - /* DHCPv6 client will not be started if no IPv6 link-local address is configured. */ - return link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network); -} - -static bool link_lldp_rx_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (link->iftype != ARPHRD_ETHER) - return false; - - if (!link->network) - return false; - - if (link->network->bridge) - return false; - - return link->network->lldp_mode != LLDP_MODE_NO; -} - -static bool link_lldp_emit_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (link->iftype != ARPHRD_ETHER) - return false; - - if (!link->network) - return false; - - return link->network->lldp_emit != LLDP_EMIT_NO; -} - -static bool link_ipv4_forward_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) - return false; - - return link->network->ip_forward & ADDRESS_FAMILY_IPV4; -} - -static bool link_ipv6_forward_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->ip_forward == _ADDRESS_FAMILY_BOOLEAN_INVALID) - return false; - - return link->network->ip_forward & ADDRESS_FAMILY_IPV6; -} - -static bool link_proxy_arp_enabled(Link *link) { - assert(link); - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - if (link->network->proxy_arp < 0) - return false; - - return true; -} - -static bool link_ipv6_accept_ra_enabled(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return false; - - if (link->flags & IFF_LOOPBACK) - return false; - - if (!link->network) - return false; - - /* If unset use system default (enabled if local forwarding is disabled. - * disabled if local forwarding is enabled). - * If set, ignore or enforce RA independent of local forwarding state. - */ - if (link->network->ipv6_accept_ra < 0) - /* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */ - return !link_ipv6_forward_enabled(link); - else if (link->network->ipv6_accept_ra > 0) - /* accept RA even if ip_forward is enabled */ - return true; - else - /* ignore RA */ - return false; -} - -static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) { - assert(link); - - if (!socket_ipv6_is_supported()) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (link->flags & IFF_LOOPBACK) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - if (!link->network) - return _IPV6_PRIVACY_EXTENSIONS_INVALID; - - return link->network->ipv6_privacy_extensions; -} - -static int link_enable_ipv6(Link *link) { - const char *p = NULL; - bool disabled; - int r; - - if (link->flags & IFF_LOOPBACK) - return 0; - - disabled = !link_ipv6_enabled(link); - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/disable_ipv6"); - - r = write_string_file(p, one_zero(disabled), WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot %s IPv6 for interface %s: %m", disabled ? "disable" : "enable", link->ifname); - else - log_link_info(link, "IPv6 %sd for interface: %m", enable_disable(!disabled)); - - return 0; -} - -void link_update_operstate(Link *link) { - LinkOperationalState operstate; - assert(link); - - if (link->kernel_operstate == IF_OPER_DORMANT) - operstate = LINK_OPERSTATE_DORMANT; - else if (link_has_carrier(link)) { - Address *address; - uint8_t scope = RT_SCOPE_NOWHERE; - Iterator i; - - /* if we have carrier, check what addresses we have */ - SET_FOREACH(address, link->addresses, i) { - if (!address_is_ready(address)) - continue; - - if (address->scope < scope) - scope = address->scope; - } - - /* for operstate we also take foreign addresses into account */ - SET_FOREACH(address, link->addresses_foreign, i) { - if (!address_is_ready(address)) - continue; - - if (address->scope < scope) - scope = address->scope; - } - - if (scope < RT_SCOPE_SITE) - /* universally accessible addresses found */ - operstate = LINK_OPERSTATE_ROUTABLE; - else if (scope < RT_SCOPE_HOST) - /* only link or site local addresses found */ - operstate = LINK_OPERSTATE_DEGRADED; - else - /* no useful addresses found */ - operstate = LINK_OPERSTATE_CARRIER; - } else if (link->flags & IFF_UP) - operstate = LINK_OPERSTATE_NO_CARRIER; - else - operstate = LINK_OPERSTATE_OFF; - - if (link->operstate != operstate) { - link->operstate = operstate; - link_send_changed(link, "OperationalState", NULL); - link_dirty(link); - } -} - -#define FLAG_STRING(string, flag, old, new) \ - (((old ^ new) & flag) \ - ? ((old & flag) ? (" -" string) : (" +" string)) \ - : "") - -static int link_update_flags(Link *link, sd_netlink_message *m) { - unsigned flags, unknown_flags_added, unknown_flags_removed, unknown_flags; - uint8_t operstate; - int r; - - assert(link); - - r = sd_rtnl_message_link_get_flags(m, &flags); - if (r < 0) - return log_link_warning_errno(link, r, "Could not get link flags: %m"); - - r = sd_netlink_message_read_u8(m, IFLA_OPERSTATE, &operstate); - if (r < 0) - /* if we got a message without operstate, take it to mean - the state was unchanged */ - operstate = link->kernel_operstate; - - if ((link->flags == flags) && (link->kernel_operstate == operstate)) - 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", - FLAG_STRING("LOOPBACK", IFF_LOOPBACK, link->flags, flags), - FLAG_STRING("MASTER", IFF_MASTER, link->flags, flags), - FLAG_STRING("SLAVE", IFF_SLAVE, link->flags, flags), - FLAG_STRING("UP", IFF_UP, link->flags, flags), - FLAG_STRING("DORMANT", IFF_DORMANT, link->flags, flags), - FLAG_STRING("LOWER_UP", IFF_LOWER_UP, link->flags, flags), - FLAG_STRING("RUNNING", IFF_RUNNING, link->flags, flags), - FLAG_STRING("MULTICAST", IFF_MULTICAST, link->flags, flags), - FLAG_STRING("BROADCAST", IFF_BROADCAST, link->flags, flags), - FLAG_STRING("POINTOPOINT", IFF_POINTOPOINT, link->flags, flags), - FLAG_STRING("PROMISC", IFF_PROMISC, link->flags, flags), - FLAG_STRING("ALLMULTI", IFF_ALLMULTI, link->flags, flags), - FLAG_STRING("PORTSEL", IFF_PORTSEL, link->flags, flags), - FLAG_STRING("AUTOMEDIA", IFF_AUTOMEDIA, link->flags, flags), - FLAG_STRING("DYNAMIC", IFF_DYNAMIC, link->flags, flags), - FLAG_STRING("NOARP", IFF_NOARP, link->flags, flags), - FLAG_STRING("NOTRAILERS", IFF_NOTRAILERS, link->flags, flags), - FLAG_STRING("DEBUG", IFF_DEBUG, link->flags, flags), - FLAG_STRING("ECHO", IFF_ECHO, link->flags, flags)); - - unknown_flags = ~(IFF_LOOPBACK | IFF_MASTER | IFF_SLAVE | IFF_UP | - IFF_DORMANT | IFF_LOWER_UP | IFF_RUNNING | - IFF_MULTICAST | IFF_BROADCAST | IFF_POINTOPOINT | - IFF_PROMISC | IFF_ALLMULTI | IFF_PORTSEL | - IFF_AUTOMEDIA | IFF_DYNAMIC | IFF_NOARP | - IFF_NOTRAILERS | IFF_DEBUG | IFF_ECHO); - unknown_flags_added = ((link->flags ^ flags) & flags & unknown_flags); - unknown_flags_removed = ((link->flags ^ flags) & link->flags & unknown_flags); - - /* link flags are currently at most 18 bits, let's align to - * printing 20 */ - if (unknown_flags_added) - log_link_debug(link, - "Unknown link flags gained: %#.5x (ignoring)", - unknown_flags_added); - - if (unknown_flags_removed) - log_link_debug(link, - "Unknown link flags lost: %#.5x (ignoring)", - unknown_flags_removed); - } - - link->flags = flags; - link->kernel_operstate = operstate; - - link_update_operstate(link); - - return 0; -} - -static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { - _cleanup_link_unref_ Link *link = NULL; - uint16_t type; - const char *ifname, *kind = NULL; - int r, ifindex; - unsigned short iftype; - - assert(manager); - assert(message); - assert(ret); - - /* check for link kind */ - r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); - if (r == 0) { - (void)sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind); - r = sd_netlink_message_exit_container(message); - if (r < 0) - return r; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) - return r; - else if (type != RTM_NEWLINK) - return -EINVAL; - - r = sd_rtnl_message_link_get_ifindex(message, &ifindex); - if (r < 0) - return r; - else if (ifindex <= 0) - return -EINVAL; - - r = sd_rtnl_message_link_get_type(message, &iftype); - if (r < 0) - return r; - - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &ifname); - if (r < 0) - return r; - - link = new0(Link, 1); - if (!link) - return -ENOMEM; - - link->n_ref = 1; - link->manager = manager; - link->state = LINK_STATE_PENDING; - link->rtnl_extended_attrs = true; - link->ifindex = ifindex; - link->iftype = iftype; - link->ifname = strdup(ifname); - if (!link->ifname) - return -ENOMEM; - - if (kind) { - link->kind = strdup(kind); - if (!link->kind) - return -ENOMEM; - } - - r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac); - if (r < 0) - log_link_debug_errno(link, r, "MAC address not found for new device, continuing without"); - - if (asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex) < 0) - return -ENOMEM; - - if (asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex) < 0) - return -ENOMEM; - - if (asprintf(&link->lldp_file, "/run/systemd/netif/lldp/%d", link->ifindex) < 0) - return -ENOMEM; - - r = hashmap_ensure_allocated(&manager->links, NULL); - if (r < 0) - return r; - - r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link); - if (r < 0) - return r; - - r = link_update_flags(link, message); - if (r < 0) - return r; - - *ret = link; - link = NULL; - - return 0; -} - -static void link_free(Link *link) { - Address *address; - Iterator i; - Link *carrier; - - if (!link) - return; - - while (!set_isempty(link->addresses)) - address_free(set_first(link->addresses)); - - while (!set_isempty(link->addresses_foreign)) - address_free(set_first(link->addresses_foreign)); - - link->addresses = set_free(link->addresses); - - link->addresses_foreign = set_free(link->addresses_foreign); - - while ((address = link->pool_addresses)) { - LIST_REMOVE(addresses, link->pool_addresses, address); - address_free(address); - } - - sd_dhcp_server_unref(link->dhcp_server); - sd_dhcp_client_unref(link->dhcp_client); - sd_dhcp_lease_unref(link->dhcp_lease); - - link_lldp_emit_stop(link); - - free(link->lease_file); - - sd_lldp_unref(link->lldp); - free(link->lldp_file); - - ndisc_flush(link); - - sd_ipv4ll_unref(link->ipv4ll); - sd_dhcp6_client_unref(link->dhcp6_client); - sd_ndisc_unref(link->ndisc); - - if (link->manager) - hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex)); - - free(link->ifname); - - free(link->kind); - - (void)unlink(link->state_file); - free(link->state_file); - - 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); -} - -Link *link_unref(Link *link) { - if (!link) - return NULL; - - assert(link->n_ref > 0); - - link->n_ref--; - - if (link->n_ref > 0) - return NULL; - - link_free(link); - - return NULL; -} - -Link *link_ref(Link *link) { - if (!link) - return NULL; - - assert(link->n_ref > 0); - - link->n_ref++; - - return link; -} - -int link_get(Manager *m, int ifindex, Link **ret) { - Link *link; - - assert(m); - assert(ifindex); - assert(ret); - - link = hashmap_get(m->links, INT_TO_PTR(ifindex)); - if (!link) - return -ENODEV; - - *ret = link; - - return 0; -} - -static void link_set_state(Link *link, LinkState state) { - assert(link); - - if (link->state == state) - return; - - link->state = state; - - link_send_changed(link, "AdministrativeState", NULL); -} - -static void link_enter_unmanaged(Link *link) { - assert(link); - - log_link_debug(link, "Unmanaged"); - - link_set_state(link, LINK_STATE_UNMANAGED); - - link_dirty(link); -} - -static int link_stop_clients(Link *link) { - int r = 0, k; - - assert(link); - assert(link->manager); - assert(link->manager->event); - - if (link->dhcp_client) { - k = sd_dhcp_client_stop(link->dhcp_client); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop DHCPv4 client: %m"); - } - - if (link->ipv4ll) { - k = sd_ipv4ll_stop(link->ipv4ll); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop IPv4 link-local: %m"); - } - - if (link->dhcp6_client) { - k = sd_dhcp6_client_stop(link->dhcp6_client); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m"); - } - - if (link->ndisc) { - k = sd_ndisc_stop(link->ndisc); - if (k < 0) - r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m"); - } - - link_lldp_emit_stop(link); - return r; -} - -void link_enter_failed(Link *link) { - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - log_link_warning(link, "Failed"); - - link_set_state(link, LINK_STATE_FAILED); - - link_stop_clients(link); - - link_dirty(link); -} - -static Address* link_find_dhcp_server_address(Link *link) { - Address *address; - - assert(link); - assert(link->network); - - /* The first statically configured address if there is any */ - LIST_FOREACH(addresses, address, link->network->static_addresses) { - - if (address->family != AF_INET) - continue; - - if (in_addr_is_null(address->family, &address->in_addr)) - continue; - - return address; - } - - /* If that didn't work, find a suitable address we got from the pool */ - LIST_FOREACH(addresses, address, link->pool_addresses) { - if (address->family != AF_INET) - continue; - - return address; - } - - return NULL; -} - -static int link_enter_configured(Link *link) { - assert(link); - assert(link->network); - assert(link->state == LINK_STATE_SETTING_ROUTES); - - log_link_info(link, "Configured"); - - link_set_state(link, LINK_STATE_CONFIGURED); - - link_dirty(link); - - return 0; -} - -void link_check_ready(Link *link) { - Address *a; - Iterator i; - - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - if (!link->network) - return; - - if (!link->static_configured) - return; - - if (link_ipv4ll_enabled(link)) - if (!link->ipv4ll_address || - !link->ipv4ll_route) - return; - - if (link_ipv6ll_enabled(link)) - if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0) - return; - - if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) && - !link->dhcp4_configured) || - (link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) && - !link->dhcp6_configured) || - (link_dhcp4_enabled(link) && link_dhcp6_enabled(link) && - !link->dhcp4_configured && !link->dhcp6_configured)) - return; - - if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured) - return; - - SET_FOREACH(a, link->addresses, i) - if (!address_is_ready(a)) - return; - - if (link->state != LINK_STATE_CONFIGURED) - link_enter_configured(link); - - return; -} - -static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link->link_messages > 0); - assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, - LINK_STATE_SETTING_ROUTES, LINK_STATE_FAILED, - LINK_STATE_LINGER)); - - link->link_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "Could not set route: %m"); - - if (link->link_messages == 0) { - log_link_debug(link, "Routes set"); - link->static_configured = true; - link_check_ready(link); - } - - return 1; -} - -static int link_enter_set_routes(Link *link) { - Route *rt; - int r; - - assert(link); - assert(link->network); - assert(link->state == LINK_STATE_SETTING_ADDRESSES); - - link_set_state(link, LINK_STATE_SETTING_ROUTES); - - LIST_FOREACH(routes, rt, link->network->static_routes) { - r = route_configure(rt, link, route_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set routes: %m"); - link_enter_failed(link); - return r; - } - - link->link_messages++; - } - - if (link->link_messages == 0) { - link->static_configured = true; - link_check_ready(link); - } else - log_link_debug(link, "Setting routes"); - - return 0; -} - -int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -ESRCH) - log_link_warning_errno(link, r, "Could not drop route: %m"); - - return 1; -} - -static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->ifname); - assert(link->link_messages > 0); - assert(IN_SET(link->state, LINK_STATE_SETTING_ADDRESSES, - LINK_STATE_FAILED, LINK_STATE_LINGER)); - - link->link_messages--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "could not set address: %m"); - else if (r >= 0) - manager_rtnl_process_address(rtnl, m, link->manager); - - if (link->link_messages == 0) { - log_link_debug(link, "Addresses set"); - link_enter_set_routes(link); - } - - return 1; -} - -static int link_push_dns_to_dhcp_server(Link *link, sd_dhcp_server *s) { - _cleanup_free_ struct in_addr *addresses = NULL; - size_t n_addresses = 0, n_allocated = 0; - char **a; - - log_debug("Copying DNS server information from %s", link->ifname); - - if (!link->network) - return 0; - - STRV_FOREACH(a, link->network->dns) { - struct in_addr ia; - - /* Only look for IPv4 addresses */ - if (inet_pton(AF_INET, *a, &ia) <= 0) - continue; - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) - return log_oom(); - - addresses[n_addresses++] = ia; - } - - if (link->network->dhcp_use_dns && - link->dhcp_lease) { - const struct in_addr *da = NULL; - int n; - - n = sd_dhcp_lease_get_dns(link->dhcp_lease, &da); - if (n > 0) { - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) - return log_oom(); - - memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); - n_addresses += n; - } - } - - if (n_addresses <= 0) - return 0; - - return sd_dhcp_server_set_dns(s, addresses, n_addresses); -} - -static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) { - _cleanup_free_ struct in_addr *addresses = NULL; - size_t n_addresses = 0, n_allocated = 0; - char **a; - - if (!link->network) - return 0; - - log_debug("Copying NTP server information from %s", link->ifname); - - STRV_FOREACH(a, link->network->ntp) { - struct in_addr ia; - - /* Only look for IPv4 addresses */ - if (inet_pton(AF_INET, *a, &ia) <= 0) - continue; - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + 1)) - return log_oom(); - - addresses[n_addresses++] = ia; - } - - if (link->network->dhcp_use_ntp && - link->dhcp_lease) { - const struct in_addr *da = NULL; - int n; - - n = sd_dhcp_lease_get_ntp(link->dhcp_lease, &da); - if (n > 0) { - - if (!GREEDY_REALLOC(addresses, n_allocated, n_addresses + n)) - return log_oom(); - - memcpy(addresses + n_addresses, da, n * sizeof(struct in_addr)); - n_addresses += n; - } - } - - if (n_addresses <= 0) - return 0; - - return sd_dhcp_server_set_ntp(s, addresses, n_addresses); -} - -static int link_set_bridge_fdb(Link *link) { - FdbEntry *fdb_entry; - int r; - - LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) { - r = fdb_entry_configure(link, fdb_entry); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m"); - } - - return 0; -} - -static int link_enter_set_addresses(Link *link) { - Address *ad; - int r; - - assert(link); - assert(link->network); - assert(link->state != _LINK_STATE_INVALID); - - r = link_set_bridge_fdb(link); - if (r < 0) - return r; - - link_set_state(link, LINK_STATE_SETTING_ADDRESSES); - - LIST_FOREACH(addresses, ad, link->network->static_addresses) { - r = address_configure(ad, link, address_handler, false); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set addresses: %m"); - link_enter_failed(link); - return r; - } - - link->link_messages++; - } - - /* now that we can figure out a default address for the dhcp server, - start it */ - if (link_dhcp4_server_enabled(link)) { - Address *address; - Link *uplink = NULL; - bool acquired_uplink = false; - - address = link_find_dhcp_server_address(link); - if (!address) { - log_link_warning(link, "Failed to find suitable address for DHCPv4 server instance."); - link_enter_failed(link); - return 0; - } - - /* use the server address' subnet as the pool */ - r = sd_dhcp_server_configure_pool(link->dhcp_server, &address->in_addr.in, address->prefixlen, - link->network->dhcp_server_pool_offset, link->network->dhcp_server_pool_size); - if (r < 0) - return r; - - /* TODO: - r = sd_dhcp_server_set_router(link->dhcp_server, - &main_address->in_addr.in); - if (r < 0) - return r; - */ - - if (link->network->dhcp_server_max_lease_time_usec > 0) { - r = sd_dhcp_server_set_max_lease_time( - link->dhcp_server, - DIV_ROUND_UP(link->network->dhcp_server_max_lease_time_usec, USEC_PER_SEC)); - if (r < 0) - return r; - } - - if (link->network->dhcp_server_default_lease_time_usec > 0) { - r = sd_dhcp_server_set_default_lease_time( - link->dhcp_server, - DIV_ROUND_UP(link->network->dhcp_server_default_lease_time_usec, USEC_PER_SEC)); - if (r < 0) - return r; - } - - if (link->network->dhcp_server_emit_dns) { - - if (link->network->n_dhcp_server_dns > 0) - r = sd_dhcp_server_set_dns(link->dhcp_server, link->network->dhcp_server_dns, link->network->n_dhcp_server_dns); - else { - uplink = manager_find_uplink(link->manager, link); - acquired_uplink = true; - - if (!uplink) { - log_link_debug(link, "Not emitting DNS server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_dns_to_dhcp_server(uplink, link->dhcp_server); - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set DNS server for DHCP server, ignoring: %m"); - } - - - if (link->network->dhcp_server_emit_ntp) { - - if (link->network->n_dhcp_server_ntp > 0) - r = sd_dhcp_server_set_ntp(link->dhcp_server, link->network->dhcp_server_ntp, link->network->n_dhcp_server_ntp); - else { - if (!acquired_uplink) - uplink = manager_find_uplink(link->manager, link); - - if (!uplink) { - log_link_debug(link, "Not emitting NTP server information on link, couldn't find suitable uplink."); - r = 0; - } else - r = link_push_ntp_to_dhcp_server(uplink, link->dhcp_server); - - } - if (r < 0) - log_link_warning_errno(link, r, "Failed to set NTP server for DHCP server, ignoring: %m"); - } - - r = sd_dhcp_server_set_emit_router(link->dhcp_server, link->network->dhcp_server_emit_router); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to set router emission for DHCP server: %m"); - return r; - } - - if (link->network->dhcp_server_emit_timezone) { - _cleanup_free_ char *buffer = NULL; - const char *tz = NULL; - - if (link->network->dhcp_server_timezone) - tz = link->network->dhcp_server_timezone; - else { - r = get_timezone(&buffer); - if (r < 0) - log_warning_errno(r, "Failed to determine timezone: %m"); - else - tz = buffer; - } - - if (tz) { - r = sd_dhcp_server_set_timezone(link->dhcp_server, tz); - if (r < 0) - return r; - } - } - - r = sd_dhcp_server_start(link->dhcp_server); - if (r < 0) { - 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"); - } - - if (link->link_messages == 0) - link_enter_set_routes(link); - else - log_link_debug(link, "Setting addresses"); - - return 0; -} - -int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EADDRNOTAVAIL) - log_link_warning_errno(link, r, "Could not drop address: %m"); - - return 1; -} - -static int link_set_bridge_vlan(Link *link) { - int r = 0; - - r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap); - if (r < 0) - log_link_error_errno(link, r, "Failed to assign VLANs to bridge port: %m"); - - return r; -} - -static int link_set_proxy_arp(Link *link) { - const char *p = NULL; - int r; - - if (!link_proxy_arp_enabled(link)) - return 0; - - p = strjoina("/proc/sys/net/ipv4/conf/", link->ifname, "/proxy_arp"); - - r = write_string_file(p, one_zero(link->network->proxy_arp), WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure proxy ARP for interface: %m"); - - return 0; -} - -static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - log_link_debug(link, "Set link"); - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "Could not join netdev: %m"); - link_enter_failed(link); - return 1; - } - - return 0; -} - -static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - _cleanup_link_unref_ Link *link = userdata; - const sd_bus_error *e; - - assert(m); - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - e = sd_bus_message_get_error(m); - if (e) - log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set hostname: %s", e->message); - - return 1; -} - -int link_set_hostname(Link *link, const char *hostname) { - int r; - - assert(link); - assert(link->manager); - - log_link_debug(link, "Setting transient hostname: '%s'", strna(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."); - return 0; - } - - r = sd_bus_call_method_async( - link->manager->bus, - NULL, - "org.freedesktop.hostname1", - "/org/freedesktop/hostname1", - "org.freedesktop.hostname1", - "SetHostname", - set_hostname_handler, - link, - "sb", - hostname, - false); - - if (r < 0) - return log_link_error_errno(link, r, "Could not set transient hostname: %m"); - - link_ref(link); - - return 0; -} - -static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) { - _cleanup_link_unref_ Link *link = userdata; - const sd_bus_error *e; - - assert(m); - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - e = sd_bus_message_get_error(m); - if (e) - log_link_warning_errno(link, sd_bus_error_get_errno(e), "Could not set timezone: %s", e->message); - - return 1; -} - -int link_set_timezone(Link *link, const char *tz) { - int r; - - assert(link); - assert(link->manager); - assert(tz); - - log_link_debug(link, "Setting system timezone: '%s'", tz); - - if (!link->manager->bus) { - log_link_info(link, "Not connected to system bus, ignoring timezone."); - return 0; - } - - r = sd_bus_call_method_async( - link->manager->bus, - NULL, - "org.freedesktop.timedate1", - "/org/freedesktop/timedate1", - "org.freedesktop.timedate1", - "SetTimezone", - set_timezone_handler, - link, - "sb", - tz, - false); - if (r < 0) - return log_link_error_errno(link, r, "Could not set timezone: %m"); - - link_ref(link); - - return 0; -} - -static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0) - log_link_warning_errno(link, r, "Could not set MTU: %m"); - - return 1; -} - -int link_set_mtu(Link *link, uint32_t mtu) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - - 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) - return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m"); - - r = sd_netlink_message_append_u32(req, IFLA_MTU, mtu); - if (r < 0) - return log_link_error_errno(link, r, "Could not append MTU: %m"); - - r = sd_netlink_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); - - return 0; -} - -static int set_flags_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0) - log_link_warning_errno(link, r, "Could not set link flags: %m"); - - return 1; -} - -static int link_set_flags(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - unsigned ifi_change = 0; - unsigned ifi_flags = 0; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->arp < 0) - return 0; - - 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"); - - if (link->network->arp >= 0) { - ifi_change |= IFF_NOARP; - ifi_flags |= link->network->arp ? 0 : IFF_NOARP; - } - - r = sd_rtnl_message_link_set_flags(req, ifi_flags, ifi_change); - if (r < 0) - return log_link_error_errno(link, r, "Could not set link flags: %m"); - - r = sd_netlink_call_async(link->manager->rtnl, req, set_flags_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_set_bridge(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - assert(link->network); - - 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) - return log_link_error_errno(link, r, "Could not set message family: %m"); - - r = sd_netlink_message_open_container(req, IFLA_PROTINFO); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m"); - - r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m"); - - r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m"); - - r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m"); - - r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m"); - - r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m"); - - if (link->network->cost != 0) { - r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_COST attribute: %m"); - } - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_LINKINFO attribute: %m"); - - r = sd_netlink_call_async(link->manager->rtnl, req, link_set_handler, link, 0, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return r; -} - -static int link_lldp_save(Link *link) { - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; - sd_lldp_neighbor **l = NULL; - int n = 0, r, i; - - assert(link); - assert(link->lldp_file); - - if (!link->lldp) { - (void) unlink(link->lldp_file); - return 0; - } - - r = sd_lldp_get_neighbors(link->lldp, &l); - if (r < 0) - goto finish; - if (r == 0) { - (void) unlink(link->lldp_file); - goto finish; - } - - n = r; - - r = fopen_temporary(link->lldp_file, &f, &temp_path); - if (r < 0) - goto finish; - - fchmod(fileno(f), 0644); - - for (i = 0; i < n; i++) { - const void *p; - le64_t u; - size_t sz; - - r = sd_lldp_neighbor_get_raw(l[i], &p, &sz); - if (r < 0) - goto finish; - - u = htole64(sz); - (void) fwrite(&u, 1, sizeof(u), f); - (void) fwrite(p, 1, sz, f); - } - - r = fflush_and_check(f); - if (r < 0) - goto finish; - - if (rename(temp_path, link->lldp_file) < 0) { - r = -errno; - goto finish; - } - -finish: - if (r < 0) { - (void) unlink(link->lldp_file); - if (temp_path) - (void) unlink(temp_path); - - log_link_error_errno(link, r, "Failed to save LLDP data to %s: %m", link->lldp_file); - } - - if (l) { - for (i = 0; i < n; i++) - sd_lldp_neighbor_unref(l[i]); - free(l); - } - - return r; -} - -static void lldp_handler(sd_lldp *lldp, sd_lldp_event event, sd_lldp_neighbor *n, void *userdata) { - Link *link = userdata; - int r; - - assert(link); - - (void) link_lldp_save(link); - - if (link_lldp_emit_enabled(link) && event == SD_LLDP_EVENT_ADDED) { - /* If we received information about a new neighbor, restart the LLDP "fast" logic */ - - log_link_debug(link, "Received LLDP datagram from previously unknown neighbor, restarting 'fast' LLDP transmission."); - - r = link_lldp_emit_start(link); - if (r < 0) - log_link_warning_errno(link, r, "Failed to restart LLDP transmission: %m"); - } -} - -static int link_acquire_ipv6_conf(Link *link) { - int r; - - assert(link); - - if (link_dhcp6_enabled(link)) { - assert(link->dhcp6_client); - assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); - - /* start DHCPv6 client in stateless mode */ - r = dhcp6_request_address(link, true); - if (r < 0 && r != -EBUSY) - return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m"); - else - log_link_debug(link, "Acquiring DHCPv6 lease"); - } - - if (link_ipv6_accept_ra_enabled(link)) { - assert(link->ndisc); - - log_link_debug(link, "Discovering IPv6 routers"); - - r = sd_ndisc_start(link->ndisc); - if (r < 0 && r != -EBUSY) - return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m"); - } - - return 0; -} - -static int link_acquire_ipv4_conf(Link *link) { - int r; - - assert(link); - assert(link->network); - assert(link->manager); - assert(link->manager->event); - - if (link_ipv4ll_enabled(link)) { - assert(link->ipv4ll); - - log_link_debug(link, "Acquiring IPv4 link-local address"); - - r = sd_ipv4ll_start(link->ipv4ll); - 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"); - - r = sd_dhcp_client_start(link->dhcp_client); - if (r < 0) - return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m"); - } - - return 0; -} - -static int link_acquire_conf(Link *link) { - int r; - - assert(link); - - r = link_acquire_ipv4_conf(link); - if (r < 0) - return r; - - if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) == 0) { - r = link_acquire_ipv6_conf(link); - if (r < 0) - return r; - } - - if (link_lldp_emit_enabled(link)) { - r = link_lldp_emit_start(link); - if (r < 0) - return log_link_warning_errno(link, r, "Failed to start LLDP transmission: %m"); - } - - return 0; -} - -bool link_has_carrier(Link *link) { - /* see Documentation/networking/operstates.txt in the kernel sources */ - - if (link->kernel_operstate == IF_OPER_UP) - return true; - - if (link->kernel_operstate == IF_OPER_UNKNOWN) - /* operstate may not be implemented, so fall back to flags */ - if ((link->flags & IFF_LOWER_UP) && !(link->flags & IFF_DORMANT)) - return true; - - return false; -} - -static int link_up_handler(sd_netlink *rtnl, sd_netlink_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_netlink_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, "Could not bring up interface: %m"); - - return 1; -} - -static int link_up(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - uint8_t ipv6ll_mode; - int r; - - assert(link); - assert(link->network); - assert(link->manager); - assert(link->manager->rtnl); - - log_link_debug(link, "Bringing link up"); - - 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"); - - /* set it free if not enslaved with networkd */ - if (!link->network->bridge && !link->network->bond && !link->network->vrf) { - r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0); - if (r < 0) - return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m"); - } - - r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP); - if (r < 0) - return log_link_error_errno(link, r, "Could not set link flags: %m"); - - if (link->network->mac) { - r = sd_netlink_message_append_ether_addr(req, IFLA_ADDRESS, link->network->mac); - if (r < 0) - return log_link_error_errno(link, r, "Could not set MAC address: %m"); - } - - /* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled) - for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */ - (void) link_enable_ipv6(link); - - if (link->network->mtu) { - /* IPv6 protocol requires a minimum MTU of IPV6_MTU_MIN(1280) bytes - on the interface. Bump up MTU bytes to IPV6_MTU_MIN. */ - if (link_ipv6_enabled(link) && link->network->mtu < IPV6_MIN_MTU) { - - log_link_warning(link, "Bumping MTU to " STRINGIFY(IPV6_MIN_MTU) ", as " - "IPv6 is requested and requires a minimum MTU of " STRINGIFY(IPV6_MIN_MTU) " bytes: %m"); - - link->network->mtu = IPV6_MIN_MTU; - } - - r = sd_netlink_message_append_u32(req, IFLA_MTU, link->network->mtu); - if (r < 0) - return log_link_error_errno(link, r, "Could not set MTU: %m"); - } - - r = sd_netlink_message_open_container(req, IFLA_AF_SPEC); - if (r < 0) - return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m"); - - if (link_ipv6_enabled(link)) { - /* if the kernel lacks ipv6 support setting IFF_UP fails if any ipv6 options are passed */ - r = sd_netlink_message_open_container(req, AF_INET6); - if (r < 0) - return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m"); - - if (!link_ipv6ll_enabled(link)) - ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE; - else { - const char *p = NULL; - _cleanup_free_ char *stable_secret = NULL; - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/stable_secret"); - r = read_one_line_file(p, &stable_secret); - - if (r < 0) - ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64; - else - ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY; - } - r = sd_netlink_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_netlink_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_netlink_message_close_container(req); - if (r < 0) - return log_link_error_errno(link, r, "Could not close AF_INET6 container: %m"); - } - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m"); - - r = sd_netlink_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_netlink *rtnl, sd_netlink_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_netlink_message_get_errno(m); - if (r < 0) - log_link_warning_errno(link, r, "Could not bring down interface: %m"); - - return 1; -} - -static int link_down(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_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_netlink_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_up_can(Link *link) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - - log_link_debug(link, "Bringing CAN link up"); - - 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) - return log_link_error_errno(link, r, "Could not set link flags: %m"); - - r = sd_netlink_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_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; - } - - 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 (list_updated) - link_dirty(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_dirty(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; - } - } - - if (list_updated) - link_dirty(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_dirty(carrier); - } - - 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 = link_handle_bound_by_list(link); - if (r < 0) - return r; - - 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_dirty(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_dirty(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_dirty(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"); - - (void)unlink(link->state_file); - link_unref(link); - - return; -} - -static int link_joined(Link *link) { - int r; - - assert(link); - assert(link->network); - - 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); - return r; - } - } - - if (link->network->bridge) { - r = link_set_bridge(link); - if (r < 0) - log_link_error_errno(link, r, "Could not set bridge message: %m"); - } - - if (link->network->use_br_vlan && - (link->network->bridge || streq_ptr("bridge", link->kind))) { - r = link_set_bridge_vlan(link); - if (r < 0) - log_link_error_errno(link, r, "Could not set bridge vlan: %m"); - } - - return link_enter_set_addresses(link); -} - -static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - assert(link->network); - - link->enslaving--; - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "Could not join netdev: %m"); - link_enter_failed(link); - return 1; - } else - log_link_debug(link, "Joined netdev"); - - if (link->enslaving <= 0) - link_joined(link); - - return 1; -} - -static int link_enter_join_netdev(Link *link) { - NetDev *netdev; - Iterator i; - int r; - - assert(link); - assert(link->network); - assert(link->state == LINK_STATE_PENDING); - - link_set_state(link, LINK_STATE_ENSLAVING); - - link_dirty(link); - - if (!link->network->bridge && - !link->network->bond && - !link->network->vrf && - hashmap_isempty(link->network->stacked_netdevs)) - return link_joined(link); - - if (link->network->bond) { - 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_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; - } - - link->enslaving++; - } - - if (link->network->bridge) { - 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_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; - } - - link->enslaving++; - } - - if (link->network->vrf) { - log_struct(LOG_DEBUG, - LOG_LINK_INTERFACE(link), - LOG_NETDEV_INTERFACE(link->network->vrf), - LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname), - NULL); - r = netdev_join(link->network->vrf, link, netdev_join_handler); - if (r < 0) { - log_struct_errno(LOG_WARNING, r, - LOG_LINK_INTERFACE(link), - LOG_NETDEV_INTERFACE(link->network->vrf), - LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname), - NULL); - link_enter_failed(link); - return r; - } - - link->enslaving++; - } - - HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) { - - 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_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; - } - - link->enslaving++; - } - - return 0; -} - -static int link_set_ipv4_forward(Link *link) { - int r; - - if (!link_ipv4_forward_enabled(link)) - return 0; - - /* We propagate the forwarding flag from one interface to the - * global setting one way. This means: as long as at least one - * interface was configured at any time that had IP forwarding - * enabled the setting will stay on for good. We do this - * primarily to keep IPv4 and IPv6 packet forwarding behaviour - * somewhat in sync (see below). */ - - r = write_string_file("/proc/sys/net/ipv4/ip_forward", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot turn on IPv4 packet forwarding, ignoring: %m"); - - return 0; -} - -static int link_set_ipv6_forward(Link *link) { - int r; - - if (!link_ipv6_forward_enabled(link)) - return 0; - - /* On Linux, the IPv6 stack does not know a per-interface - * packet forwarding setting: either packet forwarding is on - * for all, or off for all. We hence don't bother with a - * per-interface setting, but simply propagate the interface - * flag, if it is set, to the global flag, one-way. Note that - * while IPv4 would allow a per-interface flag, we expose the - * same behaviour there and also propagate the setting from - * one to all, to keep things simple (see above). */ - - r = write_string_file("/proc/sys/net/ipv6/conf/all/forwarding", "1", WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure IPv6 packet forwarding, ignoring: %m"); - - return 0; -} - -static int link_set_ipv6_privacy_extensions(Link *link) { - char buf[DECIMAL_STR_MAX(unsigned) + 1]; - IPv6PrivacyExtensions s; - const char *p = NULL; - int r; - - s = link_ipv6_privacy_extensions(link); - if (s < 0) - return 0; - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/use_tempaddr"); - xsprintf(buf, "%u", (unsigned) link->network->ipv6_privacy_extensions); - - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface: %m"); - - return 0; -} - -static int link_set_ipv6_accept_ra(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->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra"); - - /* We handle router advertisements ourselves, tell the kernel to GTFO */ - r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m"); - - return 0; -} - -static int link_set_ipv6_dad_transmits(Link *link) { - char buf[DECIMAL_STR_MAX(int) + 1]; - const char *p = NULL; - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_dad_transmits < 0) - return 0; - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/dad_transmits"); - xsprintf(buf, "%i", link->network->ipv6_dad_transmits); - - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv6 dad transmits for interface: %m"); - - return 0; -} - -static int link_set_ipv6_hop_limit(Link *link) { - char buf[DECIMAL_STR_MAX(int) + 1]; - const char *p = NULL; - int r; - - /* Make this a NOP if IPv6 is not available */ - if (!socket_ipv6_is_supported()) - return 0; - - if (link->flags & IFF_LOOPBACK) - return 0; - - if (!link->network) - return 0; - - if (link->network->ipv6_hop_limit < 0) - return 0; - - p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/hop_limit"); - xsprintf(buf, "%i", link->network->ipv6_hop_limit); - - r = write_string_file(p, buf, WRITE_STRING_FILE_VERIFY_ON_FAILURE); - if (r < 0) - log_link_warning_errno(link, r, "Cannot set IPv6 hop limit for interface: %m"); - - return 0; -} - -static int link_drop_foreign_config(Link *link) { - Address *address; - Route *route; - Iterator i; - int r; - - SET_FOREACH(address, link->addresses_foreign, i) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) - continue; - - r = address_remove(address, link, link_address_remove_handler); - if (r < 0) - return r; - } - - SET_FOREACH(route, link->routes_foreign, i) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; - - r = route_remove(route, link, link_route_remove_handler); - if (r < 0) - return r; - } - - return 0; -} - -static int link_drop_config(Link *link) { - Address *address; - Route *route; - Iterator i; - int r; - - SET_FOREACH(address, link->addresses, i) { - /* we consider IPv6LL addresses to be managed by the kernel */ - if (address->family == AF_INET6 && in_addr_is_link_local(AF_INET6, &address->in_addr) == 1) - continue; - - r = address_remove(address, link, link_address_remove_handler); - if (r < 0) - return r; - } - - SET_FOREACH(route, link->routes, i) { - /* do not touch routes managed by the kernel */ - if (route->protocol == RTPROT_KERNEL) - continue; - - r = route_remove(route, link, link_route_remove_handler); - if (r < 0) - return r; - } - - ndisc_flush(link); - - return 0; -} - -static int link_update_lldp(Link *link) { - int r; - - assert(link); - - if (!link->lldp) - return 0; - - if (link->flags & IFF_UP) { - r = sd_lldp_start(link->lldp); - if (r > 0) - log_link_debug(link, "Started LLDP."); - } else { - r = sd_lldp_stop(link->lldp); - if (r > 0) - log_link_debug(link, "Stopped LLDP."); - } - - return r; -} - -static int link_configure(Link *link) { - int r; - - assert(link); - assert(link->network); - assert(link->state == LINK_STATE_PENDING); - - if (streq_ptr(link->kind, "vcan")) { - - if (!(link->flags & IFF_UP)) { - r = link_up_can(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } - - return 0; - } - - /* Drop foreign config, but ignore loopback or critical devices. - * We do not want to remove loopback address or addresses used for root NFS. */ - if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) { - r = link_drop_foreign_config(link); - if (r < 0) - return r; - } - - r = link_set_proxy_arp(link); - if (r < 0) - return r; - - r = link_set_ipv4_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_forward(link); - if (r < 0) - return r; - - r = link_set_ipv6_privacy_extensions(link); - if (r < 0) - return r; - - r = link_set_ipv6_accept_ra(link); - if (r < 0) - return r; - - r = link_set_ipv6_dad_transmits(link); - if (r < 0) - return r; - - r = link_set_ipv6_hop_limit(link); - if (r < 0) - return r; - - r = link_set_flags(link); - if (r < 0) - return r; - - if (link_ipv4ll_enabled(link)) { - r = ipv4ll_configure(link); - if (r < 0) - return r; - } - - if (link_dhcp4_enabled(link)) { - r = dhcp4_configure(link); - if (r < 0) - return r; - } - - if (link_dhcp4_server_enabled(link)) { - r = sd_dhcp_server_new(&link->dhcp_server, link->ifindex); - if (r < 0) - return r; - - r = sd_dhcp_server_attach_event(link->dhcp_server, NULL, 0); - if (r < 0) - return r; - } - - if (link_dhcp6_enabled(link) || - link_ipv6_accept_ra_enabled(link)) { - r = dhcp6_configure(link); - if (r < 0) - return r; - } - - if (link_ipv6_accept_ra_enabled(link)) { - r = ndisc_configure(link); - if (r < 0) - return r; - } - - if (link_lldp_rx_enabled(link)) { - r = sd_lldp_new(&link->lldp); - if (r < 0) - return r; - - r = sd_lldp_set_ifindex(link->lldp, link->ifindex); - if (r < 0) - return r; - - r = sd_lldp_match_capabilities(link->lldp, - link->network->lldp_mode == LLDP_MODE_ROUTERS_ONLY ? - SD_LLDP_SYSTEM_CAPABILITIES_ALL_ROUTERS : - SD_LLDP_SYSTEM_CAPABILITIES_ALL); - if (r < 0) - return r; - - r = sd_lldp_set_filter_address(link->lldp, &link->mac); - if (r < 0) - return r; - - r = sd_lldp_attach_event(link->lldp, NULL, 0); - if (r < 0) - return r; - - r = sd_lldp_set_callback(link->lldp, lldp_handler, link); - if (r < 0) - return r; - - r = link_update_lldp(link); - if (r < 0) - return r; - } - - if (link_has_carrier(link)) { - r = link_acquire_conf(link); - if (r < 0) - return r; - } - - return link_enter_join_netdev(link); -} - -static int link_initialized_and_synced(sd_netlink *rtnl, sd_netlink_message *m, - void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - Network *network; - int r; - - assert(link); - assert(link->ifname); - assert(link->manager); - - if (link->state != LINK_STATE_PENDING) - return 1; - - 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; - - if (!link->network) { - r = network_get(link->manager, link->udev_device, link->ifname, - &link->mac, &network); - if (r == -ENOENT) { - link_enter_unmanaged(link); - return 1; - } else if (r < 0) - return r; - - if (link->flags & IFF_LOOPBACK) { - if (network->link_local != ADDRESS_FAMILY_NO) - 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"); - - if (network->dhcp_server) - 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; - - return 1; -} - -int link_initialized(Link *link, struct udev_device *device) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(device); - - if (link->state != LINK_STATE_PENDING) - return 0; - - if (link->udev_device) - return 0; - - log_link_debug(link, "udev initialized link"); - - link->udev_device = udev_device_ref(device); - - /* udev has initialized the link, but we don't know if we have yet - * processed the NEWLINK messages with the latest state. Do a GETLINK, - * when it returns we know that the pending NEWLINKs have already been - * processed and that we are up-to-date */ - - r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_GETLINK, - link->ifindex); - if (r < 0) - return r; - - r = sd_netlink_call_async(link->manager->rtnl, req, - link_initialized_and_synced, link, 0, NULL); - if (r < 0) - return r; - - link_ref(link); - - return 0; -} - -static int link_load(Link *link) { - _cleanup_free_ char *network_file = NULL, - *addresses = NULL, - *routes = NULL, - *dhcp4_address = NULL, - *ipv4ll_address = NULL; - union in_addr_union address; - union in_addr_union route_dst; - const char *p; - int r; - - assert(link); - - r = parse_env_file(link->state_file, NEWLINE, - "NETWORK_FILE", &network_file, - "ADDRESSES", &addresses, - "ROUTES", &routes, - "DHCP4_ADDRESS", &dhcp4_address, - "IPV4LL_ADDRESS", &ipv4ll_address, - NULL); - if (r < 0 && r != -ENOENT) - return log_link_error_errno(link, r, "Failed to read %s: %m", link->state_file); - - if (network_file) { - Network *network; - char *suffix; - - /* drop suffix */ - suffix = strrchr(network_file, '.'); - if (!suffix) { - log_link_debug(link, "Failed to get network name from %s", network_file); - goto network_file_fail; - } - *suffix = '\0'; - - r = network_get_by_name(link->manager, basename(network_file), &network); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to get network %s: %m", basename(network_file)); - goto network_file_fail; - } - - r = network_apply(link->manager, network, link); - if (r < 0) - return log_link_error_errno(link, r, "Failed to apply network %s: %m", basename(network_file)); - } - -network_file_fail: - - if (addresses) { - p = addresses; - - for (;;) { - _cleanup_free_ char *address_str = NULL; - char *prefixlen_str; - int family; - unsigned char prefixlen; - - r = extract_first_word(&p, &address_str, NULL, 0); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to extract next address string: %m"); - continue; - } - if (r == 0) - break; - - prefixlen_str = strchr(address_str, '/'); - if (!prefixlen_str) { - log_link_debug(link, "Failed to parse address and prefix length %s", address_str); - continue; - } - - *prefixlen_str++ = '\0'; - - r = sscanf(prefixlen_str, "%hhu", &prefixlen); - if (r != 1) { - log_link_error(link, "Failed to parse prefixlen %s", prefixlen_str); - continue; - } - - r = in_addr_from_string_auto(address_str, &family, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse address %s: %m", address_str); - continue; - } - - r = address_add(link, family, &address, prefixlen, NULL); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add address: %m"); - } - } - - if (routes) { - p = routes; - - for (;;) { - Route *route; - _cleanup_free_ char *route_str = NULL; - _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; - usec_t lifetime; - char *prefixlen_str; - int family; - unsigned char prefixlen, tos, table; - uint32_t priority; - - r = extract_first_word(&p, &route_str, NULL, 0); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to extract next route string: %m"); - continue; - } - if (r == 0) - break; - - prefixlen_str = strchr(route_str, '/'); - if (!prefixlen_str) { - log_link_debug(link, "Failed to parse route %s", route_str); - continue; - } - - *prefixlen_str++ = '\0'; - - r = sscanf(prefixlen_str, "%hhu/%hhu/%"SCNu32"/%hhu/"USEC_FMT, &prefixlen, &tos, &priority, &table, &lifetime); - if (r != 5) { - log_link_debug(link, - "Failed to parse destination prefix length, tos, priority, table or expiration %s", - prefixlen_str); - continue; - } - - r = in_addr_from_string_auto(route_str, &family, &route_dst); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse route destination %s: %m", route_str); - continue; - } - - r = route_add(link, family, &route_dst, prefixlen, tos, priority, table, &route); - if (r < 0) - return log_link_error_errno(link, r, "Failed to add route: %m"); - - if (lifetime != USEC_INFINITY) { - r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), lifetime, - 0, route_expire_handler, route); - if (r < 0) - log_link_warning_errno(link, r, "Could not arm route expiration handler: %m"); - } - - route->lifetime = lifetime; - sd_event_source_unref(route->expire); - route->expire = expire; - expire = NULL; - } - } - - if (dhcp4_address) { - r = in_addr_from_string(AF_INET, dhcp4_address, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address); - goto dhcp4_address_fail; - } - - r = sd_dhcp_client_new(&link->dhcp_client); - if (r < 0) - return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m"); - - r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in); - if (r < 0) - return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address); - } - -dhcp4_address_fail: - - if (ipv4ll_address) { - r = in_addr_from_string(AF_INET, ipv4ll_address, &address); - if (r < 0) { - log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address); - goto ipv4ll_address_fail; - } - - r = sd_ipv4ll_new(&link->ipv4ll); - if (r < 0) - return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m"); - - r = sd_ipv4ll_set_address(link->ipv4ll, &address.in); - if (r < 0) - return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address); - } - -ipv4ll_address_fail: - - return 0; -} - -int link_add(Manager *m, sd_netlink_message *message, Link **ret) { - Link *link; - _cleanup_udev_device_unref_ struct udev_device *device = NULL; - char ifindex_str[2 + DECIMAL_STR_MAX(int)]; - int r; - - assert(m); - assert(m->rtnl); - assert(message); - assert(ret); - - r = link_new(m, message, ret); - if (r < 0) - return r; - - link = *ret; - - log_link_debug(link, "Link %d added", link->ifindex); - - r = link_load(link); - if (r < 0) - return r; - - if (detect_container() <= 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) { - r = log_link_warning_errno(link, errno, "Could not find udev device: %m"); - goto failed; - } - - if (udev_device_get_is_initialized(device) <= 0) { - /* not yet ready */ - log_link_debug(link, "link pending udev initialization..."); - return 0; - } - - r = link_initialized(link, device); - if (r < 0) - goto failed; - } else { - /* we are calling a callback directly, so must take a ref */ - link_ref(link); - - r = link_initialized_and_synced(m->rtnl, NULL, link); - if (r < 0) - goto failed; - } - - return 0; -failed: - link_enter_failed(link); - return r; -} - -int link_ipv6ll_gained(Link *link, const struct in6_addr *address) { - int r; - - assert(link); - - log_link_info(link, "Gained IPv6LL"); - - link->ipv6ll_address = *address; - link_check_ready(link); - - if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) { - r = link_acquire_ipv6_conf(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - } - - return 0; -} - -static int link_carrier_gained(Link *link) { - int r; - - assert(link); - - if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) { - r = link_acquire_conf(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - - r = link_enter_set_addresses(link); - if (r < 0) - return r; - } - - r = link_handle_bound_by_list(link); - if (r < 0) - return r; - - return 0; -} - -static int link_carrier_lost(Link *link) { - int r; - - assert(link); - - r = link_stop_clients(link); - if (r < 0) { - link_enter_failed(link); - return r; - } - - r = link_drop_config(link); - if (r < 0) - return r; - - if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING)) { - log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state)); - r = link_drop_foreign_config(link); - if (r < 0) - return r; - } - - r = link_handle_bound_by_list(link); - if (r < 0) - return r; - - return 0; -} - -int link_carrier_reset(Link *link) { - int r; - - assert(link); - - if (link_has_carrier(link)) { - r = link_carrier_lost(link); - if (r < 0) - return r; - - r = link_carrier_gained(link); - if (r < 0) - return r; - - log_link_info(link, "Reset carrier"); - } - - return 0; -} - -int link_update(Link *link, sd_netlink_message *m) { - struct ether_addr mac; - const char *ifname; - uint32_t mtu; - bool had_carrier, carrier_gained, carrier_lost; - int r; - - assert(link); - assert(link->ifname); - assert(m); - - if (link->state == LINK_STATE_LINGER) { - link_ref(link); - 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_netlink_message_read_string(m, IFLA_IFNAME, &ifname); - if (r >= 0 && !streq(ifname, link->ifname)) { - log_link_info(link, "Renamed to %s", ifname); - - link_free_carrier_maps(link); - - r = free_and_strdup(&link->ifname, ifname); - if (r < 0) - return r; - - r = link_new_carrier_maps(link); - if (r < 0) - return r; - } - - r = sd_netlink_message_read_u32(m, IFLA_MTU, &mtu); - if (r >= 0 && mtu > 0) { - link->mtu = mtu; - if (!link->original_mtu) { - link->original_mtu = 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_errno(link, r, "Could not update MTU in DHCP client: %m"); - return r; - } - } - } - - /* The kernel may broadcast NEWLINK messages without the MAC address - set, simply ignore them. */ - r = sd_netlink_message_read_ether_addr(m, IFLA_ADDRESS, &mac); - if (r >= 0) { - if (memcmp(link->mac.ether_addr_octet, mac.ether_addr_octet, - ETH_ALEN)) { - - memcpy(link->mac.ether_addr_octet, mac.ether_addr_octet, - ETH_ALEN); - - log_link_debug(link, "MAC address: " - "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", - mac.ether_addr_octet[0], - mac.ether_addr_octet[1], - mac.ether_addr_octet[2], - mac.ether_addr_octet[3], - mac.ether_addr_octet[4], - mac.ether_addr_octet[5]); - - if (link->ipv4ll) { - r = sd_ipv4ll_set_mac(link->ipv4ll, &link->mac); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in IPv4LL client: %m"); - } - - if (link->dhcp_client) { - const DUID *duid = link_duid(link); - - r = sd_dhcp_client_set_mac(link->dhcp_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCP client: %m"); - - r = sd_dhcp_client_set_iaid_duid(link->dhcp_client, - link->network->iaid, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DUID/IAID in DHCP client: %m"); - } - - if (link->dhcp6_client) { - const DUID* duid = link_duid(link); - - r = sd_dhcp6_client_set_mac(link->dhcp6_client, - (const uint8_t *) &link->mac, - sizeof (link->mac), - ARPHRD_ETHER); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update MAC address in DHCPv6 client: %m"); - - r = sd_dhcp6_client_set_iaid(link->dhcp6_client, - link->network->iaid); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 IAID: %m"); - - r = sd_dhcp6_client_set_duid(link->dhcp6_client, - duid->type, - duid->raw_data_len > 0 ? duid->raw_data : NULL, - duid->raw_data_len); - if (r < 0) - return log_link_warning_errno(link, r, "Could not update DHCPv6 DUID: %m"); - } - } - } - - had_carrier = link_has_carrier(link); - - r = link_update_flags(link, m); - if (r < 0) - return r; - - r = link_update_lldp(link); - if (r < 0) - return r; - - carrier_gained = !had_carrier && link_has_carrier(link); - carrier_lost = had_carrier && !link_has_carrier(link); - - if (carrier_gained) { - 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"); - - r = link_carrier_lost(link); - if (r < 0) - return r; - } - - return 0; -} - -static void print_link_hashmap(FILE *f, const char *prefix, Hashmap* h) { - bool space = false; - Iterator i; - Link *link; - - assert(f); - assert(prefix); - - if (hashmap_isempty(h)) - return; - - fputs(prefix, f); - HASHMAP_FOREACH(link, h, i) { - if (space) - fputc(' ', f); - - fprintf(f, "%i", link->ifindex); - space = true; - } - - fputc('\n', f); -} - -int link_save(Link *link) { - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; - const char *admin_state, *oper_state; - Address *a; - Route *route; - Iterator i; - int r; - - assert(link); - assert(link->state_file); - assert(link->lease_file); - assert(link->manager); - - if (link->state == LINK_STATE_LINGER) { - unlink(link->state_file); - return 0; - } - - link_lldp_save(link); - - admin_state = link_state_to_string(link->state); - assert(admin_state); - - oper_state = link_operstate_to_string(link->operstate); - assert(oper_state); - - r = fopen_temporary(link->state_file, &f, &temp_path); - if (r < 0) - goto fail; - - fchmod(fileno(f), 0644); - - fprintf(f, - "# This is private data. Do not parse.\n" - "ADMIN_STATE=%s\n" - "OPER_STATE=%s\n", - admin_state, oper_state); - - if (link->network) { - bool space; - sd_dhcp6_lease *dhcp6_lease = NULL; - const char *dhcp_domainname = NULL; - char **dhcp6_domains = NULL; - - if (link->dhcp6_client) { - r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease); - if (r < 0 && r != -ENOMSG) - log_link_debug(link, "No DHCPv6 lease"); - } - - fprintf(f, "NETWORK_FILE=%s\n", link->network->filename); - - fputs("DNS=", f); - space = false; - fputstrv(f, link->network->dns, NULL, &space); - - if (link->network->dhcp_use_dns && - link->dhcp_lease) { - const struct in_addr *addresses; - - r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); - if (r > 0) { - if (space) - fputc(' ', f); - serialize_in_addrs(f, addresses, r); - space = true; - } - } - - if (link->network->dhcp_use_dns && dhcp6_lease) { - struct in6_addr *in6_addrs; - - r = sd_dhcp6_lease_get_dns(dhcp6_lease, &in6_addrs); - if (r > 0) { - if (space) - fputc(' ', f); - serialize_in6_addrs(f, in6_addrs, r); - space = true; - } - } - - /* Make sure to flush out old entries before we use the NDISC data */ - ndisc_vacuum(link); - - if (link->network->dhcp_use_dns && link->ndisc_rdnss) { - NDiscRDNSS *dd; - - SET_FOREACH(dd, link->ndisc_rdnss, i) { - if (space) - fputc(' ', f); - - serialize_in6_addrs(f, &dd->address, 1); - space = true; - } - } - - fputc('\n', f); - - fputs("NTP=", f); - space = false; - fputstrv(f, link->network->ntp, NULL, &space); - - if (link->network->dhcp_use_ntp && - link->dhcp_lease) { - const struct in_addr *addresses; - - r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); - if (r > 0) { - if (space) - fputc(' ', f); - serialize_in_addrs(f, addresses, r); - space = true; - } - } - - if (link->network->dhcp_use_ntp && dhcp6_lease) { - struct in6_addr *in6_addrs; - char **hosts; - - r = sd_dhcp6_lease_get_ntp_addrs(dhcp6_lease, - &in6_addrs); - if (r > 0) { - if (space) - fputc(' ', f); - serialize_in6_addrs(f, in6_addrs, r); - space = true; - } - - r = sd_dhcp6_lease_get_ntp_fqdn(dhcp6_lease, &hosts); - if (r > 0) - fputstrv(f, hosts, NULL, &space); - } - - fputc('\n', f); - - if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { - if (link->dhcp_lease) - (void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname); - if (dhcp6_lease) - (void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains); - } - - fputs("DOMAINS=", f); - fputstrv(f, link->network->search_domains, NULL, &space); - - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) { - NDiscDNSSL *dd; - - if (dhcp_domainname) - fputs_with_space(f, dhcp_domainname, NULL, &space); - if (dhcp6_domains) - fputstrv(f, dhcp6_domains, NULL, &space); - - SET_FOREACH(dd, link->ndisc_dnssl, i) - fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); - } - - fputc('\n', f); - - fputs("ROUTE_DOMAINS=", f); - fputstrv(f, link->network->route_domains, NULL, NULL); - - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) { - NDiscDNSSL *dd; - - if (dhcp_domainname) - fputs_with_space(f, dhcp_domainname, NULL, &space); - if (dhcp6_domains) - fputstrv(f, dhcp6_domains, NULL, &space); - - SET_FOREACH(dd, link->ndisc_dnssl, i) - fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space); - } - - fputc('\n', f); - - fprintf(f, "LLMNR=%s\n", - resolve_support_to_string(link->network->llmnr)); - fprintf(f, "MDNS=%s\n", - resolve_support_to_string(link->network->mdns)); - - if (link->network->dnssec_mode != _DNSSEC_MODE_INVALID) - fprintf(f, "DNSSEC=%s\n", - dnssec_mode_to_string(link->network->dnssec_mode)); - - if (!set_isempty(link->network->dnssec_negative_trust_anchors)) { - const char *n; - - fputs("DNSSEC_NTA=", f); - space = false; - SET_FOREACH(n, link->network->dnssec_negative_trust_anchors, i) - fputs_with_space(f, n, NULL, &space); - fputc('\n', f); - } - - fputs("ADDRESSES=", f); - space = false; - SET_FOREACH(a, link->addresses, i) { - _cleanup_free_ char *address_str = NULL; - - r = in_addr_to_string(a->family, &a->in_addr, &address_str); - if (r < 0) - goto fail; - - fprintf(f, "%s%s/%u", space ? " " : "", address_str, a->prefixlen); - space = true; - } - fputc('\n', f); - - fputs("ROUTES=", f); - space = false; - SET_FOREACH(route, link->routes, i) { - _cleanup_free_ char *route_str = NULL; - - r = in_addr_to_string(route->family, &route->dst, &route_str); - if (r < 0) - goto fail; - - fprintf(f, "%s%s/%hhu/%hhu/%"PRIu32"/%hhu/"USEC_FMT, space ? " " : "", route_str, - route->dst_prefixlen, route->tos, route->priority, route->table, route->lifetime); - space = true; - } - - fputc('\n', f); - } - - print_link_hashmap(f, "CARRIER_BOUND_TO=", link->bound_to_links); - print_link_hashmap(f, "CARRIER_BOUND_BY=", link->bound_by_links); - - if (link->dhcp_lease) { - struct in_addr address; - const char *tz = NULL; - - assert(link->network); - - r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz); - if (r >= 0) - fprintf(f, "TIMEZONE=%s\n", tz); - - r = sd_dhcp_lease_get_address(link->dhcp_lease, &address); - if (r >= 0) { - fputs("DHCP4_ADDRESS=", f); - serialize_in_addrs(f, &address, 1); - fputc('\n', f); - } - - r = dhcp_lease_save(link->dhcp_lease, link->lease_file); - if (r < 0) - goto fail; - - fprintf(f, - "DHCP_LEASE=%s\n", - link->lease_file); - } else - unlink(link->lease_file); - - if (link->ipv4ll) { - struct in_addr address; - - r = sd_ipv4ll_get_address(link->ipv4ll, &address); - if (r >= 0) { - fputs("IPV4LL_ADDRESS=", f); - serialize_in_addrs(f, &address, 1); - fputc('\n', f); - } - } - - r = fflush_and_check(f); - if (r < 0) - goto fail; - - if (rename(temp_path, link->state_file) < 0) { - r = -errno; - goto fail; - } - - return 0; - -fail: - (void) unlink(link->state_file); - if (temp_path) - (void) unlink(temp_path); - - return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file); -} - -/* The serialized state in /run is no longer up-to-date. */ -void link_dirty(Link *link) { - int r; - - assert(link); - - /* mark manager dirty as link is dirty */ - manager_dirty(link->manager); - - r = set_ensure_allocated(&link->manager->dirty_links, NULL); - if (r < 0) - /* allocation errors are ignored */ - return; - - r = set_put(link->manager->dirty_links, link); - if (r <= 0) - /* don't take another ref if the link was already dirty */ - return; - - link_ref(link); -} - -/* The serialized state in /run is up-to-date */ -void link_clean(Link *link) { - assert(link); - assert(link->manager); - - set_remove(link->manager->dirty_links, link); - link_unref(link); -} - -static const char* const link_state_table[_LINK_STATE_MAX] = { - [LINK_STATE_PENDING] = "pending", - [LINK_STATE_ENSLAVING] = "configuring", - [LINK_STATE_SETTING_ADDRESSES] = "configuring", - [LINK_STATE_SETTING_ROUTES] = "configuring", - [LINK_STATE_CONFIGURED] = "configured", - [LINK_STATE_UNMANAGED] = "unmanaged", - [LINK_STATE_FAILED] = "failed", - [LINK_STATE_LINGER] = "linger", -}; - -DEFINE_STRING_TABLE_LOOKUP(link_state, LinkState); - -static const char* const link_operstate_table[_LINK_OPERSTATE_MAX] = { - [LINK_OPERSTATE_OFF] = "off", - [LINK_OPERSTATE_NO_CARRIER] = "no-carrier", - [LINK_OPERSTATE_DORMANT] = "dormant", - [LINK_OPERSTATE_CARRIER] = "carrier", - [LINK_OPERSTATE_DEGRADED] = "degraded", - [LINK_OPERSTATE_ROUTABLE] = "routable", -}; - -DEFINE_STRING_TABLE_LOOKUP(link_operstate, LinkOperationalState); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h deleted file mode 100644 index 77f72d070e..0000000000 --- a/src/network/networkd-link.h +++ /dev/null @@ -1,213 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <endian.h> - -#include "sd-bus.h" -#include "sd-dhcp-client.h" -#include "sd-dhcp-server.h" -#include "sd-dhcp6-client.h" -#include "sd-ipv4ll.h" -#include "sd-lldp.h" -#include "sd-ndisc.h" -#include "sd-netlink.h" - -#include "list.h" -#include "set.h" - -typedef enum LinkState { - LINK_STATE_PENDING, - LINK_STATE_ENSLAVING, - LINK_STATE_SETTING_ADDRESSES, - LINK_STATE_SETTING_ROUTES, - LINK_STATE_CONFIGURED, - LINK_STATE_UNMANAGED, - LINK_STATE_FAILED, - LINK_STATE_LINGER, - _LINK_STATE_MAX, - _LINK_STATE_INVALID = -1 -} LinkState; - -typedef enum LinkOperationalState { - LINK_OPERSTATE_OFF, - LINK_OPERSTATE_NO_CARRIER, - LINK_OPERSTATE_DORMANT, - LINK_OPERSTATE_CARRIER, - LINK_OPERSTATE_DEGRADED, - LINK_OPERSTATE_ROUTABLE, - _LINK_OPERSTATE_MAX, - _LINK_OPERSTATE_INVALID = -1 -} LinkOperationalState; - -typedef struct Manager Manager; -typedef struct Network Network; -typedef struct Address Address; - -typedef struct Link { - Manager *manager; - - int n_ref; - - int ifindex; - char *ifname; - char *kind; - unsigned short iftype; - char *state_file; - struct ether_addr mac; - struct in6_addr ipv6ll_address; - uint32_t mtu; - struct udev_device *udev_device; - - unsigned flags; - uint8_t kernel_operstate; - - Network *network; - - LinkState state; - LinkOperationalState operstate; - - unsigned link_messages; - unsigned enslaving; - - Set *addresses; - Set *addresses_foreign; - Set *routes; - Set *routes_foreign; - - sd_dhcp_client *dhcp_client; - sd_dhcp_lease *dhcp_lease; - char *lease_file; - uint16_t original_mtu; - unsigned dhcp4_messages; - bool dhcp4_configured; - bool dhcp6_configured; - - unsigned ndisc_messages; - bool ndisc_configured; - - sd_ipv4ll *ipv4ll; - bool ipv4ll_address:1; - bool ipv4ll_route:1; - - bool static_configured; - - LIST_HEAD(Address, pool_addresses); - - sd_dhcp_server *dhcp_server; - - sd_ndisc *ndisc; - Set *ndisc_rdnss; - Set *ndisc_dnssl; - - sd_dhcp6_client *dhcp6_client; - bool rtnl_extended_attrs; - - /* This is about LLDP reception */ - sd_lldp *lldp; - char *lldp_file; - - /* This is about LLDP transmission */ - unsigned lldp_tx_fast; /* The LLDP txFast counter (See 802.1ab-2009, section 9.2.5.18) */ - sd_event_source *lldp_emit_event_source; - - Hashmap *bound_by_links; - Hashmap *bound_to_links; -} Link; - -Link *link_unref(Link *link); -Link *link_ref(Link *link); -int link_get(Manager *m, int ifindex, Link **ret); -int link_add(Manager *manager, sd_netlink_message *message, Link **ret); -void link_drop(Link *link); - -int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); -int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata); - -void link_enter_failed(Link *link); -int link_initialized(Link *link, struct udev_device *device); - -void link_check_ready(Link *link); - -void link_update_operstate(Link *link); -int link_update(Link *link, sd_netlink_message *message); - -void link_dirty(Link *link); -void link_clean(Link *link); -int link_save(Link *link); - -int link_carrier_reset(Link *link); -bool link_has_carrier(Link *link); - -int link_ipv6ll_gained(Link *link, const struct in6_addr *address); - -int link_set_mtu(Link *link, uint32_t mtu); -int link_set_hostname(Link *link, const char *hostname); -int link_set_timezone(Link *link, const char *timezone); - -int ipv4ll_configure(Link *link); -int dhcp4_configure(Link *link); -int dhcp6_configure(Link *link); -int dhcp6_request_address(Link *link, int ir); - -const char* link_state_to_string(LinkState s) _const_; -LinkState link_state_from_string(const char *s) _pure_; - -const char* link_operstate_to_string(LinkOperationalState s) _const_; -LinkOperationalState link_operstate_from_string(const char *s) _pure_; - -extern const sd_bus_vtable link_vtable[]; - -int link_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int link_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); -int link_send_changed(Link *link, const char *property, ...) _sentinel_; - -DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref); -#define _cleanup_link_unref_ _cleanup_(link_unrefp) - -/* Macros which append INTERFACE= to the message */ - -#define log_link_full(link, level, error, ...) \ - ({ \ - const Link *_l = (link); \ - _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__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_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__) -#define log_link_notice_errno(link, error, ...) log_link_full(link, LOG_NOTICE, error, ##__VA_ARGS__) -#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_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, \ - (be32toh((address).s_addr) >> 16) & 0xFFu, \ - (be32toh((address).s_addr) >> 8) & 0xFFu, \ - be32toh((address).s_addr) & 0xFFu diff --git a/src/network/networkd-lldp-tx.c b/src/network/networkd-lldp-tx.c deleted file mode 100644 index 3aa768388b..0000000000 --- a/src/network/networkd-lldp-tx.c +++ /dev/null @@ -1,416 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2016 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <endian.h> -#include <inttypes.h> -#include <string.h> - -#include "alloc-util.h" -#include "fd-util.h" -#include "fileio.h" -#include "hostname-util.h" -#include "networkd-lldp-tx.h" -#include "networkd.h" -#include "parse-util.h" -#include "random-util.h" -#include "socket-util.h" -#include "string-util.h" -#include "unaligned.h" - -/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */ -#define LLDP_TX_FAST_INIT 4U - -/* The LLDP spec calls this "msgTxHold", see 9.2.5.6 */ -#define LLDP_TX_HOLD 4U - -/* The jitter range to add, see 9.2.2. */ -#define LLDP_JITTER_USEC (400U * USEC_PER_MSEC) - -/* The LLDP spec calls this msgTxInterval, but we subtract half the jitter off it. */ -#define LLDP_TX_INTERVAL_USEC (30U * USEC_PER_SEC - LLDP_JITTER_USEC / 2) - -/* The LLDP spec calls this msgFastTx, but we subtract half the jitter off it. */ -#define LLDP_FAST_TX_USEC (1U * USEC_PER_SEC - LLDP_JITTER_USEC / 2) - -static const struct ether_addr lldp_multicast_addr[_LLDP_EMIT_MAX] = { - [LLDP_EMIT_NEAREST_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e }}, - [LLDP_EMIT_NON_TPMR_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 }}, - [LLDP_EMIT_CUSTOMER_BRIDGE] = {{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }}, -}; - -static int lldp_write_tlv_header(uint8_t **p, uint8_t id, size_t sz) { - assert(p); - - if (id > 127) - return -EBADMSG; - if (sz > 511) - return -ENOBUFS; - - (*p)[0] = (id << 1) | !!(sz & 256); - (*p)[1] = sz & 255; - - *p = *p + 2; - return 0; -} - -static int lldp_make_packet( - LLDPEmit mode, - const struct ether_addr *hwaddr, - const char *machine_id, - const char *ifname, - uint16_t ttl, - const char *port_description, - const char *hostname, - const char *pretty_hostname, - uint16_t system_capabilities, - uint16_t enabled_capabilities, - void **ret, size_t *sz) { - - size_t machine_id_length, ifname_length, port_description_length = 0, hostname_length = 0, pretty_hostname_length = 0; - _cleanup_free_ void *packet = NULL; - struct ether_header *h; - uint8_t *p; - size_t l; - int r; - - assert(mode > LLDP_EMIT_NO); - assert(mode < _LLDP_EMIT_MAX); - assert(hwaddr); - assert(machine_id); - assert(ifname); - assert(ret); - assert(sz); - - machine_id_length = strlen(machine_id); - ifname_length = strlen(ifname); - - if (port_description) - port_description_length = strlen(port_description); - - if (hostname) - hostname_length = strlen(hostname); - - if (pretty_hostname) - pretty_hostname_length = strlen(pretty_hostname); - - l = sizeof(struct ether_header) + - /* Chassis ID */ - 2 + 1 + machine_id_length + - /* Port ID */ - 2 + 1 + ifname_length + - /* TTL */ - 2 + 2 + - /* System Capabilities */ - 2 + 4 + - /* End */ - 2; - - /* Port Description */ - if (port_description) - l += 2 + port_description_length; - - /* System Name */ - if (hostname) - l += 2 + hostname_length; - - /* System Description */ - if (pretty_hostname) - l += 2 + pretty_hostname_length; - - packet = malloc(l); - if (!packet) - return -ENOMEM; - - h = (struct ether_header*) packet; - h->ether_type = htobe16(ETHERTYPE_LLDP); - memcpy(h->ether_dhost, lldp_multicast_addr + mode, ETH_ALEN); - memcpy(h->ether_shost, hwaddr, ETH_ALEN); - - p = (uint8_t*) packet + sizeof(struct ether_header); - - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_CHASSIS_ID, 1 + machine_id_length); - if (r < 0) - return r; - *(p++) = SD_LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED; - p = mempcpy(p, machine_id, machine_id_length); - - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_ID, 1 + ifname_length); - if (r < 0) - return r; - *(p++) = SD_LLDP_PORT_SUBTYPE_INTERFACE_NAME; - p = mempcpy(p, ifname, ifname_length); - - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_TTL, 2); - if (r < 0) - return r; - unaligned_write_be16(p, ttl); - p += 2; - - if (port_description) { - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_PORT_DESCRIPTION, port_description_length); - if (r < 0) - return r; - p = mempcpy(p, port_description, port_description_length); - } - - if (hostname) { - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_NAME, hostname_length); - if (r < 0) - return r; - p = mempcpy(p, hostname, hostname_length); - } - - if (pretty_hostname) { - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_DESCRIPTION, pretty_hostname_length); - if (r < 0) - return r; - p = mempcpy(p, pretty_hostname, pretty_hostname_length); - } - - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_SYSTEM_CAPABILITIES, 4); - if (r < 0) - return r; - unaligned_write_be16(p, system_capabilities); - p += 2; - unaligned_write_be16(p, enabled_capabilities); - p += 2; - - r = lldp_write_tlv_header(&p, SD_LLDP_TYPE_END, 0); - if (r < 0) - return r; - - assert(p == (uint8_t*) packet + l); - - *ret = packet; - *sz = l; - - packet = NULL; - return 0; -} - -static int lldp_send_packet( - int ifindex, - const struct ether_addr *address, - const void *packet, - size_t packet_size) { - - union sockaddr_union sa = { - .ll.sll_family = AF_PACKET, - .ll.sll_protocol = htobe16(ETHERTYPE_LLDP), - .ll.sll_ifindex = ifindex, - .ll.sll_halen = ETH_ALEN, - }; - - _cleanup_close_ int fd = -1; - ssize_t l; - - assert(ifindex > 0); - assert(address); - assert(packet || packet_size <= 0); - - memcpy(sa.ll.sll_addr, address, ETH_ALEN); - - fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, IPPROTO_RAW); - if (fd < 0) - return -errno; - - l = sendto(fd, packet, packet_size, MSG_NOSIGNAL, &sa.sa, sizeof(sa.ll)); - if (l < 0) - return -errno; - - if ((size_t) l != packet_size) - return -EIO; - - return 0; -} - -static int link_send_lldp(Link *link) { - char machine_id_string[SD_ID128_STRING_MAX]; - _cleanup_free_ char *hostname = NULL, *pretty_hostname = NULL; - _cleanup_free_ void *packet = NULL; - size_t packet_size = 0; - sd_id128_t machine_id; - uint16_t caps; - usec_t ttl; - int r; - - assert(link); - - if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) - return 0; - - assert(link->network->lldp_emit < _LLDP_EMIT_MAX); - - r = sd_id128_get_machine(&machine_id); - if (r < 0) - return r; - - (void) gethostname_strict(&hostname); - (void) parse_env_file("/etc/machine-info", NEWLINE, "PRETTY_HOSTNAME", &pretty_hostname, NULL); - - assert_cc(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1 <= (UINT16_MAX - 1) * USEC_PER_SEC); - ttl = DIV_ROUND_UP(LLDP_TX_INTERVAL_USEC * LLDP_TX_HOLD + 1, USEC_PER_SEC); - - caps = (link->network && link->network->ip_forward != ADDRESS_FAMILY_NO) ? - SD_LLDP_SYSTEM_CAPABILITIES_ROUTER : - SD_LLDP_SYSTEM_CAPABILITIES_STATION; - - r = lldp_make_packet(link->network->lldp_emit, - &link->mac, - sd_id128_to_string(machine_id, machine_id_string), - link->ifname, - (uint16_t) ttl, - link->network ? link->network->description : NULL, - hostname, - pretty_hostname, - SD_LLDP_SYSTEM_CAPABILITIES_STATION|SD_LLDP_SYSTEM_CAPABILITIES_BRIDGE|SD_LLDP_SYSTEM_CAPABILITIES_ROUTER, - caps, - &packet, &packet_size); - if (r < 0) - return r; - - return lldp_send_packet(link->ifindex, lldp_multicast_addr + link->network->lldp_emit, packet, packet_size); -} - -static int on_lldp_timer(sd_event_source *s, usec_t t, void *userdata) { - Link *link = userdata; - usec_t current, delay, next; - int r; - - assert(s); - assert(userdata); - - log_link_debug(link, "Sending LLDP packet..."); - - r = link_send_lldp(link); - if (r < 0) - log_link_debug_errno(link, r, "Failed to send LLDP packet, ignoring: %m"); - - if (link->lldp_tx_fast > 0) - link->lldp_tx_fast--; - - assert_se(sd_event_now(sd_event_source_get_event(s), clock_boottime_or_monotonic(), ¤t) >= 0); - - delay = link->lldp_tx_fast > 0 ? LLDP_FAST_TX_USEC : LLDP_TX_INTERVAL_USEC; - next = usec_add(usec_add(current, delay), (usec_t) random_u64() % LLDP_JITTER_USEC); - - r = sd_event_source_set_time(s, next); - if (r < 0) - return log_link_error_errno(link, r, "Failed to restart LLDP timer: %m"); - - r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT); - if (r < 0) - return log_link_error_errno(link, r, "Failed to enable LLDP timer: %m"); - - return 0; -} - -int link_lldp_emit_start(Link *link) { - usec_t next; - int r; - - assert(link); - - if (!link->network || link->network->lldp_emit == LLDP_EMIT_NO) { - link_lldp_emit_stop(link); - return 0; - } - - /* Starts the LLDP transmission in "fast" mode. If it is already started, turns "fast" mode back on again. */ - - link->lldp_tx_fast = LLDP_TX_FAST_INIT; - - next = usec_add(usec_add(now(clock_boottime_or_monotonic()), LLDP_FAST_TX_USEC), - (usec_t) random_u64() % LLDP_JITTER_USEC); - - if (link->lldp_emit_event_source) { - usec_t old; - - /* Lower the timeout, maybe */ - r = sd_event_source_get_time(link->lldp_emit_event_source, &old); - if (r < 0) - return r; - - if (old <= next) - return 0; - - return sd_event_source_set_time(link->lldp_emit_event_source, next); - } else { - r = sd_event_add_time( - link->manager->event, - &link->lldp_emit_event_source, - clock_boottime_or_monotonic(), - next, - 0, - on_lldp_timer, - link); - if (r < 0) - return r; - - (void) sd_event_source_set_description(link->lldp_emit_event_source, "lldp-tx"); - } - - return 0; -} - -void link_lldp_emit_stop(Link *link) { - assert(link); - - link->lldp_emit_event_source = sd_event_source_unref(link->lldp_emit_event_source); -} - -int config_parse_lldp_emit( - 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) { - - LLDPEmit *emit = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - if (isempty(rvalue)) - *emit = LLDP_EMIT_NO; - else if (streq(rvalue, "nearest-bridge")) - *emit = LLDP_EMIT_NEAREST_BRIDGE; - else if (streq(rvalue, "non-tpmr-bridge")) - *emit = LLDP_EMIT_NON_TPMR_BRIDGE; - else if (streq(rvalue, "customer-bridge")) - *emit = LLDP_EMIT_CUSTOMER_BRIDGE; - else { - r = parse_boolean(rvalue); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse LLDP emission setting, ignoring: %s", rvalue); - return 0; - } - - *emit = r ? LLDP_EMIT_NEAREST_BRIDGE : LLDP_EMIT_NO; - } - - return 0; -} diff --git a/src/network/networkd-lldp-tx.h b/src/network/networkd-lldp-tx.h deleted file mode 100644 index 4680c9d950..0000000000 --- a/src/network/networkd-lldp-tx.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2016 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd-link.h" - -typedef enum LLDPEmit { - LLDP_EMIT_NO, - LLDP_EMIT_NEAREST_BRIDGE, - LLDP_EMIT_NON_TPMR_BRIDGE, - LLDP_EMIT_CUSTOMER_BRIDGE, - _LLDP_EMIT_MAX, -} LLDPEmit; - -int link_lldp_emit_start(Link *link); -void link_lldp_emit_stop(Link *link); - -int config_parse_lldp_emit(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-manager-bus.c b/src/network/networkd-manager-bus.c deleted file mode 100644 index 0c429b9471..0000000000 --- a/src/network/networkd-manager-bus.c +++ /dev/null @@ -1,49 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "bus-util.h" -#include "networkd.h" - -static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_operational_state, link_operstate, LinkOperationalState); - -const sd_bus_vtable manager_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("OperationalState", "s", property_get_operational_state, offsetof(Manager, operational_state), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - - SD_BUS_VTABLE_END -}; - -int manager_send_changed(Manager *manager, const char *property, ...) { - char **l; - - assert(manager); - - if (!manager->bus) - return 0; /* replace by assert when we have kdbus */ - - l = strv_from_stdarg_alloca(property); - - return sd_bus_emit_properties_changed_strv( - manager->bus, - "/org/freedesktop/network1", - "org.freedesktop.network1.Manager", - l); -} diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c deleted file mode 100644 index 9174dcc7f4..0000000000 --- a/src/network/networkd-manager.c +++ /dev/null @@ -1,1329 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. - ***/ - -#include <sys/socket.h> -#include <linux/if.h> - -#include "sd-daemon.h" -#include "sd-netlink.h" - -#include "alloc-util.h" -#include "bus-util.h" -#include "conf-parser.h" -#include "def.h" -#include "dns-domain.h" -#include "fd-util.h" -#include "fileio.h" -#include "libudev-private.h" -#include "local-addresses.h" -#include "netlink-util.h" -#include "networkd.h" -#include "ordered-set.h" -#include "path-util.h" -#include "set.h" -#include "udev-util.h" -#include "virt.h" - -/* use 8 MB for receive socket kernel queue. */ -#define RCVBUF_SIZE (8*1024*1024) - -const char* const network_dirs[] = { - "/etc/systemd/network", - "/run/systemd/network", - "/usr/lib/systemd/network", -#ifdef HAVE_SPLIT_USR - "/lib/systemd/network", -#endif - NULL}; - -static int setup_default_address_pool(Manager *m) { - AddressPool *p; - int r; - - assert(m); - - /* Add in the well-known private address ranges. */ - - r = address_pool_new_from_string(m, &p, AF_INET6, "fc00::", 7); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "192.168.0.0", 16); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "172.16.0.0", 12); - if (r < 0) - return r; - - r = address_pool_new_from_string(m, &p, AF_INET, "10.0.0.0", 8); - if (r < 0) - return r; - - return 0; -} - -static int on_bus_retry(sd_event_source *s, usec_t usec, void *userdata) { - Manager *m = userdata; - - assert(s); - assert(m); - - m->bus_retry_event_source = sd_event_source_unref(m->bus_retry_event_source); - - manager_connect_bus(m); - - return 0; -} - -static int manager_reset_all(Manager *m) { - Link *link; - Iterator i; - int r; - - assert(m); - - HASHMAP_FOREACH(link, m->links, i) { - r = link_carrier_reset(link); - if (r < 0) - log_link_warning_errno(link, r, "Could not reset carrier: %m"); - } - - return 0; -} - -static int match_prepare_for_sleep(sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { - Manager *m = userdata; - int b, r; - - assert(message); - - r = sd_bus_message_read(message, "b", &b); - if (r < 0) { - log_debug_errno(r, "Failed to parse PrepareForSleep signal: %m"); - return 0; - } - - if (b) - return 0; - - log_debug("Coming back from suspend, resetting all connections..."); - - manager_reset_all(m); - - return 0; -} - -int manager_connect_bus(Manager *m) { - int r; - - assert(m); - - r = sd_bus_default_system(&m->bus); - if (r == -ENOENT) { - /* We failed to connect? Yuck, we must be in early - * boot. Let's try in 5s again. As soon as we have - * kdbus we can stop doing this... */ - - log_debug_errno(r, "Failed to connect to bus, trying again in 5s: %m"); - - r = sd_event_add_time(m->event, &m->bus_retry_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + 5*USEC_PER_SEC, 0, on_bus_retry, m); - if (r < 0) - return log_error_errno(r, "Failed to install bus reconnect time event: %m"); - - return 0; - } - - if (r < 0) - return r; - - r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot, - "type='signal'," - "sender='org.freedesktop.login1'," - "interface='org.freedesktop.login1.Manager'," - "member='PrepareForSleep'," - "path='/org/freedesktop/login1'", - match_prepare_for_sleep, - m); - if (r < 0) - return log_error_errno(r, "Failed to add match for PrepareForSleep: %m"); - - r = sd_bus_add_object_vtable(m->bus, NULL, "/org/freedesktop/network1", "org.freedesktop.network1.Manager", manager_vtable, m); - if (r < 0) - return log_error_errno(r, "Failed to add manager object vtable: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/link", "org.freedesktop.network1.Link", link_vtable, link_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add link object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/link", link_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add link enumerator: %m"); - - r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/network1/network", "org.freedesktop.network1.Network", network_vtable, network_object_find, m); - if (r < 0) - return log_error_errno(r, "Failed to add network object vtable: %m"); - - r = sd_bus_add_node_enumerator(m->bus, NULL, "/org/freedesktop/network1/network", network_node_enumerator, m); - if (r < 0) - return log_error_errno(r, "Failed to add network enumerator: %m"); - - r = sd_bus_request_name(m->bus, "org.freedesktop.network1", 0); - if (r < 0) - return log_error_errno(r, "Failed to register name: %m"); - - r = sd_bus_attach_event(m->bus, m->event, 0); - if (r < 0) - return log_error_errno(r, "Failed to attach bus to event loop: %m"); - - return 0; -} - -static int manager_udev_process_link(Manager *m, struct udev_device *device) { - Link *link = NULL; - int r, ifindex; - - assert(m); - assert(device); - - if (!streq_ptr(udev_device_get_action(device), "add")) - return 0; - - ifindex = udev_device_get_ifindex(device); - if (ifindex <= 0) { - log_debug("Ignoring udev ADD event for device with invalid ifindex"); - return 0; - } - - r = link_get(m, ifindex, &link); - if (r == -ENODEV) - return 0; - else if (r < 0) - return r; - - r = link_initialized(link, device); - if (r < 0) - return r; - - return 0; -} - -static int manager_dispatch_link_udev(sd_event_source *source, int fd, uint32_t revents, void *userdata) { - Manager *m = userdata; - struct udev_monitor *monitor = m->udev_monitor; - _cleanup_udev_device_unref_ struct udev_device *device = NULL; - - device = udev_monitor_receive_device(monitor); - if (!device) - return -ENOMEM; - - manager_udev_process_link(m, device); - return 0; -} - -static int manager_connect_udev(Manager *m) { - int r; - - /* udev does not initialize devices inside containers, - * so we rely on them being already initialized before - * entering the container */ - if (detect_container() > 0) - return 0; - - m->udev = udev_new(); - if (!m->udev) - return -ENOMEM; - - m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); - if (!m->udev_monitor) - return -ENOMEM; - - r = udev_monitor_filter_add_match_subsystem_devtype(m->udev_monitor, "net", NULL); - if (r < 0) - return log_error_errno(r, "Could not add udev monitor filter: %m"); - - r = udev_monitor_enable_receiving(m->udev_monitor); - if (r < 0) { - log_error("Could not enable udev monitor"); - return r; - } - - r = sd_event_add_io(m->event, - &m->udev_event_source, - udev_monitor_get_fd(m->udev_monitor), - EPOLLIN, manager_dispatch_link_udev, - m); - if (r < 0) - return r; - - r = sd_event_source_set_description(m->udev_event_source, "networkd-udev"); - if (r < 0) - return r; - - return 0; -} - -int manager_rtnl_process_route(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; - Link *link = NULL; - uint16_t type; - uint32_t ifindex, priority = 0; - unsigned char protocol, scope, tos, table; - int family; - unsigned char dst_prefixlen, src_prefixlen; - union in_addr_union dst = {}, gw = {}, src = {}, prefsrc = {}; - Route *route = NULL; - int r; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_warning_errno(r, "rtnl: failed to receive route: %m"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get message type: %m"); - return 0; - } else if (type != RTM_NEWROUTE && type != RTM_DELROUTE) { - log_warning("rtnl: received unexpected message type when processing route"); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTA_OIF, &ifindex); - if (r == -ENODATA) { - log_debug("rtnl: received route without ifindex, ignoring"); - return 0; - } else if (r < 0) { - log_warning_errno(r, "rtnl: could not get ifindex from route, ignoring: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received route message with invalid ifindex, ignoring: %d", ifindex); - return 0; - } else { - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will - * get the route again, so just ignore it */ - if (!m->enumerating) - log_warning("rtnl: received route for nonexistent link (%d), ignoring", ifindex); - return 0; - } - } - - r = sd_rtnl_message_route_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received address with invalid family, ignoring."); - return 0; - } - - r = sd_rtnl_message_route_get_protocol(message, &protocol); - if (r < 0) { - log_warning_errno(r, "rtnl: could not get route protocol: %m"); - return 0; - } - - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, RTA_DST, &dst.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route without valid destination, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_GATEWAY, &gw.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid gateway, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_SRC, &src.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid source, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in_addr(message, RTA_PREFSRC, &prefsrc.in); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid preferred source, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, RTA_DST, &dst.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route without valid destination, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_GATEWAY, &gw.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid gateway, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_SRC, &src.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid source, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_in6_addr(message, RTA_PREFSRC, &prefsrc.in6); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid preferred source, ignoring: %m"); - return 0; - } - - break; - - default: - log_link_debug(link, "rtnl: ignoring unsupported address family: %d", family); - return 0; - } - - r = sd_rtnl_message_route_get_dst_prefixlen(message, &dst_prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route with invalid destination prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_src_prefixlen(message, &src_prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route with invalid source prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_scope(message, &scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_tos(message, &tos); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route with invalid tos, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_route_get_table(message, &table); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received route with invalid table, ignoring: %m"); - return 0; - } - - r = sd_netlink_message_read_u32(message, RTA_PRIORITY, &priority); - if (r < 0 && r != -ENODATA) { - log_link_warning_errno(link, r, "rtnl: received route with invalid priority, ignoring: %m"); - return 0; - } - - route_get(link, family, &dst, dst_prefixlen, tos, priority, table, &route); - - switch (type) { - case RTM_NEWROUTE: - if (!route) { - /* A route appeared that we did not request */ - r = route_add_foreign(link, family, &dst, dst_prefixlen, tos, priority, table, &route); - if (r < 0) - return 0; - } - - route_update(route, &src, src_prefixlen, &gw, &prefsrc, scope, protocol); - - break; - - case RTM_DELROUTE: - route_free(route); - break; - - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - -int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; - Link *link = NULL; - uint16_t type; - unsigned char flags; - int family; - unsigned char prefixlen; - unsigned char scope; - union in_addr_union in_addr; - struct ifa_cacheinfo cinfo; - Address *address = NULL; - char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX]; - const char *valid_str = NULL; - int r, ifindex; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_warning_errno(r, "rtnl: failed to receive address: %m"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - if (r < 0) { - 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 from address: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received address message with invalid ifindex: %d", ifindex); - return 0; - } else { - r = link_get(m, ifindex, &link); - if (r < 0 || !link) { - /* when enumerating we might be out of sync, but we will - * get the address again, so just ignore it */ - if (!m->enumerating) - log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex); - return 0; - } - } - - r = sd_rtnl_message_addr_get_family(message, &family); - if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) { - log_link_warning(link, "rtnl: received address with invalid family, ignoring."); - return 0; - } - - r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_scope(message, &scope); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m"); - return 0; - } - - r = sd_rtnl_message_addr_get_flags(message, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m"); - return 0; - } - - switch (family) { - case AF_INET: - r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); - return 0; - } - - break; - - case AF_INET6: - r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6); - if (r < 0) { - log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m"); - return 0; - } - - break; - - default: - log_link_debug(link, "rtnl: ignoring unsupported address family: %d", family); - } - - if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) { - log_link_warning(link, "Could not print address"); - return 0; - } - - r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo); - if (r >= 0) { - if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME) - valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX, - cinfo.ifa_valid * USEC_PER_SEC, - USEC_PER_SEC); - } - - address_get(link, family, &in_addr, prefixlen, &address); - - switch (type) { - case RTM_NEWADDR: - if (address) - log_link_debug(link, "Updating address: %s/%u (valid %s%s)", buf, prefixlen, - valid_str ? "for " : "forever", valid_str ?: ""); - else { - /* An address appeared that we did not request */ - r = address_add_foreign(link, family, &in_addr, prefixlen, &address); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen); - return 0; - } else - log_link_debug(link, "Adding address: %s/%u (valid %s%s)", buf, prefixlen, - valid_str ? "for " : "forever", valid_str ?: ""); - } - - address_update(address, flags, scope, &cinfo); - - break; - - case RTM_DELADDR: - - if (address) { - log_link_debug(link, "Removing address: %s/%u (valid %s%s)", buf, prefixlen, - valid_str ? "for " : "forever", valid_str ?: ""); - address_drop(address); - } else - log_link_warning(link, "Removing non-existent address: %s/%u (valid %s%s)", buf, prefixlen, - valid_str ? "for " : "forever", valid_str ?: ""); - - break; - default: - assert_not_reached("Received invalid RTNL message type"); - } - - return 1; -} - -static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) { - Manager *m = userdata; - Link *link = NULL; - NetDev *netdev = NULL; - uint16_t type; - const char *name; - int r, ifindex; - - assert(rtnl); - assert(message); - assert(m); - - if (sd_netlink_message_is_error(message)) { - r = sd_netlink_message_get_errno(message); - if (r < 0) - log_warning_errno(r, "rtnl: Could not receive link: %m"); - - return 0; - } - - r = sd_netlink_message_get_type(message, &type); - 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 from link: %m"); - return 0; - } else if (ifindex <= 0) { - log_warning("rtnl: received link message with invalid ifindex: %d", ifindex); - return 0; - } - - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name); - if (r < 0) { - log_warning_errno(r, "rtnl: Received link message without ifname: %m"); - return 0; - } - - (void) link_get(m, ifindex, &link); - (void) netdev_get(m, name, &netdev); - - switch (type) { - case RTM_NEWLINK: - if (!link) { - /* link is new, so add it */ - r = link_add(m, message, &link); - if (r < 0) { - log_warning_errno(r, "Could not add new link: %m"); - return 0; - } - } - - if (netdev) { - /* netdev exists, so make sure the ifindex matches */ - r = netdev_set_ifindex(netdev, message); - if (r < 0) { - log_warning_errno(r, "Could not set ifindex on netdev: %m"); - return 0; - } - } - - r = link_update(link, message); - if (r < 0) - return 0; - - break; - - case RTM_DELLINK: - link_drop(link); - netdev_drop(netdev); - - break; - - default: - assert_not_reached("Received invalid RTNL message type."); - } - - return 1; -} - -static int systemd_netlink_fd(void) { - int n, fd, rtnl_fd = -EINVAL; - - n = sd_listen_fds(true); - if (n <= 0) - return -EINVAL; - - for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd ++) { - if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { - if (rtnl_fd >= 0) - return -EINVAL; - - rtnl_fd = fd; - } - } - - return rtnl_fd; -} - -static int manager_connect_rtnl(Manager *m) { - int fd, r; - - assert(m); - - fd = systemd_netlink_fd(); - if (fd < 0) - r = sd_netlink_open(&m->rtnl); - else - r = sd_netlink_open_fd(&m->rtnl, fd); - if (r < 0) - return r; - - r = sd_netlink_inc_rcvbuf(m->rtnl, RCVBUF_SIZE); - if (r < 0) - return r; - - r = sd_netlink_attach_event(m->rtnl, m->event, 0); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, &manager_rtnl_process_link, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, &manager_rtnl_process_link, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_NEWROUTE, &manager_rtnl_process_route, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_DELROUTE, &manager_rtnl_process_route, m); - if (r < 0) - return r; - - return 0; -} - -static int ordered_set_put_in_addr(OrderedSet *s, const struct in_addr *address) { - char *p; - int r; - - assert(s); - - r = in_addr_to_string(AF_INET, (const union in_addr_union*) address, &p); - if (r < 0) - return r; - - r = ordered_set_consume(s, p); - if (r == -EEXIST) - return 0; - - return r; -} - -static int ordered_set_put_in_addrv(OrderedSet *s, const struct in_addr *addresses, int n) { - int r, i, c = 0; - - assert(s); - assert(n <= 0 || addresses); - - for (i = 0; i < n; i++) { - r = ordered_set_put_in_addr(s, addresses+i); - if (r < 0) - return r; - - c += r; - } - - return c; -} - -static void print_string_set(FILE *f, const char *field, OrderedSet *s) { - bool space = false; - Iterator i; - char *p; - - if (ordered_set_isempty(s)) - return; - - fputs(field, f); - - ORDERED_SET_FOREACH(p, s, i) - fputs_with_space(f, p, NULL, &space); - - fputc('\n', f); -} - -static int manager_save(Manager *m) { - _cleanup_ordered_set_free_free_ OrderedSet *dns = NULL, *ntp = NULL, *search_domains = NULL, *route_domains = NULL; - Link *link; - Iterator i; - _cleanup_free_ char *temp_path = NULL; - _cleanup_fclose_ FILE *f = NULL; - LinkOperationalState operstate = LINK_OPERSTATE_OFF; - const char *operstate_str; - int r; - - assert(m); - assert(m->state_file); - - /* We add all NTP and DNS server to a set, to filter out duplicates */ - dns = ordered_set_new(&string_hash_ops); - if (!dns) - return -ENOMEM; - - ntp = ordered_set_new(&string_hash_ops); - if (!ntp) - return -ENOMEM; - - search_domains = ordered_set_new(&dns_name_hash_ops); - if (!search_domains) - return -ENOMEM; - - route_domains = ordered_set_new(&dns_name_hash_ops); - if (!route_domains) - return -ENOMEM; - - HASHMAP_FOREACH(link, m->links, i) { - if (link->flags & IFF_LOOPBACK) - continue; - - if (link->operstate > operstate) - operstate = link->operstate; - - if (!link->network) - continue; - - /* First add the static configured entries */ - r = ordered_set_put_strdupv(dns, link->network->dns); - if (r < 0) - return r; - - r = ordered_set_put_strdupv(ntp, link->network->ntp); - if (r < 0) - return r; - - r = ordered_set_put_strdupv(search_domains, link->network->search_domains); - if (r < 0) - return r; - - r = ordered_set_put_strdupv(route_domains, link->network->route_domains); - if (r < 0) - return r; - - if (!link->dhcp_lease) - continue; - - /* Secondly, add the entries acquired via DHCP */ - if (link->network->dhcp_use_dns) { - const struct in_addr *addresses; - - r = sd_dhcp_lease_get_dns(link->dhcp_lease, &addresses); - if (r > 0) { - r = ordered_set_put_in_addrv(dns, addresses, r); - if (r < 0) - return r; - } else if (r < 0 && r != -ENODATA) - return r; - } - - if (link->network->dhcp_use_ntp) { - const struct in_addr *addresses; - - r = sd_dhcp_lease_get_ntp(link->dhcp_lease, &addresses); - if (r > 0) { - r = ordered_set_put_in_addrv(ntp, addresses, r); - if (r < 0) - return r; - } else if (r < 0 && r != -ENODATA) - return r; - } - - if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) { - const char *domainname; - - r = sd_dhcp_lease_get_domainname(link->dhcp_lease, &domainname); - if (r >= 0) { - - if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) - r = ordered_set_put_strdup(search_domains, domainname); - else - r = ordered_set_put_strdup(route_domains, domainname); - - if (r < 0) - return r; - } else if (r != -ENODATA) - return r; - } - } - - operstate_str = link_operstate_to_string(operstate); - assert(operstate_str); - - r = fopen_temporary(m->state_file, &f, &temp_path); - if (r < 0) - return r; - - fchmod(fileno(f), 0644); - - fprintf(f, - "# This is private data. Do not parse.\n" - "OPER_STATE=%s\n", operstate_str); - - print_string_set(f, "DNS=", dns); - print_string_set(f, "NTP=", ntp); - print_string_set(f, "DOMAINS=", search_domains); - print_string_set(f, "ROUTE_DOMAINS=", route_domains); - - r = fflush_and_check(f); - if (r < 0) - goto fail; - - if (rename(temp_path, m->state_file) < 0) { - r = -errno; - goto fail; - } - - if (m->operational_state != operstate) { - m->operational_state = operstate; - r = manager_send_changed(m, "OperationalState", NULL); - if (r < 0) - log_error_errno(r, "Could not emit changed OperationalState: %m"); - } - - m->dirty = false; - - return 0; - -fail: - (void) unlink(m->state_file); - (void) unlink(temp_path); - - return log_error_errno(r, "Failed to save network state to %s: %m", m->state_file); -} - -static int manager_dirty_handler(sd_event_source *s, void *userdata) { - Manager *m = userdata; - Link *link; - Iterator i; - int r; - - assert(m); - - if (m->dirty) - manager_save(m); - - SET_FOREACH(link, m->dirty_links, i) { - r = link_save(link); - if (r >= 0) - link_clean(link); - } - - return 1; -} - -int manager_new(Manager **ret) { - _cleanup_manager_free_ Manager *m = NULL; - int r; - - m = new0(Manager, 1); - if (!m) - return -ENOMEM; - - m->state_file = strdup("/run/systemd/netif/state"); - if (!m->state_file) - return -ENOMEM; - - r = sd_event_default(&m->event); - if (r < 0) - return r; - - sd_event_set_watchdog(m->event, true); - - sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); - sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); - - r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); - if (r < 0) - return r; - - r = manager_connect_rtnl(m); - if (r < 0) - return r; - - r = manager_connect_udev(m); - if (r < 0) - return r; - - m->netdevs = hashmap_new(&string_hash_ops); - if (!m->netdevs) - return -ENOMEM; - - LIST_HEAD_INIT(m->networks); - - r = setup_default_address_pool(m); - if (r < 0) - return r; - - m->duid.type = DUID_TYPE_EN; - - *ret = m; - m = NULL; - - return 0; -} - -void manager_free(Manager *m) { - Network *network; - NetDev *netdev; - Link *link; - AddressPool *pool; - - if (!m) - return; - - free(m->state_file); - - while ((link = hashmap_first(m->links))) - link_unref(link); - hashmap_free(m->links); - - while ((network = m->networks)) - network_free(network); - - hashmap_free(m->networks_by_name); - - while ((netdev = hashmap_first(m->netdevs))) - netdev_unref(netdev); - hashmap_free(m->netdevs); - - while ((pool = m->address_pools)) - address_pool_free(pool); - - sd_netlink_unref(m->rtnl); - sd_event_unref(m->event); - - sd_event_source_unref(m->udev_event_source); - udev_monitor_unref(m->udev_monitor); - udev_unref(m->udev); - - sd_bus_unref(m->bus); - sd_bus_slot_unref(m->prepare_for_sleep_slot); - sd_event_source_unref(m->bus_retry_event_source); - - free(m); -} - -static bool manager_check_idle(void *userdata) { - Manager *m = userdata; - Link *link; - Iterator i; - - assert(m); - - /* Check whether we are idle now. The only case when we decide to be idle is when there's only a loopback - * device around, for which we have no configuration, and which already left the PENDING state. In all other - * cases we are not idle. */ - - HASHMAP_FOREACH(link, m->links, i) { - /* We are not woken on udev activity, so let's just wait for the pending udev event */ - if (link->state == LINK_STATE_PENDING) - return false; - - if ((link->flags & IFF_LOOPBACK) == 0) - return false; - - if (link->network) - return false; - } - - return true; -} - -int manager_run(Manager *m) { - Link *link; - Iterator i; - - assert(m); - - /* The dirty handler will deal with future serialization, but the first one - must be done explicitly. */ - - manager_save(m); - - HASHMAP_FOREACH(link, m->links, i) - link_save(link); - - if (m->bus) - return bus_event_loop_with_idle( - m->event, - m->bus, - "org.freedesktop.network1", - DEFAULT_EXIT_USEC, - manager_check_idle, - m); - else - /* failed to connect to the bus, so we lose exit-on-idle logic, - this should not happen except if dbus is not around at all */ - return sd_event_loop(m->event); -} - -int manager_load_config(Manager *m) { - int r; - - /* update timestamp */ - paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, true); - - r = netdev_load(m); - if (r < 0) - return r; - - r = network_load(m); - if (r < 0) - return r; - - return 0; -} - -bool manager_should_reload(Manager *m) { - return paths_check_timestamp(network_dirs, &m->network_dirs_ts_usec, false); -} - -int manager_rtnl_enumerate_links(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *link; - int r; - - assert(m); - assert(m->rtnl); - - r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); - if (r < 0) - return r; - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (link = reply; link; link = sd_netlink_message_next(link)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_link(m->rtnl, link, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; -} - -int manager_rtnl_enumerate_addresses(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *addr; - int r; - - assert(m); - assert(m->rtnl); - - r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, 0, 0); - if (r < 0) - return r; - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (addr = reply; addr; addr = sd_netlink_message_next(addr)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_address(m->rtnl, addr, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; -} - -int manager_rtnl_enumerate_routes(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *route; - int r; - - assert(m); - assert(m->rtnl); - - r = sd_rtnl_message_new_route(m->rtnl, &req, RTM_GETROUTE, 0, 0); - if (r < 0) - return r; - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (route = reply; route; route = sd_netlink_message_next(route)) { - int k; - - m->enumerating = true; - - k = manager_rtnl_process_route(m->rtnl, route, m); - if (k < 0) - r = k; - - m->enumerating = false; - } - - return r; -} - -int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) { - AddressPool *p; - int r; - - assert(m); - assert(prefixlen > 0); - assert(found); - - LIST_FOREACH(address_pools, p, m->address_pools) { - if (p->family != family) - continue; - - r = address_pool_acquire(p, prefixlen, found); - if (r != 0) - return r; - } - - return 0; -} - -Link* manager_find_uplink(Manager *m, Link *exclude) { - _cleanup_free_ struct local_address *gateways = NULL; - int n, i; - - assert(m); - - /* Looks for a suitable "uplink", via black magic: an - * interface that is up and where the default route with the - * highest priority points to. */ - - n = local_gateways(m->rtnl, 0, AF_UNSPEC, &gateways); - if (n < 0) { - log_warning_errno(n, "Failed to determine list of default gateways: %m"); - return NULL; - } - - for (i = 0; i < n; i++) { - Link *link; - - link = hashmap_get(m->links, INT_TO_PTR(gateways[i].ifindex)); - if (!link) { - log_debug("Weird, found a gateway for a link we don't know. Ignoring."); - continue; - } - - if (link == exclude) - continue; - - if (link->operstate < LINK_OPERSTATE_ROUTABLE) - continue; - - return link; - } - - return NULL; -} - -void manager_dirty(Manager *manager) { - assert(manager); - - /* the serialized state in /run is no longer up-to-date */ - manager->dirty = true; -} diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c deleted file mode 100644 index 4853791aa5..0000000000 --- a/src/network/networkd-ndisc.c +++ /dev/null @@ -1,701 +0,0 @@ -/*** - This file is part of systemd. - - Copyright (C) 2014 Intel Corporation. All rights reserved. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/icmp6.h> - -#include "sd-ndisc.h" - -#include "networkd.h" -#include "networkd-ndisc.h" - -#define NDISC_DNSSL_MAX 64U -#define NDISC_RDNSS_MAX 64U - -static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_link_unref_ Link *link = userdata; - int r; - - assert(link); - assert(link->ndisc_messages > 0); - - link->ndisc_messages--; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) { - log_link_error_errno(link, r, "Could not set NDisc route or address: %m"); - link_enter_failed(link); - } - - if (link->ndisc_messages == 0) { - link->ndisc_configured = true; - link_check_ready(link); - } - - return 1; -} - -static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) { - _cleanup_route_free_ Route *route = NULL; - struct in6_addr gateway; - uint16_t lifetime; - unsigned preference; - usec_t time_now; - int r; - Address *address; - Iterator i; - - assert(link); - assert(rt); - - r = sd_ndisc_router_get_lifetime(rt, &lifetime); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); - return; - } - if (lifetime == 0) /* not a default router */ - return; - - r = sd_ndisc_router_get_address(rt, &gateway); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); - return; - } - - SET_FOREACH(address, link->addresses, i) { - if (!memcmp(&gateway, &address->in_addr.in6, - sizeof(address->in_addr.in6))) { - char buffer[INET6_ADDRSTRLEN]; - - log_link_debug(link, "No NDisc route added, gateway %s matches local address", - inet_ntop(AF_INET6, - &address->in_addr.in6, - buffer, sizeof(buffer))); - return; - } - } - - SET_FOREACH(address, link->addresses_foreign, i) { - if (!memcmp(&gateway, &address->in_addr.in6, - sizeof(address->in_addr.in6))) { - char buffer[INET6_ADDRSTRLEN]; - - log_link_debug(link, "No NDisc route added, gateway %s matches local address", - inet_ntop(AF_INET6, - &address->in_addr.in6, - buffer, sizeof(buffer))); - return; - } - } - - r = sd_ndisc_router_get_preference(rt, &preference); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); - return; - } - - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); - return; - } - - r = route_new(&route); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate route: %m"); - return; - } - - route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; - route->protocol = RTPROT_RA; - route->pref = preference; - route->gw.in6 = gateway; - route->lifetime = time_now + lifetime * USEC_PER_SEC; - - r = route_configure(route, link, ndisc_netlink_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set default route: %m"); - link_enter_failed(link); - return; - } - - link->ndisc_messages++; -} - -static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) { - _cleanup_address_free_ Address *address = NULL; - uint32_t lifetime_valid, lifetime_preferred; - unsigned prefixlen; - int r; - - assert(link); - assert(rt); - - r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix length: %m"); - return; - } - - r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m"); - return; - } - - r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m"); - return; - } - - r = address_new(&address); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate address: %m"); - return; - } - - address->family = AF_INET6; - r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix address: %m"); - return; - } - - if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0) - memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8); - else { - /* see RFC4291 section 2.5.1 */ - address->in_addr.in6.s6_addr[8] = link->mac.ether_addr_octet[0]; - address->in_addr.in6.s6_addr[8] ^= 1 << 1; - address->in_addr.in6.s6_addr[9] = link->mac.ether_addr_octet[1]; - address->in_addr.in6.s6_addr[10] = link->mac.ether_addr_octet[2]; - address->in_addr.in6.s6_addr[11] = 0xff; - address->in_addr.in6.s6_addr[12] = 0xfe; - address->in_addr.in6.s6_addr[13] = link->mac.ether_addr_octet[3]; - address->in_addr.in6.s6_addr[14] = link->mac.ether_addr_octet[4]; - address->in_addr.in6.s6_addr[15] = link->mac.ether_addr_octet[5]; - } - address->prefixlen = prefixlen; - address->flags = IFA_F_NOPREFIXROUTE|IFA_F_MANAGETEMPADDR; - address->cinfo.ifa_prefered = lifetime_preferred; - address->cinfo.ifa_valid = lifetime_valid; - - r = address_configure(address, link, ndisc_netlink_handler, true); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set SLAAC address: %m"); - link_enter_failed(link); - return; - } - - link->ndisc_messages++; -} - -static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) { - _cleanup_route_free_ Route *route = NULL; - usec_t time_now; - uint32_t lifetime; - unsigned prefixlen; - int r; - - assert(link); - assert(rt); - - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); - return; - } - - r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix length: %m"); - return; - } - - r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix lifetime: %m"); - return; - } - - r = route_new(&route); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate route: %m"); - return; - } - - route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; - route->protocol = RTPROT_RA; - route->flags = RTM_F_PREFIX; - route->dst_prefixlen = prefixlen; - route->lifetime = time_now + lifetime * USEC_PER_SEC; - - r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get prefix address: %m"); - return; - } - - r = route_configure(route, link, ndisc_netlink_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set prefix route: %m"); - link_enter_failed(link); - return; - } - - link->ndisc_messages++; -} - -static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) { - _cleanup_route_free_ Route *route = NULL; - struct in6_addr gateway; - uint32_t lifetime; - unsigned preference, prefixlen; - usec_t time_now; - int r; - - assert(link); - - r = sd_ndisc_router_route_get_lifetime(rt, &lifetime); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); - return; - } - if (lifetime == 0) - return; - - r = sd_ndisc_router_get_address(rt, &gateway); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m"); - return; - } - - r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get route prefix length: %m"); - return; - } - - r = sd_ndisc_router_route_get_preference(rt, &preference); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m"); - return; - } - - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); - return; - } - - r = route_new(&route); - if (r < 0) { - log_link_error_errno(link, r, "Could not allocate route: %m"); - return; - } - - route->family = AF_INET6; - route->table = link->network->ipv6_accept_ra_route_table; - route->protocol = RTPROT_RA; - route->pref = preference; - route->gw.in6 = gateway; - route->dst_prefixlen = prefixlen; - route->lifetime = time_now + lifetime * USEC_PER_SEC; - - r = sd_ndisc_router_route_get_address(rt, &route->dst.in6); - if (r < 0) { - log_link_error_errno(link, r, "Failed to get route address: %m"); - return; - } - - r = route_configure(route, link, ndisc_netlink_handler); - if (r < 0) { - log_link_warning_errno(link, r, "Could not set additional route: %m"); - link_enter_failed(link); - return; - } - - link->ndisc_messages++; -} - -static void ndisc_rdnss_hash_func(const void *p, struct siphash *state) { - const NDiscRDNSS *x = p; - - siphash24_compress(&x->address, sizeof(x->address), state); -} - -static int ndisc_rdnss_compare_func(const void *_a, const void *_b) { - const NDiscRDNSS *a = _a, *b = _b; - - return memcmp(&a->address, &b->address, sizeof(a->address)); -} - -static const struct hash_ops ndisc_rdnss_hash_ops = { - .hash = ndisc_rdnss_hash_func, - .compare = ndisc_rdnss_compare_func -}; - -static void ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) { - uint32_t lifetime; - const struct in6_addr *a; - usec_t time_now; - int i, n, r; - - assert(link); - assert(rt); - - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); - return; - } - - r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); - return; - } - - n = sd_ndisc_router_rdnss_get_addresses(rt, &a); - if (n < 0) { - log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m"); - return; - } - - for (i = 0; i < n; i++) { - NDiscRDNSS d = { - .address = a[i] - }, *x; - - if (lifetime == 0) { - (void) set_remove(link->ndisc_rdnss, &d); - link_dirty(link); - continue; - } - - x = set_get(link->ndisc_rdnss, &d); - if (x) { - x->valid_until = time_now + lifetime * USEC_PER_SEC; - continue; - } - - ndisc_vacuum(link); - - if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) { - log_link_warning(link, "Too many RDNSS records per link, ignoring."); - continue; - } - - r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops); - if (r < 0) { - log_oom(); - return; - } - - x = new0(NDiscRDNSS, 1); - if (!x) { - log_oom(); - return; - } - - x->address = a[i]; - x->valid_until = time_now + lifetime * USEC_PER_SEC; - - r = set_put(link->ndisc_rdnss, x); - if (r < 0) { - free(x); - log_oom(); - return; - } - - assert(r > 0); - link_dirty(link); - } -} - -static void ndisc_dnssl_hash_func(const void *p, struct siphash *state) { - const NDiscDNSSL *x = p; - - siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state); -} - -static int ndisc_dnssl_compare_func(const void *_a, const void *_b) { - const NDiscDNSSL *a = _a, *b = _b; - - return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b)); -} - -static const struct hash_ops ndisc_dnssl_hash_ops = { - .hash = ndisc_dnssl_hash_func, - .compare = ndisc_dnssl_compare_func -}; - -static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) { - _cleanup_strv_free_ char **l = NULL; - uint32_t lifetime; - usec_t time_now; - char **i; - int r; - - assert(link); - assert(rt); - - r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA timestamp: %m"); - return; - } - - r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m"); - return; - } - - r = sd_ndisc_router_dnssl_get_domains(rt, &l); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m"); - return; - } - - STRV_FOREACH(i, l) { - _cleanup_free_ NDiscDNSSL *s; - NDiscDNSSL *x; - - s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1); - if (!s) { - log_oom(); - return; - } - - strcpy(NDISC_DNSSL_DOMAIN(s), *i); - - if (lifetime == 0) { - (void) set_remove(link->ndisc_dnssl, s); - link_dirty(link); - continue; - } - - x = set_get(link->ndisc_dnssl, s); - if (x) { - x->valid_until = time_now + lifetime * USEC_PER_SEC; - continue; - } - - ndisc_vacuum(link); - - if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) { - log_link_warning(link, "Too many DNSSL records per link, ignoring."); - continue; - } - - r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops); - if (r < 0) { - log_oom(); - return; - } - - s->valid_until = time_now + lifetime * USEC_PER_SEC; - - r = set_put(link->ndisc_dnssl, s); - if (r < 0) { - log_oom(); - return; - } - - s = NULL; - assert(r > 0); - link_dirty(link); - } -} - -static void ndisc_router_process_options(Link *link, sd_ndisc_router *rt) { - int r; - - assert(link); - assert(rt); - - r = sd_ndisc_router_option_rewind(rt); - for (;;) { - uint8_t type; - - if (r < 0) { - log_link_warning_errno(link, r, "Failed to iterate through options: %m"); - return; - } - if (r == 0) /* EOF */ - break; - - r = sd_ndisc_router_option_get_type(rt, &type); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA option type: %m"); - return; - } - - switch (type) { - - case SD_NDISC_OPTION_PREFIX_INFORMATION: { - uint8_t flags; - - r = sd_ndisc_router_prefix_get_flags(rt, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m"); - return; - } - - if (flags & ND_OPT_PI_FLAG_ONLINK) - ndisc_router_process_onlink_prefix(link, rt); - if (flags & ND_OPT_PI_FLAG_AUTO) - ndisc_router_process_autonomous_prefix(link, rt); - - break; - } - - case SD_NDISC_OPTION_ROUTE_INFORMATION: - ndisc_router_process_route(link, rt); - break; - - case SD_NDISC_OPTION_RDNSS: - ndisc_router_process_rdnss(link, rt); - break; - - case SD_NDISC_OPTION_DNSSL: - ndisc_router_process_dnssl(link, rt); - break; - } - - r = sd_ndisc_router_option_next(rt); - } -} - -static void ndisc_router_handler(Link *link, sd_ndisc_router *rt) { - uint64_t flags; - int r; - - assert(link); - assert(link->network); - assert(link->manager); - assert(rt); - - r = sd_ndisc_router_get_flags(rt, &flags); - if (r < 0) { - log_link_warning_errno(link, r, "Failed to get RA flags: %m"); - return; - } - - if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) { - /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */ - r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED)); - if (r < 0 && r != -EBUSY) - log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m"); - else - log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request"); - } - - ndisc_router_process_default(link, rt); - ndisc_router_process_options(link, rt); -} - -static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) { - Link *link = userdata; - - assert(link); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return; - - switch (event) { - - case SD_NDISC_EVENT_ROUTER: - ndisc_router_handler(link, rt); - break; - - case SD_NDISC_EVENT_TIMEOUT: - link->ndisc_configured = true; - link_check_ready(link); - - break; - default: - log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event); - } -} - -int ndisc_configure(Link *link) { - int r; - - assert(link); - - r = sd_ndisc_new(&link->ndisc); - if (r < 0) - return r; - - r = sd_ndisc_attach_event(link->ndisc, NULL, 0); - if (r < 0) - return r; - - r = sd_ndisc_set_mac(link->ndisc, &link->mac); - if (r < 0) - return r; - - r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex); - if (r < 0) - return r; - - r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link); - if (r < 0) - return r; - - return 0; -} - -void ndisc_vacuum(Link *link) { - NDiscRDNSS *r; - NDiscDNSSL *d; - Iterator i; - usec_t time_now; - - assert(link); - - /* Removes all RDNSS and DNSSL entries whose validity time has passed */ - - time_now = now(clock_boottime_or_monotonic()); - - SET_FOREACH(r, link->ndisc_rdnss, i) - if (r->valid_until < time_now) { - free(set_remove(link->ndisc_rdnss, r)); - link_dirty(link); - } - - SET_FOREACH(d, link->ndisc_dnssl, i) - if (d->valid_until < time_now) { - free(set_remove(link->ndisc_dnssl, d)); - link_dirty(link); - } -} - -void ndisc_flush(Link *link) { - assert(link); - - /* Removes all RDNSS and DNSSL entries, without exception */ - - link->ndisc_rdnss = set_free_free(link->ndisc_rdnss); - link->ndisc_dnssl = set_free_free(link->ndisc_dnssl); -} diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h deleted file mode 100644 index 127126190e..0000000000 --- a/src/network/networkd-ndisc.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd-link.h" - -typedef struct NDiscRDNSS { - usec_t valid_until; - struct in6_addr address; -} NDiscRDNSS; - -typedef struct NDiscDNSSL { - usec_t valid_until; - /* The domain name follows immediately. */ -} NDiscDNSSL; - -static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) { - return ((char*) n) + ALIGN(sizeof(NDiscDNSSL)); -} - -int ndisc_configure(Link *link); -void ndisc_vacuum(Link *link); -void ndisc_flush(Link *link); diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c deleted file mode 100644 index 46d1669337..0000000000 --- a/src/network/networkd-netdev-bond.c +++ /dev/null @@ -1,444 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - Copyright 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if_bonding.h> - -#include "sd-netlink.h" - -#include "alloc-util.h" -#include "conf-parser.h" -#include "extract-word.h" -#include "missing.h" -#include "networkd-netdev-bond.h" -#include "string-table.h" -#include "string-util.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", - [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor", - [NETDEV_BOND_MODE_BROADCAST] = "broadcast", - [NETDEV_BOND_MODE_802_3AD] = "802.3ad", - [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb", - [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb", -}; - -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", - [NETDEV_BOND_XMIT_HASH_POLICY_LAYER23] = "layer2+3", - [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23] = "encap2+3", - [NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34] = "encap3+4", -}; - -DEFINE_STRING_TABLE_LOOKUP(bond_xmit_hash_policy, BondXmitHashPolicy); -DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_xmit_hash_policy, - bond_xmit_hash_policy, - BondXmitHashPolicy, - "Failed to parse bond transmit hash policy") - -static const char* const bond_lacp_rate_table[_NETDEV_BOND_LACP_RATE_MAX] = { - [NETDEV_BOND_LACP_RATE_SLOW] = "slow", - [NETDEV_BOND_LACP_RATE_FAST] = "fast", -}; - -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: - return BOND_MODE_ROUNDROBIN; - case NETDEV_BOND_MODE_ACTIVE_BACKUP: - return BOND_MODE_ACTIVEBACKUP; - case NETDEV_BOND_MODE_BALANCE_XOR: - return BOND_MODE_XOR; - case NETDEV_BOND_MODE_BROADCAST: - return BOND_MODE_BROADCAST; - case NETDEV_BOND_MODE_802_3AD: - return BOND_MODE_8023AD; - case NETDEV_BOND_MODE_BALANCE_TLB: - return BOND_MODE_TLB; - case NETDEV_BOND_MODE_BALANCE_ALB: - return BOND_MODE_ALB; - default: - return (uint8_t) -1; - } -} - -static uint8_t bond_xmit_hash_policy_to_kernel(BondXmitHashPolicy policy) { - switch (policy) { - case NETDEV_BOND_XMIT_HASH_POLICY_LAYER2: - return BOND_XMIT_POLICY_LAYER2; - case NETDEV_BOND_XMIT_HASH_POLICY_LAYER34: - return BOND_XMIT_POLICY_LAYER34; - case NETDEV_BOND_XMIT_HASH_POLICY_LAYER23: - return BOND_XMIT_POLICY_LAYER23; - case NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23: - return BOND_XMIT_POLICY_ENCAP23; - case NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34: - return BOND_XMIT_POLICY_ENCAP34; - default: - return (uint8_t) -1; - } -} - -static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Bond *b; - ArpIpTarget *target = NULL; - int r, i = 0; - - assert(netdev); - assert(!link); - assert(m); - - b = BOND(netdev); - - assert(b); - - if (b->mode != _NETDEV_BOND_MODE_INVALID) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_MODE, - bond_mode_to_kernel(b->mode)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MODE attribute: %m"); - } - - if (b->xmit_hash_policy != _NETDEV_BOND_XMIT_HASH_POLICY_INVALID) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_XMIT_HASH_POLICY, - bond_xmit_hash_policy_to_kernel(b->xmit_hash_policy)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_XMIT_HASH_POLICY attribute: %m"); - } - - if (b->lacp_rate != _NETDEV_BOND_LACP_RATE_INVALID && - b->mode == NETDEV_BOND_MODE_802_3AD) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_LACP_RATE, b->lacp_rate ); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m"); - } - - if (b->miimon != 0) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_MIIMON, b->miimon / USEC_PER_MSEC); - if (r < 0) - log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_BOND_MIIMON attribute: %m"); - } - - if (b->downdelay != 0) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_DOWNDELAY, b->downdelay / USEC_PER_MSEC); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_DOWNDELAY attribute: %m"); - } - - if (b->updelay != 0) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_UPDELAY, b->updelay / USEC_PER_MSEC); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_UPDELAY attribute: %m"); - } - - if (b->arp_interval != 0) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_INTERVAL, b->arp_interval / USEC_PER_MSEC); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_INTERVAL attribute: %m"); - - if ((b->lp_interval >= LEARNING_PACKETS_INTERVAL_MIN_SEC) && - (b->lp_interval <= LEARNING_PACKETS_INTERVAL_MAX_SEC)) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_LP_INTERVAL, b->lp_interval / USEC_PER_SEC); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_LP_INTERVAL attribute: %m"); - } - } - - if (b->ad_select != _NETDEV_BOND_AD_SELECT_INVALID && - b->mode == NETDEV_BOND_MODE_802_3AD) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_AD_SELECT, b->ad_select); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_SELECT attribute: %m"); - } - - if (b->fail_over_mac != _NETDEV_BOND_FAIL_OVER_MAC_INVALID && - b->mode == NETDEV_BOND_MODE_ACTIVE_BACKUP) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_FAIL_OVER_MAC, b->fail_over_mac); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_FAIL_OVER_MAC attribute: %m"); - } - - if (b->arp_validate != _NETDEV_BOND_ARP_VALIDATE_INVALID) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_VALIDATE, b->arp_validate); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m"); - } - - if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); - } - - if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_PRIMARY_RESELECT, b->primary_reselect); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PRIMARY_RESELECT attribute: %m"); - } - - if (b->resend_igmp <= RESEND_IGMP_MAX) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_RESEND_IGMP, b->resend_igmp); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_RESEND_IGMP attribute: %m"); - } - - if (b->packets_per_slave <= PACKETS_PER_SLAVE_MAX && - b->mode == NETDEV_BOND_MODE_BALANCE_RR) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_PACKETS_PER_SLAVE, b->packets_per_slave); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PACKETS_PER_SLAVE attribute: %m"); - } - - if (b->num_grat_arp <= GRATUITOUS_ARP_MAX) { - r = sd_netlink_message_append_u8(m, IFLA_BOND_NUM_PEER_NOTIF, b->num_grat_arp); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_NUM_PEER_NOTIF attribute: %m"); - } - - if (b->min_links != 0) { - r = sd_netlink_message_append_u32(m, IFLA_BOND_MIN_LINKS, b->min_links); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_MIN_LINKS attribute: %m"); - } - - r = sd_netlink_message_append_u8(m, IFLA_BOND_ALL_SLAVES_ACTIVE, b->all_slaves_active); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ALL_SLAVES_ACTIVE attribute: %m"); - - if (b->arp_interval > 0) { - if (b->n_arp_ip_targets > 0) { - - r = sd_netlink_message_open_container(m, IFLA_BOND_ARP_IP_TARGET); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not open contaniner IFLA_BOND_ARP_IP_TARGET : %m"); - - LIST_FOREACH(arp_ip_target, target, b->arp_ip_targets) { - r = sd_netlink_message_append_u32(m, i++, target->ip.in.s_addr); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m"); - } - - r = sd_netlink_message_close_container(m); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not close contaniner IFLA_BOND_ARP_IP_TARGET : %m"); - } - } - - 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; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - for (;;) { - _cleanup_free_ ArpIpTarget *buffer = NULL; - _cleanup_free_ char *n = NULL; - int f; - - r = extract_first_word(&rvalue, &n, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Bond ARP ip target address, ignoring assignment: %s", rvalue); - return 0; - } - - if (r == 0) - break; - - 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, r, "Bond ARP ip target address is invalid, ignoring assignment: %s", n); - return 0; - } - - if (f != AF_INET) { - log_syntax(unit, LOG_ERR, filename, line, 0, "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 > NETDEV_BOND_ARP_TARGETS_MAX) - log_syntax(unit, LOG_WARNING, filename, line, 0, - "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d", - b->n_arp_ip_targets, NETDEV_BOND_ARP_TARGETS_MAX); - - return 0; -} - -static void bond_done(NetDev *netdev) { - ArpIpTarget *t = NULL, *n = NULL; - Bond *b; - - assert(netdev); - - b = BOND(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; - - assert(netdev); - - b = BOND(netdev); - - assert(b); - - 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 deleted file mode 100644 index b941edb344..0000000000 --- a/src/network/networkd-netdev-bond.h +++ /dev/null @@ -1,172 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "in-addr-util.h" -#include "list.h" - -#include "networkd-netdev.h" - -/* - * Maximum number of targets supported by the kernel for a single - * bond netdev. - */ -#define NETDEV_BOND_ARP_TARGETS_MAX 16 - -typedef enum BondMode { - NETDEV_BOND_MODE_BALANCE_RR, - NETDEV_BOND_MODE_ACTIVE_BACKUP, - NETDEV_BOND_MODE_BALANCE_XOR, - NETDEV_BOND_MODE_BROADCAST, - NETDEV_BOND_MODE_802_3AD, - NETDEV_BOND_MODE_BALANCE_TLB, - NETDEV_BOND_MODE_BALANCE_ALB, - _NETDEV_BOND_MODE_MAX, - _NETDEV_BOND_MODE_INVALID = -1 -} BondMode; - -typedef enum BondXmitHashPolicy { - NETDEV_BOND_XMIT_HASH_POLICY_LAYER2, - NETDEV_BOND_XMIT_HASH_POLICY_LAYER34, - NETDEV_BOND_XMIT_HASH_POLICY_LAYER23, - NETDEV_BOND_XMIT_HASH_POLICY_ENCAP23, - NETDEV_BOND_XMIT_HASH_POLICY_ENCAP34, - _NETDEV_BOND_XMIT_HASH_POLICY_MAX, - _NETDEV_BOND_XMIT_HASH_POLICY_INVALID = -1 -} BondXmitHashPolicy; - -typedef enum BondLacpRate { - NETDEV_BOND_LACP_RATE_SLOW, - NETDEV_BOND_LACP_RATE_FAST, - _NETDEV_BOND_LACP_RATE_MAX, - _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; - -typedef 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; -} Bond; - -DEFINE_NETDEV_CAST(BOND, Bond); -extern const NetDevVTable bond_vtable; - -const char *bond_mode_to_string(BondMode d) _const_; -BondMode bond_mode_from_string(const char *d) _pure_; - -const char *bond_xmit_hash_policy_to_string(BondXmitHashPolicy d) _const_; -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 deleted file mode 100644 index 002ad94210..0000000000 --- a/src/network/networkd-netdev-bridge.c +++ /dev/null @@ -1,171 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - Copyright 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "missing.h" -#include "netlink-util.h" -#include "networkd.h" -#include "networkd-netdev-bridge.h" - -/* callback for brige netdev's parameter set */ -static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_netdev_unref_ NetDev *netdev = userdata; - int r; - - assert(netdev); - assert(m); - - r = sd_netlink_message_get_errno(m); - if (r < 0) { - log_netdev_warning_errno(netdev, r, "Bridge parameters could not be set: %m"); - return 1; - } - - log_netdev_debug(netdev, "Bridge parameters set success"); - - return 1; -} - -static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - Bridge *b; - int r; - - assert(netdev); - - b = BRIDGE(netdev); - - assert(b); - - r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, netdev->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not allocate RTM_SETLINK message: %m"); - - r = sd_netlink_message_set_flags(req, NLM_F_REQUEST | NLM_F_ACK); - if (r < 0) - return log_link_error_errno(link, r, "Could not set netlink flags: %m"); - - r = sd_netlink_message_open_container(req, IFLA_LINKINFO); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_PROTINFO attribute: %m"); - - r = sd_netlink_message_open_container_union(req, 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"); - - /* convert to jiffes */ - if (b->forward_delay > 0) { - r = sd_netlink_message_append_u32(req, IFLA_BR_FORWARD_DELAY, usec_to_jiffies(b->forward_delay)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_FORWARD_DELAY attribute: %m"); - } - - if (b->hello_time > 0) { - r = sd_netlink_message_append_u32(req, IFLA_BR_HELLO_TIME, usec_to_jiffies(b->hello_time)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_HELLO_TIME attribute: %m"); - } - - if (b->max_age > 0) { - r = sd_netlink_message_append_u32(req, IFLA_BR_MAX_AGE, usec_to_jiffies(b->max_age)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MAX_AGE attribute: %m"); - } - - if (b->ageing_time > 0) { - r = sd_netlink_message_append_u32(req, IFLA_BR_AGEING_TIME, usec_to_jiffies(b->ageing_time)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_AGEING_TIME attribute: %m"); - } - - if (b->priority > 0) { - r = sd_netlink_message_append_u16(req, IFLA_BR_PRIORITY, b->priority); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m"); - } - - if (b->default_pvid > 0) { - r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m"); - } - - if (b->mcast_querier >= 0) { - r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_QUERIER, b->mcast_querier); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_QUERIER attribute: %m"); - } - - if (b->mcast_snooping >= 0) { - r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_SNOOPING, b->mcast_snooping); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m"); - } - - if (b->vlan_filtering >= 0) { - r = sd_netlink_message_append_u8(req, IFLA_BR_VLAN_FILTERING, b->vlan_filtering); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m"); - } - - if (b->stp >= 0) { - r = sd_netlink_message_append_u32(req, IFLA_BR_STP_STATE, b->stp); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_STP_STATE attribute: %m"); - } - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); - - r = sd_netlink_message_close_container(req); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); - - r = sd_netlink_call_async(netdev->manager->rtnl, req, netdev_bridge_set_handler, netdev, 0, NULL); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not send rtnetlink message: %m"); - - netdev_ref(netdev); - - return r; -} - -static void bridge_init(NetDev *n) { - Bridge *b; - - b = BRIDGE(n); - - assert(b); - - b->mcast_querier = -1; - b->mcast_snooping = -1; - b->vlan_filtering = -1; - b->stp = -1; -} - -const NetDevVTable bridge_vtable = { - .object_size = sizeof(Bridge), - .init = bridge_init, - .sections = "Match\0NetDev\0Bridge\0", - .post_create = netdev_bridge_post_create, - .create_type = NETDEV_CREATE_MASTER, -}; diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h deleted file mode 100644 index 53f72f1ea5..0000000000 --- a/src/network/networkd-netdev-bridge.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd-netdev.h" - -typedef struct Bridge { - NetDev meta; - - int mcast_querier; - int mcast_snooping; - int vlan_filtering; - int stp; - uint16_t priority; - uint16_t default_pvid; - - usec_t forward_delay; - usec_t hello_time; - usec_t max_age; - usec_t ageing_time; -} Bridge; - -DEFINE_NETDEV_CAST(BRIDGE, Bridge); -extern const NetDevVTable bridge_vtable; diff --git a/src/network/networkd-netdev-dummy.c b/src/network/networkd-netdev-dummy.c deleted file mode 100644 index 6617a86c20..0000000000 --- a/src/network/networkd-netdev-dummy.c +++ /dev/null @@ -1,28 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Susant Sahani <susant@redhat.com> - Copyright 2014 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - - -#include "networkd-netdev-dummy.h" - -const NetDevVTable dummy_vtable = { - .object_size = sizeof(Dummy), - .sections = "Match\0NetDev\0", - .create_type = NETDEV_CREATE_INDEPENDENT, -}; diff --git a/src/network/networkd-netdev-dummy.h b/src/network/networkd-netdev-dummy.h deleted file mode 100644 index efe302267e..0000000000 --- a/src/network/networkd-netdev-dummy.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd-netdev.h" - -typedef struct Dummy { - NetDev meta; -} Dummy; - -DEFINE_NETDEV_CAST(DUMMY, Dummy); -extern const NetDevVTable dummy_vtable; diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf deleted file mode 100644 index 323eaa8032..0000000000 --- a/src/network/networkd-netdev-gperf.gperf +++ /dev/null @@ -1,118 +0,0 @@ -%{ -#include <stddef.h> -#include "conf-parser.h" -#include "network-internal.h" -#include "networkd-netdev-bond.h" -#include "networkd-netdev-bridge.h" -#include "networkd-netdev-ipvlan.h" -#include "networkd-netdev-macvlan.h" -#include "networkd-netdev-tunnel.h" -#include "networkd-netdev-tuntap.h" -#include "networkd-netdev-veth.h" -#include "networkd-netdev-vlan.h" -#include "networkd-netdev-vxlan.h" -#include "networkd-netdev-vrf.h" -#include "networkd-netdev.h" -#include "vlan-util.h" -%} -struct ConfigPerfItem; -%null_strings -%language=ANSI-C -%define slot-name section_and_lvalue -%define hash-function-name network_netdev_gperf_hash -%define lookup-function-name network_netdev_gperf_lookup -%readonly-tables -%omit-struct-type -%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_vlanid, 0, offsetof(VLan, id) -MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) -MACVTAP.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.Key, config_parse_tunnel_key, 0, offsetof(Tunnel, key) -Tunnel.InputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, ikey) -Tunnel.OutputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, okey) -Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) -Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode) -Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel) -Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp) -Tunnel.EncapsulationLimit, config_parse_encap_limit, 0, offsetof(Tunnel, encap_limit) -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.UDPChecksum, config_parse_bool, 0, offsetof(VxLan, udpcsum) -VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) -VXLAN.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx) -VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) -VXLAN.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx) -VXLAN.RemoteChecksumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx) -VXLAN.RemoteChecksumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx) -VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing) -VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy) -VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb) -VXLAN.PortRange, config_parse_port_range, 0, 0 -VXLAN.DestinationPort, config_parse_destination_port, 0, offsetof(VxLan, dest_port) -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.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr) -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) -Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time) -Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age) -Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time) -Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay) -Bridge.Priority, config_parse_uint16, 0, offsetof(Bridge, priority) -Bridge.DefaultPVID, config_parse_vlanid, 0, offsetof(Bridge, default_pvid) -Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier) -Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping) -Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering) -Bridge.STP, config_parse_tristate, 0, offsetof(Bridge, stp) -VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table_id) diff --git a/src/network/networkd-netdev-ipvlan.c b/src/network/networkd-netdev-ipvlan.c deleted file mode 100644 index af4177e43a..0000000000 --- a/src/network/networkd-netdev-ipvlan.c +++ /dev/null @@ -1,73 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013-2015 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "conf-parser.h" -#include "networkd-netdev-ipvlan.h" -#include "string-table.h" - -static const char* const ipvlan_mode_table[_NETDEV_IPVLAN_MODE_MAX] = { - [NETDEV_IPVLAN_MODE_L2] = "L2", - [NETDEV_IPVLAN_MODE_L3] = "L3", -}; - -DEFINE_STRING_TABLE_LOOKUP(ipvlan_mode, IPVlanMode); -DEFINE_CONFIG_PARSE_ENUM(config_parse_ipvlan_mode, ipvlan_mode, IPVlanMode, "Failed to parse ipvlan mode"); - -static int netdev_ipvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { - IPVlan *m; - int r; - - assert(netdev); - assert(link); - assert(netdev->ifname); - - m = IPVLAN(netdev); - - assert(m); - - if (m->mode != _NETDEV_IPVLAN_MODE_INVALID) { - r = sd_netlink_message_append_u16(req, IFLA_IPVLAN_MODE, m->mode); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPVLAN_MODE attribute: %m"); - } - - return 0; -} - -static void ipvlan_init(NetDev *n) { - IPVlan *m; - - assert(n); - - m = IPVLAN(n); - - assert(m); - - m->mode = _NETDEV_IPVLAN_MODE_INVALID; -} - -const NetDevVTable ipvlan_vtable = { - .object_size = sizeof(IPVlan), - .init = ipvlan_init, - .sections = "Match\0NetDev\0IPVLAN\0", - .fill_message_create = netdev_ipvlan_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, -}; diff --git a/src/network/networkd-netdev-ipvlan.h b/src/network/networkd-netdev-ipvlan.h deleted file mode 100644 index 10d4079844..0000000000 --- a/src/network/networkd-netdev-ipvlan.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014-2015 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "missing.h" -#include "networkd-netdev.h" - -typedef enum IPVlanMode { - NETDEV_IPVLAN_MODE_L2 = IPVLAN_MODE_L2, - NETDEV_IPVLAN_MODE_L3 = IPVLAN_MODE_L3, - _NETDEV_IPVLAN_MODE_MAX, - _NETDEV_IPVLAN_MODE_INVALID = -1 -} IPVlanMode; - -typedef struct IPVlan { - NetDev meta; - - IPVlanMode mode; -} IPVlan; - -DEFINE_NETDEV_CAST(IPVLAN, IPVlan); -extern const NetDevVTable ipvlan_vtable; - -const char *ipvlan_mode_to_string(IPVlanMode d) _const_; -IPVlanMode ipvlan_mode_from_string(const char *d) _pure_; - -int config_parse_ipvlan_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); diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c deleted file mode 100644 index 48e98aa51b..0000000000 --- a/src/network/networkd-netdev-macvlan.c +++ /dev/null @@ -1,89 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "conf-parser.h" -#include "networkd-netdev-macvlan.h" -#include "string-table.h" - -static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { - [NETDEV_MACVLAN_MODE_PRIVATE] = "private", - [NETDEV_MACVLAN_MODE_VEPA] = "vepa", - [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge", - [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru", -}; - -DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode); -DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode"); - -static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { - MacVlan *m; - int r; - - assert(netdev); - assert(link); - assert(netdev->ifname); - - if (netdev->kind == NETDEV_KIND_MACVLAN) - m = MACVLAN(netdev); - else - m = MACVTAP(netdev); - - assert(m); - - if (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { - r = sd_netlink_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_MACVLAN_MODE attribute: %m"); - } - - return 0; -} - -static void macvlan_init(NetDev *n) { - MacVlan *m; - - assert(n); - - if (n->kind == NETDEV_KIND_MACVLAN) - m = MACVLAN(n); - else - m = MACVTAP(n); - - assert(m); - - m->mode = _NETDEV_MACVLAN_MODE_INVALID; -} - -const NetDevVTable macvtap_vtable = { - .object_size = sizeof(MacVlan), - .init = macvlan_init, - .sections = "Match\0NetDev\0MACVTAP\0", - .fill_message_create = netdev_macvlan_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, -}; - -const NetDevVTable macvlan_vtable = { - .object_size = sizeof(MacVlan), - .init = macvlan_init, - .sections = "Match\0NetDev\0MACVLAN\0", - .fill_message_create = netdev_macvlan_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, -}; diff --git a/src/network/networkd-netdev-macvlan.h b/src/network/networkd-netdev-macvlan.h deleted file mode 100644 index 3663f4f051..0000000000 --- a/src/network/networkd-netdev-macvlan.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct MacVlan MacVlan; - -#include "networkd-netdev.h" - -typedef enum MacVlanMode { - NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE, - NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA, - NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE, - NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU, - _NETDEV_MACVLAN_MODE_MAX, - _NETDEV_MACVLAN_MODE_INVALID = -1 -} MacVlanMode; - -struct MacVlan { - NetDev meta; - - MacVlanMode mode; -}; - -DEFINE_NETDEV_CAST(MACVLAN, MacVlan); -DEFINE_NETDEV_CAST(MACVTAP, MacVlan); -extern const NetDevVTable macvlan_vtable; -extern const NetDevVTable macvtap_vtable; - -const char *macvlan_mode_to_string(MacVlanMode d) _const_; -MacVlanMode macvlan_mode_from_string(const char *d) _pure_; - -int config_parse_macvlan_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); diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c deleted file mode 100644 index 9138ee4511..0000000000 --- a/src/network/networkd-netdev-tunnel.c +++ /dev/null @@ -1,731 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <arpa/inet.h> -#include <net/if.h> -#include <linux/ip.h> -#include <linux/if_tunnel.h> -#include <linux/ip6_tunnel.h> - -#include "sd-netlink.h" - -#include "conf-parser.h" -#include "missing.h" -#include "networkd-link.h" -#include "networkd-netdev-tunnel.h" -#include "parse-util.h" -#include "string-table.h" -#include "string-util.h" -#include "util.h" - -#define DEFAULT_TNL_HOP_LIMIT 64 -#define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF) - -static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = { - [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6", - [NETDEV_IP6_TNL_MODE_IPIP6] = "ipip6", - [NETDEV_IP6_TNL_MODE_ANYIP6] = "any", -}; - -DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode); -DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode"); - -static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = IPIP(netdev); - int r; - - assert(netdev); - assert(link); - assert(m); - assert(t); - assert(IN_SET(t->family, AF_INET, AF_UNSPEC)); - - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); - - return r; -} - -static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = SIT(netdev); - int r; - - assert(netdev); - assert(link); - assert(m); - assert(t); - assert(IN_SET(t->family, AF_INET, AF_UNSPEC)); - - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PMTUDISC, t->pmtudisc); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PMTUDISC attribute: %m"); - - return r; -} - -static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t; - int r; - - assert(netdev); - - if (netdev->kind == NETDEV_KIND_GRE) - t = GRE(netdev); - else - t = GRETAP(netdev); - - assert(t); - assert(IN_SET(t->family, AF_INET, AF_UNSPEC)); - assert(link); - assert(m); - - r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in); - if (r < 0) - log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_GRE_TOS, t->tos); - if (r < 0) - log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TOS attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_GRE_PMTUDISC, t->pmtudisc); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_PMTUDISC attribute: %m"); - - return r; -} - -static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t; - int r; - - assert(netdev); - - if (netdev->kind == NETDEV_KIND_IP6GRE) - t = IP6GRE(netdev); - else - t = IP6GRETAP(netdev); - - assert(t); - assert(t->family == AF_INET6); - assert(link); - assert(m); - - r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LINK attribute: %m"); - - r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_REMOTE attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_GRE_TTL, t->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m"); - - if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { - r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m"); - } - - r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m"); - - return r; -} - -static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) { - uint32_t ikey, okey; - Tunnel *t; - int r; - - assert(link); - assert(m); - - if (netdev->kind == NETDEV_KIND_VTI) - t = VTI(netdev); - else - t = VTI6(netdev); - - assert(t); - - if (t->key != 0) - ikey = okey = htobe32(t->key); - else { - ikey = htobe32(t->ikey); - okey = htobe32(t->okey); - } - - r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m"); - - r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m"); - - return 0; -} - -static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = VTI(netdev); - int r; - - assert(netdev); - assert(link); - assert(m); - assert(t); - assert(t->family == AF_INET); - - r = sd_netlink_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 = netdev_vti_fill_message_key(netdev, link, m); - if (r < 0) - return r; - - r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in); - 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_netlink_message *m) { - Tunnel *t = VTI6(netdev); - int r; - - assert(netdev); - assert(link); - assert(m); - assert(t); - assert(t->family == AF_INET6); - - r = sd_netlink_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 = netdev_vti_fill_message_key(netdev, link, m); - if (r < 0) - return r; - - r = sd_netlink_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_netlink_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; -} - -static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Tunnel *t = IP6TNL(netdev); - uint8_t proto; - int r; - - assert(netdev); - assert(link); - assert(m); - assert(t); - assert(t->family == AF_INET6); - - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m"); - - r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m"); - - r = sd_netlink_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_REMOTE attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m"); - - if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) { - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m"); - } - - if (t->copy_dscp) - t->flags |= IP6_TNL_F_RCV_DSCP_COPY; - - if (t->encap_limit != IPV6_DEFAULT_TNL_ENCAP_LIMIT) { - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m"); - } - - r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m"); - - switch (t->ip6tnl_mode) { - case NETDEV_IP6_TNL_MODE_IP6IP6: - proto = IPPROTO_IPV6; - break; - case NETDEV_IP6_TNL_MODE_IPIP6: - proto = IPPROTO_IPIP; - break; - case NETDEV_IP6_TNL_MODE_ANYIP6: - default: - proto = 0; - break; - } - - r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_MODE attribute: %m"); - - return r; -} - -static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { - Tunnel *t = NULL; - - assert(netdev); - assert(filename); - - switch (netdev->kind) { - case NETDEV_KIND_IPIP: - t = IPIP(netdev); - break; - case NETDEV_KIND_SIT: - t = SIT(netdev); - break; - case NETDEV_KIND_GRE: - t = GRE(netdev); - break; - case NETDEV_KIND_GRETAP: - t = GRETAP(netdev); - break; - case NETDEV_KIND_IP6GRE: - t = IP6GRE(netdev); - break; - case NETDEV_KIND_IP6GRETAP: - t = IP6GRETAP(netdev); - break; - case NETDEV_KIND_VTI: - t = VTI(netdev); - break; - case NETDEV_KIND_VTI6: - t = VTI6(netdev); - break; - case NETDEV_KIND_IP6TNL: - t = IP6TNL(netdev); - break; - default: - assert_not_reached("Invalid tunnel kind"); - } - - assert(t); - - if (t->family != AF_INET && t->family != AF_INET6 && t->family != 0) { - log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); - return -EINVAL; - } - - if (netdev->kind == NETDEV_KIND_IP6TNL) { - if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) { - log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename); - return -EINVAL; - } - } - - return 0; -} - -int config_parse_tunnel_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) { - Tunnel *t = userdata; - union in_addr_union *addr = data, buffer; - int r, f; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - if (streq(rvalue, "any")) { - t->family = 0; - return 0; - } else { - - r = in_addr_from_string_auto(rvalue, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel address is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - if (t->family != AF_UNSPEC && t->family != f) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue); - return 0; - } - } - - t->family = f; - *addr = buffer; - - return 0; -} - -int config_parse_tunnel_key(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) { - union in_addr_union buffer; - Tunnel *t = userdata; - uint32_t k; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = in_addr_from_string(AF_INET, rvalue, &buffer); - if (r < 0) { - r = safe_atou32(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue); - return 0; - } - } else - k = be32toh(buffer.in.s_addr); - - if (streq(lvalue, "Key")) - t->key = k; - else if (streq(lvalue, "InputKey")) - t->ikey = k; - else - t->okey = k; - - return 0; -} - -int config_parse_ipv6_flowlabel(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) { - IPv6FlowLabel *ipv6_flowlabel = data; - Tunnel *t = userdata; - int k = 0; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ipv6_flowlabel); - - if (streq(rvalue, "inherit")) { - *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL; - t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL; - } else { - r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata); - if (r < 0) - return r; - - if (k > 0xFFFFF) - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue); - else { - *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL; - t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL; - } - } - - return 0; -} - -int config_parse_encap_limit(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) { - Tunnel *t = userdata; - int k = 0; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - if (streq(rvalue, "none")) - t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT; - else { - r = safe_atoi(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue); - return 0; - } - - if (k > 255 || k < 0) - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k); - else { - t->encap_limit = k; - t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT; - } - } - - return 0; -} - -static void ipip_init(NetDev *n) { - Tunnel *t = IPIP(n); - - assert(n); - assert(t); - - t->pmtudisc = true; - t->family = AF_UNSPEC; -} - -static void sit_init(NetDev *n) { - Tunnel *t = SIT(n); - - assert(n); - assert(t); - - t->pmtudisc = true; - t->family = AF_UNSPEC; -} - -static void vti_init(NetDev *n) { - Tunnel *t; - - assert(n); - - if (n->kind == NETDEV_KIND_VTI) - t = VTI(n); - else - t = VTI6(n); - - assert(t); - - t->pmtudisc = true; -} - -static void gre_init(NetDev *n) { - Tunnel *t; - - assert(n); - - if (n->kind == NETDEV_KIND_GRE) - t = GRE(n); - else - t = GRETAP(n); - - assert(t); - - t->pmtudisc = true; - t->family = AF_UNSPEC; -} - -static void ip6gre_init(NetDev *n) { - Tunnel *t; - - assert(n); - - if (n->kind == NETDEV_KIND_IP6GRE) - t = IP6GRE(n); - else - t = IP6GRETAP(n); - - assert(t); - - t->ttl = DEFAULT_TNL_HOP_LIMIT; -} - -static void ip6tnl_init(NetDev *n) { - Tunnel *t = IP6TNL(n); - - assert(n); - assert(t); - - t->ttl = DEFAULT_TNL_HOP_LIMIT; - t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT; - t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID; - t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID; -} - -const NetDevVTable ipip_vtable = { - .object_size = sizeof(Tunnel), - .init = ipip_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_ipip_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable sit_vtable = { - .object_size = sizeof(Tunnel), - .init = sit_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_sit_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable vti_vtable = { - .object_size = sizeof(Tunnel), - .init = vti_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_vti_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .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, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_gre_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable gretap_vtable = { - .object_size = sizeof(Tunnel), - .init = gre_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_gre_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable ip6gre_vtable = { - .object_size = sizeof(Tunnel), - .init = ip6gre_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_ip6gre_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable ip6gretap_vtable = { - .object_size = sizeof(Tunnel), - .init = ip6gre_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_ip6gre_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; - -const NetDevVTable ip6tnl_vtable = { - .object_size = sizeof(Tunnel), - .init = ip6tnl_init, - .sections = "Match\0NetDev\0Tunnel\0", - .fill_message_create = netdev_ip6tnl_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_tunnel_verify, -}; diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h deleted file mode 100644 index 32a46bd82f..0000000000 --- a/src/network/networkd-netdev-tunnel.h +++ /dev/null @@ -1,119 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "in-addr-util.h" - -#include "networkd-netdev.h" - -typedef enum Ip6TnlMode { - NETDEV_IP6_TNL_MODE_IP6IP6, - NETDEV_IP6_TNL_MODE_IPIP6, - NETDEV_IP6_TNL_MODE_ANYIP6, - _NETDEV_IP6_TNL_MODE_MAX, - _NETDEV_IP6_TNL_MODE_INVALID = -1, -} Ip6TnlMode; - -typedef enum IPv6FlowLabel { - NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1, - _NETDEV_IPV6_FLOWLABEL_MAX, - _NETDEV_IPV6_FLOWLABEL_INVALID = -1, -} IPv6FlowLabel; - -typedef struct Tunnel { - NetDev meta; - - uint8_t encap_limit; - - int family; - int ipv6_flowlabel; - - unsigned ttl; - unsigned tos; - unsigned flags; - - uint32_t key; - uint32_t ikey; - uint32_t okey; - - union in_addr_union local; - union in_addr_union remote; - - Ip6TnlMode ip6tnl_mode; - - bool pmtudisc; - bool copy_dscp; -} Tunnel; - -DEFINE_NETDEV_CAST(IPIP, Tunnel); -DEFINE_NETDEV_CAST(GRE, Tunnel); -DEFINE_NETDEV_CAST(GRETAP, Tunnel); -DEFINE_NETDEV_CAST(IP6GRE, Tunnel); -DEFINE_NETDEV_CAST(IP6GRETAP, Tunnel); -DEFINE_NETDEV_CAST(SIT, Tunnel); -DEFINE_NETDEV_CAST(VTI, Tunnel); -DEFINE_NETDEV_CAST(VTI6, Tunnel); -DEFINE_NETDEV_CAST(IP6TNL, 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; -extern const NetDevVTable ip6gretap_vtable; -extern const NetDevVTable ip6tnl_vtable; - -const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_; -Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_; - -int config_parse_ip6tnl_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_tunnel_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); - -int config_parse_ipv6_flowlabel(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_encap_limit(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_tunnel_key(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-tuntap.c b/src/network/networkd-netdev-tuntap.c deleted file mode 100644 index 088a4d8d32..0000000000 --- a/src/network/networkd-netdev-tuntap.c +++ /dev/null @@ -1,183 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Susant Sahani <susant@redhat.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <fcntl.h> -#include <linux/if_tun.h> -#include <net/if.h> -#include <netinet/if_ether.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "alloc-util.h" -#include "fd-util.h" -#include "networkd-netdev-tuntap.h" -#include "user-util.h" - -#define TUN_DEV "/dev/net/tun" - -static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { - TunTap *t; - - assert(netdev); - assert(netdev->ifname); - assert(ifr); - - if (netdev->kind == NETDEV_KIND_TAP) { - t = TAP(netdev); - ifr->ifr_flags |= IFF_TAP; - } else { - t = TUN(netdev); - ifr->ifr_flags |= IFF_TUN; - } - - if (!t->packet_info) - ifr->ifr_flags |= IFF_NO_PI; - - if (t->one_queue) - ifr->ifr_flags |= IFF_ONE_QUEUE; - - if (t->multi_queue) - ifr->ifr_flags |= IFF_MULTI_QUEUE; - - if (t->vnet_hdr) - ifr->ifr_flags |= IFF_VNET_HDR; - - strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); - - return 0; -} - -static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { - _cleanup_close_ int fd; - TunTap *t = NULL; - const char *user; - const char *group; - uid_t uid; - gid_t gid; - int r; - - assert(netdev); - assert(ifr); - - fd = open(TUN_DEV, O_RDWR); - if (fd < 0) - return log_netdev_error_errno(netdev, -errno, "Failed to open tun dev: %m"); - - r = ioctl(fd, TUNSETIFF, ifr); - if (r < 0) - return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m"); - - if (netdev->kind == NETDEV_KIND_TAP) - t = TAP(netdev); - else - t = TUN(netdev); - - assert(t); - - if (t->user_name) { - - user = t->user_name; - - r = get_user_creds(&user, &uid, NULL, NULL, NULL); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name); - - r = ioctl(fd, TUNSETOWNER, uid); - if (r < 0) - return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m"); - } - - if (t->group_name) { - - group = t->group_name; - - r = get_group_creds(&group, &gid); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name); - - r = ioctl(fd, TUNSETGROUP, gid); - if (r < 0) - return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m"); - - } - - r = ioctl(fd, TUNSETPERSIST, 1); - if (r < 0) - return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m"); - - return 0; -} - -static int netdev_create_tuntap(NetDev *netdev) { - struct ifreq ifr = {}; - int r; - - r = netdev_fill_tuntap_message(netdev, &ifr); - if (r < 0) - return r; - - return netdev_tuntap_add(netdev, &ifr); -} - -static void tuntap_done(NetDev *netdev) { - TunTap *t = NULL; - - assert(netdev); - - if (netdev->kind == NETDEV_KIND_TUN) - t = TUN(netdev); - else - t = TAP(netdev); - - assert(t); - - t->user_name = mfree(t->user_name); - t->group_name = mfree(t->group_name); -} - -static int tuntap_verify(NetDev *netdev, const char *filename) { - assert(netdev); - - if (netdev->mtu) - log_netdev_warning(netdev, "MTU 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; -} - -const NetDevVTable tun_vtable = { - .object_size = sizeof(TunTap), - .sections = "Match\0NetDev\0Tun\0", - .config_verify = tuntap_verify, - .done = tuntap_done, - .create = netdev_create_tuntap, - .create_type = NETDEV_CREATE_INDEPENDENT, -}; - -const NetDevVTable tap_vtable = { - .object_size = sizeof(TunTap), - .sections = "Match\0NetDev\0Tap\0", - .config_verify = tuntap_verify, - .done = tuntap_done, - .create = netdev_create_tuntap, - .create_type = NETDEV_CREATE_INDEPENDENT, -}; diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h deleted file mode 100644 index 120f00a353..0000000000 --- a/src/network/networkd-netdev-tuntap.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct TunTap TunTap; - -#include "networkd-netdev.h" - -struct TunTap { - NetDev meta; - - char *user_name; - char *group_name; - bool one_queue; - bool multi_queue; - bool packet_info; - bool vnet_hdr; -}; - -DEFINE_NETDEV_CAST(TUN, TunTap); -DEFINE_NETDEV_CAST(TAP, TunTap); -extern const NetDevVTable tun_vtable; -extern const NetDevVTable tap_vtable; diff --git a/src/network/networkd-netdev-vcan.c b/src/network/networkd-netdev-vcan.c deleted file mode 100644 index bfce6e1962..0000000000 --- a/src/network/networkd-netdev-vcan.c +++ /dev/null @@ -1,25 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2016 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "networkd-netdev-vcan.h" - -const NetDevVTable vcan_vtable = { - .object_size = sizeof(VCan), - .create_type = NETDEV_CREATE_INDEPENDENT, -}; diff --git a/src/network/networkd-netdev-vcan.h b/src/network/networkd-netdev-vcan.h deleted file mode 100644 index 6ba47fd70e..0000000000 --- a/src/network/networkd-netdev-vcan.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2016 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct VCan VCan; - -#include <linux/can/netlink.h> - -#include "networkd-netdev.h" - -struct VCan { - NetDev meta; -}; - -DEFINE_NETDEV_CAST(VCAN, VCan); - -extern const NetDevVTable vcan_vtable; diff --git a/src/network/networkd-netdev-veth.c b/src/network/networkd-netdev-veth.c deleted file mode 100644 index b122a06c25..0000000000 --- a/src/network/networkd-netdev-veth.c +++ /dev/null @@ -1,111 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Susant Sahani <susant@redhat.com> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> -#include <linux/veth.h> - -#include "sd-netlink.h" - -#include "networkd-netdev-veth.h" - -static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Veth *v; - int r; - - assert(netdev); - assert(!link); - assert(m); - - v = VETH(netdev); - - assert(v); - - r = sd_netlink_message_open_container(m, VETH_INFO_PEER); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append VETH_INFO_PEER attribute: %m"); - - if (v->ifname_peer) { - r = sd_netlink_message_append_string(m, IFLA_IFNAME, v->ifname_peer); - if (r < 0) - return log_error_errno(r, "Failed to add netlink interface name: %m"); - } - - if (v->mac_peer) { - r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, v->mac_peer); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); - } - - r = sd_netlink_message_close_container(m); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); - - return r; -} - -static int netdev_veth_verify(NetDev *netdev, const char *filename) { - Veth *v; - int r; - - assert(netdev); - assert(filename); - - v = VETH(netdev); - - assert(v); - - if (!v->ifname_peer) { - log_warning("Veth NetDev without peer name configured in %s. Ignoring", - filename); - return -EINVAL; - } - - if (!v->mac_peer) { - r = netdev_get_mac(v->ifname_peer, &v->mac_peer); - if (r < 0) { - log_warning("Failed to generate predictable MAC address for %s. Ignoring", - v->ifname_peer); - return -EINVAL; - } - } - - return 0; -} - -static void veth_done(NetDev *n) { - Veth *v; - - assert(n); - - v = VETH(n); - - assert(v); - - free(v->ifname_peer); - free(v->mac_peer); -} - -const NetDevVTable veth_vtable = { - .object_size = sizeof(Veth), - .sections = "Match\0NetDev\0Peer\0", - .done = veth_done, - .fill_message_create = netdev_veth_fill_message_create, - .create_type = NETDEV_CREATE_INDEPENDENT, - .config_verify = netdev_veth_verify, -}; diff --git a/src/network/networkd-netdev-veth.h b/src/network/networkd-netdev-veth.h deleted file mode 100644 index e69bfbc8f0..0000000000 --- a/src/network/networkd-netdev-veth.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct Veth Veth; - -#include "networkd-netdev.h" - -struct Veth { - NetDev meta; - - char *ifname_peer; - struct ether_addr *mac_peer; -}; - -DEFINE_NETDEV_CAST(VETH, Veth); -extern const NetDevVTable veth_vtable; diff --git a/src/network/networkd-netdev-vlan.c b/src/network/networkd-netdev-vlan.c deleted file mode 100644 index 3cc072388f..0000000000 --- a/src/network/networkd-netdev-vlan.c +++ /dev/null @@ -1,78 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "networkd-netdev-vlan.h" -#include "vlan-util.h" - -static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) { - VLan *v; - int r; - - assert(netdev); - assert(link); - assert(req); - - v = VLAN(netdev); - - assert(v); - - r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m"); - - return 0; -} - -static int netdev_vlan_verify(NetDev *netdev, const char *filename) { - VLan *v; - - assert(netdev); - assert(filename); - - v = VLAN(netdev); - - assert(v); - - if (v->id == VLANID_INVALID) { - log_warning("VLAN without valid Id (%"PRIu16") configured in %s.", v->id, filename); - return -EINVAL; - } - - return 0; -} - -static void vlan_init(NetDev *netdev) { - VLan *v = VLAN(netdev); - - assert(netdev); - assert(v); - - v->id = VLANID_INVALID; -} - -const NetDevVTable vlan_vtable = { - .object_size = sizeof(VLan), - .init = vlan_init, - .sections = "Match\0NetDev\0VLAN\0", - .fill_message_create = netdev_vlan_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_vlan_verify, -}; diff --git a/src/network/networkd-netdev-vlan.h b/src/network/networkd-netdev-vlan.h deleted file mode 100644 index 2dfe314b6e..0000000000 --- a/src/network/networkd-netdev-vlan.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct VLan VLan; - -#include "networkd-netdev.h" - -struct VLan { - NetDev meta; - - uint16_t id; -}; - -DEFINE_NETDEV_CAST(VLAN, VLan); -extern const NetDevVTable vlan_vtable; diff --git a/src/network/networkd-netdev-vrf.c b/src/network/networkd-netdev-vrf.c deleted file mode 100644 index 89bd142e8c..0000000000 --- a/src/network/networkd-netdev-vrf.c +++ /dev/null @@ -1,50 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2016 Andreas Rammhold <andreas@rammhold.de> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "sd-netlink.h" -#include "missing.h" -#include "networkd-netdev-vrf.h" - -static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - Vrf *v; - int r; - - assert(netdev); - assert(!link); - assert(m); - - v = VRF(netdev); - - assert(v); - - r = sd_netlink_message_append_u32(m, IFLA_VRF_TABLE, v->table_id); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IPLA_VRF_TABLE attribute: %m"); - - return r; -} - -const NetDevVTable vrf_vtable = { - .object_size = sizeof(Vrf), - .sections = "NetDev\0VRF\0", - .fill_message_create = netdev_vrf_fill_message_create, - .create_type = NETDEV_CREATE_MASTER, -}; diff --git a/src/network/networkd-netdev-vrf.h b/src/network/networkd-netdev-vrf.h deleted file mode 100644 index 3d92a26a4d..0000000000 --- a/src/network/networkd-netdev-vrf.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2016 Andreas Rammhold <andreas@rammhold.de> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct Vrf Vrf; - -#include "networkd-netdev.h" - -struct Vrf { - NetDev meta; - - uint32_t table_id; -}; - -DEFINE_NETDEV_CAST(VRF, Vrf); -extern const NetDevVTable vrf_vtable; diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c deleted file mode 100644 index 706e52b698..0000000000 --- a/src/network/networkd-netdev-vxlan.c +++ /dev/null @@ -1,304 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Susant Sahani - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "sd-netlink.h" - -#include "conf-parser.h" -#include "alloc-util.h" -#include "extract-word.h" -#include "parse-util.h" -#include "missing.h" - -#include "networkd-link.h" -#include "networkd-netdev-vxlan.h" - -static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) { - VxLan *v; - int r; - - assert(netdev); - assert(link); - assert(m); - - v = VXLAN(netdev); - - assert(v); - - if (v->id <= VXLAN_VID_MAX) { - r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->id); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_ID attribute: %m"); - } - - r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_GROUP, &v->group.in); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GROUP attribute: %m"); - - r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LINK attribute: %m"); - - if (v->ttl) { - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TTL attribute: %m"); - } - - if (v->tos) { - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_TOS, v->tos); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_TOS attribute: %m"); - } - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_LEARNING, v->learning); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LEARNING attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_RSC, v->route_short_circuit); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_RSC attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_PROXY, v->arp_proxy); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PROXY attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L2MISS, v->l2miss); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L2MISS attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_L3MISS, v->l3miss); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_L3MISS attribute: %m"); - - if (v->fdb_ageing) { - r = sd_netlink_message_append_u32(m, IFLA_VXLAN_AGEING, v->fdb_ageing / USEC_PER_SEC); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_AGEING attribute: %m"); - } - - if (v->max_fdb) { - r = sd_netlink_message_append_u32(m, IFLA_VXLAN_LIMIT, v->max_fdb); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LIMIT attribute: %m"); - } - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_CSUM, v->udpcsum); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_CSUM attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, v->udp6zerocsumtx); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_TX attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, v->udp6zerocsumrx); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_TX, v->remote_csum_tx); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m"); - - r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_RX, v->remote_csum_rx); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m"); - - r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m"); - - if (v->port_range.low || v->port_range.high) { - struct ifla_vxlan_port_range port_range; - - port_range.low = htobe16(v->port_range.low); - port_range.high = htobe16(v->port_range.high); - - r = sd_netlink_message_append_data(m, IFLA_VXLAN_PORT_RANGE, &port_range, sizeof(port_range)); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT_RANGE attribute: %m"); - } - - if (v->group_policy) { - r = sd_netlink_message_append_flag(m, IFLA_VXLAN_GBP); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GBP attribute: %m"); - } - - return r; -} - -int config_parse_vxlan_group_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) { - VxLan *v = userdata; - union in_addr_union *addr = data, buffer; - int r, f; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = in_addr_from_string_auto(rvalue, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "vxlan multicast group address is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - if (v->family != AF_UNSPEC && v->family != f) { - log_syntax(unit, LOG_ERR, filename, line, 0, "vxlan multicast group incompatible, ignoring assignment: %s", rvalue); - return 0; - } - - v->family = f; - *addr = buffer; - - return 0; -} - -int config_parse_port_range(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) { - _cleanup_free_ char *word = NULL; - VxLan *v = userdata; - unsigned low, high; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = extract_first_word(&rvalue, &word, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract VXLAN port range, ignoring: %s", rvalue); - return 0; - } - - if (r == 0) - return 0; - - r = parse_range(word, &low, &high); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN port range '%s'", word); - return 0; - } - - if (low <= 0 || low > 65535 || high <= 0 || high > 65535) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse VXLAN port range '%s'. Port should be greater than 0 and less than 65535.", word); - return 0; - } - - if (high < low) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Failed to parse VXLAN port range '%s'. Port range %u .. %u not valid", word, low, high); - return 0; - } - - v->port_range.low = low; - v->port_range.high = high; - - return 0; -} - -int config_parse_destination_port(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) { - VxLan *v = userdata; - uint16_t port; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = safe_atou16(rvalue, &port); - if (r < 0 || port <= 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VXLAN destination port '%s'.", rvalue); - return 0; - } - - v->dest_port = port; - - return 0; -} - -static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { - VxLan *v = VXLAN(netdev); - - assert(netdev); - assert(v); - assert(filename); - - if (v->id > VXLAN_VID_MAX) { - log_warning("VXLAN without valid Id configured in %s. Ignoring", filename); - return -EINVAL; - } - - return 0; -} - -static void vxlan_init(NetDev *netdev) { - VxLan *v; - - assert(netdev); - - v = VXLAN(netdev); - - assert(v); - - v->id = VXLAN_VID_MAX + 1; - v->learning = true; - v->udpcsum = false; - v->udp6zerocsumtx = false; - v->udp6zerocsumrx = false; -} - -const NetDevVTable vxlan_vtable = { - .object_size = sizeof(VxLan), - .init = vxlan_init, - .sections = "Match\0NetDev\0VXLAN\0", - .fill_message_create = netdev_vxlan_fill_message_create, - .create_type = NETDEV_CREATE_STACKED, - .config_verify = netdev_vxlan_verify, -}; diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h deleted file mode 100644 index 3906820afb..0000000000 --- a/src/network/networkd-netdev-vxlan.h +++ /dev/null @@ -1,93 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct VxLan VxLan; - -#include "in-addr-util.h" -#include "networkd-netdev.h" - -#define VXLAN_VID_MAX (1u << 24) - 1 - -struct VxLan { - NetDev meta; - - uint64_t id; - - int family; - union in_addr_union group; - - unsigned tos; - unsigned ttl; - unsigned max_fdb; - - uint16_t dest_port; - - usec_t fdb_ageing; - - bool learning; - bool arp_proxy; - bool route_short_circuit; - bool l2miss; - bool l3miss; - bool udpcsum; - bool udp6zerocsumtx; - bool udp6zerocsumrx; - bool remote_csum_tx; - bool remote_csum_rx; - bool group_policy; - - struct ifla_vxlan_port_range port_range; -}; - -DEFINE_NETDEV_CAST(VXLAN, VxLan); -extern const NetDevVTable vxlan_vtable; - -int config_parse_vxlan_group_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); -int config_parse_port_range(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_destination_port(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.c b/src/network/networkd-netdev.c deleted file mode 100644 index a210ba1242..0000000000 --- a/src/network/networkd-netdev.c +++ /dev/null @@ -1,717 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <net/if.h> - -#include "alloc-util.h" -#include "conf-files.h" -#include "conf-parser.h" -#include "fd-util.h" -#include "list.h" -#include "netlink-util.h" -#include "network-internal.h" -#include "networkd-netdev.h" -#include "networkd.h" -#include "siphash24.h" -#include "stat-util.h" -#include "string-table.h" -#include "string-util.h" - -const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = { - [NETDEV_KIND_BRIDGE] = &bridge_vtable, - [NETDEV_KIND_BOND] = &bond_vtable, - [NETDEV_KIND_VLAN] = &vlan_vtable, - [NETDEV_KIND_MACVLAN] = &macvlan_vtable, - [NETDEV_KIND_MACVTAP] = &macvtap_vtable, - [NETDEV_KIND_IPVLAN] = &ipvlan_vtable, - [NETDEV_KIND_VXLAN] = &vxlan_vtable, - [NETDEV_KIND_IPIP] = &ipip_vtable, - [NETDEV_KIND_GRE] = &gre_vtable, - [NETDEV_KIND_GRETAP] = &gretap_vtable, - [NETDEV_KIND_IP6GRE] = &ip6gre_vtable, - [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, - [NETDEV_KIND_TAP] = &tap_vtable, - [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable, - [NETDEV_KIND_VRF] = &vrf_vtable, - [NETDEV_KIND_VCAN] = &vcan_vtable, -}; - -static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { - [NETDEV_KIND_BRIDGE] = "bridge", - [NETDEV_KIND_BOND] = "bond", - [NETDEV_KIND_VLAN] = "vlan", - [NETDEV_KIND_MACVLAN] = "macvlan", - [NETDEV_KIND_MACVTAP] = "macvtap", - [NETDEV_KIND_IPVLAN] = "ipvlan", - [NETDEV_KIND_VXLAN] = "vxlan", - [NETDEV_KIND_IPIP] = "ipip", - [NETDEV_KIND_GRE] = "gre", - [NETDEV_KIND_GRETAP] = "gretap", - [NETDEV_KIND_IP6GRE] = "ip6gre", - [NETDEV_KIND_IP6GRETAP] = "ip6gretap", - [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", - [NETDEV_KIND_IP6TNL] = "ip6tnl", - [NETDEV_KIND_VRF] = "vrf", - [NETDEV_KIND_VCAN] = "vcan", -}; - -DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); -DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Failed to parse netdev kind"); - -static void netdev_cancel_callbacks(NetDev *netdev) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - netdev_join_callback *callback; - - if (!netdev) - return; - - rtnl_message_new_synthetic_error(-ENODEV, 0, &m); - - while ((callback = netdev->callbacks)) { - if (m) { - assert(callback->link); - assert(callback->callback); - assert(netdev->manager); - assert(netdev->manager->rtnl); - - callback->callback(netdev->manager->rtnl, m, callback->link); - } - - LIST_REMOVE(callbacks, netdev->callbacks, callback); - link_unref(callback->link); - free(callback); - } -} - -static void netdev_free(NetDev *netdev) { - if (!netdev) - return; - - netdev_cancel_callbacks(netdev); - - if (netdev->ifname) - hashmap_remove(netdev->manager->netdevs, netdev->ifname); - - free(netdev->filename); - - free(netdev->description); - free(netdev->ifname); - free(netdev->mac); - - condition_free_list(netdev->match_host); - condition_free_list(netdev->match_virt); - condition_free_list(netdev->match_kernel); - condition_free_list(netdev->match_arch); - - if (NETDEV_VTABLE(netdev) && - NETDEV_VTABLE(netdev)->done) - NETDEV_VTABLE(netdev)->done(netdev); - - free(netdev); -} - -NetDev *netdev_unref(NetDev *netdev) { - if (netdev && (-- netdev->n_ref <= 0)) - netdev_free(netdev); - - return NULL; -} - -NetDev *netdev_ref(NetDev *netdev) { - if (netdev) - assert_se(++ netdev->n_ref >= 2); - - return netdev; -} - -void netdev_drop(NetDev *netdev) { - if (!netdev || netdev->state == NETDEV_STATE_LINGER) - return; - - netdev->state = NETDEV_STATE_LINGER; - - log_netdev_debug(netdev, "netdev removed"); - - netdev_cancel_callbacks(netdev); - - netdev_unref(netdev); - - return; -} - -int netdev_get(Manager *manager, const char *name, NetDev **ret) { - NetDev *netdev; - - assert(manager); - assert(name); - assert(ret); - - netdev = hashmap_get(manager->netdevs, name); - if (!netdev) { - *ret = NULL; - return -ENOENT; - } - - *ret = netdev; - - return 0; -} - -static int netdev_enter_failed(NetDev *netdev) { - netdev->state = NETDEV_STATE_FAILED; - - netdev_cancel_callbacks(netdev); - - return 0; -} - -static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(netdev); - assert(netdev->state == NETDEV_STATE_READY); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)); - assert(link); - assert(callback); - - 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_netlink_message_append_u32(req, IFLA_MASTER, netdev->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_MASTER attribute: %m"); - - r = sd_netlink_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL); - 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); - - return 0; -} - -static int netdev_enter_ready(NetDev *netdev) { - netdev_join_callback *callback, *callback_next; - int r; - - assert(netdev); - assert(netdev->ifname); - - if (netdev->state != NETDEV_STATE_CREATING) - return 0; - - netdev->state = NETDEV_STATE_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 - * link was ready */ - r = netdev_enslave_ready(netdev, callback->link, callback->callback); - if (r < 0) - return r; - - LIST_REMOVE(callbacks, netdev->callbacks, callback); - link_unref(callback->link); - free(callback); - } - - if (NETDEV_VTABLE(netdev)->post_create) - NETDEV_VTABLE(netdev)->post_create(netdev, NULL, NULL); - - return 0; -} - -/* callback for netdev's created without a backing Link */ -static int netdev_create_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - _cleanup_netdev_unref_ NetDev *netdev = userdata; - int r; - - assert(netdev->state != _NETDEV_STATE_INVALID); - - r = sd_netlink_message_get_errno(m); - if (r == -EEXIST) - log_netdev_info(netdev, "netdev exists, using existing without changing its parameters"); - else if (r < 0) { - log_netdev_warning_errno(netdev, r, "netdev could not be created: %m"); - netdev_drop(netdev); - - return 1; - } - - log_netdev_debug(netdev, "Created"); - - return 1; -} - -int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { - int r; - - assert(netdev); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF)); - - if (netdev->state == NETDEV_STATE_READY) { - r = netdev_enslave_ready(netdev, link, callback); - if (r < 0) - return r; - } else if (IN_SET(netdev->state, NETDEV_STATE_LINGER, NETDEV_STATE_FAILED)) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - - r = rtnl_message_new_synthetic_error(-ENODEV, 0, &m); - if (r >= 0) - callback(netdev->manager->rtnl, m, link); - } else { - /* the netdev is not yet read, save this request for when it is */ - netdev_join_callback *cb; - - cb = new0(netdev_join_callback, 1); - if (!cb) - return log_oom(); - - cb->callback = callback; - cb->link = link; - link_ref(link); - - LIST_PREPEND(callbacks, netdev->callbacks, cb); - - log_netdev_debug(netdev, "Will enslave '%s', when ready", link->ifname); - } - - return 0; -} - -int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *message) { - uint16_t type; - const char *kind; - const char *received_kind; - const char *received_name; - int r, ifindex; - - assert(netdev); - assert(message); - - r = sd_netlink_message_get_type(message, &type); - 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, "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_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 -EINVAL; - } - - if (netdev->ifindex > 0) { - if (netdev->ifindex != ifindex) { - log_netdev_error(netdev, "Could not set ifindex to %d, already set to %d", - ifindex, netdev->ifindex); - netdev_enter_failed(netdev); - return -EEXIST; - } else - /* ifindex already set to the same for this netdev */ - return 0; - } - - r = sd_netlink_message_read_string(message, IFLA_IFNAME, &received_name); - 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); - netdev_enter_failed(netdev); - return r; - } - - r = sd_netlink_message_enter_container(message, IFLA_LINKINFO); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get LINKINFO: %m"); - - r = sd_netlink_message_read_string(message, IFLA_INFO_KIND, &received_kind); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not get KIND: %m"); - - r = sd_netlink_message_exit_container(message); - 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 */ - kind = "tun"; - else { - kind = netdev_kind_to_string(netdev->kind); - if (!kind) { - log_netdev_error(netdev, "Could not get kind"); - netdev_enter_failed(netdev); - return -EINVAL; - } - } - - if (!streq(kind, received_kind)) { - log_netdev_error(netdev, - "Received newlink with wrong KIND %s, " - "expected %s", received_kind, kind); - netdev_enter_failed(netdev); - return r; - } - - netdev->ifindex = ifindex; - - log_netdev_debug(netdev, "netdev has index %d", netdev->ifindex); - - netdev_enter_ready(netdev); - - return 0; -} - -#define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48) - -int netdev_get_mac(const char *ifname, struct ether_addr **ret) { - _cleanup_free_ struct ether_addr *mac = NULL; - uint64_t result; - size_t l, sz; - uint8_t *v; - int r; - - assert(ifname); - assert(ret); - - mac = new0(struct ether_addr, 1); - if (!mac) - return -ENOMEM; - - l = strlen(ifname); - sz = sizeof(sd_id128_t) + l; - v = alloca(sz); - - /* fetch some persistent data unique to the machine */ - r = sd_id128_get_machine((sd_id128_t*) v); - if (r < 0) - return r; - - /* combine with some data unique (on this machine) to this - * netdev */ - memcpy(v + sizeof(sd_id128_t), ifname, l); - - /* Let's hash the host machine ID plus the container name. We - * use a fixed, but originally randomly created hash key here. */ - result = siphash24(v, sz, HASH_KEY.bytes); - - assert_cc(ETH_ALEN <= sizeof(result)); - memcpy(mac->ether_addr_octet, &result, ETH_ALEN); - - /* see eth_random_addr in the kernel */ - mac->ether_addr_octet[0] &= 0xfe; /* clear multicast bit */ - mac->ether_addr_octet[0] |= 0x02; /* set local assignment bit (IEEE802) */ - - *ret = mac; - mac = NULL; - - return 0; -} - -static int netdev_create(NetDev *netdev, Link *link, - sd_netlink_message_handler_t callback) { - int r; - - assert(netdev); - assert(!link || callback); - - /* create netdev */ - if (NETDEV_VTABLE(netdev)->create) { - assert(!link); - - r = NETDEV_VTABLE(netdev)->create(netdev); - if (r < 0) - return r; - - log_netdev_debug(netdev, "Created"); - } else { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL; - - r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not allocate RTM_NEWLINK message: %m"); - - r = sd_netlink_message_append_string(m, IFLA_IFNAME, netdev->ifname); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_IFNAME, attribute: %m"); - - if (netdev->mac) { - r = sd_netlink_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_ADDRESS attribute: %m"); - } - - if (netdev->mtu) { - r = sd_netlink_message_append_u32(m, IFLA_MTU, netdev->mtu); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_MTU attribute: %m"); - } - - if (link) { - r = sd_netlink_message_append_u32(m, IFLA_LINK, link->ifindex); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINK attribute: %m"); - } - - r = sd_netlink_message_open_container(m, IFLA_LINKINFO); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); - - r = sd_netlink_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); - if (r < 0) - return r; - } - - r = sd_netlink_message_close_container(m); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m"); - - r = sd_netlink_message_close_container(m); - if (r < 0) - return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m"); - - if (link) { - r = sd_netlink_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_netlink_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"); - } - - return 0; -} - -/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */ -int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback) { - int r; - - assert(netdev); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(NETDEV_VTABLE(netdev)); - - switch (NETDEV_VTABLE(netdev)->create_type) { - case NETDEV_CREATE_MASTER: - r = netdev_enslave(netdev, link, callback); - if (r < 0) - return r; - - break; - case NETDEV_CREATE_STACKED: - r = netdev_create(netdev, link, callback); - if (r < 0) - return r; - - break; - default: - assert_not_reached("Can not join independent netdev"); - } - - return 0; -} - -static int netdev_load_one(Manager *manager, const char *filename) { - _cleanup_netdev_unref_ NetDev *netdev = NULL; - _cleanup_free_ NetDev *netdev_raw = NULL; - _cleanup_fclose_ FILE *file = NULL; - const char *dropin_dirname; - int r; - - assert(manager); - assert(filename); - - file = fopen(filename, "re"); - if (!file) { - if (errno == ENOENT) - return 0; - else - return -errno; - } - - if (null_or_empty_fd(fileno(file))) { - log_debug("Skipping empty file: %s", filename); - return 0; - } - - netdev_raw = new0(NetDev, 1); - if (!netdev_raw) - return log_oom(); - - netdev_raw->kind = _NETDEV_KIND_INVALID; - dropin_dirname = strjoina(basename(filename), ".d"); - - r = config_parse_many(filename, network_dirs, dropin_dirname, - "Match\0NetDev\0", - config_item_perf_lookup, network_netdev_gperf_lookup, - true, netdev_raw); - if (r < 0) - return r; - - r = fseek(file, 0, SEEK_SET); - if (r < 0) - return -errno; - - /* skip out early if configuration does not match the environment */ - if (net_match_config(NULL, NULL, NULL, NULL, NULL, - netdev_raw->match_host, netdev_raw->match_virt, - netdev_raw->match_kernel, netdev_raw->match_arch, - NULL, NULL, NULL, NULL, NULL, NULL) <= 0) - return 0; - - if (netdev_raw->kind == _NETDEV_KIND_INVALID) { - log_warning("NetDev has no Kind configured in %s. Ignoring", filename); - return 0; - } - - if (!netdev_raw->ifname) { - log_warning("NetDev without Name configured in %s. Ignoring", filename); - return 0; - } - - netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); - if (!netdev) - return log_oom(); - - netdev->n_ref = 1; - netdev->manager = manager; - netdev->state = _NETDEV_STATE_INVALID; - netdev->kind = netdev_raw->kind; - netdev->ifname = netdev_raw->ifname; - - if (NETDEV_VTABLE(netdev)->init) - NETDEV_VTABLE(netdev)->init(netdev); - - r = config_parse(NULL, filename, file, - NETDEV_VTABLE(netdev)->sections, - config_item_perf_lookup, network_netdev_gperf_lookup, - false, false, false, netdev); - if (r < 0) - return r; - - /* verify configuration */ - if (NETDEV_VTABLE(netdev)->config_verify) { - r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename); - if (r < 0) - return 0; - } - - netdev->filename = strdup(filename); - if (!netdev->filename) - return log_oom(); - - if (!netdev->mac && netdev->kind != NETDEV_KIND_VLAN) { - r = netdev_get_mac(netdev->ifname, &netdev->mac); - 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); - if (r < 0) - return r; - - LIST_HEAD_INIT(netdev->callbacks); - - log_netdev_debug(netdev, "loaded %s", netdev_kind_to_string(netdev->kind)); - - switch (NETDEV_VTABLE(netdev)->create_type) { - case NETDEV_CREATE_MASTER: - case NETDEV_CREATE_INDEPENDENT: - r = netdev_create(netdev, NULL, NULL); - if (r < 0) - return 0; - - break; - default: - break; - } - - netdev = NULL; - - return 0; -} - -int netdev_load(Manager *manager) { - _cleanup_strv_free_ char **files = NULL; - NetDev *netdev; - char **f; - int r; - - assert(manager); - - while ((netdev = hashmap_first(manager->netdevs))) - netdev_unref(netdev); - - r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs); - if (r < 0) - return log_error_errno(r, "Failed to enumerate netdev files: %m"); - - STRV_FOREACH_BACKWARDS(f, files) { - r = netdev_load_one(manager, *f); - if (r < 0) - return r; - } - - return 0; -} diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h deleted file mode 100644 index 37c7431213..0000000000 --- a/src/network/networkd-netdev.h +++ /dev/null @@ -1,202 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "sd-netlink.h" - -#include "list.h" -#include "time-util.h" - -typedef struct netdev_join_callback netdev_join_callback; -typedef struct Link Link; - -struct netdev_join_callback { - sd_netlink_message_handler_t callback; - Link *link; - - LIST_FIELDS(netdev_join_callback, callbacks); -}; - -typedef enum NetDevKind { - NETDEV_KIND_BRIDGE, - NETDEV_KIND_BOND, - NETDEV_KIND_VLAN, - NETDEV_KIND_MACVLAN, - NETDEV_KIND_MACVTAP, - NETDEV_KIND_IPVLAN, - NETDEV_KIND_VXLAN, - NETDEV_KIND_IPIP, - NETDEV_KIND_GRE, - NETDEV_KIND_GRETAP, - NETDEV_KIND_IP6GRE, - NETDEV_KIND_IP6GRETAP, - NETDEV_KIND_SIT, - NETDEV_KIND_VETH, - NETDEV_KIND_VTI, - NETDEV_KIND_VTI6, - NETDEV_KIND_IP6TNL, - NETDEV_KIND_DUMMY, - NETDEV_KIND_TUN, - NETDEV_KIND_TAP, - NETDEV_KIND_VRF, - NETDEV_KIND_VCAN, - _NETDEV_KIND_MAX, - _NETDEV_KIND_INVALID = -1 -} NetDevKind; - -typedef enum NetDevState { - NETDEV_STATE_FAILED, - NETDEV_STATE_CREATING, - NETDEV_STATE_READY, - NETDEV_STATE_LINGER, - _NETDEV_STATE_MAX, - _NETDEV_STATE_INVALID = -1, -} NetDevState; - -typedef enum NetDevCreateType { - NETDEV_CREATE_INDEPENDENT, - NETDEV_CREATE_MASTER, - NETDEV_CREATE_STACKED, - _NETDEV_CREATE_MAX, - _NETDEV_CREATE_INVALID = -1, -} NetDevCreateType; - -typedef struct Manager Manager; -typedef struct Condition Condition; - -typedef struct NetDev { - Manager *manager; - - int n_ref; - - char *filename; - - Condition *match_host; - Condition *match_virt; - Condition *match_kernel; - Condition *match_arch; - - NetDevState state; - NetDevKind kind; - char *description; - char *ifname; - struct ether_addr *mac; - size_t mtu; - int ifindex; - - LIST_HEAD(netdev_join_callback, callbacks); -} NetDev; - -typedef struct NetDevVTable { - /* How much memory does an object of this unit type need */ - size_t object_size; - - /* Config file sections this netdev kind understands, separated - * by NUL chars */ - const char *sections; - - /* This should reset all type-specific variables. This should - * not allocate memory, and is called with zero-initialized - * data. It should hence only initialize variables that need - * to be set != 0. */ - void (*init)(NetDev *n); - - /* This should free all kind-specific variables. It should be - * idempotent. */ - void (*done)(NetDev *n); - - /* fill in message to create netdev */ - int (*fill_message_create)(NetDev *netdev, Link *link, sd_netlink_message *message); - - /* specifies if netdev is independent, or a master device or a stacked device */ - NetDevCreateType create_type; - - /* create netdev, if not done via rtnl */ - int (*create)(NetDev *netdev); - - /* perform additional configuration after netdev has been createad */ - int (*post_create)(NetDev *netdev, Link *link, sd_netlink_message *message); - - /* verify that compulsory configuration options were specified */ - int (*config_verify)(NetDev *netdev, const char *filename); -} NetDevVTable; - -extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; - -#define NETDEV_VTABLE(n) netdev_vtable[(n)->kind] - -/* For casting a netdev into the various netdev kinds */ -#define DEFINE_NETDEV_CAST(UPPERCASE, MixedCase) \ - static inline MixedCase* UPPERCASE(NetDev *n) { \ - if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \ - return NULL; \ - \ - return (MixedCase*) n; \ - } - -/* For casting the various netdev kinds into a netdev */ -#define NETDEV(n) (&(n)->meta) - -int netdev_load(Manager *manager); -void netdev_drop(NetDev *netdev); - -NetDev *netdev_unref(NetDev *netdev); -NetDev *netdev_ref(NetDev *netdev); - -DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref); -#define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp) - -int netdev_get(Manager *manager, const char *name, NetDev **ret); -int netdev_set_ifindex(NetDev *netdev, sd_netlink_message *newlink); -int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t callback); -int netdev_get_mac(const char *ifname, struct ether_addr **ret); -int netdev_join(NetDev *netdev, Link *link, sd_netlink_message_handler_t cb); - -const char *netdev_kind_to_string(NetDevKind d) _const_; -NetDevKind netdev_kind_from_string(const char *d) _pure_; - -int config_parse_netdev_kind(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); - -/* gperf */ -const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, GPERF_LEN_TYPE length); - -/* Macros which append INTERFACE= to the message */ - -#define log_netdev_full(netdev, level, error, ...) \ - ({ \ - const NetDev *_n = (netdev); \ - _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__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 deleted file mode 100644 index 6e21676d23..0000000000 --- a/src/network/networkd-network-bus.c +++ /dev/null @@ -1,153 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2015 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "networkd.h" -#include "string-util.h" -#include "strv.h" - -static int property_get_ether_addrs( - sd_bus *bus, - const char *path, - const char *interface, - const char *property, - sd_bus_message *reply, - void *userdata, - sd_bus_error *error) { - - Network *n = userdata; - const char *ether = NULL; - int r; - - assert(bus); - assert(reply); - assert(n); - - if (n->match_mac) - ether = ether_ntoa(n->match_mac); - - r = sd_bus_message_open_container(reply, 'a', "s"); - if (r < 0) - return r; - - if (ether) { - r = sd_bus_message_append(reply, "s", strempty(ether)); - if (r < 0) - return r; - } - - return sd_bus_message_close_container(reply); -} - -const sd_bus_vtable network_vtable[] = { - SD_BUS_VTABLE_START(0), - - SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, 0, SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("MatchName", "as", NULL, offsetof(Network, match_name), SD_BUS_VTABLE_PROPERTY_CONST), - - SD_BUS_VTABLE_END -}; - -static char *network_bus_path(Network *network) { - _cleanup_free_ char *name = NULL; - char *networkname, *d, *path; - int r; - - assert(network); - assert(network->filename); - - name = strdup(network->filename); - if (!name) - return NULL; - - networkname = basename(name); - - d = strrchr(networkname, '.'); - if (!d) - return NULL; - - assert(streq(d, ".network")); - - *d = '\0'; - - r = sd_bus_path_encode("/org/freedesktop/network1/network", networkname, &path); - if (r < 0) - return NULL; - - return path; -} - -int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { - _cleanup_strv_free_ char **l = NULL; - Manager *m = userdata; - Network *network; - int r; - - assert(bus); - assert(path); - assert(m); - assert(nodes); - - LIST_FOREACH(networks, network, m->networks) { - char *p; - - p = network_bus_path(network); - if (!p) - return -ENOMEM; - - r = strv_consume(&l, p); - if (r < 0) - return r; - } - - *nodes = l; - l = NULL; - - return 1; -} - -int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { - Manager *m = userdata; - Network *network; - _cleanup_free_ char *name = NULL; - int r; - - assert(bus); - assert(path); - assert(interface); - assert(m); - assert(found); - - r = sd_bus_path_decode(path, "/org/freedesktop/network1/network", &name); - if (r < 0) - return 0; - - r = network_get_by_name(m, name, &network); - if (r < 0) - return 0; - - *found = network; - - return 1; -} diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf deleted file mode 100644 index bcf8186c33..0000000000 --- a/src/network/networkd-network-gperf.gperf +++ /dev/null @@ -1,135 +0,0 @@ -%{ -#include <stddef.h> -#include "conf-parser.h" -#include "networkd.h" -#include "networkd-conf.h" -#include "network-internal.h" -#include "vlan-util.h" -%} -struct ConfigPerfItem; -%null_strings -%language=ANSI-C -%define slot-name section_and_lvalue -%define hash-function-name network_network_gperf_hash -%define lookup-function-name network_network_gperf_lookup -%readonly-tables -%omit-struct-type -%struct-type -%includes -%% -Match.MACAddress, config_parse_hwaddr, 0, offsetof(Network, match_mac) -Match.Path, config_parse_strv, 0, offsetof(Network, match_path) -Match.Driver, config_parse_strv, 0, offsetof(Network, match_driver) -Match.Type, config_parse_strv, 0, offsetof(Network, match_type) -Match.Name, config_parse_ifnames, 0, offsetof(Network, match_name) -Match.Host, config_parse_net_condition, CONDITION_HOST, offsetof(Network, match_host) -Match.Virtualization, config_parse_net_condition, CONDITION_VIRTUALIZATION, offsetof(Network, match_virt) -Match.KernelCommandLine, config_parse_net_condition, CONDITION_KERNEL_COMMAND_LINE, offsetof(Network, match_kernel) -Match.Architecture, config_parse_net_condition, CONDITION_ARCHITECTURE, offsetof(Network, match_arch) -Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) -Link.MTUBytes, config_parse_iec_size, 0, offsetof(Network, mtu) -Link.ARP, config_parse_tristate, 0, offsetof(Network, arp) -Network.Description, config_parse_string, 0, offsetof(Network, description) -Network.Bridge, config_parse_netdev, 0, offsetof(Network, bridge) -Network.Bond, config_parse_netdev, 0, offsetof(Network, bond) -Network.VLAN, config_parse_netdev, 0, 0 -Network.MACVLAN, config_parse_netdev, 0, 0 -Network.MACVTAP, config_parse_netdev, 0, 0 -Network.IPVLAN, config_parse_netdev, 0, 0 -Network.VXLAN, config_parse_netdev, 0, 0 -Network.Tunnel, config_parse_tunnel, 0, 0 -Network.VRF, config_parse_netdev, 0, 0 -Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp) -Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server) -Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local) -Network.IPv4LLRoute, config_parse_bool, 0, offsetof(Network, ipv4ll_route) -Network.IPv6Token, config_parse_ipv6token, 0, offsetof(Network, ipv6_token) -Network.LLDP, config_parse_lldp_mode, 0, offsetof(Network, lldp_mode) -Network.EmitLLDP, config_parse_lldp_emit, 0, offsetof(Network, lldp_emit) -Network.Address, config_parse_address, 0, 0 -Network.Gateway, config_parse_gateway, 0, 0 -Network.Domains, config_parse_domains, 0, 0 -Network.DNS, config_parse_dns, 0, 0 -Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr) -Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns) -Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode) -Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0 -Network.NTP, config_parse_strv, 0, offsetof(Network, ntp) -Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward) -Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade) -Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions) -Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) -/* legacy alias for the above */ -Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra) -Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits) -Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit) -Network.ProxyARP, config_parse_tristate, 0, offsetof(Network, proxy_arp) -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 -Address.Label, config_parse_label, 0, 0 -Address.PreferredLifetime, config_parse_lifetime, 0, 0 -Address.HomeAddress, config_parse_address_flags, 0, 0 -Address.DuplicateAddressDetection, config_parse_address_flags, 0, 0 -Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0 -Address.PrefixRoute, config_parse_address_flags, 0, 0 -Address.AutoJoin, config_parse_address_flags, 0, 0 -Route.Gateway, config_parse_gateway, 0, 0 -Route.Destination, config_parse_destination, 0, 0 -Route.Source, config_parse_destination, 0, 0 -Route.Metric, config_parse_route_priority, 0, 0 -Route.Scope, config_parse_route_scope, 0, 0 -Route.PreferredSource, config_parse_preferred_src, 0, 0 -Route.Table, config_parse_route_table, 0, 0 -DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier) -DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) -DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_use_ntp) -DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) -DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) -DHCP.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) -DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_use_routes) -DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_send_hostname) -DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname) -DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast) -DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) -DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier) -DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type) -DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid) -DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric) -DHCP.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, dhcp_route_table) -DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone) -DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid) -IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns) -IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains) -IPv6AcceptRA.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, ipv6_accept_ra_route_table) -DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec) -DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec) -DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns) -DHCPServer.DNS, config_parse_dhcp_server_dns, 0, 0 -DHCPServer.EmitNTP, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_ntp) -DHCPServer.NTP, config_parse_dhcp_server_ntp, 0, 0 -DHCPServer.EmitRouter, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_router) -DHCPServer.EmitTimezone, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_timezone) -DHCPServer.Timezone, config_parse_timezone, 0, offsetof(Network, dhcp_server_timezone) -DHCPServer.PoolOffset, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_offset) -DHCPServer.PoolSize, config_parse_uint32, 0, offsetof(Network, dhcp_server_pool_size) -Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost) -Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu) -Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin) -Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave) -Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root) -Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood) -BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0 -BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0 -BridgeVLAN.PVID, config_parse_brvlan_pvid, 0, 0 -BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0 -BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0 -/* backwards compatibility: do not add new entries to this section */ -Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local) -DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns) -DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_use_mtu) -DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_use_hostname) -DHCP.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) -DHCPv4.UseDomainName, config_parse_dhcp_use_domains, 0, offsetof(Network, dhcp_use_domains) -DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c deleted file mode 100644 index 042232fcac..0000000000 --- a/src/network/networkd-network.c +++ /dev/null @@ -1,1136 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <ctype.h> -#include <net/if.h> - -#include "alloc-util.h" -#include "conf-files.h" -#include "conf-parser.h" -#include "dns-domain.h" -#include "fd-util.h" -#include "hostname-util.h" -#include "network-internal.h" -#include "networkd-network.h" -#include "networkd.h" -#include "parse-util.h" -#include "set.h" -#include "stat-util.h" -#include "string-table.h" -#include "string-util.h" -#include "util.h" - -static int network_load_one(Manager *manager, const char *filename) { - _cleanup_network_free_ Network *network = NULL; - _cleanup_fclose_ FILE *file = NULL; - char *d; - const char *dropin_dirname; - Route *route; - Address *address; - int r; - - assert(manager); - assert(filename); - - file = fopen(filename, "re"); - if (!file) { - if (errno == ENOENT) - return 0; - - return -errno; - } - - if (null_or_empty_fd(fileno(file))) { - log_debug("Skipping empty file: %s", filename); - return 0; - } - - network = new0(Network, 1); - if (!network) - return log_oom(); - - network->manager = manager; - - LIST_HEAD_INIT(network->static_addresses); - LIST_HEAD_INIT(network->static_routes); - LIST_HEAD_INIT(network->static_fdb_entries); - - network->stacked_netdevs = hashmap_new(&string_hash_ops); - if (!network->stacked_netdevs) - return log_oom(); - - network->addresses_by_section = hashmap_new(NULL); - if (!network->addresses_by_section) - return log_oom(); - - network->routes_by_section = hashmap_new(NULL); - if (!network->routes_by_section) - return log_oom(); - - network->fdb_entries_by_section = hashmap_new(NULL); - if (!network->fdb_entries_by_section) - return log_oom(); - - network->filename = strdup(filename); - if (!network->filename) - return log_oom(); - - network->name = strdup(basename(filename)); - if (!network->name) - return log_oom(); - - d = strrchr(network->name, '.'); - if (!d) - return -EINVAL; - - assert(streq(d, ".network")); - - *d = '\0'; - - network->dhcp = ADDRESS_FAMILY_NO; - network->dhcp_use_ntp = true; - network->dhcp_use_dns = true; - network->dhcp_use_hostname = true; - network->dhcp_use_routes = true; - network->dhcp_send_hostname = true; - network->dhcp_route_metric = DHCP_ROUTE_METRIC; - network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID; - network->dhcp_route_table = RT_TABLE_MAIN; - - network->dhcp_server_emit_dns = true; - network->dhcp_server_emit_ntp = true; - network->dhcp_server_emit_router = true; - network->dhcp_server_emit_timezone = true; - - network->use_bpdu = true; - network->allow_port_to_be_root = true; - network->unicast_flood = true; - - network->lldp_mode = LLDP_MODE_ROUTERS_ONLY; - - network->llmnr = RESOLVE_SUPPORT_YES; - network->mdns = RESOLVE_SUPPORT_NO; - network->dnssec_mode = _DNSSEC_MODE_INVALID; - - network->link_local = ADDRESS_FAMILY_IPV6; - - network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; - network->ipv6_accept_ra = -1; - network->ipv6_dad_transmits = -1; - network->ipv6_hop_limit = -1; - network->duid.type = _DUID_TYPE_INVALID; - network->proxy_arp = -1; - network->arp = -1; - network->ipv6_accept_ra_use_dns = true; - network->ipv6_accept_ra_route_table = RT_TABLE_MAIN; - - dropin_dirname = strjoina(network->name, ".network.d"); - - r = config_parse_many(filename, network_dirs, dropin_dirname, - "Match\0" - "Link\0" - "Network\0" - "Address\0" - "Route\0" - "DHCP\0" - "DHCPv4\0" /* compat */ - "DHCPServer\0" - "IPv6AcceptRA\0" - "Bridge\0" - "BridgeFDB\0" - "BridgeVLAN\0", - config_item_perf_lookup, network_network_gperf_lookup, - false, network); - if (r < 0) - return r; - - /* IPMasquerade=yes implies IPForward=yes */ - if (network->ip_masquerade) - network->ip_forward |= ADDRESS_FAMILY_IPV4; - - LIST_PREPEND(networks, manager->networks, network); - - r = hashmap_ensure_allocated(&manager->networks_by_name, &string_hash_ops); - if (r < 0) - return r; - - r = hashmap_put(manager->networks_by_name, network->name, network); - if (r < 0) - return r; - - LIST_FOREACH(routes, route, network->static_routes) { - if (!route->family) { - log_warning("Route section without Gateway field configured in %s. " - "Ignoring", filename); - return 0; - } - } - - LIST_FOREACH(addresses, address, network->static_addresses) { - if (!address->family) { - log_warning("Address section without Address field configured in %s. " - "Ignoring", filename); - return 0; - } - } - - network = NULL; - - return 0; -} - -int network_load(Manager *manager) { - Network *network; - _cleanup_strv_free_ char **files = NULL; - char **f; - int r; - - assert(manager); - - while ((network = manager->networks)) - network_free(network); - - r = conf_files_list_strv(&files, ".network", NULL, network_dirs); - if (r < 0) - return log_error_errno(r, "Failed to enumerate network files: %m"); - - STRV_FOREACH_BACKWARDS(f, files) { - r = network_load_one(manager, *f); - if (r < 0) - return r; - } - - return 0; -} - -void network_free(Network *network) { - NetDev *netdev; - Route *route; - Address *address; - FdbEntry *fdb_entry; - Iterator i; - - if (!network) - return; - - free(network->filename); - - free(network->match_mac); - strv_free(network->match_path); - strv_free(network->match_driver); - strv_free(network->match_type); - strv_free(network->match_name); - - free(network->description); - free(network->dhcp_vendor_class_identifier); - free(network->dhcp_hostname); - - free(network->mac); - - strv_free(network->ntp); - strv_free(network->dns); - strv_free(network->search_domains); - strv_free(network->route_domains); - strv_free(network->bind_carrier); - - netdev_unref(network->bridge); - netdev_unref(network->bond); - netdev_unref(network->vrf); - - HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) { - hashmap_remove(network->stacked_netdevs, netdev->ifname); - netdev_unref(netdev); - } - hashmap_free(network->stacked_netdevs); - - while ((route = network->static_routes)) - route_free(route); - - while ((address = network->static_addresses)) - address_free(address); - - while ((fdb_entry = network->static_fdb_entries)) - fdb_entry_free(fdb_entry); - - hashmap_free(network->addresses_by_section); - hashmap_free(network->routes_by_section); - hashmap_free(network->fdb_entries_by_section); - - if (network->manager) { - if (network->manager->networks) - LIST_REMOVE(networks, network->manager->networks, network); - - if (network->manager->networks_by_name) - hashmap_remove(network->manager->networks_by_name, network->name); - } - - free(network->name); - - condition_free_list(network->match_host); - condition_free_list(network->match_virt); - condition_free_list(network->match_kernel); - condition_free_list(network->match_arch); - - free(network->dhcp_server_timezone); - free(network->dhcp_server_dns); - free(network->dhcp_server_ntp); - - set_free_free(network->dnssec_negative_trust_anchors); - - free(network); -} - -int network_get_by_name(Manager *manager, const char *name, Network **ret) { - Network *network; - - assert(manager); - assert(name); - assert(ret); - - network = hashmap_get(manager->networks_by_name, name); - if (!network) - return -ENOENT; - - *ret = network; - - return 0; -} - -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, 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); - - if (name_assign_type == NET_NAME_ENUM) - log_warning("%s: found matching network '%s', based on potentially unpredictable ifname", - ifname, network->filename); - else - log_debug("%s: found matching network '%s'", ifname, network->filename); - } else - log_debug("%s: found matching network '%s'", ifname, network->filename); - - *ret = network; - return 0; - } - } - - *ret = NULL; - - return -ENOENT; -} - -int network_apply(Manager *manager, Network *network, Link *link) { - int r; - - assert(manager); - assert(network); - assert(link); - - link->network = network; - - if (network->ipv4ll_route) { - Route *route; - - r = route_new_static(network, 0, &route); - if (r < 0) - return r; - - r = inet_pton(AF_INET, "169.254.0.0", &route->dst.in); - if (r == 0) - return -EINVAL; - if (r < 0) - return -errno; - - route->family = AF_INET; - route->dst_prefixlen = 16; - route->scope = RT_SCOPE_LINK; - route->priority = IPV4LL_ROUTE_METRIC; - route->protocol = RTPROT_STATIC; - } - - if (!strv_isempty(network->dns) || - !strv_isempty(network->ntp) || - !strv_isempty(network->search_domains) || - !strv_isempty(network->route_domains)) - link_dirty(link); - - return 0; -} - -bool network_has_static_ipv6_addresses(Network *network) { - Address *address; - - assert(network); - - LIST_FOREACH(addresses, address, network->static_addresses) { - if (address->family == AF_INET6) - return true; - } - - return false; -} - -int config_parse_netdev(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_free_ char *kind_string = NULL; - char *p; - NetDev *netdev; - NetDevKind kind; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - kind_string = strdup(lvalue); - if (!kind_string) - return log_oom(); - - /* the keys are CamelCase versions of the kind */ - for (p = kind_string; *p; p++) - *p = tolower(*p); - - kind = netdev_kind_from_string(kind_string); - if (kind == _NETDEV_KIND_INVALID) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid NetDev kind: %s", lvalue); - return 0; - } - - r = netdev_get(network->manager, rvalue, &netdev); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "%s could not be found, ignoring assignment: %s", lvalue, rvalue); - return 0; - } - - if (netdev->kind != kind) { - log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue); - return 0; - } - - switch (kind) { - case NETDEV_KIND_BRIDGE: - network->bridge = netdev; - - break; - case NETDEV_KIND_BOND: - network->bond = netdev; - - break; - case NETDEV_KIND_VRF: - network->vrf = netdev; - - break; - case NETDEV_KIND_VLAN: - case NETDEV_KIND_MACVLAN: - case NETDEV_KIND_MACVTAP: - case NETDEV_KIND_IPVLAN: - case NETDEV_KIND_VXLAN: - case NETDEV_KIND_VCAN: - r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue); - return 0; - } - - break; - default: - assert_not_reached("Can not parse NetDev"); - } - - netdev_ref(netdev); - - return 0; -} - -int config_parse_domains( - 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) { - - const char *p; - Network *n = data; - int r; - - assert(n); - assert(lvalue); - assert(rvalue); - - if (isempty(rvalue)) { - n->search_domains = strv_free(n->search_domains); - n->route_domains = strv_free(n->route_domains); - return 0; - } - - p = rvalue; - for (;;) { - _cleanup_free_ char *w = NULL, *normalized = NULL; - const char *domain; - bool is_route; - - r = extract_first_word(&p, &w, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract search or route domain, ignoring: %s", rvalue); - break; - } - if (r == 0) - break; - - is_route = w[0] == '~'; - domain = is_route ? w + 1 : w; - - if (dns_name_is_root(domain) || streq(domain, "*")) { - /* If the root domain appears as is, or the special token "*" is found, we'll consider this as - * routing domain, unconditionally. */ - is_route = true; - domain = "."; /* make sure we don't allow empty strings, thus write the root domain as "." */ - - } else { - r = dns_name_normalize(domain, &normalized); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "'%s' is not a valid domain name, ignoring.", domain); - continue; - } - - domain = normalized; - - if (is_localhost(domain)) { - log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configure as search or route domains, ignoring assignment: %s", domain); - continue; - } - } - - if (is_route) { - r = strv_extend(&n->route_domains, domain); - if (r < 0) - return log_oom(); - - } else { - r = strv_extend(&n->search_domains, domain); - if (r < 0) - return log_oom(); - } - } - - strv_uniq(n->route_domains); - strv_uniq(n->search_domains); - - return 0; -} - -int config_parse_tunnel(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; - NetDev *netdev; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = netdev_get(network->manager, rvalue, &netdev); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Tunnel is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - if (netdev->kind != NETDEV_KIND_IPIP && - netdev->kind != NETDEV_KIND_SIT && - netdev->kind != NETDEV_KIND_GRE && - netdev->kind != NETDEV_KIND_GRETAP && - 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, 0, - "NetDev is not a tunnel, ignoring assignment: %s", rvalue); - return 0; - } - - r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Cannot add VLAN '%s' to network, ignoring: %m", rvalue); - return 0; - } - - netdev_ref(netdev); - - return 0; -} - -int config_parse_ipv4ll( - 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) { - - AddressFamilyBoolean *link_local = data; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - /* Note that this is mostly like - * config_parse_address_family_boolean(), except that it - * applies only to IPv4 */ - - SET_FLAG(*link_local, ADDRESS_FAMILY_IPV4, parse_boolean(rvalue)); - - return 0; -} - -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) { - - AddressFamilyBoolean *dhcp = data, s; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - /* Note that this is mostly like - * config_parse_address_family_boolean(), except that it - * understands some old names for the enum values */ - - s = address_family_boolean_from_string(rvalue); - if (s < 0) { - - /* Previously, we had a slightly different enum here, - * support its values for compatbility. */ - - if (streq(rvalue, "none")) - s = ADDRESS_FAMILY_NO; - else if (streq(rvalue, "v4")) - s = ADDRESS_FAMILY_IPV4; - else if (streq(rvalue, "v6")) - s = ADDRESS_FAMILY_IPV6; - else if (streq(rvalue, "both")) - s = ADDRESS_FAMILY_YES; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue); - return 0; - } - } - - *dhcp = s; - 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"); - -int config_parse_ipv6token( - 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) { - - union in_addr_union buffer; - struct in6_addr *token = data; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(token); - - 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); - 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); - return 0; - } - - if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue); - return 0; - } - - *token = buffer.in6; - - return 0; -} - -static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = { - [IPV6_PRIVACY_EXTENSIONS_NO] = "no", - [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public", - [IPV6_PRIVACY_EXTENSIONS_YES] = "yes", -}; - -DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions); - -int config_parse_ipv6_privacy_extensions( - 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) { - - IPv6PrivacyExtensions *ipv6_privacy_extensions = data; - int k; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(ipv6_privacy_extensions); - - /* Our enum shall be a superset of booleans, hence first try - * to parse as boolean, and then as enum */ - - k = parse_boolean(rvalue); - if (k > 0) - *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES; - else if (k == 0) - *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO; - else { - IPv6PrivacyExtensions s; - - s = ipv6_privacy_extensions_from_string(rvalue); - if (s < 0) { - - if (streq(rvalue, "kernel")) - s = _IPV6_PRIVACY_EXTENSIONS_INVALID; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue); - return 0; - } - } - - *ipv6_privacy_extensions = s; - } - - return 0; -} - -int config_parse_hostname( - 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) { - - char **hostname = data, *hn = NULL; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata); - if (r < 0) - return r; - - if (!hostname_is_valid(hn, false)) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Hostname is not valid, ignoring assignment: %s", rvalue); - free(hn); - return 0; - } - - free(*hostname); - *hostname = hostname_cleanup(hn); - return 0; -} - -int config_parse_timezone( - 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) { - - char **datap = data, *tz = NULL; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata); - if (r < 0) - return r; - - if (!timezone_is_valid(tz)) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Timezone is not valid, ignoring assignment: %s", rvalue); - free(tz); - return 0; - } - - free(*datap); - *datap = tz; - - return 0; -} - -int config_parse_dhcp_server_dns( - 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 *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - struct in_addr a, *m; - - r = extract_first_word(&p, &w, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - - if (r == 0) - return 0; - - if (inet_pton(AF_INET, w, &a) <= 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DNS server address, ignoring: %s", w); - continue; - } - - m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_dns++] = a; - n->dhcp_server_dns = m; - } -} - -int config_parse_dhcp_server_ntp( - 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 *n = data; - const char *p = rvalue; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - struct in_addr a, *m; - - r = extract_first_word(&p, &w, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue); - return 0; - } - - if (r == 0) - return 0; - - if (inet_pton(AF_INET, w, &a) <= 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse NTP server address, ignoring: %s", w); - continue; - } - - m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr)); - if (!m) - return log_oom(); - - m[n->n_dhcp_server_ntp++] = a; - n->dhcp_server_ntp = m; - } -} - -int config_parse_dns( - 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 *n = userdata; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - - for (;;) { - _cleanup_free_ char *w = NULL; - union in_addr_union a; - int family; - - r = extract_first_word(&rvalue, &w, WHITESPACE, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE); - if (r == 0) - break; - if (r == -ENOMEM) - return log_oom(); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue); - break; - } - - r = in_addr_from_string_auto(w, &family, &a); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse dns server address, ignoring: %s", w); - continue; - } - - r = strv_consume(&n->dns, w); - if (r < 0) - return log_oom(); - - w = NULL; - } - - return 0; -} - -int config_parse_dnssec_negative_trust_anchors( - 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) { - - const char *p = rvalue; - Network *n = data; - int r; - - assert(n); - assert(lvalue); - assert(rvalue); - - if (isempty(rvalue)) { - n->dnssec_negative_trust_anchors = set_free_free(n->dnssec_negative_trust_anchors); - return 0; - } - - for (;;) { - _cleanup_free_ char *w = NULL; - - r = extract_first_word(&p, &w, NULL, 0); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract negative trust anchor domain, ignoring: %s", rvalue); - break; - } - if (r == 0) - break; - - r = dns_name_is_valid(w); - if (r <= 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "%s is not a valid domain name, ignoring.", w); - continue; - } - - r = set_ensure_allocated(&n->dnssec_negative_trust_anchors, &dns_name_hash_ops); - if (r < 0) - return log_oom(); - - r = set_put(n->dnssec_negative_trust_anchors, w); - if (r < 0) - return log_oom(); - if (r > 0) - w = NULL; - } - - return 0; -} - -int config_parse_dhcp_route_table(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) { - uint32_t rt; - int r; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - r = safe_atou32(rvalue, &rt); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Unable to read RouteTable, ignoring assignment: %s", rvalue); - return 0; - } - - *((uint32_t *)data) = rt; - - return 0; -} - -DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting"); - -static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = { - [DHCP_USE_DOMAINS_NO] = "no", - [DHCP_USE_DOMAINS_ROUTE] = "route", - [DHCP_USE_DOMAINS_YES] = "yes", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES); - -DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting."); - -static const char* const lldp_mode_table[_LLDP_MODE_MAX] = { - [LLDP_MODE_NO] = "no", - [LLDP_MODE_YES] = "yes", - [LLDP_MODE_ROUTERS_ONLY] = "routers-only", -}; - -DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(lldp_mode, LLDPMode, LLDP_MODE_YES); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h deleted file mode 100644 index 09c3b3a3ae..0000000000 --- a/src/network/networkd-network.h +++ /dev/null @@ -1,253 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "sd-bus.h" -#include "udev.h" - -#include "condition.h" -#include "dhcp-identifier.h" -#include "hashmap.h" -#include "resolve-util.h" - -#include "networkd-address.h" -#include "networkd-brvlan.h" -#include "networkd-fdb.h" -#include "networkd-lldp-tx.h" -#include "networkd-netdev.h" -#include "networkd-route.h" -#include "networkd-util.h" - -#define DHCP_ROUTE_METRIC 1024 -#define IPV4LL_ROUTE_METRIC 2048 - -#define BRIDGE_VLAN_BITMAP_MAX 4096 -#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32) - -typedef enum DCHPClientIdentifier { - DHCP_CLIENT_ID_MAC, - DHCP_CLIENT_ID_DUID, - _DHCP_CLIENT_ID_MAX, - _DHCP_CLIENT_ID_INVALID = -1, -} DCHPClientIdentifier; - -typedef enum IPv6PrivacyExtensions { - /* The values map to the kernel's /proc/sys/net/ipv6/conf/xxx/use_tempaddr values */ - IPV6_PRIVACY_EXTENSIONS_NO, - IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC, - IPV6_PRIVACY_EXTENSIONS_YES, /* aka prefer-temporary */ - _IPV6_PRIVACY_EXTENSIONS_MAX, - _IPV6_PRIVACY_EXTENSIONS_INVALID = -1, -} IPv6PrivacyExtensions; - -typedef enum DHCPUseDomains { - DHCP_USE_DOMAINS_NO, - DHCP_USE_DOMAINS_YES, - DHCP_USE_DOMAINS_ROUTE, - _DHCP_USE_DOMAINS_MAX, - _DHCP_USE_DOMAINS_INVALID = -1, -} DHCPUseDomains; - -typedef enum LLDPMode { - LLDP_MODE_NO = 0, - LLDP_MODE_YES = 1, - LLDP_MODE_ROUTERS_ONLY = 2, - _LLDP_MODE_MAX, - _LLDP_MODE_INVALID = -1, -} LLDPMode; - -typedef struct DUID { - /* Value of Type in [DHCP] section */ - DUIDType type; - - uint8_t raw_data_len; - uint8_t raw_data[MAX_DUID_LEN]; -} DUID; - -typedef struct Manager Manager; - -struct Network { - Manager *manager; - - char *filename; - char *name; - - struct ether_addr *match_mac; - char **match_path; - char **match_driver; - char **match_type; - char **match_name; - - Condition *match_host; - Condition *match_virt; - Condition *match_kernel; - Condition *match_arch; - - char *description; - - NetDev *bridge; - NetDev *bond; - NetDev *vrf; - Hashmap *stacked_netdevs; - - /* DHCP Client Support */ - AddressFamilyBoolean dhcp; - DCHPClientIdentifier dhcp_client_identifier; - char *dhcp_vendor_class_identifier; - char *dhcp_hostname; - bool dhcp_use_dns; - bool dhcp_use_ntp; - bool dhcp_use_mtu; - bool dhcp_use_hostname; - DHCPUseDomains dhcp_use_domains; - bool dhcp_send_hostname; - bool dhcp_broadcast; - bool dhcp_critical; - bool dhcp_use_routes; - bool dhcp_use_timezone; - unsigned dhcp_route_metric; - uint32_t dhcp_route_table; - - /* DHCP Server Support */ - bool dhcp_server; - bool dhcp_server_emit_dns; - struct in_addr *dhcp_server_dns; - unsigned n_dhcp_server_dns; - bool dhcp_server_emit_ntp; - struct in_addr *dhcp_server_ntp; - unsigned n_dhcp_server_ntp; - bool dhcp_server_emit_router; - bool dhcp_server_emit_timezone; - char *dhcp_server_timezone; - usec_t dhcp_server_default_lease_time_usec, dhcp_server_max_lease_time_usec; - uint32_t dhcp_server_pool_offset; - uint32_t dhcp_server_pool_size; - - /* IPV4LL Support */ - AddressFamilyBoolean link_local; - bool ipv4ll_route; - - /* Bridge Support */ - bool use_bpdu; - bool hairpin; - bool fast_leave; - bool allow_port_to_be_root; - bool unicast_flood; - unsigned cost; - - bool use_br_vlan; - uint16_t pvid; - uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN]; - uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN]; - - AddressFamilyBoolean ip_forward; - bool ip_masquerade; - - int ipv6_accept_ra; - int ipv6_dad_transmits; - int ipv6_hop_limit; - int proxy_arp; - - bool ipv6_accept_ra_use_dns; - DHCPUseDomains ipv6_accept_ra_use_domains; - uint32_t ipv6_accept_ra_route_table; - - union in_addr_union ipv6_token; - IPv6PrivacyExtensions ipv6_privacy_extensions; - - struct ether_addr *mac; - unsigned mtu; - int arp; - uint32_t iaid; - DUID duid; - - LLDPMode lldp_mode; /* LLDP reception */ - LLDPEmit lldp_emit; /* LLDP transmission */ - - LIST_HEAD(Address, static_addresses); - LIST_HEAD(Route, static_routes); - LIST_HEAD(FdbEntry, static_fdb_entries); - - unsigned n_static_addresses; - unsigned n_static_routes; - unsigned n_static_fdb_entries; - - Hashmap *addresses_by_section; - Hashmap *routes_by_section; - Hashmap *fdb_entries_by_section; - - char **search_domains, **route_domains, **dns, **ntp, **bind_carrier; - - ResolveSupport llmnr; - ResolveSupport mdns; - DnssecMode dnssec_mode; - Set *dnssec_negative_trust_anchors; - - LIST_FIELDS(Network, networks); -}; - -void network_free(Network *network); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free); -#define _cleanup_network_free_ _cleanup_(network_freep) - -int network_load(Manager *manager); - -int network_get_by_name(Manager *manager, const char *name, Network **ret); -int network_get(Manager *manager, struct udev_device *device, const char *ifname, const struct ether_addr *mac, Network **ret); -int network_apply(Manager *manager, Network *network, Link *link); - -bool network_has_static_ipv6_addresses(Network *network); - -int config_parse_netdev(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_domains(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_tunnel(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(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_dns(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); -int config_parse_ipv6token(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_ipv6_privacy_extensions(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_hostname(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_timezone(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_server_dns(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_server_ntp(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_dnssec_negative_trust_anchors(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_use_domains(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_lldp_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_dhcp_route_table(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); - -/* Legacy IPv4LL support */ -int config_parse_ipv4ll(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); - -const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); - -extern const sd_bus_vtable network_vtable[]; - -int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); -int network_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); - -const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_; -IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_; - -const char* dhcp_use_domains_to_string(DHCPUseDomains p) _const_; -DHCPUseDomains dhcp_use_domains_from_string(const char *s) _pure_; - -const char* lldp_mode_to_string(LLDPMode m) _const_; -LLDPMode lldp_mode_from_string(const char *s) _pure_; diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c deleted file mode 100644 index 6f60ee5e31..0000000000 --- a/src/network/networkd-route.c +++ /dev/null @@ -1,918 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "conf-parser.h" -#include "in-addr-util.h" -#include "netlink-util.h" -#include "networkd-route.h" -#include "networkd.h" -#include "parse-util.h" -#include "set.h" -#include "string-util.h" -#include "sysctl-util.h" -#include "util.h" - -#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U - -static unsigned routes_max(void) { - static thread_local unsigned cached = 0; - - _cleanup_free_ char *s4 = NULL, *s6 = NULL; - unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY; - - if (cached > 0) - return cached; - - if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) { - truncate_nl(s4); - if (safe_atou(s4, &val4) >= 0 && - val4 == 2147483647U) - /* This is the default "no limit" value in the kernel */ - val4 = ROUTES_DEFAULT_MAX_PER_FAMILY; - } - - if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) { - truncate_nl(s6); - (void) safe_atou(s6, &val6); - } - - cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) + - MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6); - return cached; -} - -int route_new(Route **ret) { - _cleanup_route_free_ Route *route = NULL; - - route = new0(Route, 1); - if (!route) - return -ENOMEM; - - route->family = AF_UNSPEC; - route->scope = RT_SCOPE_UNIVERSE; - route->protocol = RTPROT_UNSPEC; - route->table = RT_TABLE_MAIN; - route->lifetime = USEC_INFINITY; - - *ret = route; - route = NULL; - - return 0; -} - -int route_new_static(Network *network, unsigned section, Route **ret) { - _cleanup_route_free_ Route *route = NULL; - int r; - - assert(network); - assert(ret); - - if (section) { - route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section)); - if (route) { - *ret = route; - route = NULL; - - return 0; - } - } - - if (network->n_static_routes >= routes_max()) - return -E2BIG; - - r = route_new(&route); - if (r < 0) - return r; - - route->protocol = RTPROT_STATIC; - - if (section) { - route->section = section; - - r = hashmap_put(network->routes_by_section, UINT_TO_PTR(route->section), route); - if (r < 0) - return r; - } - - route->network = network; - LIST_PREPEND(routes, network->static_routes, route); - network->n_static_routes++; - - *ret = route; - route = NULL; - - return 0; -} - -void route_free(Route *route) { - if (!route) - return; - - if (route->network) { - LIST_REMOVE(routes, route->network->static_routes, route); - - assert(route->network->n_static_routes > 0); - route->network->n_static_routes--; - - if (route->section) - hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section)); - } - - if (route->link) { - set_remove(route->link->routes, route); - set_remove(route->link->routes_foreign, route); - } - - sd_event_source_unref(route->expire); - - free(route); -} - -static void route_hash_func(const void *b, struct siphash *state) { - const Route *route = b; - - assert(route); - - siphash24_compress(&route->family, sizeof(route->family), state); - - switch (route->family) { - case AF_INET: - case AF_INET6: - /* Equality of routes are given by the 4-touple - (dst_prefix,dst_prefixlen,tos,priority,table) */ - siphash24_compress(&route->dst, FAMILY_ADDRESS_SIZE(route->family), state); - siphash24_compress(&route->dst_prefixlen, sizeof(route->dst_prefixlen), state); - siphash24_compress(&route->tos, sizeof(route->tos), state); - siphash24_compress(&route->priority, sizeof(route->priority), state); - siphash24_compress(&route->table, sizeof(route->table), state); - - break; - default: - /* treat any other address family as AF_UNSPEC */ - break; - } -} - -static int route_compare_func(const void *_a, const void *_b) { - const Route *a = _a, *b = _b; - - if (a->family < b->family) - return -1; - if (a->family > b->family) - return 1; - - switch (a->family) { - case AF_INET: - case AF_INET6: - if (a->dst_prefixlen < b->dst_prefixlen) - return -1; - if (a->dst_prefixlen > b->dst_prefixlen) - return 1; - - if (a->tos < b->tos) - return -1; - if (a->tos > b->tos) - return 1; - - if (a->priority < b->priority) - return -1; - if (a->priority > b->priority) - return 1; - - if (a->table < b->table) - return -1; - if (a->table > b->table) - return 1; - - return memcmp(&a->dst, &b->dst, FAMILY_ADDRESS_SIZE(a->family)); - default: - /* treat any other address family as AF_UNSPEC */ - return 0; - } -} - -static const struct hash_ops route_hash_ops = { - .hash = route_hash_func, - .compare = route_compare_func -}; - -int route_get(Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, - Route **ret) { - - Route route, *existing; - - assert(link); - assert(dst); - - route = (Route) { - .family = family, - .dst = *dst, - .dst_prefixlen = dst_prefixlen, - .tos = tos, - .priority = priority, - .table = table, - }; - - existing = set_get(link->routes, &route); - if (existing) { - if (ret) - *ret = existing; - return 1; - } - - existing = set_get(link->routes_foreign, &route); - if (existing) { - if (ret) - *ret = existing; - return 0; - } - - return -ENOENT; -} - -static int route_add_internal( - Link *link, - Set **routes, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, - Route **ret) { - - _cleanup_route_free_ Route *route = NULL; - int r; - - assert(link); - assert(routes); - assert(dst); - - r = route_new(&route); - if (r < 0) - return r; - - route->family = family; - route->dst = *dst; - route->dst_prefixlen = dst_prefixlen; - route->tos = tos; - route->priority = priority; - route->table = table; - - r = set_ensure_allocated(routes, &route_hash_ops); - if (r < 0) - return r; - - r = set_put(*routes, route); - if (r < 0) - return r; - - route->link = link; - - if (ret) - *ret = route; - - route = NULL; - - return 0; -} - -int route_add_foreign( - Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, - Route **ret) { - - return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret); -} - -int route_add( - Link *link, - int family, - const union in_addr_union *dst, - unsigned char dst_prefixlen, - unsigned char tos, - uint32_t priority, - unsigned char table, - Route **ret) { - - Route *route; - int r; - - r = route_get(link, family, dst, dst_prefixlen, tos, priority, table, &route); - if (r == -ENOENT) { - /* Route does not exist, create a new one */ - r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, tos, priority, table, &route); - if (r < 0) - return r; - } else if (r == 0) { - /* Take over a foreign route */ - r = set_ensure_allocated(&link->routes, &route_hash_ops); - if (r < 0) - return r; - - r = set_put(link->routes, route); - if (r < 0) - return r; - - set_remove(link->routes_foreign, route); - } else if (r == 1) { - /* Route exists, do nothing */ - ; - } else - return r; - - if (ret) - *ret = route; - - return 0; -} - -int route_update(Route *route, - const union in_addr_union *src, - unsigned char src_prefixlen, - const union in_addr_union *gw, - const union in_addr_union *prefsrc, - unsigned char scope, - unsigned char protocol) { - - assert(route); - assert(src); - assert(gw); - assert(prefsrc); - - route->src = *src; - route->src_prefixlen = src_prefixlen; - route->gw = *gw; - route->prefsrc = *prefsrc; - route->scope = scope; - route->protocol = protocol; - - return 0; -} - -int route_remove(Route *route, Link *link, - sd_netlink_message_handler_t callback) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(link->ifindex > 0); - assert(route->family == AF_INET || route->family == AF_INET6); - - r = sd_rtnl_message_new_route(link->manager->rtnl, &req, - RTM_DELROUTE, route->family, - route->protocol); - if (r < 0) - return log_error_errno(r, "Could not create RTM_DELROUTE message: %m"); - - if (!in_addr_is_null(route->family, &route->gw)) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->gw.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); - } - - if (route->dst_prefixlen) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_DST attribute: %m"); - - r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set destination prefix length: %m"); - } - - if (route->src_prefixlen) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_SRC attribute: %m"); - - r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set source prefix length: %m"); - } - - if (!in_addr_is_null(route->family, &route->prefsrc)) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m"); - } - - r = sd_rtnl_message_route_set_scope(req, route->scope); - if (r < 0) - return log_error_errno(r, "Could not set scope: %m"); - - r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); - if (r < 0) - return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m"); - - r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); - if (r < 0) - return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); - - r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); - if (r < 0) - return log_error_errno(r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - return 0; -} - -static int route_expire_callback(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) { - Link *link = userdata; - int r; - - assert(rtnl); - assert(m); - assert(link); - assert(link->ifname); - - if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER)) - return 1; - - r = sd_netlink_message_get_errno(m); - if (r < 0 && r != -EEXIST) - log_link_warning_errno(link, r, "could not remove route: %m"); - - return 1; -} - -int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) { - Route *route = userdata; - int r; - - assert(route); - - r = route_remove(route, route->link, route_expire_callback); - if (r < 0) - log_warning_errno(r, "Could not remove route: %m"); - else - route_free(route); - - return 1; -} - -int route_configure( - Route *route, - Link *link, - sd_netlink_message_handler_t callback) { - - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL; - _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL; - usec_t lifetime; - int r; - - assert(link); - assert(link->manager); - assert(link->manager->rtnl); - assert(link->ifindex > 0); - assert(route->family == AF_INET || route->family == AF_INET6); - - if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 && - set_size(link->routes) >= routes_max()) - return -E2BIG; - - r = sd_rtnl_message_new_route(link->manager->rtnl, &req, - RTM_NEWROUTE, route->family, - route->protocol); - if (r < 0) - return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m"); - - if (!in_addr_is_null(route->family, &route->gw)) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->gw.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m"); - - r = sd_rtnl_message_route_set_family(req, route->family); - if (r < 0) - return log_error_errno(r, "Could not set route family: %m"); - } - - if (route->dst_prefixlen) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_DST attribute: %m"); - - r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set destination prefix length: %m"); - } - - if (route->src_prefixlen) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_SRC attribute: %m"); - - r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen); - if (r < 0) - return log_error_errno(r, "Could not set source prefix length: %m"); - } - - if (!in_addr_is_null(route->family, &route->prefsrc)) { - if (route->family == AF_INET) - r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc.in); - else if (route->family == AF_INET6) - r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc.in6); - if (r < 0) - return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m"); - } - - r = sd_rtnl_message_route_set_scope(req, route->scope); - if (r < 0) - return log_error_errno(r, "Could not set scope: %m"); - - r = sd_rtnl_message_route_set_flags(req, route->flags); - if (r < 0) - return log_error_errno(r, "Could not set flags: %m"); - - if (route->table != RT_TABLE_MAIN) { - if (route->table < 256) { - r = sd_rtnl_message_route_set_table(req, route->table); - if (r < 0) - return log_error_errno(r, "Could not set route table: %m"); - } else { - r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC); - if (r < 0) - return log_error_errno(r, "Could not set route table: %m"); - - /* Table attribute to allow more than 256. */ - r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table)); - if (r < 0) - return log_error_errno(r, "Could not append RTA_TABLE attribute: %m"); - } - } - - r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority); - if (r < 0) - return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m"); - - r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref); - if (r < 0) - return log_error_errno(r, "Could not append RTA_PREF attribute: %m"); - - r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex); - if (r < 0) - return log_error_errno(r, "Could not append RTA_OIF attribute: %m"); - - r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL); - if (r < 0) - return log_error_errno(r, "Could not send rtnetlink message: %m"); - - link_ref(link); - - lifetime = route->lifetime; - - r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route); - if (r < 0) - return log_error_errno(r, "Could not add route: %m"); - - /* TODO: drop expiration handling once it can be pushed into the kernel */ - route->lifetime = lifetime; - - if (route->lifetime != USEC_INFINITY) { - r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(), - route->lifetime, 0, route_expire_handler, route); - if (r < 0) - return log_error_errno(r, "Could not arm expiration timer: %m"); - } - - sd_event_source_unref(route->expire); - route->expire = expire; - expire = NULL; - - return 0; -} - -int config_parse_gateway(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_route_free_ Route *n = NULL; - union in_addr_union buffer; - int r, f; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - if (streq(section, "Network")) { - /* we are not in an Route section, so treat - * this as the special '0' section */ - section_line = 0; - } - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - r = in_addr_from_string_auto(rvalue, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Route is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - n->family = f; - n->gw = buffer; - n = NULL; - - return 0; -} - -int config_parse_preferred_src(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_route_free_ Route *n = NULL; - union in_addr_union buffer; - int r, f; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - r = in_addr_from_string_auto(rvalue, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Preferred source is invalid, ignoring assignment: %s", rvalue); - return 0; - } - - n->family = f; - n->prefsrc = buffer; - n = NULL; - - return 0; -} - -int config_parse_destination(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_route_free_ Route *n = NULL; - const char *address, *e; - union in_addr_union buffer; - unsigned char prefixlen; - int r, f; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - /* Destination|Source=address/prefixlen */ - - /* address */ - e = strchr(rvalue, '/'); - if (e) - address = strndupa(rvalue, e - rvalue); - else - address = rvalue; - - r = in_addr_from_string_auto(address, &f, &buffer); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Destination is invalid, ignoring assignment: %s", address); - return 0; - } - - if (f != AF_INET && f != AF_INET6) { - log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown address family, ignoring assignment: %s", address); - return 0; - } - - /* prefixlen */ - if (e) { - r = safe_atou8(e + 1, &prefixlen); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, "Route destination prefix length is invalid, ignoring assignment: %s", e + 1); - return 0; - } - } else { - switch (f) { - case AF_INET: - prefixlen = 32; - break; - case AF_INET6: - prefixlen = 128; - break; - } - } - - n->family = f; - if (streq(lvalue, "Destination")) { - n->dst = buffer; - n->dst_prefixlen = prefixlen; - } else if (streq(lvalue, "Source")) { - n->src = buffer; - n->src_prefixlen = prefixlen; - } else - assert_not_reached(lvalue); - - n = NULL; - - return 0; -} - -int config_parse_route_priority(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_route_free_ Route *n = NULL; - uint32_t k; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - r = safe_atou32(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue); - return 0; - } - - n->priority = k; - n = NULL; - - return 0; -} - -int config_parse_route_scope(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_route_free_ Route *n = NULL; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - if (streq(rvalue, "host")) - n->scope = RT_SCOPE_HOST; - else if (streq(rvalue, "link")) - n->scope = RT_SCOPE_LINK; - else if (streq(rvalue, "global")) - n->scope = RT_SCOPE_UNIVERSE; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue); - return 0; - } - - n = NULL; - - return 0; -} - -int config_parse_route_table(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) { - _cleanup_route_free_ Route *n = NULL; - Network *network = userdata; - uint32_t k; - int r; - - assert(filename); - assert(section); - assert(lvalue); - assert(rvalue); - assert(data); - - r = route_new_static(network, section_line, &n); - if (r < 0) - return r; - - r = safe_atou32(rvalue, &k); - if (r < 0) { - log_syntax(unit, LOG_ERR, filename, line, r, - "Could not parse route table number \"%s\", ignoring assignment: %m", rvalue); - return 0; - } - - n->table = k; - - n = NULL; - - return 0; -} diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h deleted file mode 100644 index d4e4dbac0b..0000000000 --- a/src/network/networkd-route.h +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct Route Route; - -#include "networkd-network.h" - -struct Route { - Network *network; - unsigned section; - - Link *link; - - int family; - unsigned char dst_prefixlen; - unsigned char src_prefixlen; - unsigned char scope; - unsigned char protocol; /* RTPROT_* */ - unsigned char tos; - uint32_t priority; /* note that ip(8) calls this 'metric' */ - uint32_t table; - unsigned char pref; - unsigned flags; - - union in_addr_union gw; - union in_addr_union dst; - union in_addr_union src; - union in_addr_union prefsrc; - - usec_t lifetime; - sd_event_source *expire; - - LIST_FIELDS(Route, routes); -}; - -int route_new_static(Network *network, unsigned section, Route **ret); -int route_new(Route **ret); -void route_free(Route *route); -int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback); -int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback); - -int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret); -int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol); - -int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free); -#define _cleanup_route_free_ _cleanup_(route_freep) - -int config_parse_gateway(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_preferred_src(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_destination(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_route_priority(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_route_scope(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_route_table(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-util.c b/src/network/networkd-util.c deleted file mode 100644 index 555a7c68a1..0000000000 --- a/src/network/networkd-util.c +++ /dev/null @@ -1,101 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "conf-parser.h" -#include "networkd-util.h" -#include "parse-util.h" -#include "string-table.h" -#include "string-util.h" -#include "util.h" - -const char *address_family_boolean_to_string(AddressFamilyBoolean b) { - if (b == ADDRESS_FAMILY_YES || - b == ADDRESS_FAMILY_NO) - return yes_no(b == ADDRESS_FAMILY_YES); - - if (b == ADDRESS_FAMILY_IPV4) - return "ipv4"; - if (b == ADDRESS_FAMILY_IPV6) - return "ipv6"; - - return NULL; -} - -AddressFamilyBoolean address_family_boolean_from_string(const char *s) { - int r; - - /* Make this a true superset of a boolean */ - - r = parse_boolean(s); - if (r > 0) - return ADDRESS_FAMILY_YES; - if (r == 0) - return ADDRESS_FAMILY_NO; - - if (streq(s, "ipv4")) - return ADDRESS_FAMILY_IPV4; - if (streq(s, "ipv6")) - return ADDRESS_FAMILY_IPV6; - - return _ADDRESS_FAMILY_BOOLEAN_INVALID; -} - -DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option"); - -int config_parse_address_family_boolean_with_kernel( - 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) { - - AddressFamilyBoolean *fwd = data, s; - - assert(filename); - assert(lvalue); - assert(rvalue); - assert(data); - - /* This function is mostly obsolete now. It simply redirects - * "kernel" to "no". In older networkd versions we used to - * distuingish IPForward=off from IPForward=kernel, where the - * former would explicitly turn off forwarding while the - * latter would simply not touch the setting. But that logic - * is gone, hence silently accept the old setting, but turn it - * to "no". */ - - s = address_family_boolean_from_string(rvalue); - if (s < 0) { - if (streq(rvalue, "kernel")) - s = ADDRESS_FAMILY_NO; - else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForward= option, ignoring: %s", rvalue); - return 0; - } - } - - *fwd = s; - - return 0; -} diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h deleted file mode 100644 index d5c385bea4..0000000000 --- a/src/network/networkd-util.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "macro.h" - -typedef enum AddressFamilyBoolean { - /* This is a bitmask, though it usually doesn't feel that way! */ - ADDRESS_FAMILY_NO = 0, - ADDRESS_FAMILY_IPV4 = 1, - ADDRESS_FAMILY_IPV6 = 2, - ADDRESS_FAMILY_YES = 3, - _ADDRESS_FAMILY_BOOLEAN_MAX, - _ADDRESS_FAMILY_BOOLEAN_INVALID = -1, -} AddressFamilyBoolean; - -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); -int config_parse_address_family_boolean_with_kernel(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); - -const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_; -AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_; diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c deleted file mode 100644 index e63ba07e90..0000000000 --- a/src/network/networkd-wait-online-link.c +++ /dev/null @@ -1,130 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - Copyright 2014 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "sd-network.h" - -#include "alloc-util.h" -#include "networkd-wait-online-link.h" -#include "string-util.h" - -int link_new(Manager *m, Link **ret, int ifindex, const char *ifname) { - _cleanup_(link_freep) Link *l = NULL; - int r; - - assert(m); - assert(ifindex > 0); - - r = hashmap_ensure_allocated(&m->links, NULL); - if (r < 0) - return r; - - r = hashmap_ensure_allocated(&m->links_by_name, &string_hash_ops); - if (r < 0) - return r; - - l = new0(Link, 1); - if (!l) - return -ENOMEM; - - l->manager = m; - - l->ifname = strdup(ifname); - if (!l->ifname) - return -ENOMEM; - - r = hashmap_put(m->links_by_name, l->ifname, l); - if (r < 0) - return r; - - l->ifindex = ifindex; - - r = hashmap_put(m->links, INT_TO_PTR(ifindex), l); - if (r < 0) - return r; - - if (ret) - *ret = l; - l = NULL; - - return 0; -} - -Link *link_free(Link *l) { - - if (!l) - return NULL; - - if (l->manager) { - hashmap_remove(l->manager->links, INT_TO_PTR(l->ifindex)); - hashmap_remove(l->manager->links_by_name, l->ifname); - } - - free(l->ifname); - return mfree(l); - } - -int link_update_rtnl(Link *l, sd_netlink_message *m) { - const char *ifname; - int r; - - assert(l); - assert(l->manager); - assert(m); - - r = sd_rtnl_message_link_get_flags(m, &l->flags); - if (r < 0) - return r; - - r = sd_netlink_message_read_string(m, IFLA_IFNAME, &ifname); - if (r < 0) - return r; - - if (!streq(l->ifname, ifname)) { - char *new_ifname; - - new_ifname = strdup(ifname); - if (!new_ifname) - return -ENOMEM; - - hashmap_remove(l->manager->links_by_name, l->ifname); - free(l->ifname); - l->ifname = new_ifname; - - r = hashmap_put(l->manager->links_by_name, l->ifname, l); - if (r < 0) - return r; - } - - return 0; -} - -int link_update_monitor(Link *l) { - assert(l); - - l->operational_state = mfree(l->operational_state); - - sd_network_link_get_operational_state(l->ifindex, &l->operational_state); - - l->state = mfree(l->state); - - sd_network_link_get_setup_state(l->ifindex, &l->state); - - return 0; -} diff --git a/src/network/networkd-wait-online-link.h b/src/network/networkd-wait-online-link.h deleted file mode 100644 index dc35085c55..0000000000 --- a/src/network/networkd-wait-online-link.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Lennart Poettering - Copyright 2014 Tom Gundersen - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -typedef struct Link Link; - -#include "networkd-wait-online.h" - -struct Link { - Manager *manager; - - int ifindex; - char *ifname; - unsigned flags; - - char *operational_state; - char *state; -}; - -int link_new(Manager *m, Link **ret, int ifindex, const char *ifname); -Link *link_free(Link *l); -int link_update_rtnl(Link *l, sd_netlink_message *m); -int link_update_monitor(Link *l); -bool link_relevant(Link *l); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_free); diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c deleted file mode 100644 index 725b3310dd..0000000000 --- a/src/network/networkd-wait-online-manager.c +++ /dev/null @@ -1,329 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <netinet/ether.h> -#include <linux/if.h> -#include <fnmatch.h> - -#include "alloc-util.h" -#include "netlink-util.h" -#include "network-internal.h" -#include "networkd-wait-online-link.h" -#include "networkd-wait-online.h" -#include "time-util.h" -#include "util.h" - -bool manager_ignore_link(Manager *m, Link *link) { - assert(m); - assert(link); - - /* always ignore the loopback interface */ - if (link->flags & IFF_LOOPBACK) - return true; - - /* if interfaces are given on the command line, ignore all others */ - if (m->interfaces && !strv_contains(m->interfaces, link->ifname)) - return true; - - /* ignore interfaces we explicitly are asked to ignore */ - return strv_fnmatch(m->ignore, link->ifname, 0); -} - -bool manager_all_configured(Manager *m) { - Iterator i; - Link *l; - char **ifname; - bool one_ready = false; - - /* wait for all the links given on the command line to appear */ - STRV_FOREACH(ifname, m->interfaces) { - l = hashmap_get(m->links_by_name, *ifname); - if (!l) { - log_debug("still waiting for %s", *ifname); - return false; - } - } - - /* wait for all links networkd manages to be in admin state 'configured' - and at least one link to gain a carrier */ - HASHMAP_FOREACH(l, m->links, i) { - if (manager_ignore_link(m, l)) { - log_info("ignoring: %s", l->ifname); - continue; - } - - if (!l->state) { - log_debug("link %s has not yet been processed by udev", - l->ifname); - return false; - } - - if (STR_IN_SET(l->state, "configuring", "pending")) { - log_debug("link %s is being processed by networkd", - l->ifname); - return false; - } - - if (l->operational_state && - STR_IN_SET(l->operational_state, "degraded", "routable")) - /* we wait for at least one link to be ready, - regardless of who manages it */ - one_ready = true; - } - - return one_ready; -} - -static int manager_process_link(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { - Manager *m = userdata; - uint16_t type; - Link *l; - const char *ifname; - int ifindex, r; - - assert(rtnl); - assert(m); - assert(mm); - - r = sd_netlink_message_get_type(mm, &type); - if (r < 0) - goto fail; - - r = sd_rtnl_message_link_get_ifindex(mm, &ifindex); - if (r < 0) - goto fail; - - r = sd_netlink_message_read_string(mm, IFLA_IFNAME, &ifname); - if (r < 0) - goto fail; - - l = hashmap_get(m->links, INT_TO_PTR(ifindex)); - - switch (type) { - - case RTM_NEWLINK: - if (!l) { - log_debug("Found link %i", ifindex); - - r = link_new(m, &l, ifindex, ifname); - if (r < 0) - goto fail; - - r = link_update_monitor(l); - if (r < 0) - goto fail; - } - - r = link_update_rtnl(l, mm); - if (r < 0) - goto fail; - - break; - - case RTM_DELLINK: - if (l) { - log_debug("Removing link %i", l->ifindex); - link_free(l); - } - - break; - } - - return 0; - -fail: - log_warning_errno(r, "Failed to process RTNL link message: %m"); - return 0; -} - -static int on_rtnl_event(sd_netlink *rtnl, sd_netlink_message *mm, void *userdata) { - Manager *m = userdata; - int r; - - r = manager_process_link(rtnl, mm, m); - if (r < 0) - return r; - - if (manager_all_configured(m)) - sd_event_exit(m->event, 0); - - return 1; -} - -static int manager_rtnl_listen(Manager *m) { - _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL, *reply = NULL; - sd_netlink_message *i; - int r; - - assert(m); - - /* First, subscribe to interfaces coming and going */ - r = sd_netlink_open(&m->rtnl); - if (r < 0) - return r; - - r = sd_netlink_attach_event(m->rtnl, m->event, 0); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_NEWLINK, on_rtnl_event, m); - if (r < 0) - return r; - - r = sd_netlink_add_match(m->rtnl, RTM_DELLINK, on_rtnl_event, m); - if (r < 0) - return r; - - /* Then, enumerate all links */ - r = sd_rtnl_message_new_link(m->rtnl, &req, RTM_GETLINK, 0); - if (r < 0) - return r; - - r = sd_netlink_message_request_dump(req, true); - if (r < 0) - return r; - - r = sd_netlink_call(m->rtnl, req, 0, &reply); - if (r < 0) - return r; - - for (i = reply; i; i = sd_netlink_message_next(i)) { - r = manager_process_link(m->rtnl, i, m); - if (r < 0) - return r; - } - - return r; -} - -static int on_network_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - Manager *m = userdata; - Iterator i; - Link *l; - int r; - - assert(m); - - sd_network_monitor_flush(m->network_monitor); - - HASHMAP_FOREACH(l, m->links, i) { - r = link_update_monitor(l); - if (r < 0) - log_warning_errno(r, "Failed to update monitor information for %i: %m", l->ifindex); - } - - if (manager_all_configured(m)) - sd_event_exit(m->event, 0); - - return 0; -} - -static int manager_network_monitor_listen(Manager *m) { - int r, fd, events; - - assert(m); - - r = sd_network_monitor_new(&m->network_monitor, NULL); - if (r < 0) - return r; - - fd = sd_network_monitor_get_fd(m->network_monitor); - if (fd < 0) - return fd; - - events = sd_network_monitor_get_events(m->network_monitor); - if (events < 0) - return events; - - r = sd_event_add_io(m->event, &m->network_monitor_event_source, - fd, events, &on_network_event, m); - if (r < 0) - return r; - - return 0; -} - -int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout) { - _cleanup_(manager_freep) Manager *m = NULL; - int r; - - assert(ret); - - m = new0(Manager, 1); - if (!m) - return -ENOMEM; - - m->interfaces = interfaces; - m->ignore = ignore; - - r = sd_event_default(&m->event); - if (r < 0) - return r; - - sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL); - sd_event_add_signal(m->event, NULL, SIGINT, NULL, NULL); - - if (timeout > 0) { - usec_t usec; - - usec = now(clock_boottime_or_monotonic()) + timeout; - - r = sd_event_add_time(m->event, NULL, clock_boottime_or_monotonic(), usec, 0, NULL, INT_TO_PTR(-ETIMEDOUT)); - if (r < 0) - return r; - } - - sd_event_set_watchdog(m->event, true); - - r = manager_network_monitor_listen(m); - if (r < 0) - return r; - - r = manager_rtnl_listen(m); - if (r < 0) - return r; - - *ret = m; - m = NULL; - - return 0; -} - -void manager_free(Manager *m) { - Link *l; - - if (!m) - return; - - while ((l = hashmap_first(m->links))) - link_free(l); - hashmap_free(m->links); - hashmap_free(m->links_by_name); - - sd_event_source_unref(m->network_monitor_event_source); - sd_network_monitor_unref(m->network_monitor); - - sd_event_source_unref(m->rtnl_event_source); - sd_netlink_unref(m->rtnl); - - sd_event_unref(m->event); - free(m); - - return; -} diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c deleted file mode 100644 index 3220c4b7ef..0000000000 --- a/src/network/networkd-wait-online.c +++ /dev/null @@ -1,166 +0,0 @@ - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <getopt.h> - -#include "sd-daemon.h" - -#include "networkd-wait-online.h" -#include "signal-util.h" -#include "strv.h" - -static bool arg_quiet = false; -static usec_t arg_timeout = 120 * USEC_PER_SEC; -static char **arg_interfaces = NULL; -static char **arg_ignore = NULL; - -static void help(void) { - printf("%s [OPTIONS...]\n\n" - "Block until network is configured.\n\n" - " -h --help Show this help\n" - " --version Print version string\n" - " -q --quiet Do not show status information\n" - " -i --interface=INTERFACE Block until at least these interfaces have appeared\n" - " --ignore=INTERFACE Don't take these interfaces into account\n" - " --timeout=SECS Maximum time to wait for network connectivity\n" - , program_invocation_short_name); -} - -static int parse_argv(int argc, char *argv[]) { - - enum { - ARG_VERSION = 0x100, - ARG_IGNORE, - ARG_TIMEOUT, - }; - - static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "quiet", no_argument, NULL, 'q' }, - { "interface", required_argument, NULL, 'i' }, - { "ignore", required_argument, NULL, ARG_IGNORE }, - { "timeout", required_argument, NULL, ARG_TIMEOUT }, - {} - }; - - int c, r; - - assert(argc >= 0); - assert(argv); - - while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0) - - switch (c) { - - case 'h': - help(); - return 0; - - case 'q': - arg_quiet = true; - break; - - case ARG_VERSION: - return version(); - - case 'i': - if (strv_extend(&arg_interfaces, optarg) < 0) - return log_oom(); - - break; - - case ARG_IGNORE: - if (strv_extend(&arg_ignore, optarg) < 0) - return log_oom(); - - break; - - case ARG_TIMEOUT: - r = parse_sec(optarg, &arg_timeout); - if (r < 0) - return r; - - break; - - case '?': - return -EINVAL; - - default: - assert_not_reached("Unhandled option"); - } - - return 1; -} - -int main(int argc, char *argv[]) { - _cleanup_(manager_freep) Manager *m = NULL; - int r; - - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - umask(0022); - - r = parse_argv(argc, argv); - if (r <= 0) - return r; - - if (arg_quiet) - log_set_max_level(LOG_WARNING); - - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); - - r = manager_new(&m, arg_interfaces, arg_ignore, arg_timeout); - if (r < 0) { - log_error_errno(r, "Could not create manager: %m"); - goto finish; - } - - if (manager_all_configured(m)) { - r = 0; - goto finish; - } - - sd_notify(false, - "READY=1\n" - "STATUS=Waiting for network connections..."); - - r = sd_event_loop(m->event); - if (r < 0) { - log_error_errno(r, "Event loop failed: %m"); - goto finish; - } - -finish: - strv_free(arg_interfaces); - strv_free(arg_ignore); - - if (r >= 0) { - sd_notify(false, "STATUS=All interfaces configured..."); - - return EXIT_SUCCESS; - } else { - sd_notify(false, "STATUS=Failed waiting for network connectivity..."); - - return EXIT_FAILURE; - } -} diff --git a/src/network/networkd-wait-online.h b/src/network/networkd-wait-online.h deleted file mode 100644 index f91995c306..0000000000 --- a/src/network/networkd-wait-online.h +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2014 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "sd-event.h" -#include "sd-netlink.h" -#include "sd-network.h" - -#include "hashmap.h" - -typedef struct Manager Manager; - -#include "networkd-wait-online-link.h" - -struct Manager { - Hashmap *links; - Hashmap *links_by_name; - - char **interfaces; - char **ignore; - - sd_netlink *rtnl; - sd_event_source *rtnl_event_source; - - sd_network_monitor *network_monitor; - sd_event_source *network_monitor_event_source; - - sd_event *event; -}; - -void manager_free(Manager *m); -int manager_new(Manager **ret, char **interfaces, char **ignore, usec_t timeout); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); - -bool manager_all_configured(Manager *m); -bool manager_ignore_link(Manager *m, Link *link); diff --git a/src/network/networkd.c b/src/network/networkd.c deleted file mode 100644 index c8f81a2ca6..0000000000 --- a/src/network/networkd.c +++ /dev/null @@ -1,139 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "sd-daemon.h" - -#include "capability-util.h" -#include "networkd.h" -#include "networkd-conf.h" -#include "signal-util.h" -#include "user-util.h" - -int main(int argc, char *argv[]) { - _cleanup_manager_free_ Manager *m = NULL; - const char *user = "systemd-network"; - uid_t uid; - gid_t gid; - int r; - - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - umask(0022); - - if (argc != 1) { - log_error("This program takes no arguments."); - r = -EINVAL; - goto out; - } - - r = get_user_creds(&user, &uid, &gid, NULL, NULL); - if (r < 0) { - log_error_errno(r, "Cannot resolve user name %s: %m", user); - goto out; - } - - /* Always create the directories people can create inotify - * watches in. */ - r = mkdir_safe_label("/run/systemd/netif", 0755, uid, gid); - if (r < 0) - 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_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_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_warning_errno(r, "Could not create runtime directory 'lldp': %m"); - - r = drop_privileges(uid, gid, - (1ULL << CAP_NET_ADMIN) | - (1ULL << CAP_NET_BIND_SERVICE) | - (1ULL << CAP_NET_BROADCAST) | - (1ULL << CAP_NET_RAW)); - if (r < 0) - goto out; - - assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); - - r = manager_new(&m); - if (r < 0) { - log_error_errno(r, "Could not create manager: %m"); - goto out; - } - - r = manager_connect_bus(m); - if (r < 0) { - log_error_errno(r, "Could not connect to bus: %m"); - goto out; - } - - r = manager_parse_config_file(m); - if (r < 0) - log_warning_errno(r, "Failed to parse configuration file: %m"); - - r = manager_load_config(m); - if (r < 0) { - log_error_errno(r, "Could not load configuration files: %m"); - goto out; - } - - r = manager_rtnl_enumerate_links(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate links: %m"); - goto out; - } - - r = manager_rtnl_enumerate_addresses(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate addresses: %m"); - goto out; - } - - r = manager_rtnl_enumerate_routes(m); - if (r < 0) { - log_error_errno(r, "Could not enumerate routes: %m"); - goto out; - } - - log_info("Enumeration completed"); - - sd_notify(false, - "READY=1\n" - "STATUS=Processing requests..."); - - r = manager_run(m); - if (r < 0) { - log_error_errno(r, "Event loop failed: %m"); - goto out; - } - -out: - sd_notify(false, - "STOPPING=1\n" - "STATUS=Shutting down..."); - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/network/networkd.h b/src/network/networkd.h deleted file mode 100644 index cb1b73145e..0000000000 --- a/src/network/networkd.h +++ /dev/null @@ -1,114 +0,0 @@ -#pragma once - -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <arpa/inet.h> - -#include "sd-bus.h" -#include "sd-event.h" -#include "sd-netlink.h" -#include "udev.h" - -#include "dhcp-identifier.h" -#include "hashmap.h" -#include "list.h" - -#include "networkd-address-pool.h" -#include "networkd-link.h" -#include "networkd-netdev-bond.h" -#include "networkd-netdev-bridge.h" -#include "networkd-netdev-dummy.h" -#include "networkd-netdev-ipvlan.h" -#include "networkd-netdev-macvlan.h" -#include "networkd-netdev-tunnel.h" -#include "networkd-netdev-tuntap.h" -#include "networkd-netdev-veth.h" -#include "networkd-netdev-vlan.h" -#include "networkd-netdev-vrf.h" -#include "networkd-netdev-vxlan.h" -#include "networkd-netdev-vcan.h" -#include "networkd-network.h" -#include "networkd-util.h" - -extern const char* const network_dirs[]; - -struct Manager { - sd_netlink *rtnl; - sd_event *event; - sd_event_source *bus_retry_event_source; - sd_bus *bus; - sd_bus_slot *prepare_for_sleep_slot; - struct udev *udev; - struct udev_monitor *udev_monitor; - sd_event_source *udev_event_source; - - bool enumerating:1; - bool dirty:1; - - Set *dirty_links; - - char *state_file; - LinkOperationalState operational_state; - - Hashmap *links; - Hashmap *netdevs; - Hashmap *networks_by_name; - LIST_HEAD(Network, networks); - LIST_HEAD(AddressPool, address_pools); - - usec_t network_dirs_ts_usec; - - DUID duid; -}; - -static inline const DUID* link_duid(const Link *link) { - if (link->network->duid.type != _DUID_TYPE_INVALID) - return &link->network->duid; - else - return &link->manager->duid; -} - -extern const sd_bus_vtable manager_vtable[]; - -int manager_new(Manager **ret); -void manager_free(Manager *m); - -int manager_connect_bus(Manager *m); -int manager_run(Manager *m); - -int manager_load_config(Manager *m); -bool manager_should_reload(Manager *m); - -int manager_rtnl_enumerate_links(Manager *m); -int manager_rtnl_enumerate_addresses(Manager *m); -int manager_rtnl_enumerate_routes(Manager *m); - -int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata); -int manager_rtnl_process_route(sd_netlink *nl, sd_netlink_message *message, void *userdata); - -int manager_send_changed(Manager *m, const char *property, ...) _sentinel_; -void manager_dirty(Manager *m); - -int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found); - -Link* manager_find_uplink(Manager *m, Link *exclude); - -DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); -#define _cleanup_manager_free_ _cleanup_(manager_freep) diff --git a/src/network/org.freedesktop.network1.conf b/src/network/org.freedesktop.network1.conf deleted file mode 100644 index 52dad33668..0000000000 --- a/src/network/org.freedesktop.network1.conf +++ /dev/null @@ -1,42 +0,0 @@ -<?xml version="1.0"?> <!--*-nxml-*--> -<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> - -<!-- - This file is part of systemd. - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. ---> - -<busconfig> - - <policy user="systemd-network"> - <allow own="org.freedesktop.network1"/> - <allow send_destination="org.freedesktop.network1"/> - <allow receive_sender="org.freedesktop.network1"/> - </policy> - - <policy context="default"> - <deny send_destination="org.freedesktop.network1"/> - - <allow send_destination="org.freedesktop.network1" - send_interface="org.freedesktop.DBus.Introspectable"/> - - <allow send_destination="org.freedesktop.network1" - send_interface="org.freedesktop.DBus.Peer"/> - - <allow send_destination="org.freedesktop.network1" - send_interface="org.freedesktop.DBus.Properties" - send_member="Get"/> - - <allow send_destination="org.freedesktop.network1" - send_interface="org.freedesktop.DBus.Properties" - send_member="GetAll"/> - - <allow receive_sender="org.freedesktop.network1"/> - </policy> - -</busconfig> diff --git a/src/network/org.freedesktop.network1.service b/src/network/org.freedesktop.network1.service deleted file mode 100644 index bea885fe53..0000000000 --- a/src/network/org.freedesktop.network1.service +++ /dev/null @@ -1,12 +0,0 @@ -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -[D-BUS Service] -Name=org.freedesktop.network1 -Exec=/bin/false -User=root -SystemdService=dbus-org.freedesktop.network1.service diff --git a/src/network/test-network-tables.c b/src/network/test-network-tables.c deleted file mode 100644 index adbe09a5e1..0000000000 --- a/src/network/test-network-tables.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "dhcp6-internal.h" -#include "dhcp6-protocol.h" -#include "ethtool-util.h" -#include "netlink-internal.h" -#include "networkd-netdev-bond.h" -#include "networkd-netdev-macvlan.h" -#include "networkd.h" -#include "test-tables.h" - -int main(int argc, char **argv) { - test_table(bond_mode, NETDEV_BOND_MODE); - /* test_table(link_state, LINK_STATE); — not a reversible mapping */ - test_table(link_operstate, LINK_OPERSTATE); - test_table(address_family_boolean, ADDRESS_FAMILY_BOOLEAN); - test_table(netdev_kind, NETDEV_KIND); - test_table(dhcp6_message_status, DHCP6_STATUS); - test_table(duplex, DUP); - test_table(wol, WOL); - test_table(nl_union_link_info_data, NL_UNION_LINK_INFO_DATA); - - test_table_sparse(macvlan_mode, NETDEV_MACVLAN_MODE); - test_table_sparse(ipvlan_mode, NETDEV_IPVLAN_MODE); - test_table_sparse(dhcp6_message_type, DHCP6_MESSAGE); - - return EXIT_SUCCESS; -} diff --git a/src/network/test-network.c b/src/network/test-network.c deleted file mode 100644 index 855646173f..0000000000 --- a/src/network/test-network.c +++ /dev/null @@ -1,216 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2013 Tom Gundersen <teg@jklm.no> - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "alloc-util.h" -#include "dhcp-lease-internal.h" -#include "network-internal.h" -#include "networkd.h" - -static void test_deserialize_in_addr(void) { - _cleanup_free_ struct in_addr *addresses = NULL; - _cleanup_free_ struct in6_addr *addresses6 = NULL; - struct in_addr a, b, c; - struct in6_addr d, e, f; - int size; - const char *addresses_string = "192.168.0.1 0:0:0:0:0:FFFF:204.152.189.116 192.168.0.2 ::1 192.168.0.3 1:0:0:0:0:0:0:8"; - - assert_se(inet_pton(AF_INET, "0:0:0:0:0:FFFF:204.152.189.116", &a) == 0); - assert_se(inet_pton(AF_INET6, "192.168.0.1", &d) == 0); - - assert_se(inet_pton(AF_INET, "192.168.0.1", &a) == 1); - assert_se(inet_pton(AF_INET, "192.168.0.2", &b) == 1); - assert_se(inet_pton(AF_INET, "192.168.0.3", &c) == 1); - assert_se(inet_pton(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116", &d) == 1); - assert_se(inet_pton(AF_INET6, "::1", &e) == 1); - assert_se(inet_pton(AF_INET6, "1:0:0:0:0:0:0:8", &f) == 1); - - assert_se((size = deserialize_in_addrs(&addresses, addresses_string)) >= 0); - assert_se(size == 3); - assert_se(!memcmp(&a, &addresses[0], sizeof(struct in_addr))); - assert_se(!memcmp(&b, &addresses[1], sizeof(struct in_addr))); - assert_se(!memcmp(&c, &addresses[2], sizeof(struct in_addr))); - - assert_se((size = deserialize_in6_addrs(&addresses6, addresses_string)) >= 0); - assert_se(size == 3); - assert_se(!memcmp(&d, &addresses6[0], sizeof(struct in6_addr))); - assert_se(!memcmp(&e, &addresses6[1], sizeof(struct in6_addr))); - assert_se(!memcmp(&f, &addresses6[2], sizeof(struct in6_addr))); -} - -static void test_deserialize_dhcp_routes(void) { - size_t size, allocated; - - { - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, "") >= 0); - assert_se(size == 0); - } - - { - /* no errors */ - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0/24,10.1.2.1 0.0.0.0/0,10.0.1.1"; - - assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); - - assert_se(size == 3); - assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); - assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); - assert_se(routes[0].dst_prefixlen == 16); - - assert_se(routes[1].dst_addr.s_addr == inet_addr("10.1.2.0")); - assert_se(routes[1].gw_addr.s_addr == inet_addr("10.1.2.1")); - assert_se(routes[1].dst_prefixlen == 24); - - assert_se(routes[2].dst_addr.s_addr == inet_addr("0.0.0.0")); - assert_se(routes[2].gw_addr.s_addr == inet_addr("10.0.1.1")); - assert_se(routes[2].dst_prefixlen == 0); - } - - { - /* error in second word */ - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - const char *routes_string = "192.168.0.0/16,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.1"; - - assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); - - assert_se(size == 2); - assert_se(routes[0].dst_addr.s_addr == inet_addr("192.168.0.0")); - assert_se(routes[0].gw_addr.s_addr == inet_addr("192.168.0.1")); - assert_se(routes[0].dst_prefixlen == 16); - - assert_se(routes[1].dst_addr.s_addr == inet_addr("0.0.0.0")); - assert_se(routes[1].gw_addr.s_addr == inet_addr("10.0.1.1")); - assert_se(routes[1].dst_prefixlen == 0); - } - - { - /* error in every word */ - _cleanup_free_ struct sd_dhcp_route *routes = NULL; - const char *routes_string = "192.168.0.0/55,192.168.0.1 10.1.2.0#24,10.1.2.1 0.0.0.0/0,10.0.1.X"; - - assert_se(deserialize_dhcp_routes(&routes, &size, &allocated, routes_string) >= 0); - assert_se(size == 0); - } -} - -static int test_load_config(Manager *manager) { - int r; -/* TODO: should_reload, is false if the config dirs do not exist, so - * so we can't do this test here, move it to a test for paths_check_timestamps - * directly - * - * assert_se(network_should_reload(manager) == true); -*/ - - r = manager_load_config(manager); - if (r == -EPERM) - return r; - assert_se(r >= 0); - - assert_se(manager_should_reload(manager) == false); - - return 0; -} - -static void test_network_get(Manager *manager, struct udev_device *loopback) { - Network *network; - const struct ether_addr mac = {}; - - /* let's assume that the test machine does not have a .network file - that applies to the loopback device... */ - assert_se(network_get(manager, loopback, "lo", &mac, &network) == -ENOENT); - assert_se(!network); -} - -static void test_address_equality(void) { - _cleanup_address_free_ Address *a1 = NULL, *a2 = NULL; - - assert_se(address_new(&a1) >= 0); - assert_se(address_new(&a2) >= 0); - - assert_se(address_equal(NULL, NULL)); - assert_se(!address_equal(a1, NULL)); - assert_se(!address_equal(NULL, a2)); - assert_se(address_equal(a1, a2)); - - a1->family = AF_INET; - assert_se(!address_equal(a1, a2)); - - a2->family = AF_INET; - assert_se(address_equal(a1, a2)); - - assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in)); - assert_se(!address_equal(a1, a2)); - assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in)); - assert_se(address_equal(a1, a2)); - assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in)); - assert_se(address_equal(a1, a2)); - assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in)); - assert_se(address_equal(a1, a2)); - a1->prefixlen = 10; - assert_se(!address_equal(a1, a2)); - a2->prefixlen = 10; - assert_se(address_equal(a1, a2)); - - a1->family = AF_INET6; - assert_se(!address_equal(a1, a2)); - - a2->family = AF_INET6; - assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a1->in_addr.in6)); - assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::2", &a2->in_addr.in6)); - assert_se(address_equal(a1, a2)); - - a2->prefixlen = 8; - assert_se(address_equal(a1, a2)); - - assert_se(inet_pton(AF_INET6, "2001:4ca0:4f01::1", &a2->in_addr.in6)); - assert_se(!address_equal(a1, a2)); -} - -int main(void) { - _cleanup_manager_free_ Manager *manager = NULL; - struct udev *udev; - struct udev_device *loopback; - int r; - - test_deserialize_in_addr(); - test_deserialize_dhcp_routes(); - test_address_equality(); - - assert_se(manager_new(&manager) >= 0); - - r = test_load_config(manager); - if (r == -EPERM) - return EXIT_TEST_SKIP; - - udev = udev_new(); - assert_se(udev); - - loopback = udev_device_new_from_syspath(udev, "/sys/class/net/lo"); - assert_se(loopback); - assert_se(udev_device_get_ifindex(loopback) == 1); - - test_network_get(manager, loopback); - - assert_se(manager_rtnl_enumerate_links(manager) >= 0); - - udev_device_unref(loopback); - udev_unref(udev); -} diff --git a/src/network/test-networkd-conf.c b/src/network/test-networkd-conf.c deleted file mode 100644 index 0e1a18457d..0000000000 --- a/src/network/test-networkd-conf.c +++ /dev/null @@ -1,142 +0,0 @@ -/*** - This file is part of systemd. - - Copyright 2016 Zbigniew Jędrzejewski-Szmek - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include "hexdecoct.h" -#include "log.h" -#include "macro.h" -#include "string-util.h" -#include "ether-addr-util.h" - -#include "networkd-conf.h" -#include "networkd-network.h" -#include "network-internal.h" - -static void test_config_parse_duid_type_one(const char *rvalue, int ret, DUIDType expected) { - DUIDType actual = 0; - int r; - - r = config_parse_duid_type("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); - log_info_errno(r, "\"%s\" → %d (%m)", rvalue, actual); - assert_se(r == ret); - assert_se(expected == actual); -} - -static void test_config_parse_duid_type(void) { - test_config_parse_duid_type_one("", 0, 0); - test_config_parse_duid_type_one("link-layer-time", 0, DUID_TYPE_LLT); - test_config_parse_duid_type_one("vendor", 0, DUID_TYPE_EN); - test_config_parse_duid_type_one("link-layer", 0, DUID_TYPE_LL); - test_config_parse_duid_type_one("uuid", 0, DUID_TYPE_UUID); - test_config_parse_duid_type_one("foo", 0, 0); -} - -static void test_config_parse_duid_rawdata_one(const char *rvalue, int ret, const DUID* expected) { - DUID actual = {}; - int r; - _cleanup_free_ char *d = NULL; - - r = config_parse_duid_rawdata("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); - d = hexmem(actual.raw_data, actual.raw_data_len); - log_info_errno(r, "\"%s\" → \"%s\" (%m)", - rvalue, strnull(d)); - assert_se(r == ret); - if (expected) { - assert_se(actual.raw_data_len == expected->raw_data_len); - assert_se(memcmp(actual.raw_data, expected->raw_data, expected->raw_data_len) == 0); - } -} - -static void test_config_parse_hwaddr_one(const char *rvalue, int ret, const struct ether_addr* expected) { - struct ether_addr *actual = NULL; - int r; - - r = config_parse_hwaddr("network", "filename", 1, "section", 1, "lvalue", 0, rvalue, &actual, NULL); - assert_se(ret == r); - if (expected) { - assert_se(actual); - assert(ether_addr_equal(expected, actual)); - } else { - assert_se(actual == NULL); - } - free(actual); -} - -#define BYTES_0_128 "0:1:2:3:4:5:6:7:8:9:a:b:c:d:e:f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f:20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:3e:3f:40:41:42:43:44:45:46:47:48:49:4a:4b:4c:4d:4e:4f:50:51:52:53:54:55:56:57:58:59:5a:5b:5c:5d:5e:5f:60:61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:78:79:7a:7b:7c:7d:7e:7f:80" - -#define BYTES_1_128 {0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xa,0xb,0xc,0xd,0xe,0xf,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80} - -static void test_config_parse_duid_rawdata(void) { - test_config_parse_duid_rawdata_one("", 0, &(DUID){}); - test_config_parse_duid_rawdata_one("00:11:22:33:44:55:66:77", 0, - &(DUID){0, 8, {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}}); - test_config_parse_duid_rawdata_one("00:11:22:", 0, - &(DUID){0, 3, {0x00,0x11,0x22}}); - test_config_parse_duid_rawdata_one("000:11:22", 0, &(DUID){}); /* error, output is all zeros */ - test_config_parse_duid_rawdata_one("00:111:22", 0, &(DUID){}); - test_config_parse_duid_rawdata_one("0:1:2:3:4:5:6:7", 0, - &(DUID){0, 8, {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7}}); - test_config_parse_duid_rawdata_one("11::", 0, &(DUID){0, 1, {0x11}}); /* FIXME: should this be an error? */ - test_config_parse_duid_rawdata_one("abcdef", 0, &(DUID){}); - test_config_parse_duid_rawdata_one(BYTES_0_128, 0, &(DUID){}); - test_config_parse_duid_rawdata_one(BYTES_0_128 + 2, 0, &(DUID){0, 128, BYTES_1_128}); -} - -static void test_config_parse_hwaddr(void) { - const struct ether_addr t[] = { - { .ether_addr_octet = { 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff } }, - { .ether_addr_octet = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab } }, - }; - test_config_parse_hwaddr_one("", 0, NULL); - test_config_parse_hwaddr_one("no:ta:ma:ca:dd:re", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:fx", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff", 0, &t[0]); - test_config_parse_hwaddr_one(" aa:bb:cc:dd:ee:ff", 0, &t[0]); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\n", 0, &t[0]); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff \t\nxxx", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc: dd:ee:ff", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc:d d:ee:ff", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee", 0, NULL); - test_config_parse_hwaddr_one("9:aa:bb:cc:dd:ee:ff", 0, NULL); - test_config_parse_hwaddr_one("aa:bb:cc:dd:ee:ff:gg", 0, NULL); - test_config_parse_hwaddr_one("aa:Bb:CC:dd:ee:ff", 0, &t[0]); - test_config_parse_hwaddr_one("01:23:45:67:89:aB", 0, &t[1]); - test_config_parse_hwaddr_one("1:23:45:67:89:aB", 0, &t[1]); - test_config_parse_hwaddr_one("aa-bb-cc-dd-ee-ff", 0, &t[0]); - test_config_parse_hwaddr_one("AA-BB-CC-DD-EE-FF", 0, &t[0]); - test_config_parse_hwaddr_one("01-23-45-67-89-ab", 0, &t[1]); - test_config_parse_hwaddr_one("aabb.ccdd.eeff", 0, &t[0]); - test_config_parse_hwaddr_one("0123.4567.89ab", 0, &t[1]); - test_config_parse_hwaddr_one("123.4567.89ab.", 0, NULL); - test_config_parse_hwaddr_one("aabbcc.ddeeff", 0, NULL); - test_config_parse_hwaddr_one("aabbccddeeff", 0, NULL); - test_config_parse_hwaddr_one("aabbccddee:ff", 0, NULL); - test_config_parse_hwaddr_one("012345.6789ab", 0, NULL); - test_config_parse_hwaddr_one("123.4567.89ab", 0, &t[1]); -} - -int main(int argc, char **argv) { - log_parse_environment(); - log_open(); - - test_config_parse_duid_type(); - test_config_parse_duid_rawdata(); - test_config_parse_hwaddr(); - - return 0; -} |