summaryrefslogtreecommitdiff
path: root/src/grp-network
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-09-14 18:33:57 -0400
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-09-14 18:33:57 -0400
commit3c72c8d3ee67388336aca58c5afa3fb93a9c24c0 (patch)
treed072df7fee0f5906fad88c08398b2fe887cbc064 /src/grp-network
parente51613a3291342c6006edda8783755fb8994fd75 (diff)
parent6ba6ca19507add38549e07058c57489a8cd98cd1 (diff)
Merge branch 'notsystemd/postmove' into notsystemd/master
# Conflicts: # src/grp-journal/systemd-journald/Makefile # src/grp-login/systemd-logind/Makefile # src/grp-machine/grp-import/systemd-export/Makefile # src/grp-machine/grp-import/systemd-import/Makefile # src/grp-machine/grp-import/systemd-pull/Makefile # src/grp-machine/systemd-machined/Makefile # src/grp-network/libnetworkd-core/Makefile # src/grp-resolve/libbasic-dns/Makefile # src/grp-resolve/systemd-resolved/Makefile # src/grp-utils/systemd-path/Makefile # src/libshared/src/Makefile # src/libsystemd-network/include/systemd-network/sd-ndisc.h # src/libsystemd/Makefile # src/libsystemd/src/test.mk # src/libudev/Makefile # src/systemd-dbus1-generator/Makefile # src/systemd-nspawn/nspawn.c Signed-off-by: Luke Shumaker <lukeshu@sbcglobal.net>
Diffstat (limited to 'src/grp-network')
-rw-r--r--src/grp-network/libnetworkd-core/Makefile7
-rw-r--r--src/grp-network/libnetworkd-core/networkd-address.c72
-rw-r--r--src/grp-network/libnetworkd-core/networkd-address.h2
-rw-r--r--src/grp-network/libnetworkd-core/networkd-brvlan.c331
-rw-r--r--src/grp-network/libnetworkd-core/networkd-brvlan.h29
-rw-r--r--src/grp-network/libnetworkd-core/networkd-conf.c2
-rw-r--r--src/grp-network/libnetworkd-core/networkd-dhcp4.c2
-rw-r--r--src/grp-network/libnetworkd-core/networkd-dhcp6.c48
-rw-r--r--src/grp-network/libnetworkd-core/networkd-fdb.c34
-rw-r--r--src/grp-network/libnetworkd-core/networkd-fdb.h4
-rw-r--r--src/grp-network/libnetworkd-core/networkd-ipv4ll.c8
-rw-r--r--src/grp-network/libnetworkd-core/networkd-link.c178
-rw-r--r--src/grp-network/libnetworkd-core/networkd-link.h10
-rw-r--r--src/grp-network/libnetworkd-core/networkd-ndisc.c537
-rw-r--r--src/grp-network/libnetworkd-core/networkd-ndisc.h39
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-bridge.c7
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-bridge.h1
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-gperf.gperf9
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-tunnel.c79
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-tunnel.h9
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-vlan.c16
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-vlan.h4
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-vrf.c51
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev-vrf.h33
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev.c10
-rw-r--r--src/grp-network/libnetworkd-core/networkd-netdev.h1
-rw-r--r--src/grp-network/libnetworkd-core/networkd-network-bus.c2
-rw-r--r--src/grp-network/libnetworkd-core/networkd-network-gperf.gperf11
-rw-r--r--src/grp-network/libnetworkd-core/networkd-network.c15
-rw-r--r--src/grp-network/libnetworkd-core/networkd-network.h16
-rw-r--r--src/grp-network/libnetworkd-core/networkd-route.c126
-rw-r--r--src/grp-network/libnetworkd-core/networkd-route.h8
-rw-r--r--src/grp-network/libnetworkd-core/networkd.h1
-rw-r--r--src/grp-network/networkctl/Makefile2
-rw-r--r--src/grp-network/systemd-networkd-wait-online/Makefile2
-rw-r--r--src/grp-network/systemd-networkd-wait-online/networkd-wait-online-manager.c8
-rw-r--r--src/grp-network/systemd-networkd/systemd-networkd.service.m4.in2
37 files changed, 1470 insertions, 246 deletions
diff --git a/src/grp-network/libnetworkd-core/Makefile b/src/grp-network/libnetworkd-core/Makefile
index 4375a4d4f3..3821f06c0f 100644
--- a/src/grp-network/libnetworkd-core/Makefile
+++ b/src/grp-network/libnetworkd-core/Makefile
@@ -38,6 +38,8 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-link.c \
src/network/networkd-netdev.h \
src/network/networkd-netdev.c \
+ src/network/networkd-netdev-vrf.h \
+ src/network/networkd-netdev-vrf.c \
src/network/networkd-netdev-tunnel.h \
src/network/networkd-netdev-tunnel.c \
src/network/networkd-netdev-veth.h \
@@ -62,6 +64,7 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-ipv4ll.c \
src/network/networkd-dhcp4.c \
src/network/networkd-dhcp6.c \
+ src/network/networkd-ndisc.h \
src/network/networkd-ndisc.c \
src/network/networkd-network.h \
src/network/networkd-network.c \
@@ -74,6 +77,8 @@ libnetworkd_core_la_SOURCES = \
src/network/networkd-manager-bus.c \
src/network/networkd-fdb.h \
src/network/networkd-fdb.c \
+ src/network/networkd-brvlan.h \
+ src/network/networkd-brvlan.c \
src/network/networkd-address-pool.h \
src/network/networkd-address-pool.c \
src/network/networkd-util.h \
@@ -90,7 +95,7 @@ libnetworkd_core_la_LIBADD = \
libsystemd-network.la \
libsystemd-internal.la \
libfirewall.la \
- libshared.la
+ libsystemd-shared.la
sd.CPPFLAGS += -DPKGSYSCONFDIR=\"$(pkgsysconfdir)\"
diff --git a/src/grp-network/libnetworkd-core/networkd-address.c b/src/grp-network/libnetworkd-core/networkd-address.c
index 3c814db91b..cd24bc12f2 100644
--- a/src/grp-network/libnetworkd-core/networkd-address.c
+++ b/src/grp-network/libnetworkd-core/networkd-address.c
@@ -33,6 +33,9 @@
#include "networkd-address.h"
#include "networkd.h"
+#define ADDRESSES_PER_LINK_MAX 2048U
+#define STATIC_ADDRESSES_PER_NETWORK_MAX 1024U
+
int address_new(Address **ret) {
_cleanup_address_free_ Address *address = NULL;
@@ -55,6 +58,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
_cleanup_address_free_ Address *address = NULL;
int r;
+ assert(network);
+ assert(ret);
+
if (section) {
address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
if (address) {
@@ -65,18 +71,21 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
}
}
+ if (network->n_static_addresses >= STATIC_ADDRESSES_PER_NETWORK_MAX)
+ return -E2BIG;
+
r = address_new(&address);
if (r < 0)
return r;
if (section) {
address->section = section;
- hashmap_put(network->addresses_by_section,
- UINT_TO_PTR(address->section), address);
+ hashmap_put(network->addresses_by_section, UINT_TO_PTR(address->section), address);
}
address->network = network;
LIST_APPEND(addresses, network->static_addresses, address);
+ network->n_static_addresses++;
*ret = address;
address = NULL;
@@ -90,10 +99,11 @@ void address_free(Address *address) {
if (address->network) {
LIST_REMOVE(addresses, address->network->static_addresses, address);
+ assert(address->network->n_static_addresses > 0);
+ address->network->n_static_addresses--;
if (address->section)
- hashmap_remove(address->network->addresses_by_section,
- UINT_TO_PTR(address->section));
+ hashmap_remove(address->network->addresses_by_section, UINT_TO_PTR(address->section));
}
if (address->link) {
@@ -329,7 +339,12 @@ static int address_release(Address *address) {
return 0;
}
-int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) {
+int address_update(
+ Address *address,
+ unsigned char flags,
+ unsigned char scope,
+ const struct ifa_cacheinfo *cinfo) {
+
bool ready;
int r;
@@ -384,31 +399,38 @@ int address_drop(Address *address) {
return 0;
}
-int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
- Address address = {}, *existing;
+int address_get(Link *link,
+ int family,
+ const union in_addr_union *in_addr,
+ unsigned char prefixlen,
+ Address **ret) {
+
+ Address address, *existing;
assert(link);
assert(in_addr);
- assert(ret);
- address.family = family;
- address.in_addr = *in_addr;
- address.prefixlen = prefixlen;
+ address = (Address) {
+ .family = family,
+ .in_addr = *in_addr,
+ .prefixlen = prefixlen,
+ };
existing = set_get(link->addresses, &address);
if (existing) {
- *ret = existing;
-
+ if (ret)
+ *ret = existing;
return 1;
- } else {
- existing = set_get(link->addresses_foreign, &address);
- if (!existing)
- return -ENOENT;
}
- *ret = existing;
+ existing = set_get(link->addresses_foreign, &address);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
- return 0;
+ return -ENOENT;
}
int address_remove(
@@ -510,7 +532,12 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
return 0;
}
-int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update) {
+int address_configure(
+ Address *address,
+ Link *link,
+ sd_netlink_message_handler_t callback,
+ bool update) {
+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
@@ -521,6 +548,11 @@ int address_configure(Address *address, Link *link, sd_netlink_message_handler_t
assert(link->manager);
assert(link->manager->rtnl);
+ /* If this is a new address, then refuse adding more than the limit */
+ if (address_get(link, address->family, &address->in_addr, address->prefixlen, NULL) <= 0 &&
+ set_size(link->addresses) >= ADDRESSES_PER_LINK_MAX)
+ return -E2BIG;
+
r = address_acquire(link, address, &address);
if (r < 0)
return r;
diff --git a/src/grp-network/libnetworkd-core/networkd-address.h b/src/grp-network/libnetworkd-core/networkd-address.h
index 1e178a0ca3..9378621580 100644
--- a/src/grp-network/libnetworkd-core/networkd-address.h
+++ b/src/grp-network/libnetworkd-core/networkd-address.h
@@ -63,7 +63,7 @@ void address_free(Address *address);
int address_add_foreign(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
-int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo);
+int address_update(Address *address, unsigned char flags, unsigned char scope, const struct ifa_cacheinfo *cinfo);
int address_drop(Address *address);
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback, bool update);
int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback);
diff --git a/src/grp-network/libnetworkd-core/networkd-brvlan.c b/src/grp-network/libnetworkd-core/networkd-brvlan.c
new file mode 100644
index 0000000000..118a6ed464
--- /dev/null
+++ b/src/grp-network/libnetworkd-core/networkd-brvlan.c
@@ -0,0 +1,331 @@
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2016 BISDN GmbH. All rights reserved.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/in.h>
+#include <stdbool.h>
+
+#include <linux/if_bridge.h>
+
+#include "basic/alloc-util.h"
+#include "basic/parse-util.h"
+#include "sd-netlink/netlink-util.h"
+#include "shared/conf-parser.h"
+#include "shared/vlan-util.h"
+
+#include "networkd-brvlan.h"
+#include "networkd.h"
+
+static bool is_bit_set(unsigned bit, uint32_t scope) {
+ assert(bit < sizeof(scope)*8);
+ return scope & (1 << bit);
+}
+
+static inline void set_bit(unsigned nr, uint32_t *addr) {
+ if (nr < BRIDGE_VLAN_BITMAP_MAX)
+ addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
+}
+
+static int find_next_bit(int i, uint32_t x) {
+ int j;
+
+ if (i >= 32)
+ return -1;
+
+ /* find first bit */
+ if (i < 0)
+ return BUILTIN_FFS_U32(x);
+
+ /* mask off prior finds to get next */
+ j = __builtin_ffs(x >> i);
+ return j ? j + i : 0;
+}
+
+static int append_vlan_info_data(Link *const link, sd_netlink_message *req, uint16_t pvid, const uint32_t *br_vid_bitmap, const uint32_t *br_untagged_bitmap) {
+ struct bridge_vlan_info br_vlan;
+ int i, j, k, r, done, cnt;
+ uint16_t begin, end;
+ bool untagged = false;
+
+ assert(link);
+ assert(req);
+ assert(br_vid_bitmap);
+ assert(br_untagged_bitmap);
+
+ i = cnt = -1;
+
+ begin = end = UINT16_MAX;
+ for (k = 0; k < BRIDGE_VLAN_BITMAP_LEN; k++) {
+ unsigned base_bit;
+ uint32_t vid_map = br_vid_bitmap[k];
+ uint32_t untagged_map = br_untagged_bitmap[k];
+
+ base_bit = k * 32;
+ i = -1;
+ done = 0;
+ do {
+ j = find_next_bit(i, vid_map);
+ if (j > 0) {
+ /* first hit of any bit */
+ if (begin == UINT16_MAX && end == UINT16_MAX) {
+ begin = end = j - 1 + base_bit;
+ untagged = is_bit_set(j - 1, untagged_map);
+ goto next;
+ }
+
+ /* this bit is a continuation of prior bits */
+ if (j - 2 + base_bit == end && untagged == is_bit_set(j - 1, untagged_map) && (uint16_t)j - 1 + base_bit != pvid && (uint16_t)begin != pvid) {
+ end++;
+ goto next;
+ }
+ } else
+ done = 1;
+
+ if (begin != UINT16_MAX) {
+ cnt++;
+ if (done && k < BRIDGE_VLAN_BITMAP_LEN - 1)
+ break;
+
+ br_vlan.flags = 0;
+ if (untagged)
+ br_vlan.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
+
+ if (begin == end) {
+ br_vlan.vid = begin;
+
+ if (begin == pvid)
+ br_vlan.flags |= BRIDGE_VLAN_INFO_PVID;
+
+ r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m");
+ } else {
+ br_vlan.vid = begin;
+ br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_BEGIN;
+
+ r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m");
+
+ br_vlan.vid = end;
+ br_vlan.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
+ br_vlan.flags |= BRIDGE_VLAN_INFO_RANGE_END;
+
+ r = sd_netlink_message_append_data(req, IFLA_BRIDGE_VLAN_INFO, &br_vlan, sizeof(br_vlan));
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRIDGE_VLAN_INFO attribute: %m");
+ }
+
+ if (done)
+ break;
+ }
+ if (j > 0) {
+ begin = end = j - 1 + base_bit;
+ untagged = is_bit_set(j - 1, untagged_map);
+ }
+
+ next:
+ i = j;
+ } while(!done);
+ }
+ if (!cnt)
+ return -EINVAL;
+
+ return cnt;
+}
+
+static int set_brvlan_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
+ Link *link = userdata;
+ int r;
+
+ assert(link);
+
+ r = sd_netlink_message_get_errno(m);
+ if (r < 0 && r != -EEXIST)
+ log_link_error_errno(link, r, "Could not add VLAN to bridge port: %m");
+
+ return 1;
+}
+
+int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+ uint16_t flags;
+ sd_netlink *rtnl;
+
+ assert(link);
+ assert(link->manager);
+ assert(br_vid_bitmap);
+ assert(br_untagged_bitmap);
+ assert(link->network);
+
+ /* pvid might not be in br_vid_bitmap yet */
+ if (pvid)
+ set_bit(pvid, br_vid_bitmap);
+
+ rtnl = link->manager->rtnl;
+
+ /* create new RTM message */
+ r = sd_rtnl_message_new_link(rtnl, &req, RTM_SETLINK, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_rtnl_message_link_set_family(req, PF_BRIDGE);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set message family: %m");
+
+ r = sd_netlink_message_open_container(req, IFLA_AF_SPEC);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not open IFLA_AF_SPEC container: %m");
+
+ /* master needs flag self */
+ if (!link->network->bridge) {
+ flags = BRIDGE_FLAGS_SELF;
+ sd_netlink_message_append_data(req, IFLA_BRIDGE_FLAGS, &flags, sizeof(uint16_t));
+ }
+
+ /* add vlan info */
+ r = append_vlan_info_data(link, req, pvid, br_vid_bitmap, br_untagged_bitmap);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append VLANs: %m");
+
+ r = sd_netlink_message_close_container(req);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not close IFLA_AF_SPEC container: %m");
+
+ /* send message to the kernel */
+ r = sd_netlink_call_async(rtnl, req, set_brvlan_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ return 0;
+}
+
+static int parse_vid_range(const char *rvalue, uint16_t *vid, uint16_t *vid_end) {
+ int r;
+ char *p;
+ char *_rvalue = NULL;
+ uint16_t _vid = UINT16_MAX;
+ uint16_t _vid_end = UINT16_MAX;
+
+ assert(rvalue);
+ assert(vid);
+ assert(vid_end);
+
+ _rvalue = strdupa(rvalue);
+ p = strchr(_rvalue, '-');
+ if (p) {
+ *p = '\0';
+ p++;
+ r = parse_vlanid(_rvalue, &_vid);
+ if (r < 0)
+ return r;
+
+ if (_vid == 0)
+ return -ERANGE;
+
+ r = parse_vlanid(p, &_vid_end);
+ if (r < 0)
+ return r;
+
+ if (_vid_end == 0)
+ return -ERANGE;
+ } else {
+ r = parse_vlanid(_rvalue, &_vid);
+ if (r < 0)
+ return r;
+
+ if (_vid == 0)
+ return -ERANGE;
+ }
+
+ *vid = _vid;
+ *vid_end = _vid_end;
+ return r;
+}
+
+int config_parse_brvlan_vlan(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata) {
+ Network *network = userdata;
+ int r;
+ uint16_t vid, vid_end;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = parse_vid_range(rvalue, &vid, &vid_end);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse VLAN, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (UINT16_MAX == vid_end)
+ set_bit(vid++, network->br_vid_bitmap);
+ else {
+ if (vid >= vid_end) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
+ return 0;
+ }
+ for (; vid <= vid_end; vid++)
+ set_bit(vid, network->br_vid_bitmap);
+ }
+ return 0;
+}
+
+int config_parse_brvlan_untagged(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata) {
+ Network *network = userdata;
+ int r;
+ uint16_t vid, vid_end;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = parse_vid_range(rvalue, &vid, &vid_end);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Could not parse VLAN: %s", rvalue);
+ return 0;
+ }
+
+ if (UINT16_MAX == vid_end) {
+ set_bit(vid, network->br_vid_bitmap);
+ set_bit(vid, network->br_untagged_bitmap);
+ } else {
+ if (vid >= vid_end) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid VLAN range, ignoring %s", rvalue);
+ return 0;
+ }
+ for (; vid <= vid_end; vid++) {
+ set_bit(vid, network->br_vid_bitmap);
+ set_bit(vid, network->br_untagged_bitmap);
+ }
+ }
+ return 0;
+}
diff --git a/src/grp-network/libnetworkd-core/networkd-brvlan.h b/src/grp-network/libnetworkd-core/networkd-brvlan.h
new file mode 100644
index 0000000000..6aa6883bfc
--- /dev/null
+++ b/src/grp-network/libnetworkd-core/networkd-brvlan.h
@@ -0,0 +1,29 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright (C) 2016 BISDN GmbH. All rights reserved.
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <stdint.h>
+
+typedef struct Link Link;
+
+int br_vlan_configure(Link *link, uint16_t pvid, uint32_t *br_vid_bitmap, uint32_t *br_untagged_bitmap);
+
+int config_parse_brvlan_vlan(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_brvlan_untagged(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/grp-network/libnetworkd-core/networkd-conf.c b/src/grp-network/libnetworkd-core/networkd-conf.c
index e9993f9f32..44f5170219 100644
--- a/src/grp-network/libnetworkd-core/networkd-conf.c
+++ b/src/grp-network/libnetworkd-core/networkd-conf.c
@@ -71,7 +71,7 @@ int config_parse_duid_rawdata(
for (;;) {
int n1, n2, len, r;
uint32_t byte;
- _cleanup_free_ char *cbyte = NULL;
+ _cleanup_free_ char *cbyte = NULL;
r = extract_first_word(&rvalue, &cbyte, ":", 0);
if (r < 0) {
diff --git a/src/grp-network/libnetworkd-core/networkd-dhcp4.c b/src/grp-network/libnetworkd-core/networkd-dhcp4.c
index fe565ad075..2e7858ccd3 100644
--- a/src/grp-network/libnetworkd-core/networkd-dhcp4.c
+++ b/src/grp-network/libnetworkd-core/networkd-dhcp4.c
@@ -556,7 +556,7 @@ int dhcp4_configure(Link *link) {
if (r < 0)
return r;
- r = sd_dhcp_client_set_index(link->dhcp_client, link->ifindex);
+ r = sd_dhcp_client_set_ifindex(link->dhcp_client, link->ifindex);
if (r < 0)
return r;
diff --git a/src/grp-network/libnetworkd-core/networkd-dhcp6.c b/src/grp-network/libnetworkd-core/networkd-dhcp6.c
index 6399849ff6..d00190c520 100644
--- a/src/grp-network/libnetworkd-core/networkd-dhcp6.c
+++ b/src/grp-network/libnetworkd-core/networkd-dhcp6.c
@@ -61,10 +61,15 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
return 1;
}
-static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
- uint32_t lifetime_preferred, uint32_t lifetime_valid) {
- int r;
+static int dhcp6_address_change(
+ Link *link,
+ struct in6_addr *ip6_addr,
+ uint32_t lifetime_preferred,
+ uint32_t lifetime_valid) {
+
_cleanup_address_free_ Address *addr = NULL;
+ char buffer[INET6_ADDRSTRLEN];
+ int r;
r = address_new(&addr);
if (r < 0)
@@ -80,8 +85,8 @@ static int dhcp6_address_change(Link *link, struct in6_addr *ip6_addr,
addr->cinfo.ifa_valid = lifetime_valid;
log_link_info(link,
- "DHCPv6 address "SD_NDISC_ADDRESS_FORMAT_STR"/%d timeout preferred %d valid %d",
- SD_NDISC_ADDRESS_FORMAT_VAL(addr->in_addr.in6),
+ "DHCPv6 address %s/%d timeout preferred %d valid %d",
+ inet_ntop(AF_INET6, &addr->in_addr.in6, buffer, sizeof(buffer)),
addr->prefixlen, lifetime_preferred, lifetime_valid);
r = address_configure(addr, link, dhcp6_address_handler, true);
@@ -165,19 +170,13 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
link_check_ready(link);
}
-int dhcp6_request_address(Link *link) {
+int dhcp6_request_address(Link *link, int ir) {
int r, inf_req;
bool running;
assert(link);
assert(link->dhcp6_client);
-
- r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
- if (r < 0)
- return r;
-
- if (!inf_req)
- return 0;
+ assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
r = sd_dhcp6_client_is_running(link->dhcp6_client);
if (r < 0)
@@ -186,12 +185,27 @@ int dhcp6_request_address(Link *link) {
running = !!r;
if (running) {
+ r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
+ if (r < 0)
+ return r;
+
+ if (inf_req == ir)
+ return 0;
+
r = sd_dhcp6_client_stop(link->dhcp6_client);
if (r < 0)
return r;
+ } else {
+ r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
+ if (r < 0)
+ return r;
}
- r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
+ r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir);
+ if (r < 0)
+ return r;
+
+ r = sd_dhcp6_client_start(link->dhcp6_client);
if (r < 0)
return r;
@@ -216,10 +230,6 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
- r = sd_dhcp6_client_set_information_request(client, true);
- if (r < 0)
- goto error;
-
r = sd_dhcp6_client_set_mac(client,
(const uint8_t *) &link->mac,
sizeof (link->mac), ARPHRD_ETHER);
@@ -238,7 +248,7 @@ int dhcp6_configure(Link *link) {
if (r < 0)
goto error;
- r = sd_dhcp6_client_set_index(client, link->ifindex);
+ r = sd_dhcp6_client_set_ifindex(client, link->ifindex);
if (r < 0)
goto error;
diff --git a/src/grp-network/libnetworkd-core/networkd-fdb.c b/src/grp-network/libnetworkd-core/networkd-fdb.c
index 5f6146d52c..2949def65b 100644
--- a/src/grp-network/libnetworkd-core/networkd-fdb.c
+++ b/src/grp-network/libnetworkd-core/networkd-fdb.c
@@ -24,18 +24,24 @@
#include "basic/util.h"
#include "sd-netlink/netlink-util.h"
#include "shared/conf-parser.h"
+#include "shared/vlan-util.h"
#include "networkd-fdb.h"
#include "networkd.h"
+#define STATIC_FDB_ENTRIES_PER_NETWORK_MAX 1024U
+
/* create a new FDB entry or get an existing one. */
-int fdb_entry_new_static(Network *const network,
- const unsigned section,
- FdbEntry **ret) {
+int fdb_entry_new_static(
+ Network *network,
+ unsigned section,
+ FdbEntry **ret) {
+
_cleanup_fdbentry_free_ FdbEntry *fdb_entry = NULL;
struct ether_addr *mac_addr = NULL;
assert(network);
+ assert(ret);
/* search entry in hashmap first. */
if (section) {
@@ -48,6 +54,9 @@ int fdb_entry_new_static(Network *const network,
}
}
+ if (network->n_static_fdb_entries >= STATIC_FDB_ENTRIES_PER_NETWORK_MAX)
+ return -E2BIG;
+
/* allocate space for MAC address. */
mac_addr = new0(struct ether_addr, 1);
if (!mac_addr)
@@ -55,7 +64,6 @@ int fdb_entry_new_static(Network *const network,
/* allocate space for and FDB entry. */
fdb_entry = new0(FdbEntry, 1);
-
if (!fdb_entry) {
/* free previously allocated space for mac_addr. */
free(mac_addr);
@@ -67,6 +75,7 @@ int fdb_entry_new_static(Network *const network,
fdb_entry->mac_addr = mac_addr;
LIST_PREPEND(static_fdb_entries, network->static_fdb_entries, fdb_entry);
+ network->n_static_fdb_entries++;
if (section) {
fdb_entry->section = section;
@@ -95,7 +104,7 @@ static int set_fdb_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
}
/* send a request to the kernel to add a FDB entry in its static MAC table. */
-int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry) {
+int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
sd_netlink *rtnl;
int r;
@@ -146,12 +155,13 @@ void fdb_entry_free(FdbEntry *fdb_entry) {
return;
if (fdb_entry->network) {
- LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries,
- fdb_entry);
+ LIST_REMOVE(static_fdb_entries, fdb_entry->network->static_fdb_entries, fdb_entry);
+
+ assert(fdb_entry->network->n_static_fdb_entries > 0);
+ fdb_entry->network->n_static_fdb_entries--;
if (fdb_entry->section)
- hashmap_remove(fdb_entry->network->fdb_entries_by_section,
- UINT_TO_PTR(fdb_entry->section));
+ hashmap_remove(fdb_entry->network->fdb_entries_by_section, UINT_TO_PTR(fdb_entry->section));
}
free(fdb_entry->mac_addr);
@@ -232,9 +242,9 @@ int config_parse_fdb_vlan_id(
if (r < 0)
return log_oom();
- r = config_parse_unsigned(unit, filename, line, section,
- section_line, lvalue, ltype,
- rvalue, &fdb_entry->vlan_id, userdata);
+ r = config_parse_vlanid(unit, filename, line, section,
+ section_line, lvalue, ltype,
+ rvalue, &fdb_entry->vlan_id, userdata);
if (r < 0)
return r;
diff --git a/src/grp-network/libnetworkd-core/networkd-fdb.h b/src/grp-network/libnetworkd-core/networkd-fdb.h
index c04a2b0d37..a1ad4183dc 100644
--- a/src/grp-network/libnetworkd-core/networkd-fdb.h
+++ b/src/grp-network/libnetworkd-core/networkd-fdb.h
@@ -36,9 +36,9 @@ struct FdbEntry {
LIST_FIELDS(FdbEntry, static_fdb_entries);
};
-int fdb_entry_new_static(Network *const network, const unsigned section, FdbEntry **ret);
+int fdb_entry_new_static(Network *network, unsigned section, FdbEntry **ret);
void fdb_entry_free(FdbEntry *fdb_entry);
-int fdb_entry_configure(Link *const link, FdbEntry *const fdb_entry);
+int fdb_entry_configure(Link *link, FdbEntry *fdb_entry);
DEFINE_TRIVIAL_CLEANUP_FUNC(FdbEntry*, fdb_entry_free);
#define _cleanup_fdbentry_free_ _cleanup_(fdb_entry_freep)
diff --git a/src/grp-network/libnetworkd-core/networkd-ipv4ll.c b/src/grp-network/libnetworkd-core/networkd-ipv4ll.c
index 735cbc624d..5c6ffe30a7 100644
--- a/src/grp-network/libnetworkd-core/networkd-ipv4ll.c
+++ b/src/grp-network/libnetworkd-core/networkd-ipv4ll.c
@@ -140,7 +140,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
ll_addr->family = AF_INET;
ll_addr->in_addr.in = address;
ll_addr->prefixlen = 16;
- ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htonl(0xfffffffflu >> ll_addr->prefixlen);
+ ll_addr->broadcast.s_addr = ll_addr->in_addr.in.s_addr | htobe32(0xfffffffflu >> ll_addr->prefixlen);
ll_addr->scope = RT_SCOPE_LINK;
r = address_configure(ll_addr, link, ipv4ll_address_handler, false);
@@ -217,9 +217,7 @@ int ipv4ll_configure(Link *link) {
if (link->udev_device) {
r = net_get_unique_predictable_data(link->udev_device, &seed);
if (r >= 0) {
- assert_cc(sizeof(unsigned) <= 8);
-
- r = sd_ipv4ll_set_address_seed(link->ipv4ll, (unsigned)seed);
+ r = sd_ipv4ll_set_address_seed(link->ipv4ll, seed);
if (r < 0)
return r;
}
@@ -233,7 +231,7 @@ int ipv4ll_configure(Link *link) {
if (r < 0)
return r;
- r = sd_ipv4ll_set_index(link->ipv4ll, link->ifindex);
+ r = sd_ipv4ll_set_ifindex(link->ipv4ll, link->ifindex);
if (r < 0)
return r;
diff --git a/src/grp-network/libnetworkd-core/networkd-link.c b/src/grp-network/libnetworkd-core/networkd-link.c
index 72f6b5057e..d73629d679 100644
--- a/src/grp-network/libnetworkd-core/networkd-link.c
+++ b/src/grp-network/libnetworkd-core/networkd-link.c
@@ -38,6 +38,7 @@
#include "systemd-network/network-internal.h"
#include "networkd-lldp-tx.h"
+#include "networkd-ndisc.h"
#include "networkd.h"
static bool link_dhcp6_enabled(Link *link) {
@@ -112,7 +113,11 @@ static bool link_ipv6_enabled(Link *link) {
if (!socket_ipv6_is_supported())
return false;
- return link_dhcp6_enabled(link) || link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
+ if (link->network->bridge)
+ return false;
+
+ /* DHCPv6 client will not be started if no IPv6 link-local address is configured. */
+ return link_ipv6ll_enabled(link) || network_has_static_ipv6_addresses(link->network);
}
static bool link_lldp_rx_enabled(Link *link) {
@@ -393,7 +398,7 @@ static int link_update_flags(Link *link, sd_netlink_message *m) {
static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
_cleanup_link_unref_ Link *link = NULL;
uint16_t type;
- const char *ifname;
+ const char *ifname, *kind = NULL;
int r, ifindex;
unsigned short iftype;
@@ -401,6 +406,15 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
assert(message);
assert(ret);
+ /* check for link kind */
+ r = sd_netlink_message_enter_container(message, IFLA_LINKINFO);
+ if (r == 0) {
+ (void)sd_netlink_message_read_string(message, IFLA_INFO_KIND, &kind);
+ r = sd_netlink_message_exit_container(message);
+ if (r < 0)
+ return r;
+ }
+
r = sd_netlink_message_get_type(message, &type);
if (r < 0)
return r;
@@ -435,6 +449,12 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) {
if (!link->ifname)
return -ENOMEM;
+ if (kind) {
+ link->kind = strdup(kind);
+ if (!link->kind)
+ return -ENOMEM;
+ }
+
r = sd_netlink_message_read_ether_addr(message, IFLA_ADDRESS, &link->mac);
if (r < 0)
log_link_debug_errno(link, r, "MAC address not found for new device, continuing without");
@@ -502,13 +522,18 @@ static void link_free(Link *link) {
sd_ipv4ll_unref(link->ipv4ll);
sd_dhcp6_client_unref(link->dhcp6_client);
- sd_ndisc_unref(link->ndisc_router_discovery);
+ sd_ndisc_unref(link->ndisc);
+
+ set_free_free(link->ndisc_rdnss);
+ set_free_free(link->ndisc_dnssl);
if (link->manager)
hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
free(link->ifname);
+ free(link->kind);
+
(void)unlink(link->state_file);
free(link->state_file);
@@ -614,8 +639,8 @@ static int link_stop_clients(Link *link) {
r = log_link_warning_errno(link, k, "Could not stop DHCPv6 client: %m");
}
- if (link->ndisc_router_discovery) {
- k = sd_ndisc_stop(link->ndisc_router_discovery);
+ if (link->ndisc) {
+ k = sd_ndisc_stop(link->ndisc);
if (k < 0)
r = log_link_warning_errno(link, k, "Could not stop IPv6 Router Discovery: %m");
}
@@ -1090,7 +1115,17 @@ int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *u
return 1;
}
-static int link_set_bridge_fdb(Link *const link) {
+static int link_set_bridge_vlan(Link *link) {
+ int r = 0;
+
+ r = br_vlan_configure(link, link->network->pvid, link->network->br_vid_bitmap, link->network->br_untagged_bitmap);
+ if (r < 0)
+ log_link_error_errno(link, r, "Failed to assign VLANs to bridge port: %m");
+
+ return r;
+}
+
+static int link_set_bridge_fdb(Link *link) {
FdbEntry *fdb_entry;
int r = 0;
@@ -1105,7 +1140,7 @@ static int link_set_bridge_fdb(Link *const link) {
return r;
}
-static int link_set_proxy_arp(Link *const link) {
+static int link_set_proxy_arp(Link *link) {
const char *p = NULL;
int r;
@@ -1442,23 +1477,20 @@ static int link_acquire_ipv6_conf(Link *link) {
assert(link->dhcp6_client);
assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
- log_link_debug(link, "Acquiring DHCPv6 lease");
-
- r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
- if (r < 0 && r != -EBUSY)
- return log_link_warning_errno(link, r, "Could not set IPv6LL address in DHCP client: %m");
-
- r = sd_dhcp6_client_start(link->dhcp6_client);
+ /* start DHCPv6 client in stateless mode */
+ r = dhcp6_request_address(link, true);
if (r < 0 && r != -EBUSY)
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
+ else
+ log_link_debug(link, "Acquiring DHCPv6 lease");
}
if (link_ipv6_accept_ra_enabled(link)) {
- assert(link->ndisc_router_discovery);
+ assert(link->ndisc);
log_link_debug(link, "Discovering IPv6 routers");
- r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
+ r = sd_ndisc_start(link->ndisc);
if (r < 0 && r != -EBUSY)
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
}
@@ -1569,6 +1601,13 @@ static int link_up(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+ /* set it free if not enslaved with networkd */
+ if (!link->network->bridge && !link->network->bond && !link->network->vrf) {
+ r = sd_netlink_message_append_u32(req, IFLA_MASTER, 0);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_MASTER attribute: %m");
+ }
+
r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
if (r < 0)
return log_link_error_errno(link, r, "Could not set link flags: %m");
@@ -1579,8 +1618,8 @@ static int link_up(Link *link) {
return log_link_error_errno(link, r, "Could not set MAC address: %m");
}
- /* If IPv6 not configured (no static IPv6 address and neither DHCPv6 nor IPv6LL is enabled)
- for this interface then disable IPv6 else enable it. */
+ /* If IPv6 not configured (no static IPv6 address and IPv6LL autoconfiguration is disabled)
+ for this interface, or if it is a bridge slave, then disable IPv6 else enable it. */
(void) link_enable_ipv6(link);
if (link->network->mtu) {
@@ -1609,7 +1648,20 @@ static int link_up(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not open AF_INET6 container: %m");
- ipv6ll_mode = link_ipv6ll_enabled(link) ? IN6_ADDR_GEN_MODE_EUI64 : IN6_ADDR_GEN_MODE_NONE;
+ if (!link_ipv6ll_enabled(link))
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_NONE;
+ else {
+ const char *p = NULL;
+ _cleanup_free_ char *stable_secret = NULL;
+
+ p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/stable_secret");
+ r = read_one_line_file(p, &stable_secret);
+
+ if (r < 0)
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_EUI64;
+ else
+ ipv6ll_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ }
r = sd_netlink_message_append_u8(req, IFLA_INET6_ADDR_GEN_MODE, ipv6ll_mode);
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_INET6_ADDR_GEN_MODE: %m");
@@ -1955,6 +2007,12 @@ static int link_joined(Link *link) {
log_link_error_errno(link, r, "Could not set bridge message: %m");
}
+ if (link->network->bridge || streq_ptr("bridge", link->kind)) {
+ r = link_set_bridge_vlan(link);
+ if (r < 0)
+ log_link_error_errno(link, r, "Could not set bridge vlan: %m");
+ }
+
return link_enter_set_addresses(link);
}
@@ -1999,6 +2057,7 @@ static int link_enter_join_netdev(Link *link) {
if (!link->network->bridge &&
!link->network->bond &&
+ !link->network->vrf &&
hashmap_isempty(link->network->stacked_netdevs))
return link_joined(link);
@@ -2045,6 +2104,26 @@ static int link_enter_join_netdev(Link *link) {
link->enslaving++;
}
+ if (link->network->vrf) {
+ log_struct(LOG_DEBUG,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(link->network->vrf),
+ LOG_LINK_MESSAGE(link, "Enslaving by '%s'", link->network->vrf->ifname),
+ NULL);
+ r = netdev_join(link->network->vrf, link, netdev_join_handler);
+ if (r < 0) {
+ log_struct_errno(LOG_WARNING, r,
+ LOG_LINK_INTERFACE(link),
+ LOG_NETDEV_INTERFACE(link->network->vrf),
+ LOG_LINK_MESSAGE(link, "Could not join netdev '%s': %m", link->network->vrf->ifname),
+ NULL);
+ link_enter_failed(link);
+ return r;
+ }
+
+ link->enslaving++;
+ }
+
HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
log_struct(LOG_DEBUG,
@@ -2096,7 +2175,7 @@ static int link_set_ipv6_forward(Link *link) {
if (!link_ipv6_forward_enabled(link))
return 0;
- /* On Linux, the IPv6 stack does not not know a per-interface
+ /* On Linux, the IPv6 stack does not know a per-interface
* packet forwarding setting: either packet forwarding is on
* for all, or off for all. We hence don't bother with a
* per-interface setting, but simply propagate the interface
@@ -2148,7 +2227,7 @@ static int link_set_ipv6_accept_ra(Link *link) {
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
- /* We handle router advertisments ourselves, tell the kernel to GTFO */
+ /* We handle router advertisements ourselves, tell the kernel to GTFO */
r = write_string_file(p, "0", WRITE_STRING_FILE_VERIFY_ON_FAILURE);
if (r < 0)
log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
@@ -2233,7 +2312,7 @@ static int link_drop_foreign_config(Link *link) {
if (route->protocol == RTPROT_KERNEL)
continue;
- r = route_remove(route, link, link_address_remove_handler);
+ r = route_remove(route, link, link_route_remove_handler);
if (r < 0)
return r;
}
@@ -2345,7 +2424,11 @@ static int link_configure(Link *link) {
}
if (link_lldp_rx_enabled(link)) {
- r = sd_lldp_new(&link->lldp, link->ifindex);
+ r = sd_lldp_new(&link->lldp);
+ if (r < 0)
+ return r;
+
+ r = sd_lldp_set_ifindex(link->lldp, link->ifindex);
if (r < 0)
return r;
@@ -2645,7 +2728,7 @@ network_file_fail:
r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to set inital DHCPv4 address %s: %m", dhcp4_address);
+ return log_link_error_errno(link, r, "Falied to set initial DHCPv4 address %s: %m", dhcp4_address);
}
dhcp4_address_fail:
@@ -2663,7 +2746,7 @@ dhcp4_address_fail:
r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to set inital IPv4LL address %s: %m", ipv4ll_address);
+ return log_link_error_errno(link, r, "Falied to set initial IPv4LL address %s: %m", ipv4ll_address);
}
ipv4ll_address_fail:
@@ -3064,6 +3147,22 @@ int link_save(Link *link) {
if (space)
fputc(' ', f);
serialize_in6_addrs(f, in6_addrs, r);
+ space = true;
+ }
+ }
+
+ /* Make sure to flush out old entries before we use the NDISC data */
+ ndisc_vacuum(link);
+
+ if (link->network->dhcp_use_dns && link->ndisc_rdnss) {
+ NDiscRDNSS *dd;
+
+ SET_FOREACH(dd, link->ndisc_rdnss, i) {
+ if (space)
+ fputc(' ', f);
+
+ serialize_in6_addrs(f, &dd->address, 1);
+ space = true;
}
}
@@ -3109,7 +3208,6 @@ int link_save(Link *link) {
if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
if (link->dhcp_lease)
(void) sd_dhcp_lease_get_domainname(link->dhcp_lease, &dhcp_domainname);
-
if (dhcp6_lease)
(void) sd_dhcp6_lease_get_domains(dhcp6_lease, &dhcp6_domains);
}
@@ -3117,22 +3215,34 @@ int link_save(Link *link) {
fputs("DOMAINS=", f);
fputstrv(f, link->network->search_domains, NULL, &space);
- if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp_domainname)
- fputs_with_space(f, dhcp_domainname, NULL, &space);
+ if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES) {
+ NDiscDNSSL *dd;
- if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_YES && dhcp6_domains)
- fputstrv(f, dhcp6_domains, NULL, &space);
+ if (dhcp_domainname)
+ fputs_with_space(f, dhcp_domainname, NULL, &space);
+ if (dhcp6_domains)
+ fputstrv(f, dhcp6_domains, NULL, &space);
+
+ SET_FOREACH(dd, link->ndisc_dnssl, i)
+ fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
+ }
fputc('\n', f);
fputs("ROUTE_DOMAINS=", f);
fputstrv(f, link->network->route_domains, NULL, NULL);
- if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp_domainname)
- fputs_with_space(f, dhcp_domainname, NULL, &space);
+ if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE) {
+ NDiscDNSSL *dd;
- if (link->network->dhcp_use_domains == DHCP_USE_DOMAINS_ROUTE && dhcp6_domains)
- fputstrv(f, dhcp6_domains, NULL, &space);
+ if (dhcp_domainname)
+ fputs_with_space(f, dhcp_domainname, NULL, &space);
+ if (dhcp6_domains)
+ fputstrv(f, dhcp6_domains, NULL, &space);
+
+ SET_FOREACH(dd, link->ndisc_dnssl, i)
+ fputs_with_space(f, NDISC_DNSSL_DOMAIN(dd), NULL, &space);
+ }
fputc('\n', f);
diff --git a/src/grp-network/libnetworkd-core/networkd-link.h b/src/grp-network/libnetworkd-core/networkd-link.h
index ac10bd41b7..5c7b64a243 100644
--- a/src/grp-network/libnetworkd-core/networkd-link.h
+++ b/src/grp-network/libnetworkd-core/networkd-link.h
@@ -68,6 +68,7 @@ typedef struct Link {
int ifindex;
char *ifname;
+ char *kind;
unsigned short iftype;
char *state_file;
struct ether_addr mac;
@@ -98,6 +99,7 @@ typedef struct Link {
unsigned dhcp4_messages;
bool dhcp4_configured;
bool dhcp6_configured;
+
unsigned ndisc_messages;
bool ndisc_configured;
@@ -111,7 +113,10 @@ typedef struct Link {
sd_dhcp_server *dhcp_server;
- sd_ndisc *ndisc_router_discovery;
+ sd_ndisc *ndisc;
+ Set *ndisc_rdnss;
+ Set *ndisc_dnssl;
+
sd_dhcp6_client *dhcp6_client;
bool rtnl_extended_attrs;
@@ -160,8 +165,7 @@ int link_set_timezone(Link *link, const char *timezone);
int ipv4ll_configure(Link *link);
int dhcp4_configure(Link *link);
int dhcp6_configure(Link *link);
-int dhcp6_request_address(Link *link);
-int ndisc_configure(Link *link);
+int dhcp6_request_address(Link *link, int ir);
const char* link_state_to_string(LinkState s) _const_;
LinkState link_state_from_string(const char *s) _pure_;
diff --git a/src/grp-network/libnetworkd-core/networkd-ndisc.c b/src/grp-network/libnetworkd-core/networkd-ndisc.c
index c454be7ba3..27fbf3bc76 100644
--- a/src/grp-network/libnetworkd-core/networkd-ndisc.c
+++ b/src/grp-network/libnetworkd-core/networkd-ndisc.c
@@ -17,16 +17,16 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <netinet/ether.h>
#include <netinet/icmp6.h>
-#include <netinet/in.h>
-
-#include <linux/if.h>
#include "systemd-network/sd-ndisc.h"
+#include "networkd-ndisc.h"
#include "networkd.h"
+#define NDISC_DNSSL_MAX 64U
+#define NDISC_RDNSS_MAX 64U
+
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@@ -50,19 +50,92 @@ static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *
return 1;
}
-static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
- unsigned lifetime_preferred, unsigned lifetime_valid, void *userdata) {
- _cleanup_address_free_ Address *address = NULL;
- Link *link = userdata;
+static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
+ _cleanup_route_free_ Route *route = NULL;
+ struct in6_addr gateway;
+ uint16_t lifetime;
+ unsigned preference;
usec_t time_now;
int r;
- assert(nd);
assert(link);
- assert(link->network);
+ assert(rt);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ r = sd_ndisc_router_get_lifetime(rt, &lifetime);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
+ return;
+ }
+ if (lifetime == 0) /* not a default router */
+ return;
+
+ r = sd_ndisc_router_get_address(rt, &gateway);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
+ return;
+ }
+
+ r = sd_ndisc_router_get_preference(rt, &preference);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
+ return;
+ }
+
+ r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
+ return;
+ }
+
+ r = route_new(&route);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Could not allocate route: %m");
+ return;
+ }
+
+ route->family = AF_INET6;
+ route->table = RT_TABLE_MAIN;
+ route->protocol = RTPROT_RA;
+ route->pref = preference;
+ route->gw.in6 = gateway;
+ route->lifetime = time_now + lifetime * USEC_PER_SEC;
+
+ r = route_configure(route, link, ndisc_netlink_handler);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Could not set default route: %m");
+ link_enter_failed(link);
+ return;
+ }
+
+ link->ndisc_messages++;
+}
+
+static void ndisc_router_process_autonomous_prefix(Link *link, sd_ndisc_router *rt) {
+ _cleanup_address_free_ Address *address = NULL;
+ uint32_t lifetime_valid, lifetime_preferred;
+ unsigned prefixlen;
+ int r;
+
+ assert(link);
+ assert(rt);
+
+ r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix length: %m");
return;
+ }
+
+ r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime_valid);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix valid lifetime: %m");
+ return;
+ }
+
+ r = sd_ndisc_router_prefix_get_preferred_lifetime(rt, &lifetime_preferred);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix preferred lifetime: %m");
+ return;
+ }
r = address_new(&address);
if (r < 0) {
@@ -70,10 +143,13 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
return;
}
- assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
-
address->family = AF_INET6;
- address->in_addr.in6 = *prefix;
+ r = sd_ndisc_router_prefix_get_address(rt, &address->in_addr.in6);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix address: %m");
+ return;
+ }
+
if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0)
memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&link->network->ipv6_token) + 8, 8);
else {
@@ -103,17 +179,33 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
link->ndisc_messages++;
}
-static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata) {
+static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt) {
_cleanup_route_free_ Route *route = NULL;
- Link *link = userdata;
usec_t time_now;
+ uint32_t lifetime;
+ unsigned prefixlen;
int r;
- assert(nd);
assert(link);
+ assert(rt);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
return;
+ }
+
+ r = sd_ndisc_router_prefix_get_prefixlen(rt, &prefixlen);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix length: %m");
+ return;
+ }
+
+ r = sd_ndisc_router_prefix_get_valid_lifetime(rt, &lifetime);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix lifetime: %m");
+ return;
+ }
r = route_new(&route);
if (r < 0) {
@@ -121,16 +213,19 @@ static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *pre
return;
}
- assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
-
route->family = AF_INET6;
route->table = RT_TABLE_MAIN;
route->protocol = RTPROT_RA;
route->flags = RTM_F_PREFIX;
- route->dst.in6 = *prefix;
route->dst_prefixlen = prefixlen;
route->lifetime = time_now + lifetime * USEC_PER_SEC;
+ r = sd_ndisc_router_prefix_get_address(rt, &route->dst.in6);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get prefix address: %m");
+ return;
+ }
+
r = route_configure(route, link, ndisc_netlink_handler);
if (r < 0) {
log_link_warning_errno(link, r, "Could not set prefix route: %m");
@@ -141,34 +236,47 @@ static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *pre
link->ndisc_messages++;
}
-static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
+static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
_cleanup_route_free_ Route *route = NULL;
- Link *link = userdata;
+ struct in6_addr gateway;
+ uint32_t lifetime;
+ unsigned preference, prefixlen;
usec_t time_now;
int r;
assert(link);
- assert(link->network);
- assert(link->manager);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ r = sd_ndisc_router_route_get_lifetime(rt, &lifetime);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
+ return;
+ }
+ if (lifetime == 0)
return;
- if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) {
- if (flags & ND_RA_FLAG_MANAGED)
- dhcp6_request_address(link);
+ r = sd_ndisc_router_get_address(rt, &gateway);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get gateway address from RA: %m");
+ return;
+ }
- r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
- if (r < 0 && r != -EBUSY)
- log_link_warning_errno(link, r, "Could not set IPv6LL address in DHCP client: %m");
+ r = sd_ndisc_router_route_get_prefixlen(rt, &prefixlen);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get route prefix length: %m");
+ return;
+ }
- r = sd_dhcp6_client_start(link->dhcp6_client);
- if (r < 0 && r != -EBUSY)
- log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m");
+ r = sd_ndisc_router_route_get_preference(rt, &preference);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
+ return;
}
- if (!gateway)
+ r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
return;
+ }
r = route_new(&route);
if (r < 0) {
@@ -176,18 +284,23 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
return;
}
- assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
-
route->family = AF_INET6;
route->table = RT_TABLE_MAIN;
route->protocol = RTPROT_RA;
- route->pref = pref;
- route->gw.in6 = *gateway;
+ route->pref = preference;
+ route->gw.in6 = gateway;
+ route->dst_prefixlen = prefixlen;
route->lifetime = time_now + lifetime * USEC_PER_SEC;
+ r = sd_ndisc_router_route_get_address(rt, &route->dst.in6);
+ if (r < 0) {
+ log_link_error_errno(link, r, "Failed to get route address: %m");
+ return;
+ }
+
r = route_configure(route, link, ndisc_netlink_handler);
if (r < 0) {
- log_link_warning_errno(link, r, "Could not set default route: %m");
+ log_link_warning_errno(link, r, "Could not set additional route: %m");
link_enter_failed(link);
return;
}
@@ -195,33 +308,303 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
link->ndisc_messages++;
}
-static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
- Link *link = userdata;
+static void ndisc_rdnss_hash_func(const void *p, struct siphash *state) {
+ const NDiscRDNSS *x = p;
+
+ siphash24_compress(&x->address, sizeof(x->address), state);
+}
+
+static int ndisc_rdnss_compare_func(const void *_a, const void *_b) {
+ const NDiscRDNSS *a = _a, *b = _b;
+
+ return memcmp(&a->address, &b->address, sizeof(a->address));
+}
+
+static const struct hash_ops ndisc_rdnss_hash_ops = {
+ .hash = ndisc_rdnss_hash_func,
+ .compare = ndisc_rdnss_compare_func
+};
+
+static void ndisc_router_process_rdnss(Link *link, sd_ndisc_router *rt) {
+ uint32_t lifetime;
+ const struct in6_addr *a;
+ usec_t time_now;
+ int i, n, r;
+
+ assert(link);
+ assert(rt);
+
+ r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
+ return;
+ }
+
+ r = sd_ndisc_router_rdnss_get_lifetime(rt, &lifetime);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
+ return;
+ }
+
+ n = sd_ndisc_router_rdnss_get_addresses(rt, &a);
+ if (n < 0) {
+ log_link_warning_errno(link, n, "Failed to get RDNSS addresses: %m");
+ return;
+ }
+
+ for (i = 0; i < n; i++) {
+ NDiscRDNSS d = {
+ .address = a[i]
+ }, *x;
+
+ if (lifetime == 0) {
+ (void) set_remove(link->ndisc_rdnss, &d);
+ link_dirty(link);
+ continue;
+ }
+
+ x = set_get(link->ndisc_rdnss, &d);
+ if (x) {
+ x->valid_until = time_now + lifetime * USEC_PER_SEC;
+ continue;
+ }
+
+ ndisc_vacuum(link);
+
+ if (set_size(link->ndisc_rdnss) >= NDISC_RDNSS_MAX) {
+ log_link_warning(link, "Too many RDNSS records per link, ignoring.");
+ continue;
+ }
+
+ r = set_ensure_allocated(&link->ndisc_rdnss, &ndisc_rdnss_hash_ops);
+ if (r < 0) {
+ log_oom();
+ return;
+ }
+
+ x = new0(NDiscRDNSS, 1);
+ if (!x) {
+ log_oom();
+ return;
+ }
+
+ x->address = a[i];
+ x->valid_until = time_now + lifetime * USEC_PER_SEC;
+
+ r = set_put(link->ndisc_rdnss, x);
+ if (r < 0) {
+ free(x);
+ log_oom();
+ return;
+ }
+
+ assert(r > 0);
+ link_dirty(link);
+ }
+}
+
+static void ndisc_dnssl_hash_func(const void *p, struct siphash *state) {
+ const NDiscDNSSL *x = p;
+
+ siphash24_compress(NDISC_DNSSL_DOMAIN(x), strlen(NDISC_DNSSL_DOMAIN(x)), state);
+}
+
+static int ndisc_dnssl_compare_func(const void *_a, const void *_b) {
+ const NDiscDNSSL *a = _a, *b = _b;
+
+ return strcmp(NDISC_DNSSL_DOMAIN(a), NDISC_DNSSL_DOMAIN(b));
+}
+
+static const struct hash_ops ndisc_dnssl_hash_ops = {
+ .hash = ndisc_dnssl_hash_func,
+ .compare = ndisc_dnssl_compare_func
+};
+
+static void ndisc_router_process_dnssl(Link *link, sd_ndisc_router *rt) {
+ _cleanup_strv_free_ char **l = NULL;
+ uint32_t lifetime;
+ usec_t time_now;
+ char **i;
int r;
assert(link);
+ assert(rt);
- if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ r = sd_ndisc_router_get_timestamp(rt, clock_boottime_or_monotonic(), &time_now);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA timestamp: %m");
return;
+ }
- switch (event) {
- case SD_NDISC_EVENT_TIMEOUT:
- dhcp6_request_address(link);
+ r = sd_ndisc_router_dnssl_get_lifetime(rt, &lifetime);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RDNSS lifetime: %m");
+ return;
+ }
- r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
- if (r < 0 && r != -EBUSY)
- log_link_warning_errno(link, r, "Could not set IPv6LL address in DHCP client: %m");
+ r = sd_ndisc_router_dnssl_get_domains(rt, &l);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RDNSS addresses: %m");
+ return;
+ }
+
+ STRV_FOREACH(i, l) {
+ _cleanup_free_ NDiscDNSSL *s;
+ NDiscDNSSL *x;
+
+ s = malloc0(ALIGN(sizeof(NDiscDNSSL)) + strlen(*i) + 1);
+ if (!s) {
+ log_oom();
+ return;
+ }
+
+ strcpy(NDISC_DNSSL_DOMAIN(s), *i);
+
+ if (lifetime == 0) {
+ (void) set_remove(link->ndisc_dnssl, s);
+ link_dirty(link);
+ continue;
+ }
+
+ x = set_get(link->ndisc_dnssl, s);
+ if (x) {
+ x->valid_until = time_now + lifetime * USEC_PER_SEC;
+ continue;
+ }
+
+ ndisc_vacuum(link);
+
+ if (set_size(link->ndisc_dnssl) >= NDISC_DNSSL_MAX) {
+ log_link_warning(link, "Too many DNSSL records per link, ignoring.");
+ continue;
+ }
+
+ r = set_ensure_allocated(&link->ndisc_dnssl, &ndisc_dnssl_hash_ops);
+ if (r < 0) {
+ log_oom();
+ return;
+ }
+
+ s->valid_until = time_now + lifetime * USEC_PER_SEC;
+
+ r = set_put(link->ndisc_dnssl, s);
+ if (r < 0) {
+ log_oom();
+ return;
+ }
+
+ s = NULL;
+ assert(r > 0);
+ link_dirty(link);
+ }
+}
+
+static void ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
+ int r;
+
+ assert(link);
+ assert(rt);
+
+ r = sd_ndisc_router_option_rewind(rt);
+ for (;;) {
+ uint8_t type;
+
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to iterate through options: %m");
+ return;
+ }
+ if (r == 0) /* EOF */
+ break;
+
+ r = sd_ndisc_router_option_get_type(rt, &type);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA option type: %m");
+ return;
+ }
+
+ switch (type) {
+
+ case SD_NDISC_OPTION_PREFIX_INFORMATION: {
+ uint8_t flags;
+
+ r = sd_ndisc_router_prefix_get_flags(rt, &flags);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA prefix flags: %m");
+ return;
+ }
+
+ if (flags & ND_OPT_PI_FLAG_ONLINK)
+ ndisc_router_process_onlink_prefix(link, rt);
+ if (flags & ND_OPT_PI_FLAG_AUTO)
+ ndisc_router_process_autonomous_prefix(link, rt);
+
+ break;
+ }
+
+ case SD_NDISC_OPTION_ROUTE_INFORMATION:
+ ndisc_router_process_route(link, rt);
+ break;
+
+ case SD_NDISC_OPTION_RDNSS:
+ ndisc_router_process_rdnss(link, rt);
+ break;
+
+ case SD_NDISC_OPTION_DNSSL:
+ ndisc_router_process_dnssl(link, rt);
+ break;
+ }
+
+ r = sd_ndisc_router_option_next(rt);
+ }
+}
+
+static void ndisc_router_handler(Link *link, sd_ndisc_router *rt) {
+ uint64_t flags;
+ int r;
- r = sd_dhcp6_client_start(link->dhcp6_client);
+ assert(link);
+ assert(link->network);
+ assert(link->manager);
+ assert(rt);
+
+ r = sd_ndisc_router_get_flags(rt, &flags);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to get RA flags: %m");
+ return;
+ }
+
+ if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) {
+ /* (re)start DHCPv6 client in stateful or stateless mode according to RA flags */
+ r = dhcp6_request_address(link, !(flags & ND_RA_FLAG_MANAGED));
if (r < 0 && r != -EBUSY)
- log_link_warning_errno(link, r, "Starting DHCPv6 client after NDisc timeout failed: %m");
+ log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease on NDisc request: %m");
+ else
+ log_link_debug(link, "Acquiring DHCPv6 lease on NDisc request");
+ }
+
+ ndisc_router_process_default(link, rt);
+ ndisc_router_process_options(link, rt);
+}
+static void ndisc_handler(sd_ndisc *nd, sd_ndisc_event event, sd_ndisc_router *rt, void *userdata) {
+ Link *link = userdata;
+
+ assert(link);
+
+ if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
+ return;
+
+ switch (event) {
+
+ case SD_NDISC_EVENT_ROUTER:
+ ndisc_router_handler(link, rt);
+ break;
+
+ case SD_NDISC_EVENT_TIMEOUT:
link->ndisc_configured = true;
link_check_ready(link);
break;
- case SD_NDISC_EVENT_STOP:
- break;
default:
log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
}
@@ -230,30 +613,52 @@ static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
int ndisc_configure(Link *link) {
int r;
- assert_return(link, -EINVAL);
+ assert(link);
+
+ r = sd_ndisc_new(&link->ndisc);
+ if (r < 0)
+ return r;
- r = sd_ndisc_new(&link->ndisc_router_discovery);
+ r = sd_ndisc_attach_event(link->ndisc, NULL, 0);
if (r < 0)
return r;
- r = sd_ndisc_attach_event(link->ndisc_router_discovery, NULL, 0);
+ r = sd_ndisc_set_mac(link->ndisc, &link->mac);
if (r < 0)
return r;
- r = sd_ndisc_set_mac(link->ndisc_router_discovery, &link->mac);
+ r = sd_ndisc_set_ifindex(link->ndisc, link->ifindex);
if (r < 0)
return r;
- r = sd_ndisc_set_index(link->ndisc_router_discovery, link->ifindex);
+ r = sd_ndisc_set_callback(link->ndisc, ndisc_handler, link);
if (r < 0)
return r;
- r = sd_ndisc_set_callback(link->ndisc_router_discovery,
- ndisc_router_handler,
- ndisc_prefix_onlink_handler,
- ndisc_prefix_autonomous_handler,
- ndisc_handler,
- link);
+ return 0;
+}
+
+void ndisc_vacuum(Link *link) {
+ NDiscRDNSS *r;
+ NDiscDNSSL *d;
+ Iterator i;
+ usec_t time_now;
+
+ assert(link);
+
+ /* Removes all RDNSS and DNSSL entries whose validity time has passed */
+
+ time_now = now(clock_boottime_or_monotonic());
+
+ SET_FOREACH(r, link->ndisc_rdnss, i)
+ if (r->valid_until < time_now) {
+ (void) set_remove(link->ndisc_rdnss, r);
+ link_dirty(link);
+ }
- return r;
+ SET_FOREACH(d, link->ndisc_dnssl, i)
+ if (d->valid_until < time_now) {
+ (void) set_remove(link->ndisc_dnssl, d);
+ link_dirty(link);
+ }
}
diff --git a/src/grp-network/libnetworkd-core/networkd-ndisc.h b/src/grp-network/libnetworkd-core/networkd-ndisc.h
new file mode 100644
index 0000000000..2002f55107
--- /dev/null
+++ b/src/grp-network/libnetworkd-core/networkd-ndisc.h
@@ -0,0 +1,39 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2013 Tom Gundersen <teg@jklm.no>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "networkd-link.h"
+
+typedef struct NDiscRDNSS {
+ usec_t valid_until;
+ struct in6_addr address;
+} NDiscRDNSS;
+
+typedef struct NDiscDNSSL {
+ usec_t valid_until;
+ /* The domain name follows immediately. */
+} NDiscDNSSL;
+
+static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
+ return ((char*) n) + ALIGN(sizeof(NDiscDNSSL));
+}
+
+int ndisc_configure(Link *link);
+void ndisc_vacuum(Link *link);
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-bridge.c b/src/grp-network/libnetworkd-core/networkd-netdev-bridge.c
index 54ef059df0..2de2587e36 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-bridge.c
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-bridge.c
@@ -103,6 +103,12 @@ static int netdev_bridge_post_create(NetDev *netdev, Link *link, sd_netlink_mess
return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_MCAST_SNOOPING attribute: %m");
}
+ if (b->vlan_filtering >= 0) {
+ r = sd_netlink_message_append_u8(req, IFLA_BR_VLAN_FILTERING, b->vlan_filtering);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_FILTERING attribute: %m");
+ }
+
r = sd_netlink_message_close_container(req);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
@@ -129,6 +135,7 @@ static void bridge_init(NetDev *n) {
b->mcast_querier = -1;
b->mcast_snooping = -1;
+ b->vlan_filtering = -1;
}
const NetDevVTable bridge_vtable = {
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-bridge.h b/src/grp-network/libnetworkd-core/networkd-netdev-bridge.h
index f2ae21fc50..a637aea0a3 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-bridge.h
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-bridge.h
@@ -26,6 +26,7 @@ typedef struct Bridge {
int mcast_querier;
int mcast_snooping;
+ int vlan_filtering;
usec_t forward_delay;
usec_t hello_time;
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-gperf.gperf b/src/grp-network/libnetworkd-core/networkd-netdev-gperf.gperf
index 09eed25146..e478b53f43 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-gperf.gperf
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-gperf.gperf
@@ -2,6 +2,7 @@
#include <stddef.h>
#include "shared/conf-parser.h"
+#include "shared/vlan-util.h"
#include "systemd-network/network-internal.h"
#include "networkd-netdev-bond.h"
@@ -12,6 +13,7 @@
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
+#include "networkd-netdev-vrf.h"
#include "networkd-netdev-vxlan.h"
#include "networkd-netdev.h"
%}
@@ -35,7 +37,7 @@ NetDev.Name, config_parse_ifname, 0,
NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind)
NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu)
NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac)
-VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id)
+VLAN.Id, config_parse_vlanid, 0, offsetof(VLan, id)
MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
MACVTAP.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode)
IPVLAN.Mode, config_parse_ipvlan_mode, 0, offsetof(IPVlan, mode)
@@ -43,6 +45,9 @@ Tunnel.Local, config_parse_tunnel_address, 0,
Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote)
Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos)
Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl)
+Tunnel.Key, config_parse_tunnel_key, 0, offsetof(Tunnel, key)
+Tunnel.InputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, ikey)
+Tunnel.OutputKey, config_parse_tunnel_key, 0, offsetof(Tunnel, okey)
Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc)
Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode)
Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel)
@@ -102,3 +107,5 @@ Bridge.MaxAgeSec, config_parse_sec, 0,
Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay)
Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier)
Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping)
+Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering)
+VRF.TableId, config_parse_uint32, 0, offsetof(Vrf, table_id)
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.c b/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.c
index c372dd7860..e94c19126b 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.c
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.c
@@ -36,7 +36,7 @@
#include "networkd-netdev-tunnel.h"
#define DEFAULT_TNL_HOP_LIMIT 64
-#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
+#define IP6_FLOWINFO_FLOWLABEL htobe32(0x000FFFFF)
static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
[NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -201,6 +201,33 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
return r;
}
+static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ Tunnel *t = VTI(netdev);
+ uint32_t ikey, okey;
+ int r;
+
+ assert(link);
+ assert(m);
+ assert(t);
+
+ if (t->key != 0)
+ ikey = okey = htobe32(t->key);
+ else {
+ ikey = htobe32(t->ikey);
+ okey = htobe32(t->okey);
+ }
+
+ r = sd_netlink_message_append_u32(m, IFLA_VTI_IKEY, ikey);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_IKEY attribute: %m");
+
+ r = sd_netlink_message_append_u32(m, IFLA_VTI_OKEY, okey);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_VTI_OKEY attribute: %m");
+
+ return 0;
+}
+
static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
Tunnel *t = VTI(netdev);
int r;
@@ -215,6 +242,10 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_netlink
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
+ r = netdev_vti_fill_message_key(netdev, link, m);
+ if (r < 0)
+ return r;
+
r = sd_netlink_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
@@ -240,6 +271,10 @@ static int netdev_vti6_fill_message_create(NetDev *netdev, Link *link, sd_netlin
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LINK attribute: %m");
+ r = netdev_vti_fill_message_key(netdev, link, m);
+ if (r < 0)
+ return r;
+
r = sd_netlink_message_append_in6_addr(m, IFLA_VTI_LOCAL, &t->local.in6);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_LOCAL attribute: %m");
@@ -414,6 +449,46 @@ int config_parse_tunnel_address(const char *unit,
return 0;
}
+int config_parse_tunnel_key(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ union in_addr_union buffer;
+ Tunnel *t = userdata;
+ uint32_t k;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = in_addr_from_string(AF_INET, rvalue, &buffer);
+ if (r < 0) {
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse tunnel key ignoring assignment: %s", rvalue);
+ return 0;
+ }
+ } else
+ k = be32toh(buffer.in.s_addr);
+
+ if (streq(lvalue, "Key"))
+ t->key = k;
+ else if (streq(lvalue, "InputKey"))
+ t->ikey = k;
+ else
+ t->okey = k;
+
+ return 0;
+}
+
int config_parse_ipv6_flowlabel(const char* unit,
const char *filename,
unsigned line,
@@ -445,7 +520,7 @@ int config_parse_ipv6_flowlabel(const char* unit,
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;
+ *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;
t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
}
}
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.h b/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.h
index 6b65431e7e..09bd86656e 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.h
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-tunnel.h
@@ -49,6 +49,10 @@ typedef struct Tunnel {
unsigned tos;
unsigned flags;
+ uint32_t key;
+ uint32_t ikey;
+ uint32_t okey;
+
union in_addr_union local;
union in_addr_union remote;
@@ -108,3 +112,8 @@ int config_parse_encap_limit(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_key(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata);
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-vlan.c b/src/grp-network/libnetworkd-core/networkd-netdev-vlan.c
index b1f4714afa..0c24d5e859 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-vlan.c
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-vlan.c
@@ -19,6 +19,8 @@
#include <net/if.h>
+#include "shared/vlan-util.h"
+
#include "networkd-netdev-vlan.h"
static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *req) {
@@ -33,11 +35,9 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_netlin
assert(v);
- if (v->id <= VLANID_MAX) {
- r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id);
- if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m");
- }
+ r = sd_netlink_message_append_u16(req, IFLA_VLAN_ID, v->id);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_VLAN_ID attribute: %m");
return 0;
}
@@ -52,8 +52,8 @@ static int netdev_vlan_verify(NetDev *netdev, const char *filename) {
assert(v);
- if (v->id > VLANID_MAX) {
- log_warning("VLAN without valid Id (%"PRIu64") configured in %s. Ignoring", v->id, filename);
+ if (v->id == VLANID_INVALID) {
+ log_warning("VLAN without valid Id (%"PRIu16") configured in %s.", v->id, filename);
return -EINVAL;
}
@@ -66,7 +66,7 @@ static void vlan_init(NetDev *netdev) {
assert(netdev);
assert(v);
- v->id = VLANID_MAX + 1;
+ v->id = VLANID_INVALID;
}
const NetDevVTable vlan_vtable = {
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-vlan.h b/src/grp-network/libnetworkd-core/networkd-netdev-vlan.h
index 73aacf4a0f..2dfe314b6e 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev-vlan.h
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-vlan.h
@@ -23,12 +23,10 @@ typedef struct VLan VLan;
#include "networkd-netdev.h"
-#define VLANID_MAX 4094
-
struct VLan {
NetDev meta;
- uint64_t id;
+ uint16_t id;
};
DEFINE_NETDEV_CAST(VLAN, VLan);
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-vrf.c b/src/grp-network/libnetworkd-core/networkd-netdev-vrf.c
new file mode 100644
index 0000000000..8f91a11757
--- /dev/null
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-vrf.c
@@ -0,0 +1,51 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <net/if.h>
+
+#include "basic/missing.h"
+#include "sd-netlink/sd-netlink.h"
+
+#include "networkd-netdev-vrf.h"
+
+static int netdev_vrf_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ Vrf *v;
+ int r;
+
+ assert(netdev);
+ assert(!link);
+ assert(m);
+
+ v = VRF(netdev);
+
+ assert(v);
+
+ r = sd_netlink_message_append_u32(m, IFLA_VRF_TABLE, v->table_id);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IPLA_VRF_TABLE attribute: %m");
+
+ return r;
+}
+
+const NetDevVTable vrf_vtable = {
+ .object_size = sizeof(Vrf),
+ .sections = "NetDev\0VRF\0",
+ .fill_message_create = netdev_vrf_fill_message_create,
+ .create_type = NETDEV_CREATE_MASTER,
+};
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev-vrf.h b/src/grp-network/libnetworkd-core/networkd-netdev-vrf.h
new file mode 100644
index 0000000000..3d92a26a4d
--- /dev/null
+++ b/src/grp-network/libnetworkd-core/networkd-netdev-vrf.h
@@ -0,0 +1,33 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Andreas Rammhold <andreas@rammhold.de>
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef struct Vrf Vrf;
+
+#include "networkd-netdev.h"
+
+struct Vrf {
+ NetDev meta;
+
+ uint32_t table_id;
+};
+
+DEFINE_NETDEV_CAST(VRF, Vrf);
+extern const NetDevVTable vrf_vtable;
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev.c b/src/grp-network/libnetworkd-core/networkd-netdev.c
index c421042196..7cc5969cce 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev.c
+++ b/src/grp-network/libnetworkd-core/networkd-netdev.c
@@ -56,6 +56,8 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TUN] = &tun_vtable,
[NETDEV_KIND_TAP] = &tap_vtable,
[NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
+ [NETDEV_KIND_VRF] = &vrf_vtable,
+
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -79,6 +81,8 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TUN] = "tun",
[NETDEV_KIND_TAP] = "tap",
[NETDEV_KIND_IP6TNL] = "ip6tnl",
+ [NETDEV_KIND_VRF] = "vrf",
+
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -199,7 +203,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_netlink_message_h
assert(netdev->state == NETDEV_STATE_READY);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
assert(link);
assert(callback);
@@ -282,7 +286,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_netlink_message_handler_t call
assert(netdev);
assert(netdev->manager);
assert(netdev->manager->rtnl);
- assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
+ assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND, NETDEV_KIND_VRF));
if (netdev->state == NETDEV_STATE_READY) {
r = netdev_enslave_ready(netdev, link, callback);
@@ -616,7 +620,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
return 0;
- if (!NETDEV_VTABLE(netdev_raw)) {
+ if (netdev_raw->kind == _NETDEV_KIND_INVALID) {
log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename);
return 0;
}
diff --git a/src/grp-network/libnetworkd-core/networkd-netdev.h b/src/grp-network/libnetworkd-core/networkd-netdev.h
index 43311852b2..dcec00af47 100644
--- a/src/grp-network/libnetworkd-core/networkd-netdev.h
+++ b/src/grp-network/libnetworkd-core/networkd-netdev.h
@@ -54,6 +54,7 @@ typedef enum NetDevKind {
NETDEV_KIND_DUMMY,
NETDEV_KIND_TUN,
NETDEV_KIND_TAP,
+ NETDEV_KIND_VRF,
_NETDEV_KIND_MAX,
_NETDEV_KIND_INVALID = -1
} NetDevKind;
diff --git a/src/grp-network/libnetworkd-core/networkd-network-bus.c b/src/grp-network/libnetworkd-core/networkd-network-bus.c
index 572c0913a9..d4cd275ffe 100644
--- a/src/grp-network/libnetworkd-core/networkd-network-bus.c
+++ b/src/grp-network/libnetworkd-core/networkd-network-bus.c
@@ -61,7 +61,7 @@ const sd_bus_vtable network_vtable[] = {
SD_BUS_PROPERTY("Description", "s", NULL, offsetof(Network, description), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("SourcePath", "s", NULL, offsetof(Network, filename), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, offsetof(Network, match_mac), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("MatchMAC", "as", property_get_ether_addrs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchPath", "as", NULL, offsetof(Network, match_path), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchDriver", "as", NULL, offsetof(Network, match_driver), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MatchType", "as", NULL, offsetof(Network, match_type), SD_BUS_VTABLE_PROPERTY_CONST),
diff --git a/src/grp-network/libnetworkd-core/networkd-network-gperf.gperf b/src/grp-network/libnetworkd-core/networkd-network-gperf.gperf
index 490fbb06e9..e214790436 100644
--- a/src/grp-network/libnetworkd-core/networkd-network-gperf.gperf
+++ b/src/grp-network/libnetworkd-core/networkd-network-gperf.gperf
@@ -2,6 +2,7 @@
#include <stddef.h>
#include "shared/conf-parser.h"
+#include "shared/vlan-util.h"
#include "systemd-network/network-internal.h"
#include "networkd-conf.h"
@@ -38,6 +39,7 @@ Network.MACVTAP, config_parse_netdev,
Network.IPVLAN, config_parse_netdev, 0, 0
Network.VXLAN, config_parse_netdev, 0, 0
Network.Tunnel, config_parse_tunnel, 0, 0
+Network.VRF, config_parse_netdev, 0, 0
Network.DHCP, config_parse_dhcp, 0, offsetof(Network, dhcp)
Network.DHCPServer, config_parse_bool, 0, offsetof(Network, dhcp_server)
Network.LinkLocalAddressing, config_parse_address_family_boolean, 0, offsetof(Network, link_local)
@@ -52,11 +54,13 @@ Network.DNS, config_parse_strv,
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
-Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, offsetof(Network, dnssec_negative_trust_anchors)
+Network.DNSSECNegativeTrustAnchors, config_parse_dnssec_negative_trust_anchors, 0, 0
Network.NTP, config_parse_strv, 0, offsetof(Network, ntp)
Network.IPForward, config_parse_address_family_boolean_with_kernel,0, offsetof(Network, ip_forward)
Network.IPMasquerade, config_parse_bool, 0, offsetof(Network, ip_masquerade)
Network.IPv6PrivacyExtensions, config_parse_ipv6_privacy_extensions, 0, offsetof(Network, ipv6_privacy_extensions)
+Network.IPv6AcceptRA, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
+/* legacy alias for the above */
Network.IPv6AcceptRouterAdvertisements, config_parse_tristate, 0, offsetof(Network, ipv6_accept_ra)
Network.IPv6DuplicateAddressDetection, config_parse_int, 0, offsetof(Network, ipv6_dad_transmits)
Network.IPv6HopLimit, config_parse_int, 0, offsetof(Network, ipv6_hop_limit)
@@ -91,6 +95,8 @@ DHCP.DUIDRawData, config_parse_duid_rawdata,
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
+IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
+IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
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)
@@ -110,6 +116,9 @@ Bridge.AllowPortToBeRoot, config_parse_bool,
Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
+BridgeVLAN.PVID, config_parse_vlanid, 0, offsetof(Network, pvid)
+BridgeVLAN.VLAN, config_parse_brvlan_vlan, 0, 0
+BridgeVLAN.EgressUntagged, config_parse_brvlan_untagged, 0, 0
/* backwards compatibility: do not add new entries to this section */
Network.IPv4LL, config_parse_ipv4ll, 0, offsetof(Network, link_local)
DHCPv4.UseDNS, config_parse_bool, 0, offsetof(Network, dhcp_use_dns)
diff --git a/src/grp-network/libnetworkd-core/networkd-network.c b/src/grp-network/libnetworkd-core/networkd-network.c
index 2895fd4bd9..697b748e52 100644
--- a/src/grp-network/libnetworkd-core/networkd-network.c
+++ b/src/grp-network/libnetworkd-core/networkd-network.c
@@ -52,8 +52,8 @@ static int network_load_one(Manager *manager, const char *filename) {
if (!file) {
if (errno == ENOENT)
return 0;
- else
- return -errno;
+
+ return -errno;
}
if (null_or_empty_fd(fileno(file))) {
@@ -135,6 +135,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->ipv6_hop_limit = -1;
network->duid.type = _DUID_TYPE_INVALID;
network->proxy_arp = -1;
+ network->ipv6_accept_ra_use_dns = true;
r = config_parse(NULL, filename, file,
"Match\0"
@@ -145,8 +146,10 @@ static int network_load_one(Manager *manager, const char *filename) {
"DHCP\0"
"DHCPv4\0" /* compat */
"DHCPServer\0"
+ "IPv6AcceptRA\0"
"Bridge\0"
- "BridgeFDB\0",
+ "BridgeFDB\0"
+ "BridgeVLAN\0",
config_item_perf_lookup, network_network_gperf_lookup,
false, false, true, network);
if (r < 0)
@@ -242,8 +245,8 @@ void network_free(Network *network) {
strv_free(network->bind_carrier);
netdev_unref(network->bridge);
-
netdev_unref(network->bond);
+ netdev_unref(network->vrf);
HASHMAP_FOREACH(netdev, network->stacked_netdevs, i) {
hashmap_remove(network->stacked_netdevs, netdev->ifname);
@@ -469,6 +472,10 @@ int config_parse_netdev(const char *unit,
network->bond = netdev;
break;
+ case NETDEV_KIND_VRF:
+ network->vrf = netdev;
+
+ break;
case NETDEV_KIND_VLAN:
case NETDEV_KIND_MACVLAN:
case NETDEV_KIND_MACVTAP:
diff --git a/src/grp-network/libnetworkd-core/networkd-network.h b/src/grp-network/libnetworkd-core/networkd-network.h
index fdf76b8924..66430a7c45 100644
--- a/src/grp-network/libnetworkd-core/networkd-network.h
+++ b/src/grp-network/libnetworkd-core/networkd-network.h
@@ -28,6 +28,7 @@
#include "udev.h"
#include "networkd-address.h"
+#include "networkd-brvlan.h"
#include "networkd-fdb.h"
#include "networkd-lldp-tx.h"
#include "networkd-netdev.h"
@@ -37,6 +38,9 @@
#define DHCP_ROUTE_METRIC 1024
#define IPV4LL_ROUTE_METRIC 2048
+#define BRIDGE_VLAN_BITMAP_MAX 4096
+#define BRIDGE_VLAN_BITMAP_LEN (BRIDGE_VLAN_BITMAP_MAX / 32)
+
typedef enum DCHPClientIdentifier {
DHCP_CLIENT_ID_MAC,
DHCP_CLIENT_ID_DUID,
@@ -100,6 +104,7 @@ struct Network {
NetDev *bridge;
NetDev *bond;
+ NetDev *vrf;
Hashmap *stacked_netdevs;
/* DHCP Client Support */
@@ -146,6 +151,10 @@ struct Network {
bool unicast_flood;
unsigned cost;
+ uint16_t pvid;
+ uint32_t br_vid_bitmap[BRIDGE_VLAN_BITMAP_LEN];
+ uint32_t br_untagged_bitmap[BRIDGE_VLAN_BITMAP_LEN];
+
AddressFamilyBoolean ip_forward;
bool ip_masquerade;
@@ -154,6 +163,9 @@ struct Network {
int ipv6_hop_limit;
int proxy_arp;
+ bool ipv6_accept_ra_use_dns;
+ DHCPUseDomains ipv6_accept_ra_use_domains;
+
union in_addr_union ipv6_token;
IPv6PrivacyExtensions ipv6_privacy_extensions;
@@ -169,6 +181,10 @@ struct Network {
LIST_HEAD(Route, static_routes);
LIST_HEAD(FdbEntry, static_fdb_entries);
+ unsigned n_static_addresses;
+ unsigned n_static_routes;
+ unsigned n_static_fdb_entries;
+
Hashmap *addresses_by_section;
Hashmap *routes_by_section;
Hashmap *fdb_entries_by_section;
diff --git a/src/grp-network/libnetworkd-core/networkd-route.c b/src/grp-network/libnetworkd-core/networkd-route.c
index 974a7fa847..f6e2d4858e 100644
--- a/src/grp-network/libnetworkd-core/networkd-route.c
+++ b/src/grp-network/libnetworkd-core/networkd-route.c
@@ -29,6 +29,9 @@
#include "networkd-route.h"
#include "networkd.h"
+#define ROUTES_PER_LINK_MAX 2048U
+#define STATIC_ROUTES_PER_NETWORK_MAX 1024U
+
int route_new(Route **ret) {
_cleanup_route_free_ Route *route = NULL;
@@ -52,6 +55,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
_cleanup_route_free_ Route *route = NULL;
int r;
+ assert(network);
+ assert(ret);
+
if (section) {
route = hashmap_get(network->routes_by_section, UINT_TO_PTR(section));
if (route) {
@@ -62,6 +68,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
}
}
+ if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX)
+ return -E2BIG;
+
r = route_new(&route);
if (r < 0)
return r;
@@ -78,6 +87,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
route->network = network;
LIST_PREPEND(routes, network->static_routes, route);
+ network->n_static_routes++;
*ret = route;
route = NULL;
@@ -92,9 +102,11 @@ void route_free(Route *route) {
if (route->network) {
LIST_REMOVE(routes, route->network->static_routes, route);
+ assert(route->network->n_static_routes > 0);
+ route->network->n_static_routes--;
+
if (route->section)
- hashmap_remove(route->network->routes_by_section,
- UINT_TO_PTR(route->section));
+ hashmap_remove(route->network->routes_by_section, UINT_TO_PTR(route->section));
}
if (route->link) {
@@ -177,48 +189,55 @@ static const struct hash_ops route_hash_ops = {
int route_get(Link *link,
int family,
- union in_addr_union *dst,
+ const union in_addr_union *dst,
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
unsigned char table,
Route **ret) {
- Route route = {
+
+ Route route, *existing;
+
+ assert(link);
+ assert(dst);
+
+ route = (Route) {
.family = family,
+ .dst = *dst,
.dst_prefixlen = dst_prefixlen,
.tos = tos,
.priority = priority,
.table = table,
- }, *existing;
-
- assert(link);
- assert(dst);
- assert(ret);
-
- route.dst = *dst;
+ };
existing = set_get(link->routes, &route);
if (existing) {
- *ret = existing;
+ if (ret)
+ *ret = existing;
return 1;
- } else {
- existing = set_get(link->routes_foreign, &route);
- if (!existing)
- return -ENOENT;
}
- *ret = existing;
+ existing = set_get(link->routes_foreign, &route);
+ if (existing) {
+ if (ret)
+ *ret = existing;
+ return 0;
+ }
- return 0;
+ return -ENOENT;
}
-static int route_add_internal(Link *link, Set **routes,
- int family,
- union in_addr_union *dst,
- unsigned char dst_prefixlen,
- unsigned char tos,
- uint32_t priority,
- unsigned char table, Route **ret) {
+static int route_add_internal(
+ Link *link,
+ Set **routes,
+ int family,
+ const union in_addr_union *dst,
+ unsigned char dst_prefixlen,
+ unsigned char tos,
+ uint32_t priority,
+ unsigned char table,
+ Route **ret) {
+
_cleanup_route_free_ Route *route = NULL;
int r;
@@ -255,23 +274,29 @@ static int route_add_internal(Link *link, Set **routes,
return 0;
}
-int route_add_foreign(Link *link,
- int family,
- union in_addr_union *dst,
- unsigned char dst_prefixlen,
- unsigned char tos,
- uint32_t priority,
- unsigned char table, Route **ret) {
+int route_add_foreign(
+ Link *link,
+ int family,
+ const union in_addr_union *dst,
+ unsigned char dst_prefixlen,
+ unsigned char tos,
+ uint32_t priority,
+ unsigned char table,
+ Route **ret) {
+
return route_add_internal(link, &link->routes_foreign, family, dst, dst_prefixlen, tos, priority, table, ret);
}
-int route_add(Link *link,
+int route_add(
+ Link *link,
int family,
- union in_addr_union *dst,
+ const union in_addr_union *dst,
unsigned char dst_prefixlen,
unsigned char tos,
uint32_t priority,
- unsigned char table, Route **ret) {
+ unsigned char table,
+ Route **ret) {
+
Route *route;
int r;
@@ -304,12 +329,13 @@ int route_add(Link *link,
}
int route_update(Route *route,
- union in_addr_union *src,
+ const union in_addr_union *src,
unsigned char src_prefixlen,
- union in_addr_union *gw,
- union in_addr_union *prefsrc,
+ const union in_addr_union *gw,
+ const union in_addr_union *prefsrc,
unsigned char scope,
unsigned char protocol) {
+
assert(route);
assert(src);
assert(gw);
@@ -450,8 +476,11 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
return 1;
}
-int route_configure(Route *route, Link *link,
- sd_netlink_message_handler_t callback) {
+int route_configure(
+ Route *route,
+ Link *link,
+ sd_netlink_message_handler_t callback) {
+
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
_cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
usec_t lifetime;
@@ -463,6 +492,10 @@ int route_configure(Route *route, Link *link,
assert(link->ifindex > 0);
assert(route->family == AF_INET || route->family == AF_INET6);
+ if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
+ set_size(link->routes) >= ROUTES_PER_LINK_MAX)
+ return -E2BIG;
+
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
RTM_NEWROUTE, route->family,
route->protocol);
@@ -763,6 +796,7 @@ int config_parse_route_priority(const char *unit,
void *userdata) {
Network *network = userdata;
_cleanup_route_free_ Route *n = NULL;
+ uint32_t k;
int r;
assert(filename);
@@ -775,12 +809,14 @@ int config_parse_route_priority(const char *unit,
if (r < 0)
return r;
- r = config_parse_uint32(unit, filename, line, section,
- section_line, lvalue, ltype,
- rvalue, &n->priority, userdata);
- if (r < 0)
- return r;
+ r = safe_atou32(rvalue, &k);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue);
+ return 0;
+ }
+ n->priority = k;
n = NULL;
return 0;
diff --git a/src/grp-network/libnetworkd-core/networkd-route.h b/src/grp-network/libnetworkd-core/networkd-route.h
index 39de8363ed..d4e4dbac0b 100644
--- a/src/grp-network/libnetworkd-core/networkd-route.h
+++ b/src/grp-network/libnetworkd-core/networkd-route.h
@@ -57,10 +57,10 @@ void route_free(Route *route);
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback);
-int route_get(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
-int route_add(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
-int route_add_foreign(Link *link, int family, union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
-int route_update(Route *route, union in_addr_union *src, unsigned char src_prefixlen, union in_addr_union *gw, union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
+int route_get(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
+int route_add(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
+int route_add_foreign(Link *link, int family, const union in_addr_union *dst, unsigned char dst_prefixlen, unsigned char tos, uint32_t priority, unsigned char table, Route **ret);
+int route_update(Route *route, const union in_addr_union *src, unsigned char src_prefixlen, const union in_addr_union *gw, const union in_addr_union *prefsrc, unsigned char scope, unsigned char protocol);
int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata);
diff --git a/src/grp-network/libnetworkd-core/networkd.h b/src/grp-network/libnetworkd-core/networkd.h
index cfee5dd045..dbc846a07e 100644
--- a/src/grp-network/libnetworkd-core/networkd.h
+++ b/src/grp-network/libnetworkd-core/networkd.h
@@ -41,6 +41,7 @@
#include "networkd-netdev-tuntap.h"
#include "networkd-netdev-veth.h"
#include "networkd-netdev-vlan.h"
+#include "networkd-netdev-vrf.h"
#include "networkd-netdev-vxlan.h"
#include "networkd-network.h"
#include "networkd-util.h"
diff --git a/src/grp-network/networkctl/Makefile b/src/grp-network/networkctl/Makefile
index f92d402f78..7b651c7f74 100644
--- a/src/grp-network/networkctl/Makefile
+++ b/src/grp-network/networkctl/Makefile
@@ -30,7 +30,7 @@ networkctl_SOURCES = \
src/network/networkctl.c
networkctl_LDADD = \
- libshared.la \
+ libsystemd-shared.la \
libsystemd-network.la
dist_bashcompletion_data += \
diff --git a/src/grp-network/systemd-networkd-wait-online/Makefile b/src/grp-network/systemd-networkd-wait-online/Makefile
index 8d1870c862..25134d4966 100644
--- a/src/grp-network/systemd-networkd-wait-online/Makefile
+++ b/src/grp-network/systemd-networkd-wait-online/Makefile
@@ -39,7 +39,7 @@ systemd_networkd_wait_online_SOURCES = \
systemd_networkd_wait_online_LDADD = \
libsystemd-network.la \
- libshared.la
+ libsystemd-shared.la
nodist_systemunit_DATA += \
units/systemd-networkd-wait-online.service
diff --git a/src/grp-network/systemd-networkd-wait-online/networkd-wait-online-manager.c b/src/grp-network/systemd-networkd-wait-online/networkd-wait-online-manager.c
index 9ec0550d44..e4f6d68f16 100644
--- a/src/grp-network/systemd-networkd-wait-online/networkd-wait-online-manager.c
+++ b/src/grp-network/systemd-networkd-wait-online/networkd-wait-online-manager.c
@@ -32,8 +32,6 @@
#include "networkd-wait-online.h"
bool manager_ignore_link(Manager *m, Link *link) {
- char **ignore;
-
assert(m);
assert(link);
@@ -46,11 +44,7 @@ bool manager_ignore_link(Manager *m, Link *link) {
return true;
/* ignore interfaces we explicitly are asked to ignore */
- STRV_FOREACH(ignore, m->ignore)
- if (fnmatch(*ignore, link->ifname, 0) == 0)
- return true;
-
- return false;
+ return strv_fnmatch(m->ignore, link->ifname, 0);
}
bool manager_all_configured(Manager *m) {
diff --git a/src/grp-network/systemd-networkd/systemd-networkd.service.m4.in b/src/grp-network/systemd-networkd/systemd-networkd.service.m4.in
index 27d4d58962..38d967d2d1 100644
--- a/src/grp-network/systemd-networkd/systemd-networkd.service.m4.in
+++ b/src/grp-network/systemd-networkd/systemd-networkd.service.m4.in
@@ -31,6 +31,8 @@ CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_N
ProtectSystem=full
ProtectHome=yes
WatchdogSec=3min
+MemoryDenyWriteExecute=yes
+SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io
[Install]
WantedBy=multi-user.target