dhcp: allow runtime DHCP client selection via config file

This commit is contained in:
Dan Williams
2010-01-12 22:55:24 -08:00
parent 1806235049
commit 702836b42f
10 changed files with 156 additions and 109 deletions

View File

@@ -286,67 +286,73 @@ else
fi
AC_SUBST(PPPD_PLUGIN_DIR)
# DHCP client
AC_ARG_WITH([dhcp-client], AS_HELP_STRING([--with-dhcp-client=dhcpcd|dhclient], [path to the chosen dhcp client]))
# dhclient support
AC_ARG_WITH([dhclient], AS_HELP_STRING([--with-dhclient=yes|no|path], [Enable dhclient 4.x support]))
# If a full path is given, use that and do not test if it works or not.
case "${with_dhcp_client}" in
case "${with_dhclient}" in
/*)
DHCP_CLIENT_PATH="${with_dhcp_client}"
AC_MSG_NOTICE(using the DHCP client ${DHCP_CLIENT_PATH})
DHCLIENT_PATH="${with_dhclient}"
AC_MSG_NOTICE(using dhclient at ${DHCLIENT_PATH})
;;
no) AC_MSG_NOTICE(dhclient support disabled)
;;
*)
AC_MSG_CHECKING(for dhclient)
# NM only works with ISC dhclient - other derivatives don't have
# the same userland. NM also requires dhclient 4.x since older
# versions do not have IPv6 support.
for path in /sbin /usr/sbin /usr/pkg/sbin /usr/local/sbin; do
test -x "${path}/dhclient" || continue
case `"$path/dhclient" --version 2>&1` in
"isc-dhclient-4"*) DHCLIENT_PATH="$path/dhclient"; break;;
esac
done
if test -n "${DHCLIENT_PATH}"; then
AC_MSG_RESULT($DHCLIENT_PATH)
else
AC_MSG_RESULT(no)
fi
;;
esac
if test -z "$DHCP_CLIENT_PATH" -a \( -z "$with_dhcp_client" -o x`basename "$with_dhcp_client"` = "xdhclient" \); then
# We only work with ISC dhclient - the FreeBSD and OpenBSD derivatives don't have the same userland.
AC_MSG_CHECKING(for dhclient)
for client in "$with_dhcp_client" /sbin/dhclient /usr/pkg/sbin/dhclient /usr/local/sbin/dhclient; do
test -x "$client" || continue
case `"$client" --version 2>&1` in
"isc-dhclient-"*) DHCP_CLIENT_PATH="$client"; break;;
esac
done
if test -z "$DHCP_CLIENT_PATH"; then
AC_MSG_RESULT(no)
if test -n "$with_dhcp_client"; then
AC_MSG_ERROR([Could not find ISC dhclient])
# dhcpcd support
AC_ARG_WITH([dhcpcd], AS_HELP_STRING([--with-dhcpcd=yes|no|path], [Enable dhcpcd 4.x support]))
# If a full path is given, use that and do not test if it works or not.
case "${with_dhcpcd}" in
/*)
DHCPCD_PATH="${with_dhcpcd}"
AC_MSG_NOTICE(using dhcpcd at ${DHCPCD_PATH})
;;
no) AC_MSG_NOTICE(dhcpcd support disabled)
;;
*)
AC_MSG_CHECKING(for dhcpcd)
# We fully work with upstream dhcpcd-4
for path in /sbin /usr/sbin /usr/pkg/sbin /usr/local/sbin; do
test -x "${path}/dhclient" || continue
case `"$path/dhcpcd" --version 2>/dev/null` in
"dhcpcd "[123]*);;
"dhcpcd "*) DHCP_CLIENT_PATH="$path/dhcpcd"; break;;
esac
done
if test -n "${DHCPCD_PATH}"; then
AC_MSG_RESULT($DHCPCD_PATH)
else
AC_MSG_RESULT(no)
fi
else
AC_MSG_RESULT($DHCP_CLIENT_PATH)
fi
fi
if test -z "$DHCP_CLIENT_PATH" -a \( -z "$with_dhcp_client" -o x`basename "$with_dhcp_client"` = "xdhcpcd" \); then
test -n "$DHCP_CLIENT_PATH" && echo bar
# We fully work with upstream dhcpcd-4
AC_MSG_CHECKING([for dhcpcd])
for client in "$with_dhcp_client" /sbin/dhcpcd /usr/pkg/sbin/dhcpcd /usr/local/sbin/dhcpcd; do
test -x "$client" || continue
case `"$client" --version 2>/dev/null` in
"dhcpcd "[123]*);;
"dhcpcd "*) DHCP_CLIENT_PATH="$client"; break;;
esac
done
if test -z "$DHCP_CLIENT_PATH"; then
AC_MSG_RESULT(no)
if test -n "$with_dhcp_client"; then
AC_MSG_ERROR([Could not find dhcpcd-4 or newer])
fi
else
AC_MSG_RESULT($DHCP_CLIENT_PATH)
fi
fi
if test -z "$DHCP_CLIENT_PATH"; then
;;
esac
if test -z "$DHCPCD_PATH" -a -z "$DHCLIENT_PATH"; then
# DHCP clients are not a build time dependency, only runtime.
# dhclient has been the longtime default for NM and it's in /sbin
# in most distros, so use it.
AC_MSG_WARN([Could not find a suitable DHCP client])
DHCP_CLIENT_PATH=/sbin/dhclient
DHCLIENT_PATH=/sbin/dhclient
AC_MSG_WARN([Falling back to ISC dhclient, ${DHCP_CLIENT_PATH}])
fi
AC_SUBST(DHCP_CLIENT_PATH)
DHCP_CLIENT=`basename "$DHCP_CLIENT_PATH"`
if test "$DHCP_CLIENT" != "dhclient" -a "$DHCP_CLIENT" != "dhcpcd"; then
AC_MSG_ERROR([No backend for the DHCP client ${DHCP_CLIENT}])
fi
AC_SUBST(DHCP_CLIENT)
AC_SUBST(DHCLIENT_PATH)
AC_SUBST(DHCPCD_PATH)
# resolvconf support
AC_ARG_WITH([resolvconf],
@@ -492,12 +498,25 @@ NetworkManager.pc
AC_OUTPUT
echo
echo Distribution targeting: ${with_distro}
echo Distribution target: ${with_distro}
echo 'if this is not correct, please specifiy your distro with --with-distro=DISTRO'
echo
if test -n "${DHCLIENT_PATH}"; then
echo ISC dhclient support: ${DHCLIENT_PATH}
else
echo ISC dhclient support: no
fi
if test -n "${DHCPCD_PATH}"; then
echo dhcpcd support: ${DHCPCD_PATH}
else
echo dhcpcd support: no
fi
echo
echo Building documentation: ${with_docs}
echo
echo Building tests: ${with_tests}
echo

View File

@@ -302,7 +302,10 @@ done:
}
static gboolean
parse_config_file (const char *filename, char **plugins, GError **error)
parse_config_file (const char *filename,
char **plugins,
char **dhcp_client,
GError **error)
{
GKeyFile *config;
@@ -321,6 +324,8 @@ parse_config_file (const char *filename, char **plugins, GError **error)
if (*error)
return FALSE;
*dhcp_client = g_key_file_get_value (config, "main", "dhcp", NULL);
g_key_file_free (config);
return TRUE;
}
@@ -435,7 +440,7 @@ main (int argc, char *argv[])
gboolean become_daemon = FALSE;
gboolean g_fatal_warnings = FALSE;
char *pidfile = NULL, *user_pidfile = NULL;
char *config = NULL, *plugins = NULL;
char *config = NULL, *plugins = NULL, *dhcp = NULL;
char *state_file = NM_DEFAULT_SYSTEM_STATE_FILE;
gboolean wifi_enabled = TRUE, net_enabled = TRUE, wwan_enabled = TRUE;
gboolean success;
@@ -498,7 +503,7 @@ main (int argc, char *argv[])
/* Parse the config file */
if (config) {
if (!parse_config_file (config, &plugins, &error)) {
if (!parse_config_file (config, &plugins, &dhcp, &error)) {
g_warning ("Config file %s invalid: (%d) %s.",
config,
error ? error->code : -1,
@@ -507,7 +512,7 @@ main (int argc, char *argv[])
}
} else {
config = NM_DEFAULT_SYSTEM_CONF_FILE;
if (!parse_config_file (config, &plugins, &error)) {
if (!parse_config_file (config, &plugins, &dhcp, &error)) {
g_warning ("Default config file %s invalid: (%d) %s.",
config,
error ? error->code : -1,
@@ -620,9 +625,9 @@ main (int argc, char *argv[])
goto done;
}
dhcp_mgr = nm_dhcp_manager_get ();
dhcp_mgr = nm_dhcp_manager_new (dhcp ? dhcp : "dhclient", &error);
if (!dhcp_mgr) {
nm_warning ("Failed to start the DHCP manager.");
nm_warning ("Failed to start the DHCP manager: %s.", error->message);
goto done;
}

View File

@@ -27,7 +27,8 @@ libdhcp_manager_la_CPPFLAGS = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DDHCP_CLIENT_PATH=\"$(DHCP_CLIENT_PATH)\"
-DDHCLIENT_PATH=\"$(DHCLIENT_PATH)\" \
-DDHCPCD_PATH=\"$(DHCPCD_PATH)\"
libdhcp_manager_la_LIBADD = \
$(top_builddir)/marshallers/libmarshallers.la \

View File

@@ -114,9 +114,5 @@ NMIP4Config *nm_dhcp_client_get_ip4_config (NMDHCPClient *self, gboolean test)
/* Backend helpers */
void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name);
/* Implemented by the backends */
GSList *nm_dhcp_backend_get_lease_config (const char *iface,
const char *uuid);
#endif /* NM_DHCP_CLIENT_H */

View File

@@ -110,7 +110,7 @@ add_lease_option (GHashTable *hash, char *line)
}
GSList *
nm_dhcp_backend_get_lease_config (const char *iface, const char *uuid)
nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid)
{
GSList *parsed = NULL, *iter, *leases = NULL;
char *contents = NULL;
@@ -469,13 +469,13 @@ real_ip4_start (NMDHCPClient *client,
return -1;
}
if (!g_file_test (DHCP_CLIENT_PATH, G_FILE_TEST_EXISTS)) {
nm_warning (DHCP_CLIENT_PATH " does not exist.");
if (!g_file_test (DHCLIENT_PATH, G_FILE_TEST_EXISTS)) {
nm_warning (DHCLIENT_PATH " does not exist.");
return -1;
}
/* Kill any existing dhclient from the pidfile */
binary_name = g_path_get_basename (DHCP_CLIENT_PATH);
binary_name = g_path_get_basename (DHCLIENT_PATH);
nm_dhcp_client_stop_existing (priv->pid_file, binary_name);
g_free (binary_name);
@@ -492,7 +492,7 @@ real_ip4_start (NMDHCPClient *client,
}
argv = g_ptr_array_new ();
g_ptr_array_add (argv, (gpointer) DHCP_CLIENT_PATH);
g_ptr_array_add (argv, (gpointer) DHCLIENT_PATH);
g_ptr_array_add (argv, (gpointer) "-d");

View File

@@ -41,5 +41,7 @@ typedef struct {
GType nm_dhcp_dhclient_get_type (void);
GSList *nm_dhcp_dhclient_get_lease_config (const char *iface, const char *uuid);
#endif /* NM_DHCP_DHCLIENT_H */

View File

@@ -47,7 +47,7 @@ typedef struct {
GSList *
nm_dhcp_backend_get_lease_config (const char *iface, const char *uuid)
nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid)
{
return NULL;
}
@@ -83,18 +83,18 @@ real_ip4_start (NMDHCPClient *client,
return -1;
}
if (!g_file_test (DHCP_CLIENT_PATH, G_FILE_TEST_EXISTS)) {
nm_warning (DHCP_CLIENT_PATH " does not exist.");
if (!g_file_test (DHCPCD_PATH, G_FILE_TEST_EXISTS)) {
nm_warning (DHCPCD_PATH " does not exist.");
return -1;
}
/* Kill any existing dhclient from the pidfile */
binary_name = g_path_get_basename (DHCP_CLIENT_PATH);
binary_name = g_path_get_basename (DHCPCD_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) DHCP_CLIENT_PATH);
g_ptr_array_add (argv, (gpointer) DHCPCD_PATH);
g_ptr_array_add (argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */

View File

@@ -41,5 +41,7 @@ typedef struct {
GType nm_dhcp_dhcpcd_get_type (void);
GSList *nm_dhcp_dhcpcd_get_lease_config (const char *iface, const char *uuid);
#endif /* NM_DHCP_DHCPCD_H */

View File

@@ -36,6 +36,7 @@
#include "nm-dhcp-manager.h"
#include "nm-dhcp-dhclient.h"
#include "nm-dhcp-dhcpcd.h"
#include "nm-marshal.h"
#include "nm-utils.h"
#include "nm-dbus-manager.h"
@@ -46,8 +47,14 @@
#define NM_DHCP_CLIENT_DBUS_SERVICE "org.freedesktop.nm_dhcp_client"
#define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client"
static NMDHCPManager *singleton = NULL;
typedef GSList * (*GetLeaseConfigFunc) (const char *iface, const char *uuid);
typedef struct {
guint32 next_id;
GType client_type;
GetLeaseConfigFunc get_lease_config_func;
NMDBusManager * dbus_mgr;
GHashTable * clients;
DBusGProxy * proxy;
@@ -219,23 +226,36 @@ out:
g_free (reason);
}
static NMDHCPManager *
nm_dhcp_manager_new (void)
NMDHCPManager *
nm_dhcp_manager_new (const char *client, GError **error)
{
NMDHCPManager *manager;
NMDHCPManagerPrivate *priv;
DBusGConnection *g_connection;
manager = g_object_new (NM_TYPE_DHCP_MANAGER, NULL);
priv = NM_DHCP_MANAGER_GET_PRIVATE (manager);
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 */
if (!strcmp (client, "dhclient") && strlen (DHCLIENT_PATH)) {
priv->client_type = NM_TYPE_DHCP_DHCLIENT;
priv->get_lease_config_func = nm_dhcp_dhclient_get_lease_config;
} else if (!strcmp (client, "dhcpcd") && strlen (DHCPCD_PATH)) {
priv->client_type = NM_TYPE_DHCP_DHCPCD;
priv->get_lease_config_func = nm_dhcp_dhcpcd_get_lease_config;
} else {
g_set_error (error, 0, 0, "unknown or missing DHCP client '%s'", client);
goto error;
}
priv->clients = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL,
(GDestroyNotify) g_object_unref);
if (!priv->clients) {
nm_warning ("Error: not enough memory to initialize DHCP manager tables");
g_object_unref (manager);
return NULL;
g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager");
goto error;
}
priv->dbus_mgr = nm_dbus_manager_get ();
@@ -245,9 +265,8 @@ nm_dhcp_manager_new (void)
"/",
NM_DHCP_CLIENT_DBUS_IFACE);
if (!priv->proxy) {
nm_warning ("Error: could not init DHCP manager proxy");
g_object_unref (manager);
return NULL;
g_set_error_literal (error, 0, 0, "not enough memory to initialize DHCP manager proxy");
goto error;
}
dbus_g_proxy_add_signal (priv->proxy,
@@ -256,11 +275,16 @@ nm_dhcp_manager_new (void)
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (priv->proxy, "Event",
G_CALLBACK (nm_dhcp_manager_handle_event),
manager,
NULL);
G_CALLBACK (nm_dhcp_manager_handle_event),
singleton,
NULL);
return manager;
return singleton;
error:
g_object_unref (singleton);
singleton = NULL;
return singleton;
}
#define STATE_ID_TAG "state-id"
@@ -416,7 +440,7 @@ nm_dhcp_manager_get_lease_config (NMDHCPManager *self,
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (uuid != NULL, NULL);
return nm_dhcp_backend_get_lease_config (iface, uuid);
return NM_DHCP_MANAGER_GET_PRIVATE (self)->get_lease_config_func (iface, uuid);
}
NMIP4Config *
@@ -443,23 +467,13 @@ nm_dhcp_manager_test_ip4_options_to_config (const char *iface,
NMDHCPManager *
nm_dhcp_manager_get (void)
{
static NMDHCPManager *singleton = NULL;
if (!singleton)
singleton = nm_dhcp_manager_new ();
else
g_object_ref (singleton);
g_assert (singleton);
return singleton;
g_warn_if_fail (singleton != NULL);
return g_object_ref (singleton);
}
static void
nm_dhcp_manager_init (NMDHCPManager *manager)
{
NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (manager);
priv->next_id = 1;
}
static void
@@ -468,10 +482,12 @@ dispose (GObject *object)
NMDHCPManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (object);
GList *values, *iter;
values = g_hash_table_get_values (priv->clients);
for (iter = values; iter; iter = g_list_next (iter))
remove_client (NM_DHCP_MANAGER (object), NM_DHCP_CLIENT (iter->data));
g_list_free (values);
if (priv->clients) {
values = g_hash_table_get_values (priv->clients);
for (iter = values; iter; iter = g_list_next (iter))
remove_client (NM_DHCP_MANAGER (object), NM_DHCP_CLIENT (iter->data));
g_list_free (values);
}
G_OBJECT_CLASS (nm_dhcp_manager_parent_class)->dispose (object);
}
@@ -486,9 +502,12 @@ finalize (GObject *object)
priv->hostname_provider = NULL;
}
g_hash_table_destroy (priv->clients);
g_object_unref (priv->proxy);
g_object_unref (priv->dbus_mgr);
if (priv->clients)
g_hash_table_destroy (priv->clients);
if (priv->proxy)
g_object_unref (priv->proxy);
if (priv->dbus_mgr)
g_object_unref (priv->dbus_mgr);
G_OBJECT_CLASS (nm_dhcp_manager_parent_class)->finalize (object);
}

View File

@@ -70,4 +70,7 @@ NMIP4Config *nm_dhcp_manager_test_ip4_options_to_config (const char *iface,
GHashTable *options,
const char *reason);
/* Only for NetworkManager.c */
NMDHCPManager *nm_dhcp_manager_new (const char *client, GError **error);
#endif /* NM_DHCP_MANAGER_H */