import CS hyperv-daemons-0-0.43.20190303git.el9
This commit is contained in:
parent
0c29d01ae0
commit
9ac5cf03eb
@ -0,0 +1,67 @@
|
||||
From 1df9596722c093afd097fd7a9689092a5cee7d2a Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Tue, 10 Oct 2023 11:50:30 +0530
|
||||
Subject: [PATCH 4/4] Changes for adding keyfile support in RHEL specific
|
||||
script
|
||||
|
||||
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||
RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile
|
||||
RH-Jira: RHEL-9902
|
||||
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [4/4] b60a8d644b0e777373c92f4778c3d4560f6f2642 (anisinha/centos-hyperv-daemons)
|
||||
|
||||
Some adjustments to the RHEL specific customization script in order to support
|
||||
Network Manager keyfiles. These changes were tested internally by Red Hat QE.
|
||||
These changes are mostly trivial and are not pushed upstream at this momemnt.
|
||||
|
||||
Jira: https://issues.redhat.com/browse/RHEL-9902
|
||||
|
||||
See also https://issues.redhat.com/browse/RHEL-14505
|
||||
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
---
|
||||
hv_set_ifconfig.sh | 25 ++++++++++++++-----------
|
||||
1 file changed, 14 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 9c2ee30..0bdf2bc 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -74,19 +74,22 @@
|
||||
# call.
|
||||
#
|
||||
|
||||
+# This is RHEL specific bash script that configures NM keyfiles.
|
||||
+# ifcfg files passed as the first argument to this script remains untouched.
|
||||
|
||||
+if [ -z "$2" ]; then
|
||||
+ echo "No input NM keyfile. Exiting!"
|
||||
+ exit 1
|
||||
+fi
|
||||
|
||||
-echo "IPV6INIT=yes" >> $1
|
||||
-echo "PEERDNS=yes" >> $1
|
||||
-echo "ONBOOT=yes" >> $1
|
||||
+sed -i '/\[ipv4\]/a ignore-auto-dns=false' $2
|
||||
+sed -i '/\[connection\]/a autoconnect=true' $2
|
||||
|
||||
-#Unlike older sysconfig scripts, NetworkManager expects GATEWAYx=ipaddr for all values of x.
|
||||
-#So the first gateway is GATEWAY0 instead of GATEWAY. Other values should remain unchanged.
|
||||
-#Workaround this by replacing GATEWAY= with GATEWAY0=.
|
||||
-sed -i "s/GATEWAY=/GATEWAY0=/" $1
|
||||
+filename="${2##*/}"
|
||||
+chmod 600 $2
|
||||
+cp $2 /etc/NetworkManager/system-connections/
|
||||
|
||||
-cp $1 /etc/sysconfig/network-scripts/
|
||||
+nmcli connection load "/etc/NetworkManager/system-connections/${filename}"
|
||||
+nmcli connection up filename "/etc/NetworkManager/system-connections/${filename}"
|
||||
|
||||
-filename="${1##*/}"
|
||||
-nmcli connection load "/etc/sysconfig/network-scripts/${filename}"
|
||||
-nmcli connection up filename "/etc/sysconfig/network-scripts/${filename}"
|
||||
+exit 0
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,335 @@
|
||||
From d252f80372544b9b7e060b90bf5c5b0ccf6093d6 Mon Sep 17 00:00:00 2001
|
||||
From: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Date: Fri, 22 Mar 2024 06:46:02 -0700
|
||||
Subject: [PATCH 3/4] hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for
|
||||
keyfile format
|
||||
|
||||
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||
RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile
|
||||
RH-Jira: RHEL-9902
|
||||
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [3/4] e164b6951b873467f8c87e0d01b1fd89326aa64e (anisinha/centos-hyperv-daemons)
|
||||
|
||||
If the network configuration strings are passed as a combination of IPv4
|
||||
and IPv6 addresses, the current KVP daemon does not handle processing for
|
||||
the keyfile configuration format.
|
||||
With these changes, the keyfile config generation logic scans through the
|
||||
list twice to generate IPv4 and IPv6 sections for the configuration files
|
||||
to handle this support.
|
||||
|
||||
Testcases ran:Rhel 9, Hyper-V VMs
|
||||
(IPv4 only, IPv6 only, IPv4 and IPv6 combination)
|
||||
|
||||
Cherry-picked from Linux kernel upstream commit
|
||||
f971f6dd3742d2 ("hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format")
|
||||
Co-developed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Reviewed-by: Easwar Hariharan <eahariha@linux.microsoft.com>
|
||||
Tested-by: Ani Sinha <anisinha@redhat.com>
|
||||
Reviewed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Link: https://lore.kernel.org/r/1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Message-ID: <1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com>
|
||||
---
|
||||
hv_kvp_daemon.c | 213 ++++++++++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 172 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 2f1862e..aa350d8 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -76,6 +76,12 @@ enum {
|
||||
DNS
|
||||
};
|
||||
|
||||
+enum {
|
||||
+ IPV4 = 1,
|
||||
+ IPV6,
|
||||
+ IP_TYPE_MAX
|
||||
+};
|
||||
+
|
||||
static int in_hand_shake;
|
||||
|
||||
static char *os_name = "";
|
||||
@@ -102,6 +108,11 @@ static struct utsname uts_buf;
|
||||
|
||||
#define MAX_FILE_NAME 100
|
||||
#define ENTRIES_PER_BLOCK 50
|
||||
+/*
|
||||
+ * Change this entry if the number of addresses increases in future
|
||||
+ */
|
||||
+#define MAX_IP_ENTRIES 64
|
||||
+#define OUTSTR_BUF_SIZE ((INET6_ADDRSTRLEN + 1) * MAX_IP_ENTRIES)
|
||||
|
||||
struct kvp_record {
|
||||
char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
|
||||
@@ -1171,6 +1182,18 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+int ip_version_check(const char *input_addr)
|
||||
+{
|
||||
+ struct in6_addr addr;
|
||||
+
|
||||
+ if (inet_pton(AF_INET, input_addr, &addr))
|
||||
+ return IPV4;
|
||||
+ else if (inet_pton(AF_INET6, input_addr, &addr))
|
||||
+ return IPV6;
|
||||
+
|
||||
+ return -EINVAL;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Only IPv4 subnet strings needs to be converted to plen
|
||||
* For IPv6 the subnet is already privided in plen format
|
||||
@@ -1197,14 +1220,75 @@ static int kvp_subnet_to_plen(char *subnet_addr_str)
|
||||
return plen;
|
||||
}
|
||||
|
||||
+static int process_dns_gateway_nm(FILE *f, char *ip_string, int type,
|
||||
+ int ip_sec)
|
||||
+{
|
||||
+ char addr[INET6_ADDRSTRLEN], *output_str;
|
||||
+ int ip_offset = 0, error = 0, ip_ver;
|
||||
+ char *param_name;
|
||||
+
|
||||
+ if (type == DNS)
|
||||
+ param_name = "dns";
|
||||
+ else if (type == GATEWAY)
|
||||
+ param_name = "gateway";
|
||||
+ else
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ output_str = (char *)calloc(OUTSTR_BUF_SIZE, sizeof(char));
|
||||
+ if (!output_str)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ while (1) {
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+
|
||||
+ if (!parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||
+ (MAX_IP_ADDR_SIZE * 2)))
|
||||
+ break;
|
||||
+
|
||||
+ ip_ver = ip_version_check(addr);
|
||||
+ if (ip_ver < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if ((ip_ver == IPV4 && ip_sec == IPV4) ||
|
||||
+ (ip_ver == IPV6 && ip_sec == IPV6)) {
|
||||
+ /*
|
||||
+ * do a bound check to avoid out-of bound writes
|
||||
+ */
|
||||
+ if ((OUTSTR_BUF_SIZE - strlen(output_str)) >
|
||||
+ (strlen(addr) + 1)) {
|
||||
+ strncat(output_str, addr,
|
||||
+ OUTSTR_BUF_SIZE -
|
||||
+ strlen(output_str) - 1);
|
||||
+ strncat(output_str, ",",
|
||||
+ OUTSTR_BUF_SIZE -
|
||||
+ strlen(output_str) - 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (strlen(output_str)) {
|
||||
+ /*
|
||||
+ * This is to get rid of that extra comma character
|
||||
+ * in the end of the string
|
||||
+ */
|
||||
+ output_str[strlen(output_str) - 1] = '\0';
|
||||
+ error = fprintf(f, "%s=%s\n", param_name, output_str);
|
||||
+ }
|
||||
+
|
||||
+ free(output_str);
|
||||
+ return error;
|
||||
+}
|
||||
+
|
||||
static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
- int is_ipv6)
|
||||
+ int ip_sec)
|
||||
{
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
char subnet_addr[INET6_ADDRSTRLEN];
|
||||
- int error, i = 0;
|
||||
+ int error = 0, i = 0;
|
||||
int ip_offset = 0, subnet_offset = 0;
|
||||
- int plen;
|
||||
+ int plen, ip_ver;
|
||||
|
||||
memset(addr, 0, sizeof(addr));
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
@@ -1216,10 +1300,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
subnet_addr,
|
||||
(MAX_IP_ADDR_SIZE *
|
||||
2))) {
|
||||
- if (!is_ipv6)
|
||||
+ ip_ver = ip_version_check(addr);
|
||||
+ if (ip_ver < 0)
|
||||
+ continue;
|
||||
+
|
||||
+ if (ip_ver == IPV4 && ip_sec == IPV4)
|
||||
plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||
- else
|
||||
+ else if (ip_ver == IPV6 && ip_sec == IPV6)
|
||||
plen = atoi(subnet_addr);
|
||||
+ else
|
||||
+ continue;
|
||||
|
||||
if (plen < 0)
|
||||
return plen;
|
||||
@@ -1233,17 +1323,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return error;
|
||||
}
|
||||
|
||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
{
|
||||
- int error = 0;
|
||||
+ int error = 0, ip_ver;
|
||||
char if_filename[PATH_MAX];
|
||||
char nm_filename[PATH_MAX];
|
||||
FILE *ifcfg_file, *nmfile;
|
||||
char cmd[PATH_MAX];
|
||||
- int is_ipv6 = 0;
|
||||
char *mac_addr;
|
||||
int str_len;
|
||||
|
||||
@@ -1421,52 +1510,94 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- if (new_val->addr_family & ADDR_FAMILY_IPV6) {
|
||||
- error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- is_ipv6 = 1;
|
||||
- } else {
|
||||
- error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Now we populate the keyfile format
|
||||
+ *
|
||||
+ * The keyfile format expects the IPv6 and IPv4 configuration in
|
||||
+ * different sections. Therefore we iterate through the list twice,
|
||||
+ * once to populate the IPv4 section and the next time for IPv6
|
||||
*/
|
||||
+ ip_ver = IPV4;
|
||||
+ do {
|
||||
+ if (ip_ver == IPV4) {
|
||||
+ error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
|
||||
- if (new_val->dhcp_enabled) {
|
||||
- error = kvp_write_file(nmfile, "method", "", "auto");
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
- } else {
|
||||
- error = kvp_write_file(nmfile, "method", "", "manual");
|
||||
+ /*
|
||||
+ * Write the configuration for ipaddress, netmask, gateway and
|
||||
+ * name services
|
||||
+ */
|
||||
+ error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
+ (char *)new_val->sub_net,
|
||||
+ ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
|
||||
- /*
|
||||
- * Write the configuration for ipaddress, netmask, gateway and
|
||||
- * name services
|
||||
- */
|
||||
- error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
- (char *)new_val->sub_net, is_ipv6);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
+ /*
|
||||
+ * As dhcp_enabled is only valid for ipv4, we do not set dhcp
|
||||
+ * methods for ipv6 based on dhcp_enabled flag.
|
||||
+ *
|
||||
+ * For ipv4, set method to manual only when dhcp_enabled is
|
||||
+ * false and specific ipv4 addresses are configured. If neither
|
||||
+ * dhcp_enabled is true and no ipv4 addresses are configured,
|
||||
+ * set method to 'disabled'.
|
||||
+ *
|
||||
+ * For ipv6, set method to manual when we configure ipv6
|
||||
+ * addresses. Otherwise set method to 'auto' so that SLAAC from
|
||||
+ * RA may be used.
|
||||
+ */
|
||||
+ if (ip_ver == IPV4) {
|
||||
+ if (new_val->dhcp_enabled) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else if (error) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "disabled");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+ } else if (ip_ver == IPV6) {
|
||||
+ if (error) {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "",
|
||||
+ "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- /* we do not want ipv4 addresses in ipv6 section and vice versa */
|
||||
- if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
|
||||
- error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ error = process_dns_gateway_nm(nmfile,
|
||||
+ (char *)new_val->gate_way,
|
||||
+ GATEWAY, ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
|
||||
- if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
|
||||
- error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ error = process_dns_gateway_nm(nmfile,
|
||||
+ (char *)new_val->dns_addr, DNS,
|
||||
+ ip_ver);
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
- }
|
||||
+
|
||||
+ ip_ver++;
|
||||
+ } while (ip_ver < IP_TYPE_MAX);
|
||||
+
|
||||
fclose(nmfile);
|
||||
fclose(ifcfg_file);
|
||||
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,100 @@
|
||||
From 61d2686d4b36e5a9099d80131044807f69142249 Mon Sep 17 00:00:00 2001
|
||||
From: Ani Sinha <anisinha@redhat.com>
|
||||
Date: Mon, 16 Oct 2023 19:03:33 +0530
|
||||
Subject: [PATCH 2/4] hv/hv_kvp_daemon: Some small fixes for handling NM
|
||||
keyfiles
|
||||
|
||||
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||
RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile
|
||||
RH-Jira: RHEL-9902
|
||||
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [2/4] 1676c48ed1f2d91dd1f8c43f6c8009e3bebf295a (anisinha/centos-hyperv-daemons)
|
||||
|
||||
Some small fixes:
|
||||
- lets make sure we are not adding ipv4 addresses in ipv6 section in
|
||||
keyfile and vice versa.
|
||||
- ADDR_FAMILY_IPV6 is a bit in addr_family. Test that bit instead of
|
||||
checking the whole value of addr_family.
|
||||
- Some trivial fixes in hv_set_ifconfig.sh.
|
||||
|
||||
These fixes are proposed after doing some internal testing at Red Hat.
|
||||
|
||||
Cherry-picked from upstream linux
|
||||
kernel commit c3803203bc5ec910a ("hv/hv_kvp_daemon: Some small fixes for handling NM keyfiles")
|
||||
CC: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
CC: Saurabh Sengar <ssengar@linux.microsoft.com>
|
||||
Fixes: 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile")
|
||||
Signed-off-by: Ani Sinha <anisinha@redhat.com>
|
||||
Reviewed-by: Shradha Gupta <Shradhagupta@linux.microsoft.com>
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Message-ID: <20231016133122.2419537-1-anisinha@redhat.com>
|
||||
---
|
||||
hv_kvp_daemon.c | 20 ++++++++++++--------
|
||||
hv_set_ifconfig.sh | 4 ++--
|
||||
2 files changed, 14 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index d50b4e8..2f1862e 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -1421,7 +1421,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- if (new_val->addr_family == ADDR_FAMILY_IPV6) {
|
||||
+ if (new_val->addr_family & ADDR_FAMILY_IPV6) {
|
||||
error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
@@ -1455,14 +1455,18 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
if (error < 0)
|
||||
goto setval_error;
|
||||
|
||||
- error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
-
|
||||
- error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
- if (error < 0)
|
||||
- goto setval_error;
|
||||
+ /* we do not want ipv4 addresses in ipv6 section and vice versa */
|
||||
+ if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) {
|
||||
+ error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
|
||||
+ if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) {
|
||||
+ error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
fclose(nmfile);
|
||||
fclose(ifcfg_file);
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index 35aae6f..9c2ee30 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -53,7 +53,7 @@
|
||||
# or "manual" if no boot-time protocol should be used)
|
||||
#
|
||||
# address1=ipaddr1/plen
|
||||
-# address=ipaddr2/plen
|
||||
+# address2=ipaddr2/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
@@ -61,7 +61,7 @@
|
||||
#
|
||||
# [ipv6]
|
||||
# address1=ipaddr1/plen
|
||||
-# address2=ipaddr1/plen
|
||||
+# address2=ipaddr2/plen
|
||||
#
|
||||
# gateway=gateway1;gateway2
|
||||
#
|
||||
--
|
||||
2.39.3
|
||||
|
@ -0,0 +1,426 @@
|
||||
From 626a1af79f67bd9150dd6ff496d0dbbfb93bc320 Mon Sep 17 00:00:00 2001
|
||||
From: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Date: Mon, 9 Oct 2023 03:38:40 -0700
|
||||
Subject: [PATCH 1/4] hv/hv_kvp_daemon:Support for keyfile based connection
|
||||
profile
|
||||
|
||||
RH-Author: Ani Sinha <anisinha@redhat.com>
|
||||
RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile
|
||||
RH-Jira: RHEL-9902
|
||||
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
||||
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
||||
RH-Commit: [1/4] 0cb079b0cc30bef47bddd193e262dfa52b7f2874 (anisinha/centos-hyperv-daemons)
|
||||
|
||||
Ifcfg config file support in NetworkManger is deprecated. This patch
|
||||
provides support for the new keyfile config format for connection
|
||||
profiles in NetworkManager. The patch modifies the hv_kvp_daemon code
|
||||
to generate the new network configuration in keyfile
|
||||
format(.ini-style format) along with a ifcfg format configuration.
|
||||
The ifcfg format configuration is also retained to support easy
|
||||
backward compatibility for distro vendors. These configurations are
|
||||
stored in temp files which are further translated using the
|
||||
hv_set_ifconfig.sh script. This script is implemented by individual
|
||||
distros based on the network management commands supported.
|
||||
For example, RHEL's implementation could be found here:
|
||||
https://gitlab.com/redhat/centos-stream/src/hyperv-daemons/-/blob/c9s/hv_set_ifconfig.sh
|
||||
Debian's implementation could be found here:
|
||||
https://github.com/endlessm/linux/blob/master/debian/cloud-tools/hv_set_ifconfig
|
||||
|
||||
The next part of this support is to let the Distro vendors consume
|
||||
these modified implementations to the new configuration format.
|
||||
|
||||
Cherry-picked from upstream linux
|
||||
kernel commit 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile")
|
||||
Tested-on: Rhel9(Hyper-V, Azure)(nm and ifcfg files verified)
|
||||
Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
|
||||
Reviewed-by: Saurabh Sengar <ssengar@linux.microsoft.com>
|
||||
Reviewed-by: Ani Sinha <anisinha@redhat.com>
|
||||
Signed-off-by: Wei Liu <wei.liu@kernel.org>
|
||||
Link: https://lore.kernel.org/r/1696847920-31125-1-git-send-email-shradhagupta@linux.microsoft.com
|
||||
---
|
||||
hv_kvp_daemon.c | 233 +++++++++++++++++++++++++++++++++++++++------
|
||||
hv_set_ifconfig.sh | 30 +++++-
|
||||
2 files changed, 230 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/hv_kvp_daemon.c b/hv_kvp_daemon.c
|
||||
index 2ad9af3..d50b4e8 100644
|
||||
--- a/hv_kvp_daemon.c
|
||||
+++ b/hv_kvp_daemon.c
|
||||
@@ -1171,12 +1171,79 @@ static int process_ip_string(FILE *f, char *ip_string, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Only IPv4 subnet strings needs to be converted to plen
|
||||
+ * For IPv6 the subnet is already privided in plen format
|
||||
+ */
|
||||
+static int kvp_subnet_to_plen(char *subnet_addr_str)
|
||||
+{
|
||||
+ int plen = 0;
|
||||
+ struct in_addr subnet_addr4;
|
||||
+
|
||||
+ /*
|
||||
+ * Convert subnet address to binary representation
|
||||
+ */
|
||||
+ if (inet_pton(AF_INET, subnet_addr_str, &subnet_addr4) == 1) {
|
||||
+ uint32_t subnet_mask = ntohl(subnet_addr4.s_addr);
|
||||
+
|
||||
+ while (subnet_mask & 0x80000000) {
|
||||
+ plen++;
|
||||
+ subnet_mask <<= 1;
|
||||
+ }
|
||||
+ } else {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return plen;
|
||||
+}
|
||||
+
|
||||
+static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet,
|
||||
+ int is_ipv6)
|
||||
+{
|
||||
+ char addr[INET6_ADDRSTRLEN];
|
||||
+ char subnet_addr[INET6_ADDRSTRLEN];
|
||||
+ int error, i = 0;
|
||||
+ int ip_offset = 0, subnet_offset = 0;
|
||||
+ int plen;
|
||||
+
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+ memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
+
|
||||
+ while (parse_ip_val_buffer(ip_string, &ip_offset, addr,
|
||||
+ (MAX_IP_ADDR_SIZE * 2)) &&
|
||||
+ parse_ip_val_buffer(subnet,
|
||||
+ &subnet_offset,
|
||||
+ subnet_addr,
|
||||
+ (MAX_IP_ADDR_SIZE *
|
||||
+ 2))) {
|
||||
+ if (!is_ipv6)
|
||||
+ plen = kvp_subnet_to_plen((char *)subnet_addr);
|
||||
+ else
|
||||
+ plen = atoi(subnet_addr);
|
||||
+
|
||||
+ if (plen < 0)
|
||||
+ return plen;
|
||||
+
|
||||
+ error = fprintf(f, "address%d=%s/%d\n", ++i, (char *)addr,
|
||||
+ plen);
|
||||
+ if (error < 0)
|
||||
+ return error;
|
||||
+
|
||||
+ memset(addr, 0, sizeof(addr));
|
||||
+ memset(subnet_addr, 0, sizeof(subnet_addr));
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
{
|
||||
int error = 0;
|
||||
- char if_file[PATH_MAX];
|
||||
- FILE *file;
|
||||
+ char if_filename[PATH_MAX];
|
||||
+ char nm_filename[PATH_MAX];
|
||||
+ FILE *ifcfg_file, *nmfile;
|
||||
char cmd[PATH_MAX];
|
||||
+ int is_ipv6 = 0;
|
||||
char *mac_addr;
|
||||
int str_len;
|
||||
|
||||
@@ -1197,7 +1264,7 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* in a given distro to configure the interface and so are free
|
||||
* ignore information that may not be relevant.
|
||||
*
|
||||
- * Here is the format of the ip configuration file:
|
||||
+ * Here is the ifcfg format of the ip configuration file:
|
||||
*
|
||||
* HWADDR=macaddr
|
||||
* DEVICE=interface name
|
||||
@@ -1220,6 +1287,32 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
* IPV6NETMASK.
|
||||
*
|
||||
+ * Here is the keyfile format of the ip configuration file:
|
||||
+ *
|
||||
+ * [ethernet]
|
||||
+ * mac-address=macaddr
|
||||
+ * [connection]
|
||||
+ * interface-name=interface name
|
||||
+ *
|
||||
+ * [ipv4]
|
||||
+ * method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
+ * or "manual" if no boot-time protocol should be used)
|
||||
+ *
|
||||
+ * address1=ipaddr1/plen
|
||||
+ * address2=ipaddr2/plen
|
||||
+ *
|
||||
+ * gateway=gateway1;gateway2
|
||||
+ *
|
||||
+ * dns=dns1;dns2
|
||||
+ *
|
||||
+ * [ipv6]
|
||||
+ * address1=ipaddr1/plen
|
||||
+ * address2=ipaddr2/plen
|
||||
+ *
|
||||
+ * gateway=gateway1;gateway2
|
||||
+ *
|
||||
+ * dns=dns1;dns2
|
||||
+ *
|
||||
* The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
* configured for the interface. Furthermore, the configuration
|
||||
* needs to be persistent. A subsequent GET call on the interface
|
||||
@@ -1227,14 +1320,29 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* call.
|
||||
*/
|
||||
|
||||
- snprintf(if_file, sizeof(if_file), "%s%s%s", KVP_CONFIG_LOC,
|
||||
- "/ifcfg-", if_name);
|
||||
+ /*
|
||||
+ * We are populating both ifcfg and nmconnection files
|
||||
+ */
|
||||
+ snprintf(if_filename, sizeof(if_filename), "%s%s%s", KVP_CONFIG_LOC,
|
||||
+ "/ifcfg-", if_name);
|
||||
|
||||
- file = fopen(if_file, "w");
|
||||
+ ifcfg_file = fopen(if_filename, "w");
|
||||
|
||||
- if (file == NULL) {
|
||||
+ if (!ifcfg_file) {
|
||||
syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
- errno, strerror(errno));
|
||||
+ errno, strerror(errno));
|
||||
+ return HV_E_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ snprintf(nm_filename, sizeof(nm_filename), "%s%s%s%s", KVP_CONFIG_LOC,
|
||||
+ "/", if_name, ".nmconnection");
|
||||
+
|
||||
+ nmfile = fopen(nm_filename, "w");
|
||||
+
|
||||
+ if (!nmfile) {
|
||||
+ syslog(LOG_ERR, "Failed to open config file; error: %d %s",
|
||||
+ errno, strerror(errno));
|
||||
+ fclose(ifcfg_file);
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
|
||||
@@ -1248,14 +1356,31 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
- error = kvp_write_file(file, "HWADDR", "", mac_addr);
|
||||
- free(mac_addr);
|
||||
+ error = kvp_write_file(ifcfg_file, "HWADDR", "", mac_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(ifcfg_file, "DEVICE", "", if_name);
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "\n[connection]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(nmfile, "interface-name", "", if_name);
|
||||
if (error)
|
||||
- goto setval_error;
|
||||
+ goto setmac_error;
|
||||
|
||||
- error = kvp_write_file(file, "DEVICE", "", if_name);
|
||||
+ error = fprintf(nmfile, "\n[ethernet]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ error = kvp_write_file(nmfile, "mac-address", "", mac_addr);
|
||||
if (error)
|
||||
- goto setval_error;
|
||||
+ goto setmac_error;
|
||||
+
|
||||
+ free(mac_addr);
|
||||
|
||||
/*
|
||||
* The dhcp_enabled flag is only for IPv4. In the case the host only
|
||||
@@ -1263,47 +1388,91 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
* proceed to parse and pass the IPv6 information to the
|
||||
* disto-specific script hv_set_ifconfig.
|
||||
*/
|
||||
+
|
||||
+ /*
|
||||
+ * First populate the ifcfg file format
|
||||
+ */
|
||||
if (new_val->dhcp_enabled) {
|
||||
- error = kvp_write_file(file, "BOOTPROTO", "", "dhcp");
|
||||
+ error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "dhcp");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
-
|
||||
} else {
|
||||
- error = kvp_write_file(file, "BOOTPROTO", "", "none");
|
||||
+ error = kvp_write_file(ifcfg_file, "BOOTPROTO", "", "none");
|
||||
if (error)
|
||||
goto setval_error;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * Write the configuration for ipaddress, netmask, gateway and
|
||||
- * name servers.
|
||||
- */
|
||||
-
|
||||
- error = process_ip_string(file, (char *)new_val->ip_addr, IPADDR);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->ip_addr,
|
||||
+ IPADDR);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->sub_net, NETMASK);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->sub_net,
|
||||
+ NETMASK);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->gate_way, GATEWAY);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->gate_way,
|
||||
+ GATEWAY);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- error = process_ip_string(file, (char *)new_val->dns_addr, DNS);
|
||||
+ error = process_ip_string(ifcfg_file, (char *)new_val->dns_addr, DNS);
|
||||
if (error)
|
||||
goto setval_error;
|
||||
|
||||
- fclose(file);
|
||||
+ if (new_val->addr_family == ADDR_FAMILY_IPV6) {
|
||||
+ error = fprintf(nmfile, "\n[ipv6]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ is_ipv6 = 1;
|
||||
+ } else {
|
||||
+ error = fprintf(nmfile, "\n[ipv4]\n");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Now we populate the keyfile format
|
||||
+ */
|
||||
+
|
||||
+ if (new_val->dhcp_enabled) {
|
||||
+ error = kvp_write_file(nmfile, "method", "", "auto");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ } else {
|
||||
+ error = kvp_write_file(nmfile, "method", "", "manual");
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Write the configuration for ipaddress, netmask, gateway and
|
||||
+ * name services
|
||||
+ */
|
||||
+ error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr,
|
||||
+ (char *)new_val->sub_net, is_ipv6);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr);
|
||||
+ if (error < 0)
|
||||
+ goto setval_error;
|
||||
+
|
||||
+ fclose(nmfile);
|
||||
+ fclose(ifcfg_file);
|
||||
|
||||
/*
|
||||
* Now that we have populated the configuration file,
|
||||
* invoke the external script to do its magic.
|
||||
*/
|
||||
|
||||
- str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
|
||||
- "hv_set_ifconfig", if_file);
|
||||
+ str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s",
|
||||
+ "hv_set_ifconfig", if_filename, nm_filename);
|
||||
/*
|
||||
* This is a little overcautious, but it's necessary to suppress some
|
||||
* false warnings from gcc 8.0.1.
|
||||
@@ -1316,14 +1485,16 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
|
||||
|
||||
if (system(cmd)) {
|
||||
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
|
||||
- cmd, errno, strerror(errno));
|
||||
+ cmd, errno, strerror(errno));
|
||||
return HV_E_FAIL;
|
||||
}
|
||||
return 0;
|
||||
-
|
||||
+setmac_error:
|
||||
+ free(mac_addr);
|
||||
setval_error:
|
||||
syslog(LOG_ERR, "Failed to write config file");
|
||||
- fclose(file);
|
||||
+ fclose(ifcfg_file);
|
||||
+ fclose(nmfile);
|
||||
return error;
|
||||
}
|
||||
|
||||
diff --git a/hv_set_ifconfig.sh b/hv_set_ifconfig.sh
|
||||
index fe7fccf..35aae6f 100644
|
||||
--- a/hv_set_ifconfig.sh
|
||||
+++ b/hv_set_ifconfig.sh
|
||||
@@ -18,12 +18,12 @@
|
||||
#
|
||||
# This example script is based on a RHEL environment.
|
||||
#
|
||||
-# Here is the format of the ip configuration file:
|
||||
+# Here is the ifcfg format of the ip configuration file:
|
||||
#
|
||||
# HWADDR=macaddr
|
||||
# DEVICE=interface name
|
||||
# BOOTPROTO=<protocol> (where <protocol> is "dhcp" if DHCP is configured
|
||||
-# or "none" if no boot-time protocol should be used)
|
||||
+# or "none" if no boot-time protocol should be used)
|
||||
#
|
||||
# IPADDR0=ipaddr1
|
||||
# IPADDR1=ipaddr2
|
||||
@@ -41,6 +41,32 @@
|
||||
# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as
|
||||
# IPV6NETMASK.
|
||||
#
|
||||
+# Here is the keyfile format of the ip configuration file:
|
||||
+#
|
||||
+# [ethernet]
|
||||
+# mac-address=macaddr
|
||||
+# [connection]
|
||||
+# interface-name=interface name
|
||||
+#
|
||||
+# [ipv4]
|
||||
+# method=<protocol> (where <protocol> is "auto" if DHCP is configured
|
||||
+# or "manual" if no boot-time protocol should be used)
|
||||
+#
|
||||
+# address1=ipaddr1/plen
|
||||
+# address=ipaddr2/plen
|
||||
+#
|
||||
+# gateway=gateway1;gateway2
|
||||
+#
|
||||
+# dns=dns1;
|
||||
+#
|
||||
+# [ipv6]
|
||||
+# address1=ipaddr1/plen
|
||||
+# address2=ipaddr1/plen
|
||||
+#
|
||||
+# gateway=gateway1;gateway2
|
||||
+#
|
||||
+# dns=dns1;dns2
|
||||
+#
|
||||
# The host can specify multiple ipv4 and ipv6 addresses to be
|
||||
# configured for the interface. Furthermore, the configuration
|
||||
# needs to be persistent. A subsequent GET call on the interface
|
||||
--
|
||||
2.39.3
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
Name: hyperv-daemons
|
||||
Version: 0
|
||||
Release: 0.42%{?snapver}%{?dist}
|
||||
Release: 0.43%{?snapver}%{?dist}
|
||||
Summary: Hyper-V daemons suite
|
||||
|
||||
License: GPLv2
|
||||
@ -60,6 +60,14 @@ Patch10: hpvd-tools-hv-Remove-an-extraneous-the.patch
|
||||
Patch11: hpvd-tools-hv-kvp-remove-unnecessary-void-conversions.patch
|
||||
# For bz#2218931 - [Hyper-V] [RHEL-9] /usr/sbin/vmbus_testing python script prints: "SyntaxWarning: "is" with a literal."
|
||||
Patch12: hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch
|
||||
# For RHEL-9902 - [Hyper-V][RHEL-9] hyperv-daemons write incompatible IPv6 prefix (IPV6NETMASK) in ifcfg
|
||||
Patch13: hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch
|
||||
# For RHEL-9902 - [Hyper-V][RHEL-9] hyperv-daemons write incompatible IPv6 prefix (IPV6NETMASK) in ifcfg
|
||||
Patch14: hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch
|
||||
# For RHEL-9902 - [Hyper-V][RHEL-9] hyperv-daemons write incompatible IPv6 prefix (IPV6NETMASK) in ifcfg
|
||||
Patch15: hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch
|
||||
# For RHEL-9902 - [Hyper-V][RHEL-9] hyperv-daemons write incompatible IPv6 prefix (IPV6NETMASK) in ifcfg
|
||||
Patch16: hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch
|
||||
|
||||
# Source-git patches
|
||||
|
||||
@ -171,6 +179,10 @@ cp -pvL %{SOURCE301} lsvmbus
|
||||
%patch10 -p1
|
||||
%patch11 -p1
|
||||
%patch12 -p1
|
||||
%patch13 -p1
|
||||
%patch14 -p1
|
||||
%patch15 -p1
|
||||
%patch16 -p1
|
||||
|
||||
%build
|
||||
# HYPERV KVP DAEMON
|
||||
@ -288,6 +300,14 @@ fi
|
||||
%{_sbindir}/vmbus_testing
|
||||
|
||||
%changelog
|
||||
* Thu Apr 25 2024 Miroslav Rezanina <mrezanin@redhat.com> - 0-0.43.20190303git
|
||||
- hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch [RHEL-9902]
|
||||
- hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch [RHEL-9902]
|
||||
- hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch [RHEL-9902]
|
||||
- hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch [RHEL-9902]
|
||||
- Resolves: RHEL-9902
|
||||
([Hyper-V][RHEL-9] hyperv-daemons write incompatible IPv6 prefix (IPV6NETMASK) in ifcfg)
|
||||
|
||||
* Mon Jul 10 2023 Miroslav Rezanina <mrezanin@redhat.com> - 0-0.42.20190303git
|
||||
- hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch [bz#2218931]
|
||||
- Resolves: bz#2218931
|
||||
|
Loading…
Reference in New Issue
Block a user