mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-28 13:20:08 +01:00
merge: branch 'lr/stable-privacy-rfc7217'
https://bugzilla.gnome.org/show_bug.cgi?id=755216
This commit is contained in:
commit
9b31d6e210
23 changed files with 767 additions and 133 deletions
|
|
@ -322,8 +322,9 @@ NmcOutputField nmc_fields_setting_ip6_config[] = {
|
|||
SETTING_FIELD (NM_SETTING_IP_CONFIG_NEVER_DEFAULT), /* 11 */
|
||||
SETTING_FIELD (NM_SETTING_IP_CONFIG_MAY_FAIL), /* 12 */
|
||||
SETTING_FIELD (NM_SETTING_IP6_CONFIG_IP6_PRIVACY), /* 13 */
|
||||
SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 14 */
|
||||
SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 15 */
|
||||
SETTING_FIELD (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE), /* 14 */
|
||||
SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME), /* 15 */
|
||||
SETTING_FIELD (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME), /* 16 */
|
||||
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
|
||||
};
|
||||
#define NMC_FIELDS_SETTING_IP6_CONFIG_ALL "name"","\
|
||||
|
|
@ -340,6 +341,7 @@ NmcOutputField nmc_fields_setting_ip6_config[] = {
|
|||
NM_SETTING_IP_CONFIG_NEVER_DEFAULT","\
|
||||
NM_SETTING_IP_CONFIG_MAY_FAIL","\
|
||||
NM_SETTING_IP6_CONFIG_IP6_PRIVACY","\
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE","\
|
||||
NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME","\
|
||||
NM_SETTING_IP_CONFIG_DHCP_HOSTNAME
|
||||
#define NMC_FIELDS_SETTING_IP6_CONFIG_COMMON NMC_FIELDS_SETTING_IP4_CONFIG_ALL
|
||||
|
|
@ -4129,6 +4131,36 @@ nmc_property_ipv6_set_ip6_privacy (NMSetting *setting, const char *prop, const c
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* 'addr_gen_mode' */
|
||||
static char *
|
||||
nmc_property_ipv6_get_addr_gen_mode (NMSetting *setting, NmcPropertyGetType get_type)
|
||||
{
|
||||
NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting);
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
|
||||
addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode (s_ip6);
|
||||
return nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (), addr_gen_mode);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
nmc_property_ipv6_set_addr_gen_mode (NMSetting *setting, const char *prop,
|
||||
const char *val, GError **error)
|
||||
{
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
|
||||
if (!nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), val,
|
||||
(int *) &addr_gen_mode, NULL)) {
|
||||
g_set_error (error, 1, 0, _("invalid option '%s', use one of [%s]"),
|
||||
val, "eui64,stable-privacy");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_set (setting, prop, addr_gen_mode, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* --- NM_SETTING_OLPC_MESH_SETTING_NAME property setter functions --- */
|
||||
static gboolean
|
||||
nmc_property_olpc_set_channel (NMSetting *setting, const char *prop, const char *val, GError **error)
|
||||
|
|
@ -6104,6 +6136,13 @@ nmc_properties_init (void)
|
|||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nmc_add_prop_funcs (GLUE (IP6_CONFIG, ADDR_GEN_MODE),
|
||||
nmc_property_ipv6_get_addr_gen_mode,
|
||||
nmc_property_ipv6_set_addr_gen_mode,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nmc_add_prop_funcs (GLUE_IP (6, DHCP_SEND_HOSTNAME),
|
||||
nmc_property_ipv6_get_dhcp_send_hostname,
|
||||
nmc_property_set_bool,
|
||||
|
|
@ -7355,8 +7394,9 @@ setting_ip6_config_details (NMSetting *setting, NmCli *nmc, const char *one_pro
|
|||
set_val_str (arr, 11, nmc_property_ipv6_get_never_default (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 12, nmc_property_ipv6_get_may_fail (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 13, nmc_property_ipv6_get_ip6_privacy (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 14, nmc_property_ipv6_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 15, nmc_property_ipv6_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 14, nmc_property_ipv6_get_addr_gen_mode (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 15, nmc_property_ipv6_get_dhcp_send_hostname (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
set_val_str (arr, 16, nmc_property_ipv6_get_dhcp_hostname (setting, NMC_PROPERTY_GET_PRETTY));
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
print_data (nmc); /* Print all data */
|
||||
|
|
|
|||
|
|
@ -559,6 +559,28 @@ ip6_dns_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
|||
g_strfreev (list);
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
|
||||
{
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
const char *setting_name = nm_setting_get_name (setting);
|
||||
gs_free char *s = NULL;
|
||||
|
||||
s = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL);
|
||||
if (s) {
|
||||
if (!nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), s,
|
||||
(int *) &addr_gen_mode, NULL)) {
|
||||
handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
|
||||
_("invalid option '%s', use one of [%s]"),
|
||||
s, "eui64,stable-privacy");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64;
|
||||
|
||||
g_object_set (G_OBJECT (setting), key, (gint) addr_gen_mode, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
mac_address_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key, gsize enforce_length)
|
||||
{
|
||||
|
|
@ -1177,6 +1199,10 @@ static KeyParser key_parsers[] = {
|
|||
NM_SETTING_IP_CONFIG_DNS,
|
||||
FALSE,
|
||||
ip6_dns_parser },
|
||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
|
||||
FALSE,
|
||||
ip6_addr_gen_mode_parser },
|
||||
{ NM_SETTING_WIRED_SETTING_NAME,
|
||||
NM_SETTING_WIRED_MAC_ADDRESS,
|
||||
TRUE,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,24 @@ dns_writer (KeyfileWriterInfo *info,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_addr_gen_mode_writer (KeyfileWriterInfo *info,
|
||||
NMSetting *setting,
|
||||
const char *key,
|
||||
const GValue *value)
|
||||
{
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
const char *str;
|
||||
|
||||
addr_gen_mode = (NMSettingIP6ConfigAddrGenMode) g_value_get_int (value);
|
||||
str = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (),
|
||||
addr_gen_mode);
|
||||
nm_keyfile_plugin_kf_set_string (info->keyfile,
|
||||
nm_setting_get_name (setting),
|
||||
key,
|
||||
str);
|
||||
}
|
||||
|
||||
static void
|
||||
write_ip_values (GKeyFile *file,
|
||||
const char *setting_name,
|
||||
|
|
@ -557,6 +575,9 @@ static KeyWriter key_writers[] = {
|
|||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP_CONFIG_DNS,
|
||||
dns_writer },
|
||||
{ NM_SETTING_IP6_CONFIG_SETTING_NAME,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
|
||||
ip6_addr_gen_mode_writer },
|
||||
{ NM_SETTING_WIRELESS_SETTING_NAME,
|
||||
NM_SETTING_WIRELESS_SSID,
|
||||
ssid_writer },
|
||||
|
|
@ -587,7 +608,8 @@ static KeyWriter key_writers[] = {
|
|||
static gboolean
|
||||
can_omit_default_value (NMSetting *setting, const char *property)
|
||||
{
|
||||
if (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS))
|
||||
if ( (NM_IS_SETTING_VLAN (setting) && !strcmp (property, NM_SETTING_VLAN_FLAGS))
|
||||
|| (NM_IS_SETTING_IP6_CONFIG (setting) && !strcmp (property, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE)))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "nm-setting-ip6-config.h"
|
||||
#include "nm-setting-private.h"
|
||||
#include "nm-core-enum-types.h"
|
||||
#include "nm-macros-internal.h"
|
||||
|
||||
/**
|
||||
* SECTION:nm-setting-ip6-config
|
||||
|
|
@ -57,12 +58,14 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG)
|
|||
|
||||
typedef struct {
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
} NMSettingIP6ConfigPrivate;
|
||||
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_IP6_PRIVACY,
|
||||
PROP_ADDR_GEN_MODE,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -97,9 +100,30 @@ nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting)
|
|||
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ip6_privacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_ip6_config_get_addr_gen_mode:
|
||||
* @setting: the #NMSettingIP6Config
|
||||
*
|
||||
* Returns the value contained in the #NMSettingIP6Config:addr-gen-mode
|
||||
* property.
|
||||
*
|
||||
* Returns: IPv6 Address Generation Mode.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
NMSettingIP6ConfigAddrGenMode
|
||||
nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting),
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY);
|
||||
|
||||
return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->addr_gen_mode;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
verify (NMSetting *setting, NMConnection *connection, GError **error)
|
||||
{
|
||||
NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting);
|
||||
NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
|
||||
NMSettingVerifyResult ret;
|
||||
const char *method;
|
||||
|
|
@ -166,6 +190,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (!NM_IN_SET (priv->addr_gen_mode,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("property is invalid"));
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -330,6 +365,9 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_IP6_PRIVACY:
|
||||
priv->ip6_privacy = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_ADDR_GEN_MODE:
|
||||
priv->addr_gen_mode = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -346,6 +384,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_IP6_PRIVACY:
|
||||
g_value_set_enum (value, priv->ip6_privacy);
|
||||
break;
|
||||
case PROP_ADDR_GEN_MODE:
|
||||
g_value_set_int (value, priv->addr_gen_mode);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -511,6 +552,10 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
|
|||
*
|
||||
* If also global configuration is unspecified or set to "-1", fallback to read
|
||||
* "/proc/sys/net/ipv6/conf/default/use_tempaddr".
|
||||
*
|
||||
* Note that this setting is distinct from the Stable Privacy addresses
|
||||
* that can be enabled with the "addr-gen-mode" property's "stable-privacy"
|
||||
* setting as another way of avoiding host tracking with IPv6 addresses.
|
||||
**/
|
||||
/* ---ifcfg-rh---
|
||||
* property: ip6-privacy
|
||||
|
|
@ -531,6 +576,53 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
|
|||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingIP6Config:addr-gen-mode:
|
||||
*
|
||||
* Configure method for creating the address for use with RFC4862 IPv6
|
||||
* Stateless Address Autoconfiguration. The permitted values are: "eui64",
|
||||
* "stable-privacy" or unset.
|
||||
*
|
||||
* If the property is set to "eui64", the addresses will be generated
|
||||
* using the interface tokens derived from hardware address. This makes
|
||||
* the host part of the address to stay constant, making it possible
|
||||
* to track host's presence when it changes networks. The address changes
|
||||
* when the interface hardware is replaced.
|
||||
*
|
||||
* The value of "stable-privacy" enables use of cryptographically
|
||||
* secure hash of a secret host-specific key along with the connection
|
||||
* identification and the network address as specified by RFC7217.
|
||||
* This makes it impossible to use the address track host's presence,
|
||||
* and makes the address stable when the network interface hardware is
|
||||
* replaced.
|
||||
*
|
||||
* Leaving this unset causes a default that could be subject to change
|
||||
* in future versions to be used.
|
||||
*
|
||||
* Note that this setting is distinct from the Privacy Extensions as
|
||||
* configured by "ip6-privacy" property and it does not affect the
|
||||
* temporary addresses configured with this option.
|
||||
*
|
||||
* Since: 1.2
|
||||
**/
|
||||
/* ---ifcfg-rh---
|
||||
* property: addr-gen-mode
|
||||
* variable: IPV6_ADDR_GEN_MODE
|
||||
* values: IPV6_ADDR_GEN_MODE: eui64, stable-privacy
|
||||
* default: eui64
|
||||
* description: Configure IPv6 Stable Privacy addressing for SLAAC (RFC7217).
|
||||
* example: IPV6_ADDR_GEN_MODE=stable-privacy
|
||||
* ---end---
|
||||
*/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_ADDR_GEN_MODE,
|
||||
g_param_spec_int (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, "", "",
|
||||
G_MININT, G_MAXINT,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* IP6-specific property overrides */
|
||||
|
||||
/* ---dbus---
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ G_BEGIN_DECLS
|
|||
|
||||
#define NM_SETTING_IP6_CONFIG_IP6_PRIVACY "ip6-privacy"
|
||||
|
||||
#define NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE "addr-gen-mode"
|
||||
|
||||
/**
|
||||
* NM_SETTING_IP6_CONFIG_METHOD_IGNORE:
|
||||
*
|
||||
|
|
@ -114,6 +116,25 @@ typedef enum {
|
|||
NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR = 2
|
||||
} NMSettingIP6ConfigPrivacy;
|
||||
|
||||
/**
|
||||
* NMSettingIP6ConfigAddrGenMode:
|
||||
* @NM_SETTING_IP6_CONFIG_PRIVACY_EUI64: The Interface Identifier is derived
|
||||
* from the interface hardware address.
|
||||
* @NM_SETTING_IP6_CONFIG_PRIVACY_STABLE_PRIVACY: The Interface Identifier
|
||||
* is created by using a cryptographically secure hash of a secret host-specific
|
||||
* key along with the connection identification and the network address as
|
||||
* specified by RFC7217.
|
||||
*
|
||||
* #NMSettingIP6ConfigAddrGenMode controls how the the Interface Identifier for
|
||||
* RFC4862 Stateless Address Autoconfiguration is created.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
typedef enum {
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64 = 0,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY = 1,
|
||||
} NMSettingIP6ConfigAddrGenMode;
|
||||
|
||||
struct _NMSettingIP6Config {
|
||||
NMSettingIPConfig parent;
|
||||
};
|
||||
|
|
@ -130,6 +151,8 @@ GType nm_setting_ip6_config_get_type (void);
|
|||
NMSetting *nm_setting_ip6_config_new (void);
|
||||
|
||||
NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting);
|
||||
NM_AVAILABLE_IN_1_2
|
||||
NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -882,6 +882,8 @@ global:
|
|||
nm_setting_connection_get_metered;
|
||||
nm_setting_connection_lldp_get_type;
|
||||
nm_setting_ip4_config_get_dhcp_timeout;
|
||||
nm_setting_ip6_config_addr_gen_mode_get_type;
|
||||
nm_setting_ip6_config_get_addr_gen_mode;
|
||||
nm_setting_ip_config_add_dns_option;
|
||||
nm_setting_ip_config_clear_dns_options;
|
||||
nm_setting_ip_config_get_dns_option;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <resolv.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/stat.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/if_infiniband.h>
|
||||
|
||||
|
|
@ -3213,7 +3214,6 @@ nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
|
|||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
|
||||
const NMUtilsIPv6IfaceId iid)
|
||||
|
|
@ -3228,6 +3228,125 @@ nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
|
|||
memcpy (iid, addr->s6_addr + 8, 8);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_set_stable_privacy (struct in6_addr *addr,
|
||||
const char *ifname,
|
||||
const char *uuid,
|
||||
guint dad_counter,
|
||||
gchar *secret_key,
|
||||
gsize key_len,
|
||||
GError **error)
|
||||
{
|
||||
GChecksum *sum;
|
||||
guint8 digest[32];
|
||||
guint32 tmp[2];
|
||||
gsize len = sizeof (digest);
|
||||
|
||||
g_return_val_if_fail (key_len, FALSE);
|
||||
|
||||
/* Documentation suggests that this can fail.
|
||||
* Maybe in case of a missing algorithm in crypto library? */
|
||||
sum = g_checksum_new (G_CHECKSUM_SHA256);
|
||||
if (!sum) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Can't create a SHA256 hash");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
key_len = CLAMP (key_len, 0, G_MAXUINT32);
|
||||
|
||||
g_checksum_update (sum, addr->s6_addr, 8);
|
||||
g_checksum_update (sum, (const guchar *) ifname, strlen (ifname) + 1);
|
||||
if (!uuid)
|
||||
uuid = "";
|
||||
g_checksum_update (sum, (const guchar *) uuid, strlen (uuid) + 1);
|
||||
tmp[0] = htonl (dad_counter);
|
||||
tmp[1] = htonl (key_len);
|
||||
g_checksum_update (sum, (const guchar *) tmp, sizeof (tmp));
|
||||
g_checksum_update (sum, (const guchar *) secret_key, key_len);
|
||||
|
||||
g_checksum_get_digest (sum, digest, &len);
|
||||
g_checksum_free (sum);
|
||||
|
||||
g_return_val_if_fail (len == 32, FALSE);
|
||||
|
||||
memcpy (addr->s6_addr + 8, &digest[0], 8);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define RFC7217_IDGEN_RETRIES 3
|
||||
/**
|
||||
* nm_utils_ipv6_addr_set_stable_privacy:
|
||||
*
|
||||
* Extend the address prefix with an interface identifier using the
|
||||
* RFC 7217 Stable Privacy mechanism.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE if the address could not be generated.
|
||||
*/
|
||||
gboolean
|
||||
nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
|
||||
const char *ifname,
|
||||
const char *uuid,
|
||||
guint dad_counter,
|
||||
GError **error)
|
||||
{
|
||||
gchar *secret_key = NULL;
|
||||
gsize key_len = 0;
|
||||
gboolean success = FALSE;
|
||||
|
||||
if (dad_counter >= RFC7217_IDGEN_RETRIES) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Too many DAD collisions");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Let's try to load a saved secret key first. */
|
||||
if (g_file_get_contents (NMSTATEDIR "/secret_key", &secret_key, &key_len, NULL)) {
|
||||
if (key_len < 16) {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Key is too short to be usable");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
int urandom = open ("/dev/urandom", O_RDONLY);
|
||||
mode_t key_mask;
|
||||
|
||||
if (!urandom) {
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Can't open /dev/urandom: %s", strerror (errno));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* RFC7217 mandates the key SHOULD be at least 128 bits.
|
||||
* Let's use twice as much. */
|
||||
key_len = 32;
|
||||
secret_key = g_malloc (key_len);
|
||||
|
||||
key_mask = umask (0077);
|
||||
if (read (urandom, secret_key, key_len) == key_len) {
|
||||
if (!g_file_set_contents (NMSTATEDIR "/secret_key", secret_key, key_len, error)) {
|
||||
g_prefix_error (error, "Can't write " NMSTATEDIR "/secret_key");
|
||||
key_len = 0;
|
||||
}
|
||||
} else {
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"Could not obtain a secret");
|
||||
key_len = 0;
|
||||
}
|
||||
umask (key_mask);
|
||||
close (urandom);
|
||||
}
|
||||
|
||||
if (key_len) {
|
||||
success = _set_stable_privacy (addr, ifname, uuid, dad_counter,
|
||||
secret_key, key_len, error);
|
||||
}
|
||||
|
||||
g_free (secret_key);
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_utils_setpgid:
|
||||
* @unused: unused
|
||||
|
|
|
|||
|
|
@ -286,6 +286,12 @@ gboolean nm_utils_get_ipv6_interface_identifier (NMLinkType link_type,
|
|||
void nm_utils_ipv6_addr_set_interface_identfier (struct in6_addr *addr,
|
||||
const NMUtilsIPv6IfaceId iid);
|
||||
|
||||
gboolean nm_utils_ipv6_addr_set_stable_privacy (struct in6_addr *addr,
|
||||
const char *ifname,
|
||||
const char *uuid,
|
||||
guint dad_counter,
|
||||
GError **error);
|
||||
|
||||
void nm_utils_ipv6_interface_identfier_get_from_addr (NMUtilsIPv6IfaceId *iid,
|
||||
const struct in6_addr *addr);
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <netlink/route/addr.h>
|
||||
#include <linux/if_addr.h>
|
||||
|
||||
#include "nm-default.h"
|
||||
#include "nm-device.h"
|
||||
|
|
@ -201,6 +202,7 @@ typedef struct {
|
|||
guint queued_ip4_config_id;
|
||||
guint queued_ip6_config_id;
|
||||
GSList *pending_actions;
|
||||
GSList *dad6_failed_addrs;
|
||||
|
||||
char * udi;
|
||||
char * iface; /* may change, could be renamed by user */
|
||||
|
|
@ -324,6 +326,7 @@ typedef struct {
|
|||
NMIP6Config * ac_ip6_config;
|
||||
|
||||
guint linklocal6_timeout_id;
|
||||
guint8 linklocal6_dad_counter;
|
||||
|
||||
GHashTable * ip6_saved_properties;
|
||||
|
||||
|
|
@ -4774,16 +4777,20 @@ linklocal6_cleanup (NMDevice *self)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
linklocal6_failed (NMDevice *self)
|
||||
{
|
||||
linklocal6_cleanup (self);
|
||||
nm_device_activate_schedule_ip6_config_timeout (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
linklocal6_timeout_cb (gpointer user_data)
|
||||
{
|
||||
NMDevice *self = user_data;
|
||||
|
||||
linklocal6_cleanup (self);
|
||||
|
||||
_LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout");
|
||||
|
||||
nm_device_activate_schedule_ip6_config_timeout (self);
|
||||
linklocal6_failed (self);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
|
|
@ -4827,9 +4834,11 @@ check_and_add_ipv6ll_addr (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int ip_ifindex = nm_device_get_ip_ifindex (self);
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
struct in6_addr lladdr;
|
||||
guint i, n;
|
||||
NMConnection *connection;
|
||||
NMSettingIP6Config *s_ip6 = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
if (priv->nm_ipv6ll == FALSE)
|
||||
return;
|
||||
|
|
@ -4840,22 +4849,54 @@ check_and_add_ipv6ll_addr (NMDevice *self)
|
|||
const NMPlatformIP6Address *addr;
|
||||
|
||||
addr = nm_ip6_config_get_address (priv->ip6_config, i);
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) {
|
||||
if ( IN6_IS_ADDR_LINKLOCAL (&addr->address)
|
||||
&& !(addr->flags & IFA_F_DADFAILED)) {
|
||||
/* Already have an LL address, nothing to do */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
_LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 may be broken");
|
||||
return;
|
||||
}
|
||||
|
||||
memset (&lladdr, 0, sizeof (lladdr));
|
||||
lladdr.s6_addr16[0] = htons (0xfe80);
|
||||
nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid);
|
||||
_LOGD (LOGD_IP6, "adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL));
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
if (connection)
|
||||
s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection));
|
||||
|
||||
if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
|
||||
if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr,
|
||||
nm_device_get_iface (self),
|
||||
nm_connection_get_uuid (connection),
|
||||
priv->linklocal6_dad_counter++,
|
||||
&error)) {
|
||||
_LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
linklocal6_failed (self);
|
||||
return;
|
||||
}
|
||||
_LOGD (LOGD_IP6, "linklocal6: using IPv6 stable-privacy addressing");
|
||||
} else {
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
if (priv->linklocal6_timeout_id) {
|
||||
/* We already started and attempt to add a LL address. For the EUI-64
|
||||
* mode we can't pick a new one, we'll just fail. */
|
||||
_LOGW (LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address");
|
||||
linklocal6_failed (self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
_LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue");
|
||||
return;
|
||||
}
|
||||
_LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address");
|
||||
|
||||
nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid);
|
||||
}
|
||||
|
||||
_LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL));
|
||||
if (!nm_platform_ip6_address_add (NM_PLATFORM_GET,
|
||||
ip_ifindex,
|
||||
lladdr,
|
||||
|
|
@ -5128,10 +5169,15 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
g_assert (priv->rdisc);
|
||||
|
||||
if (nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &iid)) {
|
||||
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
||||
} else if (!nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
_LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 cannot continue");
|
||||
return FALSE;
|
||||
_LOGD (LOGD_IP6, "addrconf6: IPv6 tokenized identifier present");
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
} else if (nm_device_get_ip_iface_identifier (self, &iid)) {
|
||||
_LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
} else {
|
||||
/* Don't abort the addrconf at this point -- if rdisc needs the iid
|
||||
* it will notice this itself. */
|
||||
_LOGI (LOGD_IP6, "addrconf6: no interface identifier; IPv6 adddress creation may fail");
|
||||
}
|
||||
|
||||
/* Apply any manual configuration before starting RA */
|
||||
|
|
@ -5152,7 +5198,6 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
G_CALLBACK (rdisc_ra_timeout),
|
||||
self);
|
||||
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -5163,7 +5208,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMConnection *connection;
|
||||
NMActStageReturn ret;
|
||||
const char *ip_iface = nm_device_get_ip_iface (self);
|
||||
NMSettingIP6Config *s_ip6 = NULL;
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
g_assert (connection);
|
||||
|
|
@ -5174,9 +5219,15 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
|||
priv->ac_ip6_config = NULL;
|
||||
}
|
||||
|
||||
priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface);
|
||||
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),
|
||||
nm_device_get_ip_iface (self),
|
||||
nm_connection_get_uuid (connection),
|
||||
nm_setting_ip6_config_get_addr_gen_mode (s_ip6));
|
||||
if (!priv->rdisc) {
|
||||
_LOGE (LOGD_IP6, "failed to start router discovery (%s)", ip_iface);
|
||||
_LOGE (LOGD_IP6, "addrconf6: failed to start router discovery");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -7794,6 +7845,8 @@ queued_ip6_config_change (gpointer user_data)
|
|||
{
|
||||
NMDevice *self = NM_DEVICE (user_data);
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
GSList *iter;
|
||||
gboolean need_ipv6ll = FALSE;
|
||||
|
||||
/* Wait for any queued state changes */
|
||||
if (priv->queued_state.id)
|
||||
|
|
@ -7803,12 +7856,32 @@ queued_ip6_config_change (gpointer user_data)
|
|||
g_object_ref (self);
|
||||
update_ip6_config (self, FALSE);
|
||||
|
||||
/* Handle DAD falures */
|
||||
for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) {
|
||||
NMPlatformIP6Address *addr = iter->data;
|
||||
|
||||
if (addr->source >= NM_IP_CONFIG_SOURCE_USER)
|
||||
continue;
|
||||
|
||||
_LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address",
|
||||
nm_platform_ip6_address_to_string (addr, NULL, 0));
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
|
||||
need_ipv6ll = TRUE;
|
||||
else
|
||||
nm_rdisc_dad_failed (priv->rdisc, &addr->address);
|
||||
}
|
||||
g_slist_free_full (priv->dad6_failed_addrs, g_free);
|
||||
|
||||
/* If no IPv6 link-local address exists but other addresses do then we
|
||||
* must add the LL address to remain conformant with RFC 3513 chapter 2.1
|
||||
* ("Addressing Model"): "All interfaces are required to have at least
|
||||
* one link-local unicast address".
|
||||
*/
|
||||
if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config))
|
||||
need_ipv6ll = TRUE;
|
||||
|
||||
if (need_ipv6ll)
|
||||
check_and_add_ipv6ll_addr (self);
|
||||
|
||||
g_object_unref (self);
|
||||
|
|
@ -7826,11 +7899,13 @@ device_ipx_changed (NMPlatform *platform,
|
|||
NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
NMPlatformIP6Address *addr;
|
||||
|
||||
if (nm_device_get_ip_ifindex (self) != ifindex)
|
||||
return;
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
switch (obj_type) {
|
||||
case NMP_OBJECT_TYPE_IP4_ADDRESS:
|
||||
case NMP_OBJECT_TYPE_IP4_ROUTE:
|
||||
|
|
@ -7840,6 +7915,14 @@ device_ipx_changed (NMPlatform *platform,
|
|||
}
|
||||
break;
|
||||
case NMP_OBJECT_TYPE_IP6_ADDRESS:
|
||||
addr = platform_object;
|
||||
|
||||
if ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED)
|
||||
|| (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE)) {
|
||||
priv->dad6_failed_addrs = g_slist_append (priv->dad6_failed_addrs,
|
||||
g_memdup (addr, sizeof (NMPlatformIP6Address)));
|
||||
}
|
||||
/* fallthrough */
|
||||
case NMP_OBJECT_TYPE_IP6_ROUTE:
|
||||
if (!priv->queued_ip6_config_id) {
|
||||
priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self);
|
||||
|
|
@ -8580,6 +8663,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||
priv->v4_commit_first_time = TRUE;
|
||||
priv->v6_commit_first_time = TRUE;
|
||||
|
||||
priv->linklocal6_dad_counter = 0;
|
||||
|
||||
nm_default_route_manager_ip4_update_default_route (nm_default_route_manager_get (), self);
|
||||
nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self);
|
||||
|
||||
|
|
@ -8828,6 +8913,9 @@ nm_device_spawn_iface_helper (NMDevice *self)
|
|||
g_ptr_array_add (argv, hex_iid);
|
||||
}
|
||||
|
||||
g_ptr_array_add (argv, g_strdup ("--addr-gen-mode"));
|
||||
g_ptr_array_add (argv, g_strdup_printf ("%d", nm_setting_ip6_config_get_addr_gen_mode (NM_SETTING_IP6_CONFIG (s_ip6))));
|
||||
|
||||
configured = TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -9731,6 +9819,7 @@ finalize (GObject *object)
|
|||
g_free (priv->perm_hw_addr);
|
||||
g_free (priv->initial_hw_addr);
|
||||
g_slist_free_full (priv->pending_actions, g_free);
|
||||
g_slist_free_full (priv->dad6_failed_addrs, g_free);
|
||||
g_clear_pointer (&priv->physical_port_id, g_free);
|
||||
g_free (priv->udi);
|
||||
g_free (priv->iface);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ extern unsigned int if_nametoindex (const char *__ifname);
|
|||
#include "nm-rdisc.h"
|
||||
#include "nm-lndp-rdisc.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
|
||||
#if !defined(NM_DIST_VERSION)
|
||||
# define NM_DIST_VERSION VERSION
|
||||
|
|
@ -69,6 +70,7 @@ static struct {
|
|||
char *dhcp4_clientid;
|
||||
char *dhcp4_hostname;
|
||||
char *iid_str;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
char *logging_backend;
|
||||
char *opt_log_level;
|
||||
char *opt_log_domains;
|
||||
|
|
@ -292,6 +294,7 @@ do_early_setup (int *argc, char **argv[])
|
|||
{ "priority4", '\0', 0, G_OPTION_ARG_INT64, &priority64_v4, N_("Route priority for IPv4"), N_("0") },
|
||||
{ "priority6", '\0', 0, G_OPTION_ARG_INT64, &priority64_v6, N_("Route priority for IPv6"), N_("1024") },
|
||||
{ "iid", 'e', 0, G_OPTION_ARG_STRING, &global_opt.iid_str, N_("Hex-encoded Interface Identifier"), "" },
|
||||
{ "addr-gen-mode", 'e', 0, G_OPTION_ARG_INT, &global_opt.addr_gen_mode, N_("IPv6 SLAAC address generation mode"), "eui64" },
|
||||
{ "logging-backend", '\0', 0, G_OPTION_ARG_STRING, &global_opt.logging_backend, N_("The logging backend configuration value. See logging.backend in NetworkManager.conf"), NULL },
|
||||
|
||||
/* Logging/debugging */
|
||||
|
|
@ -321,6 +324,20 @@ do_early_setup (int *argc, char **argv[])
|
|||
global_opt.priority_v6 = (guint32) priority64_v6;
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_address_changed (NMPlatform *platform,
|
||||
NMPObjectType obj_type,
|
||||
int iface,
|
||||
NMPlatformIP6Address *addr,
|
||||
NMPlatformSignalChangeType change_type,
|
||||
NMPlatformReason reason,
|
||||
NMRDisc *rdisc)
|
||||
{
|
||||
if ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED)
|
||||
|| (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE))
|
||||
nm_rdisc_dad_failed (rdisc, &addr->address);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
|
|
@ -456,7 +473,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);
|
||||
rdisc = nm_lndp_rdisc_new (ifindex, global_opt.ifname, global_opt.uuid, global_opt.addr_gen_mode);
|
||||
g_assert (rdisc);
|
||||
|
||||
if (iid)
|
||||
|
|
@ -467,6 +484,10 @@ main (int argc, char *argv[])
|
|||
nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_pinfo"), "0");
|
||||
nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_rtr_pref"), "0");
|
||||
|
||||
g_signal_connect (NM_PLATFORM_GET,
|
||||
NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
|
||||
G_CALLBACK (ip6_address_changed),
|
||||
rdisc);
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
G_CALLBACK (rdisc_config_changed),
|
||||
|
|
|
|||
|
|
@ -36,14 +36,23 @@ typedef struct {
|
|||
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
GArray *gateways;
|
||||
GArray *addresses;
|
||||
GArray *routes;
|
||||
GArray *prefixes;
|
||||
GArray *dns_servers;
|
||||
GArray *dns_domains;
|
||||
int hop_limit;
|
||||
guint32 mtu;
|
||||
} FakeRa;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr network;
|
||||
int plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
NMRDiscPreference preference;
|
||||
} FakePrefix;
|
||||
|
||||
typedef struct {
|
||||
guint receive_ra_id;
|
||||
GSList *ras;
|
||||
|
|
@ -67,8 +76,7 @@ fake_ra_free (gpointer data)
|
|||
FakeRa *ra = data;
|
||||
|
||||
g_array_free (ra->gateways, TRUE);
|
||||
g_array_free (ra->addresses, TRUE);
|
||||
g_array_free (ra->routes, TRUE);
|
||||
g_array_free (ra->prefixes, TRUE);
|
||||
g_array_free (ra->dns_servers, TRUE);
|
||||
g_array_free (ra->dns_domains, TRUE);
|
||||
g_free (ra);
|
||||
|
|
@ -110,8 +118,7 @@ nm_fake_rdisc_add_ra (NMFakeRDisc *self,
|
|||
ra->hop_limit = hop_limit;
|
||||
ra->mtu = mtu;
|
||||
ra->gateways = g_array_new (FALSE, FALSE, sizeof (NMRDiscGateway));
|
||||
ra->addresses = g_array_new (FALSE, FALSE, sizeof (NMRDiscAddress));
|
||||
ra->routes = g_array_new (FALSE, FALSE, sizeof (NMRDiscRoute));
|
||||
ra->prefixes = g_array_new (FALSE, FALSE, sizeof (FakePrefix));
|
||||
ra->dns_servers = g_array_new (FALSE, FALSE, sizeof (NMRDiscDNSServer));
|
||||
ra->dns_domains = g_array_new (FALSE, FALSE, sizeof (NMRDiscDNSDomain));
|
||||
g_array_set_clear_func (ra->dns_domains, ra_dns_domain_free);
|
||||
|
|
@ -142,49 +149,31 @@ nm_fake_rdisc_add_gateway (NMFakeRDisc *self,
|
|||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_address (NMFakeRDisc *self,
|
||||
guint ra_id,
|
||||
const char *addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred)
|
||||
nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
||||
guint ra_id,
|
||||
const char *network,
|
||||
guint plen,
|
||||
const char *gateway,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
NMRDiscPreference preference)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
NMRDiscAddress *a;
|
||||
FakePrefix *prefix;
|
||||
|
||||
g_assert (ra);
|
||||
g_array_set_size (ra->addresses, ra->addresses->len + 1);
|
||||
a = &g_array_index (ra->addresses, NMRDiscAddress, ra->addresses->len - 1);
|
||||
g_assert (inet_pton (AF_INET6, addr, &a->address) == 1);
|
||||
a->timestamp = timestamp;
|
||||
a->lifetime = lifetime;
|
||||
a->preferred = preferred;
|
||||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_route (NMFakeRDisc *self,
|
||||
guint ra_id,
|
||||
const char *network,
|
||||
guint plen,
|
||||
const char *gateway,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
NMRDiscPreference preference)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
NMRDiscRoute *route;
|
||||
|
||||
g_assert (ra);
|
||||
g_array_set_size (ra->routes, ra->routes->len + 1);
|
||||
route = &g_array_index (ra->routes, NMRDiscRoute, ra->routes->len - 1);
|
||||
g_assert (inet_pton (AF_INET6, network, &route->network) == 1);
|
||||
g_assert (inet_pton (AF_INET6, gateway, &route->gateway) == 1);
|
||||
route->plen = plen;
|
||||
route->timestamp = timestamp;
|
||||
route->lifetime = lifetime;
|
||||
route->preference = preference;
|
||||
g_array_set_size (ra->prefixes, ra->prefixes->len + 1);
|
||||
prefix = &g_array_index (ra->prefixes, FakePrefix, ra->prefixes->len - 1);
|
||||
memset (prefix, 0, sizeof (*prefix));
|
||||
g_assert (inet_pton (AF_INET6, network, &prefix->network) == 1);
|
||||
g_assert (inet_pton (AF_INET6, gateway, &prefix->gateway) == 1);
|
||||
prefix->plen = plen;
|
||||
prefix->timestamp = timestamp;
|
||||
prefix->lifetime = lifetime;
|
||||
prefix->preferred = preferred;
|
||||
prefix->preference = preference;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -265,18 +254,32 @@ receive_ra (gpointer user_data)
|
|||
changed |= NM_RDISC_CONFIG_GATEWAYS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->addresses->len; i++) {
|
||||
NMRDiscAddress *item = &g_array_index (ra->addresses, NMRDiscAddress, i);
|
||||
for (i = 0; i < ra->prefixes->len; i++) {
|
||||
FakePrefix *item = &g_array_index (ra->prefixes, FakePrefix, i);
|
||||
NMRDiscRoute route = {
|
||||
.network = item->network,
|
||||
.plen = item->plen,
|
||||
.gateway = item->gateway,
|
||||
.timestamp = item->timestamp,
|
||||
.lifetime = item->lifetime,
|
||||
.preference = item->preference,
|
||||
};
|
||||
|
||||
if (nm_rdisc_add_address (rdisc, item))
|
||||
changed |= NM_RDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->routes->len; i++) {
|
||||
NMRDiscRoute *item = &g_array_index (ra->routes, NMRDiscRoute, i);
|
||||
|
||||
if (nm_rdisc_add_route (rdisc, item))
|
||||
if (nm_rdisc_add_route (rdisc, &route))
|
||||
changed |= NM_RDISC_CONFIG_ROUTES;
|
||||
|
||||
if (item->plen == 64) {
|
||||
NMRDiscAddress address = {
|
||||
.address = item->network,
|
||||
.timestamp = item->timestamp,
|
||||
.lifetime = item->lifetime,
|
||||
.preferred = item->preferred,
|
||||
.dad_counter = 0,
|
||||
};
|
||||
|
||||
if (nm_rdisc_complete_and_add_address (rdisc, &address))
|
||||
changed |= NM_RDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->dns_servers->len; i++) {
|
||||
|
|
|
|||
|
|
@ -59,20 +59,14 @@ void nm_fake_rdisc_add_gateway (NMFakeRDisc *self,
|
|||
guint32 lifetime,
|
||||
NMRDiscPreference preference);
|
||||
|
||||
void nm_fake_rdisc_add_address (NMFakeRDisc *self,
|
||||
guint ra_id,
|
||||
const char *addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred);
|
||||
|
||||
void nm_fake_rdisc_add_route (NMFakeRDisc *self,
|
||||
void nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
||||
guint ra_id,
|
||||
const char *network,
|
||||
guint plen,
|
||||
const char *gateway,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
NMRDiscPreference preference);
|
||||
|
||||
void nm_fake_rdisc_add_dns_server (NMFakeRDisc *self,
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
|
||||
/* Address */
|
||||
if (ndp_msg_opt_prefix_flag_auto_addr_conf (msg, offset)) {
|
||||
if (route.plen == 64 && rdisc->iid.id) {
|
||||
if (route.plen == 64) {
|
||||
memset (&address, 0, sizeof (address));
|
||||
address.address = route.network;
|
||||
address.timestamp = now;
|
||||
|
|
@ -172,10 +172,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
|
||||
/* Add the Interface Identifier to the lower 64 bits */
|
||||
nm_utils_ipv6_addr_set_interface_identfier (&address.address, rdisc->iid);
|
||||
|
||||
if (nm_rdisc_add_address (rdisc, &address))
|
||||
if (nm_rdisc_complete_and_add_address (rdisc, &address))
|
||||
changed |= NM_RDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
|
|
@ -300,7 +297,7 @@ ipv6_sysctl_get (const char *ifname, const char *property, gint32 defval)
|
|||
}
|
||||
|
||||
NMRDisc *
|
||||
nm_lndp_rdisc_new (int ifindex, const char *ifname)
|
||||
nm_lndp_rdisc_new (int ifindex, const char *ifname, const char *uuid, NMSettingIP6ConfigAddrGenMode addr_gen_mode)
|
||||
{
|
||||
NMRDisc *rdisc;
|
||||
NMLNDPRDiscPrivate *priv;
|
||||
|
|
@ -310,6 +307,8 @@ nm_lndp_rdisc_new (int ifindex, const char *ifname)
|
|||
|
||||
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",
|
||||
NM_RDISC_MAX_ADDRESSES_DEFAULT);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,6 @@ typedef struct {
|
|||
|
||||
GType nm_lndp_rdisc_get_type (void);
|
||||
|
||||
NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname);
|
||||
NMRDisc *nm_lndp_rdisc_new (int ifindex, const char *ifname, const char *uuid, NMSettingIP6ConfigAddrGenMode addr_gen_mode);
|
||||
|
||||
#endif /* __NETWORKMANAGER_LNDP_RDISC_H__ */
|
||||
|
|
|
|||
|
|
@ -27,11 +27,11 @@
|
|||
|
||||
void nm_rdisc_ra_received (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap changed);
|
||||
|
||||
gboolean nm_rdisc_add_gateway (NMRDisc *rdisc, const NMRDiscGateway *new);
|
||||
gboolean nm_rdisc_add_address (NMRDisc *rdisc, const NMRDiscAddress *new);
|
||||
gboolean nm_rdisc_add_route (NMRDisc *rdisc, const NMRDiscRoute *new);
|
||||
gboolean nm_rdisc_add_dns_server (NMRDisc *rdisc, const NMRDiscDNSServer *new);
|
||||
gboolean nm_rdisc_add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDomain *new);
|
||||
gboolean nm_rdisc_add_gateway (NMRDisc *rdisc, const NMRDiscGateway *new);
|
||||
gboolean nm_rdisc_complete_and_add_address (NMRDisc *rdisc, NMRDiscAddress *new);
|
||||
gboolean nm_rdisc_add_route (NMRDisc *rdisc, const NMRDiscRoute *new);
|
||||
gboolean nm_rdisc_add_dns_server (NMRDisc *rdisc, const NMRDiscDNSServer *new);
|
||||
gboolean nm_rdisc_add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDomain *new);
|
||||
|
||||
/*********************************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
#include "nm-default.h"
|
||||
#include "nm-utils.h"
|
||||
|
||||
#include <nm-setting-ip6-config.h>
|
||||
|
||||
#define _NMLOG_PREFIX_NAME "rdisc"
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -87,11 +89,63 @@ nm_rdisc_add_gateway (NMRDisc *rdisc, const NMRDiscGateway *new)
|
|||
return !!new->lifetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* complete_address:
|
||||
* @rdisc: the #NMRDisc
|
||||
* @addr: the #NMRDiscAddress
|
||||
*
|
||||
* Adds the host part to the address that has network part set.
|
||||
* If the address already has a host part, add a different host part
|
||||
* if possible (this is useful in case DAD failed).
|
||||
*
|
||||
* Can fail if a different address can not be generated (DAD failure
|
||||
* for an EUI-64 address or DAD counter overflow).
|
||||
*
|
||||
* Returns: %TRUE if the address could be completed, %FALSE otherwise.
|
||||
**/
|
||||
static gboolean
|
||||
complete_address (NMRDisc *rdisc, NMRDiscAddress *addr)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (rdisc->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) {
|
||||
if (!nm_utils_ipv6_addr_set_stable_privacy (&addr->address,
|
||||
rdisc->ifname,
|
||||
rdisc->uuid,
|
||||
addr->dad_counter++,
|
||||
&error)) {
|
||||
_LOGW ("complete-address: failed to generate an stable-privacy address: %s",
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
_LOGD ("complete-address: using an stable-privacy address");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!rdisc->iid.id) {
|
||||
_LOGW ("complete-address: can't generate an EUI-64 address: no interface identifier");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (addr->address.s6_addr32[2] == 0x0 && addr->address.s6_addr32[3] == 0x0) {
|
||||
_LOGD ("complete-address: adding an EUI-64 address");
|
||||
nm_utils_ipv6_addr_set_interface_identfier (&addr->address, rdisc->iid);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_LOGW ("complete-address: can't generate a new EUI-64 address");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_rdisc_add_address (NMRDisc *rdisc, const NMRDiscAddress *new)
|
||||
nm_rdisc_complete_and_add_address (NMRDisc *rdisc, NMRDiscAddress *new)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!complete_address (rdisc, new))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < rdisc->addresses->len; i++) {
|
||||
NMRDiscAddress *item = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
|
||||
|
||||
|
|
@ -233,7 +287,10 @@ nm_rdisc_add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDomain *new)
|
|||
* the old identifier are removed. The caller should ensure the addresses
|
||||
* will be reset by soliciting router advertisements.
|
||||
*
|
||||
* Returns: %TRUE if the token was changed, %FALSE otherwise.
|
||||
* In case the stable privacy addressing is used %FALSE is returned and
|
||||
* addresses are left untouched.
|
||||
*
|
||||
* Returns: %TRUE if addresses need to be regenerated, %FALSE otherwise.
|
||||
**/
|
||||
gboolean
|
||||
nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
|
||||
|
|
@ -242,6 +299,10 @@ nm_rdisc_set_iid (NMRDisc *rdisc, const NMUtilsIPv6IfaceId iid)
|
|||
|
||||
if (rdisc->iid.id != iid.id) {
|
||||
rdisc->iid = iid;
|
||||
|
||||
if (rdisc->addr_gen_mode == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY)
|
||||
return FALSE;
|
||||
|
||||
if (rdisc->addresses->len) {
|
||||
_LOGD ("IPv6 interface identifier changed, flushing addresses");
|
||||
g_array_remove_range (rdisc->addresses, 0, rdisc->addresses->len);
|
||||
|
|
@ -350,6 +411,28 @@ nm_rdisc_start (NMRDisc *rdisc)
|
|||
solicit (rdisc);
|
||||
}
|
||||
|
||||
void
|
||||
nm_rdisc_dad_failed (NMRDisc *rdisc, struct in6_addr *address)
|
||||
{
|
||||
int i;
|
||||
gboolean changed = FALSE;
|
||||
|
||||
for (i = 0; i < rdisc->addresses->len; i++) {
|
||||
NMRDiscAddress *item = &g_array_index (rdisc->addresses, NMRDiscAddress, i);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL (&item->address, address))
|
||||
continue;
|
||||
|
||||
_LOGD ("DAD failed for discovered address %s", nm_utils_inet6_ntop (address, NULL));
|
||||
if (!complete_address (rdisc, item))
|
||||
g_array_remove_index (rdisc->addresses, i--);
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
g_signal_emit_by_name (rdisc, NM_RDISC_CONFIG_CHANGED, NM_RDISC_CONFIG_ADDRESSES);
|
||||
}
|
||||
|
||||
#define CONFIG_MAP_MAX_STR 7
|
||||
|
||||
static void
|
||||
|
|
@ -636,6 +719,7 @@ finalize (GObject *object)
|
|||
NMRDisc *rdisc = NM_RDISC (object);
|
||||
|
||||
g_free (rdisc->ifname);
|
||||
g_free (rdisc->uuid);
|
||||
g_array_unref (rdisc->gateways);
|
||||
g_array_unref (rdisc->addresses);
|
||||
g_array_unref (rdisc->routes);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <netinet/in.h>
|
||||
|
||||
#include "nm-default.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#define NM_TYPE_RDISC (nm_rdisc_get_type ())
|
||||
|
|
@ -61,6 +62,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint8 dad_counter;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
|
|
@ -114,6 +116,8 @@ typedef struct {
|
|||
|
||||
int ifindex;
|
||||
char *ifname;
|
||||
char *uuid;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
gint32 max_addresses;
|
||||
gint32 rtr_solicitations;
|
||||
|
|
@ -143,5 +147,6 @@ GType nm_rdisc_get_type (void);
|
|||
|
||||
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);
|
||||
|
||||
#endif /* __NETWORKMANAGER_RDISC_H__ */
|
||||
|
|
|
|||
|
|
@ -37,8 +37,11 @@ rdisc_new (void)
|
|||
NMRDisc *rdisc;
|
||||
const int ifindex = 1;
|
||||
const char *ifname = nm_platform_link_get_name (NM_PLATFORM_GET, ifindex);
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
rdisc = nm_fake_rdisc_new (ifindex, ifname);
|
||||
iid.id_u8[7] = 1;
|
||||
nm_rdisc_set_iid (rdisc, iid);
|
||||
g_assert (rdisc);
|
||||
return NM_FAKE_RDISC (rdisc);
|
||||
}
|
||||
|
|
@ -145,8 +148,7 @@ test_simple (void)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_OTHERCONF, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_rdisc_add_dns_server (rdisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_rdisc_add_dns_domain (rdisc, id, "foobar.com", now, 10);
|
||||
|
||||
|
|
@ -198,7 +200,7 @@ test_everything_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, TestData *dat
|
|||
g_assert_cmpint (rdisc->gateways->len, ==, 1);
|
||||
match_gateway (rdisc->gateways, 0, "fe80::2", data->timestamp1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (rdisc->addresses->len, ==, 1);
|
||||
match_address (rdisc->addresses, 0, "2001:db8:a:a::2", data->timestamp1, 10, 10);
|
||||
match_address (rdisc->addresses, 0, "2001:db8:a:b::1", data->timestamp1, 10, 10);
|
||||
g_assert_cmpint (rdisc->routes->len, ==, 1);
|
||||
match_route (rdisc->routes, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1, 10, 10);
|
||||
g_assert_cmpint (rdisc->dns_servers->len, ==, 1);
|
||||
|
|
@ -225,8 +227,7 @@ test_everything (void)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_rdisc_add_dns_server (rdisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_rdisc_add_dns_domain (rdisc, id, "foobar.com", now, 10);
|
||||
|
||||
|
|
@ -234,15 +235,13 @@ test_everything (void)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 0, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 0, 0);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 0, 0);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 0, 0, 0);
|
||||
nm_fake_rdisc_add_dns_server (rdisc, id, "2001:db8:c:c::1", now, 0);
|
||||
nm_fake_rdisc_add_dns_domain (rdisc, id, "foobar.com", now, 0);
|
||||
|
||||
/* and add some new stuff */
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::2", now, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::2", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_rdisc_add_dns_server (rdisc, id, "2001:db8:c:c::2", now, 10);
|
||||
nm_fake_rdisc_add_dns_domain (rdisc, id, "foobar2.com", now, 10);
|
||||
|
||||
|
|
@ -276,7 +275,7 @@ test_preference_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, TestData *dat
|
|||
match_gateway (rdisc->gateways, 1, "fe80::1", data->timestamp1, 10, NM_RDISC_PREFERENCE_LOW);
|
||||
g_assert_cmpint (rdisc->addresses->len, ==, 2);
|
||||
match_address (rdisc->addresses, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_address (rdisc->addresses, 1, "2001:db8:a:a::2", data->timestamp1 + 1, 10, 10);
|
||||
match_address (rdisc->addresses, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
g_assert_cmpint (rdisc->routes->len, ==, 2);
|
||||
match_route (rdisc->routes, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
match_route (rdisc->routes, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5);
|
||||
|
|
@ -290,7 +289,7 @@ test_preference_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, TestData *dat
|
|||
match_gateway (rdisc->gateways, 1, "fe80::2", data->timestamp1 + 1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (rdisc->addresses->len, ==, 2);
|
||||
match_address (rdisc->addresses, 0, "2001:db8:a:a::1", data->timestamp1 + 2, 10, 10);
|
||||
match_address (rdisc->addresses, 1, "2001:db8:a:a::2", data->timestamp1 + 1, 10, 10);
|
||||
match_address (rdisc->addresses, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
g_assert_cmpint (rdisc->routes->len, ==, 2);
|
||||
match_route (rdisc->routes, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1 + 2, 10, 15);
|
||||
match_route (rdisc->routes, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
|
|
@ -318,20 +317,17 @@ test_preference (void)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 10, NM_RDISC_PREFERENCE_LOW);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 5);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5);
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::2", ++now, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::2", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", ++now, 10, NM_RDISC_PREFERENCE_HIGH);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_route (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 15);
|
||||
nm_fake_rdisc_add_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 15);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
|
|
@ -380,7 +376,6 @@ test_dns_solicit_loop_rs_sent (NMFakeRDisc *rdisc, TestData *data)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 0, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
|
||||
nm_fake_rdisc_emit_new_ras (rdisc);
|
||||
} else if (data->rs_counter >= 6) {
|
||||
|
|
@ -410,7 +405,6 @@ test_dns_solicit_loop (void)
|
|||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
g_assert (id);
|
||||
nm_fake_rdisc_add_gateway (rdisc, id, "fe80::1", now, 10, NM_RDISC_PREFERENCE_LOW);
|
||||
nm_fake_rdisc_add_address (rdisc, id, "2001:db8:a:a::1", now, 10, 10);
|
||||
nm_fake_rdisc_add_dns_server (rdisc, id, "2001:db8:c:c::1", now, 6);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ main (int argc, char **argv)
|
|||
NMRDisc *rdisc;
|
||||
int ifindex = 1;
|
||||
const char *ifname;
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT");
|
||||
|
||||
|
|
@ -60,12 +61,17 @@ main (int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
rdisc = nm_lndp_rdisc_new (ifindex, ifname);
|
||||
rdisc = nm_lndp_rdisc_new (ifindex,
|
||||
ifname,
|
||||
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64);
|
||||
if (!rdisc) {
|
||||
g_print ("Failed to create NMRDisc instance\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
iid.id_u8[7] = 1;
|
||||
nm_rdisc_set_iid (rdisc, iid);
|
||||
nm_rdisc_start (rdisc);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
|
|
|
|||
|
|
@ -1317,8 +1317,9 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
shvarFile *network_ifcfg;
|
||||
gboolean never_default = FALSE;
|
||||
gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip;
|
||||
char *ip6_privacy_str;
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy_val;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
char *tmp;
|
||||
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
||||
|
||||
|
|
@ -1402,20 +1403,20 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
/* TODO - handle other methods */
|
||||
|
||||
/* Read IPv6 Privacy Extensions configuration */
|
||||
ip6_privacy_str = svGetValue (ifcfg, "IPV6_PRIVACY", FALSE);
|
||||
if (ip6_privacy_str) {
|
||||
tmp = svGetValue (ifcfg, "IPV6_PRIVACY", FALSE);
|
||||
if (tmp) {
|
||||
ip6_privacy = svGetValueBoolean (ifcfg, "IPV6_PRIVACY", FALSE);
|
||||
if (!ip6_privacy)
|
||||
ip6_privacy = g_strcmp0 (ip6_privacy_str, "rfc4941") == 0 ||
|
||||
g_strcmp0 (ip6_privacy_str, "rfc3041") == 0;
|
||||
ip6_privacy = g_strcmp0 (tmp, "rfc4941") == 0 ||
|
||||
g_strcmp0 (tmp, "rfc3041") == 0;
|
||||
}
|
||||
ip6_privacy_prefer_public_ip = svGetValueBoolean (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", FALSE);
|
||||
ip6_privacy_val = ip6_privacy_str ?
|
||||
ip6_privacy_val = tmp ?
|
||||
(ip6_privacy ?
|
||||
(ip6_privacy_prefer_public_ip ? NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR : NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR) :
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED) :
|
||||
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN;
|
||||
g_free (ip6_privacy_str);
|
||||
g_free (tmp);
|
||||
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD, method,
|
||||
|
|
@ -1499,6 +1500,22 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
}
|
||||
}
|
||||
|
||||
/* IPv6 addressing mode configuration */
|
||||
tmp = svGetValue (ifcfg, "IPV6_ADDR_GEN_MODE", FALSE);
|
||||
if (tmp) {
|
||||
if (nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), tmp,
|
||||
(int *) &addr_gen_mode, NULL))
|
||||
g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, addr_gen_mode, NULL);
|
||||
else
|
||||
PARSE_WARNING ("Invalid IPV6_ADDR_GEN_MODE");
|
||||
g_free (tmp);
|
||||
} else {
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* DNS servers
|
||||
* Pick up just IPv6 addresses (IPv4 addresses are taken by make_ip4_setting())
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2391,6 +2391,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
gint64 route_metric;
|
||||
GString *ip_str1, *ip_str2, *ip_ptr;
|
||||
char *route6_path;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
|
||||
s_ip6 = nm_connection_get_setting_ip6_config (connection);
|
||||
if (!s_ip6) {
|
||||
|
|
@ -2403,6 +2404,7 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svSetValue (ifcfg, "IPV6_PEERROUTES", "yes", FALSE);
|
||||
svSetValue (ifcfg, "IPV6_FAILURE_FATAL", "no", FALSE);
|
||||
svSetValue (ifcfg, "IPV6_ROUTE_METRIC", NULL, FALSE);
|
||||
svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", "stable-privacy", FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -2540,6 +2542,15 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
break;
|
||||
}
|
||||
|
||||
/* IPv6 Address generation mode */
|
||||
addr_gen_mode = nm_setting_ip6_config_get_addr_gen_mode (NM_SETTING_IP6_CONFIG (s_ip6));
|
||||
if (addr_gen_mode != NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64) {
|
||||
tmp = nm_utils_enum_to_str (nm_setting_ip6_config_addr_gen_mode_get_type (),
|
||||
addr_gen_mode);
|
||||
svSetValue (ifcfg, "IPV6_ADDR_GEN_MODE", tmp, FALSE);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
/* Static routes go to route6-<dev> file */
|
||||
route6_path = utils_get_route6_path (ifcfg->fileName);
|
||||
if (!route6_path) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ noinst_PROGRAMS = \
|
|||
test-route-manager-fake \
|
||||
test-dcb \
|
||||
test-resolvconf-capture \
|
||||
test-wired-defname
|
||||
test-wired-defname \
|
||||
test-utils
|
||||
|
||||
####### ip4 config test #######
|
||||
|
||||
|
|
@ -110,6 +111,22 @@ test_wired_defname_SOURCES = \
|
|||
test_wired_defname_LDADD = \
|
||||
$(top_builddir)/src/libNetworkManager.la
|
||||
|
||||
####### utils test #######
|
||||
|
||||
test_utils_SOURCES = \
|
||||
test-utils.c
|
||||
|
||||
test_utils_DEPENDENCIES = \
|
||||
$(top_srcdir)/src/NetworkManagerUtils.c
|
||||
|
||||
test_utils_CPPFLAGS = \
|
||||
$(AM_CPPFLAGS) \
|
||||
-DPREFIX=\"/nonexistent\" \
|
||||
-DNMSTATEDIR=\"/nonsense\"
|
||||
|
||||
test_utils_LDADD = \
|
||||
$(top_builddir)/src/libNetworkManager.la
|
||||
|
||||
####### secret agent interface test #######
|
||||
|
||||
EXTRA_DIST = test-secret-agent.py
|
||||
|
|
@ -126,7 +143,8 @@ TESTS = \
|
|||
test-resolvconf-capture \
|
||||
test-general \
|
||||
test-general-with-expect \
|
||||
test-wired-defname
|
||||
test-wired-defname \
|
||||
test-utils
|
||||
|
||||
|
||||
if ENABLE_TESTS
|
||||
|
|
|
|||
63
src/tests/test-utils.c
Normal file
63
src/tests/test-utils.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2015 Red Hat, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "NetworkManagerUtils.c"
|
||||
|
||||
#include "nm-test-utils.h"
|
||||
|
||||
static void
|
||||
test_stable_privacy (void)
|
||||
{
|
||||
struct in6_addr addr1;
|
||||
|
||||
inet_pton (AF_INET6, "1234::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", "6b138152-9f3e-4b97-aaf7-e6e553f2a24e", 0, "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "1234::4ceb:14cd:3d54:793f");
|
||||
|
||||
/* We get an address without the UUID. */
|
||||
inet_pton (AF_INET6, "1::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "1::11aa:2530:9144:dafa");
|
||||
|
||||
/* We get a different address in a different network. */
|
||||
inet_pton (AF_INET6, "2::", &addr1);
|
||||
_set_stable_privacy (&addr1, "eth666", NULL, 384, "key", 3, NULL);
|
||||
nmtst_assert_ip6_address (&addr1, "2::338e:8d:c11:8726");
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
nmtst_init_with_logging (&argc, &argv, NULL, "ALL");
|
||||
|
||||
g_test_add_func ("/utils/stable_privacy", test_stable_privacy);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue