From e22e68e214d24eadda9cd0475949bc3af59bad53 Mon Sep 17 00:00:00 2001 From: gjb Date: Fri, 26 Sep 2014 03:03:58 +0000 Subject: [PATCH] Properly revert r272128. Approved by: re (implicit) Sponsored by: The FreeBSD Foundation git-svn-id: svn://svn.freebsd.org/base/stable/10@272152 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- ObsoleteFiles.inc | 2 - contrib/hyperv/tools/hv_kvp_daemon.8 | 68 - contrib/hyperv/tools/hv_kvp_daemon.c | 1518 ----------------- contrib/hyperv/tools/scripts/hv_get_dhcp_info | 24 - contrib/hyperv/tools/scripts/hv_get_dns_info | 12 - contrib/hyperv/tools/scripts/hv_set_ifconfig | 73 - etc/devd/Makefile | 4 - etc/devd/hyperv.conf | 19 - etc/mtree/BSD.usr.dist | 2 - etc/mtree/BSD.var.dist | 2 - libexec/Makefile | 5 - libexec/hyperv/Makefile | 10 - share/mk/bsd.own.mk | 6 - sys/conf/files.amd64 | 1 - sys/conf/files.i386 | 1 - sys/dev/hyperv/include/hyperv.h | 29 - sys/dev/hyperv/utilities/hv_kvp.c | 1001 ----------- sys/dev/hyperv/utilities/hv_kvp.h | 143 +- sys/dev/hyperv/utilities/hv_util.c | 47 +- sys/dev/hyperv/utilities/unicode.h | 201 --- sys/modules/hyperv/utilities/Makefile | 2 +- tools/build/mk/OptionalObsoleteFiles.inc | 8 - tools/build/options/WITHOUT_HYPERV | 2 - tools/build/options/WITH_HYPERV | 2 - usr.sbin/Makefile.amd64 | 3 - usr.sbin/Makefile.i386 | 3 - usr.sbin/hyperv/Makefile | 7 - usr.sbin/hyperv/Makefile.inc | 3 - usr.sbin/hyperv/tools/Makefile | 13 - 29 files changed, 103 insertions(+), 3108 deletions(-) delete mode 100644 contrib/hyperv/tools/hv_kvp_daemon.8 delete mode 100644 contrib/hyperv/tools/hv_kvp_daemon.c delete mode 100644 contrib/hyperv/tools/scripts/hv_get_dhcp_info delete mode 100644 contrib/hyperv/tools/scripts/hv_get_dns_info delete mode 100644 contrib/hyperv/tools/scripts/hv_set_ifconfig delete mode 100644 etc/devd/hyperv.conf delete mode 100644 libexec/hyperv/Makefile delete mode 100644 sys/dev/hyperv/utilities/hv_kvp.c delete mode 100644 sys/dev/hyperv/utilities/unicode.h delete mode 100644 tools/build/options/WITHOUT_HYPERV delete mode 100644 tools/build/options/WITH_HYPERV delete mode 100644 usr.sbin/hyperv/Makefile delete mode 100644 usr.sbin/hyperv/Makefile.inc delete mode 100644 usr.sbin/hyperv/tools/Makefile diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index 0ddd4f59e..7bff0c530 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -38,8 +38,6 @@ # xargs -n1 | sort | uniq -d; # done -# 20140925: hv_kvpd rc.d script removed in favor of devd configuration -OLD_FILES+=etc/rc.d/hv_kvpd # 20140814: libopie version bump OLD_LIBS+=usr/lib/libopie.so.7 OLD_LIBS+=usr/lib32/libopie.so.7 diff --git a/contrib/hyperv/tools/hv_kvp_daemon.8 b/contrib/hyperv/tools/hv_kvp_daemon.8 deleted file mode 100644 index af574edef..000000000 --- a/contrib/hyperv/tools/hv_kvp_daemon.8 +++ /dev/null @@ -1,68 +0,0 @@ -.\" Copyright (c) 2014 Microsoft Corp. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd September 10, 2013 -.Dt HYPER-V 4 -.Os -.Sh NAME -.Nm hv_kvp_daemon -.Nd Hyper-V Key Value Pair Daemon -.Sh SYNOPSIS -The \fBhv_kvp_daemon\fP daemon provides the ability to store, retrieve, modify and delete -Key Value pairs for FreeBSD guest partitions running on Hyper-V. -.Sh DESCRIPTION -Hyper-V allows administrators to store custom metadata in the form -of Key Value pairs inside the FreeBSD guest partition. Administrators can -use Windows Powershell scripts to add, read, modify and delete such -Key Value pairs. - -The \fBhv_kvp_daemon\fP accepts Key Value pair management requests from the -\fBhv_utils\fP driver and performs the actual metadata management on the file-system. - -The same daemon and driver combination is also used to set and get -IP addresses from a FreeBSD guest. - -The set functionality is particularly -useful when the FreeBSD guest is assigned a static IP address and is failed -over from one Hyper-V host to another. After failover, Hyper-V uses the set IP -functionality to automatically -update the FreeBSD guest's IP address to its original static value. - -On the other hand, the get IP functionality is used to update the guest IP -address in the Hyper-V management console window. -.Sh SEE ALSO -.Xr hv_vmbus 4 , -.Xr hv_utils 4 , -.Xr hv_netvsc 4 , -.Xr hv_storvsc 4 , -.Xr hv_ata_pci_disengage 4 -.Sh HISTORY -Support for Hyper-V in the form of ports was first released in September 2013. -The daemon was developed through a joint effort between Citrix Inc., -Microsoft Corp. and Network Appliance Inc.. -.Sh AUTHORS -.An -nosplit -.Fx -support for \fBhv_kvp_daemon\fP was first added by -.An Microsoft BSD Integration Services Team Aq bsdic@microsoft.com . diff --git a/contrib/hyperv/tools/hv_kvp_daemon.c b/contrib/hyperv/tools/hv_kvp_daemon.c deleted file mode 100644 index 890ca5b55..000000000 --- a/contrib/hyperv/tools/hv_kvp_daemon.c +++ /dev/null @@ -1,1518 +0,0 @@ -/*- - * Copyright (c) 2014 Microsoft Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hv_kvp.h" - -typedef uint8_t __u8; -typedef uint16_t __u16; -typedef uint32_t __u32; -typedef uint64_t __u64; - -/* - * ENUM Data - */ - -enum key_index { - FullyQualifiedDomainName = 0, - IntegrationServicesVersion, /*This key is serviced in the kernel*/ - NetworkAddressIPv4, - NetworkAddressIPv6, - OSBuildNumber, - OSName, - OSMajorVersion, - OSMinorVersion, - OSVersion, - ProcessorArchitecture -}; - - -enum { - IPADDR = 0, - NETMASK, - GATEWAY, - DNS -}; - - -/* Global Variables */ - -/* - * The structure for operation handlers. - */ -struct kvp_op_hdlr { - int kvp_op_key; - void (*kvp_op_init)(void); - int (*kvp_op_exec)(struct hv_kvp_msg *kvp_op_msg, void *data); -}; - -static struct kvp_op_hdlr kvp_op_hdlrs[HV_KVP_OP_COUNT]; - -/* OS information */ - -static const char *os_name = ""; -static const char *os_major = ""; -static const char *os_minor = ""; -static const char *processor_arch; -static const char *os_build; -static const char *lic_version = "BSD Pre-Release version"; -static struct utsname uts_buf; - -/* Global flags */ -static int is_daemon = 1; -static int is_debugging = 0; - -#define KVP_LOG(priority, format, args...) do { \ - if (is_debugging == 1) { \ - if (is_daemon == 1) \ - syslog(priority, format, ## args); \ - else \ - printf(format, ## args); \ - } else { \ - if (priority < LOG_DEBUG) { \ - if (is_daemon == 1) \ - syslog(priority, format, ## args); \ - else \ - printf(format, ## args); \ - } \ - } \ - } while(0) - -/* - * For KVP pool file - */ - -#define MAX_FILE_NAME 100 -#define ENTRIES_PER_BLOCK 50 - -struct kvp_record { - char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; - char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; -}; - -struct kvp_pool { - int pool_fd; - int num_blocks; - struct kvp_record *records; - int num_records; - char fname[MAX_FILE_NAME]; -}; - -static struct kvp_pool kvp_pools[HV_KVP_POOL_COUNT]; - - -static void -kvp_acquire_lock(int pool) -{ - struct flock fl = { 0, 0, 0, F_WRLCK, SEEK_SET, 0 }; - - fl.l_pid = getpid(); - - if (fcntl(kvp_pools[pool].pool_fd, F_SETLKW, &fl) == -1) { - KVP_LOG(LOG_ERR, "Failed to acquire the lock pool: %d", pool); - exit(EXIT_FAILURE); - } -} - - -static void -kvp_release_lock(int pool) -{ - struct flock fl = { 0, 0, 0, F_UNLCK, SEEK_SET, 0 }; - - fl.l_pid = getpid(); - - if (fcntl(kvp_pools[pool].pool_fd, F_SETLK, &fl) == -1) { - perror("fcntl"); - KVP_LOG(LOG_ERR, "Failed to release the lock pool: %d\n", pool); - exit(EXIT_FAILURE); - } -} - - -/* - * Write in-memory copy of KVP to pool files - */ -static void -kvp_update_file(int pool) -{ - FILE *filep; - size_t bytes_written; - - kvp_acquire_lock(pool); - - filep = fopen(kvp_pools[pool].fname, "w"); - if (!filep) { - kvp_release_lock(pool); - KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool); - exit(EXIT_FAILURE); - } - - bytes_written = fwrite(kvp_pools[pool].records, - sizeof(struct kvp_record), - kvp_pools[pool].num_records, filep); - - if (ferror(filep) || fclose(filep)) { - kvp_release_lock(pool); - KVP_LOG(LOG_ERR, "Failed to write file, pool: %d\n", pool); - exit(EXIT_FAILURE); - } - - kvp_release_lock(pool); -} - - -/* - * Read KVPs from pool files and store in memory - */ -static void -kvp_update_mem_state(int pool) -{ - FILE *filep; - size_t records_read = 0; - struct kvp_record *record = kvp_pools[pool].records; - struct kvp_record *readp; - int num_blocks = kvp_pools[pool].num_blocks; - int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; - - kvp_acquire_lock(pool); - - filep = fopen(kvp_pools[pool].fname, "r"); - if (!filep) { - kvp_release_lock(pool); - KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool); - exit(EXIT_FAILURE); - } - for ( ; ; ) - { - readp = &record[records_read]; - records_read += fread(readp, sizeof(struct kvp_record), - ENTRIES_PER_BLOCK * num_blocks, - filep); - - if (ferror(filep)) { - KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n", pool); - exit(EXIT_FAILURE); - } - - if (!feof(filep)) { - /* - * Have more data to read. Expand the memory. - */ - num_blocks++; - record = realloc(record, alloc_unit * num_blocks); - - if (record == NULL) { - KVP_LOG(LOG_ERR, "malloc failed\n"); - exit(EXIT_FAILURE); - } - continue; - } - break; - } - - kvp_pools[pool].num_blocks = num_blocks; - kvp_pools[pool].records = record; - kvp_pools[pool].num_records = records_read; - - fclose(filep); - kvp_release_lock(pool); -} - - -static int -kvp_file_init(void) -{ - int fd; - FILE *filep; - size_t records_read; - char *fname; - struct kvp_record *record; - struct kvp_record *readp; - int num_blocks; - int i; - int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK; - - if (access("/var/db/hyperv/pool", F_OK)) { - if (mkdir("/var/db/hyperv/pool", - S_IRUSR | S_IWUSR | S_IROTH)) { - KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n"); - exit(EXIT_FAILURE); - } - } - - for (i = 0; i < HV_KVP_POOL_COUNT; i++) - { - fname = kvp_pools[i].fname; - records_read = 0; - num_blocks = 1; - snprintf(fname, MAX_FILE_NAME, "/var/db/hyperv/pool/.kvp_pool_%d", i); - fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH); - - if (fd == -1) { - return (1); - } - - - filep = fopen(fname, "r"); - if (!filep) { - return (1); - } - - record = malloc(alloc_unit * num_blocks); - if (record == NULL) { - fclose(filep); - return (1); - } - for ( ; ; ) - { - readp = &record[records_read]; - records_read += fread(readp, sizeof(struct kvp_record), - ENTRIES_PER_BLOCK, - filep); - - if (ferror(filep)) { - KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n", - i); - exit(EXIT_FAILURE); - } - - if (!feof(filep)) { - /* - * More data to read. - */ - num_blocks++; - record = realloc(record, alloc_unit * - num_blocks); - if (record == NULL) { - fclose(filep); - return (1); - } - continue; - } - break; - } - kvp_pools[i].pool_fd = fd; - kvp_pools[i].num_blocks = num_blocks; - kvp_pools[i].records = record; - kvp_pools[i].num_records = records_read; - fclose(filep); - } - - return (0); -} - - -static int -kvp_key_delete(int pool, __u8 *key, int key_size) -{ - int i; - int j, k; - int num_records; - struct kvp_record *record; - - KVP_LOG(LOG_DEBUG, "kvp_key_delete: pool = %d, " - "key = %s\n", pool, key); - - /* Update in-memory state */ - kvp_update_mem_state(pool); - - num_records = kvp_pools[pool].num_records; - record = kvp_pools[pool].records; - - for (i = 0; i < num_records; i++) - { - if (memcmp(key, record[i].key, key_size)) { - continue; - } - - KVP_LOG(LOG_DEBUG, "Found delete key in pool %d.\n", - pool); - /* - * We found a match at the end; Just update the number of - * entries and we are done. - */ - if (i == num_records) { - kvp_pools[pool].num_records--; - kvp_update_file(pool); - return (0); - } - - /* - * We found a match in the middle; Move the remaining - * entries up. - */ - j = i; - k = j + 1; - for ( ; k < num_records; k++) - { - strcpy(record[j].key, record[k].key); - strcpy(record[j].value, record[k].value); - j++; - } - kvp_pools[pool].num_records--; - kvp_update_file(pool); - return (0); - } - KVP_LOG(LOG_DEBUG, "Not found delete key in pool %d.\n", - pool); - return (1); -} - - -static int -kvp_key_add_or_modify(int pool, __u8 *key, __u32 key_size, __u8 *value, - __u32 value_size) -{ - int i; - int num_records; - struct kvp_record *record; - int num_blocks; - - KVP_LOG(LOG_DEBUG, "kvp_key_add_or_modify: pool = %d, " - "key = %s, value = %s\n,", pool, key, value); - - if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || - (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { - KVP_LOG(LOG_ERR, "kvp_key_add_or_modify: returning 1\n"); - return (1); - } - - /* Update the in-memory state. */ - kvp_update_mem_state(pool); - - num_records = kvp_pools[pool].num_records; - record = kvp_pools[pool].records; - num_blocks = kvp_pools[pool].num_blocks; - - for (i = 0; i < num_records; i++) - { - if (memcmp(key, record[i].key, key_size)) { - continue; - } - - /* - * Key exists. Just update the value and we are done. - */ - memcpy(record[i].value, value, value_size); - kvp_update_file(pool); - return (0); - } - - /* - * Key doesn't exist; Add a new KVP. - */ - if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) { - /* Increase the size of the recodrd array. */ - record = realloc(record, sizeof(struct kvp_record) * - ENTRIES_PER_BLOCK * (num_blocks + 1)); - - if (record == NULL) { - return (1); - } - kvp_pools[pool].num_blocks++; - } - memcpy(record[i].value, value, value_size); - memcpy(record[i].key, key, key_size); - kvp_pools[pool].records = record; - kvp_pools[pool].num_records++; - kvp_update_file(pool); - return (0); -} - - -static int -kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value, - int value_size) -{ - int i; - int num_records; - struct kvp_record *record; - - KVP_LOG(LOG_DEBUG, "kvp_get_value: pool = %d, key = %s\n,", - pool, key); - - if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) || - (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { - return (1); - } - - /* Update the in-memory state first. */ - kvp_update_mem_state(pool); - - num_records = kvp_pools[pool].num_records; - record = kvp_pools[pool].records; - - for (i = 0; i < num_records; i++) - { - if (memcmp(key, record[i].key, key_size)) { - continue; - } - - /* Found the key */ - memcpy(value, record[i].value, value_size); - return (0); - } - - return (1); -} - - -static int -kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, - __u8 *value, int value_size) -{ - struct kvp_record *record; - - KVP_LOG(LOG_DEBUG, "kvp_pool_enumerate: pool = %d, index = %d\n,", - pool, index); - - /* First update our in-memory state first. */ - kvp_update_mem_state(pool); - record = kvp_pools[pool].records; - - /* Index starts with 0 */ - if (index >= kvp_pools[pool].num_records) { - return (1); - } - - memcpy(key, record[index].key, key_size); - memcpy(value, record[index].value, value_size); - return (0); -} - - -static void -kvp_get_os_info(void) -{ - char *p; - - uname(&uts_buf); - os_build = uts_buf.release; - os_name = uts_buf.sysname; - processor_arch = uts_buf.machine; - - /* - * Win7 host expects the build string to be of the form: x.y.z - * Strip additional information we may have. - */ - p = strchr(os_build, '-'); - if (p) { - *p = '\0'; - } - - /* - * We don't have any other information about the FreeBSD os. - */ - return; -} - -/* - * Given the interface name, return the MAC address. - */ -static char * -kvp_if_name_to_mac(char *if_name) -{ - char *mac_addr = NULL; - struct ifaddrs *ifaddrs_ptr; - struct ifaddrs *head_ifaddrs_ptr; - struct sockaddr_dl *sdl; - int status; - - status = getifaddrs(&ifaddrs_ptr); - - if (status >= 0) { - head_ifaddrs_ptr = ifaddrs_ptr; - do { - sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr; - if ((sdl->sdl_type == IFT_ETHER) && - (strcmp(ifaddrs_ptr->ifa_name, if_name) == 0)) { - mac_addr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl)))); - break; - } - } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL); - freeifaddrs(head_ifaddrs_ptr); - } - - return (mac_addr); -} - - -/* - * Given the MAC address, return the interface name. - */ -static char * -kvp_mac_to_if_name(char *mac) -{ - char *if_name = NULL; - struct ifaddrs *ifaddrs_ptr; - struct ifaddrs *head_ifaddrs_ptr; - struct sockaddr_dl *sdl; - int status; - size_t i; - char *buf_ptr; - - status = getifaddrs(&ifaddrs_ptr); - - if (status >= 0) { - head_ifaddrs_ptr = ifaddrs_ptr; - do { - sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr; - if (sdl->sdl_type == IFT_ETHER) { - buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl)))); - for (i = 0; i < strlen(buf_ptr); i++) - { - buf_ptr[i] = toupper(buf_ptr[i]); - } - - if (strncmp(buf_ptr, mac, strlen(mac)) == 0) { - /* Caller will free the memory */ - if_name = strdup(ifaddrs_ptr->ifa_name); - free(buf_ptr); - break; - }else if (buf_ptr != NULL) { - free(buf_ptr); - } - } - } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL); - freeifaddrs(head_ifaddrs_ptr); - } - return (if_name); -} - - -static void -kvp_process_ipconfig_file(char *cmd, - char *config_buf, size_t len, - size_t element_size, int offset) -{ - char buf[256]; - char *p; - char *x; - FILE *file; - - /* - * First execute the command. - */ - file = popen(cmd, "r"); - if (file == NULL) { - return; - } - - if (offset == 0) { - memset(config_buf, 0, len); - } - while ((p = fgets(buf, sizeof(buf), file)) != NULL) { - if ((len - strlen(config_buf)) < (element_size + 1)) { - break; - } - - x = strchr(p, '\n'); - *x = '\0'; - strlcat(config_buf, p, len); - strlcat(config_buf, ";", len); - } - pclose(file); -} - - -static void -kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer) -{ - char cmd[512]; - char dhcp_info[128]; - char *p; - FILE *file; - - /* - * Retrieve the IPV4 address of default gateway. - */ - snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name); - - /* - * Execute the command to gather gateway IPV4 info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); - - /* - * Retrieve the IPV6 address of default gateway. - */ - snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name); - - /* - * Execute the command to gather gateway IPV6 info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, - (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); - - /* - * we just invoke an external script to get the DNS info. - * - * Following is the expected format of the information from the script: - * - * ipaddr1 (nameserver1) - * ipaddr2 (nameserver2) - * . - * . - */ - /* Scripts are stored in /usr/libexec/hyperv/ directory */ - snprintf(cmd, sizeof(cmd), "%s", "sh /usr/libexec/hyperv/hv_get_dns_info"); - - /* - * Execute the command to get DNS info. - */ - kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr, - (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0); - - /* - * Invoke an external script to get the DHCP state info. - * The parameter to the script is the interface name. - * Here is the expected output: - * - * Enabled: DHCP enabled. - */ - - - snprintf(cmd, sizeof(cmd), "%s %s", - "sh /usr/libexec/hyperv/hv_get_dhcp_info", if_name); - - file = popen(cmd, "r"); - if (file == NULL) { - return; - } - - p = fgets(dhcp_info, sizeof(dhcp_info), file); - if (p == NULL) { - pclose(file); - return; - } - - if (!strncmp(p, "Enabled", 7)) { - buffer->dhcp_enabled = 1; - } else{ - buffer->dhcp_enabled = 0; - } - - pclose(file); -} - - -static unsigned int -hweight32(unsigned int *w) -{ - unsigned int res = *w - ((*w >> 1) & 0x55555555); - - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res + (res >> 4)) & 0x0F0F0F0F; - res = res + (res >> 8); - return ((res + (res >> 16)) & 0x000000FF); -} - - -static int -kvp_process_ip_address(void *addrp, - int family, char *buffer, - int length, int *offset) -{ - struct sockaddr_in *addr; - struct sockaddr_in6 *addr6; - int addr_length; - char tmp[50]; - const char *str; - - if (family == AF_INET) { - addr = (struct sockaddr_in *)addrp; - str = inet_ntop(family, &addr->sin_addr, tmp, 50); - addr_length = INET_ADDRSTRLEN; - } else { - addr6 = (struct sockaddr_in6 *)addrp; - str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50); - addr_length = INET6_ADDRSTRLEN; - } - - if ((length - *offset) < addr_length + 1) { - return (HV_KVP_E_FAIL); - } - if (str == NULL) { - strlcpy(buffer, "inet_ntop failed\n", length); - return (HV_KVP_E_FAIL); - } - if (*offset == 0) { - strlcpy(buffer, tmp, length); - } else{ - strlcat(buffer, tmp, length); - } - strlcat(buffer, ";", length); - - *offset += strlen(str) + 1; - return (0); -} - - -static int -kvp_get_ip_info(int family, char *if_name, int op, - void *out_buffer, size_t length) -{ - struct ifaddrs *ifap; - struct ifaddrs *curp; - int offset = 0; - int sn_offset = 0; - int error = 0; - char *buffer; - size_t buffer_length; - struct hv_kvp_ipaddr_value *ip_buffer; - char cidr_mask[5]; - int weight; - int i; - unsigned int *w = NULL; - char *sn_str; - size_t sn_str_length; - struct sockaddr_in6 *addr6; - - if (op == HV_KVP_OP_ENUMERATE) { - buffer = out_buffer; - buffer_length = length; - } else { - ip_buffer = out_buffer; - buffer = (char *)ip_buffer->ip_addr; - buffer_length = sizeof(ip_buffer->ip_addr); - ip_buffer->addr_family = 0; - } - - if (getifaddrs(&ifap)) { - strlcpy(buffer, "getifaddrs failed\n", buffer_length); - return (HV_KVP_E_FAIL); - } - - curp = ifap; - while (curp != NULL) { - if (curp->ifa_addr == NULL) { - curp = curp->ifa_next; - continue; - } - - if ((if_name != NULL) && - (strncmp(curp->ifa_name, if_name, strlen(if_name)))) { - /* - * We want info about a specific interface; - * just continue. - */ - curp = curp->ifa_next; - continue; - } - - /* - * We support two address families: AF_INET and AF_INET6. - * If family value is 0, we gather both supported - * address families; if not we gather info on - * the specified address family. - */ - if ((family != 0) && (curp->ifa_addr->sa_family != family)) { - curp = curp->ifa_next; - continue; - } - if ((curp->ifa_addr->sa_family != AF_INET) && - (curp->ifa_addr->sa_family != AF_INET6)) { - curp = curp->ifa_next; - continue; - } - - if (op == HV_KVP_OP_GET_IP_INFO) { - /* - * Get the info other than the IP address. - */ - if (curp->ifa_addr->sa_family == AF_INET) { - ip_buffer->addr_family |= ADDR_FAMILY_IPV4; - - /* - * Get subnet info. - */ - error = kvp_process_ip_address( - curp->ifa_netmask, - AF_INET, - (char *) - ip_buffer->sub_net, - length, - &sn_offset); - if (error) { - goto kvp_get_ip_info_ipaddr; - } - } else { - ip_buffer->addr_family |= ADDR_FAMILY_IPV6; - - /* - * Get subnet info in CIDR format. - */ - weight = 0; - sn_str = (char *)ip_buffer->sub_net; - sn_str_length = sizeof(ip_buffer->sub_net); - addr6 = (struct sockaddr_in6 *)(uintptr_t) - curp->ifa_netmask; - w = (unsigned int *)(uintptr_t)addr6->sin6_addr.s6_addr; - - for (i = 0; i < 4; i++) - { - weight += hweight32(&w[i]); - } - - snprintf(cidr_mask, sizeof(cidr_mask), "/%d", weight); - if ((length - sn_offset) < - (strlen(cidr_mask) + 1)) { - goto kvp_get_ip_info_ipaddr; - } - - if (sn_offset == 0) { - strlcpy(sn_str, cidr_mask, sn_str_length); - } else{ - strlcat(sn_str, cidr_mask, sn_str_length); - } - strlcat((char *)ip_buffer->sub_net, ";", sn_str_length); - sn_offset += strlen(sn_str) + 1; - } - - /* - * Collect other ip configuration info. - */ - - kvp_get_ipconfig_info(if_name, ip_buffer); - } - -kvp_get_ip_info_ipaddr: - error = kvp_process_ip_address(curp->ifa_addr, - curp->ifa_addr->sa_family, - buffer, - length, &offset); - if (error) { - goto kvp_get_ip_info_done; - } - - curp = curp->ifa_next; - } - -kvp_get_ip_info_done: - freeifaddrs(ifap); - return (error); -} - - -static int -kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3) -{ - int ret; - - ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); - - if (ret < 0) { - return (HV_KVP_E_FAIL); - } - - return (0); -} - - -static int -kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) -{ - int error = 0; - char if_file[128]; - FILE *file; - char cmd[512]; - char *mac_addr; - - /* - * FreeBSD - Configuration File - */ - snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv", - "hv_set_ip_data"); - file = fopen(if_file, "w"); - - if (file == NULL) { - KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); - return (HV_KVP_E_FAIL); - } - - /* - * Write out the MAC address. - */ - - mac_addr = kvp_if_name_to_mac(if_name); - if (mac_addr == NULL) { - error = HV_KVP_E_FAIL; - goto kvp_set_ip_info_error; - } - /* MAC Address */ - error = kvp_write_file(file, "HWADDR", "", mac_addr); - if (error) { - goto kvp_set_ip_info_error; - } - - /* Interface Name */ - error = kvp_write_file(file, "IF_NAME", "", if_name); - if (error) { - goto kvp_set_ip_info_error; - } - - /* IP Address */ - error = kvp_write_file(file, "IP_ADDR", "", - (char *)new_val->ip_addr); - if (error) { - goto kvp_set_ip_info_error; - } - - /* Subnet Mask */ - error = kvp_write_file(file, "SUBNET", "", - (char *)new_val->sub_net); - if (error) { - goto kvp_set_ip_info_error; - } - - - /* Gateway */ - error = kvp_write_file(file, "GATEWAY", "", - (char *)new_val->gate_way); - if (error) { - goto kvp_set_ip_info_error; - } - - /* DNS */ - error = kvp_write_file(file, "DNS", "", (char *)new_val->dns_addr); - if (error) { - goto kvp_set_ip_info_error; - } - - /* DHCP */ - if (new_val->dhcp_enabled) { - error = kvp_write_file(file, "DHCP", "", "1"); - } else{ - error = kvp_write_file(file, "DHCP", "", "0"); - } - - if (error) { - goto kvp_set_ip_info_error; - } - - free(mac_addr); - fclose(file); - - /* - * Invoke the external script with the populated - * configuration file. - */ - - snprintf(cmd, sizeof(cmd), "%s %s", - "sh /usr/libexec/hyperv/hv_set_ifconfig", if_file); - system(cmd); - return (0); - -kvp_set_ip_info_error: - KVP_LOG(LOG_ERR, "Failed to write config file\n"); - free(mac_addr); - fclose(file); - return (error); -} - - -static int -kvp_get_domain_name(char *buffer, int length) -{ - struct addrinfo hints, *info; - int error = 0; - - gethostname(buffer, length); - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; /* Get only ipv4 addrinfo. */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - - error = getaddrinfo(buffer, NULL, &hints, &info); - if (error != 0) { - strlcpy(buffer, "getaddrinfo failed\n", length); - return (error); - } - strlcpy(buffer, info->ai_canonname, length); - freeaddrinfo(info); - return (error); -} - - -static int -kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused) -{ - struct hv_kvp_ipaddr_value *ip_val; - char *if_name; - - assert(op_msg != NULL); - KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); - - ip_val = &op_msg->body.kvp_ip_val; - op_msg->hdr.error = HV_KVP_S_OK; - - if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id); - - if (if_name == NULL) { - /* No interface found with the mac address. */ - op_msg->hdr.error = HV_KVP_E_FAIL; - goto kvp_op_getipinfo_done; - } - - op_msg->hdr.error = kvp_get_ip_info(0, if_name, - HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2)); - - free(if_name); - -kvp_op_getipinfo_done: - return(op_msg->hdr.error); -} - - -static int -kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused) -{ - struct hv_kvp_ipaddr_value *ip_val; - char *if_name; - - assert(op_msg != NULL); - KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); - - ip_val = &op_msg->body.kvp_ip_val; - op_msg->hdr.error = HV_KVP_S_OK; - - if_name = (char *)ip_val->adapter_id; - - if (if_name == NULL) { - /* No adapter provided. */ - op_msg->hdr.error = HV_KVP_GUID_NOTFOUND; - goto kvp_op_setipinfo_done; - } - - op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val); - -kvp_op_setipinfo_done: - return(op_msg->hdr.error); -} - - -static int -kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) -{ - struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data; - int error = 0; - int op_pool; - - assert(op_msg != NULL); - assert(op_hdlr != NULL); - - op_pool = op_msg->hdr.kvp_hdr.pool; - op_msg->hdr.error = HV_KVP_S_OK; - - switch(op_hdlr->kvp_op_key) { - case HV_KVP_OP_SET: - if (op_pool == HV_KVP_POOL_AUTO) { - /* Auto Pool is not writeable from host side. */ - error = 1; - KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n", - op_pool); - } else { - error = kvp_key_add_or_modify(op_pool, - op_msg->body.kvp_set.data.key, - op_msg->body.kvp_set.data.key_size, - op_msg->body.kvp_set.data.msg_value.value, - op_msg->body.kvp_set.data.value_size); - } - break; - - case HV_KVP_OP_GET: - error = kvp_get_value(op_pool, - op_msg->body.kvp_get.data.key, - op_msg->body.kvp_get.data.key_size, - op_msg->body.kvp_get.data.msg_value.value, - op_msg->body.kvp_get.data.value_size); - break; - - case HV_KVP_OP_DELETE: - if (op_pool == HV_KVP_POOL_AUTO) { - /* Auto Pool is not writeable from host side. */ - error = 1; - KVP_LOG(LOG_ERR, "Ilegal to change pool %d from host\n", - op_pool); - } else { - error = kvp_key_delete(op_pool, - op_msg->body.kvp_delete.key, - op_msg->body.kvp_delete.key_size); - } - break; - - default: - break; - } - - if (error != 0) - op_msg->hdr.error = HV_KVP_S_CONT; - - return(error); -} - - -static int -kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) -{ - char *key_name, *key_value; - int error = 0; - int op_pool; - int op; - - assert(op_msg != NULL); - - op = op_msg->hdr.kvp_hdr.operation; - op_pool = op_msg->hdr.kvp_hdr.pool; - op_msg->hdr.error = HV_KVP_S_OK; - - /* - * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate - * pool and return the KVP according to the index requested. - */ - if (op_pool != HV_KVP_POOL_AUTO) { - if (kvp_pool_enumerate(op_pool, - op_msg->body.kvp_enum_data.index, - op_msg->body.kvp_enum_data.data.key, - HV_KVP_EXCHANGE_MAX_KEY_SIZE, - op_msg->body.kvp_enum_data.data.msg_value.value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { - op_msg->hdr.error = HV_KVP_S_CONT; - error = -1; - } - goto kvp_op_enumerate_done; - } - - key_name = (char *)op_msg->body.kvp_enum_data.data.key; - key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value; - - switch (op_msg->body.kvp_enum_data.index) - { - case FullyQualifiedDomainName: - kvp_get_domain_name(key_value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "FullyQualifiedDomainName"); - break; - - case IntegrationServicesVersion: - strcpy(key_name, "IntegrationServicesVersion"); - strcpy(key_value, lic_version); - break; - - case NetworkAddressIPv4: - kvp_get_ip_info(AF_INET, NULL, HV_KVP_OP_ENUMERATE, - key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "NetworkAddressIPv4"); - break; - - case NetworkAddressIPv6: - kvp_get_ip_info(AF_INET6, NULL, HV_KVP_OP_ENUMERATE, - key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE); - strcpy(key_name, "NetworkAddressIPv6"); - break; - - case OSBuildNumber: - strcpy(key_value, os_build); - strcpy(key_name, "OSBuildNumber"); - break; - - case OSName: - strcpy(key_value, os_name); - strcpy(key_name, "OSName"); - break; - - case OSMajorVersion: - strcpy(key_value, os_major); - strcpy(key_name, "OSMajorVersion"); - break; - - case OSMinorVersion: - strcpy(key_value, os_minor); - strcpy(key_name, "OSMinorVersion"); - break; - - case OSVersion: - strcpy(key_value, os_build); - strcpy(key_name, "OSVersion"); - break; - - case ProcessorArchitecture: - strcpy(key_value, processor_arch); - strcpy(key_name, "ProcessorArchitecture"); - break; - - default: -#ifdef DEBUG - KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n", - op_msg->body.kvp_enum_data.index); -#endif - op_msg->hdr.error = HV_KVP_S_CONT; - error = -1; - break; - } - -kvp_op_enumerate_done: - return(error); -} - - -/* - * Load handler, and call init routine if provided. - */ -static int -kvp_op_load(int key, void (*init)(void), - int (*exec)(struct hv_kvp_msg *, void *)) -{ - int error = 0; - - if (key < 0 || key >= HV_KVP_OP_COUNT) { - KVP_LOG(LOG_ERR, "Operation key out of supported range\n"); - error = -1; - goto kvp_op_load_done; - } - - kvp_op_hdlrs[key].kvp_op_key = key; - kvp_op_hdlrs[key].kvp_op_init = init; - kvp_op_hdlrs[key].kvp_op_exec = exec; - - if (kvp_op_hdlrs[key].kvp_op_init != NULL) - kvp_op_hdlrs[key].kvp_op_init(); - -kvp_op_load_done: - return(error); -} - - -/* - * Initialize the operation hanlders. - */ -static int -kvp_ops_init(void) -{ - int i; - - /* Set the initial values. */ - for (i = 0; i < HV_KVP_OP_COUNT; i++) { - kvp_op_hdlrs[i].kvp_op_key = -1; - kvp_op_hdlrs[i].kvp_op_init = NULL; - kvp_op_hdlrs[i].kvp_op_exec = NULL; - } - - return(kvp_op_load(HV_KVP_OP_GET, NULL, kvp_op_setgetdel) | - kvp_op_load(HV_KVP_OP_SET, NULL, kvp_op_setgetdel) | - kvp_op_load(HV_KVP_OP_DELETE, NULL, kvp_op_setgetdel) | - kvp_op_load(HV_KVP_OP_ENUMERATE, kvp_get_os_info, - kvp_op_enumerate) | - kvp_op_load(HV_KVP_OP_GET_IP_INFO, NULL, kvp_op_getipinfo) | - kvp_op_load(HV_KVP_OP_SET_IP_INFO, NULL, kvp_op_setipinfo)); -} - - -int -main(int argc, char *argv[]) -{ - struct hv_kvp_msg *hv_kvp_dev_buf; - struct hv_kvp_msg *hv_msg; - struct pollfd hv_kvp_poll_fd[1]; - int op, pool; - int hv_kvp_dev_fd, error, len, r; - int ch; - - while ((ch = getopt(argc, argv, "dn")) != -1) { - switch (ch) { - case 'n': - /* Run as regular process for debugging purpose. */ - is_daemon = 0; - break; - case 'd': - /* Generate debugging output */ - is_debugging = 1; - break; - default: - break; - } - } - - openlog("HV_KVP", 0, LOG_USER); - - /* Become daemon first. */ - if (is_daemon == 1) - daemon(1, 0); - else - KVP_LOG(LOG_DEBUG, "Run as regular process.\n"); - - KVP_LOG(LOG_INFO, "HV_KVP starting; pid is: %d\n", getpid()); - - /* Communication buffer hv_kvp_dev_buf */ - hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf)); - /* Buffer for daemon internal use */ - hv_msg = malloc(sizeof(*hv_msg)); - - /* Memory allocation failed */ - if (hv_kvp_dev_buf == NULL || hv_msg == NULL) { - KVP_LOG(LOG_ERR, "Failed to allocate memory for hv buffer\n"); - exit(EXIT_FAILURE); - } - - /* Initialize op handlers */ - if (kvp_ops_init() != 0) { - KVP_LOG(LOG_ERR, "Failed to initizlize operation handlers\n"); - exit(EXIT_FAILURE); - } - - if (kvp_file_init()) { - KVP_LOG(LOG_ERR, "Failed to initialize the pools\n"); - exit(EXIT_FAILURE); - } - - /* Open the Character Device */ - hv_kvp_dev_fd = open("/dev/hv_kvp_dev", O_RDWR); - - if (hv_kvp_dev_fd < 0) { - KVP_LOG(LOG_ERR, "open /dev/hv_kvp_dev failed; error: %d %s\n", - errno, strerror(errno)); - exit(EXIT_FAILURE); - } - - /* Initialize the struct for polling the char device */ - hv_kvp_poll_fd[0].fd = hv_kvp_dev_fd; - hv_kvp_poll_fd[0].events = (POLLIN | POLLRDNORM); - - /* Register the daemon to the KVP driver */ - memset(hv_kvp_dev_buf, 0, sizeof(*hv_kvp_dev_buf)); - hv_kvp_dev_buf->hdr.kvp_hdr.operation = HV_KVP_OP_REGISTER; - len = write(hv_kvp_dev_fd, hv_kvp_dev_buf, sizeof(*hv_kvp_dev_buf)); - - - for (;;) { - r = poll (hv_kvp_poll_fd, 1, 100); - - KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n", - r, hv_kvp_poll_fd[0].revents); - - if (r == 0 || (r < 0 && errno == EAGAIN) || - (r < 0 && errno == EINTR)) { - /* Nothing to read */ - continue; - } - - if (r < 0) { - /* - * For pread return failure other than EAGAIN, - * we want to exit. - */ - KVP_LOG(LOG_ERR, "Poll failed.\n"); - perror("poll"); - exit(EIO); - } - - /* Read from character device */ - len = pread(hv_kvp_dev_fd, hv_kvp_dev_buf, - sizeof(*hv_kvp_dev_buf), 0); - - if (len < 0) { - KVP_LOG(LOG_ERR, "Read failed.\n"); - perror("pread"); - exit(EIO); - } - - if (len != sizeof(struct hv_kvp_msg)) { - KVP_LOG(LOG_ERR, "read len is: %d\n", len); - continue; - } - - /* Copy hv_kvp_dev_buf to hv_msg */ - memcpy(hv_msg, hv_kvp_dev_buf, sizeof(*hv_msg)); - - /* - * We will use the KVP header information to pass back - * the error from this daemon. So, first save the op - * and pool info to local variables. - */ - - op = hv_msg->hdr.kvp_hdr.operation; - pool = hv_msg->hdr.kvp_hdr.pool; - - if (op < 0 || op >= HV_KVP_OP_COUNT || - kvp_op_hdlrs[op].kvp_op_exec == NULL) { - KVP_LOG(LOG_WARNING, - "Unsupported operation OP = %d\n", op); - hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED; - } else { - /* - * Call the operateion handler's execution routine. - */ - error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, - (void *)&kvp_op_hdlrs[op]); - if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT) - KVP_LOG(LOG_WARNING, - "Operation failed OP = %d, error = 0x%x\n", - op, error); - } - - /* - * Send the value back to the kernel. The response is - * already in the receive buffer. - */ -hv_kvp_done: - len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0); - - if (len != sizeof(struct hv_kvp_msg)) { - KVP_LOG(LOG_ERR, "write len is: %d\n", len); - goto hv_kvp_done; - } - } -} diff --git a/contrib/hyperv/tools/scripts/hv_get_dhcp_info b/contrib/hyperv/tools/scripts/hv_get_dhcp_info deleted file mode 100644 index b56efd30f..000000000 --- a/contrib/hyperv/tools/scripts/hv_get_dhcp_info +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -# This is the script retrieves the DHCP state of a given interface. -# The kvp daemon code invokes this external script to gather -# DHCP setting for the specific interface. -# -# Input: Name of the interface -# -# Output: The script prints the string "Enabled" to stdout to indicate -# that DHCP is enabled on the interface. If DHCP is not enabled, -# the script prints the string "Disabled" to stdout. -# - -. /etc/rc.subr -. /etc/network.subr - -load_rc_config netif - -if dhcpif hn0; -then -echo "Enabled" -else -echo "Disabled" -fi diff --git a/contrib/hyperv/tools/scripts/hv_get_dns_info b/contrib/hyperv/tools/scripts/hv_get_dns_info deleted file mode 100644 index 7a34440fd..000000000 --- a/contrib/hyperv/tools/scripts/hv_get_dns_info +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -# This script parses /etc/resolv.conf to retrive DNS information. -# Khe kvp daemon code invokes this external script to gather -# DNS information. -# This script is expected to print the nameserver values to stdout. - -#if test -r /etc/resolv.conf -#then -# awk -- '/^nameserver/ { print $2 }' /etc/resolv.conf -#fi -cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }' - diff --git a/contrib/hyperv/tools/scripts/hv_set_ifconfig b/contrib/hyperv/tools/scripts/hv_set_ifconfig deleted file mode 100644 index 3dc42e7bb..000000000 --- a/contrib/hyperv/tools/scripts/hv_set_ifconfig +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh - -# This script activates an interface based on the specified -# configuration. The kvp daemon code invokes this external script -# to configure the interface. -# -# The only argument to this script is the configuration file that is to -# be used to configure the interface. -# -# Here is the format of the ip configuration file: -# -# HWADDR=macaddr -# IF_NAME=interface name -# DHCP=yes (This is optional; if yes, DHCP is configured) -# -# IPADDR=ipaddr1 -# IPADDR_1=ipaddr2 -# IPADDR_x=ipaddry (where y = x + 1) -# -# NETMASK=netmask1 -# NETMASK_x=netmasky (where y = x + 1) -# -# GATEWAY=ipaddr1 -# GATEWAY_x=ipaddry (where y = x + 1) -# -# DNSx=ipaddrx (where first DNS address is tagged as DNS1 etc) -# -# IPV6 addresses will be tagged as IPV6ADDR, IPV6 gateway will be -# tagged as IPV6_DEFAULTGW and IPV6 NETMASK will be tagged as -# IPV6NETMASK. -# -# 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 -# is expected to return the configuration that is set via the SET -# call. -# - -. $1 - -sed -i".bak" '/ifconfig_hn0="SYNCDHCP"/d' /etc/rc.conf -sed -i".bak" '/ifconfig_hn0="DHCP"/d' /etc/rc.conf - -# MAC Address -ifconfig $IF_NAME ether $HWADDR - -# IP and Subnet Mask -ifconfig $IF_NAME inet $IP_ADDR netmask $SUBNET - -# DNS -sed -i".bak" '/nameserver/d' /etc/resolv.conf -echo "nameserver" $DNS >> /etc/resolv.conf - -#Gateway -# Need to implment if Gateway is not present -route flush -route add default $GATEWAY -#route change default $GATEWAY - -#/etc/rc.d/netif restart -#/etc/rc.d/routing restart - - -# DHCP -if [ $DHCP -eq 1 ] -then - echo ifconfig_hn0=\"DHCP\" >> /etc/rc.conf - echo Enabled -else - echo Disabled DHCP >> /var/log/messages - echo Disabled -fi -echo "Set IP-Injection Success" diff --git a/etc/devd/Makefile b/etc/devd/Makefile index 50bc45788..433436b08 100644 --- a/etc/devd/Makefile +++ b/etc/devd/Makefile @@ -10,10 +10,6 @@ FILES+= apple.conf FILES+= asus.conf .endif -.if ${MK_HYPERV} != "no" -FILES+= hyperv.conf -.endif - NO_OBJ= FILESDIR= /etc/devd FILESMODE= 644 diff --git a/etc/devd/hyperv.conf b/etc/devd/hyperv.conf deleted file mode 100644 index bed7383d0..000000000 --- a/etc/devd/hyperv.conf +++ /dev/null @@ -1,19 +0,0 @@ -# $FreeBSD$ -# -# Hyper-V specific events - -notify 10 { - match "system" "DEVFS"; - match "subsystem" "CDEV"; - match "type" "CREATE"; - match "cdev" "hv_kvp_dev"; - action "/usr/sbin/hv_kvp_daemon"; -}; - -notify 10 { - match "system" "DEVFS"; - match "subsystem" "CDEV"; - match "type" "DESTROY"; - match "cdev" "hv_kvp_dev"; - action "pkill -x hv_kvp_daemon"; -}; diff --git a/etc/mtree/BSD.usr.dist b/etc/mtree/BSD.usr.dist index a310e88eb..2c4085373 100644 --- a/etc/mtree/BSD.usr.dist +++ b/etc/mtree/BSD.usr.dist @@ -108,8 +108,6 @@ .. bsdinstall .. - hyperv - .. lpr ru .. diff --git a/etc/mtree/BSD.var.dist b/etc/mtree/BSD.var.dist index 240381449..ba02aba44 100644 --- a/etc/mtree/BSD.var.dist +++ b/etc/mtree/BSD.var.dist @@ -42,8 +42,6 @@ .. freebsd-update mode=0700 .. - hyperv mode=0700 - .. ipf mode=0700 .. pkg diff --git a/libexec/Makefile b/libexec/Makefile index 66e24261e..cf5c12016 100644 --- a/libexec/Makefile +++ b/libexec/Makefile @@ -10,7 +10,6 @@ SUBDIR= ${_atf} \ fingerd \ ftpd \ getty \ - ${_hyperv} \ ${_mail.local} \ ${_mknetid} \ ${_pppoed} \ @@ -43,10 +42,6 @@ _atrun= atrun _comsat= comsat .endif -.if ${MK_HYPERV} != "no" -_hyperv= hyperv -.endif - .if ${MK_NIS} != "no" _mknetid= mknetid _ypxfr= ypxfr diff --git a/libexec/hyperv/Makefile b/libexec/hyperv/Makefile deleted file mode 100644 index 37abdf5b8..000000000 --- a/libexec/hyperv/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $FreeBSD$ - -.PATH: ${.CURDIR}/../../contrib/hyperv/tools/scripts - -BINDIR= /usr/libexec/hyperv - -SCRIPTS= hv_set_ifconfig hv_get_dns_info hv_get_dhcp_info -NO_OBJ= - -.include diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index f043cab9c..444a909b9 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -438,12 +438,6 @@ __DEFAULT_YES_OPTIONS+=FDT .else __DEFAULT_NO_OPTIONS+=FDT .endif -# HyperV is only available for x86 and amd64. -.if ${__T} == "amd64" || ${__T} == "i386" -__DEFAULT_YES_OPTIONS+=HYPERV -.else -__DEFAULT_NO_OPTIONS+=HYPERV -.endif .undef __T # diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 4d5cb6082..28f9619a1 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -234,7 +234,6 @@ dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv -dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 2446a7bd7..43b0e5b38 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -227,7 +227,6 @@ dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c optional hyperv dev/hyperv/netvsc/hv_rndis_filter.c optional hyperv dev/hyperv/stordisengage/hv_ata_pci_disengage.c optional hyperv dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c optional hyperv -dev/hyperv/utilities/hv_kvp.c optional hyperv dev/hyperv/utilities/hv_util.c optional hyperv dev/hyperv/vmbus/hv_channel.c optional hyperv dev/hyperv/vmbus/hv_channel_mgmt.c optional hyperv diff --git a/sys/dev/hyperv/include/hyperv.h b/sys/dev/hyperv/include/hyperv.h index 8a45d89cd..4257b371c 100644 --- a/sys/dev/hyperv/include/hyperv.h +++ b/sys/dev/hyperv/include/hyperv.h @@ -795,34 +795,5 @@ hv_get_phys_addr(void *virt) return (ret); } - -/** - * KVP related structures - * - */ -typedef struct hv_vmbus_service { - hv_guid guid; /* Hyper-V GUID */ - char *name; /* name of service */ - boolean_t enabled; /* service enabled */ - hv_work_queue *work_queue; /* background work queue */ - - /* - * function to initialize service - */ - int (*init)(struct hv_vmbus_service *); - - /* - * function to process Hyper-V messages - */ - void (*callback)(void *); -} hv_vmbus_service; - -extern uint8_t* receive_buffer[]; -extern hv_vmbus_service service_table[]; - -void hv_kvp_callback(void *context); -int hv_kvp_init(hv_vmbus_service *serv); -void hv_kvp_deinit(void); - #endif /* __HYPERV_H__ */ diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c deleted file mode 100644 index 848d364a4..000000000 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ /dev/null @@ -1,1001 +0,0 @@ -/*- - * Copyright (c) 2014 Microsoft Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice unmodified, this list of conditions, and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Author: Sainath Varanasi. - * Date: 4/2012 - * Email: bsdic@microsoft.com - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "unicode.h" -#include "hv_kvp.h" - -/* hv_kvp defines */ -#define BUFFERSIZE sizeof(struct hv_kvp_msg) -#define KVP_SUCCESS 0 -#define KVP_ERROR 1 -#define kvp_hdr hdr.kvp_hdr - -/* hv_kvp debug control */ -static int hv_kvp_log = 0; -SYSCTL_INT(_dev, OID_AUTO, hv_kvp_log, CTLFLAG_RW, &hv_kvp_log, 0, - "hv_kvp log"); - -#define hv_kvp_log_error(...) do { \ - if (hv_kvp_log > 0) \ - log(LOG_ERR, "hv_kvp: " __VA_ARGS__); \ -} while (0) - -#define hv_kvp_log_info(...) do { \ - if (hv_kvp_log > 1) \ - log(LOG_INFO, "hv_kvp: " __VA_ARGS__); \ -} while (0) - -/* character device prototypes */ -static d_open_t hv_kvp_dev_open; -static d_close_t hv_kvp_dev_close; -static d_read_t hv_kvp_dev_daemon_read; -static d_write_t hv_kvp_dev_daemon_write; -static d_poll_t hv_kvp_dev_daemon_poll; - -/* hv_kvp prototypes */ -static int hv_kvp_req_in_progress(void); -static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *); -static void hv_kvp_send_msg_to_daemon(void); -static void hv_kvp_process_request(void *context); - -/* hv_kvp character device structure */ -static struct cdevsw hv_kvp_cdevsw = -{ - .d_version = D_VERSION, - .d_open = hv_kvp_dev_open, - .d_close = hv_kvp_dev_close, - .d_read = hv_kvp_dev_daemon_read, - .d_write = hv_kvp_dev_daemon_write, - .d_poll = hv_kvp_dev_daemon_poll, - .d_name = "hv_kvp_dev", -}; -static struct cdev *hv_kvp_dev; -static struct hv_kvp_msg *hv_kvp_dev_buf; -struct proc *daemon_task; - -/* - * Global state to track and synchronize multiple - * KVP transaction requests from the host. - */ -static struct { - - /* Pre-allocated work item for queue */ - hv_work_item work_item; - - /* Unless specified the pending mutex should be - * used to alter the values of the following paramters: - * 1. req_in_progress - * 2. req_timed_out - * 3. pending_reqs. - */ - struct mtx pending_mutex; - - /* To track if transaction is active or not */ - boolean_t req_in_progress; - /* Tracks if daemon did not reply back in time */ - boolean_t req_timed_out; - /* Tracks if daemon is serving a request currently */ - boolean_t daemon_busy; - /* Count of KVP requests from Hyper-V. */ - uint64_t pending_reqs; - - - /* Length of host message */ - uint32_t host_msg_len; - - /* Pointer to channel */ - hv_vmbus_channel *channelp; - - /* Host message id */ - uint64_t host_msg_id; - - /* Current kvp message from the host */ - struct hv_kvp_msg *host_kvp_msg; - - /* Current kvp message for daemon */ - struct hv_kvp_msg daemon_kvp_msg; - - /* Rcv buffer for communicating with the host*/ - uint8_t *rcv_buf; - - /* Device semaphore to control communication */ - struct sema dev_sema; - - /* Indicates if daemon registered with driver */ - boolean_t register_done; - - /* Character device status */ - boolean_t dev_accessed; -} kvp_globals; - -/* global vars */ -MALLOC_DECLARE(M_HV_KVP_DEV_BUF); -MALLOC_DEFINE(M_HV_KVP_DEV_BUF, "hv_kvp_dev buffer", "buffer for hv_kvp_dev module"); - -/* - * hv_kvp low level functions - */ - -/* - * Check if kvp transaction is in progres - */ -static int -hv_kvp_req_in_progress(void) -{ - - return (kvp_globals.req_in_progress); -} - - -/* - * This routine is called whenever a message is received from the host - */ -static void -hv_kvp_transaction_init(uint32_t rcv_len, hv_vmbus_channel *rcv_channel, - uint64_t request_id, uint8_t *rcv_buf) -{ - - /* Store all the relevant message details in the global structure */ - /* Do not need to use mutex for req_in_progress here */ - kvp_globals.req_in_progress = true; - kvp_globals.host_msg_len = rcv_len; - kvp_globals.channelp = rcv_channel; - kvp_globals.host_msg_id = request_id; - kvp_globals.rcv_buf = rcv_buf; - kvp_globals.host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[ - sizeof(struct hv_vmbus_pipe_hdr) + - sizeof(struct hv_vmbus_icmsg_hdr)]; -} - - -/* - * hv_kvp - version neogtiation function - */ -static void -hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, - struct hv_vmbus_icmsg_negotiate *negop, - uint8_t *buf) -{ - int icframe_vercnt; - int icmsg_vercnt; - - icmsghdrp->icmsgsize = 0x10; - - negop = (struct hv_vmbus_icmsg_negotiate *)&buf[ - sizeof(struct hv_vmbus_pipe_hdr) + - sizeof(struct hv_vmbus_icmsg_hdr)]; - icframe_vercnt = negop->icframe_vercnt; - icmsg_vercnt = negop->icmsg_vercnt; - - /* - * Select the framework version number we will support - */ - if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) { - icframe_vercnt = 3; - if (icmsg_vercnt >= 2) - icmsg_vercnt = 4; - else - icmsg_vercnt = 3; - } else { - icframe_vercnt = 1; - icmsg_vercnt = 1; - } - - negop->icframe_vercnt = 1; - negop->icmsg_vercnt = 1; - negop->icversion_data[0].major = icframe_vercnt; - negop->icversion_data[0].minor = 0; - negop->icversion_data[1].major = icmsg_vercnt; - negop->icversion_data[1].minor = 0; -} - - -/* - * Convert ip related info in umsg from utf8 to utf16 and store in hmsg - */ -static int -hv_kvp_convert_utf8_ipinfo_to_utf16(struct hv_kvp_msg *umsg, - struct hv_kvp_ip_msg *host_ip_msg) -{ - int err_ip, err_subnet, err_gway, err_dns, err_adap; - int UNUSED_FLAG = 1; - - utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE, - (char *)umsg->body.kvp_ip_val.ip_addr, - strlen((char *)umsg->body.kvp_ip_val.ip_addr), - UNUSED_FLAG, - &err_ip); - utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.sub_net, - MAX_IP_ADDR_SIZE, - (char *)umsg->body.kvp_ip_val.sub_net, - strlen((char *)umsg->body.kvp_ip_val.sub_net), - UNUSED_FLAG, - &err_subnet); - utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.gate_way, - MAX_GATEWAY_SIZE, - (char *)umsg->body.kvp_ip_val.gate_way, - strlen((char *)umsg->body.kvp_ip_val.gate_way), - UNUSED_FLAG, - &err_gway); - utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, - MAX_IP_ADDR_SIZE, - (char *)umsg->body.kvp_ip_val.dns_addr, - strlen((char *)umsg->body.kvp_ip_val.dns_addr), - UNUSED_FLAG, - &err_dns); - utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, - MAX_IP_ADDR_SIZE, - (char *)umsg->body.kvp_ip_val.adapter_id, - strlen((char *)umsg->body.kvp_ip_val.adapter_id), - UNUSED_FLAG, - &err_adap); - - host_ip_msg->kvp_ip_val.dhcp_enabled = umsg->body.kvp_ip_val.dhcp_enabled; - host_ip_msg->kvp_ip_val.addr_family = umsg->body.kvp_ip_val.addr_family; - - return (err_ip | err_subnet | err_gway | err_dns | err_adap); -} - - -/* - * Convert ip related info in hmsg from utf16 to utf8 and store in umsg - */ -static int -hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, - struct hv_kvp_msg *umsg) -{ - int err_ip, err_subnet, err_gway, err_dns, err_adap; - int UNUSED_FLAG = 1; - int guid_index; - struct hv_device *hv_dev; /* GUID Data Structure */ - hn_softc_t *sc; /* hn softc structure */ - char if_name[4]; - unsigned char guid_instance[40]; - char *guid_data = NULL; - char buf[39]; - - struct guid_extract { - char a1[2]; - char a2[2]; - char a3[2]; - char a4[2]; - char b1[2]; - char b2[2]; - char c1[2]; - char c2[2]; - char d[4]; - char e[12]; - }; - - struct guid_extract *id; - device_t *devs; - int devcnt; - - /* IP Address */ - utf16_to_utf8((char *)umsg->body.kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, - MAX_IP_ADDR_SIZE, - UNUSED_FLAG, - &err_ip); - - /* Adapter ID : GUID */ - utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE, - UNUSED_FLAG, - &err_adap); - - if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) { - for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) { - sc = device_get_softc(devs[devcnt]); - - /* Trying to find GUID of Network Device */ - hv_dev = sc->hn_dev_obj; - - for (guid_index = 0; guid_index < 16; guid_index++) { - sprintf(&guid_instance[guid_index * 2], "%02x", - hv_dev->device_id.data[guid_index]); - } - - guid_data = (char *)guid_instance; - id = (struct guid_extract *)guid_data; - snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}", - id->a4, id->a3, id->a2, id->a1, - id->b2, id->b1, id->c2, id->c1, id->d, id->e); - guid_data = NULL; - sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt])); - - if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) { - strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name); - break; - } - } - free(devs, M_TEMP); - } - - /* Address Family , DHCP , SUBNET, Gateway, DNS */ - umsg->kvp_hdr.operation = host_ip_msg->operation; - umsg->body.kvp_ip_val.addr_family = host_ip_msg->kvp_ip_val.addr_family; - umsg->body.kvp_ip_val.dhcp_enabled = host_ip_msg->kvp_ip_val.dhcp_enabled; - utf16_to_utf8((char *)umsg->body.kvp_ip_val.sub_net, MAX_IP_ADDR_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.sub_net, - MAX_IP_ADDR_SIZE, - UNUSED_FLAG, - &err_subnet); - - utf16_to_utf8((char *)umsg->body.kvp_ip_val.gate_way, MAX_GATEWAY_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.gate_way, - MAX_GATEWAY_SIZE, - UNUSED_FLAG, - &err_gway); - - utf16_to_utf8((char *)umsg->body.kvp_ip_val.dns_addr, MAX_IP_ADDR_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, - MAX_IP_ADDR_SIZE, - UNUSED_FLAG, - &err_dns); - - return (err_ip | err_subnet | err_gway | err_dns | err_adap); -} - - -/* - * Prepare a user kvp msg based on host kvp msg (utf16 to utf8) - * Ensure utf16_utf8 takes care of the additional string terminating char!! - */ -static void -hv_kvp_convert_hostmsg_to_usermsg(void) -{ - int utf_err = 0; - uint32_t value_type; - struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *) - kvp_globals.host_kvp_msg; - - struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; - struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; - - memset(umsg, 0, sizeof(struct hv_kvp_msg)); - - umsg->kvp_hdr.operation = hmsg->kvp_hdr.operation; - umsg->kvp_hdr.pool = hmsg->kvp_hdr.pool; - - switch (umsg->kvp_hdr.operation) { - case HV_KVP_OP_SET_IP_INFO: - hv_kvp_convert_utf16_ipinfo_to_utf8(host_ip_msg, umsg); - break; - - case HV_KVP_OP_GET_IP_INFO: - utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE, - (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, - MAX_ADAPTER_ID_SIZE, 1, &utf_err); - - umsg->body.kvp_ip_val.addr_family = - host_ip_msg->kvp_ip_val.addr_family; - break; - - case HV_KVP_OP_SET: - value_type = hmsg->body.kvp_set.data.value_type; - - switch (value_type) { - case HV_REG_SZ: - umsg->body.kvp_set.data.value_size = - utf16_to_utf8( - (char *)umsg->body.kvp_set.data.msg_value.value, - HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1, - (uint16_t *)hmsg->body.kvp_set.data.msg_value.value, - hmsg->body.kvp_set.data.value_size, - 1, &utf_err); - /* utf8 encoding */ - umsg->body.kvp_set.data.value_size = - umsg->body.kvp_set.data.value_size / 2; - break; - - case HV_REG_U32: - umsg->body.kvp_set.data.value_size = - sprintf(umsg->body.kvp_set.data.msg_value.value, "%d", - hmsg->body.kvp_set.data.msg_value.value_u32) + 1; - break; - - case HV_REG_U64: - umsg->body.kvp_set.data.value_size = - sprintf(umsg->body.kvp_set.data.msg_value.value, "%llu", - (unsigned long long) - hmsg->body.kvp_set.data.msg_value.value_u64) + 1; - break; - } - - umsg->body.kvp_set.data.key_size = - utf16_to_utf8( - umsg->body.kvp_set.data.key, - HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, - (uint16_t *)hmsg->body.kvp_set.data.key, - hmsg->body.kvp_set.data.key_size, - 1, &utf_err); - - /* utf8 encoding */ - umsg->body.kvp_set.data.key_size = - umsg->body.kvp_set.data.key_size / 2; - break; - - case HV_KVP_OP_GET: - umsg->body.kvp_get.data.key_size = - utf16_to_utf8(umsg->body.kvp_get.data.key, - HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, - (uint16_t *)hmsg->body.kvp_get.data.key, - hmsg->body.kvp_get.data.key_size, - 1, &utf_err); - /* utf8 encoding */ - umsg->body.kvp_get.data.key_size = - umsg->body.kvp_get.data.key_size / 2; - break; - - case HV_KVP_OP_DELETE: - umsg->body.kvp_delete.key_size = - utf16_to_utf8(umsg->body.kvp_delete.key, - HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, - (uint16_t *)hmsg->body.kvp_delete.key, - hmsg->body.kvp_delete.key_size, - 1, &utf_err); - /* utf8 encoding */ - umsg->body.kvp_delete.key_size = - umsg->body.kvp_delete.key_size / 2; - break; - - case HV_KVP_OP_ENUMERATE: - umsg->body.kvp_enum_data.index = - hmsg->body.kvp_enum_data.index; - break; - - default: - hv_kvp_log_info("%s: daemon_kvp_msg: Invalid operation : %d\n", - __func__, umsg->kvp_hdr.operation); - } -} - - -/* - * Prepare a host kvp msg based on user kvp msg (utf8 to utf16) - */ -static int -hv_kvp_convert_usermsg_to_hostmsg(void) -{ - int hkey_len = 0, hvalue_len = 0, utf_err = 0; - struct hv_kvp_exchg_msg_value *host_exchg_data; - char *key_name, *value; - - struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; - struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; - struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)hmsg; - - switch (hmsg->kvp_hdr.operation) { - case HV_KVP_OP_GET_IP_INFO: - return (hv_kvp_convert_utf8_ipinfo_to_utf16(umsg, host_ip_msg)); - - case HV_KVP_OP_SET_IP_INFO: - case HV_KVP_OP_SET: - case HV_KVP_OP_DELETE: - return (KVP_SUCCESS); - - case HV_KVP_OP_ENUMERATE: - host_exchg_data = &hmsg->body.kvp_enum_data.data; - key_name = umsg->body.kvp_enum_data.data.key; - hkey_len = utf8_to_utf16((uint16_t *)host_exchg_data->key, - ((HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2), - key_name, strlen(key_name), - 1, &utf_err); - /* utf16 encoding */ - host_exchg_data->key_size = 2 * (hkey_len + 1); - value = umsg->body.kvp_enum_data.data.msg_value.value; - hvalue_len = utf8_to_utf16( - (uint16_t *)host_exchg_data->msg_value.value, - ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), - value, strlen(value), - 1, &utf_err); - host_exchg_data->value_size = 2 * (hvalue_len + 1); - host_exchg_data->value_type = HV_REG_SZ; - - if ((hkey_len < 0) || (hvalue_len < 0)) - return (HV_KVP_E_FAIL); - - return (KVP_SUCCESS); - - case HV_KVP_OP_GET: - host_exchg_data = &hmsg->body.kvp_get.data; - value = umsg->body.kvp_get.data.msg_value.value; - hvalue_len = utf8_to_utf16( - (uint16_t *)host_exchg_data->msg_value.value, - ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), - value, strlen(value), - 1, &utf_err); - /* Convert value size to uft16 */ - host_exchg_data->value_size = 2 * (hvalue_len + 1); - /* Use values by string */ - host_exchg_data->value_type = HV_REG_SZ; - - if ((hkey_len < 0) || (hvalue_len < 0)) - return (HV_KVP_E_FAIL); - - return (KVP_SUCCESS); - - default: - return (HV_KVP_E_FAIL); - } -} - - -/* - * Send the response back to the host. - */ -static void -hv_kvp_respond_host(int error) -{ - struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp; - - hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *) - &kvp_globals.rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)]; - - if (error) - error = HV_KVP_E_FAIL; - - hv_icmsg_hdrp->status = error; - hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; - - error = hv_vmbus_channel_send_packet(kvp_globals.channelp, - kvp_globals.rcv_buf, - kvp_globals.host_msg_len, kvp_globals.host_msg_id, - HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); - - if (error) - hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n", - __func__, error); -} - - -/* - * This is the main kvp kernel process that interacts with both user daemon - * and the host - */ -static void -hv_kvp_send_msg_to_daemon(void) -{ - /* Prepare kvp_msg to be sent to user */ - hv_kvp_convert_hostmsg_to_usermsg(); - - /* Send the msg to user via function deamon_read - setting sema */ - sema_post(&kvp_globals.dev_sema); -} - - -/* - * Function to read the kvp request buffer from host - * and interact with daemon - */ -static void -hv_kvp_process_request(void *context) -{ - uint8_t *kvp_buf; - hv_vmbus_channel *channel = context; - uint32_t recvlen = 0; - uint64_t requestid; - struct hv_vmbus_icmsg_hdr *icmsghdrp; - int ret = 0; - uint64_t pending_cnt = 1; - - hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__); - kvp_buf = receive_buffer[HV_KVP]; - ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, - &recvlen, &requestid); - - /* - * We start counting only after the daemon registers - * and therefore there could be requests pending in - * the VMBus that are not reflected in pending_cnt. - * Therefore we continue reading as long as either of - * the below conditions is true. - */ - - while ((pending_cnt>0) || ((ret == 0) && (recvlen > 0))) { - - if ((ret == 0) && (recvlen>0)) { - - icmsghdrp = (struct hv_vmbus_icmsg_hdr *) - &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)]; - - hv_kvp_transaction_init(recvlen, channel, requestid, kvp_buf); - if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { - hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf); - hv_kvp_respond_host(ret); - - /* - * It is ok to not acquire the mutex before setting - * req_in_progress here because negotiation is the - * first thing that happens and hence there is no - * chance of a race condition. - */ - - kvp_globals.req_in_progress = false; - hv_kvp_log_info("%s :version negotiated\n", __func__); - - } else { - if (!kvp_globals.daemon_busy) { - - hv_kvp_log_info("%s: issuing qury to daemon\n", __func__); - mtx_lock(&kvp_globals.pending_mutex); - kvp_globals.req_timed_out = false; - kvp_globals.daemon_busy = true; - mtx_unlock(&kvp_globals.pending_mutex); - - hv_kvp_send_msg_to_daemon(); - hv_kvp_log_info("%s: waiting for daemon\n", __func__); - } - - /* Wait 5 seconds for daemon to respond back */ - tsleep(&kvp_globals, 0, "kvpworkitem", 5 * hz); - hv_kvp_log_info("%s: came out of wait\n", __func__); - } - } - - mtx_lock(&kvp_globals.pending_mutex); - - /* Notice that once req_timed_out is set to true - * it will remain true until the next request is - * sent to the daemon. The response from daemon - * is forwarded to host only when this flag is - * false. - */ - kvp_globals.req_timed_out = true; - - /* - * Cancel request if so need be. - */ - if (hv_kvp_req_in_progress()) { - hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__); - hv_kvp_respond_host(HV_KVP_E_FAIL); - kvp_globals.req_in_progress = false; - } - - /* - * Decrement pending request count and - */ - if (kvp_globals.pending_reqs>0) { - kvp_globals.pending_reqs = kvp_globals.pending_reqs - 1; - } - pending_cnt = kvp_globals.pending_reqs; - - mtx_unlock(&kvp_globals.pending_mutex); - - /* - * Try reading next buffer - */ - recvlen = 0; - ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, - &recvlen, &requestid); - hv_kvp_log_info("%s: read: context %p, pending_cnt %ju ret =%d, recvlen=%d\n", - __func__, context, pending_cnt, ret, recvlen); - } -} - - -/* - * Callback routine that gets called whenever there is a message from host - */ -void -hv_kvp_callback(void *context) -{ - uint64_t pending_cnt = 0; - - if (kvp_globals.register_done == false) { - - kvp_globals.channelp = context; - } else { - - mtx_lock(&kvp_globals.pending_mutex); - kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1; - pending_cnt = kvp_globals.pending_reqs; - mtx_unlock(&kvp_globals.pending_mutex); - if (pending_cnt == 1) { - hv_kvp_log_info("%s: Queuing work item\n", __func__); - hv_queue_work_item( - service_table[HV_KVP].work_queue, - hv_kvp_process_request, - context - ); - } - } -} - - -/* - * This function is called by the hv_kvp_init - - * creates character device hv_kvp_dev - * allocates memory to hv_kvp_dev_buf - * - */ -static int -hv_kvp_dev_init(void) -{ - int error = 0; - - /* initialize semaphore */ - sema_init(&kvp_globals.dev_sema, 0, "hv_kvp device semaphore"); - /* create character device */ - error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, - &hv_kvp_dev, - &hv_kvp_cdevsw, - 0, - UID_ROOT, - GID_WHEEL, - 0640, - "hv_kvp_dev"); - - if (error != 0) - return (error); - - /* - * Malloc with M_WAITOK flag will never fail. - */ - hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_HV_KVP_DEV_BUF, M_WAITOK | - M_ZERO); - - return (0); -} - - -/* - * This function is called by the hv_kvp_deinit - - * destroy character device - */ -static void -hv_kvp_dev_destroy(void) -{ - - if (daemon_task != NULL) { - PROC_LOCK(daemon_task); - kern_psignal(daemon_task, SIGKILL); - PROC_UNLOCK(daemon_task); - } - - destroy_dev(hv_kvp_dev); - free(hv_kvp_dev_buf, M_HV_KVP_DEV_BUF); - return; -} - - -static int -hv_kvp_dev_open(struct cdev *dev, int oflags, int devtype, - struct thread *td) -{ - - hv_kvp_log_info("%s: Opened device \"hv_kvp_device\" successfully.\n", __func__); - if (kvp_globals.dev_accessed) - return (-EBUSY); - - daemon_task = curproc; - kvp_globals.dev_accessed = true; - kvp_globals.daemon_busy = false; - return (0); -} - - -static int -hv_kvp_dev_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, - struct thread *td __unused) -{ - - hv_kvp_log_info("%s: Closing device \"hv_kvp_device\".\n", __func__); - kvp_globals.dev_accessed = false; - kvp_globals.register_done = false; - return (0); -} - - -/* - * hv_kvp_daemon read invokes this function - * acts as a send to daemon - */ -static int -hv_kvp_dev_daemon_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) -{ - size_t amt; - int error = 0; - - /* Check hv_kvp daemon registration status*/ - if (!kvp_globals.register_done) - return (KVP_ERROR); - - sema_wait(&kvp_globals.dev_sema); - - memcpy(hv_kvp_dev_buf, &kvp_globals.daemon_kvp_msg, sizeof(struct hv_kvp_msg)); - - amt = MIN(uio->uio_resid, uio->uio_offset >= BUFFERSIZE + 1 ? 0 : - BUFFERSIZE + 1 - uio->uio_offset); - - if ((error = uiomove(hv_kvp_dev_buf, amt, uio)) != 0) - hv_kvp_log_info("%s: hv_kvp uiomove read failed!\n", __func__); - - return (error); -} - - -/* - * hv_kvp_daemon write invokes this function - * acts as a recieve from daemon - */ -static int -hv_kvp_dev_daemon_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) -{ - size_t amt; - int error = 0; - - uio->uio_offset = 0; - - amt = MIN(uio->uio_resid, BUFFERSIZE); - error = uiomove(hv_kvp_dev_buf, amt, uio); - - if (error != 0) - return (error); - - memcpy(&kvp_globals.daemon_kvp_msg, hv_kvp_dev_buf, sizeof(struct hv_kvp_msg)); - - if (kvp_globals.register_done == false) { - if (kvp_globals.daemon_kvp_msg.kvp_hdr.operation == HV_KVP_OP_REGISTER) { - - kvp_globals.register_done = true; - if (kvp_globals.channelp) { - - hv_kvp_callback(kvp_globals.channelp); - } - } - else { - hv_kvp_log_info("%s, KVP Registration Failed\n", __func__); - return (KVP_ERROR); - } - } else { - - mtx_lock(&kvp_globals.pending_mutex); - - if(!kvp_globals.req_timed_out) { - - hv_kvp_convert_usermsg_to_hostmsg(); - hv_kvp_respond_host(KVP_SUCCESS); - wakeup(&kvp_globals); - kvp_globals.req_in_progress = false; - } - - kvp_globals.daemon_busy = false; - mtx_unlock(&kvp_globals.pending_mutex); - } - - return (error); -} - - -/* - * hv_kvp_daemon poll invokes this function to check if data is available - * for daemon to read. - */ -static int -hv_kvp_dev_daemon_poll(struct cdev *dev __unused, int events, struct thread *td __unused) -{ - int revents = 0; - - mtx_lock(&kvp_globals.pending_mutex); - /* - * We check global flag daemon_busy for the data availiability for - * userland to read. Deamon_busy is set to true before driver has data - * for daemon to read. It is set to false after daemon sends - * then response back to driver. - */ - if (kvp_globals.daemon_busy == true) - revents = POLLIN; - mtx_unlock(&kvp_globals.pending_mutex); - - return (revents); -} - - -/* - * hv_kvp initialization function - * called from hv_util service. - * - */ -int -hv_kvp_init(hv_vmbus_service *srv) -{ - int error = 0; - hv_work_queue *work_queue = NULL; - - memset(&kvp_globals, 0, sizeof(kvp_globals)); - - work_queue = hv_work_queue_create("KVP Service"); - if (work_queue == NULL) { - hv_kvp_log_info("%s: Work queue alloc failed\n", __func__); - error = ENOMEM; - hv_kvp_log_error("%s: ENOMEM\n", __func__); - goto Finish; - } - srv->work_queue = work_queue; - - error = hv_kvp_dev_init(); - mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex", - NULL, MTX_DEF); - kvp_globals.pending_reqs = 0; - - -Finish: - return (error); -} - - -void -hv_kvp_deinit(void) -{ - hv_kvp_dev_destroy(); - mtx_destroy(&kvp_globals.pending_mutex); - - return; -} diff --git a/sys/dev/hyperv/utilities/hv_kvp.h b/sys/dev/hyperv/utilities/hv_kvp.h index b67373fa7..f7dccf77d 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.h +++ b/sys/dev/hyperv/utilities/hv_kvp.h @@ -1,5 +1,7 @@ /*- - * Copyright (c) 2014 Microsoft Corp. + * Copyright (c) 2009-2012 Microsoft Corp. + * Copyright (c) 2012 NetApp Inc. + * Copyright (c) 2012 Citrix Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,15 +24,13 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ #ifndef _KVP_H #define _KVP_H /* - * An implementation of HyperV key value pair (KVP) functionality for FreeBSD + * An implementation of HyperV key value pair (KVP) functionality for FreeBSD * */ @@ -53,15 +53,15 @@ /* * bytes, including any null terminators */ -#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) +#define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) /* * Maximum key size - the registry limit for the length of an entry name * is 256 characters, including the null terminator */ -#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) +#define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) /* * In FreeBSD, we implement the KVP functionality in two components: @@ -111,20 +111,30 @@ * (not supported), a NULL key string is returned. */ - + /* * Registry value types. */ -#define HV_REG_SZ 1 -#define HV_REG_U32 4 -#define HV_REG_U64 8 +#define HV_REG_SZ 1 +#define HV_REG_U32 4 +#define HV_REG_U64 8 + + +/* + * Daemon code not supporting IP injection (legacy daemon). + */ + +#define HV_KVP_OP_REGISTER 4 /* * Daemon code supporting IP injection. + * The KVP opcode field is used to communicate the + * registration information; so define a namespace that + * will be distinct from the host defined KVP opcode. */ -#define HV_KVP_OP_REGISTER 4 +#define KVP_OP_REGISTER1 100 enum hv_kvp_exchg_op { HV_KVP_OP_GET = 0, @@ -145,41 +155,41 @@ enum hv_kvp_exchg_pool { HV_KVP_POOL_COUNT /* Number of pools, must be last. */ }; - /* * Some Hyper-V status codes. */ -#define HV_KVP_S_OK 0x00000000 -#define HV_KVP_E_FAIL 0x80004005 -#define HV_KVP_S_CONT 0x80070103 -#define HV_ERROR_NOT_SUPPORTED 0x80070032 -#define HV_ERROR_MACHINE_LOCKED 0x800704F7 -#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F -#define HV_INVALIDARG 0x80070057 -#define HV_KVP_GUID_NOTFOUND 0x80041002 +#define HV_KVP_S_OK 0x00000000 +#define HV_KVP_E_FAIL 0x80004005 +#define HV_KVP_S_CONT 0x80070103 +#define HV_ERROR_NOT_SUPPORTED 0x80070032 +#define HV_ERROR_MACHINE_LOCKED 0x800704F7 +#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F +#define HV_INVALIDARG 0x80070057 +#define HV_KVP_GUID_NOTFOUND 0x80041002 -#define ADDR_FAMILY_NONE 0x00 -#define ADDR_FAMILY_IPV4 0x01 -#define ADDR_FAMILY_IPV6 0x02 +#define ADDR_FAMILY_NONE 0x00 +#define ADDR_FAMILY_IPV4 0x01 +#define ADDR_FAMILY_IPV6 0x02 -#define MAX_ADAPTER_ID_SIZE 128 -#define MAX_IP_ADDR_SIZE 1024 -#define MAX_GATEWAY_SIZE 512 +#define MAX_ADAPTER_ID_SIZE 128 +#define MAX_IP_ADDR_SIZE 1024 +#define MAX_GATEWAY_SIZE 512 struct hv_kvp_ipaddr_value { - uint16_t adapter_id[MAX_ADAPTER_ID_SIZE]; - uint8_t addr_family; - uint8_t dhcp_enabled; - uint16_t ip_addr[MAX_IP_ADDR_SIZE]; - uint16_t sub_net[MAX_IP_ADDR_SIZE]; - uint16_t gate_way[MAX_GATEWAY_SIZE]; - uint16_t dns_addr[MAX_IP_ADDR_SIZE]; -}__attribute__((packed)); + uint16_t adapter_id[MAX_ADAPTER_ID_SIZE]; + uint8_t addr_family; + uint8_t dhcp_enabled; + uint16_t ip_addr[MAX_IP_ADDR_SIZE]; + uint16_t sub_net[MAX_IP_ADDR_SIZE]; + uint16_t gate_way[MAX_GATEWAY_SIZE]; + uint16_t dns_addr[MAX_IP_ADDR_SIZE]; +} __attribute__((packed)); + struct hv_kvp_hdr { - uint8_t operation; - uint8_t pool; + uint8_t operation; + uint8_t pool; uint16_t pad; } __attribute__((packed)); @@ -187,9 +197,9 @@ struct hv_kvp_exchg_msg_value { uint32_t value_type; uint32_t key_size; uint32_t value_size; - uint8_t key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; + uint8_t key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; union { - uint8_t value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; + uint8_t value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; uint32_t value_u32; uint64_t value_u64; } msg_value; @@ -219,16 +229,16 @@ struct hv_kvp_register { struct hv_kvp_msg { union { - struct hv_kvp_hdr kvp_hdr; - uint32_t error; + struct hv_kvp_hdr kvp_hdr; + int error; } hdr; union { - struct hv_kvp_msg_get kvp_get; - struct hv_kvp_msg_set kvp_set; + struct hv_kvp_msg_get kvp_get; + struct hv_kvp_msg_set kvp_set; struct hv_kvp_msg_delete kvp_delete; struct hv_kvp_msg_enumerate kvp_enum_data; - struct hv_kvp_ipaddr_value kvp_ip_val; - struct hv_kvp_register kvp_register; + struct hv_kvp_ipaddr_value kvp_ip_val; + struct hv_kvp_register kvp_register; } body; } __attribute__((packed)); @@ -238,17 +248,38 @@ struct hv_kvp_ip_msg { struct hv_kvp_ipaddr_value kvp_ip_val; } __attribute__((packed)); - -#define HV_SHUT_DOWN 0 -#define HV_TIME_SYNCH 1 -#define HV_HEART_BEAT 2 -#define HV_KVP 3 -#define HV_MAX_UTIL_SERVICES 4 - -#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */ -#define HV_ICTIMESYNCFLAG_PROBE 0 -#define HV_ICTIMESYNCFLAG_SYNC 1 -#define HV_ICTIMESYNCFLAG_SAMPLE 2 -#define HV_NANO_SEC_PER_SEC 1000000000 +#define BSD_SOC_PATH "/etc/hyperv/socket" + +#define HV_SHUT_DOWN 0 +#define HV_TIME_SYNCH 1 +#define HV_HEART_BEAT 2 +#define HV_KVP 3 +#define HV_MAX_UTIL_SERVICES 4 + +#define HV_WLTIMEDELTA 116444736000000000L /* in 100ns unit */ +#define HV_ICTIMESYNCFLAG_PROBE 0 +#define HV_ICTIMESYNCFLAG_SYNC 1 +#define HV_ICTIMESYNCFLAG_SAMPLE 2 +#define HV_NANO_SEC_PER_SEC 1000000000 + +typedef struct hv_vmbus_service { + hv_guid guid; /* Hyper-V GUID */ + char* name; /* name of service */ + boolean_t enabled; /* service enabled */ + hv_work_queue* work_queue; /* background work queue */ + + // + // function to initialize service + // + int (*init)(struct hv_vmbus_service *); + + // + // function to process Hyper-V messages + // + void (*callback)(void *); +} hv_vmbus_service; + +extern uint8_t* receive_buffer[]; +extern hv_vmbus_service service_table[]; #endif /* _KVP_H */ diff --git a/sys/dev/hyperv/utilities/hv_util.c b/sys/dev/hyperv/utilities/hv_util.c index 91bbc5345..e86cbd784 100644 --- a/sys/dev/hyperv/utilities/hv_util.c +++ b/sys/dev/hyperv/utilities/hv_util.c @@ -1,5 +1,7 @@ /*- - * Copyright (c) 2014 Microsoft Corp. + * Copyright (c) 2009-2012 Microsoft Corp. + * Copyright (c) 2012 NetApp Inc. + * Copyright (c) 2012 Citrix Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -22,11 +24,9 @@ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ -/* +/** * A common driver for all hyper-V util services. */ @@ -53,7 +53,7 @@ static void hv_timesync_cb(void *context); static int hv_timesync_init(hv_vmbus_service *serv); -/* +/** * Note: GUID codes below are predefined by the host hypervisor * (Hyper-V and Azure)interface and required for correct operation. */ @@ -80,16 +80,7 @@ hv_vmbus_service service_table[] = { 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d}, .name = "Hyper-V Heartbeat Service\n", .enabled = TRUE, - .callback = hv_heartbeat_cb, - }, - - /* KVP (Key Value Pair) Service */ - { .guid.data = {0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, - 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6}, - .name = "Hyper-V KVP Service\n", - .enabled = TRUE, - .init = hv_kvp_init, - .callback = hv_kvp_callback, + .callback = hv_heartbeat_cb, }, }; @@ -99,8 +90,6 @@ hv_vmbus_service service_table[] = { */ uint8_t *receive_buffer[HV_MAX_UTIL_SERVICES]; -static boolean_t destroyed_kvp = FALSE; - struct hv_ictimesync_data { uint64_t parenttime; uint64_t childtime; @@ -154,7 +143,7 @@ hv_negotiate_version( static void hv_set_host_time(void *context) { - time_sync_data* time_msg = (time_sync_data*) context; + time_sync_data *time_msg = context; uint64_t hosttime = time_msg->data; struct timespec guest_ts, host_ts; uint64_t host_tns; @@ -264,12 +253,12 @@ hv_timesync_cb(void *context) static void hv_shutdown_cb(void *context) { - uint8_t* buf; + uint8_t* buf; hv_vmbus_channel* channel = context; - uint8_t execute_shutdown = 0; + uint8_t execute_shutdown = 0; hv_vmbus_icmsg_hdr* icmsghdrp; - uint32_t recv_len; - uint64_t request_id; + uint32_t recv_len; + uint64_t request_id; int ret; hv_vmbus_shutdown_msg_data* shutdown_msg; @@ -432,11 +421,6 @@ hv_util_detach(device_t dev) struct hv_vmbus_service* service; size_t receive_buffer_offset; - if (!destroyed_kvp) { - hv_kvp_deinit(); - destroyed_kvp = TRUE; - } - hv_dev = vmbus_get_devctx(dev); hv_vmbus_channel_close(hv_dev->channel); @@ -448,22 +432,21 @@ hv_util_detach(device_t dev) free(receive_buffer[receive_buffer_offset], M_DEVBUF); receive_buffer[receive_buffer_offset] = NULL; + return (0); } -static void -hv_util_init(void) +static void hv_util_init(void) { } -static int -hv_util_modevent(module_t mod, int event, void *arg) +static int hv_util_modevent(module_t mod, int event, void *arg) { switch (event) { case MOD_LOAD: break; case MOD_UNLOAD: - break; + break; default: break; } diff --git a/sys/dev/hyperv/utilities/unicode.h b/sys/dev/hyperv/utilities/unicode.h deleted file mode 100644 index 696777cbb..000000000 --- a/sys/dev/hyperv/utilities/unicode.h +++ /dev/null @@ -1,201 +0,0 @@ -/* $NetBSD: unicode.h,v 1.1.1.1 2007/03/06 00:10:39 dillo Exp $ */ - -/*- - * Copyright (c) 2007 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ - */ - -#include - -#define UNICODE_DECOMPOSE 0x01 -#define UNICODE_PRECOMPOSE 0x02 -#define UNICODE_UTF8_LATIN1_FALLBACK 0x03 - -size_t utf8_to_utf16(uint16_t *, size_t, const char *, size_t, int, int *); -size_t utf16_to_utf8(char *, size_t, const uint16_t *, size_t, int, int *); - -size_t -utf8_to_utf16(uint16_t *dst, size_t dst_len, - const char *src, size_t src_len, - int flags, int *errp) -{ - const unsigned char *s; - size_t spos, dpos; - int error; - uint16_t c; - -#define IS_CONT(c) (((c)&0xc0) == 0x80) - - error = 0; - s = (const unsigned char *)src; - spos = dpos = 0; - while (spos= src_len || !IS_CONT(s[spos+1])) - && s[spos]>=0xa0) { - /* not valid UTF-8, assume ISO 8859-1 */ - c = s[spos++]; - } - else if (s[spos] < 0xc0 || s[spos] >= 0xf5) { - /* continuation byte without lead byte - or lead byte for codepoint above 0x10ffff */ - error++; - spos++; - continue; - } - else if (s[spos] < 0xe0) { - if (spos >= src_len || !IS_CONT(s[spos+1])) { - spos++; - error++; - continue; - } - c = ((s[spos] & 0x3f) << 6) | (s[spos+1] & 0x3f); - spos += 2; - if (c < 0x80) { - /* overlong encoding */ - error++; - continue; - } - } - else if (s[spos] < 0xf0) { - if (spos >= src_len-2 - || !IS_CONT(s[spos+1]) || !IS_CONT(s[spos+2])) { - spos++; - error++; - continue; - } - c = ((s[spos] & 0x0f) << 12) | ((s[spos+1] & 0x3f) << 6) - | (s[spos+2] & 0x3f); - spos += 3; - if (c < 0x800 || (c & 0xdf00) == 0xd800 ) { - /* overlong encoding or encoded surrogate */ - error++; - continue; - } - } - else { - uint32_t cc; - /* UTF-16 surrogate pair */ - - if (spos >= src_len-3 || !IS_CONT(s[spos+1]) - || !IS_CONT(s[spos+2]) || !IS_CONT(s[spos+3])) { - spos++; - error++; - - continue; - } - cc = ((s[spos] & 0x03) << 18) | ((s[spos+1] & 0x3f) << 12) - | ((s[spos+2] & 0x3f) << 6) | (s[spos+3] & 0x3f); - spos += 4; - if (cc < 0x10000) { - /* overlong encoding */ - error++; - continue; - } - if (dst && dpos < dst_len) - dst[dpos] = (0xd800 | ((cc-0x10000)>>10)); - dpos++; - c = 0xdc00 | ((cc-0x10000) & 0x3ffff); - } - - if (dst && dpos < dst_len) - dst[dpos] = c; - dpos++; - } - - if (errp) - *errp = error; - - return dpos; - -#undef IS_CONT -} - - -size_t -utf16_to_utf8(char *dst, size_t dst_len, - const uint16_t *src, size_t src_len, - int flags, int *errp) -{ - uint16_t spos, dpos; - int error; - -#define CHECK_LENGTH(l) (dpos > dst_len-(l) ? dst=NULL : NULL) -#define ADD_BYTE(b) (dst ? dst[dpos] = (b) : 0, dpos++) - - error = 0; - dpos = 0; - for (spos=0; spos>6)); - ADD_BYTE(0x80 | (src[spos] & 0x3f)); - } - else if ((src[spos] & 0xdc00) == 0xd800) { - uint32_t c; - /* first surrogate */ - if (spos == src_len - 1 || (src[spos] & 0xdc00) != 0xdc00) { - /* no second surrogate present */ - error++; - continue; - } - spos++; - CHECK_LENGTH(4); - c = (((src[spos]&0x3ff) << 10) | (src[spos+1]&0x3ff)) + 0x10000; - ADD_BYTE(0xf0 | (c>>18)); - ADD_BYTE(0x80 | ((c>>12) & 0x3f)); - ADD_BYTE(0x80 | ((c>>6) & 0x3f)); - ADD_BYTE(0x80 | (c & 0x3f)); - } - else if ((src[spos] & 0xdc00) == 0xdc00) { - /* second surrogate without preceding first surrogate */ - error++; - } - else { - CHECK_LENGTH(3); - ADD_BYTE(0xe0 | src[spos]>>12); - ADD_BYTE(0x80 | ((src[spos]>>6) & 0x3f)); - ADD_BYTE(0x80 | (src[spos] & 0x3f)); - } - } - - if (errp) - *errp = error; - - return dpos; - -#undef ADD_BYTE -#undef CHECK_LENGTH -} diff --git a/sys/modules/hyperv/utilities/Makefile b/sys/modules/hyperv/utilities/Makefile index f94e4410a..57a242801 100644 --- a/sys/modules/hyperv/utilities/Makefile +++ b/sys/modules/hyperv/utilities/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../../dev/hyperv/utilities KMOD= hv_utils -SRCS= hv_util.c hv_kvp.c +SRCS= hv_util.c SRCS+= bus_if.h device_if.h CFLAGS+= -I${.CURDIR}/../../../dev/hyperv/include \ diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index cfa369b40..62542b711 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -4670,11 +4670,3 @@ OLD_FILES+=usr/bin/svnserve OLD_FILES+=usr/bin/svnsync OLD_FILES+=usr/bin/svnversion .endif - -.if ${MK_HYPERV} == no -OLD_FILES+=etc/devd/hyperv.conf -OLD_FILES+=usr/libexec/hyperv/hv_set_ifconfig -OLD_FILES+=usr/libexec/hyperv/hv_get_dns_info -OLD_FILES+=usr/libexec/hyperv/hv_get_dhcp_info -OLD_FILES+=usr/sbin/hv_kvpd -.endif diff --git a/tools/build/options/WITHOUT_HYPERV b/tools/build/options/WITHOUT_HYPERV deleted file mode 100644 index ef63f70ea..000000000 --- a/tools/build/options/WITHOUT_HYPERV +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Set to not build or install HyperV utilities. diff --git a/tools/build/options/WITH_HYPERV b/tools/build/options/WITH_HYPERV deleted file mode 100644 index a6bdf72ff..000000000 --- a/tools/build/options/WITH_HYPERV +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Set to build and install HyperV utilities. diff --git a/usr.sbin/Makefile.amd64 b/usr.sbin/Makefile.amd64 index 2d1a3e8da..b82162580 100644 --- a/usr.sbin/Makefile.amd64 +++ b/usr.sbin/Makefile.amd64 @@ -18,9 +18,6 @@ SUBDIR+= boot0cfg SUBDIR+= btxld .endif SUBDIR+= cpucontrol -.if ${MK_HYPERV} != "no" -SUBDIR+= hyperv -.endif SUBDIR+= kgmon SUBDIR+= lptcontrol SUBDIR+= mount_smbfs diff --git a/usr.sbin/Makefile.i386 b/usr.sbin/Makefile.i386 index de7bb464f..7d66f783f 100644 --- a/usr.sbin/Makefile.i386 +++ b/usr.sbin/Makefile.i386 @@ -9,9 +9,6 @@ SUBDIR+= asf SUBDIR+= btxld .endif SUBDIR+= cpucontrol -.if ${MK_HYPERV} != "no" -SUBDIR+= hyperv -.endif SUBDIR+= kgmon SUBDIR+= kgzip SUBDIR+= lptcontrol diff --git a/usr.sbin/hyperv/Makefile b/usr.sbin/hyperv/Makefile deleted file mode 100644 index c11b3417c..000000000 --- a/usr.sbin/hyperv/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $FreeBSD$ - -.include - -SUBDIR = tools - -.include diff --git a/usr.sbin/hyperv/Makefile.inc b/usr.sbin/hyperv/Makefile.inc deleted file mode 100644 index 265f86d1e..000000000 --- a/usr.sbin/hyperv/Makefile.inc +++ /dev/null @@ -1,3 +0,0 @@ -# $FreeBSD$ - -.include "../Makefile.inc" diff --git a/usr.sbin/hyperv/tools/Makefile b/usr.sbin/hyperv/tools/Makefile deleted file mode 100644 index 3cfc0013c..000000000 --- a/usr.sbin/hyperv/tools/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# $FreeBSD$ - -.include - -HV_KVP_DAEMON_DISTDIR?= ${.CURDIR}/../../../contrib/hyperv/tools -.PATH: ${HV_KVP_DAEMON_DISTDIR} - -PROG= hv_kvp_daemon -MAN= hv_kvp_daemon.8 - -CFLAGS+= -I${.CURDIR}/../../../sys/dev/hyperv/utilities - -.include -- 2.42.0