summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkctl.c52
-rw-r--r--src/network/networkd-address-pool.c3
-rw-r--r--src/network/networkd-address-pool.h43
-rw-r--r--src/network/networkd-address.c27
-rw-r--r--src/network/networkd-address.h73
-rw-r--r--src/network/networkd-dhcp4.c225
-rw-r--r--src/network/networkd-dhcp6.c146
-rw-r--r--src/network/networkd-fdb.c8
-rw-r--r--src/network/networkd-fdb.h47
-rw-r--r--src/network/networkd-ipv4ll.c24
-rw-r--r--src/network/networkd-link.c431
-rw-r--r--src/network/networkd-link.h33
-rw-r--r--src/network/networkd-manager.c107
-rw-r--r--src/network/networkd-netdev-bond.c9
-rw-r--r--src/network/networkd-netdev-bond.h4
-rw-r--r--src/network/networkd-netdev-gperf.gperf7
-rw-r--r--src/network/networkd-netdev-macvlan.c26
-rw-r--r--src/network/networkd-netdev-macvlan.h1
-rw-r--r--src/network/networkd-netdev-tunnel.c112
-rw-r--r--src/network/networkd-netdev-tunnel.h31
-rw-r--r--src/network/networkd-netdev-tuntap.c7
-rw-r--r--src/network/networkd-netdev-vxlan.c16
-rw-r--r--src/network/networkd-netdev-vxlan.h12
-rw-r--r--src/network/networkd-netdev.c11
-rw-r--r--src/network/networkd-netdev.h7
-rw-r--r--src/network/networkd-network-gperf.gperf151
-rw-r--r--src/network/networkd-network.c279
-rw-r--r--src/network/networkd-network.h183
-rw-r--r--src/network/networkd-route.c23
-rw-r--r--src/network/networkd-route.h60
-rw-r--r--src/network/networkd-util.c144
-rw-r--r--src/network/networkd-util.h52
-rw-r--r--src/network/networkd-wait-online-link.c6
-rw-r--r--src/network/networkd-wait-online-manager.c8
-rw-r--r--src/network/networkd-wait-online.c12
-rw-r--r--src/network/networkd.h396
36 files changed, 1817 insertions, 959 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index 9d6c453dbc..c78b9444b6 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -19,29 +19,28 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdbool.h>
#include <getopt.h>
#include <net/if.h>
+#include <stdbool.h>
-#include "sd-network.h"
-#include "sd-netlink.h"
-#include "sd-hwdb.h"
#include "sd-device.h"
+#include "sd-hwdb.h"
+#include "sd-netlink.h"
+#include "sd-network.h"
-#include "strv.h"
-#include "build.h"
-#include "util.h"
-#include "pager.h"
-#include "lldp.h"
-#include "netlink-util.h"
+#include "arphrd-list.h"
#include "device-util.h"
+#include "ether-addr-util.h"
#include "hwdb-util.h"
-#include "arphrd-list.h"
+#include "lldp.h"
#include "local-addresses.h"
+#include "netlink-util.h"
+#include "pager.h"
#include "socket-util.h"
-#include "ether-addr-util.h"
-#include "verbs.h"
+#include "strv.h"
#include "terminal-util.h"
+#include "util.h"
+#include "verbs.h"
static bool arg_no_pager = false;
static bool arg_legend = true;
@@ -166,10 +165,10 @@ static void operational_state_to_color(const char *state, const char **on, const
if (streq_ptr(state, "routable")) {
*on = ansi_highlight_green();
- *off = ansi_highlight_off();
+ *off = ansi_normal();
} else if (streq_ptr(state, "degraded")) {
*on = ansi_highlight_yellow();
- *off = ansi_highlight_off();
+ *off = ansi_normal();
} else
*on = *off = "";
}
@@ -180,13 +179,13 @@ static void setup_state_to_color(const char *state, const char **on, const char
if (streq_ptr(state, "configured")) {
*on = ansi_highlight_green();
- *off = ansi_highlight_off();
+ *off = ansi_normal();
} else if (streq_ptr(state, "configuring")) {
*on = ansi_highlight_yellow();
- *off = ansi_highlight_off();
+ *off = ansi_normal();
} else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
*on = ansi_highlight_red();
- *off = ansi_highlight_off();
+ *off = ansi_normal();
} else
*on = *off = "";
}
@@ -227,7 +226,7 @@ static int list_links(int argc, char *argv[], void *userdata) {
_cleanup_device_unref_ sd_device *d = NULL;
const char *on_color_operational, *off_color_operational,
*on_color_setup, *off_color_setup;
- char devid[2 + DECIMAL_STR_MAX(int)];
+ char devid[2 + DECIMAL_STR_MAX(int)];
_cleanup_free_ char *t = NULL;
sd_network_link_get_operational_state(links[i].ifindex, &operational_state);
@@ -497,7 +496,7 @@ static int link_status_one(
sd_hwdb *hwdb,
const char *name) {
_cleanup_strv_free_ char **dns = NULL, **ntp = NULL, **domains = NULL;
- _cleanup_free_ char *setup_state = NULL, *operational_state = NULL;
+ _cleanup_free_ char *setup_state = NULL, *operational_state = NULL, *tz = NULL;
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL, *reply = NULL;
_cleanup_device_unref_ sd_device *d = NULL;
char devid[2 + DECIMAL_STR_MAX(int)];
@@ -570,7 +569,6 @@ static int link_status_one(
setup_state_to_color(setup_state, &on_color_setup, &off_color_setup);
sd_network_link_get_dns(ifindex, &dns);
- sd_network_link_get_ntp(ifindex, &ntp);
sd_network_link_get_domains(ifindex, &domains);
r = sd_network_link_get_wildcard_domain(ifindex);
if (r > 0) {
@@ -652,6 +650,8 @@ static int link_status_one(
dump_list(" DNS: ", dns);
if (!strv_isempty(domains))
dump_list(" Domain: ", domains);
+
+ (void) sd_network_link_get_ntp(ifindex, &ntp);
if (!strv_isempty(ntp))
dump_list(" NTP: ", ntp);
@@ -661,6 +661,10 @@ static int link_status_one(
if (!strv_isempty(carrier_bound_by))
dump_list("Carrier Bound By: ", carrier_bound_by);
+ (void) sd_network_link_get_timezone(ifindex, &tz);
+ if (tz)
+ printf(" Time Zone: %s", tz);
+
return 0;
}
@@ -976,7 +980,7 @@ static int link_lldp_status(int argc, char *argv[], void *userdata) {
return log_warning_errno(r < 0 ? r : ERANGE,
"Failed to parse TTL \"%s\": %m", b);
- time = now(CLOCK_BOOTTIME);
+ time = now(clock_boottime_or_monotonic());
if (x < time)
continue;
@@ -1058,9 +1062,7 @@ static int parse_argv(int argc, char *argv[]) {
return 0;
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_NO_PAGER:
arg_no_pager = true;
diff --git a/src/network/networkd-address-pool.c b/src/network/networkd-address-pool.c
index 584a956a7e..d609daafde 100644
--- a/src/network/networkd-address-pool.c
+++ b/src/network/networkd-address-pool.c
@@ -19,9 +19,8 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
#include "networkd.h"
-#include "networkd-link.h"
+#include "networkd-address-pool.h"
int address_pool_new(
Manager *m,
diff --git a/src/network/networkd-address-pool.h b/src/network/networkd-address-pool.h
new file mode 100644
index 0000000000..e6207ccce6
--- /dev/null
+++ b/src/network/networkd-address-pool.h
@@ -0,0 +1,43 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 "networkd.h"
+
+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
index 172ca43a7d..388beb5d4c 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -25,8 +25,10 @@
#include "util.h"
#include "conf-parser.h"
#include "firewall-util.h"
+#include "netlink-util.h"
+
#include "networkd.h"
-#include "networkd-link.h"
+#include "networkd-address.h"
static void address_init(Address *address) {
assert(address);
@@ -428,15 +430,13 @@ int config_parse_broadcast(
return r;
if (n->family == AF_INET6) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Broadcast is not valid for IPv6 addresses, ignoring assignment: %s", rvalue);
+ 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, EINVAL,
- "Broadcast is invalid, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Broadcast is invalid, ignoring assignment: %s", rvalue);
return 0;
}
@@ -485,10 +485,10 @@ int config_parse_address(const char *unit,
e = strchr(rvalue, '/');
if (e) {
unsigned i;
+
r = safe_atou(e + 1, &i);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Prefix length is invalid, ignoring assignment: %s", e + 1);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Prefix length is invalid, ignoring assignment: %s", e + 1);
return 0;
}
@@ -500,23 +500,20 @@ int config_parse_address(const char *unit,
r = in_addr_from_string_auto(address, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Address is invalid, ignoring assignment: %s", address);
+ 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, EINVAL,
- "Prefix length not specified, and a default one can not be deduced for '%s', ignoring assignment", address);
+ 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, EINVAL,
- "Address is incompatible, ignoring assignment: %s", address);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Address is incompatible, ignoring assignment: %s", address);
return 0;
}
@@ -565,9 +562,7 @@ int config_parse_label(const char *unit,
return log_oom();
if (!ascii_is_valid(label) || strlen(label) >= IFNAMSIZ) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Interface label is not ASCII clean or is too"
- " long, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Interface label is not ASCII clean or is too long, ignoring assignment: %s", rvalue);
free(label);
return 0;
}
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
new file mode 100644
index 0000000000..39789a2382
--- /dev/null
+++ b/src/network/networkd-address.h
@@ -0,0 +1,73 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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.h"
+#include "networkd-network.h"
+#include "networkd-link.h"
+
+#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
+
+struct Address {
+ Network *network;
+ unsigned section;
+
+ 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;
+
+ LIST_FIELDS(Address, addresses);
+};
+
+int address_new_static(Network *network, unsigned section, Address **ret);
+int address_new_dynamic(Address **ret);
+void address_free(Address *address);
+int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
+int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
+int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
+int address_establish(Address *address, Link *link);
+int address_release(Address *address, Link *link);
+bool address_equal(Address *a1, Address *a2);
+
+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);
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index d446bfa8b3..04f04df117 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -39,8 +39,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
- log_link_error(link, "could not set DHCPv4 route: %s",
- strerror(-r));
+ log_link_error_errno(link, r, "Could not set DHCPv4 route: %m");
link_enter_failed(link);
}
@@ -61,40 +60,25 @@ static int link_set_dhcp_routes(Link *link) {
assert(link->dhcp_lease);
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
- if (r < 0 && r != -ENOENT) {
- log_link_warning(link,
- "DHCP error: could not get gateway: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0 && r != -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) {
- log_link_warning(link,
- "DHCP error: could not get address: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
r = route_new_dynamic(&route, RTPROT_DHCP);
- if (r < 0) {
- log_link_error(link,
- "Could not allocate route: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate route: %m");
r = route_new_dynamic(&route_gw, RTPROT_DHCP);
- if (r < 0) {
- log_link_error(link,
- "Could not allocate route: %s",
- strerror(-r));
- return r;
- }
+ 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
@@ -107,12 +91,8 @@ static int link_set_dhcp_routes(Link *link) {
route_gw->metrics = link->network->dhcp_route_metric;
r = route_configure(route_gw, link, &dhcp4_route_handler);
- if (r < 0) {
- log_link_warning(link,
- "could not set host route: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set host route: %m");
link->dhcp4_messages ++;
@@ -123,9 +103,7 @@ static int link_set_dhcp_routes(Link *link) {
r = route_configure(route, link, &dhcp4_route_handler);
if (r < 0) {
- log_link_warning(link,
- "could not set routes: %s",
- strerror(-r));
+ log_link_warning_errno(link, r, "Could not set routes: %m");
link_enter_failed(link);
return r;
}
@@ -134,25 +112,17 @@ static int link_set_dhcp_routes(Link *link) {
}
n = sd_dhcp_lease_get_routes(link->dhcp_lease, &static_routes);
- if (n == -ENOENT)
+ if (n == -ENODATA)
return 0;
- if (n < 0) {
- log_link_warning(link,
- "DHCP error: could not get routes: %s",
- strerror(-n));
-
- return n;
- }
+ 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_dynamic(&route, RTPROT_DHCP);
- if (r < 0) {
- log_link_error(link, "Could not allocate route: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate route: %m");
route->family = AF_INET;
route->in_addr.in = static_routes[i].gw_addr;
@@ -161,12 +131,8 @@ static int link_set_dhcp_routes(Link *link) {
route->metrics = link->network->dhcp_route_metric;
r = route_configure(route, link, &dhcp4_route_handler);
- if (r < 0) {
- log_link_warning(link,
- "could not set host route: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_warning_errno(link, r, "Could not set host route: %m");
link->dhcp4_messages ++;
}
@@ -248,7 +214,7 @@ static int dhcp_lease_lost(Link *link) {
address->in_addr.in = addr;
address->prefixlen = prefixlen;
- address_drop(address, link, &link_address_drop_handler);
+ address_drop(address, link, &link_address_drop_handler);
}
}
@@ -270,12 +236,16 @@ static int dhcp_lease_lost(Link *link) {
if (link->network->dhcp_hostname) {
const char *hostname = NULL;
- r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
- if (r >= 0 && hostname) {
- r = link_set_hostname(link, "");
+ if (link->network->hostname)
+ hostname = link->network->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_error(link,
- "Failed to reset transient hostname");
+ log_link_warning_errno(link, r, "Failed to reset transient hostname: %m");
}
}
@@ -294,8 +264,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
- log_link_error(link, "could not set DHCPv4 address: %s",
- strerror(-r));
+ log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
link_enter_failed(link);
} else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
@@ -351,45 +320,30 @@ static int dhcp_lease_renew(sd_dhcp_client *client, Link *link) {
assert(link->network);
r = sd_dhcp_client_get_lease(client, &lease);
- if (r < 0) {
- log_link_warning(link, "DHCP error: no lease %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_warning_errno(link, r, "DHCP error: no lease: %m");
sd_dhcp_lease_unref(link->dhcp_lease);
link->dhcp4_configured = false;
- link->dhcp_lease = lease;
+ link->dhcp_lease = sd_dhcp_lease_ref(lease);
r = sd_dhcp_lease_get_address(lease, &address);
- if (r < 0) {
- log_link_warning(link, "DHCP error: no address: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_warning_errno(link, r, "DHCP error: no address: %m");
r = sd_dhcp_lease_get_netmask(lease, &netmask);
- if (r < 0) {
- log_link_warning(link, "DHCP error: no netmask: %s",
- strerror(-r));
- return r;
- }
+ if (r < 0)
+ return log_link_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) {
- log_link_warning(link,
- "DHCP error: no lifetime: %s",
- strerror(-r));
- return r;
- }
+ 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(link, "could not update IP address: %s",
- strerror(-r));
+ log_link_warning_errno(link, r, "Could not update IP address: %m");
link_enter_failed(link);
return r;
}
@@ -411,21 +365,21 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
r = sd_dhcp_client_get_lease(client, &lease);
if (r < 0)
- return log_link_error_errno(link, r, "DHCP error: no lease: %m");
+ 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");
+ 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");
+ return log_link_error_errno(link, r, "DHCP error: No netmask: %m");
prefixlen = in_addr_netmask_to_prefixlen(&netmask);
r = sd_dhcp_lease_get_router(lease, &gateway);
- if (r < 0 && r != -ENOENT)
- return log_link_error_errno(link, r, "DHCP error: could not get gateway: %m");
+ 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,
@@ -448,7 +402,7 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
"PREFIXLEN=%u", prefixlen,
NULL);
- link->dhcp_lease = lease;
+ link->dhcp_lease = sd_dhcp_lease_ref(lease);
if (link->network->dhcp_mtu) {
uint16_t mtu;
@@ -462,16 +416,32 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
}
if (link->network->dhcp_hostname) {
- const char *hostname;
+ const char *hostname = NULL;
- r = sd_dhcp_lease_get_hostname(lease, &hostname);
- if (r >= 0) {
+ if (link->network->hostname)
+ hostname = link->network->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_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) {
@@ -501,12 +471,11 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
return;
switch (event) {
- case DHCP_EVENT_EXPIRED:
- case DHCP_EVENT_STOP:
- case DHCP_EVENT_IP_CHANGE:
+ 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.");
+ log_link_error(link, "DHCPv4 connection considered system critical, ignoring request to reconfigure it.");
return;
}
@@ -518,7 +487,7 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
}
}
- if (event == DHCP_EVENT_IP_CHANGE) {
+ if (event == SD_DHCP_CLIENT_EVENT_IP_CHANGE) {
r = dhcp_lease_acquired(client, link);
if (r < 0) {
link_enter_failed(link);
@@ -527,14 +496,14 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
}
break;
- case DHCP_EVENT_RENEW:
+ case SD_DHCP_CLIENT_EVENT_RENEW:
r = dhcp_lease_renew(client, link);
if (r < 0) {
link_enter_failed(link);
return;
}
break;
- case DHCP_EVENT_IP_ACQUIRE:
+ case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
r = dhcp_lease_acquired(client, link);
if (r < 0) {
link_enter_failed(link);
@@ -543,13 +512,9 @@ static void dhcp4_handler(sd_dhcp_client *client, int event, void *userdata) {
break;
default:
if (event < 0)
- log_link_warning(link,
- "DHCP error: client failed: %s",
- strerror(-event));
+ log_link_warning_errno(link, event, "DHCP error: Client failed: %m");
else
- log_link_warning(link,
- "DHCP unknown event: %d",
- event);
+ log_link_warning(link, "DHCP unknown event: %i", event);
break;
}
@@ -597,10 +562,10 @@ int dhcp4_configure(Link *link) {
}
if (link->network->dhcp_mtu) {
- r = sd_dhcp_client_set_request_option(link->dhcp_client,
- DHCP_OPTION_INTERFACE_MTU);
- if (r < 0)
- return r;
+ r = sd_dhcp_client_set_request_option(link->dhcp_client,
+ DHCP_OPTION_INTERFACE_MTU);
+ if (r < 0)
+ return r;
}
if (link->network->dhcp_routes) {
@@ -610,20 +575,34 @@ int dhcp4_configure(Link *link) {
return r;
r = sd_dhcp_client_set_request_option(link->dhcp_client,
DHCP_OPTION_CLASSLESS_STATIC_ROUTE);
- if (r < 0)
- return r;
+ if (r < 0)
+ return r;
}
+ /* Always acquire the timezone and NTP*/
+ r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NTP_SERVER);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp_client_set_request_option(link->dhcp_client, DHCP_OPTION_NEW_TZDB_TIMEZONE);
+ if (r < 0)
+ return r;
+
if (link->network->dhcp_sendhost) {
_cleanup_free_ char *hostname = NULL;
+ const char *hn = NULL;
+
+ if (!link->network->hostname) {
+ hostname = gethostname_malloc();
+ if (!hostname)
+ return -ENOMEM;
- hostname = gethostname_malloc();
- if (!hostname)
- return -ENOMEM;
+ hn = hostname;
+ } else
+ hn = link->network->hostname;
- if (!is_localhost(hostname)) {
- r = sd_dhcp_client_set_hostname(link->dhcp_client,
- hostname);
+ if (!is_localhost(hn)) {
+ r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
if (r < 0)
return r;
}
diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c
index 3a5ac1c39b..3cb7b8d9ca 100644
--- a/src/network/networkd-dhcp6.c
+++ b/src/network/networkd-dhcp6.c
@@ -53,8 +53,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1;
}
- log_link_error(link, "Could not set DHCPv6 address: %s",
- strerror(-r));
+ log_link_error_errno(link, r, "Could not set DHCPv6 address: %m");
link_enter_failed(link);
@@ -84,8 +83,8 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
addr->cinfo.ifa_valid = lifetime_valid;
log_link_info(link,
- "DHCPv6 address "SD_ICMP6_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
- SD_ICMP6_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
+ "DHCPv6 address "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
+ SD_ICMP6_ND_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
addr->prefixlen, lifetime_preferred, lifetime_valid);
r = address_update(addr, link, dhcp6_address_handler);
@@ -115,8 +114,7 @@ static int dhcp6_lease_address_acquired(sd_dhcp6_client *client, Link *link) {
r = sd_icmp6_ra_get_prefixlen(link->icmp6_router_discovery,
&ip6_addr, &prefixlen);
if (r < 0 && r != -EADDRNOTAVAIL) {
- log_link_warning(link, "Could not get prefix information: %s",
- strerror(-r));
+ log_link_warning_errno(link, r, "Could not get prefix information: %m");
return r;
}
@@ -144,13 +142,15 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
return;
switch(event) {
- case DHCP6_EVENT_STOP:
- case DHCP6_EVENT_RESEND_EXPIRE:
- case DHCP6_EVENT_RETRANS_MAX:
- log_link_debug(link, "DHCPv6 event %d", event);
+ case SD_DHCP6_CLIENT_EVENT_STOP:
+ case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
+ case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
+ log_link_warning(link, "DHCPv6 lease lost");
+
+ link->dhcp6_configured = false;
break;
- case DHCP6_EVENT_IP_ACQUIRE:
+ case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
r = dhcp6_lease_address_acquired(client, link);
if (r < 0) {
link_enter_failed(link);
@@ -158,24 +158,25 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
}
/* fall through */
- case DHCP6_EVENT_INFORMATION_REQUEST:
+ 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(link, "DHCPv6 error: %s",
- strerror(-event));
+ log_link_warning_errno(link, event, "DHCPv6 error: %m");
else
- log_link_warning(link, "DHCPv6 unknown event: %d",
- event);
+ log_link_warning(link, "DHCPv6 unknown event: %d", event);
return;
}
+
+ link_client_handler(link);
}
static int dhcp6_configure(Link *link, int event) {
@@ -183,91 +184,86 @@ static int dhcp6_configure(Link *link, int event) {
bool information_request;
assert_return(link, -EINVAL);
+ assert_return(IN_SET(event, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT,
+ SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER,
+ SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED), -EINVAL);
- if (link->dhcp6_client) {
- if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED)
- return 0;
+ link->dhcp6_configured = false;
+ if (link->dhcp6_client) {
r = sd_dhcp6_client_get_information_request(link->dhcp6_client,
&information_request);
if (r < 0) {
- log_link_warning(link, "Could not get DHCPv6 Information request setting: %s",
- strerror(-r));
- link->dhcp6_client =
- sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
+ log_link_warning_errno(link, r, "Could not get DHCPv6 Information request setting: %m");
+ goto error;
}
- if (!information_request)
- return r;
+ if (information_request && event != SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) {
+ r = sd_dhcp6_client_stop(link->dhcp6_client);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not stop DHCPv6 while setting Managed mode: %m");
+ goto error;
+ }
+
+ r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
+ false);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not unset DHCPv6 Information request: %m");
+ goto error;
+ }
- r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
- false);
- if (r < 0) {
- log_link_warning(link, "Could not unset DHCPv6 Information request: %s",
- strerror(-r));
- link->dhcp6_client =
- sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
}
r = sd_dhcp6_client_start(link->dhcp6_client);
- if (r < 0) {
- log_link_warning(link, "Could not restart DHCPv6 after enabling Information request: %s",
- strerror(-r));
- link->dhcp6_client =
- sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
+ if (r < 0 && r != -EALREADY) {
+ log_link_warning_errno(link, r, "Could not restart DHCPv6: %m");
+ goto error;
}
+ if (r == -EALREADY)
+ link->dhcp6_configured = true;
+
return r;
}
r = sd_dhcp6_client_new(&link->dhcp6_client);
if (r < 0)
- return r;
+ goto error;
r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
- if (r < 0) {
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
- }
+ if (r < 0)
+ goto error;
r = sd_dhcp6_client_set_mac(link->dhcp6_client,
(const uint8_t *) &link->mac,
sizeof (link->mac), ARPHRD_ETHER);
- if (r < 0) {
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
- }
+ if (r < 0)
+ goto error;
r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
- if (r < 0) {
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
- }
+ if (r < 0)
+ goto error;
r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
link);
- if (r < 0) {
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
- }
+ if (r < 0)
+ goto error;
- if (event == ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER) {
+ if (event == SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) {
r = sd_dhcp6_client_set_information_request(link->dhcp6_client,
true);
- if (r < 0) {
- link->dhcp6_client =
- sd_dhcp6_client_unref(link->dhcp6_client);
- return r;
- }
+ if (r < 0)
+ goto error;
}
r = sd_dhcp6_client_start(link->dhcp6_client);
if (r < 0)
- link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
+ goto error;
+
+ return r;
+ error:
+ link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
return r;
}
@@ -287,8 +283,8 @@ static int dhcp6_prefix_expired(Link *link) {
if (r < 0)
return r;
- log_link_info(link, "IPv6 prefix "SD_ICMP6_ADDRESS_FORMAT_STR"/%d expired",
- SD_ICMP6_ADDRESS_FORMAT_VAL(*expired_prefix),
+ log_link_info(link, "IPv6 prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d expired",
+ SD_ICMP6_ND_ADDRESS_FORMAT_VAL(*expired_prefix),
expired_prefixlen);
sd_dhcp6_lease_reset_address_iter(lease);
@@ -302,7 +298,7 @@ static int dhcp6_prefix_expired(Link *link) {
if (r < 0)
continue;
- log_link_info(link, "IPv6 prefix length updated "SD_ICMP6_ADDRESS_FORMAT_STR"/%d", SD_ICMP6_ADDRESS_FORMAT_VAL(ip6_addr), 128);
+ log_link_info(link, "IPv6 prefix length updated "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d", SD_ICMP6_ND_ADDRESS_FORMAT_VAL(ip6_addr), 128);
dhcp6_address_update(link, &ip6_addr, 128, lifetime_preferred, lifetime_valid);
}
@@ -321,17 +317,17 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
return;
switch(event) {
- case ICMP6_EVENT_ROUTER_ADVERTISMENT_NONE:
+ case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_NONE:
return;
- case ICMP6_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
- case ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER:
- case ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED:
+ case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
+ case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER:
+ case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED:
dhcp6_configure(link, event);
break;
- case ICMP6_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
+ case SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_PREFIX_EXPIRED:
if (!link->rtnl_extended_attrs)
dhcp6_prefix_expired(link);
@@ -339,11 +335,9 @@ static void icmp6_router_handler(sd_icmp6_nd *nd, int event, void *userdata) {
default:
if (event < 0)
- log_link_warning(link, "ICMPv6 error: %s",
- strerror(-event));
+ log_link_warning_errno(link, event, "ICMPv6 error: %m");
else
- log_link_warning(link, "ICMPv6 unknown event: %d",
- event);
+ log_link_warning(link, "ICMPv6 unknown event: %d", event);
break;
}
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index 0f2510e904..9cb63cb79f 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -22,10 +22,12 @@
#include <net/if.h>
#include <net/ethernet.h>
-#include "networkd.h"
-#include "networkd-link.h"
#include "conf-parser.h"
#include "util.h"
+#include "netlink-util.h"
+
+#include "networkd.h"
+#include "networkd-fdb.h"
/* create a new FDB entry or get an existing one. */
int fdb_entry_new_static(Network *const network,
@@ -195,7 +197,7 @@ int config_parse_fdb_hwaddr(
&fdb_entry->mac_addr->ether_addr_octet[5]);
if (ETHER_ADDR_LEN != r) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not a valid MAC address, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Not a valid MAC address, ignoring assignment: %s", rvalue);
return 0;
}
diff --git a/src/network/networkd-fdb.h b/src/network/networkd-fdb.h
new file mode 100644
index 0000000000..f0efb902d0
--- /dev/null
+++ b/src/network/networkd-fdb.h
@@ -0,0 +1,47 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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/>.
+***/
+
+typedef struct FdbEntry FdbEntry;
+
+#include "networkd.h"
+#include "networkd-network.h"
+
+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 *const network, const unsigned section, FdbEntry **ret);
+void fdb_entry_free(FdbEntry *fdb_entry);
+int fdb_entry_configure(Link *const link, FdbEntry *const 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-ipv4ll.c b/src/network/networkd-ipv4ll.c
index 0a27a30278..1902b3d23a 100644
--- a/src/network/networkd-ipv4ll.c
+++ b/src/network/networkd-ipv4ll.c
@@ -44,7 +44,7 @@ static int ipv4ll_address_lost(Link *link) {
r = address_new_dynamic(&address);
if (r < 0) {
- log_link_error(link, "Could not allocate address: %s", strerror(-r));
+ log_link_error_errno(link, r, "Could not allocate address: %m");
return r;
}
@@ -57,8 +57,7 @@ static int ipv4ll_address_lost(Link *link) {
r = route_new_dynamic(&route, RTPROT_UNSPEC);
if (r < 0) {
- log_link_error(link, "Could not allocate route: %s",
- strerror(-r));
+ log_link_error_errno(link, r, "Could not allocate route: %m");
return r;
}
@@ -82,7 +81,7 @@ static int ipv4ll_route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *u
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
- log_link_error(link, "could not set ipv4ll route: %s", strerror(-r));
+ log_link_error_errno(link, r, "could not set ipv4ll route: %m");
link_enter_failed(link);
}
@@ -103,7 +102,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
- log_link_error(link, "could not set ipv4ll address: %s", strerror(-r));
+ log_link_error_errno(link, r, "could not set ipv4ll address: %m");
link_enter_failed(link);
} else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
@@ -179,15 +178,15 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
return;
switch(event) {
- case IPV4LL_EVENT_STOP:
- case IPV4LL_EVENT_CONFLICT:
+ 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 IPV4LL_EVENT_BIND:
+ case SD_IPV4LL_EVENT_BIND:
r = ipv4ll_address_claimed(ll, link);
if (r < 0) {
link_enter_failed(link);
@@ -195,10 +194,7 @@ static void ipv4ll_handler(sd_ipv4ll *ll, int event, void *userdata){
}
break;
default:
- if (event < 0)
- log_link_warning(link, "IPv4 link-local error: %s", strerror(-event));
- else
- log_link_warning(link, "IPv4 link-local unknown event: %d", event);
+ log_link_warning(link, "IPv4 link-local unknown event: %d", event);
break;
}
}
@@ -218,7 +214,9 @@ int ipv4ll_configure(Link *link) {
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);
+ assert_cc(sizeof(unsigned) <= 8);
+
+ r = sd_ipv4ll_set_address_seed(link->ipv4ll, *(unsigned *)seed);
if (r < 0)
return r;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 9550e89a15..db3975f466 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -29,7 +29,10 @@
#include "socket-util.h"
#include "bus-util.h"
#include "udev-util.h"
+#include "netlink-util.h"
+#include "dhcp-lease-internal.h"
#include "network-internal.h"
+
#include "networkd-link.h"
#include "networkd-netdev.h"
@@ -498,8 +501,13 @@ void link_client_handler(Link *link) {
!link->ipv4ll_route)
return;
- if (link_dhcp4_enabled(link) && !link->dhcp4_configured)
- 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->state != LINK_STATE_CONFIGURED)
link_enter_configured(link);
@@ -613,6 +621,96 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
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_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_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_enter_set_addresses(Link *link) {
Address *ad;
int r;
@@ -637,8 +735,9 @@ static int link_enter_set_addresses(Link *link) {
/* now that we can figure out a default address for the dhcp server,
start it */
if (link_dhcp4_server_enabled(link)) {
- struct in_addr pool_start;
Address *address;
+ Link *uplink = NULL;
+ bool acquired_uplink = false;
address = link_find_dhcp_server_address(link);
if (!address) {
@@ -647,16 +746,9 @@ static int link_enter_set_addresses(Link *link) {
return 0;
}
- r = sd_dhcp_server_set_address(link->dhcp_server,
- &address->in_addr.in,
- address->prefixlen);
- if (r < 0)
- return r;
-
- /* offer 32 addresses starting from the address following the server address */
- pool_start.s_addr = htobe32(be32toh(address->in_addr.in.s_addr) + 1);
- r = sd_dhcp_server_set_lease_pool(link->dhcp_server,
- &pool_start, 32);
+ /* 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;
@@ -665,13 +757,83 @@ static int link_enter_set_addresses(Link *link) {
&main_address->in_addr.in);
if (r < 0)
return r;
-
- r = sd_dhcp_server_set_prefixlen(link->dhcp_server,
- main_address->prefixlen);
- 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");
+ }
+
+ 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");
@@ -743,7 +905,7 @@ static int link_set_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
_cleanup_link_unref_ Link *link = userdata;
- int r;
+ const sd_bus_error *e;
assert(m);
assert(link);
@@ -751,21 +913,20 @@ static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
- r = sd_bus_message_get_errno(m);
- if (r > 0)
- log_link_warning_errno(link, r, "Could not set hostname: %m");
+ 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 = 0;
+ int r;
assert(link);
assert(link->manager);
- assert(hostname);
- log_link_debug(link, "Setting transient hostname: '%s'", hostname);
+ log_link_debug(link, "Setting transient hostname: '%s'", strna(hostname));
if (!link->manager->bus) {
/* TODO: replace by assert when we can rely on kdbus */
@@ -794,6 +955,57 @@ int link_set_hostname(Link *link, const char *hostname) {
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;
@@ -846,9 +1058,6 @@ static int link_set_bridge(Link *link) {
assert(link);
assert(link->network);
- if(link->network->cost == 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");
@@ -861,6 +1070,26 @@ static int link_set_bridge(Link *link) {
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)
@@ -888,13 +1117,16 @@ static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
assert(link->network);
assert(link->manager);
- if (event != UPDATE_INFO)
- return;
-
- r = sd_lldp_save(link->lldp, link->lldp_file);
- if (r < 0)
- log_link_warning_errno(link, r, "Could not save LLDP: %m");
+ switch (event) {
+ case SD_LLDP_EVENT_UPDATE_INFO:
+ r = sd_lldp_save(link->lldp, link->lldp_file);
+ if (r < 0)
+ log_link_warning_errno(link, r, "Could not save LLDP: %m");
+ break;
+ default:
+ break;
+ }
}
static int link_acquire_conf(Link *link) {
@@ -1565,6 +1797,45 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
return 0;
}
+static int link_set_ipv6_accept_ra(Link *link) {
+ const char *p = NULL, *v = 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 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 */
+ v = "1";
+ } else if (link->network->ipv6_accept_ra > 0) {
+ /* "2" means accept RA even if ip_forward is enabled */
+ v = "2";
+ } else {
+ /* "0" means ignore RA */
+ v = "0";
+ }
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
+
+ r = write_string_file(p, v, 0);
+ if (r < 0) {
+ /* If the right value is set anyway, don't complain */
+ if (verify_one_line_file(p, v) > 0)
+ return 0;
+
+ log_link_warning_errno(link, r, "Cannot configure IPv6 accept_ra for interface: %m");
+ }
+
+ return 0;
+}
+
static int link_configure(Link *link) {
int r;
@@ -1588,6 +1859,10 @@ static int link_configure(Link *link) {
if (r < 0)
return r;
+ r = link_set_ipv6_accept_ra(link);
+ if (r < 0)
+ return r;
+
if (link_ipv4ll_enabled(link)) {
r = ipv4ll_configure(link);
if (r < 0)
@@ -1928,7 +2203,7 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
log_link_debug(link, "Link %d added", link->ifindex);
- if (detect_container(NULL) <= 0) {
+ 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);
@@ -2042,10 +2317,9 @@ int link_update(Link *link, sd_netlink_message *m) {
link_free_carrier_maps(link);
- free(link->ifname);
- link->ifname = strdup(ifname);
- if (!link->ifname)
- return -ENOMEM;
+ r = free_and_strdup(&link->ifname, ifname);
+ if (r < 0)
+ return r;
r = link_new_carrier_maps(link);
if (r < 0)
@@ -2224,6 +2498,14 @@ int link_save(Link *link) {
if (link->network) {
char **address, **domain;
bool space;
+ sd_dhcp6_lease *dhcp6_lease = NULL;
+
+ if (link->dhcp6_client) {
+ r = sd_dhcp6_client_get_lease(link->dhcp6_client,
+ &dhcp6_lease);
+ if (r < 0)
+ log_link_debug(link, "No DHCPv6 lease");
+ }
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
@@ -2245,6 +2527,19 @@ int link_save(Link *link) {
if (space)
fputc(' ', f);
serialize_in_addrs(f, addresses, r);
+ space = true;
+ }
+ }
+
+ if (link->network->dhcp_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;
}
}
@@ -2268,6 +2563,32 @@ int link_save(Link *link) {
if (space)
fputc(' ', f);
serialize_in_addrs(f, addresses, r);
+ space = true;
+ }
+ }
+
+ if (link->network->dhcp_ntp && dhcp6_lease) {
+ struct in6_addr *in6_addrs;
+ char **hosts;
+ char **hostname;
+
+ 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) {
+ STRV_FOREACH(hostname, hosts) {
+ if (space)
+ fputc(' ', f);
+ fputs(*hostname, f);
+ space = true;
+ }
}
}
@@ -2291,6 +2612,21 @@ int link_save(Link *link) {
if (space)
fputc(' ', f);
fputs(domainname, f);
+ space = true;
+ }
+ }
+
+ if (link->network->dhcp_domains && dhcp6_lease) {
+ char **domains;
+
+ r = sd_dhcp6_lease_get_domains(dhcp6_lease, &domains);
+ if (r >= 0) {
+ STRV_FOREACH(domain, domains) {
+ if (space)
+ fputc(' ', f);
+ fputs(*domain, f);
+ space = true;
+ }
}
}
@@ -2300,7 +2636,7 @@ int link_save(Link *link) {
yes_no(link->network->wildcard_domain));
fprintf(f, "LLMNR=%s\n",
- llmnr_support_to_string(link->network->llmnr));
+ resolve_support_to_string(link->network->llmnr));
}
if (!hashmap_isempty(link->bound_to_links)) {
@@ -2336,9 +2672,17 @@ int link_save(Link *link) {
}
if (link->dhcp_lease) {
+ const char *tz = NULL;
+
+ r = sd_dhcp_lease_get_timezone(link->dhcp_lease, &tz);
+ if (r >= 0)
+ fprintf(f, "TIMEZONE=%s\n", tz);
+ }
+
+ if (link->dhcp_lease) {
assert(link->network);
- r = sd_dhcp_lease_save(link->dhcp_lease, link->lease_file);
+ r = dhcp_lease_save(link->dhcp_lease, link->lease_file);
if (r < 0)
goto fail;
@@ -2371,14 +2715,13 @@ int link_save(Link *link) {
}
return 0;
+
fail:
- log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
(void) unlink(link->state_file);
-
if (temp_path)
(void) unlink(temp_path);
- return r;
+ return log_link_error_errno(link, r, "Failed to save link data to %s: %m", link->state_file);
}
static const char* const link_state_table[_LINK_STATE_MAX] = {
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 2dcbbda607..7b219c6854 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -1,5 +1,7 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+#pragma once
+
/***
This file is part of systemd.
@@ -19,11 +21,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
-
#include <endian.h>
-#include "networkd.h"
+#include "sd-dhcp-client.h"
+#include "sd-dhcp-server.h"
+#include "sd-ipv4ll.h"
+#include "sd-icmp6-nd.h"
+#include "sd-dhcp6-client.h"
+#include "sd-lldp.h"
+
+typedef struct Link Link;
typedef enum LinkState {
LINK_STATE_PENDING,
@@ -38,6 +45,21 @@ typedef enum LinkState {
_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;
+
+#include "networkd.h"
+#include "networkd-network.h"
+#include "networkd-address.h"
+
struct Link {
Manager *manager;
@@ -69,6 +91,7 @@ struct Link {
uint16_t original_mtu;
unsigned dhcp4_messages;
bool dhcp4_configured;
+ bool dhcp6_configured;
sd_ipv4ll *ipv4ll;
bool ipv4ll_address;
@@ -115,6 +138,7 @@ bool link_has_carrier(Link *link);
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);
@@ -130,6 +154,9 @@ bool link_dhcp6_enabled(Link *link);
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);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index a5c2351cf9..b4259cafef 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -22,20 +22,21 @@
#include <sys/socket.h>
#include <linux/if.h>
+#include "sd-netlink.h"
+#include "sd-daemon.h"
+
#include "conf-parser.h"
#include "path-util.h"
-#include "networkd.h"
-#include "networkd-netdev.h"
-#include "networkd-link.h"
#include "libudev-private.h"
#include "udev-util.h"
#include "netlink-util.h"
#include "bus-util.h"
#include "def.h"
#include "virt.h"
+#include "set.h"
+#include "local-addresses.h"
-#include "sd-netlink.h"
-#include "sd-daemon.h"
+#include "networkd.h"
/* use 8 MB for receive socket kernel queue. */
#define RCVBUF_SIZE (8*1024*1024)
@@ -99,7 +100,7 @@ static int manager_reset_all(Manager *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");
+ log_link_warning_errno(link, r, "Could not reset carrier: %m");
}
return 0;
@@ -145,7 +146,9 @@ int manager_connect_bus(Manager *m) {
return log_error_errno(r, "Failed to install bus reconnect time event: %m");
return 0;
- } if (r < 0)
+ }
+
+ if (r < 0)
return r;
r = sd_bus_add_match(m->bus, &m->prepare_for_sleep_slot,
@@ -202,7 +205,7 @@ static int manager_udev_process_link(Manager *m, struct udev_device *device) {
ifindex = udev_device_get_ifindex(device);
if (ifindex <= 0) {
- log_debug("ignoring udev ADD event for device with invalid ifindex");
+ log_debug("Ignoring udev ADD event for device with invalid ifindex");
return 0;
}
@@ -238,7 +241,7 @@ static int manager_connect_udev(Manager *m) {
/* udev does not initialize devices inside containers,
* so we rely on them being already initialized before
* entering the container */
- if (detect_container(NULL) > 0)
+ if (detect_container() > 0)
return 0;
m->udev = udev_new();
@@ -289,23 +292,23 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
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");
+ 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");
+ 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");
+ 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");
+ 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);
@@ -315,7 +318,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
r = sd_netlink_message_read_string(message, IFLA_IFNAME, &name);
if (r < 0) {
- log_warning_errno(r, "rtnl: received link message without ifname: %m");
+ log_warning_errno(r, "rtnl: Received link message without ifname: %m");
return 0;
} else
netdev_get(m, name, &netdev);
@@ -326,7 +329,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
/* 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");
+ log_warning_errno(r, "Could not add new link: %m");
return 0;
}
}
@@ -335,7 +338,7 @@ static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *messa
/* 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");
+ log_warning_errno(r, "Could not set ifindex on netdev: %m");
return 0;
}
}
@@ -474,13 +477,13 @@ void manager_free(Manager *m) {
free(m->state_file);
+ 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->udev_event_source);
sd_event_source_unref(m->bus_retry_event_source);
- sd_event_unref(m->event);
while ((link = hashmap_first(m->links)))
link_unref(link);
@@ -499,6 +502,7 @@ void manager_free(Manager *m) {
address_pool_free(pool);
sd_netlink_unref(m->rtnl);
+ sd_event_unref(m->event);
free(m);
}
@@ -753,7 +757,7 @@ int manager_save(Manager *m) {
r = set_put_in_addrv(dns, addresses, r);
if (r < 0)
return r;
- } else if (r < 0 && r != -ENOENT)
+ } else if (r < 0 && r != -ENODATA)
return r;
}
@@ -765,7 +769,7 @@ int manager_save(Manager *m) {
r = set_put_in_addrv(ntp, addresses, r);
if (r < 0)
return r;
- } else if (r < 0 && r != -ENOENT)
+ } else if (r < 0 && r != -ENODATA)
return r;
}
@@ -777,7 +781,7 @@ int manager_save(Manager *m) {
r = set_put_strdup(domains, domainname);
if (r < 0)
return r;
- } else if (r != -ENOENT)
+ } else if (r != -ENODATA)
return r;
}
}
@@ -818,10 +822,10 @@ int manager_save(Manager *m) {
return 0;
fail:
- log_error_errno(r, "Failed to save network state to %s: %m", m->state_file);
- unlink(m->state_file);
- unlink(temp_path);
- return r;
+ (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);
}
int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, union in_addr_union *found) {
@@ -844,36 +848,39 @@ int manager_address_pool_acquire(Manager *m, int family, unsigned prefixlen, uni
return 0;
}
-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);
+Link* manager_find_uplink(Manager *m, Link *exclude) {
+ _cleanup_free_ struct local_address *gateways = NULL;
+ int n, i;
- if (b == ADDRESS_FAMILY_IPV4)
- return "ipv4";
- if (b == ADDRESS_FAMILY_IPV6)
- return "ipv6";
+ assert(m);
- return NULL;
-}
+ /* Looks for a suitable "uplink", via black magic: an
+ * interface that is up and where the default route with the
+ * highest priority points to. */
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) {
- int r;
+ 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;
+ }
- /* Make this a true superset of a boolean */
+ if (link == exclude)
+ continue;
- r = parse_boolean(s);
- if (r > 0)
- return ADDRESS_FAMILY_YES;
- if (r == 0)
- return ADDRESS_FAMILY_NO;
+ if (link->operstate < LINK_OPERSTATE_ROUTABLE)
+ continue;
- if (streq(s, "ipv4"))
- return ADDRESS_FAMILY_IPV4;
- if (streq(s, "ipv6"))
- return ADDRESS_FAMILY_IPV6;
+ return link;
+ }
- return _ADDRESS_FAMILY_BOOLEAN_INVALID;
+ return NULL;
}
-
-DEFINE_CONFIG_PARSE_ENUM(config_parse_address_family_boolean, address_family_boolean, AddressFamilyBoolean, "Failed to parse option");
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
index a60034dbe6..bcaba57937 100644
--- a/src/network/networkd-netdev-bond.c
+++ b/src/network/networkd-netdev-bond.c
@@ -204,9 +204,8 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
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) {
+ if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_AD_LACP_RATE attribute: %m");
- }
}
if (b->miimon != 0) {
@@ -358,12 +357,12 @@ int config_parse_arp_ip_target_address(const char *unit,
r = in_addr_from_string_auto(n, &f, &buffer->ip);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Bond ARP ip target address is invalid, ignoring assignment: %s", n);
+ 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, EINVAL, "Bond ARP ip target address is invalid, ignoring assignment: %s", n);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Bond ARP ip target address is invalid, ignoring assignment: %s", n);
return 0;
}
@@ -374,7 +373,7 @@ int config_parse_arp_ip_target_address(const char *unit,
}
if (b->n_arp_ip_targets > NETDEV_BOND_ARP_TARGETS_MAX)
- log_syntax(unit, LOG_WARNING, filename, line, EINVAL, "More than the maximum number of kernel-supported ARP ip targets specified: %d > %d", 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;
}
diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h
index 9991fa731f..0cdce1605e 100644
--- a/src/network/networkd-netdev-bond.h
+++ b/src/network/networkd-netdev-bond.h
@@ -1,5 +1,7 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+#pragma once
+
/***
This file is part of systemd.
@@ -19,7 +21,7 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#pragma once
+#include "in-addr-util.h"
typedef struct Bond Bond;
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index 010c106610..e0bd0e024a 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -29,6 +29,7 @@ NetDev.MTUBytes, config_parse_iec_size, 0,
NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac)
VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id)
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
+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)
@@ -36,6 +37,9 @@ Tunnel.TOS, config_parse_unsigned, 0,
Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl)
Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc)
Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode)
+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)
@@ -51,6 +55,7 @@ VXLAN.UDPCheckSum, config_parse_bool, 0,
VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx)
VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx)
VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing)
+VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy)
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)
@@ -59,7 +64,7 @@ Tun.Group, config_parse_string, 0,
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.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)
diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c
index c2c564935c..e17de793ce 100644
--- a/src/network/networkd-netdev-macvlan.c
+++ b/src/network/networkd-netdev-macvlan.c
@@ -35,14 +35,20 @@ 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 = MACVLAN(netdev);
+ MacVlan *m;
int r;
assert(netdev);
- assert(m);
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)
@@ -53,14 +59,28 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_net
}
static void macvlan_init(NetDev *n) {
- MacVlan *m = MACVLAN(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,
diff --git a/src/network/networkd-netdev-macvlan.h b/src/network/networkd-netdev-macvlan.h
index d61efc16d4..c491bfa312 100644
--- a/src/network/networkd-netdev-macvlan.h
+++ b/src/network/networkd-netdev-macvlan.h
@@ -41,6 +41,7 @@ struct 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_;
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 5533fb5c7b..c9b7fa96e2 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -33,6 +33,7 @@
#include "conf-parser.h"
#define DEFAULT_TNL_HOP_LIMIT 64
+#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
[NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -184,6 +185,16 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
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;
}
@@ -264,6 +275,25 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
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;
@@ -365,12 +395,12 @@ int config_parse_tunnel_address(const char *unit,
r = in_addr_from_string_auto(rvalue, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue);
+ 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, EINVAL, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Tunnel addresses incompatible, ignoring assignment: %s", rvalue);
return 0;
}
@@ -380,6 +410,83 @@ int config_parse_tunnel_address(const char *unit,
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 = htonl(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);
@@ -452,6 +559,7 @@ static void ip6tnl_init(NetDev *n) {
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 = {
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
index 88f57ac105..fa7decce18 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -33,12 +33,19 @@ typedef enum Ip6TnlMode {
_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;
+
struct Tunnel {
NetDev meta;
uint8_t encap_limit;
int family;
+ int ipv6_flowlabel;
unsigned ttl;
unsigned tos;
@@ -50,6 +57,7 @@ struct Tunnel {
Ip6TnlMode ip6tnl_mode;
bool pmtudisc;
+ bool copy_dscp;
};
extern const NetDevVTable ipip_vtable;
@@ -70,3 +78,26 @@ int config_parse_ip6tnl_mode(const char *unit, const char *filename,
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);
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
index ba84e802fc..6a808b6205 100644
--- a/src/network/networkd-netdev-tuntap.c
+++ b/src/network/networkd-netdev-tuntap.c
@@ -143,11 +143,8 @@ static void tuntap_done(NetDev *netdev) {
assert(t);
- free(t->user_name);
- t->user_name = NULL;
-
- free(t->group_name);
- t->group_name = NULL;
+ t->user_name = mfree(t->user_name);
+ t->group_name = mfree(t->group_name);
}
static int tuntap_verify(NetDev *netdev, const char *filename) {
diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c
index 2a5c5f0baa..03a599c0d4 100644
--- a/src/network/networkd-netdev-vxlan.c
+++ b/src/network/networkd-netdev-vxlan.c
@@ -3,7 +3,7 @@
/***
This file is part of systemd.
- Copyright 2014 Susant Sahani <susant@redhat.com>
+ 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
@@ -101,6 +101,12 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX 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;
}
@@ -125,14 +131,12 @@ int config_parse_vxlan_group_address(const char *unit,
r = in_addr_from_string_auto(rvalue, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "vxlan multicast group address is invalid, ignoring assignment: %s", rvalue);
+ 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, EINVAL,
- "vxlan multicast group incompatible, ignoring assignment: %s", rvalue);
+ 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;
}
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
index fe5254e91f..4ec33946cc 100644
--- a/src/network/networkd-netdev-vxlan.h
+++ b/src/network/networkd-netdev-vxlan.h
@@ -50,6 +50,18 @@ struct VxLan {
bool udpcsum;
bool udp6zerocsumtx;
bool udp6zerocsumrx;
+ bool group_policy;
};
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);
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 6949b403c8..ff1edf2c39 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -21,19 +21,23 @@
#include <net/if.h>
-#include "networkd-netdev.h"
-#include "networkd-link.h"
-#include "network-internal.h"
#include "conf-files.h"
#include "conf-parser.h"
#include "list.h"
#include "siphash24.h"
+#include "netlink-util.h"
+#include "network-internal.h"
+
+#include "networkd.h"
+#include "networkd-netdev.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,
@@ -56,6 +60,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[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",
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index a004f2fe5f..1f8510c4f7 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -21,11 +21,14 @@
#pragma once
-#include "networkd.h"
#include "list.h"
+typedef struct NetDev NetDev;
typedef struct NetDevVTable NetDevVTable;
+#include "networkd.h"
+#include "networkd-link.h"
+
typedef struct netdev_join_callback netdev_join_callback;
struct netdev_join_callback {
@@ -40,6 +43,7 @@ typedef enum NetDevKind {
NETDEV_KIND_BOND,
NETDEV_KIND_VLAN,
NETDEV_KIND_MACVLAN,
+ NETDEV_KIND_MACVTAP,
NETDEV_KIND_IPVLAN,
NETDEV_KIND_VXLAN,
NETDEV_KIND_IPIP,
@@ -161,6 +165,7 @@ DEFINE_CAST(BRIDGE, Bridge);
DEFINE_CAST(BOND, Bond);
DEFINE_CAST(VLAN, VLan);
DEFINE_CAST(MACVLAN, MacVlan);
+DEFINE_CAST(MACVTAP, MacVlan);
DEFINE_CAST(IPVLAN, IPVlan);
DEFINE_CAST(VXLAN, VxLan);
DEFINE_CAST(IPIP, Tunnel);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 787fc2ff5b..8257ab45da 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -15,70 +15,89 @@ struct ConfigPerfItem;
%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)
-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.IPVLAN, config_parse_netdev, 0, 0
-Network.VXLAN, config_parse_netdev, 0, 0
-Network.Tunnel, config_parse_tunnel, 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_bool, 0, offsetof(Network, lldp)
-Network.Address, config_parse_address, 0, 0
-Network.Gateway, config_parse_gateway, 0, 0
-Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
-Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
-Network.LLMNR, config_parse_llmnr, 0, offsetof(Network, llmnr)
-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.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
-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
-DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
-DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
-DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
-DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
-DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
-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.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
-Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost)
-BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
-BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
+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)
+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.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_bool, 0, offsetof(Network, lldp)
+Network.Address, config_parse_address, 0, 0
+Network.Gateway, config_parse_gateway, 0, 0
+Network.Domains, config_parse_domains, 0, offsetof(Network, domains)
+Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
+Network.LLMNR, config_parse_resolve, 0, offsetof(Network, llmnr)
+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.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
+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
+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
+DHCP.ClientIdentifier, config_parse_dhcp_client_identifier, 0, offsetof(Network, dhcp_client_identifier)
+DHCP.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
+DHCP.UseNTP, config_parse_bool, 0, offsetof(Network, dhcp_ntp)
+DHCP.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
+DHCP.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
+DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
+DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
+DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, 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.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
+DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_timezone)
+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.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
/* 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_dns)
-DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
-DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
-DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
-DHCPv4.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
+Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
+DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_dns)
+DHCPv4.UseMTU, config_parse_bool, 0, offsetof(Network, dhcp_mtu)
+DHCPv4.UseHostname, config_parse_bool, 0, offsetof(Network, dhcp_hostname)
+DHCP.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_domains)
+DHCPv4.UseDomainName, config_parse_bool, 0, offsetof(Network, dhcp_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
index a8e9ef909c..5d22598fc0 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -26,11 +26,11 @@
#include "conf-parser.h"
#include "util.h"
#include "hostname-util.h"
-#include "networkd.h"
-#include "networkd-netdev.h"
-#include "networkd-link.h"
-#include "network-internal.h"
#include "dns-domain.h"
+#include "network-internal.h"
+
+#include "networkd.h"
+#include "networkd-network.h"
static int network_load_one(Manager *manager, const char *filename) {
_cleanup_network_free_ Network *network = NULL;
@@ -107,11 +107,20 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
- network->llmnr = LLMNR_SUPPORT_YES;
+ network->dhcp_server_emit_dns = true;
+ network->dhcp_server_emit_ntp = true;
+ network->dhcp_server_emit_timezone = true;
+
+ network->use_bpdu = true;
+ network->allow_port_to_be_root = true;
+ network->unicast_flood = true;
+
+ network->llmnr = RESOLVE_SUPPORT_YES;
network->link_local = ADDRESS_FAMILY_IPV6;
network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
+ network->ipv6_accept_ra = -1;
r = config_parse(NULL, filename, file,
"Match\0"
@@ -120,7 +129,8 @@ static int network_load_one(Manager *manager, const char *filename) {
"Address\0"
"Route\0"
"DHCP\0"
- "DHCPv4\0"
+ "DHCPv4\0" /* compat */
+ "DHCPServer\0"
"Bridge\0"
"BridgeFDB\0",
config_item_perf_lookup, network_network_gperf_lookup,
@@ -207,6 +217,7 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ free(network->hostname);
free(network->mac);
@@ -253,6 +264,10 @@ void network_free(Network *network) {
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);
+
free(network);
}
@@ -394,21 +409,18 @@ int config_parse_netdev(const char *unit,
kind = netdev_kind_from_string(kind_string);
if (kind == _NETDEV_KIND_INVALID) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid NetDev kind: %s", lvalue);
+ 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, EINVAL,
- "%s could not be found, ignoring assignment: %s", lvalue, rvalue);
+ 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, EINVAL,
- "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "NetDev is not a %s, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
@@ -423,13 +435,12 @@ int config_parse_netdev(const char *unit,
break;
case NETDEV_KIND_VLAN:
case NETDEV_KIND_MACVLAN:
+ case NETDEV_KIND_MACVTAP:
case NETDEV_KIND_IPVLAN:
case NETDEV_KIND_VXLAN:
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Can not add VLAN '%s' to network: %m",
- rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue);
return 0;
}
@@ -468,7 +479,7 @@ int config_parse_domains(const char *unit,
STRV_FOREACH(domain, *domains) {
if (is_localhost(*domain))
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "'localhost' domain names may not be configured, ignoring assignment: %s", *domain);
else {
r = dns_name_is_valid(*domain);
if (r <= 0 && !streq(*domain, "*")) {
@@ -524,7 +535,7 @@ int config_parse_tunnel(const char *unit,
netdev->kind != NETDEV_KIND_VTI6 &&
netdev->kind != NETDEV_KIND_IP6TNL
) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+ log_syntax(unit, LOG_ERR, filename, line, 0,
"NetDev is not a tunnel, ignoring assignment: %s", rvalue);
return 0;
}
@@ -609,7 +620,7 @@ int config_parse_dhcp(
else if (streq(rvalue, "both"))
s = ADDRESS_FAMILY_YES;
else {
- log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse DHCP option, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse DHCP option, ignoring: %s", rvalue);
return 0;
}
}
@@ -626,15 +637,58 @@ static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
-static const char* const llmnr_support_table[_LLMNR_SUPPORT_MAX] = {
- [LLMNR_SUPPORT_NO] = "no",
- [LLMNR_SUPPORT_YES] = "yes",
- [LLMNR_SUPPORT_RESOLVE] = "resolve",
+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(llmnr_support, LLMNRSupport);
+DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
-int config_parse_llmnr(
+int config_parse_ipv6_privacy_extensions(
const char* unit,
const char *filename,
unsigned line,
@@ -646,39 +700,44 @@ int config_parse_llmnr(
void *data,
void *userdata) {
- LLMNRSupport *llmnr = data;
+ IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
int k;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(llmnr);
+ 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)
- *llmnr = LLMNR_SUPPORT_YES;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
else if (k == 0)
- *llmnr = LLMNR_SUPPORT_NO;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
else {
- LLMNRSupport s;
+ IPv6PrivacyExtensions s;
- s = llmnr_support_from_string(rvalue);
- if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse LLMNR option, ignoring: %s", rvalue);
- return 0;
+ 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;
+ }
}
- *llmnr = s;
+ *ipv6_privacy_extensions = s;
}
return 0;
}
-int config_parse_ipv6token(
- const char* unit,
+int config_parse_hostname(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -689,39 +748,65 @@ int config_parse_ipv6token(
void *data,
void *userdata) {
- union in_addr_union buffer;
- struct in6_addr *token = data;
+ char **hostname = data, *hn = NULL;
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 = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
+ if (r < 0)
+ return r;
- 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);
+ 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;
}
- if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
+ 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;
}
- *token = buffer.in6;
+ free(*datap);
+ *datap = tz;
return 0;
}
-int config_parse_address_family_boolean_with_kernel(
- const char* unit,
+int config_parse_dhcp_server_dns(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -732,38 +817,43 @@ int config_parse_address_family_boolean_with_kernel(
void *data,
void *userdata) {
- AddressFamilyBoolean *fwd = data, s;
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
- s = address_family_boolean_from_string(rvalue);
- if (s < 0) {
- if (streq(rvalue, "kernel"))
- s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
- else {
- log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding option, ignoring: %s", 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;
}
- }
- *fwd = s;
+ if (r == 0)
+ return 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;
+ }
-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",
-};
+ m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
-DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
+ m[n->n_dhcp_server_dns++] = a;
+ n->dhcp_server_dns = m;
+ }
+}
-int config_parse_ipv6_privacy_extensions(
- const char* unit,
+int config_parse_dhcp_server_ntp(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -774,38 +864,37 @@ int config_parse_ipv6_privacy_extensions(
void *data,
void *userdata) {
- IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
- int k;
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
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 */
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ struct in_addr a, *m;
- 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;
+ 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;
+ }
- s = ipv6_privacy_extensions_from_string(rvalue);
- if (s < 0) {
+ if (r == 0)
+ return 0;
- if (streq(rvalue, "kernel"))
- s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
- else {
- log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
- 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;
}
- *ipv6_privacy_extensions = s;
- }
+ m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
- return 0;
+ m[n->n_dhcp_server_ntp++] = a;
+ n->dhcp_server_ntp = m;
+ }
}
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
new file mode 100644
index 0000000000..2a43b6b347
--- /dev/null
+++ b/src/network/networkd-network.h
@@ -0,0 +1,183 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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 "condition.h"
+
+typedef struct Network Network;
+
+#include "networkd.h"
+#include "networkd-netdev.h"
+#include "networkd-address.h"
+#include "networkd-route.h"
+#include "networkd-fdb.h"
+#include "networkd-util.h"
+
+#define DHCP_ROUTE_METRIC 1024
+#define IPV4LL_ROUTE_METRIC 2048
+
+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;
+
+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;
+ Hashmap *stacked_netdevs;
+
+ /* DHCP Client Support */
+ AddressFamilyBoolean dhcp;
+ DCHPClientIdentifier dhcp_client_identifier;
+ char *dhcp_vendor_class_identifier;
+ char *hostname;
+ bool dhcp_dns;
+ bool dhcp_ntp;
+ bool dhcp_mtu;
+ bool dhcp_hostname;
+ bool dhcp_domains;
+ bool dhcp_sendhost;
+ bool dhcp_broadcast;
+ bool dhcp_critical;
+ bool dhcp_routes;
+ bool dhcp_timezone;
+ unsigned dhcp_route_metric;
+
+ /* 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_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;
+
+ AddressFamilyBoolean ip_forward;
+ bool ip_masquerade;
+
+ int ipv6_accept_ra;
+
+ union in_addr_union ipv6_token;
+ IPv6PrivacyExtensions ipv6_privacy_extensions;
+
+ struct ether_addr *mac;
+ unsigned mtu;
+
+ bool lldp;
+
+ LIST_HEAD(Address, static_addresses);
+ LIST_HEAD(Route, static_routes);
+ LIST_HEAD(FdbEntry, static_fdb_entries);
+
+ Hashmap *addresses_by_section;
+ Hashmap *routes_by_section;
+ Hashmap *fdb_entries_by_section;
+
+ bool wildcard_domain;
+ char **domains, **dns, **ntp, **bind_carrier;
+
+ ResolveSupport llmnr;
+
+ 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);
+
+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_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);
+
+/* 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, unsigned 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_;
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 31b10c458d..1f09d95674 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -19,12 +19,12 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-
-#include "networkd.h"
-#include "networkd-link.h"
-
#include "util.h"
#include "conf-parser.h"
+#include "netlink-util.h"
+
+#include "networkd.h"
+#include "networkd-route.h"
int route_new_static(Network *network, unsigned section, Route **ret) {
_cleanup_route_free_ Route *route = NULL;
@@ -294,8 +294,7 @@ int config_parse_gateway(const char *unit,
r = in_addr_from_string_auto(rvalue, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Route is invalid, ignoring assignment: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Route is invalid, ignoring assignment: %s", rvalue);
return 0;
}
@@ -345,14 +344,12 @@ int config_parse_destination(const char *unit,
r = in_addr_from_string_auto(address, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Destination is invalid, ignoring assignment: %s", address);
+ 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, EINVAL,
- "Unknown address family, ignoring assignment: %s", address);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown address family, ignoring assignment: %s", address);
return 0;
}
@@ -360,8 +357,7 @@ int config_parse_destination(const char *unit,
if (e) {
r = safe_atou8(e + 1, &prefixlen);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Route destination prefix length is invalid, ignoring assignment: %s", e + 1);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Route destination prefix length is invalid, ignoring assignment: %s", e + 1);
return 0;
}
} else {
@@ -456,8 +452,7 @@ int config_parse_route_scope(const char *unit,
else if (streq(rvalue, "global"))
n->scope = RT_SCOPE_UNIVERSE;
else {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Unknown route scope: %s", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Unknown route scope: %s", rvalue);
return 0;
}
diff --git a/src/network/networkd-route.h b/src/network/networkd-route.h
new file mode 100644
index 0000000000..d090b9c91e
--- /dev/null
+++ b/src/network/networkd-route.h
@@ -0,0 +1,60 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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.h"
+#include "networkd-network.h"
+
+struct Route {
+ Network *network;
+ unsigned section;
+
+ int family;
+ unsigned char dst_prefixlen;
+ unsigned char src_prefixlen;
+ unsigned char scope;
+ uint32_t metrics;
+ unsigned char protocol; /* RTPROT_* */
+
+ union in_addr_union in_addr;
+ union in_addr_union dst_addr;
+ union in_addr_union src_addr;
+ union in_addr_union prefsrc_addr;
+
+ LIST_FIELDS(Route, routes);
+};
+
+int route_new_static(Network *network, unsigned section, Route **ret);
+int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
+void route_free(Route *route);
+int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
+int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
+
+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_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);
diff --git a/src/network/networkd-util.c b/src/network/networkd-util.c
new file mode 100644
index 0000000000..dde6b327ed
--- /dev/null
+++ b/src/network/networkd-util.c
@@ -0,0 +1,144 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+ 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 "util.h"
+#include "conf-parser.h"
+
+#include "networkd-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);
+
+ s = address_family_boolean_from_string(rvalue);
+ if (s < 0) {
+ if (streq(rvalue, "kernel"))
+ s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse IPForwarding= option, ignoring: %s", rvalue);
+ return 0;
+ }
+ }
+
+ *fwd = s;
+
+ return 0;
+}
+
+static const char* const resolve_support_table[_RESOLVE_SUPPORT_MAX] = {
+ [RESOLVE_SUPPORT_NO] = "no",
+ [RESOLVE_SUPPORT_YES] = "yes",
+ [RESOLVE_SUPPORT_RESOLVE] = "resolve",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(resolve_support, ResolveSupport);
+
+int config_parse_resolve(
+ 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) {
+
+ ResolveSupport *resolve = data;
+ int k;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(resolve);
+
+ /* 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)
+ *resolve = RESOLVE_SUPPORT_YES;
+ else if (k == 0)
+ *resolve = RESOLVE_SUPPORT_NO;
+ else {
+ ResolveSupport s;
+
+ s = resolve_support_from_string(rvalue);
+ if (s < 0){
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse %s= option, ignoring: %s", lvalue, rvalue);
+ return 0;
+ }
+
+ *resolve = s;
+ }
+
+ return 0;
+}
diff --git a/src/network/networkd-util.h b/src/network/networkd-util.h
new file mode 100644
index 0000000000..cc41aae85a
--- /dev/null
+++ b/src/network/networkd-util.h
@@ -0,0 +1,52 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+#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;
+
+typedef enum ResolveSupport {
+ RESOLVE_SUPPORT_NO,
+ RESOLVE_SUPPORT_YES,
+ RESOLVE_SUPPORT_RESOLVE,
+ _RESOLVE_SUPPORT_MAX,
+ _RESOLVE_SUPPORT_INVALID = -1,
+} ResolveSupport;
+
+int config_parse_resolve(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(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* resolve_support_to_string(ResolveSupport i) _const_;
+ResolveSupport resolve_support_from_string(const char *s) _pure_;
+
+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
index 2d5123788c..cacb4c257e 100644
--- a/src/network/networkd-wait-online-link.c
+++ b/src/network/networkd-wait-online-link.c
@@ -120,13 +120,11 @@ int link_update_rtnl(Link *l, sd_netlink_message *m) {
int link_update_monitor(Link *l) {
assert(l);
- free(l->operational_state);
- l->operational_state = NULL;
+ l->operational_state = mfree(l->operational_state);
sd_network_link_get_operational_state(l->ifindex, &l->operational_state);
- free(l->state);
- l->state = NULL;
+ l->state = mfree(l->state);
sd_network_link_get_setup_state(l->ifindex, &l->state);
diff --git a/src/network/networkd-wait-online-manager.c b/src/network/networkd-wait-online-manager.c
index 1fc724f5a4..112d92a568 100644
--- a/src/network/networkd-wait-online-manager.c
+++ b/src/network/networkd-wait-online-manager.c
@@ -38,9 +38,15 @@ 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 */
STRV_FOREACH(ignore, m->ignore)
if (fnmatch(*ignore, link->ifname, 0) == 0)
return true;
@@ -77,7 +83,7 @@ bool manager_all_configured(Manager *m) {
return false;
}
- if (streq(l->state, "configuring")) {
+ if (STR_IN_SET(l->state, "configuring", "pending")) {
log_debug("link %s is being processed by networkd",
l->ifname);
return false;
diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c
index 32c31fdf3d..3220c4b7ef 100644
--- a/src/network/networkd-wait-online.c
+++ b/src/network/networkd-wait-online.c
@@ -21,10 +21,10 @@
#include <getopt.h>
#include "sd-daemon.h"
-#include "strv.h"
-#include "build.h"
-#include "signal-util.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;
@@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0)
switch (c) {
@@ -79,9 +79,7 @@ static int parse_argv(int argc, char *argv[]) {
break;
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case 'i':
if (strv_extend(&arg_interfaces, optarg) < 0)
diff --git a/src/network/networkd.h b/src/network/networkd.h
index f98c640822..eea57ac158 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -26,207 +26,17 @@
#include "sd-event.h"
#include "sd-netlink.h"
#include "sd-bus.h"
-#include "sd-dhcp-client.h"
-#include "sd-dhcp-server.h"
-#include "sd-ipv4ll.h"
-#include "sd-icmp6-nd.h"
-#include "sd-dhcp6-client.h"
#include "udev.h"
-#include "sd-lldp.h"
-#include "netlink-util.h"
#include "hashmap.h"
#include "list.h"
-#include "set.h"
-#include "condition.h"
-#include "in-addr-util.h"
-#define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
-#define DHCP_ROUTE_METRIC 1024
-#define IPV4LL_ROUTE_METRIC 2048
-
-typedef struct NetDev NetDev;
-typedef struct Network Network;
-typedef struct Link Link;
-typedef struct Address Address;
-typedef struct Route Route;
typedef struct Manager Manager;
-typedef struct AddressPool AddressPool;
-typedef struct FdbEntry FdbEntry;
-
-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;
-
-typedef enum LLMNRSupport {
- LLMNR_SUPPORT_NO,
- LLMNR_SUPPORT_YES,
- LLMNR_SUPPORT_RESOLVE,
- _LLMNR_SUPPORT_MAX,
- _LLMNR_SUPPORT_INVALID = -1,
-} LLMNRSupport;
-
-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 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;
-
-struct FdbEntry {
- Network *network;
- unsigned section;
-
- struct ether_addr *mac_addr;
- uint16_t vlan_id;
-
- LIST_FIELDS(FdbEntry, static_fdb_entries);
-};
-
-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;
- Hashmap *stacked_netdevs;
- AddressFamilyBoolean dhcp;
- DCHPClientIdentifier dhcp_client_identifier;
- char *dhcp_vendor_class_identifier;
- bool dhcp_dns;
- bool dhcp_ntp;
- bool dhcp_mtu;
- bool dhcp_hostname;
- bool dhcp_domains;
- bool dhcp_sendhost;
- bool dhcp_broadcast;
- bool dhcp_critical;
- bool dhcp_routes;
- unsigned dhcp_route_metric;
- AddressFamilyBoolean link_local;
- bool ipv4ll_route;
- union in_addr_union ipv6_token;
-
- bool dhcp_server;
-
- unsigned cost;
-
- AddressFamilyBoolean ip_forward;
- bool ip_masquerade;
-
- IPv6PrivacyExtensions ipv6_privacy_extensions;
-
- struct ether_addr *mac;
- unsigned mtu;
-
- bool lldp;
-
- LIST_HEAD(Address, static_addresses);
- LIST_HEAD(Route, static_routes);
- LIST_HEAD(FdbEntry, static_fdb_entries);
-
- Hashmap *addresses_by_section;
- Hashmap *routes_by_section;
- Hashmap *fdb_entries_by_section;
- bool wildcard_domain;
- char **domains, **dns, **ntp, **bind_carrier;
-
- LLMNRSupport llmnr;
-
- LIST_FIELDS(Network, networks);
-};
-
-struct Address {
- Network *network;
- unsigned section;
-
- 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;
-
- LIST_FIELDS(Address, addresses);
-};
-
-struct Route {
- Network *network;
- unsigned section;
-
- int family;
- unsigned char dst_prefixlen;
- unsigned char src_prefixlen;
- unsigned char scope;
- uint32_t metrics;
- unsigned char protocol; /* RTPROT_* */
-
- union in_addr_union in_addr;
- union in_addr_union dst_addr;
- union in_addr_union src_addr;
- union in_addr_union prefsrc_addr;
-
- LIST_FIELDS(Route, routes);
-};
-
-struct AddressPool {
- Manager *manager;
-
- int family;
- unsigned prefixlen;
-
- union in_addr_union in_addr;
-
- LIST_FIELDS(AddressPool, address_pools);
-};
+#include "networkd-network.h"
+#include "networkd-address-pool.h"
+#include "networkd-link.h"
+#include "networkd-util.h"
struct Manager {
sd_netlink *rtnl;
@@ -275,201 +85,7 @@ int manager_save(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)
-
-/* Network */
-
-int network_load(Manager *manager);
-
-void network_free(Network *network);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(Network*, network_free);
-#define _cleanup_network_free_ _cleanup_(network_freep)
-
-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);
-
-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_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_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);
-
-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);
-
-/* gperf */
-const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, unsigned length);
-
-/* Route */
-int route_new_static(Network *network, unsigned section, Route **ret);
-int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
-void route_free(Route *route);
-int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
-int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
-
-
-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_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);
-/* Address */
-int address_new_static(Network *network, unsigned section, Address **ret);
-int address_new_dynamic(Address **ret);
-void address_free(Address *address);
-int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
-int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
-int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
-int address_establish(Address *address, Link *link);
-int address_release(Address *address, Link *link);
-bool address_equal(Address *a1, Address *a2);
-
-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);
-
-/* Forwarding database table. */
-int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry);
-void fdb_entry_free(FdbEntry *fdb_entry);
-int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret);
-
-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);
-
-/* DHCP support */
-
-int config_parse_dhcp(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line,
- const char *section, unsigned section_line, const char *lvalue,
- int ltype, const char *rvalue, void *data, void *userdata);
-
-/* IPv4LL support (legacy) */
-
-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);
-
-/* IPv6 support */
-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);
-
-/* LLMNR support */
-
-const char* llmnr_support_to_string(LLMNRSupport i) _const_;
-LLMNRSupport llmnr_support_from_string(const char *s) _pure_;
-
-int config_parse_llmnr(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);
-
-/* Address Pool */
-
-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);
-
-const char *address_family_boolean_to_string(AddressFamilyBoolean b) _const_;
-AddressFamilyBoolean address_family_boolean_from_string(const char *s) _const_;
-
-int config_parse_address_family_boolean(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-/* IPForwarding parser */
-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);
-
-/* Operational State */
-
-const char* link_operstate_to_string(LinkOperationalState s) _const_;
-LinkOperationalState link_operstate_from_string(const char *s) _pure_;
-
-/* IPv6 privacy extensions support */
-
-const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
-IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
-
-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);