mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-03 06:38:05 +02:00
dhcp: drop internal systemd DHCPv4 client
This is long replaced by nettools' n-dhcp4 client. Drop it. We still require NMDhcpSystemd for the DHCPv6 client. Note that "[main].dhcp=systemd" now falls back to the internal client. But this option was undocumented and internal anyway.
This commit is contained in:
parent
b1575e814f
commit
54119d4105
9 changed files with 10 additions and 776 deletions
|
|
@ -2333,8 +2333,6 @@ src_libnm_systemd_core_libnm_systemd_core_la_SOURCES = \
|
|||
src/libnm-systemd-core/nm-sd-utils-core.h \
|
||||
src/libnm-systemd-core/nm-sd.c \
|
||||
src/libnm-systemd-core/nm-sd.h \
|
||||
src/libnm-systemd-core/nm-sd-utils-dhcp.h \
|
||||
src/libnm-systemd-core/nm-sd-utils-dhcp.c \
|
||||
src/libnm-systemd-core/sd-adapt-core/condition.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/conf-parser.h \
|
||||
src/libnm-systemd-core/sd-adapt-core/device-util.h \
|
||||
|
|
|
|||
3
NEWS
3
NEWS
|
|
@ -8,6 +8,9 @@ subject to change and not guaranteed to be compatible with
|
|||
the later release.
|
||||
USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||
|
||||
* Drop unused, internal systemd DHCPv4 client. This is long
|
||||
replaced by nettools' n-dhcp4 implementation.
|
||||
|
||||
=============================================
|
||||
NetworkManager-1.38
|
||||
Overview of changes since NetworkManager-1.36
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@
|
|||
#include "libnm-platform/nm-platform.h"
|
||||
#include "nm-dhcp-client-logging.h"
|
||||
#include "libnm-systemd-core/nm-sd.h"
|
||||
#include "libnm-systemd-core/nm-sd-utils-dhcp.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -47,7 +46,6 @@ static GType nm_dhcp_systemd_get_type(void);
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
sd_dhcp_client *client4;
|
||||
sd_dhcp6_client *client6;
|
||||
char *lease_file;
|
||||
|
||||
|
|
@ -69,675 +67,6 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NML3ConfigData *
|
||||
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
|
||||
const char *iface,
|
||||
int ifindex,
|
||||
sd_dhcp_lease *lease,
|
||||
GError **error)
|
||||
{
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
gs_unref_hashtable GHashTable *options = NULL;
|
||||
const struct in_addr *addr_list;
|
||||
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
const char *s;
|
||||
nm_auto_free_gstring GString *str = NULL;
|
||||
nm_auto_free sd_dhcp_route **routes_static = NULL;
|
||||
nm_auto_free sd_dhcp_route **routes_classless = NULL;
|
||||
const char *const *search_domains = NULL;
|
||||
guint32 default_route_metric_offset;
|
||||
guint16 mtu;
|
||||
int i;
|
||||
int num;
|
||||
int is_classless;
|
||||
int n_routes_static;
|
||||
int n_routes_classless;
|
||||
const void *data;
|
||||
gsize data_len;
|
||||
gboolean has_router_from_classless = FALSE;
|
||||
const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
|
||||
gint64 ts_time = time(NULL);
|
||||
struct in_addr a_address;
|
||||
struct in_addr a_netmask;
|
||||
struct in_addr a_next_server;
|
||||
struct in_addr server_id;
|
||||
struct in_addr broadcast;
|
||||
const struct in_addr *a_router;
|
||||
guint32 a_plen;
|
||||
guint32 a_lifetime;
|
||||
guint32 renewal;
|
||||
guint32 rebinding;
|
||||
gs_free nm_sd_dhcp_option *private_options = NULL;
|
||||
|
||||
nm_assert(lease != NULL);
|
||||
|
||||
if (sd_dhcp_lease_get_address(lease, &a_address) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get address from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_netmask(lease, &a_netmask) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get netmask from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_lifetime(lease, &a_lifetime) < 0) {
|
||||
nm_utils_error_set_literal(error,
|
||||
NM_UTILS_ERROR_UNKNOWN,
|
||||
"could not get lifetime from lease");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
|
||||
|
||||
options = nm_dhcp_option_create_options_dict();
|
||||
|
||||
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
|
||||
|
||||
a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
|
||||
_nm_utils_inet4_ntop(a_netmask.s_addr, addr_str));
|
||||
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
|
||||
a_lifetime);
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
|
||||
(guint64) (ts_time + a_lifetime));
|
||||
|
||||
if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) {
|
||||
_nm_utils_inet4_ntop(a_next_server.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
|
||||
}
|
||||
|
||||
nm_l3_config_data_add_address_4(l3cd,
|
||||
&((const NMPlatformIP4Address){
|
||||
.address = a_address.s_addr,
|
||||
.peer_address = a_address.s_addr,
|
||||
.plen = a_plen,
|
||||
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.timestamp = ts,
|
||||
.lifetime = a_lifetime,
|
||||
.preferred = a_lifetime,
|
||||
}));
|
||||
|
||||
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
|
||||
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_SERVER_ID, addr_str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) {
|
||||
_nm_utils_inet4_ntop(broadcast.s_addr, addr_str);
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_BROADCAST, addr_str);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_dns(lease, &addr_list);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
_nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
|
||||
|
||||
if (addr_list[i].s_addr == 0 || nm_ip4_addr_is_localhost(addr_list[i].s_addr)) {
|
||||
/* Skip localhost addresses, like also networkd does.
|
||||
* See https://github.com/systemd/systemd/issues/4524. */
|
||||
continue;
|
||||
}
|
||||
nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
|
||||
str->str);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_search_domains(lease, (char ***) &search_domains);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
|
||||
nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
|
||||
}
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST,
|
||||
str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_domainname(lease, &s) >= 0) {
|
||||
gs_strfreev char **domains = NULL;
|
||||
char **d;
|
||||
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s);
|
||||
|
||||
/* Multiple domains sometimes stuffed into option 15 "Domain Name".
|
||||
* As systemd escapes such characters, split them at \\032. */
|
||||
domains = g_strsplit(s, "\\032", 0);
|
||||
for (d = domains; *d; d++)
|
||||
nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
|
||||
}
|
||||
|
||||
default_route_metric_offset = 0;
|
||||
n_routes_static = sd_dhcp_lease_get_static_routes(lease, &routes_static);
|
||||
n_routes_classless = sd_dhcp_lease_get_classless_routes(lease, &routes_classless);
|
||||
for (is_classless = 1; is_classless >= 0; is_classless--) {
|
||||
int n_routes = (is_classless ? n_routes_classless : n_routes_static);
|
||||
sd_dhcp_route *const *routes = (is_classless ? routes_classless : routes_static);
|
||||
|
||||
if (n_routes <= 0)
|
||||
continue;
|
||||
|
||||
nm_gstring_prepare(&str);
|
||||
|
||||
for (i = 0; i < n_routes; i++) {
|
||||
char network_net_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
char gateway_str[NM_UTILS_INET_ADDRSTRLEN];
|
||||
guint8 r_plen;
|
||||
struct in_addr r_network;
|
||||
struct in_addr r_gateway;
|
||||
in_addr_t network_net;
|
||||
guint32 m;
|
||||
|
||||
if (sd_dhcp_route_get_destination(routes[i], &r_network) < 0)
|
||||
continue;
|
||||
if (sd_dhcp_route_get_destination_prefix_length(routes[i], &r_plen) < 0 || r_plen > 32)
|
||||
continue;
|
||||
if (sd_dhcp_route_get_gateway(routes[i], &r_gateway) < 0)
|
||||
continue;
|
||||
|
||||
network_net = nm_utils_ip4_address_clear_host_address(r_network.s_addr, r_plen);
|
||||
_nm_utils_inet4_ntop(network_net, network_net_str);
|
||||
_nm_utils_inet4_ntop(r_gateway.s_addr, gateway_str);
|
||||
|
||||
g_string_append_printf(nm_gstring_add_space_delimiter(str),
|
||||
"%s/%d %s",
|
||||
network_net_str,
|
||||
(int) r_plen,
|
||||
gateway_str);
|
||||
|
||||
if (!is_classless && n_routes_classless > 0) {
|
||||
/* RFC 3443: if the DHCP server returns both a Classless Static Routes
|
||||
* option and a Static Routes option, the DHCP client MUST ignore the
|
||||
* Static Routes option. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (r_plen == 0) {
|
||||
if (!is_classless) {
|
||||
/* for option 33 (static route), RFC 2132 says:
|
||||
*
|
||||
* The default route (0.0.0.0) is an illegal destination for a static
|
||||
* route. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric_offset++;
|
||||
has_router_from_classless = TRUE;
|
||||
} else
|
||||
m = 0;
|
||||
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.network = network_net,
|
||||
.plen = r_plen,
|
||||
.gateway = r_gateway.s_addr,
|
||||
.pref_src = a_address.s_addr,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
}));
|
||||
}
|
||||
|
||||
if (str->len > 0) {
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
is_classless ? NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
|
||||
: NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
|
||||
str->str);
|
||||
}
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_router(lease, &a_router);
|
||||
if (num > 0) {
|
||||
default_route_metric_offset = 0;
|
||||
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
guint32 m;
|
||||
|
||||
s = _nm_utils_inet4_ntop(a_router[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), s);
|
||||
|
||||
if (a_router[i].s_addr == 0) {
|
||||
/* silently skip 0.0.0.0 */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (has_router_from_classless) {
|
||||
/* If the DHCP server returns both a Classless Static Routes option and a
|
||||
* Router option, the DHCP client MUST ignore the Router option [RFC 3442].
|
||||
*
|
||||
* Be more lenient and ignore the Router option only if Classless Static
|
||||
* Routes contain a default gateway (as other DHCP backends do).
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if there are multiple default routes, we add them with differing
|
||||
* metrics. */
|
||||
m = default_route_metric_offset++;
|
||||
|
||||
nm_l3_config_data_add_route_4(l3cd,
|
||||
&((const NMPlatformIP4Route){
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
|
||||
.gateway = a_router[i].s_addr,
|
||||
.pref_src = a_address.s_addr,
|
||||
.table_any = TRUE,
|
||||
.table_coerced = 0,
|
||||
.metric_any = TRUE,
|
||||
.metric = m,
|
||||
}));
|
||||
}
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
|
||||
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
|
||||
nm_l3_config_data_set_mtu(l3cd, mtu);
|
||||
}
|
||||
|
||||
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
|
||||
if (num > 0) {
|
||||
nm_gstring_prepare(&str);
|
||||
for (i = 0; i < num; i++) {
|
||||
_nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str);
|
||||
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
|
||||
}
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) {
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME,
|
||||
renewal);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) {
|
||||
nm_dhcp_option_add_option_u64(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME,
|
||||
rebinding);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) {
|
||||
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
|
||||
}
|
||||
|
||||
if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
|
||||
if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
|
||||
nm_l3_config_data_set_metered(l3cd, TRUE);
|
||||
}
|
||||
|
||||
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
|
||||
if (num > 0) {
|
||||
for (i = 0; i < num; i++) {
|
||||
guint8 code = private_options[i].code;
|
||||
const guint8 *l_data = private_options[i].data;
|
||||
gsize l_data_len = private_options[i].data_len;
|
||||
char *option_string;
|
||||
|
||||
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
|
||||
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
|
||||
gs_free char *to_free = NULL;
|
||||
const char *escaped;
|
||||
|
||||
escaped =
|
||||
nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
|
||||
nm_dhcp_option_add_option(options,
|
||||
AF_INET,
|
||||
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
|
||||
escaped ?: "");
|
||||
|
||||
nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
|
||||
nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE) {
|
||||
/* nettools and dhclient parse option 249 (Microsoft Classless Static Route)
|
||||
* as fallback for routes and ignores them from private options.
|
||||
*
|
||||
* The systemd plugin does not, and for consistency with nettools we
|
||||
* also don't expose it as private option either. */
|
||||
continue;
|
||||
}
|
||||
|
||||
option_string = nm_utils_bin2hexstr_full(l_data, l_data_len, ':', FALSE, NULL);
|
||||
nm_dhcp_option_take_option(options, AF_INET, code, option_string);
|
||||
}
|
||||
}
|
||||
|
||||
nm_dhcp_option_add_requests_to_options(options, AF_INET);
|
||||
|
||||
nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
|
||||
|
||||
return g_steal_pointer(&l3cd);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
bound4_handle(NMDhcpSystemd *self, gboolean extended)
|
||||
{
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const char *iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
|
||||
nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
|
||||
sd_dhcp_lease *lease = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
|
||||
_LOGW("no lease!");
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
_LOGD("lease available");
|
||||
|
||||
l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
|
||||
iface,
|
||||
nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
|
||||
lease,
|
||||
&error);
|
||||
if (!l3cd) {
|
||||
_LOGW("%s", error->message);
|
||||
g_clear_error(&error);
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
dhcp_lease_save(lease, priv->lease_file);
|
||||
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
|
||||
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
|
||||
l3cd);
|
||||
}
|
||||
|
||||
static int
|
||||
dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
|
||||
{
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD(user_data);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
sd_dhcp_lease *lease = NULL;
|
||||
struct in_addr addr;
|
||||
int r;
|
||||
|
||||
nm_assert(priv->client4 == client);
|
||||
|
||||
_LOGD("client event %d", event);
|
||||
|
||||
switch (event) {
|
||||
case SD_DHCP_CLIENT_EVENT_EXPIRED:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_STOP:
|
||||
nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_RENEW:
|
||||
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
|
||||
bound4_handle(self, TRUE);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
|
||||
bound4_handle(self, FALSE);
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_SELECTING:
|
||||
r = sd_dhcp_client_get_lease(priv->client4, &lease);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_dhcp_lease_get_server_identifier(lease, &addr);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (nm_dhcp_client_server_id_is_rejected(NM_DHCP_CLIENT(user_data), &addr)) {
|
||||
_LOGD("server-id %s is in the reject-list, ignoring",
|
||||
nm_utils_inet_ntop(AF_INET, &addr, addr_str));
|
||||
return -ENOMSG;
|
||||
}
|
||||
break;
|
||||
case SD_DHCP_CLIENT_EVENT_TRANSIENT_FAILURE:
|
||||
break;
|
||||
default:
|
||||
_LOGW("unhandled DHCP event %d", event);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ip4_start(NMDhcpClient *client, GError **error)
|
||||
{
|
||||
nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD(client);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
|
||||
const NMDhcpClientConfig *client_config;
|
||||
gs_free char *lease_file = NULL;
|
||||
GBytes *hwaddr;
|
||||
const uint8_t *hwaddr_arr;
|
||||
gsize hwaddr_len;
|
||||
int arp_type;
|
||||
GBytes *client_id;
|
||||
gs_unref_bytes GBytes *client_id_new = NULL;
|
||||
GBytes *vendor_class_identifier;
|
||||
const uint8_t *client_id_arr;
|
||||
size_t client_id_len;
|
||||
struct in_addr last_addr = {0};
|
||||
const char *hostname;
|
||||
const char *mud_url;
|
||||
int r, i;
|
||||
GBytes *bcast_hwaddr;
|
||||
const uint8_t *bcast_hwaddr_arr;
|
||||
gsize bcast_hwaddr_len;
|
||||
|
||||
g_return_val_if_fail(!priv->client4, FALSE);
|
||||
g_return_val_if_fail(!priv->client6, FALSE);
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
||||
/* TODO: honor nm_dhcp_client_get_anycast_address() */
|
||||
|
||||
r = sd_dhcp_client_new(&sd_client, FALSE);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to create dhcp-client: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_LOGT("dhcp-client4: set " NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(sd_client));
|
||||
|
||||
r = sd_dhcp_client_attach_event(sd_client, NULL, 0);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to attach event: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
hwaddr = client_config->hwaddr;
|
||||
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|
||||
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
|
||||
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bcast_hwaddr_arr = NULL;
|
||||
bcast_hwaddr = client_config->bcast_hwaddr;
|
||||
if (bcast_hwaddr) {
|
||||
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
|
||||
if (bcast_hwaddr_len != hwaddr_len)
|
||||
bcast_hwaddr_arr = NULL;
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_mac(sd_client,
|
||||
hwaddr_arr,
|
||||
bcast_hwaddr_arr,
|
||||
hwaddr_len,
|
||||
(guint16) arp_type);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set MAC address: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_ifindex(sd_client, nm_dhcp_client_get_ifindex(client));
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set ifindex: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
nm_dhcp_utils_get_leasefile_path(AF_INET,
|
||||
"internal",
|
||||
client_config->iface,
|
||||
client_config->uuid,
|
||||
&lease_file);
|
||||
|
||||
if (client_config->v4.last_address)
|
||||
inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
|
||||
else {
|
||||
nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
|
||||
|
||||
dhcp_lease_load(&lease, lease_file);
|
||||
if (lease)
|
||||
sd_dhcp_lease_get_address(lease, &last_addr);
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_request_broadcast(sd_client, client_config->v4.request_broadcast);
|
||||
nm_assert(r >= 0);
|
||||
|
||||
if (last_addr.s_addr) {
|
||||
r = sd_dhcp_client_set_request_address(sd_client, &last_addr);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set last IPv4 address: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
client_id = client_config->client_id;
|
||||
if (!client_id) {
|
||||
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
|
||||
client_id = client_id_new;
|
||||
}
|
||||
|
||||
if (!(client_id_arr = g_bytes_get_data(client_id, &client_id_len)) || client_id_len < 2) {
|
||||
/* invalid client-ids are not expected. */
|
||||
nm_assert_not_reached();
|
||||
|
||||
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Note that we always set a client-id. In particular for infiniband that is necessary,
|
||||
* see https://tools.ietf.org/html/rfc4390#section-2.1 . */
|
||||
r = sd_dhcp_client_set_client_id(sd_client,
|
||||
client_id_arr[0],
|
||||
client_id_arr + 1,
|
||||
NM_MIN(client_id_len - 1, _NM_MAX_CLIENT_ID_LEN));
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set IPv4 client-id: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Add requested options */
|
||||
for (i = 0; i < (int) G_N_ELEMENTS(_nm_dhcp_option_dhcp4_options); i++) {
|
||||
if (_nm_dhcp_option_dhcp4_options[i].include) {
|
||||
nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255);
|
||||
r = sd_dhcp_client_set_request_option(sd_client,
|
||||
_nm_dhcp_option_dhcp4_options[i].option_num);
|
||||
nm_assert(r >= 0 || r == -EEXIST);
|
||||
}
|
||||
}
|
||||
|
||||
hostname = client_config->hostname;
|
||||
if (hostname) {
|
||||
/* FIXME: sd-dhcp decides which hostname/FQDN option to send (12 or 81)
|
||||
* only based on whether the hostname has a domain part or not. At the
|
||||
* moment there is no way to force one or another.
|
||||
*/
|
||||
r = sd_dhcp_client_set_hostname(sd_client, hostname);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mud_url = client_config->mud_url;
|
||||
if (mud_url) {
|
||||
r = sd_dhcp_client_set_mud_url(sd_client, mud_url);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP MUDURL: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
vendor_class_identifier = client_config->vendor_class_identifier;
|
||||
if (vendor_class_identifier) {
|
||||
const char *option_data;
|
||||
gsize len;
|
||||
|
||||
option_data = g_bytes_get_data(vendor_class_identifier, &len);
|
||||
nm_assert(option_data);
|
||||
nm_assert(len <= 255);
|
||||
|
||||
option_data = nm_strndup_a(300, option_data, len, NULL);
|
||||
|
||||
r = sd_dhcp_client_set_vendor_class_identifier(sd_client, option_data);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set DHCP vendor class identifier: %s");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_dhcp_client_set_callback(sd_client, dhcp_event_cb, client);
|
||||
if (r < 0) {
|
||||
nm_utils_error_set_errno(error, r, "failed to set callback: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->client4 = g_steal_pointer(&sd_client);
|
||||
|
||||
g_free(priv->lease_file);
|
||||
priv->lease_file = g_steal_pointer(&lease_file);
|
||||
|
||||
nm_dhcp_client_set_effective_client_id(client, client_id);
|
||||
|
||||
r = sd_dhcp_client_start(priv->client4);
|
||||
if (r < 0) {
|
||||
sd_dhcp_client_set_callback(priv->client4, NULL, NULL);
|
||||
nm_clear_pointer(&priv->client4, sd_dhcp_client_unref);
|
||||
nm_utils_error_set_errno(error, r, "failed to start DHCP client: %s");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NML3ConfigData *
|
||||
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
|
||||
const char *iface,
|
||||
|
|
@ -945,7 +274,6 @@ ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error)
|
|||
GBytes *duid;
|
||||
gboolean prefix_delegation;
|
||||
|
||||
g_return_val_if_fail(!priv->client4, FALSE);
|
||||
g_return_val_if_fail(!priv->client6, FALSE);
|
||||
|
||||
client_config = nm_dhcp_client_get_config(client);
|
||||
|
|
@ -1073,18 +401,13 @@ stop(NMDhcpClient *client, gboolean release)
|
|||
|
||||
NM_DHCP_CLIENT_CLASS(nm_dhcp_systemd_parent_class)->stop(client, release);
|
||||
|
||||
_LOGT("dhcp-client%d: stop %p",
|
||||
priv->client4 ? '4' : '6',
|
||||
priv->client4 ? (gpointer) priv->client4 : (gpointer) priv->client6);
|
||||
_LOGT("dhcp-client6: stop");
|
||||
|
||||
if (priv->client4) {
|
||||
sd_dhcp_client_set_callback(priv->client4, NULL, NULL);
|
||||
r = sd_dhcp_client_stop(priv->client4);
|
||||
} else if (priv->client6) {
|
||||
sd_dhcp6_client_set_callback(priv->client6, NULL, NULL);
|
||||
r = sd_dhcp6_client_stop(priv->client6);
|
||||
}
|
||||
if (!priv->client6)
|
||||
return;
|
||||
|
||||
sd_dhcp6_client_set_callback(priv->client6, NULL, NULL);
|
||||
r = sd_dhcp6_client_stop(priv->client6);
|
||||
if (r)
|
||||
_LOGW("failed to stop client (%d)", r);
|
||||
}
|
||||
|
|
@ -1102,12 +425,6 @@ dispose(GObject *object)
|
|||
|
||||
nm_clear_g_free(&priv->lease_file);
|
||||
|
||||
if (priv->client4) {
|
||||
sd_dhcp_client_stop(priv->client4);
|
||||
sd_dhcp_client_unref(priv->client4);
|
||||
priv->client4 = NULL;
|
||||
}
|
||||
|
||||
if (priv->client6) {
|
||||
sd_dhcp6_client_stop(priv->client6);
|
||||
sd_dhcp6_client_unref(priv->client6);
|
||||
|
|
@ -1125,14 +442,13 @@ nm_dhcp_systemd_class_init(NMDhcpSystemdClass *sdhcp_class)
|
|||
|
||||
object_class->dispose = dispose;
|
||||
|
||||
client_class->ip4_start = ip4_start;
|
||||
client_class->ip6_start = ip6_start;
|
||||
client_class->stop = stop;
|
||||
}
|
||||
|
||||
const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = {
|
||||
.name = "systemd",
|
||||
.get_type_4 = nm_dhcp_systemd_get_type,
|
||||
.get_type_4 = nm_dhcp_nettools_get_type,
|
||||
.get_type_6 = nm_dhcp_systemd_get_type,
|
||||
.undocumented = TRUE,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,27 +12,6 @@
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_dhcp_create(void)
|
||||
{
|
||||
sd_dhcp_client *client4 = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_dhcp_client_new(&client4, FALSE);
|
||||
g_assert(r == 0);
|
||||
g_assert(client4);
|
||||
|
||||
if (/* never true */ client4 == (gpointer) &r) {
|
||||
/* we don't want to call this, but ensure that the linker
|
||||
* includes all these symbols. */
|
||||
sd_dhcp_client_start(client4);
|
||||
}
|
||||
|
||||
sd_dhcp_client_unref(client4);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
test_lldp_create(void)
|
||||
{
|
||||
|
|
@ -261,7 +240,6 @@ main(int argc, char **argv)
|
|||
{
|
||||
nmtst_init(&argc, &argv, TRUE);
|
||||
|
||||
g_test_add_func("/systemd/dhcp/create", test_dhcp_create);
|
||||
g_test_add_func("/systemd/lldp/create", test_lldp_create);
|
||||
g_test_add_func("/systemd/sd-event", test_sd_event);
|
||||
g_test_add_func("/systemd/test_path_equal", test_path_equal);
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ libnm_systemd_core = static_library(
|
|||
'src/libsystemd/sd-id128/sd-id128.c',
|
||||
'nm-sd.c',
|
||||
'nm-sd-utils-core.c',
|
||||
'nm-sd-utils-dhcp.c',
|
||||
'sd-adapt-core/nm-sd-adapt-core.c',
|
||||
),
|
||||
include_directories: [
|
||||
|
|
|
|||
|
|
@ -1,40 +0,0 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#include "libnm-systemd-core/nm-default-systemd-core.h"
|
||||
|
||||
#include "nm-sd-utils-dhcp.h"
|
||||
|
||||
#include "sd-adapt-core/nm-sd-adapt-core.h"
|
||||
#include "src/libsystemd-network/dhcp-lease-internal.h"
|
||||
|
||||
int
|
||||
nm_sd_dhcp_lease_get_private_options(sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
g_return_val_if_fail(lease, -EINVAL);
|
||||
g_return_val_if_fail(out_options, -EINVAL);
|
||||
g_return_val_if_fail(*out_options == NULL, -EINVAL);
|
||||
|
||||
if (lease->private_options == NULL)
|
||||
return -ENODATA;
|
||||
|
||||
LIST_FOREACH(options, raw_option, lease->private_options)
|
||||
cnt++;
|
||||
|
||||
*out_options = g_new(nm_sd_dhcp_option, cnt);
|
||||
cnt = 0;
|
||||
|
||||
LIST_FOREACH(options, raw_option, lease->private_options)
|
||||
{
|
||||
(*out_options)[cnt].code = raw_option->tag;
|
||||
(*out_options)[cnt].data = raw_option->data;
|
||||
(*out_options)[cnt].data_len = raw_option->length;
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__
|
||||
#define __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__
|
||||
|
||||
#include "nm-sd.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t code;
|
||||
uint8_t data_len;
|
||||
void *data;
|
||||
} nm_sd_dhcp_option;
|
||||
|
||||
int nm_sd_dhcp_lease_get_private_options(sd_dhcp_lease *lease, nm_sd_dhcp_option **out_options);
|
||||
|
||||
#endif /* __NETWORKMANAGER_DHCP_SYSTEMD_UTILS_H__ */
|
||||
|
|
@ -108,6 +108,5 @@ nm_sd_event_attach_default(void)
|
|||
/* ensure that defines in nm-sd.h correspond to the internal defines. */
|
||||
|
||||
#include "nm-sd-adapt-core.h"
|
||||
#include "dhcp-lease-internal.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef __NM_SD_H__
|
||||
#define __NM_SD_H__
|
||||
|
||||
#include "src/systemd/sd-dhcp-client.h"
|
||||
#include "src/systemd/sd-dhcp-lease.h"
|
||||
#include "src/systemd/sd-dhcp6-client.h"
|
||||
#include "src/systemd/sd-lldp-rx.h"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue