diff options
| author | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
| commit | aafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch) | |
| tree | a2a9bb4d007339a0b1304540388230ccedac32bd /src/dhcp/nm-dhcp-utils.c | |
| parent | e7b44ef4c80907346ec7492a09c45277459924fc (diff) | |
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/dhcp/nm-dhcp-utils.c')
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.c | 1428 |
1 files changed, 730 insertions, 698 deletions
diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index 1c305238..bf10e2b5 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -21,690 +21,702 @@ /*****************************************************************************/ static gboolean -ip4_process_dhcpcd_rfc3442_routes (const char *iface, - const char *str, - guint32 route_table, - guint32 route_metric, - NMIP4Config *ip4_config, - guint32 *gwaddr) +ip4_process_dhcpcd_rfc3442_routes(const char * iface, + const char * str, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - char **routes, **r; - gboolean have_routes = FALSE; - - routes = g_strsplit (str, " ", 0); - if (g_strv_length (routes) == 0) - goto out; - - if ((g_strv_length (routes) % 2) != 0) { - _LOG2W (LOGD_DHCP4, iface, " classless static routes provided, but invalid"); - goto out; - } - - for (r = routes; *r; r += 2) { - char *slash; - NMPlatformIP4Route route; - int rt_cidr = 32; - guint32 rt_addr, rt_route; - - slash = strchr(*r, '/'); - if (slash) { - *slash = '\0'; - errno = 0; - rt_cidr = strtol (slash + 1, NULL, 10); - if (errno || rt_cidr > 32) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route cidr: '%s'", slash + 1); - continue; - } - } - if (inet_pton (AF_INET, *r, &rt_addr) <= 0) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route address: '%s'", *r); - continue; - } - if (inet_pton (AF_INET, *(r + 1), &rt_route) <= 0) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route gateway: '%s'", *(r + 1)); - continue; - } - - have_routes = TRUE; - if (rt_cidr == 0 && rt_addr == 0) { - /* FIXME: how to handle multiple routers? */ - *gwaddr = rt_route; - } else { - _LOG2I (LOGD_DHCP4, iface, " classless static route %s/%d gw %s", *r, rt_cidr, *(r + 1)); - memset (&route, 0, sizeof (route)); - route.network = nm_utils_ip4_address_clear_host_address (rt_addr, rt_cidr); - route.plen = rt_cidr; - route.gateway = rt_route; - route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; - route.metric = route_metric; - route.table_coerced = nm_platform_route_table_coerce (route_table); - nm_ip4_config_add_route (ip4_config, &route, NULL); - } - } - -out: - g_strfreev (routes); - return have_routes; + gs_free const char **routes = NULL; + const char ** r; + gboolean have_routes = FALSE; + + routes = nm_utils_strsplit_set(str, " "); + if (!routes) + return FALSE; + + if ((NM_PTRARRAY_LEN(routes) % 2) != 0) { + _LOG2W(LOGD_DHCP4, iface, " classless static routes provided, but invalid"); + return FALSE; + } + + for (r = routes; *r; r += 2) { + char * slash; + NMPlatformIP4Route route; + int rt_cidr = 32; + guint32 rt_addr, rt_route; + + slash = strchr(*r, '/'); + if (slash) { + *slash = '\0'; + errno = 0; + rt_cidr = strtol(slash + 1, NULL, 10); + if (errno || rt_cidr > 32) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route cidr: '%s'", + slash + 1); + continue; + } + } + if (inet_pton(AF_INET, *r, &rt_addr) <= 0) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route address: '%s'", + *r); + continue; + } + if (inet_pton(AF_INET, *(r + 1), &rt_route) <= 0) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route gateway: '%s'", + *(r + 1)); + continue; + } + + have_routes = TRUE; + if (rt_cidr == 0 && rt_addr == 0) { + /* FIXME: how to handle multiple routers? */ + *gwaddr = rt_route; + } else { + _LOG2I(LOGD_DHCP4, + iface, + " classless static route %s/%d gw %s", + *r, + rt_cidr, + *(r + 1)); + memset(&route, 0, sizeof(route)); + route.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr); + route.plen = rt_cidr; + route.gateway = rt_route; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; + route.metric = route_metric; + route.table_coerced = nm_platform_route_table_coerce(route_table); + nm_ip4_config_add_route(ip4_config, &route, NULL); + } + } + + return have_routes; } static gboolean -process_dhclient_rfc3442_route (const char *const**p_octets, - NMPlatformIP4Route *route) +process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route *route) { - const char *const*o = *p_octets; - gs_free char *next_hop = NULL; - int addr_len; - int v_plen; - in_addr_t tmp_addr; - in_addr_t v_network = 0; - - v_plen = _nm_utils_ascii_str_to_int64 (*o, 10, 0, 32, -1); - if (v_plen == -1) - return FALSE; - o++; - - addr_len = v_plen > 0 - ? ((v_plen - 1) / 8) + 1 - : 0; - - /* ensure there's at least the address + next hop left */ - if (NM_PTRARRAY_LEN (o) < addr_len + 4) - return FALSE; - - if (v_plen > 0) { - const char *addr[4] = { "0", "0", "0", "0" }; - gs_free char *str_addr = NULL; - int i; - - for (i = 0; i < addr_len; i++) - addr[i] = *o++; - - str_addr = g_strjoin (".", addr[0], addr[1], addr[2], addr[3], NULL); - if (inet_pton (AF_INET, str_addr, &tmp_addr) <= 0) - return FALSE; - v_network = nm_utils_ip4_address_clear_host_address (tmp_addr, v_plen); - } - - next_hop = g_strjoin (".", o[0], o[1], o[2], o[3], NULL); - o += 4; - if (inet_pton (AF_INET, next_hop, &tmp_addr) <= 0) - return FALSE; - - *route = (NMPlatformIP4Route) { - .network = v_network, - .plen = v_plen, - .gateway = tmp_addr, - }; - *p_octets = o; - return TRUE; + const char *const *o = *p_octets; + gs_free char * next_hop = NULL; + int addr_len; + int v_plen; + in_addr_t tmp_addr; + in_addr_t v_network = 0; + + v_plen = _nm_utils_ascii_str_to_int64(*o, 10, 0, 32, -1); + if (v_plen == -1) + return FALSE; + o++; + + addr_len = v_plen > 0 ? ((v_plen - 1) / 8) + 1 : 0; + + /* ensure there's at least the address + next hop left */ + if (NM_PTRARRAY_LEN(o) < addr_len + 4) + return FALSE; + + if (v_plen > 0) { + const char * addr[4] = {"0", "0", "0", "0"}; + gs_free char *str_addr = NULL; + int i; + + for (i = 0; i < addr_len; i++) + addr[i] = *o++; + + str_addr = g_strjoin(".", addr[0], addr[1], addr[2], addr[3], NULL); + if (inet_pton(AF_INET, str_addr, &tmp_addr) <= 0) + return FALSE; + v_network = nm_utils_ip4_address_clear_host_address(tmp_addr, v_plen); + } + + next_hop = g_strjoin(".", o[0], o[1], o[2], o[3], NULL); + o += 4; + if (inet_pton(AF_INET, next_hop, &tmp_addr) <= 0) + return FALSE; + + *route = (NMPlatformIP4Route){ + .network = v_network, + .plen = v_plen, + .gateway = tmp_addr, + }; + *p_octets = o; + return TRUE; } static gboolean -ip4_process_dhclient_rfc3442_routes (const char *iface, - const char *str, - guint32 route_table, - guint32 route_metric, - NMIP4Config *ip4_config, - guint32 *gwaddr) +ip4_process_dhclient_rfc3442_routes(const char * iface, + const char * str, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - gs_free const char **octets = NULL; - const char *const*o; - gboolean have_routes = FALSE; - - octets = nm_utils_strsplit_set_with_empty (str, " ."); - if (NM_PTRARRAY_LEN (octets) < 5) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); - return FALSE; - } - - o = octets; - while (*o) { - NMPlatformIP4Route route; - - if (!process_dhclient_rfc3442_route (&o, &route)) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes"); - return have_routes; - } - - have_routes = TRUE; - if (!route.plen) { - /* gateway passed as classless static route */ - *gwaddr = route.gateway; - } else { - char b1[INET_ADDRSTRLEN]; - char b2[INET_ADDRSTRLEN]; - - /* normal route */ - route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; - route.metric = route_metric; - route.table_coerced = nm_platform_route_table_coerce (route_table); - nm_ip4_config_add_route (ip4_config, &route, NULL); - - _LOG2I (LOGD_DHCP4, iface, " classless static route %s/%d gw %s", - _nm_utils_inet4_ntop (route.network, b1), - route.plen, - _nm_utils_inet4_ntop (route.gateway, b2)); - } - } - - return have_routes; + gs_free const char **octets = NULL; + const char *const * o; + gboolean have_routes = FALSE; + + octets = nm_utils_strsplit_set_with_empty(str, " ."); + if (NM_PTRARRAY_LEN(octets) < 5) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); + return FALSE; + } + + o = octets; + while (*o) { + NMPlatformIP4Route route; + + if (!process_dhclient_rfc3442_route(&o, &route)) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes"); + return have_routes; + } + + have_routes = TRUE; + if (!route.plen) { + /* gateway passed as classless static route */ + *gwaddr = route.gateway; + } else { + char b1[INET_ADDRSTRLEN]; + char b2[INET_ADDRSTRLEN]; + + /* normal route */ + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; + route.metric = route_metric; + route.table_coerced = nm_platform_route_table_coerce(route_table); + nm_ip4_config_add_route(ip4_config, &route, NULL); + + _LOG2I(LOGD_DHCP4, + iface, + " classless static route %s/%d gw %s", + _nm_utils_inet4_ntop(route.network, b1), + route.plen, + _nm_utils_inet4_ntop(route.gateway, b2)); + } + } + + return have_routes; } static gboolean -ip4_process_classless_routes (const char *iface, - GHashTable *options, - guint32 route_table, - guint32 route_metric, - NMIP4Config *ip4_config, - guint32 *gwaddr) +ip4_process_classless_routes(const char * iface, + GHashTable * options, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - const char *str, *p; - - g_return_val_if_fail (options != NULL, FALSE); - g_return_val_if_fail (ip4_config != NULL, FALSE); - - *gwaddr = 0; - - /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a - * slightly different format: - * - * option classless-static-routes = array of (destination-descriptor ip-address); - * - * which results in: - * - * 0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6 - * - * dhcpcd supports classless static routes natively and uses this same - * option identifier with the following format: - * - * 192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41 - */ - str = g_hash_table_lookup (options, "classless_static_routes"); - - /* dhclient doesn't have actual support for rfc3442 classless static routes - * upstream. Thus, people resort to defining the option in dhclient.conf - * and using arbitrary formats like so: - * - * option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; - * - * See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html - */ - if (!str) - str = g_hash_table_lookup (options, "rfc3442_classless_static_routes"); - - /* Microsoft version; same as rfc3442 but with a different option # (249) */ - if (!str) - str = g_hash_table_lookup (options, "ms_classless_static_routes"); - - if (!str || !strlen (str)) - return FALSE; - - p = str; - while (*p) { - if (!g_ascii_isdigit (*p) && (*p != ' ') && (*p != '.') && (*p != '/')) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); - return FALSE; - } - p++; - }; - - if (strchr (str, '/')) { - /* dhcpcd format */ - return ip4_process_dhcpcd_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr); - } - - return ip4_process_dhclient_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr); + const char *str, *p; + + g_return_val_if_fail(options != NULL, FALSE); + g_return_val_if_fail(ip4_config != NULL, FALSE); + + *gwaddr = 0; + + /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a + * slightly different format: + * + * option classless-static-routes = array of (destination-descriptor ip-address); + * + * which results in: + * + * 0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6 + * + * dhcpcd supports classless static routes natively and uses this same + * option identifier with the following format: + * + * 192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41 + */ + str = g_hash_table_lookup(options, "classless_static_routes"); + + /* dhclient doesn't have actual support for rfc3442 classless static routes + * upstream. Thus, people resort to defining the option in dhclient.conf + * and using arbitrary formats like so: + * + * option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; + * + * See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html + */ + if (!str) + str = g_hash_table_lookup(options, "rfc3442_classless_static_routes"); + + /* Microsoft version; same as rfc3442 but with a different option # (249) */ + if (!str) + str = g_hash_table_lookup(options, "ms_classless_static_routes"); + + if (!str || !strlen(str)) + return FALSE; + + p = str; + while (*p) { + if (!g_ascii_isdigit(*p) && (*p != ' ') && (*p != '.') && (*p != '/')) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); + return FALSE; + } + p++; + }; + + if (strchr(str, '/')) { + /* dhcpcd format */ + return ip4_process_dhcpcd_rfc3442_routes(iface, + str, + route_table, + route_metric, + ip4_config, + gwaddr); + } + + return ip4_process_dhclient_rfc3442_routes(iface, + str, + route_table, + route_metric, + ip4_config, + gwaddr); } static void -process_classful_routes (const char *iface, - GHashTable *options, - guint32 route_table, - guint32 route_metric, - NMIP4Config *ip4_config) +process_classful_routes(const char * iface, + GHashTable * options, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config) { - const char *str; - char **searches, **s; - - str = g_hash_table_lookup (options, "static_routes"); - if (!str) - return; - - searches = g_strsplit (str, " ", 0); - if ((g_strv_length (searches) % 2)) { - _LOG2I (LOGD_DHCP, iface, " static routes provided, but invalid"); - goto out; - } - - for (s = searches; *s; s += 2) { - NMPlatformIP4Route route; - guint32 rt_addr, rt_route; - - if (inet_pton (AF_INET, *s, &rt_addr) <= 0) { - _LOG2W (LOGD_DHCP, iface, "DHCP provided invalid static route address: '%s'", *s); - continue; - } - if (inet_pton (AF_INET, *(s + 1), &rt_route) <= 0) { - _LOG2W (LOGD_DHCP, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1)); - continue; - } - - // FIXME: ensure the IP address and route are sane - - memset (&route, 0, sizeof (route)); - route.network = rt_addr; - /* RFC 2132, updated by RFC 3442: - The Static Routes option (option 33) does not provide a subnet mask - for each route - it is assumed that the subnet mask is implicit in - whatever network number is specified in each route entry */ - route.plen = _nm_utils_ip4_get_default_prefix (rt_addr); - if (rt_addr & ~_nm_utils_ip4_prefix_to_netmask (route.plen)) { - /* RFC 943: target not "this network"; using host routing */ - route.plen = 32; - } - route.gateway = rt_route; - route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; - route.metric = route_metric; - route.table_coerced = nm_platform_route_table_coerce (route_table); - - route.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen); - - nm_ip4_config_add_route (ip4_config, &route, NULL); - _LOG2I (LOGD_DHCP, iface, " static route %s", - nm_platform_ip4_route_to_string (&route, NULL, 0)); - } - -out: - g_strfreev (searches); + gs_free const char **searches = NULL; + const char ** s; + const char * str; + + str = g_hash_table_lookup(options, "static_routes"); + if (!str) + return; + + searches = nm_utils_strsplit_set(str, " "); + if (!searches) + return; + + if ((NM_PTRARRAY_LEN(searches) % 2) != 0) { + _LOG2I(LOGD_DHCP, iface, " static routes provided, but invalid"); + return; + } + + for (s = searches; *s; s += 2) { + NMPlatformIP4Route route; + guint32 rt_addr, rt_route; + + if (inet_pton(AF_INET, *s, &rt_addr) <= 0) { + _LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route address: '%s'", *s); + continue; + } + if (inet_pton(AF_INET, *(s + 1), &rt_route) <= 0) { + _LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1)); + continue; + } + + // FIXME: ensure the IP address and route are sane + + memset(&route, 0, sizeof(route)); + route.network = rt_addr; + /* RFC 2132, updated by RFC 3442: + * The Static Routes option (option 33) does not provide a subnet mask + * for each route - it is assumed that the subnet mask is implicit in + * whatever network number is specified in each route entry */ + route.plen = _nm_utils_ip4_get_default_prefix(rt_addr); + if (rt_addr & ~_nm_utils_ip4_prefix_to_netmask(route.plen)) { + /* RFC 943: target not "this network"; using host routing */ + route.plen = 32; + } + route.gateway = rt_route; + route.rt_source = NM_IP_CONFIG_SOURCE_DHCP; + route.metric = route_metric; + route.table_coerced = nm_platform_route_table_coerce(route_table); + + route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen); + + nm_ip4_config_add_route(ip4_config, &route, NULL); + _LOG2I(LOGD_DHCP, + iface, + " static route %s", + nm_platform_ip4_route_to_string(&route, NULL, 0)); + } } static void -process_domain_search (const char *iface, - const char *str, - GFunc add_func, - gpointer user_data) +process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data) { - char **searches, **s; - char *unescaped, *p; - int i; - - g_return_if_fail (str != NULL); - g_return_if_fail (add_func != NULL); - - p = unescaped = g_strdup (str); - do { - p = strstr (p, "\\032"); - if (!p) - break; - - /* Clear the escaped space with real spaces */ - for (i = 0; i < 4; i++) - *p++ = ' '; - } while (*p++); - - if (strchr (unescaped, '\\')) { - _LOG2W (LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped); - goto out; - } - - searches = g_strsplit (unescaped, " ", 0); - for (s = searches; *s; s++) { - if (strlen (*s)) { - _LOG2I (LOGD_DHCP, iface, " domain search '%s'", *s); - add_func (*s, user_data); - } - } - g_strfreev (searches); - -out: - g_free (unescaped); + gs_free const char **searches = NULL; + gs_free char * unescaped = NULL; + const char ** s; + char * p; + int i; + + g_return_if_fail(str != NULL); + g_return_if_fail(add_func != NULL); + + unescaped = g_strdup(str); + + p = unescaped; + do { + p = strstr(p, "\\032"); + if (!p) + break; + + /* Clear the escaped space with real spaces */ + for (i = 0; i < 4; i++) + *p++ = ' '; + } while (*p++); + + if (strchr(unescaped, '\\')) { + _LOG2W(LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped); + return; + } + + searches = nm_utils_strsplit_set(unescaped, " "); + for (s = searches; searches && *s; s++) { + _LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s); + add_func((gpointer) *s, user_data); + } } static void -ip4_add_domain_search (gpointer data, gpointer user_data) +ip4_add_domain_search(gpointer data, gpointer user_data) { - nm_ip4_config_add_search (NM_IP4_CONFIG (user_data), (const char *) data); + nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data); } NMIP4Config * -nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx, - int ifindex, - const char *iface, - GHashTable *options, - guint32 route_table, - guint32 route_metric) +nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, + int ifindex, + const char * iface, + GHashTable * options, + guint32 route_table, + guint32 route_metric) { - NMIP4Config *ip4_config = NULL; - guint32 tmp_addr; - in_addr_t addr; - NMPlatformIP4Address address; - char *str = NULL; - gboolean gateway_has = FALSE; - guint32 gateway = 0; - guint8 plen = 0; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - - g_return_val_if_fail (options != NULL, NULL); - - ip4_config = nm_ip4_config_new (multi_idx, ifindex); - memset (&address, 0, sizeof (address)); - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - - str = g_hash_table_lookup (options, "ip_address"); - if (str && (inet_pton (AF_INET, str, &addr) > 0)) - _LOG2I (LOGD_DHCP4, iface, " address %s", str); - else - goto error; - - str = g_hash_table_lookup (options, "subnet_mask"); - if (str && (inet_pton (AF_INET, str, &tmp_addr) > 0)) { - plen = nm_utils_ip4_netmask_to_prefix (tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " plen %d (%s)", plen, str); - } else { - /* Get default netmask for the IP according to appropriate class. */ - plen = _nm_utils_ip4_get_default_prefix (addr); - _LOG2I (LOGD_DHCP4, iface, " plen %d (default)", plen); - } - nm_platform_ip4_address_set_addr (&address, addr, plen); - - /* Routes: if the server returns classless static routes, we MUST ignore - * the 'static_routes' option. - */ - if (!ip4_process_classless_routes (iface, options, route_table, route_metric, ip4_config, &gateway)) - process_classful_routes (iface, options, route_table, route_metric, ip4_config); - - if (gateway) { - _LOG2I (LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop (gateway, sbuf)); - gateway_has = TRUE; - } else { - /* If the gateway wasn't provided as a classless static route with a - * subnet length of 0, try to find it using the old-style 'routers' option. - */ - str = g_hash_table_lookup (options, "routers"); - if (str) { - char **routers = g_strsplit (str, " ", 0); - char **s; - - for (s = routers; *s; s++) { - /* FIXME: how to handle multiple routers? */ - if (inet_pton (AF_INET, *s, &gateway) > 0) { - _LOG2I (LOGD_DHCP4, iface, " gateway %s", *s); - gateway_has = TRUE; - break; - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s); - } - g_strfreev (routers); - } - } - - if (gateway_has) { - const NMPlatformIP4Route r = { - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .gateway = gateway, - .table_coerced = nm_platform_route_table_coerce (route_table), - .metric = route_metric, - }; - - nm_ip4_config_add_route (ip4_config, &r, NULL); - } - - str = g_hash_table_lookup (options, "dhcp_lease_time"); - if (str) { - address.lifetime = address.preferred = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP4, iface, " lease time %u", address.lifetime); - } - - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - nm_ip4_config_add_address (ip4_config, &address); - - str = g_hash_table_lookup (options, "host_name"); - if (str) - _LOG2I (LOGD_DHCP4, iface, " hostname '%s'", str); - - str = g_hash_table_lookup (options, "domain_name_servers"); - if (str) { - char **dns = g_strsplit (str, " ", 0); - char **s; - - for (s = dns; *s; s++) { - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - if (tmp_addr) { - nm_ip4_config_add_nameserver (ip4_config, tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " nameserver '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid nameserver '%s'", *s); - } - g_strfreev (dns); - } - - str = g_hash_table_lookup (options, "domain_name"); - if (str) { - char **domains = g_strsplit (str, " ", 0); - char **s; - - for (s = domains; *s; s++) { - _LOG2I (LOGD_DHCP4, iface, " domain name '%s'", *s); - nm_ip4_config_add_domain (ip4_config, *s); - } - g_strfreev (domains); - } - - str = g_hash_table_lookup (options, "domain_search"); - if (str) - process_domain_search (iface, str, ip4_add_domain_search, ip4_config); - - str = g_hash_table_lookup (options, "netbios_name_servers"); - if (str) { - char **nbns = g_strsplit (str, " ", 0); - char **s; - - for (s = nbns; *s; s++) { - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - if (tmp_addr) { - nm_ip4_config_add_wins (ip4_config, tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " wins '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid WINS server '%s'", *s); - } - g_strfreev (nbns); - } - - str = g_hash_table_lookup (options, "interface_mtu"); - if (str) { - int int_mtu; - - errno = 0; - int_mtu = strtol (str, NULL, 10); - if (NM_IN_SET (errno, EINVAL, ERANGE)) - goto error; - - if (int_mtu > 576) - nm_ip4_config_set_mtu (ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP); - } - - str = g_hash_table_lookup (options, "nis_domain"); - if (str) { - _LOG2I (LOGD_DHCP4, iface, " NIS domain '%s'", str); - nm_ip4_config_set_nis_domain (ip4_config, str); - } - - str = g_hash_table_lookup (options, "nis_servers"); - if (str) { - char **nis = g_strsplit (str, " ", 0); - char **s; - - for (s = nis; *s; s++) { - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - if (tmp_addr) { - nm_ip4_config_add_nis_server (ip4_config, tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " nis '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid NIS server '%s'", *s); - } - g_strfreev (nis); - } - - str = g_hash_table_lookup (options, "vendor_encapsulated_options"); - nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED")); - - return ip4_config; - -error: - g_object_unref (ip4_config); - return NULL; + gs_unref_object NMIP4Config *ip4_config = NULL; + guint32 tmp_addr; + in_addr_t addr; + NMPlatformIP4Address address; + char * str = NULL; + gboolean gateway_has = FALSE; + guint32 gateway = 0; + guint8 plen = 0; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + + g_return_val_if_fail(options != NULL, NULL); + + ip4_config = nm_ip4_config_new(multi_idx, ifindex); + memset(&address, 0, sizeof(address)); + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + + str = g_hash_table_lookup(options, "ip_address"); + if (str && (inet_pton(AF_INET, str, &addr) > 0)) + _LOG2I(LOGD_DHCP4, iface, " address %s", str); + else + return NULL; + + str = g_hash_table_lookup(options, "subnet_mask"); + if (str && (inet_pton(AF_INET, str, &tmp_addr) > 0)) { + plen = nm_utils_ip4_netmask_to_prefix(tmp_addr); + _LOG2I(LOGD_DHCP4, iface, " plen %d (%s)", plen, str); + } else { + /* Get default netmask for the IP according to appropriate class. */ + plen = _nm_utils_ip4_get_default_prefix(addr); + _LOG2I(LOGD_DHCP4, iface, " plen %d (default)", plen); + } + nm_platform_ip4_address_set_addr(&address, addr, plen); + + /* Routes: if the server returns classless static routes, we MUST ignore + * the 'static_routes' option. + */ + if (!ip4_process_classless_routes(iface, + options, + route_table, + route_metric, + ip4_config, + &gateway)) + process_classful_routes(iface, options, route_table, route_metric, ip4_config); + + if (gateway) { + _LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf)); + gateway_has = TRUE; + } else { + /* If the gateway wasn't provided as a classless static route with a + * subnet length of 0, try to find it using the old-style 'routers' option. + */ + str = g_hash_table_lookup(options, "routers"); + if (str) { + gs_free const char **routers = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = routers; routers && *s; s++) { + /* FIXME: how to handle multiple routers? */ + if (inet_pton(AF_INET, *s, &gateway) > 0) { + _LOG2I(LOGD_DHCP4, iface, " gateway %s", *s); + gateway_has = TRUE; + break; + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s); + } + } + } + + if (gateway_has) { + const NMPlatformIP4Route r = { + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .gateway = gateway, + .table_coerced = nm_platform_route_table_coerce(route_table), + .metric = route_metric, + }; + + nm_ip4_config_add_route(ip4_config, &r, NULL); + } + + str = g_hash_table_lookup(options, "dhcp_lease_time"); + if (str) { + address.lifetime = address.preferred = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP4, iface, " lease time %u", address.lifetime); + } + + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + nm_ip4_config_add_address(ip4_config, &address); + + str = g_hash_table_lookup(options, "host_name"); + if (str) + _LOG2I(LOGD_DHCP4, iface, " hostname '%s'", str); + + str = g_hash_table_lookup(options, "domain_name_servers"); + if (str) { + gs_free const char **dns = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = dns; dns && *s; s++) { + if (inet_pton(AF_INET, *s, &tmp_addr) > 0) { + if (tmp_addr) { + nm_ip4_config_add_nameserver(ip4_config, tmp_addr); + _LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid nameserver '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "domain_name"); + if (str) { + gs_free const char **domains = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = domains; domains && *s; s++) { + _LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s); + nm_ip4_config_add_domain(ip4_config, *s); + } + } + + str = g_hash_table_lookup(options, "domain_search"); + if (str) + process_domain_search(iface, str, ip4_add_domain_search, ip4_config); + + str = g_hash_table_lookup(options, "netbios_name_servers"); + if (str) { + gs_free const char **nbns = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = nbns; nbns && *s; s++) { + if (inet_pton(AF_INET, *s, &tmp_addr) > 0) { + if (tmp_addr) { + nm_ip4_config_add_wins(ip4_config, tmp_addr); + _LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid WINS server '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "interface_mtu"); + if (str) { + int int_mtu; + + errno = 0; + int_mtu = strtol(str, NULL, 10); + if (NM_IN_SET(errno, EINVAL, ERANGE)) + return NULL; + + if (int_mtu > 576) + nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP); + } + + str = g_hash_table_lookup(options, "nis_domain"); + if (str) { + _LOG2I(LOGD_DHCP4, iface, " NIS domain '%s'", str); + nm_ip4_config_set_nis_domain(ip4_config, str); + } + + str = g_hash_table_lookup(options, "nis_servers"); + if (str) { + gs_free const char **nis = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = nis; nis && *s; s++) { + if (inet_pton(AF_INET, *s, &tmp_addr) > 0) { + if (tmp_addr) { + nm_ip4_config_add_nis_server(ip4_config, tmp_addr); + _LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid NIS server '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "vendor_encapsulated_options"); + nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED")); + + return g_steal_pointer(&ip4_config); } /*****************************************************************************/ static void -ip6_add_domain_search (gpointer data, gpointer user_data) +ip6_add_domain_search(gpointer data, gpointer user_data) { - nm_ip6_config_add_search (NM_IP6_CONFIG (user_data), (const char *) data); + nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data); } NMPlatformIP6Address -nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options) +nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options) { - gs_strfreev char **split_addr = NULL; - NMPlatformIP6Address address = { 0, }; - struct in6_addr tmp_addr; - char *str = NULL; - int prefix; - - g_return_val_if_fail (options != NULL, address); - - str = g_hash_table_lookup (options, "ip6_prefix"); - if (!str) - return address; - - split_addr = g_strsplit (str, "/", 2); - if (split_addr[0] == NULL && split_addr[1] == NULL) { - nm_log_warn (LOGD_DHCP6, "DHCP returned prefix without length '%s'", str); - return address; - } - - if (!inet_pton (AF_INET6, split_addr[0], &tmp_addr)) { - nm_log_warn (LOGD_DHCP6, "DHCP returned invalid prefix '%s'", str); - return address; - } - - prefix = _nm_utils_ascii_str_to_int64 (split_addr[1], 10, 0, 128, -1); - if (prefix < 0) { - nm_log_warn (LOGD_DHCP6, "DHCP returned prefix with invalid length '%s'", str); - return address; - } - - address.address = tmp_addr; - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - address.plen = prefix; - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - - str = g_hash_table_lookup (options, "max_life"); - if (str) - address.lifetime = strtoul (str, NULL, 10); - - str = g_hash_table_lookup (options, "preferred_life"); - if (str) - address.preferred = strtoul (str, NULL, 10); - - return address; + gs_strfreev char ** split_addr = NULL; + NMPlatformIP6Address address = { + 0, + }; + struct in6_addr tmp_addr; + char * str = NULL; + int prefix; + + g_return_val_if_fail(options != NULL, address); + + str = g_hash_table_lookup(options, "ip6_prefix"); + if (!str) + return address; + + split_addr = g_strsplit(str, "/", 2); + if (split_addr[0] == NULL && split_addr[1] == NULL) { + nm_log_warn(LOGD_DHCP6, "DHCP returned prefix without length '%s'", str); + return address; + } + + if (!inet_pton(AF_INET6, split_addr[0], &tmp_addr)) { + nm_log_warn(LOGD_DHCP6, "DHCP returned invalid prefix '%s'", str); + return address; + } + + prefix = _nm_utils_ascii_str_to_int64(split_addr[1], 10, 0, 128, -1); + if (prefix < 0) { + nm_log_warn(LOGD_DHCP6, "DHCP returned prefix with invalid length '%s'", str); + return address; + } + + address.address = tmp_addr; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + address.plen = prefix; + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + + str = g_hash_table_lookup(options, "max_life"); + if (str) + address.lifetime = strtoul(str, NULL, 10); + + str = g_hash_table_lookup(options, "preferred_life"); + if (str) + address.preferred = strtoul(str, NULL, 10); + + return address; } NMIP6Config * -nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx, - int ifindex, - const char *iface, - GHashTable *options, - gboolean info_only) +nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx, + int ifindex, + const char * iface, + GHashTable * options, + gboolean info_only) { - NMIP6Config *ip6_config = NULL; - struct in6_addr tmp_addr; - NMPlatformIP6Address address; - char *str = NULL; - - g_return_val_if_fail (options != NULL, NULL); - - memset (&address, 0, sizeof (address)); - address.plen = 128; - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - - ip6_config = nm_ip6_config_new (multi_idx, ifindex); - - str = g_hash_table_lookup (options, "max_life"); - if (str) { - address.lifetime = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP6, iface, " valid_lft %u", address.lifetime); - } - - str = g_hash_table_lookup (options, "preferred_life"); - if (str) { - address.preferred = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP6, iface, " preferred_lft %u", address.preferred); - } - - str = g_hash_table_lookup (options, "ip6_address"); - if (str) { - if (!inet_pton (AF_INET6, str, &tmp_addr)) { - _LOG2W (LOGD_DHCP6, iface, "(%s): DHCP returned invalid address '%s'", - iface, str); - goto error; - } - - address.address = tmp_addr; - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - nm_ip6_config_add_address (ip6_config, &address); - _LOG2I (LOGD_DHCP6, iface, " address %s", str); - } else if (info_only == FALSE) { - /* No address in Managed mode is a hard error */ - goto error; - } - - str = g_hash_table_lookup (options, "host_name"); - if (str) - _LOG2I (LOGD_DHCP6, iface, " hostname '%s'", str); - - str = g_hash_table_lookup (options, "dhcp6_name_servers"); - if (str) { - char **dns = g_strsplit (str, " ", 0); - char **s; - - for (s = dns; *s; s++) { - if (inet_pton (AF_INET6, *s, &tmp_addr) > 0) { - if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_addr)) { - nm_ip6_config_add_nameserver (ip6_config, &tmp_addr); - _LOG2I (LOGD_DHCP6, iface, " nameserver '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP6, iface, "ignoring invalid nameserver '%s'", *s); - } - g_strfreev (dns); - } - - str = g_hash_table_lookup (options, "dhcp6_domain_search"); - if (str) - process_domain_search (iface, str, ip6_add_domain_search, ip6_config); - - return ip6_config; - -error: - g_object_unref (ip6_config); - return NULL; + gs_unref_object NMIP6Config *ip6_config = NULL; + struct in6_addr tmp_addr; + NMPlatformIP6Address address; + char * str = NULL; + + g_return_val_if_fail(options != NULL, NULL); + + memset(&address, 0, sizeof(address)); + address.plen = 128; + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + + ip6_config = nm_ip6_config_new(multi_idx, ifindex); + + str = g_hash_table_lookup(options, "max_life"); + if (str) { + address.lifetime = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP6, iface, " valid_lft %u", address.lifetime); + } + + str = g_hash_table_lookup(options, "preferred_life"); + if (str) { + address.preferred = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP6, iface, " preferred_lft %u", address.preferred); + } + + str = g_hash_table_lookup(options, "ip6_address"); + if (str) { + if (!inet_pton(AF_INET6, str, &tmp_addr)) { + _LOG2W(LOGD_DHCP6, iface, "(%s): DHCP returned invalid address '%s'", iface, str); + return NULL; + } + + address.address = tmp_addr; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + nm_ip6_config_add_address(ip6_config, &address); + _LOG2I(LOGD_DHCP6, iface, " address %s", str); + } else if (info_only == FALSE) { + /* No address in Managed mode is a hard error */ + return NULL; + } + + str = g_hash_table_lookup(options, "host_name"); + if (str) + _LOG2I(LOGD_DHCP6, iface, " hostname '%s'", str); + + str = g_hash_table_lookup(options, "dhcp6_name_servers"); + if (str) { + gs_free const char **dns = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = dns; dns && *s; s++) { + if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) { + if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) { + nm_ip6_config_add_nameserver(ip6_config, &tmp_addr); + _LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP6, iface, "ignoring invalid nameserver '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "dhcp6_domain_search"); + if (str) + process_domain_search(iface, str, ip6_add_domain_search, ip6_config); + + return g_steal_pointer(&ip6_config); } char * -nm_dhcp_utils_duid_to_string (GBytes *duid) +nm_dhcp_utils_duid_to_string(GBytes *duid) { - gconstpointer data; - gsize len; + gconstpointer data; + gsize len; - g_return_val_if_fail (duid, NULL); + g_return_val_if_fail(duid, NULL); - data = g_bytes_get_data (duid, &len); - return nm_utils_bin2hexstr_full (data, len, ':', FALSE, NULL); + data = g_bytes_get_data(duid, &len); + return nm_utils_bin2hexstr_full(data, len, ':', FALSE, NULL); } /** @@ -720,34 +732,34 @@ nm_dhcp_utils_duid_to_string (GBytes *duid) * to the DHCP server. */ GBytes * -nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) +nm_dhcp_utils_client_id_string_to_bytes(const char *client_id) { - GBytes *bytes = NULL; - guint len; - char *c; - - g_return_val_if_fail (client_id && client_id[0], NULL); - - /* Try as hex encoded */ - if (strchr (client_id, ':')) { - bytes = nm_utils_hexstr2bin (client_id); - - /* the result must be at least two bytes long, - * because @client_id contains a delimiter - * but nm_utils_hexstr2bin() does not allow - * leading nor trailing delimiters. */ - nm_assert (!bytes || g_bytes_get_size (bytes) >= 2); - } - if (!bytes) { - /* Fall back to string */ - len = strlen (client_id); - c = g_malloc (len + 1); - c[0] = 0; /* type: non-hardware address per RFC 2132 section 9.14 */ - memcpy (c + 1, client_id, len); - bytes = g_bytes_new_take (c, len + 1); - } - - return bytes; + GBytes *bytes = NULL; + guint len; + char * c; + + g_return_val_if_fail(client_id && client_id[0], NULL); + + /* Try as hex encoded */ + if (strchr(client_id, ':')) { + bytes = nm_utils_hexstr2bin(client_id); + + /* the result must be at least two bytes long, + * because @client_id contains a delimiter + * but nm_utils_hexstr2bin() does not allow + * leading nor trailing delimiters. */ + nm_assert(!bytes || g_bytes_get_size(bytes) >= 2); + } + if (!bytes) { + /* Fall back to string */ + len = strlen(client_id); + c = g_malloc(len + 1); + c[0] = 0; /* type: non-hardware address per RFC 2132 section 9.14 */ + memcpy(c + 1, client_id, len); + bytes = g_bytes_new_take(c, len + 1); + } + + return bytes; } /** @@ -765,40 +777,60 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) * Returns: TRUE if the lease file already exists, FALSE otherwise. */ gboolean -nm_dhcp_utils_get_leasefile_path (int addr_family, - const char *plugin_name, - const char *iface, - const char *uuid, - char **out_leasefile_path) +nm_dhcp_utils_get_leasefile_path(int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char ** out_leasefile_path) { - gs_free char *rundir_path = NULL; - gs_free char *statedir_path = NULL; - - rundir_path = g_strdup_printf (NMRUNDIR "/%s%s-%s-%s.lease", - plugin_name, - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { - *out_leasefile_path = g_steal_pointer (&rundir_path); - return TRUE; - } - - statedir_path = g_strdup_printf (NMSTATEDIR "/%s%s-%s-%s.lease", - plugin_name, - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (statedir_path, G_FILE_TEST_EXISTS)) { - *out_leasefile_path = g_steal_pointer (&statedir_path); - return TRUE; - } - - if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) - *out_leasefile_path = g_steal_pointer (&rundir_path); - else - *out_leasefile_path = g_steal_pointer (&statedir_path); - return FALSE; + gs_free char *rundir_path = NULL; + gs_free char *statedir_path = NULL; + + rundir_path = g_strdup_printf(NMRUNDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test(rundir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer(&rundir_path); + return TRUE; + } + + statedir_path = g_strdup_printf(NMSTATEDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test(statedir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer(&statedir_path); + return TRUE; + } + + if (nm_config_get_configure_and_quit(nm_config_get()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) + *out_leasefile_path = g_steal_pointer(&rundir_path); + else + *out_leasefile_path = g_steal_pointer(&statedir_path); + return FALSE; +} + +char * +nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease) +{ + const char *start; + const char *iaid; + + if (!lease) + return NULL; + + iaid = g_hash_table_lookup(lease, "iaid"); + if (!iaid) + return NULL; + + start = g_hash_table_lookup(lease, "life_starts"); + if (!start) + return NULL; + + return g_strdup_printf("%s|%s", iaid, start); } |