From f71f40bc20ea085bf49f2a31fed5476bce0eee91 Mon Sep 17 00:00:00 2001 From: Antonio Cardace Date: Mon, 24 Aug 2020 18:08:09 +0200 Subject: [PATCH] core: add support for dhcpv4 vendor class identifier option https://bugzilla.redhat.com/show_bug.cgi?id=1871042 Signed-off-by: Antonio Cardace --- src/devices/nm-device.c | 45 ++++++++++++++++++++++++++++++++++++++ src/dhcp/nm-dhcp-client.c | 21 ++++++++++++++++++ src/dhcp/nm-dhcp-client.h | 35 +++++++++++++++-------------- src/dhcp/nm-dhcp-manager.c | 8 +++++++ src/dhcp/nm-dhcp-manager.h | 1 + src/dhcp/nm-dhcp-options.h | 1 + src/nm-iface-helper.c | 1 + 7 files changed, 96 insertions(+), 16 deletions(-) diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index ad23d14ce4..4e8b2bf3c8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -8821,11 +8821,53 @@ out_good: return result; } +static GBytes * +dhcp4_get_vendor_class_identifier (NMDevice *self, NMSettingIP4Config *s_ip4) +{ + gs_free char *config_data_prop = NULL; + gs_free char *to_free = NULL; + gboolean validate = FALSE; + const char *conn_prop; + GBytes *bytes = NULL; + const char *bin; + gsize len; + + conn_prop = nm_setting_ip4_config_get_dhcp_vendor_class_identifier (s_ip4); + + if (!conn_prop) { + /* set in NetworkManager.conf ? */ + validate = TRUE; + config_data_prop = nm_config_data_get_connection_default ( + NM_CONFIG_GET_DATA, + NM_CON_DEFAULT ("ipv4.dhcp-vendor-class-identifier"), + self); + conn_prop = config_data_prop; + } + + if (conn_prop) { + bin = nm_utils_buf_utf8safe_unescape (conn_prop, + NM_UTILS_STR_UTF8_SAFE_FLAG_NONE, + &len, + (gpointer *) &to_free); + + if (validate && (bin[0] == '\0' || len > 255 || strlen (bin) != len)) + return NULL; + + if (to_free) + bytes = g_bytes_new_take (g_steal_pointer (&to_free), len); + else + bytes = g_bytes_new (bin, len); + } + + return bytes; +} + static NMActStageReturn dhcp4_start (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMSettingIPConfig *s_ip4; + gs_unref_bytes GBytes *vendor_class_identifier = NULL; gs_unref_bytes GBytes *hwaddr = NULL; gs_unref_bytes GBytes *bcast_hwaddr = NULL; gs_unref_bytes GBytes *client_id = NULL; @@ -8854,6 +8896,8 @@ dhcp4_start (NMDevice *self) } client_id = dhcp4_get_client_id (self, connection, hwaddr); + vendor_class_identifier + = dhcp4_get_vendor_class_identifier (self, NM_SETTING_IP4_CONFIG (s_ip4)); g_warn_if_fail (priv->dhcp_data_4.client == NULL); priv->dhcp_data_4.client = nm_dhcp_manager_start_ip4 (nm_dhcp_manager_get (), @@ -8874,6 +8918,7 @@ dhcp4_start (NMDevice *self) get_dhcp_timeout (self, AF_INET), priv->dhcp_anycast_address, NULL, + vendor_class_identifier, &error); if (!priv->dhcp_data_4.client) { _LOGW (LOGD_DHCP4, "failure to start DHCP: %s", error->message); diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index a1b786ca9b..d130a8d4be 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -51,6 +51,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, PROP_HOSTNAME, PROP_HOSTNAME_FLAGS, PROP_MUD_URL, + PROP_VENDOR_CLASS_IDENTIFIER, ); typedef struct _NMDhcpClientPrivate { @@ -62,6 +63,7 @@ typedef struct _NMDhcpClientPrivate { GBytes * client_id; char * hostname; char * mud_url; + GBytes * vendor_class_identifier; pid_t pid; guint timeout_id; guint watch_id; @@ -322,6 +324,14 @@ nm_dhcp_client_get_mud_url (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->mud_url; } +GBytes * +nm_dhcp_client_get_vendor_class_identifier (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->vendor_class_identifier; +} + /*****************************************************************************/ static const char *state_table[NM_DHCP_STATE_MAX + 1] = { @@ -1076,6 +1086,10 @@ set_property (GObject *object, guint prop_id, /* construct-only */ priv->timeout = g_value_get_uint (value); break; + case PROP_VENDOR_CLASS_IDENTIFIER: + /* construct-only */ + priv->vendor_class_identifier = g_value_dup_boxed (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1120,6 +1134,7 @@ dispose (GObject *object) nm_clear_pointer (&priv->client_id, g_bytes_unref); nm_clear_pointer (&priv->hwaddr, g_bytes_unref); nm_clear_pointer (&priv->bcast_hwaddr, g_bytes_unref); + nm_clear_pointer (&priv->vendor_class_identifier, g_bytes_unref); G_OBJECT_CLASS (nm_dhcp_client_parent_class)->dispose (object); @@ -1237,6 +1252,12 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_VENDOR_CLASS_IDENTIFIER] = + g_param_spec_boxed (NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER, "", "", + G_TYPE_BYTES, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[SIGNAL_STATE_CHANGED] = diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 479ea000a9..11e531999f 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -22,22 +22,23 @@ #define NM_IS_DHCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_CLIENT)) #define NM_DHCP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass)) -#define NM_DHCP_CLIENT_ADDR_FAMILY "addr-family" -#define NM_DHCP_CLIENT_FLAGS "flags" -#define NM_DHCP_CLIENT_HWADDR "hwaddr" -#define NM_DHCP_CLIENT_BROADCAST_HWADDR "broadcast-hwaddr" -#define NM_DHCP_CLIENT_IFINDEX "ifindex" -#define NM_DHCP_CLIENT_INTERFACE "iface" -#define NM_DHCP_CLIENT_MULTI_IDX "multi-idx" -#define NM_DHCP_CLIENT_HOSTNAME "hostname" -#define NM_DHCP_CLIENT_MUD_URL "mud-url" -#define NM_DHCP_CLIENT_ROUTE_METRIC "route-metric" -#define NM_DHCP_CLIENT_ROUTE_TABLE "route-table" -#define NM_DHCP_CLIENT_TIMEOUT "timeout" -#define NM_DHCP_CLIENT_UUID "uuid" -#define NM_DHCP_CLIENT_IAID "iaid" -#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit" -#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags" +#define NM_DHCP_CLIENT_ADDR_FAMILY "addr-family" +#define NM_DHCP_CLIENT_FLAGS "flags" +#define NM_DHCP_CLIENT_HWADDR "hwaddr" +#define NM_DHCP_CLIENT_BROADCAST_HWADDR "broadcast-hwaddr" +#define NM_DHCP_CLIENT_IFINDEX "ifindex" +#define NM_DHCP_CLIENT_INTERFACE "iface" +#define NM_DHCP_CLIENT_MULTI_IDX "multi-idx" +#define NM_DHCP_CLIENT_HOSTNAME "hostname" +#define NM_DHCP_CLIENT_MUD_URL "mud-url" +#define NM_DHCP_CLIENT_ROUTE_METRIC "route-metric" +#define NM_DHCP_CLIENT_ROUTE_TABLE "route-table" +#define NM_DHCP_CLIENT_TIMEOUT "timeout" +#define NM_DHCP_CLIENT_UUID "uuid" +#define NM_DHCP_CLIENT_IAID "iaid" +#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit" +#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags" +#define NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER "vendor-class-identifier" #define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed" #define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated" @@ -150,6 +151,8 @@ gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self); gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self); +GBytes *nm_dhcp_client_get_vendor_class_identifier (NMDhcpClient *self); + gboolean nm_dhcp_client_start_ip4 (NMDhcpClient *self, GBytes *client_id, const char *dhcp_anycast_addr, diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c index 9acf145a5a..df2261ae0d 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/dhcp/nm-dhcp-manager.c @@ -225,6 +225,7 @@ client_start (NMDhcpManager *self, NMSettingIP6ConfigPrivacy privacy, const char *last_ip4_address, guint needed_prefixes, + GBytes *vendor_class_identifier, GError **error) { NMDhcpManagerPrivate *priv; @@ -238,6 +239,9 @@ client_start (NMDhcpManager *self, g_return_val_if_fail (ifindex > 0, NULL); g_return_val_if_fail (uuid != NULL, NULL); g_return_val_if_fail (!dhcp_client_id || g_bytes_get_size (dhcp_client_id) >= 2, NULL); + g_return_val_if_fail ( !vendor_class_identifier + || g_bytes_get_size (vendor_class_identifier) <= 255, + NULL); g_return_val_if_fail (!error || !*error, NULL); if (addr_family == AF_INET) { @@ -313,6 +317,7 @@ client_start (NMDhcpManager *self, NM_DHCP_CLIENT_ROUTE_METRIC, (guint) route_metric, NM_DHCP_CLIENT_TIMEOUT, (guint) timeout, NM_DHCP_CLIENT_HOSTNAME_FLAGS, (guint) hostname_flags, + NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER, vendor_class_identifier, NM_DHCP_CLIENT_FLAGS, (guint) (0 | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0) @@ -393,6 +398,7 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, guint32 timeout, const char *dhcp_anycast_addr, const char *last_ip_address, + GBytes *vendor_class_identifier, GError **error) { NMDhcpManagerPrivate *priv; @@ -452,6 +458,7 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self, 0, last_ip_address, 0, + vendor_class_identifier, error); } @@ -515,6 +522,7 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self, privacy, NULL, needed_prefixes, + NULL, error); } diff --git a/src/dhcp/nm-dhcp-manager.h b/src/dhcp/nm-dhcp-manager.h index e8e65ef31c..ce3f560470 100644 --- a/src/dhcp/nm-dhcp-manager.h +++ b/src/dhcp/nm-dhcp-manager.h @@ -48,6 +48,7 @@ NMDhcpClient * nm_dhcp_manager_start_ip4 (NMDhcpManager *manager, guint32 timeout, const char *dhcp_anycast_addr, const char *last_ip_address, + GBytes *vendor_class_identifier, GError **error); NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager, diff --git a/src/dhcp/nm-dhcp-options.h b/src/dhcp/nm-dhcp-options.h index bc3df5acd3..118ae47079 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/dhcp/nm-dhcp-options.h @@ -59,6 +59,7 @@ typedef enum { 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_VENDOR_CLASS_IDENTIFIER = 60, NM_DHCP_OPTION_DHCP4_CLIENT_ID = 61, NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN = 62, NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS = 63, diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index c7d65d2a66..da84640d26 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -538,6 +538,7 @@ main (int argc, char *argv[]) NM_DHCP_TIMEOUT_DEFAULT, NULL, global_opt.dhcp4_address, + NULL, &error); if (!dhcp4_client) g_error ("failure to start DHCP: %s", error->message);