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

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