rdisc: move sysctl configuration values to NMRDiscPrivate

While at it, tighten up the integer values, types and ranges
and ensure no interger overflow can happen when calculating
timeouts and retry.
This commit is contained in:
Thomas Haller 2016-07-06 17:09:01 +02:00
parent 1bc3df0bd4
commit c81eff0669
4 changed files with 100 additions and 58 deletions

View file

@ -344,18 +344,10 @@ nm_fake_rdisc_emit_new_ras (NMFakeRDisc *self)
NMRDisc *
nm_fake_rdisc_new (int ifindex, const char *ifname)
{
NMRDisc *rdisc;
rdisc = g_object_new (NM_TYPE_FAKE_RDISC,
NM_RDISC_IFINDEX, ifindex,
NM_RDISC_IFNAME, ifname,
NULL);
rdisc->max_addresses = NM_RDISC_MAX_ADDRESSES_DEFAULT;
rdisc->rtr_solicitations = NM_RDISC_RTR_SOLICITATIONS_DEFAULT;
rdisc->rtr_solicitation_interval = NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT;
return rdisc;
return g_object_new (NM_TYPE_FAKE_RDISC,
NM_RDISC_IFINDEX, ifindex,
NM_RDISC_IFNAME, ifname,
NULL);
}
static void
@ -388,10 +380,10 @@ nm_fake_rdisc_class_init (NMFakeRDiscClass *klass)
rdisc_class->start = start;
rdisc_class->send_rs = send_rs;
signals[RS_SENT] = g_signal_new (
NM_FAKE_RDISC_RS_SENT,
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[RS_SENT] =
g_signal_new (NM_FAKE_RDISC_RS_SENT,
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 0);
}

View file

@ -337,14 +337,17 @@ start (NMRDisc *rdisc)
/*****************************************************************************/
static inline gint32
ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property, gint32 defval)
static inline int
ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property, int min, int max, int defval)
{
return nm_platform_sysctl_get_int32 (platform, nm_utils_ip6_property_path (ifname, property), defval);
return (int) nm_platform_sysctl_get_int_checked (platform,
nm_utils_ip6_property_path (ifname, property),
10,
min,
max,
defval);
}
/*****************************************************************************/
static void
nm_lndp_rdisc_init (NMLndpRDisc *lndp_rdisc)
{
@ -377,15 +380,17 @@ nm_lndp_rdisc_new (NMPlatform *platform,
NM_RDISC_IFNAME, ifname,
NM_RDISC_NETWORK_ID, network_id,
NM_RDISC_ADDR_GEN_MODE, (int) addr_gen_mode,
NM_RDISC_MAX_ADDRESSES, ipv6_sysctl_get (platform, ifname,
"max_addresses",
0, G_MAXINT32, NM_RDISC_MAX_ADDRESSES_DEFAULT),
NM_RDISC_ROUTER_SOLICITATIONS, ipv6_sysctl_get (platform, ifname,
"router_solicitations",
1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATIONS_DEFAULT),
NM_RDISC_ROUTER_SOLICITATION_INTERVAL, ipv6_sysctl_get (platform, ifname,
"router_solicitation_interval",
1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT),
NULL);
rdisc->max_addresses = ipv6_sysctl_get (platform, ifname, "max_addresses",
NM_RDISC_MAX_ADDRESSES_DEFAULT);
rdisc->rtr_solicitations = ipv6_sysctl_get (platform, ifname, "router_solicitations",
NM_RDISC_RTR_SOLICITATIONS_DEFAULT);
rdisc->rtr_solicitation_interval = ipv6_sysctl_get (platform, ifname, "router_solicitation_interval",
NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT);
priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
errsv = ndp_open (&priv->ndp);

View file

@ -38,19 +38,23 @@
/*****************************************************************************/
struct _NMRDiscPrivate {
int solicitations_left;
gint32 solicitations_left;
guint send_rs_id;
gint64 last_rs;
gint32 last_rs;
guint ra_timeout_id; /* first RA timeout */
guint timeout_id; /* prefix/dns/etc lifetime timeout */
char *last_send_rs_error;
NMUtilsIPv6IfaceId iid;
/* immutable values: */
int ifindex;
char *ifname;
char *network_id;
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
NMUtilsStableType stable_type;
gint32 max_addresses;
gint32 router_solicitations;
gint32 router_solicitation_interval;
NMPlatform *platform;
NMPNetns *netns;
@ -65,6 +69,9 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
PROP_STABLE_TYPE,
PROP_NETWORK_ID,
PROP_ADDR_GEN_MODE,
PROP_MAX_ADDRESSES,
PROP_ROUTER_SOLICITATIONS,
PROP_ROUTER_SOLICITATION_INTERVAL,
);
enum {
@ -241,6 +248,7 @@ complete_address (NMRDisc *rdisc, NMRDiscAddress *addr)
gboolean
nm_rdisc_complete_and_add_address (NMRDisc *rdisc, NMRDiscAddress *new)
{
NMRDiscPrivate *priv;
int i;
if (!complete_address (rdisc, new))
@ -264,11 +272,13 @@ nm_rdisc_complete_and_add_address (NMRDisc *rdisc, NMRDiscAddress *new)
}
}
priv = NM_RDISC_GET_PRIVATE (rdisc);
/* we create at most max_addresses autoconf addresses. This is different from
* what the kernel does, because it considers *all* addresses (including
* static and other temporary addresses).
**/
if (rdisc->max_addresses && rdisc->addresses->len >= rdisc->max_addresses)
if (priv->max_addresses && rdisc->addresses->len >= priv->max_addresses)
return FALSE;
if (new->lifetime)
@ -421,13 +431,15 @@ nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
}
static gboolean
send_rs (NMRDisc *rdisc)
send_rs_timeout (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;
priv->send_rs_id = 0;
if (!nm_rdisc_netns_push (rdisc, &netns))
return G_SOURCE_REMOVE;
@ -451,13 +463,12 @@ send_rs (NMRDisc *rdisc)
priv->last_rs = nm_utils_get_monotonic_timestamp_s ();
if (priv->solicitations_left > 0) {
_LOGD ("scheduling router solicitation retry in %d seconds.",
rdisc->rtr_solicitation_interval);
priv->send_rs_id = g_timeout_add_seconds (rdisc->rtr_solicitation_interval,
(GSourceFunc) send_rs, rdisc);
(int) priv->router_solicitation_interval);
priv->send_rs_id = g_timeout_add_seconds (priv->router_solicitation_interval,
(GSourceFunc) send_rs_timeout, rdisc);
} else {
_LOGD ("did not receive a router advertisement after %d solicitations.",
rdisc->rtr_solicitations);
priv->send_rs_id = 0;
(int) priv->router_solicitations);
}
return G_SOURCE_REMOVE;
@ -467,17 +478,20 @@ static void
solicit (NMRDisc *rdisc)
{
NMRDiscPrivate *priv = NM_RDISC_GET_PRIVATE (rdisc);
guint32 now = nm_utils_get_monotonic_timestamp_s ();
gint64 next;
gint64 next, now;
if (!priv->send_rs_id) {
priv->solicitations_left = rdisc->rtr_solicitations;
if (priv->send_rs_id)
return;
next = CLAMP (priv->last_rs + rdisc->rtr_solicitation_interval - now, 0, G_MAXINT32);
_LOGD ("scheduling explicit router solicitation request in %" G_GINT64_FORMAT " seconds.",
next);
priv->send_rs_id = g_timeout_add_seconds ((guint32) next, (GSourceFunc) send_rs, rdisc);
}
now = nm_utils_get_monotonic_timestamp_s ();
priv->solicitations_left = priv->router_solicitations;
next = (((gint64) priv->last_rs) + priv->router_solicitation_interval) - now;
next = CLAMP (next, 0, G_MAXINT32);
_LOGD ("scheduling explicit router solicitation request in %" G_GINT64_FORMAT " seconds.",
next);
priv->send_rs_id = g_timeout_add_seconds ((guint32) next, (GSourceFunc) send_rs_timeout, rdisc);
}
static gboolean
@ -496,7 +510,7 @@ 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;
gint64 ra_wait_secs;
g_assert (klass->start);
@ -506,9 +520,10 @@ nm_rdisc_start (NMRDisc *rdisc)
return;
nm_clear_g_source (&priv->ra_timeout_id);
ra_wait_secs = CLAMP (rdisc->rtr_solicitations * rdisc->rtr_solicitation_interval, 30, 120);
ra_wait_secs = (((gint64) priv->router_solicitations) * priv->router_solicitation_interval) + 1;
ra_wait_secs = CLAMP (ra_wait_secs, 30, 120);
priv->ra_timeout_id = g_timeout_add_seconds (ra_wait_secs, rdisc_ra_timeout_cb, rdisc);
_LOGD ("scheduling RA timeout in %d seconds", ra_wait_secs);
_LOGD ("scheduling RA timeout in %d seconds", (int) ra_wait_secs);
if (klass->start)
klass->start (rdisc);
@ -829,6 +844,18 @@ set_property (GObject *object, guint prop_id,
/* construct-only */
priv->addr_gen_mode = g_value_get_int (value);
break;
case PROP_MAX_ADDRESSES:
/* construct-only */
priv->max_addresses = g_value_get_int (value);
break;
case PROP_ROUTER_SOLICITATIONS:
/* construct-only */
priv->router_solicitations = g_value_get_int (value);
break;
case PROP_ROUTER_SOLICITATION_INTERVAL:
/* construct-only */
priv->router_solicitation_interval = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -851,7 +878,7 @@ nm_rdisc_init (NMRDisc *rdisc)
g_array_set_clear_func (rdisc->dns_domains, dns_domain_free);
rdisc->hop_limit = 64;
/* Start at very low number so that last_rs - rtr_solicitation_interval
/* Start at very low number so that last_rs - router_solicitation_interval
* is much lower than nm_utils_get_monotonic_timestamp_s() at startup.
*/
priv->last_rs = G_MININT32;
@ -940,6 +967,24 @@ nm_rdisc_class_init (NMRDiscClass *klass)
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_MAX_ADDRESSES] =
g_param_spec_int (NM_RDISC_MAX_ADDRESSES, "", "",
0, G_MAXINT32, NM_RDISC_MAX_ADDRESSES_DEFAULT,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ROUTER_SOLICITATIONS] =
g_param_spec_int (NM_RDISC_ROUTER_SOLICITATIONS, "", "",
1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATIONS_DEFAULT,
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_ROUTER_SOLICITATION_INTERVAL] =
g_param_spec_int (NM_RDISC_ROUTER_SOLICITATION_INTERVAL, "", "",
1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT,
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] =

View file

@ -40,6 +40,10 @@
#define NM_RDISC_NETWORK_ID "network-id"
#define NM_RDISC_ADDR_GEN_MODE "addr-gen-mode"
#define NM_RDISC_STABLE_TYPE "stable-type"
#define NM_RDISC_MAX_ADDRESSES "max-addresses"
#define NM_RDISC_ROUTER_SOLICITATIONS "router-solicitations"
#define NM_RDISC_ROUTER_SOLICITATION_INTERVAL "router-solicitation-interval"
#define NM_RDISC_CONFIG_CHANGED "config-changed"
#define NM_RDISC_RA_TIMEOUT "ra-timeout"
@ -105,8 +109,8 @@ typedef enum {
} NMRDiscConfigMap;
#define NM_RDISC_MAX_ADDRESSES_DEFAULT 16
#define NM_RDISC_RTR_SOLICITATIONS_DEFAULT 3
#define NM_RDISC_RTR_SOLICITATION_INTERVAL_DEFAULT 4
#define NM_RDISC_ROUTER_SOLICITATIONS_DEFAULT 3
#define NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4
struct _NMRDiscPrivate;
@ -121,10 +125,6 @@ typedef struct {
struct _NMRDiscPrivate *_priv;
gint32 max_addresses;
gint32 rtr_solicitations;
gint32 rtr_solicitation_interval;
NMRDiscDHCPLevel dhcp_level;
GArray *gateways;
GArray *addresses;