Blame src/core/initrd/nmi-cmdline-reader.c

Packit Service 5ffa24
/* SPDX-License-Identifier: LGPL-2.1-or-later */
Packit Service 5ffa24
/*
Packit Service 5ffa24
 * Copyright (C) 2018 Red Hat, Inc.
Packit Service 5ffa24
 */
Packit Service 5ffa24
Packit Service 2bceb2
#include "src/core/nm-default-daemon.h"
Packit Service 5ffa24
Packit Service 5ffa24
#include <linux/if_ether.h>
Packit Service 5ffa24
#include <linux/if_infiniband.h>
Packit Service 5ffa24
Packit Service 5ffa24
#include "nm-core-internal.h"
Packit Service 5ffa24
#include "nm-initrd-generator.h"
Packit Service 5ffa24
#include "systemd/nm-sd-utils-shared.h"
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
#define _NMLOG(level, domain, ...)                               \
Packit Service 5ffa24
    nm_log((level),                                              \
Packit Service 5ffa24
           (domain),                                             \
Packit Service 5ffa24
           NULL,                                                 \
Packit Service 5ffa24
           NULL,                                                 \
Packit Service 5ffa24
           "cmdline-reader: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) \
Packit Service 5ffa24
               _NM_UTILS_MACRO_REST(__VA_ARGS__))
Packit Service 5ffa24
Packit Service 5ffa24
/*****************************************************************************/
Packit Service 5ffa24
Packit Service 5ffa24
typedef struct {
Packit Service 5ffa24
    GHashTable *  hash;
Packit Service 5ffa24
    GPtrArray *   array;
Packit Service 5ffa24
    GPtrArray *   vlan_parents;
Packit Service 5ffa24
    GHashTable *  explicit_ip_connections;
Packit Service 5ffa24
    NMConnection *bootdev_connection; /* connection for bootdev=$ifname */
Packit Service 5ffa24
    NMConnection *default_connection; /* connection not bound to any ifname */
Packit Service 5ffa24
    char *        hostname;
Packit Service 5ffa24
Packit Service 5ffa24
    /* Parameters to be set for all connections */
Packit Service 5ffa24
    gboolean ignore_auto_dns;
Packit Service 5ffa24
    int      dhcp_timeout;
Packit Service 5ffa24
    char *   dhcp4_vci;
Packit Service 5ffa24
Packit Service 5ffa24
    gint64 carrier_timeout_sec;
Packit Service 5ffa24
} Reader;
Packit Service 5ffa24
Packit Service 5ffa24
static Reader *
Packit Service 5ffa24
reader_new(void)
Packit Service 5ffa24
{
Packit Service 5ffa24
    Reader *reader;
Packit Service 5ffa24
Packit Service 5ffa24
    reader  = g_slice_new(Reader);
Packit Service 5ffa24
    *reader = (Reader){
Packit Service 5ffa24
        .hash = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_object_unref),
Packit Service 5ffa24
        .explicit_ip_connections =
Packit Service 5ffa24
            g_hash_table_new_full(nm_direct_hash, NULL, g_object_unref, NULL),
Packit Service 5ffa24
        .vlan_parents = g_ptr_array_new_with_free_func(g_free),
Packit Service 5ffa24
        .array        = g_ptr_array_new(),
Packit Service 5ffa24
    };
Packit Service 5ffa24
Packit Service 5ffa24
    return reader;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static GHashTable *
Packit Service 5ffa24
reader_destroy(Reader *reader, gboolean free_hash)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *hash = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    g_ptr_array_unref(reader->array);
Packit Service 5ffa24
    g_ptr_array_unref(reader->vlan_parents);
Packit Service 5ffa24
    g_hash_table_unref(reader->explicit_ip_connections);
Packit Service 5ffa24
    hash = g_steal_pointer(&reader->hash);
Packit Service 5ffa24
    nm_clear_g_free(&reader->hostname);
Packit Service 5ffa24
    nm_clear_g_free(&reader->dhcp4_vci);
Packit Service 5ffa24
    nm_g_slice_free(reader);
Packit Service 5ffa24
    if (!free_hash)
Packit Service 5ffa24
        return g_steal_pointer(&hash);
Packit Service 5ffa24
    return NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static NMConnection *
Packit Service 5ffa24
reader_add_connection(Reader *reader, const char *name, NMConnection *connection_take)
Packit Service 5ffa24
{
Packit Service 5ffa24
    char *name_dup;
Packit Service 5ffa24
Packit Service 5ffa24
    name_dup = g_strdup(name);
Packit Service 5ffa24
    if (g_hash_table_insert(reader->hash, name_dup, connection_take))
Packit Service 5ffa24
        g_ptr_array_add(reader->array, name_dup);
Packit Service 5ffa24
Packit Service 5ffa24
    return connection_take;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
/* Returns a new connection owned by the reader */
Packit Service 5ffa24
static NMConnection *
Packit Service 5ffa24
reader_create_connection(Reader *                 reader,
Packit Service 5ffa24
                         const char *             basename,
Packit Service 5ffa24
                         const char *             id,
Packit Service 5ffa24
                         const char *             ifname,
Packit Service 5ffa24
                         const char *             mac,
Packit Service 5ffa24
                         const char *             type_name,
Packit Service 5ffa24
                         NMConnectionMultiConnect multi_connect)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *connection;
Packit Service 5ffa24
    NMSetting *   setting;
Packit Service 5ffa24
Packit Service 5ffa24
    connection = reader_add_connection(reader, basename, nm_simple_connection_new());
Packit Service 5ffa24
Packit Service 5ffa24
    /* Start off assuming dynamic IP configurations. */
Packit Service 5ffa24
Packit Service 5ffa24
    setting = nm_setting_ip4_config_new();
Packit Service 5ffa24
    nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
    g_object_set(setting,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                 NM_SETTING_IP4_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                 TRUE,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,
Packit Service 5ffa24
                 reader->ignore_auto_dns,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,
Packit Service 5ffa24
                 reader->dhcp_timeout,
Packit Service 5ffa24
                 NM_SETTING_IP4_CONFIG_DHCP_VENDOR_CLASS_IDENTIFIER,
Packit Service 5ffa24
                 reader->dhcp4_vci,
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    setting = nm_setting_ip6_config_new();
Packit Service 5ffa24
    nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
    g_object_set(setting,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                 NM_SETTING_IP4_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                 TRUE,
Packit Service 5ffa24
                 NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
Packit Service 5ffa24
                 (int) NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS,
Packit Service 5ffa24
                 reader->ignore_auto_dns,
Packit Service 5ffa24
                 NM_SETTING_IP_CONFIG_DHCP_TIMEOUT,
Packit Service 5ffa24
                 reader->dhcp_timeout,
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    setting = nm_setting_connection_new();
Packit Service 5ffa24
    nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
    g_object_set(setting,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_ID,
Packit Service 5ffa24
                 id,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_UUID,
Packit Service 5ffa24
                 nm_utils_uuid_generate_a(),
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_INTERFACE_NAME,
Packit Service 5ffa24
                 ifname,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_TYPE,
Packit Service 5ffa24
                 type_name,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_MULTI_CONNECT,
Packit Service 5ffa24
                 multi_connect,
Packit Service f8a693
                 NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES,
Packit Service f8a693
                 1,
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) {
Packit Service 5ffa24
        setting = nm_setting_infiniband_new();
Packit Service 5ffa24
        nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
        g_object_set(setting, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (mac) {
Packit Service 5ffa24
        if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) {
Packit Service 5ffa24
            setting = (NMSetting *) nm_connection_get_setting_infiniband(connection);
Packit Service 5ffa24
            g_object_set(setting, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            setting = nm_setting_wired_new();
Packit Service 5ffa24
            nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
            g_object_set(setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return connection;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static NMConnection *
Packit Service 5ffa24
reader_get_default_connection(Reader *reader)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *con;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!reader->default_connection) {
Packit Service 5ffa24
        con = reader_create_connection(reader,
Packit Service 5ffa24
                                       "default_connection",
Packit Service 5ffa24
                                       "Wired Connection",
Packit Service 5ffa24
                                       NULL,
Packit Service 5ffa24
                                       NULL,
Packit Service 5ffa24
                                       NM_SETTING_WIRED_SETTING_NAME,
Packit Service 5ffa24
                                       NM_CONNECTION_MULTI_CONNECT_MULTIPLE);
Packit Service 5ffa24
        nm_connection_add_setting(con, nm_setting_wired_new());
Packit Service 5ffa24
        reader->default_connection = con;
Packit Service 5ffa24
    }
Packit Service 5ffa24
    return reader->default_connection;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static NMConnection *
Packit Service 5ffa24
reader_get_connection(Reader *    reader,
Packit Service 5ffa24
                      const char *iface_spec,
Packit Service 5ffa24
                      const char *type_name,
Packit Service 5ffa24
                      gboolean    create_if_missing)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *connection = NULL;
Packit Service 5ffa24
    NMSetting *   setting;
Packit Service 5ffa24
    const char *  ifname = NULL;
Packit Service 5ffa24
    gs_free char *mac    = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (iface_spec) {
Packit Service 5ffa24
        if (nm_utils_is_valid_iface_name(iface_spec, NULL))
Packit Service 5ffa24
            ifname = iface_spec;
Packit Service 5ffa24
        else {
Packit Service 5ffa24
            mac = nm_utils_hwaddr_canonical(iface_spec, -1);
Packit Service 5ffa24
            if (!mac)
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "invalid interface '%s'", iface_spec);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (!ifname && !mac) {
Packit Service 5ffa24
        NMConnection *       candidate;
Packit Service 5ffa24
        NMSettingConnection *s_con;
Packit Service 5ffa24
        guint                i;
Packit Service 5ffa24
Packit Service 5ffa24
        /*
Packit Service 5ffa24
         * If ifname was not given, we'll match the connection by type.
Packit Service 5ffa24
         * If the type was not given either, then we're happy with any connection but slaves.
Packit Service 5ffa24
         * This is so that things like "bond=bond0:eth1,eth2 nameserver=1.3.3.7 end up
Packit Service 5ffa24
         * slapping the nameserver to the most reasonable connection (bond0).
Packit Service 5ffa24
         */
Packit Service 5ffa24
        for (i = 0; i < reader->array->len; i++) {
Packit Service 5ffa24
            candidate = g_hash_table_lookup(reader->hash, reader->array->pdata[i]);
Packit Service 5ffa24
            s_con     = nm_connection_get_setting_connection(candidate);
Packit Service 5ffa24
Packit Service 5ffa24
            if (type_name == NULL && nm_setting_connection_get_master(s_con) == NULL) {
Packit Service 5ffa24
                connection = candidate;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            if (type_name != NULL
Packit Service 5ffa24
                && nm_streq(nm_setting_connection_get_connection_type(s_con), type_name)) {
Packit Service 5ffa24
                connection = candidate;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else
Packit Service 5ffa24
        connection = g_hash_table_lookup(reader->hash, (gpointer) ifname ?: mac);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!connection) {
Packit Service 5ffa24
        if (!create_if_missing)
Packit Service 5ffa24
            return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        if (!type_name) {
Packit Service 5ffa24
            if (NM_STR_HAS_PREFIX(ifname, "ib")
Packit Service 5ffa24
                || (mac && nm_utils_hwaddr_valid(mac, INFINIBAND_ALEN)))
Packit Service 5ffa24
                type_name = NM_SETTING_INFINIBAND_SETTING_NAME;
Packit Service 5ffa24
            else
Packit Service 5ffa24
                type_name = NM_SETTING_WIRED_SETTING_NAME;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        connection = reader_create_connection(reader,
Packit Service 5ffa24
                                              ifname ?: mac,
Packit Service 5ffa24
                                              ifname ?: (mac ?: "Wired Connection"),
Packit Service 5ffa24
                                              ifname,
Packit Service 5ffa24
                                              mac,
Packit Service 5ffa24
                                              type_name,
Packit Service 5ffa24
                                              NM_CONNECTION_MULTI_CONNECT_SINGLE);
Packit Service 5ffa24
    }
Packit Service 5ffa24
    setting = (NMSetting *) nm_connection_get_setting_connection(connection);
Packit Service 5ffa24
Packit Service 5ffa24
    if (type_name) {
Packit Service 5ffa24
        g_object_set(setting, NM_SETTING_CONNECTION_TYPE, type_name, NULL);
Packit Service 5ffa24
        if (!nm_connection_get_setting_by_name(connection, type_name)) {
Packit Service 5ffa24
            setting = g_object_new(nm_setting_lookup_type(type_name), NULL);
Packit Service 5ffa24
            nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return connection;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static char *
Packit Service 5ffa24
get_word(char **argument, const char separator)
Packit Service 5ffa24
{
Packit Service 5ffa24
    char *word;
Packit Service 5ffa24
    int   nest = 0;
Packit Service 5ffa24
Packit Service 5ffa24
    if (*argument == NULL)
Packit Service 5ffa24
        return NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (**argument == '[') {
Packit Service 5ffa24
        nest++;
Packit Service 5ffa24
        (*argument)++;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    word = *argument;
Packit Service 5ffa24
Packit Service 5ffa24
    while (**argument != '\0') {
Packit Service 5ffa24
        if (nest && **argument == ']') {
Packit Service 5ffa24
            **argument = '\0';
Packit Service 5ffa24
            (*argument)++;
Packit Service 5ffa24
            nest--;
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (nest == 0 && **argument == separator) {
Packit Service 5ffa24
            **argument = '\0';
Packit Service 5ffa24
            (*argument)++;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
        (*argument)++;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    return *word ? word : NULL;
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_set(NMConnection *connection,
Packit Service 5ffa24
               const char *  setting_name,
Packit Service 5ffa24
               const char *  property,
Packit Service 5ffa24
               const char *  value)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSetting *              setting;
Packit Service 5ffa24
    GType                    setting_type;
Packit Service 5ffa24
    nm_auto_unref_gtypeclass GObjectClass *object_class = NULL;
Packit Service 5ffa24
    GParamSpec *                           spec;
Packit Service 5ffa24
Packit Service 5ffa24
    setting_type = nm_setting_lookup_type(setting_name);
Packit Service 5ffa24
    object_class = g_type_class_ref(setting_type);
Packit Service 5ffa24
    spec         = g_object_class_find_property(object_class, property);
Packit Service 5ffa24
    nm_assert(spec);
Packit Service 5ffa24
Packit Service 5ffa24
    setting = nm_connection_get_setting_by_name(connection, setting_name);
Packit Service 5ffa24
    if (!setting) {
Packit Service 5ffa24
        setting = g_object_new(setting_type, NULL);
Packit Service 5ffa24
        nm_connection_add_setting(connection, setting);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (G_IS_PARAM_SPEC_UINT(spec)) {
Packit Service 5ffa24
        guint v;
Packit Service 5ffa24
Packit Service 5ffa24
        v = _nm_utils_ascii_str_to_int64(value, 10, 0, G_MAXUINT, 0);
Packit Service 5ffa24
        if (errno || !nm_g_object_set_property_uint(G_OBJECT(setting), property, v, NULL)) {
Packit Service 5ffa24
            _LOGW(LOGD_CORE,
Packit Service 5ffa24
                  "Could not set property '%s.%s' to '%s'",
Packit Service 5ffa24
                  setting_name,
Packit Service 5ffa24
                  property,
Packit Service 5ffa24
                  value);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else if (G_IS_PARAM_SPEC_STRING(spec))
Packit Service 5ffa24
        g_object_set(setting, property, value, NULL);
Packit Service 5ffa24
    else
Packit Service 5ffa24
        _LOGW(LOGD_CORE, "Don't know how to set '%s' of %s", property, setting_name);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_read_all_connections_from_fw(Reader *reader, const char *sysfs_dir)
Packit Service 5ffa24
{
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *ibft = NULL;
Packit Service 5ffa24
    NMConnection *                 dt_connection;
Packit Service 5ffa24
    const char *                   mac;
Packit Service 5ffa24
    GHashTable *                   nic;
Packit Service 5ffa24
    const char *                   index;
Packit Service 5ffa24
    GError *                       error = NULL;
Packit Service 5ffa24
    guint                          i, length;
Packit Service 5ffa24
    gs_free const char **          keys = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    ibft = nmi_ibft_read(sysfs_dir);
Packit Service 5ffa24
    keys = nm_utils_strdict_get_keys(ibft, TRUE, &length);
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < length; i++) {
Packit Service 5ffa24
        gs_unref_object NMConnection *connection = NULL;
Packit Service 5ffa24
        gs_free char *                name       = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        mac        = keys[i];
Packit Service 5ffa24
        nic        = g_hash_table_lookup(ibft, mac);
Packit Service 5ffa24
        connection = nm_simple_connection_new();
Packit Service 5ffa24
        index      = g_hash_table_lookup(nic, "index");
Packit Service 5ffa24
        if (!index) {
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Ignoring an iBFT entry without an index");
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nmi_ibft_update_connection_from_nic(connection, nic, &error)) {
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Unable to merge iBFT configuration: %s", error->message);
Packit Service 5ffa24
            g_error_free(error);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        name = g_strdup_printf("ibft%s", index);
Packit Service 5ffa24
        reader_add_connection(reader, name, g_steal_pointer(&connection));
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    dt_connection = nmi_dt_reader_parse(sysfs_dir);
Packit Service 5ffa24
    if (dt_connection)
Packit Service 5ffa24
        reader_add_connection(reader, "ofw", dt_connection);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_parse_ip(Reader *reader, const char *sysfs_dir, char *argument)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *     connection;
Packit Service 5ffa24
    NMSettingIPConfig *s_ip4 = NULL, *s_ip6 = NULL;
Packit Service 5ffa24
    gs_unref_hashtable GHashTable *ibft = NULL;
Packit Service 5ffa24
    const char *                   tmp;
Packit Service 5ffa24
    const char *                   tmp2;
Packit Service 5ffa24
    const char *                   kind             = NULL;
Packit Service 5ffa24
    const char *                   client_ip        = NULL;
Packit Service 5ffa24
    const char *                   peer             = NULL;
Packit Service 5ffa24
    const char *                   gateway_ip       = NULL;
Packit Service 5ffa24
    const char *                   netmask          = NULL;
Packit Service 5ffa24
    const char *                   client_hostname  = NULL;
Packit Service 5ffa24
    const char *                   iface_spec       = NULL;
Packit Service 5ffa24
    const char *                   mtu              = NULL;
Packit Service 5ffa24
    const char *                   macaddr          = NULL;
Packit Service 5ffa24
    int                            client_ip_family = AF_UNSPEC;
Packit Service 5ffa24
    int                            client_ip_prefix = -1;
Packit Service 5ffa24
    const char *                   dns[2]           = {
Packit Service 5ffa24
        0,
Packit Service 5ffa24
    };
Packit Service 5ffa24
    int dns_addr_family[2] = {
Packit Service 5ffa24
        0,
Packit Service 5ffa24
    };
Packit Service 5ffa24
    int     i;
Packit Service 5ffa24
    GError *error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    if (!*argument)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    tmp = get_word(&argument, ':');
Packit Service 5ffa24
    if (!*argument) {
Packit Service 5ffa24
        /* ip={dhcp|on|any|dhcp6|auto6|link6|ibft} */
Packit Service 5ffa24
        kind = tmp;
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        tmp2 = get_word(&argument, ':');
Packit Service 5ffa24
        if (NM_IN_STRSET(tmp2,
Packit Service 5ffa24
                         "none",
Packit Service 5ffa24
                         "off",
Packit Service 5ffa24
                         "dhcp",
Packit Service 5ffa24
                         "on"
Packit Service 5ffa24
                         "any",
Packit Service 5ffa24
                         "dhcp6",
Packit Service 5ffa24
                         "auto",
Packit Service 5ffa24
                         "auto6",
Packit Service 5ffa24
                         "link6",
Packit Service 5ffa24
                         "ibft")) {
Packit Service 5ffa24
            /* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|link6|ibft} */
Packit Service 5ffa24
            iface_spec = tmp;
Packit Service 5ffa24
            kind       = tmp2;
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            /* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */
Packit Service 5ffa24
            client_ip = tmp;
Packit Service 5ffa24
            if (client_ip) {
Packit Service 5ffa24
                client_ip_family = get_ip_address_family(client_ip, TRUE);
Packit Service 5ffa24
                if (client_ip_family == AF_UNSPEC) {
Packit Service 5ffa24
                    _LOGW(LOGD_CORE, "Invalid IP address '%s'.", client_ip);
Packit Service 5ffa24
                    return;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            peer            = tmp2;
Packit Service 5ffa24
            gateway_ip      = get_word(&argument, ':');
Packit Service 5ffa24
            netmask         = get_word(&argument, ':');
Packit Service 5ffa24
            client_hostname = get_word(&argument, ':');
Packit Service 5ffa24
            iface_spec      = get_word(&argument, ':');
Packit Service 5ffa24
            kind            = get_word(&argument, ':');
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (client_hostname && !nm_sd_hostname_is_valid(client_hostname, FALSE))
Packit Service 5ffa24
            client_hostname = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        if (client_hostname) {
Packit Service 5ffa24
            g_free(reader->hostname);
Packit Service 5ffa24
            reader->hostname = g_strdup(client_hostname);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        tmp                = get_word(&argument, ':');
Packit Service 5ffa24
        dns_addr_family[0] = get_ip_address_family(tmp, FALSE);
Packit Service 5ffa24
        if (dns_addr_family[0] != AF_UNSPEC) {
Packit Service 5ffa24
            dns[0]             = tmp;
Packit Service 5ffa24
            dns[1]             = get_word(&argument, ':');
Packit Service 5ffa24
            dns_addr_family[1] = get_ip_address_family(dns[1], FALSE);
Packit Service 5ffa24
            if (*argument)
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            mtu     = tmp;
Packit Service 5ffa24
            macaddr = argument;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (iface_spec == NULL && NM_IN_STRSET(kind, "fw", "ibft")) {
Packit Service 5ffa24
        reader_read_all_connections_from_fw(reader, sysfs_dir);
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Parsing done, construct the NMConnection. */
Packit Service 5ffa24
    if (iface_spec)
Packit Service 5ffa24
        connection = reader_get_connection(reader, iface_spec, NULL, TRUE);
Packit Service 5ffa24
    else
Packit Service 5ffa24
        connection = reader_get_default_connection(reader);
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_add(reader->explicit_ip_connections, g_object_ref(connection));
Packit Service 5ffa24
Packit Service 5ffa24
    s_ip4 = nm_connection_get_setting_ip4_config(connection);
Packit Service 5ffa24
    s_ip6 = nm_connection_get_setting_ip6_config(connection);
Packit Service 5ffa24
Packit Service 5ffa24
    if (netmask && *netmask) {
Packit Service 5ffa24
        gboolean is_ipv4 = client_ip_family == AF_INET;
Packit Service 5ffa24
        NMIPAddr addr;
Packit Service 5ffa24
Packit Service 5ffa24
        if (is_ipv4 && nm_utils_parse_inaddr_bin(AF_INET, netmask, NULL, &addr))
Packit Service 5ffa24
            client_ip_prefix = nm_utils_ip4_netmask_to_prefix(addr.addr4);
Packit Service 5ffa24
        else
Packit Service 5ffa24
            client_ip_prefix = _nm_utils_ascii_str_to_int64(netmask, 10, 0, is_ipv4 ? 32 : 128, -1);
Packit Service 5ffa24
Packit Service 5ffa24
        if (client_ip_prefix == -1)
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Invalid IP mask: %s", netmask);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Static IP configuration might be present. */
Packit Service 5ffa24
    if (client_ip && *client_ip) {
Packit Service 5ffa24
        NMIPAddress *address = NULL;
Packit Service 5ffa24
        NMIPAddr     addr;
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_utils_parse_inaddr_prefix_bin(client_ip_family,
Packit Service 5ffa24
                                             client_ip,
Packit Service 5ffa24
                                             NULL,
Packit Service 5ffa24
                                             &addr,
Packit Service 5ffa24
                                             client_ip_prefix == -1 ? &client_ip_prefix : NULL)) {
Packit Service 5ffa24
            if (client_ip_prefix == -1) {
Packit Service 5ffa24
                switch (client_ip_family) {
Packit Service 5ffa24
                case AF_INET:
Packit Service 5ffa24
                    client_ip_prefix = _nm_utils_ip4_get_default_prefix(addr.addr4);
Packit Service 5ffa24
                    break;
Packit Service 5ffa24
                case AF_INET6:
Packit Service 5ffa24
                    client_ip_prefix = 64;
Packit Service 5ffa24
                    break;
Packit Service 5ffa24
                }
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            address = nm_ip_address_new_binary(client_ip_family,
Packit Service 5ffa24
                                               &addr.addr_ptr,
Packit Service 5ffa24
                                               client_ip_prefix,
Packit Service 5ffa24
                                               &error);
Packit Service 5ffa24
            if (!address) {
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Invalid address '%s': %s", client_ip, error->message);
Packit Service 5ffa24
                g_clear_error(&error);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        } else
Packit Service 5ffa24
            nm_assert_not_reached();
Packit Service 5ffa24
Packit Service 5ffa24
        if (address) {
Packit Service 5ffa24
            switch (client_ip_family) {
Packit Service 5ffa24
            case AF_INET:
Packit Service 5ffa24
                g_object_set(s_ip4,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                             NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                             FALSE,
Packit Service 5ffa24
                             NULL);
Packit Service 5ffa24
                nm_setting_ip_config_add_address(s_ip4, address);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            case AF_INET6:
Packit Service 5ffa24
                g_object_set(s_ip6,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                             NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                             FALSE,
Packit Service 5ffa24
                             NULL);
Packit Service 5ffa24
                nm_setting_ip_config_add_address(s_ip6, address);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            default:
Packit Service 5ffa24
                nm_assert_not_reached();
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
            nm_ip_address_unref(address);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    /* Dynamic IP configuration configured explicitly. */
Packit Service 5ffa24
    if (NM_IN_STRSET(kind, "none", "off")) {
Packit Service 5ffa24
        if (nm_setting_ip_config_get_num_addresses(s_ip6) == 0) {
Packit Service 5ffa24
            g_object_set(s_ip6,
Packit Service 5ffa24
                         NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                         NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
        if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) {
Packit Service 5ffa24
            g_object_set(s_ip4,
Packit Service 5ffa24
                         NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                         NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else if (nm_streq0(kind, "dhcp")) {
Packit Service 5ffa24
        g_object_set(s_ip4,
Packit Service 5ffa24
                     NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                     NM_SETTING_IP4_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                     NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                     FALSE,
Packit Service 5ffa24
                     NULL);
Packit Service 5ffa24
        if (nm_setting_ip_config_get_num_addresses(s_ip6) == 0) {
Packit Service 5ffa24
            g_object_set(s_ip6,
Packit Service 5ffa24
                         NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                         NM_SETTING_IP6_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else if (NM_IN_STRSET(kind, "auto6", "dhcp6")) {
Packit Service 5ffa24
        g_object_set(s_ip4, NM_SETTING_IP_CONFIG_MAY_FAIL, FALSE, NULL);
Packit Service 5ffa24
        if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) {
Packit Service 5ffa24
            g_object_set(s_ip4,
Packit Service 5ffa24
                         NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                         NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else if (nm_streq0(kind, "link6")) {
Packit Service 5ffa24
        g_object_set(s_ip6,
Packit Service 5ffa24
                     NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                     NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL,
Packit Service 5ffa24
                     NM_SETTING_IP_CONFIG_MAY_FAIL,
Packit Service 5ffa24
                     FALSE,
Packit Service 5ffa24
                     NULL);
Packit Service 5ffa24
        if (nm_setting_ip_config_get_num_addresses(s_ip4) == 0) {
Packit Service 5ffa24
            g_object_set(s_ip4,
Packit Service 5ffa24
                         NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                         NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                         NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else if (nm_streq0(kind, "ibft")) {
Packit Service 5ffa24
        NMSettingWired *s_wired;
Packit Service 5ffa24
        const char *    mac = NULL;
Packit Service 5ffa24
        const char *    ifname;
Packit Service 5ffa24
        gs_free char *  mac_free     = NULL;
Packit Service 5ffa24
        gs_free char *  address_path = NULL;
Packit Service 5ffa24
        GHashTable *    nic          = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        if ((s_wired = nm_connection_get_setting_wired(connection))
Packit Service 5ffa24
            && (mac = nm_setting_wired_get_mac_address(s_wired))) {
Packit Service 5ffa24
            /* got mac from the connection */
Packit Service 5ffa24
        } else if ((ifname = nm_connection_get_interface_name(connection))) {
Packit Service 5ffa24
            /* read it from sysfs */
Packit Service 5ffa24
            address_path = g_build_filename(sysfs_dir, "class", "net", ifname, "address", NULL);
Packit Service 5ffa24
            if (g_file_get_contents(address_path, &mac_free, NULL, &error)) {
Packit Service 5ffa24
                g_strchomp(mac_free);
Packit Service 5ffa24
                mac = mac_free;
Packit Service 5ffa24
            } else {
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Can't get a MAC address for %s: %s", ifname, error->message);
Packit Service 5ffa24
                g_clear_error(&error);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (mac) {
Packit Service 5ffa24
            gs_free char *mac_up = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
            mac_up = g_ascii_strup(mac, -1);
Packit Service 5ffa24
            ibft   = nmi_ibft_read(sysfs_dir);
Packit Service 5ffa24
            nic    = g_hash_table_lookup(ibft, mac_up);
Packit Service 5ffa24
            if (!nic)
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "No iBFT NIC for %s (%s)", iface_spec, mac_up);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (nic) {
Packit Service 5ffa24
            if (!nmi_ibft_update_connection_from_nic(connection, nic, &error)) {
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Unable to merge iBFT configuration: %s", error->message);
Packit Service 5ffa24
                g_clear_error(&error);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (peer && *peer)
Packit Service 5ffa24
        _LOGW(LOGD_CORE, "Ignoring peer: %s (not implemented)\n", peer);
Packit Service 5ffa24
Packit Service 5ffa24
    if (gateway_ip && *gateway_ip) {
Packit Service 5ffa24
        switch (get_ip_address_family(gateway_ip, FALSE)) {
Packit Service 5ffa24
        case AF_INET:
Packit Service 5ffa24
            g_object_set(s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        case AF_INET6:
Packit Service 5ffa24
            g_object_set(s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        default:
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Invalid gateway: %s", gateway_ip);
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (client_hostname && *client_hostname) {
Packit Service 5ffa24
        g_object_set(s_ip4, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL);
Packit Service 5ffa24
        g_object_set(s_ip6, NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, client_hostname, NULL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < 2; i++) {
Packit Service 5ffa24
        if (dns_addr_family[i] == AF_UNSPEC)
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        if (nm_utils_ipaddr_is_valid(dns_addr_family[i], dns[i])) {
Packit Service 5ffa24
            switch (dns_addr_family[i]) {
Packit Service 5ffa24
            case AF_INET:
Packit Service 5ffa24
                nm_setting_ip_config_add_dns(s_ip4, dns[i]);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            case AF_INET6:
Packit Service 5ffa24
                nm_setting_ip_config_add_dns(s_ip6, dns[i]);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            default:
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Unknown address family: %s", dns[i]);
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Invalid name server: %s", dns[i]);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (mtu && *mtu)
Packit Service 5ffa24
        connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu);
Packit Service 5ffa24
Packit Service 5ffa24
    if (macaddr && *macaddr)
Packit Service 5ffa24
        connection_set(connection,
Packit Service 5ffa24
                       NM_SETTING_WIRED_SETTING_NAME,
Packit Service 5ffa24
                       NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
Packit Service 5ffa24
                       macaddr);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_parse_master(Reader *reader, char *argument, const char *type_name, const char *default_name)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *       connection;
Packit Service 5ffa24
    NMSettingConnection *s_con;
Packit Service 5ffa24
    gs_free char *       master_to_free = NULL;
Packit Service 5ffa24
    const char *         master;
Packit Service 5ffa24
    char *               slaves;
Packit Service 5ffa24
    const char *         slave;
Packit Service 5ffa24
    char *               opts;
Packit Service 5ffa24
    const char *         mtu = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
    master = get_word(&argument, ':');
Packit Service 5ffa24
    if (!master)
Packit Service 5ffa24
        master = master_to_free = g_strdup_printf("%s0", default_name ?: type_name);
Packit Service 5ffa24
    slaves = get_word(&argument, ':');
Packit Service 5ffa24
Packit Service 5ffa24
    connection = reader_get_connection(reader, master, type_name, TRUE);
Packit Service 5ffa24
    s_con      = nm_connection_get_setting_connection(connection);
Packit Service 5ffa24
    master     = nm_setting_connection_get_uuid(s_con);
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq(type_name, NM_SETTING_BRIDGE_SETTING_NAME)) {
Packit Service 5ffa24
        NMSettingBridge *s_bridge = nm_connection_get_setting_bridge(connection);
Packit Service 5ffa24
Packit Service 5ffa24
        /* Avoid the forwarding delay */
Packit Service 5ffa24
        g_object_set(s_bridge, NM_SETTING_BRIDGE_STP, FALSE, NULL);
Packit Service 5ffa24
    } else if (nm_streq(type_name, NM_SETTING_BOND_SETTING_NAME)) {
Packit Service 5ffa24
        NMSettingBond *s_bond = nm_connection_get_setting_bond(connection);
Packit Service 5ffa24
Packit Service 5ffa24
        opts = get_word(&argument, ':');
Packit Service 5ffa24
        while (opts && *opts) {
Packit Service 5ffa24
            gs_free_error GError *error = NULL;
Packit Service 5ffa24
            char *                opt;
Packit Service 5ffa24
            const char *          opt_name;
Packit Service 5ffa24
Packit Service 5ffa24
            opt      = get_word(&opts, ',');
Packit Service 5ffa24
            opt_name = get_word(&opt, '=');
Packit Service 5ffa24
Packit Service 5ffa24
            if (!_nm_setting_bond_validate_option(opt_name, opt, &error)) {
Packit Service 5ffa24
                _LOGW(LOGD_CORE,
Packit Service 5ffa24
                      "Ignoring invalid bond option: %s%s%s = %s%s%s: %s",
Packit Service 5ffa24
                      NM_PRINT_FMT_QUOTE_STRING(opt_name),
Packit Service 5ffa24
                      NM_PRINT_FMT_QUOTE_STRING(opt),
Packit Service 5ffa24
                      error->message);
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            }
Packit Service 5ffa24
            nm_setting_bond_add_option(s_bond, opt_name, opt);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        mtu = get_word(&argument, ':');
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    do {
Packit Service 5ffa24
        slave = get_word(&slaves, ',');
Packit Service 5ffa24
        if (slave == NULL)
Packit Service 5ffa24
            slave = "eth0";
Packit Service 5ffa24
Packit Service 5ffa24
        connection = reader_get_connection(reader, slave, NULL, TRUE);
Packit Service 5ffa24
        s_con      = nm_connection_get_setting_connection(connection);
Packit Service 5ffa24
        g_object_set(s_con,
Packit Service 5ffa24
                     NM_SETTING_CONNECTION_SLAVE_TYPE,
Packit Service 5ffa24
                     type_name,
Packit Service 5ffa24
                     NM_SETTING_CONNECTION_MASTER,
Packit Service 5ffa24
                     master,
Packit Service 5ffa24
                     NULL);
Packit Service 42f71b
        if (mtu)
Packit Service 42f71b
            connection_set(connection, NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MTU, mtu);
Packit Service 5ffa24
    } while (slaves && *slaves != '\0');
Packit Service 5ffa24
Packit Service 5ffa24
    if (argument && *argument)
Packit Service 5ffa24
        _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_add_routes(Reader *reader, GPtrArray *array)
Packit Service 5ffa24
{
Packit Service 5ffa24
    guint i;
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < array->len; i++) {
Packit Service 5ffa24
        NMConnection *     connection = NULL;
Packit Service 5ffa24
        const char *       net;
Packit Service 5ffa24
        const char *       gateway;
Packit Service 5ffa24
        const char *       interface;
Packit Service 5ffa24
        int                family       = AF_UNSPEC;
Packit Service 5ffa24
        NMIPAddr           net_addr     = {};
Packit Service 5ffa24
        NMIPAddr           gateway_addr = {};
Packit Service 5ffa24
        int                net_prefix   = -1;
Packit Service 5ffa24
        NMIPRoute *        route;
Packit Service 5ffa24
        NMSettingIPConfig *s_ip;
Packit Service 5ffa24
        char *             argument;
Packit Service 5ffa24
        gs_free_error GError *error = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
        argument  = array->pdata[i];
Packit Service 5ffa24
        net       = get_word(&argument, ':');
Packit Service 5ffa24
        gateway   = get_word(&argument, ':');
Packit Service 5ffa24
        interface = get_word(&argument, ':');
Packit Service 5ffa24
Packit Service 5ffa24
        if (interface)
Packit Service 5ffa24
            connection = reader_get_connection(reader, interface, NULL, TRUE);
Packit Service 5ffa24
        if (!connection)
Packit Service 5ffa24
            connection = reader->bootdev_connection;
Packit Service 5ffa24
        if (!connection)
Packit Service 5ffa24
            connection = reader_get_connection(reader, interface, NULL, FALSE);
Packit Service 5ffa24
        if (!connection)
Packit Service 5ffa24
            connection = reader_get_default_connection(reader);
Packit Service 5ffa24
Packit Service 5ffa24
        if (net && *net) {
Packit Service 5ffa24
            if (!nm_utils_parse_inaddr_prefix_bin(family, net, &family, &net_addr, &net_prefix)) {
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Unrecognized address: %s", net);
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        if (gateway && *gateway) {
Packit Service 5ffa24
            if (!nm_utils_parse_inaddr_bin(family, gateway, &family, &gateway_addr)) {
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Unrecognized address: %s", gateway);
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        switch (family) {
Packit Service 5ffa24
        case AF_INET:
Packit Service 5ffa24
            s_ip = nm_connection_get_setting_ip4_config(connection);
Packit Service 5ffa24
            if (net_prefix == -1)
Packit Service 5ffa24
                net_prefix = 32;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        case AF_INET6:
Packit Service 5ffa24
            s_ip = nm_connection_get_setting_ip6_config(connection);
Packit Service 5ffa24
            if (net_prefix == -1)
Packit Service 5ffa24
                net_prefix = 128;
Packit Service 5ffa24
            break;
Packit Service 5ffa24
        default:
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Unknown address family: %s", net);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        route = nm_ip_route_new_binary(family,
Packit Service 5ffa24
                                       &net_addr.addr_ptr,
Packit Service 5ffa24
                                       net_prefix,
Packit Service 5ffa24
                                       &gateway_addr.addr_ptr,
Packit Service 5ffa24
                                       -1,
Packit Service 5ffa24
                                       &error);
Packit Service 5ffa24
        if (!route) {
Packit Service 5ffa24
            g_warning("Invalid route '%s via %s': %s\n", net, gateway, error->message);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        nm_setting_ip_config_add_route(s_ip, route);
Packit Service 5ffa24
        nm_ip_route_unref(route);
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_parse_vlan(Reader *reader, char *argument)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection * connection;
Packit Service 5ffa24
    NMSettingVlan *s_vlan;
Packit Service 5ffa24
    const char *   vlan;
Packit Service 5ffa24
    const char *   phy;
Packit Service 5ffa24
    const char *   vlanid;
Packit Service 5ffa24
Packit Service 5ffa24
    vlan = get_word(&argument, ':');
Packit Service 5ffa24
    phy  = get_word(&argument, ':');
Packit Service 5ffa24
Packit Service 5ffa24
    for (vlanid = vlan + strlen(vlan); vlanid > vlan; vlanid--) {
Packit Service 5ffa24
        if (!g_ascii_isdigit(*(vlanid - 1)))
Packit Service 5ffa24
            break;
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    connection = reader_get_connection(reader, vlan, NM_SETTING_VLAN_SETTING_NAME, TRUE);
Packit Service 5ffa24
Packit Service 5ffa24
    s_vlan = nm_connection_get_setting_vlan(connection);
Packit Service 5ffa24
    g_object_set(s_vlan,
Packit Service 5ffa24
                 NM_SETTING_VLAN_PARENT,
Packit Service 5ffa24
                 phy,
Packit Service 5ffa24
                 NM_SETTING_VLAN_ID,
Packit Service 5ffa24
                 (guint) _nm_utils_ascii_str_to_int64(vlanid, 10, 0, G_MAXUINT, G_MAXUINT),
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    if (argument && *argument)
Packit Service 5ffa24
        _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
Packit Service 5ffa24
Packit Service 5ffa24
    if (!nm_strv_ptrarray_contains(reader->vlan_parents, phy))
Packit Service 5ffa24
        g_ptr_array_add(reader->vlan_parents, g_strdup(phy));
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_parse_rd_znet(Reader *reader, char *argument, gboolean net_ifnames)
Packit Service 5ffa24
{
Packit Service 5ffa24
    const char *    nettype;
Packit Service 5ffa24
    const char *    subchannels[4] = {0, 0, 0, 0};
Packit Service 5ffa24
    const char *    tmp;
Packit Service 5ffa24
    gs_free char *  ifname = NULL;
Packit Service 5ffa24
    const char *    prefix;
Packit Service 5ffa24
    NMConnection *  connection;
Packit Service 5ffa24
    NMSettingWired *s_wired;
Packit Service 5ffa24
    static int      count_ctc = 0;
Packit Service 5ffa24
    static int      count_eth = 0;
Packit Service 5ffa24
    int             index;
Packit Service 5ffa24
Packit Service 5ffa24
    nettype        = get_word(&argument, ',');
Packit Service 5ffa24
    subchannels[0] = get_word(&argument, ',');
Packit Service 5ffa24
    subchannels[1] = get_word(&argument, ',');
Packit Service 5ffa24
Packit Service 5ffa24
    if (nm_streq0(nettype, "ctc")) {
Packit Service 5ffa24
        if (net_ifnames == TRUE) {
Packit Service 5ffa24
            prefix = "sl";
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            prefix = "ctc";
Packit Service 5ffa24
            index  = count_ctc++;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        subchannels[2] = get_word(&argument, ',');
Packit Service 5ffa24
        if (net_ifnames == TRUE) {
Packit Service 5ffa24
            prefix = "en";
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            prefix = "eth";
Packit Service 5ffa24
            index  = count_eth++;
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (net_ifnames == TRUE) {
Packit Service 5ffa24
        const char *bus_id;
Packit Service 5ffa24
        size_t      bus_id_len;
Packit Service 5ffa24
        size_t      bus_id_start;
Packit Service 5ffa24
Packit Service 5ffa24
        /* The following logic is taken from names_ccw() in systemd/src/udev/udev-builtin-net_id.c */
Packit Service 5ffa24
        bus_id       = subchannels[0];
Packit Service 5ffa24
        bus_id_len   = strlen(bus_id);
Packit Service 5ffa24
        bus_id_start = strspn(bus_id, ".0");
Packit Service 5ffa24
        bus_id += bus_id_start < bus_id_len ? bus_id_start : bus_id_len - 1;
Packit Service 5ffa24
Packit Service 5ffa24
        ifname = g_strdup_printf("%sc%s", prefix, bus_id);
Packit Service 5ffa24
    } else {
Packit Service 5ffa24
        ifname = g_strdup_printf("%s%d", prefix, index);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    connection = reader_get_connection(reader, ifname, NM_SETTING_WIRED_SETTING_NAME, FALSE);
Packit Service 5ffa24
    if (!connection)
Packit Service 5ffa24
        return;
Packit Service 5ffa24
    s_wired = nm_connection_get_setting_wired(connection);
Packit Service 5ffa24
    g_object_set(s_wired,
Packit Service 5ffa24
                 NM_SETTING_WIRED_S390_NETTYPE,
Packit Service 5ffa24
                 nettype,
Packit Service 5ffa24
                 NM_SETTING_WIRED_S390_SUBCHANNELS,
Packit Service 5ffa24
                 &subchannels,
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    while ((tmp = get_word(&argument, ',')) != NULL) {
Packit Service 5ffa24
        char *val;
Packit Service 5ffa24
Packit Service 5ffa24
        val = strchr(tmp, '=');
Packit Service 5ffa24
        if (val) {
Packit Service 5ffa24
            gs_free char *key = NULL;
Packit Service 5ffa24
Packit Service 5ffa24
            key    = g_strndup(tmp, val - tmp);
Packit Service 5ffa24
            val[0] = '\0';
Packit Service 5ffa24
            val++;
Packit Service 5ffa24
            nm_setting_wired_add_s390_option(s_wired, key, val);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
_normalize_conn(gpointer key, gpointer value, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *connection = value;
Packit Service 5ffa24
Packit Service 5ffa24
    nm_connection_normalize(connection, NULL, NULL, NULL);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
reader_add_nameservers(Reader *reader, GPtrArray *nameservers)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMConnection *     connection;
Packit Service 5ffa24
    NMSettingIPConfig *s_ip;
Packit Service 5ffa24
    GHashTableIter     iter;
Packit Service 5ffa24
    int                addr_family;
Packit Service 5ffa24
    const char *       ns;
Packit Service 5ffa24
    guint              i;
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < nameservers->len; i++) {
Packit Service 5ffa24
        ns          = nameservers->pdata[i];
Packit Service 5ffa24
        addr_family = get_ip_address_family(ns, FALSE);
Packit Service 5ffa24
        if (addr_family == AF_UNSPEC) {
Packit Service 5ffa24
            _LOGW(LOGD_CORE, "Unknown address family: %s", ns);
Packit Service 5ffa24
            continue;
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        g_hash_table_iter_init(&iter, reader->hash);
Packit Service 5ffa24
        while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &connection)) {
Packit Service 5ffa24
            switch (addr_family) {
Packit Service 5ffa24
            case AF_INET:
Packit Service 5ffa24
                s_ip = nm_connection_get_setting_ip4_config(connection);
Packit Service 5ffa24
                if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip),
Packit Service 5ffa24
                                  NM_SETTING_IP4_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                                  NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
Packit Service 5ffa24
                    continue;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            case AF_INET6:
Packit Service 5ffa24
                s_ip = nm_connection_get_setting_ip6_config(connection);
Packit Service 5ffa24
                if (!NM_IN_STRSET(nm_setting_ip_config_get_method(s_ip),
Packit Service 5ffa24
                                  NM_SETTING_IP6_CONFIG_METHOD_AUTO,
Packit Service 5ffa24
                                  NM_SETTING_IP6_CONFIG_METHOD_DHCP,
Packit Service 5ffa24
                                  NM_SETTING_IP6_CONFIG_METHOD_MANUAL))
Packit Service 5ffa24
                    continue;
Packit Service 5ffa24
                break;
Packit Service 5ffa24
            default:
Packit Service 5ffa24
                nm_assert_not_reached();
Packit Service 5ffa24
                continue;
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            nm_setting_ip_config_add_dns(s_ip, ns);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_set_needed(NMConnection *connection)
Packit Service 5ffa24
{
Packit Service 5ffa24
    NMSettingConnection *s_con;
Packit Service 5ffa24
Packit Service 5ffa24
    s_con = nm_connection_get_setting_connection(connection);
Packit Service 5ffa24
    if (!nm_streq0(nm_setting_connection_get_connection_type(s_con), NM_SETTING_WIRED_SETTING_NAME))
Packit Service 5ffa24
        return;
Packit Service 5ffa24
Packit Service 5ffa24
    g_object_set(s_con,
Packit Service 5ffa24
                 NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT,
Packit Service 5ffa24
                 (int) NMI_WAIT_DEVICE_TIMEOUT_MS,
Packit Service 5ffa24
                 NULL);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
static void
Packit Service 5ffa24
connection_set_needed_cb(gpointer key, gpointer value, gpointer user_data)
Packit Service 5ffa24
{
Packit Service 5ffa24
    connection_set_needed(value);
Packit Service 5ffa24
}
Packit Service 5ffa24
Packit Service 5ffa24
GHashTable *
Packit Service 5ffa24
nmi_cmdline_reader_parse(const char *       sysfs_dir,
Packit Service 5ffa24
                         const char *const *argv,
Packit Service 5ffa24
                         char **            hostname,
Packit Service 5ffa24
                         gint64 *           carrier_timeout_sec)
Packit Service 5ffa24
{
Packit Service 5ffa24
    Reader *          reader;
Packit Service 5ffa24
    const char *      tag;
Packit Service 5ffa24
    gboolean          ignore_bootif          = FALSE;
Packit Service 5ffa24
    gboolean          neednet                = FALSE;
Packit Service 5ffa24
    gs_free char *    bootif_val             = NULL;
Packit Service 5ffa24
    gs_free char *    bootdev                = NULL;
Packit Service 5ffa24
    gboolean          net_ifnames            = TRUE;
Packit Service 5ffa24
    gs_unref_ptrarray GPtrArray *nameservers = NULL;
Packit Service 5ffa24
    gs_unref_ptrarray GPtrArray *routes      = NULL;
Packit Service 5ffa24
    gs_unref_ptrarray GPtrArray *znets       = NULL;
Packit Service 5ffa24
    int                          i;
Packit Service f8a693
    guint64                      dhcp_timeout   = 90;
Packit Service f8a693
    guint64                      dhcp_num_tries = 1;
Packit Service 5ffa24
Packit Service 5ffa24
    reader = reader_new();
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; argv[i]; i++) {
Packit Service 5ffa24
        gs_free char *argument_clone = NULL;
Packit Service 5ffa24
        char *        argument;
Packit Service 5ffa24
Packit Service 5ffa24
        argument_clone = g_strdup(argv[i]);
Packit Service 5ffa24
        argument       = argument_clone;
Packit Service 5ffa24
Packit Service 5ffa24
        tag = get_word(&argument, '=');
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_streq(tag, "net.ifnames"))
Packit Service 5ffa24
            net_ifnames = !nm_streq(argument, "0");
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.peerdns"))
Packit Service 5ffa24
            reader->ignore_auto_dns = !_nm_utils_ascii_str_to_bool(argument, TRUE);
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.net.timeout.dhcp")) {
Packit Service f8a693
            if (nm_streq0(argument, "infinity")) {
Packit Service f8a693
                dhcp_timeout = G_MAXINT32;
Packit Service f8a693
            } else {
Packit Service f8a693
                dhcp_timeout =
Packit Service f8a693
                    _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_timeout);
Packit Service f8a693
            }
Packit Service f8a693
        } else if (nm_streq(tag, "rd.net.dhcp.retry")) {
Packit Service f8a693
            dhcp_num_tries =
Packit Service f8a693
                _nm_utils_ascii_str_to_int64(argument, 10, 1, G_MAXINT32, dhcp_num_tries);
Packit Service 5ffa24
        } else if (nm_streq(tag, "rd.net.dhcp.vendor-class")) {
Packit Service 5ffa24
            if (nm_utils_validate_dhcp4_vendor_class_id(argument, NULL))
Packit Service 5ffa24
                nm_utils_strdup_reset(&reader->dhcp4_vci, argument);
Packit Service 5ffa24
        } else if (nm_streq(tag, "rd.net.timeout.carrier")) {
Packit Service 5ffa24
            reader->carrier_timeout_sec =
Packit Service 5ffa24
                _nm_utils_ascii_str_to_int64(argument, 10, 0, G_MAXINT32, 0);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service f8a693
    reader->dhcp_timeout = NM_CLAMP(dhcp_timeout * dhcp_num_tries, 1, G_MAXINT32);
Packit Service f8a693
Packit Service 5ffa24
    for (i = 0; argv[i]; i++) {
Packit Service 5ffa24
        gs_free char *argument_clone = NULL;
Packit Service 5ffa24
        char *        argument;
Packit Service 5ffa24
        char *        word;
Packit Service 5ffa24
Packit Service 5ffa24
        argument_clone = g_strdup(argv[i]);
Packit Service 5ffa24
        argument       = argument_clone;
Packit Service 5ffa24
Packit Service 5ffa24
        tag = get_word(&argument, '=');
Packit Service 5ffa24
        if (nm_streq(tag, "ip"))
Packit Service 5ffa24
            reader_parse_ip(reader, sysfs_dir, argument);
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.route")) {
Packit Service 5ffa24
            if (!routes)
Packit Service 5ffa24
                routes = g_ptr_array_new_with_free_func(g_free);
Packit Service 5ffa24
            g_ptr_array_add(routes, g_strdup(argument));
Packit Service 5ffa24
        } else if (nm_streq(tag, "bridge"))
Packit Service 5ffa24
            reader_parse_master(reader, argument, NM_SETTING_BRIDGE_SETTING_NAME, "br");
Packit Service 5ffa24
        else if (nm_streq(tag, "bond"))
Packit Service 5ffa24
            reader_parse_master(reader, argument, NM_SETTING_BOND_SETTING_NAME, NULL);
Packit Service 5ffa24
        else if (nm_streq(tag, "team"))
Packit Service 5ffa24
            reader_parse_master(reader, argument, NM_SETTING_TEAM_SETTING_NAME, NULL);
Packit Service 5ffa24
        else if (nm_streq(tag, "vlan"))
Packit Service 5ffa24
            reader_parse_vlan(reader, argument);
Packit Service 5ffa24
        else if (nm_streq(tag, "bootdev")) {
Packit Service 5ffa24
            g_free(bootdev);
Packit Service 5ffa24
            bootdev = g_strdup(argument);
Packit Service 5ffa24
        } else if (nm_streq(tag, "nameserver")) {
Packit Service 5ffa24
            word = get_word(&argument, '\0');
Packit Service 5ffa24
            if (word) {
Packit Service 5ffa24
                if (!nameservers)
Packit Service 5ffa24
                    nameservers = g_ptr_array_new_with_free_func(g_free);
Packit Service 5ffa24
                g_ptr_array_add(nameservers, g_strdup(word));
Packit Service 5ffa24
            }
Packit Service 5ffa24
            if (argument && *argument)
Packit Service 5ffa24
                _LOGW(LOGD_CORE, "Ignoring extra: '%s'.", argument);
Packit Service 5ffa24
        } else if (nm_streq(tag, "rd.iscsi.ibft") && _nm_utils_ascii_str_to_bool(argument, TRUE))
Packit Service 5ffa24
            reader_read_all_connections_from_fw(reader, sysfs_dir);
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.bootif"))
Packit Service 5ffa24
            ignore_bootif = !_nm_utils_ascii_str_to_bool(argument, TRUE);
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.neednet"))
Packit Service 5ffa24
            neednet = _nm_utils_ascii_str_to_bool(argument, TRUE);
Packit Service 5ffa24
        else if (nm_streq(tag, "rd.znet")) {
Packit Service 5ffa24
            if (!znets)
Packit Service 5ffa24
                znets = g_ptr_array_new_with_free_func(g_free);
Packit Service 5ffa24
            g_ptr_array_add(znets, g_strdup(argument));
Packit Service 5ffa24
        } else if (g_ascii_strcasecmp(tag, "BOOTIF") == 0) {
Packit Service 5ffa24
            nm_clear_g_free(&bootif_val);
Packit Service 5ffa24
            bootif_val = g_strdup(argument);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    for (i = 0; i < reader->vlan_parents->len; i++) {
Packit Service 5ffa24
        NMConnection *     connection;
Packit Service 5ffa24
        NMSettingIPConfig *s_ip;
Packit Service 5ffa24
Packit Service 5ffa24
        /* Disable IP configuration for parent connections of VLANs,
Packit Service 5ffa24
         * unless those interfaces were explicitly configured otherwise. */
Packit Service 5ffa24
Packit Service 5ffa24
        connection = reader_get_connection(reader, reader->vlan_parents->pdata[i], NULL, TRUE);
Packit Service 5ffa24
        if (!g_hash_table_contains(reader->explicit_ip_connections, connection)) {
Packit Service 5ffa24
            s_ip = nm_connection_get_setting_ip4_config(connection);
Packit Service 5ffa24
            if (s_ip) {
Packit Service 5ffa24
                g_object_set(s_ip,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                             NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                             NULL);
Packit Service 5ffa24
            }
Packit Service 5ffa24
Packit Service 5ffa24
            s_ip = nm_connection_get_setting_ip6_config(connection);
Packit Service 5ffa24
            if (s_ip) {
Packit Service 5ffa24
                g_object_set(s_ip,
Packit Service 5ffa24
                             NM_SETTING_IP_CONFIG_METHOD,
Packit Service 5ffa24
                             NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
Packit Service 5ffa24
                             NULL);
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (ignore_bootif)
Packit Service 5ffa24
        nm_clear_g_free(&bootif_val);
Packit Service 5ffa24
    if (bootif_val) {
Packit Service 5ffa24
        NMConnection *  connection;
Packit Service 5ffa24
        NMSettingWired *s_wired;
Packit Service 5ffa24
        const char *    bootif = bootif_val;
Packit Service 5ffa24
        char            prefix[4];
Packit Service 5ffa24
Packit Service 5ffa24
        if (!nm_utils_hwaddr_valid(bootif, ETH_ALEN)) {
Packit Service 5ffa24
            strncpy(prefix, bootif, 3);
Packit Service 5ffa24
            prefix[3] = '\0';
Packit Service 5ffa24
Packit Service 5ffa24
            if (NM_IN_STRSET(prefix, "01-", "01:", "00-", "00:")
Packit Service 5ffa24
                && nm_utils_hwaddr_valid(&bootif[3], ETH_ALEN)) {
Packit Service 5ffa24
                /*
Packit Service 5ffa24
                 * BOOTIF MAC address can be prefixed with a hardware type identifier.
Packit Service 5ffa24
                 * "01" stays for "wired", "00" is also accepted as it means "undefined".
Packit Service 5ffa24
                 * No others are known.
Packit Service 5ffa24
                 */
Packit Service 5ffa24
                bootif += 3;
Packit Service 5ffa24
            }
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        connection = reader_get_connection(reader, NULL, NM_SETTING_WIRED_SETTING_NAME, FALSE);
Packit Service 5ffa24
        if (!connection)
Packit Service 5ffa24
            connection = reader_get_default_connection(reader);
Packit Service 5ffa24
Packit Service 5ffa24
        s_wired = nm_connection_get_setting_wired(connection);
Packit Service 5ffa24
Packit Service 5ffa24
        if (nm_connection_get_interface_name(connection)
Packit Service 5ffa24
            || (nm_setting_wired_get_mac_address(s_wired)
Packit Service 5ffa24
                && !nm_utils_hwaddr_matches(nm_setting_wired_get_mac_address(s_wired),
Packit Service 5ffa24
                                            -1,
Packit Service 5ffa24
                                            bootif,
Packit Service 5ffa24
                                            -1))) {
Packit Service 5ffa24
            connection = reader_create_connection(reader,
Packit Service 5ffa24
                                                  "bootif_connection",
Packit Service 5ffa24
                                                  "BOOTIF Connection",
Packit Service 5ffa24
                                                  NULL,
Packit Service 5ffa24
                                                  bootif,
Packit Service 5ffa24
                                                  NM_SETTING_WIRED_SETTING_NAME,
Packit Service 5ffa24
                                                  NM_CONNECTION_MULTI_CONNECT_SINGLE);
Packit Service 5ffa24
        } else {
Packit Service 5ffa24
            g_object_set(s_wired, NM_SETTING_WIRED_MAC_ADDRESS, bootif, NULL);
Packit Service 5ffa24
        }
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (bootdev) {
Packit Service 5ffa24
        NMConnection *connection;
Packit Service 5ffa24
Packit Service 5ffa24
        connection                 = reader_get_connection(reader, bootdev, NULL, TRUE);
Packit Service 5ffa24
        reader->bootdev_connection = connection;
Packit Service 5ffa24
        connection_set_needed(connection);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (neednet) {
Packit Service 5ffa24
        if (g_hash_table_size(reader->hash) == 0) {
Packit Service 5ffa24
            /* Make sure there's some connection. */
Packit Service 5ffa24
            reader_get_default_connection(reader);
Packit Service 5ffa24
        }
Packit Service 5ffa24
Packit Service 5ffa24
        g_hash_table_foreach(reader->hash, connection_set_needed_cb, NULL);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    if (routes)
Packit Service 5ffa24
        reader_add_routes(reader, routes);
Packit Service 5ffa24
Packit Service 5ffa24
    if (nameservers)
Packit Service 5ffa24
        reader_add_nameservers(reader, nameservers);
Packit Service 5ffa24
Packit Service 5ffa24
    if (znets) {
Packit Service 5ffa24
        for (i = 0; i < znets->len; i++)
Packit Service 5ffa24
            reader_parse_rd_znet(reader, znets->pdata[i], net_ifnames);
Packit Service 5ffa24
    }
Packit Service 5ffa24
Packit Service 5ffa24
    g_hash_table_foreach(reader->hash, _normalize_conn, NULL);
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(hostname, g_steal_pointer(&reader->hostname));
Packit Service 5ffa24
Packit Service 5ffa24
    NM_SET_OUT(carrier_timeout_sec, reader->carrier_timeout_sec);
Packit Service 5ffa24
Packit Service 5ffa24
    return reader_destroy(reader, FALSE);
Packit Service 5ffa24
}