Blame src/core/nm-policy.c

Packit Service 5ffa24
/* SPDX-License-Identifier: GPL-2.0-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Copyright (C) 2004 - 2013 Red Hat, Inc.
Packit Service 5ffa24
 * Copyright (C) 2007 - 2008 Novell, Inc.
Packit Service 5ffa24
 */
Packit Service 5ffa24
Packit Service 5ffa24
#include "nm-default.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include "nm-policy.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include <unistd.h>
Packit Service 5ffa24
#include <netdb.h>
Packit Service 5ffa24
Packit Service 5ffa24
#include "NetworkManagerUtils.h"
Packit Service 5ffa24
#include "nm-act-request.h"
Packit Service 5ffa24
#include "nm-keep-alive.h"
Packit Service 5ffa24
#include "devices/nm-device.h"
Packit Service 5ffa24
#include "nm-setting-ip4-config.h"
Packit Service 5ffa24
#include "nm-setting-connection.h"
Packit Service 5ffa24
#include "platform/nm-platform.h"
Packit Service 5ffa24
#include "dns/nm-dns-manager.h"
Packit Service 5ffa24
#include "vpn/nm-vpn-manager.h"
Packit Service 5ffa24
#include "nm-auth-utils.h"
Packit Service 5ffa24
#include "nm-firewall-manager.h"
Packit Service 5ffa24
#include "nm-dispatcher.h"
Packit Service 5ffa24
#include "nm-utils.h"
Packit Service 5ffa24
#include "nm-core-internal.h"
Packit Service 5ffa24
#include "nm-manager.h"
Packit Service 5ffa24
#include "settings/nm-settings.h"
Packit Service 5ffa24
#include "settings/nm-settings-connection.h"
Packit Service 5ffa24
#include "settings/nm-agent-manager.h"
Packit Service 5ffa24
#include "nm-dhcp-config.h"
Packit Service 5ffa24
#include "nm-config.h"
Packit Service 5ffa24
#include "nm-netns.h"
Packit Service 5ffa24
#include "nm-hostname-manager.h"
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
NM_GOBJECT_PROPERTIES_DEFINE(NMPolicy,
Packit Service 5ffa24
                             PROP_MANAGER,
Packit Service 5ffa24
                             PROP_SETTINGS,
Packit Service 5ffa24
                             PROP_DEFAULT_IP4_AC,
Packit Service 5ffa24
                             PROP_DEFAULT_IP6_AC,
Packit Service 5ffa24
                             PROP_ACTIVATING_IP4_AC,
Packit Service 5ffa24
                             PROP_ACTIVATING_IP6_AC, );
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    NMManager *        manager;
Packit Service 5ffa24
    NMNetns *          netns;
Packit Service 5ffa24
    NMFirewallManager *firewall_manager;
Packit Service 5ffa24
    CList              pending_activation_checks;
Packit Service 5ffa24
Packit Service 5ffa24
    NMAgentManager *agent_mgr;
Packit Service 5ffa24
Packit Service 5ffa24
    GHashTable *devices;
Packit Service 5ffa24
    GHashTable *pending_active_connections;
Packit Service 5ffa24
Packit Service 5ffa24
    GSList *pending_secondaries;
Packit Service 5ffa24
Packit Service 5ffa24
    NMSettings *settings;
Packit Service 5ffa24
Packit Service 5ffa24
    NMHostnameManager *hostname_manager;
Packit Service 5ffa24
Packit Service 5ffa24
    NMActiveConnection *default_ac4, *activating_ac4;
Packit Service 5ffa24
    NMActiveConnection *default_ac6, *activating_ac6;
Packit Service 5ffa24
Packit Service 5ffa24
    NMDnsManager *dns_manager;
Packit Service 5ffa24
    gulong        config_changed_id;
Packit Service 5ffa24
Packit Service 5ffa24
    guint reset_retries_id; /* idle handler for resetting the retries count */
Packit Service 5ffa24
Packit Service 5ffa24
    guint schedule_activate_all_id; /* idle handler for schedule_activate_all(). */
Packit Service 5ffa24
Packit Service 5ffa24
    NMPolicyHostnameMode hostname_mode;
Packit Service 5ffa24
    char *               orig_hostname; /* hostname at NM start time */
Packit Service 5ffa24
    char *               cur_hostname;  /* hostname we want to assign */
Packit Service 5ffa24
    char *
Packit Service 5ffa24
        last_hostname; /* last hostname NM set (to detect if someone else changed it in the meanwhile) */
Packit Service 5ffa24
Packit Service 5ffa24
    bool changing_hostname : 1; /* hostname set operation in progress */
Packit Service 5ffa24
    bool dhcp_hostname : 1;     /* current hostname was set from dhcp */
Packit Service 5ffa24
    bool updating_dns : 1;
Packit Service 5ffa24
Packit Service 5ffa24
    GArray *ip6_prefix_delegations; /* pool of ip6 prefixes delegated to all devices */
Packit Service 5ffa24
} NMPolicyPrivate;
Packit Service 5ffa24
Packit Service 5ffa24
struct _NMPolicy {
Packit Service 5ffa24
    GObject         parent;
Packit Service 5ffa24
    NMPolicyPrivate _priv;
Packit Service 5ffa24
};
Packit Service 5ffa24
Packit Service 5ffa24
struct _NMPolicyClass {
Packit Service 5ffa24
    GObjectClass parent;
Packit Service 5ffa24
};
Packit Service 5ffa24
Packit Service 5ffa24
G_DEFINE_TYPE(NMPolicy, nm_policy, G_TYPE_OBJECT)
Packit Service 5ffa24
Packit Service 5ffa24
#define NM_POLICY_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMPolicy, NM_IS_POLICY)
Packit Service 5ffa24
Packit Service 5ffa24
static NMPolicy *
Packit Service 5ffa24
_PRIV_TO_SELF(NMPolicyPrivate *priv)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *self;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    self = (NMPolicy *) (((char *) priv) - G_STRUCT_OFFSET(NMPolicy, _priv));
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_POLICY(self));
Packit Service 5ffa24
    return self;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
#define _NMLOG_PREFIX_NAME "policy"
Packit Service 5ffa24
#undef _NMLOG_ENABLED
Packit Service 5ffa24
#define _NMLOG_ENABLED(level, domain) (nm_logging_enabled((level), (domain)))
Packit Service 5ffa24
#define _NMLOG(level, domain, ...)                                         \
Packit Service 5ffa24
    G_STMT_START                                                           \
Packit Service 5ffa24
    {                                                                      \
Packit Service 5ffa24
        nm_log((level),                                                    \
Packit Service 5ffa24
               (domain),                                                   \
Packit Service 5ffa24
               NULL,                                                       \
Packit Service 5ffa24
               NULL,                                                       \
Packit Service 5ffa24
               "%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__),                    \
Packit Service 5ffa24
               _NMLOG_PREFIX_NAME ": " _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
Packit Service 5ffa24
    }                                                                      \
Packit Service 5ffa24
    G_STMT_END
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void      update_system_hostname(NMPolicy *self, const char *msg);
Packit Service 5ffa24
static void      schedule_activate_all(NMPolicy *self);
Packit Service 5ffa24
static void      schedule_activate_check(NMPolicy *self, NMDevice *device);
Packit Service 5ffa24
static NMDevice *get_default_device(NMPolicy *self, int addr_family);
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_dns_manager_set_ip_config(NMDnsManager *    dns_manager,
Packit Service 5ffa24
                           NMIPConfig *      ip_config,
Packit Service 5ffa24
                           NMDnsIPConfigType ip_config_type,
Packit Service 5ffa24
                           NMDevice *        device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if (device && nm_device_sys_iface_state_is_external(device)) {
Packit Service 5ffa24
        nm_dns_manager_set_ip_config(dns_manager, ip_config, NM_DNS_IP_CONFIG_TYPE_REMOVED);
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (NM_IN_SET(ip_config_type, NM_DNS_IP_CONFIG_TYPE_DEFAULT, NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE)
Packit Service 5ffa24
        && device
Packit Service 5ffa24
        && nm_device_get_route_metric_default(nm_device_get_device_type(device))
Packit Service 5ffa24
               == NM_VPN_ROUTE_METRIC_DEFAULT) {
Packit Service 5ffa24
        /* some device types are inherently VPN. */
Packit Service 5ffa24
        ip_config_type = NM_DNS_IP_CONFIG_TYPE_VPN;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_set_ip_config(dns_manager, ip_config, ip_config_type);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    NMPlatformIP6Address prefix;
Packit Service 5ffa24
    NMDevice *           device;      /* The requesting ("uplink") device */
Packit Service 5ffa24
    guint64              next_subnet; /* Cache of the next subnet number to be
Packit Service 5ffa24
                                       * assigned from this prefix */
Packit Service 5ffa24
    GHashTable *         subnets;     /* ifindex -> NMPlatformIP6Address */
Packit Service 5ffa24
} IP6PrefixDelegation;
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_clear_ip6_subnet(gpointer key, gpointer value, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPlatformIP6Address *subnet = value;
Packit Service 5ffa24
    NMDevice *device = nm_manager_get_device_by_ifindex(NM_MANAGER_GET, GPOINTER_TO_INT(key));
Packit Service 5ffa24
Packit Service 5ffa24
    if (device) {
Packit Service 5ffa24
        /* We can not remove a subnet we already started announcing.
Packit Service 5ffa24
         * Just un-prefer it. */
Packit Service 5ffa24
        subnet->preferred = 0;
Packit Service 5ffa24
        nm_device_use_ip6_subnet(device, subnet);
Packit Service 5ffa24
    }
Packit Service 5ffa24
    g_slice_free(NMPlatformIP6Address, subnet);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
clear_ip6_prefix_delegation(gpointer data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    IP6PrefixDelegation *delegation = data;
Packit Service 5ffa24
    char                 sbuf[NM_UTILS_INET_ADDRSTRLEN];
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD(LOGD_IP6,
Packit Service 5ffa24
          "ipv6-pd: undelegating prefix %s/%d",
Packit Service 5ffa24
          _nm_utils_inet6_ntop(&delegation->prefix.address, sbuf),
Packit Service 5ffa24
          delegation->prefix.plen);
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_foreach(delegation->subnets, _clear_ip6_subnet, NULL);
Packit Service 5ffa24
    g_hash_table_destroy(delegation->subnets);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
expire_ip6_delegations(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *    priv       = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    guint32              now        = nm_utils_get_monotonic_timestamp_sec();
Packit Service 5ffa24
    IP6PrefixDelegation *delegation = NULL;
Packit Service 5ffa24
    guint                i;
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
Packit Service 5ffa24
        delegation = &g_array_index(priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
Packit Service 5ffa24
        if (delegation->prefix.timestamp + delegation->prefix.lifetime < now)
Packit Service 5ffa24
            g_array_remove_index_fast(priv->ip6_prefix_delegations, i);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Try to obtain a new subnet for a particular active connection from given
Packit Service 5ffa24
 * delegated prefix, possibly reusing the existing subnet.
Packit Service 5ffa24
 * Return value of FALSE indicates no more subnets are available from
Packit Service 5ffa24
 * this prefix (and other prefix should be used -- and requested if necessary).
Packit Service 5ffa24
 */
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
ip6_subnet_from_delegation(IP6PrefixDelegation *delegation, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPlatformIP6Address *subnet;
Packit Service 5ffa24
    int                   ifindex = nm_device_get_ifindex(device);
Packit Service 5ffa24
    char                  sbuf[NM_UTILS_INET_ADDRSTRLEN];
Packit Service 5ffa24
Packit Service 5ffa24
    subnet = g_hash_table_lookup(delegation->subnets, GINT_TO_POINTER(ifindex));
Packit Service 5ffa24
    if (!subnet) {
Packit Service 5ffa24
        /* Check for out-of-prefixes condition. */
Packit Service 5ffa24
        if (delegation->next_subnet >= (1 << (64 - delegation->prefix.plen))) {
Packit Service 5ffa24
            _LOGD(LOGD_IP6,
Packit Service 5ffa24
                  "ipv6-pd: no more prefixes in %s/%d",
Packit Service 5ffa24
                  _nm_utils_inet6_ntop(&delegation->prefix.address, sbuf),
Packit Service 5ffa24
                  delegation->prefix.plen);
Packit Service 5ffa24
            return FALSE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* Allocate a new subnet. */
Packit Service 5ffa24
        subnet = g_slice_new0(NMPlatformIP6Address);
Packit Service 5ffa24
        g_hash_table_insert(delegation->subnets, GINT_TO_POINTER(ifindex), subnet);
Packit Service 5ffa24
Packit Service 5ffa24
        subnet->plen = 64;
Packit Service 5ffa24
        subnet->address.s6_addr32[0] =
Packit Service 5ffa24
            delegation->prefix.address.s6_addr32[0] | htonl(delegation->next_subnet >> 32);
Packit Service 5ffa24
        subnet->address.s6_addr32[1] =
Packit Service 5ffa24
            delegation->prefix.address.s6_addr32[1] | htonl(delegation->next_subnet);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Out subnet pool management is pretty unsophisticated. We only add
Packit Service 5ffa24
         * the subnets and index them by ifindex. That keeps the implementation
Packit Service 5ffa24
         * simple and the dead entries make it easy to reuse the same subnet on
Packit Service 5ffa24
         * subsequent activations. On the other hand they may waste the subnet
Packit Service 5ffa24
         * space. */
Packit Service 5ffa24
        delegation->next_subnet++;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    subnet->timestamp = delegation->prefix.timestamp;
Packit Service 5ffa24
    subnet->lifetime  = delegation->prefix.lifetime;
Packit Service 5ffa24
    subnet->preferred = delegation->prefix.preferred;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD(LOGD_IP6,
Packit Service 5ffa24
          "ipv6-pd: %s allocated from a /%d prefix on %s",
Packit Service 5ffa24
          _nm_utils_inet6_ntop(&subnet->address, sbuf),
Packit Service 5ffa24
          delegation->prefix.plen,
Packit Service 5ffa24
          nm_device_get_iface(device));
Packit Service 5ffa24
Packit Service 5ffa24
    nm_device_use_ip6_subnet(device, subnet);
Packit Service 5ffa24
Packit Service 5ffa24
    return TRUE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Try to obtain a subnet from each prefix delegated to given requesting
Packit Service 5ffa24
 * ("uplink") device and assign it to the downlink device.
Packit Service 5ffa24
 * Requests a new prefix if no subnet could be found.
Packit Service 5ffa24
 */
Packit Service 5ffa24
static void
Packit Service 5ffa24
ip6_subnet_from_device(NMPolicy *self, NMDevice *from_device, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *    priv          = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    IP6PrefixDelegation *delegation    = NULL;
Packit Service 5ffa24
    gboolean             got_subnet    = FALSE;
Packit Service 5ffa24
    guint                have_prefixes = 0;
Packit Service 5ffa24
    guint                i;
Packit Service 5ffa24
Packit Service 5ffa24
    expire_ip6_delegations(self);
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
Packit Service 5ffa24
        delegation = &g_array_index(priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
Packit Service 5ffa24
Packit Service 5ffa24
        if (delegation->device != from_device)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (ip6_subnet_from_delegation(delegation, device))
Packit Service 5ffa24
            got_subnet = TRUE;
Packit Service 5ffa24
        have_prefixes++;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!got_subnet) {
Packit Service 5ffa24
        _LOGI(LOGD_IP6,
Packit Service 5ffa24
              "ipv6-pd: none of %u prefixes of %s can be shared on %s",
Packit Service 5ffa24
              have_prefixes,
Packit Service 5ffa24
              nm_device_get_iface(from_device),
Packit Service 5ffa24
              nm_device_get_iface(device));
Packit Service 5ffa24
        nm_device_request_ip6_prefixes(from_device, have_prefixes + 1);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
ip6_remove_device_prefix_delegations(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *    priv       = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    IP6PrefixDelegation *delegation = NULL;
Packit Service 5ffa24
    guint                i;
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
Packit Service 5ffa24
        delegation = &g_array_index(priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
Packit Service 5ffa24
        if (delegation->device == device)
Packit Service 5ffa24
            g_array_remove_index_fast(priv->ip6_prefix_delegations, i);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_ip6_prefix_delegated(NMDevice *device, NMPlatformIP6Address *prefix, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *    priv       = user_data;
Packit Service 5ffa24
    NMPolicy *           self       = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    IP6PrefixDelegation *delegation = NULL;
Packit Service 5ffa24
    guint                i;
Packit Service 5ffa24
    const CList *        tmp_list;
Packit Service 5ffa24
    NMActiveConnection * ac;
Packit Service 5ffa24
    char                 sbuf[NM_UTILS_INET_ADDRSTRLEN];
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI(LOGD_IP6,
Packit Service 5ffa24
          "ipv6-pd: received a prefix %s/%d from %s",
Packit Service 5ffa24
          _nm_utils_inet6_ntop(&prefix->address, sbuf),
Packit Service 5ffa24
          prefix->plen,
Packit Service 5ffa24
          nm_device_get_iface(device));
Packit Service 5ffa24
Packit Service 5ffa24
    expire_ip6_delegations(self);
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < priv->ip6_prefix_delegations->len; i++) {
Packit Service 5ffa24
        /* Look for an already known prefix to update. */
Packit Service 5ffa24
        delegation = &g_array_index(priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
Packit Service 5ffa24
        if (IN6_ARE_ADDR_EQUAL(&delegation->prefix.address, &prefix->address))
Packit Service 5ffa24
            break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (i == priv->ip6_prefix_delegations->len) {
Packit Service 5ffa24
        /* Allocate a delegation for new prefix. */
Packit Service 5ffa24
        g_array_set_size(priv->ip6_prefix_delegations, i + 1);
Packit Service 5ffa24
        delegation          = &g_array_index(priv->ip6_prefix_delegations, IP6PrefixDelegation, i);
Packit Service 5ffa24
        delegation->subnets = g_hash_table_new(nm_direct_hash, NULL);
Packit Service 5ffa24
        delegation->next_subnet = 0;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    delegation->device = device;
Packit Service 5ffa24
    delegation->prefix = *prefix;
Packit Service 5ffa24
Packit Service 5ffa24
    /* The newly activated connections are added to the end of the list,
Packit Service 5ffa24
     * so traversing it from the end makes it likely for newly
Packit Service 5ffa24
     * activated connections that have no subnet assigned to be served
Packit Service 5ffa24
     * first. That is a simple yet fair policy, which is good. */
Packit Service 5ffa24
    nm_manager_for_each_active_connection_prev (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
        NMDevice *to_device;
Packit Service 5ffa24
Packit Service 5ffa24
        to_device = nm_active_connection_get_device(ac);
Packit Service 5ffa24
        if (nm_device_needs_ip6_subnet(to_device))
Packit Service 5ffa24
            ip6_subnet_from_delegation(delegation, to_device);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_ip6_subnet_needed(NMDevice *device, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD(LOGD_IP6, "ipv6-pd: %s needs a subnet", nm_device_get_iface(device));
Packit Service 5ffa24
Packit Service 5ffa24
    if (!priv->default_ac6) {
Packit Service 5ffa24
        /* We request the prefixes when the default IPv6 device is set. */
Packit Service 5ffa24
        _LOGI(LOGD_IP6,
Packit Service 5ffa24
              "ipv6-pd: no device to obtain a subnet to share on %s from",
Packit Service 5ffa24
              nm_device_get_iface(device));
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    ip6_subnet_from_device(self, get_default_device(self, AF_INET6), device);
Packit Service 5ffa24
    nm_device_copy_ip6_dns_config(device, get_default_device(self, AF_INET6));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static NMDevice *
Packit Service 5ffa24
get_default_device(NMPolicy *self, int addr_family)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert_addr_family(addr_family);
Packit Service 5ffa24
Packit Service 5ffa24
    ac = (addr_family == AF_INET) ? priv->default_ac4 : priv->default_ac6;
Packit Service 5ffa24
Packit Service 5ffa24
    return ac ? nm_active_connection_get_device(ac) : NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static NMActiveConnection *
Packit Service 5ffa24
get_best_active_connection(NMPolicy *self, int addr_family, gboolean fully_activated)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *       tmp_lst;
Packit Service 5ffa24
    NMDevice *          device;
Packit Service 5ffa24
    guint32             best_metric             = G_MAXUINT32;
Packit Service 5ffa24
    gboolean            best_is_fully_activated = FALSE;
Packit Service 5ffa24
    NMActiveConnection *best_ac, *prev_ac;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service 5ffa24
Packit Service 5ffa24
    /* we prefer the current AC in case of identical metric.
Packit Service 5ffa24
     * Hence, try that one first. */
Packit Service 5ffa24
    prev_ac = addr_family == AF_INET ? (fully_activated ? priv->default_ac4 : priv->activating_ac4)
Packit Service 5ffa24
                                     : (fully_activated ? priv->default_ac6 : priv->activating_ac6);
Packit Service 5ffa24
    best_ac = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_device (priv->manager, device, tmp_lst) {
Packit Service 5ffa24
        NMDeviceState       state;
Packit Service 5ffa24
        const NMPObject *   r;
Packit Service 5ffa24
        NMActiveConnection *ac;
Packit Service 5ffa24
        NMConnection *      connection;
Packit Service 5ffa24
        guint32             metric;
Packit Service 5ffa24
        gboolean            is_fully_activated;
Packit Service 5ffa24
Packit Service 5ffa24
        state = nm_device_get_state(device);
Packit Service 5ffa24
        if (state <= NM_DEVICE_STATE_DISCONNECTED || state >= NM_DEVICE_STATE_DEACTIVATING)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_device_sys_iface_state_is_external(device))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        r = nm_device_get_best_default_route(device, addr_family);
Packit Service 5ffa24
        if (r) {
Packit Service 5ffa24
            /* NOTE: the best route might have rt_source NM_IP_CONFIG_SOURCE_VPN,
Packit Service 5ffa24
             * which means it was injected by a VPN, not added by device.
Packit Service 5ffa24
             *
Packit Service 5ffa24
             * In this case, is it really the best device? Why do we even need the best
Packit Service 5ffa24
             * device?? */
Packit Service 5ffa24
            metric             = NMP_OBJECT_CAST_IP_ROUTE(r)->metric;
Packit Service 5ffa24
            is_fully_activated = TRUE;
Packit Service 5ffa24
        } else if (!fully_activated && (connection = nm_device_get_applied_connection(device))
Packit Service 5ffa24
                   && nm_utils_connection_has_default_route(connection, addr_family, NULL)) {
Packit Service 5ffa24
            metric             = nm_device_get_route_metric(device, addr_family);
Packit Service 5ffa24
            is_fully_activated = FALSE;
Packit Service 5ffa24
        } else
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        ac = (NMActiveConnection *) nm_device_get_act_request(device);
Packit Service 5ffa24
        nm_assert(ac);
Packit Service 5ffa24
Packit Service 5ffa24
        if (!best_ac || (!best_is_fully_activated && is_fully_activated)
Packit Service 5ffa24
            || (metric < best_metric || (metric == best_metric && ac == prev_ac))) {
Packit Service 5ffa24
            best_ac                 = ac;
Packit Service 5ffa24
            best_metric             = metric;
Packit Service 5ffa24
            best_is_fully_activated = is_fully_activated;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!fully_activated && best_ac && best_is_fully_activated) {
Packit Service 5ffa24
        /* There's a best activating AC only if the best device
Packit Service 5ffa24
         * among all activating and already-activated devices is a
Packit Service 5ffa24
         * still-activating one. */
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return best_ac;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
all_devices_not_active(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *    tmp_lst;
Packit Service 5ffa24
    NMDevice *       device;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_device (priv->manager, device, tmp_lst) {
Packit Service 5ffa24
        NMDeviceState state;
Packit Service 5ffa24
Packit Service 5ffa24
        state = nm_device_get_state(device);
Packit Service 5ffa24
        if (state <= NM_DEVICE_STATE_DISCONNECTED || state >= NM_DEVICE_STATE_DEACTIVATING) {
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
        return FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return TRUE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
#define FALLBACK_HOSTNAME4 "localhost.localdomain"
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
settings_set_hostname_cb(const char *hostname, gboolean result, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(user_data);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    int              ret  = 0;
Packit Service 5ffa24
    int              errsv;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!result) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "set-hostname: hostname set via dbus failed, fallback to \"sethostname\"");
Packit Service 5ffa24
        ret = sethostname(hostname, strlen(hostname));
Packit Service 5ffa24
        if (ret != 0) {
Packit Service 5ffa24
            errsv = errno;
Packit Service 5ffa24
            _LOGW(LOGD_DNS,
Packit Service 5ffa24
                  "set-hostname: couldn't set the system hostname to '%s': (%d) %s",
Packit Service 5ffa24
                  hostname,
Packit Service 5ffa24
                  errsv,
Packit Service 5ffa24
                  nm_strerror_native(errsv));
Packit Service 5ffa24
            if (errsv == EPERM)
Packit Service 5ffa24
                _LOGW(
Packit Service 5ffa24
                    LOGD_DNS,
Packit Service 5ffa24
                    "set-hostname: you should use hostnamed when systemd hardening is in effect!");
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    priv->changing_hostname = FALSE;
Packit Service 5ffa24
    if (!ret)
Packit Service 5ffa24
        nm_dispatcher_call_hostname(NULL, NULL, NULL);
Packit Service 5ffa24
    g_object_unref(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
#define HOST_NAME_BUFSIZE (HOST_NAME_MAX + 2)
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
_get_hostname(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv     = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    char *           hostname = NULL;
Packit Service 5ffa24
    int              errsv;
Packit Service 5ffa24
Packit Service 5ffa24
    /* If there is an in-progress hostname change, return
Packit Service 5ffa24
     * the last hostname set as would be set soon...
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (priv->changing_hostname) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "get-hostname: \"%s\" (last on set)", priv->last_hostname);
Packit Service 5ffa24
        return g_strdup(priv->last_hostname);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* try to get the hostname via dbus... */
Packit Service 5ffa24
    if (nm_hostname_manager_get_transient_hostname(priv->hostname_manager, &hostname)) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "get-hostname: \"%s\" (from dbus)", hostname);
Packit Service 5ffa24
        return hostname;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* ...or retrieve it by yourself */
Packit Service 5ffa24
    hostname = g_malloc(HOST_NAME_BUFSIZE);
Packit Service 5ffa24
    if (gethostname(hostname, HOST_NAME_BUFSIZE - 1) != 0) {
Packit Service 5ffa24
        errsv = errno;
Packit Service 5ffa24
        _LOGT(LOGD_DNS,
Packit Service 5ffa24
              "get-hostname: couldn't get the system hostname: (%d) %s",
Packit Service 5ffa24
              errsv,
Packit Service 5ffa24
              nm_strerror_native(errsv));
Packit Service 5ffa24
        g_free(hostname);
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* the name may be truncated... */
Packit Service 5ffa24
    hostname[HOST_NAME_BUFSIZE - 1] = '\0';
Packit Service 5ffa24
    if (strlen(hostname) >= HOST_NAME_BUFSIZE - 1) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "get-hostname: system hostname too long: \"%s\"", hostname);
Packit Service 5ffa24
        g_free(hostname);
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGT(LOGD_DNS, "get-hostname: \"%s\"", hostname);
Packit Service 5ffa24
    return hostname;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_set_hostname(NMPolicy *self, const char *new_hostname, const char *msg)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv         = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    gs_free char *   old_hostname = NULL;
Packit Service 5ffa24
    const char *     name;
Packit Service 5ffa24
Packit Service 5ffa24
    /* The incoming hostname *can* be NULL, which will get translated to
Packit Service 5ffa24
     * 'localhost.localdomain' or such in the hostname policy code, but we
Packit Service 5ffa24
     * keep cur_hostname = NULL in the case because we need to know that
Packit Service 5ffa24
     * there was no valid hostname to start with.
Packit Service 5ffa24
     */
Packit Service 5ffa24
Packit Service 5ffa24
    /* Update the DNS only if the hostname is actually
Packit Service 5ffa24
     * going to change.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (!nm_streq0(priv->cur_hostname, new_hostname)) {
Packit Service 5ffa24
        g_free(priv->cur_hostname);
Packit Service 5ffa24
        priv->cur_hostname = g_strdup(new_hostname);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Notify the DNS manager of the hostname change so that the domain part, if
Packit Service 5ffa24
         * present, can be added to the search list. Set the @updating_dns flag
Packit Service 5ffa24
         * so that dns_config_changed() doesn't try again to restart DNS lookup.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        priv->updating_dns = TRUE;
Packit Service 5ffa24
        nm_dns_manager_set_hostname(priv->dns_manager,
Packit Service 5ffa24
                                    priv->cur_hostname,
Packit Service 5ffa24
                                    all_devices_not_active(self));
Packit Service 5ffa24
        priv->updating_dns = FALSE;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Finally, set kernel hostname */
Packit Service 5ffa24
    if (!new_hostname)
Packit Service 5ffa24
        name = FALLBACK_HOSTNAME4;
Packit Service 5ffa24
    else if (!new_hostname[0]) {
Packit Service 5ffa24
        g_warn_if_reached();
Packit Service 5ffa24
        name = FALLBACK_HOSTNAME4;
Packit Service 5ffa24
    } else
Packit Service 5ffa24
        name = new_hostname;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Don't set the hostname if it isn't actually changing */
Packit Service 5ffa24
    if ((old_hostname = _get_hostname(self)) && (nm_streq(name, old_hostname))) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "set-hostname: hostname already set to '%s' (%s)", name, msg);
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Keep track of the last set hostname */
Packit Service 5ffa24
    g_free(priv->last_hostname);
Packit Service 5ffa24
    priv->last_hostname     = g_strdup(name);
Packit Service 5ffa24
    priv->changing_hostname = TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI(LOGD_DNS, "set-hostname: set hostname to '%s' (%s)", name, msg);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Ask NMSettings to update the transient hostname using its
Packit Service 5ffa24
     * systemd-hostnamed proxy */
Packit Service 5ffa24
    nm_hostname_manager_set_transient_hostname(priv->hostname_manager,
Packit Service 5ffa24
                                               name,
Packit Service 5ffa24
                                               settings_set_hostname_cb,
Packit Service 5ffa24
                                               g_object_ref(self));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    NMDevice *device;
Packit Service 5ffa24
    int       priority;
Packit Service 5ffa24
    bool      from_dhcp : 1;
Packit Service 5ffa24
    bool      from_dns : 1;
Packit Service 5ffa24
    bool      IS_IPv4 : 1;
Packit Service 5ffa24
    bool      is_default : 1;
Packit Service 5ffa24
} DeviceHostnameInfo;
Packit Service 5ffa24
Packit Service 5ffa24
static int
Packit Service 5ffa24
device_hostname_info_compare(gconstpointer a, gconstpointer b)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const DeviceHostnameInfo *info1 = a;
Packit Service 5ffa24
    const DeviceHostnameInfo *info2 = b;
Packit Service 5ffa24
Packit Service 5ffa24
    NM_CMP_FIELD(info1, info2, priority);
Packit Service 5ffa24
    NM_CMP_FIELD_UNSAFE(info2, info1, is_default);
Packit Service 5ffa24
Packit Service 5ffa24
    return 0;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NM_CON_DEFAULT_NOP("hostname.from-dhcp");
Packit Service 5ffa24
NM_CON_DEFAULT_NOP("hostname.from-dns-lookup");
Packit Service 5ffa24
NM_CON_DEFAULT_NOP("hostname.only-from-default");
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
device_get_hostname_property_boolean(NMDevice *device, const char *name)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSettingHostname *s_hostname;
Packit Service 5ffa24
    char               buf[128];
Packit Service 5ffa24
    int                value;
Packit Service 5ffa24
    NMTernary          default_value;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IN_STRSET(name,
Packit Service 5ffa24
                           NM_SETTING_HOSTNAME_FROM_DHCP,
Packit Service 5ffa24
                           NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP,
Packit Service 5ffa24
                           NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT));
Packit Service 5ffa24
Packit Service 5ffa24
    s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME);
Packit Service 5ffa24
Packit Service 5ffa24
    if (s_hostname) {
Packit Service 5ffa24
        g_object_get(s_hostname, name, &value, NULL);
Packit Service 5ffa24
        if (NM_IN_SET(value, NM_TERNARY_FALSE, NM_TERNARY_TRUE))
Packit Service 5ffa24
            return value;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq(name, NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT))
Packit Service 5ffa24
        default_value = NM_TERNARY_FALSE;
Packit Service 5ffa24
    else
Packit Service 5ffa24
        default_value = NM_TERNARY_TRUE;
Packit Service 5ffa24
Packit Service 5ffa24
    return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
Packit Service 5ffa24
                                                       nm_sprintf_buf(buf, "hostname.%s", name),
Packit Service 5ffa24
                                                       device,
Packit Service 5ffa24
                                                       NM_TERNARY_FALSE,
Packit Service 5ffa24
                                                       NM_TERNARY_TRUE,
Packit Service 5ffa24
                                                       default_value);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static int
Packit Service 5ffa24
device_get_hostname_priority(NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSettingHostname *s_hostname;
Packit Service 5ffa24
    int                priority;
Packit Service 5ffa24
Packit Service 5ffa24
    s_hostname = nm_device_get_applied_setting(device, NM_TYPE_SETTING_HOSTNAME);
Packit Service 5ffa24
    if (s_hostname) {
Packit Service 5ffa24
        priority = nm_setting_hostname_get_priority(s_hostname);
Packit Service 5ffa24
        if (priority != 0)
Packit Service 5ffa24
            return priority;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return nm_config_data_get_connection_default_int64(NM_CONFIG_GET_DATA,
Packit Service 5ffa24
                                                       NM_CON_DEFAULT("hostname.priority"),
Packit Service 5ffa24
                                                       device,
Packit Service 5ffa24
                                                       G_MININT,
Packit Service 5ffa24
                                                       G_MAXINT,
Packit Service 5ffa24
                                                       100);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static GArray *
Packit Service 5ffa24
build_device_hostname_infos(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *       tmp_clist;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    GArray *            array = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_active_connection (priv->manager, ac, tmp_clist) {
Packit Service 5ffa24
        DeviceHostnameInfo *info;
Packit Service 5ffa24
        NMDevice *          device;
Packit Service 5ffa24
        gboolean            only_from_default;
Packit Service 5ffa24
        gboolean            is_default;
Packit Service 5ffa24
        int                 IS_IPv4;
Packit Service 5ffa24
Packit Service 5ffa24
        device = nm_active_connection_get_device(ac);
Packit Service 5ffa24
        if (!device)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        only_from_default =
Packit Service 5ffa24
            device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_ONLY_FROM_DEFAULT);
Packit Service 5ffa24
Packit Service 5ffa24
        for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
Packit Service 5ffa24
            is_default = (ac == (IS_IPv4 ? priv->default_ac4 : priv->default_ac6));
Packit Service 5ffa24
            if (only_from_default && !is_default)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
Packit Service 5ffa24
            if (!array)
Packit Service 5ffa24
                array = g_array_sized_new(FALSE, FALSE, sizeof(DeviceHostnameInfo), 4);
Packit Service 5ffa24
Packit Service 5ffa24
            info  = nm_g_array_append_new(array, DeviceHostnameInfo);
Packit Service 5ffa24
            *info = (DeviceHostnameInfo){
Packit Service 5ffa24
                .device   = device,
Packit Service 5ffa24
                .priority = device_get_hostname_priority(device),
Packit Service 5ffa24
                .from_dhcp =
Packit Service 5ffa24
                    device_get_hostname_property_boolean(device, NM_SETTING_HOSTNAME_FROM_DHCP),
Packit Service 5ffa24
                .from_dns =
Packit Service 5ffa24
                    device_get_hostname_property_boolean(device,
Packit Service 5ffa24
                                                         NM_SETTING_HOSTNAME_FROM_DNS_LOOKUP),
Packit Service 5ffa24
                .IS_IPv4    = IS_IPv4,
Packit Service 5ffa24
                .is_default = is_default,
Packit Service 5ffa24
            };
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (array && array->len > 1) {
Packit Service 5ffa24
        const DeviceHostnameInfo *info0;
Packit Service 5ffa24
        guint                     i;
Packit Service 5ffa24
Packit Service 5ffa24
        g_array_sort(array, device_hostname_info_compare);
Packit Service 5ffa24
Packit Service 5ffa24
        info0 = &g_array_index(array, DeviceHostnameInfo, 0);
Packit Service 5ffa24
        if (info0->priority < 0) {
Packit Service 5ffa24
            for (i = 1; i < array->len; i++) {
Packit Service 5ffa24
                const DeviceHostnameInfo *info = &g_array_index(array, DeviceHostnameInfo, i);
Packit Service 5ffa24
Packit Service 5ffa24
                if (info->priority > info0->priority) {
Packit Service 5ffa24
                    g_array_set_size(array, i);
Packit Service 5ffa24
                    break;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return array;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_dns_lookup_done(NMDevice *device, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *self = user_data;
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
Packit Service 5ffa24
Packit Service 5ffa24
    update_system_hostname(self, "lookup finished");
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_system_hostname(NMPolicy *self, const char *msg)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const char *     configured_hostname;
Packit Service 5ffa24
    gs_free char *   temp_hostname = NULL;
Packit Service 5ffa24
    const char *     dhcp_hostname, *p;
Packit Service 5ffa24
    gboolean         external_hostname = FALSE;
Packit Service 5ffa24
    NMDhcpConfig *   dhcp_config;
Packit Service 5ffa24
    gs_unref_array GArray *infos = NULL;
Packit Service 5ffa24
    DeviceHostnameInfo *   info;
Packit Service 5ffa24
    guint                  i;
Packit Service 5ffa24
    int                    addr_family;
Packit Service 5ffa24
Packit Service 5ffa24
    g_return_if_fail(self != NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_NONE) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "set-hostname: hostname is unmanaged");
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGT(LOGD_DNS, "set-hostname: updating hostname (%s)", msg);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Check if the hostname was set externally to NM, so that in that case
Packit Service 5ffa24
     * we can avoid to fallback to the one we got when we started.
Packit Service 5ffa24
     * Consider "not specific" hostnames as equal. */
Packit Service 5ffa24
    if ((temp_hostname = _get_hostname(self)) && !nm_streq0(temp_hostname, priv->last_hostname)
Packit Service 5ffa24
        && (nm_utils_is_specific_hostname(temp_hostname)
Packit Service 5ffa24
            || nm_utils_is_specific_hostname(priv->last_hostname))) {
Packit Service 5ffa24
        external_hostname = TRUE;
Packit Service 5ffa24
        _LOGI(LOGD_DNS,
Packit Service 5ffa24
              "set-hostname: current hostname was changed outside NetworkManager: '%s'",
Packit Service 5ffa24
              temp_hostname);
Packit Service 5ffa24
        priv->dhcp_hostname = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_utils_is_specific_hostname(temp_hostname))
Packit Service 5ffa24
            nm_clear_g_free(&temp_hostname);
Packit Service 5ffa24
        if (!nm_streq0(temp_hostname, priv->orig_hostname)) {
Packit Service 5ffa24
            /* Update original (fallback) hostname */
Packit Service 5ffa24
            g_free(priv->orig_hostname);
Packit Service 5ffa24
            priv->orig_hostname = g_steal_pointer(&temp_hostname);
Packit Service 5ffa24
            _LOGT(LOGD_DNS,
Packit Service 5ffa24
                  "hostname-original: update to %s%s%s",
Packit Service 5ffa24
                  NM_PRINT_FMT_QUOTE_STRING(priv->orig_hostname));
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Hostname precedence order:
Packit Service 5ffa24
     *
Packit Service 5ffa24
     * 1) a configured hostname (from settings)
Packit Service 5ffa24
     * 2) automatic hostname from DHCP of eligible interfaces
Packit Service 5ffa24
     * 3) reverse-DNS lookup of the first address on eligible interfaces
Packit Service 5ffa24
     * 4) the last hostname set outside NM
Packit Service 5ffa24
     */
Packit Service 5ffa24
Packit Service 5ffa24
    /* Try a persistent hostname first */
Packit Service 5ffa24
    configured_hostname = nm_hostname_manager_get_hostname(priv->hostname_manager);
Packit Service 5ffa24
    if (configured_hostname && nm_utils_is_specific_hostname(configured_hostname)) {
Packit Service 5ffa24
        _set_hostname(self, configured_hostname, "from system configuration");
Packit Service 5ffa24
        priv->dhcp_hostname = FALSE;
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    infos = build_device_hostname_infos(self);
Packit Service 5ffa24
Packit Service 5ffa24
    if (infos && _LOGT_ENABLED(LOGD_DNS)) {
Packit Service 5ffa24
        _LOGT(LOGD_DNS, "device hostname info:");
Packit Service 5ffa24
        for (i = 0; i < infos->len; i++) {
Packit Service 5ffa24
            info = &g_array_index(infos, DeviceHostnameInfo, i);
Packit Service 5ffa24
            _LOGT(LOGD_DNS,
Packit Service 5ffa24
                  "  - prio:%5d ipv%c%s %s %s dev:%s",
Packit Service 5ffa24
                  info->priority,
Packit Service 5ffa24
                  info->IS_IPv4 ? '4' : '6',
Packit Service 5ffa24
                  info->is_default ? " (def)" : "      ",
Packit Service 5ffa24
                  info->from_dhcp ? "dhcp " : "     ",
Packit Service 5ffa24
                  info->from_dns ? "dns " : "    ",
Packit Service 5ffa24
                  nm_device_get_iface(info->device));
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; infos && i < infos->len; i++) {
Packit Service 5ffa24
        info        = &g_array_index(infos, DeviceHostnameInfo, i);
Packit Service 5ffa24
        addr_family = info->IS_IPv4 ? AF_INET : AF_INET6;
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(info->device, device_dns_lookup_done, self);
Packit Service 5ffa24
Packit Service 5ffa24
        if (info->from_dhcp) {
Packit Service 5ffa24
            dhcp_config = nm_device_get_dhcp_config(info->device, addr_family);
Packit Service 5ffa24
            if (dhcp_config) {
Packit Service 5ffa24
                dhcp_hostname =
Packit Service 5ffa24
                    nm_dhcp_config_get_option(dhcp_config,
Packit Service 5ffa24
                                              info->IS_IPv4 ? "host_name" : "fqdn_fqdn");
Packit Service 5ffa24
                if (dhcp_hostname && dhcp_hostname[0]) {
Packit Service 5ffa24
                    p = nm_str_skip_leading_spaces(dhcp_hostname);
Packit Service 5ffa24
                    if (p[0]) {
Packit Service 5ffa24
                        _set_hostname(self, p, info->IS_IPv4 ? "from DHCPv4" : "from DHCPv6");
Packit Service 5ffa24
                        priv->dhcp_hostname = TRUE;
Packit Service 5ffa24
                        return;
Packit Service 5ffa24
                    }
Packit Service 5ffa24
                    _LOGW(LOGD_DNS,
Packit Service 5ffa24
                          "set-hostname: DHCPv%c-provided hostname '%s' looks invalid; "
Packit Service 5ffa24
                          "ignoring it",
Packit Service 5ffa24
                          nm_utils_addr_family_to_char(addr_family),
Packit Service 5ffa24
                          dhcp_hostname);
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (priv->hostname_mode != NM_POLICY_HOSTNAME_MODE_DHCP) {
Packit Service 5ffa24
            if (info->from_dns) {
Packit Service 5ffa24
                const char *result;
Packit Service 5ffa24
                gboolean    wait = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
                result = nm_device_get_hostname_from_dns_lookup(info->device, addr_family, &wait);
Packit Service 5ffa24
                if (result) {
Packit Service 5ffa24
                    _set_hostname(self, result, "from address lookup");
Packit Service 5ffa24
                    return;
Packit Service 5ffa24
                }
Packit Service 5ffa24
                if (wait) {
Packit Service 5ffa24
                    g_signal_connect(info->device,
Packit Service 5ffa24
                                     NM_DEVICE_DNS_LOOKUP_DONE,
Packit Service 5ffa24
                                     (GCallback) device_dns_lookup_done,
Packit Service 5ffa24
                                     self);
Packit Service 5ffa24
                    return;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* If an hostname was set outside NetworkManager keep it */
Packit Service 5ffa24
    if (external_hostname)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->hostname_mode == NM_POLICY_HOSTNAME_MODE_DHCP) {
Packit Service 5ffa24
        /* In dhcp hostname-mode, the hostname is updated only if it comes from
Packit Service 5ffa24
         * a DHCP host-name option: if last set was from a host-name option and
Packit Service 5ffa24
         * we are here than that connection is gone (with its host-name option),
Packit Service 5ffa24
         * so reset the hostname to the previous value
Packit Service 5ffa24
         */
Packit Service 5ffa24
        if (priv->dhcp_hostname) {
Packit Service 5ffa24
            _set_hostname(self, priv->orig_hostname, "reset dhcp hostname");
Packit Service 5ffa24
            priv->dhcp_hostname = FALSE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    priv->dhcp_hostname = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    /* If no automatically-configured hostname, try using the last hostname
Packit Service 5ffa24
     * set externally to NM
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (priv->orig_hostname) {
Packit Service 5ffa24
        _set_hostname(self, priv->orig_hostname, "from system startup");
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    _set_hostname(self, NULL, "no hostname found");
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_default_ac(NMPolicy *self, int addr_family, NMActiveConnection *best)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Clear the 'default[6]' flag on all active connections that aren't the new
Packit Service 5ffa24
     * default active connection.  We'll set the new default after; this ensures
Packit Service 5ffa24
     * we don't ever have two marked 'default[6]' simultaneously.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
        if (ac != best)
Packit Service 5ffa24
            nm_active_connection_set_default(ac, addr_family, FALSE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Mark new default active connection */
Packit Service 5ffa24
    if (best)
Packit Service 5ffa24
        nm_active_connection_set_default(best, addr_family, TRUE);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gpointer
Packit Service 5ffa24
get_best_ip_config(NMPolicy *           self,
Packit Service 5ffa24
                   int                  addr_family,
Packit Service 5ffa24
                   const char **        out_ip_iface,
Packit Service 5ffa24
                   NMActiveConnection **out_ac,
Packit Service 5ffa24
                   NMDevice **          out_device,
Packit Service 5ffa24
                   NMVpnConnection **   out_vpn)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    gpointer            conf, best_conf = NULL;
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    guint64             best_metric = G_MAXUINT64;
Packit Service 5ffa24
    NMVpnConnection *   best_vpn    = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6));
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
        NMVpnConnection *    candidate;
Packit Service 5ffa24
        NMVpnConnectionState vpn_state;
Packit Service 5ffa24
        const NMPObject *    obj;
Packit Service 5ffa24
        guint32              metric;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!NM_IS_VPN_CONNECTION(ac))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        candidate = NM_VPN_CONNECTION(ac);
Packit Service 5ffa24
Packit Service 5ffa24
        vpn_state = nm_vpn_connection_get_vpn_state(candidate);
Packit Service 5ffa24
        if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (addr_family == AF_INET)
Packit Service 5ffa24
            conf = nm_vpn_connection_get_ip4_config(candidate);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            conf = nm_vpn_connection_get_ip6_config(candidate);
Packit Service 5ffa24
        if (!conf)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (addr_family == AF_INET)
Packit Service 5ffa24
            obj = nm_ip4_config_best_default_route_get(conf);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            obj = nm_ip6_config_best_default_route_get(conf);
Packit Service 5ffa24
        if (!obj)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        metric = NMP_OBJECT_CAST_IPX_ROUTE(obj)->rx.metric;
Packit Service 5ffa24
        if (metric <= best_metric) {
Packit Service 5ffa24
            best_metric = metric;
Packit Service 5ffa24
            best_conf   = conf;
Packit Service 5ffa24
            best_vpn    = candidate;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (best_metric != G_MAXUINT64) {
Packit Service 5ffa24
        NM_SET_OUT(out_device, NULL);
Packit Service 5ffa24
        NM_SET_OUT(out_vpn, best_vpn);
Packit Service 5ffa24
        NM_SET_OUT(out_ac, NM_ACTIVE_CONNECTION(best_vpn));
Packit Service 5ffa24
        NM_SET_OUT(out_ip_iface, nm_vpn_connection_get_ip_iface(best_vpn, TRUE));
Packit Service 5ffa24
        return best_conf;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    ac = get_best_active_connection(self, addr_family, TRUE);
Packit Service 5ffa24
    if (ac) {
Packit Service 5ffa24
        NMDevice *device = nm_active_connection_get_device(ac);
Packit Service 5ffa24
Packit Service 5ffa24
        nm_assert(device);
Packit Service 5ffa24
Packit Service 5ffa24
        if (addr_family == AF_INET)
Packit Service 5ffa24
            conf = nm_device_get_ip4_config(device);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            conf = nm_device_get_ip6_config(device);
Packit Service 5ffa24
Packit Service 5ffa24
        NM_SET_OUT(out_device, device);
Packit Service 5ffa24
        NM_SET_OUT(out_vpn, NULL);
Packit Service 5ffa24
        NM_SET_OUT(out_ac, ac);
Packit Service 5ffa24
        NM_SET_OUT(out_ip_iface, nm_device_get_ip_iface(device));
Packit Service 5ffa24
        return conf;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(out_device, NULL);
Packit Service 5ffa24
    NM_SET_OUT(out_vpn, NULL);
Packit Service 5ffa24
    NM_SET_OUT(out_ac, NULL);
Packit Service 5ffa24
    NM_SET_OUT(out_ip_iface, NULL);
Packit Service 5ffa24
    return NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_ip4_routing(NMPolicy *self, gboolean force_update)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv     = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMDevice *          best     = NULL;
Packit Service 5ffa24
    NMVpnConnection *   vpn      = NULL;
Packit Service 5ffa24
    NMActiveConnection *best_ac  = NULL;
Packit Service 5ffa24
    const char *        ip_iface = NULL;
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
Packit Service 5ffa24
     * so we can get (vpn != NULL && best == NULL).
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (!get_best_ip_config(self, AF_INET, &ip_iface, &best_ac, &best, &vpn)) {
Packit Service 5ffa24
        if (nm_clear_g_object(&priv->default_ac4)) {
Packit Service 5ffa24
            _LOGt(LOGD_DNS, "set-default-ac-4: %p", NULL);
Packit Service 5ffa24
            _notify(self, PROP_DEFAULT_IP4_AC);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    g_assert((best || vpn) && best_ac);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!force_update && best_ac && best_ac == priv->default_ac4)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (best) {
Packit Service 5ffa24
        nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
            if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip4_config(NM_VPN_CONNECTION(ac))
Packit Service 5ffa24
                && !nm_active_connection_get_device(ac))
Packit Service 5ffa24
                nm_active_connection_set_device(ac, best);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    update_default_ac(self, AF_INET, best_ac);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_g_object_ref_set(&priv->default_ac4, best_ac))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    _LOGt(LOGD_DNS, "set-default-ac-4: %p", priv->default_ac4);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI(LOGD_CORE,
Packit Service 5ffa24
          "set '%s' (%s) as default for IPv4 routing and DNS",
Packit Service 5ffa24
          nm_connection_get_id(nm_active_connection_get_applied_connection(best_ac)),
Packit Service 5ffa24
          ip_iface);
Packit Service 5ffa24
    _notify(self, PROP_DEFAULT_IP4_AC);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_ip6_prefix_delegation(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMDevice *          device;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
Packit Service 5ffa24
    /* There's new default IPv6 connection, try to get a prefix for everyone. */
Packit Service 5ffa24
    nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
        device = nm_active_connection_get_device(ac);
Packit Service 5ffa24
        if (device && nm_device_needs_ip6_subnet(device))
Packit Service 5ffa24
            ip6_subnet_from_device(self, get_default_device(self, AF_INET6), device);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_ip6_routing(NMPolicy *self, gboolean force_update)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv     = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMDevice *          best     = NULL;
Packit Service 5ffa24
    NMVpnConnection *   vpn      = NULL;
Packit Service 5ffa24
    NMActiveConnection *best_ac  = NULL;
Packit Service 5ffa24
    const char *        ip_iface = NULL;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
Packit Service 5ffa24
     * so we can get (vpn != NULL && best == NULL).
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (!get_best_ip_config(self, AF_INET6, &ip_iface, &best_ac, &best, &vpn)) {
Packit Service 5ffa24
        if (nm_clear_g_object(&priv->default_ac6)) {
Packit Service 5ffa24
            _LOGt(LOGD_DNS, "set-default-ac-6: %p", NULL);
Packit Service 5ffa24
            _notify(self, PROP_DEFAULT_IP6_AC);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    g_assert((best || vpn) && best_ac);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!force_update && best_ac && best_ac == priv->default_ac6)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (best) {
Packit Service 5ffa24
        nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
            if (NM_IS_VPN_CONNECTION(ac) && nm_vpn_connection_get_ip6_config(NM_VPN_CONNECTION(ac))
Packit Service 5ffa24
                && !nm_active_connection_get_device(ac))
Packit Service 5ffa24
                nm_active_connection_set_device(ac, best);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    update_default_ac(self, AF_INET6, best_ac);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_g_object_ref_set(&priv->default_ac6, best_ac))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    _LOGt(LOGD_DNS, "set-default-ac-6: %p", priv->default_ac6);
Packit Service 5ffa24
Packit Service 5ffa24
    update_ip6_prefix_delegation(self);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI(LOGD_CORE,
Packit Service 5ffa24
          "set '%s' (%s) as default for IPv6 routing and DNS",
Packit Service 5ffa24
          nm_connection_get_id(nm_active_connection_get_applied_connection(best_ac)),
Packit Service 5ffa24
          ip_iface);
Packit Service 5ffa24
    _notify(self, PROP_DEFAULT_IP6_AC);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_ip_dns(NMPolicy *self, int addr_family, NMDevice *changed_device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    gpointer         ip_config;
Packit Service 5ffa24
    const char *     ip_iface = NULL;
Packit Service 5ffa24
    NMVpnConnection *vpn      = NULL;
Packit Service 5ffa24
    NMDevice *       device   = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert_addr_family(addr_family);
Packit Service 5ffa24
Packit Service 5ffa24
    ip_config = get_best_ip_config(self, addr_family, &ip_iface, NULL, &device, &vpn;;
Packit Service 5ffa24
    if (ip_config) {
Packit Service 5ffa24
        /* Tell the DNS manager this config is preferred by re-adding it with
Packit Service 5ffa24
         * a different IP config type.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        _dns_manager_set_ip_config(NM_POLICY_GET_PRIVATE(self)->dns_manager,
Packit Service 5ffa24
                                   ip_config,
Packit Service 5ffa24
                                   (vpn || (device && nm_device_is_vpn(device)))
Packit Service 5ffa24
                                       ? NM_DNS_IP_CONFIG_TYPE_VPN
Packit Service 5ffa24
                                       : NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE,
Packit Service 5ffa24
                                   device);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (addr_family == AF_INET6) {
Packit Service 5ffa24
        NMActiveConnection *ac;
Packit Service 5ffa24
        const CList *       tmp_list;
Packit Service 5ffa24
Packit Service 5ffa24
        /* Tell devices needing a subnet about the new DNS configuration */
Packit Service 5ffa24
        nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
            device = nm_active_connection_get_device(ac);
Packit Service 5ffa24
            if (device && device != changed_device && nm_device_needs_ip6_subnet(device))
Packit Service 5ffa24
                nm_device_copy_ip6_dns_config(device, get_default_device(self, AF_INET6));
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
update_routing_and_dns(NMPolicy *self, gboolean force_update, NMDevice *changed_device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_begin_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
Packit Service 5ffa24
    update_ip_dns(self, AF_INET, changed_device);
Packit Service 5ffa24
    update_ip_dns(self, AF_INET6, changed_device);
Packit Service 5ffa24
Packit Service 5ffa24
    update_ip4_routing(self, force_update);
Packit Service 5ffa24
    update_ip6_routing(self, force_update);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Update the system hostname */
Packit Service 5ffa24
    update_system_hostname(self, "routing and dns");
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_end_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
check_activating_active_connections(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMActiveConnection *best4, *best6 = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    best4 = get_best_active_connection(self, AF_INET, FALSE);
Packit Service 5ffa24
    best6 = get_best_active_connection(self, AF_INET6, FALSE);
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_freeze_notify(G_OBJECT(self));
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_g_object_ref_set(&priv->activating_ac4, best4)) {
Packit Service 5ffa24
        _LOGt(LOGD_DNS, "set-activating-ac-4: %p", priv->activating_ac4);
Packit Service 5ffa24
        _notify(self, PROP_ACTIVATING_IP4_AC);
Packit Service 5ffa24
    }
Packit Service 5ffa24
    if (nm_g_object_ref_set(&priv->activating_ac6, best6)) {
Packit Service 5ffa24
        _LOGt(LOGD_DNS, "set-activating-ac-6: %p", priv->activating_ac6);
Packit Service 5ffa24
        _notify(self, PROP_ACTIVATING_IP6_AC);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_thaw_notify(G_OBJECT(self));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    CList     pending_lst;
Packit Service 5ffa24
    NMPolicy *policy;
Packit Service 5ffa24
    NMDevice *device;
Packit Service 5ffa24
    guint     autoactivate_id;
Packit Service 5ffa24
} ActivateData;
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
activate_data_free(ActivateData *data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    nm_device_remove_pending_action(data->device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE);
Packit Service 5ffa24
    c_list_unlink_stale(&data->pending_lst);
Packit Service 5ffa24
    nm_clear_g_source(&data->autoactivate_id);
Packit Service 5ffa24
    g_object_unref(data->device);
Packit Service 5ffa24
    g_slice_free(ActivateData, data);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
pending_ac_gone(gpointer data, GObject *where_the_object_was)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(data);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Active connections should reach the DEACTIVATED state
Packit Service 5ffa24
     * before disappearing. */
Packit Service 5ffa24
    nm_assert_not_reached();
Packit Service 5ffa24
Packit Service 5ffa24
    if (g_hash_table_remove(priv->pending_active_connections, where_the_object_was))
Packit Service 5ffa24
        g_object_unref(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
pending_ac_state_changed(NMActiveConnection *ac, guint state, guint reason, NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *     priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMSettingsConnection *con;
Packit Service 5ffa24
Packit Service 5ffa24
    if (state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) {
Packit Service 5ffa24
        /* The AC is being deactivated before the device had a chance
Packit Service 5ffa24
         * to move to PREPARE. Schedule a new auto-activation on the
Packit Service 5ffa24
         * device, but block the current connection to avoid an activation
Packit Service 5ffa24
         * loop.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        if (reason != NM_ACTIVE_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED) {
Packit Service 5ffa24
            con = nm_active_connection_get_settings_connection(ac);
Packit Service 5ffa24
            nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                con,
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
                TRUE);
Packit Service 5ffa24
            schedule_activate_check(self, nm_active_connection_get_device(ac));
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* Cleanup */
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(ac, pending_ac_state_changed, self);
Packit Service 5ffa24
        if (!g_hash_table_remove(priv->pending_active_connections, ac))
Packit Service 5ffa24
            nm_assert_not_reached();
Packit Service 5ffa24
        g_object_weak_unref(G_OBJECT(ac), pending_ac_gone, self);
Packit Service 5ffa24
        g_object_unref(self);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
auto_activate_device(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *     priv;
Packit Service 5ffa24
    NMSettingsConnection *best_connection;
Packit Service 5ffa24
    gs_free char *        specific_object      = NULL;
Packit Service 5ffa24
    gs_free NMSettingsConnection **connections = NULL;
Packit Service 5ffa24
    guint                          i, len;
Packit Service 5ffa24
    gs_free_error GError *error            = NULL;
Packit Service 5ffa24
    gs_unref_object NMAuthSubject *subject = NULL;
Packit Service 5ffa24
    NMActiveConnection *           ac;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_POLICY(self));
Packit Service 5ffa24
    nm_assert(NM_IS_DEVICE(device));
Packit Service 5ffa24
Packit Service 5ffa24
    priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    // FIXME: if a device is already activating (or activated) with a connection
Packit Service 5ffa24
    // but another connection now overrides the current one for that device,
Packit Service 5ffa24
    // deactivate the device and activate the new connection instead of just
Packit Service 5ffa24
    // bailing if the device is already active
Packit Service 5ffa24
    if (nm_device_get_act_request(device))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_device_autoconnect_allowed(device))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    connections = nm_manager_get_activatable_connections(priv->manager, TRUE, TRUE, &len;;
Packit Service 5ffa24
    if (!connections[0])
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Find the first connection that should be auto-activated */
Packit Service 5ffa24
    best_connection = NULL;
Packit Service 5ffa24
    for (i = 0; i < len; i++) {
Packit Service 5ffa24
        NMSettingsConnection *candidate = connections[i];
Packit Service 5ffa24
        NMConnection *        cand_conn;
Packit Service 5ffa24
        NMSettingConnection * s_con;
Packit Service 5ffa24
        const char *          permission;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_settings_connection_autoconnect_is_blocked(candidate))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        cand_conn = nm_settings_connection_get_connection(candidate);
Packit Service 5ffa24
Packit Service 5ffa24
        s_con = nm_connection_get_setting_connection(cand_conn);
Packit Service 5ffa24
        if (!nm_setting_connection_get_autoconnect(s_con))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        permission = nm_utils_get_shared_wifi_permission(cand_conn);
Packit Service 5ffa24
        if (permission && !nm_settings_connection_check_permission(candidate, permission))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_device_can_auto_connect(device, candidate, &specific_object)) {
Packit Service 5ffa24
            best_connection = candidate;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!best_connection)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGI(LOGD_DEVICE,
Packit Service 5ffa24
          "auto-activating connection '%s' (%s)",
Packit Service 5ffa24
          nm_settings_connection_get_id(best_connection),
Packit Service 5ffa24
          nm_settings_connection_get_uuid(best_connection));
Packit Service 5ffa24
Packit Service 5ffa24
    subject = nm_auth_subject_new_internal();
Packit Service 5ffa24
    ac      = nm_manager_activate_connection(
Packit Service 5ffa24
        priv->manager,
Packit Service 5ffa24
        best_connection,
Packit Service 5ffa24
        NULL,
Packit Service 5ffa24
        specific_object,
Packit Service 5ffa24
        device,
Packit Service 5ffa24
        subject,
Packit Service 5ffa24
        NM_ACTIVATION_TYPE_MANAGED,
Packit Service 5ffa24
        NM_ACTIVATION_REASON_AUTOCONNECT,
Packit Service 5ffa24
        NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY,
Packit Service 5ffa24
        &error);
Packit Service 5ffa24
    if (!ac) {
Packit Service 5ffa24
        _LOGI(LOGD_DEVICE,
Packit Service 5ffa24
              "connection '%s' auto-activation failed: %s",
Packit Service 5ffa24
              nm_settings_connection_get_id(best_connection),
Packit Service 5ffa24
              error->message);
Packit Service 5ffa24
        nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
            best_connection,
Packit Service 5ffa24
            NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
            TRUE);
Packit Service 5ffa24
        schedule_activate_check(self, device);
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Subscribe to AC state-changed signal to detect when the
Packit Service 5ffa24
     * activation fails in early stages without changing device
Packit Service 5ffa24
     * state.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (g_hash_table_add(priv->pending_active_connections, ac)) {
Packit Service 5ffa24
        g_signal_connect(ac,
Packit Service 5ffa24
                         NM_ACTIVE_CONNECTION_STATE_CHANGED,
Packit Service 5ffa24
                         G_CALLBACK(pending_ac_state_changed),
Packit Service 5ffa24
                         g_object_ref(self));
Packit Service 5ffa24
        g_object_weak_ref(G_OBJECT(ac), (GWeakNotify) pending_ac_gone, self);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
auto_activate_device_cb(gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    ActivateData *data = user_data;
Packit Service 5ffa24
Packit Service 5ffa24
    g_assert(data);
Packit Service 5ffa24
    g_assert(NM_IS_POLICY(data->policy));
Packit Service 5ffa24
    g_assert(NM_IS_DEVICE(data->device));
Packit Service 5ffa24
Packit Service 5ffa24
    data->autoactivate_id = 0;
Packit Service 5ffa24
    auto_activate_device(data->policy, data->device);
Packit Service 5ffa24
    activate_data_free(data);
Packit Service 5ffa24
    return G_SOURCE_REMOVE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static ActivateData *
Packit Service 5ffa24
find_pending_activation(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    ActivateData *   data;
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry (data, &priv->pending_activation_checks, pending_lst) {
Packit Service 5ffa24
        if (data->device == device)
Packit Service 5ffa24
            return data;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    NMDevice *device;
Packit Service 5ffa24
    GSList *  secondaries;
Packit Service 5ffa24
} PendingSecondaryData;
Packit Service 5ffa24
Packit Service 5ffa24
static PendingSecondaryData *
Packit Service 5ffa24
pending_secondary_data_new(NMDevice *device, GSList *secondaries)
Packit Service 5ffa24
{
Packit Service 5ffa24
    PendingSecondaryData *data;
Packit Service 5ffa24
Packit Service 5ffa24
    data              = g_slice_new(PendingSecondaryData);
Packit Service 5ffa24
    data->device      = g_object_ref(device);
Packit Service 5ffa24
    data->secondaries = secondaries;
Packit Service 5ffa24
    return data;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
pending_secondary_data_free(PendingSecondaryData *data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    g_object_unref(data->device);
Packit Service 5ffa24
    g_slist_free_full(data->secondaries, g_object_unref);
Packit Service 5ffa24
    g_slice_free(PendingSecondaryData, data);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
process_secondaries(NMPolicy *self, NMActiveConnection *active, gboolean connected)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    GSList *         iter, *iter2, *next, *next2;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Loop through devices waiting for secondary connections to activate */
Packit Service 5ffa24
    for (iter = priv->pending_secondaries; iter; iter = next) {
Packit Service 5ffa24
        PendingSecondaryData *secondary_data = (PendingSecondaryData *) iter->data;
Packit Service 5ffa24
        NMDevice *            item_device    = secondary_data->device;
Packit Service 5ffa24
Packit Service 5ffa24
        next = g_slist_next(iter);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Look for 'active' in each device's secondary connections list */
Packit Service 5ffa24
        for (iter2 = secondary_data->secondaries; iter2; iter2 = next2) {
Packit Service 5ffa24
            NMActiveConnection *secondary_active = NM_ACTIVE_CONNECTION(iter2->data);
Packit Service 5ffa24
Packit Service 5ffa24
            next2 = g_slist_next(iter2);
Packit Service 5ffa24
Packit Service 5ffa24
            if (active != secondary_active)
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
Packit Service 5ffa24
            if (connected) {
Packit Service 5ffa24
                _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                      "secondary connection '%s' succeeded; active path '%s'",
Packit Service 5ffa24
                      nm_active_connection_get_settings_connection_id(active),
Packit Service 5ffa24
                      nm_dbus_object_get_path(NM_DBUS_OBJECT(active)));
Packit Service 5ffa24
Packit Service 5ffa24
                /* Secondary connection activated */
Packit Service 5ffa24
                secondary_data->secondaries =
Packit Service 5ffa24
                    g_slist_remove(secondary_data->secondaries, secondary_active);
Packit Service 5ffa24
                g_object_unref(secondary_active);
Packit Service 5ffa24
                if (!secondary_data->secondaries) {
Packit Service 5ffa24
                    /* No secondary UUID remained -> remove the secondary data item */
Packit Service 5ffa24
                    priv->pending_secondaries =
Packit Service 5ffa24
                        g_slist_remove(priv->pending_secondaries, secondary_data);
Packit Service 5ffa24
                    pending_secondary_data_free(secondary_data);
Packit Service 5ffa24
                    if (nm_device_get_state(item_device) == NM_DEVICE_STATE_SECONDARIES)
Packit Service 5ffa24
                        nm_device_state_changed(item_device,
Packit Service 5ffa24
                                                NM_DEVICE_STATE_ACTIVATED,
Packit Service 5ffa24
                                                NM_DEVICE_STATE_REASON_NONE);
Packit Service 5ffa24
                    break;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                      "secondary connection '%s' failed; active path '%s'",
Packit Service 5ffa24
                      nm_active_connection_get_settings_connection_id(active),
Packit Service 5ffa24
                      nm_dbus_object_get_path(NM_DBUS_OBJECT(active)));
Packit Service 5ffa24
Packit Service 5ffa24
                /* Secondary connection failed -> do not watch other connections */
Packit Service 5ffa24
                priv->pending_secondaries =
Packit Service 5ffa24
                    g_slist_remove(priv->pending_secondaries, secondary_data);
Packit Service 5ffa24
                pending_secondary_data_free(secondary_data);
Packit Service 5ffa24
                if (nm_device_get_state(item_device) == NM_DEVICE_STATE_SECONDARIES
Packit Service 5ffa24
                    || nm_device_get_state(item_device) == NM_DEVICE_STATE_ACTIVATED)
Packit Service 5ffa24
                    nm_device_state_changed(item_device,
Packit Service 5ffa24
                                            NM_DEVICE_STATE_FAILED,
Packit Service 5ffa24
                                            NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
hostname_changed(NMHostnameManager *hostname_manager, GParamSpec *pspec, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    update_system_hostname(self, "hostname changed");
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
void
Packit Service 5ffa24
nm_policy_unblock_failed_ovs_interfaces(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *            priv        = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMSettingsConnection *const *connections = NULL;
Packit Service 5ffa24
    guint                        i;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGT(LOGD_DEVICE, "unblocking failed OVS interfaces");
Packit Service 5ffa24
Packit Service 5ffa24
    connections = nm_settings_get_connections(priv->settings, NULL);
Packit Service 5ffa24
    for (i = 0; connections[i]; i++) {
Packit Service 5ffa24
        NMSettingsConnection *sett_conn  = connections[i];
Packit Service 5ffa24
        NMConnection *        connection = nm_settings_connection_get_connection(sett_conn);
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_connection_get_setting_ovs_interface(connection)) {
Packit Service 5ffa24
            nm_settings_connection_autoconnect_retries_reset(sett_conn);
Packit Service 5ffa24
            nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                sett_conn,
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
                FALSE);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
reset_autoconnect_all(
Packit Service 5ffa24
    NMPolicy *self,
Packit Service 5ffa24
    NMDevice *device, /* if present, only reset connections compatible with @device */
Packit Service 5ffa24
    gboolean  only_no_secrets)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *            priv        = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMSettingsConnection *const *connections = NULL;
Packit Service 5ffa24
    guint                        i;
Packit Service 5ffa24
    gboolean                     changed = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
          "re-enabling autoconnect for all connections%s%s%s",
Packit Service 5ffa24
          device ? " on " : "",
Packit Service 5ffa24
          device ? nm_device_get_iface(device) : "",
Packit Service 5ffa24
          only_no_secrets ? " (only clear no-secrets flag)" : "");
Packit Service 5ffa24
Packit Service 5ffa24
    connections = nm_settings_get_connections(priv->settings, NULL);
Packit Service 5ffa24
    for (i = 0; connections[i]; i++) {
Packit Service 5ffa24
        NMSettingsConnection *sett_conn = connections[i];
Packit Service 5ffa24
Packit Service 5ffa24
        if (device
Packit Service 5ffa24
            && !nm_device_check_connection_compatible(
Packit Service 5ffa24
                device,
Packit Service 5ffa24
                nm_settings_connection_get_connection(sett_conn),
Packit Service 5ffa24
                NULL))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (only_no_secrets) {
Packit Service 5ffa24
            /* we only reset the no-secrets blocked flag. */
Packit Service 5ffa24
            if (nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                    sett_conn,
Packit Service 5ffa24
                    NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
Packit Service 5ffa24
                    FALSE)) {
Packit Service 5ffa24
                /* maybe the connection is still blocked afterwards for other reasons
Packit Service 5ffa24
                 * and in the larger picture nothing changed. But it's too complicated
Packit Service 5ffa24
                 * to find out exactly. Just assume, something changed to be sure. */
Packit Service 5ffa24
                if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
Packit Service 5ffa24
                    changed = TRUE;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            /* we reset the tries-count and any blocked-reason */
Packit Service 5ffa24
            if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
Packit Service 5ffa24
                changed = TRUE;
Packit Service 5ffa24
            nm_settings_connection_autoconnect_retries_reset(sett_conn);
Packit Service 5ffa24
Packit Service 5ffa24
            if (nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                    sett_conn,
Packit Service 5ffa24
                    NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL
Packit Service 5ffa24
                        & ~NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST,
Packit Service 5ffa24
                    FALSE)) {
Packit Service 5ffa24
                if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
Packit Service 5ffa24
                    changed = TRUE;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return changed;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
sleeping_changed(NMManager *manager, GParamSpec *pspec, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv     = user_data;
Packit Service 5ffa24
    NMPolicy *       self     = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    gboolean         sleeping = FALSE, enabled = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_get(G_OBJECT(manager), NM_MANAGER_SLEEPING, &sleeping, NULL);
Packit Service 5ffa24
    g_object_get(G_OBJECT(manager), NM_MANAGER_NETWORKING_ENABLED, &enabled, NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Reset retries on all connections so they'll checked on wakeup */
Packit Service 5ffa24
    if (sleeping || !enabled)
Packit Service 5ffa24
        reset_autoconnect_all(self, NULL, FALSE);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
schedule_activate_check(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    ActivateData *      data;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    const CList *       tmp_list;
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_manager_get_state(priv->manager) == NM_STATE_ASLEEP)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_device_autoconnect_allowed(device))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    if (find_pending_activation(self, device))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_active_connection (priv->manager, ac, tmp_list) {
Packit Service 5ffa24
        if (nm_active_connection_get_device(ac) == device)
Packit Service 5ffa24
            return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_device_add_pending_action(device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE);
Packit Service 5ffa24
Packit Service 5ffa24
    data                  = g_slice_new0(ActivateData);
Packit Service 5ffa24
    data->policy          = self;
Packit Service 5ffa24
    data->device          = g_object_ref(device);
Packit Service 5ffa24
    data->autoactivate_id = g_idle_add(auto_activate_device_cb, data);
Packit Service 5ffa24
    c_list_link_tail(&priv->pending_activation_checks, &data->pending_lst);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
reset_connections_retries(gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *                   self        = (NMPolicy *) user_data;
Packit Service 5ffa24
    NMPolicyPrivate *            priv        = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMSettingsConnection *const *connections = NULL;
Packit Service 5ffa24
    guint                        i;
Packit Service 5ffa24
    gint32                       con_stamp, min_stamp, now;
Packit Service 5ffa24
    gboolean                     changed = FALSE;
Packit Service 5ffa24
Packit Service 5ffa24
    priv->reset_retries_id = 0;
Packit Service 5ffa24
Packit Service 5ffa24
    min_stamp   = 0;
Packit Service 5ffa24
    now         = nm_utils_get_monotonic_timestamp_sec();
Packit Service 5ffa24
    connections = nm_settings_get_connections(priv->settings, NULL);
Packit Service 5ffa24
    for (i = 0; connections[i]; i++) {
Packit Service 5ffa24
        NMSettingsConnection *connection = connections[i];
Packit Service 5ffa24
Packit Service 5ffa24
        con_stamp = nm_settings_connection_autoconnect_retries_blocked_until(connection);
Packit Service 5ffa24
        if (con_stamp == 0)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (con_stamp <= now) {
Packit Service 5ffa24
            nm_settings_connection_autoconnect_retries_reset(connection);
Packit Service 5ffa24
            changed = TRUE;
Packit Service 5ffa24
        } else if (min_stamp == 0 || min_stamp > con_stamp)
Packit Service 5ffa24
            min_stamp = con_stamp;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Schedule the handler again if there are some stamps left */
Packit Service 5ffa24
    if (min_stamp != 0)
Packit Service 5ffa24
        priv->reset_retries_id =
Packit Service 5ffa24
            g_timeout_add_seconds(min_stamp - now, reset_connections_retries, self);
Packit Service 5ffa24
Packit Service 5ffa24
    /* If anything changed, try to activate the newly re-enabled connections */
Packit Service 5ffa24
    if (changed)
Packit Service 5ffa24
        schedule_activate_all(self);
Packit Service 5ffa24
Packit Service 5ffa24
    return FALSE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_connection_autoconnect_retries_set(NMPolicy *self, NMSettingsConnection *connection, int tries)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_SETTINGS_CONNECTION(connection));
Packit Service 5ffa24
    nm_assert(tries >= 0);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_settings_connection_autoconnect_retries_set(connection, tries);
Packit Service 5ffa24
Packit Service 5ffa24
    if (tries == 0) {
Packit Service 5ffa24
        /* Schedule a handler to reset retries count */
Packit Service 5ffa24
        if (!priv->reset_retries_id) {
Packit Service 5ffa24
            gint32 retry_time =
Packit Service 5ffa24
                nm_settings_connection_autoconnect_retries_blocked_until(connection);
Packit Service 5ffa24
Packit Service 5ffa24
            g_warn_if_fail(retry_time != 0);
Packit Service 5ffa24
            priv->reset_retries_id =
Packit Service 5ffa24
                g_timeout_add_seconds(MAX(0, retry_time - nm_utils_get_monotonic_timestamp_sec()),
Packit Service 5ffa24
                                      reset_connections_retries,
Packit Service 5ffa24
                                      self);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
activate_slave_connections(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *            priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const char *                 master_device;
Packit Service 5ffa24
    const char *                 master_uuid_settings = NULL;
Packit Service 5ffa24
    const char *                 master_uuid_applied  = NULL;
Packit Service 5ffa24
    guint                        i;
Packit Service 5ffa24
    NMActRequest *               req;
Packit Service 5ffa24
    gboolean                     internal_activation = FALSE;
Packit Service 5ffa24
    NMSettingsConnection *const *connections;
Packit Service 5ffa24
    gboolean                     changed;
Packit Service 5ffa24
Packit Service 5ffa24
    master_device = nm_device_get_iface(device);
Packit Service 5ffa24
    g_assert(master_device);
Packit Service 5ffa24
Packit Service 5ffa24
    req = nm_device_get_act_request(device);
Packit Service 5ffa24
    if (req) {
Packit Service 5ffa24
        NMConnection *        connection;
Packit Service 5ffa24
        NMSettingsConnection *sett_conn;
Packit Service 5ffa24
        NMAuthSubject *       subject;
Packit Service 5ffa24
Packit Service 5ffa24
        connection = nm_active_connection_get_applied_connection(NM_ACTIVE_CONNECTION(req));
Packit Service 5ffa24
        if (connection)
Packit Service 5ffa24
            master_uuid_applied = nm_connection_get_uuid(connection);
Packit Service 5ffa24
Packit Service 5ffa24
        sett_conn = nm_active_connection_get_settings_connection(NM_ACTIVE_CONNECTION(req));
Packit Service 5ffa24
        if (sett_conn) {
Packit Service 5ffa24
            master_uuid_settings = nm_settings_connection_get_uuid(sett_conn);
Packit Service 5ffa24
            if (nm_streq0(master_uuid_settings, master_uuid_applied))
Packit Service 5ffa24
                master_uuid_settings = NULL;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        subject = nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(req));
Packit Service 5ffa24
        internal_activation =
Packit Service 5ffa24
            subject && (nm_auth_subject_get_subject_type(subject) == NM_AUTH_SUBJECT_TYPE_INTERNAL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    changed     = FALSE;
Packit Service 5ffa24
    connections = nm_settings_get_connections(priv->settings, NULL);
Packit Service 5ffa24
    for (i = 0; connections[i]; i++) {
Packit Service 5ffa24
        NMSettingsConnection *sett_conn = connections[i];
Packit Service 5ffa24
        NMSettingConnection * s_slave_con;
Packit Service 5ffa24
        const char *          slave_master;
Packit Service 5ffa24
Packit Service 5ffa24
        s_slave_con =
Packit Service 5ffa24
            nm_connection_get_setting_connection(nm_settings_connection_get_connection(sett_conn));
Packit Service 5ffa24
        slave_master = nm_setting_connection_get_master(s_slave_con);
Packit Service 5ffa24
        if (!slave_master)
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        if (!NM_IN_STRSET(slave_master, master_device, master_uuid_applied, master_uuid_settings))
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!internal_activation) {
Packit Service 5ffa24
            if (nm_settings_connection_autoconnect_retries_get(sett_conn) == 0)
Packit Service 5ffa24
                changed = TRUE;
Packit Service 5ffa24
            nm_settings_connection_autoconnect_retries_reset(sett_conn);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        if (nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                sett_conn,
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
                FALSE)) {
Packit Service 5ffa24
            if (!nm_settings_connection_autoconnect_is_blocked(sett_conn))
Packit Service 5ffa24
                changed = TRUE;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (changed)
Packit Service 5ffa24
        schedule_activate_all(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
activate_secondary_connections(NMPolicy *self, NMConnection *connection, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *      priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMSettingConnection *  s_con;
Packit Service 5ffa24
    NMActiveConnection *   ac;
Packit Service 5ffa24
    PendingSecondaryData * secondary_data;
Packit Service 5ffa24
    GSList *               secondary_ac_list = NULL;
Packit Service 5ffa24
    GError *               error             = NULL;
Packit Service 5ffa24
    guint32                i;
Packit Service 5ffa24
    gboolean               success = TRUE;
Packit Service 5ffa24
    NMActivationStateFlags initial_state_flags;
Packit Service 5ffa24
Packit Service 5ffa24
    s_con = nm_connection_get_setting_connection(connection);
Packit Service 5ffa24
    nm_assert(NM_IS_SETTING_CONNECTION(s_con));
Packit Service 5ffa24
Packit Service 5ffa24
    /* we propagate the activation's state flags. */
Packit Service 5ffa24
    initial_state_flags = nm_device_get_activation_state_flags(device)
Packit Service 5ffa24
                          & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY;
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < nm_setting_connection_get_num_secondaries(s_con); i++) {
Packit Service 5ffa24
        NMSettingsConnection *sett_conn;
Packit Service 5ffa24
        const char *          sec_uuid = nm_setting_connection_get_secondary(s_con, i);
Packit Service 5ffa24
        NMActRequest *        req;
Packit Service 5ffa24
Packit Service 5ffa24
        sett_conn = nm_settings_get_connection_by_uuid(priv->settings, sec_uuid);
Packit Service 5ffa24
        if (!sett_conn) {
Packit Service 5ffa24
            _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
                  "secondary connection '%s' auto-activation failed: The connection doesn't exist.",
Packit Service 5ffa24
                  sec_uuid);
Packit Service 5ffa24
            success = FALSE;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_connection_is_type(nm_settings_connection_get_connection(sett_conn),
Packit Service 5ffa24
                                   NM_SETTING_VPN_SETTING_NAME)) {
Packit Service 5ffa24
            _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
                  "secondary connection '%s (%s)' auto-activation failed: The connection is not a "
Packit Service 5ffa24
                  "VPN.",
Packit Service 5ffa24
                  nm_settings_connection_get_id(sett_conn),
Packit Service 5ffa24
                  sec_uuid);
Packit Service 5ffa24
            success = FALSE;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        req = nm_device_get_act_request(device);
Packit Service 5ffa24
Packit Service 5ffa24
        _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
              "activating secondary connection '%s (%s)' for base connection '%s (%s)'",
Packit Service 5ffa24
              nm_settings_connection_get_id(sett_conn),
Packit Service 5ffa24
              sec_uuid,
Packit Service 5ffa24
              nm_connection_get_id(connection),
Packit Service 5ffa24
              nm_connection_get_uuid(connection));
Packit Service 5ffa24
        ac = nm_manager_activate_connection(
Packit Service 5ffa24
            priv->manager,
Packit Service 5ffa24
            sett_conn,
Packit Service 5ffa24
            NULL,
Packit Service 5ffa24
            nm_dbus_object_get_path(NM_DBUS_OBJECT(req)),
Packit Service 5ffa24
            device,
Packit Service 5ffa24
            nm_active_connection_get_subject(NM_ACTIVE_CONNECTION(req)),
Packit Service 5ffa24
            NM_ACTIVATION_TYPE_MANAGED,
Packit Service 5ffa24
            nm_active_connection_get_activation_reason(NM_ACTIVE_CONNECTION(req)),
Packit Service 5ffa24
            initial_state_flags,
Packit Service 5ffa24
            &error);
Packit Service 5ffa24
        if (ac)
Packit Service 5ffa24
            secondary_ac_list = g_slist_append(secondary_ac_list, g_object_ref(ac));
Packit Service 5ffa24
        else {
Packit Service 5ffa24
            _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
                  "secondary connection '%s (%s)' auto-activation failed: (%d) %s",
Packit Service 5ffa24
                  nm_settings_connection_get_id(sett_conn),
Packit Service 5ffa24
                  sec_uuid,
Packit Service 5ffa24
                  error->code,
Packit Service 5ffa24
                  error->message);
Packit Service 5ffa24
            g_clear_error(&error);
Packit Service 5ffa24
            success = FALSE;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (success && secondary_ac_list != NULL) {
Packit Service 5ffa24
        secondary_data            = pending_secondary_data_new(device, secondary_ac_list);
Packit Service 5ffa24
        priv->pending_secondaries = g_slist_append(priv->pending_secondaries, secondary_data);
Packit Service 5ffa24
    } else
Packit Service 5ffa24
        g_slist_free_full(secondary_ac_list, g_object_unref);
Packit Service 5ffa24
Packit Service 5ffa24
    return success;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_state_changed(NMDevice *          device,
Packit Service 5ffa24
                     NMDeviceState       new_state,
Packit Service 5ffa24
                     NMDeviceState       old_state,
Packit Service 5ffa24
                     NMDeviceStateReason reason,
Packit Service 5ffa24
                     gpointer            user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *     priv = user_data;
Packit Service 5ffa24
    NMPolicy *            self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    NMActiveConnection *  ac;
Packit Service 5ffa24
    NMSettingsConnection *sett_conn = nm_device_get_settings_connection(device);
Packit Service 5ffa24
    NMIP4Config *         ip4_config;
Packit Service 5ffa24
    NMIP6Config *         ip6_config;
Packit Service 5ffa24
    NMSettingConnection * s_con = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    switch (nm_device_state_reason_check(reason)) {
Packit Service 5ffa24
    case NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED:
Packit Service 5ffa24
    case NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED:
Packit Service 5ffa24
    case NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT:
Packit Service 5ffa24
    case NM_DEVICE_STATE_REASON_GSM_APN_FAILED:
Packit Service 5ffa24
        /* Block autoconnection at settings level if there is any settings-specific
Packit Service 5ffa24
         * error reported by the modem (e.g. wrong SIM-PIN or wrong APN). Do not block
Packit Service 5ffa24
         * autoconnection at settings level for errors in the device domain (e.g.
Packit Service 5ffa24
         * a missing SIM or wrong modem initialization).
Packit Service 5ffa24
         */
Packit Service 5ffa24
        if (sett_conn) {
Packit Service 5ffa24
            nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                sett_conn,
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
                TRUE);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    default:
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    switch (new_state) {
Packit Service 5ffa24
    case NM_DEVICE_STATE_FAILED:
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Mark the connection invalid if it failed during activation so that
Packit Service 5ffa24
         * it doesn't get automatically chosen over and over and over again.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        if (sett_conn && old_state >= NM_DEVICE_STATE_PREPARE
Packit Service 5ffa24
            && old_state <= NM_DEVICE_STATE_ACTIVATED) {
Packit Service 5ffa24
            gboolean blocked = FALSE;
Packit Service 5ffa24
            int      tries;
Packit Service 5ffa24
            guint64  con_v;
Packit Service 5ffa24
Packit Service 5ffa24
            if (nm_device_state_reason_check(reason) == NM_DEVICE_STATE_REASON_NO_SECRETS) {
Packit Service 5ffa24
                /* we want to block the connection from auto-connect if it failed due to no-secrets.
Packit Service 5ffa24
                 * However, if a secret-agent registered, since the connection made the last
Packit Service 5ffa24
                 * secret-request, we do not block it. The new secret-agent might not yet
Packit Service 5ffa24
                 * been consulted, and it may be able to provide the secrets.
Packit Service 5ffa24
                 *
Packit Service 5ffa24
                 * We detect this by using a version-id of the agent-manager, which increments
Packit Service 5ffa24
                 * whenever new agents register. Note that the agent-manager's version-id is
Packit Service 5ffa24
                 * never zero and strictly increasing.
Packit Service 5ffa24
                 *
Packit Service 5ffa24
                 * A connection's version-id of zero means that the connection never tried to request secrets.
Packit Service 5ffa24
                 * That can happen when nm_settings_connection_get_secrets() fails early without actually
Packit Service 5ffa24
                 * consulting any agents.
Packit Service 5ffa24
                 */
Packit Service 5ffa24
                con_v = nm_settings_connection_get_last_secret_agent_version_id(sett_conn);
Packit Service 5ffa24
                if (con_v == 0 || con_v == nm_agent_manager_get_agent_version_id(priv->agent_mgr)) {
Packit Service 5ffa24
                    _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                          "connection '%s' now blocked from autoconnect due to no secrets",
Packit Service 5ffa24
                          nm_settings_connection_get_id(sett_conn));
Packit Service 5ffa24
                    nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                        sett_conn,
Packit Service 5ffa24
                        NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NO_SECRETS,
Packit Service 5ffa24
                        TRUE);
Packit Service 5ffa24
                    blocked = TRUE;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            } else if (nm_device_state_reason_check(reason)
Packit Service 5ffa24
                       == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) {
Packit Service 5ffa24
                /* A connection that fails due to dependency-failed is not
Packit Service 5ffa24
                 * able to reconnect until the master connection activates
Packit Service 5ffa24
                 * again; when this happens, the master clears the blocked
Packit Service 5ffa24
                 * reason for all its slaves in activate_slave_connections()
Packit Service 5ffa24
                 * and tries to reconnect them. For this to work, the slave
Packit Service 5ffa24
                 * should be marked as blocked when it fails with
Packit Service 5ffa24
                 * dependency-failed.
Packit Service 5ffa24
                 */
Packit Service 5ffa24
                _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                      "connection '%s' now blocked from autoconnect due to failed dependency",
Packit Service 5ffa24
                      nm_settings_connection_get_id(sett_conn));
Packit Service 5ffa24
                nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                    sett_conn,
Packit Service 5ffa24
                    NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED,
Packit Service 5ffa24
                    TRUE);
Packit Service 5ffa24
                blocked = TRUE;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            if (!blocked) {
Packit Service 5ffa24
                tries = nm_settings_connection_autoconnect_retries_get(sett_conn);
Packit Service 5ffa24
                if (tries > 0) {
Packit Service 5ffa24
                    _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                          "connection '%s' failed to autoconnect; %d tries left",
Packit Service 5ffa24
                          nm_settings_connection_get_id(sett_conn),
Packit Service 5ffa24
                          tries - 1);
Packit Service 5ffa24
                    _connection_autoconnect_retries_set(self, sett_conn, tries - 1);
Packit Service 5ffa24
                } else if (tries != 0) {
Packit Service 5ffa24
                    _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                          "connection '%s' failed to autoconnect; infinite tries left",
Packit Service 5ffa24
                          nm_settings_connection_get_id(sett_conn));
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            nm_settings_connection_clear_secrets(sett_conn, FALSE, FALSE);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_ACTIVATED:
Packit Service 5ffa24
        if (sett_conn) {
Packit Service 5ffa24
            /* Reset auto retries back to default since connection was successful */
Packit Service 5ffa24
            nm_settings_connection_autoconnect_retries_reset(sett_conn);
Packit Service 5ffa24
Packit Service 5ffa24
            /* And clear secrets so they will always be requested from the
Packit Service 5ffa24
             * settings service when the next connection is made.
Packit Service 5ffa24
             */
Packit Service 5ffa24
            nm_settings_connection_clear_secrets(sett_conn, FALSE, FALSE);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        /* Add device's new IPv4 and IPv6 configs to DNS */
Packit Service 5ffa24
Packit Service 5ffa24
        nm_dns_manager_begin_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
Packit Service 5ffa24
        ip4_config = nm_device_get_ip4_config(device);
Packit Service 5ffa24
        if (ip4_config)
Packit Service 5ffa24
            _dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                       NM_IP_CONFIG_CAST(ip4_config),
Packit Service 5ffa24
                                       NM_DNS_IP_CONFIG_TYPE_DEFAULT,
Packit Service 5ffa24
                                       device);
Packit Service 5ffa24
        ip6_config = nm_device_get_ip6_config(device);
Packit Service 5ffa24
        if (ip6_config)
Packit Service 5ffa24
            _dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                       NM_IP_CONFIG_CAST(ip6_config),
Packit Service 5ffa24
                                       NM_DNS_IP_CONFIG_TYPE_DEFAULT,
Packit Service 5ffa24
                                       device);
Packit Service 5ffa24
Packit Service 5ffa24
        update_routing_and_dns(self, FALSE, device);
Packit Service 5ffa24
Packit Service 5ffa24
        nm_dns_manager_end_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_UNMANAGED:
Packit Service 5ffa24
    case NM_DEVICE_STATE_UNAVAILABLE:
Packit Service 5ffa24
        if (old_state > NM_DEVICE_STATE_DISCONNECTED)
Packit Service 5ffa24
            update_routing_and_dns(self, FALSE, device);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_DEACTIVATING:
Packit Service 5ffa24
        if (sett_conn) {
Packit Service 5ffa24
            NMSettingsAutoconnectBlockedReason blocked_reason =
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE;
Packit Service 5ffa24
Packit Service 5ffa24
            switch (nm_device_state_reason_check(reason)) {
Packit Service 5ffa24
            case NM_DEVICE_STATE_REASON_USER_REQUESTED:
Packit Service 5ffa24
                blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED:
Packit Service 5ffa24
                blocked_reason = NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_FAILED;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            default:
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
            if (blocked_reason != NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_NONE) {
Packit Service 5ffa24
                _LOGD(LOGD_DEVICE,
Packit Service 5ffa24
                      "blocking autoconnect of connection '%s': %s",
Packit Service 5ffa24
                      nm_settings_connection_get_id(sett_conn),
Packit Service 5ffa24
                      NM_UTILS_LOOKUP_STR_A(nm_device_state_reason_to_str,
Packit Service 5ffa24
                                            nm_device_state_reason_check(reason)));
Packit Service 5ffa24
                nm_settings_connection_autoconnect_blocked_reason_set(sett_conn,
Packit Service 5ffa24
                                                                      blocked_reason,
Packit Service 5ffa24
                                                                      TRUE);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
        ip6_remove_device_prefix_delegations(self, device);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_DISCONNECTED:
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(device, device_dns_lookup_done, self);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Reset retry counts for a device's connections when carrier on; if cable
Packit Service 5ffa24
         * was unplugged and plugged in again, we should try to reconnect.
Packit Service 5ffa24
         */
Packit Service 5ffa24
        if (nm_device_state_reason_check(reason) == NM_DEVICE_STATE_REASON_CARRIER
Packit Service 5ffa24
            && old_state == NM_DEVICE_STATE_UNAVAILABLE)
Packit Service 5ffa24
            reset_autoconnect_all(self, device, FALSE);
Packit Service 5ffa24
Packit Service 5ffa24
        if (old_state > NM_DEVICE_STATE_DISCONNECTED)
Packit Service 5ffa24
            update_routing_and_dns(self, FALSE, device);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Device is now available for auto-activation */
Packit Service 5ffa24
        schedule_activate_check(self, device);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
Packit Service 5ffa24
    case NM_DEVICE_STATE_PREPARE:
Packit Service 5ffa24
        /* Reset auto-connect retries of all slaves and schedule them for
Packit Service 5ffa24
         * activation. */
Packit Service 5ffa24
        activate_slave_connections(self, device);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Now that the device state is progressing, we don't care
Packit Service 5ffa24
         * anymore for the AC state. */
Packit Service 5ffa24
        ac = (NMActiveConnection *) nm_device_get_act_request(device);
Packit Service 5ffa24
        if (ac && g_hash_table_remove(priv->pending_active_connections, ac)) {
Packit Service 5ffa24
            g_signal_handlers_disconnect_by_func(ac, pending_ac_state_changed, self);
Packit Service 5ffa24
            g_object_weak_unref(G_OBJECT(ac), pending_ac_gone, self);
Packit Service 5ffa24
            g_object_unref(self);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_IP_CONFIG:
Packit Service 5ffa24
        /* We must have secrets if we got here. */
Packit Service 5ffa24
        if (sett_conn)
Packit Service 5ffa24
            nm_settings_connection_autoconnect_blocked_reason_set(
Packit Service 5ffa24
                sett_conn,
Packit Service 5ffa24
                NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_ALL,
Packit Service 5ffa24
                FALSE);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case NM_DEVICE_STATE_SECONDARIES:
Packit Service 5ffa24
        if (sett_conn)
Packit Service 5ffa24
            s_con = nm_connection_get_setting_connection(
Packit Service 5ffa24
                nm_settings_connection_get_connection(sett_conn));
Packit Service 5ffa24
        if (s_con && nm_setting_connection_get_num_secondaries(s_con) > 0) {
Packit Service 5ffa24
            /* Make routes and DNS up-to-date before activating dependent connections */
Packit Service 5ffa24
            update_routing_and_dns(self, FALSE, device);
Packit Service 5ffa24
Packit Service 5ffa24
            /* Activate secondary (VPN) connections */
Packit Service 5ffa24
            if (!activate_secondary_connections(self,
Packit Service 5ffa24
                                                nm_settings_connection_get_connection(sett_conn),
Packit Service 5ffa24
                                                device)) {
Packit Service 5ffa24
                nm_device_queue_state(device,
Packit Service 5ffa24
                                      NM_DEVICE_STATE_FAILED,
Packit Service 5ffa24
                                      NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        } else
Packit Service 5ffa24
            nm_device_queue_state(device, NM_DEVICE_STATE_ACTIVATED, NM_DEVICE_STATE_REASON_NONE);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
Packit Service 5ffa24
    default:
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    check_activating_active_connections(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_ip_config_changed(NMDevice *  device,
Packit Service 5ffa24
                         NMIPConfig *new_config,
Packit Service 5ffa24
                         NMIPConfig *old_config,
Packit Service 5ffa24
                         gpointer    user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    int              addr_family;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(new_config || old_config);
Packit Service 5ffa24
    nm_assert(!new_config || NM_IS_IP_CONFIG(new_config));
Packit Service 5ffa24
    nm_assert(!old_config || NM_IS_IP_CONFIG(old_config));
Packit Service 5ffa24
Packit Service 5ffa24
    if (new_config) {
Packit Service 5ffa24
        addr_family = nm_ip_config_get_addr_family(new_config);
Packit Service 5ffa24
        nm_assert(!old_config || addr_family == nm_ip_config_get_addr_family(old_config));
Packit Service 5ffa24
    } else
Packit Service 5ffa24
        addr_family = nm_ip_config_get_addr_family(old_config);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_begin_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
Packit Service 5ffa24
    /* We catch already all the IP events registering on the device state changes but
Packit Service 5ffa24
     * the ones where the IP changes but the device state keep stable (i.e., activated):
Packit Service 5ffa24
     * ignore IP config changes but when the device is in activated state.
Packit Service 5ffa24
     * Prevents unnecessary changes to DNS information.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (nm_device_get_state(device) == NM_DEVICE_STATE_ACTIVATED) {
Packit Service 5ffa24
        if (old_config != new_config) {
Packit Service 5ffa24
            if (new_config)
Packit Service 5ffa24
                _dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                           new_config,
Packit Service 5ffa24
                                           NM_DNS_IP_CONFIG_TYPE_DEFAULT,
Packit Service 5ffa24
                                           device);
Packit Service 5ffa24
            if (old_config)
Packit Service 5ffa24
                nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                             old_config,
Packit Service 5ffa24
                                             NM_DNS_IP_CONFIG_TYPE_REMOVED);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        update_ip_dns(self, addr_family, device);
Packit Service 5ffa24
        if (addr_family == AF_INET)
Packit Service 5ffa24
            update_ip4_routing(self, TRUE);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            update_ip6_routing(self, TRUE);
Packit Service 5ffa24
        update_system_hostname(self, addr_family == AF_INET ? "ip4 conf" : "ip6 conf");
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        /* Old configs get removed immediately */
Packit Service 5ffa24
        if (old_config)
Packit Service 5ffa24
            nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                         old_config,
Packit Service 5ffa24
                                         NM_DNS_IP_CONFIG_TYPE_REMOVED);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_end_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_autoconnect_changed(NMDevice *device, GParamSpec *pspec, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    schedule_activate_check(self, device);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_recheck_auto_activate(NMDevice *device, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    schedule_activate_check(self, device);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
devices_list_unregister(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_data((GObject *) device, priv);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
devices_list_register(NMPolicy *self, NMDevice *device)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Connect state-changed with _after, so that the handler is invoked after other handlers. */
Packit Service 5ffa24
    g_signal_connect_after(device, NM_DEVICE_STATE_CHANGED, (GCallback) device_state_changed, priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     NM_DEVICE_IP4_CONFIG_CHANGED,
Packit Service 5ffa24
                     (GCallback) device_ip_config_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     NM_DEVICE_IP6_CONFIG_CHANGED,
Packit Service 5ffa24
                     (GCallback) device_ip_config_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     NM_DEVICE_IP6_PREFIX_DELEGATED,
Packit Service 5ffa24
                     (GCallback) device_ip6_prefix_delegated,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     NM_DEVICE_IP6_SUBNET_NEEDED,
Packit Service 5ffa24
                     (GCallback) device_ip6_subnet_needed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     "notify::" NM_DEVICE_AUTOCONNECT,
Packit Service 5ffa24
                     (GCallback) device_autoconnect_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(device,
Packit Service 5ffa24
                     NM_DEVICE_RECHECK_AUTO_ACTIVATE,
Packit Service 5ffa24
                     (GCallback) device_recheck_auto_activate,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_added(NMManager *manager, NMDevice *device, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    g_return_if_fail(NM_IS_POLICY(self));
Packit Service 5ffa24
Packit Service 5ffa24
    priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!g_hash_table_add(priv->devices, device))
Packit Service 5ffa24
        g_return_if_reached();
Packit Service 5ffa24
Packit Service 5ffa24
    devices_list_register(self, device);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
device_removed(NMManager *manager, NMDevice *device, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    ActivateData *   data;
Packit Service 5ffa24
Packit Service 5ffa24
    /* TODO: is this needed? The delegations are cleaned up
Packit Service 5ffa24
     * on transition to deactivated too. */
Packit Service 5ffa24
    ip6_remove_device_prefix_delegations(self, device);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Clear any idle callbacks for this device */
Packit Service 5ffa24
    data = find_pending_activation(self, device);
Packit Service 5ffa24
    if (data && data->autoactivate_id)
Packit Service 5ffa24
        activate_data_free(data);
Packit Service 5ffa24
Packit Service 5ffa24
    if (g_hash_table_remove(priv->devices, device))
Packit Service 5ffa24
        devices_list_unregister(self, device);
Packit Service 5ffa24
Packit Service 5ffa24
    /* Don't update routing and DNS here as we've already handled that
Packit Service 5ffa24
     * for devices that need it when the device's state changed to UNMANAGED.
Packit Service 5ffa24
     */
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
vpn_connection_activated(NMPolicy *self, NMVpnConnection *vpn)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMIP4Config *    ip4_config;
Packit Service 5ffa24
    NMIP6Config *    ip6_config;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_begin_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
Packit Service 5ffa24
    ip4_config = nm_vpn_connection_get_ip4_config(vpn);
Packit Service 5ffa24
    if (ip4_config)
Packit Service 5ffa24
        nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                     NM_IP_CONFIG_CAST(ip4_config),
Packit Service 5ffa24
                                     NM_DNS_IP_CONFIG_TYPE_VPN);
Packit Service 5ffa24
Packit Service 5ffa24
    ip6_config = nm_vpn_connection_get_ip6_config(vpn);
Packit Service 5ffa24
    if (ip6_config)
Packit Service 5ffa24
        nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                     NM_IP_CONFIG_CAST(ip6_config),
Packit Service 5ffa24
                                     NM_DNS_IP_CONFIG_TYPE_VPN);
Packit Service 5ffa24
Packit Service 5ffa24
    update_routing_and_dns(self, TRUE, NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_end_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
vpn_connection_deactivated(NMPolicy *self, NMVpnConnection *vpn)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMIP4Config *    ip4_config;
Packit Service 5ffa24
    NMIP6Config *    ip6_config;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_begin_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
Packit Service 5ffa24
    ip4_config = nm_vpn_connection_get_ip4_config(vpn);
Packit Service 5ffa24
    if (ip4_config)
Packit Service 5ffa24
        nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                     NM_IP_CONFIG_CAST(ip4_config),
Packit Service 5ffa24
                                     NM_DNS_IP_CONFIG_TYPE_REMOVED);
Packit Service 5ffa24
Packit Service 5ffa24
    ip6_config = nm_vpn_connection_get_ip6_config(vpn);
Packit Service 5ffa24
    if (ip6_config)
Packit Service 5ffa24
        nm_dns_manager_set_ip_config(priv->dns_manager,
Packit Service 5ffa24
                                     NM_IP_CONFIG_CAST(ip6_config),
Packit Service 5ffa24
                                     NM_DNS_IP_CONFIG_TYPE_REMOVED);
Packit Service 5ffa24
Packit Service 5ffa24
    update_routing_and_dns(self, TRUE, NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_dns_manager_end_updates(priv->dns_manager, __func__);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
vpn_connection_state_changed(NMVpnConnection *             vpn,
Packit Service 5ffa24
                             NMVpnConnectionState          new_state,
Packit Service 5ffa24
                             NMVpnConnectionState          old_state,
Packit Service 5ffa24
                             NMActiveConnectionStateReason reason,
Packit Service 5ffa24
                             NMPolicy *                    self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED)
Packit Service 5ffa24
        vpn_connection_activated(self, vpn);
Packit Service 5ffa24
    else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) {
Packit Service 5ffa24
        /* Only clean up IP/DNS if the connection ever got past IP_CONFIG */
Packit Service 5ffa24
        if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET
Packit Service 5ffa24
            && old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED)
Packit Service 5ffa24
            vpn_connection_deactivated(self, vpn);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
vpn_connection_retry_after_failure(NMVpnConnection *vpn, NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *     priv       = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMActiveConnection *  ac         = NM_ACTIVE_CONNECTION(vpn);
Packit Service 5ffa24
    NMSettingsConnection *connection = nm_active_connection_get_settings_connection(ac);
Packit Service 5ffa24
    GError *              error      = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Attempt to reconnect VPN connections that failed after being connected */
Packit Service 5ffa24
    if (!nm_manager_activate_connection(
Packit Service 5ffa24
            priv->manager,
Packit Service 5ffa24
            connection,
Packit Service 5ffa24
            NULL,
Packit Service 5ffa24
            NULL,
Packit Service 5ffa24
            NULL,
Packit Service 5ffa24
            nm_active_connection_get_subject(ac),
Packit Service 5ffa24
            NM_ACTIVATION_TYPE_MANAGED,
Packit Service 5ffa24
            nm_active_connection_get_activation_reason(ac),
Packit Service 5ffa24
            (nm_active_connection_get_state_flags(ac)
Packit Service 5ffa24
             & NM_ACTIVATION_STATE_FLAG_LIFETIME_BOUND_TO_PROFILE_VISIBILITY),
Packit Service 5ffa24
            &error)) {
Packit Service 5ffa24
        _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
              "VPN '%s' reconnect failed: %s",
Packit Service 5ffa24
              nm_settings_connection_get_id(connection),
Packit Service 5ffa24
              error->message ?: "unknown");
Packit Service 5ffa24
        g_clear_error(&error);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
active_connection_state_changed(NMActiveConnection *active, GParamSpec *pspec, NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMActiveConnectionState state = nm_active_connection_get_state(active);
Packit Service 5ffa24
Packit Service 5ffa24
    if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
Packit Service 5ffa24
        process_secondaries(self, active, TRUE);
Packit Service 5ffa24
    else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED)
Packit Service 5ffa24
        process_secondaries(self, active, FALSE);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
active_connection_keep_alive_changed(NMKeepAlive *keep_alive, GParamSpec *pspec, NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv;
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    GError *            error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_POLICY(self));
Packit Service 5ffa24
    nm_assert(NM_IS_KEEP_ALIVE(keep_alive));
Packit Service 5ffa24
    nm_assert(NM_IS_ACTIVE_CONNECTION(nm_keep_alive_get_owner(keep_alive)));
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_keep_alive_is_alive(keep_alive))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    ac = nm_keep_alive_get_owner(keep_alive);
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_active_connection_get_state(ac) > NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_manager_deactivate_connection(priv->manager,
Packit Service 5ffa24
                                          ac,
Packit Service 5ffa24
                                          NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
Packit Service 5ffa24
                                          &error)) {
Packit Service 5ffa24
        _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
              "connection '%s' is no longer kept alive, but error deactivating it: %s",
Packit Service 5ffa24
              nm_active_connection_get_settings_connection_id(ac),
Packit Service 5ffa24
              error->message);
Packit Service 5ffa24
        g_clear_error(&error);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
active_connection_added(NMManager *manager, NMActiveConnection *active, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    NMKeepAlive *    keep_alive;
Packit Service 5ffa24
Packit Service 5ffa24
    if (NM_IS_VPN_CONNECTION(active)) {
Packit Service 5ffa24
        g_signal_connect(active,
Packit Service 5ffa24
                         NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED,
Packit Service 5ffa24
                         G_CALLBACK(vpn_connection_state_changed),
Packit Service 5ffa24
                         self);
Packit Service 5ffa24
        g_signal_connect(active,
Packit Service 5ffa24
                         NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE,
Packit Service 5ffa24
                         G_CALLBACK(vpn_connection_retry_after_failure),
Packit Service 5ffa24
                         self);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    keep_alive = nm_active_connection_get_keep_alive(active);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_keep_alive_arm(keep_alive);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_connect(active,
Packit Service 5ffa24
                     "notify::" NM_ACTIVE_CONNECTION_STATE,
Packit Service 5ffa24
                     G_CALLBACK(active_connection_state_changed),
Packit Service 5ffa24
                     self);
Packit Service 5ffa24
    g_signal_connect(keep_alive,
Packit Service 5ffa24
                     "notify::" NM_KEEP_ALIVE_ALIVE,
Packit Service 5ffa24
                     G_CALLBACK(active_connection_keep_alive_changed),
Packit Service 5ffa24
                     self);
Packit Service 5ffa24
    active_connection_keep_alive_changed(keep_alive, NULL, self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
active_connection_removed(NMManager *manager, NMActiveConnection *active, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_func(active, vpn_connection_state_changed, self);
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_func(active, vpn_connection_retry_after_failure, self);
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_func(active, active_connection_state_changed, self);
Packit Service 5ffa24
    g_signal_handlers_disconnect_by_func(nm_active_connection_get_keep_alive(active),
Packit Service 5ffa24
                                         active_connection_keep_alive_changed,
Packit Service 5ffa24
                                         self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static gboolean
Packit Service 5ffa24
schedule_activate_all_cb(gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = user_data;
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *    tmp_lst;
Packit Service 5ffa24
    NMDevice *       device;
Packit Service 5ffa24
Packit Service 5ffa24
    priv->schedule_activate_all_id = 0;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_device (priv->manager, device, tmp_lst)
Packit Service 5ffa24
        schedule_activate_check(self, device);
Packit Service 5ffa24
Packit Service 5ffa24
    return G_SOURCE_REMOVE;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
schedule_activate_all(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    /* always restart the idle handler. That way, we settle
Packit Service 5ffa24
     * all other events before restarting to activate them. */
Packit Service 5ffa24
    nm_clear_g_source(&priv->schedule_activate_all_id);
Packit Service 5ffa24
    priv->schedule_activate_all_id = g_idle_add(schedule_activate_all_cb, self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_added(NMSettings *settings, NMSettingsConnection *connection, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    schedule_activate_all(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
firewall_state_changed(NMFirewallManager *manager, gboolean initialized_now, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = (NMPolicy *) user_data;
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    const CList *    tmp_lst;
Packit Service 5ffa24
    NMDevice *       device;
Packit Service 5ffa24
Packit Service 5ffa24
    if (initialized_now) {
Packit Service 5ffa24
        /* the firewall manager was initializing, but all requests
Packit Service 5ffa24
         * so fare were queued and are already sent. No need to
Packit Service 5ffa24
         * re-update the firewall zone of the devices. */
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_firewall_manager_get_running(manager))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    /* add interface of each device to correct zone */
Packit Service 5ffa24
    nm_manager_for_each_device (priv->manager, device, tmp_lst)
Packit Service 5ffa24
        nm_device_update_firewall_zone(device);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
dns_config_changed(NMDnsManager *dns_manager, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = (NMPolicy *) user_data;
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMDevice *       device;
Packit Service 5ffa24
    const CList *    tmp_lst;
Packit Service 5ffa24
Packit Service 5ffa24
    /* We are currently updating the hostname in the DNS manager.
Packit Service 5ffa24
     * This doesn't warrant a new DNS lookup.*/
Packit Service 5ffa24
    if (priv->updating_dns)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_device (priv->manager, device, tmp_lst) {
Packit Service 5ffa24
        nm_device_clear_dns_lookup_data(device);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    update_system_hostname(self, "DNS configuration changed");
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_updated(NMSettings *          settings,
Packit Service 5ffa24
                   NMSettingsConnection *connection,
Packit Service 5ffa24
                   guint                 update_reason_u,
Packit Service 5ffa24
                   gpointer              user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *                priv          = user_data;
Packit Service 5ffa24
    NMPolicy *                       self          = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
    NMSettingsConnectionUpdateReason update_reason = update_reason_u;
Packit Service 5ffa24
Packit Service 5ffa24
    if (NM_FLAGS_HAS(update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_REAPPLY_PARTIAL)) {
Packit Service 5ffa24
        const CList *tmp_lst;
Packit Service 5ffa24
        NMDevice *   device;
Packit Service 5ffa24
Packit Service 5ffa24
        /* find device with given connection */
Packit Service 5ffa24
        nm_manager_for_each_device (priv->manager, device, tmp_lst) {
Packit Service 5ffa24
            if (nm_device_get_settings_connection(device) == connection)
Packit Service 5ffa24
                nm_device_reapply_settings_immediately(device);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    schedule_activate_all(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_deactivate_if_active(NMPolicy *self, NMSettingsConnection *connection)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *   priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    NMActiveConnection *ac;
Packit Service 5ffa24
    const CList *       tmp_list, *tmp_safe;
Packit Service 5ffa24
    GError *            error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_SETTINGS_CONNECTION(connection));
Packit Service 5ffa24
Packit Service 5ffa24
    nm_manager_for_each_active_connection_safe (priv->manager, ac, tmp_list, tmp_safe) {
Packit Service 5ffa24
        if (nm_active_connection_get_settings_connection(ac) == connection
Packit Service 5ffa24
            && (nm_active_connection_get_state(ac) <= NM_ACTIVE_CONNECTION_STATE_ACTIVATED)) {
Packit Service 5ffa24
            if (!nm_manager_deactivate_connection(priv->manager,
Packit Service 5ffa24
                                                  ac,
Packit Service 5ffa24
                                                  NM_DEVICE_STATE_REASON_CONNECTION_REMOVED,
Packit Service 5ffa24
                                                  &error)) {
Packit Service 5ffa24
                _LOGW(LOGD_DEVICE,
Packit Service 5ffa24
                      "connection '%s' disappeared, but error deactivating it: (%d) %s",
Packit Service 5ffa24
                      nm_settings_connection_get_id(connection),
Packit Service 5ffa24
                      error ? error->code : -1,
Packit Service 5ffa24
                      error ? error->message : "(unknown)");
Packit Service 5ffa24
                g_clear_error(&error);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_removed(NMSettings *settings, NMSettingsConnection *connection, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    _deactivate_if_active(self, connection);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_flags_changed(NMSettings *settings, NMSettingsConnection *connection, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv = user_data;
Packit Service 5ffa24
    NMPolicy *       self = _PRIV_TO_SELF(priv);
Packit Service 5ffa24
Packit Service 5ffa24
    if (NM_FLAGS_HAS(nm_settings_connection_get_flags(connection),
Packit Service 5ffa24
                     NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE)) {
Packit Service 5ffa24
        if (!nm_settings_connection_autoconnect_is_blocked(connection))
Packit Service 5ffa24
            schedule_activate_all(self);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
secret_agent_registered(NMSettings *settings, NMSecretAgent *agent, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *self = NM_POLICY(user_data);
Packit Service 5ffa24
Packit Service 5ffa24
    /* The registered secret agent may provide some missing secrets. Thus we
Packit Service 5ffa24
     * reset retries count here and schedule activation, so that the
Packit Service 5ffa24
     * connections failed due to missing secrets may re-try auto-connection.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    if (reset_autoconnect_all(self, NULL, TRUE))
Packit Service 5ffa24
        schedule_activate_all(self);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMActiveConnection *
Packit Service 5ffa24
nm_policy_get_default_ip4_ac(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return NM_POLICY_GET_PRIVATE(self)->default_ac4;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMActiveConnection *
Packit Service 5ffa24
nm_policy_get_default_ip6_ac(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return NM_POLICY_GET_PRIVATE(self)->default_ac6;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMActiveConnection *
Packit Service 5ffa24
nm_policy_get_activating_ip4_ac(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return NM_POLICY_GET_PRIVATE(self)->activating_ac4;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMActiveConnection *
Packit Service 5ffa24
nm_policy_get_activating_ip6_ac(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    return NM_POLICY_GET_PRIVATE(self)->activating_ac6;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static NM_UTILS_LOOKUP_STR_DEFINE(_hostname_mode_to_string,
Packit Service 5ffa24
                                  NMPolicyHostnameMode,
Packit Service 5ffa24
                                  NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT("unknown"),
Packit Service 5ffa24
                                  NM_UTILS_LOOKUP_STR_ITEM(NM_POLICY_HOSTNAME_MODE_NONE, "none"),
Packit Service 5ffa24
                                  NM_UTILS_LOOKUP_STR_ITEM(NM_POLICY_HOSTNAME_MODE_DHCP, "dhcp"),
Packit Service 5ffa24
                                  NM_UTILS_LOOKUP_STR_ITEM(NM_POLICY_HOSTNAME_MODE_FULL, "full"), );
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(object);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    switch (prop_id) {
Packit Service 5ffa24
    case PROP_DEFAULT_IP4_AC:
Packit Service 5ffa24
        g_value_set_object(value, priv->default_ac4);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case PROP_DEFAULT_IP6_AC:
Packit Service 5ffa24
        g_value_set_object(value, priv->default_ac6);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case PROP_ACTIVATING_IP4_AC:
Packit Service 5ffa24
        g_value_set_object(value, priv->activating_ac4);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case PROP_ACTIVATING_IP6_AC:
Packit Service 5ffa24
        g_value_set_object(value, priv->activating_ac6);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    default:
Packit Service 5ffa24
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(object);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    switch (prop_id) {
Packit Service 5ffa24
    case PROP_MANAGER:
Packit Service 5ffa24
        /* construct-only */
Packit Service 5ffa24
        priv->manager = g_value_get_object(value);
Packit Service 5ffa24
        g_return_if_fail(NM_IS_MANAGER(priv->manager));
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    case PROP_SETTINGS:
Packit Service 5ffa24
        /* construct-only */
Packit Service 5ffa24
        priv->settings = g_value_dup_object(value);
Packit Service 5ffa24
        g_return_if_fail(NM_IS_SETTINGS(priv->settings));
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    default:
Packit Service 5ffa24
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
Packit Service 5ffa24
        break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
nm_policy_init(NMPolicy *self)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicyPrivate *priv          = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    gs_free char *   hostname_mode = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_init(&priv->pending_activation_checks);
Packit Service 5ffa24
Packit Service 5ffa24
    priv->netns = g_object_ref(nm_netns_get());
Packit Service 5ffa24
Packit Service 5ffa24
    priv->hostname_manager = g_object_ref(nm_hostname_manager_get());
Packit Service 5ffa24
Packit Service 5ffa24
    hostname_mode =
Packit Service 5ffa24
        nm_config_data_get_value(NM_CONFIG_GET_DATA_ORIG,
Packit Service 5ffa24
                                 NM_CONFIG_KEYFILE_GROUP_MAIN,
Packit Service 5ffa24
                                 NM_CONFIG_KEYFILE_KEY_MAIN_HOSTNAME_MODE,
Packit Service 5ffa24
                                 NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
Packit Service 5ffa24
    if (nm_streq0(hostname_mode, "none"))
Packit Service 5ffa24
        priv->hostname_mode = NM_POLICY_HOSTNAME_MODE_NONE;
Packit Service 5ffa24
    else if (nm_streq0(hostname_mode, "dhcp"))
Packit Service 5ffa24
        priv->hostname_mode = NM_POLICY_HOSTNAME_MODE_DHCP;
Packit Service 5ffa24
    else /* default - full mode */
Packit Service 5ffa24
        priv->hostname_mode = NM_POLICY_HOSTNAME_MODE_FULL;
Packit Service 5ffa24
Packit Service 5ffa24
    priv->devices                    = g_hash_table_new(nm_direct_hash, NULL);
Packit Service 5ffa24
    priv->pending_active_connections = g_hash_table_new(nm_direct_hash, NULL);
Packit Service 5ffa24
    priv->ip6_prefix_delegations     = g_array_new(FALSE, FALSE, sizeof(IP6PrefixDelegation));
Packit Service 5ffa24
    g_array_set_clear_func(priv->ip6_prefix_delegations, clear_ip6_prefix_delegation);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
constructed(GObject *object)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self     = NM_POLICY(object);
Packit Service 5ffa24
    NMPolicyPrivate *priv     = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    char *           hostname = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Grab hostname on startup and use that if nothing provides one */
Packit Service 5ffa24
    if ((hostname = _get_hostname(self))) {
Packit Service 5ffa24
        /* init last_hostname */
Packit Service 5ffa24
        priv->last_hostname = hostname;
Packit Service 5ffa24
Packit Service 5ffa24
        /* only cache it if it's a valid hostname */
Packit Service 5ffa24
        if (nm_utils_is_specific_hostname(hostname))
Packit Service 5ffa24
            priv->orig_hostname = g_strdup(hostname);
Packit Service 5ffa24
    }
Packit Service 5ffa24
    _LOGT(LOGD_DNS,
Packit Service 5ffa24
          "hostname-original: set to %s%s%s",
Packit Service 5ffa24
          NM_PRINT_FMT_QUOTE_STRING(priv->orig_hostname));
Packit Service 5ffa24
Packit Service 5ffa24
    priv->agent_mgr = g_object_ref(nm_agent_manager_get());
Packit Service 5ffa24
Packit Service 5ffa24
    priv->firewall_manager = g_object_ref(nm_firewall_manager_get());
Packit Service 5ffa24
    g_signal_connect(priv->firewall_manager,
Packit Service 5ffa24
                     NM_FIREWALL_MANAGER_STATE_CHANGED,
Packit Service 5ffa24
                     G_CALLBACK(firewall_state_changed),
Packit Service 5ffa24
                     self);
Packit Service 5ffa24
Packit Service 5ffa24
    priv->dns_manager = g_object_ref(nm_dns_manager_get());
Packit Service 5ffa24
    nm_dns_manager_set_initial_hostname(priv->dns_manager, priv->orig_hostname);
Packit Service 5ffa24
    priv->config_changed_id = g_signal_connect(priv->dns_manager,
Packit Service 5ffa24
                                               NM_DNS_MANAGER_CONFIG_CHANGED,
Packit Service 5ffa24
                                               G_CALLBACK(dns_config_changed),
Packit Service 5ffa24
                                               self);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_connect(priv->hostname_manager,
Packit Service 5ffa24
                     "notify::" NM_HOSTNAME_MANAGER_HOSTNAME,
Packit Service 5ffa24
                     (GCallback) hostname_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     "notify::" NM_MANAGER_SLEEPING,
Packit Service 5ffa24
                     (GCallback) sleeping_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     "notify::" NM_MANAGER_NETWORKING_ENABLED,
Packit Service 5ffa24
                     (GCallback) sleeping_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     NM_MANAGER_INTERNAL_DEVICE_ADDED,
Packit Service 5ffa24
                     (GCallback) device_added,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     NM_MANAGER_INTERNAL_DEVICE_REMOVED,
Packit Service 5ffa24
                     (GCallback) device_removed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     NM_MANAGER_ACTIVE_CONNECTION_ADDED,
Packit Service 5ffa24
                     (GCallback) active_connection_added,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->manager,
Packit Service 5ffa24
                     NM_MANAGER_ACTIVE_CONNECTION_REMOVED,
Packit Service 5ffa24
                     (GCallback) active_connection_removed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_connect(priv->settings,
Packit Service 5ffa24
                     NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
Packit Service 5ffa24
                     (GCallback) connection_added,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->settings,
Packit Service 5ffa24
                     NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
Packit Service 5ffa24
                     (GCallback) connection_updated,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->settings,
Packit Service 5ffa24
                     NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
Packit Service 5ffa24
                     (GCallback) connection_removed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
    g_signal_connect(priv->settings,
Packit Service 5ffa24
                     NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED,
Packit Service 5ffa24
                     (GCallback) connection_flags_changed,
Packit Service 5ffa24
                     priv);
Packit Service 5ffa24
Packit Service 5ffa24
    g_signal_connect(priv->agent_mgr,
Packit Service 5ffa24
                     NM_AGENT_MANAGER_AGENT_REGISTERED,
Packit Service 5ffa24
                     G_CALLBACK(secret_agent_registered),
Packit Service 5ffa24
                     self);
Packit Service 5ffa24
Packit Service 5ffa24
    G_OBJECT_CLASS(nm_policy_parent_class)->constructed(object);
Packit Service 5ffa24
Packit Service 5ffa24
    _LOGD(LOGD_DNS, "hostname-mode: %s", _hostname_mode_to_string(priv->hostname_mode));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
NMPolicy *
Packit Service 5ffa24
nm_policy_new(NMManager *manager, NMSettings *settings)
Packit Service 5ffa24
{
Packit Service 5ffa24
    g_return_val_if_fail(NM_IS_MANAGER(manager), NULL);
Packit Service 5ffa24
    g_return_val_if_fail(NM_IS_SETTINGS(settings), NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    return g_object_new(NM_TYPE_POLICY,
Packit Service 5ffa24
                        NM_POLICY_MANAGER,
Packit Service 5ffa24
                        manager,
Packit Service 5ffa24
                        NM_POLICY_SETTINGS,
Packit Service 5ffa24
                        settings,
Packit Service 5ffa24
                        NULL);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
dispose(GObject *object)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(object);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
    GHashTableIter   h_iter;
Packit Service 5ffa24
    NMDevice *       device;
Packit Service 5ffa24
    ActivateData *   data, *data_safe;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_clear_g_object(&priv->default_ac4);
Packit Service 5ffa24
    nm_clear_g_object(&priv->default_ac6);
Packit Service 5ffa24
    nm_clear_g_object(&priv->activating_ac4);
Packit Service 5ffa24
    nm_clear_g_object(&priv->activating_ac6);
Packit Service 5ffa24
    nm_clear_pointer(&priv->pending_active_connections, g_hash_table_unref);
Packit Service 5ffa24
Packit Service 5ffa24
    c_list_for_each_entry_safe (data, data_safe, &priv->pending_activation_checks, pending_lst)
Packit Service 5ffa24
        activate_data_free(data);
Packit Service 5ffa24
Packit Service 5ffa24
    g_slist_free_full(priv->pending_secondaries, (GDestroyNotify) pending_secondary_data_free);
Packit Service 5ffa24
    priv->pending_secondaries = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->firewall_manager) {
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(priv->firewall_manager, firewall_state_changed, self);
Packit Service 5ffa24
        g_clear_object(&priv->firewall_manager);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->agent_mgr) {
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_func(priv->agent_mgr, secret_agent_registered, self);
Packit Service 5ffa24
        g_clear_object(&priv->agent_mgr);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->dns_manager) {
Packit Service 5ffa24
        nm_clear_g_signal_handler(priv->dns_manager, &priv->config_changed_id);
Packit Service 5ffa24
        g_clear_object(&priv->dns_manager);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_iter_init(&h_iter, priv->devices);
Packit Service 5ffa24
    if (g_hash_table_iter_next(&h_iter, (gpointer *) &device, NULL)) {
Packit Service 5ffa24
        g_hash_table_iter_remove(&h_iter);
Packit Service 5ffa24
        devices_list_unregister(self, device);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* The manager should have disposed of ActiveConnections already, which
Packit Service 5ffa24
     * will have called active_connection_removed() and thus we don't need
Packit Service 5ffa24
     * to clean anything up.  Assert that this is TRUE.
Packit Service 5ffa24
     */
Packit Service 5ffa24
    nm_assert(c_list_is_empty(nm_manager_get_active_connections(priv->manager)));
Packit Service 5ffa24
Packit Service 5ffa24
    nm_clear_g_source(&priv->reset_retries_id);
Packit Service 5ffa24
    nm_clear_g_source(&priv->schedule_activate_all_id);
Packit Service 5ffa24
Packit Service 5ffa24
    nm_clear_g_free(&priv->orig_hostname);
Packit Service 5ffa24
    nm_clear_g_free(&priv->cur_hostname);
Packit Service 5ffa24
    nm_clear_g_free(&priv->last_hostname);
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->hostname_manager) {
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_data(priv->hostname_manager, priv);
Packit Service 5ffa24
        g_clear_object(&priv->hostname_manager);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->settings) {
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_data(priv->settings, priv);
Packit Service 5ffa24
        g_clear_object(&priv->settings);
Packit Service 5ffa24
Packit Service 5ffa24
        /* we don't clear priv->manager as we don't own a reference to it,
Packit Service 5ffa24
         * that is, NMManager must outlive NMPolicy anyway.
Packit Service 5ffa24
         *
Packit Service 5ffa24
         * Hence, we unsubscribe the signals here together with the signals
Packit Service 5ffa24
         * for settings. */
Packit Service 5ffa24
        g_signal_handlers_disconnect_by_data(priv->manager, priv);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (priv->ip6_prefix_delegations) {
Packit Service 5ffa24
        g_array_free(priv->ip6_prefix_delegations, TRUE);
Packit Service 5ffa24
        priv->ip6_prefix_delegations = NULL;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    nm_assert(NM_IS_MANAGER(priv->manager));
Packit Service 5ffa24
Packit Service 5ffa24
    G_OBJECT_CLASS(nm_policy_parent_class)->dispose(object);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
finalize(GObject *object)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMPolicy *       self = NM_POLICY(object);
Packit Service 5ffa24
    NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE(self);
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_unref(priv->devices);
Packit Service 5ffa24
Packit Service 5ffa24
    G_OBJECT_CLASS(nm_policy_parent_class)->finalize(object);
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_unref(priv->netns);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
nm_policy_class_init(NMPolicyClass *policy_class)
Packit Service 5ffa24
{
Packit Service 5ffa24
    GObjectClass *object_class = G_OBJECT_CLASS(policy_class);
Packit Service 5ffa24
Packit Service 5ffa24
    object_class->get_property = get_property;
Packit Service 5ffa24
    object_class->set_property = set_property;
Packit Service 5ffa24
    object_class->constructed  = constructed;
Packit Service 5ffa24
    object_class->dispose      = dispose;
Packit Service 5ffa24
    object_class->finalize     = finalize;
Packit Service 5ffa24
Packit Service 5ffa24
    obj_properties[PROP_MANAGER] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_MANAGER,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_MANAGER,
Packit Service 5ffa24
                            G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
    obj_properties[PROP_SETTINGS] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_SETTINGS,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_SETTINGS,
Packit Service 5ffa24
                            G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
    obj_properties[PROP_DEFAULT_IP4_AC] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_DEFAULT_IP4_AC,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_ACTIVE_CONNECTION,
Packit Service 5ffa24
                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
    obj_properties[PROP_DEFAULT_IP6_AC] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_DEFAULT_IP6_AC,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_DEVICE,
Packit Service 5ffa24
                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
    obj_properties[PROP_ACTIVATING_IP4_AC] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_ACTIVATING_IP4_AC,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_DEVICE,
Packit Service 5ffa24
                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
    obj_properties[PROP_ACTIVATING_IP6_AC] =
Packit Service 5ffa24
        g_param_spec_object(NM_POLICY_ACTIVATING_IP6_AC,
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            "",
Packit Service 5ffa24
                            NM_TYPE_DEVICE,
Packit Service 5ffa24
                            G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
Packit Service 5ffa24
}