summaryrefslogtreecommitdiff
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/networkd-dhcp4.c41
-rw-r--r--src/network/networkd-link.c23
-rw-r--r--src/network/networkd-netdev-gperf.gperf4
-rw-r--r--src/network/networkd-netdev-tunnel.c71
-rw-r--r--src/network/networkd-netdev-tunnel.h28
-rw-r--r--src/network/networkd-netdev-vxlan.h11
-rw-r--r--src/network/networkd-network-gperf.gperf6
-rw-r--r--src/network/networkd-network.c40
-rw-r--r--src/network/networkd-wait-online.c2
-rw-r--r--src/network/networkd.h32
10 files changed, 218 insertions, 40 deletions
diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c
index d446bfa8b3..4aa301b112 100644
--- a/src/network/networkd-dhcp4.c
+++ b/src/network/networkd-dhcp4.c
@@ -270,12 +270,18 @@ static int dhcp_lease_lost(Link *link) {
if (link->network->dhcp_hostname) {
const char *hostname = NULL;
- r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
- if (r >= 0 && hostname) {
- r = link_set_hostname(link, "");
+ if (!link->network->hostname)
+ r = sd_dhcp_lease_get_hostname(link->dhcp_lease, &hostname);
+ else
+ hostname = link->network->hostname;
+
+ if (r >= 0 || hostname) {
+ r = link_set_hostname(link, hostname);
if (r < 0)
- log_link_error(link,
- "Failed to reset transient hostname");
+ log_link_error_errno(link, r,
+ "Failed to set transient hostname to '%s': %m",
+ hostname);
+
}
}
@@ -464,8 +470,12 @@ static int dhcp_lease_acquired(sd_dhcp_client *client, Link *link) {
if (link->network->dhcp_hostname) {
const char *hostname;
- r = sd_dhcp_lease_get_hostname(lease, &hostname);
- if (r >= 0) {
+ if (!link->network->hostname)
+ r = sd_dhcp_lease_get_hostname(lease, &hostname);
+ else
+ hostname = link->network->hostname;
+
+ if (r >= 0 || hostname) {
r = link_set_hostname(link, hostname);
if (r < 0)
log_link_error_errno(link, r, "Failed to set transient hostname to '%s': %m", hostname);
@@ -616,14 +626,19 @@ int dhcp4_configure(Link *link) {
if (link->network->dhcp_sendhost) {
_cleanup_free_ char *hostname = NULL;
+ const char *hn = NULL;
+
+ if (!link->network->hostname) {
+ hostname = gethostname_malloc();
+ if (!hostname)
+ return -ENOMEM;
- hostname = gethostname_malloc();
- if (!hostname)
- return -ENOMEM;
+ hn = hostname;
+ } else
+ hn = link->network->hostname;
- if (!is_localhost(hostname)) {
- r = sd_dhcp_client_set_hostname(link->dhcp_client,
- hostname);
+ if (!is_localhost(hn)) {
+ r = sd_dhcp_client_set_hostname(link->dhcp_client, hn);
if (r < 0)
return r;
}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 9550e89a15..f20f68b482 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -846,9 +846,6 @@ static int link_set_bridge(Link *link) {
assert(link);
assert(link->network);
- if(link->network->cost == 0)
- return 0;
-
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
@@ -861,6 +858,26 @@ static int link_set_bridge(Link *link) {
if (r < 0)
return log_link_error_errno(link, r, "Could not append IFLA_PROTINFO attribute: %m");
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_GUARD, !link->network->use_bpdu);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_GUARD attribute: %m");
+
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_MODE, link->network->hairpin);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_MODE attribute: %m");
+
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_FAST_LEAVE, link->network->fast_leave);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_FAST_LEAVE attribute: %m");
+
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_PROTECT, !link->network->allow_port_to_be_root);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_PROTECT attribute: %m");
+
+ r = sd_netlink_message_append_u8(req, IFLA_BRPORT_UNICAST_FLOOD, link->network->unicast_flood);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Could not append IFLA_BRPORT_UNICAST_FLOOD attribute: %m");
+
if(link->network->cost != 0) {
r = sd_netlink_message_append_u32(req, IFLA_BRPORT_COST, link->network->cost);
if (r < 0)
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index 010c106610..fa3ba38a3b 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -36,6 +36,8 @@ Tunnel.TOS, config_parse_unsigned, 0,
Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl)
Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc)
Tunnel.Mode, config_parse_ip6tnl_mode, 0, offsetof(Tunnel, ip6tnl_mode)
+Tunnel.IPv6FlowLabel, config_parse_ipv6_flowlabel, 0, offsetof(Tunnel, ipv6_flowlabel)
+Tunnel.CopyDSCP, config_parse_bool, 0, offsetof(Tunnel, copy_dscp)
Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer)
Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer)
VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id)
@@ -59,7 +61,7 @@ Tun.Group, config_parse_string, 0,
Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue)
Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue)
Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info)
-Tap.VnetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
+Tap.VNetHeader, config_parse_bool, 0, offsetof(TunTap, vnet_hdr)
Tap.User, config_parse_string, 0, offsetof(TunTap, user_name)
Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name)
Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode)
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 5533fb5c7b..7fd9ef584b 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -33,6 +33,7 @@
#include "conf-parser.h"
#define DEFAULT_TNL_HOP_LIMIT 64
+#define IP6_FLOWINFO_FLOWLABEL htonl(0x000FFFFF)
static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
[NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -184,6 +185,16 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_TTL attribute: %m");
+ if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ r = sd_netlink_message_append_u32(m, IFLA_GRE_FLOWINFO, t->ipv6_flowlabel);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLOWINFO attribute: %m");
+ }
+
+ r = sd_netlink_message_append_u32(m, IFLA_GRE_FLAGS, t->flags);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_GRE_FLAGS attribute: %m");
+
return r;
}
@@ -264,6 +275,19 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
+ if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
+ }
+
+ if (t->copy_dscp)
+ t->flags |= IP6_TNL_F_RCV_DSCP_COPY;
+
+ r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+
switch (t->ip6tnl_mode) {
case NETDEV_IP6_TNL_MODE_IP6IP6:
proto = IPPROTO_IPV6;
@@ -380,6 +404,52 @@ int config_parse_tunnel_address(const char *unit,
return 0;
}
+static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = {
+ [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel);
+
+int config_parse_ipv6_flowlabel(const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ IPv6FlowLabel *ipv6_flowlabel = data;
+ Tunnel *t = userdata;
+ IPv6FlowLabel s;
+ int k = 0;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(ipv6_flowlabel);
+
+ s = ipv6_flowlabel_from_string(rvalue);
+ if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+ *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
+ t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
+ } else {
+ r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
+ if (r >= 0) {
+ if (k > 0xFFFFF)
+ log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
+ else {
+ *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
+ t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
+ }
+ }
+ }
+
+ return 0;
+}
+
static void ipip_init(NetDev *n) {
Tunnel *t = IPIP(n);
@@ -452,6 +522,7 @@ static void ip6tnl_init(NetDev *n) {
t->ttl = DEFAULT_TNL_HOP_LIMIT;
t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
+ t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
}
const NetDevVTable ipip_vtable = {
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
index 88f57ac105..1fd2b94ae1 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -33,6 +33,12 @@ typedef enum Ip6TnlMode {
_NETDEV_IP6_TNL_MODE_INVALID = -1,
} Ip6TnlMode;
+typedef enum IPv6FlowLabel {
+ NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
+ _NETDEV_IPV6_FLOWLABEL_MAX,
+ _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
+} IPv6FlowLabel;
+
struct Tunnel {
NetDev meta;
@@ -48,8 +54,10 @@ struct Tunnel {
union in_addr_union remote;
Ip6TnlMode ip6tnl_mode;
+ IPv6FlowLabel ipv6_flowlabel;
bool pmtudisc;
+ bool copy_dscp;
};
extern const NetDevVTable ipip_vtable;
@@ -70,3 +78,23 @@ int config_parse_ip6tnl_mode(const char *unit, const char *filename,
unsigned section_line, const char *lvalue,
int ltype, const char *rvalue, void *data,
void *userdata);
+
+int config_parse_tunnel_address(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata);
+
+const char *ipv6_flowlabel_to_string(IPv6FlowLabel d) _const_;
+IPv6FlowLabel ipv6_flowlabel_from_string(const char *d) _pure_;
+
+int config_parse_ipv6_flowlabel(const char *unit, const char *filename,
+ unsigned line, const char *section,
+ unsigned section_line, const char *lvalue,
+ int ltype, const char *rvalue, void *data,
+ void *userdata);
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
index fe5254e91f..e7d1306f13 100644
--- a/src/network/networkd-netdev-vxlan.h
+++ b/src/network/networkd-netdev-vxlan.h
@@ -53,3 +53,14 @@ struct VxLan {
};
extern const NetDevVTable vxlan_vtable;
+
+int config_parse_vxlan_group_address(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata);
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 787fc2ff5b..83224d7109 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -67,11 +67,17 @@ DHCP.UseHostname, config_parse_bool, 0
DHCP.UseDomains, config_parse_bool, 0, offsetof(Network, dhcp_domains)
DHCP.UseRoutes, config_parse_bool, 0, offsetof(Network, dhcp_routes)
DHCP.SendHostname, config_parse_bool, 0, offsetof(Network, dhcp_sendhost)
+DHCP.Hostname, config_parse_hostname, 0, offsetof(Network, hostname)
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
DHCP.CriticalConnection, config_parse_bool, 0, offsetof(Network, dhcp_critical)
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
DHCP.RouteMetric, config_parse_unsigned, 0, offsetof(Network, dhcp_route_metric)
Bridge.Cost, config_parse_unsigned, 0, offsetof(Network, cost)
+Bridge.UseBPDU, config_parse_bool, 0, offsetof(Network, use_bpdu)
+Bridge.HairPin, config_parse_bool, 0, offsetof(Network, hairpin)
+Bridge.FastLeave, config_parse_bool, 0, offsetof(Network, fast_leave)
+Bridge.AllowPortToBeRoot, config_parse_bool, 0, offsetof(Network, allow_port_to_be_root)
+Bridge.UnicastFlood, config_parse_bool, 0, offsetof(Network, unicast_flood)
BridgeFDB.MACAddress, config_parse_fdb_hwaddr, 0, 0
BridgeFDB.VLANId, config_parse_fdb_vlan_id, 0, 0
/* backwards compatibility: do not add new entries to this section */
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index a8e9ef909c..d8f42621af 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -107,6 +107,10 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
+ network->use_bpdu = true;
+ network->allow_port_to_be_root = true;
+ network->unicast_flood = true;
+
network->llmnr = LLMNR_SUPPORT_YES;
network->link_local = ADDRESS_FAMILY_IPV6;
@@ -207,6 +211,7 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ free(network->hostname);
free(network->mac);
@@ -809,3 +814,38 @@ int config_parse_ipv6_privacy_extensions(
return 0;
}
+
+int config_parse_hostname(const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+ char **hostname = data;
+ char *hn = NULL;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = config_parse_string(unit, filename, line, section, section_line,
+ lvalue, ltype, rvalue, &hn, userdata);
+ if (r < 0)
+ return r;
+
+ if (!hostname_is_valid(hn)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "hostname is not valid, ignoring assignment: %s", rvalue);
+
+ free(hn);
+ return 0;
+ }
+
+ *hostname = hn;
+
+ return 0;
+}
diff --git a/src/network/networkd-wait-online.c b/src/network/networkd-wait-online.c
index 32c31fdf3d..d958b48771 100644
--- a/src/network/networkd-wait-online.c
+++ b/src/network/networkd-wait-online.c
@@ -66,7 +66,7 @@ static int parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
- while ((c = getopt_long(argc, argv, "+hiq", options, NULL)) >= 0)
+ while ((c = getopt_long(argc, argv, "+hi:q", options, NULL)) >= 0)
switch (c) {
diff --git a/src/network/networkd.h b/src/network/networkd.h
index f98c640822..a285a4b08f 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -133,6 +133,7 @@ struct Network {
AddressFamilyBoolean dhcp;
DCHPClientIdentifier dhcp_client_identifier;
char *dhcp_vendor_class_identifier;
+ char *hostname;
bool dhcp_dns;
bool dhcp_ntp;
bool dhcp_mtu;
@@ -149,6 +150,11 @@ struct Network {
bool dhcp_server;
+ bool use_bpdu;
+ bool hairpin;
+ bool fast_leave;
+ bool allow_port_to_be_root;
+ bool unicast_flood;
unsigned cost;
AddressFamilyBoolean ip_forward;
@@ -319,28 +325,6 @@ int config_parse_tunnel(const char *unit,
void *data,
void *userdata);
-int config_parse_tunnel_address(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
-
-int config_parse_vxlan_group_address(const char *unit,
- const char *filename,
- unsigned line,
- const char *section,
- unsigned section_line,
- const char *lvalue,
- int ltype,
- const char *rvalue,
- void *data,
- void *userdata);
-
extern const sd_bus_vtable network_vtable[];
int network_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
@@ -473,3 +457,7 @@ const char* ipv6_privacy_extensions_to_string(IPv6PrivacyExtensions i) _const_;
IPv6PrivacyExtensions ipv6_privacy_extensions_from_string(const char *s) _pure_;
int config_parse_ipv6_privacy_extensions(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+
+/* Hostname */
+int config_parse_hostname(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);