#include "bus-error.h"
#include "bus-locator.h"
-#include "dhcp-identifier.h"
-#include "dhcp-internal.h"
+#include "dhcp-option.h"
#include "dhcp6-internal.h"
#include "escape.h"
#include "hexdecoct.h"
#include "networkd-link.h"
#include "networkd-manager.h"
#include "networkd-network.h"
+#include "networkd-route-util.h"
#include "parse-util.h"
#include "socket-util.h"
#include "string-table.h"
return link_get_vrf_table(link);
}
-uint32_t link_get_ipv6_accept_ra_route_table(Link *link) {
+uint32_t link_get_ndisc_route_table(Link *link) {
assert(link);
assert(link->network);
- if (link->network->ipv6_accept_ra_route_table_set)
- return link->network->ipv6_accept_ra_route_table;
+ if (link->network->ndisc_route_table_set)
+ return link->network->ndisc_route_table;
return link_get_vrf_table(link);
}
return false;
}
+int link_get_captive_portal(Link *link, const char **ret) {
+ const char *dhcp4_cp = NULL, *dhcp6_cp = NULL, *ndisc_cp = NULL;
+ int r;
+
+ assert(link);
+
+ if (!link->network) {
+ *ret = NULL;
+ return 0;
+ }
+
+ if (link->network->dhcp_use_captive_portal && link->dhcp_lease) {
+ r = sd_dhcp_lease_get_captive_portal(link->dhcp_lease, &dhcp4_cp);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ }
+
+ if (link->network->dhcp6_use_captive_portal && link->dhcp6_lease) {
+ r = sd_dhcp6_lease_get_captive_portal(link->dhcp6_lease, &dhcp6_cp);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ }
+
+ if (link->network->ndisc_use_captive_portal) {
+ NDiscCaptivePortal *cp;
+ usec_t usec = 0;
+
+ /* Use the captive portal with the longest lifetime. */
+
+ SET_FOREACH(cp, link->ndisc_captive_portals) {
+ if (cp->lifetime_usec < usec)
+ continue;
+
+ ndisc_cp = cp->captive_portal;
+ usec = cp->lifetime_usec;
+ }
+
+ if (set_size(link->ndisc_captive_portals) > 1)
+ log_link_debug(link, "Multiple captive portals obtained by IPv6RA, using \"%s\" and ignoring others.",
+ ndisc_cp);
+ }
+
+ if (dhcp4_cp) {
+ if (dhcp6_cp && !streq(dhcp4_cp, dhcp6_cp))
+ log_link_debug(link, "DHCPv6 captive portal (%s) does not match DHCPv4 (%s), ignoring DHCPv6 captive portal.",
+ dhcp6_cp, dhcp4_cp);
+
+ if (ndisc_cp && !streq(dhcp4_cp, ndisc_cp))
+ log_link_debug(link, "IPv6RA captive portal (%s) does not match DHCPv4 (%s), ignoring IPv6RA captive portal.",
+ ndisc_cp, dhcp4_cp);
+
+ *ret = dhcp4_cp;
+ return 1;
+ }
+
+ if (dhcp6_cp) {
+ if (ndisc_cp && !streq(dhcp6_cp, ndisc_cp))
+ log_link_debug(link, "IPv6RA captive portal (%s) does not match DHCPv6 (%s), ignoring IPv6RA captive portal.",
+ ndisc_cp, dhcp6_cp);
+
+ *ret = dhcp6_cp;
+ return 1;
+ }
+
+ *ret = ndisc_cp;
+ return !!ndisc_cp;
+}
+
int config_parse_dhcp(
const char* unit,
const char *filename,
return 0;
}
-int config_parse_dhcp_or_ra_route_metric(
+int config_parse_dhcp_route_metric(
const char* unit,
const char *filename,
unsigned line,
assert(filename);
assert(lvalue);
- assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
+ assert(IN_SET(ltype, AF_UNSPEC, AF_INET));
assert(rvalue);
assert(data);
network->dhcp_route_metric = metric;
network->dhcp_route_metric_set = true;
break;
- case AF_INET6:
- network->ipv6_accept_ra_route_metric = metric;
- network->ipv6_accept_ra_route_metric_set = true;
- break;
case AF_UNSPEC:
/* For backward compatibility. */
if (!network->dhcp_route_metric_set)
network->dhcp_route_metric = metric;
- if (!network->ipv6_accept_ra_route_metric_set)
- network->ipv6_accept_ra_route_metric = metric;
+ if (!network->ndisc_route_metric_set) {
+ network->ndisc_route_metric_high = metric;
+ network->ndisc_route_metric_medium = metric;
+ network->ndisc_route_metric_low = metric;
+ }
break;
default:
assert_not_reached();
return 0;
}
-int config_parse_dhcp_use_dns(
- const char* unit,
+int config_parse_ndisc_route_metric(
+ const char *unit,
const char *filename,
unsigned line,
const char *section,
void *data,
void *userdata) {
- Network *network = userdata;
- int r;
+ Network *network = ASSERT_PTR(userdata);
+ uint32_t metric_high, metric_medium, metric_low;
+ int r, s, t;
assert(filename);
- assert(lvalue);
- assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
assert(rvalue);
- assert(data);
- r = parse_boolean(rvalue);
- if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse UseDNS=%s, ignoring assignment: %m", rvalue);
- return 0;
- }
+ if (safe_atou32(rvalue, &metric_low) >= 0)
+ metric_high = metric_medium = metric_low;
+ else {
+ _cleanup_free_ char *high = NULL, *medium = NULL, *low = NULL;
+ const char *p = rvalue;
- switch (ltype) {
- case AF_INET:
- network->dhcp_use_dns = r;
- network->dhcp_use_dns_set = true;
- break;
- case AF_INET6:
- network->dhcp6_use_dns = r;
- network->dhcp6_use_dns_set = true;
- break;
- case AF_UNSPEC:
- /* For backward compatibility. */
- if (!network->dhcp_use_dns_set)
- network->dhcp_use_dns = r;
- if (!network->dhcp6_use_dns_set)
- network->dhcp6_use_dns = r;
- break;
- default:
- assert_not_reached();
- }
-
- return 0;
-}
-
-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) {
-
- Network *network = userdata;
- DHCPUseDomains d;
+ r = extract_many_words(&p, ":", EXTRACT_DONT_COALESCE_SEPARATORS, &high, &medium, &low);
+ if (r == -ENOMEM)
+ return log_oom();
+ if (r != 3 || !isempty(p)) {
+ log_syntax(unit, LOG_WARNING, filename, line, r < 0 ? r : 0,
+ "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
- assert(filename);
- assert(lvalue);
- assert(IN_SET(ltype, AF_UNSPEC, AF_INET, AF_INET6));
- assert(rvalue);
- assert(data);
+ r = safe_atou32(high, &metric_high);
+ s = safe_atou32(medium, &metric_medium);
+ t = safe_atou32(low, &metric_low);
+ if (r < 0 || s < 0 || t < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r < 0 ? r : s < 0 ? s : t,
+ "Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
- d = dhcp_use_domains_from_string(rvalue);
- if (d < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, d,
- "Failed to parse %s=%s, ignoring assignment: %m", lvalue, rvalue);
- return 0;
+ if (metric_high >= metric_medium || metric_medium >= metric_low) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Invalid RouteTable=%s, ignoring assignment: %m", rvalue);
+ return 0;
+ }
}
- switch (ltype) {
- case AF_INET:
- network->dhcp_use_domains = d;
- network->dhcp_use_domains_set = true;
- break;
- case AF_INET6:
- network->dhcp6_use_domains = d;
- network->dhcp6_use_domains_set = true;
- break;
- case AF_UNSPEC:
- /* For backward compatibility. */
- if (!network->dhcp_use_domains_set)
- network->dhcp_use_domains = d;
- if (!network->dhcp6_use_domains_set)
- network->dhcp6_use_domains = d;
- break;
- default:
- assert_not_reached();
- }
+ network->ndisc_route_metric_high = metric_high;
+ network->ndisc_route_metric_medium = metric_medium;
+ network->ndisc_route_metric_low = metric_low;
+ network->ndisc_route_metric_set = true;
return 0;
}
-int config_parse_dhcp_use_ntp(
+int config_parse_dhcp_send_hostname(
const char* unit,
const char *filename,
unsigned line,
r = parse_boolean(rvalue);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
- "Failed to parse UseNTP=%s, ignoring assignment: %m", rvalue);
+ "Failed to parse SendHostname=%s, ignoring assignment: %m", rvalue);
return 0;
}
switch (ltype) {
case AF_INET:
- network->dhcp_use_ntp = r;
- network->dhcp_use_ntp_set = true;
+ network->dhcp_send_hostname = r;
+ network->dhcp_send_hostname_set = true;
break;
case AF_INET6:
- network->dhcp6_use_ntp = r;
- network->dhcp6_use_ntp_set = true;
+ network->dhcp6_send_hostname = r;
+ network->dhcp6_send_hostname_set = true;
break;
case AF_UNSPEC:
/* For backward compatibility. */
- if (!network->dhcp_use_ntp_set)
- network->dhcp_use_ntp = r;
- if (!network->dhcp6_use_ntp_set)
- network->dhcp6_use_ntp = r;
+ if (!network->dhcp_send_hostname_set)
+ network->dhcp_send_hostname = r;
+ if (!network->dhcp6_send_hostname_set)
+ network->dhcp6_send_hostname = r;
break;
default:
assert_not_reached();
assert(IN_SET(ltype, AF_INET, AF_INET6));
assert(rvalue);
- r = safe_atou32(rvalue, &rt);
+ r = manager_get_route_table_from_string(network->manager, rvalue, &rt);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r,
"Failed to parse RouteTable=%s, ignoring assignment: %m", rvalue);
network->dhcp_route_table_set = true;
break;
case AF_INET6:
- network->ipv6_accept_ra_route_table = rt;
- network->ipv6_accept_ra_route_table_set = true;
+ network->ndisc_route_table = rt;
+ network->ndisc_route_table_set = true;
break;
default:
assert_not_reached();
}
case DHCP_OPTION_DATA_STRING:
sz = cunescape(p, UNESCAPE_ACCEPT_NUL, &q);
- if (sz < 0)
+ if (sz < 0) {
log_syntax(unit, LOG_WARNING, filename, line, sz,
"Failed to decode DHCP option data, ignoring assignment: %s", p);
+ return 0;
+ }
udata = q;
break;
}
}
-static const char* const dhcp_use_domains_table[_DHCP_USE_DOMAINS_MAX] = {
- [DHCP_USE_DOMAINS_NO] = "no",
- [DHCP_USE_DOMAINS_ROUTE] = "route",
- [DHCP_USE_DOMAINS_YES] = "yes",
-};
-
-DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dhcp_use_domains, DHCPUseDomains, DHCP_USE_DOMAINS_YES);
-
static const char * const dhcp_option_data_type_table[_DHCP_OPTION_DATA_MAX] = {
[DHCP_OPTION_DATA_UINT8] = "uint8",
[DHCP_OPTION_DATA_UINT16] = "uint16",
type = duid_type_from_string(type_string);
if (type < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, type,
- "Failed to parse DUID type '%s', ignoring.", type_string);
- return 0;
+ uint16_t t;
+
+ r = safe_atou16(type_string, &t);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse DUID type '%s', ignoring.", type_string);
+ return 0;
+ }
+
+ type = t;
+ assert(type == t); /* Check if type can store uint16_t. */
}
if (!isempty(p)) {
void *data,
void *userdata) {
- uint8_t raw_data[MAX_DUID_LEN];
+ uint8_t raw_data[MAX_DUID_DATA_LEN];
unsigned count = 0;
bool force = ltype;
DUID *duid = ASSERT_PTR(data);
if (r == 0)
break;
- if (count >= MAX_DUID_LEN) {
+ if (count >= MAX_DUID_DATA_LEN) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Max DUID length exceeded, ignoring assignment: %s.", rvalue);
return 0;
}