Changeset View
Changeset View
Standalone View
Standalone View
head/contrib/hyperv/tools/hv_kvp_daemon.c
Show First 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <poll.h> | #include <poll.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <syslog.h> | #include <syslog.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <assert.h> | |||||
#include "hv_kvp.h" | #include "hv_kvp.h" | ||||
#include "hv_utilreg.h" | |||||
typedef uint8_t __u8; | typedef uint8_t __u8; | ||||
typedef uint16_t __u16; | typedef uint16_t __u16; | ||||
typedef uint32_t __u32; | typedef uint32_t __u32; | ||||
typedef uint64_t __u64; | typedef uint64_t __u64; | ||||
/* | /* | ||||
* ENUM Data | * ENUM Data | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 613 Lines • ▼ Show 20 Lines | kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer) | ||||
*/ | */ | ||||
snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name); | snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name); | ||||
/* | /* | ||||
* Execute the command to gather gateway IPV4 info. | * Execute the command to gather gateway IPV4 info. | ||||
*/ | */ | ||||
kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, | kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, | ||||
(MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); | (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0); | ||||
/* | /* | ||||
* Retrieve the IPV6 address of default gateway. | * Retrieve the IPV6 address of default gateway. | ||||
*/ | */ | ||||
snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name); | snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }'", if_name); | ||||
/* | /* | ||||
* Execute the command to gather gateway IPV6 info. | * Execute the command to gather gateway IPV6 info. | ||||
*/ | */ | ||||
kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, | kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way, | ||||
(MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); | (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1); | ||||
/* | /* | ||||
* we just invoke an external script to get the DNS info. | * we just invoke an external script to get the DNS info. | ||||
* | * | ||||
* Following is the expected format of the information from the script: | * Following is the expected format of the information from the script: | ||||
* | * | ||||
* ipaddr1 (nameserver1) | * ipaddr1 (nameserver1) | ||||
* ipaddr2 (nameserver2) | * ipaddr2 (nameserver2) | ||||
* . | * . | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (family == AF_INET) { | ||||
addr_length = INET_ADDRSTRLEN; | addr_length = INET_ADDRSTRLEN; | ||||
} else { | } else { | ||||
addr6 = (struct sockaddr_in6 *)addrp; | addr6 = (struct sockaddr_in6 *)addrp; | ||||
str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50); | str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50); | ||||
addr_length = INET6_ADDRSTRLEN; | addr_length = INET6_ADDRSTRLEN; | ||||
} | } | ||||
if ((length - *offset) < addr_length + 1) { | if ((length - *offset) < addr_length + 1) { | ||||
return (HV_KVP_E_FAIL); | return (EINVAL); | ||||
} | } | ||||
if (str == NULL) { | if (str == NULL) { | ||||
strlcpy(buffer, "inet_ntop failed\n", length); | strlcpy(buffer, "inet_ntop failed\n", length); | ||||
return (HV_KVP_E_FAIL); | return (errno); | ||||
} | } | ||||
if (*offset == 0) { | if (*offset == 0) { | ||||
strlcpy(buffer, tmp, length); | strlcpy(buffer, tmp, length); | ||||
} else{ | } else{ | ||||
strlcat(buffer, tmp, length); | strlcat(buffer, tmp, length); | ||||
} | } | ||||
strlcat(buffer, ";", length); | strlcat(buffer, ";", length); | ||||
Show All 29 Lines | if (op == HV_KVP_OP_ENUMERATE) { | ||||
ip_buffer = out_buffer; | ip_buffer = out_buffer; | ||||
buffer = (char *)ip_buffer->ip_addr; | buffer = (char *)ip_buffer->ip_addr; | ||||
buffer_length = sizeof(ip_buffer->ip_addr); | buffer_length = sizeof(ip_buffer->ip_addr); | ||||
ip_buffer->addr_family = 0; | ip_buffer->addr_family = 0; | ||||
} | } | ||||
if (getifaddrs(&ifap)) { | if (getifaddrs(&ifap)) { | ||||
strlcpy(buffer, "getifaddrs failed\n", buffer_length); | strlcpy(buffer, "getifaddrs failed\n", buffer_length); | ||||
return (HV_KVP_E_FAIL); | return (errno); | ||||
} | } | ||||
curp = ifap; | curp = ifap; | ||||
while (curp != NULL) { | while (curp != NULL) { | ||||
if (curp->ifa_addr == NULL) { | if (curp->ifa_addr == NULL) { | ||||
curp = curp->ifa_next; | curp = curp->ifa_next; | ||||
continue; | continue; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | if (op == HV_KVP_OP_GET_IP_INFO) { | ||||
} | } | ||||
strlcat((char *)ip_buffer->sub_net, ";", sn_str_length); | strlcat((char *)ip_buffer->sub_net, ";", sn_str_length); | ||||
sn_offset += strlen(sn_str) + 1; | sn_offset += strlen(sn_str) + 1; | ||||
} | } | ||||
/* | /* | ||||
* Collect other ip configuration info. | * Collect other ip configuration info. | ||||
*/ | */ | ||||
kvp_get_ipconfig_info(if_name, ip_buffer); | kvp_get_ipconfig_info(if_name, ip_buffer); | ||||
} | } | ||||
kvp_get_ip_info_ipaddr: | kvp_get_ip_info_ipaddr: | ||||
error = kvp_process_ip_address(curp->ifa_addr, | error = kvp_process_ip_address(curp->ifa_addr, | ||||
curp->ifa_addr->sa_family, | curp->ifa_addr->sa_family, | ||||
buffer, | buffer, | ||||
length, &offset); | length, &offset); | ||||
Show All 13 Lines | |||||
static int | static int | ||||
kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3) | kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3) | ||||
{ | { | ||||
int ret; | int ret; | ||||
ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); | ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3); | ||||
if (ret < 0) { | if (ret < 0) { | ||||
return (HV_KVP_E_FAIL); | return (EIO); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) | ||||
{ | { | ||||
int error = 0; | int error = 0; | ||||
char if_file[128]; | char if_file[128]; | ||||
FILE *file; | FILE *file; | ||||
char cmd[512]; | char cmd[512]; | ||||
char *mac_addr; | char *mac_addr; | ||||
/* | /* | ||||
* FreeBSD - Configuration File | * FreeBSD - Configuration File | ||||
*/ | */ | ||||
snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv", | snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv", | ||||
"hv_set_ip_data"); | "hv_set_ip_data"); | ||||
file = fopen(if_file, "w"); | file = fopen(if_file, "w"); | ||||
if (file == NULL) { | if (file == NULL) { | ||||
KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); | KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n"); | ||||
return (HV_KVP_E_FAIL); | return (errno); | ||||
} | } | ||||
/* | /* | ||||
* Write out the MAC address. | * Write out the MAC address. | ||||
*/ | */ | ||||
mac_addr = kvp_if_name_to_mac(if_name); | mac_addr = kvp_if_name_to_mac(if_name); | ||||
if (mac_addr == NULL) { | if (mac_addr == NULL) { | ||||
error = HV_KVP_E_FAIL; | error = EINVAL; | ||||
goto kvp_set_ip_info_error; | goto kvp_set_ip_info_error; | ||||
} | } | ||||
/* MAC Address */ | /* MAC Address */ | ||||
error = kvp_write_file(file, "HWADDR", "", mac_addr); | error = kvp_write_file(file, "HWADDR", "", mac_addr); | ||||
if (error) { | if (error) { | ||||
goto kvp_set_ip_info_error; | goto kvp_set_ip_info_error; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused) | kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused) | ||||
{ | { | ||||
struct hv_kvp_ipaddr_value *ip_val; | struct hv_kvp_ipaddr_value *ip_val; | ||||
char *if_name; | char *if_name; | ||||
int error = 0; | |||||
assert(op_msg != NULL); | assert(op_msg != NULL); | ||||
KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); | KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n"); | ||||
ip_val = &op_msg->body.kvp_ip_val; | ip_val = &op_msg->body.kvp_ip_val; | ||||
op_msg->hdr.error = HV_KVP_S_OK; | op_msg->hdr.error = HV_S_OK; | ||||
if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id); | if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id); | ||||
if (if_name == NULL) { | if (if_name == NULL) { | ||||
/* No interface found with the mac address. */ | /* No interface found with the mac address. */ | ||||
op_msg->hdr.error = HV_KVP_E_FAIL; | op_msg->hdr.error = HV_E_FAIL; | ||||
goto kvp_op_getipinfo_done; | goto kvp_op_getipinfo_done; | ||||
} | } | ||||
op_msg->hdr.error = kvp_get_ip_info(0, if_name, | error = kvp_get_ip_info(0, if_name, | ||||
HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2)); | HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2)); | ||||
if (error) | |||||
op_msg->hdr.error = HV_E_FAIL; | |||||
free(if_name); | free(if_name); | ||||
kvp_op_getipinfo_done: | kvp_op_getipinfo_done: | ||||
return(op_msg->hdr.error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused) | kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused) | ||||
{ | { | ||||
struct hv_kvp_ipaddr_value *ip_val; | struct hv_kvp_ipaddr_value *ip_val; | ||||
char *if_name; | char *if_name; | ||||
int error = 0; | |||||
assert(op_msg != NULL); | assert(op_msg != NULL); | ||||
KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); | KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n"); | ||||
ip_val = &op_msg->body.kvp_ip_val; | ip_val = &op_msg->body.kvp_ip_val; | ||||
op_msg->hdr.error = HV_KVP_S_OK; | op_msg->hdr.error = HV_S_OK; | ||||
if_name = (char *)ip_val->adapter_id; | if_name = (char *)ip_val->adapter_id; | ||||
if (if_name == NULL) { | if (if_name == NULL) { | ||||
/* No adapter provided. */ | /* No adapter provided. */ | ||||
op_msg->hdr.error = HV_KVP_GUID_NOTFOUND; | op_msg->hdr.error = HV_GUID_NOTFOUND; | ||||
goto kvp_op_setipinfo_done; | goto kvp_op_setipinfo_done; | ||||
} | } | ||||
op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val); | error = kvp_set_ip_info(if_name, ip_val); | ||||
if (error) | |||||
op_msg->hdr.error = HV_E_FAIL; | |||||
kvp_op_setipinfo_done: | kvp_op_setipinfo_done: | ||||
return(op_msg->hdr.error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) | kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data) | ||||
{ | { | ||||
struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data; | struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data; | ||||
int error = 0; | int error = 0; | ||||
int op_pool; | int op_pool; | ||||
assert(op_msg != NULL); | assert(op_msg != NULL); | ||||
assert(op_hdlr != NULL); | assert(op_hdlr != NULL); | ||||
op_pool = op_msg->hdr.kvp_hdr.pool; | op_pool = op_msg->hdr.kvp_hdr.pool; | ||||
op_msg->hdr.error = HV_KVP_S_OK; | op_msg->hdr.error = HV_S_OK; | ||||
switch(op_hdlr->kvp_op_key) { | switch(op_hdlr->kvp_op_key) { | ||||
case HV_KVP_OP_SET: | case HV_KVP_OP_SET: | ||||
if (op_pool == HV_KVP_POOL_AUTO) { | if (op_pool == HV_KVP_POOL_AUTO) { | ||||
/* Auto Pool is not writeable from host side. */ | /* Auto Pool is not writeable from host side. */ | ||||
error = 1; | error = 1; | ||||
KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n", | KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n", | ||||
op_pool); | op_pool); | ||||
Show All 27 Lines | case HV_KVP_OP_DELETE: | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
break; | break; | ||||
} | } | ||||
if (error != 0) | if (error != 0) | ||||
op_msg->hdr.error = HV_KVP_S_CONT; | op_msg->hdr.error = HV_S_CONT; | ||||
return(error); | return(error); | ||||
} | } | ||||
static int | static int | ||||
kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) | kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused) | ||||
{ | { | ||||
char *key_name, *key_value; | char *key_name, *key_value; | ||||
int error = 0; | int error = 0; | ||||
int op_pool; | int op_pool; | ||||
int op; | int op; | ||||
assert(op_msg != NULL); | assert(op_msg != NULL); | ||||
op = op_msg->hdr.kvp_hdr.operation; | op = op_msg->hdr.kvp_hdr.operation; | ||||
op_pool = op_msg->hdr.kvp_hdr.pool; | op_pool = op_msg->hdr.kvp_hdr.pool; | ||||
op_msg->hdr.error = HV_KVP_S_OK; | op_msg->hdr.error = HV_S_OK; | ||||
/* | /* | ||||
* If the pool is not HV_KVP_POOL_AUTO, read from the appropriate | * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate | ||||
* pool and return the KVP according to the index requested. | * pool and return the KVP according to the index requested. | ||||
*/ | */ | ||||
if (op_pool != HV_KVP_POOL_AUTO) { | if (op_pool != HV_KVP_POOL_AUTO) { | ||||
if (kvp_pool_enumerate(op_pool, | if (kvp_pool_enumerate(op_pool, | ||||
op_msg->body.kvp_enum_data.index, | op_msg->body.kvp_enum_data.index, | ||||
op_msg->body.kvp_enum_data.data.key, | op_msg->body.kvp_enum_data.data.key, | ||||
HV_KVP_EXCHANGE_MAX_KEY_SIZE, | HV_KVP_EXCHANGE_MAX_KEY_SIZE, | ||||
op_msg->body.kvp_enum_data.data.msg_value.value, | op_msg->body.kvp_enum_data.data.msg_value.value, | ||||
HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { | HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) { | ||||
op_msg->hdr.error = HV_KVP_S_CONT; | op_msg->hdr.error = HV_S_CONT; | ||||
error = -1; | error = -1; | ||||
} | } | ||||
goto kvp_op_enumerate_done; | goto kvp_op_enumerate_done; | ||||
} | } | ||||
key_name = (char *)op_msg->body.kvp_enum_data.data.key; | key_name = (char *)op_msg->body.kvp_enum_data.data.key; | ||||
key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value; | key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value; | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | case ProcessorArchitecture: | ||||
strcpy(key_name, "ProcessorArchitecture"); | strcpy(key_name, "ProcessorArchitecture"); | ||||
break; | break; | ||||
default: | default: | ||||
#ifdef DEBUG | #ifdef DEBUG | ||||
KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n", | KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n", | ||||
op_msg->body.kvp_enum_data.index); | op_msg->body.kvp_enum_data.index); | ||||
#endif | #endif | ||||
op_msg->hdr.error = HV_KVP_S_CONT; | op_msg->hdr.error = HV_S_CONT; | ||||
error = -1; | error = -1; | ||||
break; | break; | ||||
} | } | ||||
kvp_op_enumerate_done: | kvp_op_enumerate_done: | ||||
if (error != 0) | |||||
op_msg->hdr.error = HV_S_CONT; | |||||
return(error); | return(error); | ||||
} | } | ||||
/* | /* | ||||
* Load handler, and call init routine if provided. | * Load handler, and call init routine if provided. | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | if (op < 0 || op >= HV_KVP_OP_COUNT || | ||||
"Unsupported operation OP = %d\n", op); | "Unsupported operation OP = %d\n", op); | ||||
hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED; | hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED; | ||||
} else { | } else { | ||||
/* | /* | ||||
* Call the operateion handler's execution routine. | * Call the operateion handler's execution routine. | ||||
*/ | */ | ||||
error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, | error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg, | ||||
(void *)&kvp_op_hdlrs[op]); | (void *)&kvp_op_hdlrs[op]); | ||||
if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT) | if (error != 0) { | ||||
assert(hv_msg->hdr.error != HV_S_OK); | |||||
if (hv_msg->hdr.error != HV_S_CONT) | |||||
KVP_LOG(LOG_WARNING, | KVP_LOG(LOG_WARNING, | ||||
"Operation failed OP = %d, error = 0x%x\n", | "Operation failed OP = %d, error = 0x%x\n", | ||||
op, error); | op, error); | ||||
} | |||||
} | } | ||||
/* | /* | ||||
* Send the value back to the kernel. The response is | * Send the value back to the kernel. The response is | ||||
* already in the receive buffer. | * already in the receive buffer. | ||||
*/ | */ | ||||
hv_kvp_done: | hv_kvp_done: | ||||
len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0); | len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0); | ||||
if (len != sizeof(struct hv_kvp_msg)) { | if (len != sizeof(struct hv_kvp_msg)) { | ||||
KVP_LOG(LOG_ERR, "write len is: %d\n", len); | KVP_LOG(LOG_ERR, "write len is: %d\n", len); | ||||
goto hv_kvp_done; | goto hv_kvp_done; | ||||
} | } | ||||
} | } | ||||
} | } |