dhcp: make client selection more forgiving

If your distributor forgot to set up the client path for you, this
makes NM look in the right places and allows you to use either client
if it's installed, no matter what NM was configured with.
This commit is contained in:
Dan Williams
2010-03-23 14:22:10 -07:00
parent 55728349a1
commit 78dd4fc9f2
6 changed files with 155 additions and 47 deletions

View File

@@ -54,11 +54,35 @@ G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT)
#define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" #define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action"
typedef struct { typedef struct {
const char *path;
char *conf_file; char *conf_file;
char *lease_file; char *lease_file;
char *pid_file; char *pid_file;
} NMDHCPDhclientPrivate; } 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 * static char *
get_leasefile_for_iface (const char * iface, const char *uuid, gboolean ipv6) get_leasefile_for_iface (const char * iface, const char *uuid, gboolean ipv6)
@@ -478,13 +502,13 @@ dhclient_start (NMDHCPClient *client,
return -1; return -1;
} }
if (!g_file_test (DHCLIENT_PATH, G_FILE_TEST_EXISTS)) { if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) {
nm_warning (DHCLIENT_PATH " does not exist."); nm_warning ("%s does not exist.", priv->path);
return -1; return -1;
} }
/* Kill any existing dhclient from the pidfile */ /* 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); nm_dhcp_client_stop_existing (priv->pid_file, binary_name);
g_free (binary_name); g_free (binary_name);
@@ -495,7 +519,7 @@ dhclient_start (NMDHCPClient *client,
} }
argv = g_ptr_array_new (); 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"); g_ptr_array_add (argv, (gpointer) "-d");
@@ -710,6 +734,9 @@ out:
static void static void
nm_dhcp_dhclient_init (NMDHCPDhclient *self) 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 static void

View File

@@ -43,5 +43,7 @@ GType nm_dhcp_dhclient_get_type (void);
GSList *nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid); 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 */ #endif /* NM_DHCP_DHCLIENT_H */

View File

@@ -42,9 +42,33 @@ G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_DHCPCD)
#define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action" #define ACTION_SCRIPT_PATH LIBEXECDIR "/nm-dhcp-client.action"
typedef struct { typedef struct {
const char *path;
char *pid_file; char *pid_file;
} NMDHCPDhcpcdPrivate; } 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 * GSList *
nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid) nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid)
@@ -83,18 +107,18 @@ real_ip4_start (NMDHCPClient *client,
return -1; return -1;
} }
if (!g_file_test (DHCPCD_PATH, G_FILE_TEST_EXISTS)) { if (!g_file_test (priv->path, G_FILE_TEST_EXISTS)) {
nm_warning (DHCPCD_PATH " does not exist."); nm_warning ("%s does not exist.", priv->path);
return -1; return -1;
} }
/* Kill any existing dhclient from the pidfile */ /* Kill any existing dhcpcd from the pidfile */
binary_name = g_path_get_basename (DHCPCD_PATH); binary_name = g_path_get_basename (priv->path);
nm_dhcp_client_stop_existing (priv->pid_file, binary_name); nm_dhcp_client_stop_existing (priv->pid_file, binary_name);
g_free (binary_name); g_free (binary_name);
argv = g_ptr_array_new (); 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()) */ g_ptr_array_add (argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */
@@ -230,6 +254,9 @@ out:
static void static void
nm_dhcp_dhcpcd_init (NMDHCPDhcpcd *self) 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 static void

View File

@@ -43,5 +43,7 @@ GType nm_dhcp_dhcpcd_get_type (void);
GSList *nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid); 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 */ #endif /* NM_DHCP_DHCPCD_H */

View File

@@ -44,6 +44,35 @@
#include "nm-dbus-glib-types.h" #include "nm-dbus-glib-types.h"
#include "nm-glib-compat.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_SERVICE "org.freedesktop.nm_dhcp_client"
#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" #define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client"
@@ -233,15 +262,48 @@ out:
static GType static GType
get_client_type (const char *client, GError **error) 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; 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; return 0;
} }
@@ -250,32 +312,19 @@ nm_dhcp_manager_new (const char *client, GError **error)
{ {
NMDHCPManagerPrivate *priv; NMDHCPManagerPrivate *priv;
DBusGConnection *g_connection; DBusGConnection *g_connection;
GType client_type;
/* Set some defaults based on build-time options */ client_type = get_client_type (client, error);
if (!client) { if (!client_type)
if (strlen (DHCLIENT_PATH) && g_file_test (DHCLIENT_PATH, G_FILE_TEST_EXISTS)) return NULL;
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;
}
}
g_warn_if_fail (singleton == NULL); g_warn_if_fail (singleton == NULL);
g_return_val_if_fail (client != NULL, NULL);
singleton = g_object_new (NM_TYPE_DHCP_MANAGER, NULL); singleton = g_object_new (NM_TYPE_DHCP_MANAGER, NULL);
priv = NM_DHCP_MANAGER_GET_PRIVATE (singleton); priv = NM_DHCP_MANAGER_GET_PRIVATE (singleton);
/* Figure out which DHCP client to use */ /* Client-specific setup */
priv->client_type = get_client_type (client, error); priv->client_type = client_type;
if (!priv->client_type)
goto error;
if (priv->client_type == NM_TYPE_DHCP_DHCLIENT) if (priv->client_type == NM_TYPE_DHCP_DHCLIENT)
priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config; priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config;
else if (priv->client_type == NM_TYPE_DHCP_DHCPCD) 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, priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, NULL,
(GDestroyNotify) g_object_unref); (GDestroyNotify) g_object_unref);
if (!priv->clients) { g_assert (priv->clients);
g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager");
goto error;
}
priv->dbus_mgr = nm_dbus_manager_get (); priv->dbus_mgr = nm_dbus_manager_get ();
g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); 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_SERVICE,
"/", "/",
NM_DHCP_CLIENT_DBUS_IFACE); NM_DHCP_CLIENT_DBUS_IFACE);
if (!priv->proxy) { g_assert (priv->proxy);
g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager proxy");
goto error;
}
dbus_g_proxy_add_signal (priv->proxy, dbus_g_proxy_add_signal (priv->proxy,
"Event", "Event",
@@ -313,11 +356,6 @@ nm_dhcp_manager_new (const char *client, GError **error)
NULL); NULL);
return singleton; return singleton;
error:
g_object_unref (singleton);
singleton = NULL;
return singleton;
} }
#define STATE_ID_TAG "state-id" #define STATE_ID_TAG "state-id"

View File

@@ -33,6 +33,18 @@
#include "nm-dhcp4-config.h" #include "nm-dhcp4-config.h"
#include "nm-hostname-provider.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_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(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)) #define NM_DHCP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_MANAGER, NMDHCPManagerClass))