static int dhcp4_remove_address_and_routes(Link *link, bool only_marked) {
Address *address;
Route *route;
- int k, r = 0;
+ int ret = 0;
assert(link);
+ assert(link->manager);
- SET_FOREACH(route, link->routes) {
+ SET_FOREACH(route, link->manager->routes) {
if (route->source != NETWORK_CONFIG_SOURCE_DHCP4)
continue;
+ if (route->nexthop.ifindex != 0 && route->nexthop.ifindex != link->ifindex)
+ continue;
if (only_marked && !route_is_marked(route))
continue;
- k = route_remove(route);
- if (k < 0)
- r = k;
-
- route_cancel_request(route, link);
+ RET_GATHER(ret, route_remove_and_cancel(route, link->manager));
}
SET_FOREACH(address, link->addresses) {
if (only_marked && !address_is_marked(address))
continue;
- k = address_remove_and_drop(address);
- if (k < 0)
- r = k;
+ RET_GATHER(ret, address_remove_and_cancel(address, link));
}
- return r;
+ return ret;
}
static int dhcp4_address_get(Link *link, Address **ret) {
assert(m);
assert(link);
- r = sd_netlink_message_get_errno(m);
- if (r < 0 && r != -EEXIST) {
- log_link_message_warning_errno(link, m, r, "Could not set DHCPv4 route");
- link_enter_failed(link);
- return 1;
- }
+ r = route_configure_handler_internal(rtnl, m, link, route, "Could not set DHCPv4 route");
+ if (r <= 0)
+ return r;
r = dhcp4_check_ready(link);
if (r < 0)
return 1;
}
-static int dhcp4_request_route(Route *in, Link *link) {
- _cleanup_(route_freep) Route *route = in;
+static int dhcp4_request_route(Route *route, Link *link) {
struct in_addr server;
Route *existing;
int r;
assert(route);
assert(link);
+ assert(link->manager);
assert(link->network);
assert(link->dhcp_lease);
route->priority = link->network->dhcp_route_metric;
if (!route->table_set)
route->table = link_get_dhcp4_route_table(link);
- if (route->mtu == 0)
- route->mtu = link->network->dhcp_route_mtu;
- if (route->quickack < 0)
- route->quickack = link->network->dhcp_quickack;
- if (route->initcwnd == 0)
- route->initcwnd = link->network->dhcp_initial_congestion_window;
- if (route->initrwnd == 0)
- route->initrwnd = link->network->dhcp_advertised_receive_window;
-
- if (route_get(NULL, link, route, &existing) < 0) /* This is a new route. */
+ r = route_metric_set(&route->metric, RTAX_MTU, link->network->dhcp_route_mtu);
+ if (r < 0)
+ return r;
+ r = route_metric_set(&route->metric, RTAX_INITCWND, link->network->dhcp_initial_congestion_window);
+ if (r < 0)
+ return r;
+ r = route_metric_set(&route->metric, RTAX_INITRWND, link->network->dhcp_advertised_receive_window);
+ if (r < 0)
+ return r;
+ r = route_metric_set(&route->metric, RTAX_QUICKACK, link->network->dhcp_quickack);
+ if (r < 0)
+ return r;
+
+ r = route_adjust_nexthops(route, link);
+ if (r < 0)
+ return r;
+
+ if (route_get(link->manager, route, &existing) < 0) /* This is a new route. */
link->dhcp4_configured = false;
else
route_unmark(existing);
- return link_request_route(link, TAKE_PTR(route), true, &link->dhcp4_messages,
- dhcp4_route_handler, NULL);
+ return link_request_route(link, route, &link->dhcp4_messages, dhcp4_route_handler);
}
static bool link_prefixroute(Link *link) {
}
static int dhcp4_request_prefix_route(Link *link) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
int r;
assert(link);
if (r < 0)
return r;
- return dhcp4_request_route(TAKE_PTR(route), link);
+ return dhcp4_request_route(route, link);
}
static int dhcp4_request_route_to_gateway(Link *link, const struct in_addr *gw) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
struct in_addr address;
int r;
route->prefsrc.in = address;
route->scope = RT_SCOPE_LINK;
- return dhcp4_request_route(TAKE_PTR(route), link);
+ return dhcp4_request_route(route, link);
}
static int dhcp4_request_route_auto(
- Route *in,
+ Route *route,
Link *link,
const struct in_addr *gw) {
- _cleanup_(route_freep) Route *route = in;
struct in_addr address;
int r;
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
route->scope = RT_SCOPE_HOST;
- route->gw_family = AF_UNSPEC;
- route->gw = IN_ADDR_NULL;
+ route->nexthop.family = AF_UNSPEC;
+ route->nexthop.gw = IN_ADDR_NULL;
route->prefsrc = IN_ADDR_NULL;
} else if (in4_addr_equal(&route->dst.in, &address)) {
IPV4_ADDRESS_FMT_VAL(route->dst.in), route->dst_prefixlen, IPV4_ADDRESS_FMT_VAL(*gw));
route->scope = RT_SCOPE_HOST;
- route->gw_family = AF_UNSPEC;
- route->gw = IN_ADDR_NULL;
+ route->nexthop.family = AF_UNSPEC;
+ route->nexthop.gw = IN_ADDR_NULL;
route->prefsrc.in = address;
} else if (in4_addr_is_null(gw)) {
}
route->scope = RT_SCOPE_LINK;
- route->gw_family = AF_UNSPEC;
- route->gw = IN_ADDR_NULL;
+ route->nexthop.family = AF_UNSPEC;
+ route->nexthop.gw = IN_ADDR_NULL;
route->prefsrc.in = address;
} else {
return r;
route->scope = RT_SCOPE_UNIVERSE;
- route->gw_family = AF_INET;
- route->gw.in = *gw;
+ route->nexthop.family = AF_INET;
+ route->nexthop.gw.in = *gw;
route->prefsrc.in = address;
}
- return dhcp4_request_route(TAKE_PTR(route), link);
+ return dhcp4_request_route(route, link);
}
static int dhcp4_request_classless_static_or_static_routes(Link *link) {
return r;
FOREACH_ARRAY(e, routes, n_routes) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
r = route_new(&route);
if (r < 0)
return r;
- r = dhcp4_request_route_auto(TAKE_PTR(route), link, &gw);
+ r = dhcp4_request_route_auto(route, link, &gw);
if (r < 0)
return r;
}
}
static int dhcp4_request_default_gateway(Link *link) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
struct in_addr address, router;
int r;
return r;
/* Next, add a default gateway. */
- route->gw_family = AF_INET;
- route->gw.in = router;
+ route->nexthop.family = AF_INET;
+ route->nexthop.gw.in = router;
route->prefsrc.in = address;
- return dhcp4_request_route(TAKE_PTR(route), link);
+ return dhcp4_request_route(route, link);
}
static int dhcp4_request_semi_static_routes(Link *link) {
assert(link->network);
HASHMAP_FOREACH(rt, link->network->routes_by_section) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
if (!rt->gateway_from_dhcp_or_ra)
continue;
- if (rt->gw_family != AF_INET)
+ if (rt->nexthop.family != AF_INET)
continue;
assert(rt->family == AF_INET);
if (r < 0)
return r;
- r = route_dup(rt, &route);
+ r = route_dup(rt, NULL, &route);
if (r < 0)
return r;
- route->gw.in = gw;
+ route->nexthop.gw.in = gw;
- r = dhcp4_request_route(TAKE_PTR(route), link);
+ r = dhcp4_request_route(route, link);
if (r < 0)
return r;
}
assert(servers || n_servers == 0);
FOREACH_ARRAY(dst, servers, n_servers) {
- _cleanup_(route_freep) Route *route = NULL;
+ _cleanup_(route_unrefp) Route *route = NULL;
struct in_addr gw;
if (in4_addr_is_null(dst))
route->dst.in = *dst;
route->dst_prefixlen = 32;
- r = dhcp4_request_route_auto(TAKE_PTR(route), link, &gw);
+ r = dhcp4_request_route_auto(route, link, &gw);
if (r < 0)
return r;
}
}
int dhcp4_lease_lost(Link *link) {
- int k, r = 0;
+ int r = 0;
assert(link);
assert(link->dhcp_lease);
sd_dhcp_lease_has_6rd(link->dhcp_lease))
dhcp4_pd_prefix_lost(link);
- k = dhcp4_remove_address_and_routes(link, /* only_marked = */ false);
- if (k < 0)
- r = k;
-
- k = dhcp_reset_mtu(link);
- if (k < 0)
- r = k;
-
- k = dhcp_reset_hostname(link);
- if (k < 0)
- r = k;
+ RET_GATHER(r, dhcp4_remove_address_and_routes(link, /* only_marked = */ false));
+ RET_GATHER(r, dhcp_reset_mtu(link));
+ RET_GATHER(r, dhcp_reset_hostname(link));
link->dhcp_lease = sd_dhcp_lease_unref(link->dhcp_lease);
link_dirty(link);
}
static int dhcp4_request_address(Link *link, bool announce) {
- _cleanup_(address_freep) Address *addr = NULL;
+ _cleanup_(address_unrefp) Address *addr = NULL;
struct in_addr address, server;
uint8_t prefixlen;
Address *existing;
assert(link);
link_mark_addresses(link, NETWORK_CONFIG_SOURCE_DHCP4);
- link_mark_routes(link, NETWORK_CONFIG_SOURCE_DHCP4);
+ manager_mark_routes(link->manager, link, NETWORK_CONFIG_SOURCE_DHCP4);
r = dhcp4_request_address(link, announce);
if (r < 0)
}
r = sd_ipv4ll_start(link->ipv4ll);
- if (r < 0)
+ if (r < 0 && r != -ESTALE) /* On exit, we cannot and should not start sd-ipv4ll. */
return log_link_warning_errno(link, r, "Could not acquire IPv4 link-local address: %m");
}
assert(link);
assert(link->network);
+ /* If it is explicitly specified, then honor the setting. */
if (link->network->dhcp_ipv6_only_mode >= 0)
return link->network->dhcp_ipv6_only_mode;
- return link_dhcp6_enabled(link) || link_ipv6_accept_ra_enabled(link);
+ /* Defaults to false, until we support 464XLAT. See issue #30891. */
+ return false;
}
static int dhcp4_configure(Link *link) {
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for classless static route: %m");
}
- if (link->network->dhcp_use_domains != DHCP_USE_DOMAINS_NO) {
+ if (link->network->dhcp_use_domains > 0) {
r = sd_dhcp_client_set_request_option(link->dhcp_client, SD_DHCP_OPTION_DOMAIN_SEARCH);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set request flag for domain search list: %m");
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set listen port: %m");
}
+ if (link->network->dhcp_port > 0) {
+ r = sd_dhcp_client_set_port(link->dhcp_client, link->network->dhcp_port);
+ if (r < 0)
+ return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set server port: %m");
+ }
if (link->network->dhcp_max_attempts > 0) {
r = sd_dhcp_client_set_max_attempts(link->dhcp_client, link->network->dhcp_max_attempts);