rdisc: make NMRDisc namespace aware

This commit is contained in:
Thomas Haller 2016-03-08 13:11:36 +01:00
parent a0c8f9c345
commit 3ba9444728
8 changed files with 121 additions and 13 deletions

View file

@ -5849,7 +5849,8 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
g_assert (s_ip6);
priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self),
priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
nm_device_get_ip_ifindex (self),
nm_device_get_ip_iface (self),
nm_connection_get_uuid (connection),
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),

View file

@ -470,7 +470,7 @@ main (int argc, char *argv[])
if (global_opt.slaac) {
nm_platform_link_set_user_ipv6ll_enabled (NM_PLATFORM_GET, ifindex, TRUE);
rdisc = nm_lndp_rdisc_new (ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL);
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode, NULL);
g_assert (rdisc);
if (iid)

View file

@ -74,6 +74,7 @@ typedef enum {
} NMIPConfigSource;
/* platform */
typedef struct _NMPlatform NMPlatform;
typedef struct _NMPlatformIP4Address NMPlatformIP4Address;
typedef struct _NMPlatformIP4Route NMPlatformIP4Route;
typedef struct _NMPlatformIP6Address NMPlatformIP6Address;

View file

@ -31,6 +31,7 @@
#include "NetworkManagerUtils.h"
#include "nm-platform.h"
#include "nmp-netns.h"
#define _NMLOG_PREFIX_NAME "rdisc-lndp"
@ -273,9 +274,14 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
static gboolean
event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMLNDPRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
_LOGD ("processing libndp events");
if (!nm_rdisc_netns_push (rdisc, &netns))
return G_SOURCE_CONTINUE;
ndp_callall_eventfd_handler (priv->ndp);
return G_SOURCE_CONTINUE;
}
@ -298,40 +304,50 @@ start (NMRDisc *rdisc)
/******************************************************************/
static inline gint32
ipv6_sysctl_get (const char *ifname, const char *property, gint32 defval)
ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property, gint32 defval)
{
return nm_platform_sysctl_get_int32 (NM_PLATFORM_GET, nm_utils_ip6_property_path (ifname, property), defval);
return nm_platform_sysctl_get_int32 (platform, nm_utils_ip6_property_path (ifname, property), defval);
}
NMRDisc *
nm_lndp_rdisc_new (int ifindex,
nm_lndp_rdisc_new (NMPlatform *platform,
int ifindex,
const char *ifname,
const char *uuid,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
GError **error)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMRDisc *rdisc;
NMLNDPRDiscPrivate *priv;
int errsv;
g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL);
g_return_val_if_fail (!error || !*error, NULL);
rdisc = g_object_new (NM_TYPE_LNDP_RDISC, NULL);
if (!nm_platform_netns_push (platform, &netns))
return NULL;
rdisc = g_object_new (NM_TYPE_LNDP_RDISC,
NM_RDISC_PLATFORM, platform,
NULL);
rdisc->ifindex = ifindex;
rdisc->ifname = g_strdup (ifname);
rdisc->uuid = g_strdup (uuid);
rdisc->addr_gen_mode = addr_gen_mode;
rdisc->max_addresses = ipv6_sysctl_get (ifname, "max_addresses",
rdisc->max_addresses = ipv6_sysctl_get (platform, ifname, "max_addresses",
NM_RDISC_MAX_ADDRESSES_DEFAULT);
rdisc->rtr_solicitations = ipv6_sysctl_get (ifname, "router_solicitations",
rdisc->rtr_solicitations = ipv6_sysctl_get (platform, ifname, "router_solicitations",
NM_RDISC_RTR_SOLICITATIONS_DEFAULT);
rdisc->rtr_solicitation_interval = ipv6_sysctl_get (ifname, "router_solicitation_interval",
rdisc->rtr_solicitation_interval = ipv6_sysctl_get (platform, ifname, "router_solicitation_interval",
NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT);
priv = NM_LNDP_RDISC_GET_PRIVATE (rdisc);
errsv = ndp_open (&priv->ndp);
if (errsv != 0) {
errsv = errsv > 0 ? errsv : -errsv;
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,

View file

@ -44,7 +44,8 @@ typedef struct {
GType nm_lndp_rdisc_get_type (void);
NMRDisc *nm_lndp_rdisc_new (int ifindex,
NMRDisc *nm_lndp_rdisc_new (NMPlatform *platform,
int ifindex,
const char *ifname,
const char *uuid,
NMSettingIP6ConfigAddrGenMode addr_gen_mode,

View file

@ -28,6 +28,8 @@
#include "nm-rdisc-private.h"
#include "nm-utils.h"
#include "nm-platform.h"
#include "nmp-netns.h"
#include <nm-setting-ip6-config.h>
@ -46,6 +48,10 @@ typedef struct {
G_DEFINE_TYPE (NMRDisc, nm_rdisc, G_TYPE_OBJECT)
NM_GOBJECT_PROPERTIES_DEFINE_BASE (
PROP_PLATFORM,
);
enum {
CONFIG_CHANGED,
RA_TIMEOUT,
@ -56,6 +62,31 @@ static guint signals[LAST_SIGNAL] = { 0 };
/******************************************************************/
NMPNetns *
nm_rdisc_netns_get (NMRDisc *self)
{
g_return_val_if_fail (NM_IS_RDISC (self), NULL);
return self->_netns;
}
gboolean
nm_rdisc_netns_push (NMRDisc *self, NMPNetns **netns)
{
g_return_val_if_fail (NM_IS_RDISC (self), FALSE);
if ( self->_netns
&& !nmp_netns_push (self->_netns)) {
NM_SET_OUT (netns, NULL);
return FALSE;
}
NM_SET_OUT (netns, self->_netns);
return TRUE;
}
/******************************************************************/
gboolean
nm_rdisc_add_gateway (NMRDisc *rdisc, const NMRDiscGateway *new)
{
@ -317,10 +348,14 @@ nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
static gboolean
send_rs (NMRDisc *rdisc)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc);
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
GError *error = NULL;
if (!nm_rdisc_netns_push (rdisc, &netns))
return G_SOURCE_REMOVE;
if (klass->send_rs (rdisc, &error)) {
_LOGD ("router solicitation sent");
priv->solicitations_left--;
@ -383,6 +418,7 @@ rdisc_ra_timeout_cb (gpointer user_data)
void
nm_rdisc_start (NMRDisc *rdisc)
{
nm_auto_pop_netns NMPNetns *netns = NULL;
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
NMRDiscClass *klass = NM_RDISC_GET_CLASS (rdisc);
guint ra_wait_secs;
@ -391,6 +427,9 @@ nm_rdisc_start (NMRDisc *rdisc)
_LOGD ("starting router discovery: %d", rdisc->ifindex);
if (!nm_rdisc_netns_push (rdisc, &netns))
return;
nm_clear_g_source (&priv->ra_timeout_id);
ra_wait_secs = CLAMP (rdisc->rtr_solicitations * rdisc->rtr_solicitation_interval, 30, 120);
priv->ra_timeout_id = g_timeout_add_seconds (ra_wait_secs, rdisc_ra_timeout_cb, rdisc);
@ -668,11 +707,42 @@ dns_domain_free (gpointer data)
g_free (((NMRDiscDNSDomain *)(data))->domain);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMRDisc *self = NM_RDISC (object);
switch (prop_id) {
case PROP_PLATFORM:
/* construct-only */
self->_platform = g_value_get_object (value) ? : NM_PLATFORM_GET;
if (!self->_platform)
g_return_if_reached ();
g_object_ref (self->_platform);
self->_netns = nm_platform_netns_get (self->_platform);
if (self->_netns)
g_object_ref (self->_netns);
g_return_if_fail (!self->_netns || self->_netns == nmp_netns_get_current ());
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_rdisc_init (NMRDisc *rdisc)
{
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
rdisc->_netns = nmp_netns_get_current ();
if (rdisc->_netns)
g_object_ref (rdisc->_netns);
rdisc->gateways = g_array_new (FALSE, FALSE, sizeof (NMRDiscGateway));
rdisc->addresses = g_array_new (FALSE, FALSE, sizeof (NMRDiscAddress));
rdisc->routes = g_array_new (FALSE, FALSE, sizeof (NMRDiscRoute));
@ -715,6 +785,9 @@ finalize (GObject *object)
g_array_unref (rdisc->dns_servers);
g_array_unref (rdisc->dns_domains);
g_clear_object (&rdisc->_netns);
g_clear_object (&rdisc->_platform);
G_OBJECT_CLASS (nm_rdisc_parent_class)->finalize (object);
}
@ -725,10 +798,19 @@ nm_rdisc_class_init (NMRDiscClass *klass)
g_type_class_add_private (klass, sizeof (NMRDiscPrivate));
object_class->set_property = set_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
klass->config_changed = config_changed;
obj_properties[PROP_PLATFORM] =
g_param_spec_object (NM_RDISC_PLATFORM, "", "",
NM_TYPE_PLATFORM,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[CONFIG_CHANGED] =
g_signal_new (NM_RDISC_CONFIG_CHANGED,
G_OBJECT_CLASS_TYPE (klass),

View file

@ -21,11 +21,9 @@
#ifndef __NETWORKMANAGER_RDISC_H__
#define __NETWORKMANAGER_RDISC_H__
#include <stdlib.h>
#include <netinet/in.h>
#include "nm-default.h"
#include "nm-setting-ip6-config.h"
#include "NetworkManagerUtils.h"
@ -36,6 +34,7 @@
#define NM_IS_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_RDISC))
#define NM_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_RDISC, NMRDiscClass))
#define NM_RDISC_PLATFORM "platform"
#define NM_RDISC_CONFIG_CHANGED "config-changed"
#define NM_RDISC_RA_TIMEOUT "ra-timeout"
@ -114,6 +113,9 @@ typedef enum {
typedef struct {
GObject parent;
NMPlatform *_platform;
NMPNetns *_netns;
int ifindex;
char *ifname;
char *uuid;
@ -149,4 +151,8 @@ gboolean nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid);
void nm_rdisc_start (NMRDisc *rdisc);
void nm_rdisc_dad_failed (NMRDisc *rdisc, struct in6_addr *address);
NMPlatform *nm_rdisc_get_platform (NMRDisc *self);
NMPNetns *nm_rdisc_netns_get (NMRDisc *self);
gboolean nm_rdisc_netns_push (NMRDisc *self, NMPNetns **netns);
#endif /* __NETWORKMANAGER_RDISC_H__ */

View file

@ -61,7 +61,8 @@ main (int argc, char **argv)
return EXIT_FAILURE;
}
rdisc = nm_lndp_rdisc_new (ifindex,
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
ifindex,
ifname,
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,