Commit 30cdd124 authored by Dan Williams's avatar Dan Williams
Browse files

dhcp: handle DHCP clients that aren't subprocesses

Make the base class mostly ignorant of process IDs, except for a
few utility functions.
parent 37b6fc1c
......@@ -45,8 +45,7 @@ typedef struct {
GByteArray * duid;
guchar state;
GPid pid;
gboolean dead;
pid_t pid;
guint timeout_id;
guint watch_id;
guint32 remove_id;
......@@ -82,7 +81,7 @@ enum {
/********************************************/
GPid
pid_t
nm_dhcp_client_get_pid (NMDHCPClient *self)
{
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), -1);
......@@ -147,7 +146,7 @@ watch_cleanup (NMDHCPClient *self)
}
void
nm_dhcp_client_stop_pid (GPid pid, const char *iface)
nm_dhcp_client_stop_pid (pid_t pid, const char *iface)
{
char *name = iface ? g_strdup_printf ("dhcp-client-%s", iface) : NULL;
......@@ -164,12 +163,13 @@ stop (NMDHCPClient *self, gboolean release, const GByteArray *duid)
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
g_return_if_fail (priv->pid > 0);
/* Clean up the watch handler since we're explicitly killing the daemon */
watch_cleanup (self);
nm_dhcp_client_stop_pid (priv->pid, priv->iface);
if (priv->pid > 0) {
/* Clean up the watch handler since we're explicitly killing the daemon */
watch_cleanup (self);
nm_dhcp_client_stop_pid (priv->pid, priv->iface);
priv->pid = -1;
}
priv->info_only = FALSE;
}
......@@ -248,25 +248,26 @@ daemon_watch_cb (GPid pid, gint status, gpointer user_data)
watch_cleanup (self);
timeout_cleanup (self);
priv->dead = TRUE;
priv->pid = -1;
dhcp_client_set_state (self, new_state, TRUE, FALSE);
}
static void
start_monitor (NMDHCPClient *self)
void
nm_dhcp_client_watch_child (NMDHCPClient *self, pid_t pid)
{
NMDHCPClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
g_return_if_fail (priv->pid > 0);
g_return_if_fail (priv->pid == -1);
priv->pid = pid;
/* Set up a timeout on the transaction to kill it after the timeout */
g_assert (priv->timeout_id == 0);
priv->timeout_id = g_timeout_add_seconds (priv->timeout,
daemon_timeout,
self);
priv->watch_id = g_child_watch_add (priv->pid,
(GChildWatchFunc) daemon_watch_cb,
self);
g_assert (priv->watch_id == 0);
priv->watch_id = g_child_watch_add (pid, daemon_watch_cb, self);
}
gboolean
......@@ -287,11 +288,7 @@ nm_dhcp_client_start_ip4 (NMDHCPClient *self,
nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv4 transaction (timeout in %d seconds)",
priv->iface, priv->timeout);
priv->pid = NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_client_id, dhcp_anycast_addr, hostname);
if (priv->pid)
start_monitor (self);
return priv->pid ? TRUE : FALSE;
return NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, dhcp_client_id, dhcp_anycast_addr, hostname);
}
/* uuid_parse does not work for machine-id, so we use our own converter */
......@@ -456,15 +453,11 @@ nm_dhcp_client_start_ip6 (NMDHCPClient *self,
nm_log_info (LOGD_DHCP, "Activation (%s) Beginning DHCPv6 transaction (timeout in %d seconds)",
priv->iface, priv->timeout);
priv->pid = NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self,
dhcp_anycast_addr,
hostname,
info_only,
priv->duid);
if (priv->pid > 0)
start_monitor (self);
return priv->pid ? TRUE : FALSE;
return NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self,
dhcp_anycast_addr,
hostname,
info_only,
priv->duid);
}
void
......@@ -492,7 +485,7 @@ nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name)
exe = proc_contents;
if (!strcmp (exe, binary_name))
nm_dhcp_client_stop_pid ((GPid) tmp, NULL);
nm_dhcp_client_stop_pid ((pid_t) tmp, NULL);
}
}
......@@ -508,23 +501,24 @@ void
nm_dhcp_client_stop (NMDHCPClient *self, gboolean release)
{
NMDHCPClientPrivate *priv;
pid_t old_pid = 0;
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
/* Kill the DHCP client */
if (!priv->dead) {
NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release, priv->duid);
priv->dead = TRUE;
old_pid = priv->pid;
NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release, priv->duid);
if (old_pid > 0) {
nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction, DHCP client pid %d",
priv->iface, priv->pid);
}
priv->iface, old_pid);
} else
nm_log_info (LOGD_DHCP, "(%s): canceled DHCP transaction", priv->iface);
g_assert (priv->pid == -1);
/* And clean stuff up */
priv->pid = -1;
dhcp_client_set_state (self, DHC_END, FALSE, TRUE);
g_hash_table_remove_all (priv->options);
......
......@@ -83,20 +83,20 @@ typedef struct {
/* Methods */
GPid (*ip4_start) (NMDHCPClient *self,
const char *dhcp_client_id,
GByteArray *anycast_addr,
const char *hostname);
gboolean (*ip4_start) (NMDHCPClient *self,
const char *dhcp_client_id,
GByteArray *anycast_addr,
const char *hostname);
GPid (*ip6_start) (NMDHCPClient *self,
GByteArray *anycast_addr,
const char *hostname,
gboolean info_only,
const GByteArray *duid);
gboolean (*ip6_start) (NMDHCPClient *self,
GByteArray *anycast_addr,
const char *hostname,
gboolean info_only,
const GByteArray *duid);
void (*stop) (NMDHCPClient *self,
gboolean release,
const GByteArray *duid);
void (*stop) (NMDHCPClient *self,
gboolean release,
const GByteArray *duid);
/**
* get_duid:
......@@ -117,7 +117,7 @@ typedef struct {
GType nm_dhcp_client_get_type (void);
GPid nm_dhcp_client_get_pid (NMDHCPClient *self);
pid_t nm_dhcp_client_get_pid (NMDHCPClient *self);
const char *nm_dhcp_client_get_iface (NMDHCPClient *self);
......@@ -154,7 +154,9 @@ NMIP6Config *nm_dhcp_client_get_ip6_config (NMDHCPClient *self, gboolean test)
/* Backend helpers */
void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name);
void nm_dhcp_client_stop_pid (GPid pid, const char *iface);
void nm_dhcp_client_stop_pid (pid_t pid, const char *iface);
void nm_dhcp_client_watch_child (NMDHCPClient *self, pid_t pid);
#endif /* NM_DHCP_CLIENT_H */
......@@ -324,7 +324,7 @@ dhclient_child_setup (gpointer user_data G_GNUC_UNUSED)
nm_unblock_posix_signals (NULL);
}
static GPid
static gboolean
dhclient_start (NMDHCPClient *client,
const char *mode_opt,
const GByteArray *duid,
......@@ -332,7 +332,7 @@ dhclient_start (NMDHCPClient *client,
{
NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (client);
GPtrArray *argv = NULL;
GPid pid = -1;
pid_t pid;
GError *error = NULL;
const char *iface, *uuid, *system_bus_address;
char *binary_name, *cmd_str, *pid_file = NULL, *system_bus_address_env = NULL;
......@@ -340,7 +340,7 @@ dhclient_start (NMDHCPClient *client,
guint log_domain;
char *escaped, *preferred_leasefile_path = NULL;
g_return_val_if_fail (priv->pid_file == NULL, -1);
g_return_val_if_fail (priv->pid_file == NULL, FALSE);
iface = nm_dhcp_client_get_iface (client);
uuid = nm_dhcp_client_get_uuid (client);
......@@ -350,7 +350,7 @@ dhclient_start (NMDHCPClient *client,
if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) {
nm_log_warn (log_domain, "%s does not exist.", priv->path);
return -1;
return FALSE;
}
pid_file = g_strdup_printf (LOCALSTATEDIR "/run/dhclient%s-%s.pid",
......@@ -404,7 +404,8 @@ dhclient_start (NMDHCPClient *client,
iface, priv->lease_file,
error ? error->code : -1,
error && error->message ? error->message : "(unknown)");
return -1;
g_free (pid_file);
return FALSE;
}
}
......@@ -456,22 +457,24 @@ dhclient_start (NMDHCPClient *client,
nm_log_dbg (log_domain, "running: %s", cmd_str);
g_free (cmd_str);
if (!g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
if (g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
&dhclient_child_setup, NULL, &pid, &error)) {
nm_log_warn (log_domain, "dhclient failed to start: '%s'", error->message);
g_error_free (error);
pid = -1;
} else {
g_assert (pid > 0);
nm_log_info (log_domain, "dhclient started with pid %d", pid);
nm_dhcp_client_watch_child (client, pid);
priv->pid_file = pid_file;
} else {
nm_log_warn (log_domain, "dhclient failed to start: '%s'", error->message);
g_error_free (error);
g_free (pid_file);
}
g_ptr_array_free (argv, TRUE);
g_free (system_bus_address_env);
return pid;
return pid > 0 ? TRUE : FALSE;
}
static GPid
static gboolean
ip4_start (NMDHCPClient *client,
const char *dhcp_client_id,
GByteArray *dhcp_anycast_addr,
......@@ -486,13 +489,13 @@ ip4_start (NMDHCPClient *client,
priv->conf_file = create_dhclient_config (iface, FALSE, uuid, dhcp_client_id, dhcp_anycast_addr, hostname);
if (!priv->conf_file) {
nm_log_warn (LOGD_DHCP4, "(%s): error creating dhclient configuration file.", iface);
return -1;
return FALSE;
}
return dhclient_start (client, NULL, NULL, FALSE);
}
static GPid
static gboolean
ip6_start (NMDHCPClient *client,
GByteArray *dhcp_anycast_addr,
const char *hostname,
......@@ -508,7 +511,7 @@ ip6_start (NMDHCPClient *client,
priv->conf_file = create_dhclient_config (iface, TRUE, uuid, NULL, dhcp_anycast_addr, hostname);
if (!priv->conf_file) {
nm_log_warn (LOGD_DHCP6, "(%s): error creating dhclient6 configuration file.", iface);
return -1;
return FALSE;
}
return dhclient_start (client, info_only ? "-S" : "-N", duid, FALSE);
......@@ -533,7 +536,7 @@ stop (NMDHCPClient *client, gboolean release, const GByteArray *duid)
}
if (release) {
GPid rpid;
pid_t rpid;
rpid = dhclient_start (client, NULL, duid, TRUE);
if (rpid > 0) {
......
......@@ -86,7 +86,7 @@ dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED)
nm_unblock_posix_signals (NULL);
}
static GPid
static gboolean
ip4_start (NMDHCPClient *client,
const char *dhcp_client_id,
GByteArray *dhcp_anycast_addr,
......@@ -94,12 +94,12 @@ ip4_start (NMDHCPClient *client,
{
NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (client);
GPtrArray *argv = NULL;
GPid pid = -1;
pid_t pid = -1;
GError *error = NULL;
char *pid_contents = NULL, *binary_name, *cmd_str;
const char *iface;
g_return_val_if_fail (priv->pid_file == NULL, -1);
g_return_val_if_fail (priv->pid_file == NULL, FALSE);
iface = nm_dhcp_client_get_iface (client);
......@@ -110,7 +110,7 @@ ip4_start (NMDHCPClient *client,
if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) {
nm_log_warn (LOGD_DHCP4, "%s does not exist.", priv->path);
return -1;
return FALSE;
}
/* Kill any existing dhcpcd from the pidfile */
......@@ -152,20 +152,22 @@ ip4_start (NMDHCPClient *client,
nm_log_dbg (LOGD_DHCP4, "running: %s", cmd_str);
g_free (cmd_str);
if (!g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
&dhcpcd_child_setup, NULL, &pid, &error)) {
if (g_spawn_async (NULL, (char **) argv->pdata, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
&dhcpcd_child_setup, NULL, &pid, &error)) {
g_assert (pid > 0);
nm_log_info (LOGD_DHCP4, "dhcpcd started with pid %d", pid);
nm_dhcp_client_watch_child (client, pid);
} else {
nm_log_warn (LOGD_DHCP4, "dhcpcd failed to start. error: '%s'", error->message);
g_error_free (error);
pid = -1;
} else
nm_log_info (LOGD_DHCP4, "dhcpcd started with pid %d", pid);
}
g_free (pid_contents);
g_ptr_array_free (argv, TRUE);
return pid;
return pid > 0 ? TRUE : FALSE;
}
static GPid
static gboolean
ip6_start (NMDHCPClient *client,
GByteArray *dhcp_anycast_addr,
const char *hostname,
......@@ -173,7 +175,7 @@ ip6_start (NMDHCPClient *client,
const GByteArray *duid)
{
nm_log_warn (LOGD_DHCP6, "the dhcpcd backend does not support IPv6.");
return -1;
return FALSE;
}
static void
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment