* [PATCH 02/13] Drivers: hv: kvp: Cleanup error handling in KVP
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 03/13] Drivers: hv: kvp: Support the new IP injection messages K. Y. Srinivasan
` (10 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
In preparation to implementing IP injection, cleanup the way we propagate
and handle errors both in the driver as well as in the user level daemon.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/hv_kvp.c | 43 +++++++++++++++++++------------------
include/linux/hyperv.h | 17 +++++++++-----
tools/hv/hv_kvp_daemon.c | 53 +++++++++++++++++++++++----------------------
3 files changed, 60 insertions(+), 53 deletions(-)
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0012eed..6e6f0c2 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -50,7 +50,6 @@ static struct {
static void kvp_send_key(struct work_struct *dummy);
-#define TIMEOUT_FIRED 1
static void kvp_respond_to_host(char *key, char *value, int error);
static void kvp_work_func(struct work_struct *dummy);
@@ -97,7 +96,7 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
- kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
+ kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
}
/*
@@ -109,27 +108,31 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct hv_kvp_msg *message;
struct hv_kvp_msg_enumerate *data;
+ int error;
message = (struct hv_kvp_msg *)msg->data;
- switch (message->kvp_hdr.operation) {
- case KVP_OP_REGISTER:
+
+ if (message->kvp_hdr.operation == KVP_OP_REGISTER) {
pr_info("KVP: user-mode registering done.\n");
kvp_register();
kvp_transaction.active = false;
- hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
- break;
-
- default:
- data = &message->body.kvp_enum_data;
- /*
- * Complete the transaction by forwarding the key value
- * to the host. But first, cancel the timeout.
- */
- if (cancel_delayed_work_sync(&kvp_work))
- kvp_respond_to_host(data->data.key,
- data->data.value,
- !strlen(data->data.key));
+ if (kvp_transaction.kvp_context)
+ hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
+ return;
}
+
+ /*
+ * We use the message header information from
+ * the user level daemon to transmit errors.
+ */
+ error = *((int *)(&message->kvp_hdr.operation));
+ data = &message->body.kvp_enum_data;
+ /*
+ * Complete the transaction by forwarding the key value
+ * to the host. But first, cancel the timeout.
+ */
+ if (cancel_delayed_work_sync(&kvp_work))
+ kvp_respond_to_host(data->data.key, data->data.value, error);
}
static void
@@ -287,6 +290,7 @@ kvp_respond_to_host(char *key, char *value, int error)
*/
return;
+ icmsghdrp->status = error;
/*
* If the error parameter is set, terminate the host's enumeration
@@ -294,15 +298,12 @@ kvp_respond_to_host(char *key, char *value, int error)
*/
if (error) {
/*
- * Something failed or the we have timedout;
+ * Something failed or we have timedout;
* terminate the current host-side iteration.
*/
- icmsghdrp->status = HV_S_CONT;
goto response_done;
}
- icmsghdrp->status = HV_S_OK;
-
kvp_msg = (struct hv_kvp_msg *)
&recv_buffer[sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)];
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 0497764..9d75699 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -142,6 +142,17 @@ enum hv_kvp_exchg_pool {
KVP_POOL_COUNT /* Number of pools, must be last. */
};
+/*
+ * Some Hyper-V status codes.
+ */
+
+#define HV_S_OK 0x00000000
+#define HV_E_FAIL 0x80004005
+#define HV_S_CONT 0x80070103
+#define HV_ERROR_NOT_SUPPORTED 0x80070032
+#define HV_ERROR_MACHINE_LOCKED 0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
+
#define ADDR_FAMILY_NONE 0x00
#define ADDR_FAMILY_IPV4 0x01
#define ADDR_FAMILY_IPV6 0x02
@@ -1000,12 +1011,6 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
#define ICMSGHDRFLAG_REQUEST 2
#define ICMSGHDRFLAG_RESPONSE 4
-#define HV_S_OK 0x00000000
-#define HV_E_FAIL 0x80004005
-#define HV_S_CONT 0x80070103
-#define HV_ERROR_NOT_SUPPORTED 0x80070032
-#define HV_ERROR_MACHINE_LOCKED 0x800704F7
-#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
/*
* While we want to handle util services as regular devices,
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d9834b3..4831997 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -394,7 +394,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
return 1;
}
-static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
+static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
__u8 *value, int value_size)
{
struct kvp_record *record;
@@ -406,16 +406,12 @@ static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
record = kvp_file_info[pool].records;
if (index >= kvp_file_info[pool].num_records) {
- /*
- * This is an invalid index; terminate enumeration;
- * - a NULL value will do the trick.
- */
- strcpy(value, "");
- return;
+ return 1;
}
memcpy(key, record[index].key, key_size);
memcpy(value, record[index].value, value_size);
+ return 0;
}
@@ -646,6 +642,8 @@ int main(void)
char *p;
char *key_value;
char *key_name;
+ int op;
+ int pool;
daemon(1, 0);
openlog("KVP", 0, LOG_USER);
@@ -721,7 +719,16 @@ int main(void)
incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
- switch (hv_msg->kvp_hdr.operation) {
+ /*
+ * We will use the KVP header information to pass back
+ * the error from this daemon. So, first copy the state
+ * and set the error code to success.
+ */
+ op = hv_msg->kvp_hdr.operation;
+ pool = hv_msg->kvp_hdr.pool;
+ *((int *)(&hv_msg->kvp_hdr.operation)) = HV_S_OK;
+
+ switch (op) {
case KVP_OP_REGISTER:
/*
* Driver is registering with us; stash away the version
@@ -738,20 +745,14 @@ int main(void)
}
continue;
- /*
- * The current protocol with the kernel component uses a
- * NULL key name to pass an error condition.
- * For the SET, GET and DELETE operations,
- * use the existing protocol to pass back error.
- */
-
case KVP_OP_SET:
if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_set.data.key,
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
- strcpy(hv_msg->body.kvp_set.data.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
case KVP_OP_GET:
@@ -760,14 +761,16 @@ int main(void)
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
- strcpy(hv_msg->body.kvp_set.data.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
case KVP_OP_DELETE:
if (kvp_key_delete(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_delete.key,
hv_msg->body.kvp_delete.key_size))
- strcpy(hv_msg->body.kvp_delete.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
default:
@@ -782,13 +785,15 @@ int main(void)
* both the key and the value; if not read from the
* appropriate pool.
*/
- if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
- kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
+ if (pool != KVP_POOL_AUTO) {
+ if (kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_enum_data.index,
hv_msg->body.kvp_enum_data.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE,
hv_msg->body.kvp_enum_data.data.value,
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
goto kvp_done;
}
@@ -841,11 +846,7 @@ int main(void)
strcpy(key_name, "ProcessorArchitecture");
break;
default:
- strcpy(key_value, "Unknown Key");
- /*
- * We use a null key name to terminate enumeration.
- */
- strcpy(key_name, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) = HV_S_CONT;
break;
}
/*
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 03/13] Drivers: hv: kvp: Support the new IP injection messages
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 02/13] Drivers: hv: kvp: Cleanup error handling in KVP K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 04/13] Tools: hv: Prepare to expand kvp_get_ip_address() functionality K. Y. Srinivasan
` (9 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Implement support for the new IP injection messages in the driver code.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/hv_kvp.c | 70 +++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 6e6f0c2..4fd0932 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -51,7 +51,7 @@ static struct {
static void kvp_send_key(struct work_struct *dummy);
-static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
static void kvp_work_func(struct work_struct *dummy);
static void kvp_register(void);
@@ -96,7 +96,7 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
- kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
+ kvp_respond_to_host(NULL, HV_E_FAIL);
}
/*
@@ -107,7 +107,6 @@ static void
kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct hv_kvp_msg *message;
- struct hv_kvp_msg_enumerate *data;
int error;
message = (struct hv_kvp_msg *)msg->data;
@@ -126,13 +125,59 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
* the user level daemon to transmit errors.
*/
error = *((int *)(&message->kvp_hdr.operation));
- data = &message->body.kvp_enum_data;
/*
* Complete the transaction by forwarding the key value
* to the host. But first, cancel the timeout.
*/
if (cancel_delayed_work_sync(&kvp_work))
- kvp_respond_to_host(data->data.key, data->data.value, error);
+ kvp_respond_to_host(message, error);
+}
+
+static void process_ipinfo(struct hv_kvp_msg *in_msg,
+ struct hv_kvp_msg *out_msg, int op)
+{
+ switch (op) {
+ case KVP_OP_SET_IP_INFO:
+ /*
+ * Transform all parameters into utf8 encoding.
+ */
+ utf16s_to_utf8s((wchar_t *)in_msg->body.kvp_ip_val.ip_addr,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out_msg->body.kvp_ip_val.ip_addr,
+ MAX_IP_ADDR_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in_msg->body.kvp_ip_val.sub_net,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out_msg->body.kvp_ip_val.sub_net,
+ MAX_IP_ADDR_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in_msg->body.kvp_ip_val.gate_way,
+ MAX_GATEWAY_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out_msg->body.kvp_ip_val.gate_way,
+ MAX_GATEWAY_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in_msg->body.kvp_ip_val.dns_addr,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out_msg->body.kvp_ip_val.dns_addr,
+ MAX_IP_ADDR_SIZE);
+
+ out_msg->body.kvp_ip_val.dhcp_enabled =
+ in_msg->body.kvp_ip_val.dhcp_enabled;
+
+ default:
+ utf16s_to_utf8s((wchar_t *)in_msg->body.kvp_ip_val.adapter_id,
+ MAX_ADAPTER_ID_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out_msg->body.kvp_ip_val.adapter_id,
+ MAX_ADAPTER_ID_SIZE);
+
+ out_msg->body.kvp_ip_val.addr_family =
+ in_msg->body.kvp_ip_val.addr_family;
+ }
}
static void
@@ -170,6 +215,12 @@ kvp_send_key(struct work_struct *dummy)
*/
switch (message->kvp_hdr.operation) {
+ case KVP_OP_SET_IP_INFO:
+ process_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
+ break;
+ case KVP_OP_GET_IP_INFO:
+ process_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
+ break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
case REG_SZ:
@@ -246,11 +297,12 @@ kvp_send_key(struct work_struct *dummy)
*/
static void
-kvp_respond_to_host(char *key, char *value, int error)
+kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
{
struct hv_kvp_msg *kvp_msg;
struct hv_kvp_exchg_msg_value *kvp_data;
char *key_name;
+ char *value;
struct icmsg_hdr *icmsghdrp;
int keylen = 0;
int valuelen = 0;
@@ -309,6 +361,9 @@ kvp_respond_to_host(char *key, char *value, int error)
sizeof(struct icmsg_hdr)];
switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
+ case KVP_OP_GET_IP_INFO:
+ process_ipinfo(msg_to_host, kvp_msg, KVP_OP_SET_IP_INFO);
+ goto response_done;
case KVP_OP_GET:
kvp_data = &kvp_msg->body.kvp_get.data;
goto copy_value;
@@ -322,7 +377,7 @@ kvp_respond_to_host(char *key, char *value, int error)
}
kvp_data = &kvp_msg->body.kvp_enum_data.data;
- key_name = key;
+ key_name = msg_to_host->body.kvp_enum_data.data.key;
/*
* The windows host expects the key/value pair to be encoded
@@ -336,6 +391,7 @@ kvp_respond_to_host(char *key, char *value, int error)
kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
copy_value:
+ value = msg_to_host->body.kvp_enum_data.data.value;
valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
(wchar_t *) kvp_data->value,
(HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 04/13] Tools: hv: Prepare to expand kvp_get_ip_address() functionality
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 02/13] Drivers: hv: kvp: Cleanup error handling in KVP K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 03/13] Drivers: hv: kvp: Support the new IP injection messages K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 05/13] Tools: hv: Further refactor kvp_get_ip_address() K. Y. Srinivasan
` (8 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
kvp_get_ip_address() implemented the functionality to retrieve IP address info.
Make this function more generic so that we could retrieve additional
per-interface information.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 129 ++++++++++++++++++++++++++++++----------------
1 files changed, 84 insertions(+), 45 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4831997..4fa6f95 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -491,7 +491,8 @@ done:
}
static int
-kvp_get_ip_address(int family, char *buffer, int length)
+kvp_get_ip_address(int family, char *if_name, int op,
+ void *out_buffer, int length)
{
struct ifaddrs *ifap;
struct ifaddrs *curp;
@@ -501,10 +502,19 @@ kvp_get_ip_address(int family, char *buffer, int length)
const char *str;
char tmp[50];
int error = 0;
-
+ char *buffer;
+ struct hv_kvp_ipaddr_value *ip_buffer;
+
+ if (op == KVP_OP_ENUMERATE) {
+ buffer = out_buffer;
+ } else {
+ ip_buffer = out_buffer;
+ buffer = (char *)ip_buffer->ip_addr;
+ ip_buffer->addr_family = 0;
+ }
/*
* On entry into this function, the buffer is capable of holding the
- * maximum key value (2048 bytes).
+ * maximum key value.
*/
if (getifaddrs(&ifap)) {
@@ -514,58 +524,87 @@ kvp_get_ip_address(int family, char *buffer, int length)
curp = ifap;
while (curp != NULL) {
- if ((curp->ifa_addr != NULL) &&
- (curp->ifa_addr->sa_family == family)) {
- if (family == AF_INET) {
- struct sockaddr_in *addr =
- (struct sockaddr_in *) curp->ifa_addr;
-
- str = inet_ntop(family, &addr->sin_addr,
- tmp, 50);
- if (str == NULL) {
- strcpy(buffer, "inet_ntop failed\n");
- error = 1;
- goto getaddr_done;
- }
- if (offset == 0)
- strcpy(buffer, tmp);
- else
- strcat(buffer, tmp);
- strcat(buffer, ";");
+ if (curp->ifa_addr == NULL) {
+ curp = curp->ifa_next;
+ continue;
+ }
- offset += strlen(str) + 1;
- if ((length - offset) < (ipv4_len + 1))
- goto getaddr_done;
+ 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;
+ }
- } else {
+ /*
+ * We only support two address families: AF_INET and AF_INET6.
+ * If a family value of 0 is specified, we collect 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 ((curp->ifa_addr->sa_family == AF_INET) &&
+ ((family == AF_INET) || (family == 0))) {
+ struct sockaddr_in *addr =
+ (struct sockaddr_in *) curp->ifa_addr;
+
+ str = inet_ntop(AF_INET, &addr->sin_addr, tmp, 50);
+ if (str == NULL) {
+ strcpy(buffer, "inet_ntop failed\n");
+ error = 1;
+ goto getaddr_done;
+ }
+ if (offset == 0)
+ strcpy(buffer, tmp);
+ else
+ strcat(buffer, tmp);
+ strcat(buffer, ";");
+
+ offset += strlen(str) + 1;
+ if ((length - offset) < (ipv4_len + 1))
+ goto getaddr_done;
+
+ } else if ((family == AF_INET6) || (family == 0)) {
/*
* We only support AF_INET and AF_INET6
* and the list of addresses is separated by a ";".
*/
- struct sockaddr_in6 *addr =
+ struct sockaddr_in6 *addr =
(struct sockaddr_in6 *) curp->ifa_addr;
- str = inet_ntop(family,
+ str = inet_ntop(AF_INET6,
&addr->sin6_addr.s6_addr,
tmp, 50);
- if (str == NULL) {
- strcpy(buffer, "inet_ntop failed\n");
- error = 1;
- goto getaddr_done;
- }
- if (offset == 0)
- strcpy(buffer, tmp);
- else
- strcat(buffer, tmp);
- strcat(buffer, ";");
- offset += strlen(str) + 1;
- if ((length - offset) < (ipv6_len + 1))
- goto getaddr_done;
-
+ if (str == NULL) {
+ strcpy(buffer, "inet_ntop failed\n");
+ error = 1;
+ goto getaddr_done;
}
+ if (offset == 0)
+ strcpy(buffer, tmp);
+ else
+ strcat(buffer, tmp);
+ strcat(buffer, ";");
+ offset += strlen(str) + 1;
+ if ((length - offset) < (ipv6_len + 1))
+ goto getaddr_done;
}
+
+
curp = curp->ifa_next;
}
@@ -812,13 +851,13 @@ int main(void)
strcpy(key_value, lic_version);
break;
case NetworkAddressIPv4:
- kvp_get_ip_address(AF_INET, key_value,
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ kvp_get_ip_address(AF_INET, NULL, KVP_OP_ENUMERATE,
+ key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "NetworkAddressIPv4");
break;
case NetworkAddressIPv6:
- kvp_get_ip_address(AF_INET6, key_value,
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ kvp_get_ip_address(AF_INET6, NULL, KVP_OP_ENUMERATE,
+ key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "NetworkAddressIPv6");
break;
case OSBuildNumber:
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 05/13] Tools: hv: Further refactor kvp_get_ip_address()
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (2 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 04/13] Tools: hv: Prepare to expand kvp_get_ip_address() functionality K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 06/13] Tools: hv: Gather address family information K. Y. Srinivasan
` (7 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
In preparation for making kvp_get_ip_address() more generic, factor out
the code for handling IP addresses.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 94 ++++++++++++++++++++-------------------------
1 files changed, 42 insertions(+), 52 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 4fa6f95..2235855 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -490,17 +490,50 @@ done:
return;
}
+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 1;
+ if (str == NULL) {
+ strcpy(buffer, "inet_ntop failed\n");
+ return 1;
+ }
+ if (*offset == 0)
+ strcpy(buffer, tmp);
+ else
+ strcat(buffer, tmp);
+ strcat(buffer, ";");
+
+ *offset += strlen(str) + 1;
+ return 0;
+}
+
static int
kvp_get_ip_address(int family, char *if_name, int op,
void *out_buffer, int length)
{
struct ifaddrs *ifap;
struct ifaddrs *curp;
- int ipv4_len = strlen("255.255.255.255") + 1;
- int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
int offset = 0;
const char *str;
- char tmp[50];
int error = 0;
char *buffer;
struct hv_kvp_ipaddr_value *ip_buffer;
@@ -555,55 +588,12 @@ kvp_get_ip_address(int family, char *if_name, int op,
continue;
}
- if ((curp->ifa_addr->sa_family == AF_INET) &&
- ((family == AF_INET) || (family == 0))) {
- struct sockaddr_in *addr =
- (struct sockaddr_in *) curp->ifa_addr;
-
- str = inet_ntop(AF_INET, &addr->sin_addr, tmp, 50);
- if (str == NULL) {
- strcpy(buffer, "inet_ntop failed\n");
- error = 1;
- goto getaddr_done;
- }
- if (offset == 0)
- strcpy(buffer, tmp);
- else
- strcat(buffer, tmp);
- strcat(buffer, ";");
-
- offset += strlen(str) + 1;
- if ((length - offset) < (ipv4_len + 1))
- goto getaddr_done;
-
- } else if ((family == AF_INET6) || (family == 0)) {
-
- /*
- * We only support AF_INET and AF_INET6
- * and the list of addresses is separated by a ";".
- */
- struct sockaddr_in6 *addr =
- (struct sockaddr_in6 *) curp->ifa_addr;
-
- str = inet_ntop(AF_INET6,
- &addr->sin6_addr.s6_addr,
- tmp, 50);
- if (str == NULL) {
- strcpy(buffer, "inet_ntop failed\n");
- error = 1;
- goto getaddr_done;
- }
- if (offset == 0)
- strcpy(buffer, tmp);
- else
- strcat(buffer, tmp);
- strcat(buffer, ";");
- offset += strlen(str) + 1;
- if ((length - offset) < (ipv6_len + 1))
- goto getaddr_done;
-
- }
-
+ error = kvp_process_ip_address(curp->ifa_addr,
+ curp->ifa_addr->sa_family,
+ buffer,
+ length, &offset);
+ if (error)
+ goto getaddr_done;
curp = curp->ifa_next;
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 06/13] Tools: hv: Gather address family information
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (3 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 05/13] Tools: hv: Further refactor kvp_get_ip_address() K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 07/13] Tools: hv: Gather subnet information K. Y. Srinivasan
` (6 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Now, gather address family information for the specified interface.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 2235855..b5db1b5 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -588,6 +588,17 @@ kvp_get_ip_address(int family, char *if_name, int op,
continue;
}
+ if (op == KVP_OP_GET_IP_INFO) {
+ /*
+ * Gather info other than the IP address.
+ * IP address info will be gathered later.
+ */
+ if (curp->ifa_addr->sa_family == AF_INET)
+ ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
+ else
+ ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
+ }
+
error = kvp_process_ip_address(curp->ifa_addr,
curp->ifa_addr->sa_family,
buffer,
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 07/13] Tools: hv: Gather subnet information
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (4 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 06/13] Tools: hv: Gather address family information K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 08/13] Tools: hv: Represent the ipv6 mask using CIDR notation K. Y. Srinivasan
` (5 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Now gather sub-net information for the specified interface.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 31 +++++++++++++++++++++++++++++--
1 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index b5db1b5..2160462 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -533,6 +533,7 @@ kvp_get_ip_address(int family, char *if_name, int op,
struct ifaddrs *ifap;
struct ifaddrs *curp;
int offset = 0;
+ int sn_offset = 0;
const char *str;
int error = 0;
char *buffer;
@@ -593,12 +594,38 @@ kvp_get_ip_address(int family, char *if_name, int op,
* Gather info other than the IP address.
* IP address info will be gathered later.
*/
- if (curp->ifa_addr->sa_family == AF_INET)
+ if (curp->ifa_addr->sa_family == AF_INET) {
ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
- else
+ /*
+ * Get subnet info.
+ */
+ error = kvp_process_ip_address(
+ curp->ifa_netmask,
+ AF_INET,
+ (char *)
+ ip_buffer->sub_net,
+ length,
+ &sn_offset);
+ if (error)
+ goto gather_ipaddr;
+ } else {
ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
+ /*
+ * Get subnet info.
+ */
+ error = kvp_process_ip_address(
+ curp->ifa_netmask,
+ AF_INET6,
+ (char *)
+ ip_buffer->sub_net,
+ length,
+ &sn_offset);
+ if (error)
+ goto gather_ipaddr;
+ }
}
+gather_ipaddr:
error = kvp_process_ip_address(curp->ifa_addr,
curp->ifa_addr->sa_family,
buffer,
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 08/13] Tools: hv: Represent the ipv6 mask using CIDR notation
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (5 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 07/13] Tools: hv: Gather subnet information K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 09/13] Tools: hv: Gather DNS information K. Y. Srinivasan
` (4 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Transfor ipv6 subnet information to CIDR notation.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 44 +++++++++++++++++++++++++++++++++++---------
1 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 2160462..8a153c5 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -490,6 +490,15 @@ done:
return;
}
+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)
@@ -538,6 +547,12 @@ kvp_get_ip_address(int family, char *if_name, int op,
int error = 0;
char *buffer;
struct hv_kvp_ipaddr_value *ip_buffer;
+ char cidr_mask[5]; /* /xyz */
+ int weight;
+ int i;
+ int *w;
+ char *sn_str;
+ struct sockaddr_in6 *addr6;
if (op == KVP_OP_ENUMERATE) {
buffer = out_buffer;
@@ -611,17 +626,28 @@ kvp_get_ip_address(int family, char *if_name, int op,
} else {
ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
/*
- * Get subnet info.
+ * Get subnet info in CIDR format.
*/
- error = kvp_process_ip_address(
- curp->ifa_netmask,
- AF_INET6,
- (char *)
- ip_buffer->sub_net,
- length,
- &sn_offset);
- if (error)
+ weight = 0;
+ sn_str = (char *)ip_buffer->sub_net;
+ addr6 = (struct sockaddr_in6 *)
+ curp->ifa_netmask;
+ w = addr6->sin6_addr.s6_addr32;
+
+ for (i = 0; i < 4; i++)
+ weight += hweight32(&w[i]);
+
+ sprintf(cidr_mask, "/%d", weight);
+ if ((length - sn_offset) <
+ (strlen(cidr_mask) + 1))
goto gather_ipaddr;
+
+ if (sn_offset == 0)
+ strcpy(sn_str, cidr_mask);
+ else
+ strcat(sn_str, cidr_mask);
+ strcat((char *)ip_buffer->sub_net, ";");
+ sn_offset += strlen(sn_str) + 1;
}
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 09/13] Tools: hv: Gather DNS information
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (6 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 08/13] Tools: hv: Represent the ipv6 mask using CIDR notation K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 10/13] Tools: hv: Gather ipv[4,6] gateway information K. Y. Srinivasan
` (3 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Now gather DNS information.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8a153c5..101ab7f 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -490,6 +490,50 @@ done:
return;
}
+static void kvp_get_ipconfig_info(char *if_name,
+ struct hv_kvp_ipaddr_value *buffer)
+{
+ char cmd[512];
+ char *dns_config = "/var/opt/hyperv/.kvp_dns_cfg";
+ FILE *file;
+ char buf[256];
+ char *dns_buf;
+ char *p;
+ char *x;
+
+ memset(cmd, 0, 512);
+ strcat(cmd, "cat /etc/resolv.conf 2>/tmp/null | ");
+ strcat(cmd, " awk '/nameserver/ {print $2 }' > ");
+ strcat(cmd, "/var/opt/hyperv/.kvp_dns_cfg");
+
+ /*
+ * Execute the command to gather dns info.
+ */
+ system(cmd);
+ file = fopen(dns_config, "r");
+ if (file == NULL)
+ return;
+
+ dns_buf = (char *)(buffer->dns_addr);
+ /*
+ * The buffer is an array of __u16 elements.
+ */
+ memset(dns_buf, 0, (MAX_IP_ADDR_SIZE * 2));
+ while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
+ if (((MAX_IP_ADDR_SIZE * 2) - strlen(dns_buf)) <
+ (INET6_ADDRSTRLEN + 1))
+ break;
+
+ x = strchr(p, '\n');
+ *x = '\0';
+ strcat(dns_buf, p);
+ strcat(dns_buf, ";");
+ }
+ fclose(file);
+
+}
+
+
static unsigned int hweight32(unsigned int *w)
{
unsigned int res = *w - ((*w >> 1) & 0x55555555);
@@ -649,6 +693,12 @@ kvp_get_ip_address(int family, char *if_name, int op,
strcat((char *)ip_buffer->sub_net, ";");
sn_offset += strlen(sn_str) + 1;
}
+
+ /*
+ * Collect other ip related configuration info.
+ */
+
+ kvp_get_ipconfig_info(if_name, ip_buffer);
}
gather_ipaddr:
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 10/13] Tools: hv: Gather ipv[4,6] gateway information
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (7 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 09/13] Tools: hv: Gather DNS information K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 11/13] Tools: hv: Gather dhcp information K. Y. Srinivasan
` (2 subsequent siblings)
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Collect ipv4 and ipv6 gateway information.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 80 ++++++++++++++++++++++++++++++++++------------
1 files changed, 59 insertions(+), 21 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 101ab7f..68a4cc1 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -490,16 +490,40 @@ done:
return;
}
+static void kvp_process_ipconfig_file(char *config_file,
+ char *config_buf, int len,
+ int element_size, int offset)
+{
+ char buf[256];
+ char *p;
+ char *x;
+ FILE *file;
+
+ file = fopen(config_file, "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';
+ strcat(config_buf, p);
+ strcat(config_buf, ";");
+ }
+ fclose(file);
+
+}
+
static void kvp_get_ipconfig_info(char *if_name,
struct hv_kvp_ipaddr_value *buffer)
{
char cmd[512];
char *dns_config = "/var/opt/hyperv/.kvp_dns_cfg";
- FILE *file;
- char buf[256];
- char *dns_buf;
- char *p;
- char *x;
+ char *gw_config = "/var/opt/hyperv/.kvp_gw_cfg";
memset(cmd, 0, 512);
strcat(cmd, "cat /etc/resolv.conf 2>/tmp/null | ");
@@ -508,29 +532,43 @@ static void kvp_get_ipconfig_info(char *if_name,
/*
* Execute the command to gather dns info.
+ * Note that all buffers are arrays of __u16.
*/
system(cmd);
- file = fopen(dns_config, "r");
- if (file == NULL)
- return;
+ kvp_process_ipconfig_file(dns_config, (char *)buffer->dns_addr,
+ (MAX_IP_ADDR_SIZE * 2), INET6_ADDRSTRLEN, 0);
- dns_buf = (char *)(buffer->dns_addr);
/*
- * The buffer is an array of __u16 elements.
+ * Get the address of default gateway (ipv4).
*/
- memset(dns_buf, 0, (MAX_IP_ADDR_SIZE * 2));
- while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
- if (((MAX_IP_ADDR_SIZE * 2) - strlen(dns_buf)) <
- (INET6_ADDRSTRLEN + 1))
- break;
+ memset(cmd, 0, 512);
+ strcat(cmd, "/sbin/ip -f inet route | grep -w ");
+ strcat(cmd, if_name);
+ strcat(cmd, " | awk '/default/ {print $3 }' > ");
+ strcat(cmd, "/var/opt/hyperv/.kvp_gw_cfg");
- x = strchr(p, '\n');
- *x = '\0';
- strcat(dns_buf, p);
- strcat(dns_buf, ";");
- }
- fclose(file);
+ /*
+ * Execute the command to gather gateway info.
+ */
+ system(cmd);
+ kvp_process_ipconfig_file(gw_config, (char *)buffer->gate_way,
+ (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
+ /*
+ * Get the address of default gateway (ipv6).
+ */
+ memset(cmd, 0, 512);
+ strcat(cmd, "/sbin/ip -f inet6 route | grep -w ");
+ strcat(cmd, if_name);
+ strcat(cmd, " | awk '/default/ {print $3 }' > ");
+ strcat(cmd, "/var/opt/hyperv/.kvp_gw_cfg");
+ /*
+ * Execute the command to gather gateway info (ipv6).
+ */
+ system(cmd);
+ kvp_process_ipconfig_file(gw_config, (char *)buffer->gate_way,
+ (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN,
+ strlen(gw_config));
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 11/13] Tools: hv: Gather dhcp information
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (8 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 10/13] Tools: hv: Gather ipv[4,6] gateway information K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 12/13] Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 13/13] Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO K. Y. Srinivasan
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Collect information on dhcp setting for the specified interface.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 68a4cc1..dcf67fa 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -524,6 +524,10 @@ static void kvp_get_ipconfig_info(char *if_name,
char cmd[512];
char *dns_config = "/var/opt/hyperv/.kvp_dns_cfg";
char *gw_config = "/var/opt/hyperv/.kvp_gw_cfg";
+ char if_cfg_file[256];
+ FILE *file;
+ char *p;
+ char buf[256];
memset(cmd, 0, 512);
strcat(cmd, "cat /etc/resolv.conf 2>/tmp/null | ");
@@ -569,6 +573,35 @@ static void kvp_get_ipconfig_info(char *if_name,
kvp_process_ipconfig_file(gw_config, (char *)buffer->gate_way,
(MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN,
strlen(gw_config));
+
+ /*
+ * Get the boot protocol for the interface.
+ * We will get the info from:
+ * /etc/sysconfig/network-scripts/ifcfg-ethx
+ * If need to parse other files to get
+ * this info, we need to add code to parse
+ * other files.
+ */
+ memset(if_cfg_file, 0, sizeof(if_cfg_file));
+ strcat(if_cfg_file, "/etc/sysconfig/network-scripts/ifcfg-");
+ strcat(if_cfg_file, if_name);
+
+ file = fopen(if_cfg_file, "r");
+ if (file == NULL)
+ /*
+ * Add code to parse other files.
+ */
+ return;
+
+ while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
+ if (strncmp(p, "BOOTPROTO", 9))
+ continue;
+ if (strncmp(p, "BOOTPROTO=none", 14))
+ buffer->dhcp_enabled = 0;
+ else
+ buffer->dhcp_enabled = 1;
+ }
+
}
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 12/13] Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (9 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 11/13] Tools: hv: Gather dhcp information K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
2012-06-21 21:31 ` [PATCH 13/13] Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO K. Y. Srinivasan
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Cc: K. Y. Srinivasan
Now implement the KVP verb - KVP_OP_GET_IP_INFO. This operation retrieves IP
information for the specified interface.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 95 ++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 92 insertions(+), 3 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index dcf67fa..569f4d7 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -41,6 +41,7 @@
#include <syslog.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <dirent.h>
/*
* KVP protocol: The user mode component first registers with the
@@ -490,6 +491,64 @@ done:
return;
}
+/*
+ * Retrieve an interface name corresponding to the specified guid.
+ * If there is a match, the function returns a pointer
+ * to the interface name and if not, a NULL is returned.
+ * If a match is found, the caller is responsible for
+ * freeing the memory.
+ */
+
+static char *kvp_get_if_name(char *guid, int guid_len)
+{
+ DIR *dir;
+ struct dirent *entry;
+ FILE *file;
+ char *p, *q;
+ char *if_name = NULL;
+ char buf[256];
+ char *kvp_net_dir = "/sys/class/net/";
+ char dev_id[100];
+
+ dir = opendir(kvp_net_dir);
+ if (dir == NULL)
+ return NULL;
+
+ memset(dev_id, 0, sizeof(dev_id));
+ strcat(dev_id, kvp_net_dir);
+ q = dev_id + strlen(kvp_net_dir);
+
+ while ((entry = readdir(dir)) != NULL) {
+ /*
+ * Set the state for the next pass.
+ */
+ *q = '\0';
+ strcat(dev_id, entry->d_name);
+ strcat(dev_id, "/device/device_id");
+
+ file = fopen(dev_id, "r");
+ if (file == NULL)
+ continue;
+
+ p = fgets(buf, sizeof(buf), file);
+ if (p) {
+ if (!strncmp(p, guid, guid_len)) {
+ /*
+ * Found the guid match; return the interface
+ * name. The caller will free the memory.
+ */
+ if_name = strdup(entry->d_name);
+ break;
+ }
+ }
+ fclose(file);
+ }
+
+ closedir(dir);
+ return if_name;
+}
+
+
static void kvp_process_ipconfig_file(char *config_file,
char *config_buf, int len,
int element_size, int offset)
@@ -651,7 +710,7 @@ static int kvp_process_ip_address(void *addrp,
}
static int
-kvp_get_ip_address(int family, char *if_name, int op,
+kvp_get_ip_info(int family, char *if_name, int op,
void *out_buffer, int length)
{
struct ifaddrs *ifap;
@@ -858,6 +917,10 @@ int main(void)
char *key_name;
int op;
int pool;
+ char *if_name;
+ struct hv_kvp_ipaddr_value *kvp_ip_val;
+
+
daemon(1, 0);
openlog("KVP", 0, LOG_USER);
@@ -959,6 +1022,32 @@ int main(void)
}
continue;
+ case KVP_OP_GET_IP_INFO:
+ kvp_ip_val = &hv_msg->body.kvp_ip_val;
+ if_name = kvp_get_if_name(
+ (char *)kvp_ip_val->adapter_id,
+ MAX_ADAPTER_ID_SIZE);
+ if (if_name == NULL) {
+ /*
+ * We could not map the guid to an
+ * interface name; return error.
+ */
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_ERROR_DEVICE_NOT_CONNECTED;
+ break;
+ }
+ error = kvp_get_ip_info(
+ 0, if_name, KVP_OP_GET_IP_INFO,
+ kvp_ip_val,
+ (MAX_IP_ADDR_SIZE * 2));
+
+ if (error)
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_ERROR_DEVICE_NOT_CONNECTED;
+
+ free(if_name);
+ break;
+
case KVP_OP_SET:
if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_set.data.key,
@@ -1026,12 +1115,12 @@ int main(void)
strcpy(key_value, lic_version);
break;
case NetworkAddressIPv4:
- kvp_get_ip_address(AF_INET, NULL, KVP_OP_ENUMERATE,
+ kvp_get_ip_info(AF_INET, NULL, KVP_OP_ENUMERATE,
key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "NetworkAddressIPv4");
break;
case NetworkAddressIPv6:
- kvp_get_ip_address(AF_INET6, NULL, KVP_OP_ENUMERATE,
+ kvp_get_ip_info(AF_INET6, NULL, KVP_OP_ENUMERATE,
key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
strcpy(key_name, "NetworkAddressIPv6");
break;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread* [PATCH 13/13] Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO
2012-06-21 21:31 ` [PATCH 01/13] Drivers: hv: Add KVP definitions for IP address injection K. Y. Srinivasan
` (10 preceding siblings ...)
2012-06-21 21:31 ` [PATCH 12/13] Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO K. Y. Srinivasan
@ 2012-06-21 21:31 ` K. Y. Srinivasan
11 siblings, 0 replies; 31+ messages in thread
From: K. Y. Srinivasan @ 2012-06-21 21:31 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, ohering, apw
Implement the KVP_OP_SET_IP_INFO verb. This operation sets the IP information
on the specified interface.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
tools/hv/hv_kvp_daemon.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 198 insertions(+), 0 deletions(-)
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 569f4d7..8eefdb5 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -847,6 +847,183 @@ getaddr_done:
return error;
}
+int parse_ip_val_buffer(char *in_buf, int *offset, char *out_buf, int out_len)
+{
+ int end;
+ char *x;
+ char *start;
+
+ /*
+ * in_buf has sequence of characters that are seperated by
+ * the character ';'. The last sequence is terminated by ';'.
+ */
+ start = in_buf + *offset;
+
+ x = strchr(start, ';');
+ if (x) {
+ *x = 0;
+ if ((x - start) <= out_len) {
+ strcpy(out_buf, start);
+ strcat(out_buf, "\n");
+ *offset = (x - start) + 1;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
+{
+ int error = 0;
+ char if_path[256];
+ char if_tmp_path[256];
+ FILE *file;
+ char addr[INET6_ADDRSTRLEN];
+ int i;
+ char cmd[256];
+ char str[256];
+ int offset;
+
+ /*
+ * Set the specified info in the appropriate config file
+ * for the specified interface and flush the settings.
+ * Currently we support distributions that maintain
+ * network configuration information in file:
+ * /etc/sysconfig/network-scripts/icfg-ifname
+ */
+ memset(if_path, 0, sizeof(if_path));
+ strcat(if_path, "/etc/sysconfig/network-scripts/ifcfg-");
+ strcat(if_path, if_name);
+
+ memset(if_tmp_path, 0, sizeof(if_tmp_path));
+ strcat(if_tmp_path, "/var/opt/hyperv/.kvp_ifcfg-");
+ strcat(if_tmp_path, if_name);
+
+ file = fopen(if_path, "r");
+ if (file == NULL) {
+ /*
+ * This system maintains the interface configuration
+ * information in a different location. Need to add
+ * code to deal with that. For now fail the operation.
+ */
+ return 1;
+ }
+
+ fclose(file);
+ /*
+ * The host gives us complete configuration information for the
+ * interface; just overwrite the current info.
+ * To deal with intermediate failues, first write a temp file.
+ */
+
+ file = fopen(if_tmp_path, "w");
+
+ if (file == NULL)
+ return 1;
+
+ if (new_val->dhcp_enabled) {
+ error = fputs("BOOTPROTO=dhcp\n", file);
+ if (error == EOF)
+ goto setval_error;
+
+ /*
+ * We are done!.
+ */
+ goto setval_done;
+ }
+
+ /*
+ * Write the configuration for ipaddress, netmask, gateway and
+ * name servers.
+ */
+ i = 0;
+ offset = 0;
+ memset(addr, 0, sizeof(addr));
+ memset(str, 0, sizeof(str));
+
+ while (parse_ip_val_buffer((char *)new_val->ip_addr, &offset, addr,
+ (MAX_IP_ADDR_SIZE * 2))) {
+ sprintf(str, "IPADDR_%d=", i++);
+ strcat(str, addr);
+ error = fputs(str, file);
+ if (error == EOF)
+ goto setval_error;
+ }
+
+ i = 0;
+ offset = 0;
+ memset(addr, 0, sizeof(addr));
+ memset(str, 0, sizeof(str));
+
+ while (parse_ip_val_buffer((char *)new_val->sub_net, &offset, addr,
+ (MAX_IP_ADDR_SIZE * 2))) {
+ sprintf(str, "NETMAK_%d=", i++);
+ strcat(str, addr);
+ error = fputs(str, file);
+ if (error == EOF)
+ goto setval_error;
+ }
+
+ i = 0;
+ offset = 0;
+ memset(addr, 0, sizeof(addr));
+ memset(str, 0, sizeof(str));
+
+ while (parse_ip_val_buffer((char *)new_val->gate_way, &offset, addr,
+ (MAX_IP_ADDR_SIZE * 2))) {
+ sprintf(str, "GATEWAY_%d=", i++);
+ strcat(str, addr);
+ error = fputs(str, file);
+ if (error == EOF)
+ goto setval_error;
+ }
+
+ i = 0;
+ offset = 0;
+ memset(addr, 0, sizeof(addr));
+ memset(str, 0, sizeof(str));
+
+ while (parse_ip_val_buffer((char *)new_val->dns_addr, &offset, addr,
+ (MAX_IP_ADDR_SIZE * 2))) {
+ sprintf(str, "DNS%d=", i++);
+ strcat(str, addr);
+ error = fputs(str, file);
+ if (error == EOF)
+ goto setval_error;
+ }
+
+ error = fputs("ONBOOT=yes\n", file);
+ if (error == EOF)
+ goto setval_error;
+
+ error = fputs("PEERDNS=yes\n", file);
+ if (error == EOF)
+ goto setval_error;
+
+setval_done:
+ /*
+ * Now move the config file to the final location.
+ */
+ fclose(file);
+ memset(cmd, 0, sizeof(cmd));
+ strcat(cmd, "mv ");
+ strcat(cmd, if_tmp_path);
+ strcat(cmd, " ");
+ strcat(cmd, if_path);
+ system(cmd);
+
+ /*
+ * Now restart the network to flush the parameters.
+ */
+ memset(cmd, 0, sizeof(cmd));
+ strcat(cmd, "service network restart");
+ system(cmd);
+ return 0;
+
+setval_error:
+ fclose(file);
+ return error;
+}
static int
kvp_get_domain_name(char *buffer, int length)
@@ -1048,6 +1225,27 @@ int main(void)
free(if_name);
break;
+ case KVP_OP_SET_IP_INFO:
+ kvp_ip_val = &hv_msg->body.kvp_ip_val;
+ if_name = kvp_get_if_name(
+ (char *)kvp_ip_val->adapter_id,
+ MAX_ADAPTER_ID_SIZE);
+ if (if_name == NULL) {
+ /*
+ * We could not map the guid to an
+ * interface name; return error.
+ */
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_ERROR_DEVICE_NOT_CONNECTED;
+ break;
+ }
+ error = kvp_set_ip_info(if_name, kvp_ip_val);
+ if (error)
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_ERROR_DEVICE_NOT_CONNECTED;
+
+ free(if_name);
+ break;
case KVP_OP_SET:
if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
hv_msg->body.kvp_set.data.key,
--
1.7.4.1
^ permalink raw reply related [flat|nested] 31+ messages in thread