summaryrefslogtreecommitdiff
path: root/src/dhcp/nm-dhcp-nettools.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/dhcp/nm-dhcp-nettools.c')
-rw-r--r--src/dhcp/nm-dhcp-nettools.c168
1 files changed, 103 insertions, 65 deletions
diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c
index 1f183f362a..86c3311f40 100644
--- a/src/dhcp/nm-dhcp-nettools.c
+++ b/src/dhcp/nm-dhcp-nettools.c
@@ -341,24 +341,21 @@ lease_get_u16 (NDhcp4ClientLease *lease,
return TRUE;
}
-#define LOG_LEASE(domain, ...) \
- G_STMT_START { \
- _LOG2I ((domain), (iface), " "__VA_ARGS__); \
- } G_STMT_END
-
static gboolean
lease_parse_address (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options,
GError **error)
{
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
const gint64 ts = nm_utils_get_monotonic_timestamp_ns ();
+ const gint64 ts_clock_boottime = nm_utils_monotonic_timestamp_as_boottime (ts, 1);
struct in_addr a_address;
struct in_addr a_netmask;
guint32 a_plen;
- guint64 a_lifetime;
+ guint64 nettools_lifetime;
+ gint64 a_lifetime;
+ gint64 a_expiry;
n_dhcp4_client_lease_get_yiaddr (lease, &a_address);
if (a_address.s_addr == INADDR_ANY) {
@@ -367,7 +364,29 @@ lease_parse_address (NDhcp4ClientLease *lease,
}
/* n_dhcp4_client_lease_get_lifetime() never fails */
- n_dhcp4_client_lease_get_lifetime (lease, &a_lifetime);
+ n_dhcp4_client_lease_get_lifetime (lease, &nettools_lifetime);
+ /* FIXME: n_dhcp4_client_lease_get_lifetime() returns the time in nsec of CLOCK_BOOTTIME.
+ * We want to retrieve the original lifetime value in seconds, so we approximate it in a_lifetime.
+ * Use a nettools API to retrieve the original value as passed by the server.
+ */
+ if (nettools_lifetime == G_MAXUINT64) {
+ a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
+ a_expiry = NM_PLATFORM_LIFETIME_PERMANENT;
+ } else {
+ gint64 ts_time = time (NULL);
+
+ a_lifetime = ((gint64) nettools_lifetime - ts_clock_boottime) / NM_UTILS_NS_PER_SECOND;
+ /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */
+ if (a_lifetime < 0)
+ a_lifetime = 0;
+ else if (a_lifetime > NM_PLATFORM_LIFETIME_PERMANENT)
+ a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT - 1;
+
+ if (ts_time > NM_PLATFORM_LIFETIME_PERMANENT - a_lifetime)
+ a_expiry = NM_PLATFORM_LIFETIME_PERMANENT - 1;
+ else
+ a_expiry = ts_time + a_lifetime;
+ }
if (!lease_get_in_addr (lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) {
nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get netmask from lease");
@@ -377,7 +396,6 @@ lease_parse_address (NDhcp4ClientLease *lease,
nm_utils_inet4_ntop (a_address.s_addr, addr_str);
a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr);
- LOG_LEASE (LOGD_DHCP4, "address %s/%u", addr_str, a_plen);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS,
@@ -387,12 +405,15 @@ lease_parse_address (NDhcp4ClientLease *lease,
NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
nm_utils_inet4_ntop (a_netmask.s_addr, addr_str));
- LOG_LEASE (LOGD_DHCP4, "expires in %u seconds",
- (guint) ((a_lifetime - ts)/1000000000));
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
- (guint64) (a_lifetime / 1000000000));
+ (guint64) a_lifetime);
+
+ nm_dhcp_option_add_option_u64 (options,
+ _nm_dhcp_option_dhcp4_options,
+ NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
+ (guint64) a_expiry);
nm_ip4_config_add_address (ip4_config,
&((const NMPlatformIP4Address) {
@@ -400,9 +421,9 @@ lease_parse_address (NDhcp4ClientLease *lease,
.peer_address = a_address.s_addr,
.plen = a_plen,
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = ts / 1000000000,
- .lifetime = (a_lifetime - ts) / 1000000000,
- .preferred = (a_lifetime - ts) / 1000000000,
+ .timestamp = ts / NM_UTILS_NS_PER_SECOND,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
}));
return TRUE;
@@ -410,7 +431,6 @@ lease_parse_address (NDhcp4ClientLease *lease,
static void
lease_parse_domain_name_servers (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options)
{
@@ -441,7 +461,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease,
nm_ip4_config_add_nameserver (ip4_config, addr.s_addr);
}
- LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
@@ -450,7 +469,6 @@ lease_parse_domain_name_servers (NDhcp4ClientLease *lease,
static void
lease_parse_routes (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options,
guint32 route_table,
@@ -480,11 +498,6 @@ lease_parse_routes (NDhcp4ClientLease *lease,
nm_utils_inet4_ntop (dest.s_addr, dest_str);
nm_utils_inet4_ntop (gateway.s_addr, gateway_str);
- LOG_LEASE (LOGD_DHCP4,
- "classless static route %s/%d gw %s",
- dest_str,
- (int) plen,
- gateway_str);
g_string_append_printf (nm_gstring_add_space_delimiter (str),
"%s/%d %s",
dest_str,
@@ -529,11 +542,6 @@ lease_parse_routes (NDhcp4ClientLease *lease,
nm_utils_inet4_ntop (dest.s_addr, dest_str);
nm_utils_inet4_ntop (gateway.s_addr, gateway_str);
- LOG_LEASE (LOGD_DHCP4,
- "static route %s/%d gw %s",
- dest_str,
- (int) plen,
- gateway_str);
g_string_append_printf (nm_gstring_add_space_delimiter (str),
"%s/%d %s",
dest_str,
@@ -610,7 +618,6 @@ lease_parse_routes (NDhcp4ClientLease *lease,
}),
NULL);
}
- LOG_LEASE (LOGD_DHCP4, "router %s", str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_ROUTER,
@@ -620,7 +627,6 @@ lease_parse_routes (NDhcp4ClientLease *lease,
static void
lease_parse_mtu (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options)
{
@@ -632,7 +638,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease,
if (mtu < 68)
return;
- LOG_LEASE (LOGD_DHCP4, "mtu %u", mtu);
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU,
@@ -642,7 +647,6 @@ lease_parse_mtu (NDhcp4ClientLease *lease,
static void
lease_parse_metered (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options)
{
@@ -658,13 +662,12 @@ lease_parse_metered (NDhcp4ClientLease *lease,
metered = !!memmem (data, n_data, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED"));
}
- LOG_LEASE (LOGD_DHCP4, "%s", metered ? "metered" : "unmetered");
+ /* TODO: expose the vendor specific option when present */
nm_ip4_config_set_metered (ip4_config, metered);
}
static void
lease_parse_ntps (NDhcp4ClientLease *lease,
- const char *iface,
GHashTable *options)
{
nm_auto_free_gstring GString *str = NULL;
@@ -685,13 +688,14 @@ lease_parse_ntps (NDhcp4ClientLease *lease,
g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
}
- LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", str->str);
- nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NTP_SERVER, str->str);
+ nm_dhcp_option_add_option (options,
+ _nm_dhcp_option_dhcp4_options,
+ NM_DHCP_OPTION_DHCP4_NTP_SERVER,
+ str->str);
}
static void
lease_parse_hostname (NDhcp4ClientLease *lease,
- const char *iface,
GHashTable *options)
{
nm_auto_free_gstring GString *str = NULL;
@@ -708,13 +712,14 @@ lease_parse_hostname (NDhcp4ClientLease *lease,
if (is_localhost(str->str))
return;
- LOG_LEASE (LOGD_DHCP4, "hostname '%s'", str->str);
- nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, str->str);
+ nm_dhcp_option_add_option (options,
+ _nm_dhcp_option_dhcp4_options,
+ NM_DHCP_OPTION_DHCP4_HOST_NAME,
+ str->str);
}
static void
lease_parse_domainname (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options)
{
@@ -741,13 +746,14 @@ lease_parse_domainname (NDhcp4ClientLease *lease,
g_string_append (nm_gstring_add_space_delimiter (str), *d);
nm_ip4_config_add_domain (ip4_config, *d);
}
- LOG_LEASE (LOGD_DHCP4, "domain name '%s'", str->str);
- nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, str->str);
+ nm_dhcp_option_add_option (options,
+ _nm_dhcp_option_dhcp4_options,
+ NM_DHCP_OPTION_DHCP4_DOMAIN_NAME,
+ str->str);
}
static void
lease_parse_search_domains (NDhcp4ClientLease *lease,
- const char *iface,
NMIP4Config *ip4_config,
GHashTable *options)
{
@@ -775,7 +781,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease,
g_string_append (nm_gstring_add_space_delimiter (str), domain->str);
nm_ip4_config_add_search (ip4_config, domain->str);
}
- LOG_LEASE (LOGD_DHCP4, "domain search '%s'", str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST,
@@ -784,7 +789,6 @@ lease_parse_search_domains (NDhcp4ClientLease *lease,
static void
lease_parse_root_path (NDhcp4ClientLease *lease,
- const char *iface,
GHashTable *options)
{
nm_auto_free_gstring GString *str = NULL;
@@ -797,16 +801,17 @@ lease_parse_root_path (NDhcp4ClientLease *lease,
return;
str = g_string_new_len ((char *)data, n_data);
- LOG_LEASE (LOGD_DHCP4, "root path '%s'", str->str);
- nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, str->str);
+ nm_dhcp_option_add_option (options,
+ _nm_dhcp_option_dhcp4_options,
+ NM_DHCP_OPTION_DHCP4_ROOT_PATH,
+ str->str);
}
static void
lease_parse_wpad (NDhcp4ClientLease *lease,
- const char *iface,
GHashTable *options)
{
- nm_auto_free_gstring GString *str = NULL;
+ gs_free char *wpad = NULL;
uint8_t *data;
size_t n_data;
int r;
@@ -815,12 +820,44 @@ lease_parse_wpad (NDhcp4ClientLease *lease,
if (r)
return;
- str = g_string_new_len ((char *)data, n_data);
- LOG_LEASE (LOGD_DHCP4, "wpad '%s'", str->str);
+ nm_utils_buf_utf8safe_escape ((char *)data, n_data, 0, &wpad);
+ if (wpad == NULL)
+ wpad = g_strndup ((char *)data, n_data);
+
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- str->str);
+ wpad);
+}
+
+static void
+lease_parse_private_options (NDhcp4ClientLease *lease,
+ GHashTable *options)
+{
+ int i;
+
+ for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) {
+ gs_free char *option_string = NULL;
+ guint8 *data;
+ gsize n_data;
+ int r;
+
+ /* We manage private options 249 (private classless static route) and 252 (wpad) in a special
+ * way, so skip them as we here just manage all (the other) private options as raw data */
+ if (NM_IN_SET (i, NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE,
+ NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY))
+ continue;
+
+ r = n_dhcp4_client_lease_query (lease, i, &data, &n_data);
+ if (r)
+ continue;
+
+ option_string = nm_utils_bin2hexstr_full (data, n_data, ':', FALSE, NULL);
+ nm_dhcp_option_take_option (options,
+ _nm_dhcp_option_dhcp4_options,
+ i,
+ g_steal_pointer (&option_string));
+ }
}
static NMIP4Config *
@@ -839,22 +876,23 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
g_return_val_if_fail (lease != NULL, NULL);
ip4_config = nm_ip4_config_new (multi_idx, ifindex);
- options = out_options ? nm_dhcp_option_create_options_dict () : NULL;
+ options = nm_dhcp_option_create_options_dict ();
- if (!lease_parse_address (lease, iface, ip4_config, options, error))
+ if (!lease_parse_address (lease, ip4_config, options, error))
return NULL;
- lease_parse_routes (lease, iface, ip4_config, options, route_table, route_metric);
- lease_parse_domain_name_servers (lease, iface, ip4_config, options);
- lease_parse_domainname (lease, iface, ip4_config, options);
- lease_parse_search_domains (lease, iface, ip4_config, options);
- lease_parse_mtu (lease, iface, ip4_config, options);
- lease_parse_metered (lease, iface, ip4_config, options);
-
- lease_parse_hostname (lease, iface, options);
- lease_parse_ntps (lease, iface, options);
- lease_parse_root_path (lease, iface, options);
- lease_parse_wpad (lease, iface, options);
+ lease_parse_routes (lease, ip4_config, options, route_table, route_metric);
+ lease_parse_domain_name_servers (lease, ip4_config, options);
+ lease_parse_domainname (lease, ip4_config, options);
+ lease_parse_search_domains (lease, ip4_config, options);
+ lease_parse_mtu (lease, ip4_config, options);
+ lease_parse_metered (lease, ip4_config, options);
+
+ lease_parse_hostname (lease, options);
+ lease_parse_ntps (lease, options);
+ lease_parse_root_path (lease, options);
+ lease_parse_wpad (lease, options);
+ lease_parse_private_options (lease, options);
NM_SET_OUT (out_options, g_steal_pointer (&options));
return g_steal_pointer (&ip4_config);