Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package hyper-v for openSUSE:Factory checked in at 2025-06-20 16:48:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hyper-v (Old) and /work/SRC/openSUSE:Factory/.hyper-v.new.31170 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hyper-v" Fri Jun 20 16:48:29 2025 rev:48 rq:1286999 version:9 Changes: -------- --- /work/SRC/openSUSE:Factory/hyper-v/hyper-v.changes 2025-01-09 15:06:32.266056761 +0100 +++ /work/SRC/openSUSE:Factory/.hyper-v.new.31170/hyper-v.changes 2025-06-20 16:48:54.847032591 +0200 @@ -1,0 +2,5 @@ +Fri Jun 6 06:06:06 UTC 2025 - oher...@suse.de + +- Enable debug logs for hv_kvp_daemon (a9c0b33e) (bsc#1244154) + +------------------------------------------------------------------- @@ -4 +9 @@ -- update route parsing in kvp daemon +- update route parsing in kvp daemon (9bbb8a07) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hyper-v.compare-with-upstream.sh ++++++ --- /var/tmp/diff_new_pack.4lmaiE/_old 2025-06-20 16:48:57.467140843 +0200 +++ /var/tmp/diff_new_pack.4lmaiE/_new 2025-06-20 16:48:57.515142826 +0200 @@ -1,7 +1,7 @@ -d=~/work/src/kernel/kerncvs.kernel.master +d=~/work/src/kernel/kerncvs.kernel.git diff -u hyper-v.tools.hv.hv_vss_daemon.c ${d}/tools/hv/hv_vss_daemon.c diff -u hyper-v.tools.hv.hv_kvp_daemon.c ${d}/tools/hv/hv_kvp_daemon.c -diff -u hyper-v.tools.hv.hv_fcopy_daemon.c ${d}/tools/hv/hv_fcopy_daemon.c +diff -u hyper-v.tools.hv.hv_fcopy_uio_daemon.c ${d}/tools/hv/hv_fcopy_uio_daemon.c diff -u hyper-v.include.linux.hyperv.h ${d}/include/uapi/linux/hyperv.h diff -u hyper-v.lsvmbus.py ${d}/tools/hv/lsvmbus ++++++ hyper-v.kvp.gethostname.patch ++++++ --- /var/tmp/diff_new_pack.4lmaiE/_old 2025-06-20 16:48:57.707150758 +0200 +++ /var/tmp/diff_new_pack.4lmaiE/_new 2025-06-20 16:48:57.743152246 +0200 @@ -1,131 +1,5 @@ --- a/hyper-v.tools.hv.hv_kvp_daemon.c +++ b/hyper-v.tools.hv.hv_kvp_daemon.c -@@ -24,6 +24,7 @@ - - #include <sys/poll.h> - #include <sys/utsname.h> -+#include <stdbool.h> - #include <stdio.h> - #include <stdlib.h> - #include <unistd.h> -@@ -677,6 +678,83 @@ static void kvp_process_ipconfig_file(ch - pclose(file); - } - -+static bool kvp_verify_ip_address(void *address_string) -+{ -+ char verify_buf[sizeof(struct in6_addr)]; -+ -+ if (inet_pton(AF_INET, address_string, verify_buf) == 1) -+ return true; -+ if (inet_pton(AF_INET6, address_string, verify_buf) == 1) -+ return true; -+ return false; -+} -+ -+static void kvp_extract_routes(void **output, size_t *output_len, char *line) -+{ -+ static const char needle[] = "via "; -+ char *match, *haystack = line; -+ -+ while ((match = strstr(haystack, needle))) { -+ char *address, *end; -+ -+ /* Address starts after needle. */ -+ address = match + strlen(needle); -+ -+ /* The char following address is a space or end of line. */ -+ end = strpbrk(address, " \t\\"); -+ if (!end) -+ end = address + strlen(address) + 1; -+ -+ /* Enough room for address and semicolon. */ -+ if (*output_len >= (end - address) + 1) { -+ memcpy(*output, address, end - address); -+ /* Terminate string for verification. */ -+ memcpy(*output + (end - address), "", 1); -+ if (kvp_verify_ip_address(*output)) { -+ /* Advance output buffer. */ -+ *output += end - address; -+ *output_len -= end - address; -+ -+ /* Each address needs a trailing semicolon. */ -+ memcpy(*output, ";", 1); -+ *output += 1; -+ *output_len -= 1; -+ } -+ } -+ haystack = end; -+ } -+} -+ -+static void kvp_get_gateway(void *buffer, size_t buffer_len) -+{ -+ static const char needle[] = "default "; -+ FILE *f; -+ void *output = buffer; -+ char *line = NULL; -+ size_t alloc_size = 0, output_len = buffer_len - 1; -+ ssize_t num_chars; -+ -+ /* Show route information in a single line, for each address family */ -+ f = popen("ip --oneline -4 route show;exec ip --oneline -6 route show", "r"); -+ while ((num_chars = getline(&line, &alloc_size, f)) > 0) { -+ /* Skip short lines. */ -+ if (num_chars <= strlen(needle)) -+ continue; -+ /* Skip lines without default route. */ -+ if (memcmp(line, needle, strlen(needle))) -+ continue; -+ /* Remove trailing newline to simplify further parsing. */ -+ if (line[num_chars - 1] == '\n') -+ line[num_chars - 1] = '\0'; -+ /* Search routes after match. */ -+ kvp_extract_routes(&output, &output_len, line + strlen(needle)); -+ } -+ /* Convert buffer into C-String. */ -+ memcpy(output, "", 1); -+ free(line); -+ pclose(f); -+} -+ - static void kvp_get_ipconfig_info(char *if_name, - struct hv_kvp_ipaddr_value *buffer) - { -@@ -684,32 +762,7 @@ static void kvp_get_ipconfig_info(char * - char dhcp_info[128]; - char *p; - FILE *file; -- -- /* -- * Get the address of default gateway (ipv4). -- */ -- sprintf(cmd, "%s %s", "ip route show dev", if_name); -- strcat(cmd, " | awk '/default/ {print $3 }'"); -- -- /* -- * Execute the command to gather gateway info. -- */ -- kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, -- (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); -- -- /* -- * Get the address of default gateway (ipv6). -- */ -- sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name); -- strcat(cmd, " | awk '/default/ {print $3 }'"); -- -- /* -- * Execute the command to gather gateway info (ipv6). -- */ -- kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, -- (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); -- -- -+ kvp_get_gateway(buffer->gate_way, sizeof(buffer->gate_way)); - /* - * Gather the DNS state. - * Since there is no standard way to get this information @@ -1335,6 +1335,7 @@ kvp_get_domain_name(char *buffer, int le struct addrinfo hints, *info ; int error = 0; ++++++ hyper-v.tools.hv.hv_kvp_daemon.c ++++++ --- /var/tmp/diff_new_pack.4lmaiE/_old 2025-06-20 16:48:58.239172740 +0200 +++ /var/tmp/diff_new_pack.4lmaiE/_new 2025-06-20 16:48:58.295175053 +0200 @@ -24,6 +24,7 @@ #include <sys/poll.h> #include <sys/utsname.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -83,6 +84,7 @@ }; static int in_hand_shake; +static int debug; static char *os_name = ""; static char *os_major = ""; @@ -183,6 +185,20 @@ kvp_release_lock(pool); } +static void kvp_dump_initial_pools(int pool) +{ + int i; + + syslog(LOG_DEBUG, "===Start dumping the contents of pool %d ===\n", + pool); + + for (i = 0; i < kvp_file_info[pool].num_records; i++) + syslog(LOG_DEBUG, "pool: %d, %d/%d key=%s val=%s\n", + pool, i + 1, kvp_file_info[pool].num_records, + kvp_file_info[pool].records[i].key, + kvp_file_info[pool].records[i].value); +} + static void kvp_update_mem_state(int pool) { FILE *filep; @@ -270,6 +286,8 @@ return 1; kvp_file_info[i].num_records = 0; kvp_update_mem_state(i); + if (debug) + kvp_dump_initial_pools(i); } return 0; @@ -297,6 +315,9 @@ * Found a match; just move the remaining * entries up. */ + if (debug) + syslog(LOG_DEBUG, "%s: deleting the KVP: pool=%d key=%s val=%s", + __func__, pool, record[i].key, record[i].value); if (i == (num_records - 1)) { kvp_file_info[pool].num_records--; kvp_update_file(pool); @@ -315,20 +336,36 @@ kvp_update_file(pool); return 0; } + + if (debug) + syslog(LOG_DEBUG, "%s: could not delete KVP: pool=%d key=%s. Record not found", + __func__, pool, key); + return 1; } static int kvp_key_add_or_modify(int pool, const __u8 *key, int key_size, const __u8 *value, int value_size) { - int i; - int num_records; struct kvp_record *record; + int num_records; int num_blocks; + int i; + + if (debug) + syslog(LOG_DEBUG, "%s: got a KVP: pool=%d key=%s val=%s", + __func__, pool, key, value); if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || - (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) + (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { + syslog(LOG_ERR, "%s: Too long key or value: key=%s, val=%s", + __func__, key, value); + + if (debug) + syslog(LOG_DEBUG, "%s: Too long key or value: pool=%d, key=%s, val=%s", + __func__, pool, key, value); return 1; + } /* * First update the in-memory state. @@ -348,6 +385,9 @@ */ memcpy(record[i].value, value, value_size); kvp_update_file(pool); + if (debug) + syslog(LOG_DEBUG, "%s: updated: pool=%d key=%s val=%s", + __func__, pool, key, value); return 0; } @@ -359,8 +399,10 @@ record = realloc(record, sizeof(struct kvp_record) * ENTRIES_PER_BLOCK * (num_blocks + 1)); - if (record == NULL) + if (!record) { + syslog(LOG_ERR, "%s: Memory alloc failure", __func__); return 1; + } kvp_file_info[pool].num_blocks++; } @@ -368,6 +410,11 @@ memcpy(record[i].key, key, key_size); kvp_file_info[pool].records = record; kvp_file_info[pool].num_records++; + + if (debug) + syslog(LOG_DEBUG, "%s: added: pool=%d key=%s val=%s", + __func__, pool, key, value); + kvp_update_file(pool); return 0; } @@ -677,6 +724,88 @@ pclose(file); } +static bool kvp_verify_ip_address(const void *address_string) +{ + char verify_buf[sizeof(struct in6_addr)]; + + if (inet_pton(AF_INET, address_string, verify_buf) == 1) + return true; + if (inet_pton(AF_INET6, address_string, verify_buf) == 1) + return true; + return false; +} + +static void kvp_extract_routes(const char *line, void **output, size_t *remaining) +{ + static const char needle[] = "via "; + const char *match, *haystack = line; + + while ((match = strstr(haystack, needle))) { + const char *address, *next_char; + + /* Address starts after needle. */ + address = match + strlen(needle); + + /* The char following address is a space or end of line. */ + next_char = strpbrk(address, " \t\\"); + if (!next_char) + next_char = address + strlen(address) + 1; + + /* Enough room for address and semicolon. */ + if (*remaining >= (next_char - address) + 1) { + memcpy(*output, address, next_char - address); + /* Terminate string for verification. */ + memcpy(*output + (next_char - address), "", 1); + if (kvp_verify_ip_address(*output)) { + /* Advance output buffer. */ + *output += next_char - address; + *remaining -= next_char - address; + + /* Each address needs a trailing semicolon. */ + memcpy(*output, ";", 1); + *output += 1; + *remaining -= 1; + } + } + haystack = next_char; + } +} + +static void kvp_get_gateway(void *buffer, size_t buffer_len) +{ + static const char needle[] = "default "; + FILE *f; + void *output = buffer; + char *line = NULL; + size_t alloc_size = 0, remaining = buffer_len - 1; + ssize_t num_chars; + + /* Show route information in a single line, for each address family */ + f = popen("ip --oneline -4 route show;ip --oneline -6 route show", "r"); + if (!f) { + /* Convert buffer into C-String. */ + memcpy(output, "", 1); + return; + } + while ((num_chars = getline(&line, &alloc_size, f)) > 0) { + /* Skip short lines. */ + if (num_chars <= strlen(needle)) + continue; + /* Skip lines without default route. */ + if (memcmp(line, needle, strlen(needle))) + continue; + /* Remove trailing newline to simplify further parsing. */ + if (line[num_chars - 1] == '\n') + line[num_chars - 1] = '\0'; + /* Search routes after match. */ + kvp_extract_routes(line + strlen(needle), &output, &remaining); + } + /* Convert buffer into C-String. */ + memcpy(output, "", 1); + free(line); + pclose(f); +} + static void kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer) { @@ -685,30 +814,7 @@ char *p; FILE *file; - /* - * Get the address of default gateway (ipv4). - */ - sprintf(cmd, "%s %s", "ip route show dev", if_name); - strcat(cmd, " | awk '/default/ {print $3 }'"); - - /* - * Execute the command to gather gateway info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); - - /* - * Get the address of default gateway (ipv6). - */ - sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name); - strcat(cmd, " | awk '/default/ {print $3 }'"); - - /* - * Execute the command to gather gateway info (ipv6). - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); - + kvp_get_gateway(buffer->gate_way, sizeof(buffer->gate_way)); /* * Gather the DNS state. @@ -1664,6 +1770,7 @@ fprintf(stderr, "Usage: %s [options]\n" "Options are:\n" " -n, --no-daemon stay in foreground, don't daemonize\n" + " -d, --debug Enable debug logs(syslog debug by default)\n" " -h, --help print this help\n", argv[0]); } @@ -1685,10 +1792,11 @@ static struct option long_options[] = { {"help", no_argument, 0, 'h' }, {"no-daemon", no_argument, 0, 'n' }, + {"debug", no_argument, 0, 'd' }, {0, 0, 0, 0 } }; - while ((opt = getopt_long(argc, argv, "hn", long_options, + while ((opt = getopt_long(argc, argv, "hnd", long_options, &long_index)) != -1) { switch (opt) { case 'n': @@ -1697,6 +1805,9 @@ case 'h': print_usage(argv); exit(0); + case 'd': + debug = 1; + break; default: print_usage(argv); exit(EXIT_FAILURE); @@ -1719,6 +1830,9 @@ */ kvp_get_domain_name(full_domain_name, sizeof(full_domain_name)); + if (debug) + syslog(LOG_INFO, "Logging debug info in syslog(debug)"); + if (kvp_file_init()) { syslog(LOG_ERR, "Failed to initialize the pools"); exit(EXIT_FAILURE);