mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-28 05:10:09 +01:00
merge: branch 'lr/ipv6-sharing'
https://bugzilla.gnome.org/show_bug.cgi?id=773777
This commit is contained in:
commit
ecc6040cd8
39 changed files with 2093 additions and 1086 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -247,8 +247,8 @@ test-*.trs
|
|||
/src/dhcp-manager/tests/test-dhcp-utils
|
||||
/src/dnsmasq-manager/tests/test-dnsmasq-utils
|
||||
/src/nm-iface-helper
|
||||
/src/rdisc/tests/test-rdisc-fake
|
||||
/src/rdisc/tests/test-rdisc-linux
|
||||
/src/ndisc/tests/test-ndisc-fake
|
||||
/src/ndisc/tests/test-ndisc-linux
|
||||
/src/settings/plugins/ibft/tests/test-ibft
|
||||
/src/settings/plugins/ifcfg-rh/nmdbus-ifcfg-rh.[ch]
|
||||
/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh
|
||||
|
|
@ -289,3 +289,4 @@ test-*.trs
|
|||
/src/devices/wifi/tests/test-wifi-ap-utils
|
||||
/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh-utils
|
||||
/src/settings/plugins/ifnet/tests/check_ifnet
|
||||
/src/rdisc/
|
||||
|
|
|
|||
38
Makefile.am
38
Makefile.am
|
|
@ -900,7 +900,7 @@ src_cppflags = \
|
|||
-I$(top_srcdir)/src/platform \
|
||||
-I$(top_srcdir)/src/platform/wifi \
|
||||
-I$(top_srcdir)/src/ppp-manager \
|
||||
-I$(top_srcdir)/src/rdisc \
|
||||
-I$(top_srcdir)/src/ndisc \
|
||||
-I$(top_srcdir)/src/settings \
|
||||
-I$(top_srcdir)/src/supplicant-manager \
|
||||
-I$(top_srcdir)/src/vpn-manager \
|
||||
|
|
@ -1142,11 +1142,11 @@ src_libNetworkManagerBase_la_SOURCES = \
|
|||
src/platform/wifi/wifi-utils.c \
|
||||
src/platform/wifi/wifi-utils.h \
|
||||
\
|
||||
src/rdisc/nm-lndp-rdisc.c \
|
||||
src/rdisc/nm-lndp-rdisc.h \
|
||||
src/rdisc/nm-rdisc.c \
|
||||
src/rdisc/nm-rdisc.h \
|
||||
src/rdisc/nm-rdisc-private.h \
|
||||
src/ndisc/nm-lndp-ndisc.c \
|
||||
src/ndisc/nm-lndp-ndisc.h \
|
||||
src/ndisc/nm-ndisc.c \
|
||||
src/ndisc/nm-ndisc.h \
|
||||
src/ndisc/nm-ndisc-private.h \
|
||||
\
|
||||
src/nm-exported-object.c \
|
||||
src/nm-exported-object.h \
|
||||
|
|
@ -1381,8 +1381,8 @@ src_tests_cppflags_linux = $(src_tests_cppflags) -DSETUP=nm_linux_platform_setup
|
|||
src_libNetworkManagerTest_la_CPPFLAGS = $(src_tests_cppflags)
|
||||
|
||||
src_libNetworkManagerTest_la_SOURCES = \
|
||||
src/rdisc/nm-fake-rdisc.c \
|
||||
src/rdisc/nm-fake-rdisc.h \
|
||||
src/ndisc/nm-fake-ndisc.c \
|
||||
src/ndisc/nm-fake-ndisc.h \
|
||||
src/platform/nm-fake-platform.c \
|
||||
src/platform/nm-fake-platform.h \
|
||||
src/platform/tests/test-common.c \
|
||||
|
|
@ -2613,26 +2613,26 @@ src_devices_tests_test_arping_LDADD = \
|
|||
src/libNetworkManagerTest.la
|
||||
|
||||
###############################################################################
|
||||
# src/rdisc/tests
|
||||
# src/ndisc/tests
|
||||
###############################################################################
|
||||
|
||||
src_rdisc_tests_ldflags = \
|
||||
src_ndisc_tests_ldflags = \
|
||||
$(CODE_COVERAGE_LDFLAGS)
|
||||
|
||||
src_rdisc_tests_ldadd = \
|
||||
src_ndisc_tests_ldadd = \
|
||||
src/libNetworkManagerTest.la \
|
||||
$(GLIB_LIBS)
|
||||
|
||||
check_programs += src/rdisc/tests/test-rdisc-fake
|
||||
check_programs_norun += src/rdisc/tests/test-rdisc-linux
|
||||
check_programs += src/ndisc/tests/test-ndisc-fake
|
||||
check_programs_norun += src/ndisc/tests/test-ndisc-linux
|
||||
|
||||
src_rdisc_tests_test_rdisc_linux_CPPFLAGS = $(src_tests_cppflags)
|
||||
src_rdisc_tests_test_rdisc_linux_LDFLAGS = $(src_rdisc_tests_flags)
|
||||
src_rdisc_tests_test_rdisc_linux_LDADD = $(src_rdisc_tests_ldadd)
|
||||
src_ndisc_tests_test_ndisc_linux_CPPFLAGS = $(src_tests_cppflags)
|
||||
src_ndisc_tests_test_ndisc_linux_LDFLAGS = $(src_ndisc_tests_flags)
|
||||
src_ndisc_tests_test_ndisc_linux_LDADD = $(src_ndisc_tests_ldadd)
|
||||
|
||||
src_rdisc_tests_test_rdisc_fake_CPPFLAGS = $(src_tests_cppflags)
|
||||
src_rdisc_tests_test_rdisc_fake_LDFLAGS = $(src_rdisc_tests_flags)
|
||||
src_rdisc_tests_test_rdisc_fake_LDADD = $(src_rdisc_tests_ldadd)
|
||||
src_ndisc_tests_test_ndisc_fake_CPPFLAGS = $(src_tests_cppflags)
|
||||
src_ndisc_tests_test_ndisc_fake_LDFLAGS = $(src_ndisc_tests_flags)
|
||||
src_ndisc_tests_test_ndisc_fake_LDADD = $(src_ndisc_tests_ldadd)
|
||||
|
||||
###############################################################################
|
||||
# src/supplicant-manager/tests
|
||||
|
|
|
|||
|
|
@ -520,7 +520,7 @@ nmc_get_client (NmCli *nmc)
|
|||
if (!nmc->client) {
|
||||
nmc->client = nm_client_new (NULL, &error);
|
||||
if (!nmc->client) {
|
||||
g_critical (_("Error: Could not create NMClient object: %s."), error->message);
|
||||
g_printerr ("%s\n", error->message);
|
||||
g_clear_error (&error);
|
||||
exit (NMC_RESULT_ERROR_UNKNOWN);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,34 +172,38 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
} else if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
|
||||
|| !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
|
||||
|| !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
|
||||
if (nm_setting_ip_config_get_num_dns (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_setting_ip_config_get_num_dns_searches (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS_SEARCH);
|
||||
return FALSE;
|
||||
}
|
||||
/* Shared allows IP addresses and DNS; link-local and disabled do not */
|
||||
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) != 0) {
|
||||
if (nm_setting_ip_config_get_num_dns (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_setting_ip_config_get_num_addresses (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
|
||||
return FALSE;
|
||||
if (nm_setting_ip_config_get_num_dns_searches (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS_SEARCH);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (nm_setting_ip_config_get_num_addresses (s_ip) > 0) {
|
||||
g_set_error (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP_CONFIG_METHOD, method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
||||
|| !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
|
||||
|
|
|
|||
|
|
@ -868,14 +868,17 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_slist_length (priv->addresses)) {
|
||||
g_set_error (error,
|
||||
NM_SETTING_IP6_CONFIG_ERROR,
|
||||
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP6_CONFIG_METHOD, priv->method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
|
||||
return FALSE;
|
||||
/* Shared allows IP addresses; link-local and disabled do not */
|
||||
if (strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) != 0) {
|
||||
if (g_slist_length (priv->addresses)) {
|
||||
g_set_error (error,
|
||||
NM_SETTING_IP6_CONFIG_ERROR,
|
||||
NM_SETTING_IP6_CONFIG_ERROR_NOT_ALLOWED_FOR_METHOD,
|
||||
_("this property is not allowed for '%s=%s'"),
|
||||
NM_SETTING_IP6_CONFIG_METHOD, priv->method);
|
||||
g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_ADDRESSES);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
} else if ( !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
|
||||
|| !strcmp (priv->method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-lndp-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
#include "nm-lndp-ndisc.h"
|
||||
#include "nm-dhcp-manager.h"
|
||||
#include "nm-act-request.h"
|
||||
#include "nm-proxy-config.h"
|
||||
|
|
@ -83,6 +83,8 @@ enum {
|
|||
AUTH_REQUEST,
|
||||
IP4_CONFIG_CHANGED,
|
||||
IP6_CONFIG_CHANGED,
|
||||
IP6_PREFIX_DELEGATED,
|
||||
IP6_SUBNET_NEEDED,
|
||||
REMOVED,
|
||||
RECHECK_AUTO_ACTIVATE,
|
||||
RECHECK_ASSUME,
|
||||
|
|
@ -373,10 +375,10 @@ typedef struct _NMDevicePrivate {
|
|||
guint32 ip6_mtu;
|
||||
NMIP6Config * dad6_ip6_config;
|
||||
|
||||
NMRDisc * rdisc;
|
||||
gulong rdisc_changed_id;
|
||||
gulong rdisc_timeout_id;
|
||||
NMSettingIP6ConfigPrivacy rdisc_use_tempaddr;
|
||||
NMNDisc * ndisc;
|
||||
gulong ndisc_changed_id;
|
||||
gulong ndisc_timeout_id;
|
||||
NMSettingIP6ConfigPrivacy ndisc_use_tempaddr;
|
||||
/* IP6 config from autoconf */
|
||||
NMIP6Config * ac_ip6_config;
|
||||
|
||||
|
|
@ -387,8 +389,9 @@ typedef struct _NMDevicePrivate {
|
|||
|
||||
struct {
|
||||
NMDhcpClient * client;
|
||||
NMRDiscDHCPLevel mode;
|
||||
NMNDiscDHCPLevel mode;
|
||||
gulong state_sigid;
|
||||
gulong prefix_sigid;
|
||||
NMDhcp6Config * config;
|
||||
/* IP6 config from DHCP */
|
||||
NMIP6Config * ip6_config;
|
||||
|
|
@ -396,8 +399,11 @@ typedef struct _NMDevicePrivate {
|
|||
char * event_id;
|
||||
guint restart_id;
|
||||
guint num_tries_left;
|
||||
guint needed_prefixes;
|
||||
} dhcp6;
|
||||
|
||||
gboolean needs_ip6_subnet;
|
||||
|
||||
/* allow autoconnect feature */
|
||||
bool autoconnect;
|
||||
|
||||
|
|
@ -1626,7 +1632,7 @@ nm_device_update_dynamic_ip_setup (NMDevice *self)
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (priv->rdisc) {
|
||||
if (priv->ndisc) {
|
||||
/* FIXME: todo */
|
||||
}
|
||||
if (priv->dnsmasq_manager) {
|
||||
|
|
@ -1811,6 +1817,73 @@ device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ndisc_set_router_config (NMNDisc *ndisc, NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
GArray *addresses, *dns_servers, *dns_domains;
|
||||
guint len, i;
|
||||
|
||||
if (nm_ndisc_get_node_type (ndisc) != NM_NDISC_NODE_TYPE_ROUTER)
|
||||
return;
|
||||
|
||||
/* Addresses whose prefixes we announce. */
|
||||
len = nm_ip6_config_get_num_addresses (priv->ip6_config);
|
||||
addresses = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscAddress), len);
|
||||
for (i = 0; i < len; i++) {
|
||||
const NMPlatformIP6Address *addr = nm_ip6_config_get_address (priv->ip6_config, i);
|
||||
NMNDiscAddress *ndisc_addr;
|
||||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
|
||||
continue;
|
||||
|
||||
if ( addr->n_ifa_flags & IFA_F_TENTATIVE
|
||||
|| addr->n_ifa_flags & IFA_F_DADFAILED)
|
||||
continue;
|
||||
|
||||
if (addr->plen != 64)
|
||||
continue;
|
||||
|
||||
ndisc_addr = &g_array_index (addresses, NMNDiscAddress, addresses->len-1);
|
||||
ndisc_addr->address = addr->address;
|
||||
ndisc_addr->timestamp = addr->timestamp;
|
||||
ndisc_addr->lifetime = addr->lifetime;
|
||||
ndisc_addr->preferred = addr->preferred;
|
||||
}
|
||||
|
||||
/* DNS servers. */
|
||||
len = nm_ip6_config_get_num_nameservers (priv->ip6_config);
|
||||
dns_servers = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscDNSServer), len);
|
||||
for (i = 0; i < len; i++) {
|
||||
const struct in6_addr *nameserver = nm_ip6_config_get_nameserver (priv->ip6_config, i);
|
||||
NMNDiscDNSServer *ndisc_nameserver;
|
||||
|
||||
ndisc_nameserver = &g_array_index (dns_servers, NMNDiscDNSServer, dns_servers->len-1);
|
||||
ndisc_nameserver->address = *nameserver;
|
||||
ndisc_nameserver->timestamp = now;
|
||||
ndisc_nameserver->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
||||
}
|
||||
|
||||
/* DNS domains. */
|
||||
len = nm_ip6_config_get_num_searches (priv->ip6_config);
|
||||
dns_domains = g_array_sized_new (FALSE, FALSE, sizeof (NMNDiscDNSDomain), len);
|
||||
for (i = 0; i < len; i++) {
|
||||
const char *search = nm_ip6_config_get_search (priv->ip6_config, i);
|
||||
NMNDiscDNSDomain *ndisc_search;
|
||||
|
||||
ndisc_search = &g_array_index (dns_domains, NMNDiscDNSDomain, dns_domains->len-1);
|
||||
ndisc_search->domain = g_strdup (search);
|
||||
ndisc_search->timestamp = now;
|
||||
ndisc_search->lifetime = NM_NDISC_ROUTER_LIFETIME;
|
||||
}
|
||||
|
||||
nm_ndisc_set_config (ndisc, addresses, dns_servers, dns_domains);
|
||||
g_array_free (addresses, TRUE);
|
||||
g_array_free (dns_servers, TRUE);
|
||||
g_array_free (dns_domains, TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_link_changed (NMDevice *self)
|
||||
{
|
||||
|
|
@ -1896,11 +1969,9 @@ device_link_changed (NMDevice *self)
|
|||
nm_device_emit_recheck_auto_activate (self);
|
||||
}
|
||||
|
||||
if (priv->rdisc && info.inet6_token.id) {
|
||||
if (nm_rdisc_set_iid (priv->rdisc, info.inet6_token)) {
|
||||
if (priv->ndisc && info.inet6_token.id) {
|
||||
if (nm_ndisc_set_iid (priv->ndisc, info.inet6_token))
|
||||
_LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface);
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
}
|
||||
}
|
||||
|
||||
if (klass->link_changed)
|
||||
|
|
@ -5268,6 +5339,7 @@ connection_ip6_method_requires_carrier (NMConnection *connection,
|
|||
static const char *ip6_carrier_methods[] = {
|
||||
NM_SETTING_IP6_CONFIG_METHOD_AUTO,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_DHCP,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_SHARED,
|
||||
NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
|
||||
NULL
|
||||
};
|
||||
|
|
@ -5428,13 +5500,14 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE;
|
||||
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
|
||||
g_clear_object (&priv->dhcp6.ip6_config);
|
||||
g_clear_pointer (&priv->dhcp6.event_id, g_free);
|
||||
nm_clear_g_source (&priv->dhcp6.restart_id);
|
||||
|
||||
if (priv->dhcp6.client) {
|
||||
nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.state_sigid);
|
||||
nm_clear_g_signal_handler (priv->dhcp6.client, &priv->dhcp6.prefix_sigid);
|
||||
|
||||
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|
||||
|| cleanup_type == CLEANUP_TYPE_REMOVED)
|
||||
|
|
@ -5635,7 +5708,7 @@ END_ADD_DEFAULT_ROUTE:
|
|||
}
|
||||
|
||||
nm_ip6_config_addresses_sort (composite,
|
||||
priv->rdisc ? priv->rdisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||
priv->ndisc ? priv->ndisc_use_tempaddr : NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
|
||||
|
||||
/* Allow setting MTU etc */
|
||||
if (commit) {
|
||||
|
|
@ -5755,7 +5828,7 @@ dhcp6_fail (NMDevice *self, gboolean timeout)
|
|||
|
||||
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, FALSE);
|
||||
|
||||
if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) {
|
||||
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
|
||||
/* Don't fail if there are static addresses configured on
|
||||
* the device, instead retry after some time.
|
||||
*/
|
||||
|
|
@ -5801,7 +5874,7 @@ dhcp6_timeout (NMDevice *self, NMDhcpClient *client)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED)
|
||||
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED)
|
||||
dhcp6_fail (self, TRUE);
|
||||
else {
|
||||
/* not a hard failure; just live with the RA info */
|
||||
|
|
@ -5878,7 +5951,7 @@ dhcp6_state_changed (NMDhcpClient *client,
|
|||
* may exit right after getting a response from the server. That's
|
||||
* normal. In that case we just ignore the exit.
|
||||
*/
|
||||
if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF)
|
||||
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF)
|
||||
break;
|
||||
/* Otherwise, fall through */
|
||||
case NM_DHCP_STATE_FAIL:
|
||||
|
|
@ -5889,6 +5962,19 @@ dhcp6_state_changed (NMDhcpClient *client,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_prefix_delegated (NMDhcpClient *client,
|
||||
NMPlatformIP6Address *prefix,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMDevice *self = NM_DEVICE (user_data);
|
||||
|
||||
/* Just re-emit. The device just contributes the prefix to the
|
||||
* pool in NMPolicy, which decides about subnet allocation
|
||||
* on the shared devices. */
|
||||
g_signal_emit (self, signals[IP6_PREFIX_DELEGATED], 0, prefix);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
|
||||
{
|
||||
|
|
@ -5925,8 +6011,9 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
|
|||
nm_setting_ip_config_get_dhcp_hostname (s_ip6),
|
||||
priv->dhcp_timeout,
|
||||
priv->dhcp_anycast_address,
|
||||
(priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE,
|
||||
nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)));
|
||||
(priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_OTHERCONF) ? TRUE : FALSE,
|
||||
nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)),
|
||||
priv->dhcp6.needed_prefixes);
|
||||
if (tmp)
|
||||
g_byte_array_free (tmp, TRUE);
|
||||
|
||||
|
|
@ -5935,6 +6022,10 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection)
|
|||
NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED,
|
||||
G_CALLBACK (dhcp6_state_changed),
|
||||
self);
|
||||
priv->dhcp6.prefix_sigid = g_signal_connect (priv->dhcp6.client,
|
||||
NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
|
||||
G_CALLBACK (dhcp6_prefix_delegated),
|
||||
self);
|
||||
}
|
||||
|
||||
return !!priv->dhcp6.client;
|
||||
|
|
@ -6001,6 +6092,95 @@ nm_device_dhcp6_renew (NMDevice *self, gboolean release)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Called on the requesting interface when a subnet can't be obtained
|
||||
* from known prefixes for a newly active shared connection.
|
||||
*/
|
||||
void
|
||||
nm_device_request_ip6_prefixes (NMDevice *self, int needed_prefixes)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
priv->dhcp6.needed_prefixes = needed_prefixes;
|
||||
|
||||
if (priv->dhcp6.client) {
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: asking DHCPv6 for %d prefixes", needed_prefixes);
|
||||
nm_device_dhcp6_renew (self, FALSE);
|
||||
} else {
|
||||
_LOGI (LOGD_IP6, "ipv6-pd: device doesn't use DHCPv6, can't request prefixes");
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_needs_ip6_subnet (NMDevice *self)
|
||||
{
|
||||
return NM_DEVICE_GET_PRIVATE (self)->needs_ip6_subnet;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called on the ipv6.method=shared interface when a new subnet is allocated
|
||||
* or the prefix from which it is allocated is renewed.
|
||||
*/
|
||||
void
|
||||
nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMPlatformIP6Address address = *subnet;
|
||||
|
||||
if (!priv->ac_ip6_config)
|
||||
priv->ac_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self));
|
||||
|
||||
/* Assign a ::1 address in the subnet for us. */
|
||||
address.address.s6_addr32[3] |= htonl (1);
|
||||
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
||||
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: using %s address (preferred for %u seconds)",
|
||||
nm_utils_inet6_ntop (&address.address, NULL),
|
||||
subnet->preferred);
|
||||
|
||||
/* This also updates the ndisc if there are actual changes. */
|
||||
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
|
||||
_LOGW (LOGD_IP6, "ipv6-pd: failed applying IP6 config for connection sharing");
|
||||
}
|
||||
|
||||
/*
|
||||
* Called whenever the policy picks a default IPv6 device.
|
||||
* The ipv6.method=shared devices just reuse its DNS configuration.
|
||||
*/
|
||||
void
|
||||
nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMIP6Config *from_config = NULL;
|
||||
int i;
|
||||
|
||||
if (priv->ac_ip6_config) {
|
||||
nm_ip6_config_reset_nameservers (priv->ac_ip6_config);
|
||||
nm_ip6_config_reset_searches (priv->ac_ip6_config);
|
||||
} else
|
||||
priv->ac_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self));
|
||||
|
||||
if (from_device)
|
||||
from_config = nm_device_get_ip6_config (from_device);
|
||||
if (!from_config)
|
||||
return;
|
||||
|
||||
for (i = 0; i < nm_ip6_config_get_num_nameservers (from_config); i++) {
|
||||
nm_ip6_config_add_nameserver (priv->ac_ip6_config,
|
||||
nm_ip6_config_get_nameserver (from_config, i));
|
||||
}
|
||||
|
||||
for (i = 0; i < nm_ip6_config_get_num_searches (from_config); i++) {
|
||||
nm_ip6_config_add_search (priv->ac_ip6_config,
|
||||
nm_ip6_config_get_search (from_config, i));
|
||||
}
|
||||
|
||||
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
|
||||
_LOGW (LOGD_IP6, "ipv6-pd: failed applying DNS config for connection sharing");
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
linklocal6_cleanup (NMDevice *self)
|
||||
{
|
||||
|
|
@ -6045,7 +6225,8 @@ linklocal6_complete (NMDevice *self)
|
|||
|
||||
_LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses successful, continue with method %s", method);
|
||||
|
||||
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
||||
if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
||||
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
||||
if (!addrconf6_start_with_link_ready (self)) {
|
||||
/* Time out IPv6 instead of failing the entire activation */
|
||||
nm_device_activate_schedule_ip6_config_timeout (self);
|
||||
|
|
@ -6234,9 +6415,9 @@ nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu)
|
|||
}
|
||||
|
||||
static void
|
||||
rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, NMDevice *self)
|
||||
ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, NMDevice *self)
|
||||
{
|
||||
NMRDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
int i;
|
||||
int system_support;
|
||||
|
|
@ -6252,8 +6433,8 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
|
||||
if (system_support)
|
||||
ifa_flags = IFA_F_NOPREFIXROUTE;
|
||||
if ( priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
|| priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
if ( priv->ndisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR
|
||||
|| priv->ndisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
{
|
||||
/* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */
|
||||
ifa_flags |= IFA_F_MANAGETEMPADDR;
|
||||
|
|
@ -6264,25 +6445,25 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
if (!priv->ac_ip6_config)
|
||||
priv->ac_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self));
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_GATEWAYS) {
|
||||
/* Use the first gateway as ordered in router discovery cache. */
|
||||
if (changed & NM_NDISC_CONFIG_GATEWAYS) {
|
||||
/* Use the first gateway as ordered in neighbor discovery cache. */
|
||||
if (rdata->gateways_n)
|
||||
nm_ip6_config_set_gateway (priv->ac_ip6_config, &rdata->gateways[0].address);
|
||||
else
|
||||
nm_ip6_config_set_gateway (priv->ac_ip6_config, NULL);
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from router discovery cache. */
|
||||
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_addresses (priv->ac_ip6_config);
|
||||
|
||||
/* rdisc->addresses contains at most max_addresses entries.
|
||||
/* ndisc->addresses contains at most max_addresses entries.
|
||||
* This is different from what the kernel does, which
|
||||
* also counts static and temporary addresses when checking
|
||||
* max_addresses.
|
||||
**/
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMRDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
NMPlatformIP6Address address;
|
||||
|
||||
memset (&address, 0, sizeof (address));
|
||||
|
|
@ -6293,24 +6474,24 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
address.preferred = discovered_address->preferred;
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_RDISC;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
address.n_ifa_flags = ifa_flags;
|
||||
|
||||
nm_ip6_config_add_address (priv->ac_ip6_config, &address);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from router discovery cache. */
|
||||
if (changed & NM_NDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_routes (priv->ac_ip6_config);
|
||||
|
||||
for (i = 0; i < rdata->routes_n; i++) {
|
||||
const NMRDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMNDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMPlatformIP6Route route = {
|
||||
.network = discovered_route->network,
|
||||
.plen = discovered_route->plen,
|
||||
.gateway = discovered_route->gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_RDISC,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||
.metric = nm_device_get_ip6_route_metric (self),
|
||||
};
|
||||
|
||||
|
|
@ -6318,34 +6499,34 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_DNS_SERVERS) {
|
||||
/* Rebuild DNS server list from router discovery cache. */
|
||||
if (changed & NM_NDISC_CONFIG_DNS_SERVERS) {
|
||||
/* Rebuild DNS server list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_nameservers (priv->ac_ip6_config);
|
||||
|
||||
for (i = 0; i < rdata->dns_servers_n; i++)
|
||||
nm_ip6_config_add_nameserver (priv->ac_ip6_config, &rdata->dns_servers[i].address);
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_DNS_DOMAINS) {
|
||||
/* Rebuild domain list from router discovery cache. */
|
||||
nm_ip6_config_reset_domains (priv->ac_ip6_config);
|
||||
if (changed & NM_NDISC_CONFIG_DNS_DOMAINS) {
|
||||
/* Rebuild domain list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_searches (priv->ac_ip6_config);
|
||||
|
||||
for (i = 0; i < rdata->dns_domains_n; i++)
|
||||
nm_ip6_config_add_domain (priv->ac_ip6_config, rdata->dns_domains[i].domain);
|
||||
nm_ip6_config_add_search (priv->ac_ip6_config, rdata->dns_domains[i].domain);
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) {
|
||||
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
||||
dhcp6_cleanup (self, CLEANUP_TYPE_DECONFIGURE, TRUE);
|
||||
|
||||
priv->dhcp6.mode = rdata->dhcp_level;
|
||||
if (priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE) {
|
||||
if (priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE) {
|
||||
NMDeviceStateReason reason;
|
||||
|
||||
_LOGD (LOGD_DEVICE | LOGD_DHCP6,
|
||||
"Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6"
|
||||
" as requested by IPv6 router...");
|
||||
if (!dhcp6_start (self, FALSE, &reason)) {
|
||||
if (priv->dhcp6.mode == NM_RDISC_DHCP_LEVEL_MANAGED) {
|
||||
if (priv->dhcp6.mode == NM_NDISC_DHCP_LEVEL_MANAGED) {
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason);
|
||||
return;
|
||||
}
|
||||
|
|
@ -6353,17 +6534,17 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_HOP_LIMIT)
|
||||
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
|
||||
nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, nm_device_get_ip_iface (self), rdata->hop_limit);
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_MTU)
|
||||
if (changed & NM_NDISC_CONFIG_MTU)
|
||||
priv->ip6_mtu = rdata->mtu;
|
||||
|
||||
nm_device_activate_schedule_ip6_config_result (self);
|
||||
}
|
||||
|
||||
static void
|
||||
rdisc_ra_timeout (NMRDisc *rdisc, NMDevice *self)
|
||||
ndisc_ra_timeout (NMNDisc *ndisc, NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
|
|
@ -6393,13 +6574,13 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMUtilsIPv6IfaceId iid;
|
||||
|
||||
g_assert (priv->rdisc);
|
||||
g_assert (priv->ndisc);
|
||||
|
||||
if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) {
|
||||
_LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier");
|
||||
nm_rdisc_set_iid (priv->rdisc, iid);
|
||||
nm_ndisc_set_iid (priv->ndisc, iid);
|
||||
} else {
|
||||
/* Don't abort the addrconf at this point -- if rdisc needs the iid
|
||||
/* Don't abort the addrconf at this point -- if ndisc needs the iid
|
||||
* it will notice this itself. */
|
||||
_LOGI (LOGD_IP6, "addrconf6: no interface identifier; IPv6 adddress creation may fail");
|
||||
}
|
||||
|
|
@ -6408,24 +6589,55 @@ addrconf6_start_with_link_ready (NMDevice *self)
|
|||
if (!ip6_config_merge_and_apply (self, TRUE, NULL))
|
||||
_LOGW (LOGD_IP6, "failed to apply manual IPv6 configuration");
|
||||
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra", "1");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
||||
/* XXX: These sysctls would probably be better set by the lndp ndisc itself. */
|
||||
switch (nm_ndisc_get_node_type (priv->ndisc)) {
|
||||
case NM_NDISC_NODE_TYPE_HOST:
|
||||
/* Accepting prefixes from discovered routers. */
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra", "1");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_defrtr", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
||||
break;
|
||||
case NM_NDISC_NODE_TYPE_ROUTER:
|
||||
/* We're the router. */
|
||||
nm_device_ipv6_sysctl_set (self, "forwarding", "1");
|
||||
nm_device_activate_schedule_ip6_config_result (self);
|
||||
priv->needs_ip6_subnet = TRUE;
|
||||
g_signal_emit (self, signals[IP6_SUBNET_NEEDED], 0);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
priv->rdisc_changed_id = g_signal_connect (priv->rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
G_CALLBACK (rdisc_config_changed),
|
||||
priv->ndisc_changed_id = g_signal_connect (priv->ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (ndisc_config_changed),
|
||||
self);
|
||||
priv->rdisc_timeout_id = g_signal_connect (priv->rdisc,
|
||||
NM_RDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (rdisc_ra_timeout),
|
||||
priv->ndisc_timeout_id = g_signal_connect (priv->ndisc,
|
||||
NM_NDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (ndisc_ra_timeout),
|
||||
self);
|
||||
|
||||
nm_rdisc_start (priv->rdisc);
|
||||
ndisc_set_router_config (priv->ndisc, self);
|
||||
nm_ndisc_start (priv->ndisc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NMNDiscNodeType
|
||||
ndisc_node_type (NMDevice *self)
|
||||
{
|
||||
NMConnection *connection;
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
g_assert (connection);
|
||||
|
||||
if (strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
|
||||
NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
|
||||
return NM_NDISC_NODE_TYPE_ROUTER;
|
||||
else
|
||||
return NM_NDISC_NODE_TYPE_HOST;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
||||
{
|
||||
|
|
@ -6451,21 +6663,22 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
|||
|
||||
stable_id = _get_stable_id (connection, &stable_type);
|
||||
if (stable_id) {
|
||||
priv->rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
|
||||
priv->ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET,
|
||||
nm_device_get_ip_ifindex (self),
|
||||
nm_device_get_ip_iface (self),
|
||||
stable_type,
|
||||
stable_id,
|
||||
nm_setting_ip6_config_get_addr_gen_mode (s_ip6),
|
||||
ndisc_node_type (self),
|
||||
&error);
|
||||
}
|
||||
if (!priv->rdisc) {
|
||||
_LOGE (LOGD_IP6, "addrconf6: failed to start router discovery: %s", error->message);
|
||||
if (!priv->ndisc) {
|
||||
_LOGE (LOGD_IP6, "addrconf6: failed to start neighbor discovery: %s", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
priv->rdisc_use_tempaddr = use_tempaddr;
|
||||
priv->ndisc_use_tempaddr = use_tempaddr;
|
||||
|
||||
if ( NM_IN_SET (use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR)
|
||||
&& !nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET)) {
|
||||
|
|
@ -6483,7 +6696,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* success; already have the LL address; kick off router discovery */
|
||||
/* success; already have the LL address; kick off neighbor discovery */
|
||||
g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS);
|
||||
return addrconf6_start_with_link_ready (self);
|
||||
}
|
||||
|
|
@ -6493,13 +6706,13 @@ addrconf6_cleanup (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
nm_clear_g_signal_handler (priv->rdisc, &priv->rdisc_changed_id);
|
||||
nm_clear_g_signal_handler (priv->rdisc, &priv->rdisc_timeout_id);
|
||||
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_changed_id);
|
||||
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_timeout_id);
|
||||
|
||||
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
|
||||
|
||||
g_clear_object (&priv->ac_ip6_config);
|
||||
g_clear_object (&priv->rdisc);
|
||||
g_clear_object (&priv->ndisc);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -6509,6 +6722,7 @@ static const char *ip6_properties_to_save[] = {
|
|||
"accept_ra_defrtr",
|
||||
"accept_ra_pinfo",
|
||||
"accept_ra_rtr_pref",
|
||||
"forwarding",
|
||||
"disable_ipv6",
|
||||
"hop_limit",
|
||||
"use_tempaddr",
|
||||
|
|
@ -6666,12 +6880,10 @@ ip6_requires_slaves (NMConnection *connection)
|
|||
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
|
||||
/* SLAAC, DHCP, and Link-Local depend on connectivity (and thus slaves)
|
||||
* to complete addressing. SLAAC and DHCP obviously need a peer to
|
||||
* provide a prefix, while Link-Local must perform DAD on the local link.
|
||||
* to complete addressing. SLAAC and DHCP need a peer to provide a prefix.
|
||||
*/
|
||||
return strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
||||
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0
|
||||
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0;
|
||||
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0;
|
||||
}
|
||||
|
||||
static NMActStageReturn
|
||||
|
|
@ -6716,7 +6928,7 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
}
|
||||
}
|
||||
|
||||
priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_NONE;
|
||||
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_NONE;
|
||||
priv->dhcp6.num_tries_left = DHCP_NUM_TRIES_MAX;
|
||||
|
||||
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
|
|
@ -6756,7 +6968,8 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
|
||||
ip6_privacy = _ip6_privacy_get (self);
|
||||
|
||||
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0) {
|
||||
if ( strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO) == 0
|
||||
|| strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
||||
if (!addrconf6_start (self, ip6_privacy)) {
|
||||
/* IPv6 might be disabled; allow IPv4 to proceed */
|
||||
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
|
||||
|
|
@ -6765,7 +6978,7 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL) == 0) {
|
||||
ret = linklocal6_start (self);
|
||||
} else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP) == 0) {
|
||||
priv->dhcp6.mode = NM_RDISC_DHCP_LEVEL_MANAGED;
|
||||
priv->dhcp6.mode = NM_NDISC_DHCP_LEVEL_MANAGED;
|
||||
if (!dhcp6_start (self, TRUE, reason)) {
|
||||
/* IPv6 might be disabled; allow IPv4 to proceed */
|
||||
ret = NM_ACT_STAGE_RETURN_IP_FAIL;
|
||||
|
|
@ -6776,8 +6989,6 @@ act_stage3_ip6_config_start (NMDevice *self,
|
|||
} else
|
||||
_LOGW (LOGD_IP6, "unhandled IPv6 config method '%s'; will fail", method);
|
||||
|
||||
/* Other methods (shared) aren't implemented yet */
|
||||
|
||||
if ( ret != NM_ACT_STAGE_RETURN_FAILURE
|
||||
&& !nm_device_uses_assumed_connection (self)) {
|
||||
switch (ip6_privacy) {
|
||||
|
|
@ -6986,12 +7197,16 @@ fw_change_zone_cb_ip_check (NMFirewallManager *firewall_manager,
|
|||
gpointer user_data)
|
||||
{
|
||||
NMDevice *self = user_data;
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
if (!fw_change_zone_handle (self, call_id, error))
|
||||
return;
|
||||
|
||||
/* FIXME: fail the device on error? */
|
||||
nm_device_start_ip_check (self);
|
||||
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
if (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE)
|
||||
nm_device_start_ip_check (self);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -7161,14 +7376,14 @@ share_init (void)
|
|||
|
||||
if (!nm_platform_sysctl_set (NM_PLATFORM_GET, "/proc/sys/net/ipv4/ip_forward", "1")) {
|
||||
errsv = errno;
|
||||
nm_log_err (LOGD_SHARING, "share: error starting IP forwarding: (%d) %s",
|
||||
nm_log_err (LOGD_SHARING, "share: error enabling IPv4 forwarding: (%d) %s",
|
||||
errsv, strerror (errsv));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!nm_platform_sysctl_set (NM_PLATFORM_GET, "/proc/sys/net/ipv4/ip_dynaddr", "1")) {
|
||||
errsv = errno;
|
||||
nm_log_err (LOGD_SHARING, "share: error starting IP forwarding: (%d) %s",
|
||||
nm_log_err (LOGD_SHARING, "share: error enabling dynamic addresses: (%d) %s",
|
||||
errsv, strerror (errsv));
|
||||
}
|
||||
|
||||
|
|
@ -7340,7 +7555,7 @@ activate_stage5_ip4_config_commit (NMDevice *self)
|
|||
if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) {
|
||||
if (!start_sharing (self, priv->ip4_config)) {
|
||||
_LOGW (LOGD_SHARING, "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed.");
|
||||
nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
||||
nm_device_ip_method_failed (self, AF_INET, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -7462,9 +7677,11 @@ activate_stage5_ip6_config_commit (NMDevice *self)
|
|||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
NMActRequest *req;
|
||||
const char *method;
|
||||
NMConnection *connection;
|
||||
NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE;
|
||||
int ip_ifindex;
|
||||
int errsv;
|
||||
|
||||
req = nm_device_get_act_request (self);
|
||||
g_assert (req);
|
||||
|
|
@ -7480,7 +7697,7 @@ activate_stage5_ip6_config_commit (NMDevice *self)
|
|||
}
|
||||
|
||||
if (ip6_config_merge_and_apply (self, TRUE, &reason)) {
|
||||
if ( priv->dhcp6.mode != NM_RDISC_DHCP_LEVEL_NONE
|
||||
if ( priv->dhcp6.mode != NM_NDISC_DHCP_LEVEL_NONE
|
||||
&& priv->ip6_state == IP_CONF) {
|
||||
if (priv->dhcp6.ip6_config) {
|
||||
/* If IPv6 wasn't the first IP to complete, and DHCP was used,
|
||||
|
|
@ -7501,6 +7718,17 @@ activate_stage5_ip6_config_commit (NMDevice *self)
|
|||
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
|
||||
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
|
||||
|
||||
/* Start IPv6 forwarding if we need it */
|
||||
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
|
||||
|
||||
if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0) {
|
||||
if (!nm_platform_sysctl_set (NM_PLATFORM_GET, "/proc/sys/net/ipv6/conf/all/forwarding", "1")) {
|
||||
errsv = errno;
|
||||
_LOGE (LOGD_SHARING, "share: error enabling IPv6 forwarding: (%d) %s", errsv, strerror (errsv));
|
||||
nm_device_ip_method_failed (self, AF_INET6, NM_DEVICE_STATE_REASON_SHARED_START_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have to wait for DAD */
|
||||
if (priv->ip6_state == IP_CONF && !priv->dad6_ip6_config) {
|
||||
priv->dad6_ip6_config = dad6_get_pending_addresses (self);
|
||||
|
|
@ -8799,6 +9027,9 @@ nm_device_set_ip6_config (NMDevice *self,
|
|||
}
|
||||
|
||||
nm_device_queue_recheck_assume (self);
|
||||
|
||||
if (priv->ndisc)
|
||||
ndisc_set_router_config (priv->ndisc, self);
|
||||
}
|
||||
|
||||
if (reason)
|
||||
|
|
@ -9069,10 +9300,10 @@ nm_device_start_ip_check (NMDevice *self)
|
|||
* first IP method completes. Any subsequently completing IP method doesn't
|
||||
* get checked.
|
||||
*/
|
||||
g_assert (!priv->gw_ping.watch);
|
||||
g_assert (!priv->gw_ping.timeout);
|
||||
g_assert (!priv->gw_ping.pid);
|
||||
g_assert (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE);
|
||||
g_return_if_fail (!priv->gw_ping.watch);
|
||||
g_return_if_fail (!priv->gw_ping.timeout);
|
||||
g_return_if_fail (!priv->gw_ping.pid);
|
||||
g_return_if_fail (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE);
|
||||
|
||||
connection = nm_device_get_applied_connection (self);
|
||||
g_assert (connection);
|
||||
|
|
@ -9633,8 +9864,8 @@ queued_ip6_config_change (gpointer user_data)
|
|||
|
||||
if (IN6_IS_ADDR_LINKLOCAL (&addr->address))
|
||||
need_ipv6ll = TRUE;
|
||||
else if (priv->rdisc)
|
||||
nm_rdisc_dad_failed (priv->rdisc, &addr->address);
|
||||
else if (priv->ndisc)
|
||||
nm_ndisc_dad_failed (priv->ndisc, &addr->address);
|
||||
}
|
||||
|
||||
/* If no IPv6 link-local address exists but other addresses do then we
|
||||
|
|
@ -10808,6 +11039,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type)
|
|||
g_slist_free_full (priv->vpn6_configs, g_object_unref);
|
||||
priv->vpn6_configs = NULL;
|
||||
|
||||
priv->needs_ip6_subnet = FALSE;
|
||||
|
||||
clear_act_request (self);
|
||||
|
||||
/* Clear legacy IPv4 address property */
|
||||
|
|
@ -11045,7 +11278,7 @@ nm_device_spawn_iface_helper (NMDevice *self)
|
|||
g_ptr_array_add (argv, g_strdup ("--slaac-required"));
|
||||
|
||||
g_ptr_array_add (argv, g_strdup ("--slaac-tempaddr"));
|
||||
g_ptr_array_add (argv, g_strdup_printf ("%d", priv->rdisc_use_tempaddr));
|
||||
g_ptr_array_add (argv, g_strdup_printf ("%d", priv->ndisc_use_tempaddr));
|
||||
|
||||
if (nm_device_get_ip_iface_identifier (self, &iid, FALSE)) {
|
||||
g_ptr_array_add (argv, g_strdup ("--iid"));
|
||||
|
|
@ -11115,6 +11348,7 @@ ip6_managed_setup (NMDevice *self)
|
|||
nm_device_ipv6_sysctl_set (self, "accept_ra_pinfo", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "accept_ra_rtr_pref", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "use_tempaddr", "0");
|
||||
nm_device_ipv6_sysctl_set (self, "forwarding", "0");
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -13092,6 +13326,20 @@ nm_device_class_init (NMDeviceClass *klass)
|
|||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT);
|
||||
|
||||
signals[IP6_PREFIX_DELEGATED] =
|
||||
g_signal_new (NM_DEVICE_IP6_PREFIX_DELEGATED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
||||
|
||||
signals[IP6_SUBNET_NEEDED] =
|
||||
g_signal_new (NM_DEVICE_IP6_SUBNET_NEEDED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[REMOVED] =
|
||||
g_signal_new (NM_DEVICE_REMOVED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@
|
|||
#define NM_DEVICE_AUTH_REQUEST "auth-request"
|
||||
#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed"
|
||||
#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed"
|
||||
#define NM_DEVICE_IP6_PREFIX_DELEGATED "ip6-prefix-delegated"
|
||||
#define NM_DEVICE_IP6_SUBNET_NEEDED "ip6-subnet-needed"
|
||||
#define NM_DEVICE_REMOVED "removed"
|
||||
#define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate"
|
||||
#define NM_DEVICE_RECHECK_ASSUME "recheck-assume"
|
||||
|
|
@ -439,6 +441,16 @@ void nm_device_set_enabled (NMDevice *device, gboolean enabled);
|
|||
|
||||
RfKillType nm_device_get_rfkill_type (NMDevice *device);
|
||||
|
||||
/* IPv6 prefix delegation */
|
||||
|
||||
void nm_device_request_ip6_prefixes (NMDevice *self, int needed_prefixes);
|
||||
|
||||
gboolean nm_device_needs_ip6_subnet (NMDevice *self);
|
||||
|
||||
void nm_device_use_ip6_subnet (NMDevice *self, const NMPlatformIP6Address *subnet);
|
||||
|
||||
void nm_device_copy_ip6_dns_config (NMDevice *self, NMDevice *from_device);
|
||||
|
||||
/**
|
||||
* NMUnmanagedFlags:
|
||||
* @NM_UNMANAGED_NONE: placeholder value
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
enum {
|
||||
SIGNAL_STATE_CHANGED,
|
||||
SIGNAL_PREFIX_DELEGATED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
|
@ -511,7 +512,8 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self,
|
|||
const struct in6_addr *ll_addr,
|
||||
const char *hostname,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy)
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
NMDhcpClientPrivate *priv;
|
||||
gs_free char *str = NULL;
|
||||
|
|
@ -544,7 +546,8 @@ nm_dhcp_client_start_ip6 (NMDhcpClient *self,
|
|||
ll_addr,
|
||||
info_only,
|
||||
privacy,
|
||||
priv->duid);
|
||||
priv->duid,
|
||||
needed_prefixes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -709,6 +712,7 @@ nm_dhcp_client_handle_event (gpointer unused,
|
|||
guint32 new_state;
|
||||
GHashTable *str_options = NULL;
|
||||
GObject *ip_config = NULL;
|
||||
NMPlatformIP6Address prefix = { 0, };
|
||||
|
||||
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
|
||||
g_return_val_if_fail (iface != NULL, FALSE);
|
||||
|
|
@ -741,10 +745,20 @@ nm_dhcp_client_handle_event (gpointer unused,
|
|||
g_variant_unref (value);
|
||||
}
|
||||
|
||||
if (nm_logging_enabled (LOGL_DEBUG, LOGD_DHCP6)) {
|
||||
GHashTableIter hash_iter;
|
||||
gpointer key, val;
|
||||
|
||||
g_hash_table_iter_init (&hash_iter, str_options);
|
||||
while (g_hash_table_iter_next (&hash_iter, &key, &val))
|
||||
_LOGD ("option '%s'=>'%s'", (const char *) key, (const char *) val);
|
||||
}
|
||||
|
||||
/* Create the IP config */
|
||||
g_warn_if_fail (g_hash_table_size (str_options));
|
||||
if (g_hash_table_size (str_options)) {
|
||||
if (priv->ipv6) {
|
||||
prefix = nm_dhcp_utils_ip6_prefix_from_options (str_options);
|
||||
ip_config = (GObject *) nm_dhcp_utils_ip6_config_from_options (priv->ifindex,
|
||||
priv->iface,
|
||||
str_options,
|
||||
|
|
@ -756,17 +770,26 @@ nm_dhcp_client_handle_event (gpointer unused,
|
|||
str_options,
|
||||
priv->priority);
|
||||
}
|
||||
|
||||
/* Fail if no valid IP config was received */
|
||||
if (ip_config == NULL) {
|
||||
_LOGW ("client bound but IP config not received");
|
||||
new_state = NM_DHCP_STATE_FAIL;
|
||||
g_clear_pointer (&str_options, g_hash_table_unref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nm_dhcp_client_set_state (self, new_state, ip_config, str_options);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED (&prefix.address)) {
|
||||
/* If we got an IPv6 prefix to delegate, we don't change the state
|
||||
* of the DHCP client instance. Instead, we just signal the prefix
|
||||
* to the device. */
|
||||
g_signal_emit (G_OBJECT (self),
|
||||
signals[SIGNAL_PREFIX_DELEGATED], 0,
|
||||
&prefix);
|
||||
} else {
|
||||
/* Fail if no valid IP config was received */
|
||||
if (new_state == NM_DHCP_STATE_BOUND && ip_config == NULL) {
|
||||
_LOGW ("client bound but IP config not received");
|
||||
new_state = NM_DHCP_STATE_FAIL;
|
||||
g_clear_pointer (&str_options, g_hash_table_unref);
|
||||
}
|
||||
|
||||
nm_dhcp_client_set_state (self, new_state, ip_config, str_options);
|
||||
}
|
||||
|
||||
if (str_options)
|
||||
g_hash_table_destroy (str_options);
|
||||
|
|
@ -963,5 +986,12 @@ nm_dhcp_client_class_init (NMDhcpClientClass *client_class)
|
|||
G_STRUCT_OFFSET (NMDhcpClientClass, state_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING);
|
||||
}
|
||||
|
||||
signals[SIGNAL_PREFIX_DELEGATED] =
|
||||
g_signal_new (NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED,
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (NMDhcpClientClass, state_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#define NM_DHCP_CLIENT_TIMEOUT "timeout"
|
||||
|
||||
#define NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED "state-changed"
|
||||
#define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated"
|
||||
|
||||
typedef enum {
|
||||
NM_DHCP_STATE_UNKNOWN = 0,
|
||||
|
|
@ -73,7 +74,8 @@ typedef struct {
|
|||
const struct in6_addr *ll_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
const GByteArray *duid);
|
||||
const GByteArray *duid,
|
||||
guint needed_prefixes);
|
||||
|
||||
void (*stop) (NMDhcpClient *self,
|
||||
gboolean release,
|
||||
|
|
@ -133,7 +135,8 @@ gboolean nm_dhcp_client_start_ip6 (NMDhcpClient *self,
|
|||
const struct in6_addr *ll_addr,
|
||||
const char *hostname,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy);
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
guint needed_prefixes);
|
||||
|
||||
void nm_dhcp_client_stop (NMDhcpClient *self, gboolean release);
|
||||
|
||||
|
|
|
|||
|
|
@ -330,7 +330,8 @@ dhclient_start (NMDhcpClient *client,
|
|||
const char *mode_opt,
|
||||
const GByteArray *duid,
|
||||
gboolean release,
|
||||
pid_t *out_pid)
|
||||
pid_t *out_pid,
|
||||
int prefixes)
|
||||
{
|
||||
NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self);
|
||||
|
|
@ -424,6 +425,8 @@ dhclient_start (NMDhcpClient *client,
|
|||
g_ptr_array_add (argv, (gpointer) "-6");
|
||||
if (mode_opt)
|
||||
g_ptr_array_add (argv, (gpointer) mode_opt);
|
||||
while (prefixes--)
|
||||
g_ptr_array_add (argv, (gpointer) "-P");
|
||||
}
|
||||
g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */
|
||||
g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path);
|
||||
|
|
@ -503,7 +506,7 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
|
|||
if (priv->conf_file) {
|
||||
if (new_client_id)
|
||||
nm_dhcp_client_set_client_id (client, new_client_id);
|
||||
success = dhclient_start (client, NULL, NULL, FALSE, NULL);
|
||||
success = dhclient_start (client, NULL, NULL, FALSE, NULL, 0);
|
||||
} else
|
||||
_LOGW ("error creating dhclient configuration file");
|
||||
|
||||
|
|
@ -516,7 +519,8 @@ ip6_start (NMDhcpClient *client,
|
|||
const struct in6_addr *ll_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
const GByteArray *duid)
|
||||
const GByteArray *duid,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client);
|
||||
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self);
|
||||
|
|
@ -532,7 +536,7 @@ ip6_start (NMDhcpClient *client,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
return dhclient_start (client, info_only ? "-S" : "-N", duid, FALSE, NULL);
|
||||
return dhclient_start (client, info_only ? "-S" : "-N", duid, FALSE, NULL, needed_prefixes);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -557,7 +561,7 @@ stop (NMDhcpClient *client, gboolean release, const GByteArray *duid)
|
|||
if (release) {
|
||||
pid_t rpid = -1;
|
||||
|
||||
if (dhclient_start (client, NULL, duid, TRUE, &rpid)) {
|
||||
if (dhclient_start (client, NULL, duid, TRUE, &rpid, 0)) {
|
||||
/* Wait a few seconds for the release to happen */
|
||||
nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,7 +185,8 @@ ip6_start (NMDhcpClient *client,
|
|||
const struct in6_addr *ll_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
const GByteArray *duid)
|
||||
const GByteArray *duid,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client);
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,8 @@ client_start (NMDhcpManager *self,
|
|||
const char *fqdn,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
const char *last_ip4_address)
|
||||
const char *last_ip4_address,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
NMDhcpManagerPrivate *priv;
|
||||
NMDhcpClient *client;
|
||||
|
|
@ -206,7 +207,7 @@ client_start (NMDhcpManager *self,
|
|||
g_signal_connect (client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (client_state_changed), self);
|
||||
|
||||
if (ipv6)
|
||||
success = nm_dhcp_client_start_ip6 (client, dhcp_anycast_addr, ipv6_ll_addr, hostname, info_only, privacy);
|
||||
success = nm_dhcp_client_start_ip6 (client, dhcp_anycast_addr, ipv6_ll_addr, hostname, info_only, privacy, needed_prefixes);
|
||||
else
|
||||
success = nm_dhcp_client_start_ip4 (client, dhcp_client_id, dhcp_anycast_addr, hostname, fqdn, last_ip4_address);
|
||||
|
||||
|
|
@ -254,7 +255,7 @@ nm_dhcp_manager_start_ip4 (NMDhcpManager *self,
|
|||
}
|
||||
return client_start (self, iface, ifindex, hwaddr, uuid, priority, FALSE, NULL,
|
||||
dhcp_client_id, timeout, dhcp_anycast_addr, hostname,
|
||||
fqdn, FALSE, 0, last_ip_address);
|
||||
fqdn, FALSE, 0, last_ip_address, 0);
|
||||
}
|
||||
|
||||
/* Caller owns a reference to the NMDhcpClient on return */
|
||||
|
|
@ -271,7 +272,8 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self,
|
|||
guint32 timeout,
|
||||
const char *dhcp_anycast_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy)
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
const char *hostname = NULL;
|
||||
|
||||
|
|
@ -281,7 +283,7 @@ nm_dhcp_manager_start_ip6 (NMDhcpManager *self,
|
|||
hostname = get_send_hostname (self, dhcp_hostname);
|
||||
return client_start (self, iface, ifindex, hwaddr, uuid, priority, TRUE,
|
||||
ll_addr, NULL, timeout, dhcp_anycast_addr, hostname, NULL, info_only,
|
||||
privacy, NULL);
|
||||
privacy, NULL, needed_prefixes);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ NMDhcpClient * nm_dhcp_manager_start_ip6 (NMDhcpManager *manager,
|
|||
guint32 timeout,
|
||||
const char *dhcp_anycast_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy);
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
guint needed_prefixes);
|
||||
|
||||
GSList * nm_dhcp_manager_get_lease_ip_configs (NMDhcpManager *self,
|
||||
const char *iface,
|
||||
|
|
|
|||
|
|
@ -894,7 +894,8 @@ ip6_start (NMDhcpClient *client,
|
|||
const struct in6_addr *ll_addr,
|
||||
gboolean info_only,
|
||||
NMSettingIP6ConfigPrivacy privacy,
|
||||
const GByteArray *duid)
|
||||
const GByteArray *duid,
|
||||
guint needed_prefixes)
|
||||
{
|
||||
NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client);
|
||||
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
|
||||
|
|
@ -916,7 +917,12 @@ ip6_start (NMDhcpClient *client,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
_LOGT ("dhcp-client6: set %p", priv->client4);
|
||||
if (needed_prefixes > 0) {
|
||||
_LOGW ("dhcp-client6: prefix delegation not yet supported, won't supply %d prefixes\n",
|
||||
needed_prefixes);
|
||||
}
|
||||
|
||||
_LOGT ("dhcp-client6: set %p", priv->client6);
|
||||
|
||||
if (info_only)
|
||||
sd_dhcp6_client_set_information_request (priv->client6, 1);
|
||||
|
|
|
|||
|
|
@ -604,6 +604,54 @@ ip6_add_domain_search (gpointer data, gpointer user_data)
|
|||
nm_ip6_config_add_search (NM_IP6_CONFIG (user_data), (const char *) data);
|
||||
}
|
||||
|
||||
NMPlatformIP6Address
|
||||
nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options)
|
||||
{
|
||||
gs_strfreev gchar **split_addr = NULL;
|
||||
NMPlatformIP6Address address = { 0, };
|
||||
struct in6_addr tmp_addr;
|
||||
char *str = NULL;
|
||||
int prefix;
|
||||
|
||||
g_return_val_if_fail (options != NULL, address);
|
||||
|
||||
str = g_hash_table_lookup (options, "ip6_prefix");
|
||||
if (!str)
|
||||
return address;
|
||||
|
||||
split_addr = g_strsplit (str, "/", 2);
|
||||
if (split_addr[0] == NULL && split_addr[1] == NULL) {
|
||||
nm_log_warn (LOGD_DHCP6, "DHCP returned prefix without length '%s'", str);
|
||||
return address;
|
||||
}
|
||||
|
||||
if (!inet_pton (AF_INET6, split_addr[0], &tmp_addr)) {
|
||||
nm_log_warn (LOGD_DHCP6, "DHCP returned invalid prefix '%s'", str);
|
||||
return address;
|
||||
}
|
||||
|
||||
prefix = _nm_utils_ascii_str_to_int64 (split_addr[1], 10, 0, 128, -1);
|
||||
if (prefix < 0) {
|
||||
nm_log_warn (LOGD_DHCP6, "DHCP returned prefix with invalid length '%s'", str);
|
||||
return address;
|
||||
}
|
||||
|
||||
address.address = tmp_addr;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
|
||||
address.plen = prefix;
|
||||
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
||||
str = g_hash_table_lookup (options, "max_life");
|
||||
if (str)
|
||||
address.lifetime = strtoul (str, NULL, 10);
|
||||
|
||||
str = g_hash_table_lookup (options, "preferred_life");
|
||||
if (str)
|
||||
address.preferred = strtoul (str, NULL, 10);
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
NMIP6Config *
|
||||
nm_dhcp_utils_ip6_config_from_options (int ifindex,
|
||||
const char *iface,
|
||||
|
|
@ -615,8 +663,6 @@ nm_dhcp_utils_ip6_config_from_options (int ifindex,
|
|||
struct in6_addr tmp_addr;
|
||||
NMPlatformIP6Address address;
|
||||
char *str = NULL;
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
|
||||
g_return_val_if_fail (options != NULL, NULL);
|
||||
|
||||
|
|
@ -624,12 +670,6 @@ nm_dhcp_utils_ip6_config_from_options (int ifindex,
|
|||
address.plen = 128;
|
||||
address.timestamp = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
||||
g_hash_table_iter_init (&iter, options);
|
||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||
_LOG2D (LOGD_DHCP6, iface, "(%s): option '%s'=>'%s'",
|
||||
iface, (const char *) key, (const char *) value);
|
||||
}
|
||||
|
||||
ip6_config = nm_ip6_config_new (ifindex);
|
||||
|
||||
str = g_hash_table_lookup (options, "max_life");
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ NMIP6Config *nm_dhcp_utils_ip6_config_from_options (int ifindex,
|
|||
guint priority,
|
||||
gboolean info_only);
|
||||
|
||||
NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options);
|
||||
|
||||
char * nm_dhcp_utils_duid_to_string (const GByteArray *duid);
|
||||
|
||||
GBytes * nm_dhcp_utils_client_id_string_to_bytes (const char *client_id);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-fake-rdisc.c - Fake implementation of router discovery
|
||||
/* nm-fake-ndisc.c - Fake implementation of neighbor discovery
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,14 +20,14 @@
|
|||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-fake-rdisc.h"
|
||||
#include "nm-fake-ndisc.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "nm-rdisc-private.h"
|
||||
#include "nm-ndisc-private.h"
|
||||
|
||||
#define _NMLOG_PREFIX_NAME "rdisc-fake"
|
||||
#define _NMLOG_PREFIX_NAME "ndisc-fake"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ typedef struct {
|
|||
guint id;
|
||||
guint when;
|
||||
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
NMNDiscDHCPLevel dhcp_level;
|
||||
GArray *gateways;
|
||||
GArray *prefixes;
|
||||
GArray *dns_servers;
|
||||
|
|
@ -51,7 +51,7 @@ typedef struct {
|
|||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
NMRDiscPreference preference;
|
||||
NMNDiscPreference preference;
|
||||
} FakePrefix;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -65,20 +65,20 @@ static guint signals[LAST_SIGNAL] = { 0 };
|
|||
typedef struct {
|
||||
guint receive_ra_id;
|
||||
GSList *ras;
|
||||
} NMFakeRDiscPrivate;
|
||||
} NMFakeNDiscPrivate;
|
||||
|
||||
struct _NMFakeRRDisc {
|
||||
NMRDisc parent;
|
||||
NMFakeRDiscPrivate _priv;
|
||||
struct _NMFakeRNDisc {
|
||||
NMNDisc parent;
|
||||
NMFakeNDiscPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMFakeRRDiscClass {
|
||||
NMRDiscClass parent;
|
||||
struct _NMFakeRNDiscClass {
|
||||
NMNDiscClass parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (NMFakeRDisc, nm_fake_rdisc, NM_TYPE_RDISC)
|
||||
G_DEFINE_TYPE (NMFakeNDisc, nm_fake_ndisc, NM_TYPE_NDISC)
|
||||
|
||||
#define NM_FAKE_RDISC_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMFakeRDisc, NM_IS_FAKE_RDISC)
|
||||
#define NM_FAKE_NDISC_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMFakeNDisc, NM_IS_FAKE_NDISC)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ fake_ra_free (gpointer data)
|
|||
static void
|
||||
ra_dns_domain_free (gpointer data)
|
||||
{
|
||||
g_free (((NMRDiscDNSDomain *)(data))->domain);
|
||||
g_free (((NMNDiscDNSDomain *)(data))->domain);
|
||||
}
|
||||
|
||||
static FakeRa *
|
||||
|
|
@ -113,13 +113,13 @@ find_ra (GSList *ras, guint id)
|
|||
}
|
||||
|
||||
guint
|
||||
nm_fake_rdisc_add_ra (NMFakeRDisc *self,
|
||||
nm_fake_ndisc_add_ra (NMFakeNDisc *self,
|
||||
guint seconds_after_previous,
|
||||
NMRDiscDHCPLevel dhcp_level,
|
||||
NMNDiscDHCPLevel dhcp_level,
|
||||
int hop_limit,
|
||||
guint32 mtu)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
static guint counter = 1;
|
||||
FakeRa *ra;
|
||||
|
||||
|
|
@ -129,10 +129,10 @@ nm_fake_rdisc_add_ra (NMFakeRDisc *self,
|
|||
ra->dhcp_level = dhcp_level;
|
||||
ra->hop_limit = hop_limit;
|
||||
ra->mtu = mtu;
|
||||
ra->gateways = g_array_new (FALSE, FALSE, sizeof (NMRDiscGateway));
|
||||
ra->gateways = g_array_new (FALSE, FALSE, sizeof (NMNDiscGateway));
|
||||
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));
|
||||
ra->dns_servers = g_array_new (FALSE, FALSE, sizeof (NMNDiscDNSServer));
|
||||
ra->dns_domains = g_array_new (FALSE, FALSE, sizeof (NMNDiscDNSDomain));
|
||||
g_array_set_clear_func (ra->dns_domains, ra_dns_domain_free);
|
||||
|
||||
priv->ras = g_slist_append (priv->ras, ra);
|
||||
|
|
@ -140,20 +140,20 @@ nm_fake_rdisc_add_ra (NMFakeRDisc *self,
|
|||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_gateway (NMFakeRDisc *self,
|
||||
nm_fake_ndisc_add_gateway (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
NMRDiscPreference preference)
|
||||
NMNDiscPreference preference)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
NMRDiscGateway *gw;
|
||||
NMNDiscGateway *gw;
|
||||
|
||||
g_assert (ra);
|
||||
g_array_set_size (ra->gateways, ra->gateways->len + 1);
|
||||
gw = &g_array_index (ra->gateways, NMRDiscGateway, ra->gateways->len - 1);
|
||||
gw = &g_array_index (ra->gateways, NMNDiscGateway, ra->gateways->len - 1);
|
||||
g_assert (inet_pton (AF_INET6, addr, &gw->address) == 1);
|
||||
gw->timestamp = timestamp;
|
||||
gw->lifetime = lifetime;
|
||||
|
|
@ -161,7 +161,7 @@ nm_fake_rdisc_add_gateway (NMFakeRDisc *self,
|
|||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
||||
nm_fake_ndisc_add_prefix (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *network,
|
||||
guint plen,
|
||||
|
|
@ -169,9 +169,9 @@ nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
|||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
NMRDiscPreference preference)
|
||||
NMNDiscPreference preference)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
FakePrefix *prefix;
|
||||
|
||||
|
|
@ -189,70 +189,70 @@ nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
|||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_dns_server (NMFakeRDisc *self,
|
||||
nm_fake_ndisc_add_dns_server (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *address,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
NMRDiscDNSServer *dns;
|
||||
NMNDiscDNSServer *dns;
|
||||
|
||||
g_assert (ra);
|
||||
g_array_set_size (ra->dns_servers, ra->dns_servers->len + 1);
|
||||
dns = &g_array_index (ra->dns_servers, NMRDiscDNSServer, ra->dns_servers->len - 1);
|
||||
dns = &g_array_index (ra->dns_servers, NMNDiscDNSServer, ra->dns_servers->len - 1);
|
||||
g_assert (inet_pton (AF_INET6, address, &dns->address) == 1);
|
||||
dns->timestamp = timestamp;
|
||||
dns->lifetime = lifetime;
|
||||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_add_dns_domain (NMFakeRDisc *self,
|
||||
nm_fake_ndisc_add_dns_domain (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *domain,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
FakeRa *ra = find_ra (priv->ras, ra_id);
|
||||
NMRDiscDNSDomain *dns;
|
||||
NMNDiscDNSDomain *dns;
|
||||
|
||||
g_assert (ra);
|
||||
g_array_set_size (ra->dns_domains, ra->dns_domains->len + 1);
|
||||
dns = &g_array_index (ra->dns_domains, NMRDiscDNSDomain, ra->dns_domains->len - 1);
|
||||
dns = &g_array_index (ra->dns_domains, NMNDiscDNSDomain, ra->dns_domains->len - 1);
|
||||
dns->domain = g_strdup (domain);
|
||||
dns->timestamp = timestamp;
|
||||
dns->lifetime = lifetime;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_fake_rdisc_done (NMFakeRDisc *self)
|
||||
nm_fake_ndisc_done (NMFakeNDisc *self)
|
||||
{
|
||||
return !NM_FAKE_RDISC_GET_PRIVATE (self)->ras;
|
||||
return !NM_FAKE_NDISC_GET_PRIVATE (self)->ras;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
send_rs (NMRDisc *rdisc, GError **error)
|
||||
send_rs (NMNDisc *ndisc, GError **error)
|
||||
{
|
||||
g_signal_emit (rdisc, signals[RS_SENT], 0);
|
||||
g_signal_emit (ndisc, signals[RS_SENT], 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
receive_ra (gpointer user_data)
|
||||
{
|
||||
NMFakeRDisc *self = user_data;
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE (self);
|
||||
NMRDisc *rdisc = NM_RDISC (self);
|
||||
NMRDiscDataInternal *rdata = rdisc->rdata;
|
||||
NMFakeNDisc *self = user_data;
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE (self);
|
||||
NMNDisc *ndisc = NM_NDISC (self);
|
||||
NMNDiscDataInternal *rdata = ndisc->rdata;
|
||||
FakeRa *ra = priv->ras->data;
|
||||
NMRDiscConfigMap changed = 0;
|
||||
NMNDiscConfigMap changed = 0;
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
guint i;
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
NMNDiscDHCPLevel dhcp_level;
|
||||
|
||||
priv->receive_ra_id = 0;
|
||||
|
||||
|
|
@ -261,19 +261,19 @@ receive_ra (gpointer user_data)
|
|||
|
||||
if (rdata->public.dhcp_level != dhcp_level) {
|
||||
rdata->public.dhcp_level = dhcp_level;
|
||||
changed |= NM_RDISC_CONFIG_DHCP_LEVEL;
|
||||
changed |= NM_NDISC_CONFIG_DHCP_LEVEL;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->gateways->len; i++) {
|
||||
NMRDiscGateway *item = &g_array_index (ra->gateways, NMRDiscGateway, i);
|
||||
NMNDiscGateway *item = &g_array_index (ra->gateways, NMNDiscGateway, i);
|
||||
|
||||
if (nm_rdisc_add_gateway (rdisc, item))
|
||||
changed |= NM_RDISC_CONFIG_GATEWAYS;
|
||||
if (nm_ndisc_add_gateway (ndisc, item))
|
||||
changed |= NM_NDISC_CONFIG_GATEWAYS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->prefixes->len; i++) {
|
||||
FakePrefix *item = &g_array_index (ra->prefixes, FakePrefix, i);
|
||||
NMRDiscRoute route = {
|
||||
NMNDiscRoute route = {
|
||||
.network = item->network,
|
||||
.plen = item->plen,
|
||||
.gateway = item->gateway,
|
||||
|
|
@ -284,11 +284,11 @@ receive_ra (gpointer user_data)
|
|||
|
||||
g_assert (route.plen > 0 && route.plen <= 128);
|
||||
|
||||
if (nm_rdisc_add_route (rdisc, &route))
|
||||
changed |= NM_RDISC_CONFIG_ROUTES;
|
||||
if (nm_ndisc_add_route (ndisc, &route))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
|
||||
if (item->plen == 64) {
|
||||
NMRDiscAddress address = {
|
||||
NMNDiscAddress address = {
|
||||
.address = item->network,
|
||||
.timestamp = item->timestamp,
|
||||
.lifetime = item->lifetime,
|
||||
|
|
@ -296,39 +296,39 @@ receive_ra (gpointer user_data)
|
|||
.dad_counter = 0,
|
||||
};
|
||||
|
||||
if (nm_rdisc_complete_and_add_address (rdisc, &address))
|
||||
changed |= NM_RDISC_CONFIG_ADDRESSES;
|
||||
if (nm_ndisc_complete_and_add_address (ndisc, &address))
|
||||
changed |= NM_NDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->dns_servers->len; i++) {
|
||||
NMRDiscDNSServer *item = &g_array_index (ra->dns_servers, NMRDiscDNSServer, i);
|
||||
NMNDiscDNSServer *item = &g_array_index (ra->dns_servers, NMNDiscDNSServer, i);
|
||||
|
||||
if (nm_rdisc_add_dns_server (rdisc, item))
|
||||
changed |= NM_RDISC_CONFIG_DNS_SERVERS;
|
||||
if (nm_ndisc_add_dns_server (ndisc, item))
|
||||
changed |= NM_NDISC_CONFIG_DNS_SERVERS;
|
||||
}
|
||||
|
||||
for (i = 0; i < ra->dns_domains->len; i++) {
|
||||
NMRDiscDNSDomain *item = &g_array_index (ra->dns_domains, NMRDiscDNSDomain, i);
|
||||
NMNDiscDNSDomain *item = &g_array_index (ra->dns_domains, NMNDiscDNSDomain, i);
|
||||
|
||||
if (nm_rdisc_add_dns_domain (rdisc, item))
|
||||
changed |= NM_RDISC_CONFIG_DNS_DOMAINS;
|
||||
if (nm_ndisc_add_dns_domain (ndisc, item))
|
||||
changed |= NM_NDISC_CONFIG_DNS_DOMAINS;
|
||||
}
|
||||
|
||||
if (rdata->public.mtu != ra->mtu) {
|
||||
rdata->public.mtu = ra->mtu;
|
||||
changed |= NM_RDISC_CONFIG_MTU;
|
||||
changed |= NM_NDISC_CONFIG_MTU;
|
||||
}
|
||||
|
||||
if (rdata->public.hop_limit != ra->hop_limit) {
|
||||
rdata->public.hop_limit = ra->hop_limit;
|
||||
changed |= NM_RDISC_CONFIG_HOP_LIMIT;
|
||||
changed |= NM_NDISC_CONFIG_HOP_LIMIT;
|
||||
}
|
||||
|
||||
priv->ras = g_slist_remove (priv->ras, priv->ras->data);
|
||||
fake_ra_free (ra);
|
||||
|
||||
nm_rdisc_ra_received (NM_RDISC (self), now, changed);
|
||||
nm_ndisc_ra_received (NM_NDISC (self), now, changed);
|
||||
|
||||
/* Schedule next RA */
|
||||
if (priv->ras) {
|
||||
|
|
@ -340,9 +340,9 @@ receive_ra (gpointer user_data)
|
|||
}
|
||||
|
||||
static void
|
||||
start (NMRDisc *rdisc)
|
||||
start (NMNDisc *ndisc)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE ((NMFakeRDisc *) rdisc);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE ((NMFakeNDisc *) ndisc);
|
||||
FakeRa *ra;
|
||||
|
||||
/* Queue up the first fake RA */
|
||||
|
|
@ -350,58 +350,59 @@ start (NMRDisc *rdisc)
|
|||
ra = priv->ras->data;
|
||||
|
||||
g_assert (!priv->receive_ra_id);
|
||||
priv->receive_ra_id = g_timeout_add_seconds (ra->when, receive_ra, rdisc);
|
||||
priv->receive_ra_id = g_timeout_add_seconds (ra->when, receive_ra, ndisc);
|
||||
}
|
||||
|
||||
void
|
||||
nm_fake_rdisc_emit_new_ras (NMFakeRDisc *self)
|
||||
nm_fake_ndisc_emit_new_ras (NMFakeNDisc *self)
|
||||
{
|
||||
if (!NM_FAKE_RDISC_GET_PRIVATE (self)->receive_ra_id)
|
||||
start (NM_RDISC (self));
|
||||
if (!NM_FAKE_NDISC_GET_PRIVATE (self)->receive_ra_id)
|
||||
start (NM_NDISC (self));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
nm_fake_rdisc_init (NMFakeRDisc *fake_rdisc)
|
||||
nm_fake_ndisc_init (NMFakeNDisc *fake_ndisc)
|
||||
{
|
||||
}
|
||||
|
||||
NMRDisc *
|
||||
nm_fake_rdisc_new (int ifindex, const char *ifname)
|
||||
NMNDisc *
|
||||
nm_fake_ndisc_new (int ifindex, const char *ifname)
|
||||
{
|
||||
return g_object_new (NM_TYPE_FAKE_RDISC,
|
||||
NM_RDISC_IFINDEX, ifindex,
|
||||
NM_RDISC_IFNAME, ifname,
|
||||
return g_object_new (NM_TYPE_FAKE_NDISC,
|
||||
NM_NDISC_IFINDEX, ifindex,
|
||||
NM_NDISC_IFNAME, ifname,
|
||||
NM_NDISC_NODE_TYPE, (int) NM_NDISC_NODE_TYPE_HOST,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMFakeRDiscPrivate *priv = NM_FAKE_RDISC_GET_PRIVATE ((NMFakeRDisc *) object);
|
||||
NMFakeNDiscPrivate *priv = NM_FAKE_NDISC_GET_PRIVATE ((NMFakeNDisc *) object);
|
||||
|
||||
nm_clear_g_source (&priv->receive_ra_id);
|
||||
|
||||
g_slist_free_full (priv->ras, fake_ra_free);
|
||||
priv->ras = NULL;
|
||||
|
||||
G_OBJECT_CLASS (nm_fake_rdisc_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (nm_fake_ndisc_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_fake_rdisc_class_init (NMFakeRDiscClass *klass)
|
||||
nm_fake_ndisc_class_init (NMFakeNDiscClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMRDiscClass *rdisc_class = NM_RDISC_CLASS (klass);
|
||||
NMNDiscClass *ndisc_class = NM_NDISC_CLASS (klass);
|
||||
|
||||
object_class->dispose = dispose;
|
||||
|
||||
rdisc_class->start = start;
|
||||
rdisc_class->send_rs = send_rs;
|
||||
ndisc_class->start = start;
|
||||
ndisc_class->send_rs = send_rs;
|
||||
|
||||
signals[RS_SENT] =
|
||||
g_signal_new (NM_FAKE_RDISC_RS_SENT,
|
||||
g_signal_new (NM_FAKE_NDISC_RS_SENT,
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
0, NULL, NULL, NULL,
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-fake-rdisc.h - Fake implementation of router discovery
|
||||
/* nm-fake-ndisc.h - Fake implementation of neighbor discovery
|
||||
*
|
||||
* 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
|
||||
|
|
@ -18,41 +18,41 @@
|
|||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_FAKE_RDISC_H__
|
||||
#define __NETWORKMANAGER_FAKE_RDISC_H__
|
||||
#ifndef __NETWORKMANAGER_FAKE_NDISC_H__
|
||||
#define __NETWORKMANAGER_FAKE_NDISC_H__
|
||||
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
|
||||
#define NM_TYPE_FAKE_RDISC (nm_fake_rdisc_get_type ())
|
||||
#define NM_FAKE_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FAKE_RDISC, NMFakeRDisc))
|
||||
#define NM_FAKE_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FAKE_RDISC, NMFakeRDiscClass))
|
||||
#define NM_IS_FAKE_RDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_FAKE_RDISC))
|
||||
#define NM_IS_FAKE_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_FAKE_RDISC))
|
||||
#define NM_FAKE_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_FAKE_RDISC, NMFakeRDiscClass))
|
||||
#define NM_TYPE_FAKE_NDISC (nm_fake_ndisc_get_type ())
|
||||
#define NM_FAKE_NDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_FAKE_NDISC, NMFakeNDisc))
|
||||
#define NM_FAKE_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_FAKE_NDISC, NMFakeNDiscClass))
|
||||
#define NM_IS_FAKE_NDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_FAKE_NDISC))
|
||||
#define NM_IS_FAKE_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_FAKE_NDISC))
|
||||
#define NM_FAKE_NDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_FAKE_NDISC, NMFakeNDiscClass))
|
||||
|
||||
#define NM_FAKE_RDISC_RS_SENT "rs-sent"
|
||||
#define NM_FAKE_NDISC_RS_SENT "rs-sent"
|
||||
|
||||
typedef struct _NMFakeRRDisc NMFakeRDisc;
|
||||
typedef struct _NMFakeRRDiscClass NMFakeRDiscClass;
|
||||
typedef struct _NMFakeRNDisc NMFakeNDisc;
|
||||
typedef struct _NMFakeRNDiscClass NMFakeNDiscClass;
|
||||
|
||||
GType nm_fake_rdisc_get_type (void);
|
||||
GType nm_fake_ndisc_get_type (void);
|
||||
|
||||
NMRDisc *nm_fake_rdisc_new (int ifindex, const char *ifname);
|
||||
NMNDisc *nm_fake_ndisc_new (int ifindex, const char *ifname);
|
||||
|
||||
guint nm_fake_rdisc_add_ra (NMFakeRDisc *self,
|
||||
guint nm_fake_ndisc_add_ra (NMFakeNDisc *self,
|
||||
guint seconds,
|
||||
NMRDiscDHCPLevel dhcp_level,
|
||||
NMNDiscDHCPLevel dhcp_level,
|
||||
int hop_limit,
|
||||
guint32 mtu);
|
||||
|
||||
void nm_fake_rdisc_add_gateway (NMFakeRDisc *self,
|
||||
void nm_fake_ndisc_add_gateway (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *addr,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
NMRDiscPreference preference);
|
||||
NMNDiscPreference preference);
|
||||
|
||||
void nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
||||
void nm_fake_ndisc_add_prefix (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *network,
|
||||
guint plen,
|
||||
|
|
@ -60,22 +60,22 @@ void nm_fake_rdisc_add_prefix (NMFakeRDisc *self,
|
|||
guint32 timestamp,
|
||||
guint32 lifetime,
|
||||
guint32 preferred,
|
||||
NMRDiscPreference preference);
|
||||
NMNDiscPreference preference);
|
||||
|
||||
void nm_fake_rdisc_add_dns_server (NMFakeRDisc *self,
|
||||
void nm_fake_ndisc_add_dns_server (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *address,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime);
|
||||
|
||||
void nm_fake_rdisc_add_dns_domain (NMFakeRDisc *self,
|
||||
void nm_fake_ndisc_add_dns_domain (NMFakeNDisc *self,
|
||||
guint ra_id,
|
||||
const char *domain,
|
||||
guint32 timestamp,
|
||||
guint32 lifetime);
|
||||
|
||||
void nm_fake_rdisc_emit_new_ras (NMFakeRDisc *self);
|
||||
void nm_fake_ndisc_emit_new_ras (NMFakeNDisc *self);
|
||||
|
||||
gboolean nm_fake_rdisc_done (NMFakeRDisc *self);
|
||||
gboolean nm_fake_ndisc_done (NMFakeNDisc *self);
|
||||
|
||||
#endif /* __NETWORKMANAGER_FAKE_RDISC_H__ */
|
||||
#endif /* __NETWORKMANAGER_FAKE_NDISC_H__ */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-lndp-rdisc.c - Router discovery implementation using libndp
|
||||
/* nm-lndp-ndisc.c - Router discovery implementation using libndp
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,20 +20,21 @@
|
|||
|
||||
#include "nm-default.h"
|
||||
|
||||
#include "nm-lndp-rdisc.h"
|
||||
#include "nm-lndp-ndisc.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/icmp6.h>
|
||||
/* stdarg.h included because of a bug in ndp.h */
|
||||
#include <stdarg.h>
|
||||
#include <ndp.h>
|
||||
|
||||
#include "nm-rdisc-private.h"
|
||||
#include "nm-ndisc-private.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-platform.h"
|
||||
#include "nmp-netns.h"
|
||||
|
||||
#define _NMLOG_PREFIX_NAME "rdisc-lndp"
|
||||
#define _NMLOG_PREFIX_NAME "ndisc-lndp"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -42,32 +43,31 @@ typedef struct {
|
|||
|
||||
GIOChannel *event_channel;
|
||||
guint event_id;
|
||||
guint ra_timeout_id; /* first RA timeout */
|
||||
} NMLndpRDiscPrivate;
|
||||
} NMLndpNDiscPrivate;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
struct _NMLndpRDisc {
|
||||
NMRDisc parent;
|
||||
NMLndpRDiscPrivate _priv;
|
||||
struct _NMLndpNDisc {
|
||||
NMNDisc parent;
|
||||
NMLndpNDiscPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMLndpRDiscClass {
|
||||
NMRDiscClass parent;
|
||||
struct _NMLndpNDiscClass {
|
||||
NMNDiscClass parent;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
G_DEFINE_TYPE (NMLndpRDisc, nm_lndp_rdisc, NM_TYPE_RDISC)
|
||||
G_DEFINE_TYPE (NMLndpNDisc, nm_lndp_ndisc, NM_TYPE_NDISC)
|
||||
|
||||
#define NM_LNDP_RDISC_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMLndpRDisc, NM_IS_LNDP_RDISC)
|
||||
#define NM_LNDP_NDISC_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMLndpNDisc, NM_IS_LNDP_NDISC)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static gboolean
|
||||
send_rs (NMRDisc *rdisc, GError **error)
|
||||
send_rs (NMNDisc *ndisc, GError **error)
|
||||
{
|
||||
NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
|
||||
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
struct ndp_msg *msg;
|
||||
int errsv;
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ send_rs (NMRDisc *rdisc, GError **error)
|
|||
"cannot create router solicitation");
|
||||
return FALSE;
|
||||
}
|
||||
ndp_msg_ifindex_set (msg, nm_rdisc_get_ifindex (rdisc));
|
||||
ndp_msg_ifindex_set (msg, nm_ndisc_get_ifindex (ndisc));
|
||||
|
||||
errsv = ndp_msg_send (priv->ndp, msg);
|
||||
ndp_msg_destroy (msg);
|
||||
|
|
@ -93,19 +93,19 @@ send_rs (NMRDisc *rdisc, GError **error)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
_NM_UTILS_LOOKUP_DEFINE (static, translate_preference, enum ndp_route_preference, NMRDiscPreference,
|
||||
NM_UTILS_LOOKUP_DEFAULT (NM_RDISC_PREFERENCE_INVALID),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_LOW, NM_RDISC_PREFERENCE_LOW),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_MEDIUM, NM_RDISC_PREFERENCE_MEDIUM),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_HIGH, NM_RDISC_PREFERENCE_HIGH),
|
||||
_NM_UTILS_LOOKUP_DEFINE (static, translate_preference, enum ndp_route_preference, NMNDiscPreference,
|
||||
NM_UTILS_LOOKUP_DEFAULT (NM_NDISC_PREFERENCE_INVALID),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_LOW, NM_NDISC_PREFERENCE_LOW),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_MEDIUM, NM_NDISC_PREFERENCE_MEDIUM),
|
||||
NM_UTILS_LOOKUP_ITEM (NDP_ROUTE_PREF_HIGH, NM_NDISC_PREFERENCE_HIGH),
|
||||
);
|
||||
|
||||
static int
|
||||
receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
||||
{
|
||||
NMRDisc *rdisc = (NMRDisc *) user_data;
|
||||
NMRDiscDataInternal *rdata = rdisc->rdata;
|
||||
NMRDiscConfigMap changed = 0;
|
||||
NMNDisc *ndisc = (NMNDisc *) user_data;
|
||||
NMNDiscDataInternal *rdata = ndisc->rdata;
|
||||
NMNDiscConfigMap changed = 0;
|
||||
struct ndp_msgra *msgra = ndp_msgra (msg);
|
||||
struct in6_addr gateway_addr;
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
|
@ -132,24 +132,24 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
* rewrite the flag with every inbound RA.
|
||||
*/
|
||||
{
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
NMNDiscDHCPLevel dhcp_level;
|
||||
|
||||
if (ndp_msgra_flag_managed (msgra))
|
||||
dhcp_level = NM_RDISC_DHCP_LEVEL_MANAGED;
|
||||
dhcp_level = NM_NDISC_DHCP_LEVEL_MANAGED;
|
||||
else if (ndp_msgra_flag_other (msgra))
|
||||
dhcp_level = NM_RDISC_DHCP_LEVEL_OTHERCONF;
|
||||
dhcp_level = NM_NDISC_DHCP_LEVEL_OTHERCONF;
|
||||
else
|
||||
dhcp_level = NM_RDISC_DHCP_LEVEL_NONE;
|
||||
dhcp_level = NM_NDISC_DHCP_LEVEL_NONE;
|
||||
|
||||
/* when receiving multiple RA (possibly from different routers),
|
||||
* let's keep the "most managed" level. */
|
||||
G_STATIC_ASSERT_EXPR (NM_RDISC_DHCP_LEVEL_MANAGED > NM_RDISC_DHCP_LEVEL_OTHERCONF);
|
||||
G_STATIC_ASSERT_EXPR (NM_RDISC_DHCP_LEVEL_OTHERCONF > NM_RDISC_DHCP_LEVEL_NONE);
|
||||
G_STATIC_ASSERT_EXPR (NM_NDISC_DHCP_LEVEL_MANAGED > NM_NDISC_DHCP_LEVEL_OTHERCONF);
|
||||
G_STATIC_ASSERT_EXPR (NM_NDISC_DHCP_LEVEL_OTHERCONF > NM_NDISC_DHCP_LEVEL_NONE);
|
||||
dhcp_level = MAX (dhcp_level, rdata->public.dhcp_level);
|
||||
|
||||
if (dhcp_level != rdata->public.dhcp_level) {
|
||||
rdata->public.dhcp_level = dhcp_level;
|
||||
changed |= NM_RDISC_CONFIG_DHCP_LEVEL;
|
||||
changed |= NM_NDISC_CONFIG_DHCP_LEVEL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -161,15 +161,15 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
*/
|
||||
gateway_addr = *ndp_msg_addrto (msg);
|
||||
{
|
||||
NMRDiscGateway gateway = {
|
||||
NMNDiscGateway gateway = {
|
||||
.address = gateway_addr,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msgra_router_lifetime (msgra),
|
||||
.preference = translate_preference (ndp_msgra_route_preference (msgra)),
|
||||
};
|
||||
|
||||
if (nm_rdisc_add_gateway (rdisc, &gateway))
|
||||
changed |= NM_RDISC_CONFIG_GATEWAYS;
|
||||
if (nm_ndisc_add_gateway (ndisc, &gateway))
|
||||
changed |= NM_NDISC_CONFIG_GATEWAYS;
|
||||
}
|
||||
|
||||
/* Addresses & Routes */
|
||||
|
|
@ -185,21 +185,21 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
nm_utils_ip6_address_clear_host_address (&r_network, ndp_msg_opt_prefix (msg, offset), r_plen);
|
||||
|
||||
if (ndp_msg_opt_prefix_flag_on_link (msg, offset)) {
|
||||
NMRDiscRoute route = {
|
||||
NMNDiscRoute route = {
|
||||
.network = r_network,
|
||||
.plen = r_plen,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
|
||||
};
|
||||
|
||||
if (nm_rdisc_add_route (rdisc, &route))
|
||||
changed |= NM_RDISC_CONFIG_ROUTES;
|
||||
if (nm_ndisc_add_route (ndisc, &route))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
}
|
||||
|
||||
/* Address */
|
||||
if ( r_plen == 64
|
||||
&& ndp_msg_opt_prefix_flag_auto_addr_conf (msg, offset)) {
|
||||
NMRDiscAddress address = {
|
||||
NMNDiscAddress address = {
|
||||
.address = r_network,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_prefix_valid_time (msg, offset),
|
||||
|
|
@ -208,12 +208,12 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
if (nm_rdisc_complete_and_add_address (rdisc, &address))
|
||||
changed |= NM_RDISC_CONFIG_ADDRESSES;
|
||||
if (nm_ndisc_complete_and_add_address (ndisc, &address))
|
||||
changed |= NM_NDISC_CONFIG_ADDRESSES;
|
||||
}
|
||||
}
|
||||
ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_ROUTE) {
|
||||
NMRDiscRoute route = {
|
||||
NMNDiscRoute route = {
|
||||
.gateway = gateway_addr,
|
||||
.plen = ndp_msg_opt_route_prefix_len (msg, offset),
|
||||
.timestamp = now,
|
||||
|
|
@ -226,8 +226,8 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
|
||||
/* Routers through this particular gateway */
|
||||
nm_utils_ip6_address_clear_host_address (&route.network, ndp_msg_opt_route_prefix (msg, offset), route.plen);
|
||||
if (nm_rdisc_add_route (rdisc, &route))
|
||||
changed |= NM_RDISC_CONFIG_ROUTES;
|
||||
if (nm_ndisc_add_route (ndisc, &route))
|
||||
changed |= NM_NDISC_CONFIG_ROUTES;
|
||||
}
|
||||
|
||||
/* DNS information */
|
||||
|
|
@ -236,7 +236,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
int addr_index;
|
||||
|
||||
ndp_msg_opt_rdnss_for_each_addr (addr, addr_index, msg, offset) {
|
||||
NMRDiscDNSServer dns_server = {
|
||||
NMNDiscDNSServer dns_server = {
|
||||
.address = *addr,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
|
||||
|
|
@ -249,8 +249,8 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
*/
|
||||
if (dns_server.lifetime && dns_server.lifetime < 7200)
|
||||
dns_server.lifetime = 7200;
|
||||
if (nm_rdisc_add_dns_server (rdisc, &dns_server))
|
||||
changed |= NM_RDISC_CONFIG_DNS_SERVERS;
|
||||
if (nm_ndisc_add_dns_server (ndisc, &dns_server))
|
||||
changed |= NM_NDISC_CONFIG_DNS_SERVERS;
|
||||
}
|
||||
}
|
||||
ndp_msg_opt_for_each_offset(offset, msg, NDP_MSG_OPT_DNSSL) {
|
||||
|
|
@ -258,7 +258,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
int domain_index;
|
||||
|
||||
ndp_msg_opt_dnssl_for_each_domain (domain, domain_index, msg, offset) {
|
||||
NMRDiscDNSDomain dns_domain = {
|
||||
NMNDiscDNSDomain dns_domain = {
|
||||
.domain = domain,
|
||||
.timestamp = now,
|
||||
.lifetime = ndp_msg_opt_rdnss_lifetime (msg, offset),
|
||||
|
|
@ -271,15 +271,15 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
*/
|
||||
if (dns_domain.lifetime && dns_domain.lifetime < 7200)
|
||||
dns_domain.lifetime = 7200;
|
||||
if (nm_rdisc_add_dns_domain (rdisc, &dns_domain))
|
||||
changed |= NM_RDISC_CONFIG_DNS_DOMAINS;
|
||||
if (nm_ndisc_add_dns_domain (ndisc, &dns_domain))
|
||||
changed |= NM_NDISC_CONFIG_DNS_DOMAINS;
|
||||
}
|
||||
}
|
||||
|
||||
hop_limit = ndp_msgra_curhoplimit (msgra);
|
||||
if (rdata->public.hop_limit != hop_limit) {
|
||||
rdata->public.hop_limit = hop_limit;
|
||||
changed |= NM_RDISC_CONFIG_HOP_LIMIT;
|
||||
changed |= NM_NDISC_CONFIG_HOP_LIMIT;
|
||||
}
|
||||
|
||||
/* MTU */
|
||||
|
|
@ -288,7 +288,7 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
if (mtu >= 1280) {
|
||||
if (rdata->public.mtu != mtu) {
|
||||
rdata->public.mtu = mtu;
|
||||
changed |= NM_RDISC_CONFIG_MTU;
|
||||
changed |= NM_NDISC_CONFIG_MTU;
|
||||
}
|
||||
} else {
|
||||
/* All sorts of bad things would happen if we accepted this.
|
||||
|
|
@ -299,19 +299,189 @@ receive_ra (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
nm_rdisc_ra_received (rdisc, now, changed);
|
||||
nm_ndisc_ra_received (ndisc, now, changed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *
|
||||
_ndp_msg_add_option (struct ndp_msg *msg, int len)
|
||||
{
|
||||
void *ret = (uint8_t *)msg + ndp_msg_payload_len (msg);
|
||||
|
||||
len += ndp_msg_payload_len (msg);
|
||||
if (len > ndp_msg_payload_maxlen (msg))
|
||||
return NULL;
|
||||
|
||||
ndp_msg_payload_len_set (msg, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define NM_ND_OPT_RDNSS 25
|
||||
typedef struct {
|
||||
struct nd_opt_hdr header;
|
||||
uint16_t reserved;
|
||||
uint32_t lifetime;;
|
||||
struct in6_addr addrs[0];
|
||||
} NMLndpRdnssOption;
|
||||
|
||||
#define NM_ND_OPT_DNSSL 31
|
||||
typedef struct {
|
||||
struct nd_opt_hdr header;
|
||||
uint16_t reserved;
|
||||
uint32_t lifetime;
|
||||
char search_list[0];
|
||||
} NMLndpDnsslOption;
|
||||
|
||||
static gboolean
|
||||
send_ra (NMNDisc *ndisc, GError **error)
|
||||
{
|
||||
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
NMNDiscDataInternal *rdata = ndisc->rdata;
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
int errsv;
|
||||
struct in6_addr *addr;
|
||||
struct ndp_msg *msg;
|
||||
struct nd_opt_prefix_info *prefix;
|
||||
int i;
|
||||
|
||||
errsv = ndp_msg_new (&msg, NDP_MSG_RA);
|
||||
if (errsv) {
|
||||
errsv = errsv > 0 ? errsv : -errsv;
|
||||
g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"cannot create a router advertisement");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ndp_msg_ifindex_set (msg, nm_ndisc_get_ifindex (ndisc));
|
||||
|
||||
/* Multicast to all nodes. */
|
||||
addr = ndp_msg_addrto (msg);
|
||||
addr->s6_addr32[0] = htonl(0xff020000);
|
||||
addr->s6_addr32[1] = 0;
|
||||
addr->s6_addr32[2] = 0;
|
||||
addr->s6_addr32[3] = htonl(0x1);
|
||||
|
||||
ndp_msgra_router_lifetime_set (ndp_msgra (msg), NM_NDISC_ROUTER_LIFETIME);
|
||||
|
||||
/* The device let us know about all addresses that the device got
|
||||
* whose prefixes are suitable for delegating. Let's announce them. */
|
||||
for (i = 0; i < rdata->addresses->len; i++) {
|
||||
NMNDiscAddress *address = &g_array_index (rdata->addresses, NMNDiscAddress, i);
|
||||
guint32 age = now - address->timestamp;
|
||||
guint32 lifetime = address->lifetime;
|
||||
guint32 preferred = address->preferred;
|
||||
|
||||
/* Clamp the life times if they're not forever. */
|
||||
if (lifetime != 0xffffffff)
|
||||
lifetime = lifetime > age ? lifetime - age : 0;
|
||||
if (preferred != 0xffffffff)
|
||||
preferred = preferred > age ? preferred - age : 0;
|
||||
|
||||
prefix = _ndp_msg_add_option (msg, sizeof(*prefix));
|
||||
if (!prefix) {
|
||||
/* Maybe we could sent separate RAs, but why bother... */
|
||||
_LOGW ("The RA is too big, had to omit some some prefixes.");
|
||||
break;
|
||||
}
|
||||
|
||||
prefix->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
|
||||
prefix->nd_opt_pi_len = 4;
|
||||
prefix->nd_opt_pi_prefix_len = 64;
|
||||
prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_ONLINK;
|
||||
prefix->nd_opt_pi_flags_reserved |= ND_OPT_PI_FLAG_AUTO;
|
||||
prefix->nd_opt_pi_valid_time = htonl(lifetime);
|
||||
prefix->nd_opt_pi_preferred_time = htonl(preferred);
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[0] = address->address.s6_addr32[0];
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[1] = address->address.s6_addr32[1];
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[2] = 0;
|
||||
prefix->nd_opt_pi_prefix.s6_addr32[3] = 0;
|
||||
}
|
||||
|
||||
if (rdata->dns_servers->len) {
|
||||
NMLndpRdnssOption *option;
|
||||
int len = sizeof(*option) + sizeof(option->addrs[0]) * rdata->dns_servers->len;
|
||||
|
||||
option = _ndp_msg_add_option (msg, len);
|
||||
if (option) {
|
||||
option->header.nd_opt_type = NM_ND_OPT_RDNSS;
|
||||
option->header.nd_opt_len = len / 8;
|
||||
option->lifetime = htonl (900);
|
||||
|
||||
for (i = 0; i < rdata->dns_servers->len; i++) {
|
||||
NMNDiscDNSServer *dns_server = &g_array_index (rdata->dns_servers, NMNDiscDNSServer, i);
|
||||
option->addrs[i] = dns_server->address;
|
||||
}
|
||||
} else {
|
||||
_LOGW ("The RA is too big, had to omit DNS information.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (rdata->dns_domains->len) {
|
||||
NMLndpDnsslOption *option;
|
||||
NMNDiscDNSDomain *dns_server;
|
||||
int len = sizeof(*option);
|
||||
char *search_list;
|
||||
|
||||
for (i = 0; i < rdata->dns_domains->len; i++) {
|
||||
dns_server = &g_array_index (rdata->dns_domains, NMNDiscDNSDomain, i);
|
||||
len += strlen (dns_server->domain) + 2;
|
||||
}
|
||||
len = (len + 8) & ~0x7;
|
||||
|
||||
option = _ndp_msg_add_option (msg, len);
|
||||
if (option) {
|
||||
option->header.nd_opt_type = NM_ND_OPT_DNSSL;
|
||||
option->header.nd_opt_len = len / 8;
|
||||
option->lifetime = htonl (900);
|
||||
|
||||
search_list = option->search_list;
|
||||
for (i = 0; i < rdata->dns_domains->len; i++) {
|
||||
NMNDiscDNSDomain *dns_domain = &g_array_index (rdata->dns_domains, NMNDiscDNSDomain, i);
|
||||
uint8_t domain_len = strlen (dns_domain->domain);
|
||||
|
||||
*search_list++ = domain_len;
|
||||
memcpy (search_list, dns_domain->domain, domain_len);
|
||||
search_list += domain_len;
|
||||
*search_list++ = '\0';
|
||||
}
|
||||
} else {
|
||||
_LOGW ("The RA is too big, had to omit DNS search list.");
|
||||
}
|
||||
}
|
||||
|
||||
errsv = ndp_msg_send (priv->ndp, msg);
|
||||
|
||||
ndp_msg_destroy (msg);
|
||||
if (errsv) {
|
||||
errsv = errsv > 0 ? errsv : -errsv;
|
||||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"%s (%d)",
|
||||
g_strerror (errsv), errsv);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
receive_rs (struct ndp *ndp, struct ndp_msg *msg, gpointer user_data)
|
||||
{
|
||||
NMNDisc *ndisc = user_data;
|
||||
|
||||
nm_ndisc_rs_received (ndisc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
|
||||
event_ready (GIOChannel *source, GIOCondition condition, NMNDisc *ndisc)
|
||||
{
|
||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||
NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
|
||||
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
|
||||
_LOGD ("processing libndp events");
|
||||
|
||||
if (!nm_rdisc_netns_push (rdisc, &netns))
|
||||
if (!nm_ndisc_netns_push (ndisc, &netns))
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
ndp_callall_eventfd_handler (priv->ndp);
|
||||
|
|
@ -319,18 +489,30 @@ event_ready (GIOChannel *source, GIOCondition condition, NMRDisc *rdisc)
|
|||
}
|
||||
|
||||
static void
|
||||
start (NMRDisc *rdisc)
|
||||
start (NMNDisc *ndisc)
|
||||
{
|
||||
NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
|
||||
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
int fd = ndp_get_eventfd (priv->ndp);
|
||||
|
||||
g_return_if_fail (!priv->event_channel);
|
||||
g_return_if_fail (!priv->event_id);
|
||||
|
||||
priv->event_channel = g_io_channel_unix_new (fd);
|
||||
priv->event_id = g_io_add_watch (priv->event_channel, G_IO_IN, (GIOFunc) event_ready, rdisc);
|
||||
priv->event_id = g_io_add_watch (priv->event_channel, G_IO_IN, (GIOFunc) event_ready, ndisc);
|
||||
|
||||
/* Flush any pending messages to avoid using obsolete information */
|
||||
event_ready (priv->event_channel, 0, rdisc);
|
||||
event_ready (priv->event_channel, 0, ndisc);
|
||||
|
||||
ndp_msgrcv_handler_register (priv->ndp, receive_ra, NDP_MSG_RA, nm_rdisc_get_ifindex (rdisc), rdisc);
|
||||
switch (nm_ndisc_get_node_type (ndisc)) {
|
||||
case NM_NDISC_NODE_TYPE_HOST:
|
||||
ndp_msgrcv_handler_register (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc);
|
||||
break;
|
||||
case NM_NDISC_NODE_TYPE_ROUTER:
|
||||
ndp_msgrcv_handler_register (priv->ndp, receive_rs, NDP_MSG_RS, nm_ndisc_get_ifindex (ndisc), ndisc);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -347,22 +529,23 @@ ipv6_sysctl_get (NMPlatform *platform, const char *ifname, const char *property,
|
|||
}
|
||||
|
||||
static void
|
||||
nm_lndp_rdisc_init (NMLndpRDisc *lndp_rdisc)
|
||||
nm_lndp_ndisc_init (NMLndpNDisc *lndp_ndisc)
|
||||
{
|
||||
}
|
||||
|
||||
NMRDisc *
|
||||
nm_lndp_rdisc_new (NMPlatform *platform,
|
||||
NMNDisc *
|
||||
nm_lndp_ndisc_new (NMPlatform *platform,
|
||||
int ifindex,
|
||||
const char *ifname,
|
||||
NMUtilsStableType stable_type,
|
||||
const char *network_id,
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
|
||||
NMNDiscNodeType node_type,
|
||||
GError **error)
|
||||
{
|
||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||
NMRDisc *rdisc;
|
||||
NMLndpRDiscPrivate *priv;
|
||||
NMNDisc *ndisc;
|
||||
NMLndpNDiscPrivate *priv;
|
||||
int errsv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_PLATFORM (platform), NULL);
|
||||
|
|
@ -371,25 +554,26 @@ nm_lndp_rdisc_new (NMPlatform *platform,
|
|||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return NULL;
|
||||
|
||||
rdisc = g_object_new (NM_TYPE_LNDP_RDISC,
|
||||
NM_RDISC_PLATFORM, platform,
|
||||
NM_RDISC_STABLE_TYPE, (int) stable_type,
|
||||
NM_RDISC_IFINDEX, ifindex,
|
||||
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,
|
||||
ndisc = g_object_new (NM_TYPE_LNDP_NDISC,
|
||||
NM_NDISC_PLATFORM, platform,
|
||||
NM_NDISC_STABLE_TYPE, (int) stable_type,
|
||||
NM_NDISC_IFINDEX, ifindex,
|
||||
NM_NDISC_IFNAME, ifname,
|
||||
NM_NDISC_NETWORK_ID, network_id,
|
||||
NM_NDISC_ADDR_GEN_MODE, (int) addr_gen_mode,
|
||||
NM_NDISC_NODE_TYPE, (int) node_type,
|
||||
NM_NDISC_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,
|
||||
0, G_MAXINT32, NM_NDISC_MAX_ADDRESSES_DEFAULT),
|
||||
NM_NDISC_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,
|
||||
1, G_MAXINT32, NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT),
|
||||
NM_NDISC_ROUTER_SOLICITATION_INTERVAL, ipv6_sysctl_get (platform, ifname,
|
||||
"router_solicitation_interval",
|
||||
1, G_MAXINT32, NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT),
|
||||
1, G_MAXINT32, NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT),
|
||||
NULL);
|
||||
|
||||
priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
|
||||
priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
|
||||
errsv = ndp_open (&priv->ndp);
|
||||
|
||||
|
|
@ -398,37 +582,47 @@ nm_lndp_rdisc_new (NMPlatform *platform,
|
|||
g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN,
|
||||
"failure creating libndp socket: %s (%d)",
|
||||
g_strerror (errsv), errsv);
|
||||
g_object_unref (rdisc);
|
||||
g_object_unref (ndisc);
|
||||
return NULL;
|
||||
}
|
||||
return rdisc;
|
||||
return ndisc;
|
||||
}
|
||||
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMRDisc *rdisc = (NMRDisc *) object;
|
||||
NMLndpRDiscPrivate *priv = NM_LNDP_RDISC_GET_PRIVATE ((NMLndpRDisc *) rdisc);
|
||||
NMNDisc *ndisc = (NMNDisc *) object;
|
||||
NMLndpNDiscPrivate *priv = NM_LNDP_NDISC_GET_PRIVATE ((NMLndpNDisc *) ndisc);
|
||||
|
||||
nm_clear_g_source (&priv->event_id);
|
||||
g_clear_pointer (&priv->event_channel, g_io_channel_unref);
|
||||
|
||||
if (priv->ndp) {
|
||||
ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_rdisc_get_ifindex (rdisc), rdisc);
|
||||
switch (nm_ndisc_get_node_type (ndisc)) {
|
||||
case NM_NDISC_NODE_TYPE_HOST:
|
||||
ndp_msgrcv_handler_unregister (priv->ndp, receive_rs, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc);
|
||||
break;
|
||||
case NM_NDISC_NODE_TYPE_ROUTER:
|
||||
ndp_msgrcv_handler_unregister (priv->ndp, receive_ra, NDP_MSG_RA, nm_ndisc_get_ifindex (ndisc), ndisc);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
ndp_close (priv->ndp);
|
||||
priv->ndp = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_lndp_rdisc_parent_class)->dispose (object);
|
||||
G_OBJECT_CLASS (nm_lndp_ndisc_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
nm_lndp_rdisc_class_init (NMLndpRDiscClass *klass)
|
||||
nm_lndp_ndisc_class_init (NMLndpNDiscClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
NMRDiscClass *rdisc_class = NM_RDISC_CLASS (klass);
|
||||
NMNDiscClass *ndisc_class = NM_NDISC_CLASS (klass);
|
||||
|
||||
object_class->dispose = dispose;
|
||||
rdisc_class->start = start;
|
||||
rdisc_class->send_rs = send_rs;
|
||||
ndisc_class->start = start;
|
||||
ndisc_class->send_rs = send_rs;
|
||||
ndisc_class->send_ra = send_ra;
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-lndp-rdisc.h - Implementation of router discovery using libndp
|
||||
/* nm-lndp-ndisc.h - Implementation of neighbor discovery using libndp
|
||||
*
|
||||
* 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
|
||||
|
|
@ -18,30 +18,31 @@
|
|||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_LNDP_RDISC_H__
|
||||
#define __NETWORKMANAGER_LNDP_RDISC_H__
|
||||
#ifndef __NETWORKMANAGER_LNDP_NDISC_H__
|
||||
#define __NETWORKMANAGER_LNDP_NDISC_H__
|
||||
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
#include "nm-core-utils.h"
|
||||
|
||||
#define NM_TYPE_LNDP_RDISC (nm_lndp_rdisc_get_type ())
|
||||
#define NM_LNDP_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LNDP_RDISC, NMLndpRDisc))
|
||||
#define NM_LNDP_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LNDP_RDISC, NMLndpRDiscClass))
|
||||
#define NM_IS_LNDP_RDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LNDP_RDISC))
|
||||
#define NM_IS_LNDP_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_LNDP_RDISC))
|
||||
#define NM_LNDP_RDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_LNDP_RDISC, NMLndpRDiscClass))
|
||||
#define NM_TYPE_LNDP_NDISC (nm_lndp_ndisc_get_type ())
|
||||
#define NM_LNDP_NDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LNDP_NDISC, NMLndpNDisc))
|
||||
#define NM_LNDP_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LNDP_NDISC, NMLndpNDiscClass))
|
||||
#define NM_IS_LNDP_NDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LNDP_NDISC))
|
||||
#define NM_IS_LNDP_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_LNDP_NDISC))
|
||||
#define NM_LNDP_NDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_LNDP_NDISC, NMLndpNDiscClass))
|
||||
|
||||
typedef struct _NMLndpRDisc NMLndpRDisc;
|
||||
typedef struct _NMLndpRDiscClass NMLndpRDiscClass;
|
||||
typedef struct _NMLndpNDisc NMLndpNDisc;
|
||||
typedef struct _NMLndpNDiscClass NMLndpNDiscClass;
|
||||
|
||||
GType nm_lndp_rdisc_get_type (void);
|
||||
GType nm_lndp_ndisc_get_type (void);
|
||||
|
||||
NMRDisc *nm_lndp_rdisc_new (NMPlatform *platform,
|
||||
NMNDisc *nm_lndp_ndisc_new (NMPlatform *platform,
|
||||
int ifindex,
|
||||
const char *ifname,
|
||||
NMUtilsStableType stable_type,
|
||||
const char *network_id,
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode,
|
||||
NMNDiscNodeType node_type,
|
||||
GError **error);
|
||||
|
||||
#endif /* __NETWORKMANAGER_LNDP_RDISC_H__ */
|
||||
#endif /* __NETWORKMANAGER_LNDP_NDISC_H__ */
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-rdisc.h - Perform IPv6 router discovery
|
||||
/* nm-ndisc.h - Perform IPv6 neighbor discovery
|
||||
*
|
||||
* 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
|
||||
|
|
@ -18,15 +18,15 @@
|
|||
* Copyright 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_RDISC_PRIVATE_H__
|
||||
#define __NETWORKMANAGER_RDISC_PRIVATE_H__
|
||||
#ifndef __NETWORKMANAGER_NDISC_PRIVATE_H__
|
||||
#define __NETWORKMANAGER_NDISC_PRIVATE_H__
|
||||
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
|
||||
/* Functions only used by rdisc implementations */
|
||||
/* Functions only used by ndisc implementations */
|
||||
|
||||
struct _NMRDiscDataInternal {
|
||||
NMRDiscData public;
|
||||
struct _NMNDiscDataInternal {
|
||||
NMNDiscData public;
|
||||
GArray *gateways;
|
||||
GArray *addresses;
|
||||
GArray *routes;
|
||||
|
|
@ -34,20 +34,21 @@ struct _NMRDiscDataInternal {
|
|||
GArray *dns_domains;
|
||||
};
|
||||
|
||||
typedef struct _NMRDiscDataInternal NMRDiscDataInternal;
|
||||
typedef struct _NMNDiscDataInternal NMNDiscDataInternal;
|
||||
|
||||
void nm_rdisc_ra_received (NMRDisc *rdisc, guint32 now, NMRDiscConfigMap changed);
|
||||
void nm_ndisc_ra_received (NMNDisc *ndisc, guint32 now, NMNDiscConfigMap changed);
|
||||
void nm_ndisc_rs_received (NMNDisc *ndisc);
|
||||
|
||||
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);
|
||||
gboolean nm_ndisc_add_gateway (NMNDisc *ndisc, const NMNDiscGateway *new);
|
||||
gboolean nm_ndisc_complete_and_add_address (NMNDisc *ndisc, NMNDiscAddress *new);
|
||||
gboolean nm_ndisc_add_route (NMNDisc *ndisc, const NMNDiscRoute *new);
|
||||
gboolean nm_ndisc_add_dns_server (NMNDisc *ndisc, const NMNDiscDNSServer *new);
|
||||
gboolean nm_ndisc_add_dns_domain (NMNDisc *ndisc, const NMNDiscDNSDomain *new);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define _NMLOG_DOMAIN LOGD_IP6
|
||||
#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, rdisc, __VA_ARGS__)
|
||||
#define _NMLOG(level, ...) _LOG(level, _NMLOG_DOMAIN, ndisc, __VA_ARGS__)
|
||||
|
||||
#define _LOG(level, domain, self, ...) \
|
||||
G_STMT_START { \
|
||||
|
|
@ -55,14 +56,14 @@ gboolean nm_rdisc_add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDoma
|
|||
const NMLogDomain __domain = (domain); \
|
||||
\
|
||||
if (nm_logging_enabled (__level, __domain)) { \
|
||||
NMRDisc *const __self = (self); \
|
||||
NMNDisc *const __self = (self); \
|
||||
char __prefix[64]; \
|
||||
\
|
||||
_nm_log (__level, __domain, 0, \
|
||||
"%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
|
||||
(__self \
|
||||
? ({ \
|
||||
const char *__ifname = nm_rdisc_get_ifname (__self); \
|
||||
const char *__ifname = nm_ndisc_get_ifname (__self); \
|
||||
nm_sprintf_buf (__prefix, "%s[%p,%s%s%s]", \
|
||||
_NMLOG_PREFIX_NAME, __self, \
|
||||
NM_PRINT_FMT_QUOTE_STRING (__ifname)); \
|
||||
|
|
@ -74,4 +75,4 @@ gboolean nm_rdisc_add_dns_domain (NMRDisc *rdisc, const NMRDiscDNSDoma
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NETWORKMANAGER_RDISC_PRIVATE_H__ */
|
||||
#endif /* __NETWORKMANAGER_NDISC_PRIVATE_H__ */
|
||||
File diff suppressed because it is too large
Load diff
189
src/ndisc/nm-ndisc.h
Normal file
189
src/ndisc/nm-ndisc.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-ndisc.h - Perform IPv6 neighbor discovery
|
||||
*
|
||||
* 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) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_NDISC_H__
|
||||
#define __NETWORKMANAGER_NDISC_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#define NM_TYPE_NDISC (nm_ndisc_get_type ())
|
||||
#define NM_NDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_NDISC, NMNDisc))
|
||||
#define NM_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_NDISC, NMNDiscClass))
|
||||
#define NM_IS_NDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_NDISC))
|
||||
#define NM_IS_NDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_NDISC))
|
||||
#define NM_NDISC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_NDISC, NMNDiscClass))
|
||||
|
||||
#define NM_NDISC_PLATFORM "platform"
|
||||
#define NM_NDISC_IFINDEX "ifindex"
|
||||
#define NM_NDISC_IFNAME "ifname"
|
||||
#define NM_NDISC_NETWORK_ID "network-id"
|
||||
#define NM_NDISC_ADDR_GEN_MODE "addr-gen-mode"
|
||||
#define NM_NDISC_STABLE_TYPE "stable-type"
|
||||
#define NM_NDISC_NODE_TYPE "node-type"
|
||||
#define NM_NDISC_MAX_ADDRESSES "max-addresses"
|
||||
#define NM_NDISC_ROUTER_SOLICITATIONS "router-solicitations"
|
||||
#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL "router-solicitation-interval"
|
||||
|
||||
#define NM_NDISC_CONFIG_RECEIVED "config-received"
|
||||
#define NM_NDISC_RA_TIMEOUT "ra-timeout"
|
||||
|
||||
typedef enum {
|
||||
NM_NDISC_DHCP_LEVEL_UNKNOWN,
|
||||
NM_NDISC_DHCP_LEVEL_NONE,
|
||||
NM_NDISC_DHCP_LEVEL_OTHERCONF,
|
||||
NM_NDISC_DHCP_LEVEL_MANAGED
|
||||
} NMNDiscDHCPLevel;
|
||||
|
||||
typedef enum {
|
||||
NM_NDISC_PREFERENCE_INVALID,
|
||||
NM_NDISC_PREFERENCE_LOW,
|
||||
NM_NDISC_PREFERENCE_MEDIUM,
|
||||
NM_NDISC_PREFERENCE_HIGH
|
||||
} NMNDiscPreference;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
NMNDiscPreference preference;
|
||||
} NMNDiscGateway;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint8 dad_counter;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
} NMNDiscAddress;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr network;
|
||||
guint8 plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
NMNDiscPreference preference;
|
||||
} NMNDiscRoute;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
} NMNDiscDNSServer;
|
||||
|
||||
typedef struct {
|
||||
char *domain;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
} NMNDiscDNSDomain;
|
||||
|
||||
typedef enum {
|
||||
NM_NDISC_CONFIG_DHCP_LEVEL = 1 << 0,
|
||||
NM_NDISC_CONFIG_GATEWAYS = 1 << 1,
|
||||
NM_NDISC_CONFIG_ADDRESSES = 1 << 2,
|
||||
NM_NDISC_CONFIG_ROUTES = 1 << 3,
|
||||
NM_NDISC_CONFIG_DNS_SERVERS = 1 << 4,
|
||||
NM_NDISC_CONFIG_DNS_DOMAINS = 1 << 5,
|
||||
NM_NDISC_CONFIG_HOP_LIMIT = 1 << 6,
|
||||
NM_NDISC_CONFIG_MTU = 1 << 7,
|
||||
} NMNDiscConfigMap;
|
||||
|
||||
typedef enum {
|
||||
NM_NDISC_NODE_TYPE_INVALID,
|
||||
NM_NDISC_NODE_TYPE_HOST,
|
||||
NM_NDISC_NODE_TYPE_ROUTER,
|
||||
} NMNDiscNodeType;
|
||||
|
||||
#define NM_NDISC_MAX_ADDRESSES_DEFAULT 16
|
||||
#define NM_NDISC_ROUTER_SOLICITATIONS_DEFAULT 3 /* RFC4861 MAX_RTR_SOLICITATIONS */
|
||||
#define NM_NDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4 /* RFC4861 RTR_SOLICITATION_INTERVAL */
|
||||
#define NM_NDISC_ROUTER_ADVERTISEMENTS_DEFAULT 3 /* RFC4861 MAX_INITIAL_RTR_ADVERTISEMENTS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY 3 /* RFC4861 MIN_DELAY_BETWEEN_RAS */
|
||||
#define NM_NDISC_ROUTER_ADVERT_INITIAL_INTERVAL 16 /* RFC4861 MAX_INITIAL_RTR_ADVERT_INTERVAL */
|
||||
#define NM_NDISC_ROUTER_ADVERT_DELAY_MS 500 /* RFC4861 MAX_RA_DELAY_TIME */
|
||||
#define NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL 600 /* RFC4861 MaxRtrAdvInterval default */
|
||||
#define NM_NDISC_ROUTER_LIFETIME 900 /* 1.5 * NM_NDISC_ROUTER_ADVERT_MAX_INTERVAL */
|
||||
|
||||
struct _NMNDiscPrivate;
|
||||
struct _NMNDiscDataInternal;
|
||||
|
||||
typedef struct {
|
||||
NMNDiscDHCPLevel dhcp_level;
|
||||
guint32 mtu;
|
||||
int hop_limit;
|
||||
|
||||
guint gateways_n;
|
||||
guint addresses_n;
|
||||
guint routes_n;
|
||||
guint dns_servers_n;
|
||||
guint dns_domains_n;
|
||||
|
||||
const NMNDiscGateway *gateways;
|
||||
const NMNDiscAddress *addresses;
|
||||
const NMNDiscRoute *routes;
|
||||
const NMNDiscDNSServer *dns_servers;
|
||||
const NMNDiscDNSDomain *dns_domains;
|
||||
} NMNDiscData;
|
||||
|
||||
/**
|
||||
* NMNDisc:
|
||||
*
|
||||
* Interface-specific structure that handles incoming router advertisements,
|
||||
* caches advertised items and removes them when they are obsolete.
|
||||
*/
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
union {
|
||||
struct _NMNDiscPrivate *_priv;
|
||||
struct _NMNDiscDataInternal *rdata;
|
||||
};
|
||||
} NMNDisc;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
void (*start) (NMNDisc *ndisc);
|
||||
gboolean (*send_rs) (NMNDisc *ndisc, GError **error);
|
||||
gboolean (*send_ra) (NMNDisc *ndisc, GError **error);
|
||||
} NMNDiscClass;
|
||||
|
||||
GType nm_ndisc_get_type (void);
|
||||
|
||||
int nm_ndisc_get_ifindex (NMNDisc *self);
|
||||
const char *nm_ndisc_get_ifname (NMNDisc *self);
|
||||
NMNDiscNodeType nm_ndisc_get_node_type (NMNDisc *self);
|
||||
|
||||
gboolean nm_ndisc_set_iid (NMNDisc *ndisc, const NMUtilsIPv6IfaceId iid);
|
||||
void nm_ndisc_start (NMNDisc *ndisc);
|
||||
void nm_ndisc_dad_failed (NMNDisc *ndisc, struct in6_addr *address);
|
||||
void nm_ndisc_set_config (NMNDisc *ndisc,
|
||||
const GArray *addresses,
|
||||
const GArray *dns_servers,
|
||||
const GArray *dns_domains);
|
||||
|
||||
NMPlatform *nm_ndisc_get_platform (NMNDisc *self);
|
||||
NMPNetns *nm_ndisc_netns_get (NMNDisc *self);
|
||||
gboolean nm_ndisc_netns_push (NMNDisc *self, NMPNetns **netns);
|
||||
|
||||
#endif /* __NETWORKMANAGER_NDISC_H__ */
|
||||
1
src/ndisc/tests/.gitignore
vendored
Normal file
1
src/ndisc/tests/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/ndisc
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* rdisc.c - test program
|
||||
/* ndisc.c - test program
|
||||
*
|
||||
* 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
|
||||
|
|
@ -23,32 +23,32 @@
|
|||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-fake-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
#include "nm-fake-ndisc.h"
|
||||
|
||||
#include "nm-fake-platform.h"
|
||||
|
||||
#include "nm-test-utils-core.h"
|
||||
|
||||
static NMFakeRDisc *
|
||||
rdisc_new (void)
|
||||
static NMFakeNDisc *
|
||||
ndisc_new (void)
|
||||
{
|
||||
NMRDisc *rdisc;
|
||||
NMNDisc *ndisc;
|
||||
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);
|
||||
ndisc = nm_fake_ndisc_new (ifindex, ifname);
|
||||
iid.id_u8[7] = 1;
|
||||
nm_rdisc_set_iid (rdisc, iid);
|
||||
g_assert (rdisc);
|
||||
return NM_FAKE_RDISC (rdisc);
|
||||
nm_ndisc_set_iid (ndisc, iid);
|
||||
g_assert (ndisc);
|
||||
return NM_FAKE_NDISC (ndisc);
|
||||
}
|
||||
|
||||
static void
|
||||
match_gateway (const NMRDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt, NMRDiscPreference pref)
|
||||
match_gateway (const NMNDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt, NMNDiscPreference pref)
|
||||
{
|
||||
const NMRDiscGateway *gw;
|
||||
const NMNDiscGateway *gw;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert (rdata);
|
||||
|
|
@ -64,9 +64,9 @@ match_gateway (const NMRDiscData *rdata, guint idx, const char *addr, guint32 ts
|
|||
}
|
||||
|
||||
static void
|
||||
match_address (const NMRDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt, guint32 preferred)
|
||||
match_address (const NMNDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt, guint32 preferred)
|
||||
{
|
||||
const NMRDiscAddress *a;
|
||||
const NMNDiscAddress *a;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert (rdata);
|
||||
|
|
@ -82,9 +82,9 @@ match_address (const NMRDiscData *rdata, guint idx, const char *addr, guint32 ts
|
|||
}
|
||||
|
||||
static void
|
||||
match_route (const NMRDiscData *rdata, guint idx, const char *nw, int plen, const char *gw, guint32 ts, guint32 lt, NMRDiscPreference pref)
|
||||
match_route (const NMNDiscData *rdata, guint idx, const char *nw, int plen, const char *gw, guint32 ts, guint32 lt, NMNDiscPreference pref)
|
||||
{
|
||||
const NMRDiscRoute *route;
|
||||
const NMNDiscRoute *route;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert (rdata);
|
||||
|
|
@ -103,9 +103,9 @@ match_route (const NMRDiscData *rdata, guint idx, const char *nw, int plen, cons
|
|||
}
|
||||
|
||||
static void
|
||||
match_dns_server (const NMRDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt)
|
||||
match_dns_server (const NMNDiscData *rdata, guint idx, const char *addr, guint32 ts, guint32 lt)
|
||||
{
|
||||
const NMRDiscDNSServer *dns;
|
||||
const NMNDiscDNSServer *dns;
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
|
||||
g_assert (rdata);
|
||||
|
|
@ -120,9 +120,9 @@ match_dns_server (const NMRDiscData *rdata, guint idx, const char *addr, guint32
|
|||
}
|
||||
|
||||
static void
|
||||
match_dns_domain (const NMRDiscData *rdata, guint idx, const char *domain, guint32 ts, guint32 lt)
|
||||
match_dns_domain (const NMNDiscData *rdata, guint idx, const char *domain, guint32 ts, guint32 lt)
|
||||
{
|
||||
const NMRDiscDNSDomain *dns;
|
||||
const NMNDiscDNSDomain *dns;
|
||||
|
||||
g_assert (rdata);
|
||||
g_assert_cmpint (idx, <, rdata->dns_domains_n);
|
||||
|
|
@ -145,26 +145,26 @@ typedef struct {
|
|||
} TestData;
|
||||
|
||||
static void
|
||||
test_simple_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_simple_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
{
|
||||
NMRDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
|
||||
g_assert_cmpint (changed, ==, NM_RDISC_CONFIG_DHCP_LEVEL |
|
||||
NM_RDISC_CONFIG_GATEWAYS |
|
||||
NM_RDISC_CONFIG_ADDRESSES |
|
||||
NM_RDISC_CONFIG_ROUTES |
|
||||
NM_RDISC_CONFIG_DNS_SERVERS |
|
||||
NM_RDISC_CONFIG_DNS_DOMAINS |
|
||||
NM_RDISC_CONFIG_HOP_LIMIT |
|
||||
NM_RDISC_CONFIG_MTU);
|
||||
g_assert_cmpint (rdata->dhcp_level, ==, NM_RDISC_DHCP_LEVEL_OTHERCONF);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (changed, ==, NM_NDISC_CONFIG_DHCP_LEVEL |
|
||||
NM_NDISC_CONFIG_GATEWAYS |
|
||||
NM_NDISC_CONFIG_ADDRESSES |
|
||||
NM_NDISC_CONFIG_ROUTES |
|
||||
NM_NDISC_CONFIG_DNS_SERVERS |
|
||||
NM_NDISC_CONFIG_DNS_DOMAINS |
|
||||
NM_NDISC_CONFIG_HOP_LIMIT |
|
||||
NM_NDISC_CONFIG_MTU);
|
||||
g_assert_cmpint (rdata->dhcp_level, ==, NM_NDISC_DHCP_LEVEL_OTHERCONF);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_route (rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10);
|
||||
match_dns_server (rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10);
|
||||
match_dns_domain (rdata, 0, "foobar.com", data->timestamp1, 10);
|
||||
|
||||
g_assert (nm_fake_rdisc_done (NM_FAKE_RDISC (rdisc)));
|
||||
g_assert (nm_fake_ndisc_done (NM_FAKE_NDISC (ndisc)));
|
||||
data->counter++;
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
|
@ -172,67 +172,67 @@ test_simple_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int
|
|||
static void
|
||||
test_simple (void)
|
||||
{
|
||||
NMFakeRDisc *rdisc = rdisc_new ();
|
||||
NMFakeNDisc *ndisc = ndisc_new ();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
TestData data = { g_main_loop_new (NULL, FALSE), 0, 0, now };
|
||||
guint id;
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_OTHERCONF, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_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);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", now, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix (ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server (ndisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain (ndisc, id, "foobar.com", now, 10);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (test_simple_changed),
|
||||
&data);
|
||||
|
||||
nm_rdisc_start (NM_RDISC (rdisc));
|
||||
nm_ndisc_start (NM_NDISC (ndisc));
|
||||
g_main_loop_run (data.loop);
|
||||
g_assert_cmpint (data.counter, ==, 1);
|
||||
|
||||
g_object_unref (rdisc);
|
||||
g_object_unref (ndisc);
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_everything_rs_sent (NMRDisc *rdisc, TestData *data)
|
||||
test_everything_rs_sent (NMNDisc *ndisc, TestData *data)
|
||||
{
|
||||
g_assert_cmpint (data->rs_counter, ==, 0);
|
||||
data->rs_counter++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_everything_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_everything_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
{
|
||||
NMRDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
|
||||
if (data->counter == 0) {
|
||||
g_assert_cmpint (data->rs_counter, ==, 1);
|
||||
g_assert_cmpint (changed, ==, NM_RDISC_CONFIG_DHCP_LEVEL |
|
||||
NM_RDISC_CONFIG_GATEWAYS |
|
||||
NM_RDISC_CONFIG_ADDRESSES |
|
||||
NM_RDISC_CONFIG_ROUTES |
|
||||
NM_RDISC_CONFIG_DNS_SERVERS |
|
||||
NM_RDISC_CONFIG_DNS_DOMAINS |
|
||||
NM_RDISC_CONFIG_HOP_LIMIT |
|
||||
NM_RDISC_CONFIG_MTU);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (changed, ==, NM_NDISC_CONFIG_DHCP_LEVEL |
|
||||
NM_NDISC_CONFIG_GATEWAYS |
|
||||
NM_NDISC_CONFIG_ADDRESSES |
|
||||
NM_NDISC_CONFIG_ROUTES |
|
||||
NM_NDISC_CONFIG_DNS_SERVERS |
|
||||
NM_NDISC_CONFIG_DNS_DOMAINS |
|
||||
NM_NDISC_CONFIG_HOP_LIMIT |
|
||||
NM_NDISC_CONFIG_MTU);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_route (rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 10);
|
||||
match_dns_server (rdata, 0, "2001:db8:c:c::1", data->timestamp1, 10);
|
||||
match_dns_domain (rdata, 0, "foobar.com", data->timestamp1, 10);
|
||||
} else if (data->counter == 1) {
|
||||
g_assert_cmpint (changed, ==, NM_RDISC_CONFIG_GATEWAYS |
|
||||
NM_RDISC_CONFIG_ADDRESSES |
|
||||
NM_RDISC_CONFIG_ROUTES |
|
||||
NM_RDISC_CONFIG_DNS_SERVERS |
|
||||
NM_RDISC_CONFIG_DNS_DOMAINS);
|
||||
g_assert_cmpint (changed, ==, NM_NDISC_CONFIG_GATEWAYS |
|
||||
NM_NDISC_CONFIG_ADDRESSES |
|
||||
NM_NDISC_CONFIG_ROUTES |
|
||||
NM_NDISC_CONFIG_DNS_SERVERS |
|
||||
NM_NDISC_CONFIG_DNS_DOMAINS);
|
||||
|
||||
g_assert_cmpint (rdata->gateways_n, ==, 1);
|
||||
match_gateway (rdata, 0, "fe80::2", data->timestamp1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
match_gateway (rdata, 0, "fe80::2", data->timestamp1, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (rdata->addresses_n, ==, 1);
|
||||
match_address (rdata, 0, "2001:db8:a:b::1", data->timestamp1, 10, 10);
|
||||
g_assert_cmpint (rdata->routes_n, ==, 1);
|
||||
|
|
@ -242,7 +242,7 @@ test_everything_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed
|
|||
g_assert_cmpint (rdata->dns_domains_n, ==, 1);
|
||||
match_dns_domain (rdata, 0, "foobar2.com", data->timestamp1, 10);
|
||||
|
||||
g_assert (nm_fake_rdisc_done (NM_FAKE_RDISC (rdisc)));
|
||||
g_assert (nm_fake_ndisc_done (NM_FAKE_NDISC (ndisc)));
|
||||
g_main_loop_quit (data->loop);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
|
@ -253,62 +253,62 @@ test_everything_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed
|
|||
static void
|
||||
test_everything (void)
|
||||
{
|
||||
NMFakeRDisc *rdisc = rdisc_new ();
|
||||
NMFakeNDisc *ndisc = ndisc_new ();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
TestData data = { g_main_loop_new (NULL, FALSE), 0, 0, now };
|
||||
guint id;
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_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);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", now, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix (ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server (ndisc, id, "2001:db8:c:c::1", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain (ndisc, id, "foobar.com", now, 10);
|
||||
|
||||
/* expire everything from the first RA in the second */
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_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);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", now, 0, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix (ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 0, 0, 0);
|
||||
nm_fake_ndisc_add_dns_server (ndisc, id, "2001:db8:c:c::1", now, 0);
|
||||
nm_fake_ndisc_add_dns_domain (ndisc, 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_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);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::2", now, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix (ndisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_dns_server (ndisc, id, "2001:db8:c:c::2", now, 10);
|
||||
nm_fake_ndisc_add_dns_domain (ndisc, id, "foobar2.com", now, 10);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (test_everything_changed),
|
||||
&data);
|
||||
g_signal_connect (rdisc,
|
||||
NM_FAKE_RDISC_RS_SENT,
|
||||
g_signal_connect (ndisc,
|
||||
NM_FAKE_NDISC_RS_SENT,
|
||||
G_CALLBACK (test_everything_rs_sent),
|
||||
&data);
|
||||
|
||||
nm_rdisc_start (NM_RDISC (rdisc));
|
||||
nm_ndisc_start (NM_NDISC (ndisc));
|
||||
g_main_loop_run (data.loop);
|
||||
g_assert_cmpint (data.counter, ==, 2);
|
||||
g_assert_cmpint (data.rs_counter, ==, 1);
|
||||
|
||||
g_object_unref (rdisc);
|
||||
g_object_unref (ndisc);
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_preference_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_preference_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
{
|
||||
NMRDiscConfigMap changed = changed_int;
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
|
||||
if (data->counter == 1) {
|
||||
g_assert_cmpint (changed, ==, NM_RDISC_CONFIG_GATEWAYS |
|
||||
NM_RDISC_CONFIG_ADDRESSES |
|
||||
NM_RDISC_CONFIG_ROUTES);
|
||||
g_assert_cmpint (changed, ==, NM_NDISC_CONFIG_GATEWAYS |
|
||||
NM_NDISC_CONFIG_ADDRESSES |
|
||||
NM_NDISC_CONFIG_ROUTES);
|
||||
g_assert_cmpint (rdata->gateways_n, ==, 2);
|
||||
match_gateway (rdata, 0, "fe80::2", data->timestamp1 + 1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
match_gateway (rdata, 1, "fe80::1", data->timestamp1, 10, NM_RDISC_PREFERENCE_LOW);
|
||||
match_gateway (rdata, 0, "fe80::2", data->timestamp1 + 1, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
match_gateway (rdata, 1, "fe80::1", data->timestamp1, 10, NM_NDISC_PREFERENCE_LOW);
|
||||
g_assert_cmpint (rdata->addresses_n, ==, 2);
|
||||
match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1, 10, 10);
|
||||
match_address (rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
|
|
@ -316,13 +316,13 @@ test_preference_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed
|
|||
match_route (rdata, 0, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
match_route (rdata, 1, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1, 10, 5);
|
||||
} else if (data->counter == 2) {
|
||||
g_assert_cmpint (changed, ==, NM_RDISC_CONFIG_GATEWAYS |
|
||||
NM_RDISC_CONFIG_ADDRESSES |
|
||||
NM_RDISC_CONFIG_ROUTES);
|
||||
g_assert_cmpint (changed, ==, NM_NDISC_CONFIG_GATEWAYS |
|
||||
NM_NDISC_CONFIG_ADDRESSES |
|
||||
NM_NDISC_CONFIG_ROUTES);
|
||||
|
||||
g_assert_cmpint (rdata->gateways_n, ==, 2);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1 + 2, 10, NM_RDISC_PREFERENCE_HIGH);
|
||||
match_gateway (rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_RDISC_PREFERENCE_MEDIUM);
|
||||
match_gateway (rdata, 0, "fe80::1", data->timestamp1 + 2, 10, NM_NDISC_PREFERENCE_HIGH);
|
||||
match_gateway (rdata, 1, "fe80::2", data->timestamp1 + 1, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
g_assert_cmpint (rdata->addresses_n, ==, 2);
|
||||
match_address (rdata, 0, "2001:db8:a:a::1", data->timestamp1 + 2, 10, 10);
|
||||
match_address (rdata, 1, "2001:db8:a:b::1", data->timestamp1 + 1, 10, 10);
|
||||
|
|
@ -330,7 +330,7 @@ test_preference_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed
|
|||
match_route (rdata, 0, "2001:db8:a:a::", 64, "fe80::1", data->timestamp1 + 2, 10, 15);
|
||||
match_route (rdata, 1, "2001:db8:a:b::", 64, "fe80::2", data->timestamp1 + 1, 10, 10);
|
||||
|
||||
g_assert (nm_fake_rdisc_done (NM_FAKE_RDISC (rdisc)));
|
||||
g_assert (nm_fake_ndisc_done (NM_FAKE_NDISC (ndisc)));
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
||||
|
|
@ -340,7 +340,7 @@ test_preference_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed
|
|||
static void
|
||||
test_preference (void)
|
||||
{
|
||||
NMFakeRDisc *rdisc = rdisc_new ();
|
||||
NMFakeNDisc *ndisc = ndisc_new ();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
TestData data = { g_main_loop_new (NULL, FALSE), 0, 0, now };
|
||||
guint id;
|
||||
|
|
@ -350,36 +350,36 @@ test_preference (void)
|
|||
* not get duplicates in the gateway list.
|
||||
*/
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 5);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", now, 10, NM_NDISC_PREFERENCE_LOW);
|
||||
nm_fake_ndisc_add_prefix (ndisc, 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);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_prefix (rdisc, id, "2001:db8:a:b::", 64, "fe80::2", now, 10, 10, 10);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::2", ++now, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
nm_fake_ndisc_add_prefix (ndisc, 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);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_prefix (rdisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 15);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", ++now, 10, NM_NDISC_PREFERENCE_HIGH);
|
||||
nm_fake_ndisc_add_prefix (ndisc, id, "2001:db8:a:a::", 64, "fe80::1", now, 10, 10, 15);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (test_preference_changed),
|
||||
&data);
|
||||
|
||||
nm_rdisc_start (NM_RDISC (rdisc));
|
||||
nm_ndisc_start (NM_NDISC (ndisc));
|
||||
g_main_loop_run (data.loop);
|
||||
g_assert_cmpint (data.counter, ==, 3);
|
||||
|
||||
g_object_unref (rdisc);
|
||||
g_object_unref (ndisc);
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dns_solicit_loop_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, TestData *data)
|
||||
test_dns_solicit_loop_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, TestData *data)
|
||||
{
|
||||
data->counter++;
|
||||
}
|
||||
|
|
@ -393,7 +393,7 @@ success_timeout (TestData *data)
|
|||
}
|
||||
|
||||
static void
|
||||
test_dns_solicit_loop_rs_sent (NMFakeRDisc *rdisc, TestData *data)
|
||||
test_dns_solicit_loop_rs_sent (NMFakeNDisc *ndisc, TestData *data)
|
||||
{
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
guint id;
|
||||
|
|
@ -409,11 +409,11 @@ test_dns_solicit_loop_rs_sent (NMFakeRDisc *rdisc, TestData *data)
|
|||
* DNS servers reaching 1/2 lifetime, emit a new RA without the DNS
|
||||
* servers again.
|
||||
*/
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 0, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 0, NM_NDISC_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_ndisc_add_gateway (ndisc, id, "fe80::1", now, 10, NM_NDISC_PREFERENCE_MEDIUM);
|
||||
|
||||
nm_fake_rdisc_emit_new_ras (rdisc);
|
||||
nm_fake_ndisc_emit_new_ras (ndisc);
|
||||
} else if (data->rs_counter >= 6) {
|
||||
/* Fail if we've sent too many solicitations in the past 4 seconds */
|
||||
g_assert_cmpint (now - data->first_solicit, >, 4);
|
||||
|
|
@ -426,7 +426,7 @@ test_dns_solicit_loop_rs_sent (NMFakeRDisc *rdisc, TestData *data)
|
|||
static void
|
||||
test_dns_solicit_loop (void)
|
||||
{
|
||||
NMFakeRDisc *rdisc = rdisc_new ();
|
||||
NMFakeNDisc *ndisc = ndisc_new ();
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
TestData data = { g_main_loop_new (NULL, FALSE), 0, 0, now, 0 };
|
||||
guint id;
|
||||
|
|
@ -438,25 +438,25 @@ test_dns_solicit_loop (void)
|
|||
* first.
|
||||
*/
|
||||
|
||||
id = nm_fake_rdisc_add_ra (rdisc, 1, NM_RDISC_DHCP_LEVEL_NONE, 4, 1500);
|
||||
id = nm_fake_ndisc_add_ra (ndisc, 1, NM_NDISC_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_dns_server (rdisc, id, "2001:db8:c:c::1", now, 6);
|
||||
nm_fake_ndisc_add_gateway (ndisc, id, "fe80::1", now, 10, NM_NDISC_PREFERENCE_LOW);
|
||||
nm_fake_ndisc_add_dns_server (ndisc, id, "2001:db8:c:c::1", now, 6);
|
||||
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_CONFIG_CHANGED,
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (test_dns_solicit_loop_changed),
|
||||
&data);
|
||||
g_signal_connect (rdisc,
|
||||
NM_FAKE_RDISC_RS_SENT,
|
||||
g_signal_connect (ndisc,
|
||||
NM_FAKE_NDISC_RS_SENT,
|
||||
G_CALLBACK (test_dns_solicit_loop_rs_sent),
|
||||
&data);
|
||||
|
||||
nm_rdisc_start (NM_RDISC (rdisc));
|
||||
nm_ndisc_start (NM_NDISC (ndisc));
|
||||
g_main_loop_run (data.loop);
|
||||
g_assert_cmpint (data.counter, ==, 3);
|
||||
|
||||
g_object_unref (rdisc);
|
||||
g_object_unref (ndisc);
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
|
|
@ -468,16 +468,16 @@ main (int argc, char **argv)
|
|||
nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT");
|
||||
|
||||
if (nmtst_test_quick ()) {
|
||||
g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", g_get_prgname () ?: "test-rdisc-fake");
|
||||
g_print ("Skipping test: don't run long running test %s (NMTST_DEBUG=slow)\n", g_get_prgname () ?: "test-ndisc-fake");
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
nm_fake_platform_setup ();
|
||||
|
||||
g_test_add_func ("/rdisc/simple", test_simple);
|
||||
g_test_add_func ("/rdisc/everything-changed", test_everything);
|
||||
g_test_add_func ("/rdisc/preference-changed", test_preference);
|
||||
g_test_add_func ("/rdisc/dns-solicit-loop", test_dns_solicit_loop);
|
||||
g_test_add_func ("/ndisc/simple", test_simple);
|
||||
g_test_add_func ("/ndisc/everything-changed", test_everything);
|
||||
g_test_add_func ("/ndisc/preference-changed", test_preference);
|
||||
g_test_add_func ("/ndisc/dns-solicit-loop", test_dns_solicit_loop);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* rdisc.c - test program
|
||||
/* ndisc.c - test program
|
||||
*
|
||||
* 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
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-lndp-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
#include "nm-lndp-ndisc.h"
|
||||
|
||||
#include "nm-linux-platform.h"
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ int
|
|||
main (int argc, char **argv)
|
||||
{
|
||||
GMainLoop *loop;
|
||||
NMRDisc *rdisc;
|
||||
NMNDisc *ndisc;
|
||||
int ifindex = 1;
|
||||
const char *ifname;
|
||||
NMUtilsIPv6IfaceId iid = { };
|
||||
|
|
@ -61,25 +61,26 @@ main (int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET,
|
||||
ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET,
|
||||
ifindex,
|
||||
ifname,
|
||||
NM_UTILS_STABLE_TYPE_UUID,
|
||||
"8ce666e8-d34d-4fb1-b858-f15a7al28086",
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
|
||||
NM_NDISC_NODE_TYPE_HOST,
|
||||
&error);
|
||||
if (!rdisc) {
|
||||
g_print ("Failed to create NMRDisc instance: %s\n", error->message);
|
||||
if (!ndisc) {
|
||||
g_print ("Failed to create NMNDisc instance: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
iid.id_u8[7] = 1;
|
||||
nm_rdisc_set_iid (rdisc, iid);
|
||||
nm_rdisc_start (rdisc);
|
||||
nm_ndisc_set_iid (ndisc, iid);
|
||||
nm_ndisc_start (ndisc);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
g_clear_object (&rdisc);
|
||||
g_clear_object (&ndisc);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -3511,14 +3511,15 @@ nm_utils_lifetime_get (guint32 timestamp,
|
|||
|
||||
nm_assert (now >= 0);
|
||||
|
||||
if (lifetime == 0) {
|
||||
if (timestamp == 0 && lifetime == 0) {
|
||||
/* We treat lifetime==0 && timestamp == 0 addresses as permanent addresses to allow easy
|
||||
* creation of such addresses (without requiring to set the lifetime fields to
|
||||
* NM_PLATFORM_LIFETIME_PERMANENT). The real lifetime==0 addresses (E.g. DHCP6 telling us
|
||||
* to drop an address will have timestamp set.
|
||||
*/
|
||||
*out_lifetime = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
*out_preferred = NM_PLATFORM_LIFETIME_PERMANENT;
|
||||
|
||||
/* We treat lifetime==0 as permanent addresses to allow easy creation of such addresses
|
||||
* (without requiring to set the lifetime fields to NM_PLATFORM_LIFETIME_PERMANENT).
|
||||
* In that case we also expect that the other fields (timestamp and preferred) are left unset. */
|
||||
g_return_val_if_fail (timestamp == 0 && preferred == 0, TRUE);
|
||||
g_return_val_if_fail (preferred == 0, TRUE);
|
||||
} else {
|
||||
if (now <= 0)
|
||||
now = nm_utils_get_monotonic_timestamp_s ();
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ extern unsigned int if_nametoindex (const char *__ifname);
|
|||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-linux-platform.h"
|
||||
#include "nm-dhcp-manager.h"
|
||||
#include "nm-rdisc.h"
|
||||
#include "nm-lndp-rdisc.h"
|
||||
#include "nm-ndisc.h"
|
||||
#include "nm-lndp-ndisc.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "systemd/nm-sd.h"
|
||||
|
|
@ -146,10 +146,10 @@ dhcp4_state_changed (NMDhcpClient *client,
|
|||
}
|
||||
|
||||
static void
|
||||
rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_int, gpointer user_data)
|
||||
ndisc_config_changed (NMNDisc *ndisc, const NMNDiscData *rdata, guint changed_int, gpointer user_data)
|
||||
{
|
||||
NMRDiscConfigMap changed = changed_int;
|
||||
static NMIP6Config *rdisc_config = NULL;
|
||||
NMNDiscConfigMap changed = changed_int;
|
||||
static NMIP6Config *ndisc_config = NULL;
|
||||
NMIP6Config *existing;
|
||||
static int system_support = -1;
|
||||
guint32 ifa_flags = 0x00;
|
||||
|
|
@ -176,30 +176,30 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
}
|
||||
|
||||
existing = nm_ip6_config_capture (gl.ifindex, FALSE, global_opt.tempaddr);
|
||||
if (rdisc_config)
|
||||
nm_ip6_config_subtract (existing, rdisc_config);
|
||||
if (ndisc_config)
|
||||
nm_ip6_config_subtract (existing, ndisc_config);
|
||||
else
|
||||
rdisc_config = nm_ip6_config_new (gl.ifindex);
|
||||
ndisc_config = nm_ip6_config_new (gl.ifindex);
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_GATEWAYS) {
|
||||
/* Use the first gateway as ordered in router discovery cache. */
|
||||
if (changed & NM_NDISC_CONFIG_GATEWAYS) {
|
||||
/* Use the first gateway as ordered in neighbor discovery cache. */
|
||||
if (rdata->gateways_n)
|
||||
nm_ip6_config_set_gateway (rdisc_config, &rdata->gateways[0].address);
|
||||
nm_ip6_config_set_gateway (ndisc_config, &rdata->gateways[0].address);
|
||||
else
|
||||
nm_ip6_config_set_gateway (rdisc_config, NULL);
|
||||
nm_ip6_config_set_gateway (ndisc_config, NULL);
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from router discovery cache. */
|
||||
nm_ip6_config_reset_addresses (rdisc_config);
|
||||
if (changed & NM_NDISC_CONFIG_ADDRESSES) {
|
||||
/* Rebuild address list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_addresses (ndisc_config);
|
||||
|
||||
/* rdisc->addresses contains at most max_addresses entries.
|
||||
/* ndisc->addresses contains at most max_addresses entries.
|
||||
* This is different from what the kernel does, which
|
||||
* also counts static and temporary addresses when checking
|
||||
* max_addresses.
|
||||
**/
|
||||
for (i = 0; i < rdata->addresses_n; i++) {
|
||||
const NMRDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
const NMNDiscAddress *discovered_address = &rdata->addresses[i];
|
||||
NMPlatformIP6Address address;
|
||||
|
||||
memset (&address, 0, sizeof (address));
|
||||
|
|
@ -210,52 +210,52 @@ rdisc_config_changed (NMRDisc *rdisc, const NMRDiscData *rdata, guint changed_in
|
|||
address.preferred = discovered_address->preferred;
|
||||
if (address.preferred > address.lifetime)
|
||||
address.preferred = address.lifetime;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_RDISC;
|
||||
address.addr_source = NM_IP_CONFIG_SOURCE_NDISC;
|
||||
address.n_ifa_flags = ifa_flags;
|
||||
|
||||
nm_ip6_config_add_address (rdisc_config, &address);
|
||||
nm_ip6_config_add_address (ndisc_config, &address);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from router discovery cache. */
|
||||
nm_ip6_config_reset_routes (rdisc_config);
|
||||
if (changed & NM_NDISC_CONFIG_ROUTES) {
|
||||
/* Rebuild route list from neighbor discovery cache. */
|
||||
nm_ip6_config_reset_routes (ndisc_config);
|
||||
|
||||
for (i = 0; i < rdata->routes_n; i++) {
|
||||
const NMRDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMNDiscRoute *discovered_route = &rdata->routes[i];
|
||||
const NMPlatformIP6Route route = {
|
||||
.network = discovered_route->network,
|
||||
.plen = discovered_route->plen,
|
||||
.gateway = discovered_route->gateway,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_RDISC,
|
||||
.rt_source = NM_IP_CONFIG_SOURCE_NDISC,
|
||||
.metric = global_opt.priority_v6,
|
||||
};
|
||||
|
||||
nm_ip6_config_add_route (rdisc_config, &route);
|
||||
nm_ip6_config_add_route (ndisc_config, &route);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_DHCP_LEVEL) {
|
||||
if (changed & NM_NDISC_CONFIG_DHCP_LEVEL) {
|
||||
/* Unsupported until systemd DHCPv6 is ready */
|
||||
}
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_HOP_LIMIT)
|
||||
if (changed & NM_NDISC_CONFIG_HOP_LIMIT)
|
||||
nm_platform_sysctl_set_ip6_hop_limit_safe (NM_PLATFORM_GET, global_opt.ifname, rdata->hop_limit);
|
||||
|
||||
if (changed & NM_RDISC_CONFIG_MTU) {
|
||||
if (changed & NM_NDISC_CONFIG_MTU) {
|
||||
char val[16];
|
||||
|
||||
g_snprintf (val, sizeof (val), "%d", rdata->mtu);
|
||||
nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val);
|
||||
}
|
||||
|
||||
nm_ip6_config_merge (existing, rdisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||
nm_ip6_config_merge (existing, ndisc_config, NM_IP_CONFIG_MERGE_DEFAULT);
|
||||
if (!nm_ip6_config_commit (existing, gl.ifindex, TRUE))
|
||||
_LOGW (LOGD_IP6, "failed to apply IPv6 config");
|
||||
}
|
||||
|
||||
static void
|
||||
rdisc_ra_timeout (NMRDisc *rdisc, gpointer user_data)
|
||||
ndisc_ra_timeout (NMNDisc *ndisc, gpointer user_data)
|
||||
{
|
||||
if (global_opt.slaac_required) {
|
||||
_LOGW (LOGD_IP6, "IPv6 timed out or failed, quitting...");
|
||||
|
|
@ -337,13 +337,13 @@ ip6_address_changed (NMPlatform *platform,
|
|||
int iface,
|
||||
NMPlatformIP6Address *addr,
|
||||
int change_type_i,
|
||||
NMRDisc *rdisc)
|
||||
NMNDisc *ndisc)
|
||||
{
|
||||
const NMPlatformSignalChangeType change_type = change_type_i;
|
||||
|
||||
if ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->n_ifa_flags & IFA_F_DADFAILED)
|
||||
|| (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->n_ifa_flags & IFA_F_TENTATIVE))
|
||||
nm_rdisc_dad_failed (rdisc, &addr->address);
|
||||
nm_ndisc_dad_failed (ndisc, &addr->address);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -354,7 +354,7 @@ main (int argc, char *argv[])
|
|||
gboolean wrote_pidfile = FALSE;
|
||||
gs_free char *pidfile = NULL;
|
||||
gs_unref_object NMDhcpClient *dhcp4_client = NULL;
|
||||
gs_unref_object NMRDisc *rdisc = NULL;
|
||||
gs_unref_object NMNDisc *ndisc = NULL;
|
||||
GByteArray *hwaddr = NULL;
|
||||
size_t hwaddr_len = 0;
|
||||
gconstpointer tmp;
|
||||
|
|
@ -502,13 +502,15 @@ main (int argc, char *argv[])
|
|||
stable_type = (global_opt.stable_id[0] - '0');
|
||||
stable_id = &global_opt.stable_id[2];
|
||||
}
|
||||
rdisc = nm_lndp_rdisc_new (NM_PLATFORM_GET, gl.ifindex, global_opt.ifname,
|
||||
ndisc = nm_lndp_ndisc_new (NM_PLATFORM_GET, gl.ifindex, global_opt.ifname,
|
||||
stable_type, stable_id,
|
||||
global_opt.addr_gen_mode, NULL);
|
||||
g_assert (rdisc);
|
||||
global_opt.addr_gen_mode,
|
||||
NM_NDISC_NODE_TYPE_HOST,
|
||||
NULL);
|
||||
g_assert (ndisc);
|
||||
|
||||
if (iid)
|
||||
nm_rdisc_set_iid (rdisc, *iid);
|
||||
nm_ndisc_set_iid (ndisc, *iid);
|
||||
|
||||
nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra"), "1");
|
||||
nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "accept_ra_defrtr"), "0");
|
||||
|
|
@ -518,16 +520,16 @@ main (int argc, char *argv[])
|
|||
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),
|
||||
ndisc);
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_CONFIG_RECEIVED,
|
||||
G_CALLBACK (ndisc_config_changed),
|
||||
NULL);
|
||||
g_signal_connect (rdisc,
|
||||
NM_RDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (rdisc_ra_timeout),
|
||||
g_signal_connect (ndisc,
|
||||
NM_NDISC_RA_TIMEOUT,
|
||||
G_CALLBACK (ndisc_ra_timeout),
|
||||
NULL);
|
||||
nm_rdisc_start (rdisc);
|
||||
nm_ndisc_start (ndisc);
|
||||
}
|
||||
|
||||
sd_id = nm_sd_event_attach_default ();
|
||||
|
|
|
|||
|
|
@ -3404,18 +3404,6 @@ validate_activation_request (NMManager *self,
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* Not implemented yet, we want to fail early */
|
||||
if ( nm_connection_get_setting_connection (connection)
|
||||
&& nm_connection_get_setting_ip6_config (connection)
|
||||
&& !strcmp (nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG),
|
||||
NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
|
||||
g_set_error_literal (error,
|
||||
NM_MANAGER_ERROR,
|
||||
NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE,
|
||||
"Sharing IPv6 connections is not supported yet.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check whether it's a VPN or not */
|
||||
if ( nm_connection_get_setting_vpn (connection)
|
||||
|| nm_connection_is_type (connection, NM_SETTING_VPN_SETTING_NAME))
|
||||
|
|
|
|||
282
src/nm-policy.c
282
src/nm-policy.c
|
|
@ -88,6 +88,8 @@ typedef struct {
|
|||
char *orig_hostname; /* hostname at NM start time */
|
||||
char *cur_hostname; /* hostname we want to assign */
|
||||
gboolean hostname_changed; /* TRUE if NM ever set the hostname */
|
||||
|
||||
GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
|
||||
} NMPolicyPrivate;
|
||||
|
||||
struct _NMPolicy {
|
||||
|
|
@ -133,6 +135,236 @@ static void schedule_activate_all (NMPolicy *self);
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMPlatformIP6Address prefix;
|
||||
NMDevice *device; /* The requesting ("uplink") device */
|
||||
guint64 next_subnet; /* Cache of the next subnet number to be
|
||||
* assigned from this prefix */
|
||||
GHashTable *subnets; /* ifindex -> NMPlatformIP6Address */
|
||||
} IP6PrefixDelegation;
|
||||
|
||||
static void
|
||||
_clear_ip6_subnet (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
NMPlatformIP6Address *subnet = value;
|
||||
NMDevice *device = nm_manager_get_device_by_ifindex (nm_manager_get (),
|
||||
GPOINTER_TO_INT (key));
|
||||
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
/* We can not remove a subnet we already started announcing.
|
||||
* Just un-prefer it. */
|
||||
subnet->preferred = 0;
|
||||
nm_device_use_ip6_subnet (device, subnet);
|
||||
g_slice_free (NMPlatformIP6Address, subnet);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_ip6_prefix_delegation (gpointer data)
|
||||
{
|
||||
IP6PrefixDelegation *delegation = data;
|
||||
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: undelegating prefix %s/%d",
|
||||
nm_utils_inet6_ntop (&delegation->prefix.address, NULL),
|
||||
delegation->prefix.plen);
|
||||
|
||||
g_hash_table_foreach (delegation->subnets, _clear_ip6_subnet, NULL);
|
||||
g_hash_table_destroy (delegation->subnets);
|
||||
}
|
||||
|
||||
static void
|
||||
expire_ip6_delegations (NMPolicy *self)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
guint32 now = nm_utils_get_monotonic_timestamp_s ();
|
||||
IP6PrefixDelegation *delegation = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
|
||||
delegation = &g_array_index (priv->ip6_prefix_delegations,
|
||||
IP6PrefixDelegation, i);
|
||||
if (delegation->prefix.timestamp + delegation->prefix.lifetime < now)
|
||||
g_array_remove_index_fast (priv->ip6_prefix_delegations, i);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to obtain a new subnet for a particular active connection from given
|
||||
* delegated prefix, possibly reusing the existing subnet.
|
||||
* Return value of FALSE indicates no more subnets are available from
|
||||
* this prefix (and other prefix should be used -- and requested if necessary).
|
||||
*/
|
||||
static gboolean
|
||||
ip6_subnet_from_delegation (IP6PrefixDelegation *delegation, NMDevice *device)
|
||||
{
|
||||
NMPlatformIP6Address *subnet;
|
||||
int ifindex = nm_device_get_ifindex (device);
|
||||
|
||||
subnet = g_hash_table_lookup (delegation->subnets, GINT_TO_POINTER (ifindex));
|
||||
if (!subnet) {
|
||||
/* Check for out-of-prefixes condition. */
|
||||
if (delegation->next_subnet >= (1 << (64 - delegation->prefix.plen))) {
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: no more prefixes in %s/%d",
|
||||
nm_utils_inet6_ntop (&delegation->prefix.address, NULL),
|
||||
delegation->prefix.plen);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Allocate a new subnet. */
|
||||
subnet = g_slice_new0 (NMPlatformIP6Address);
|
||||
g_hash_table_insert (delegation->subnets, GINT_TO_POINTER (ifindex), subnet);
|
||||
|
||||
subnet->plen = 64;
|
||||
subnet->address.s6_addr32[0] = delegation->prefix.address.s6_addr32[0]
|
||||
| htonl (delegation->next_subnet >> 32);
|
||||
subnet->address.s6_addr32[1] = delegation->prefix.address.s6_addr32[1]
|
||||
| htonl (delegation->next_subnet);
|
||||
|
||||
/* Out subnet pool management is pretty unsophisticated. We only add
|
||||
* the subnets and index them by ifindex. That keeps the implementation
|
||||
* simple and the dead entries make it easy to reuse the same subnet on
|
||||
* subsequent activations. On the other hand they may waste the subnet
|
||||
* space. */
|
||||
delegation->next_subnet++;
|
||||
}
|
||||
|
||||
subnet->timestamp = delegation->prefix.timestamp;
|
||||
subnet->lifetime = delegation->prefix.lifetime;
|
||||
subnet->preferred = delegation->prefix.preferred;
|
||||
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: %s allocated from a /%d prefix on %s",
|
||||
nm_utils_inet6_ntop (&subnet->address, NULL),
|
||||
delegation->prefix.plen,
|
||||
nm_device_get_iface (device));
|
||||
|
||||
nm_device_use_ip6_subnet (device, subnet);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to obtain a subnet from each prefix delegated to given requesting
|
||||
* ("uplink") device and assign it to the downlink device.
|
||||
* Requests a new prefix if no subnet could be found.
|
||||
*/
|
||||
static void
|
||||
ip6_subnet_from_device (NMPolicy *self, NMDevice *from_device, NMDevice *device)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
IP6PrefixDelegation *delegation = NULL;
|
||||
gboolean got_subnet = FALSE;
|
||||
int have_prefixes = 0;
|
||||
int i;
|
||||
|
||||
expire_ip6_delegations (self);
|
||||
|
||||
for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
|
||||
delegation = &g_array_index (priv->ip6_prefix_delegations,
|
||||
IP6PrefixDelegation, i);
|
||||
|
||||
if (delegation->device != from_device)
|
||||
continue;
|
||||
|
||||
if (ip6_subnet_from_delegation (delegation, device))
|
||||
got_subnet = TRUE;
|
||||
have_prefixes++;
|
||||
}
|
||||
|
||||
if (!got_subnet) {
|
||||
_LOGI (LOGD_IP6, "ipv6-pd: none of %d prefixes of %s can be shared on %s",
|
||||
have_prefixes, nm_device_get_iface (from_device),
|
||||
nm_device_get_iface (device));
|
||||
nm_device_request_ip6_prefixes (from_device, have_prefixes + 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_remove_device_prefix_delegations (NMPolicy *self, NMDevice *device)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
IP6PrefixDelegation *delegation = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
|
||||
delegation = &g_array_index (priv->ip6_prefix_delegations,
|
||||
IP6PrefixDelegation, i);
|
||||
if (delegation->device == device)
|
||||
g_array_remove_index_fast (priv->ip6_prefix_delegations, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_ip6_prefix_delegated (NMDevice *device,
|
||||
NMPlatformIP6Address *prefix,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF (priv);
|
||||
IP6PrefixDelegation *delegation = NULL;
|
||||
const GSList *connections, *iter;
|
||||
int i;
|
||||
|
||||
_LOGI (LOGD_IP6, "ipv6-pd: received a prefix %s/%d from %s",
|
||||
nm_utils_inet6_ntop (&prefix->address, NULL),
|
||||
prefix->plen,
|
||||
nm_device_get_iface (device));
|
||||
|
||||
expire_ip6_delegations (self);
|
||||
|
||||
for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
|
||||
/* Look for an already known prefix to update. */
|
||||
delegation = &g_array_index (priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
|
||||
if (IN6_ARE_ADDR_EQUAL (&delegation->prefix.address, &prefix->address))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == priv->ip6_prefix_delegations->len) {
|
||||
/* Allocate a delegation delegation for new prefix. */
|
||||
g_array_set_size (priv->ip6_prefix_delegations, i + 1);
|
||||
delegation = &g_array_index (priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
|
||||
delegation->subnets = g_hash_table_new (NULL, NULL);
|
||||
delegation->next_subnet = 0;
|
||||
}
|
||||
|
||||
delegation->device = device;
|
||||
delegation->prefix = *prefix;
|
||||
|
||||
/* The newly activated connections are added to the list beginning,
|
||||
* so traversing it from the beginning makes it likely for newly
|
||||
* activated connections that have no subnet assigned to be served
|
||||
* first. That is a simple yet fair policy, which is good. */
|
||||
connections = nm_manager_get_active_connections (priv->manager);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *to_device = nm_active_connection_get_device (iter->data);
|
||||
|
||||
if (nm_device_needs_ip6_subnet (to_device))
|
||||
ip6_subnet_from_delegation (delegation, to_device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_ip6_subnet_needed (NMDevice *device,
|
||||
gpointer user_data)
|
||||
{
|
||||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF (priv);
|
||||
|
||||
_LOGD (LOGD_IP6, "ipv6-pd: %s needs a subnet",
|
||||
nm_device_get_iface (device));
|
||||
|
||||
if (!priv->default_device6) {
|
||||
/* We request the prefixes when the default IPv6 device is set. */
|
||||
_LOGI (LOGD_IP6, "ipv6-pd: no device to obtain a subnet to share on %s from",
|
||||
nm_device_get_iface (device));
|
||||
return;
|
||||
}
|
||||
ip6_subnet_from_device (self, priv->default_device6, device);
|
||||
nm_device_copy_ip6_dns_config (device, priv->default_device6);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static NMDevice *
|
||||
get_best_ip4_device (NMPolicy *self, gboolean fully_activated)
|
||||
{
|
||||
|
|
@ -544,6 +776,21 @@ get_best_ip6_config (NMPolicy *self,
|
|||
out_vpn);
|
||||
}
|
||||
|
||||
static void
|
||||
update_ip6_dns_delegation (NMPolicy *self)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
const GSList *connections, *iter;
|
||||
|
||||
connections = nm_manager_get_active_connections (priv->manager);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *device = nm_active_connection_get_device (iter->data);
|
||||
|
||||
if (device && nm_device_needs_ip6_subnet (device))
|
||||
nm_device_copy_ip6_dns_config (device, priv->default_device6);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr)
|
||||
{
|
||||
|
|
@ -562,6 +809,24 @@ update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr)
|
|||
*/
|
||||
nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, dns_type);
|
||||
}
|
||||
|
||||
update_ip6_dns_delegation (self);
|
||||
}
|
||||
|
||||
static void
|
||||
update_ip6_prefix_delegation (NMPolicy *self)
|
||||
{
|
||||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
const GSList *connections, *iter;
|
||||
|
||||
/* There's new default IPv6 connection, try to get a prefix for everyone. */
|
||||
connections = nm_manager_get_active_connections (priv->manager);
|
||||
for (iter = connections; iter; iter = g_slist_next (iter)) {
|
||||
NMDevice *device = nm_active_connection_get_device (iter->data);
|
||||
|
||||
if (device && nm_device_needs_ip6_subnet (device))
|
||||
ip6_subnet_from_device (self, priv->default_device6, device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -615,8 +880,10 @@ update_ip6_routing (NMPolicy *self, gboolean force_update)
|
|||
|
||||
if (default_device6 == priv->default_device6)
|
||||
return;
|
||||
|
||||
priv->default_device6 = default_device6;
|
||||
|
||||
update_ip6_prefix_delegation (self);
|
||||
|
||||
connection = nm_active_connection_get_applied_connection (best_ac);
|
||||
_LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv6 routing and DNS",
|
||||
nm_connection_get_id (connection), ip_iface);
|
||||
|
|
@ -1276,6 +1543,7 @@ device_state_changed (NMDevice *device,
|
|||
}
|
||||
}
|
||||
}
|
||||
ip6_remove_device_prefix_delegations (self, device);
|
||||
break;
|
||||
case NM_DEVICE_STATE_DISCONNECTED:
|
||||
/* Reset retry counts for a device's connections when carrier on; if cable
|
||||
|
|
@ -1394,6 +1662,8 @@ device_ip6_config_changed (NMDevice *device,
|
|||
nm_dns_manager_end_updates (priv->dns_manager, __func__);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
device_autoconnect_changed (NMDevice *device,
|
||||
GParamSpec *pspec,
|
||||
|
|
@ -1432,6 +1702,8 @@ devices_list_register (NMPolicy *self, NMDevice *device)
|
|||
g_signal_connect_after (device, NM_DEVICE_STATE_CHANGED, (GCallback) device_state_changed, priv);
|
||||
g_signal_connect (device, NM_DEVICE_IP4_CONFIG_CHANGED, (GCallback) device_ip4_config_changed, priv);
|
||||
g_signal_connect (device, NM_DEVICE_IP6_CONFIG_CHANGED, (GCallback) device_ip6_config_changed, priv);
|
||||
g_signal_connect (device, NM_DEVICE_IP6_PREFIX_DELEGATED, (GCallback) device_ip6_prefix_delegated, priv);
|
||||
g_signal_connect (device, NM_DEVICE_IP6_SUBNET_NEEDED, (GCallback) device_ip6_subnet_needed, priv);
|
||||
g_signal_connect (device, "notify::" NM_DEVICE_AUTOCONNECT, (GCallback) device_autoconnect_changed, priv);
|
||||
g_signal_connect (device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, (GCallback) device_recheck_auto_activate, priv);
|
||||
}
|
||||
|
|
@ -1458,6 +1730,10 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data)
|
|||
NMPolicyPrivate *priv = user_data;
|
||||
NMPolicy *self = _PRIV_TO_SELF (priv);
|
||||
|
||||
/* XXX is this needed? The delegations are cleaned up
|
||||
* on transition to deactivated too. */
|
||||
ip6_remove_device_prefix_delegations (self, device);
|
||||
|
||||
/* Clear any idle callbacks for this device */
|
||||
clear_pending_activate_check (self, device);
|
||||
|
||||
|
|
@ -1886,6 +2162,8 @@ nm_policy_init (NMPolicy *self)
|
|||
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
|
||||
|
||||
priv->devices = g_hash_table_new (NULL, NULL);
|
||||
priv->ip6_prefix_delegations = g_array_new (FALSE, FALSE, sizeof (IP6PrefixDelegation));
|
||||
g_array_set_clear_func (priv->ip6_prefix_delegations, clear_ip6_prefix_delegation);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2006,6 +2284,8 @@ dispose (GObject *object)
|
|||
g_signal_handlers_disconnect_by_data (priv->manager, priv);
|
||||
}
|
||||
|
||||
g_array_free (priv->ip6_prefix_delegations, TRUE);
|
||||
|
||||
nm_assert (NM_IS_MANAGER (priv->manager));
|
||||
|
||||
G_OBJECT_CLASS (nm_policy_parent_class)->dispose (object);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ typedef enum {
|
|||
NM_IP_CONFIG_SOURCE_WWAN,
|
||||
NM_IP_CONFIG_SOURCE_VPN,
|
||||
NM_IP_CONFIG_SOURCE_DHCP,
|
||||
NM_IP_CONFIG_SOURCE_RDISC,
|
||||
NM_IP_CONFIG_SOURCE_NDISC,
|
||||
NM_IP_CONFIG_SOURCE_USER,
|
||||
} NMIPConfigSource;
|
||||
|
||||
|
|
|
|||
|
|
@ -2579,7 +2579,7 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
|
|||
|
||||
/* Try to write the entire value three times if a partial write occurs */
|
||||
errsv = 0;
|
||||
for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) {
|
||||
for (tries = 0, nwrote = 0; tries < 3 && nwrote < len - 1; tries++) {
|
||||
nwrote = write (fd, actual, len);
|
||||
if (nwrote == -1) {
|
||||
errsv = errno;
|
||||
|
|
@ -2593,12 +2593,12 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
|
|||
if (nwrote == -1 && errsv != EEXIST) {
|
||||
_LOGE ("sysctl: failed to set '%s' to '%s': (%d) %s",
|
||||
path, value, errsv, strerror (errsv));
|
||||
} else if (nwrote < len) {
|
||||
} else if (nwrote < len - 1) {
|
||||
_LOGE ("sysctl: failed to set '%s' to '%s' after three attempts",
|
||||
path, value);
|
||||
}
|
||||
|
||||
if (nwrote != len) {
|
||||
if (nwrote < len - 1) {
|
||||
if (close (fd) != 0) {
|
||||
if (errsv != 0)
|
||||
errno = errsv;
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source)
|
|||
return RTPROT_KERNEL;
|
||||
case NM_IP_CONFIG_SOURCE_DHCP:
|
||||
return RTPROT_DHCP;
|
||||
case NM_IP_CONFIG_SOURCE_RDISC:
|
||||
case NM_IP_CONFIG_SOURCE_NDISC:
|
||||
return RTPROT_RA;
|
||||
|
||||
default:
|
||||
|
|
@ -501,7 +501,7 @@ nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source)
|
|||
return NM_IP_CONFIG_SOURCE_KERNEL;
|
||||
|
||||
case NM_IP_CONFIG_SOURCE_RTPROT_RA:
|
||||
return NM_IP_CONFIG_SOURCE_RDISC;
|
||||
return NM_IP_CONFIG_SOURCE_NDISC;
|
||||
|
||||
case NM_IP_CONFIG_SOURCE_RTPROT_DHCP:
|
||||
return NM_IP_CONFIG_SOURCE_DHCP;
|
||||
|
|
@ -538,7 +538,7 @@ nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize
|
|||
case NM_IP_CONFIG_SOURCE_WWAN: s = "wwan"; break;
|
||||
case NM_IP_CONFIG_SOURCE_VPN: s = "vpn"; break;
|
||||
case NM_IP_CONFIG_SOURCE_DHCP: s = "dhcp"; break;
|
||||
case NM_IP_CONFIG_SOURCE_RDISC: s = "rdisc"; break;
|
||||
case NM_IP_CONFIG_SOURCE_NDISC: s = "ndisc"; break;
|
||||
case NM_IP_CONFIG_SOURCE_USER: s = "user"; break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1,170 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/* nm-rdisc.h - Perform IPv6 router discovery
|
||||
*
|
||||
* 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) 2013 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef __NETWORKMANAGER_RDISC_H__
|
||||
#define __NETWORKMANAGER_RDISC_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "nm-setting-ip6-config.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#define NM_TYPE_RDISC (nm_rdisc_get_type ())
|
||||
#define NM_RDISC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_RDISC, NMRDisc))
|
||||
#define NM_RDISC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_RDISC, NMRDiscClass))
|
||||
#define NM_IS_RDISC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_RDISC))
|
||||
#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_IFINDEX "ifindex"
|
||||
#define NM_RDISC_IFNAME "ifname"
|
||||
#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"
|
||||
|
||||
typedef enum {
|
||||
NM_RDISC_DHCP_LEVEL_UNKNOWN,
|
||||
NM_RDISC_DHCP_LEVEL_NONE,
|
||||
NM_RDISC_DHCP_LEVEL_OTHERCONF,
|
||||
NM_RDISC_DHCP_LEVEL_MANAGED
|
||||
} NMRDiscDHCPLevel;
|
||||
|
||||
typedef enum {
|
||||
NM_RDISC_PREFERENCE_INVALID,
|
||||
NM_RDISC_PREFERENCE_LOW,
|
||||
NM_RDISC_PREFERENCE_MEDIUM,
|
||||
NM_RDISC_PREFERENCE_HIGH
|
||||
} NMRDiscPreference;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
NMRDiscPreference preference;
|
||||
} NMRDiscGateway;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint8 dad_counter;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
guint32 preferred;
|
||||
} NMRDiscAddress;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr network;
|
||||
guint8 plen;
|
||||
struct in6_addr gateway;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
NMRDiscPreference preference;
|
||||
} NMRDiscRoute;
|
||||
|
||||
typedef struct {
|
||||
struct in6_addr address;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
} NMRDiscDNSServer;
|
||||
|
||||
typedef struct {
|
||||
char *domain;
|
||||
guint32 timestamp;
|
||||
guint32 lifetime;
|
||||
} NMRDiscDNSDomain;
|
||||
|
||||
typedef enum {
|
||||
NM_RDISC_CONFIG_DHCP_LEVEL = 1 << 0,
|
||||
NM_RDISC_CONFIG_GATEWAYS = 1 << 1,
|
||||
NM_RDISC_CONFIG_ADDRESSES = 1 << 2,
|
||||
NM_RDISC_CONFIG_ROUTES = 1 << 3,
|
||||
NM_RDISC_CONFIG_DNS_SERVERS = 1 << 4,
|
||||
NM_RDISC_CONFIG_DNS_DOMAINS = 1 << 5,
|
||||
NM_RDISC_CONFIG_HOP_LIMIT = 1 << 6,
|
||||
NM_RDISC_CONFIG_MTU = 1 << 7,
|
||||
} NMRDiscConfigMap;
|
||||
|
||||
#define NM_RDISC_MAX_ADDRESSES_DEFAULT 16
|
||||
#define NM_RDISC_ROUTER_SOLICITATIONS_DEFAULT 3
|
||||
#define NM_RDISC_ROUTER_SOLICITATION_INTERVAL_DEFAULT 4
|
||||
|
||||
struct _NMRDiscPrivate;
|
||||
struct _NMRDiscDataInternal;
|
||||
|
||||
typedef struct {
|
||||
NMRDiscDHCPLevel dhcp_level;
|
||||
guint32 mtu;
|
||||
int hop_limit;
|
||||
|
||||
guint gateways_n;
|
||||
guint addresses_n;
|
||||
guint routes_n;
|
||||
guint dns_servers_n;
|
||||
guint dns_domains_n;
|
||||
|
||||
const NMRDiscGateway *gateways;
|
||||
const NMRDiscAddress *addresses;
|
||||
const NMRDiscRoute *routes;
|
||||
const NMRDiscDNSServer *dns_servers;
|
||||
const NMRDiscDNSDomain *dns_domains;
|
||||
} NMRDiscData;
|
||||
|
||||
/**
|
||||
* NMRDisc:
|
||||
*
|
||||
* Interface-specific structure that handles incoming router advertisements,
|
||||
* caches advertised items and removes them when they are obsolete.
|
||||
*/
|
||||
typedef struct {
|
||||
GObject parent;
|
||||
union {
|
||||
struct _NMRDiscPrivate *_priv;
|
||||
struct _NMRDiscDataInternal *rdata;
|
||||
};
|
||||
} NMRDisc;
|
||||
|
||||
typedef struct {
|
||||
GObjectClass parent;
|
||||
|
||||
void (*start) (NMRDisc *rdisc);
|
||||
gboolean (*send_rs) (NMRDisc *rdisc, GError **error);
|
||||
} NMRDiscClass;
|
||||
|
||||
GType nm_rdisc_get_type (void);
|
||||
|
||||
int nm_rdisc_get_ifindex (NMRDisc *self);
|
||||
const char *nm_rdisc_get_ifname (NMRDisc *self);
|
||||
|
||||
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__ */
|
||||
1
src/rdisc/tests/.gitignore
vendored
1
src/rdisc/tests/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
/rdisc
|
||||
|
|
@ -1381,7 +1381,7 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
char *route6_path = NULL;
|
||||
gs_free char *dns_options_free = NULL;
|
||||
const char *dns_options = NULL;
|
||||
gboolean ipv6init, ipv6forwarding, ipv6_autoconf, dhcp6 = FALSE;
|
||||
gboolean ipv6init, ipv6forwarding, dhcp6 = FALSE;
|
||||
char *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
|
||||
char *ipv6addr, *ipv6addr_secondaries;
|
||||
char **list = NULL, **iter;
|
||||
|
|
@ -1392,7 +1392,6 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
gboolean ip6_privacy = FALSE, ip6_privacy_prefer_public_ip;
|
||||
NMSettingIP6ConfigPrivacy ip6_privacy_val;
|
||||
NMSettingIP6ConfigAddrGenMode addr_gen_mode;
|
||||
char *tmp;
|
||||
|
||||
s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
|
||||
|
||||
|
|
@ -1455,10 +1454,12 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
method = NM_SETTING_IP6_CONFIG_METHOD_IGNORE; /* IPv6 is disabled */
|
||||
else {
|
||||
ipv6forwarding = svGetValueBoolean (ifcfg, "IPV6FORWARDING", FALSE);
|
||||
ipv6_autoconf = svGetValueBoolean (ifcfg, "IPV6_AUTOCONF", !ipv6forwarding);
|
||||
str_value = svGetValueString (ifcfg, "IPV6_AUTOCONF");
|
||||
dhcp6 = svGetValueBoolean (ifcfg, "DHCPV6C", FALSE);
|
||||
|
||||
if (ipv6_autoconf)
|
||||
if (!g_strcmp0 (str_value, "shared"))
|
||||
method = NM_SETTING_IP6_CONFIG_METHOD_SHARED;
|
||||
else if (svParseBoolean (str_value, !ipv6forwarding))
|
||||
method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
|
||||
else if (dhcp6)
|
||||
method = NM_SETTING_IP6_CONFIG_METHOD_DHCP;
|
||||
|
|
@ -1476,20 +1477,20 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
/* TODO - handle other methods */
|
||||
|
||||
/* Read IPv6 Privacy Extensions configuration */
|
||||
tmp = svGetValueString (ifcfg, "IPV6_PRIVACY");
|
||||
if (tmp) {
|
||||
ip6_privacy = svGetValueBoolean (ifcfg, "IPV6_PRIVACY", FALSE);
|
||||
str_value = svGetValueString (ifcfg, "IPV6_PRIVACY");
|
||||
if (str_value) {
|
||||
ip6_privacy = svParseBoolean (str_value, FALSE);
|
||||
if (!ip6_privacy)
|
||||
ip6_privacy = g_strcmp0 (tmp, "rfc4941") == 0 ||
|
||||
g_strcmp0 (tmp, "rfc3041") == 0;
|
||||
ip6_privacy = (g_strcmp0 (str_value, "rfc4941") == 0) ||
|
||||
(g_strcmp0 (str_value, "rfc3041") == 0);
|
||||
}
|
||||
ip6_privacy_prefer_public_ip = svGetValueBoolean (ifcfg, "IPV6_PRIVACY_PREFER_PUBLIC_IP", FALSE);
|
||||
ip6_privacy_val = tmp ?
|
||||
ip6_privacy_val = str_value ?
|
||||
(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 (tmp);
|
||||
g_free (str_value);
|
||||
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP_CONFIG_METHOD, method,
|
||||
|
|
@ -1574,14 +1575,14 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
}
|
||||
|
||||
/* IPv6 addressing mode configuration */
|
||||
tmp = svGetValueString (ifcfg, "IPV6_ADDR_GEN_MODE");
|
||||
if (tmp) {
|
||||
if (nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), tmp,
|
||||
str_value = svGetValueString (ifcfg, "IPV6_ADDR_GEN_MODE");
|
||||
if (str_value) {
|
||||
if (nm_utils_enum_from_str (nm_setting_ip6_config_addr_gen_mode_get_type (), str_value,
|
||||
(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);
|
||||
g_free (str_value);
|
||||
} else {
|
||||
g_object_set (s_ip6,
|
||||
NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
|
||||
|
|
@ -1590,10 +1591,10 @@ make_ip6_setting (shvarFile *ifcfg,
|
|||
}
|
||||
|
||||
/* IPv6 tokenized interface identifier */
|
||||
tmp = svGetValueString (ifcfg, "IPV6_TOKEN");
|
||||
if (tmp) {
|
||||
g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, tmp, NULL);
|
||||
g_free (tmp);
|
||||
str_value = svGetValueString (ifcfg, "IPV6_TOKEN");
|
||||
if (str_value) {
|
||||
g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_TOKEN, str_value, NULL);
|
||||
g_free (str_value);
|
||||
}
|
||||
|
||||
/* DNS servers
|
||||
|
|
|
|||
|
|
@ -2477,8 +2477,8 @@ write_ip6_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svUnsetValue (ifcfg, "DHCPV6C");
|
||||
} else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
|
||||
svSetValueString (ifcfg, "IPV6INIT", "yes");
|
||||
svSetValueString (ifcfg, "IPV6_AUTOCONF", "shared");
|
||||
svUnsetValue (ifcfg, "DHCPV6C");
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
/* Write out IP addresses */
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "nm-test-utils-core.h"
|
||||
|
||||
/* Reference implementation for nm_utils_ip6_address_clear_host_address.
|
||||
* Taken originally from set_address_masked(), src/rdisc/nm-lndp-rdisc.c
|
||||
* Taken originally from set_address_masked(), src/ndisc/nm-lndp-ndisc.c
|
||||
**/
|
||||
static void
|
||||
ip6_address_clear_host_address_reference (struct in6_addr *dst, struct in6_addr *src, guint8 plen)
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ test_nm_ip6_config_addresses_sort (void)
|
|||
nm_ip6_config_reset_addresses (config);
|
||||
ADDR_ADD("2607:f0d0:1002:51::4", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
|
||||
ADDR_ADD("2607:f0d0:1002:51::5", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
|
||||
ADDR_ADD("2607:f0d0:1002:51::6", NULL, 64, 0, NM_IP_CONFIG_SOURCE_RDISC, 0, 0, 0, IFA_F_MANAGETEMPADDR);
|
||||
ADDR_ADD("2607:f0d0:1002:51::6", NULL, 64, 0, NM_IP_CONFIG_SOURCE_NDISC, 0, 0, 0, IFA_F_MANAGETEMPADDR);
|
||||
ADDR_ADD("2607:f0d0:1002:51::3", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, IFA_F_SECONDARY);
|
||||
ADDR_ADD("2607:f0d0:1002:51::8", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, IFA_F_SECONDARY);
|
||||
ADDR_ADD("2607:f0d0:1002:51::0", NULL, 64, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, IFA_F_SECONDARY);
|
||||
|
|
@ -307,7 +307,7 @@ test_nm_ip6_config_addresses_sort (void)
|
|||
ADDR_ADD("2607:f0d0:1002:51::5", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, 0);
|
||||
ADDR_ADD("2607:f0d0:1002:51::8", NULL, 64, 0, NM_IP_CONFIG_SOURCE_USER, 0, 0, 0, IFA_F_SECONDARY);
|
||||
ADDR_ADD("2607:f0d0:1002:51::0", NULL, 64, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, IFA_F_SECONDARY);
|
||||
ADDR_ADD("2607:f0d0:1002:51::6", NULL, 64, 0, NM_IP_CONFIG_SOURCE_RDISC, 0, 0, 0, IFA_F_MANAGETEMPADDR);
|
||||
ADDR_ADD("2607:f0d0:1002:51::6", NULL, 64, 0, NM_IP_CONFIG_SOURCE_NDISC, 0, 0, 0, IFA_F_MANAGETEMPADDR);
|
||||
ADDR_ADD("fec0::1", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
|
||||
ADDR_ADD("fe80::208:74ff:feda:625c", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
|
||||
ADDR_ADD("fe80::208:74ff:feda:625d", NULL, 128, 0, NM_IP_CONFIG_SOURCE_KERNEL, 0, 0, 0, 0);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue