diff options
Diffstat (limited to 'src/dhcp/nm-dhcp-client.c')
| -rw-r--r-- | src/dhcp/nm-dhcp-client.c | 202 |
1 files changed, 94 insertions, 108 deletions
diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index ea3938d6..ba517606 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -52,23 +52,24 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; NM_GOBJECT_PROPERTIES_DEFINE_BASE ( - PROP_MULTI_IDX, PROP_ADDR_FAMILY, + PROP_FLAGS, + PROP_HWADDR, PROP_IFACE, PROP_IFINDEX, - PROP_HWADDR, - PROP_UUID, - PROP_ROUTE_TABLE, + PROP_MULTI_IDX, PROP_ROUTE_METRIC, + PROP_ROUTE_TABLE, PROP_TIMEOUT, + PROP_UUID, ); typedef struct _NMDhcpClientPrivate { NMDedupMultiIndex *multi_idx; char * iface; - GByteArray * hwaddr; + GBytes * hwaddr; char * uuid; - GByteArray * duid; + GBytes * duid; GBytes * client_id; char * hostname; pid_t pid; @@ -138,7 +139,7 @@ nm_dhcp_client_get_uuid (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->uuid; } -const GByteArray * +GBytes * nm_dhcp_client_get_duid (NMDhcpClient *self) { g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); @@ -146,7 +147,7 @@ nm_dhcp_client_get_duid (NMDhcpClient *self) return NM_DHCP_CLIENT_GET_PRIVATE (self)->duid; } -const GByteArray * +GBytes * nm_dhcp_client_get_hw_addr (NMDhcpClient *self) { g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); @@ -238,20 +239,6 @@ nm_dhcp_client_set_client_id_bin (NMDhcpClient *self, _set_client_id (self, b, TRUE); } -void -nm_dhcp_client_set_client_id_str (NMDhcpClient *self, - const char *dhcp_client_id) -{ - g_return_if_fail (NM_IS_DHCP_CLIENT (self)); - g_return_if_fail (!dhcp_client_id || dhcp_client_id[0]); - - _set_client_id (self, - dhcp_client_id - ? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id) - : NULL, - TRUE); -} - const char * nm_dhcp_client_get_hostname (NMDhcpClient *self) { @@ -261,6 +248,14 @@ nm_dhcp_client_get_hostname (NMDhcpClient *self) } gboolean +nm_dhcp_client_get_info_only (NMDhcpClient *self) +{ + g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + + return NM_DHCP_CLIENT_GET_PRIVATE (self)->info_only; +} + +gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self) { g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); @@ -339,13 +334,13 @@ nm_dhcp_client_stop_pid (pid_t pid, const char *iface) g_return_if_fail (pid > 1); - nm_utils_kill_child_sync (pid, SIGTERM, LOGD_DHCP, name ? name : "dhcp-client", NULL, + nm_utils_kill_child_sync (pid, SIGTERM, LOGD_DHCP, name ?: "dhcp-client", NULL, 1000 / 2, 1000 / 20); g_free (name); } static void -stop (NMDhcpClient *self, gboolean release, const GByteArray *duid) +stop (NMDhcpClient *self, gboolean release, GBytes *duid) { NMDhcpClientPrivate *priv; @@ -359,32 +354,30 @@ stop (NMDhcpClient *self, gboolean release, const GByteArray *duid) nm_dhcp_client_stop_pid (priv->pid, priv->iface); } priv->pid = -1; - priv->info_only = FALSE; } void nm_dhcp_client_set_state (NMDhcpClient *self, NMDhcpState new_state, - GObject *ip_config, + NMIPConfig *ip_config, GHashTable *options) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); gs_free char *event_id = NULL; + if (new_state == NM_DHCP_STATE_BOUND) { + g_return_if_fail (NM_IS_IP_CONFIG (ip_config, priv->addr_family)); + g_return_if_fail (options); + } else { + g_return_if_fail (!ip_config); + g_return_if_fail (!options); + } + if (new_state >= NM_DHCP_STATE_BOUND) timeout_cleanup (self); if (new_state >= NM_DHCP_STATE_TIMEOUT) watch_cleanup (self); - if (new_state == NM_DHCP_STATE_BOUND) { - g_assert ( (priv->addr_family == AF_INET && NM_IS_IP4_CONFIG (ip_config)) - || (priv->addr_family == AF_INET6 && NM_IS_IP6_CONFIG (ip_config))); - g_assert (options); - } else { - g_assert (ip_config == NULL); - g_assert (options == NULL); - } - /* The client may send same-state transitions for RENEW/REBIND events and * the lease may have changed, so handle same-state transitions for the * BOUND state. Ignore same-state transitions for other events since @@ -492,10 +485,9 @@ nm_dhcp_client_watch_child (NMDhcpClient *self, pid_t pid) gboolean nm_dhcp_client_start_ip4 (NMDhcpClient *self, - const char *dhcp_client_id, + GBytes *client_id, const char *dhcp_anycast_addr, const char *hostname, - gboolean use_fqdn, const char *last_ip4_address) { NMDhcpClientPrivate *priv; @@ -512,19 +504,19 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self, else _LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); - nm_dhcp_client_set_client_id_str (self, dhcp_client_id); + nm_dhcp_client_set_client_id (self, client_id); g_clear_pointer (&priv->hostname, g_free); priv->hostname = g_strdup (hostname); - priv->use_fqdn = use_fqdn; return NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_anycast_addr, last_ip4_address); } -static GByteArray * +static GBytes * generate_duid_from_machine_id (void) { - GByteArray *duid; + const int DUID_SIZE = 18; + guint8 *duid_buffer; GChecksum *sum; guint8 buffer[32]; /* SHA256 digest size */ gsize sumlen = sizeof (buffer); @@ -532,6 +524,7 @@ generate_duid_from_machine_id (void) uuid_t uuid; gs_free char *machine_id_s = NULL; gs_free char *str = NULL; + GBytes *duid; machine_id_s = nm_utils_machine_id_read (); if (nm_utils_machine_id_parse (machine_id_s, uuid)) { @@ -554,36 +547,31 @@ generate_duid_from_machine_id (void) * u16: type (DUID-UUID = 4) * u8[16]: UUID bytes */ - duid = g_byte_array_sized_new (18); - g_byte_array_append (duid, (guint8 *) &duid_type, sizeof (duid_type)); + duid_buffer = g_malloc (DUID_SIZE); + + G_STATIC_ASSERT_EXPR (sizeof (duid_type) == 2); + memcpy (&duid_buffer[0], &duid_type, 2); /* Since SHA256 is 256 bits, but UUID is 128 bits, we just take the first * 128 bits of the SHA256 as the DUID-UUID. */ - g_byte_array_append (duid, buffer, 16); + memcpy (&duid_buffer[2], buffer, 16); + duid = g_bytes_new_take (duid_buffer, DUID_SIZE); nm_log_dbg (LOGD_DHCP, "dhcp: generated DUID %s", (str = nm_dhcp_utils_duid_to_string (duid))); return duid; } -static GByteArray * +static GBytes * get_duid (NMDhcpClient *self) { - static GByteArray *duid = NULL; - GByteArray *copy = NULL; + static GBytes *duid = NULL; - if (G_UNLIKELY (duid == NULL)) { + if (G_UNLIKELY (!duid)) duid = generate_duid_from_machine_id (); - g_assert (duid); - } - if (G_LIKELY (duid)) { - copy = g_byte_array_sized_new (duid->len); - g_byte_array_append (copy, duid->data, duid->len); - } - - return copy; + return g_bytes_ref (duid); } gboolean @@ -591,7 +579,6 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, const char *dhcp_anycast_addr, const struct in6_addr *ll_addr, const char *hostname, - gboolean info_only, NMSettingIP6ConfigPrivacy privacy, guint needed_prefixes) { @@ -616,8 +603,6 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, g_clear_pointer (&priv->hostname, g_free); priv->hostname = g_strdup (hostname); - priv->info_only = info_only; - if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) _LOGI ("activation: beginning transaction (no timeout)"); else @@ -626,7 +611,6 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self, return NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self, dhcp_anycast_addr, ll_addr, - info_only, privacy, priv->duid, needed_prefixes); @@ -675,8 +659,10 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) out: if (remove (pid_file) == -1) { - nm_log_dbg (LOGD_DHCP, "dhcp: could not remove pid file \"%s\": %d (%s)", - pid_file, errno, g_strerror (errno)); + int errsv = errno; + + nm_log_dbg (LOGD_DHCP, "dhcp: could not remove pid file \"%s\": %s (%d)", + pid_file, g_strerror (errsv), errsv); } } @@ -751,14 +737,6 @@ maybe_add_option (NMDhcpClient *self, GVariant *value) { char *str_value = NULL; - const char **p; - static const char *ignored_keys[] = { - "interface", - "pid", - "reason", - "dhcp_message_type", - NULL - }; g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING)); @@ -766,10 +744,11 @@ maybe_add_option (NMDhcpClient *self, return; /* Filter out stuff that's not actually new DHCP options */ - for (p = ignored_keys; *p; p++) { - if (!strcmp (*p, key)) - return; - } + if (NM_IN_STRSET (key, "interface", + "pid", + "reason", + "dhcp_message_type")) + return; if (g_str_has_prefix (key, NEW_TAG)) key += NM_STRLEN (NEW_TAG); @@ -792,8 +771,8 @@ nm_dhcp_client_handle_event (gpointer unused, NMDhcpClientPrivate *priv; guint32 old_state; guint32 new_state; - GHashTable *str_options = NULL; - GObject *ip_config = NULL; + gs_unref_hashtable GHashTable *str_options = NULL; + gs_unref_object NMIPConfig *ip_config = NULL; NMPlatformIP6Address prefix = { 0, }; g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); @@ -811,8 +790,8 @@ nm_dhcp_client_handle_event (gpointer unused, old_state = priv->state; new_state = reason_to_state (self, priv->iface, reason); - _LOGD ("DHCP reason '%s' -> state '%s'", - reason, state_to_string (new_state)); + _LOGD ("DHCP state '%s' -> '%s' (reason: '%s')", + state_to_string (old_state), state_to_string (new_state), reason); if (new_state == NM_DHCP_STATE_BOUND) { GVariantIter iter; @@ -837,24 +816,24 @@ nm_dhcp_client_handle_event (gpointer unused, } /* Create the IP config */ - g_warn_if_fail (g_hash_table_size (str_options)); - if (g_hash_table_size (str_options)) { + if (g_hash_table_size (str_options) > 0) { if (priv->addr_family == AF_INET) { - ip_config = (GObject *) nm_dhcp_utils_ip4_config_from_options (nm_dhcp_client_get_multi_idx (self), - priv->ifindex, - priv->iface, - str_options, - priv->route_table, - priv->route_metric); + ip_config = NM_IP_CONFIG_CAST (nm_dhcp_utils_ip4_config_from_options (nm_dhcp_client_get_multi_idx (self), + priv->ifindex, + priv->iface, + str_options, + priv->route_table, + priv->route_metric)); } else { prefix = nm_dhcp_utils_ip6_prefix_from_options (str_options); - ip_config = (GObject *) nm_dhcp_utils_ip6_config_from_options (nm_dhcp_client_get_multi_idx (self), - priv->ifindex, - priv->iface, - str_options, - priv->info_only); + ip_config = NM_IP_CONFIG_CAST (nm_dhcp_utils_ip6_config_from_options (nm_dhcp_client_get_multi_idx (self), + priv->ifindex, + priv->iface, + str_options, + priv->info_only)); } - } + } else + g_warn_if_reached (); } if (!IN6_IS_ADDR_UNSPECIFIED (&prefix.address)) { @@ -866,7 +845,8 @@ nm_dhcp_client_handle_event (gpointer unused, &prefix); } else { /* Fail if no valid IP config was received */ - if (new_state == NM_DHCP_STATE_BOUND && ip_config == NULL) { + if ( new_state == NM_DHCP_STATE_BOUND + && !ip_config) { _LOGW ("client bound but IP config not received"); new_state = NM_DHCP_STATE_FAIL; g_clear_pointer (&str_options, g_hash_table_unref); @@ -875,10 +855,6 @@ nm_dhcp_client_handle_event (gpointer unused, nm_dhcp_client_set_state (self, new_state, ip_config, str_options); } - if (str_options) - g_hash_table_destroy (str_options); - g_clear_object (&ip_config); - return TRUE; } @@ -923,8 +899,16 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE ((NMDhcpClient *) object); + guint flags; switch (prop_id) { + case PROP_FLAGS: + /* construct-only */ + flags = g_value_get_uint (value); + nm_assert ((flags & ~((guint) (NM_DHCP_CLIENT_FLAGS_INFO_ONLY | NM_DHCP_CLIENT_FLAGS_USE_FQDN))) == 0); + priv->info_only = NM_FLAGS_HAS (flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY); + priv->use_fqdn = NM_FLAGS_HAS (flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN); + break; case PROP_MULTI_IDX: /* construct-only */ priv->multi_idx = g_value_get_pointer (value); @@ -983,6 +967,8 @@ nm_dhcp_client_init (NMDhcpClient *self) priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DHCP_CLIENT, NMDhcpClientPrivate); self->_priv = priv; + c_list_init (&self->dhcp_client_lst); + priv->pid = -1; } @@ -997,6 +983,8 @@ dispose (GObject *object) * the DHCP client. */ + nm_assert (c_list_is_empty (&self->dhcp_client_lst)); + watch_cleanup (self); timeout_cleanup (self); @@ -1004,16 +992,8 @@ dispose (GObject *object) g_clear_pointer (&priv->hostname, g_free); g_clear_pointer (&priv->uuid, g_free); g_clear_pointer (&priv->client_id, g_bytes_unref); - - if (priv->hwaddr) { - g_byte_array_free (priv->hwaddr, TRUE); - priv->hwaddr = NULL; - } - - if (priv->duid) { - g_byte_array_free (priv->duid, TRUE); - priv->duid = NULL; - } + g_clear_pointer (&priv->hwaddr, g_bytes_unref); + g_clear_pointer (&priv->duid, g_bytes_unref); G_OBJECT_CLASS (nm_dhcp_client_parent_class)->dispose (object); @@ -1054,7 +1034,7 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) obj_properties[PROP_HWADDR] = g_param_spec_boxed (NM_DHCP_CLIENT_HWADDR, "", "", - G_TYPE_BYTE_ARRAY, + G_TYPE_BYTES, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); @@ -1088,6 +1068,12 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_FLAGS] = + g_param_spec_uint (NM_DHCP_CLIENT_FLAGS, "", "", + 0, G_MAXUINT32, 0, + 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] = |