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 051f6c
	GPtrArray *vlan_parents;
Packit Service 051f6c
	GHashTable *explicit_ip_connections;
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 39775f
	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 051f6c
		.hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_object_unref),
Packit Service 051f6c
		.explicit_ip_connections = g_hash_table_new_full (nm_direct_hash, NULL, g_object_unref, NULL),
Packit Service 051f6c
		.vlan_parents = g_ptr_array_new_with_free_func (g_free),
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 051f6c
	g_ptr_array_unref (reader->vlan_parents);
Packit Service 051f6c
	g_hash_table_unref (reader->explicit_ip_connections);
Packit Service b23acc
	hash = g_steal_pointer (&reader->hash);
Packit Service b23acc
	nm_clear_g_free (&reader->hostname);
Packit Service 39775f
	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 331025
                          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 39775f
	              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 82c12a
	if (nm_streq0 (type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) {
Packit Service 82c12a
		setting = nm_setting_infiniband_new ();
Packit Service 331025
		nm_connection_add_setting (connection, setting);
Packit Service 82c12a
		g_object_set (setting, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL);
Packit Service 82c12a
	}
Packit Service 82c12a
Packit Service 82c12a
	if (mac) {
Packit Service 82c12a
		if (nm_streq0 (type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) {
Packit Service 82c12a
			setting = (NMSetting *) nm_connection_get_setting_infiniband (connection);
Packit Service 82c12a
			g_object_set (setting, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL);
Packit Service 82c12a
		} else {
Packit Service 82c12a
			setting = nm_setting_wired_new ();
Packit Service 82c12a
			nm_connection_add_setting (connection, setting);
Packit Service 82c12a
			g_object_set (setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
Packit Service 82c12a
		}
Packit Service 331025
	}
Packit Service 331025
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 331025
		                                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 331025
                       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 331025
	const char *ifname = NULL;
Packit Service 331025
	gs_free char *mac = NULL;
Packit Service 331025
Packit Service 331025
	if (iface_spec) {
Packit Service 331025
		if (nm_utils_is_valid_iface_name (iface_spec, NULL))
Packit Service 331025
			ifname = iface_spec;
Packit Service 331025
		else {
Packit Service 82c12a
			mac = nm_utils_hwaddr_canonical (iface_spec, -1);
Packit Service 331025
			if (!mac)
Packit Service 331025
				_LOGW (LOGD_CORE, "invalid interface '%s'", iface_spec);
Packit Service 331025
		}
Packit Service 331025
	}
Packit Service b23acc
Packit Service 331025
	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 331025
		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 82c12a
		if (!type_name) {
Packit Service 82c12a
			if (   NM_STR_HAS_PREFIX (ifname, "ib")
Packit Service 82c12a
			    || (mac && nm_utils_hwaddr_valid (mac, INFINIBAND_ALEN)))
Packit Service 82c12a
				type_name = NM_SETTING_INFINIBAND_SETTING_NAME;
Packit Service 82c12a
			else
Packit Service 82c12a
				type_name = NM_SETTING_WIRED_SETTING_NAME;
Packit Service 82c12a
		}
Packit Service b23acc
Packit Service 331025
		connection = reader_create_connection (reader, ifname ?: mac,
Packit Service 331025
		                                       ifname ?: (mac ?: "Wired Connection"),
Packit Service 331025
		                                       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 97715f
	const char *tmp2;
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 331025
	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 97715f
		tmp2 = get_word (&argument, ':');
Packit Service 97715f
		if (NM_IN_STRSET (tmp2,
Packit Service 97715f
		    "none",
Packit Service 97715f
		    "off",
Packit Service 97715f
		    "dhcp",
Packit Service 97715f
		    "on"
Packit Service 97715f
		    "any",
Packit Service 97715f
		    "dhcp6",
Packit Service 97715f
		    "auto",
Packit Service 97715f
		    "auto6",
Packit Service 97715f
		    "ibft")) {
Packit Service 97715f
			/* <ifname>:{none|off|dhcp|on|any|dhcp6|auto|auto6|ibft} */
Packit Service 97715f
			iface_spec = tmp;
Packit Service 97715f
			kind = tmp2;
Packit Service 97715f
		} else {
Packit Service 97715f
			/* <client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<kind> */
Packit Service b23acc
			client_ip = tmp;
Packit Service 97715f
			if (client_ip) {
Packit Service 97715f
				client_ip_family = get_ip_address_family (client_ip, TRUE);
Packit Service 97715f
				if (client_ip_family == AF_UNSPEC) {
Packit Service 97715f
					_LOGW (LOGD_CORE, "Invalid IP address '%s'.", client_ip);
Packit Service 97715f
					return;
Packit Service 97715f
				}
Packit Service 97715f
			}
Packit Service 97715f
Packit Service 97715f
			peer = tmp2;
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 331025
			iface_spec = get_word (&argument, ':');
Packit Service 97715f
			kind = get_word (&argument, ':');
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 b23acc
		tmp = get_word (&argument, ':');
Packit Service 051f6c
		dns_addr_family[0] = get_ip_address_family (tmp, FALSE);
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 051f6c
			dns_addr_family[1] = get_ip_address_family (dns[1], FALSE);
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 331025
	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 331025
	if (iface_spec)
Packit Service 331025
		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 051f6c
	g_hash_table_add (reader->explicit_ip_connections, g_object_ref (connection));
Packit Service 051f6c
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 331025
		gboolean is_ipv4 = client_ip_family == AF_INET;
Packit Service b23acc
		NMIPAddr addr;
Packit Service b23acc
Packit Service 331025
		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 331025
			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 051f6c
		} else
Packit Service 051f6c
			nm_assert_not_reached ();
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 051f6c
				nm_assert_not_reached ();
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 331025
		NMSettingWired *s_wired;
Packit Service 331025
		const char *mac = NULL;
Packit Service 331025
		const char *ifname;
Packit Service 331025
		gs_free char *mac_free = NULL;
Packit Service 331025
		gs_free char *address_path = NULL;
Packit Service b23acc
		GHashTable *nic = NULL;
Packit Service b23acc
Packit Service 331025
		if (   (s_wired = nm_connection_get_setting_wired (connection))
Packit Service 331025
		    && (mac = nm_setting_wired_get_mac_address (s_wired))) {
Packit Service 331025
			/* got mac from the connection */
Packit Service 331025
		} else if ((ifname = nm_connection_get_interface_name (connection))) {
Packit Service 331025
			/* read it from sysfs */
Packit Service 331025
			address_path = g_build_filename (sysfs_dir, "class", "net", ifname, "address", NULL);
Packit Service 331025
			if (g_file_get_contents (address_path, &mac_free, NULL, &error)) {
Packit Service 331025
				g_strchomp (mac_free);
Packit Service 331025
				mac = mac_free;
Packit Service 331025
			} else {
Packit Service 331025
				_LOGW (LOGD_CORE, "Can't get a MAC address for %s: %s", ifname, error->message);
Packit Service 331025
				g_clear_error (&error);
Packit Service 331025
			}
Packit Service b23acc
		}
Packit Service b23acc
Packit Service b23acc
		if (mac) {
Packit Service 331025
			gs_free char *mac_up = NULL;
Packit Service 331025
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 331025
				_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 051f6c
		switch (get_ip_address_family (gateway_ip, FALSE)) {
Packit Service 051f6c
		case AF_INET:
Packit Service 051f6c
			g_object_set (s_ip4, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
Packit Service 051f6c
			break;
Packit Service 051f6c
		case AF_INET6:
Packit Service 051f6c
			g_object_set (s_ip6, NM_SETTING_IP_CONFIG_GATEWAY, gateway_ip, NULL);
Packit Service 051f6c
			break;
Packit Service 051f6c
		default:
Packit Service b23acc
			_LOGW (LOGD_CORE, "Invalid gateway: %s", gateway_ip);
Packit Service 051f6c
			break;
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 dfc7b2
	if (nm_streq (type_name, NM_SETTING_BRIDGE_SETTING_NAME)) {
Packit Service dfc7b2
		NMSettingBridge *s_bridge = nm_connection_get_setting_bridge (connection);
Packit Service dfc7b2
Packit Service dfc7b2
		/* Avoid the forwarding delay */
Packit Service dfc7b2
		g_object_set (s_bridge,
Packit Service dfc7b2
		              NM_SETTING_BRIDGE_STP, FALSE,
Packit Service dfc7b2
		              NULL);
Packit Service dfc7b2
	} else if (nm_streq (type_name, NM_SETTING_BOND_SETTING_NAME)) {
Packit Service dfc7b2
		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 051f6c
Packit Service 051f6c
	if (!nm_strv_ptrarray_contains (reader->vlan_parents, phy))
Packit Service 051f6c
		g_ptr_array_add (reader->vlan_parents, g_strdup (phy));
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 051f6c
		addr_family = get_ip_address_family (ns, FALSE);
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 dfc7b2
static void
Packit Service dfc7b2
connection_set_needed (NMConnection *connection)
Packit Service dfc7b2
{
Packit Service dfc7b2
	NMSettingConnection *s_con;
Packit Service dfc7b2
Packit Service dfc7b2
	s_con = nm_connection_get_setting_connection (connection);
Packit Service dfc7b2
	if (!nm_streq0 (nm_setting_connection_get_connection_type (s_con),
Packit Service dfc7b2
	                NM_SETTING_WIRED_SETTING_NAME))
Packit Service dfc7b2
		return;
Packit Service dfc7b2
Packit Service dfc7b2
	g_object_set (s_con,
Packit Service dfc7b2
	              NM_SETTING_CONNECTION_WAIT_DEVICE_TIMEOUT, (int) NMI_WAIT_DEVICE_TIMEOUT_MS,
Packit Service dfc7b2
	              NULL);
Packit Service dfc7b2
}
Packit Service dfc7b2
Packit Service dfc7b2
static void
Packit Service dfc7b2
connection_set_needed_cb (gpointer key, gpointer value, gpointer user_data)
Packit Service dfc7b2
{
Packit Service dfc7b2
	connection_set_needed (value);
Packit Service dfc7b2
}
Packit Service dfc7b2
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 39775f
		} else if (nm_streq (tag, "rd.net.dhcp.vendor-class")) {
Packit Service 39775f
			if (nm_utils_validate_dhcp4_vendor_class_id (argument, NULL))
Packit Service 39775f
				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 051f6c
	for (i = 0; i < reader->vlan_parents->len; i++) {
Packit Service 051f6c
		NMConnection *connection;
Packit Service 051f6c
		NMSettingIPConfig *s_ip;
Packit Service 051f6c
Packit Service 051f6c
		/* Disable IP configuration for parent connections of VLANs,
Packit Service 051f6c
		 * unless those interfaces were explicitly configured otherwise. */
Packit Service 051f6c
Packit Service 051f6c
		connection = reader_get_connection (reader, reader->vlan_parents->pdata[i], NULL, TRUE);
Packit Service 051f6c
		if (!g_hash_table_contains (reader->explicit_ip_connections, connection)) {
Packit Service 051f6c
			s_ip = nm_connection_get_setting_ip4_config (connection);
Packit Service 051f6c
			if (s_ip) {
Packit Service 051f6c
				g_object_set (s_ip,
Packit Service 051f6c
				              NM_SETTING_IP_CONFIG_METHOD,
Packit Service 051f6c
				              NM_SETTING_IP4_CONFIG_METHOD_DISABLED,
Packit Service 051f6c
				              NULL);
Packit Service 051f6c
			}
Packit Service 051f6c
Packit Service 051f6c
			s_ip = nm_connection_get_setting_ip6_config (connection);
Packit Service 051f6c
			if (s_ip) {
Packit Service 051f6c
				g_object_set (s_ip,
Packit Service 051f6c
				              NM_SETTING_IP_CONFIG_METHOD,
Packit Service 051f6c
				              NM_SETTING_IP6_CONFIG_METHOD_DISABLED,
Packit Service 051f6c
				              NULL);
Packit Service 051f6c
			}
Packit Service 051f6c
		}
Packit Service 051f6c
	}
Packit Service 051f6c
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 331025
			                                       bootif,
Packit Service b23acc
			                                       NM_SETTING_WIRED_SETTING_NAME,
Packit Service b23acc
			                                       NM_CONNECTION_MULTI_CONNECT_SINGLE);
Packit Service 331025
		} else {
Packit Service 331025
			g_object_set (s_wired,
Packit Service 331025
			              NM_SETTING_WIRED_MAC_ADDRESS, bootif,
Packit Service 331025
			              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 dfc7b2
		connection_set_needed (connection);
Packit Service b23acc
	}
Packit Service b23acc
Packit Service dfc7b2
	if (neednet) {
Packit Service dfc7b2
		if (g_hash_table_size (reader->hash) == 0) {
Packit Service dfc7b2
			/* Make sure there's some connection. */
Packit Service dfc7b2
			reader_get_default_connection (reader);
Packit Service dfc7b2
		}
Packit Service dfc7b2
Packit Service dfc7b2
		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
}