diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c index 836d40f93..d6cfbf3f7 100644 --- a/src/core/dhcp/nm-dhcp-client.c +++ b/src/core/dhcp/nm-dhcp-client.c @@ -50,7 +50,9 @@ typedef struct _NMDhcpClientPrivate { union { struct { - int _unused; + struct { + GDBusMethodInvocation *invocation; + } bound; } v4; struct { GSource *lladdr_timeout_source; @@ -74,7 +76,6 @@ G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) /*****************************************************************************/ static gboolean _dhcp_client_accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error); -static gboolean _dhcp_client_can_accept(NMDhcpClient *self); _nm_unused static gboolean _dhcp_client_decline(NMDhcpClient *self, const NML3ConfigData *l3cd, @@ -419,8 +420,7 @@ _nm_dhcp_client_notify(NMDhcpClient *self, * as a static address (bypassing ACD), then NML3Cfg is aware of that and signals * immediate success. */ - if (_dhcp_client_can_accept(self) && client_event_type == NM_DHCP_CLIENT_EVENT_TYPE_BOUND - && priv->l3cd + if (client_event_type == NM_DHCP_CLIENT_EVENT_TYPE_BOUND && priv->l3cd && nm_l3_config_data_get_num_addresses(priv->l3cd, priv->config.addr_family) > 0) { priv->l3cfg_notify.wait_dhcp_commit = TRUE; } else { @@ -483,6 +483,25 @@ nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid) watch_cleanup(self); } +static gboolean +_accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error) +{ + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + + if (!NM_IS_IPv4(priv->config.addr_family)) + return TRUE; + + if (!priv->v4.bound.invocation) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "calling accept in unexpected script state"); + return FALSE; + } + + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + return TRUE; +} + static gboolean _dhcp_client_accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **error) { @@ -495,27 +514,29 @@ _dhcp_client_accept(NMDhcpClient *self, const NML3ConfigData *l3cd, GError **err g_return_val_if_fail(NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd, FALSE); - if (!klass->accept) - return TRUE; - return klass->accept(self, l3cd, error); } static gboolean -_dhcp_client_can_accept(NMDhcpClient *self) +decline(NMDhcpClient *self, const NML3ConfigData *l3cd, const char *error_message, GError **error) { - gboolean can_accept; - NMDhcpClientClass *klass; + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - nm_assert(NM_IS_DHCP_CLIENT(self)); + if (!NM_IS_IPv4(priv->config.addr_family)) + return TRUE; - klass = NM_DHCP_CLIENT_GET_CLASS(self); + if (!priv->v4.bound.invocation) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "calling decline in unexpected script state"); + return FALSE; + } - can_accept = !!klass->accept; - - nm_assert(can_accept == (!!klass->decline)); - - return can_accept; + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "acd failed"); + return TRUE; } static gboolean @@ -533,9 +554,6 @@ _dhcp_client_decline(NMDhcpClient *self, g_return_val_if_fail(NM_DHCP_CLIENT_GET_PRIVATE(self)->l3cd, FALSE); - if (!klass->decline) - return TRUE; - return klass->decline(self, l3cd, error_message, error); } @@ -801,6 +819,13 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) priv->is_stopped = TRUE; + if (NM_IS_IPv4(priv->config.addr_family) && priv->v4.bound.invocation) { + g_dbus_method_invocation_return_error(g_steal_pointer(&priv->v4.bound.invocation), + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_FAILED, + "dhcp stopping"); + } + priv->l3cfg_notify.wait_dhcp_commit = FALSE; priv->l3cfg_notify.wait_ll_address = FALSE; l3_cfg_notify_check_connected(self); @@ -934,12 +959,13 @@ nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient *self, const NMPlatformIP } gboolean -nm_dhcp_client_handle_event(gpointer unused, - const char *iface, - int pid, - GVariant *options, - const char *reason, - NMDhcpClient *self) +nm_dhcp_client_handle_event(gpointer unused, + const char *iface, + int pid, + GVariant *options, + const char *reason, + GDBusMethodInvocation *invocation, + NMDhcpClient *self) { NMDhcpClientPrivate *priv; nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL; @@ -953,6 +979,7 @@ nm_dhcp_client_handle_event(gpointer unused, g_return_val_if_fail(pid > 0, FALSE); g_return_val_if_fail(g_variant_is_of_type(options, G_VARIANT_TYPE_VARDICT), FALSE); g_return_val_if_fail(reason != NULL, FALSE); + g_return_val_if_fail(G_IS_DBUS_METHOD_INVOCATION(invocation), FALSE); priv = NM_DHCP_CLIENT_GET_PRIVATE(self); @@ -964,7 +991,7 @@ nm_dhcp_client_handle_event(gpointer unused, _LOGD("DHCP event (reason: '%s')", reason); if (NM_IN_STRSET_ASCII_CASE(reason, "preinit")) - return TRUE; + goto out_handled; if (NM_IN_STRSET_ASCII_CASE(reason, "bound", "bound6", "static")) client_event_type = NM_DHCP_CLIENT_EVENT_TYPE_BOUND; @@ -1028,7 +1055,7 @@ nm_dhcp_client_handle_event(gpointer unused, * of the DHCP client instance. Instead, we just signal the prefix * to the device. */ nm_dhcp_client_emit_ipv6_prefix_delegated(self, &prefix); - return TRUE; + goto out_handled; } if (NM_IN_SET(client_event_type, @@ -1040,7 +1067,20 @@ nm_dhcp_client_handle_event(gpointer unused, client_event_type = NM_DHCP_CLIENT_EVENT_TYPE_FAIL; } + if (priv->v4.bound.invocation) + g_dbus_method_invocation_return_value(g_steal_pointer(&priv->v4.bound.invocation), NULL); + + if (NM_IS_IPv4(priv->config.addr_family) + && NM_IN_SET(client_event_type, + NM_DHCP_CLIENT_EVENT_TYPE_BOUND, + NM_DHCP_CLIENT_EVENT_TYPE_EXTENDED)) + priv->v4.bound.invocation = g_steal_pointer(&invocation); + _nm_dhcp_client_notify(self, client_event_type, l3cd); + +out_handled: + if (invocation) + g_dbus_method_invocation_return_value(invocation, NULL); return TRUE; } @@ -1185,7 +1225,10 @@ set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *ps * explicitly initialize the respective union member. */ if (NM_IS_IPv4(priv->config.addr_family)) { priv->v4 = (typeof(priv->v4)){ - ._unused = 0, + .bound = + { + .invocation = NULL, + }, }; } else { priv->v6 = (typeof(priv->v6)){ @@ -1255,6 +1298,8 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class) object_class->dispose = dispose; object_class->finalize = finalize; object_class->set_property = set_property; + client_class->accept = _accept; + client_class->decline = decline; client_class->stop = stop; client_class->get_duid = get_duid; diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h index 283d3af44..e4b999292 100644 --- a/src/core/dhcp/nm-dhcp-client.h +++ b/src/core/dhcp/nm-dhcp-client.h @@ -261,12 +261,13 @@ void _nm_dhcp_client_notify(NMDhcpClient *self, NMDhcpClientEventType client_event_type, const NML3ConfigData *l3cd); -gboolean nm_dhcp_client_handle_event(gpointer unused, - const char *iface, - int pid, - GVariant *options, - const char *reason, - NMDhcpClient *self); +gboolean nm_dhcp_client_handle_event(gpointer unused, + const char *iface, + int pid, + GVariant *options, + const char *reason, + GDBusMethodInvocation *invocation, + NMDhcpClient *self); void nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient *self, const NMPlatformIP6Address *prefix); diff --git a/src/core/dhcp/nm-dhcp-helper.c b/src/core/dhcp/nm-dhcp-helper.c index 41862f2b6..aab658a2a 100644 --- a/src/core/dhcp/nm-dhcp-helper.c +++ b/src/core/dhcp/nm-dhcp-helper.c @@ -100,21 +100,6 @@ next:; return g_variant_ref_sink(g_variant_new("(a{sv})", &builder)); } -static void -kill_pid(void) -{ - const char *pid_str; - pid_t pid = 0; - - pid_str = getenv("pid"); - if (pid_str) - pid = strtol(pid_str, NULL, 10); - if (pid) { - _LOGI("a fatal error occurred, kill dhclient instance with pid %d", pid); - kill(pid, SIGTERM); - } -} - int main(int argc, char *argv[]) { @@ -180,7 +165,7 @@ do_notify: parameters, NULL, G_DBUS_CALL_FLAGS_NONE, - 1000, + 60000, NULL, &error); @@ -236,7 +221,5 @@ do_notify: } out: - if (!success) - kill_pid(); return success ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/src/core/dhcp/nm-dhcp-listener.c b/src/core/dhcp/nm-dhcp-listener.c index 2c567593b..0854c1dcb 100644 --- a/src/core/dhcp/nm-dhcp-listener.c +++ b/src/core/dhcp/nm-dhcp-listener.c @@ -128,7 +128,7 @@ get_option(GVariant *options, const char *key) } static void -_method_call_handle(NMDhcpListener *self, GVariant *parameters) +_method_call_handle(NMDhcpListener *self, GDBusMethodInvocation *invocation, GVariant *parameters) { gs_free char *iface = NULL; gs_free char *pid_str = NULL; @@ -142,23 +142,23 @@ _method_call_handle(NMDhcpListener *self, GVariant *parameters) iface = get_option(options, "interface"); if (iface == NULL) { _LOGW("dhcp-event: didn't have associated interface."); - return; + goto out; } pid_str = get_option(options, "pid"); pid = _nm_utils_ascii_str_to_int64(pid_str, 10, 0, G_MAXINT32, -1); if (pid == -1) { _LOGW("dhcp-event: couldn't convert PID '%s' to an integer", pid_str ?: "(null)"); - return; + goto out; } reason = get_option(options, "reason"); if (reason == NULL) { _LOGW("dhcp-event: (pid %d) DHCP event didn't have a reason", pid); - return; + goto out; } - g_signal_emit(self, signals[EVENT], 0, iface, pid, options, reason, &handled); + g_signal_emit(self, signals[EVENT], 0, iface, pid, options, reason, invocation, &handled); if (!handled) { if (g_ascii_strcasecmp(reason, "RELEASE") == 0) { /* Ignore event when the dhcp client gets killed and we receive its last message */ @@ -166,6 +166,10 @@ _method_call_handle(NMDhcpListener *self, GVariant *parameters) } else _LOGW("dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface); } + +out: + if (!handled) + g_dbus_method_invocation_return_value(invocation, NULL); } static void @@ -190,8 +194,7 @@ _method_call(GDBusConnection *connection, return; } - _method_call_handle(self, parameters); - g_dbus_method_invocation_return_value(invocation, NULL); + _method_call_handle(self, invocation, parameters); } static GDBusInterfaceInfo *const interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO( @@ -311,9 +314,10 @@ nm_dhcp_listener_class_init(NMDhcpListenerClass *listener_class) NULL, NULL, G_TYPE_BOOLEAN, /* listeners return TRUE if handled */ - 4, + 5, G_TYPE_STRING, /* iface */ G_TYPE_INT, /* pid */ G_TYPE_VARIANT, /* options */ - G_TYPE_STRING); /* reason */ + G_TYPE_STRING, /* reason */ + G_TYPE_DBUS_METHOD_INVOCATION /* invocation*/); }