From 279384c196518b305293a00d252f230f34eae803 Mon Sep 17 00:00:00 2001 From: Miroslav Rezanina Date: Thu, 25 Apr 2024 01:47:02 -0400 Subject: [PATCH] * Thu Apr 25 2024 Miroslav Rezanina - 0-0.43.20190303git --- .hyperv-daemons.metadata | 8 + ...ng-keyfile-support-in-RHEL-specific-.patch | 67 +++ ...-Handle-IPv4-and-Ipv6-combination-fo.patch | 335 ++++++++++++++ ...-Some-small-fixes-for-handling-NM-ke.patch | 100 ++++ ...-Support-for-keyfile-based-connectio.patch | 426 ++++++++++++++++++ hyperv-daemons.spec | 22 +- 6 files changed, 957 insertions(+), 1 deletion(-) create mode 100644 .hyperv-daemons.metadata create mode 100644 hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch create mode 100644 hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch create mode 100644 hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch create mode 100644 hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch diff --git a/.hyperv-daemons.metadata b/.hyperv-daemons.metadata new file mode 100644 index 0000000..6120857 --- /dev/null +++ b/.hyperv-daemons.metadata @@ -0,0 +1,8 @@ +2cd98103a543d28c03d5709ec1b95dd39eae389b hv_get_dhcp_info.sh +dc29a44d5c965f0a76b94aafbd721c341ba0ad11 hv_get_dns_info.sh +d49974d222b1b0b939f8c5c1845be20c7b48edd7 hv_kvp_daemon.c +f2dca28c84e2616f32f30707218b43d56dd10957 hv_set_ifconfig.sh +0ad7fed7a159efdd68a2bce3722dcc34157252cb hv_vss_daemon.c +b8d0b62d5b3eba8ed873d4287d2fb51739be6984 hv_fcopy_daemon.c +d3c00f9396c6d0277727cec522ff6ad1ea0bc2da COPYING +618fe2e15962cc1f0d3a60c25170a164abf23048 lsvmbus diff --git a/hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch b/hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch new file mode 100644 index 0000000..46b6543 --- /dev/null +++ b/hpvd-Changes-for-adding-keyfile-support-in-RHEL-specific-.patch @@ -0,0 +1,67 @@ +From 1df9596722c093afd097fd7a9689092a5cee7d2a Mon Sep 17 00:00:00 2001 +From: Ani Sinha +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 +RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile +RH-Jira: RHEL-9902 +RH-Acked-by: Cathy Avery +RH-Acked-by: Miroslav Rezanina +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 +--- + 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 + diff --git a/hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch b/hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch new file mode 100644 index 0000000..80c8394 --- /dev/null +++ b/hpvd-hv-hv_kvp_daemon-Handle-IPv4-and-Ipv6-combination-fo.patch @@ -0,0 +1,335 @@ +From d252f80372544b9b7e060b90bf5c5b0ccf6093d6 Mon Sep 17 00:00:00 2001 +From: Shradha Gupta +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 +RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile +RH-Jira: RHEL-9902 +RH-Acked-by: Cathy Avery +RH-Acked-by: Miroslav Rezanina +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 +Signed-off-by: Ani Sinha +Signed-off-by: Shradha Gupta +Reviewed-by: Easwar Hariharan +Tested-by: Ani Sinha +Reviewed-by: Ani Sinha +Link: https://lore.kernel.org/r/1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com +Signed-off-by: Wei Liu +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 + diff --git a/hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch b/hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch new file mode 100644 index 0000000..80dfc97 --- /dev/null +++ b/hpvd-hv-hv_kvp_daemon-Some-small-fixes-for-handling-NM-ke.patch @@ -0,0 +1,100 @@ +From 61d2686d4b36e5a9099d80131044807f69142249 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +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 +RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile +RH-Jira: RHEL-9902 +RH-Acked-by: Cathy Avery +RH-Acked-by: Miroslav Rezanina +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 +CC: Saurabh Sengar +Fixes: 42999c904612 ("hv/hv_kvp_daemon:Support for keyfile based connection profile") +Signed-off-by: Ani Sinha +Reviewed-by: Shradha Gupta +Signed-off-by: Wei Liu +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 + diff --git a/hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch b/hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch new file mode 100644 index 0000000..1bbad06 --- /dev/null +++ b/hpvd-hv-hv_kvp_daemon-Support-for-keyfile-based-connectio.patch @@ -0,0 +1,426 @@ +From 626a1af79f67bd9150dd6ff496d0dbbfb93bc320 Mon Sep 17 00:00:00 2001 +From: Shradha Gupta +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 +RH-MergeRequest: 8: hv/hv_kvp_daemon:Support for keyfile based connection profile +RH-Jira: RHEL-9902 +RH-Acked-by: Cathy Avery +RH-Acked-by: Miroslav Rezanina +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 +Reviewed-by: Saurabh Sengar +Reviewed-by: Ani Sinha +Signed-off-by: Wei Liu +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= (where 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= (where 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= (where 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 + diff --git a/hyperv-daemons.spec b/hyperv-daemons.spec index 41ea4eb..b1396dd 100644 --- a/hyperv-daemons.spec +++ b/hyperv-daemons.spec @@ -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 - 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 - 0-0.42.20190303git - hpvd-vmbus_testing-fix-wrong-python-syntax-for-integer-va.patch [bz#2218931] - Resolves: bz#2218931