assert(netmask);
assert(lifetime);
+ /* address_handler calls link_request_set_routes() and link_request_set_nexthop(). Before they
+ * are called, the related flags must be cleared. Otherwise, the link becomes configured state
+ * before routes are configured. */
+ link->static_routes_configured = false;
+ link->static_nexthops_configured = false;
+
prefixlen = in4_addr_netmask_to_prefixlen(netmask);
r = address_new(&addr);
link->dhcp_lease_old = TAKE_PTR(link->dhcp_lease);
- /* On ip address change, to keep the connectability, we would like to assign new address and
+ /* On IP address change, to keep the connectability, we would like to assign new address and
* routes, and then release old lease. There are two possible success paths:
*
* 1. new address and routes are configured.
return 0;
}
-static int dhcp_server_is_black_listed(Link *link, sd_dhcp_client *client) {
+static int dhcp_server_is_deny_listed(Link *link, sd_dhcp_client *client) {
+ sd_dhcp_lease *lease;
+ struct in_addr addr;
+ int r;
+
+ assert(link);
+ assert(link->network);
+ assert(client);
+
+ r = sd_dhcp_client_get_lease(client, &lease);
+ if (r < 0)
+ return log_link_error_errno(link, r, "Failed to get DHCP lease: %m");
+
+ r = sd_dhcp_lease_get_server_identifier(lease, &addr);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
+
+ if (set_contains(link->network->dhcp_deny_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+ log_struct(LOG_DEBUG,
+ LOG_LINK_INTERFACE(link),
+ LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in deny-listed IP addresses, ignoring offer",
+ ADDRESS_FMT_VAL(addr)));
+ return true;
+ }
+
+ return false;
+}
+
+static int dhcp_server_is_allow_listed(Link *link, sd_dhcp_client *client) {
sd_dhcp_lease *lease;
struct in_addr addr;
int r;
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
if (r < 0)
- return log_link_debug_errno(link, r, "Failed to get DHCP server ip address: %m");
+ return log_link_debug_errno(link, r, "Failed to get DHCP server IP address: %m");
- if (set_contains(link->network->dhcp_black_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
+ if (set_contains(link->network->dhcp_allow_listed_ip, UINT32_TO_PTR(addr.s_addr))) {
log_struct(LOG_DEBUG,
LOG_LINK_INTERFACE(link),
- LOG_LINK_MESSAGE(link, "DHCPv4 ip '%u.%u.%u.%u' found in black listed ip addresses, ignoring offer",
+ LOG_LINK_MESSAGE(link, "DHCPv4 IP '%u.%u.%u.%u' found in allow-listed IP addresses, accepting offer",
ADDRESS_FMT_VAL(addr)));
return true;
}
}
break;
case SD_DHCP_CLIENT_EVENT_SELECTING:
- r = dhcp_server_is_black_listed(link, client);
- if (r < 0)
- return r;
- if (r != 0)
- return -ENOMSG;
-
+ if (!set_isempty(link->network->dhcp_allow_listed_ip)) {
+ r = dhcp_server_is_allow_listed(link, client);
+ if (r < 0)
+ return r;
+ if (r == 0)
+ return -ENOMSG;
+ } else {
+ r = dhcp_server_is_deny_listed(link, client);
+ if (r < 0)
+ return r;
+ if (r != 0)
+ return -ENOMSG;
+ }
break;
default:
if (event < 0)
if (link->network->ip_service_type > 0) {
r = sd_dhcp_client_set_service_type(link->dhcp_client, link->network->ip_service_type);
if (r < 0)
- return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set ip service type: %m");
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set IP service type: %m");
+ }
+
+ if (link->network->dhcp_fallback_lease_lifetime > 0) {
+ r = sd_dhcp_client_set_fallback_lease_lifetime(link->dhcp_client, link->network->dhcp_fallback_lease_lifetime);
+ if (r < 0)
+ return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed set to lease lifetime: %m");
}
if (link->network->dhcp_send_decline) {
return 0;
}
-int config_parse_dhcp_black_listed_ip_address(
+int config_parse_dhcp_acl_ip_address(
const char *unit,
const char *filename,
unsigned line,
void *userdata) {
Network *network = data;
- const char *p;
+ Set **acl;
int r;
assert(filename);
assert(rvalue);
assert(data);
+ acl = STR_IN_SET(lvalue, "DenyList", "BlackList") ? &network->dhcp_deny_listed_ip : &network->dhcp_allow_listed_ip;
+
if (isempty(rvalue)) {
- network->dhcp_black_listed_ip = set_free(network->dhcp_black_listed_ip);
+ *acl = set_free(*acl);
return 0;
}
- for (p = rvalue;;) {
+ for (const char *p = rvalue;;) {
_cleanup_free_ char *n = NULL;
union in_addr_union ip;
r = extract_first_word(&p, &n, NULL, 0);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DHCP black listed ip address, ignoring assignment: %s",
- rvalue);
+ "Failed to parse DHCP '%s=' IP address, ignoring assignment: %s",
+ lvalue, rvalue);
return 0;
}
if (r == 0)
r = in_addr_from_string(AF_INET, n, &ip);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, r,
- "DHCP black listed ip address is invalid, ignoring assignment: %s", n);
+ "DHCP '%s=' IP address is invalid, ignoring assignment: %s", lvalue, n);
continue;
}
- r = set_ensure_allocated(&network->dhcp_black_listed_ip, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(network->dhcp_black_listed_ip, UINT32_TO_PTR(ip.in.s_addr));
+ r = set_ensure_put(acl, NULL, UINT32_TO_PTR(ip.in.s_addr));
if (r < 0)
log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP black listed ip address '%s', ignoring assignment: %m", n);
+ "Failed to store DHCP '%s=' IP address '%s', ignoring assignment: %m", lvalue, n);
}
return 0;
}
-int config_parse_dhcp_user_class(
+int config_parse_dhcp_ip_service_type(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
- char ***l = data;
- int r;
-
- assert(l);
+ assert(filename);
assert(lvalue);
assert(rvalue);
- if (isempty(rvalue)) {
- *l = strv_free(*l);
- return 0;
- }
-
- for (;;) {
- _cleanup_free_ char *w = NULL;
-
- r = extract_first_word(&rvalue, &w, NULL, 0);
- if (r == -ENOMEM)
- return log_oom();
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to split user classes option, ignoring: %s", rvalue);
- break;
- }
- if (r == 0)
- break;
-
- if (strlen(w) > 255) {
- log_syntax(unit, LOG_ERR, filename, line, 0,
- "%s length is not in the range 1-255, ignoring.", w);
- continue;
- }
-
- r = strv_push(l, w);
- if (r < 0)
- return log_oom();
-
- w = NULL;
- }
+ if (streq(rvalue, "CS4"))
+ *((int *)data) = IPTOS_CLASS_CS4;
+ else if (streq(rvalue, "CS6"))
+ *((int *)data) = IPTOS_CLASS_CS6;
+ else
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "Failed to parse IPServiceType type '%s', ignoring.", rvalue);
return 0;
}
-int config_parse_dhcp_request_options(
+int config_parse_dhcp_mud_url(
const char *unit,
const char *filename,
unsigned line,
void *data,
void *userdata) {
+ _cleanup_free_ char *unescaped = NULL;
Network *network = data;
- const char *p;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
- assert(data);
if (isempty(rvalue)) {
- network->dhcp_request_options = set_free(network->dhcp_request_options);
+ network->dhcp_mudurl = mfree(network->dhcp_mudurl);
return 0;
}
- for (p = rvalue;;) {
- _cleanup_free_ char *n = NULL;
- uint32_t i;
-
- r = extract_first_word(&p, &n, NULL, 0);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to parse DHCP request option, ignoring assignment: %s",
- rvalue);
- return 0;
- }
- if (r == 0)
- return 0;
-
- r = safe_atou32(n, &i);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "DHCP request option is invalid, ignoring assignment: %s", n);
- continue;
- }
-
- if (i < 1 || i >= 255) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "DHCP request option is invalid, valid range is 1-254, ignoring assignment: %s", n);
- continue;
- }
-
- r = set_ensure_allocated(&network->dhcp_request_options, NULL);
- if (r < 0)
- return log_oom();
-
- r = set_put(network->dhcp_request_options, UINT32_TO_PTR(i));
- if (r < 0)
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to store DHCP request option '%s', ignoring assignment: %m", n);
+ r = cunescape(rvalue, 0, &unescaped);
+ if (r < 0) {
+ log_syntax(unit, LOG_ERR, filename, line, r,
+ "Failed to Failed to unescape MUD URL, ignoring: %s", rvalue);
+ return 0;
}
- return 0;
-}
-
-int config_parse_dhcp_ip_service_type(
- 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) {
-
- assert(filename);
- assert(lvalue);
- assert(rvalue);
+ if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
+ log_syntax(unit, LOG_ERR, filename, line, 0,
+ "Failed to parse MUD URL '%s', ignoring: %m", rvalue);
- if (streq(rvalue, "CS4"))
- *((int *)data) = IPTOS_CLASS_CS4;
- else if (streq(rvalue, "CS6"))
- *((int *)data) = IPTOS_CLASS_CS6;
- else
- log_syntax(unit, LOG_WARNING, filename, line, 0,
- "Failed to parse IPServiceType type '%s', ignoring.", rvalue);
+ return 0;
+ }
- return 0;
+ return free_and_strdup_warn(&network->dhcp_mudurl, unescaped);
}
-int config_parse_dhcp_mud_url(
- const char *unit,
+int config_parse_dhcp_fallback_lease_lifetime(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *rvalue,
void *data,
void *userdata) {
-
- _cleanup_free_ char *unescaped = NULL;
- Network *network = data;
- int r;
+ Network *network = userdata;
+ uint32_t k;
assert(filename);
+ assert(section);
assert(lvalue);
assert(rvalue);
+ assert(data);
if (isempty(rvalue)) {
- network->dhcp_mudurl = mfree(network->dhcp_mudurl);
+ network->dhcp_fallback_lease_lifetime = 0;
return 0;
}
- r = cunescape(rvalue, 0, &unescaped);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r,
- "Failed to Failed to unescape MUD URL, ignoring: %s", rvalue);
- return 0;
- }
-
- if (!http_url_is_valid(unescaped) || strlen(unescaped) > 255) {
+ /* We accept only "forever" or "infinity". */
+ if (STR_IN_SET(rvalue, "forever", "infinity"))
+ k = CACHE_INFO_INFINITY_LIFE_TIME;
+ else {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Failed to parse MUD URL '%s', ignoring: %m", rvalue);
-
+ "Invalid LeaseLifetime= value, ignoring: %s", rvalue);
return 0;
}
- return free_and_strdup_warn(&network->dhcp_mudurl, unescaped);
+ network->dhcp_fallback_lease_lifetime = k;
+
+ return 0;
}
static const char* const dhcp_client_identifier_table[_DHCP_CLIENT_ID_MAX] = {