diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index ac8f29a10..9ea31ef7a 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -54,11 +54,35 @@ G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) #define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" typedef struct { + const char *path; char *conf_file; char *lease_file; char *pid_file; } NMDHCPDhclientPrivate; +const char * +nm_dhcp_dhclient_get_path (const char *try_first) +{ + static const char *dhclient_paths[] = { + "/sbin/dhclient", + "/usr/sbin/dhclient", + "/usr/pkg/sbin/dhclient", + "/usr/local/sbin/dhclient", + NULL + }; + const char **path = dhclient_paths; + + if (strlen (try_first) && g_file_test (try_first, G_FILE_TEST_EXISTS)) + return try_first; + + while (*path != NULL) { + if (g_file_test (*path, G_FILE_TEST_EXISTS)) + break; + path++; + } + + return *path; +} static char * get_leasefile_for_iface (const char * iface, const char *uuid, gboolean ipv6) @@ -478,13 +502,13 @@ dhclient_start (NMDHCPClient *client, return -1; } - if (!g_file_test (DHCLIENT_PATH, G_FILE_TEST_EXISTS)) { - nm_warning (DHCLIENT_PATH " does not exist."); + if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) { + nm_warning ("%s does not exist.", priv->path); return -1; } /* Kill any existing dhclient from the pidfile */ - binary_name = g_path_get_basename (DHCLIENT_PATH); + binary_name = g_path_get_basename (priv->path); nm_dhcp_client_stop_existing (priv->pid_file, binary_name); g_free (binary_name); @@ -495,7 +519,7 @@ dhclient_start (NMDHCPClient *client, } argv = g_ptr_array_new (); - g_ptr_array_add (argv, (gpointer) DHCLIENT_PATH); + g_ptr_array_add (argv, (gpointer) priv->path); g_ptr_array_add (argv, (gpointer) "-d"); @@ -710,6 +734,9 @@ out: static void nm_dhcp_dhclient_init (NMDHCPDhclient *self) { + NMDHCPDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); + + priv->path = nm_dhcp_dhclient_get_path (DHCLIENT_PATH); } static void diff --git a/src/dhcp-manager/nm-dhcp-dhclient.h b/src/dhcp-manager/nm-dhcp-dhclient.h index db9f73d25..be242de05 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.h +++ b/src/dhcp-manager/nm-dhcp-dhclient.h @@ -43,5 +43,7 @@ GType nm_dhcp_dhclient_get_type (void); GSList *nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid); +const char *nm_dhcp_dhclient_get_path (const char *try_first); + #endif /* NM_DHCP_DHCLIENT_H */ diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 1e014e70b..6895498a2 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -42,9 +42,33 @@ G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_DHCPCD) #define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" typedef struct { + const char *path; char *pid_file; } NMDHCPDhcpcdPrivate; +const char * +nm_dhcp_dhcpcd_get_path (const char *try_first) +{ + static const char *dhcpcd_paths[] = { + "/sbin/dhcpcd", + "/usr/sbin/dhcpcd", + "/usr/pkg/sbin/dhcpcd", + "/usr/local/sbin/dhcpcd", + NULL + }; + const char **path = dhcpcd_paths; + + if (strlen (try_first) && g_file_test (try_first, G_FILE_TEST_EXISTS)) + return try_first; + + while (*path != NULL) { + if (g_file_test (*path, G_FILE_TEST_EXISTS)) + break; + path++; + } + + return *path; +} GSList * nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid) @@ -83,18 +107,18 @@ real_ip4_start (NMDHCPClient *client, return -1; } - if (!g_file_test (DHCPCD_PATH, G_FILE_TEST_EXISTS)) { - nm_warning (DHCPCD_PATH " does not exist."); + if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) { + nm_warning ("%s does not exist.", priv->path); return -1; } - /* Kill any existing dhclient from the pidfile */ - binary_name = g_path_get_basename (DHCPCD_PATH); + /* Kill any existing dhcpcd from the pidfile */ + binary_name = g_path_get_basename (priv->path); nm_dhcp_client_stop_existing (priv->pid_file, binary_name); g_free (binary_name); argv = g_ptr_array_new (); - g_ptr_array_add (argv, (gpointer) DHCPCD_PATH); + g_ptr_array_add (argv, (gpointer) priv->path); g_ptr_array_add (argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */ @@ -230,6 +254,9 @@ out: static void nm_dhcp_dhcpcd_init (NMDHCPDhcpcd *self) { + NMDHCPDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); + + priv->path = nm_dhcp_dhcpcd_get_path (DHCPCD_PATH); } static void diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.h b/src/dhcp-manager/nm-dhcp-dhcpcd.h index 9a9812941..586c56978 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.h +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.h @@ -43,5 +43,7 @@ GType nm_dhcp_dhcpcd_get_type (void); GSList *nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid); +const char *nm_dhcp_dhcpcd_get_path (const char *try_first); + #endif /* NM_DHCP_DHCPCD_H */ diff --git a/src/dhcp-manager/nm-dhcp-manager.c b/src/dhcp-manager/nm-dhcp-manager.c index 374c66368..765606788 100644 --- a/src/dhcp-manager/nm-dhcp-manager.c +++ b/src/dhcp-manager/nm-dhcp-manager.c @@ -44,6 +44,35 @@ #include "nm-dbus-glib-types.h" #include "nm-glib-compat.h" +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GQuark +nm_dhcp_manager_error_quark (void) +{ + static GQuark ret = 0; + + if (ret == 0) + ret = g_quark_from_static_string ("nm_dhcp_manager_error"); + + return ret; +} + +GType +nm_dhcp_manager_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + ENUM_ENTRY (NM_DHCP_MANAGER_ERROR_BAD_CLIENT, "BadClient"), + ENUM_ENTRY (NM_DHCP_MANAGER_ERROR_INTERNAL, "InternalError"), + { 0, 0, 0 } + }; + etype = g_enum_register_static ("NMDhcpManagerError", values); + } + return etype; +} + #define NM_DHCP_CLIENT_DBUS_SERVICE "org.freedesktop.nm_dhcp_client" #define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" @@ -233,15 +262,48 @@ out: static GType get_client_type (const char *client, GError **error) { - g_return_val_if_fail (client != NULL, 0); + const char *dhclient_path = NULL; + const char *dhcpcd_path = NULL; - if (!strcmp (client, "dhclient") && strlen (DHCLIENT_PATH)) + dhclient_path = nm_dhcp_dhclient_get_path (DHCLIENT_PATH); + dhcpcd_path = nm_dhcp_dhcpcd_get_path (DHCPCD_PATH); + + if (!client) { + if (dhclient_path) + return NM_TYPE_DHCP_DHCLIENT; + else if (dhcpcd_path) + return NM_TYPE_DHCP_DHCPCD; + else { + g_set_error_literal (error, + NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, + _("no usable DHCP client could be found.")); + return 0; + } + } + + if (!strcmp (client, "dhclient")) { + if (!dhclient_path) { + g_set_error_literal (error, + NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, + _("'dhclient' could be found.")); + return 0; + } return NM_TYPE_DHCP_DHCLIENT; - else if (!strcmp (client, "dhcpcd") && strlen (DHCPCD_PATH)) - return NM_TYPE_DHCP_DHCPCD; - else - g_set_error (error, 0, 0, "unknown or missing DHCP client '%s'", client); + } + if (!strcmp (client, "dhcpcd")) { + if (!dhcpcd_path) { + g_set_error_literal (error, + NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, + _("'dhcpcd' could be found.")); + return 0; + } + return NM_TYPE_DHCP_DHCPCD; + } + + g_set_error (error, + NM_DHCP_MANAGER_ERROR, NM_DHCP_MANAGER_ERROR_BAD_CLIENT, + _("unsupported DHCP client '%s'"), client); return 0; } @@ -250,32 +312,19 @@ nm_dhcp_manager_new (const char *client, GError **error) { NMDHCPManagerPrivate *priv; DBusGConnection *g_connection; + GType client_type; - /* Set some defaults based on build-time options */ - if (!client) { - if (strlen (DHCLIENT_PATH) && g_file_test (DHCLIENT_PATH, G_FILE_TEST_EXISTS)) - client = "dhclient"; - else if (strlen (DHCPCD_PATH) && g_file_test (DHCPCD_PATH, G_FILE_TEST_EXISTS)) - client = "dhcpcd"; - else { - g_set_error_literal (error, 0, 0, - "no suitable DHCP client; see 'man NetworkManager'" - " to specify one."); - return NULL; - } - } + client_type = get_client_type (client, error); + if (!client_type) + return NULL; g_warn_if_fail (singleton == NULL); - g_return_val_if_fail (client != NULL, NULL); singleton = g_object_new (NM_TYPE_DHCP_MANAGER, NULL); priv = NM_DHCP_MANAGER_GET_PRIVATE (singleton); - /* Figure out which DHCP client to use */ - priv->client_type = get_client_type (client, error); - if (!priv->client_type) - goto error; - + /* Client-specific setup */ + priv->client_type = client_type; if (priv->client_type == NM_TYPE_DHCP_DHCLIENT) priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config; else if (priv->client_type == NM_TYPE_DHCP_DHCPCD) @@ -286,10 +335,7 @@ nm_dhcp_manager_new (const char *client, GError **error) priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) g_object_unref); - if (!priv->clients) { - g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager"); - goto error; - } + g_assert (priv->clients); priv->dbus_mgr = nm_dbus_manager_get (); g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); @@ -297,10 +343,7 @@ nm_dhcp_manager_new (const char *client, GError **error) NM_DHCP_CLIENT_DBUS_SERVICE, "/", NM_DHCP_CLIENT_DBUS_IFACE); - if (!priv->proxy) { - g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager proxy"); - goto error; - } + g_assert (priv->proxy); dbus_g_proxy_add_signal (priv->proxy, "Event", @@ -313,11 +356,6 @@ nm_dhcp_manager_new (const char *client, GError **error) NULL); return singleton; - -error: - g_object_unref (singleton); - singleton = NULL; - return singleton; } #define STATE_ID_TAG "state-id" diff --git a/src/dhcp-manager/nm-dhcp-manager.h b/src/dhcp-manager/nm-dhcp-manager.h index df78f1885..9d83d0960 100644 --- a/src/dhcp-manager/nm-dhcp-manager.h +++ b/src/dhcp-manager/nm-dhcp-manager.h @@ -33,6 +33,18 @@ #include "nm-dhcp4-config.h" #include "nm-hostname-provider.h" +enum { + NM_DHCP_MANAGER_ERROR_BAD_CLIENT = 0, + NM_DHCP_MANAGER_ERROR_INTERNAL = 1, +}; + +#define NM_DHCP_MANAGER_ERROR (nm_dhcp_manager_error_quark ()) +#define NN_TYPE_DHCP_MANAGER_ERROR (nm_dhcp_manager_error_get_type ()) + +GQuark nm_dhcp_manager_error_quark (void); +GType nm_dhcp_manager_error_get_type (void); + + #define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type ()) #define NM_DHCP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_MANAGER, NMDHCPManager)) #define NM_DHCP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_MANAGER, NMDHCPManagerClass))