summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkctl.c2
-rw-r--r--src/network/networkd-address.c59
-rw-r--r--src/network/networkd-address.h6
-rw-r--r--src/network/networkd-conf.c2
-rw-r--r--src/network/networkd-dhcp4.c3
-rw-r--r--src/network/networkd-fdb.c12
-rw-r--r--src/network/networkd-link.c102
-rw-r--r--src/network/networkd-link.h4
-rw-r--r--src/network/networkd-ndisc.c47
-rw-r--r--src/network/networkd-ndisc.h1
-rw-r--r--src/network/networkd-netdev-bond.c6
-rw-r--r--src/network/networkd-netdev-bridge.c20
-rw-r--r--src/network/networkd-netdev-bridge.h3
-rw-r--r--src/network/networkd-netdev-gperf.gperf8
-rw-r--r--src/network/networkd-netdev-tunnel.c8
-rw-r--r--src/network/networkd-netdev-vcan.c25
-rw-r--r--src/network/networkd-netdev-vcan.h34
-rw-r--r--src/network/networkd-netdev-vxlan.c8
-rw-r--r--src/network/networkd-netdev-vxlan.h2
-rw-r--r--src/network/networkd-netdev.c19
-rw-r--r--src/network/networkd-netdev.h5
-rw-r--r--src/network/networkd-network-gperf.gperf9
-rw-r--r--src/network/networkd-network.c120
-rw-r--r--src/network/networkd-network.h4
-rw-r--r--src/network/networkd-route.c55
-rw-r--r--src/network/networkd-wait-online-link.c3
-rw-r--r--src/network/networkd.h1
27 files changed, 471 insertions, 97 deletions
diff --git a/src/network/networkctl.c b/src/network/networkctl.c
index d2df9b7560..6f7f41bf7d 100644
--- a/src/network/networkctl.c
+++ b/src/network/networkctl.c
@@ -122,7 +122,7 @@ static void setup_state_to_color(const char *state, const char **on, const char
} else if (streq_ptr(state, "configuring")) {
*on = ansi_highlight_yellow();
*off = ansi_normal();
- } else if (streq_ptr(state, "failed") || streq_ptr(state, "linger")) {
+ } else if (STRPTR_IN_SET(state, "failed", "linger")) {
*on = ansi_highlight_red();
*off = ansi_normal();
} else
diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 5498e352d8..ed52d5e42d 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -571,6 +571,21 @@ int address_configure(
address->flags |= IFA_F_PERMANENT;
+ if (address->home_address)
+ address->flags |= IFA_F_HOMEADDRESS;
+
+ if (address->duplicate_address_detection)
+ address->flags |= IFA_F_NODAD;
+
+ if (address->manage_temporary_address)
+ address->flags |= IFA_F_MANAGETEMPADDR;
+
+ if (address->prefix_route)
+ address->flags |= IFA_F_NOPREFIXROUTE;
+
+ if (address->autojoin)
+ address->flags |= IFA_F_MCAUTOJOIN;
+
r = sd_rtnl_message_addr_set_flags(req, (address->flags & 0xff));
if (r < 0)
return log_error_errno(r, "Could not set flags: %m");
@@ -856,6 +871,50 @@ int config_parse_lifetime(const char *unit,
return 0;
}
+int config_parse_address_flags(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ Network *network = userdata;
+ _cleanup_address_free_ Address *n = NULL;
+ int r;
+
+ assert(filename);
+ assert(section);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = address_new_static(network, section_line, &n);
+ if (r < 0)
+ return r;
+
+ r = parse_boolean(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse address flag, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if (streq(lvalue, "HomeAddress"))
+ n->home_address = r;
+ else if (streq(lvalue, "DuplicateAddressDetection"))
+ n->duplicate_address_detection = r;
+ else if (streq(lvalue, "ManageTemporaryAddress"))
+ n->manage_temporary_address = r;
+ else if (streq(lvalue, "PrefixRoute"))
+ n->prefix_route = r;
+ else if (streq(lvalue, "AutoJoin"))
+ n->autojoin = r;
+
+ return 0;
+}
+
bool address_is_ready(const Address *a) {
assert(a);
diff --git a/src/network/networkd-address.h b/src/network/networkd-address.h
index 03c4bea7c6..bc3b4fc7f3 100644
--- a/src/network/networkd-address.h
+++ b/src/network/networkd-address.h
@@ -53,6 +53,11 @@ struct Address {
union in_addr_union in_addr_peer;
bool ip_masquerade_done:1;
+ bool duplicate_address_detection;
+ bool manage_temporary_address;
+ bool home_address;
+ bool prefix_route;
+ bool autojoin;
LIST_FIELDS(Address, addresses);
};
@@ -77,3 +82,4 @@ int config_parse_address(const char *unit, const char *filename, unsigned line,
int config_parse_broadcast(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_lifetime(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_address_flags(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-conf.c b/src/network/networkd-conf.c
index c03e2b2ebf..49bb8c18f6 100644
--- a/src/network/networkd-conf.c
+++ b/src/network/networkd-conf.c
@@ -29,7 +29,7 @@
int manager_parse_config_file(Manager *m) {
assert(m);
- return config_parse_many(PKGSYSCONFDIR "/networkd.conf",
+ return config_parse_many_nulstr(PKGSYSCONFDIR "/networkd.conf",
CONF_PATHS_NULSTR("systemd/networkd.conf.d"),
"DHCP\0",
config_item_perf_lookup, networkd_gperf_lookup,
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index 12fb8e3fce..76d3d132ea 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -95,6 +95,7 @@ static int link_set_dhcp_routes(Link *link) {
route_gw->scope = RT_SCOPE_LINK;
route_gw->protocol = RTPROT_DHCP;
route_gw->priority = link->network->dhcp_route_metric;
+ route_gw->table = link->network->dhcp_route_table;
r = route_configure(route_gw, link, dhcp4_route_handler);
if (r < 0)
@@ -106,6 +107,7 @@ static int link_set_dhcp_routes(Link *link) {
route->gw.in = gateway;
route->prefsrc.in = address;
route->priority = link->network->dhcp_route_metric;
+ route->table = link->network->dhcp_route_table;
r = route_configure(route, link, dhcp4_route_handler);
if (r < 0) {
@@ -136,6 +138,7 @@ static int link_set_dhcp_routes(Link *link) {
assert_se(sd_dhcp_route_get_destination(static_routes[i], &route->dst.in) >= 0);
assert_se(sd_dhcp_route_get_destination_prefix_length(static_routes[i], &route->dst_prefixlen) >= 0);
route->priority = link->network->dhcp_route_metric;
+ route->table = link->network->dhcp_route_table;
r = route_configure(route, link, dhcp4_route_handler);
if (r < 0)
diff --git a/src/network/networkd-fdb.c b/src/network/networkd-fdb.c
index be8aebee2d..ed5a47589e 100644
--- a/src/network/networkd-fdb.c
+++ b/src/network/networkd-fdb.c
@@ -107,20 +107,28 @@ int fdb_entry_configure(Link *link, FdbEntry *fdb_entry) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
sd_netlink *rtnl;
int r;
+ uint8_t flags;
+ Bridge *bridge;
assert(link);
+ assert(link->network);
assert(link->manager);
assert(fdb_entry);
rtnl = link->manager->rtnl;
+ bridge = BRIDGE(link->network->bridge);
/* create new RTM message */
r = sd_rtnl_message_new_neigh(rtnl, &req, RTM_NEWNEIGH, link->ifindex, PF_BRIDGE);
if (r < 0)
return rtnl_log_create_error(r);
- /* only NTF_SELF flag supported. */
- r = sd_rtnl_message_neigh_set_flags(req, NTF_SELF);
+ if (bridge)
+ flags = NTF_MASTER;
+ else
+ flags = NTF_SELF;
+
+ r = sd_rtnl_message_neigh_set_flags(req, flags);
if (r < 0)
return rtnl_log_create_error(r);
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 69ee7424ce..aefe7335b9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -514,13 +514,12 @@ static void link_free(Link *link) {
sd_lldp_unref(link->lldp);
free(link->lldp_file);
+ ndisc_flush(link);
+
sd_ipv4ll_unref(link->ipv4ll);
sd_dhcp6_client_unref(link->dhcp6_client);
sd_ndisc_unref(link->ndisc);
- 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));
@@ -942,6 +941,19 @@ static int link_push_ntp_to_dhcp_server(Link *link, sd_dhcp_server *s) {
return sd_dhcp_server_set_ntp(s, addresses, n_addresses);
}
+static int link_set_bridge_fdb(Link *link) {
+ FdbEntry *fdb_entry;
+ int r;
+
+ LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
+ r = fdb_entry_configure(link, fdb_entry);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
+ }
+
+ return 0;
+}
+
static int link_enter_set_addresses(Link *link) {
Address *ad;
int r;
@@ -950,6 +962,10 @@ static int link_enter_set_addresses(Link *link) {
assert(link->network);
assert(link->state != _LINK_STATE_INVALID);
+ r = link_set_bridge_fdb(link);
+ if (r < 0)
+ return r;
+
link_set_state(link, LINK_STATE_SETTING_ADDRESSES);
LIST_FOREACH(addresses, ad, link->network->static_addresses) {
@@ -1119,21 +1135,6 @@ static int link_set_bridge_vlan(Link *link) {
return r;
}
-static int link_set_bridge_fdb(Link *link) {
- FdbEntry *fdb_entry;
- int r = 0;
-
- LIST_FOREACH(static_fdb_entries, fdb_entry, link->network->static_fdb_entries) {
- r = fdb_entry_configure(link, fdb_entry);
- if (r < 0) {
- log_link_error_errno(link, r, "Failed to add MAC entry to static MAC table: %m");
- break;
- }
- }
-
- return r;
-}
-
static int link_set_proxy_arp(Link *link) {
const char *p = NULL;
int r;
@@ -1787,6 +1788,31 @@ static int link_down(Link *link) {
return 0;
}
+static int link_up_can(Link *link) {
+ _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
+ int r;
+
+ assert(link);
+
+ log_link_debug(link, "Bringing CAN link up");
+
+ r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
+
+ r = sd_rtnl_message_link_set_flags(req, IFF_UP, IFF_UP);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not set link flags: %m");
+
+ r = sd_netlink_call_async(link->manager->rtnl, req, link_up_handler, link, 0, NULL);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
+
+ link_ref(link);
+
+ return 0;
+}
+
static int link_handle_bound_to_list(Link *link) {
Link *l;
Iterator i;
@@ -2400,6 +2426,8 @@ static int link_drop_config(Link *link) {
return r;
}
+ ndisc_flush(link);
+
return 0;
}
@@ -2431,6 +2459,19 @@ static int link_configure(Link *link) {
assert(link->network);
assert(link->state == LINK_STATE_PENDING);
+ if (streq_ptr(link->kind, "vcan")) {
+
+ if (!(link->flags & IFF_UP)) {
+ r = link_up_can(link);
+ if (r < 0) {
+ link_enter_failed(link);
+ return r;
+ }
+ }
+
+ return 0;
+ }
+
/* Drop foreign config, but ignore loopback or critical devices.
* We do not want to remove loopback address or addresses used for root NFS. */
if (!(link->flags & IFF_LOOPBACK) && !(link->network->dhcp_critical)) {
@@ -2439,10 +2480,6 @@ static int link_configure(Link *link) {
return r;
}
- r = link_set_bridge_fdb(link);
- if (r < 0)
- return r;
-
r = link_set_proxy_arp(link);
if (r < 0)
return r;
@@ -2805,17 +2842,17 @@ network_file_fail:
if (dhcp4_address) {
r = in_addr_from_string(AF_INET, dhcp4_address, &address);
if (r < 0) {
- log_link_debug_errno(link, r, "Falied to parse DHCPv4 address %s: %m", dhcp4_address);
+ log_link_debug_errno(link, r, "Failed to parse DHCPv4 address %s: %m", dhcp4_address);
goto dhcp4_address_fail;
}
r = sd_dhcp_client_new(&link->dhcp_client);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to create DHCPv4 client: %m");
+ return log_link_error_errno(link, r, "Failed to create DHCPv4 client: %m");
r = sd_dhcp_client_set_request_address(link->dhcp_client, &address.in);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to set initial DHCPv4 address %s: %m", dhcp4_address);
+ return log_link_error_errno(link, r, "Failed to set initial DHCPv4 address %s: %m", dhcp4_address);
}
dhcp4_address_fail:
@@ -2823,17 +2860,17 @@ dhcp4_address_fail:
if (ipv4ll_address) {
r = in_addr_from_string(AF_INET, ipv4ll_address, &address);
if (r < 0) {
- log_link_debug_errno(link, r, "Falied to parse IPv4LL address %s: %m", ipv4ll_address);
+ log_link_debug_errno(link, r, "Failed to parse IPv4LL address %s: %m", ipv4ll_address);
goto ipv4ll_address_fail;
}
r = sd_ipv4ll_new(&link->ipv4ll);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to create IPv4LL client: %m");
+ return log_link_error_errno(link, r, "Failed to create IPv4LL client: %m");
r = sd_ipv4ll_set_address(link->ipv4ll, &address.in);
if (r < 0)
- return log_link_error_errno(link, r, "Falied to set initial IPv4LL address %s: %m", ipv4ll_address);
+ return log_link_error_errno(link, r, "Failed to set initial IPv4LL address %s: %m", ipv4ll_address);
}
ipv4ll_address_fail:
@@ -2957,9 +2994,12 @@ static int link_carrier_lost(Link *link) {
if (r < 0)
return r;
- r = link_drop_foreign_config(link);
- if (r < 0)
- return r;
+ if (!IN_SET(link->state, LINK_STATE_UNMANAGED, LINK_STATE_PENDING)) {
+ log_link_debug(link, "State is %s, dropping config", link_state_to_string(link->state));
+ r = link_drop_foreign_config(link);
+ if (r < 0)
+ return r;
+ }
r = link_handle_bound_by_list(link);
if (r < 0)
diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h
index 2809b1fe0b..77f72d070e 100644
--- a/src/network/networkd-link.h
+++ b/src/network/networkd-link.h
@@ -186,8 +186,8 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Link*, link_unref);
#define log_link_full(link, level, error, ...) \
({ \
- Link *_l = (link); \
- _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, ##__VA_ARGS__) : \
+ const Link *_l = (link); \
+ _l ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _l->ifname, NULL, NULL, ##__VA_ARGS__) : \
log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
}) \
diff --git a/src/network/networkd-ndisc.c b/src/network/networkd-ndisc.c
index d9c18b32a5..4853791aa5 100644
--- a/src/network/networkd-ndisc.c
+++ b/src/network/networkd-ndisc.c
@@ -57,6 +57,8 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
unsigned preference;
usec_t time_now;
int r;
+ Address *address;
+ Iterator i;
assert(link);
assert(rt);
@@ -75,6 +77,32 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
return;
}
+ SET_FOREACH(address, link->addresses, i) {
+ if (!memcmp(&gateway, &address->in_addr.in6,
+ sizeof(address->in_addr.in6))) {
+ char buffer[INET6_ADDRSTRLEN];
+
+ log_link_debug(link, "No NDisc route added, gateway %s matches local address",
+ inet_ntop(AF_INET6,
+ &address->in_addr.in6,
+ buffer, sizeof(buffer)));
+ return;
+ }
+ }
+
+ SET_FOREACH(address, link->addresses_foreign, i) {
+ if (!memcmp(&gateway, &address->in_addr.in6,
+ sizeof(address->in_addr.in6))) {
+ char buffer[INET6_ADDRSTRLEN];
+
+ log_link_debug(link, "No NDisc route added, gateway %s matches local address",
+ inet_ntop(AF_INET6,
+ &address->in_addr.in6,
+ buffer, sizeof(buffer)));
+ return;
+ }
+ }
+
r = sd_ndisc_router_get_preference(rt, &preference);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to get default router preference from RA: %m");
@@ -94,7 +122,7 @@ static void ndisc_router_process_default(Link *link, sd_ndisc_router *rt) {
}
route->family = AF_INET6;
- route->table = RT_TABLE_MAIN;
+ route->table = link->network->ipv6_accept_ra_route_table;
route->protocol = RTPROT_RA;
route->pref = preference;
route->gw.in6 = gateway;
@@ -214,7 +242,7 @@ static void ndisc_router_process_onlink_prefix(Link *link, sd_ndisc_router *rt)
}
route->family = AF_INET6;
- route->table = RT_TABLE_MAIN;
+ route->table = link->network->ipv6_accept_ra_route_table;
route->protocol = RTPROT_RA;
route->flags = RTM_F_PREFIX;
route->dst_prefixlen = prefixlen;
@@ -285,7 +313,7 @@ static void ndisc_router_process_route(Link *link, sd_ndisc_router *rt) {
}
route->family = AF_INET6;
- route->table = RT_TABLE_MAIN;
+ route->table = link->network->ipv6_accept_ra_route_table;
route->protocol = RTPROT_RA;
route->pref = preference;
route->gw.in6 = gateway;
@@ -652,13 +680,22 @@ void ndisc_vacuum(Link *link) {
SET_FOREACH(r, link->ndisc_rdnss, i)
if (r->valid_until < time_now) {
- (void) set_remove(link->ndisc_rdnss, r);
+ free(set_remove(link->ndisc_rdnss, r));
link_dirty(link);
}
SET_FOREACH(d, link->ndisc_dnssl, i)
if (d->valid_until < time_now) {
- (void) set_remove(link->ndisc_dnssl, d);
+ free(set_remove(link->ndisc_dnssl, d));
link_dirty(link);
}
}
+
+void ndisc_flush(Link *link) {
+ assert(link);
+
+ /* Removes all RDNSS and DNSSL entries, without exception */
+
+ link->ndisc_rdnss = set_free_free(link->ndisc_rdnss);
+ link->ndisc_dnssl = set_free_free(link->ndisc_dnssl);
+}
diff --git a/src/network/networkd-ndisc.h b/src/network/networkd-ndisc.h
index 2002f55107..127126190e 100644
--- a/src/network/networkd-ndisc.h
+++ b/src/network/networkd-ndisc.h
@@ -37,3 +37,4 @@ static inline char* NDISC_DNSSL_DOMAIN(const NDiscDNSSL *n) {
int ndisc_configure(Link *link);
void ndisc_vacuum(Link *link);
+void ndisc_flush(Link *link);
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
index 7913b0088e..46d1669337 100644
--- a/src/network/networkd-netdev-bond.c
+++ b/src/network/networkd-netdev-bond.c
@@ -268,13 +268,13 @@ static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_netlin
if (b->arp_all_targets != _NETDEV_BOND_ARP_ALL_TARGETS_INVALID) {
r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->arp_all_targets);
if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_VALIDATE attribute: %m");
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m");
}
if (b->primary_reselect != _NETDEV_BOND_PRIMARY_RESELECT_INVALID) {
- r = sd_netlink_message_append_u32(m, IFLA_BOND_ARP_ALL_TARGETS, b->primary_reselect);
+ r = sd_netlink_message_append_u8(m, IFLA_BOND_PRIMARY_RESELECT, b->primary_reselect);
if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_ARP_ALL_TARGETS attribute: %m");
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BOND_PRIMARY_RESELECT attribute: %m");
}
if (b->resend_igmp <= RESEND_IGMP_MAX) {
diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c
index 12b0fe972f..002ad94210 100644
--- a/src/network/networkd-netdev-bridge.c
+++ b/src/network/networkd-netdev-bridge.c
@@ -39,7 +39,7 @@ static int netdev_bridge_set_handler(sd_netlink *rtnl, sd_netlink_message *m, vo
return 1;
}
- log_netdev_debug(netdev, "Bridge parametres set success");
+ log_netdev_debug(netdev, "Bridge parameters set success");
return 1;
}
@@ -90,6 +90,24 @@ 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_MAX_AGE attribute: %m");
}
+ if (b->ageing_time > 0) {
+ r = sd_netlink_message_append_u32(req, IFLA_BR_AGEING_TIME, usec_to_jiffies(b->ageing_time));
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_AGEING_TIME attribute: %m");
+ }
+
+ if (b->priority > 0) {
+ r = sd_netlink_message_append_u16(req, IFLA_BR_PRIORITY, b->priority);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_PRIORITY attribute: %m");
+ }
+
+ if (b->default_pvid > 0) {
+ r = sd_netlink_message_append_u16(req, IFLA_BR_VLAN_DEFAULT_PVID, b->default_pvid);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_BR_VLAN_DEFAULT_PVID attribute: %m");
+ }
+
if (b->mcast_querier >= 0) {
r = sd_netlink_message_append_u8(req, IFLA_BR_MCAST_QUERIER, b->mcast_querier);
if (r < 0)
diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h
index 4ce0fbb6f9..53f72f1ea5 100644
--- a/src/network/networkd-netdev-bridge.h
+++ b/src/network/networkd-netdev-bridge.h
@@ -28,10 +28,13 @@ typedef struct Bridge {
int mcast_snooping;
int vlan_filtering;
int stp;
+ uint16_t priority;
+ uint16_t default_pvid;
usec_t forward_delay;
usec_t hello_time;
usec_t max_age;
+ usec_t ageing_time;
} Bridge;
DEFINE_NETDEV_CAST(BRIDGE, Bridge);
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index a1ca1a3d4e..323eaa8032 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -63,8 +63,13 @@ VXLAN.L2MissNotification, config_parse_bool, 0,
VXLAN.L3MissNotification, config_parse_bool, 0, offsetof(VxLan, l3miss)
VXLAN.RouteShortCircuit, config_parse_bool, 0, offsetof(VxLan, route_short_circuit)
VXLAN.UDPCheckSum, config_parse_bool, 0, offsetof(VxLan, udpcsum)
+VXLAN.UDPChecksum, config_parse_bool, 0, offsetof(VxLan, udpcsum)
VXLAN.UDP6ZeroCheckSumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx)
+VXLAN.UDP6ZeroChecksumRx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumrx)
VXLAN.UDP6ZeroCheckSumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx)
+VXLAN.UDP6ZeroChecksumTx, config_parse_bool, 0, offsetof(VxLan, udp6zerocsumtx)
+VXLAN.RemoteChecksumTx, config_parse_bool, 0, offsetof(VxLan, remote_csum_tx)
+VXLAN.RemoteChecksumRx, config_parse_bool, 0, offsetof(VxLan, remote_csum_rx)
VXLAN.FDBAgeingSec, config_parse_sec, 0, offsetof(VxLan, fdb_ageing)
VXLAN.GroupPolicyExtension, config_parse_bool, 0, offsetof(VxLan, group_policy)
VXLAN.MaximumFDBEntries, config_parse_unsigned, 0, offsetof(VxLan, max_fdb)
@@ -102,7 +107,10 @@ Bond.ARPIntervalSec, config_parse_sec, 0,
Bond.LearnPacketIntervalSec, config_parse_sec, 0, offsetof(Bond, lp_interval)
Bridge.HelloTimeSec, config_parse_sec, 0, offsetof(Bridge, hello_time)
Bridge.MaxAgeSec, config_parse_sec, 0, offsetof(Bridge, max_age)
+Bridge.AgeingTimeSec, config_parse_sec, 0, offsetof(Bridge, ageing_time)
Bridge.ForwardDelaySec, config_parse_sec, 0, offsetof(Bridge, forward_delay)
+Bridge.Priority, config_parse_uint16, 0, offsetof(Bridge, priority)
+Bridge.DefaultPVID, config_parse_vlanid, 0, offsetof(Bridge, default_pvid)
Bridge.MulticastQuerier, config_parse_tristate, 0, offsetof(Bridge, mcast_querier)
Bridge.MulticastSnooping, config_parse_tristate, 0, offsetof(Bridge, mcast_snooping)
Bridge.VLANFiltering, config_parse_tristate, 0, offsetof(Bridge, vlan_filtering)
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 77a4734df8..9138ee4511 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -201,12 +201,18 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
}
static int netdev_vti_fill_message_key(NetDev *netdev, Link *link, sd_netlink_message *m) {
- Tunnel *t = VTI(netdev);
uint32_t ikey, okey;
+ Tunnel *t;
int r;
assert(link);
assert(m);
+
+ if (netdev->kind == NETDEV_KIND_VTI)
+ t = VTI(netdev);
+ else
+ t = VTI6(netdev);
+
assert(t);
if (t->key != 0)
diff --git a/src/network/networkd-netdev-vcan.c b/src/network/networkd-netdev-vcan.c
new file mode 100644
index 0000000000..bfce6e1962
--- /dev/null
+++ b/src/network/networkd-netdev-vcan.c
@@ -0,0 +1,25 @@
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Susant Sahani
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include "networkd-netdev-vcan.h"
+
+const NetDevVTable vcan_vtable = {
+ .object_size = sizeof(VCan),
+ .create_type = NETDEV_CREATE_INDEPENDENT,
+};
diff --git a/src/network/networkd-netdev-vcan.h b/src/network/networkd-netdev-vcan.h
new file mode 100644
index 0000000000..6ba47fd70e
--- /dev/null
+++ b/src/network/networkd-netdev-vcan.h
@@ -0,0 +1,34 @@
+#pragma once
+
+/***
+ This file is part of systemd.
+
+ Copyright 2016 Susant Sahani
+
+ systemd is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ systemd is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+typedef struct VCan VCan;
+
+#include <linux/can/netlink.h>
+
+#include "networkd-netdev.h"
+
+struct VCan {
+ NetDev meta;
+};
+
+DEFINE_NETDEV_CAST(VCAN, VCan);
+
+extern const NetDevVTable vcan_vtable;
diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c
index 724f9861be..706e52b698 100644
--- a/src/network/networkd-netdev-vxlan.c
+++ b/src/network/networkd-netdev-vxlan.c
@@ -112,6 +112,14 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_UDP_ZERO_CSUM6_RX attribute: %m");
+ r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_TX, v->remote_csum_tx);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_TX attribute: %m");
+
+ r = sd_netlink_message_append_u8(m, IFLA_VXLAN_REMCSUM_RX, v->remote_csum_rx);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_REMCSUM_RX attribute: %m");
+
r = sd_netlink_message_append_u16(m, IFLA_VXLAN_PORT, htobe16(v->dest_port));
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_PORT attribute: %m");
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
index 4614c66fd1..3906820afb 100644
--- a/src/network/networkd-netdev-vxlan.h
+++ b/src/network/networkd-netdev-vxlan.h
@@ -50,6 +50,8 @@ struct VxLan {
bool udpcsum;
bool udp6zerocsumtx;
bool udp6zerocsumrx;
+ bool remote_csum_tx;
+ bool remote_csum_rx;
bool group_policy;
struct ifla_vxlan_port_range port_range;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index e7edc366af..a210ba1242 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -34,7 +34,6 @@
#include "string-util.h"
const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
-
[NETDEV_KIND_BRIDGE] = &bridge_vtable,
[NETDEV_KIND_BOND] = &bond_vtable,
[NETDEV_KIND_VLAN] = &vlan_vtable,
@@ -56,7 +55,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TAP] = &tap_vtable,
[NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
[NETDEV_KIND_VRF] = &vrf_vtable,
-
+ [NETDEV_KIND_VCAN] = &vcan_vtable,
};
static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -81,7 +80,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
[NETDEV_KIND_TAP] = "tap",
[NETDEV_KIND_IP6TNL] = "ip6tnl",
[NETDEV_KIND_VRF] = "vrf",
-
+ [NETDEV_KIND_VCAN] = "vcan",
};
DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
@@ -516,7 +515,7 @@ static int netdev_create(NetDev *netdev, Link *link,
r = sd_netlink_message_close_container(m);
if (r < 0)
- return log_netdev_error_errno(netdev, r, "Could not append IFLA_LINKINFO attribute: %m");
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_INFO_DATA attribute: %m");
r = sd_netlink_message_close_container(m);
if (r < 0)
@@ -577,6 +576,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
_cleanup_netdev_unref_ NetDev *netdev = NULL;
_cleanup_free_ NetDev *netdev_raw = NULL;
_cleanup_fclose_ FILE *file = NULL;
+ const char *dropin_dirname;
int r;
assert(manager);
@@ -600,11 +600,12 @@ static int netdev_load_one(Manager *manager, const char *filename) {
return log_oom();
netdev_raw->kind = _NETDEV_KIND_INVALID;
+ dropin_dirname = strjoina(basename(filename), ".d");
- r = config_parse(NULL, filename, file,
- "Match\0NetDev\0",
- config_item_perf_lookup, network_netdev_gperf_lookup,
- true, false, true, netdev_raw);
+ r = config_parse_many(filename, network_dirs, dropin_dirname,
+ "Match\0NetDev\0",
+ config_item_perf_lookup, network_netdev_gperf_lookup,
+ true, netdev_raw);
if (r < 0)
return r;
@@ -620,7 +621,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
return 0;
if (netdev_raw->kind == _NETDEV_KIND_INVALID) {
- log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename);
+ log_warning("NetDev has no Kind configured in %s. Ignoring", filename);
return 0;
}
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index b92a973b85..70ff947b99 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -56,6 +56,7 @@ typedef enum NetDevKind {
NETDEV_KIND_TUN,
NETDEV_KIND_TAP,
NETDEV_KIND_VRF,
+ NETDEV_KIND_VCAN,
_NETDEV_KIND_MAX,
_NETDEV_KIND_INVALID = -1
} NetDevKind;
@@ -180,8 +181,8 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign
#define log_netdev_full(netdev, level, error, ...) \
({ \
- NetDev *_n = (netdev); \
- _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, ##__VA_ARGS__) : \
+ const NetDev *_n = (netdev); \
+ _n ? log_object_internal(level, error, __FILE__, __LINE__, __func__, "INTERFACE=", _n->ifname, NULL, NULL, ##__VA_ARGS__) : \
log_internal(level, error, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
})
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index b96f0b7210..bcf8186c33 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -49,7 +49,7 @@ Network.EmitLLDP, config_parse_lldp_emit,
Network.Address, config_parse_address, 0, 0
Network.Gateway, config_parse_gateway, 0, 0
Network.Domains, config_parse_domains, 0, 0
-Network.DNS, config_parse_strv, 0, offsetof(Network, dns)
+Network.DNS, config_parse_dns, 0, 0
Network.LLMNR, config_parse_resolve_support, 0, offsetof(Network, llmnr)
Network.MulticastDNS, config_parse_resolve_support, 0, offsetof(Network, mdns)
Network.DNSSEC, config_parse_dnssec_mode, 0, offsetof(Network, dnssec_mode)
@@ -70,6 +70,11 @@ Address.Peer, config_parse_address,
Address.Broadcast, config_parse_broadcast, 0, 0
Address.Label, config_parse_label, 0, 0
Address.PreferredLifetime, config_parse_lifetime, 0, 0
+Address.HomeAddress, config_parse_address_flags, 0, 0
+Address.DuplicateAddressDetection, config_parse_address_flags, 0, 0
+Address.ManageTemporaryAddress, config_parse_address_flags, 0, 0
+Address.PrefixRoute, config_parse_address_flags, 0, 0
+Address.AutoJoin, config_parse_address_flags, 0, 0
Route.Gateway, config_parse_gateway, 0, 0
Route.Destination, config_parse_destination, 0, 0
Route.Source, config_parse_destination, 0, 0
@@ -92,10 +97,12 @@ DHCP.VendorClassIdentifier, config_parse_string,
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid.type)
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
+DHCP.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, dhcp_route_table)
DHCP.UseTimezone, config_parse_bool, 0, offsetof(Network, dhcp_use_timezone)
DHCP.IAID, config_parse_iaid, 0, offsetof(Network, iaid)
IPv6AcceptRA.UseDNS, config_parse_bool, 0, offsetof(Network, ipv6_accept_ra_use_dns)
IPv6AcceptRA.UseDomains, config_parse_dhcp_use_domains, 0, offsetof(Network, ipv6_accept_ra_use_domains)
+IPv6AcceptRA.RouteTable, config_parse_dhcp_route_table, 0, offsetof(Network, ipv6_accept_ra_route_table)
DHCPServer.MaxLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_max_lease_time_usec)
DHCPServer.DefaultLeaseTimeSec, config_parse_sec, 0, offsetof(Network, dhcp_server_default_lease_time_usec)
DHCPServer.EmitDNS, config_parse_bool, 0, offsetof(Network, dhcp_server_emit_dns)
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 49faba5b12..042232fcac 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -40,6 +40,7 @@ static int network_load_one(Manager *manager, const char *filename) {
_cleanup_network_free_ Network *network = NULL;
_cleanup_fclose_ FILE *file = NULL;
char *d;
+ const char *dropin_dirname;
Route *route;
Address *address;
int r;
@@ -110,6 +111,7 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_send_hostname = true;
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
+ network->dhcp_route_table = RT_TABLE_MAIN;
network->dhcp_server_emit_dns = true;
network->dhcp_server_emit_ntp = true;
@@ -136,22 +138,25 @@ static int network_load_one(Manager *manager, const char *filename) {
network->proxy_arp = -1;
network->arp = -1;
network->ipv6_accept_ra_use_dns = true;
-
- r = config_parse(NULL, filename, file,
- "Match\0"
- "Link\0"
- "Network\0"
- "Address\0"
- "Route\0"
- "DHCP\0"
- "DHCPv4\0" /* compat */
- "DHCPServer\0"
- "IPv6AcceptRA\0"
- "Bridge\0"
- "BridgeFDB\0"
- "BridgeVLAN\0",
- config_item_perf_lookup, network_network_gperf_lookup,
- false, false, true, network);
+ network->ipv6_accept_ra_route_table = RT_TABLE_MAIN;
+
+ dropin_dirname = strjoina(network->name, ".network.d");
+
+ r = config_parse_many(filename, network_dirs, dropin_dirname,
+ "Match\0"
+ "Link\0"
+ "Network\0"
+ "Address\0"
+ "Route\0"
+ "DHCP\0"
+ "DHCPv4\0" /* compat */
+ "DHCPServer\0"
+ "IPv6AcceptRA\0"
+ "Bridge\0"
+ "BridgeFDB\0"
+ "BridgeVLAN\0",
+ config_item_perf_lookup, network_network_gperf_lookup,
+ false, network);
if (r < 0)
return r;
@@ -479,9 +484,10 @@ int config_parse_netdev(const char *unit,
case NETDEV_KIND_MACVTAP:
case NETDEV_KIND_IPVLAN:
case NETDEV_KIND_VXLAN:
+ case NETDEV_KIND_VCAN:
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Can not add VLAN '%s' to network: %m", rvalue);
+ log_syntax(unit, LOG_ERR, filename, line, r, "Can not add NetDev '%s' to network: %m", rvalue);
return 0;
}
@@ -973,6 +979,56 @@ int config_parse_dhcp_server_ntp(
}
}
+int config_parse_dns(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ Network *n = userdata;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ union in_addr_union a;
+ int family;
+
+ r = extract_first_word(&rvalue, &w, WHITESPACE, EXTRACT_QUOTES|EXTRACT_RETAIN_ESCAPE);
+ if (r == 0)
+ break;
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid syntax, ignoring: %s", rvalue);
+ break;
+ }
+
+ r = in_addr_from_string_auto(w, &family, &a);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse dns server address, ignoring: %s", w);
+ continue;
+ }
+
+ r = strv_consume(&n->dns, w);
+ if (r < 0)
+ return log_oom();
+
+ w = NULL;
+ }
+
+ return 0;
+}
+
int config_parse_dnssec_negative_trust_anchors(
const char *unit,
const char *filename,
@@ -1029,6 +1085,36 @@ int config_parse_dnssec_negative_trust_anchors(
return 0;
}
+int config_parse_dhcp_route_table(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ uint32_t rt;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(data);
+
+ r = safe_atou32(rvalue, &rt);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Unable to read RouteTable, ignoring assignment: %s", rvalue);
+ return 0;
+ }
+
+ *((uint32_t *)data) = rt;
+
+ return 0;
+}
+
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_use_domains, dhcp_use_domains, DHCPUseDomains, "Failed to parse DHCP use domains setting");
static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h
index 5460eb4d1c..42fc82d392 100644
--- a/src/network/networkd-network.h
+++ b/src/network/networkd-network.h
@@ -123,6 +123,7 @@ struct Network {
bool dhcp_use_routes;
bool dhcp_use_timezone;
unsigned dhcp_route_metric;
+ uint32_t dhcp_route_table;
/* DHCP Server Support */
bool dhcp_server;
@@ -166,6 +167,7 @@ struct Network {
bool ipv6_accept_ra_use_dns;
DHCPUseDomains ipv6_accept_ra_use_domains;
+ uint32_t ipv6_accept_ra_route_table;
union in_addr_union ipv6_token;
IPv6PrivacyExtensions ipv6_privacy_extensions;
@@ -218,6 +220,7 @@ int config_parse_netdev(const char *unit, const char *filename, unsigned line, c
int config_parse_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_tunnel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_dhcp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dns(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_dhcp_client_identifier(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_ipv6token(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
@@ -228,6 +231,7 @@ int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigne
int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
/* Legacy IPv4LL support */
int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index cedaf47cf8..6f60ee5e31 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -26,10 +26,37 @@
#include "parse-util.h"
#include "set.h"
#include "string-util.h"
+#include "sysctl-util.h"
#include "util.h"
-#define ROUTES_PER_LINK_MAX 2048U
-#define STATIC_ROUTES_PER_NETWORK_MAX 1024U
+#define ROUTES_DEFAULT_MAX_PER_FAMILY 4096U
+
+static unsigned routes_max(void) {
+ static thread_local unsigned cached = 0;
+
+ _cleanup_free_ char *s4 = NULL, *s6 = NULL;
+ unsigned val4 = ROUTES_DEFAULT_MAX_PER_FAMILY, val6 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+
+ if (cached > 0)
+ return cached;
+
+ if (sysctl_read("net/ipv4/route/max_size", &s4) >= 0) {
+ truncate_nl(s4);
+ if (safe_atou(s4, &val4) >= 0 &&
+ val4 == 2147483647U)
+ /* This is the default "no limit" value in the kernel */
+ val4 = ROUTES_DEFAULT_MAX_PER_FAMILY;
+ }
+
+ if (sysctl_read("net/ipv6/route/max_size", &s6) >= 0) {
+ truncate_nl(s6);
+ (void) safe_atou(s6, &val6);
+ }
+
+ cached = MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val4) +
+ MAX(ROUTES_DEFAULT_MAX_PER_FAMILY, val6);
+ return cached;
+}
int route_new(Route **ret) {
_cleanup_route_free_ Route *route = NULL;
@@ -41,7 +68,7 @@ int route_new(Route **ret) {
route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_UNSPEC;
- route->table = RT_TABLE_DEFAULT;
+ route->table = RT_TABLE_MAIN;
route->lifetime = USEC_INFINITY;
*ret = route;
@@ -67,7 +94,7 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
}
}
- if (network->n_static_routes >= STATIC_ROUTES_PER_NETWORK_MAX)
+ if (network->n_static_routes >= routes_max())
return -E2BIG;
r = route_new(&route);
@@ -322,7 +349,8 @@ int route_add(
} else
return r;
- *ret = route;
+ if (ret)
+ *ret = route;
return 0;
}
@@ -440,20 +468,14 @@ static int route_expire_callback(sd_netlink *rtnl, sd_netlink_message *m, void *
assert(m);
assert(link);
assert(link->ifname);
- assert(link->link_messages > 0);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
- link->link_messages--;
-
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_warning_errno(link, r, "could not remove route: %m");
- if (link->link_messages == 0)
- log_link_debug(link, "route removed");
-
return 1;
}
@@ -466,11 +488,8 @@ int route_expire_handler(sd_event_source *s, uint64_t usec, void *userdata) {
r = route_remove(route, route->link, route_expire_callback);
if (r < 0)
log_warning_errno(r, "Could not remove route: %m");
- else {
- /* route may not be exist in kernel. If we fail still remove it */
- route->link->link_messages++;
+ else
route_free(route);
- }
return 1;
}
@@ -492,7 +511,7 @@ int route_configure(
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)
+ set_size(link->routes) >= routes_max())
return -E2BIG;
r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
@@ -557,14 +576,12 @@ int route_configure(
if (r < 0)
return log_error_errno(r, "Could not set flags: %m");
- if (route->table != RT_TABLE_DEFAULT) {
-
+ if (route->table != RT_TABLE_MAIN) {
if (route->table < 256) {
r = sd_rtnl_message_route_set_table(req, route->table);
if (r < 0)
return log_error_errno(r, "Could not set route table: %m");
} else {
-
r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
if (r < 0)
return log_error_errno(r, "Could not set route table: %m");
diff --git a/src/network/networkd-wait-online-link.c b/src/network/networkd-wait-online-link.c
index 5727422e3d..e63ba07e90 100644
--- a/src/network/networkd-wait-online-link.c
+++ b/src/network/networkd-wait-online-link.c
@@ -77,8 +77,7 @@ Link *link_free(Link *l) {
}
free(l->ifname);
- free(l);
- return NULL;
+ return mfree(l);
}
int link_update_rtnl(Link *l, sd_netlink_message *m) {
diff --git a/src/network/networkd.h b/src/network/networkd.h
index c4bd712147..cb1b73145e 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -43,6 +43,7 @@
#include "networkd-netdev-vlan.h"
#include "networkd-netdev-vrf.h"
#include "networkd-netdev-vxlan.h"
+#include "networkd-netdev-vcan.h"
#include "networkd-network.h"
#include "networkd-util.h"