|
@@ -492,7 +492,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;
|
|
@@ -502,10 +503,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)) {
|
|
@@ -515,58 +525,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;
|
|
|
}
|
|
|
|
|
@@ -811,13 +850,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:
|