dhcp: move client-specific knowledge out of the manager

This commit is contained in:
Dan Williams 2014-10-29 17:12:46 -05:00
parent 0b98dc4387
commit 318a8c2d72
10 changed files with 153 additions and 79 deletions

View file

@ -124,6 +124,7 @@ sbin_PROGRAMS = NetworkManager
NetworkManager_SOURCES = \
$(nm_device_sources) $(nm_device_headers) \
$(nm_dhcp_client_sources) $(nm_dhcp_client_headers) \
main-utils.c \
main-utils.h \
main.c
@ -155,8 +156,21 @@ nm_device_headers = \
devices/nm-device-vlan.h \
devices/nm-device-vxlan.h
nm_dhcp_client_sources = \
dhcp-manager/nm-dhcp-dhclient.c \
dhcp-manager/nm-dhcp-dhclient-utils.c \
dhcp-manager/nm-dhcp-dhcpcd.c \
dhcp-manager/nm-dhcp-systemd.c
nm_dhcp_client_headers = \
dhcp-manager/nm-dhcp-dhclient.h \
dhcp-manager/nm-dhcp-dhclient-utils.h \
dhcp-manager/nm-dhcp-dhcpcd.h \
dhcp-manager/nm-dhcp-systemd.h
nm_sources = \
$(nm_device_headers) \
$(nm_dhcp_client_headers) \
devices/nm-device.c \
devices/nm-device.h \
devices/nm-device-ethernet-utils.c \
@ -174,14 +188,6 @@ nm_sources = \
dhcp-manager/nm-dhcp-utils.h \
dhcp-manager/nm-dhcp-listener.c \
dhcp-manager/nm-dhcp-listener.h \
dhcp-manager/nm-dhcp-dhclient.c \
dhcp-manager/nm-dhcp-dhclient.h \
dhcp-manager/nm-dhcp-dhclient-utils.c \
dhcp-manager/nm-dhcp-dhclient-utils.h \
dhcp-manager/nm-dhcp-dhcpcd.c \
dhcp-manager/nm-dhcp-dhcpcd.h \
dhcp-manager/nm-dhcp-systemd.h \
dhcp-manager/nm-dhcp-systemd.c \
dhcp-manager/nm-dhcp-manager.c \
dhcp-manager/nm-dhcp-manager.h \
\

View file

@ -99,6 +99,17 @@ typedef struct {
GType nm_dhcp_client_get_type (void);
typedef const char *(*NMDhcpClientGetPathFunc) (void);
typedef GSList * (*NMDhcpClientGetLeaseConfigsFunc) (const char *iface,
const char *uuid,
gboolean ipv6);
void _nm_dhcp_client_register (GType gtype,
const char *name,
NMDhcpClientGetPathFunc get_path_func,
NMDhcpClientGetLeaseConfigsFunc get_lease_configs_func);
pid_t nm_dhcp_client_get_pid (NMDhcpClient *self);
const char *nm_dhcp_client_get_iface (NMDhcpClient *self);

View file

@ -56,7 +56,7 @@ typedef struct {
char *pid_file;
} NMDhcpDhclientPrivate;
const char *
static const char *
nm_dhcp_dhclient_get_path (void)
{
const char *path = NULL;
@ -123,7 +123,7 @@ get_dhclient_leasefile (const char *iface,
return NULL;
}
GSList *
static GSList *
nm_dhcp_dhclient_get_lease_ip_configs (const char *iface,
const char *uuid,
gboolean ipv6)
@ -653,3 +653,13 @@ nm_dhcp_dhclient_class_init (NMDhcpDhclientClass *dhclient_class)
client_class->get_duid = get_duid;
}
static void __attribute__((constructor))
register_dhcp_dhclient (void)
{
g_type_init ();
_nm_dhcp_client_register (NM_TYPE_DHCP_DHCLIENT,
"dhclient",
nm_dhcp_dhclient_get_path,
nm_dhcp_dhclient_get_lease_ip_configs);
}

View file

@ -41,11 +41,5 @@ typedef struct {
GType nm_dhcp_dhclient_get_type (void);
GSList *nm_dhcp_dhclient_get_lease_ip_configs (const char *iface,
const char *uuid,
gboolean ipv6);
const char *nm_dhcp_dhclient_get_path (void);
#endif /* __NETWORKMANAGER_DHCP_DHCLIENT_H__ */

View file

@ -48,7 +48,7 @@ typedef struct {
char *pid_file;
} NMDhcpDhcpcdPrivate;
const char *
static const char *
nm_dhcp_dhcpcd_get_path (void)
{
const char *path = NULL;
@ -227,3 +227,13 @@ nm_dhcp_dhcpcd_class_init (NMDhcpDhcpcdClass *dhcpcd_class)
client_class->stop = stop;
}
static void __attribute__((constructor))
register_dhcp_dhclient (void)
{
g_type_init ();
_nm_dhcp_client_register (NM_TYPE_DHCP_DHCPCD,
"dhcpcd",
nm_dhcp_dhcpcd_get_path,
NULL);
}

View file

@ -41,7 +41,5 @@ typedef struct {
GType nm_dhcp_dhcpcd_get_type (void);
const char *nm_dhcp_dhcpcd_get_path (void);
#endif /* __NETWORKMANAGER_DHCP_DHCPCD_H__ */

View file

@ -52,7 +52,6 @@ typedef GSList * (*GetLeaseConfigFunc) (const char *iface, const char *uuid, gbo
typedef struct {
GType client_type;
GetLeaseConfigFunc get_lease_ip_configs_func;
GHashTable * clients;
char * default_hostname;
} NMDhcpManagerPrivate;
@ -63,6 +62,79 @@ G_DEFINE_TYPE (NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT)
/***************************************************/
typedef struct {
GType gtype;
const char *name;
NMDhcpClientGetPathFunc get_path_func;
NMDhcpClientGetLeaseConfigsFunc get_lease_configs_func;
} ClientDesc;
static GSList *client_descs = NULL;
void
_nm_dhcp_client_register (GType gtype,
const char *name,
NMDhcpClientGetPathFunc get_path_func,
NMDhcpClientGetLeaseConfigsFunc get_lease_configs_func)
{
ClientDesc *desc;
GSList *iter;
g_return_if_fail (gtype != G_TYPE_INVALID);
g_return_if_fail (name != NULL);
for (iter = client_descs; iter; iter = iter->next) {
desc = iter->data;
g_return_if_fail (desc->gtype != gtype);
g_return_if_fail (strcmp (desc->name, name) != 0);
}
desc = g_slice_new0 (ClientDesc);
desc->gtype = gtype;
desc->name = name;
desc->get_path_func = get_path_func;
desc->get_lease_configs_func = get_lease_configs_func;
client_descs = g_slist_prepend (client_descs, desc);
nm_log_info (LOGD_DHCP, "Registered DHCP client '%s'", name);
}
static ClientDesc *
find_client_desc (const char *name, GType gtype)
{
GSList *iter;
g_return_val_if_fail (name || gtype, NULL);
for (iter = client_descs; iter; iter = iter->next) {
ClientDesc *desc = iter->data;
if (name && strcmp (desc->name, name) != 0)
continue;
if (gtype && desc->name != 0)
continue;
return desc;
}
return NULL;
}
static GType
is_client_enabled (const char *name, GError **error)
{
ClientDesc *desc;
desc = find_client_desc (name, G_TYPE_INVALID);
if (desc && (!desc->get_path_func || desc->get_path_func()))
return desc->gtype;
g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("'%s' support not found or not enabled."),
name);
return G_TYPE_INVALID;
}
/***************************************************/
static NMDhcpClient *
get_client_for_ifindex (NMDhcpManager *manager, int ifindex, gboolean ip6)
{
@ -90,52 +162,23 @@ get_client_for_ifindex (NMDhcpManager *manager, int ifindex, gboolean ip6)
static GType
get_client_type (const char *client, GError **error)
{
gboolean use_dhclient, use_dhcpcd;
GType client_gtype;
/* If a client was disabled at build-time, these will return FALSE */
use_dhclient = !!nm_dhcp_dhclient_get_path ();
use_dhcpcd = !!nm_dhcp_dhcpcd_get_path ();
if (!client) {
if (use_dhclient)
return NM_TYPE_DHCP_DHCLIENT;
else if (use_dhcpcd)
return NM_TYPE_DHCP_DHCPCD;
else {
g_set_error_literal (error,
NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("no usable DHCP client could be found."));
return G_TYPE_INVALID;
if (client)
client_gtype = is_client_enabled (client, error);
else {
/* Fallbacks */
client_gtype = is_client_enabled ("dhclient", NULL);
if (client_gtype == G_TYPE_INVALID)
client_gtype = is_client_enabled ("dhcpcd", NULL);
if (client_gtype == G_TYPE_INVALID)
client_gtype = is_client_enabled ("internal", NULL);
if (client_gtype == G_TYPE_INVALID) {
g_set_error_literal (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("no usable DHCP client could be found."));
}
}
if (!strcmp (client, "dhclient")) {
if (!use_dhclient) {
g_set_error_literal (error,
NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("'dhclient' could not be found or was disabled."));
return G_TYPE_INVALID;
}
return NM_TYPE_DHCP_DHCLIENT;
}
if (!strcmp (client, "dhcpcd")) {
if (!use_dhcpcd) {
g_set_error_literal (error,
NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("'dhcpcd' could not be found or was disabled."));
return G_TYPE_INVALID;
}
return NM_TYPE_DHCP_DHCPCD;
}
if (!strcmp (client, "internal"))
return NM_TYPE_DHCP_SYSTEMD;
g_set_error (error,
NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED,
_("unsupported DHCP client '%s'"), client);
return G_TYPE_INVALID;
return client_gtype;
}
static void client_state_changed (NMDhcpClient *client,
@ -312,16 +355,15 @@ nm_dhcp_manager_get_lease_ip_configs (NMDhcpManager *self,
const char *uuid,
gboolean ipv6)
{
NMDhcpManagerPrivate *priv;
ClientDesc *desc;
g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (uuid != NULL, NULL);
priv = NM_DHCP_MANAGER_GET_PRIVATE (self);
if (priv->get_lease_ip_configs_func)
return priv->get_lease_ip_configs_func (iface, uuid, ipv6);
desc = find_client_desc (NULL, NM_DHCP_MANAGER_GET_PRIVATE (self)->client_type);
if (desc && desc->get_lease_configs_func)
return desc->get_lease_configs_func (iface, uuid, ipv6);
return NULL;
}
@ -348,12 +390,7 @@ nm_dhcp_manager_init (NMDhcpManager *self)
/* Client-specific setup */
client = nm_config_get_dhcp_client (nm_config_get ());
priv->client_type = get_client_type (client, &error);
if (priv->client_type == NM_TYPE_DHCP_DHCLIENT)
priv->get_lease_ip_configs_func = nm_dhcp_dhclient_get_lease_ip_configs;
else if (priv->client_type == NM_TYPE_DHCP_SYSTEMD)
priv->get_lease_ip_configs_func = nm_dhcp_systemd_get_lease_ip_configs;
else if (priv->client_type == G_TYPE_INVALID) {
if (priv->client_type == G_TYPE_INVALID) {
nm_log_warn (LOGD_DHCP, "No usable DHCP client found (%s)! DHCP configurations will fail.",
error->message);
}

View file

@ -374,7 +374,7 @@ get_leasefile_path (const char *iface, const char *uuid, gboolean ipv6)
iface);
}
GSList *
static GSList *
nm_dhcp_systemd_get_lease_ip_configs (const char *iface,
const char *uuid,
gboolean ipv6)
@ -808,3 +808,13 @@ nm_dhcp_systemd_class_init (NMDhcpSystemdClass *sdhcp_class)
client_class->stop = stop;
}
static void __attribute__((constructor))
register_dhcp_dhclient (void)
{
g_type_init ();
_nm_dhcp_client_register (NM_TYPE_DHCP_SYSTEMD,
"internal",
NULL,
nm_dhcp_systemd_get_lease_ip_configs);
}

View file

@ -41,9 +41,5 @@ typedef struct {
GType nm_dhcp_systemd_get_type (void);
GSList *nm_dhcp_systemd_get_lease_ip_configs (const char *iface,
const char *uuid,
gboolean ipv6);
#endif /* NM_DHCP_SYSTEMD_H */

View file

@ -18,6 +18,8 @@ noinst_PROGRAMS = \
####### dhclient leases test #######
test_dhcp_dhclient_SOURCES = \
$(top_srcdir)/src/dhcp-manager/nm-dhcp-dhclient-utils.h \
$(top_srcdir)/src/dhcp-manager/nm-dhcp-dhclient-utils.c \
test-dhcp-dhclient.c
test_dhcp_dhclient_LDADD = \