summaryrefslogtreecommitdiff
path: root/src/network/networkd-network.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/networkd-network.c')
-rw-r--r--src/network/networkd-network.c260
1 files changed, 177 insertions, 83 deletions
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index a8e9ef909c..57495b58e0 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -26,11 +26,11 @@
#include "conf-parser.h"
#include "util.h"
#include "hostname-util.h"
-#include "networkd.h"
-#include "networkd-netdev.h"
-#include "networkd-link.h"
-#include "network-internal.h"
#include "dns-domain.h"
+#include "network-internal.h"
+
+#include "networkd.h"
+#include "networkd-network.h"
static int network_load_one(Manager *manager, const char *filename) {
_cleanup_network_free_ Network *network = NULL;
@@ -107,11 +107,20 @@ static int network_load_one(Manager *manager, const char *filename) {
network->dhcp_route_metric = DHCP_ROUTE_METRIC;
network->dhcp_client_identifier = DHCP_CLIENT_ID_DUID;
- network->llmnr = LLMNR_SUPPORT_YES;
+ network->dhcp_server_emit_dns = true;
+ network->dhcp_server_emit_ntp = true;
+ network->dhcp_server_emit_timezone = true;
+
+ network->use_bpdu = true;
+ network->allow_port_to_be_root = true;
+ network->unicast_flood = true;
+
+ network->llmnr = RESOLVE_SUPPORT_YES;
network->link_local = ADDRESS_FAMILY_IPV6;
network->ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
+ network->ipv6_accept_ra = -1;
r = config_parse(NULL, filename, file,
"Match\0"
@@ -120,7 +129,8 @@ static int network_load_one(Manager *manager, const char *filename) {
"Address\0"
"Route\0"
"DHCP\0"
- "DHCPv4\0"
+ "DHCPv4\0" /* compat */
+ "DHCPServer\0"
"Bridge\0"
"BridgeFDB\0",
config_item_perf_lookup, network_network_gperf_lookup,
@@ -207,6 +217,7 @@ void network_free(Network *network) {
free(network->description);
free(network->dhcp_vendor_class_identifier);
+ free(network->hostname);
free(network->mac);
@@ -253,6 +264,10 @@ void network_free(Network *network) {
condition_free_list(network->match_kernel);
condition_free_list(network->match_arch);
+ free(network->dhcp_server_timezone);
+ free(network->dhcp_server_dns);
+ free(network->dhcp_server_ntp);
+
free(network);
}
@@ -423,6 +438,7 @@ int config_parse_netdev(const char *unit,
break;
case NETDEV_KIND_VLAN:
case NETDEV_KIND_MACVLAN:
+ case NETDEV_KIND_MACVTAP:
case NETDEV_KIND_IPVLAN:
case NETDEV_KIND_VXLAN:
r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
@@ -626,15 +642,58 @@ static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(dhcp_client_identifier, DCHPClientIdentifier);
DEFINE_CONFIG_PARSE_ENUM(config_parse_dhcp_client_identifier, dhcp_client_identifier, DCHPClientIdentifier, "Failed to parse client identifier type");
-static const char* const llmnr_support_table[_LLMNR_SUPPORT_MAX] = {
- [LLMNR_SUPPORT_NO] = "no",
- [LLMNR_SUPPORT_YES] = "yes",
- [LLMNR_SUPPORT_RESOLVE] = "resolve",
+int config_parse_ipv6token(
+ const char* unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ union in_addr_union buffer;
+ struct in6_addr *token = data;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+ assert(token);
+
+ r = in_addr_from_string(AF_INET6, rvalue, &buffer);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ r = in_addr_is_null(AF_INET6, &buffer);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *token = buffer.in6;
+
+ return 0;
+}
+
+static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
+ [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
+ [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
+ [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
};
-DEFINE_STRING_TABLE_LOOKUP(llmnr_support, LLMNRSupport);
+DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
-int config_parse_llmnr(
+int config_parse_ipv6_privacy_extensions(
const char* unit,
const char *filename,
unsigned line,
@@ -646,39 +705,44 @@ int config_parse_llmnr(
void *data,
void *userdata) {
- LLMNRSupport *llmnr = data;
+ IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
int k;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(llmnr);
+ assert(ipv6_privacy_extensions);
/* Our enum shall be a superset of booleans, hence first try
* to parse as boolean, and then as enum */
k = parse_boolean(rvalue);
if (k > 0)
- *llmnr = LLMNR_SUPPORT_YES;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
else if (k == 0)
- *llmnr = LLMNR_SUPPORT_NO;
+ *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
else {
- LLMNRSupport s;
+ IPv6PrivacyExtensions s;
- s = llmnr_support_from_string(rvalue);
- if (s < 0){
- log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse LLMNR option, ignoring: %s", rvalue);
- return 0;
+ s = ipv6_privacy_extensions_from_string(rvalue);
+ if (s < 0) {
+
+ if (streq(rvalue, "kernel"))
+ s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
+ else {
+ log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
+ return 0;
+ }
}
- *llmnr = s;
+ *ipv6_privacy_extensions = s;
}
return 0;
}
-int config_parse_ipv6token(
- const char* unit,
+int config_parse_hostname(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -689,39 +753,65 @@ int config_parse_ipv6token(
void *data,
void *userdata) {
- union in_addr_union buffer;
- struct in6_addr *token = data;
+ char **hostname = data, *hn = NULL;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(token);
- r = in_addr_from_string(AF_INET6, rvalue, &buffer);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse IPv6 token, ignoring: %s", rvalue);
- return 0;
- }
+ r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &hn, userdata);
+ if (r < 0)
+ return r;
- r = in_addr_is_null(AF_INET6, &buffer);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "IPv6 token can not be the ANY address, ignoring: %s", rvalue);
+ if (!hostname_is_valid(hn, false)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Hostname is not valid, ignoring assignment: %s", rvalue);
+ free(hn);
return 0;
}
- if ((buffer.in6.s6_addr32[0] | buffer.in6.s6_addr32[1]) != 0) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL, "IPv6 token can not be longer than 64 bits, ignoring: %s", rvalue);
+ free(*hostname);
+ *hostname = hostname_cleanup(hn);
+ return 0;
+}
+
+int config_parse_timezone(
+ const char *unit,
+ const char *filename,
+ unsigned line,
+ const char *section,
+ unsigned section_line,
+ const char *lvalue,
+ int ltype,
+ const char *rvalue,
+ void *data,
+ void *userdata) {
+
+ char **datap = data, *tz = NULL;
+ int r;
+
+ assert(filename);
+ assert(lvalue);
+ assert(rvalue);
+
+ r = config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &tz, userdata);
+ if (r < 0)
+ return r;
+
+ if (!timezone_is_valid(tz)) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Timezone is not valid, ignoring assignment: %s", rvalue);
+ free(tz);
return 0;
}
- *token = buffer.in6;
+ free(*datap);
+ *datap = tz;
return 0;
}
-int config_parse_address_family_boolean_with_kernel(
- const char* unit,
+int config_parse_dhcp_server_dns(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -732,38 +822,43 @@ int config_parse_address_family_boolean_with_kernel(
void *data,
void *userdata) {
- AddressFamilyBoolean *fwd = data, s;
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
- s = address_family_boolean_from_string(rvalue);
- if (s < 0) {
- if (streq(rvalue, "kernel"))
- s = _ADDRESS_FAMILY_BOOLEAN_INVALID;
- else {
- log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPForwarding option, ignoring: %s", rvalue);
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ struct in_addr a, *m;
+
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to extract word, ignoring: %s", rvalue);
return 0;
}
- }
- *fwd = s;
+ if (r == 0)
+ return 0;
- return 0;
-}
+ if (inet_pton(AF_INET, w, &a) <= 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse DNS server address, ignoring: %s", w);
+ continue;
+ }
-static const char* const ipv6_privacy_extensions_table[_IPV6_PRIVACY_EXTENSIONS_MAX] = {
- [IPV6_PRIVACY_EXTENSIONS_NO] = "no",
- [IPV6_PRIVACY_EXTENSIONS_PREFER_PUBLIC] = "prefer-public",
- [IPV6_PRIVACY_EXTENSIONS_YES] = "yes",
-};
+ m = realloc(n->dhcp_server_dns, (n->n_dhcp_server_dns + 1) * sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
-DEFINE_STRING_TABLE_LOOKUP(ipv6_privacy_extensions, IPv6PrivacyExtensions);
+ m[n->n_dhcp_server_dns++] = a;
+ n->dhcp_server_dns = m;
+ }
+}
-int config_parse_ipv6_privacy_extensions(
- const char* unit,
+int config_parse_dhcp_server_ntp(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
@@ -774,38 +869,37 @@ int config_parse_ipv6_privacy_extensions(
void *data,
void *userdata) {
- IPv6PrivacyExtensions *ipv6_privacy_extensions = data;
- int k;
+ Network *n = data;
+ const char *p = rvalue;
+ int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(ipv6_privacy_extensions);
- /* Our enum shall be a superset of booleans, hence first try
- * to parse as boolean, and then as enum */
+ for (;;) {
+ _cleanup_free_ char *w = NULL;
+ struct in_addr a, *m;
- k = parse_boolean(rvalue);
- if (k > 0)
- *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_YES;
- else if (k == 0)
- *ipv6_privacy_extensions = IPV6_PRIVACY_EXTENSIONS_NO;
- else {
- IPv6PrivacyExtensions s;
+ r = extract_first_word(&p, &w, NULL, 0);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, r, line, "Failed to extract word, ignoring: %s", rvalue);
+ return 0;
+ }
- s = ipv6_privacy_extensions_from_string(rvalue);
- if (s < 0) {
+ if (r == 0)
+ return 0;
- if (streq(rvalue, "kernel"))
- s = _IPV6_PRIVACY_EXTENSIONS_INVALID;
- else {
- log_syntax(unit, LOG_ERR, filename, line, s, "Failed to parse IPv6 privacy extensions option, ignoring: %s", rvalue);
- return 0;
- }
+ if (inet_pton(AF_INET, w, &a) <= 0) {
+ log_syntax(unit, LOG_ERR, filename, r, line, "Failed to parse NTP server address, ignoring: %s", w);
+ continue;
}
- *ipv6_privacy_extensions = s;
- }
+ m = realloc(n->dhcp_server_ntp, (n->n_dhcp_server_ntp + 1) * sizeof(struct in_addr));
+ if (!m)
+ return log_oom();
- return 0;
+ m[n->n_dhcp_server_ntp++] = a;
+ n->dhcp_server_ntp = m;
+ }
}