diff options
| author | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-02-14 19:23:28 +0100 |
| commit | 2f94dba7385fd0e0ef19a06eb4a2fcf6c43d7946 (patch) | |
| tree | e2222f5577115985dd52044d2991253403cdd952 /src/core/dhcp/nm-dhcp-systemd.c | |
| parent | 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (diff) | |
New upstream version 1.35.91 upstream/1.35.91
Diffstat (limited to 'src/core/dhcp/nm-dhcp-systemd.c')
| -rw-r--r-- | src/core/dhcp/nm-dhcp-systemd.c | 513 |
1 files changed, 269 insertions, 244 deletions
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c index af1d2238..0884def3 100644 --- a/src/core/dhcp/nm-dhcp-systemd.c +++ b/src/core/dhcp/nm-dhcp-systemd.c @@ -17,6 +17,7 @@ #include "libnm-std-aux/unaligned.h" #include "nm-utils.h" +#include "nm-l3-config-data.h" #include "nm-dhcp-utils.h" #include "nm-dhcp-options.h" #include "nm-core-utils.h" @@ -46,13 +47,11 @@ static GType nm_dhcp_systemd_get_type(void); /*****************************************************************************/ typedef struct { - sd_dhcp_client * client4; + sd_dhcp_client *client4; sd_dhcp6_client *client6; - char * lease_file; + char *lease_file; guint request_count; - - bool privacy : 1; } NMDhcpSystemdPrivate; struct _NMDhcpSystemd { @@ -70,45 +69,41 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) /*****************************************************************************/ -static NMIP4Config * +static NML3ConfigData * lease_to_ip4_config(NMDedupMultiIndex *multi_idx, - const char * iface, + const char *iface, int ifindex, - sd_dhcp_lease * lease, - guint32 route_table, - guint32 route_metric, - GHashTable ** out_options, - GError ** error) + sd_dhcp_lease *lease, + GError **error) { - gs_unref_object NMIP4Config *ip4_config = 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 = NULL; - const char *const * search_domains = NULL; - guint16 mtu; - int i, num; - const void * data; - gsize data_len; - gboolean metered = FALSE; - gboolean has_router_from_classless = FALSE; - gboolean has_classless_route = FALSE; - gboolean has_static_route = 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_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 = NULL; + const char *const *search_domains = NULL; + guint16 mtu; + int i, num; + const void *data; + gsize data_len; + gboolean has_router_from_classless = FALSE; + gboolean has_classless_route = FALSE; + gboolean has_static_route = 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); @@ -133,9 +128,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, return NULL; } - ip4_config = nm_ip4_config_new(multi_idx, ifindex); + l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP); - options = out_options ? nm_dhcp_option_create_options_dict() : NULL; + 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); @@ -160,16 +155,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str); } - nm_ip4_config_add_address(ip4_config, - &((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, - })); + 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); @@ -193,7 +188,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, * See https://github.com/systemd/systemd/issues/4524. */ continue; } - nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr); + nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr); } nm_dhcp_option_add_option(options, AF_INET, @@ -206,7 +201,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_gstring_prepare(&str); for (i = 0; i < num; i++) { g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]); - nm_ip4_config_add_search(ip4_config, search_domains[i]); + nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]); } nm_dhcp_option_add_option(options, AF_INET, @@ -216,7 +211,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, if (sd_dhcp_lease_get_domainname(lease, &s) >= 0) { gs_strfreev char **domains = NULL; - char ** d; + char **d; nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, s); @@ -224,7 +219,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, * As systemd escapes such characters, split them at \\032. */ domains = g_strsplit(s, "\\032", 0); for (d = domains; *d; d++) - nm_ip4_config_add_domain(ip4_config, *d); + nm_l3_config_data_add_domain(l3cd, AF_INET, *d); } if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) { @@ -233,9 +228,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, num = sd_dhcp_lease_get_routes(lease, &routes); if (num > 0) { - nm_auto_free_gstring GString *str_classless = NULL; - nm_auto_free_gstring GString *str_static = NULL; - guint32 default_route_metric = route_metric; + nm_auto_free_gstring GString *str_classless = NULL; + nm_auto_free_gstring GString *str_static = NULL; + guint32 default_route_metric_offset = 0; for (i = 0; i < num; i++) { switch (sd_dhcp_route_get_option(routes[i])) { @@ -307,25 +302,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, if (r_plen == 0) { /* if there are multiple default routes, we add them with differing * metrics. */ - m = default_route_metric; - if (default_route_metric < G_MAXUINT32) - default_route_metric++; - + m = default_route_metric_offset++; has_router_from_classless = TRUE; } else - m = route_metric; - - nm_ip4_config_add_route( - ip4_config, - &((const NMPlatformIP4Route){ - .network = network_net, - .plen = r_plen, - .gateway = r_gateway.s_addr, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .metric = m, - .table_coerced = nm_platform_route_table_coerce(route_table), - }), - NULL); + m = 0; + + nm_l3_config_data_add_route_4(l3cd, + &((const NMPlatformIP4Route){ + .network = network_net, + .plen = r_plen, + .gateway = r_gateway.s_addr, + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .metric_any = TRUE, + .metric = m, + .table_any = TRUE, + .table_coerced = 0, + })); } if (str_classless && str_classless->len > 0) @@ -342,7 +334,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, num = sd_dhcp_lease_get_router(lease, &a_router); if (num > 0) { - guint32 default_route_metric = route_metric; + guint32 default_route_metric_offset = 0; nm_gstring_prepare(&str); for (i = 0; i < num; i++) { @@ -368,26 +360,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, /* if there are multiple default routes, we add them with differing * metrics. */ - m = default_route_metric; - if (default_route_metric < G_MAXUINT32) - default_route_metric++; - - nm_ip4_config_add_route( - ip4_config, - &((const NMPlatformIP4Route){ - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .gateway = a_router[i].s_addr, - .table_coerced = nm_platform_route_table_coerce(route_table), - .metric = m, - }), - NULL); + 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, + .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_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); + nm_l3_config_data_set_mtu(l3cd, mtu); } num = sd_dhcp_lease_get_ntp(lease, &addr_list); @@ -422,9 +412,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, 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) - metered = !!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")); - nm_ip4_config_set_metered(ip4_config, metered); + 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) { @@ -432,16 +423,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, 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; + 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)) { - nm_dhcp_option_add_option_utf8safe_escape( - options, - AF_INET, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - l_data, - 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; } @@ -458,8 +455,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, nm_dhcp_option_take_option(options, AF_INET, code, option_string); } } - NM_SET_OUT(out_options, g_steal_pointer(&options)); - return g_steal_pointer(&ip4_config); + + 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); } /*****************************************************************************/ @@ -467,52 +468,46 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx, 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)); - gs_unref_object NMIP4Config *ip4_config = NULL; - gs_unref_hashtable GHashTable *options = NULL; - sd_dhcp_lease * lease = NULL; - GError * error = NULL; + 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, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL); return; } _LOGD("lease available"); - ip4_config = 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, - nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)), - nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)), - &options, - &error); - if (!ip4_config) { + 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, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL); return; } - nm_dhcp_option_add_requests_to_options(options, AF_INET); 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, - NM_IP_CONFIG_CAST(ip4_config), - options); + l3cd); } static int dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) { - NMDhcpSystemd * self = NM_DHCP_SYSTEMD(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; + sd_dhcp_lease *lease = NULL; struct in_addr addr; int r; @@ -522,10 +517,10 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) switch (event) { case SD_DHCP_CLIENT_EVENT_EXPIRED: - nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL); + 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, NULL); + 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: @@ -558,32 +553,35 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) } static gboolean -ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) +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); - gs_free char * lease_file = NULL; - GBytes * hwaddr; - const uint8_t * hwaddr_arr; + 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; + 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); @@ -600,7 +598,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) return FALSE; } - hwaddr = nm_dhcp_client_get_hw_addr(client); + 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"); @@ -608,7 +606,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) } bcast_hwaddr_arr = NULL; - if ((bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self)))) { + 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; @@ -632,12 +631,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) nm_dhcp_utils_get_leasefile_path(AF_INET, "internal", - nm_dhcp_client_get_iface(client), - nm_dhcp_client_get_uuid(client), + client_config->iface, + client_config->uuid, &lease_file); - if (last_ip4_address) - inet_pton(AF_INET, last_ip4_address, &last_addr); + 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; @@ -646,9 +645,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) sd_dhcp_lease_get_address(lease, &last_addr); } - r = sd_dhcp_client_set_request_broadcast(sd_client, - NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), - NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)); + r = sd_dhcp_client_set_request_broadcast(sd_client, client_config->v4.request_broadcast); nm_assert(r >= 0); if (last_addr.s_addr) { @@ -659,7 +656,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) } } - client_id = nm_dhcp_client_get_client_id(client); + 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; @@ -694,7 +691,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) } } - hostname = nm_dhcp_client_get_hostname(client); + 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 @@ -707,7 +704,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) } } - mud_url = nm_dhcp_client_get_mud_url(client); + mud_url = client_config->mud_url; if (mud_url) { r = sd_dhcp_client_set_mud_url(sd_client, mud_url); if (r < 0) { @@ -716,7 +713,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) } } - vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client); + vendor_class_identifier = client_config->vendor_class_identifier; if (vendor_class_identifier) { const char *option_data; gsize len; @@ -745,7 +742,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) g_free(priv->lease_file); priv->lease_file = g_steal_pointer(&lease_file); - nm_dhcp_client_set_client_id(client, client_id); + nm_dhcp_client_set_effective_client_id(client, client_id); r = sd_dhcp_client_start(priv->client4); if (r < 0) { @@ -755,36 +752,37 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error) return FALSE; } - nm_dhcp_client_start_timeout(client); return TRUE; } -static NMIP6Config * +static NML3ConfigData * lease_to_ip6_config(NMDedupMultiIndex *multi_idx, - const char * iface, + const char *iface, int ifindex, - sd_dhcp6_lease * lease, + sd_dhcp6_lease *lease, gboolean info_only, - GHashTable ** out_options, gint32 ts, - GError ** error) + GError **error) { - gs_unref_object NMIP6Config *ip6_config = NULL; - gs_unref_hashtable GHashTable *options = NULL; - struct in6_addr tmp_addr; - const struct in6_addr * dns; - uint32_t lft_pref, lft_valid; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - char ** domains; - const char * s; - nm_auto_free_gstring GString *str = NULL; - int num, i; + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + gs_unref_hashtable GHashTable *options = NULL; + struct in6_addr tmp_addr; + const struct in6_addr *dns; + uint32_t lft_pref, lft_valid; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + char **domains; + char **ntp_fqdns; + const struct in6_addr *ntp_addrs; + const char *s; + nm_auto_free_gstring GString *str = NULL; + gboolean has_any_addresses = FALSE; + int num, i; nm_assert(lease); - ip6_config = nm_ip6_config_new(multi_idx, ifindex); + l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP); - options = out_options ? nm_dhcp_option_create_options_dict() : NULL; + options = nm_dhcp_option_create_options_dict(); sd_dhcp6_lease_reset_address_iter(lease); nm_gstring_prepare(&str); @@ -798,15 +796,19 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, .addr_source = NM_IP_CONFIG_SOURCE_DHCP, }; - nm_ip6_config_add_address(ip6_config, &address); + nm_l3_config_data_add_address_6(l3cd, &address); _nm_utils_inet6_ntop(&tmp_addr, addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str); - }; - if (str->len) + + has_any_addresses = TRUE; + } + + if (str->len) { nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str); + } - if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) { + if (!info_only && !has_any_addresses) { g_set_error_literal(error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, @@ -820,7 +822,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, for (i = 0; i < num; i++) { _nm_utils_inet6_ntop(&dns[i], addr_str); g_string_append(nm_gstring_add_space_delimiter(str), addr_str); - nm_ip6_config_add_nameserver(ip6_config, &dns[i]); + nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns[i]); } nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str); } @@ -830,7 +832,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, nm_gstring_prepare(&str); for (i = 0; i < num; i++) { g_string_append(nm_gstring_add_space_delimiter(str), domains[i]); - nm_ip6_config_add_search(ip6_config, domains[i]); + nm_l3_config_data_add_search(l3cd, AF_INET6, domains[i]); } nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str); } @@ -839,51 +841,72 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx, nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s); } - NM_SET_OUT(out_options, g_steal_pointer(&options)); - return g_steal_pointer(&ip6_config); + /* RFC 5908, section 4 states: "This option MUST include one, and only + * one, time source suboption." It is not clear why systemd chose to + * return array of addresses and FQDNs. Given there seem to be no + * technical obstacles to including multiple options, let's just + * pass on whatever systemd tells us. + */ + nm_gstring_prepare(&str); + num = sd_dhcp6_lease_get_ntp_fqdn(lease, &ntp_fqdns); + if (num > 0) { + for (i = 0; i < num; i++) { + g_string_append(nm_gstring_add_space_delimiter(str), ntp_fqdns[i]); + } + } + num = sd_dhcp6_lease_get_ntp_addrs(lease, &ntp_addrs); + if (num > 0) { + for (i = 0; i < num; i++) { + _nm_utils_inet6_ntop(&ntp_addrs[i], addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + } + } + if (str->len) { + nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NTP_SERVER, str->str); + } + + nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET6, g_steal_pointer(&options)); + + return g_steal_pointer(&l3cd); } static void bound6_handle(NMDhcpSystemd *self) { - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); - const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); - const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)); - gs_unref_object NMIP6Config *ip6_config = NULL; - gs_unref_hashtable GHashTable *options = NULL; - gs_free_error GError *error = NULL; - NMPlatformIP6Address prefix = {0}; - sd_dhcp6_lease * lease = NULL; + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); + const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); + const char *iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)); + const NMDhcpClientConfig *client_config; + nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; + gs_free_error GError *error = NULL; + NMPlatformIP6Address prefix = {0}; + sd_dhcp6_lease *lease = NULL; + + client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self)); if (sd_dhcp6_client_get_lease(priv->client6, &lease) < 0 || !lease) { _LOGW(" no lease!"); - nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL); return; } _LOGD("lease available"); - ip6_config = - lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)), - iface, - nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)), - lease, - NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)), - NM_DHCP_CLIENT_FLAGS_INFO_ONLY), - &options, - ts, - &error); - - if (!ip6_config) { + l3cd = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)), + iface, + nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)), + lease, + client_config->v6.info_only, + ts, + &error); + + if (!l3cd) { _LOGW("%s", error->message); - nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL); return; } - nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), - NM_DHCP_STATE_BOUND, - NM_IP_CONFIG_CAST(ip6_config), - options); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_BOUND, l3cd); sd_dhcp6_lease_reset_pd_prefix_iter(lease); while (!sd_dhcp6_lease_get_pd(lease, @@ -899,7 +922,7 @@ bound6_handle(NMDhcpSystemd *self) static void dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data) { - NMDhcpSystemd * self = NM_DHCP_SYSTEMD(user_data); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD(user_data); NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); nm_assert(priv->client6 == client); @@ -908,11 +931,11 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data) switch (event) { case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX: - nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL); break; case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE: case SD_DHCP6_CLIENT_EVENT_STOP: - nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL); break; case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: @@ -925,29 +948,29 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data) } static gboolean -ip6_start(NMDhcpClient * client, - const struct in6_addr * ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError ** error) +ip6_start(NMDhcpClient *client, const struct in6_addr *ll_addr, GError **error) { - NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client); - NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD(client); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); nm_auto(sd_dhcp6_client_unrefp) sd_dhcp6_client *sd_client = NULL; - const char * hostname; - const char * mud_url; + const NMDhcpClientConfig *client_config; + const char *hostname; + const char *mud_url; int r, i; - const guint8 * duid_arr; + const guint8 *duid_arr; gsize duid_len; - GBytes * duid; + 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); + /* TODO: honor nm_dhcp_client_get_anycast_address() */ - if (!(duid = nm_dhcp_client_get_client_id(client)) - || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) { + duid = nm_dhcp_client_get_effective_client_id(client); + if (!duid || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) { nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing DUID"); g_return_val_if_reached(FALSE); } @@ -960,13 +983,13 @@ ip6_start(NMDhcpClient * client, _LOGT("dhcp-client6: set %p", sd_client); - if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_INFO_ONLY)) { + if (client_config->v6.info_only) { sd_dhcp6_client_set_address_request(sd_client, 0); - if (needed_prefixes == 0) + if (client_config->v6.needed_prefixes == 0) sd_dhcp6_client_set_information_request(sd_client, 1); } - r = sd_dhcp6_client_set_iaid(sd_client, nm_dhcp_client_get_iaid(client)); + r = sd_dhcp6_client_set_iaid(sd_client, client_config->v6.iaid); if (r < 0) { nm_utils_error_set_errno(error, r, "failed to set IAID: %s"); return FALSE; @@ -1002,7 +1025,7 @@ ip6_start(NMDhcpClient * client, } } - mud_url = nm_dhcp_client_get_mud_url(client); + mud_url = client_config->mud_url; if (mud_url) { r = sd_dhcp6_client_set_request_mud_url(sd_client, mud_url); if (r < 0) { @@ -1011,16 +1034,19 @@ ip6_start(NMDhcpClient * client, } } - if (needed_prefixes > 0) { - if (needed_prefixes > 1) + prefix_delegation = FALSE; + if (client_config->v6.needed_prefixes > 0) { + if (client_config->v6.needed_prefixes > 1) { + /* FIXME: systemd-networkd API only allows to request a + * single prefix */ _LOGW("dhcp-client6: only one prefix request is supported"); - /* FIXME: systemd-networkd API only allows to request a - * single prefix */ - r = sd_dhcp6_client_set_prefix_delegation(sd_client, TRUE); - if (r < 0) { - nm_utils_error_set_errno(error, r, "failed to enable prefix delegation: %s"); - return FALSE; } + prefix_delegation = TRUE; + } + r = sd_dhcp6_client_set_prefix_delegation(sd_client, prefix_delegation); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to enable prefix delegation: %s"); + return FALSE; } r = sd_dhcp6_client_set_local_address(sd_client, ll_addr); @@ -1029,7 +1055,7 @@ ip6_start(NMDhcpClient * client, return FALSE; } - hostname = nm_dhcp_client_get_hostname(client); + hostname = client_config->hostname; r = sd_dhcp6_client_set_fqdn(sd_client, hostname); if (r < 0) { nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s"); @@ -1052,14 +1078,13 @@ ip6_start(NMDhcpClient * client, return FALSE; } - nm_dhcp_client_start_timeout(client); return TRUE; } static void stop(NMDhcpClient *client, gboolean release) { - NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client); + NMDhcpSystemd *self = NM_DHCP_SYSTEMD(client); NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); int r = 0; @@ -1113,7 +1138,7 @@ static void nm_dhcp_systemd_class_init(NMDhcpSystemdClass *sdhcp_class) { NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(sdhcp_class); - GObjectClass * object_class = G_OBJECT_CLASS(sdhcp_class); + GObjectClass *object_class = G_OBJECT_CLASS(sdhcp_class); object_class->dispose = dispose; |