nm-policy.c 88.7 KB
Newer Older
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
Dan Williams's avatar
Dan Williams committed
2 3 4 5 6 7 8 9 10 11 12 13
/* NetworkManager -- Network link manager
 *
 * 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 of the License, 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.
 *
14 15 16
 * 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.
Dan Williams's avatar
Dan Williams committed
17
 *
18
 * Copyright (C) 2004 - 2013 Red Hat, Inc.
19
 * Copyright (C) 2007 - 2008 Novell, Inc.
Dan Williams's avatar
Dan Williams committed
20 21
 */

22
#include "nm-default.h"
23

24 25
#include "nm-policy.h"

Dan Williams's avatar
Dan Williams committed
26
#include <string.h>
27 28 29
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
Dan Williams's avatar
Dan Williams committed
30 31

#include "NetworkManagerUtils.h"
32
#include "nm-act-request.h"
33
#include "devices/nm-device.h"
Dan Williams's avatar
Dan Williams committed
34
#include "nm-setting-ip4-config.h"
35
#include "nm-setting-connection.h"
36 37 38
#include "platform/nm-platform.h"
#include "dns/nm-dns-manager.h"
#include "vpn/nm-vpn-manager.h"
39
#include "nm-auth-utils.h"
40
#include "nm-firewall-manager.h"
41
#include "nm-dispatcher.h"
42
#include "nm-utils.h"
43
#include "nm-core-internal.h"
44
#include "nm-manager.h"
45 46
#include "settings/nm-settings.h"
#include "settings/nm-settings-connection.h"
47
#include "settings/nm-agent-manager.h"
48 49
#include "nm-dhcp4-config.h"
#include "nm-dhcp6-config.h"
50
#include "nm-config.h"
51
#include "nm-netns.h"
52
#include "nm-hostname-manager.h"
53

54
/*****************************************************************************/
55

56 57 58 59 60 61 62 63
NM_GOBJECT_PROPERTIES_DEFINE (NMPolicy,
	PROP_MANAGER,
	PROP_SETTINGS,
	PROP_DEFAULT_IP4_DEVICE,
	PROP_DEFAULT_IP6_DEVICE,
	PROP_ACTIVATING_IP4_DEVICE,
	PROP_ACTIVATING_IP6_DEVICE,
);
64

65
typedef struct {
66
	NMManager *manager;
67
	NMNetns *netns;
68
	NMFirewallManager *firewall_manager;
69
	CList pending_activation_checks;
70

71 72
	NMAgentManager *agent_mgr;

73
	GHashTable *devices;
74
	GHashTable *pending_active_connections;
75

76 77
	GSList *pending_secondaries;

78
	NMSettings *settings;
79

80 81
	NMHostnameManager *hostname_manager;

82 83
	NMDevice *default_device4, *activating_device4;
	NMDevice *default_device6, *activating_device6;
84

85 86 87 88 89 90
	struct {
		GInetAddress *addr;
		GResolver *resolver;
		GCancellable *cancellable;
	} lookup;

91 92
	NMDnsManager *dns_manager;
	gulong config_changed_id;
93

94
	guint reset_retries_id;  /* idle handler for resetting the retries count */
95

96 97
	guint schedule_activate_all_id; /* idle handler for schedule_activate_all(). */

98
	NMPolicyHostnameMode hostname_mode;
99
	char *orig_hostname; /* hostname at NM start time */
100
	char *cur_hostname;  /* hostname we want to assign */
101 102
	char *last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */
	gboolean changing_hostname; /* hostname set operation still in progress */
103
	gboolean dhcp_hostname; /* current hostname was set from dhcp */
104 105

	GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
106 107 108 109 110 111 112 113 114
} NMPolicyPrivate;

struct _NMPolicy {
	GObject parent;
	NMPolicyPrivate _priv;
};

struct _NMPolicyClass {
	GObjectClass parent;
115
};
Dan Winship's avatar
Dan Winship committed
116

117 118 119 120 121 122
G_DEFINE_TYPE (NMPolicy, nm_policy, G_TYPE_OBJECT)

#define NM_POLICY_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMPolicy, NM_IS_POLICY)

static NMPolicy *
_PRIV_TO_SELF (NMPolicyPrivate *priv)
123
{
124 125 126 127 128 129
	NMPolicy *self;

	nm_assert (priv);

	self = (NMPolicy *) (((char *) priv) - G_STRUCT_OFFSET (NMPolicy, _priv));

130
	nm_assert (NM_IS_POLICY (self));
131
	return self;
132
}
Dan Winship's avatar
Dan Winship committed
133

134
/*****************************************************************************/
135

136 137 138
#define _NMLOG_PREFIX_NAME    "policy"
#define _NMLOG(level, domain, ...) \
    G_STMT_START { \
139
        nm_log ((level), (domain), NULL, NULL, \
140 141 142 143 144 145
                "%s" _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \
                _NMLOG_PREFIX_NAME": " \
                _NM_UTILS_MACRO_REST (__VA_ARGS__)); \
    } G_STMT_END

/*****************************************************************************/
146

147
static void schedule_activate_all (NMPolicy *self);
148
static void schedule_activate_check (NMPolicy *self, NMDevice *device);
149

150
/*****************************************************************************/
151

152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
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));

167 168 169 170 171 172
	if (device) {
		/* We can not remove a subnet we already started announcing.
		 * Just un-prefer it. */
		subnet->preferred = 0;
		nm_device_use_ip6_subnet (device, subnet);
	}
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
	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 ();
194 195
	IP6PrefixDelegation *delegation = NULL;
	guint i;
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269

	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;
270 271
	guint have_prefixes = 0;
	guint i;
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287

	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) {
288
		_LOGI (LOGD_IP6, "ipv6-pd: none of %u prefixes of %s can be shared on %s",
289 290 291 292 293 294 295 296 297 298
		       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);
299 300
	IP6PrefixDelegation *delegation = NULL;
	guint i;
301 302

	for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
303
		delegation = &g_array_index (priv->ip6_prefix_delegations,
304 305 306 307 308 309 310 311 312 313 314 315 316
		                             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);
317 318
	IP6PrefixDelegation *delegation = NULL;
	guint i;
319 320
	const CList *tmp_list;
	NMActiveConnection *ac;
321 322 323 324 325 326 327 328

	_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);

329 330 331 332 333 334 335 336 337 338 339
	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);
340
		delegation->subnets = g_hash_table_new (nm_direct_hash, NULL);
341
		delegation->next_subnet = 0;
342
	}
343 344 345 346 347 348 349 350

	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. */
351 352
	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
		NMDevice *to_device;
353

354
		to_device = nm_active_connection_get_device (ac);
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
		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);
}

/*****************************************************************************/

382
static NMDevice *
383 384 385
get_best_ip_device (NMPolicy *self,
                    int addr_family,
                    gboolean fully_activated)
386
{
387
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
	const GSList *iter;
	NMDevice *best_device;
	NMDevice *prev_device;
	guint32 best_metric = G_MAXUINT32;
	gboolean best_is_fully_activated = FALSE;

	nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));

	/* we prefer the current device in case of identical metric.
	 * Hence, try that one first.*/
	best_device = NULL;
	prev_device =   addr_family == AF_INET
	              ? (fully_activated ? priv->default_device4 : priv->activating_device4)
	              : (fully_activated ? priv->default_device6 : priv->activating_device6);

	for (iter = nm_manager_get_devices (priv->manager); iter; iter = iter->next) {
		NMDevice *device = NM_DEVICE (iter->data);
		NMDeviceState state;
		const NMPObject *r;
		NMConnection *connection;
		guint32 metric;
		gboolean is_fully_activated;
410

411 412 413 414
		state = nm_device_get_state (device);
		if (   state <= NM_DEVICE_STATE_DISCONNECTED
		    || state >= NM_DEVICE_STATE_DEACTIVATING)
			continue;
415

416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
		if (nm_device_sys_iface_state_is_external (device))
			continue;

		r = nm_device_get_best_default_route (device, addr_family);
		if (r) {
			/* XXX: the best route might have rt_source NM_IP_CONFIG_SOURCE_VPN,
			 * which means it was injected by a VPN, not added by device.
			 *
			 * In this case, is it really the best device? Why do we even need the best
			 * device?? */
			metric = nm_utils_ip_route_metric_normalize (addr_family,
			                                             NMP_OBJECT_CAST_IP_ROUTE (r)->metric);
			is_fully_activated = TRUE;
		} else if (   !fully_activated
		           && (connection = nm_device_get_applied_connection (device))
		           && nm_utils_connection_has_default_route (connection, addr_family, NULL)) {
			metric = nm_utils_ip_route_metric_normalize (addr_family,
433
			                                             nm_device_get_route_metric (device, addr_family));
434 435 436
			is_fully_activated = FALSE;
		} else
			continue;
437

438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
		if (   !best_device
		    || (!best_is_fully_activated && is_fully_activated)
		    || (   metric < best_metric
		        || (metric == best_metric && device == prev_device))) {
			best_device = device;
			best_metric = metric;
			best_is_fully_activated = is_fully_activated;
		}
	}

	if (   !fully_activated
	    && best_device
	    && best_is_fully_activated) {
		/* There's only a best activating device if the best device
		 * among all activating and already-activated devices is a
		 * still-activating one. */
		return NULL;
	}

	return best_device;
458 459
}

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
static gboolean
all_devices_not_active (NMPolicy *self)
{
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
	const GSList *iter = nm_manager_get_devices (priv->manager);

	while (iter != NULL) {
		NMDeviceState state;

		state = nm_device_get_state (NM_DEVICE (iter->data));
		if (   state <= NM_DEVICE_STATE_DISCONNECTED
		    || state >= NM_DEVICE_STATE_DEACTIVATING) {
			iter = g_slist_next (iter);
			continue;
		}
		return FALSE;
	}
	return TRUE;
}

480 481
#define FALLBACK_HOSTNAME4 "localhost.localdomain"

482 483 484 485
static void
settings_set_hostname_cb (const char *hostname,
                          gboolean result,
                          gpointer user_data)
486
{
487 488
	NMPolicy *self = NM_POLICY (user_data);
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
489 490 491
	int ret = 0;

	if (!result) {
492
		_LOGT (LOGD_DNS, "set-hostname: hostname set via dbus failed, fallback to \"sethostname\"");
493 494 495 496
		ret = sethostname (hostname, strlen (hostname));
		if (ret != 0) {
			int errsv = errno;

497
			_LOGW (LOGD_DNS, "set-hostname: couldn't set the system hostname to '%s': (%d) %s",
498 499
			       hostname, errsv, strerror (errsv));
			if (errsv == EPERM)
500
				_LOGW (LOGD_DNS, "set-hostname: you should use hostnamed when systemd hardening is in effect!");
501 502 503
		}
	}

504
	priv->changing_hostname = FALSE;
505
	if (!ret)
506
		nm_dispatcher_call_hostname (NULL, NULL, NULL);
507
	g_object_unref (self);
508 509
}

510 511 512
#define HOST_NAME_BUFSIZE (HOST_NAME_MAX + 2)

static char *
513
_get_hostname (NMPolicy *self)
514 515
{
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
516
	char *hostname = NULL;
517

518 519 520 521
	/* If there is an in-progress hostname change, return
	 * the last hostname set as would be set soon...
	 */
	if (priv->changing_hostname) {
522
		_LOGT (LOGD_DNS, "get-hostname: \"%s\" (last on set)", priv->last_hostname);
523
		return g_strdup (priv->last_hostname);
524 525
	}

526
	/* try to get the hostname via dbus... */
527 528 529
	if (nm_hostname_manager_get_transient_hostname (priv->hostname_manager, &hostname)) {
		_LOGT (LOGD_DNS, "get-hostname: \"%s\" (from dbus)", hostname);
		return hostname;
530 531 532
	}

	/* ...or retrieve it by yourself */
533 534
	hostname = g_malloc (HOST_NAME_BUFSIZE);
	if (gethostname (hostname, HOST_NAME_BUFSIZE -1) != 0) {
535 536
		int errsv = errno;

537
		_LOGT (LOGD_DNS, "get-hostname: couldn't get the system hostname: (%d) %s",
538
		       errsv, g_strerror (errsv));
539
		g_free (hostname);
540 541 542 543
		return NULL;
	}

	/* the name may be truncated... */
544 545 546 547
	hostname[HOST_NAME_BUFSIZE - 1] = '\0';
	if (strlen (hostname) >= HOST_NAME_BUFSIZE -1) {
		_LOGT (LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", hostname);
		g_free (hostname);
548 549 550
		return NULL;
	}

551 552
	_LOGT (LOGD_DNS, "get-hostname: \"%s\"", hostname);
	return hostname;
553 554
}

555
static void
556
_set_hostname (NMPolicy *self,
557 558
               const char *new_hostname,
               const char *msg)
559
{
560
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
561
	gs_free char *old_hostname = NULL;
562
	const char *name;
Dan Winship's avatar
Dan Winship committed
563

564 565 566 567 568 569
	/* The incoming hostname *can* be NULL, which will get translated to
	 * 'localhost.localdomain' or such in the hostname policy code, but we
	 * keep cur_hostname = NULL in the case because we need to know that
	 * there was no valid hostname to start with.
	 */

570
	/* Clear lookup addresses if we have a hostname, so that we don't
571
	 * restart the reverse lookup thread later.
572
	 */
573
	if (new_hostname)
574
		g_clear_object (&priv->lookup.addr);
575

576 577 578 579
	/* Update the DNS only if the hostname is actually
	 * going to change.
	 */
	if (!nm_streq0 (priv->cur_hostname, new_hostname)) {
580 581 582 583 584 585
		g_free (priv->cur_hostname);
		priv->cur_hostname = g_strdup (new_hostname);

		/* Notify the DNS manager of the hostname change so that the domain part, if
		 * present, can be added to the search list.
		 */
586 587
		nm_dns_manager_set_hostname (priv->dns_manager, priv->cur_hostname,
		                             all_devices_not_active (self));
588
	}
589

590
	 /* Finally, set kernel hostname */
591
	if (!new_hostname)
592
		name = FALLBACK_HOSTNAME4;
593
	else if (!new_hostname[0]) {
594 595 596
		g_warn_if_reached ();
		name = FALLBACK_HOSTNAME4;
	} else
597
		name = new_hostname;
598

599
	/* Don't set the hostname if it isn't actually changing */
600
	if (   (old_hostname = _get_hostname (self))
601
	    && (nm_streq (name, old_hostname))) {
602
		_LOGT (LOGD_DNS, "set-hostname: hostname already set to '%s' (%s)", name, msg);
603
		return;
604 605
	}

606 607 608 609 610
	/* Keep track of the last set hostname */
	g_free (priv->last_hostname);
	priv->last_hostname = g_strdup (name);
	priv->changing_hostname = TRUE;

611
	_LOGI (LOGD_DNS, "set-hostname: set hostname to '%s' (%s)", name, msg);
612 613 614

	/* Ask NMSettings to update the transient hostname using its
	 * systemd-hostnamed proxy */
615 616 617 618
	nm_hostname_manager_set_transient_hostname (priv->hostname_manager,
	                                            name,
	                                            settings_set_hostname_cb,
	                                            g_object_ref (self));
619 620 621
}

static void
622 623
lookup_callback (GObject *source,
                 GAsyncResult *result,
624
                 gpointer user_data)
625
{
626 627 628 629
	NMPolicy *self;
	NMPolicyPrivate *priv;
	gs_free char *hostname = NULL;
	gs_free_error GError *error = NULL;
630 631

	hostname = g_resolver_lookup_by_address_finish (G_RESOLVER (source), result, &error);
632
	if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
633
		return;
634 635 636 637

	self = user_data;
	priv = NM_POLICY_GET_PRIVATE (self);

638
	g_clear_object (&priv->lookup.cancellable);
639 640

	if (hostname)
641
		_set_hostname (self, hostname, "from address lookup");
642
	else
643
		_set_hostname (self, NULL, error->message);
644 645
}

646 647 648 649 650
static void
lookup_by_address (NMPolicy *self)
{
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);

651 652 653 654 655
	nm_clear_g_cancellable (&priv->lookup.cancellable);
	priv->lookup.cancellable = g_cancellable_new ();
	g_resolver_lookup_by_address_async (priv->lookup.resolver,
	                                    priv->lookup.addr,
	                                    priv->lookup.cancellable,
656 657 658
	                                    lookup_callback, self);
}

659
static void
660
update_system_hostname (NMPolicy *self, const char *msg)
661
{
662
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
663
	const char *configured_hostname;
664
	gs_free char *temp_hostname = NULL;
665
	const char *dhcp_hostname, *p;
666 667
	NMIP4Config *ip4_config;
	NMIP6Config *ip6_config;
668
	gboolean external_hostname = FALSE;
669 670
	const NMPlatformIP4Address *addr4;
	const NMPlatformIP6Address *addr6;
671

672
	g_return_if_fail (self != NULL);
673

674 675
	if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_NONE) {
		_LOGT (LOGD_DNS, "set-hostname: hostname is unmanaged");
676
		return;
677 678 679
	}

	_LOGT (LOGD_DNS, "set-hostname: updating hostname (%s)", msg);
680

681
	nm_clear_g_cancellable (&priv->lookup.cancellable);
682

683 684 685
	/* Check if the hostname was set externally to NM, so that in that case
	 * we can avoid to fallback to the one we got when we started.
	 * Consider "not specific" hostnames as equal. */
686
	if (   (temp_hostname = _get_hostname (self))
687 688 689 690
	    && !nm_streq0 (temp_hostname, priv->last_hostname)
	    && (   nm_utils_is_specific_hostname (temp_hostname)
	        || nm_utils_is_specific_hostname (priv->last_hostname))) {
		external_hostname = TRUE;
691
		_LOGI (LOGD_DNS, "set-hostname: current hostname was changed outside NetworkManager: '%s'",
692
		       temp_hostname);
693
		priv->dhcp_hostname = FALSE;
694

695 696
		if (!nm_utils_is_specific_hostname (temp_hostname))
			nm_clear_g_free (&temp_hostname);
697 698 699
		if (!nm_streq0 (temp_hostname, priv->orig_hostname)) {
			/* Update original (fallback) hostname */
			g_free (priv->orig_hostname);
700 701 702
			priv->orig_hostname = g_steal_pointer (&temp_hostname);
			_LOGT (LOGD_DNS, "hostname-original: update to %s%s%s",
			       NM_PRINT_FMT_QUOTE_STRING (priv->orig_hostname));
703 704 705
		}
	}

706 707
	/* Hostname precedence order:
	 *
708
	 * 1) a configured hostname (from settings)
709
	 * 2) automatic hostname from the default device's config (DHCP, VPN, etc)
710
	 * 3) the last hostname set outside NM
711 712
	 * 4) reverse-DNS of the best device's IPv4 address
	 *
713 714
	 */

715
	/* Try a persistent hostname first */
716
	configured_hostname = nm_hostname_manager_get_hostname (priv->hostname_manager);
717
	if (configured_hostname && nm_utils_is_specific_hostname (configured_hostname)) {
718
		_set_hostname (self, configured_hostname, "from system configuration");
719
		priv->dhcp_hostname = FALSE;
720 721 722
		return;
	}

723
	if (priv->default_device4) {
724
		NMDhcp4Config *dhcp4_config;
725 726

		/* Grab a hostname out of the device's DHCP4 config */
727
		dhcp4_config = nm_device_get_dhcp4_config (priv->default_device4);
728
		if (dhcp4_config) {
729 730 731 732 733 734 735
			dhcp_hostname = nm_dhcp4_config_get_option (dhcp4_config, "host_name");
			if (dhcp_hostname && dhcp_hostname[0]) {
				p = nm_str_skip_leading_spaces (dhcp_hostname);
				if (p[0]) {
					_set_hostname (self, p, "from DHCPv4");
					priv->dhcp_hostname = TRUE;
					return;
736
				}
737
				_LOGW (LOGD_DNS, "set-hostname: DHCPv4-provided hostname '%s' looks invalid; ignoring it",
738
				       dhcp_hostname);
739 740
			}
		}
741 742
	}

743
	if (priv->default_device6) {
744
		NMDhcp6Config *dhcp6_config;
745

746
		/* Grab a hostname out of the device's DHCP6 config */
747
		dhcp6_config = nm_device_get_dhcp6_config (priv->default_device6);
748
		if (dhcp6_config) {
749 750 751 752 753 754 755
			dhcp_hostname = nm_dhcp6_config_get_option (dhcp6_config, "host_name");
			if (dhcp_hostname && dhcp_hostname[0]) {
				p = nm_str_skip_leading_spaces (dhcp_hostname);
				if (p[0]) {
					_set_hostname (self, p, "from DHCPv6");
					priv->dhcp_hostname = TRUE;
					return;
756
				}
757
				_LOGW (LOGD_DNS, "set-hostname: DHCPv6-provided hostname '%s' looks invalid; ignoring it",
758
				       dhcp_hostname);
759
			}
760 761 762
		}
	}

763 764 765 766
	/* If an hostname was set outside NetworkManager keep it */
	if (external_hostname)
		return;

767 768 769 770 771 772 773 774 775 776
	if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_DHCP) {
		/* In dhcp hostname-mode, the hostname is updated only if it comes from
		 * a DHCP host-name option: if last set was from a host-name option and
		 * we are here than that connection is gone (with its host-name option),
		 * so reset the hostname to the previous value
		 */
		if (priv->dhcp_hostname) {
			_set_hostname (self, priv->orig_hostname, "reset dhcp hostname");
			priv->dhcp_hostname = FALSE;
		}
777
		return;
778 779 780
	}

	priv->dhcp_hostname = FALSE;
781

782
	if (!priv->default_device4 && !priv->default_device6) {
783 784 785 786 787 788 789 790 791
		/* No best device; fall back to the last hostname set externally
		 * to NM or if there wasn't one, 'localhost.localdomain'
		 */
		_set_hostname (self, priv->orig_hostname, "no default device");
		return;
	}

	/* If no automatically-configured hostname, try using the last hostname
	 * set externally to NM
792
	 */
Dan Winship's avatar
Dan Winship committed
793
	if (priv->orig_hostname) {
794
		_set_hostname (self, priv->orig_hostname, "from system startup");
795 796 797
		return;
	}

798 799
	/* No configured hostname, no automatically determined hostname, and no
	 * bootup hostname. Start reverse DNS of the current IPv4 or IPv6 address.
800
	 */
801 802
	ip4_config = priv->default_device4 ? nm_device_get_ip4_config (priv->default_device4) : NULL;
	ip6_config = priv->default_device6 ? nm_device_get_ip6_config (priv->default_device6) : NULL;
803

804 805
	if (   ip4_config
	    && (addr4 = nm_ip4_config_get_first_address (ip4_config))) {
806 807
		g_clear_object (&priv->lookup.addr);
		priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr4->address,
808
		                                                   G_SOCKET_FAMILY_IPV4);
809 810
	} else if (   ip6_config
	           && (addr6 = nm_ip6_config_get_first_address (ip6_config))) {
811 812
		g_clear_object (&priv->lookup.addr);
		priv->lookup.addr = g_inet_address_new_from_bytes ((guint8 *) &addr6->address,
813
		                                                   G_SOCKET_FAMILY_IPV6);
814
	} else {
815
		/* No valid IP config; fall back to localhost.localdomain */
816
		_set_hostname (self, NULL, "no IP config");
817
		return;
818
	}
819

820
	lookup_by_address (self);
821 822 823
}

static void
824
update_default_ac (NMPolicy *self,
825 826
                   int addr_family,
                   NMActiveConnection *best)
827
{
828
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
829 830
	const CList *tmp_list;
	NMActiveConnection *ac;
831

832 833 834 835
	/* Clear the 'default[6]' flag on all active connections that aren't the new
	 * default active connection.  We'll set the new default after; this ensures
	 * we don't ever have two marked 'default[6]' simultaneously.
	 */
836 837
	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
		if (ac != best)
838
			nm_active_connection_set_default (ac, addr_family, FALSE);
839 840 841 842
	}

	/* Mark new default active connection */
	if (best)
843
		nm_active_connection_set_default (best, addr_family, TRUE);
844 845
}

846 847 848 849 850 851 852
static gpointer
get_best_ip_config (NMPolicy *self,
                    int addr_family,
                    const char **out_ip_iface,
                    NMActiveConnection **out_ac,
                    NMDevice **out_device,
                    NMVpnConnection **out_vpn)
853
{
854 855 856
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
	NMDevice *device;
	gpointer conf;
857 858
	const CList *tmp_list;
	NMActiveConnection *ac;
859 860 861

	nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6));

862
	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
863 864 865
		NMVpnConnection *candidate;
		NMVpnConnectionState vpn_state;

866
		if (!NM_IS_VPN_CONNECTION (ac))
867 868
			continue;

869
		candidate = NM_VPN_CONNECTION (ac);
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893

		vpn_state = nm_vpn_connection_get_vpn_state (candidate);
		if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
			continue;

		if (addr_family == AF_INET)
			conf = nm_vpn_connection_get_ip4_config (candidate);
		else
			conf = nm_vpn_connection_get_ip6_config (candidate);
		if (!conf)
			continue;

		if (addr_family == AF_INET) {
			if (!nm_ip4_config_best_default_route_get (conf))
				continue;
		} else {
			if (!nm_ip6_config_best_default_route_get (conf))
				continue;
		}

		/* FIXME: in case of multiple VPN candidates, choose the one with the
		 * best metric. */
		NM_SET_OUT (out_device, NULL);
		NM_SET_OUT (out_vpn, candidate);
894
		NM_SET_OUT (out_ac, ac);
895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
		NM_SET_OUT (out_ip_iface, nm_vpn_connection_get_ip_iface (candidate, TRUE));
		return conf;
	}

	device = get_best_ip_device (self, addr_family, TRUE);
	if (device) {
		NMActRequest *req;

		if (addr_family == AF_INET)
			conf = nm_device_get_ip4_config (device);
		else
			conf = nm_device_get_ip6_config (device);
		req = nm_device_get_act_request (device);

		if (conf && req) {
			NM_SET_OUT (out_device, device);
			NM_SET_OUT (out_vpn, NULL);
			NM_SET_OUT (out_ac, NM_ACTIVE_CONNECTION (req));
			NM_SET_OUT (out_ip_iface, nm_device_get_ip_iface (device));
			return conf;
		}
	}

	NM_SET_OUT (out_device, NULL);
	NM_SET_OUT (out_vpn, NULL);
	NM_SET_OUT (out_ac, NULL);
	NM_SET_OUT (out_ip_iface, NULL);
	return NULL;
923
}
924

925
static void
926
update_ip4_routing (NMPolicy *self, gboolean force_update)
927
{
928
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
929
	NMDevice *best = NULL;
930
	NMVpnConnection *vpn = NULL;
931 932
	NMActiveConnection *best_ac = NULL;
	const char *ip_iface = NULL;
933 934
	const CList *tmp_list;
	NMActiveConnection *ac;
935

936 937
	/* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
	 * so we can get (vpn != NULL && best == NULL).
938
	 */
939
	if (!get_best_ip_config (self, AF_INET, &ip_iface, &best_ac, &best, &vpn)) {
940
		if (nm_clear_g_object (&priv->default_device4)) {
941
			_LOGt (LOGD_DNS, "set-default-device-4: %p", NULL);
942
			_notify (self, PROP_DEFAULT_IP4_DEVICE);
943
		}
944 945 946
		return;
	}
	g_assert ((best || vpn) && best_ac);
947

948 949 950
	if (   !force_update
	    && best
	    && best == priv->default_device4)
951
		return;
952

953
	if (best) {
954 955 956 957 958
		nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
			if (   NM_IS_VPN_CONNECTION (ac)
			    && nm_vpn_connection_get_ip4_config (NM_VPN_CONNECTION (ac))
			    && !nm_active_connection_get_device (ac))
				nm_active_connection_set_device (ac, best);
959 960 961
		}
	}

962
	if (vpn)
963
		best = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
964

965
	update_default_ac (self, AF_INET, best_ac);
966

967
	if (!nm_g_object_ref_set (&priv->default_device4, best))
968
		return;
969
	_LOGt (LOGD_DNS, "set-default-device-4: %p", priv->default_device4);
970

971
	_LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv4 routing and DNS",
972 973
	       nm_connection_get_id (nm_active_connection_get_applied_connection (best_ac)),
	       ip_iface);
974
	_notify (self, PROP_DEFAULT_IP4_DEVICE);
975 976
}

977 978 979 980
static void
update_ip6_dns_delegation (NMPolicy *self)
{
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
981 982 983
	NMDevice *device;
	NMActiveConnection *ac;
	const CList *tmp_list;
984

985 986
	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
		device = nm_active_connection_get_device (ac);
987 988 989 990 991 992 993 994 995
		if (device && nm_device_needs_ip6_subnet (device))
			nm_device_copy_ip6_dns_config (device, priv->default_device6);
	}
}

static void
update_ip6_prefix_delegation (NMPolicy *self)
{
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
996 997 998
	NMDevice *device;
	NMActiveConnection *ac;
	const CList *tmp_list;
999 1000

	/* There's new default IPv6 connection, try to get a prefix for everyone. */
1001 1002
	nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
		device = nm_active_connection_get_device (ac);
1003 1004 1005
		if (device && nm_device_needs_ip6_subnet (device))
			ip6_subnet_from_device (self, priv->default_device6, device);
	}
1006
}
1007

1008
static void
1009
update_ip6_routing (NMPolicy *self, gboolean force_update)
1010
{
1011
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
1012
	NMDevice *best = NULL;
1013
	NMVpnConnection *vpn = NULL;
1014 1015
	NMActiveConnection *best_ac = NULL;
	const char *ip_iface = NULL;
1016 1017
	NMActiveConnection *ac;
	const CList *tmp_list;
1018

1019 1020
	/* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
	 * so we can get (vpn != NULL && best == NULL).
1021
	 */
1022
	if (!get_best_ip_config (self, AF_INET6, &ip_iface, &best_ac, &best, &vpn)) {
1023
		if (nm_clear_g_object (&priv->default_device6)) {
1024
			_LOGt (LOGD_DNS, "set-default-device-6: %p", NULL);
1025
			_notify (self, PROP_DEFAULT_IP6_DEVICE);
1026
		}
1027
		return;
1028
	}
1029
	g_assert ((best || vpn) && best_ac);
1030

1031 1032 1033
	if (   !force_update
	    && best
	    && best == priv->default_device6)
1034
		return;
1035

1036
	if (best) {
1037 1038 1039 1040 1041
		nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
			if (   NM_IS_VPN_CONNECTION (ac)
			    && nm_vpn_connection_get_ip6_config (NM_VPN_CONNECTION (ac))
			    && !nm_active_connection_get_device (ac))
				nm_active_connection_set_device (ac, best);
1042 1043 1044
		}
	}

1045
	if (vpn)
1046
		best = nm_active_connection_get_device (NM_ACTIVE_CONNECTION (vpn));
1047

1048
	update_default_ac (self, AF_INET6, best_ac);
1049

1050
	if (!nm_g_object_ref_set (&priv->default_device6, best))
1051
		return;
1052
	_LOGt (LOGD_DNS, "set-default-device-6: %p", priv->default_device6);
1053 1054 1055

	update_ip6_prefix_delegation (self);

1056
	_LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv6 routing and DNS",
1057 1058
	       nm_connection_get_id (nm_active_connection_get_applied_connection (best_ac)),
	       ip_iface);
1059
	_notify (self, PROP_DEFAULT_IP6_DEVICE);
1060 1061
}

1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
static void
update_ip_dns (NMPolicy *self, int addr_family)
{
	gpointer ip_config;
	const char *ip_iface = NULL;
	NMVpnConnection *vpn = NULL;

	nm_assert_addr_family (addr_family);

	ip_config = get_best_ip_config (self, addr_family, &ip_iface, NULL, NULL, &vpn);
	if (ip_config) {
		/* Tell the DNS manager this config is preferred by re-adding it with
		 * a different IP config type.
		 */
1076
		nm_dns_manager_set_ip_config (NM_POLICY_GET_PRIVATE (self)->dns_manager,
1077
		                              ip_config,
1078 1079 1080
		                              vpn
		                                ? NM_DNS_IP_CONFIG_TYPE_VPN
		                                : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE);
1081 1082 1083 1084 1085 1086
	}

	if (addr_family == AF_INET6)
		update_ip6_dns_delegation (self);
}

1087
static void
1088
update_routing_and_dns (NMPolicy *self, gboolean force_update)
1089
{
1090
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
1091

1092
	nm_dns_manager_begin_updates (priv->dns_manager, __func__);
1093

1094 1095
	update_ip_dns (self, AF_INET);
	update_ip_dns (self, AF_INET6);
1096

1097 1098
	update_ip4_routing (self, force_update);
	update_ip6_routing (self, force_update);
1099

1100
	/* Update the system hostname */
1101
	update_system_hostname (self, "routing and dns");
1102

1103
	nm_dns_manager_end_updates (priv->dns_manager, __func__);
1104 1105
}

1106
static void
1107
check_activating_devices (NMPolicy *self)
1108
{
1109
	NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self);
1110 1111
	NMDevice *best4, *best6 = NULL;

1112 1113
	best4 = get_best_ip_device (self, AF_INET, FALSE);
	best6 = get_best_ip_device (self, AF_INET6, FALSE);