Francesco Giudici 2019-07-05 17:54:52 +02:00
commit 7d8f20b00e
10 changed files with 849 additions and 212 deletions

View file

@ -1836,6 +1836,8 @@ src_libnm_systemd_core_la_SOURCES = \
src/systemd/nm-sd-utils-core.h \
src/systemd/nm-sd.c \
src/systemd/nm-sd.h \
src/systemd/nm-sd-utils-dhcp.h \
src/systemd/nm-sd-utils-dhcp.c \
src/systemd/sd-adapt-core/condition.h \
src/systemd/sd-adapt-core/conf-parser.h \
src/systemd/sd-adapt-core/device-util.h \
@ -1964,6 +1966,8 @@ src_libNetworkManagerBase_la_SOURCES = \
src/dhcp/nm-dhcp-nettools.c \
src/dhcp/nm-dhcp-utils.c \
src/dhcp/nm-dhcp-utils.h \
src/dhcp/nm-dhcp-options.c \
src/dhcp/nm-dhcp-options.h \
src/dhcp/nm-dhcp-systemd.c \
src/dhcp/nm-dhcp-manager.c \
src/dhcp/nm-dhcp-manager.h \

View file

@ -381,6 +381,8 @@ construct_device_dhcp_items (GPtrArray *items, int addr_family, GVariant *dhcp_c
const char *key;
GVariant *val;
char four_or_six;
gboolean found_unknown_245 = FALSE;
gs_unref_variant GVariant *private_245_val = NULL;
if (!dhcp_config)
return;
@ -402,10 +404,43 @@ construct_device_dhcp_items (GPtrArray *items, int addr_family, GVariant *dhcp_c
four_or_six,
ucased,
g_variant_get_string (val, NULL));
/* MS Azure sends the server endpoint in the dhcp private
* option 245. cloud-init searches the Azure server endpoint
* value looking for the standard dhclient label used for
* that option, which is "unknown_245".
* The 11-dhclient script shipped with Fedora and RHEL dhcp
* package converts our dispatcher environment vars to the
* dhclient ones (new_<some_option>) and calls dhclient hook
* scripts.
* Let's make cloud-init happy and let's duplicate the dhcp
* option 245 with the legacy name of the default dhclient
* label also when using the internal client.
* Note however that the dhclient plugin will have unknown_
* labels represented as ascii string when possible, falling
* back to hex string otherwise.
* private_ labels instead are always in hex string format.
* This shouldn't affect the MS Azure server endpoint value,
* as it usually belongs to the 240.0.0.0/4 network and so
* is always represented as an hex string. Moreover, cloudinit
* code checks just for an hex value in unknown_245.
*/
if (addr_family == AF_INET) {
if (nm_streq (key, "private_245"))
private_245_val = g_variant_ref (val);
else if (nm_streq (key, "unknown_245"))
found_unknown_245 = true;
}
}
}
g_variant_unref (val);
}
if (private_245_val != NULL && !found_unknown_245) {
_items_add_printf (items,
"DHCP4_UNKNOWN_245=%s",
g_variant_get_string (private_245_val, NULL));
}
}
/*****************************************************************************/
@ -534,7 +569,7 @@ nm_dispatcher_utils_construct_envp (const char *action,
_items_add_key0 (items, NULL, "DEVICE_IP_IFACE", ip_iface);
}
/* Device it's aren't valid if the device isn't activated */
/* Device items aren't valid if the device isn't activated */
if ( iface
&& dev_state == NM_DEVICE_STATE_ACTIVATED) {
construct_proxy_items (items, device_proxy_props, NULL);

View file

@ -730,6 +730,23 @@ bytearray_variant_to_string (NMDhcpClient *self, GVariant *value, const char *ke
return converted;
}
static int
label_is_unknown_xyz (const char *label)
{
if (!NM_STR_HAS_PREFIX (label, "unknown_"))
return -EINVAL;
label += NM_STRLEN ("unknown_");
if ( label[0] != '2'
|| !g_ascii_isdigit (label[1])
|| !g_ascii_isdigit (label[2])
|| label[3] != '\0')
return -EINVAL;
return _nm_utils_ascii_str_to_int64 (label, 10, 224, 254, -EINVAL);
}
#define OLD_TAG "old_"
#define NEW_TAG "new_"
@ -753,14 +770,41 @@ maybe_add_option (NMDhcpClient *self,
"dhcp_message_type"))
return;
if (g_str_has_prefix (key, NEW_TAG))
if (NM_STR_HAS_PREFIX (key, NEW_TAG))
key += NM_STRLEN (NEW_TAG);
if (!key[0])
if (NM_STR_HAS_PREFIX (key, "private_") || !key[0])
return;
str_value = bytearray_variant_to_string (self, value, key);
if (str_value)
if (str_value) {
int priv_opt_num;
g_hash_table_insert (hash, g_strdup (key), str_value);
/* dhclient has no special labels for private dhcp options: it uses "unknown_xyz"
* labels for that. We need to identify those to alias them to our "private_xyz"
* format unsed in the internal dchp plugins.
*/
if ((priv_opt_num = label_is_unknown_xyz (key)) > 0) {
gs_free guint8 *check_val = NULL;
char *hex_str = NULL;
gsize len;
/* dhclient passes values from dhcp private options in its own "string" format:
* if the raw values are printable as ascii strings, it will pass the string
* representation; if the values are not printable as an ascii string, it will
* pass a string displaying the hex values (hex string). Try to enforce passing
* always an hex string, converting string representation if needed.
*/
check_val = nm_utils_hexstr2bin_alloc (str_value, FALSE, TRUE, ":", 0, &len);
hex_str = nm_utils_bin2hexstr_full (check_val ?: (guint8 *) str_value,
check_val ? len : strlen (str_value),
':', FALSE, NULL);
g_hash_table_insert (hash,
g_strdup_printf ("private_%d", priv_opt_num),
hex_str);
}
}
}
gboolean

276
src/dhcp/nm-dhcp-options.c Normal file
View file

@ -0,0 +1,276 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2019 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-dhcp-options.h"
#define REQPREFIX "requested_"
#define REQ(_num, _name, _include) \
{ \
.name = REQPREFIX""_name, \
.option_num = _num, \
.include = _include, \
}
const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = {
REQ (NM_DHCP_OPTION_DHCP4_SUBNET_MASK, "subnet_mask", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_TIME_OFFSET, "time_offset", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, "domain_name_servers", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_HOST_NAME, "host_name", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, "domain_name", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, "interface_mtu", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_BROADCAST, "broadcast_address", TRUE ),
/* RFC 3442: The Classless Static Routes option code MUST appear in the parameter
* request list prior to both the Router option code and the Static
* Routes option code, if present. */
REQ (NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, "rfc3442_classless_static_routes", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_ROUTER, "routers", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, "static_routes", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, "nis_domain", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_NIS_SERVERS, "nis_servers", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_NTP_SERVER, "ntp_servers", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_SERVER_ID, "dhcp_server_identifier", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, "domain_search", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, "ms_classless_static_routes", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, "wpad", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_ROOT_PATH, "root_path", TRUE ),
REQ (NM_DHCP_OPTION_DHCP4_TIME_SERVERS, "time_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS, "ien116_name_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_LOG_SERVERS, "log_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS, "cookie_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_LPR_SERVERS, "lpr_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS, "impress_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS, "resource_location_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE, "boot_size", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_MERIT_DUMP, "merit_dump", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SWAP_SERVER, "swap_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH, "extensions_path", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING, "ip_forwarding", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING, "non_local_source_routing", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_POLICY_FILTER, "policy_filter", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MDR, "max_dgram_reassembly", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_TTL, "default_ip_ttl", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT, "path_mtu_aging_timeout", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE, "path_mtu_plateau_table", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL, "all_subnets_local", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY, "perform_mask_discovery", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER, "mask_supplier", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY, "router_discovery", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR, "router_solicitation_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION, "trailer_encapsulation", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT, "arp_cache_timeout", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION, "ieee802_3_encapsulation", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL, "default_tcp_ttl", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL, "tcp_keepalive_internal", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE, "tcp_keepalive_garbage", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, "vendor_encapsulated_options", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, "netbios_name_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER, "netbios_dd_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_FONT_SERVERS, "font_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER, "x_display_manager", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, "dhcp_lease_time", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, "dhcp_renewal_time", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, "dhcp_rebinding_time", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, "tcode", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN, "nwip_domain", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS, "nwip_suboptions", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN, "nisplus_domain", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS, "nisplus_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME, "tftp_server_name", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, "bootfile_name", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT, "mobile_ip_home_agent", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SMTP_SERVER, "smtp_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_POP_SERVER, "pop_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NNTP_SERVER, "nntp_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_WWW_SERVER, "www_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_FINGER_SERVER, "finger_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IRC_SERVER, "irc_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER, "streettalk_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER, "streettalk_directory_assistance_server", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT, "slp_directory_agent", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE, "slp_service_scope", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION, "relay_agent_information", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NDS_SERVERS, "nds_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME, "nds_tree_name", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NDS_CONTEXT, "nds_context", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES, "bcms_controller_names", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS, "bcms_controller_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION, "client_last_transaction_time", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP, "associated_ip", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE, "pxe_system_type", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID, "pxe_interface_id", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID, "pxe_client_id", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_UAP_SERVERS, "uap_servers", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC, "geoconf_civic", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS, "netinfo_server_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG, "netinfo_server_tag", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_DEFAULT_URL, "default_url", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_AUTO_CONFIG, "auto_config", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH, "name_service_search", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION, "subnet_selection", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_VIVCO, "vivco", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_VIVSO, "vivso", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PANA_AGENT, "pana_agent", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_V4_LOST, "v4_lost", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS, "sip_ua_cs_domains", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF, "ipv4_address_andsf", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION, "rndss_selection", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS, "tftp_server_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS, "v4_portparams", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL, "v4_captive_portal", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE, "loader_configfile", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX, "loader_pathprefix", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME, "loader_reboottime", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_OPTION_6RD, "option_6rd", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN, "v4_access_domain", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_224, "private_224", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_225, "private_225", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_226, "private_226", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_227, "private_227", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_228, "private_228", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_229, "private_229", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_230, "private_230", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_231, "private_231", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_232, "private_232", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_233, "private_233", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_234, "private_234", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_235, "private_235", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_236, "private_236", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_237, "private_237", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_238, "private_238", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_239, "private_239", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_240, "private_240", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_241, "private_241", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_242, "private_242", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_243, "private_243", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_244, "private_244", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_245, "private_245", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_246, "private_246", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_247, "private_247", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_248, "private_248", FALSE ),
/* DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE */
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_250, "private_250", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_251, "private_251", FALSE ),
/* DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY */
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_253, "private_253", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_254, "private_254", FALSE ),
/* Internal values */
REQ (NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE ),
{ 0 }
};
const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = {
REQ (NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE ),
/* Don't request server ID by default; some servers don't reply to
* Information Requests that request the Server ID.
*/
REQ (NM_DHCP_OPTION_DHCP6_SERVERID, "dhcp6_server_id", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_DNS_SERVERS, "dhcp6_name_servers", TRUE ),
REQ (NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, "dhcp6_domain_search", TRUE ),
REQ (NM_DHCP_OPTION_DHCP6_SNTP_SERVERS, "dhcp6_sntp_servers", TRUE ),
/* Internal values */
REQ (NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, "ip6_address", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN, "ip6_prefixlen", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE, "preferred_life", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE, "max_life", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_STARTS, "starts", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS, "life_starts", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE ),
REQ (NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE ),
{ 0 }
};
const char *
nm_dhcp_option_request_string (const NMDhcpOption *requests, guint option)
{
guint i = 0;
while (requests[i].name) {
if (requests[i].option_num == option)
return requests[i].name + NM_STRLEN (REQPREFIX);
i++;
}
/* Option should always be found */
nm_assert_not_reached ();
return NULL;
}
void
nm_dhcp_option_take_option (GHashTable *options,
const NMDhcpOption *requests,
guint option,
char *value)
{
nm_assert (options);
nm_assert (requests);
nm_assert (value);
g_hash_table_insert (options,
(gpointer) nm_dhcp_option_request_string (requests, option),
value);
}
void
nm_dhcp_option_add_option (GHashTable *options, const NMDhcpOption *requests, guint option, const char *value)
{
if (options)
nm_dhcp_option_take_option (options, requests, option, g_strdup (value));
}
void
nm_dhcp_option_add_option_u64 (GHashTable *options, const NMDhcpOption *requests, guint option, guint64 value)
{
if (options)
nm_dhcp_option_take_option (options, requests, option, g_strdup_printf ("%" G_GUINT64_FORMAT, value));
}
void
nm_dhcp_option_add_requests_to_options (GHashTable *options, const NMDhcpOption *requests)
{
guint i;
if (!options)
return;
for (i = 0; requests[i].name; i++) {
if (requests[i].include)
g_hash_table_insert (options, (gpointer) requests[i].name, g_strdup ("1"));
}
}
GHashTable *
nm_dhcp_option_create_options_dict (void)
{
return g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free);
}

202
src/dhcp/nm-dhcp-options.h Normal file
View file

@ -0,0 +1,202 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2019 Red Hat, Inc.
*/
#ifndef __NM_DHCP_OPTIONS_H__
#define __NM_DHCP_OPTIONS_H__
typedef enum {
NM_DHCP_OPTION_DHCP4_PAD = 0,
NM_DHCP_OPTION_DHCP4_SUBNET_MASK = 1,
NM_DHCP_OPTION_DHCP4_TIME_OFFSET = 2,
NM_DHCP_OPTION_DHCP4_ROUTER = 3,
NM_DHCP_OPTION_DHCP4_TIME_SERVERS = 4,
NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS = 5,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER = 6,
NM_DHCP_OPTION_DHCP4_LOG_SERVERS = 7,
NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS = 8,
NM_DHCP_OPTION_DHCP4_LPR_SERVERS = 9,
NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS = 10,
NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS = 11,
NM_DHCP_OPTION_DHCP4_HOST_NAME = 12,
NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE = 13,
NM_DHCP_OPTION_DHCP4_MERIT_DUMP = 14,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME = 15,
NM_DHCP_OPTION_DHCP4_SWAP_SERVER = 16,
NM_DHCP_OPTION_DHCP4_ROOT_PATH = 17,
NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH = 18,
NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING = 19,
NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING = 20,
NM_DHCP_OPTION_DHCP4_POLICY_FILTER = 21,
NM_DHCP_OPTION_DHCP4_INTERFACE_MDR = 22,
NM_DHCP_OPTION_DHCP4_INTERFACE_TTL = 23,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT = 24,
NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE = 25,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU = 26,
NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL = 27,
NM_DHCP_OPTION_DHCP4_BROADCAST = 28,
NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY = 29,
NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER = 30,
NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY = 31,
NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR = 32,
NM_DHCP_OPTION_DHCP4_STATIC_ROUTE = 33,
NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION = 34,
NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT = 35,
NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION = 36,
NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL = 37,
NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL = 38,
NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE = 39,
NM_DHCP_OPTION_DHCP4_NIS_DOMAIN = 40,
NM_DHCP_OPTION_DHCP4_NIS_SERVERS = 41,
NM_DHCP_OPTION_DHCP4_NTP_SERVER = 42,
NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC = 43,
NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER = 44,
NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER = 45,
NM_DHCP_OPTION_DHCP4_FONT_SERVERS = 48,
NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER = 49,
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME = 51,
NM_DHCP_OPTION_DHCP4_SERVER_ID = 54,
NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME = 58,
NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME = 59,
NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN = 62,
NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS = 63,
NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN = 64,
NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS = 65,
NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME = 66,
NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME = 67,
NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT = 68,
NM_DHCP_OPTION_DHCP4_SMTP_SERVER = 69,
NM_DHCP_OPTION_DHCP4_POP_SERVER = 70,
NM_DHCP_OPTION_DHCP4_NNTP_SERVER = 71,
NM_DHCP_OPTION_DHCP4_WWW_SERVER = 72,
NM_DHCP_OPTION_DHCP4_FINGER_SERVER = 73,
NM_DHCP_OPTION_DHCP4_IRC_SERVER = 74,
NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER = 75,
NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER = 76,
NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT = 78,
NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE = 79,
NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION = 82,
NM_DHCP_OPTION_DHCP4_NDS_SERVERS = 85,
NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME = 86,
NM_DHCP_OPTION_DHCP4_NDS_CONTEXT = 87,
NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES = 88,
NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS = 89,
NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION = 91,
NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP = 92,
NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE = 93,
NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID = 94,
NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID = 97,
NM_DHCP_OPTION_DHCP4_UAP_SERVERS = 98,
NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC = 99,
NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE = 101,
NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS = 112,
NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG = 113,
NM_DHCP_OPTION_DHCP4_DEFAULT_URL = 114,
NM_DHCP_OPTION_DHCP4_AUTO_CONFIG = 116,
NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH = 117,
NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION = 118,
NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST = 119,
NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE = 121,
NM_DHCP_OPTION_DHCP4_VIVCO = 124,
NM_DHCP_OPTION_DHCP4_VIVSO = 125,
NM_DHCP_OPTION_DHCP4_PANA_AGENT = 136,
NM_DHCP_OPTION_DHCP4_V4_LOST = 137,
NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS = 141,
NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF = 142,
NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION = 146,
NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS = 150,
NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS = 159,
NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL = 160,
NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE = 209,
NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX = 210,
NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME = 211,
NM_DHCP_OPTION_DHCP4_OPTION_6RD = 212,
NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN = 213,
NM_DHCP_OPTION_DHCP4_PRIVATE_224 = 224,
NM_DHCP_OPTION_DHCP4_PRIVATE_225 = 225,
NM_DHCP_OPTION_DHCP4_PRIVATE_226 = 226,
NM_DHCP_OPTION_DHCP4_PRIVATE_227 = 227,
NM_DHCP_OPTION_DHCP4_PRIVATE_228 = 228,
NM_DHCP_OPTION_DHCP4_PRIVATE_229 = 229,
NM_DHCP_OPTION_DHCP4_PRIVATE_230 = 230,
NM_DHCP_OPTION_DHCP4_PRIVATE_231 = 231,
NM_DHCP_OPTION_DHCP4_PRIVATE_232 = 232,
NM_DHCP_OPTION_DHCP4_PRIVATE_233 = 233,
NM_DHCP_OPTION_DHCP4_PRIVATE_234 = 234,
NM_DHCP_OPTION_DHCP4_PRIVATE_235 = 235,
NM_DHCP_OPTION_DHCP4_PRIVATE_236 = 236,
NM_DHCP_OPTION_DHCP4_PRIVATE_237 = 237,
NM_DHCP_OPTION_DHCP4_PRIVATE_238 = 238,
NM_DHCP_OPTION_DHCP4_PRIVATE_239 = 239,
NM_DHCP_OPTION_DHCP4_PRIVATE_240 = 240,
NM_DHCP_OPTION_DHCP4_PRIVATE_241 = 241,
NM_DHCP_OPTION_DHCP4_PRIVATE_242 = 242,
NM_DHCP_OPTION_DHCP4_PRIVATE_243 = 243,
NM_DHCP_OPTION_DHCP4_PRIVATE_244 = 244,
NM_DHCP_OPTION_DHCP4_PRIVATE_245 = 245,
NM_DHCP_OPTION_DHCP4_PRIVATE_246 = 246,
NM_DHCP_OPTION_DHCP4_PRIVATE_247 = 247,
NM_DHCP_OPTION_DHCP4_PRIVATE_248 = 248,
NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE = 249,
NM_DHCP_OPTION_DHCP4_PRIVATE_250 = 250,
NM_DHCP_OPTION_DHCP4_PRIVATE_251 = 251,
NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY = 252,
NM_DHCP_OPTION_DHCP4_PRIVATE_253 = 253,
NM_DHCP_OPTION_DHCP4_PRIVATE_254 = 254,
NM_DHCP_OPTION_DHCP4_END = 255,
/* Internal values */
NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS = 1024,
NM_DHCP_OPTION_DHCP4_NM_EXPIRY = 1025,
} NMDhcpOptionDhcp4Options;
typedef enum {
NM_DHCP_OPTION_DHCP6_CLIENTID = 1,
NM_DHCP_OPTION_DHCP6_SERVERID = 2,
NM_DHCP_OPTION_DHCP6_DNS_SERVERS = 23,
NM_DHCP_OPTION_DHCP6_DOMAIN_LIST = 24,
NM_DHCP_OPTION_DHCP6_SNTP_SERVERS = 31,
/* Internal values */
NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS = 1026,
NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN = 1027,
NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE = 1028,
NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE = 1029,
NM_DHCP_OPTION_DHCP6_NM_STARTS = 1030,
NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS = 1031,
NM_DHCP_OPTION_DHCP6_NM_RENEW = 1032,
NM_DHCP_OPTION_DHCP6_NM_REBIND = 1033,
NM_DHCP_OPTION_DHCP6_NM_IAID = 1034,
} NMDhcpOptionDhcp6Options;
typedef struct {
const char *name;
uint16_t option_num;
bool include;
} NMDhcpOption;
extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[];
extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[];
const char *nm_dhcp_option_request_string (const NMDhcpOption *requests, guint option);
void nm_dhcp_option_take_option (GHashTable *options, const NMDhcpOption *requests, guint option, char *value);
void nm_dhcp_option_add_option (GHashTable *options, const NMDhcpOption *requests, guint option, const char *value);
void nm_dhcp_option_add_option_u64 (GHashTable *options, const NMDhcpOption *requests, guint option, guint64 value);
void nm_dhcp_option_add_requests_to_options (GHashTable *options, const NMDhcpOption *requests);
GHashTable *nm_dhcp_option_create_options_dict (void);
#endif /* __NM_DHCP_OPTIONS_H__ */

View file

@ -32,11 +32,13 @@
#include "nm-utils.h"
#include "nm-config.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "nm-core-utils.h"
#include "NetworkManagerUtils.h"
#include "platform/nm-platform.h"
#include "nm-dhcp-client-logging.h"
#include "systemd/nm-sd.h"
#include "systemd/nm-sd-utils-dhcp.h"
/*****************************************************************************/
@ -79,160 +81,10 @@ G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
/*****************************************************************************/
#define DHCP_OPTION_NIS_DOMAIN 40
#define DHCP_OPTION_NIS_SERVERS 41
/* Internal values */
#define DHCP_OPTION_IP_ADDRESS 1024
#define DHCP_OPTION_EXPIRY 1025
#define DHCP6_OPTION_IP_ADDRESS 1026
#define DHCP6_OPTION_PREFIXLEN 1027
#define DHCP6_OPTION_PREFERRED_LIFE 1028
#define DHCP6_OPTION_MAX_LIFE 1029
#define DHCP6_OPTION_STARTS 1030
#define DHCP6_OPTION_LIFE_STARTS 1031
#define DHCP6_OPTION_RENEW 1032
#define DHCP6_OPTION_REBIND 1033
#define DHCP6_OPTION_IAID 1034
typedef struct {
const char *name;
uint16_t option_num;
bool include;
} ReqOption;
#define REQPREFIX "requested_"
#define REQ(_num, _name, _include) \
{ \
.name = REQPREFIX""_name, \
.option_num = _num, \
.include = _include, \
}
static const ReqOption dhcp4_requests[] = {
REQ (SD_DHCP_OPTION_SUBNET_MASK, "subnet_mask", TRUE ),
REQ (SD_DHCP_OPTION_TIME_OFFSET, "time_offset", TRUE ),
REQ (SD_DHCP_OPTION_DOMAIN_NAME_SERVER, "domain_name_servers", TRUE ),
REQ (SD_DHCP_OPTION_HOST_NAME, "host_name", TRUE ),
REQ (SD_DHCP_OPTION_DOMAIN_NAME, "domain_name", TRUE ),
REQ (SD_DHCP_OPTION_INTERFACE_MTU, "interface_mtu", TRUE ),
REQ (SD_DHCP_OPTION_BROADCAST, "broadcast_address", TRUE ),
/* RFC 3442: The Classless Static Routes option code MUST appear in the parameter
* request list prior to both the Router option code and the Static
* Routes option code, if present. */
REQ (SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, "rfc3442_classless_static_routes", TRUE ),
REQ (SD_DHCP_OPTION_ROUTER, "routers", TRUE ),
REQ (SD_DHCP_OPTION_STATIC_ROUTE, "static_routes", TRUE ),
REQ (DHCP_OPTION_NIS_DOMAIN, "nis_domain", TRUE ),
REQ (DHCP_OPTION_NIS_SERVERS, "nis_servers", TRUE ),
REQ (SD_DHCP_OPTION_NTP_SERVER, "ntp_servers", TRUE ),
REQ (SD_DHCP_OPTION_SERVER_IDENTIFIER, "dhcp_server_identifier", TRUE ),
REQ (SD_DHCP_OPTION_DOMAIN_SEARCH_LIST, "domain_search", TRUE ),
REQ (SD_DHCP_OPTION_PRIVATE_CLASSLESS_STATIC_ROUTE, "ms_classless_static_routes", TRUE ),
REQ (SD_DHCP_OPTION_PRIVATE_PROXY_AUTODISCOVERY, "wpad", TRUE ),
REQ (SD_DHCP_OPTION_ROOT_PATH, "root_path", TRUE ),
/* Internal values */
REQ (SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, "expiry", FALSE ),
REQ (SD_DHCP_OPTION_CLIENT_IDENTIFIER, "dhcp_client_identifier", FALSE ),
REQ (DHCP_OPTION_IP_ADDRESS, "ip_address", FALSE ),
{ 0 }
};
static const ReqOption dhcp6_requests[] = {
REQ (SD_DHCP6_OPTION_CLIENTID, "dhcp6_client_id", FALSE ),
/* Don't request server ID by default; some servers don't reply to
* Information Requests that request the Server ID.
*/
REQ (SD_DHCP6_OPTION_SERVERID, "dhcp6_server_id", FALSE ),
REQ (SD_DHCP6_OPTION_DNS_SERVERS, "dhcp6_name_servers", TRUE ),
REQ (SD_DHCP6_OPTION_DOMAIN_LIST, "dhcp6_domain_search", TRUE ),
REQ (SD_DHCP6_OPTION_SNTP_SERVERS, "dhcp6_sntp_servers", TRUE ),
/* Internal values */
REQ (DHCP6_OPTION_IP_ADDRESS, "ip6_address", FALSE ),
REQ (DHCP6_OPTION_PREFIXLEN, "ip6_prefixlen", FALSE ),
REQ (DHCP6_OPTION_PREFERRED_LIFE, "preferred_life", FALSE ),
REQ (DHCP6_OPTION_MAX_LIFE, "max_life", FALSE ),
REQ (DHCP6_OPTION_STARTS, "starts", FALSE ),
REQ (DHCP6_OPTION_LIFE_STARTS, "life_starts", FALSE ),
REQ (DHCP6_OPTION_RENEW, "renew", FALSE ),
REQ (DHCP6_OPTION_REBIND, "rebind", FALSE ),
REQ (DHCP6_OPTION_IAID, "iaid", FALSE ),
{ 0 }
};
static void
take_option (GHashTable *options,
const ReqOption *requests,
guint option,
char *value)
{
guint i;
nm_assert (options);
nm_assert (requests);
nm_assert (value);
for (i = 0; requests[i].name; i++) {
nm_assert (g_str_has_prefix (requests[i].name, REQPREFIX));
if (requests[i].option_num == option) {
g_hash_table_insert (options,
(gpointer) (requests[i].name + NM_STRLEN (REQPREFIX)),
value);
return;
}
}
/* Option should always be found */
nm_assert_not_reached ();
}
static void
add_option (GHashTable *options, const ReqOption *requests, guint option, const char *value)
{
if (options)
take_option (options, requests, option, g_strdup (value));
}
static void
add_option_u64 (GHashTable *options, const ReqOption *requests, guint option, guint64 value)
{
if (options)
take_option (options, requests, option, g_strdup_printf ("%" G_GUINT64_FORMAT, value));
}
static void
add_requests_to_options (GHashTable *options, const ReqOption *requests)
{
guint i;
if (!options)
return;
for (i = 0; requests[i].name; i++) {
if (requests[i].include)
g_hash_table_insert (options, (gpointer) requests[i].name, g_strdup ("1"));
}
}
static GHashTable *
create_options_dict (void)
{
return g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free);
}
#define LOG_LEASE(domain, ...) \
G_STMT_START { \
if (log_lease) { \
_LOG2I ((domain), (iface), " "__VA_ARGS__); \
_LOG2D ((domain), (iface), " "__VA_ARGS__); \
} \
} G_STMT_END
@ -267,9 +119,14 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
gint64 ts_time = time (NULL);
struct in_addr a_address;
struct in_addr a_netmask;
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;
g_return_val_if_fail (lease != NULL, NULL);
@ -290,26 +147,35 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
ip4_config = nm_ip4_config_new (multi_idx, ifindex);
options = out_options ? create_options_dict () : NULL;
options = out_options ? nm_dhcp_option_create_options_dict () : NULL;
nm_utils_inet4_ntop (a_address.s_addr, addr_str);
LOG_LEASE (LOGD_DHCP4, "address %s", addr_str);
add_option (options, dhcp4_requests, DHCP_OPTION_IP_ADDRESS, addr_str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS),
addr_str);
nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr);
LOG_LEASE (LOGD_DHCP4, "plen %u", (guint) a_plen);
add_option (options,
dhcp4_requests,
SD_DHCP_OPTION_SUBNET_MASK,
nm_utils_inet4_ntop (a_netmask.s_addr, addr_str));
LOG_LEASE (LOGD_DHCP4, "%s '%u'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SUBNET_MASK),
(guint) a_plen);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_SUBNET_MASK,
nm_utils_inet4_ntop (a_netmask.s_addr, addr_str));
LOG_LEASE (LOGD_DHCP4, "expires in %u seconds (at %lld)",
LOG_LEASE (LOGD_DHCP4, "%s '%u' seconds (at %lld)",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NM_EXPIRY),
(guint) a_lifetime,
(long long) (ts_time + a_lifetime));
add_option_u64 (options,
dhcp4_requests,
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME,
(guint64) (ts_time + a_lifetime));
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_NM_EXPIRY,
(guint64) (ts_time + a_lifetime));
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME,
a_lifetime);
nm_ip4_config_add_address (ip4_config,
&((const NMPlatformIP4Address) {
@ -322,6 +188,28 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
.preferred = a_lifetime,
}));
if (sd_dhcp_lease_get_server_identifier (lease, &server_id) >= 0) {
nm_utils_inet4_ntop (server_id.s_addr, addr_str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_SERVER_ID),
addr_str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
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);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_BROADCAST),
addr_str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_BROADCAST,
addr_str);
}
num = sd_dhcp_lease_get_dns (lease, &addr_list);
if (num > 0) {
nm_gstring_prepare (&str);
@ -337,8 +225,13 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
}
nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr);
}
LOG_LEASE (LOGD_DHCP4, "nameserver '%s'", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME_SERVER, str->str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER),
str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
str->str);
}
num = sd_dhcp_lease_get_search_domains (lease, (char ***) &search_domains);
@ -348,16 +241,23 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
g_string_append (nm_gstring_add_space_delimiter (str), search_domains[i]);
nm_ip4_config_add_search (ip4_config, search_domains[i]);
}
LOG_LEASE (LOGD_DHCP4, "domain search '%s'", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_SEARCH_LIST, str->str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST),
str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
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;
LOG_LEASE (LOGD_DHCP4, "domain name '%s'", s);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_DOMAIN_NAME, s);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME),
s);
nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, 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. */
@ -367,8 +267,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
}
if (sd_dhcp_lease_get_hostname (lease, &s) >= 0) {
LOG_LEASE (LOGD_DHCP4, "hostname '%s'", s);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_HOST_NAME, s);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME),
s);
nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_HOST_NAME, s);
}
num = sd_dhcp_lease_get_routes (lease, &routes);
@ -379,10 +281,10 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
for (i = 0; i < num; i++) {
switch (sd_dhcp_route_get_option (routes[i])) {
case SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE:
case NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE:
has_classless_route = TRUE;
break;
case SD_DHCP_OPTION_STATIC_ROUTE:
case NM_DHCP_OPTION_DHCP4_STATIC_ROUTE:
has_static_route = TRUE;
break;
}
@ -404,8 +306,8 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
guint32 m;
option = sd_dhcp_route_get_option (routes[i]);
if (!NM_IN_SET (option, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE,
SD_DHCP_OPTION_STATIC_ROUTE))
if (!NM_IN_SET (option, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
NM_DHCP_OPTION_DHCP4_STATIC_ROUTE))
continue;
if (sd_dhcp_route_get_destination (routes[i], &r_network) < 0)
@ -422,14 +324,14 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
nm_utils_inet4_ntop (r_gateway.s_addr, gateway_str);
LOG_LEASE (LOGD_DHCP4,
"%sstatic route %s/%d gw %s",
option == SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
? "classless "
"%sstatic_route %s/%d gw %s",
option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
? "rfc3442_classless_"
: "",
network_net_str,
(int) r_plen,
gateway_str);
g_string_append_printf (nm_gstring_add_space_delimiter ( option == SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE
g_string_append_printf (nm_gstring_add_space_delimiter ( option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE
? str_classless
: str_static),
"%s/%d %s",
@ -437,7 +339,7 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
(int) r_plen,
gateway_str);
if ( option == SD_DHCP_OPTION_STATIC_ROUTE
if ( option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE
&& has_classless_route) {
/* RFC 3443: if the DHCP server returns both a Classless Static Routes
* option and a Static Routes option, the DHCP client MUST ignore the
@ -446,7 +348,7 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
}
if ( r_plen == 0
&& option == SD_DHCP_OPTION_STATIC_ROUTE) {
&& option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE) {
/* for option 33 (static route), RFC 2132 says:
*
* The default route (0.0.0.0) is an illegal destination for a static
@ -478,9 +380,15 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
}
if (str_classless && str_classless->len > 0)
add_option (options, dhcp4_requests, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE, str_classless->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE,
str_classless->str);
if (str_static && str_static->len > 0)
add_option (options, dhcp4_requests, SD_DHCP_OPTION_STATIC_ROUTE, str_static->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_STATIC_ROUTE,
str_static->str);
}
num = sd_dhcp_lease_get_router (lease, &a_router);
@ -524,14 +432,21 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
}),
NULL);
}
LOG_LEASE (LOGD_DHCP4, "router %s", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROUTER, str->str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER),
str->str);
nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
}
if ( sd_dhcp_lease_get_mtu (lease, &mtu) >= 0
&& mtu) {
LOG_LEASE (LOGD_DHCP4, "mtu %u", mtu);
add_option_u64 (options, dhcp4_requests, SD_DHCP_OPTION_INTERFACE_MTU, mtu);
LOG_LEASE (LOGD_DHCP4, "%s '%u'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU),
mtu);
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_INTERFACE_MTU,
mtu);
nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
}
@ -542,19 +457,77 @@ lease_to_ip4_config (NMDedupMultiIndex *multi_idx,
nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str);
g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
}
LOG_LEASE (LOGD_DHCP4, "ntp server '%s'", str->str);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_NTP_SERVER, str->str);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_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);
}
if (sd_dhcp_lease_get_root_path (lease, &s) >= 0) {
LOG_LEASE (LOGD_DHCP4, "root path '%s'", s);
add_option (options, dhcp4_requests, SD_DHCP_OPTION_ROOT_PATH, s);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH),
s);
nm_dhcp_option_add_option (options, _nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_ROOT_PATH, s);
}
if (sd_dhcp_lease_get_t1 (lease, &renewal) >= 0) {
LOG_LEASE (LOGD_DHCP4, "%s '%u'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME),
renewal);
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME,
renewal);
}
if (sd_dhcp_lease_get_t2 (lease, &rebinding) >= 0) {
LOG_LEASE (LOGD_DHCP4, "%s '%u'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME),
rebinding);
nm_dhcp_option_add_option_u64 (options,
_nm_dhcp_option_dhcp4_options,
NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME,
rebinding);
}
if (sd_dhcp_lease_get_timezone (lease, &s) >= 0) {
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE),
s);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp4_options,
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);
num = nm_sd_dhcp_lease_get_private_options (lease, &private_options);
if (num > 0) {
for (i = 0; i < num; i++) {
char *option_string;
option_string = nm_utils_bin2hexstr_full (private_options[i].data,
private_options[i].data_len,
':', FALSE, NULL);
LOG_LEASE (LOGD_DHCP4, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp4_options, private_options[i].code),
option_string);
if (!options) {
g_free (option_string);
continue;
}
nm_dhcp_option_take_option (options,
_nm_dhcp_option_dhcp4_options,
private_options[i].code,
option_string);
}
}
NM_SET_OUT (out_options, g_steal_pointer (&options));
return g_steal_pointer (&ip4_config);
}
@ -627,7 +600,7 @@ bound4_handle (NMDhcpSystemd *self)
return;
}
add_requests_to_options (options, dhcp4_requests);
nm_dhcp_option_add_requests_to_options (options, _nm_dhcp_option_dhcp4_options);
dhcp_lease_save (lease, priv->lease_file);
nm_dhcp_client_set_state (NM_DHCP_CLIENT (self),
@ -780,10 +753,10 @@ ip4_start (NMDhcpClient *client,
}
/* Add requested options */
for (i = 0; dhcp4_requests[i].name; i++) {
if (dhcp4_requests[i].include) {
nm_assert (dhcp4_requests[i].option_num <= 255);
r = sd_dhcp_client_set_request_option (sd_client, dhcp4_requests[i].option_num);
for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; 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);
}
}
@ -850,7 +823,7 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
ip6_config = nm_ip6_config_new (multi_idx, ifindex);
options = out_options ? create_options_dict () : NULL;
options = out_options ? nm_dhcp_option_create_options_dict () : NULL;
sd_dhcp6_lease_reset_address_iter (lease);
nm_gstring_prepare (&str);
@ -870,12 +843,15 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
nm_utils_inet6_ntop (&tmp_addr, addr_str);
g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
LOG_LEASE (LOGD_DHCP6,
"address %s",
LOG_LEASE (LOGD_DHCP6, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS),
nm_platform_ip6_address_to_string (&address, sbuf, sizeof (sbuf)));
};
if (str->len)
add_option (options, dhcp6_requests, DHCP6_OPTION_IP_ADDRESS, str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS,
str->str);
if ( !info_only
&& nm_ip6_config_get_num_addresses (ip6_config) == 0) {
@ -894,8 +870,13 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
g_string_append (nm_gstring_add_space_delimiter (str), addr_str);
nm_ip6_config_add_nameserver (ip6_config, &dns[i]);
}
LOG_LEASE (LOGD_DHCP6, "nameserver %s", str->str);
add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DNS_SERVERS, str->str);
LOG_LEASE (LOGD_DHCP6, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DNS_SERVERS),
str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_DNS_SERVERS,
str->str);
}
num = sd_dhcp6_lease_get_domains (lease, &domains);
@ -905,8 +886,13 @@ lease_to_ip6_config (NMDedupMultiIndex *multi_idx,
g_string_append (nm_gstring_add_space_delimiter (str), domains[i]);
nm_ip6_config_add_search (ip6_config, domains[i]);
}
LOG_LEASE (LOGD_DHCP6, "domain name '%s'", str->str);
add_option (options, dhcp6_requests, SD_DHCP6_OPTION_DOMAIN_LIST, str->str);
LOG_LEASE (LOGD_DHCP6, "%s '%s'",
nm_dhcp_option_request_string (_nm_dhcp_option_dhcp6_options, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST),
str->str);
nm_dhcp_option_add_option (options,
_nm_dhcp_option_dhcp6_options,
NM_DHCP_OPTION_DHCP6_DOMAIN_LIST,
str->str);
}
NM_SET_OUT (out_options, g_steal_pointer (&options));
@ -1079,9 +1065,9 @@ ip6_start (NMDhcpClient *client,
}
/* Add requested options */
for (i = 0; dhcp6_requests[i].name; i++) {
if (dhcp6_requests[i].include) {
r = sd_dhcp6_client_set_request_option (sd_client, dhcp6_requests[i].option_num);
for (i = 0; _nm_dhcp_option_dhcp6_options[i].name; i++) {
if (_nm_dhcp_option_dhcp6_options[i].include) {
r = sd_dhcp6_client_set_request_option (sd_client, _nm_dhcp_option_dhcp6_options[i].option_num);
nm_assert (r >= 0 || r == -EEXIST);
}
}

View file

@ -25,6 +25,7 @@ sources = files(
'dhcp/nm-dhcp-nettools.c',
'dhcp/nm-dhcp-systemd.c',
'dhcp/nm-dhcp-utils.c',
'dhcp/nm-dhcp-options.c',
'ndisc/nm-lndp-ndisc.c',
'ndisc/nm-ndisc.c',
'platform/nm-netlink.c',

View file

@ -25,6 +25,7 @@ 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',
),
include_directories: [
src_inc,

View file

@ -0,0 +1,54 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 2019 Red Hat, Inc.
*/
#include "nm-default.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)
{
struct sd_dhcp_raw_option *raw_option;
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;
}

View file

@ -0,0 +1,34 @@
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* (C) Copyright 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__ */