diff options
author | K. Y. Srinivasan <kys@microsoft.com> | 2012-08-16 21:32:17 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-17 11:23:58 -0400 |
commit | 6a60a6a8ea97795a288469c21262522894a1e6db (patch) | |
tree | d51f0e970221137502beb00146aaf2575e75dac2 /tools | |
parent | 04405784591117539eac4f5348c86d66dc0dd4f1 (diff) |
Tools: hv: Represent the ipv6 mask using CIDR notation
Transform ipv6 subnet information to CIDR notation.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/hv/hv_kvp_daemon.c | 46 |
1 files changed, 36 insertions, 10 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index de1724cbaf59..a63e83a0159f 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -491,6 +491,15 @@ done: | |||
491 | return; | 491 | return; |
492 | } | 492 | } |
493 | 493 | ||
494 | static unsigned int hweight32(unsigned int *w) | ||
495 | { | ||
496 | unsigned int res = *w - ((*w >> 1) & 0x55555555); | ||
497 | res = (res & 0x33333333) + ((res >> 2) & 0x33333333); | ||
498 | res = (res + (res >> 4)) & 0x0F0F0F0F; | ||
499 | res = res + (res >> 8); | ||
500 | return (res + (res >> 16)) & 0x000000FF; | ||
501 | } | ||
502 | |||
494 | static int kvp_process_ip_address(void *addrp, | 503 | static int kvp_process_ip_address(void *addrp, |
495 | int family, char *buffer, | 504 | int family, char *buffer, |
496 | int length, int *offset) | 505 | int length, int *offset) |
@@ -535,10 +544,15 @@ kvp_get_ip_address(int family, char *if_name, int op, | |||
535 | struct ifaddrs *curp; | 544 | struct ifaddrs *curp; |
536 | int offset = 0; | 545 | int offset = 0; |
537 | int sn_offset = 0; | 546 | int sn_offset = 0; |
538 | const char *str; | ||
539 | int error = 0; | 547 | int error = 0; |
540 | char *buffer; | 548 | char *buffer; |
541 | struct hv_kvp_ipaddr_value *ip_buffer; | 549 | struct hv_kvp_ipaddr_value *ip_buffer; |
550 | char cidr_mask[5]; /* /xyz */ | ||
551 | int weight; | ||
552 | int i; | ||
553 | unsigned int *w; | ||
554 | char *sn_str; | ||
555 | struct sockaddr_in6 *addr6; | ||
542 | 556 | ||
543 | if (op == KVP_OP_ENUMERATE) { | 557 | if (op == KVP_OP_ENUMERATE) { |
544 | buffer = out_buffer; | 558 | buffer = out_buffer; |
@@ -611,18 +625,30 @@ kvp_get_ip_address(int family, char *if_name, int op, | |||
611 | goto gather_ipaddr; | 625 | goto gather_ipaddr; |
612 | } else { | 626 | } else { |
613 | ip_buffer->addr_family |= ADDR_FAMILY_IPV6; | 627 | ip_buffer->addr_family |= ADDR_FAMILY_IPV6; |
628 | |||
614 | /* | 629 | /* |
615 | * Get subnet info. | 630 | * Get subnet info in CIDR format. |
616 | */ | 631 | */ |
617 | error = kvp_process_ip_address( | 632 | weight = 0; |
618 | curp->ifa_netmask, | 633 | sn_str = (char *)ip_buffer->sub_net; |
619 | AF_INET6, | 634 | addr6 = (struct sockaddr_in6 *) |
620 | (char *) | 635 | curp->ifa_netmask; |
621 | ip_buffer->sub_net, | 636 | w = addr6->sin6_addr.s6_addr32; |
622 | length, | 637 | |
623 | &sn_offset); | 638 | for (i = 0; i < 4; i++) |
624 | if (error) | 639 | weight += hweight32(&w[i]); |
640 | |||
641 | sprintf(cidr_mask, "/%d", weight); | ||
642 | if ((length - sn_offset) < | ||
643 | (strlen(cidr_mask) + 1)) | ||
625 | goto gather_ipaddr; | 644 | goto gather_ipaddr; |
645 | |||
646 | if (sn_offset == 0) | ||
647 | strcpy(sn_str, cidr_mask); | ||
648 | else | ||
649 | strcat(sn_str, cidr_mask); | ||
650 | strcat((char *)ip_buffer->sub_net, ";"); | ||
651 | sn_offset += strlen(sn_str) + 1; | ||
626 | } | 652 | } |
627 | } | 653 | } |
628 | 654 | ||