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