summaryrefslogtreecommitdiff
path: root/src/core/devices/nm-device.h
blob: d9cfc7e621465ec336bf02e109a4dd261f187019 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
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
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
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
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
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
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
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
805
806
807
808
809
810
811
812
813
814
815
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2005 - 2017 Red Hat, Inc.
 * Copyright (C) 2006 - 2008 Novell, Inc.
 */

#ifndef __NETWORKMANAGER_DEVICE_H__
#define __NETWORKMANAGER_DEVICE_H__

#include <netinet/in.h>

#include "NetworkManagerUtils.h"
#include "nm-connection.h"
#include "nm-dbus-interface.h"
#include "nm-dbus-object.h"
#include "nm-device-utils.h"
#include "nm-l3cfg.h"
#include "nm-rfkill-manager.h"
#include "nm-setting-connection.h"

/* Properties */
#define NM_DEVICE_UDI                   "udi"
#define NM_DEVICE_PATH                  "path"
#define NM_DEVICE_IFACE                 "interface"
#define NM_DEVICE_IP_IFACE              "ip-interface"
#define NM_DEVICE_DRIVER                "driver"
#define NM_DEVICE_DRIVER_VERSION        "driver-version"
#define NM_DEVICE_FIRMWARE_VERSION      "firmware-version"
#define NM_DEVICE_CAPABILITIES          "capabilities"
#define NM_DEVICE_CARRIER               "carrier"
#define NM_DEVICE_IP4_ADDRESS           "ip4-address"
#define NM_DEVICE_IP4_CONFIG            "ip4-config"
#define NM_DEVICE_DHCP4_CONFIG          "dhcp4-config"
#define NM_DEVICE_IP6_CONFIG            "ip6-config"
#define NM_DEVICE_DHCP6_CONFIG          "dhcp6-config"
#define NM_DEVICE_STATE                 "state"
#define NM_DEVICE_STATE_REASON          "state-reason"
#define NM_DEVICE_ACTIVE_CONNECTION     "active-connection"
#define NM_DEVICE_DEVICE_TYPE           "device-type" /* ugh */
#define NM_DEVICE_LINK_TYPE             "link-type"
#define NM_DEVICE_MANAGED               "managed"
#define NM_DEVICE_AUTOCONNECT           "autoconnect"
#define NM_DEVICE_FIRMWARE_MISSING      "firmware-missing"
#define NM_DEVICE_NM_PLUGIN_MISSING     "nm-plugin-missing"
#define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections"
#define NM_DEVICE_PHYSICAL_PORT_ID      "physical-port-id"
#define NM_DEVICE_MTU                   "mtu"
#define NM_DEVICE_HW_ADDRESS            "hw-address"
#define NM_DEVICE_PORTS                 "ports"

/* "perm-hw-address" is exposed on D-Bus both for NMDeviceEthernet
 * and NMDeviceWifi. */
#define NM_DEVICE_PERM_HW_ADDRESS "perm-hw-address"

#define NM_DEVICE_METERED        "metered"
#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors"
#define NM_DEVICE_REAL           "real"

/* "parent" is exposed on D-Bus by subclasses like NMDeviceIPTunnel */
#define NM_DEVICE_PARENT "parent"

/* the "slaves" property is internal in the parent class, but exposed
 * by the derived classes NMDeviceBond, NMDeviceBridge, NMDeviceTeam,
 * NMDeviceOvsBridge and NMDeviceOvsPort. */
#define NM_DEVICE_SLAVES "slaves" /* partially internal */

#define NM_DEVICE_TYPE_DESC          "type-desc"          /* Internal only */
#define NM_DEVICE_IFINDEX            "ifindex"            /* Internal only */
#define NM_DEVICE_MASTER             "master"             /* Internal only */
#define NM_DEVICE_HAS_PENDING_ACTION "has-pending-action" /* Internal only */

/* Internal signals */
#define NM_DEVICE_DNS_LOOKUP_DONE          "dns-lookup-done"
#define NM_DEVICE_L3CD_CHANGED             "l3cd-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"
#define NM_DEVICE_STATE_CHANGED            "state-changed"
#define NM_DEVICE_LINK_INITIALIZED         "link-initialized"
#define NM_DEVICE_AUTOCONNECT_ALLOWED      "autoconnect-allowed"
#define NM_DEVICE_PLATFORM_ADDRESS_CHANGED "platform-address-changed"

#define NM_DEVICE_STATISTICS_REFRESH_RATE_MS "refresh-rate-ms"
#define NM_DEVICE_STATISTICS_TX_BYTES        "tx-bytes"
#define NM_DEVICE_STATISTICS_RX_BYTES        "rx-bytes"

#define NM_DEVICE_IP4_CONNECTIVITY "ip4-connectivity"
#define NM_DEVICE_IP6_CONNECTIVITY "ip6-connectivity"
#define NM_DEVICE_INTERFACE_FLAGS  "interface-flags"

#define NM_TYPE_DEVICE            (nm_device_get_type())
#define NM_DEVICE(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE, NMDevice))
#define NM_DEVICE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE, NMDeviceClass))
#define NM_IS_DEVICE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE))
#define NM_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE))
#define NM_DEVICE_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE, NMDeviceClass))

typedef enum NMActStageReturn NMActStageReturn;

/* These flags affect whether a connection is considered available on a device
 * (check_connection_available()). The flags should have the meaning of relaxing
 * a condition, so that adding a flag might make a connection available that would
 * not be available otherwise. Adding a flag should never make a connection
 * not available if it would be available otherwise. */
typedef enum {
    NM_DEVICE_CHECK_CON_AVAILABLE_NONE = 0,

    /* since NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST is a collection of flags with more fine grained
     * parts, this flag in general indicates that this is a user-request. */
    _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = (1L << 0),

    /* we also consider devices which have no carrier but are still waiting for the driver
     * to detect carrier. Usually, such devices are not yet available, however for a user-request
     * they are. They might fail later if carrier doesn't come. */
    _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER = (1L << 1),

    /* usually, a profile is only available if the Wi-Fi AP is in range. For an
     * explicit user request, we also consider profiles for APs that are not (yet)
     * visible. */
    _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP = (1L << 2),

    /* a device can be marked as unmanaged for various reasons. Some of these reasons
     * are authoritative, others not. Non-authoritative reasons can be overruled by
     * `nmcli device set $DEVICE managed yes`. Also, for an explicit user activation
     * request we may want to consider the device as managed. This flag makes devices
     * that are unmanaged appear available. */
    _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED = (1L << 3),

    /* a collection of flags, that are commonly set for an explicit user-request. */
    NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST =
        _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST
        | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER
        | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP
        | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_OVERRULE_UNMANAGED,

    NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 4) - 1,
} NMDeviceCheckConAvailableFlags;

struct _NMDevicePrivate;

struct _NMDevice {
    NMDBusObject             parent;
    struct _NMDevicePrivate *_priv;
    CList                    devices_lst;
};

/* The flags have an relaxing meaning, that means, specifying more flags, can make
 * a device appear more available. It can never make a device less available. */
typedef enum {
    NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0,

    /* the device is considered available, even if it has no carrier.
     *
     * For various device types (software devices) we ignore carrier based
     * on the type. So, for them, this flag has no effect anyway. */
    _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0),

    NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER,

    NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (1L << 1) - 1,
} NMDeviceCheckDevAvailableFlags;

typedef void (*NMDeviceDeactivateCallback)(NMDevice *self, GError *error, gpointer user_data);

typedef struct _NMDeviceClass {
    NMDBusObjectClass parent;

    struct _NMDeviceClass *default_type_description_klass;
    const char            *default_type_description;

    const char *connection_type_supported;

    /* most device types, can only handle profiles of a particular type. This
     * is the connection.type setting, as checked by nm_device_check_connection_compatible() */
    const char *connection_type_check_compatible;

    const NMLinkType *link_types;

    /* if the device MTU is set based on parent's one, this specifies
     * a delta in the MTU allowed value due the encapsulation overhead */
    guint16 mtu_parent_delta;

    /* Whether the device type is a master-type. This depends purely on the
     * type (NMDeviceClass), not the actual device instance. */
    bool is_master : 1;

    /* Force setting the MTU actually means first setting the MTU
     * to (desired_MTU-1) and then setting the desired_MTU
     * so that kernel actually applies the MTU, otherwise
     * kernel will ignore the request if the link's MTU is the
     * same as the desired one.
     *
     * This is just a workaround made for bridges (ATM) that employ
     * a auto-MTU adjust mechanism if no MTU is manually set.
     */
    bool mtu_force_set : 1;

    /* Control whether to call stage1 and stage2 callbacks also for assuming
     * a device or for external activations. In this case, the callback must
     * take care not to touch the device's configuration. */
    bool act_stage1_prepare_also_for_external_or_assume : 1;
    bool act_stage2_config_also_for_external_or_assume : 1;

    bool act_stage1_prepare_set_hwaddr_ethernet : 1;

    bool can_reapply_change_ovs_external_ids : 1;

    NMRfkillType rfkill_type : 4;

    void (*state_changed)(NMDevice           *device,
                          NMDeviceState       new_state,
                          NMDeviceState       old_state,
                          NMDeviceStateReason reason);

    void (*link_changed)(NMDevice *self, const NMPlatformLink *pllink);

    /**
     * create_and_realize():
     * @self: the #NMDevice
     * @connection: the #NMConnection being activated
     * @parent: the parent #NMDevice, if any
     * @out_plink: on success, a backing kernel network device if one exists.
     *   The returned pointer is owned by platform and only valid until the
     *   next platform operation.
     * @error: location to store error, or %NULL
     *
     * Create any backing resources (kernel devices, etc) required for this
     * device to activate @connection.  If the device is backed by a kernel
     * network device, that device should be returned in @out_plink after
     * being created.
     *
     * Returns: %TRUE on success, %FALSE on error
     */
    gboolean (*create_and_realize)(NMDevice              *self,
                                   NMConnection          *connection,
                                   NMDevice              *parent,
                                   const NMPlatformLink **out_plink,
                                   GError               **error);

    /**
     * realize_start_notify():
     * @self: the #NMDevice
     * @pllink: the #NMPlatformLink if backed by a kernel netdevice
     *
     * Hook for derived classes to be notfied during realize_start_setup()
     * and perform additional setup.
     *
     * The default implementation of NMDevice calls link_changed().
     */
    void (*realize_start_notify)(NMDevice *self, const NMPlatformLink *pllink);

    /**
     * unrealize():
     * @self: the #NMDevice
     *
     * Remove the device backing resources.
     */
    gboolean (*unrealize)(NMDevice *self, GError **error);

    /**
     * unrealize_notify():
     * @self: the #NMDevice
     *
     * Hook for derived classes to clear any properties that depend on backing resources
     * (kernel devices, etc). This is called by nm_device_unrealize() during unrealization.
     */
    void (*unrealize_notify)(NMDevice *self);

    /* Hardware state (IFF_UP) */
    gboolean (*can_unmanaged_external_down)(NMDevice *self);

    /* Carrier state (IFF_LOWER_UP) */
    void (*carrier_changed_notify)(NMDevice *, gboolean carrier);

    gboolean (*get_ip_iface_identifier)(NMDevice *self, NMUtilsIPv6IfaceId *out_iid);

    NMDeviceCapabilities (*get_generic_capabilities)(NMDevice *self);

    gboolean (*is_available)(NMDevice *self, NMDeviceCheckDevAvailableFlags flags);

    gboolean (*get_enabled)(NMDevice *self);

    void (*set_enabled)(NMDevice *self, gboolean enabled);

    /* let the subclass return additional NMPlatformRoutingRule (in form of NMPObject
     * pointers) that shall be added to the rules provided by this device.
     * The returned GPtrArray will be g_ptr_array_unref()'ed. The subclass may or
     * may not keep an additional reference and return this array again and again. */
    GPtrArray *(*get_extra_rules)(NMDevice *self);

    /* allow derived classes to override the result of nm_device_autoconnect_allowed().
     * If the value changes, the class should call nm_device_emit_recheck_auto_activate(),
     * which emits NM_DEVICE_RECHECK_AUTO_ACTIVATE signal. */
    gboolean (*get_autoconnect_allowed)(NMDevice *self);

    gboolean (*can_auto_connect)(NMDevice             *self,
                                 NMSettingsConnection *sett_conn,
                                 char                **specific_object);

    guint32 (*get_configured_mtu)(NMDevice          *self,
                                  NMDeviceMtuSource *out_source,
                                  gboolean          *out_force);

    /* allow the subclass to overwrite the routing table. This is mainly useful
     * to change from partial mode (route-table=0) to full-sync mode (route-table=254). */
    guint32 (*coerce_route_table)(NMDevice *self,
                                  int       addr_family,
                                  guint32   route_table,
                                  gboolean  is_user_config);

    const char *(*get_auto_ip_config_method)(NMDevice *self, int addr_family);

    /* Checks whether the connection is compatible with the device using
     * only the devices type and characteristics.  Does not use any live
     * network information like Wi-Fi scan lists etc.
     */
    gboolean (*check_connection_compatible)(NMDevice     *self,
                                            NMConnection *connection,
                                            GError      **error);

    /* Checks whether the connection is likely available to be activated,
     * including any live network information like scan lists.  The connection
     * is checked against the object defined by @specific_object, if given.
     * Returns TRUE if the connection is available; FALSE if not.
     *
     * The passed @flags affect whether a connection is considered
     * available or not. Adding more flags, means the connection is
     * *more* available.
     *
     * Specifying @specific_object can only reduce the availability of a connection.
     */
    gboolean (*check_connection_available)(NMDevice                      *self,
                                           NMConnection                  *connection,
                                           NMDeviceCheckConAvailableFlags flags,
                                           const char                    *specific_object,
                                           GError                       **error);

    gboolean (*complete_connection)(NMDevice            *self,
                                    NMConnection        *connection,
                                    const char          *specific_object,
                                    NMConnection *const *existing_connections,
                                    GError             **error);

    NMActStageReturn (*act_stage1_prepare)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
    NMActStageReturn (*act_stage2_config)(NMDevice *self, NMDeviceStateReason *out_failure_reason);
    void (*act_stage3_ip_config)(NMDevice *self, int addr_family);
    gboolean (*ready_for_ip_config)(NMDevice *self);

    const char *(*get_ip_method_auto)(NMDevice *self, int addr_family);

    /* Async deactivating (in the DEACTIVATING phase) */
    void (*deactivate_async)(NMDevice                  *self,
                             GCancellable              *cancellable,
                             NMDeviceDeactivateCallback callback,
                             gpointer                   user_data);

    void (*deactivate_reset_hw_addr)(NMDevice *self);

    /* Sync deactivating (in the DISCONNECTED phase) */
    void (*deactivate)(NMDevice *self);

    const char *(*get_type_description)(NMDevice *self);

    const char *(*get_s390_subchannels)(NMDevice *self);

    /* Update the connection with currently configured L2 settings */
    void (*update_connection)(NMDevice *device, NMConnection *connection);

    gboolean (*master_update_slave_connection)(NMDevice     *self,
                                               NMDevice     *slave,
                                               NMConnection *connection,
                                               GError      **error);

    gboolean (*enslave_slave)(NMDevice     *self,
                              NMDevice     *slave,
                              NMConnection *connection,
                              gboolean      configure);

    void (*release_slave)(NMDevice *self, NMDevice *slave, gboolean configure);

    void (*parent_changed_notify)(NMDevice *self,
                                  int       old_ifindex,
                                  NMDevice *old_parent,
                                  int       new_ifindex,
                                  NMDevice *new_parent);

    gboolean (*owns_iface)(NMDevice *self, const char *iface);

    NMConnection *(*new_default_connection)(NMDevice *self);

    gboolean (*unmanaged_on_quit)(NMDevice *self);

    gboolean (*can_reapply_change)(NMDevice   *self,
                                   const char *setting_name,
                                   NMSetting  *s_old,
                                   NMSetting  *s_new,
                                   GHashTable *diffs,
                                   GError    **error);

    void (*reapply_connection)(NMDevice *self, NMConnection *con_old, NMConnection *con_new);

    guint32 (*get_dhcp_timeout_for_device)(NMDevice *self, int addr_family);

    gboolean (*get_guessed_metered)(NMDevice *self);

    gboolean (*can_update_from_platform_link)(NMDevice *self, const NMPlatformLink *plink);

    gboolean (*set_platform_mtu)(NMDevice *self, guint32 mtu);

    const char *(*get_dhcp_anycast_address)(NMDevice *self);
} NMDeviceClass;

GType nm_device_get_type(void);

struct _NMDedupMultiIndex *nm_device_get_multi_index(NMDevice *self);
NMNetns                   *nm_device_get_netns(NMDevice *self);
NMPlatform                *nm_device_get_platform(NMDevice *self);

const char *nm_device_get_udi(NMDevice *dev);
const char *nm_device_get_iface(NMDevice *dev);

static inline const char *
_nm_device_get_iface(NMDevice *device)
{
    /* like nm_device_get_iface(), but gracefully accept NULL without
     * asserting. */
    return device ? nm_device_get_iface(device) : NULL;
}

int          nm_device_get_ifindex(NMDevice *dev);
gboolean     nm_device_is_software(NMDevice *dev);
gboolean     nm_device_is_real(NMDevice *dev);
const char  *nm_device_get_ip_iface(NMDevice *dev);
const char  *nm_device_get_ip_iface_from_platform(NMDevice *dev);
int          nm_device_get_ip_ifindex(const NMDevice *dev);
const char  *nm_device_get_driver(NMDevice *dev);
const char  *nm_device_get_driver_version(NMDevice *dev);
const char  *nm_device_get_type_desc(NMDevice *dev);
const char  *nm_device_get_type_description(NMDevice *dev);
NMDeviceType nm_device_get_device_type(NMDevice *dev);
NMLinkType   nm_device_get_link_type(NMDevice *dev);
NMMetered    nm_device_get_metered(NMDevice *dev);

guint32 nm_device_get_route_table(NMDevice *self, int addr_family);
guint32 nm_device_get_route_metric(NMDevice *dev, int addr_family);

guint32 nm_device_get_route_metric_default(NMDeviceType device_type);

const char *nm_device_get_hw_address(NMDevice *dev);
const char *nm_device_get_permanent_hw_address(NMDevice *self);
const char *nm_device_get_permanent_hw_address_full(NMDevice *self,
                                                    gboolean  force_freeze,
                                                    gboolean *out_is_fake);
const char *nm_device_get_initial_hw_address(NMDevice *dev);

NMDhcpConfig *nm_device_get_dhcp_config(NMDevice *dev, int addr_family);

NML3Cfg *nm_device_get_l3cfg(NMDevice *self);

const NML3ConfigData *nm_device_get_l3cd(NMDevice *self, gboolean get_commited);

void nm_device_l3cfg_commit(NMDevice *self, NML3CfgCommitType commit_type, gboolean commit_sync);

int       nm_device_parent_get_ifindex(NMDevice *dev);
NMDevice *nm_device_parent_get_device(NMDevice *dev);
void      nm_device_parent_set_ifindex(NMDevice *self, int parent_ifindex);
gboolean  nm_device_parent_notify_changed(NMDevice *self,
                                          NMDevice *change_candidate,
                                          gboolean  device_removed);

const char *nm_device_parent_find_for_connection(NMDevice   *self,
                                                 const char *current_setting_parent);

/* Master */
gboolean nm_device_is_master(NMDevice *dev);

/* Slave */
NMDevice *nm_device_get_master(NMDevice *dev);

NMActRequest          *nm_device_get_act_request(NMDevice *dev);
NMSettingsConnection  *nm_device_get_settings_connection(NMDevice *dev);
NMConnection          *nm_device_get_settings_connection_get_connection(NMDevice *self);
NMConnection          *nm_device_get_applied_connection(NMDevice *dev);
gboolean               nm_device_has_unmodified_applied_connection(NMDevice             *self,
                                                                   NMSettingCompareFlags compare_flags);
NMActivationStateFlags nm_device_get_activation_state_flags(NMDevice *self);

gpointer /* (NMSetting *) */ nm_device_get_applied_setting(NMDevice *dev, GType setting_type);

void nm_device_removed(NMDevice *self, gboolean unconfigure_ip_config);

gboolean nm_device_ignore_carrier_by_default(NMDevice *self);

gboolean nm_device_is_available(NMDevice *dev, NMDeviceCheckDevAvailableFlags flags);
gboolean nm_device_has_carrier(NMDevice *dev);

NMConnection *nm_device_generate_connection(NMDevice *self,
                                            NMDevice *master,
                                            gboolean *out_maybe_later,
                                            GError  **error);

gboolean nm_device_master_update_slave_connection(NMDevice     *master,
                                                  NMDevice     *slave,
                                                  NMConnection *connection,
                                                  GError      **error);

gboolean
nm_device_can_auto_connect(NMDevice *self, NMSettingsConnection *sett_conn, char **specific_object);

gboolean nm_device_complete_connection(NMDevice            *device,
                                       NMConnection        *connection,
                                       const char          *specific_object,
                                       NMConnection *const *existing_connections,
                                       GError             **error);

gboolean
nm_device_check_connection_compatible(NMDevice *device, NMConnection *connection, GError **error);

gboolean nm_device_check_slave_connection_compatible(NMDevice *device, NMConnection *connection);

gboolean nm_device_can_assume_connections(NMDevice *self);
gboolean nm_device_unmanage_on_quit(NMDevice *self);

gboolean nm_device_spec_match_list(NMDevice *device, const GSList *specs);
int      nm_device_spec_match_list_full(NMDevice *self, const GSList *specs, int no_match_value);

gboolean nm_device_is_activating(NMDevice *dev);
gboolean nm_device_autoconnect_allowed(NMDevice *self);

NMDeviceState nm_device_get_state(NMDevice *device);

gboolean nm_device_get_enabled(NMDevice *device);

void nm_device_set_enabled(NMDevice *device, gboolean enabled);

NMRfkillType nm_device_get_rfkill_type(NMDevice *device);

/* IPv6 prefix delegation */

void nm_device_request_ip6_prefixes(NMDevice *self, guint 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
 * @NM_UNMANAGED_SLEEPING: %TRUE when unmanaged because NM is sleeping.
 * @NM_UNMANAGED_QUITTING: %TRUE when unmanaged because NM is shutting down.
 * @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged
 * @NM_UNMANAGED_BY_TYPE: %TRUE for unmanaging device by type, like loopback.
 * @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not
 *   yet initialized. Unrealized device are also unmanaged for this reason.
 * @NM_UNMANAGED_USER_EXPLICIT: %TRUE when unmanaged by explicit user decision
 *   (e.g. via a D-Bus command)
 * @NM_UNMANAGED_USER_SETTINGS: %TRUE when unmanaged by user decision via
 *   the settings plugin (for example keyfile.unmanaged-devices or ifcfg-rh's
 *   NM_CONTROLLED=no). Although this is user-configuration (provided from
 *   the settings plugins, such as NM_CONTROLLED=no in ifcfg-rh), it cannot
 *   be overruled and is authoritative. That is because users may depend on
 *   dropping a ifcfg-rh file to ensure the device is unmanaged.
 * @NM_UNMANAGED_USER_CONF: %TRUE when unmanaged by user decision via
 *   the NetworkManager.conf ("unmanaged" in the [device] section).
 *   Contray to @NM_UNMANAGED_USER_SETTINGS, this can be overwritten via
 *   D-Bus.
 * @NM_UNMANAGED_BY_DEFAULT: %TRUE for certain device types where we unmanage
 *   them by default
 * @NM_UNMANAGED_USER_UDEV: %TRUE when unmanaged by user decision (via UDev rule)
 * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM
 * @NM_UNMANAGED_IS_SLAVE: indicates that the device is enslaved. Note that
 *   setting the NM_UNMANAGED_IS_SLAVE to %TRUE makes no sense, this flag has only
 *   meaning to set a slave device as managed if the parent is managed too.
 */
typedef enum {
    NM_UNMANAGED_NONE = 0,

    /* these flags are authoritative. If one of them is set,
     * the device cannot be managed. */
    NM_UNMANAGED_SLEEPING      = (1LL << 0),
    NM_UNMANAGED_QUITTING      = (1LL << 1),
    NM_UNMANAGED_PARENT        = (1LL << 2),
    NM_UNMANAGED_BY_TYPE       = (1LL << 3),
    NM_UNMANAGED_PLATFORM_INIT = (1LL << 4),
    NM_UNMANAGED_USER_EXPLICIT = (1LL << 5),
    NM_UNMANAGED_USER_SETTINGS = (1LL << 6),

    /* These flags can be non-effective and be overwritten
     * by other flags. */
    NM_UNMANAGED_BY_DEFAULT    = (1LL << 7),
    NM_UNMANAGED_USER_CONF     = (1LL << 8),
    NM_UNMANAGED_USER_UDEV     = (1LL << 9),
    NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 10),
    NM_UNMANAGED_IS_SLAVE      = (1LL << 11),

    NM_UNMANAGED_ALL = ((1LL << 12) - 1),
} NMUnmanagedFlags;

typedef enum {
    NM_UNMAN_FLAG_OP_SET_MANAGED   = FALSE,
    NM_UNMAN_FLAG_OP_SET_UNMANAGED = TRUE,
    NM_UNMAN_FLAG_OP_FORGET        = 2,
} NMUnmanFlagOp;

const char *nm_unmanaged_flags2str(NMUnmanagedFlags flags, char *buf, gsize len);

gboolean         nm_device_get_managed(NMDevice *device, gboolean for_user_request);
NMUnmanagedFlags nm_device_get_unmanaged_mask(NMDevice *device, NMUnmanagedFlags flag);
NMUnmanagedFlags nm_device_get_unmanaged_flags(NMDevice *device, NMUnmanagedFlags flag);
void nm_device_set_unmanaged_flags(NMDevice *device, NMUnmanagedFlags flags, NMUnmanFlagOp set_op);
void nm_device_set_unmanaged_by_flags(NMDevice           *device,
                                      NMUnmanagedFlags    flags,
                                      NMUnmanFlagOp       set_op,
                                      NMDeviceStateReason reason);
void nm_device_set_unmanaged_by_flags_queue(NMDevice           *self,
                                            NMUnmanagedFlags    flags,
                                            NMUnmanFlagOp       set_op,
                                            NMDeviceStateReason reason);
void nm_device_set_unmanaged_by_user_settings(NMDevice *self, gboolean now);
void nm_device_set_unmanaged_by_user_udev(NMDevice *self);
void nm_device_set_unmanaged_by_user_conf(NMDevice *self);
void nm_device_set_unmanaged_by_quitting(NMDevice *device);

gboolean nm_device_check_unrealized_device_managed(NMDevice *self);

gboolean nm_device_is_nm_owned(NMDevice *device);

gboolean nm_device_has_capability(NMDevice *self, NMDeviceCapabilities caps);

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

void nm_device_assume_state_get(NMDevice    *self,
                                gboolean    *out_assume_state_guess_assume,
                                const char **out_assume_state_connection_uuid);
void nm_device_assume_state_reset(NMDevice *self);

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

gboolean nm_device_realize_start(NMDevice             *device,
                                 const NMPlatformLink *plink,
                                 gboolean              assume_state_guess_assume,
                                 const char           *assume_state_connection_uuid,
                                 gboolean              set_nm_owned,
                                 NMUnmanFlagOp         unmanaged_user_explicit,
                                 gboolean             *out_compatible,
                                 GError              **error);
void     nm_device_realize_finish(NMDevice *self, const NMPlatformLink *plink);
gboolean nm_device_create_and_realize(NMDevice     *self,
                                      NMConnection *connection,
                                      NMDevice     *parent,
                                      GError      **error);
gboolean nm_device_unrealize(NMDevice *device, gboolean remove_resources, GError **error);

void nm_device_update_from_platform_link(NMDevice *self, const NMPlatformLink *plink);

typedef enum {
    NM_DEVICE_AUTOCONNECT_BLOCKED_NONE = 0,

    NM_DEVICE_AUTOCONNECT_BLOCKED_USER = (1LL << 0),

    NM_DEVICE_AUTOCONNECT_BLOCKED_WRONG_PIN         = (1LL << 1),
    NM_DEVICE_AUTOCONNECT_BLOCKED_MANUAL_DISCONNECT = (1LL << 2),
    NM_DEVICE_AUTOCONNECT_BLOCKED_SIM_MISSING       = (1LL << 3),
    NM_DEVICE_AUTOCONNECT_BLOCKED_INIT_FAILED       = (1LL << 4),

    _NM_DEVICE_AUTOCONNECT_BLOCKED_LAST,

    NM_DEVICE_AUTOCONNECT_BLOCKED_ALL = (((_NM_DEVICE_AUTOCONNECT_BLOCKED_LAST - 1) << 1) - 1),

    NM_DEVICE_AUTOCONNECT_BLOCKED_INTERNAL =
        NM_DEVICE_AUTOCONNECT_BLOCKED_ALL & ~NM_DEVICE_AUTOCONNECT_BLOCKED_USER,
} NMDeviceAutoconnectBlockedFlags;

NMDeviceAutoconnectBlockedFlags
nm_device_autoconnect_blocked_get(NMDevice *device, NMDeviceAutoconnectBlockedFlags mask);

void nm_device_autoconnect_blocked_set_full(NMDevice                       *device,
                                            NMDeviceAutoconnectBlockedFlags mask,
                                            NMDeviceAutoconnectBlockedFlags values);

static inline void
nm_device_autoconnect_blocked_set(NMDevice *device, NMDeviceAutoconnectBlockedFlags mask)
{
    nm_device_autoconnect_blocked_set_full(device, mask, mask);
}

static inline void
nm_device_autoconnect_blocked_unset(NMDevice *device, NMDeviceAutoconnectBlockedFlags mask)
{
    nm_device_autoconnect_blocked_set_full(device, mask, NM_DEVICE_AUTOCONNECT_BLOCKED_NONE);
}

void nm_device_emit_recheck_auto_activate(NMDevice *device);

NMDeviceSysIfaceState nm_device_sys_iface_state_get(NMDevice *device);

gboolean nm_device_sys_iface_state_is_external(NMDevice *self);
gboolean nm_device_sys_iface_state_is_external_or_assume(NMDevice *self);

void nm_device_sys_iface_state_set(NMDevice *device, NMDeviceSysIfaceState sys_iface_state);

void nm_device_state_changed(NMDevice *device, NMDeviceState state, NMDeviceStateReason reason);

void nm_device_queue_state(NMDevice *self, NMDeviceState state, NMDeviceStateReason reason);

gboolean nm_device_get_firmware_missing(NMDevice *self);

void nm_device_disconnect_active_connection(NMActiveConnection           *active,
                                            NMDeviceStateReason           device_reason,
                                            NMActiveConnectionStateReason active_reason);

void nm_device_queue_activation(NMDevice *device, NMActRequest *req);

gboolean nm_device_supports_vlans(NMDevice *device);

gboolean
nm_device_add_pending_action(NMDevice *device, const char *action, gboolean assert_not_yet_pending);
gboolean
nm_device_remove_pending_action(NMDevice *device, const char *action, gboolean assert_is_pending);
const char *nm_device_has_pending_action_reason(NMDevice *device);

static inline gboolean
nm_device_has_pending_action(NMDevice *device)
{
    return !!nm_device_has_pending_action_reason(device);
}

NMSettingsConnection *
nm_device_get_best_connection(NMDevice *device, const char *specific_object, GError **error);

gboolean nm_device_check_connection_available(NMDevice                      *device,
                                              NMConnection                  *connection,
                                              NMDeviceCheckConAvailableFlags flags,
                                              const char                    *specific_object,
                                              GError                       **error);

void nm_device_notify_availability_maybe_changed(NMDevice *self);

gboolean nm_device_owns_iface(NMDevice *device, const char *iface);

NMConnection *nm_device_new_default_connection(NMDevice *self);

const NMPObject *nm_device_get_best_default_route(NMDevice *self, int addr_family);

gboolean nm_device_reapply(NMDevice *self, NMConnection *connection, GError **error);
void     nm_device_reapply_settings_immediately(NMDevice *self);

void nm_device_update_firewall_zone(NMDevice *self);
void nm_device_update_metered(NMDevice *self);

gboolean nm_device_update_hw_address(NMDevice *self);
void     nm_device_update_initial_hw_address(NMDevice *self);
void     nm_device_update_permanent_hw_address(NMDevice *self, gboolean force_freeze);
void     nm_device_update_dynamic_ip_setup(NMDevice *self);
guint    nm_device_get_supplicant_timeout(NMDevice *self);

gboolean nm_device_auth_retries_try_next(NMDevice *self);

gboolean nm_device_hw_addr_get_cloned(NMDevice     *self,
                                      NMConnection *connection,
                                      gboolean      is_wifi,
                                      char        **hwaddr,
                                      gboolean     *preserve,
                                      GError      **error);

typedef struct _NMDeviceConnectivityHandle NMDeviceConnectivityHandle;

typedef void (*NMDeviceConnectivityCallback)(NMDevice                   *self,
                                             NMDeviceConnectivityHandle *handle,
                                             NMConnectivityState         state,
                                             GError                     *error,
                                             gpointer                    user_data);

void nm_device_check_connectivity_update_interval(NMDevice *self);

NMDeviceConnectivityHandle *nm_device_check_connectivity(NMDevice                    *self,
                                                         int                          addr_family,
                                                         NMDeviceConnectivityCallback callback,
                                                         gpointer                     user_data);

void nm_device_check_connectivity_cancel(NMDeviceConnectivityHandle *handle);

NMConnectivityState nm_device_get_connectivity_state(NMDevice *self, int addr_family);

typedef struct _NMBtVTableNetworkServer NMBtVTableNetworkServer;

typedef void (*NMBtVTableRegisterCallback)(GError *error, gpointer user_data);

struct _NMBtVTableNetworkServer {
    gboolean (*is_available)(const NMBtVTableNetworkServer *vtable,
                             const char                    *addr,
                             NMDevice                      *device_accept_busy);

    gboolean (*register_bridge)(const NMBtVTableNetworkServer *vtable,
                                const char                    *addr,
                                NMDevice                      *device,
                                GCancellable                  *cancellable,
                                NMBtVTableRegisterCallback     callback,
                                gpointer                       callback_user_data,
                                GError                       **error);
    gboolean (*unregister_bridge)(const NMBtVTableNetworkServer *vtable, NMDevice *device);
};

gboolean nm_device_is_vpn(NMDevice *self);

const char *
nm_device_get_hostname_from_dns_lookup(NMDevice *self, int addr_family, gboolean *out_pending);

void nm_device_clear_dns_lookup_data(NMDevice *self);

#endif /* __NETWORKMANAGER_DEVICE_H__ */