From 14b0f3a9dc9ea90d60a3b057350fd4d637dc021a Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Wed, 28 Jun 2023 15:04:35 +0200 Subject: New upstream version 1.42.8 --- src/core/devices/nm-device-bond.c | 88 ++++-- src/core/devices/nm-device.c | 24 +- src/core/devices/team/nm-device-team.c | 18 +- src/core/devices/wifi/nm-device-wifi-p2p.c | 4 +- src/core/nm-firewall-utils.c | 4 +- src/core/nm-l3-ipv6ll.c | 34 ++- src/core/platform/nm-fake-platform.c | 28 +- src/core/platform/tests/test-link.c | 53 +++- src/core/ppp/meson.build | 6 +- src/core/ppp/nm-ppp-manager.c | 6 +- src/core/ppp/nm-ppp-mgr.c | 2 +- src/core/ppp/nm-ppp-status.h | 37 ++- src/core/ppp/nm-pppd-compat.c | 308 +++++++++++++++++++++ src/core/ppp/nm-pppd-compat.h | 64 +++++ src/core/ppp/nm-pppd-plugin.c | 198 ++++++------- .../plugins/ifcfg-rh/nms-ifcfg-rh-reader.c | 35 ++- .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c | 2 + .../settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h | 2 +- .../plugins/ifcfg-rh/nms-ifcfg-rh-writer.c | 36 ++- .../tests/network-scripts/ifcfg-test-infiniband | 8 - .../tests/network-scripts/ifcfg-test-infiniband0 | 8 + .../tests/network-scripts/ifcfg-test-infiniband1 | 12 + .../tests/network-scripts/ifcfg-test-infiniband2 | 12 + .../plugins/ifcfg-rh/tests/test-ifcfg-rh.c | 85 ++++-- 24 files changed, 820 insertions(+), 254 deletions(-) create mode 100644 src/core/ppp/nm-pppd-compat.c create mode 100644 src/core/ppp/nm-pppd-compat.h delete mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband0 create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband1 create mode 100644 src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband2 (limited to 'src/core') diff --git a/src/core/devices/nm-device-bond.c b/src/core/devices/nm-device-bond.c index 0b0697e3..56c5ec50 100644 --- a/src/core/devices/nm-device-bond.c +++ b/src/core/devices/nm-device-bond.c @@ -227,24 +227,23 @@ controller_update_port_connection(NMDevice *self, NMConnection *connection, GError **error) { - NMSettingBondPort *s_port; - int ifindex_port = nm_device_get_ifindex(port); - NMConnection *applied_connection = nm_device_get_applied_connection(self); - uint queue_id = NM_BOND_PORT_QUEUE_ID_DEF; - gs_free char *queue_id_str = NULL; + NMSettingBondPort *s_port; + int ifindex_port = nm_device_get_ifindex(port); + NMConnection *applied_connection = nm_device_get_applied_connection(self); + const NMPlatformLink *pllink; g_return_val_if_fail(ifindex_port > 0, FALSE); s_port = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_BOND_PORT); + pllink = nm_platform_link_get(nm_device_get_platform(port), ifindex_port); - queue_id_str = - nm_platform_sysctl_slave_get_option(nm_device_get_platform(self), ifindex_port, "queue_id"); - if (queue_id_str) { - queue_id = - _nm_utils_ascii_str_to_int64(queue_id_str, 10, 0, 65535, NM_BOND_PORT_QUEUE_ID_DEF); - g_object_set(s_port, NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); - } else - _LOGW(LOGD_BOND, "failed to read bond port setting '%s'", NM_SETTING_BOND_PORT_QUEUE_ID); + if (pllink && pllink->port_kind == NM_PORT_KIND_BOND) + g_object_set(s_port, + NM_SETTING_BOND_PORT_QUEUE_ID, + pllink->port_data.bond.queue_id, + NM_SETTING_BOND_PORT_PRIO, + pllink->port_data.bond.prio, + NULL); g_object_set(nm_connection_get_setting_connection(connection), NM_SETTING_CONNECTION_MASTER, @@ -600,23 +599,52 @@ act_stage1_prepare(NMDevice *device, NMDeviceStateReason *out_failure_reason) static void commit_port_options(NMDevice *bond_device, NMDevice *port, NMSettingBondPort *s_port) { - char queue_id_str[IFNAMSIZ + NM_STRLEN(":") + 5 + 100]; - - /* - * The queue-id of bond port is read only, we should modify bond interface using: - * echo "eth1:2" > /sys/class/net/bond0/bonding/queue_id - * Kernel allows parital editing, so no need to care about other bond ports. - */ - g_snprintf(queue_id_str, - sizeof(queue_id_str), - "%s:%" G_GUINT32_FORMAT, - nm_device_get_iface(port), - s_port ? nm_setting_bond_port_get_queue_id(s_port) : NM_BOND_PORT_QUEUE_ID_DEF); - - nm_platform_sysctl_master_set_option(nm_device_get_platform(bond_device), - nm_device_get_ifindex(bond_device), - "queue_id", - queue_id_str); + NMBondMode mode = NM_BOND_MODE_UNKNOWN; + const char *value; + NMSettingBond *s_bond; + gint32 prio; + gboolean prio_has; + + s_bond = nm_device_get_applied_setting(bond_device, NM_TYPE_SETTING_BOND); + if (s_bond) { + value = nm_setting_bond_get_option_normalized(s_bond, NM_SETTING_BOND_OPTION_MODE); + mode = _nm_setting_bond_mode_from_string(value); + } + + prio = s_port ? nm_setting_bond_port_get_prio(s_port) : NM_BOND_PORT_PRIO_DEF; + + if (prio != 0) { + /* The profile explicitly sets the priority. No matter what, we try to set it + * in netlink. */ + prio_has = TRUE; + } else if (!NM_IN_SET(mode, NM_BOND_MODE_ACTIVEBACKUP, NM_BOND_MODE_TLB, NM_BOND_MODE_ALB)) { + /* The priority only is configurable with certain modes. If we don't have + * one of those modes, don't try to set the priority explicitly to zero. */ + prio_has = FALSE; + } else if (nm_platform_kernel_support_get_full( + NM_PLATFORM_KERNEL_SUPPORT_TYPE_IFLA_BOND_SLAVE_PRIO, + FALSE) + == NM_OPTION_BOOL_TRUE) { + /* We can only detect support if we have it. We cannot detect lack of support if + * we don't have it. + * + * But we did explicitly detect support, so explicitly set the prio to zero. */ + prio_has = TRUE; + } else { + /* We either have an unsuitable mode or didn't detect kernel support for the + * priority. Don't explicitly set priority to zero. It is already the default, + * so it shouldn't be necessary. */ + prio_has = FALSE; + } + + nm_platform_link_change(nm_device_get_platform(port), + nm_device_get_ifindex(port), + &((NMPlatformLinkBondPort){ + .queue_id = s_port ? nm_setting_bond_port_get_queue_id(s_port) + : NM_BOND_PORT_QUEUE_ID_DEF, + .prio = prio_has ? prio : 0, + .prio_has = prio_has, + })); } static NMTernary diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c index d080b540..62a9ff1e 100644 --- a/src/core/devices/nm-device.c +++ b/src/core/devices/nm-device.c @@ -11691,7 +11691,18 @@ _dev_ipac6_start(NMDevice *self) } if (nm_ndisc_get_node_type(priv->ipac6_data.ndisc) == NM_NDISC_NODE_TYPE_ROUTER) { - nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1"); + gs_free char *sysctl_value = NULL; + + sysctl_value = nm_device_sysctl_ip_conf_get(self, AF_INET6, "forwarding"); + if (!nm_streq0(sysctl_value, "1")) { + if (sysctl_value && !g_hash_table_contains(priv->ip6_saved_properties, "forwarding")) { + g_hash_table_insert(priv->ip6_saved_properties, + "forwarding", + g_steal_pointer(&sysctl_value)); + } + nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "1"); + } + priv->needs_ip6_subnet = TRUE; g_signal_emit(self, signals[IP6_SUBNET_NEEDED], 0); } @@ -11749,7 +11760,6 @@ _dev_sysctl_save_ip6_properties(NMDevice *self) { static const char *const ip6_properties_to_save[] = { "accept_ra", - "forwarding", "disable_ipv6", "hop_limit", "use_tempaddr", @@ -12892,6 +12902,7 @@ check_and_reapply_connection(NMDevice *self, NMConnection *con_old; NMConnection *con_new; GHashTableIter iter; + NMSettingsConnection *sett_conn; if (priv->state < NM_DEVICE_STATE_PREPARE || priv->state > NM_DEVICE_STATE_ACTIVATED) { g_set_error_literal(error, @@ -13064,6 +13075,14 @@ check_and_reapply_connection(NMDevice *self, if (priv->state >= NM_DEVICE_STATE_ACTIVATED) nm_device_update_metered(self); + sett_conn = nm_device_get_settings_connection(self); + if (sett_conn) { + nm_settings_connection_autoconnect_blocked_reason_set( + sett_conn, + NM_SETTINGS_AUTO_CONNECT_BLOCKED_REASON_USER_REQUEST, + FALSE); + } + /* Notify dispatcher when re-applied */ _LOGD(LOGD_DEVICE, "Notifying re-apply complete"); nm_dispatcher_call_device(NM_DISPATCHER_ACTION_REAPPLY, self, NULL, NULL, NULL, NULL); @@ -15649,7 +15668,6 @@ ip6_managed_setup(NMDevice *self) _dev_sysctl_set_disable_ipv6(self, FALSE); nm_device_sysctl_ip_conf_set(self, AF_INET6, "accept_ra", "0"); nm_device_sysctl_ip_conf_set(self, AF_INET6, "use_tempaddr", "0"); - nm_device_sysctl_ip_conf_set(self, AF_INET6, "forwarding", "0"); } static void diff --git a/src/core/devices/team/nm-device-team.c b/src/core/devices/team/nm-device-team.c index 3e3fe52b..5c955986 100644 --- a/src/core/devices/team/nm-device-team.c +++ b/src/core/devices/team/nm-device-team.c @@ -226,24 +226,10 @@ update_connection(NMDevice *device, NMConnection *connection) NMDeviceTeam *self = NM_DEVICE_TEAM(device); NMSettingTeam *s_team = _nm_connection_ensure_setting(connection, NM_TYPE_SETTING_TEAM); NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE(self); - struct teamdctl *tdc = priv->tdc; - GError *error = NULL; /* Read the configuration only if not already set */ - if (!priv->config) { - if (ensure_teamd_connection(device, &error)) { - teamd_read_config(self); - } else { - _LOGD(LOGD_TEAM, "could not connect to teamd: %s", error->message); - g_clear_error(&error); - } - } - - /* Restore previous tdc state */ - if (priv->tdc && !tdc) { - teamdctl_disconnect(priv->tdc); - teamdctl_free(priv->tdc); - priv->tdc = NULL; + if (!priv->config && priv->tdc) { + teamd_read_config(self); } g_object_set(G_OBJECT(s_team), NM_SETTING_TEAM_CONFIG, _get_config(self), NULL); diff --git a/src/core/devices/wifi/nm-device-wifi-p2p.c b/src/core/devices/wifi/nm-device-wifi-p2p.c index 6c0a4d5e..424464c1 100644 --- a/src/core/devices/wifi/nm-device-wifi-p2p.c +++ b/src/core/devices/wifi/nm-device-wifi-p2p.c @@ -585,7 +585,7 @@ act_stage3_ip_config(NMDevice *device, int addr_family) nm_device_devip_set_state(device, AF_INET, NM_DEVICE_IP_STATE_READY, l3cd); /* This just disables the addressing indicator. */ - method = NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; } } @@ -643,7 +643,7 @@ get_auto_ip_config_method(NMDevice *device, int addr_family) if (addr_family == AF_INET && priv->group_iface && !nm_supplicant_interface_get_p2p_group_owner(priv->group_iface) && nm_supplicant_interface_get_p2p_assigned_addr(priv->group_iface, NULL, NULL)) - return NM_SETTING_IP4_CONFIG_METHOD_DISABLED; + return NM_SETTING_IP4_CONFIG_METHOD_MANUAL; /* Override the AUTO method to mean shared if we are group owner. */ if (priv->group_iface && nm_supplicant_interface_get_p2p_group_owner(priv->group_iface)) { diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c index f231583a..03f1a9a5 100644 --- a/src/core/nm-firewall-utils.c +++ b/src/core/nm-firewall-utils.c @@ -889,12 +889,12 @@ nm_firewall_nft_stdio_mlag(gboolean up, */ _append(&strbuf, "add set netdev %s macset-tagged {" - " typeof ether saddr . vlan id; flags timeout; " + " typeof ether saddr . vlan id; flags dynamic,timeout; " "}", table_name); _append(&strbuf, "add set netdev %s macset-untagged {" - " typeof ether saddr; flags timeout;" + " typeof ether saddr; flags dynamic,timeout; " "}", table_name); diff --git a/src/core/nm-l3-ipv6ll.c b/src/core/nm-l3-ipv6ll.c index 2e2a6a0a..0133ebe6 100644 --- a/src/core/nm-l3-ipv6ll.c +++ b/src/core/nm-l3-ipv6ll.c @@ -391,7 +391,7 @@ _pladdr_find_ll(NML3IPv6LL *self, gboolean *out_cur_addr_failed) /*****************************************************************************/ static void -_lladdr_handle_changed(NML3IPv6LL *self) +_lladdr_handle_changed(NML3IPv6LL *self, gboolean force_commit) { const NML3ConfigData *l3cd; gboolean changed = FALSE; @@ -420,7 +420,9 @@ _lladdr_handle_changed(NML3IPv6LL *self) NM_DNS_PRIORITY_DEFAULT_NORMAL, NM_L3_ACD_DEFEND_TYPE_ALWAYS, 0, - NM_L3CFG_CONFIG_FLAGS_NONE, + /* Even if the address was removed from platform, it must + * be re-added, hence FORCE_ONCE. */ + NM_L3CFG_CONFIG_FLAGS_FORCE_ONCE, NM_L3_CONFIG_MERGE_FLAGS_NONE)) changed = TRUE; } else { @@ -434,7 +436,7 @@ _lladdr_handle_changed(NML3IPv6LL *self) self->l3cfg_commit_handle, "ipv6ll"); - if (changed) + if (changed || force_commit) nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO); if (!self->emit_changed_idle_source) { @@ -515,6 +517,7 @@ _check(NML3IPv6LL *self) const NMPlatformIP6Address *pladdr; char sbuf[INET6_ADDRSTRLEN]; gboolean cur_addr_failed; + gboolean restarted = FALSE; struct in6_addr lladdr; pladdr = _pladdr_find_ll(self, &cur_addr_failed); @@ -526,14 +529,14 @@ _check(NML3IPv6LL *self) if (_set_cur_lladdr_obj(self, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, pladdr)) { _LOGT("changed: waiting for address %s to complete DAD", nm_inet6_ntop(&self->cur_lladdr, sbuf)); - _lladdr_handle_changed(self); + _lladdr_handle_changed(self, FALSE); } return; } if (_set_cur_lladdr_obj(self, NM_L3_IPV6LL_STATE_READY, pladdr)) { _LOGT("changed: address %s is ready", nm_inet6_ntop(&self->cur_lladdr, sbuf)); - _lladdr_handle_changed(self); + _lladdr_handle_changed(self, FALSE); } return; } @@ -543,11 +546,17 @@ _check(NML3IPv6LL *self) * Prematurely abort DAD to generate a new address below. */ nm_assert( NM_IN_SET(self->state, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, NM_L3_IPV6LL_STATE_READY)); - if (self->state == NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS) - _LOGT("changed: address %s did not complete DAD", - nm_inet6_ntop(&self->cur_lladdr, sbuf)); - else { + + if (cur_addr_failed) { + /* On DAD failure, we always try to regenerate a new address. */ + _LOGT("changed: address %s failed", nm_inet6_ntop(&self->cur_lladdr, sbuf)); + } else { _LOGT("changed: address %s is gone", nm_inet6_ntop(&self->cur_lladdr, sbuf)); + /* When the address is removed, we always try to re-add it. */ + nm_clear_g_source_inst(&self->wait_for_addr_source); + lladdr = self->cur_lladdr; + restarted = TRUE; + goto commit; } /* reset the state here, so that we are sure that the following @@ -569,18 +578,19 @@ _check(NML3IPv6LL *self) if (_set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_DAD_FAILED, NULL)) { _LOGW("changed: no IPv6 link local address to retry after Duplicate Address Detection " "failures (back off)"); - _lladdr_handle_changed(self); + _lladdr_handle_changed(self, FALSE); } return; } +commit: /* we give NML3Cfg 2 seconds to configure the address on the interface. We * thus very soon expect to see this address configured (and kernel started DAD). * If that does not happen within timeout, we assume that this address failed DAD. */ self->wait_for_addr_source = nm_g_timeout_add_source(2000, _wait_for_addr_timeout_cb, self); - if (_set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, &lladdr)) { + if (_set_cur_lladdr_bin(self, NM_L3_IPV6LL_STATE_DAD_IN_PROGRESS, &lladdr) || restarted) { _LOGT("changed: starting DAD for address %s", nm_inet6_ntop(&self->cur_lladdr, sbuf)); - _lladdr_handle_changed(self); + _lladdr_handle_changed(self, restarted); } return; } diff --git a/src/core/platform/nm-fake-platform.c b/src/core/platform/nm-fake-platform.c index 86d6bc5f..0c366d82 100644 --- a/src/core/platform/nm-fake-platform.c +++ b/src/core/platform/nm-fake-platform.c @@ -666,6 +666,31 @@ link_supports_sriov(NMPlatform *platform, int ifindex) } } +static gboolean +link_change(NMPlatform *platform, + int ifindex, + NMPortKind port_kind, + const NMPlatformLinkPortData *port_data) +{ + NMFakePlatformLink *device = link_get(platform, ifindex); + nm_auto_nmpobj NMPObject *obj_tmp = NULL; + + switch (port_kind) { + case NM_PORT_KIND_BOND: + obj_tmp = nmp_object_clone(device->obj, FALSE); + obj_tmp->link.port_kind = NM_PORT_KIND_BOND; + obj_tmp->link.port_data.bond.queue_id = port_data->bond.queue_id; + obj_tmp->link.port_data.bond.prio_has = port_data->bond.prio_has; + obj_tmp->link.port_data.bond.prio = port_data->bond.prio; + link_set_obj(platform, device, obj_tmp); + return TRUE; + case NM_PORT_KIND_NONE: + return TRUE; + } + + return nm_assert_unreachable_val(TRUE); +} + static gboolean link_enslave(NMPlatform *platform, int master, int slave) { @@ -770,7 +795,7 @@ static gboolean infiniband_partition_delete(NMPlatform *platform, int parent, int p_key) { NMFakePlatformLink *parent_device; - gs_free char *name = NULL; + char name[IFNAMSIZ]; parent_device = link_get(platform, parent); g_return_val_if_fail(parent_device != NULL, FALSE); @@ -1325,6 +1350,7 @@ nm_fake_platform_class_init(NMFakePlatformClass *klass) platform_class->link_set_address = link_set_address; platform_class->link_set_mtu = link_set_mtu; + platform_class->link_change = link_change; platform_class->link_change_flags = link_change_flags; platform_class->link_get_driver_info = link_get_driver_info; diff --git a/src/core/platform/tests/test-link.c b/src/core/platform/tests/test-link.c index 9a1eaf89..33858671 100644 --- a/src/core/platform/tests/test-link.c +++ b/src/core/platform/tests/test-link.c @@ -112,7 +112,7 @@ software_add(NMLinkType link_type, const char *name) gboolean bond0_exists = !!nm_platform_link_get_by_ifname(NM_PLATFORM_GET, "bond0"); int r; const NMPlatformLnkBond nm_platform_lnk_bond_default = { - .mode = 3, + .mode = nmtst_rand_select(3, 1), }; r = nm_platform_link_bond_add(NM_PLATFORM_GET, name, &nm_platform_lnk_bond_default, NULL); @@ -263,6 +263,38 @@ test_slave(int master, int type, SignalData *master_changed) else g_assert(!nm_platform_link_is_up(NM_PLATFORM_GET, ifindex)); + if (NM_IN_SET(link_type, NM_LINK_TYPE_BOND)) { + NMPlatformLinkBondPort bond_port; + gboolean prio_has; + gboolean prio_supported; + const NMPlatformLink *link; + const NMPlatformLnkBond *lnk; + + link = nmtstp_link_get_typed(NM_PLATFORM_GET, 0, SLAVE_NAME, NM_LINK_TYPE_DUMMY); + g_assert(link); + + lnk = nm_platform_link_get_lnk_bond(NM_PLATFORM_GET, master, NULL); + g_assert(lnk); + + g_assert(NM_IN_SET(lnk->mode, 3, 1)); + prio_supported = (lnk->mode == 1); + prio_has = nmtst_get_rand_bool() && prio_supported; + + bond_port = (NMPlatformLinkBondPort){ + .queue_id = 5, + .prio_has = prio_has, + .prio = prio_has ? 6 : 0, + }; + + g_assert(nm_platform_link_change(NM_PLATFORM_GET, ifindex, &bond_port)); + accept_signals(link_changed, 1, 3); + + link = nmtstp_link_get(NM_PLATFORM_GET, ifindex, SLAVE_NAME); + g_assert(link); + g_assert_cmpint(link->port_data.bond.queue_id, ==, 5); + g_assert(link->port_data.bond.prio_has || link->port_data.bond.prio == 0); + } + test_link_changed_signal_arg1 = FALSE; test_link_changed_signal_arg2 = FALSE; g_signal_connect(NM_PLATFORM_GET, @@ -3349,7 +3381,9 @@ test_netns_bind_to_path(gpointer fixture, gconstpointer test_data) nm_auto_pop_netns NMPNetns *netns_pop = NULL; NMPlatform *platforms[3]; NMPNetns *netns; + int errsv; int i; + int r; if (_test_netns_check_skip()) return; @@ -3379,7 +3413,15 @@ test_netns_bind_to_path(gpointer fixture, gconstpointer test_data) g_assert(nmp_netns_bind_to_path(netns, P_VAR_RUN_NETNS_BINDNAME, NULL)); g_assert(g_file_test(P_VAR_RUN_NETNS_BINDNAME, G_FILE_TEST_EXISTS)); - g_assert_cmpint(nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true"), ==, 0); + + r = nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " true"); + if (r != 0) { + gs_free char *msg = g_strdup_printf("`ip netns exec` fails with code %d. Skip test", r); + + g_test_skip(msg); + return; + } + g_assert_cmpint( nmtstp_run_command("ip netns exec " P_NETNS_BINDNAME " ip link show dummy2b 1>/dev/null"), ==, @@ -3392,7 +3434,12 @@ test_netns_bind_to_path(gpointer fixture, gconstpointer test_data) !=, 0); - g_assert_cmpint(umount(P_VAR_RUN), ==, 0); + r = umount(P_VAR_RUN); + if (r != 0) { + errsv = errno; + g_assert_cmpint(errsv, ==, 0); + g_assert_cmpint(r, ==, 0); + } } /*****************************************************************************/ diff --git a/src/core/ppp/meson.build b/src/core/ppp/meson.build index 9ee46113..2365ffa8 100644 --- a/src/core/ppp/meson.build +++ b/src/core/ppp/meson.build @@ -3,7 +3,10 @@ nm_pppd_plugin = shared_module( 'nm-pppd-plugin', name_prefix: '', - sources: 'nm-pppd-plugin.c', + sources: [ + 'nm-pppd-compat.c', + 'nm-pppd-plugin.c', + ], include_directories: [ src_inc, top_inc, @@ -11,6 +14,7 @@ nm_pppd_plugin = shared_module( dependencies: [ libnm_core_public_dep, glib_dep, + pppd_dep, ], link_with: [ libnm_core_impl, diff --git a/src/core/ppp/nm-ppp-manager.c b/src/core/ppp/nm-ppp-manager.c index 14cd5731..fbc5d075 100644 --- a/src/core/ppp/nm-ppp-manager.c +++ b/src/core/ppp/nm-ppp-manager.c @@ -428,7 +428,7 @@ impl_ppp_manager_set_state(NMDBusObject *obj, if (ppp_state >= NM_PPP_STATUS_INTERN_DEAD) { /* we don't expect an intern state to be reported by the plugin. */ - ppp_state = NM_PPP_STATUS_UNKNOWN; + ppp_state = NM_PPP_STATUS_INTERN_UNKNOWN; } g_signal_emit(self, signals[STATE_CHANGED], 0, (guint) ppp_state); @@ -843,7 +843,7 @@ create_pppd_cmd_line(NMPPPManager *self, const char *pppoe_service; nm_strv_ptrarray_add_string_dup(cmd, "plugin"); - nm_strv_ptrarray_add_string_dup(cmd, "rp-pppoe.so"); + nm_strv_ptrarray_add_string_dup(cmd, NM_PPPOE_PLUGIN_NAME); nm_strv_ptrarray_add_string_concat(cmd, "nic-", priv->parent_iface); @@ -872,7 +872,7 @@ create_pppd_cmd_line(NMPPPManager *self, } else if (!strcmp(protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { nm_strv_ptrarray_add_string_dup(cmd, "plugin"); - nm_strv_ptrarray_add_string_dup(cmd, "rp-pppoe.so"); + nm_strv_ptrarray_add_string_dup(cmd, NM_PPPOE_PLUGIN_NAME); nm_strv_ptrarray_add_string_dup(cmd, priv->parent_iface); } diff --git a/src/core/ppp/nm-ppp-mgr.c b/src/core/ppp/nm-ppp-mgr.c index bebffaf3..91d9a021 100644 --- a/src/core/ppp/nm-ppp-mgr.c +++ b/src/core/ppp/nm-ppp-mgr.c @@ -257,7 +257,7 @@ _ppp_signal_state_changed(NMPPPManager *ppp_manager, guint ppp_state_u, gpointer const char *reason_msg; if ((guint) ppp_state != ppp_state_u) - ppp_state = NM_PPP_STATUS_UNKNOWN; + ppp_state = NM_PPP_STATUS_INTERN_UNKNOWN; switch (ppp_state) { case NM_PPP_STATUS_DISCONNECT: diff --git a/src/core/ppp/nm-ppp-status.h b/src/core/ppp/nm-ppp-status.h index df0ac10b..a2576e9c 100644 --- a/src/core/ppp/nm-ppp-status.h +++ b/src/core/ppp/nm-ppp-status.h @@ -8,24 +8,31 @@ #define __NM_PPP_STATUS_H__ typedef enum { - NM_PPP_STATUS_UNKNOWN, - - NM_PPP_STATUS_DEAD, - NM_PPP_STATUS_INITIALIZE, - NM_PPP_STATUS_SERIALCONN, - NM_PPP_STATUS_DORMANT, - NM_PPP_STATUS_ESTABLISH, - NM_PPP_STATUS_AUTHENTICATE, - NM_PPP_STATUS_CALLBACK, - NM_PPP_STATUS_NETWORK, - NM_PPP_STATUS_RUNNING, - NM_PPP_STATUS_TERMINATE, - NM_PPP_STATUS_DISCONNECT, - NM_PPP_STATUS_HOLDOFF, - NM_PPP_STATUS_MASTER, + + /* The numeric values correspond to the PHASE_{DEAD,} defines from . */ + NM_PPP_STATUS_DEAD = 0, + NM_PPP_STATUS_INITIALIZE = 1, + NM_PPP_STATUS_SERIALCONN = 2, + NM_PPP_STATUS_DORMANT = 3, + NM_PPP_STATUS_ESTABLISH = 4, + NM_PPP_STATUS_AUTHENTICATE = 5, + NM_PPP_STATUS_CALLBACK = 6, + NM_PPP_STATUS_NETWORK = 7, + NM_PPP_STATUS_RUNNING = 8, + NM_PPP_STATUS_TERMINATE = 9, + NM_PPP_STATUS_DISCONNECT = 10, + NM_PPP_STATUS_HOLDOFF = 11, + NM_PPP_STATUS_MASTER = 12, /* these states are internal and not announced by the pppd plugin. */ + NM_PPP_STATUS_INTERN_UNKNOWN = 20, NM_PPP_STATUS_INTERN_DEAD, } NMPPPStatus; +/*****************************************************************************/ + +/* The plugin name "(rp-)pppoe.so" depends on the ppp version. */ + +#define NM_PPPOE_PLUGIN_NAME (NM_PPP_VERSION_2_5_OR_NEWER ? "pppoe.so" : "rp-pppoe.so") + #endif /* __NM_PPP_STATUS_H__ */ diff --git a/src/core/ppp/nm-pppd-compat.c b/src/core/ppp/nm-pppd-compat.c new file mode 100644 index 00000000..f7940c55 --- /dev/null +++ b/src/core/ppp/nm-pppd-compat.c @@ -0,0 +1,308 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023 Eivind Næss, eivnaes@yahoo.com + */ + +/*****************************************************************************/ + +/* PPP headers define some symbols as we do. We need to be careful to handle + * the conflict, and include stuff in a certain order. */ + +#include +#define ___CONFIG_H__ + +/*****************************************************************************/ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) +_Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wstrict-prototypes\"") +#define _NM_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop") +#elif defined(__clang__) +_Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") + _Pragma("clang diagnostic ignored \"-Wstrict-prototypes\"") +#define _NM_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop") +#else +#define _NM_PRAGMA_WARNING_REENABLE +#endif + +/*****************************************************************************/ + +#define INET6 1 + +#include + +#ifdef DATE +/* Before ppp 2.5, pppd/patchlevel.h defined "DATE". Use that for detection. */ +#define PPP_VERSION_2_5_OR_NEWER 0 +#else +#define PPP_VERSION_2_5_OR_NEWER 1 +#endif + +#include +#include +#include +#include +#include + +#if PPP_VERSION_2_5_OR_NEWER +#include +#else +#include +#include +#endif + + char pppd_version[] = ( +#if PPP_VERSION_2_5_OR_NEWER + PPPD_VERSION +#else + VERSION +#endif + ); + +#undef VERSION + +_NM_PRAGMA_WARNING_REENABLE; + +/*****************************************************************************/ + +#include "libnm-glib-aux/nm-default-glib.h" + +#include "nm-pppd-compat.h" + +#include +#include + +#include "nm-ppp-status.h" + +/*****************************************************************************/ + +G_STATIC_ASSERT(PPP_VERSION_2_5_OR_NEWER == NM_PPP_VERSION_2_5_OR_NEWER); + +/*****************************************************************************/ + +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DEAD == PHASE_DEAD); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_INITIALIZE == PHASE_INITIALIZE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_SERIALCONN == PHASE_SERIALCONN); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DORMANT == PHASE_DORMANT); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_ESTABLISH == PHASE_ESTABLISH); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_AUTHENTICATE == PHASE_AUTHENTICATE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_CALLBACK == PHASE_CALLBACK); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_NETWORK == PHASE_NETWORK); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_RUNNING == PHASE_RUNNING); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_TERMINATE == PHASE_TERMINATE); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_DISCONNECT == PHASE_DISCONNECT); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_HOLDOFF == PHASE_HOLDOFF); +G_STATIC_ASSERT((gint64) NM_PPP_STATUS_MASTER == PHASE_MASTER); + +G_STATIC_ASSERT(NM_PPPD_COMPAT_MAXNAMELEN == MAXNAMELEN); +G_STATIC_ASSERT(NM_PPPD_COMPAT_MAXSECRETLEN == MAXSECRETLEN); + +/*****************************************************************************/ + +int +nm_pppd_compat_get_ifunit(void) +{ + int i; + +#if PPP_VERSION_2_5_OR_NEWER + i = ppp_ifunit(); +#else + i = ifunit; +#endif + + return i; +} + +const char * +nm_pppd_compat_get_ifname(void) +{ + const char *s; + +#if PPP_VERSION_2_5_OR_NEWER + s = ppp_ifname(); +#else + s = ifname; +#endif + + nm_assert(s); + nm_assert(strlen(s) < IFNAMSIZ); + return s; +} + +void +nm_pppd_compat_set_ifname(const char *arg_ifname) +{ + nm_assert(arg_ifname); + nm_assert(strlen(arg_ifname) < IFNAMSIZ); + +#if PPP_VERSION_2_5_OR_NEWER + ppp_set_ifname(arg_ifname); +#else + g_strlcpy(ifname, arg_ifname, IFNAMSIZ); +#endif +} + +const char * +nm_pppd_compat_get_ipparam(void) +{ + const char *s; + +#if PPP_VERSION_2_5_OR_NEWER + s = ppp_ipparam(); +#else + s = ipparam; +#endif + + return s; +} + +void +nm_pppd_compat_get_ipcp_options(NMPppdCompatIPCPOptions *out_got, NMPppdCompatIPCPOptions *out_his) +{ + const ipcp_options *const got = &ipcp_gotoptions[0]; + const ipcp_options *const his = &ipcp_hisoptions[0]; + + nm_assert(out_got); + nm_assert(out_his); + + *out_got = (NMPppdCompatIPCPOptions){ + .ouraddr = got->ouraddr, + .hisaddr = got->hisaddr, + .dnsaddr = {got->dnsaddr[0], got->dnsaddr[1]}, + .winsaddr = {got->winsaddr[0], got->winsaddr[1]}, + }; + + *out_his = (NMPppdCompatIPCPOptions){ + .ouraddr = his->ouraddr, + .hisaddr = his->hisaddr, + .dnsaddr = {his->dnsaddr[0], his->dnsaddr[1]}, + .winsaddr = {his->winsaddr[0], his->winsaddr[1]}, + }; +} + +void +nm_pppd_compat_get_ipv6cp_options(NMPppdCompatIPV6CPOptions *out_got, + NMPppdCompatIPV6CPOptions *out_his) +{ + const ipv6cp_options *const his = &ipv6cp_hisoptions[0]; + const ipv6cp_options *const got = &ipv6cp_gotoptions[0]; + + G_STATIC_ASSERT(sizeof(guint64) == sizeof(eui64_t)); + + nm_assert(out_got); + nm_assert(out_his); + + *out_got = (NMPppdCompatIPV6CPOptions){}; + memcpy(&out_got->ourid, &got->ourid, sizeof(guint64)); + memcpy(&out_got->hisid, &got->hisid, sizeof(guint64)); + + *out_his = (NMPppdCompatIPV6CPOptions){}; + memcpy(&out_his->ourid, &his->ourid, sizeof(guint64)); + memcpy(&out_his->hisid, &his->hisid, sizeof(guint64)); +} + +void +nm_pppd_compat_set_chap_passwd_hook(int (*hook)(char *user, char *password)) +{ + chap_passwd_hook = hook; +} + +void +nm_pppd_compat_set_chap_check_hook(int (*hook)(void)) +{ + chap_check_hook = hook; +} + +void +nm_pppd_compat_set_pap_passwd_hook(int (*hook)(char *user, char *passwd)) +{ + pap_passwd_hook = hook; +} + +void +nm_pppd_compat_set_pap_check_hook(int (*hook)(void)) +{ + pap_check_hook = hook; +} + +gboolean +nm_pppd_compat_add_notify(NMPppdCompatNotifyT type, void (*func)(void *ctx, int arg), void *ctx) +{ + nm_assert(NM_IN_SET(type, + NM_PPPD_COMPAT_NF_PID_CHANGE, + NM_PPPD_COMPAT_NF_PHASE_CHANGE, + NM_PPPD_COMPAT_NF_EXIT, + NM_PPPD_COMPAT_NF_SIGNALED, + NM_PPPD_COMPAT_NF_IP_UP, + NM_PPPD_COMPAT_NF_IP_DOWN, + NM_PPPD_COMPAT_NF_IPV6_UP, + NM_PPPD_COMPAT_NF_IPV6_DOWN, + NM_PPPD_COMPAT_NF_AUTH_UP, + NM_PPPD_COMPAT_NF_LINK_DOWN, + NM_PPPD_COMPAT_NF_FORK)); + nm_assert(func); + +#if PPP_VERSION_2_5_OR_NEWER + { + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_PID_CHANGE == NF_PID_CHANGE); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_PHASE_CHANGE == NF_PHASE_CHANGE); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_EXIT == NF_EXIT); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_SIGNALED == NF_SIGNALED); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IP_UP == NF_IP_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IP_DOWN == NF_IP_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IPV6_UP == NF_IPV6_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_IPV6_DOWN == NF_IPV6_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_AUTH_UP == NF_AUTH_UP); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_LINK_DOWN == NF_LINK_DOWN); + G_STATIC_ASSERT((gint64) NM_PPPD_COMPAT_NF_FORK == NF_FORK); + + ppp_add_notify((gint64) type, func, ctx); + return TRUE; + } +#else + { + static struct notifier **list[] = { + [NM_PPPD_COMPAT_NF_PID_CHANGE] = &pidchange, + [NM_PPPD_COMPAT_NF_PHASE_CHANGE] = &phasechange, + [NM_PPPD_COMPAT_NF_EXIT] = &exitnotify, + [NM_PPPD_COMPAT_NF_SIGNALED] = &sigreceived, + [NM_PPPD_COMPAT_NF_IP_UP] = &ip_up_notifier, + [NM_PPPD_COMPAT_NF_IP_DOWN] = &ip_down_notifier, + [NM_PPPD_COMPAT_NF_IPV6_UP] = NULL /* ipv6_up_notifier */, + [NM_PPPD_COMPAT_NF_IPV6_DOWN] = NULL /* ipv6_down_notifier */, + [NM_PPPD_COMPAT_NF_AUTH_UP] = &auth_up_notifier, + [NM_PPPD_COMPAT_NF_LINK_DOWN] = &link_down_notifier, + [NM_PPPD_COMPAT_NF_FORK] = &fork_notifier, + }; + struct notifier **notifier; + + nm_assert(_NM_INT_NOT_NEGATIVE(type) && type < G_N_ELEMENTS(list)); + + if (NM_IN_SET(type, NM_PPPD_COMPAT_NF_IPV6_UP, NM_PPPD_COMPAT_NF_IPV6_DOWN)) { + static gsize load_once = 0; + + /* pppd might be build without IPv6 support. Load the symbols dynamically. */ + if (g_once_init_enter(&load_once)) { + void *handle; + + handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); + if (handle) { + list[NM_PPPD_COMPAT_NF_IPV6_UP] = dlsym(handle, "ipv6_up_notifier"); + list[NM_PPPD_COMPAT_NF_IPV6_DOWN] = dlsym(handle, "ipv6_down_notifier"); + dlclose(handle); + } + g_once_init_leave(&load_once, 1); + } + + notifier = list[type]; + } else { + notifier = list[type]; + nm_assert(notifier); + } + + if (notifier) + add_notifier(notifier, func, ctx); + + return !!notifier; + } +#endif +} diff --git a/src/core/ppp/nm-pppd-compat.h b/src/core/ppp/nm-pppd-compat.h new file mode 100644 index 00000000..11376e36 --- /dev/null +++ b/src/core/ppp/nm-pppd-compat.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2023 Eivind Næss, eivnaes@yahoo.com + */ + +#ifndef __NM_PPPD_COMPAT_H__ +#define __NM_PPPD_COMPAT_H__ + +#define NM_PPPD_COMPAT_MAXNAMELEN 256 +#define NM_PPPD_COMPAT_MAXSECRETLEN 256 + +int nm_pppd_compat_get_ifunit(void); + +const char *nm_pppd_compat_get_ifname(void); +void nm_pppd_compat_set_ifname(const char *ifname); + +const char *nm_pppd_compat_get_ipparam(void); + +typedef struct { + /* has information from "ipcp_options" */ + in_addr_t ouraddr; + in_addr_t hisaddr; + in_addr_t dnsaddr[2]; + in_addr_t winsaddr[2]; +} NMPppdCompatIPCPOptions; + +void nm_pppd_compat_get_ipcp_options(NMPppdCompatIPCPOptions *out_got, + NMPppdCompatIPCPOptions *out_his); + +typedef struct { + /* has information from "ipv6cp_options" */ + guint64 ourid; + guint64 hisid; +} NMPppdCompatIPV6CPOptions; + +void nm_pppd_compat_get_ipv6cp_options(NMPppdCompatIPV6CPOptions *out_got, + NMPppdCompatIPV6CPOptions *out_his); + +void nm_pppd_compat_set_chap_passwd_hook(int (*hook)(char *user, char *password)); + +void nm_pppd_compat_set_chap_check_hook(int (*hook)(void)); + +void nm_pppd_compat_set_pap_passwd_hook(int (*hook)(char *user, char *passwd)); + +void nm_pppd_compat_set_pap_check_hook(int (*hook)(void)); + +typedef enum { + NM_PPPD_COMPAT_NF_PID_CHANGE, + NM_PPPD_COMPAT_NF_PHASE_CHANGE, + NM_PPPD_COMPAT_NF_EXIT, + NM_PPPD_COMPAT_NF_SIGNALED, + NM_PPPD_COMPAT_NF_IP_UP, + NM_PPPD_COMPAT_NF_IP_DOWN, + NM_PPPD_COMPAT_NF_IPV6_UP, + NM_PPPD_COMPAT_NF_IPV6_DOWN, + NM_PPPD_COMPAT_NF_AUTH_UP, + NM_PPPD_COMPAT_NF_LINK_DOWN, + NM_PPPD_COMPAT_NF_FORK, +} NMPppdCompatNotifyT; + +gboolean +nm_pppd_compat_add_notify(NMPppdCompatNotifyT type, void (*func)(void *ctx, int arg), void *ctx); + +#endif /* #ifdef __NM_PPPD_COMPAT_H__ */ diff --git a/src/core/ppp/nm-pppd-plugin.c b/src/core/ppp/nm-pppd-plugin.c index e2e34d2a..93425f38 100644 --- a/src/core/ppp/nm-pppd-plugin.c +++ b/src/core/ppp/nm-pppd-plugin.c @@ -4,33 +4,23 @@ * Copyright (C) 2008 Red Hat, Inc. */ -#include -#define ___CONFIG_H__ +#include "libnm-glib-aux/nm-default-glib.h" + +#include "nm-pppd-plugin.h" -#include -#include -#include #include #include #include #include #include +#include -#define INET6 -#include -#include - -#include "libnm-glib-aux/nm-default-glib.h" - -#include "nm-dbus-interface.h" - -#include "nm-pppd-plugin.h" +#include "nm-pppd-compat.h" #include "nm-ppp-status.h" +#include "nm-dbus-interface.h" int plugin_init(void); -char pppd_version[] = VERSION; - static struct { GDBusConnection *dbus_connection; char *ipparam; @@ -39,73 +29,63 @@ static struct { static void nm_phasechange(int arg) { - NMPPPStatus ppp_status = NM_PPP_STATUS_UNKNOWN; + NMPPPStatus ppp_status; char *ppp_phase; g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); + ppp_status = arg; + switch (arg) { - case PHASE_DEAD: - ppp_status = NM_PPP_STATUS_DEAD; - ppp_phase = "dead"; + case NM_PPP_STATUS_DEAD: + ppp_phase = "dead"; break; - case PHASE_INITIALIZE: - ppp_status = NM_PPP_STATUS_INITIALIZE; - ppp_phase = "initialize"; + case NM_PPP_STATUS_INITIALIZE: + ppp_phase = "initialize"; break; - case PHASE_SERIALCONN: - ppp_status = NM_PPP_STATUS_SERIALCONN; - ppp_phase = "serial connection"; + case NM_PPP_STATUS_SERIALCONN: + ppp_phase = "serial connection"; break; - case PHASE_DORMANT: - ppp_status = NM_PPP_STATUS_DORMANT; - ppp_phase = "dormant"; + case NM_PPP_STATUS_DORMANT: + ppp_phase = "dormant"; break; - case PHASE_ESTABLISH: - ppp_status = NM_PPP_STATUS_ESTABLISH; - ppp_phase = "establish"; + case NM_PPP_STATUS_ESTABLISH: + ppp_phase = "establish"; break; - case PHASE_AUTHENTICATE: - ppp_status = NM_PPP_STATUS_AUTHENTICATE; - ppp_phase = "authenticate"; + case NM_PPP_STATUS_AUTHENTICATE: + ppp_phase = "authenticate"; break; - case PHASE_CALLBACK: - ppp_status = NM_PPP_STATUS_CALLBACK; - ppp_phase = "callback"; + case NM_PPP_STATUS_CALLBACK: + ppp_phase = "callback"; break; - case PHASE_NETWORK: - ppp_status = NM_PPP_STATUS_NETWORK; - ppp_phase = "network"; + case NM_PPP_STATUS_NETWORK: + ppp_phase = "network"; break; - case PHASE_RUNNING: - ppp_status = NM_PPP_STATUS_RUNNING; - ppp_phase = "running"; + case NM_PPP_STATUS_RUNNING: + ppp_phase = "running"; break; - case PHASE_TERMINATE: - ppp_status = NM_PPP_STATUS_TERMINATE; - ppp_phase = "terminate"; + case NM_PPP_STATUS_TERMINATE: + ppp_phase = "terminate"; break; - case PHASE_DISCONNECT: - ppp_status = NM_PPP_STATUS_DISCONNECT; - ppp_phase = "disconnect"; + case NM_PPP_STATUS_DISCONNECT: + ppp_phase = "disconnect"; break; - case PHASE_HOLDOFF: - ppp_status = NM_PPP_STATUS_HOLDOFF; - ppp_phase = "holdoff"; + case NM_PPP_STATUS_HOLDOFF: + ppp_phase = "holdoff"; break; - case PHASE_MASTER: - ppp_status = NM_PPP_STATUS_MASTER; - ppp_phase = "master"; + case NM_PPP_STATUS_MASTER: + ppp_phase = "master"; break; default: - ppp_phase = "unknown"; + ppp_status = NM_PPP_STATUS_INTERN_UNKNOWN; + ppp_phase = "unknown"; break; } g_message("nm-ppp-plugin: status %d / phase '%s'", ppp_status, ppp_phase); - if (ppp_status != NM_PPP_STATUS_UNKNOWN) { + if (ppp_status != NM_PPP_STATUS_INTERN_UNKNOWN) { g_dbus_connection_call(gl.dbus_connection, NM_DBUS_SERVICE, gl.ipparam, @@ -125,7 +105,7 @@ nm_phasechange(int arg) char new_name[IF_NAMESIZE]; int ifindex; - ifindex = if_nametoindex(ifname); + ifindex = if_nametoindex(nm_pppd_compat_get_ifname()); /* Make a sync call to ensure that when the call * terminates the interface already has its final @@ -143,9 +123,12 @@ nm_phasechange(int arg) NULL); /* Update the name in pppd if NM changed it */ - if (if_indextoname(ifindex, new_name) && !nm_streq0(ifname, new_name)) { - g_message("nm-ppp-plugin: interface name changed from '%s' to '%s'", ifname, new_name); - g_strlcpy(ifname, new_name, IF_NAMESIZE); + if (if_indextoname(ifindex, new_name) + && !nm_streq0(nm_pppd_compat_get_ifname(), new_name)) { + g_message("nm-ppp-plugin: interface name changed from '%s' to '%s'", + nm_pppd_compat_get_ifname(), + new_name); + nm_pppd_compat_set_ifname(new_name); } } } @@ -154,7 +137,7 @@ static void nm_phasechange_hook(void *data, int arg) { /* We send the nofication in exitnotify instead */ - if (arg == PHASE_DEAD) + if (arg == NM_PPP_STATUS_DEAD) return; nm_phasechange(arg); @@ -163,18 +146,21 @@ nm_phasechange_hook(void *data, int arg) static void nm_ip_up(void *data, int arg) { - ipcp_options opts = ipcp_gotoptions[0]; - ipcp_options peer_opts = ipcp_hisoptions[0]; - GVariantBuilder builder; - guint32 pppd_made_up_address = htonl(0x0a404040 + ifunit); + NMPppdCompatIPCPOptions opts; + NMPppdCompatIPCPOptions peer_opts; + GVariantBuilder builder; + const in_addr_t pppd_made_up_address = + htonl(0x0a404040u + ((guint) nm_pppd_compat_get_ifunit())); g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); g_message("nm-ppp-plugin: ip-up event"); + nm_pppd_compat_get_ipcp_options(&opts, &peer_opts); + if (!opts.ouraddr) { g_warning("nm-ppp-plugin: didn't receive an internal IP from pppd!"); - nm_phasechange(PHASE_DEAD); + nm_phasechange(NM_PPP_STATUS_DEAD); return; } @@ -186,7 +172,7 @@ nm_ip_up(void *data, int arg) g_variant_builder_add(&builder, "{sv}", NM_PPP_IP4_CONFIG_INTERFACE, - g_variant_new_string(ifname)); + g_variant_new_string(nm_pppd_compat_get_ifname())); g_variant_builder_add(&builder, "{sv}", @@ -263,28 +249,19 @@ nm_ip_up(void *data, int arg) NULL); } -static GVariant * -eui64_to_variant(eui64_t eui) -{ - guint64 iid; - - G_STATIC_ASSERT(sizeof(iid) == sizeof(eui)); - - memcpy(&iid, &eui, sizeof(eui)); - return g_variant_new_uint64(iid); -} - static void nm_ip6_up(void *data, int arg) { - ipv6cp_options *ho = &ipv6cp_hisoptions[0]; - ipv6cp_options *go = &ipv6cp_gotoptions[0]; - GVariantBuilder builder; + NMPppdCompatIPV6CPOptions his; + NMPppdCompatIPV6CPOptions got; + GVariantBuilder builder; g_return_if_fail(G_IS_DBUS_CONNECTION(gl.dbus_connection)); g_message("nm-ppp-plugin: ip6-up event"); + nm_pppd_compat_get_ipv6cp_options(&got, &his); + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); /* Keep sending the interface name to be backwards compatible * with older versions of NM during a package upgrade, where @@ -292,12 +269,15 @@ nm_ip6_up(void *data, int arg) g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_INTERFACE, - g_variant_new_string(ifname)); - g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_OUR_IID, eui64_to_variant(go->ourid)); + g_variant_new_string(nm_pppd_compat_get_ifname())); + g_variant_builder_add(&builder, + "{sv}", + NM_PPP_IP6_CONFIG_OUR_IID, + g_variant_new_uint64(got.ourid)); g_variant_builder_add(&builder, "{sv}", NM_PPP_IP6_CONFIG_PEER_IID, - eui64_to_variant(ho->hisid)); + g_variant_new_uint64(his.hisid)); /* DNS is done via DHCPv6 or router advertisements */ @@ -368,8 +348,8 @@ get_credentials(char *username, char *password) g_variant_get(ret, "(&s&s)", &my_username, &my_password); - g_strlcpy(username, my_username, MAXNAMELEN); - g_strlcpy(password, my_password, MAXSECRETLEN); + g_strlcpy(username, my_username, NM_PPPD_COMPAT_MAXNAMELEN); + g_strlcpy(password, my_password, NM_PPPD_COMPAT_MAXSECRETLEN); return 1; } @@ -382,7 +362,7 @@ nm_exit_notify(void *data, int arg) /* We wait until this point to notify dead phase to make sure that * the serial port has recovered already its original settings. */ - nm_phasechange(PHASE_DEAD); + nm_phasechange(NM_PPP_STATUS_DEAD); g_message("nm-ppp-plugin: cleaning up"); @@ -390,27 +370,6 @@ nm_exit_notify(void *data, int arg) nm_clear_g_free(&gl.ipparam); } -static void -add_ip6_notifier(void) -{ - static struct notifier **notifier = NULL; - static gsize load_once = 0; - - if (g_once_init_enter(&load_once)) { - void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL); - - if (handle) { - notifier = dlsym(handle, "ipv6_up_notifier"); - dlclose(handle); - } - g_once_init_leave(&load_once, 1); - } - if (notifier) - add_notifier(notifier, nm_ip6_up, NULL); - else - g_message("nm-ppp-plugin: no IPV6CP notifier support; IPv6 not available"); -} - int plugin_init(void) { @@ -427,17 +386,16 @@ plugin_init(void) return -1; } - gl.ipparam = g_strdup(ipparam); - - chap_passwd_hook = get_credentials; - chap_check_hook = get_chap_check; - pap_passwd_hook = get_credentials; - pap_check_hook = get_pap_check; + gl.ipparam = g_strdup(nm_pppd_compat_get_ipparam()); - add_notifier(&phasechange, nm_phasechange_hook, NULL); - add_notifier(&ip_up_notifier, nm_ip_up, NULL); - add_notifier(&exitnotify, nm_exit_notify, NULL); - add_ip6_notifier(); + nm_pppd_compat_set_chap_passwd_hook(get_credentials); + nm_pppd_compat_set_chap_check_hook(get_chap_check); + nm_pppd_compat_set_pap_passwd_hook(get_credentials); + nm_pppd_compat_set_pap_check_hook(get_pap_check); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_PHASE_CHANGE, nm_phasechange_hook, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_IP_UP, nm_ip_up, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_EXIT, nm_exit_notify, NULL); + nm_pppd_compat_add_notify(NM_PPPD_COMPAT_NF_IPV6_UP, nm_ip6_up, NULL); return 0; } diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c index aa593331..6cfb5705 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-reader.c @@ -5377,6 +5377,7 @@ parse_infiniband_p_key(shvarFile *ifcfg, int *out_p_key, char **out_parent, GErr gs_free char *physdev = NULL; gs_free char *pkey_id = NULL; int id; + int fixup_id = 0; physdev = svGetValueStr_cp(ifcfg, "PHYSDEV"); if (!physdev) { @@ -5387,7 +5388,14 @@ parse_infiniband_p_key(shvarFile *ifcfg, int *out_p_key, char **out_parent, GErr return FALSE; } - pkey_id = svGetValueStr_cp(ifcfg, "PKEY_ID"); + pkey_id = svGetValueStr_cp(ifcfg, "PKEY_ID_NM"); + if (!pkey_id) { + /* Only check for "$PKEY_ID". That key is interpreted as having the + * full membership flag set ("fixup_id"). */ + fixup_id = 0x8000; + pkey_id = svGetValueStr_cp(ifcfg, "PKEY_ID"); + } + if (!pkey_id) { g_set_error(error, NM_SETTINGS_ERROR, @@ -5406,6 +5414,8 @@ parse_infiniband_p_key(shvarFile *ifcfg, int *out_p_key, char **out_parent, GErr return FALSE; } + id |= fixup_id; + *out_p_key = id; *out_parent = g_steal_pointer(&physdev); return TRUE; @@ -5576,6 +5586,7 @@ make_bond_port_setting(shvarFile *ifcfg) gs_free char *value_to_free = NULL; const char *value; guint queue_id; + gint32 prio; g_return_val_if_fail(ifcfg != NULL, FALSE); @@ -5584,11 +5595,23 @@ make_bond_port_setting(shvarFile *ifcfg) s_port = nm_setting_bond_port_new(); queue_id = _nm_utils_ascii_str_to_uint64(value, 10, 0, G_MAXUINT16, NM_BOND_PORT_QUEUE_ID_DEF); - if (errno != 0) { - PARSE_WARNING("Invalid bond port queue_id value '%s'", value); - return s_port; - } - g_object_set(G_OBJECT(s_port), NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); + if (errno != 0) + PARSE_WARNING("Invalid bond port queue_id value BOND_PORT_QUEUE_ID '%s'", value); + else + g_object_set(G_OBJECT(s_port), NM_SETTING_BOND_PORT_QUEUE_ID, queue_id, NULL); + } + + nm_clear_g_free(&value_to_free); + value = svGetValue(ifcfg, "BOND_PORT_PRIO", &value_to_free); + if (value) { + if (!s_port) + s_port = nm_setting_bond_port_new(); + prio = + _nm_utils_ascii_str_to_int64(value, 10, G_MININT32, G_MAXINT32, NM_BOND_PORT_PRIO_DEF); + if (errno != 0) + PARSE_WARNING("Invalid bond port prio value BOND_PORT_PRIO '%s'", value); + else + g_object_set(G_OBJECT(s_port), NM_SETTING_BOND_PORT_PRIO, prio, NULL); } return s_port; diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c index 552310dd..207b8700 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.c @@ -827,6 +827,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("BAND", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BONDING_MASTER", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BONDING_OPTS", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("BOND_PORT_PRIO", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BOND_PORT_QUEUE_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BOOTPROTO", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("BRIDGE", NMS_IFCFG_KEY_TYPE_IS_PLAIN), @@ -1031,6 +1032,7 @@ const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[] = { _KEY_TYPE("PHYSDEV", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("PKEY", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("PKEY_ID", NMS_IFCFG_KEY_TYPE_IS_PLAIN), + _KEY_TYPE("PKEY_ID_NM", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("PMF", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("PORTNAME", NMS_IFCFG_KEY_TYPE_IS_PLAIN), _KEY_TYPE("POWERSAVE", NMS_IFCFG_KEY_TYPE_IS_PLAIN), diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h index 4fa9f18c..51b118e3 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-utils.h @@ -33,7 +33,7 @@ typedef struct { NMSIfcfgKeyTypeFlags key_flags; } NMSIfcfgKeyTypeInfo; -extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[261]; +extern const NMSIfcfgKeyTypeInfo nms_ifcfg_well_known_keys[263]; const NMSIfcfgKeyTypeInfo *nms_ifcfg_well_known_key_find_info(const char *key, gssize *out_idx); diff --git a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c index 41260020..97637063 100644 --- a/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c +++ b/src/core/settings/plugins/ifcfg-rh/nms-ifcfg-rh-writer.c @@ -1023,7 +1023,10 @@ write_wireless_setting(NMConnection *connection, } static gboolean -write_infiniband_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) +write_infiniband_setting(NMConnection *connection, + shvarFile *ifcfg, + char **out_interface_name, + GError **error) { NMSettingInfiniband *s_infiniband; const char *mac, *transport_mode, *parent; @@ -1052,11 +1055,23 @@ write_infiniband_setting(NMConnection *connection, shvarFile *ifcfg, GError **er p_key = nm_setting_infiniband_get_p_key(s_infiniband); if (p_key != -1) { svSetValueStr(ifcfg, "PKEY", "yes"); + svSetValueInt64(ifcfg, "PKEY_ID", p_key); + if (!NM_FLAGS_HAS(p_key, 0x8000)) { + /* initscripts' ifup-ib used to always interpret the PKEY_ID with + * the full membership flag (0x8000) set. For compatibility, we do + * interpret PKEY_ID as having that flag set. + * + * However, now we want to persist a p-key which doesn't have the + * flag. Use a NetworkManager specific variable for that. This configuration + * is not supported by initscripts' ifup-ib. + */ + svSetValueInt64(ifcfg, "PKEY_ID_NM", p_key); + } + parent = nm_setting_infiniband_get_parent(s_infiniband); - if (parent) - svSetValueStr(ifcfg, "PHYSDEV", parent); + svSetValueStr(ifcfg, "PHYSDEV", parent); } svSetValueStr(ifcfg, "TYPE", TYPE_INFINIBAND); @@ -1911,8 +1926,10 @@ write_bond_port_setting(NMConnection *connection, shvarFile *ifcfg) NMSettingBondPort *s_port; s_port = _nm_connection_get_setting(connection, NM_TYPE_SETTING_BOND_PORT); - if (s_port) + if (s_port) { svSetValueInt64(ifcfg, "BOND_PORT_QUEUE_ID", nm_setting_bond_port_get_queue_id(s_port)); + svSetValueInt64(ifcfg, "BOND_PORT_PRIO", nm_setting_bond_port_get_prio(s_port)); + } } static gboolean @@ -2093,7 +2110,7 @@ write_dcb_setting(NMConnection *connection, shvarFile *ifcfg, GError **error) } static void -write_connection_setting(NMSettingConnection *s_con, shvarFile *ifcfg) +write_connection_setting(NMSettingConnection *s_con, shvarFile *ifcfg, const char *interface_name) { guint32 n, i; nm_auto_free_gstring GString *str = NULL; @@ -2110,7 +2127,9 @@ write_connection_setting(NMSettingConnection *s_con, shvarFile *ifcfg) svSetValueStr(ifcfg, "NAME", nm_setting_connection_get_id(s_con)); svSetValueStr(ifcfg, "UUID", nm_setting_connection_get_uuid(s_con)); svSetValueStr(ifcfg, "STABLE_ID", nm_setting_connection_get_stable_id(s_con)); - svSetValueStr(ifcfg, "DEVICE", nm_setting_connection_get_interface_name(s_con)); + svSetValueStr(ifcfg, + "DEVICE", + interface_name ?: nm_setting_connection_get_interface_name(s_con)); svSetValueBoolean(ifcfg, "ONBOOT", nm_setting_connection_get_autoconnect(s_con)); vint = nm_setting_connection_get_autoconnect_priority(s_con); @@ -3308,6 +3327,7 @@ do_write_construct(NMConnection *connection, nm_auto_shvar_file_close shvarFile *route_content_svformat = NULL; nm_auto_free_gstring GString *route_content = NULL; nm_auto_free_gstring GString *route6_content = NULL; + gs_free char *interface_name = NULL; nm_assert(NM_IS_CONNECTION(connection)); nm_assert(_nm_connection_verify(connection, NULL) == NM_SETTING_VERIFY_SUCCESS); @@ -3413,7 +3433,7 @@ do_write_construct(NMConnection *connection, if (!write_wireless_setting(connection, ifcfg, secrets, &no_8021x, error)) return FALSE; } else if (!strcmp(type, NM_SETTING_INFINIBAND_SETTING_NAME)) { - if (!write_infiniband_setting(connection, ifcfg, error)) + if (!write_infiniband_setting(connection, ifcfg, &interface_name, error)) return FALSE; } else if (!strcmp(type, NM_SETTING_BOND_SETTING_NAME)) { if (!write_bond_setting(connection, ifcfg, &wired, error)) @@ -3518,7 +3538,7 @@ do_write_construct(NMConnection *connection, write_ip_routing_rules(connection, ifcfg, route_ignore); - write_connection_setting(s_con, ifcfg); + write_connection_setting(s_con, ifcfg, interface_name); NM_SET_OUT(out_ifcfg, g_steal_pointer(&ifcfg)); NM_SET_OUT(out_blobs, g_steal_pointer(&blobs)); diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband deleted file mode 100644 index 6c36f1de..00000000 --- a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband +++ /dev/null @@ -1,8 +0,0 @@ -TYPE=InfiniBand -DEVICE=ib0 -HWADDR=80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22 -CONNECTED_MODE=yes -MTU=65520 -IPADDR=192.168.2.2 -NETMASK=255.255.255.0 -GATEWAY=192.168.2.1 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband0 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband0 new file mode 100644 index 00000000..6c36f1de --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband0 @@ -0,0 +1,8 @@ +TYPE=InfiniBand +DEVICE=ib0 +HWADDR=80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22 +CONNECTED_MODE=yes +MTU=65520 +IPADDR=192.168.2.2 +NETMASK=255.255.255.0 +GATEWAY=192.168.2.1 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband1 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband1 new file mode 100644 index 00000000..dcb7758e --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband1 @@ -0,0 +1,12 @@ +TYPE=InfiniBand +HWADDR=80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22 +CONNECTED_MODE=yes +MTU=65520 +IPADDR=192.168.2.2 +NETMASK=255.255.255.0 +GATEWAY=192.168.2.1 + +DEVICE=ib0.80c1 +PKEY=yes +PKEY_ID=0x00c1 +PHYSDEV=ib0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband2 b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband2 new file mode 100644 index 00000000..2e6d9edf --- /dev/null +++ b/src/core/settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-infiniband2 @@ -0,0 +1,12 @@ +TYPE=InfiniBand +HWADDR=80:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff:00:11:22 +CONNECTED_MODE=yes +MTU=65520 +IPADDR=192.168.2.2 +NETMASK=255.255.255.0 +GATEWAY=192.168.2.1 + +DEVICE=ib0.00c1 +PKEY=yes +PKEY_ID=0x00c1 +PHYSDEV=ib0 diff --git a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 40ff7c67..8c1e9d94 100644 --- a/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/core/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -8352,6 +8352,7 @@ test_write_bond_port(void) s_bond_port = _nm_connection_new_setting(connection, NM_TYPE_SETTING_BOND_PORT); g_object_set(s_bond_port, NM_SETTING_BOND_PORT_QUEUE_ID, 1, NULL); + g_object_set(s_bond_port, NM_SETTING_BOND_PORT_PRIO, 10, NULL); nmtst_assert_connection_verifies(connection); @@ -8363,8 +8364,9 @@ test_write_bond_port(void) } static void -test_read_infiniband(void) +test_read_infiniband(gconstpointer test_data) { + const guint TEST_IDX = GPOINTER_TO_UINT(test_data); gs_unref_object NMConnection *connection = NULL; NMSettingInfiniband *s_infiniband; char *unmanaged = NULL; @@ -8373,11 +8375,15 @@ test_read_infiniband(void) 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22}; const char *transport_mode; + const char *test_files[] = { + TEST_IFCFG_DIR "/ifcfg-test-infiniband0", + TEST_IFCFG_DIR "/ifcfg-test-infiniband1", + TEST_IFCFG_DIR "/ifcfg-test-infiniband2", + }; - connection = _connection_from_file(TEST_IFCFG_DIR "/ifcfg-test-infiniband", - NULL, - TYPE_INFINIBAND, - &unmanaged); + g_assert(TEST_IDX < G_N_ELEMENTS(test_files)); + + connection = _connection_from_file(test_files[TEST_IDX], NULL, TYPE_INFINIBAND, &unmanaged); g_assert(!unmanaged); s_infiniband = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_INFINIBAND); @@ -8389,6 +8395,25 @@ test_read_infiniband(void) transport_mode = nm_setting_infiniband_get_transport_mode(s_infiniband); g_assert(transport_mode); g_assert_cmpstr(transport_mode, ==, "connected"); + + nmtst_assert_connection_verifies_without_normalization(connection); + + switch (TEST_IDX) { + case 0: + g_assert_cmpint(nm_setting_infiniband_get_p_key(s_infiniband), ==, -1); + g_assert_cmpstr(nm_setting_infiniband_get_parent(s_infiniband), ==, NULL); + g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "ib0"); + break; + case 1: + case 2: + g_assert_cmpint(nm_setting_infiniband_get_p_key(s_infiniband), ==, 0x80c1); + g_assert_cmpstr(nm_setting_infiniband_get_parent(s_infiniband), ==, "ib0"); + g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, "ib0.80c1"); + break; + default: + g_assert_not_reached(); + break; + } } static void @@ -8409,21 +8434,20 @@ test_read_ipoib(void) s_infiniband = nmtst_connection_assert_setting(connection, NM_TYPE_SETTING_INFINIBAND); pkey = nm_setting_infiniband_get_p_key(s_infiniband); - g_assert(pkey); - g_assert_cmpint(pkey, ==, 12); + g_assert_cmpint(pkey, ==, 0x800c); transport_mode = nm_setting_infiniband_get_transport_mode(s_infiniband); - g_assert(transport_mode); g_assert_cmpstr(transport_mode, ==, "connected"); } static void test_write_infiniband(gconstpointer test_data) { - const int TEST_IDX = GPOINTER_TO_INT(test_data); - nmtst_auto_unlinkfile char *testfile = NULL; - gs_unref_object NMConnection *connection = NULL; - gs_unref_object NMConnection *reread = NULL; + const int TEST_IDX = GPOINTER_TO_INT(test_data); + nmtst_auto_unlinkfile char *testfile = NULL; + gs_unref_object NMConnection *connection = NULL; + gs_unref_object NMConnection *reread = NULL; + gboolean reread_same = FALSE; NMSettingConnection *s_con; NMSettingInfiniband *s_infiniband; NMSettingIPConfig *s_ip4; @@ -8433,6 +8457,7 @@ test_write_infiniband(gconstpointer test_data) NMIPAddress *addr; GError *error = NULL; const char *interface_name = NULL; + int p_key; connection = nm_simple_connection_new(); @@ -8448,14 +8473,21 @@ test_write_infiniband(gconstpointer test_data) NM_SETTING_INFINIBAND_SETTING_NAME, NULL); - if (NM_IN_SET(TEST_IDX, 1, 3)) - interface_name = "ib0.000c"; + if (NM_IN_SET(TEST_IDX, 1, 2)) + p_key = nmtst_get_rand_bool() ? 0x000c : 0x800c; + else + p_key = -1; + + if (NM_IN_SET(TEST_IDX, 1, 3)) { + if (p_key >= 0x8000) + interface_name = "ib0.800c"; + } g_object_set(s_con, NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); s_infiniband = _nm_connection_new_setting(connection, NM_TYPE_SETTING_INFINIBAND); g_object_set(s_infiniband, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected", NULL); - if (NM_IN_SET(TEST_IDX, 1, 2)) { + if (p_key == -1) { g_object_set(s_infiniband, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, @@ -8465,7 +8497,7 @@ test_write_infiniband(gconstpointer test_data) } else { g_object_set(s_infiniband, NM_SETTING_INFINIBAND_P_KEY, - 12, + p_key, NM_SETTING_INFINIBAND_PARENT, "ib0", NULL); @@ -8494,13 +8526,20 @@ test_write_infiniband(gconstpointer test_data) nmtst_assert_connection_verifies(connection); - _writer_new_connection(connection, TEST_SCRATCH_DIR, &testfile); - - reread = _connection_from_file(testfile, NULL, TYPE_INFINIBAND, NULL); - - nmtst_assert_connection_equals(connection, TRUE, reread, FALSE); + _writer_new_connection_reread(connection, + TEST_SCRATCH_DIR, + &testfile, + NO_EXPECTED, + &reread, + &reread_same); + _assert_reread_same(connection, reread); + g_assert(reread_same); g_assert_cmpstr(interface_name, ==, nm_connection_get_interface_name(reread)); + g_assert_cmpint(nm_setting_infiniband_get_p_key( + _nm_connection_get_setting(reread, NM_TYPE_SETTING_INFINIBAND)), + ==, + p_key); } static void @@ -10672,7 +10711,9 @@ main(int argc, char **argv) g_test_add_func(TPATH "wifi/read/wep-no-keys", test_read_wifi_wep_no_keys); g_test_add_func(TPATH "wifi/read/wep-agent-keys", test_read_wifi_wep_agent_keys); - g_test_add_func(TPATH "infiniband/read", test_read_infiniband); + g_test_add_data_func(TPATH "infiniband/read/0", GUINT_TO_POINTER(0), test_read_infiniband); + g_test_add_data_func(TPATH "infiniband/read/1", GUINT_TO_POINTER(1), test_read_infiniband); + g_test_add_data_func(TPATH "infiniband/read/2", GUINT_TO_POINTER(2), test_read_infiniband); g_test_add_func(TPATH "ipoib/read", test_read_ipoib); g_test_add_func(TPATH "vlan/read", test_read_vlan_interface); g_test_add_func(TPATH "vlan/read-flags-1", test_read_vlan_flags_1); -- cgit 1.3.0-6-gf8a5