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:
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
|
||||||
|
@@ -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"
|
||||||
|
@@ -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))
|
||||||
|
Reference in New Issue
Block a user