nm-device.c 503 KB
Newer Older
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
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.
17
 *
18
 * Copyright (C) 2005 - 2017 Red Hat, Inc.
19
 * Copyright (C) 2006 - 2008 Novell, Inc.
20
21
 */

22
#include "nm-default.h"
23

24
25
#include "nm-device.h"

26
27
#include <netinet/in.h>
#include <string.h>
Dan Williams's avatar
Dan Williams committed
28
29
30
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
31
32
33
34
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <arpa/inet.h>
35
#include <fcntl.h>
36
#include <linux/if_addr.h>
37
#include <linux/if_arp.h>
38
#include <linux/rtnetlink.h>
39
#include <linux/pkt_sched.h>
40

41
42
#include "nm-utils/nm-dedup-multi.h"

43
#include "nm-common-macros.h"
44
45
#include "nm-device-private.h"
#include "NetworkManagerUtils.h"
46
#include "nm-manager.h"
47
#include "platform/nm-platform.h"
48
#include "platform/nmp-object.h"
49
50
51
#include "ndisc/nm-ndisc.h"
#include "ndisc/nm-lndp-ndisc.h"
#include "dhcp/nm-dhcp-manager.h"
52
#include "dhcp/nm-dhcp-utils.h"
53
#include "nm-act-request.h"
Atul Anand's avatar
Atul Anand committed
54
#include "nm-proxy-config.h"
55
56
#include "nm-ip4-config.h"
#include "nm-ip6-config.h"
Atul Anand's avatar
Atul Anand committed
57
#include "nm-pacrunner-manager.h"
58
#include "dnsmasq/nm-dnsmasq-manager.h"
59
#include "nm-dhcp4-config.h"
60
#include "nm-dhcp6-config.h"
61
#include "nm-rfkill-manager.h"
Jiri Popelka's avatar
Jiri Popelka committed
62
#include "nm-firewall-manager.h"
63
64
#include "settings/nm-settings-connection.h"
#include "settings/nm-settings.h"
65
#include "nm-auth-utils.h"
66
#include "nm-netns.h"
67
#include "nm-dispatcher.h"
68
#include "nm-config.h"
69
#include "nm-utils/c-list.h"
70
#include "dns/nm-dns-manager.h"
71
#include "nm-core-internal.h"
72
#include "systemd/nm-sd.h"
73
#include "nm-lldp-listener.h"
Beniamino Galvani's avatar
Beniamino Galvani committed
74
#include "nm-audit-manager.h"
75
#include "nm-arping-manager.h"
76
77
#include "nm-connectivity.h"
#include "nm-dbus-interface.h"
78
#include "nm-device-vlan.h"
79

80
81
82
#include "nm-device-logging.h"
_LOG_DECLARE_SELF (NMDevice);

83
/*****************************************************************************/
84

85
#define DEFAULT_AUTOCONNECT    TRUE
86
#define DHCP_GRACE_PERIOD_SEC  480
87

88
#define CARRIER_WAIT_TIME_MS 6000
89
90
#define CARRIER_WAIT_TIME_AFTER_MTU_MS 10000

91
92
93
94
#define NM_DEVICE_AUTH_RETRIES_UNSET    -1
#define NM_DEVICE_AUTH_RETRIES_INFINITY -2
#define NM_DEVICE_AUTH_RETRIES_DEFAULT  3

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*****************************************************************************/

typedef void (*ActivationHandleFunc) (NMDevice *self);

typedef struct {
	ActivationHandleFunc func;
	guint id;
} ActivationHandleData;

typedef enum {
	CLEANUP_TYPE_KEEP,
	CLEANUP_TYPE_REMOVED,
	CLEANUP_TYPE_DECONFIGURE,
} CleanupType;

typedef enum {
	IP_NONE = 0,
	IP_WAIT,
	IP_CONF,
	IP_DONE,
	IP_FAIL
} IpState;

typedef struct {
119
	CList lst_slave;
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
	NMDevice *slave;
	gulong watch_id;
	bool slave_is_enslaved;
	bool configure;
} SlaveInfo;

typedef struct {
	NMDevice *device;
	guint idle_add_id;
	int ifindex;
} DeleteOnDeactivateData;

typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean);

typedef struct {
	ArpingCallback callback;
	NMDevice *device;
	NMIP4Config **configs;
} ArpingData;

typedef enum {
	HW_ADDR_TYPE_UNSET = 0,
	HW_ADDR_TYPE_PERMANENT,
	HW_ADDR_TYPE_EXPLICIT,
	HW_ADDR_TYPE_GENERATED,
} HwAddrType;

147
148
149
150
151
152
153
typedef enum {
	FIREWALL_STATE_UNMANAGED = 0,
	FIREWALL_STATE_INITIALIZED,
	FIREWALL_STATE_WAIT_STAGE_3,
	FIREWALL_STATE_WAIT_IP_CONFIG,
} FirewallState;

154
155
156
157
158
159
typedef struct {
	NMIPConfig *orig;      /* the original configuration applied to the device */
	NMIPConfig *current;   /* configuration after external changes.  NULL means
	                          that the original configuration didn't change. */
} AppliedConfig;

160
/*****************************************************************************/
161

162
enum {
163
	STATE_CHANGED,
164
	AUTOCONNECT_ALLOWED,
165
	AUTH_REQUEST,
166
167
	IP4_CONFIG_CHANGED,
	IP6_CONFIG_CHANGED,
168
169
	IP6_PREFIX_DELEGATED,
	IP6_SUBNET_NEEDED,
170
	REMOVED,
171
	RECHECK_AUTO_ACTIVATE,
172
	RECHECK_ASSUME,
173
174
175
176
	LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = { 0 };

177
NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
178
179
180
181
	PROP_UDI,
	PROP_IFACE,
	PROP_IP_IFACE,
	PROP_DRIVER,
182
183
	PROP_DRIVER_VERSION,
	PROP_FIRMWARE_VERSION,
184
	PROP_CAPABILITIES,
185
	PROP_CARRIER,
Jiří Klimeš's avatar
Jiří Klimeš committed
186
	PROP_MTU,
187
188
189
190
191
192
	PROP_IP4_ADDRESS,
	PROP_IP4_CONFIG,
	PROP_DHCP4_CONFIG,
	PROP_IP6_CONFIG,
	PROP_DHCP6_CONFIG,
	PROP_STATE,
193
	PROP_STATE_REASON,
194
195
	PROP_ACTIVE_CONNECTION,
	PROP_DEVICE_TYPE,
196
	PROP_LINK_TYPE,
197
	PROP_MANAGED,
198
	PROP_AUTOCONNECT,
199
	PROP_FIRMWARE_MISSING,
200
	PROP_NM_PLUGIN_MISSING,
201
202
203
	PROP_TYPE_DESC,
	PROP_RFKILL_TYPE,
	PROP_IFINDEX,
204
	PROP_AVAILABLE_CONNECTIONS,
205
	PROP_PHYSICAL_PORT_ID,
Dan Winship's avatar
Dan Winship committed
206
	PROP_MASTER,
207
	PROP_PARENT,
208
	PROP_HW_ADDRESS,
209
	PROP_PERM_HW_ADDRESS,
210
	PROP_HAS_PENDING_ACTION,
211
	PROP_METERED,
212
	PROP_LLDP_NEIGHBORS,
213
	PROP_REAL,
214
	PROP_SLAVES,
215
216
217
	PROP_REFRESH_RATE_MS,
	PROP_TX_BYTES,
	PROP_RX_BYTES,
218
	PROP_CONNECTIVITY,
219
);
220

221
typedef struct _NMDevicePrivate {
222
	bool in_state_changed;
223

224
225
226
	guint device_link_changed_id;
	guint device_ip_link_changed_id;

227
	NMDeviceState state;
228
	NMDeviceStateReason state_reason;
229
	struct {
230
231
232
		guint id;

		/* The @state/@reason is only valid, when @id is set. */
233
234
235
		NMDeviceState state;
		NMDeviceStateReason reason;
	} queued_state;
Thomas Haller's avatar
Thomas Haller committed
236

237
238
	guint queued_ip4_config_id;
	guint queued_ip6_config_id;
239
	GSList *pending_actions;
240
	GSList *dad6_failed_addrs;
241

242
243
	NMDevice *parent_device;

244
245
	char *        udi;
	char *        iface;   /* may change, could be renamed by user */
246
	int           ifindex;
247

248
249
	int parent_ifindex;

250
251
	int auth_retries;

252
253
254
255
	union {
		const guint8 hw_addr_len; /* read-only */
		guint8 hw_addr_len_;
	};
256
257

	HwAddrType hw_addr_type:5;
258

259
260
261
262
263
264
	bool          real:1;

	/* there was a IP config change, but no idle action was scheduled because device
	 * is still not platform-init */
	bool queued_ip4_config_pending:1;
	bool queued_ip6_config_pending:1;
265

266
267
268
	bool update_ip_config_completed_v4:1;
	bool update_ip_config_completed_v6:1;

269
	char *        ip_iface;
270
	int           ip_ifindex;
271
272
	NMDeviceType  type;
	char *        type_desc;
273
	NMLinkType    link_type;
274
	NMDeviceCapabilities capabilities;
275
	char *        driver;
276
277
	char *        driver_version;
	char *        firmware_version;
278
	RfKillType    rfkill_type;
279
280
281
	bool          firmware_missing:1;
	bool          nm_plugin_missing:1;
	bool          hw_addr_perm_fake:1; /* whether the permanent HW address could not be read and is a fake */
282
283
284

	NMUtilsStableType current_stable_id_type:3;

285
	bool          nm_owned:1; /* whether the device is a device owned and created by NM */
Thomas Haller's avatar
Thomas Haller committed
286

287
288
289
	bool          assume_state_guess_assume:1;
	char *        assume_state_connection_uuid;

290
	GHashTable *  available_connections;
291
	char *        hw_addr;
292
293
	char *        hw_addr_perm;
	char *        hw_addr_initial;
294
	char *        physical_port_id;
295
	guint         dev_id;
296

297
	NMUnmanagedFlags        unmanaged_mask;
298
	NMUnmanagedFlags        unmanaged_flags;
299
	DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */
300

301
302
	GCancellable *deactivating_cancellable;

303
	guint32         ip4_address;
304

305
	NMActRequest *  queued_act_request;
306
307
308
309
	bool            queued_act_request_is_waiting_for_carrier:1;
	bool            act_request_public:1;
	NMActRequest   *act_request;
	gulong          act_request_id;
310
311
	ActivationHandleData act_handle4; /* for layer2 and IPv4. */
	ActivationHandleData act_handle6;
312
	guint           recheck_assume_id;
313
	struct {
314
		guint               call_id;
315
316
317
		NMDeviceStateReason available_reason;
		NMDeviceStateReason unavailable_reason;
	}               recheck_available;
318
319
320
321
322
	struct {
		guint               call_id;
		NMDeviceState       post_state;
		NMDeviceStateReason post_state_reason;
	}               dispatcher;
323

324
325
326
327
	/* Link stuff */
	guint           link_connected_id;
	guint           link_disconnected_id;
	guint           carrier_defer_id;
328
	guint           carrier_wait_id;
329
	gulong          config_changed_id;
Jiří Klimeš's avatar
Jiří Klimeš committed
330
	guint32         mtu;
331
	guint32         ip6_mtu;
332
333
334
	guint32 mtu_initial;
	guint32 ip6_mtu_initial;

335
336
337
	guint32         v4_route_table;
	guint32         v6_route_table;

338
	/* when carrier goes away, we give a grace period of _get_carrier_wait_ms()
339
340
341
342
343
344
345
	 * until taking action.
	 *
	 * When changing MTU, the device might take longer then that. So, whenever
	 * NM changes the MTU it sets @carrier_wait_until_ms to CARRIER_WAIT_TIME_AFTER_MTU_MS
	 * in the future. This is used to extend the grace period in this particular case. */
	gint64          carrier_wait_until_ms;

Thomas Haller's avatar
Thomas Haller committed
346
347
348
	bool            carrier:1;
	bool            ignore_carrier:1;

349
350
351
	bool mtu_initialized:1;

	bool            up:1;   /* IFF_UP */
352

353
354
355
	bool            v4_commit_first_time:1;
	bool            v6_commit_first_time:1;

356
357
358
	bool            default_route_metric_penalty_ip4_has:1;
	bool            default_route_metric_penalty_ip6_has:1;

359
360
	NMDeviceSysIfaceState sys_iface_state:2;

361
362
	bool            v4_route_table_initialized:1;
	bool            v6_route_table_initialized:1;
363

364
365
	NMDeviceAutoconnectBlockedFlags autoconnect_blocked_flags:4;

366
367
368
369
370
	bool            is_enslaved:1;
	bool            master_ready_handled:1;

	bool            ipv6ll_handle:1; /* TRUE if NM handles the device's IPv6LL address */

371
	/* Generic DHCP stuff */
372
	char *          dhcp_anycast_address;
373

374
375
	char *          current_stable_id;

Atul Anand's avatar
Atul Anand committed
376
	/* Proxy Configuration */
377
	NMProxyConfig *proxy_config;
378
	NMPacrunnerManager *pacrunner_manager;
379
	NMPacrunnerCallId *pacrunner_call_id;
Atul Anand's avatar
Atul Anand committed
380

381
	/* IP4 configuration info */
382
	NMIP4Config *   ip4_config;     /* Combined config from VPN, settings, and device */
383
384
385
386
	union {
		const IpState   ip4_state;
		IpState         ip4_state_;
	};
387
	NMIP4Config *   con_ip4_config; /* config from the setting */
388
389
	AppliedConfig   dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */
	AppliedConfig   wwan_ip4_config; /* WWAN configuration */
390
	NMIP4Config *   ext_ip4_config; /* Stuff added outside NM */
391
	GSList *        vpn4_configs;   /* VPNs which use this device */
392

393
394
	bool v4_has_shadowed_routes;
	const char *ip4_rp_filter;
395
396

	/* DHCPv4 tracking */
397
398
399
400
	struct {
		NMDhcpClient *  client;
		gulong          state_sigid;
		NMDhcp4Config * config;
401
		char *          pac_url;
402
		bool            was_active;
403
		guint           grace_id;
404
	} dhcp4;
405

406
407
408
409
410
	struct {
		NMLogDomain log_domain;
		guint timeout;
		guint watch;
		GPid pid;
411
412
		char *binary;
		char *address;
413
414
		guint deadline;
	} gw_ping;
415

416
	/* dnsmasq stuff for shared connections */
417
418
	NMDnsMasqManager *dnsmasq_manager;
	gulong            dnsmasq_state_id;
419

420
	/* Firewall */
421
422
	FirewallState fw_state:4;
	NMFirewallManager *fw_mgr;
423
	NMFirewallManagerCallId fw_call;
Jiri Popelka's avatar
Jiri Popelka committed
424

425
	/* IPv4LL stuff */
426
427
	sd_ipv4ll *    ipv4ll;
	guint          ipv4ll_timeout;
428
	guint          rt6_temporary_not_available_id;
429

430
431
432
433
434
435
	/* IPv4 DAD stuff */
	struct {
		GSList *          dad_list;
		NMArpingManager * announcing;
	} arping;

436
	/* IP6 configuration info */
437
	NMIP6Config *  ip6_config;
438
439
440
441
	union {
		const IpState   ip6_state;
		IpState         ip6_state_;
	};
442
	NMIP6Config *  con_ip6_config; /* config from the setting */
443
	AppliedConfig  wwan_ip6_config;
444
	AppliedConfig  ac_ip6_config;  /* config from IPv6 autoconfiguration */
445
	NMIP6Config *  ext_ip6_config; /* Stuff added outside NM */
446
	NMIP6Config *  ext_ip6_config_captured; /* Configuration captured from platform. */
447
	GSList *       vpn6_configs;   /* VPNs which use this device */
448
	NMIP6Config *  dad6_ip6_config;
449

450
451
	GHashTable *   rt6_temporary_not_available;

Lubomir Rintel's avatar
Lubomir Rintel committed
452
453
454
455
	NMNDisc *      ndisc;
	gulong         ndisc_changed_id;
	gulong         ndisc_timeout_id;
	NMSettingIP6ConfigPrivacy ndisc_use_tempaddr;
456

457
	guint          linklocal6_timeout_id;
458
	guint8         linklocal6_dad_counter;
459

460
	GHashTable *   ip6_saved_properties;
461

462
463
	struct {
		NMDhcpClient *   client;
Lubomir Rintel's avatar
Lubomir Rintel committed
464
		NMNDiscDHCPLevel mode;
465
		gulong           state_sigid;
466
		gulong           prefix_sigid;
467
468
		NMDhcp6Config *  config;
		/* IP6 config from DHCP */
469
		AppliedConfig    ip6_config;
470
471
		/* Event ID of the current IP6 config from DHCP */
		char *           event_id;
472
		guint            needed_prefixes;
473
		bool             was_active;
474
		guint            grace_id;
475
	} dhcp6;
476

477
478
	gboolean needs_ip6_subnet;

Jiri Pirko's avatar
Jiri Pirko committed
479
	/* master interface for bridge/bond/team slave */
480
	NMDevice *      master;
481
	gulong          master_ready_id;
482

483
	/* slave management */
484
	CList           slaves;    /* list of SlaveInfo */
485

486
487
	NMMetered       metered;

488
489
	NMSettings *settings;

490
491
	NMNetns *netns;

492
	NMLldpListener *lldp_listener;
493
	NMConnectivityState connectivity_state;
494
	gulong concheck_periodic_id;
495
	guint64 concheck_seq;
496
497

	guint check_delete_unrealized_id;
498

499
	struct {
500
		guint timeout_id;
501
502
503
504
		guint refresh_rate_ms;
		guint64 tx_bytes;
		guint64 rx_bytes;
	} stats;
505

506
} NMDevicePrivate;
507

508
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_DBUS_OBJECT)
509
510
511
512
513

#define NM_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDevice, NM_IS_DEVICE)

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

514
515
516
static const NMDBusInterfaceInfoExtended interface_info_device;
static const GDBusSignalInfo signal_info_state_changed;

517
static void nm_device_set_proxy_config (NMDevice *self, const char *pac_url);
Atul Anand's avatar
Atul Anand committed
518

519
static gboolean update_ext_ip_config (NMDevice *self, int addr_family, gboolean intersect_configs);
520

521
static gboolean nm_device_set_ip4_config (NMDevice *self,
522
                                          NMIP4Config *config,
523
524
                                          gboolean commit,
                                          GPtrArray *ip4_dev_route_blacklist);
525
526
527
static gboolean ip_config_merge_and_apply (NMDevice *self,
                                           int addr_family,
                                           gboolean commit);
528

529
static gboolean nm_device_set_ip6_config (NMDevice *self,
530
                                          NMIP6Config *config,
531
                                          gboolean commit);
532

533
static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure);
534
535
static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success);
static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason);
536

537
538
static void addrconf6_start_with_link_ready (NMDevice *self);
static gboolean linklocal6_start (NMDevice *self);
539

540
static void _carrier_wait_check_queued_act_request (NMDevice *self);
541
static gint64 _get_carrier_wait_ms (NMDevice *self);
542

543
static const char *_activation_func_to_string (ActivationHandleFunc func);
544
static void activation_source_handle_cb (NMDevice *self, int addr_family);
545

546
static void _set_state_full (NMDevice *self,
547
548
549
                             NMDeviceState state,
                             NMDeviceStateReason reason,
                             gboolean quitting);
550
static void queued_state_clear (NMDevice *device);
551
552
static gboolean queued_ip4_config_change (gpointer user_data);
static gboolean queued_ip6_config_change (gpointer user_data);
553
554
static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data);
static gboolean ip_config_valid (NMDeviceState state);
555
static NMActStageReturn dhcp4_start (NMDevice *self);
556
static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll);
557
static void nm_device_start_ip_check (NMDevice *self);
558
559
static void realize_start_setup (NMDevice *self,
                                 const NMPlatformLink *plink,
560
561
                                 gboolean assume_state_guess_assume,
                                 const char *assume_state_connection_uuid,
562
                                 gboolean set_nm_owned,
563
                                 NMUnmanFlagOp unmanaged_user_explicit);
564
static void _set_mtu (NMDevice *self, guint32 mtu);
565
static void _commit_mtu (NMDevice *self, const NMIP4Config *config);
566
static void _cancel_activation (NMDevice *self);
567

568
/*****************************************************************************/
569

570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState,
	NM_UTILS_LOOKUP_DEFAULT  (                              NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNKNOWN,      NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNMANAGED,    NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNAVAILABLE,  NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DISCONNECTED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_PREPARE,      NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_CONFIG,       NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_NEED_AUTH,    NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CONFIG,    NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CHECK,     NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_SECONDARIES,  NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_ACTIVATED,    NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DEACTIVATING, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_FAILED,       NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"),
);
586

587
588
const char *
nm_device_state_to_str (NMDeviceState state)
589
{
590
	return queued_state_to_string (state) + NM_STRLEN (NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE);
591
}
592

593
NM_UTILS_LOOKUP_STR_DEFINE (nm_device_state_reason_to_str, NMDeviceStateReason,
594
	NM_UTILS_LOOKUP_DEFAULT (NULL),
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_UNKNOWN,                        "unknown"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NONE,                           "none"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_MANAGED,                    "managed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NOW_UNMANAGED,                  "unmanaged"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONFIG_FAILED,                  "config-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE,          "ip-config-unavailable"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED,              "ip-config-expired"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NO_SECRETS,                     "no-secrets"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT,          "supplicant-disconnect"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED,       "supplicant-config-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED,              "supplicant-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT,             "supplicant-timeout"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_START_FAILED,               "ppp-start-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_DISCONNECT,                 "ppp-disconnect"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PPP_FAILED,                     "ppp-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_START_FAILED,              "dhcp-start-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_ERROR,                     "dhcp-error"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DHCP_FAILED,                    "dhcp-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_START_FAILED,            "sharing-start-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SHARED_FAILED,                  "sharing-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED,            "autoip-start-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_ERROR,                   "autoip-error"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_AUTOIP_FAILED,                  "autoip-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_BUSY,                     "modem-busy"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE,             "modem-no-dialtone"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER,               "modem-no-carrier"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT,             "modem-dial-timeout"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED,              "modem-dial-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED,              "modem-init-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_APN_FAILED,                 "gsm-apn-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, "gsm-registration-idle"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED,        "gsm-registration-denied"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT,       "gsm-registration-timeout"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED,        "gsm-registration-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED,           "gsm-pin-check-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_FIRMWARE_MISSING,               "firmware-missing"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_REMOVED,                        "removed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SLEEPING,                       "sleeping"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,             "connection-removed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_USER_REQUESTED,                 "user-requested"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CARRIER,                        "carrier-changed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED,             "connection-assumed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,           "supplicant-available"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND,                "modem-not-found"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BT_FAILED,                      "bluetooth-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED,           "gsm-sim-not-inserted"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED,           "gsm-sim-pin-required"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED,           "gsm-sim-puk-required"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_GSM_SIM_WRONG,                  "gsm-sim-wrong"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_INFINIBAND_MODE,                "infiniband-mode"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED,              "dependency-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_BR2684_FAILED,                  "br2684-bridge-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE,      "modem-manager-unavailable"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SSID_NOT_FOUND,                 "ssid-not-found"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED,    "secondary-connection-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED,                "dcb-fcoe-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED,           "teamd-control-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_FAILED,                   "modem-failed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_MODEM_AVAILABLE,                "modem-available"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT,              "sim-pin-incorrect"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_NEW_ACTIVATION,                 "new-activation"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_CHANGED,                 "parent-changed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED,         "parent-managed-changed"),
658
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_OVSDB_FAILED,                   "ovsdb-failed"),
659
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE,           "ip-address-duplicate"),
660
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED,          "ip-method-unsupported"),
661
);
662

663
#define reason_to_string(reason) \
664
	NM_UTILS_LOOKUP_STR (nm_device_state_reason_to_str, reason)
665

666
/*****************************************************************************/
667

668
669
670
671
672
673
NMSettings *
nm_device_get_settings (NMDevice *self)
{
	return NM_DEVICE_GET_PRIVATE (self)->settings;
}

674
675
676
677
678
679
NMNetns *
nm_device_get_netns (NMDevice *self)
{
	return NM_DEVICE_GET_PRIVATE (self)->netns;
}

680
681
682
683
684
685
NMDedupMultiIndex *
nm_device_get_multi_index (NMDevice *self)
{
	return nm_netns_get_multi_idx (nm_device_get_netns (self));
}

686
687
688
689
690
691
NMPlatform *
nm_device_get_platform (NMDevice *self)
{
	return nm_netns_get_platform (nm_device_get_netns (self));
}

692
693
694
695
696
697
698
699
700
701
702
703
704
705
static NMIP4Config *
_ip4_config_new (NMDevice *self)
{
	return nm_ip4_config_new (nm_device_get_multi_index (self),
	                          nm_device_get_ip_ifindex (self));
}

static NMIP6Config *
_ip6_config_new (NMDevice *self)
{
	return nm_ip6_config_new (nm_device_get_multi_index (self),
	                          nm_device_get_ip_ifindex (self));
}

706
707
708
709
710
711
712
713
714
715
static NMIPConfig *
_ip_config_new (NMDevice *self, int addr_family)
{
	nm_assert_addr_family (addr_family);

	return addr_family == AF_INET
	       ? (gpointer) _ip4_config_new (self)
	       : (gpointer) _ip6_config_new (self);
}

716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
static void
applied_config_clear (AppliedConfig *config)
{
	g_clear_object (&config->current);
	g_clear_object (&config->orig);
}

static void
applied_config_init (AppliedConfig *config, gpointer ip_config)
{
	nm_g_object_ref (ip_config);
	applied_config_clear (config);
	config->orig = ip_config;
}

731
732
733
734
735
736
737
738
static void
applied_config_init_new (AppliedConfig *config, NMDevice *self, int addr_family)
{
	gs_unref_object NMIPConfig *c = _ip_config_new (self, addr_family);

	applied_config_init (config, c);
}

739
740
741
742
743
744
static NMIPConfig *
applied_config_get_current (AppliedConfig *config)
{
	return config->current ?: config->orig;
}

745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
static void
applied_config_add_address (AppliedConfig *config, const NMPlatformIPAddress *address)
{
	if (config->orig)
		nm_ip_config_add_address (config->orig, address);
	else
		nm_assert (!config->current);

	if (config->current)
		nm_ip_config_add_address (config->current, address);
}

static void
applied_config_add_nameserver (AppliedConfig *config, const NMIPAddr *ns)
{
	if (config->orig)
		nm_ip_config_add_nameserver (config->orig, ns);
	else
		nm_assert (!config->current);

	if (config->current)
		nm_ip_config_add_nameserver (config->current, ns);
}

static void
applied_config_add_search (AppliedConfig *config, const char *new)
{
	if (config->orig)
		nm_ip_config_add_search (config->orig, new);
	else
		nm_assert (!config->current);

	if (config->current)
		nm_ip_config_add_search (config->current, new);
}

static void
applied_config_reset_searches (AppliedConfig *config)
{
	if (config->orig)
		nm_ip_config_reset_searches (config->orig);
	else
		nm_assert (!config->current);

	if (config->current)
		nm_ip_config_reset_searches (config->current);
}

static void
applied_config_reset_nameservers (AppliedConfig *config)
{
	if (config->orig)
		nm_ip_config_reset_nameservers (config->orig);
	else
		nm_assert (!config->current);

	if (config->current)
		nm_ip_config_reset_nameservers (config->current);
}

805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
/*****************************************************************************/

NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_sys_iface_state_to_str, NMDeviceSysIfaceState,
	NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_EXTERNAL, "external"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_ASSUME,   "assume"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_MANAGED,  "managed"),
	NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_SYS_IFACE_STATE_REMOVED,  "removed"),
);

NMDeviceSysIfaceState
nm_device_sys_iface_state_get (NMDevice *self)
{
	g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);

	return NM_DEVICE_GET_PRIVATE (self)->sys_iface_state;
}

gboolean
nm_device_sys_iface_state_is_external (NMDevice *self)
{
	return NM_IN_SET (nm_device_sys_iface_state_get (self),
	                  NM_DEVICE_SYS_IFACE_STATE_EXTERNAL);
}

gboolean
nm_device_sys_iface_state_is_external_or_assume (NMDevice *self)
{
	return NM_IN_SET (nm_device_sys_iface_state_get (self),
	                  NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
	                  NM_DEVICE_SYS_IFACE_STATE_ASSUME);
}

void
nm_device_sys_iface_state_set (NMDevice *self,
                               NMDeviceSysIfaceState sys_iface_state)
{
	NMDevicePrivate *priv;

	g_return_if_fail (NM_IS_DEVICE (self));
	g_return_if_fail (NM_IN_SET (sys_iface_state,
	                             NM_DEVICE_SYS_IFACE_STATE_EXTERNAL,
	                             NM_DEVICE_SYS_IFACE_STATE_ASSUME,
	                             NM_DEVICE_SYS_IFACE_STATE_MANAGED,
	                             NM_DEVICE_SYS_IFACE_STATE_REMOVED));

	priv = NM_DEVICE_GET_PRIVATE (self);
	if (priv->sys_iface_state != sys_iface_state) {
		_LOGT (LOGD_DEVICE, "sys-iface-state: %s -> %s",
		       _sys_iface_state_to_str (priv->sys_iface_state),
		       _sys_iface_state_to_str (sys_iface_state));
		priv->sys_iface_state = sys_iface_state;
	}

	/* this function only sets a flag, no immediate actions are initiated.
	 *
	 * If you change this, make sure that all callers are fine with such actions. */

	nm_assert (priv->sys_iface_state == sys_iface_state);
}

866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
static void
_active_connection_set_state_flags_full (NMDevice *self,
                                         NMActivationStateFlags flags,
                                         NMActivationStateFlags mask)
{
	NMActiveConnection *ac;

	ac = NM_ACTIVE_CONNECTION (nm_device_get_act_request (self));
	if (ac)
		nm_active_connection_set_state_flags_full (ac, flags, mask);
}

static void
_active_connection_set_state_flags (NMDevice *self,
                                    NMActivationStateFlags flags)
{
	_active_connection_set_state_flags_full (self, flags, flags);
}

885
886
/*****************************************************************************/

887
888
889
890
891
892
893
894
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
923
924
925
926
927
928
929
930
931
932
void
nm_device_assume_state_get (NMDevice *self,
                            gboolean *out_assume_state_guess_assume,
                            const char **out_assume_state_connection_uuid)
{
	NMDevicePrivate *priv;

	g_return_if_fail (NM_IS_DEVICE (self));

	priv = NM_DEVICE_GET_PRIVATE (self);
	NM_SET_OUT (out_assume_state_guess_assume, priv->assume_state_guess_assume);
	NM_SET_OUT (out_assume_state_connection_uuid, priv->assume_state_connection_uuid);
}

static void
_assume_state_set (NMDevice *self,
                   gboolean assume_state_guess_assume,
                   const char *assume_state_connection_uuid)
{
	NMDevicePrivate *priv;

	nm_assert (NM_IS_DEVICE (self));

	priv = NM_DEVICE_GET_PRIVATE (self);
	if (   priv->assume_state_guess_assume == !!assume_state_guess_assume
	    && nm_streq0 (priv->assume_state_connection_uuid, assume_state_connection_uuid))
		return;

	_LOGD (LOGD_DEVICE, "assume-state: set guess-assume=%c, connection=%s%s%s",
	       assume_state_guess_assume ? '1' : '0',
	       NM_PRINT_FMT_QUOTE_STRING (assume_state_connection_uuid));
	priv->assume_state_guess_assume = assume_state_guess_assume;
	g_free (priv->assume_state_connection_uuid);
	priv->assume_state_connection_uuid = g_strdup (assume_state_connection_uuid);
}

void
nm_device_assume_state_reset (NMDevice *self)
{
	g_return_if_fail (NM_IS_DEVICE (self));

	_assume_state_set (self, FALSE, NULL);
}

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

933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
static void
init_ip4_config_dns_priority (NMDevice *self, NMIP4Config *config)
{
	gs_free char *value = NULL;
	gint priority;

	value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
	                                               "ipv4.dns-priority",
	                                               self);
	priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0);
	nm_ip4_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL);
}

static void
init_ip6_config_dns_priority (NMDevice *self, NMIP6Config *config)
{
	gs_free char *value = NULL;
	gint priority;

	value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
	                                               "ipv6.dns-priority",
	                                               self);
	priority = _nm_utils_ascii_str_to_int64 (value, 10, G_MININT, G_MAXINT, 0);
	nm_ip6_config_set_dns_priority (config, priority ?: NM_DNS_PRIORITY_DEFAULT_NORMAL);
}

959
/*****************************************************************************/
960

961
962
963
static gboolean
nm_device_ipv4_sysctl_set (NMDevice *self, const char *property, const char *value)
{
964
	NMPlatform *platform = nm_device_get_platform (self);
965
966
	gs_free char *value_to_free = NULL;
	const char *value_to_set;
967
	char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
968

969
970
971
	if (!nm_device_get_ip_ifindex (self))
		return FALSE;

972
973
974
975
976
	if (value) {
		value_to_set = value;
	} else {
		/* Set to a default value when we've got a NULL @value. */
		value_to_free = nm_platform_sysctl_get (platform,
977
		                                        NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, "default", property)));
978
979
980
981
		value_to_set = value_to_free;
	}

	return nm_platform_sysctl_set (platform,
982
	                               NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, nm_device_get_ip_iface (self), property)),
983
984
985
986
987
988
	                               value_to_set);
}

static guint32
nm_device_ipv4_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback)
{
989
	char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
990

991
992
993
	if (!nm_device_get_ip_ifindex (self))
		return fallback;

994
	return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self),
995
	                                           NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET, buf, nm_device_get_ip_iface (self), property)),
996
997
998
999
1000
1001
	                                           10,
	                                           0,
	                                           G_MAXUINT32,
	                                           fallback);
}

1002
gboolean
1003
1004
nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value)
{
1005
	char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
1006

1007
1008
1009
	if (!nm_device_get_ip_ifindex (self))
		return FALSE;

1010
	return nm_platform_sysctl_set (nm_device_get_platform (self), NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, nm_device_get_ip_iface (self), property)), value);
1011
1012
}

1013
static guint32
1014
nm_device_ipv6_sysctl_get_uint32 (NMDevice *self, const char *property, guint32 fallback)
1015
{
1016
	char buf[NM_UTILS_SYSCTL_IP_CONF_PATH_BUFSIZE];
1017

1018
1019
1020
	if (!nm_device_get_ip_ifindex (self))
		return fallback;

1021
	return nm_platform_sysctl_get_int_checked (nm_device_get_platform (self),
1022
	                                           NMP_SYSCTL_PATHID_ABSOLUTE (nm_utils_sysctl_ip_conf_path (AF_INET6, buf, nm_device_get_ip_iface (self), property)),
1023
1024
1025
1026
	                                           10,
	                                           0,
	                                           G_MAXUINT32,
	                                           fallback);
1027
1028
}

1029
1030
gboolean
nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps)
1031
{
1032
	return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->capabilities, caps);
1033
}
1034

1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
static void
_add_capabilities (NMDevice *self, NMDeviceCapabilities capabilities)
{
	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);

	if (!NM_FLAGS_ALL (priv->capabilities, capabilities)) {
		priv->capabilities |= capabilities;
		_notify (self, PROP_CAPABILITIES);
	}
}

1046
/*****************************************************************************/
1047

1048
static const char *
1049
1050
1051
_get_stable_id (NMDevice *self,
                NMConnection *connection,
                NMUtilsStableType *out_stable_type)
1052
{
1053
	NMDevicePrivate *priv;
1054

1055
	nm_assert (NM_IS_DEVICE (self));
1056
1057
1058
	nm_assert (NM_IS_CONNECTION (connection));
	nm_assert (out_stable_type);

1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
	priv = NM_DEVICE_GET_PRIVATE (self);

	/* we cache the generated stable ID for the time of an activation.
	 *
	 * The reason is, that we don't want the stable-id to change as long
	 * as the device is active.
	 *
	 * Especially with ${RANDOM} stable-id we want to generate *one* configuration
	 * for each activation. */
	if (G_UNLIKELY (!priv->current_stable_id)) {
		gs_free char *default_id = NULL;
		gs_free char *generated = NULL;
		NMUtilsStableType stable_type;
		NMSettingConnection *s_con;
		const char *stable_id;
		const char *uuid;

		s_con = nm_connection_get_setting_connection (connection);

		stable_id = nm_setting_connection_get_stable_id (s_con);

		if (!stable_id) {
			default_id = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA,
			                                                    "connection.stable-id",
			                                                    self);
			stable_id = default_id;
		}
1086

1087
1088
1089
1090
1091
1092
1093
1094
1095
		uuid = nm_connection_get_uuid (connection);

		stable_type = nm_utils_stable_id_parse (stable_id,
		                                        uuid,
		                                        NULL,
		                                        &generated);

		/* current_stable_id_type is a bitfield! */
		priv->current_stable_id_type = stable_type;
Thomas Haller's avatar
Thomas Haller committed
1096
1097
1098
		nm_assert (stable_type <= (NMUtilsStableType) 0x3);
		nm_assert (stable_type + (NMUtilsStableType) 1 > (NMUtilsStableType) 0);
		nm_assert (priv->current_stable_id_type == stable_type);
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115

		if (stable_type == NM_UTILS_STABLE_TYPE_UUID)
			priv->current_stable_id = g_strdup (uuid);
		else if (stable_type == NM_UTILS_STABLE_TYPE_STABLE_ID)
			priv->current_stable_id = g_strdup (stable_id);
		else if (stable_type == NM_UTILS_STABLE_TYPE_GENERATED)
			priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_generated_complete (generated));
		else {
			nm_assert (stable_type == NM_UTILS_STABLE_TYPE_RANDOM);
			priv->current_stable_id = nm_str_realloc (nm_utils_stable_id_random ());
		}
		_LOGT (LOGD_DEVICE,
		       "stable-id: type=%d, \"%s\""
		       "%s%s%s",
		       (int) priv->current_stable_id_type,
		       priv->current_stable_id,
		       NM_PRINT_FMT_QUOTED (stable_type == NM_UTILS_STABLE_TYPE_GENERATED, " from \"", generated, "\"", ""));
1116
1117
	}

1118
1119
	*out_stable_type = priv->current_stable_id_type;
	return priv->current_stable_id;
1120
1121
}

1122
/*****************************************************************************/
1123

1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_ip_state_to_string, IpState,
	NM_UTILS_LOOKUP_DEFAULT_WARN ("unknown"),
	NM_UTILS_LOOKUP_STR_ITEM (IP_NONE, "none"),
	NM_UTILS_LOOKUP_STR_ITEM (IP_WAIT, "wait"),
	NM_UTILS_LOOKUP_STR_ITEM (IP_CONF, "conf"),
	NM_UTILS_LOOKUP_STR_ITEM (IP_DONE, "done"),
	NM_UTILS_LOOKUP_STR_ITEM (IP_FAIL, "fail"),
);

static void
_set_ip_state (NMDevice *self, int addr_family, IpState new_state)
{
	IpState *p;
	NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);

1139
	nm_assert_addr_family (addr_family);
1140

1141