aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/hv/hv_kvp_daemon.c337
1 files changed, 249 insertions, 88 deletions
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d9834b362943..65d54c89394e 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -69,15 +69,16 @@ enum key_index {
69}; 69};
70 70
71static char kvp_send_buffer[4096]; 71static char kvp_send_buffer[4096];
72static char kvp_recv_buffer[4096]; 72static char kvp_recv_buffer[4096 * 2];
73static struct sockaddr_nl addr; 73static struct sockaddr_nl addr;
74static int in_hand_shake = 1;
74 75
75static char *os_name = ""; 76static char *os_name = "";
76static char *os_major = ""; 77static char *os_major = "";
77static char *os_minor = ""; 78static char *os_minor = "";
78static char *processor_arch; 79static char *processor_arch;
79static char *os_build; 80static char *os_build;
80static char *lic_version; 81static char *lic_version = "Unknown version";
81static struct utsname uts_buf; 82static struct utsname uts_buf;
82 83
83 84
@@ -394,7 +395,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
394 return 1; 395 return 1;
395} 396}
396 397
397static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size, 398static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
398 __u8 *value, int value_size) 399 __u8 *value, int value_size)
399{ 400{
400 struct kvp_record *record; 401 struct kvp_record *record;
@@ -406,16 +407,12 @@ static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
406 record = kvp_file_info[pool].records; 407 record = kvp_file_info[pool].records;
407 408
408 if (index >= kvp_file_info[pool].num_records) { 409 if (index >= kvp_file_info[pool].num_records) {
409 /* 410 return 1;
410 * This is an invalid index; terminate enumeration;
411 * - a NULL value will do the trick.
412 */
413 strcpy(value, "");
414 return;
415 } 411 }
416 412
417 memcpy(key, record[index].key, key_size); 413 memcpy(key, record[index].key, key_size);
418 memcpy(value, record[index].value, value_size); 414 memcpy(value, record[index].value, value_size);
415 return 0;
419} 416}
420 417
421 418
@@ -494,21 +491,141 @@ done:
494 return; 491 return;
495} 492}
496 493
494static void kvp_process_ipconfig_file(char *cmd,
495 char *config_buf, int len,
496 int element_size, int offset)
497{
498 char buf[256];
499 char *p;
500 char *x;
501 FILE *file;
502
503 /*
504 * First execute the command.
505 */
506 file = popen(cmd, "r");
507 if (file == NULL)
508 return;
509
510 if (offset == 0)
511 memset(config_buf, 0, len);
512 while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
513 if ((len - strlen(config_buf)) < (element_size + 1))
514 break;
515
516 x = strchr(p, '\n');
517 *x = '\0';
518 strcat(config_buf, p);
519 strcat(config_buf, ";");
520 }
521 pclose(file);
522}
523
524static void kvp_get_ipconfig_info(char *if_name,
525 struct hv_kvp_ipaddr_value *buffer)
526{
527 char cmd[512];
528
529 /*
530 * Get the address of default gateway (ipv4).
531 */
532 sprintf(cmd, "%s %s", "ip route show dev", if_name);
533 strcat(cmd, " | awk '/default/ {print $3 }'");
534
535 /*
536 * Execute the command to gather gateway info.
537 */
538 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
539 (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
540
541 /*
542 * Get the address of default gateway (ipv6).
543 */
544 sprintf(cmd, "%s %s", "ip -f inet6 route show dev", if_name);
545 strcat(cmd, " | awk '/default/ {print $3 }'");
546
547 /*
548 * Execute the command to gather gateway info (ipv6).
549 */
550 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
551 (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
552
553}
554
555
556static unsigned int hweight32(unsigned int *w)
557{
558 unsigned int res = *w - ((*w >> 1) & 0x55555555);
559 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
560 res = (res + (res >> 4)) & 0x0F0F0F0F;
561 res = res + (res >> 8);
562 return (res + (res >> 16)) & 0x000000FF;
563}
564
565static int kvp_process_ip_address(void *addrp,
566 int family, char *buffer,
567 int length, int *offset)
568{
569 struct sockaddr_in *addr;
570 struct sockaddr_in6 *addr6;
571 int addr_length;
572 char tmp[50];
573 const char *str;
574
575 if (family == AF_INET) {
576 addr = (struct sockaddr_in *)addrp;
577 str = inet_ntop(family, &addr->sin_addr, tmp, 50);
578 addr_length = INET_ADDRSTRLEN;
579 } else {
580 addr6 = (struct sockaddr_in6 *)addrp;
581 str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
582 addr_length = INET6_ADDRSTRLEN;
583 }
584
585 if ((length - *offset) < addr_length + 1)
586 return 1;
587 if (str == NULL) {
588 strcpy(buffer, "inet_ntop failed\n");
589 return 1;
590 }
591 if (*offset == 0)
592 strcpy(buffer, tmp);
593 else
594 strcat(buffer, tmp);
595 strcat(buffer, ";");
596
597 *offset += strlen(str) + 1;
598 return 0;
599}
600
497static int 601static int
498kvp_get_ip_address(int family, char *buffer, int length) 602kvp_get_ip_address(int family, char *if_name, int op,
603 void *out_buffer, int length)
499{ 604{
500 struct ifaddrs *ifap; 605 struct ifaddrs *ifap;
501 struct ifaddrs *curp; 606 struct ifaddrs *curp;
502 int ipv4_len = strlen("255.255.255.255") + 1;
503 int ipv6_len = strlen("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")+1;
504 int offset = 0; 607 int offset = 0;
505 const char *str; 608 int sn_offset = 0;
506 char tmp[50];
507 int error = 0; 609 int error = 0;
508 610 char *buffer;
611 struct hv_kvp_ipaddr_value *ip_buffer;
612 char cidr_mask[5]; /* /xyz */
613 int weight;
614 int i;
615 unsigned int *w;
616 char *sn_str;
617 struct sockaddr_in6 *addr6;
618
619 if (op == KVP_OP_ENUMERATE) {
620 buffer = out_buffer;
621 } else {
622 ip_buffer = out_buffer;
623 buffer = (char *)ip_buffer->ip_addr;
624 ip_buffer->addr_family = 0;
625 }
509 /* 626 /*
510 * On entry into this function, the buffer is capable of holding the 627 * On entry into this function, the buffer is capable of holding the
511 * maximum key value (2048 bytes). 628 * maximum key value.
512 */ 629 */
513 630
514 if (getifaddrs(&ifap)) { 631 if (getifaddrs(&ifap)) {
@@ -518,58 +635,99 @@ kvp_get_ip_address(int family, char *buffer, int length)
518 635
519 curp = ifap; 636 curp = ifap;
520 while (curp != NULL) { 637 while (curp != NULL) {
521 if ((curp->ifa_addr != NULL) && 638 if (curp->ifa_addr == NULL) {
522 (curp->ifa_addr->sa_family == family)) { 639 curp = curp->ifa_next;
523 if (family == AF_INET) { 640 continue;
524 struct sockaddr_in *addr = 641 }
525 (struct sockaddr_in *) curp->ifa_addr;
526
527 str = inet_ntop(family, &addr->sin_addr,
528 tmp, 50);
529 if (str == NULL) {
530 strcpy(buffer, "inet_ntop failed\n");
531 error = 1;
532 goto getaddr_done;
533 }
534 if (offset == 0)
535 strcpy(buffer, tmp);
536 else
537 strcat(buffer, tmp);
538 strcat(buffer, ";");
539 642
540 offset += strlen(str) + 1; 643 if ((if_name != NULL) &&
541 if ((length - offset) < (ipv4_len + 1)) 644 (strncmp(curp->ifa_name, if_name, strlen(if_name)))) {
542 goto getaddr_done; 645 /*
646 * We want info about a specific interface;
647 * just continue.
648 */
649 curp = curp->ifa_next;
650 continue;
651 }
543 652
544 } else { 653 /*
654 * We only support two address families: AF_INET and AF_INET6.
655 * If a family value of 0 is specified, we collect both
656 * supported address families; if not we gather info on
657 * the specified address family.
658 */
659 if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
660 curp = curp->ifa_next;
661 continue;
662 }
663 if ((curp->ifa_addr->sa_family != AF_INET) &&
664 (curp->ifa_addr->sa_family != AF_INET6)) {
665 curp = curp->ifa_next;
666 continue;
667 }
545 668
669 if (op == KVP_OP_GET_IP_INFO) {
546 /* 670 /*
547 * We only support AF_INET and AF_INET6 671 * Gather info other than the IP address.
548 * and the list of addresses is separated by a ";". 672 * IP address info will be gathered later.
549 */ 673 */
550 struct sockaddr_in6 *addr = 674 if (curp->ifa_addr->sa_family == AF_INET) {
551 (struct sockaddr_in6 *) curp->ifa_addr; 675 ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
552 676 /*
553 str = inet_ntop(family, 677 * Get subnet info.
554 &addr->sin6_addr.s6_addr, 678 */
555 tmp, 50); 679 error = kvp_process_ip_address(
556 if (str == NULL) { 680 curp->ifa_netmask,
557 strcpy(buffer, "inet_ntop failed\n"); 681 AF_INET,
558 error = 1; 682 (char *)
559 goto getaddr_done; 683 ip_buffer->sub_net,
560 } 684 length,
561 if (offset == 0) 685 &sn_offset);
562 strcpy(buffer, tmp); 686 if (error)
563 else 687 goto gather_ipaddr;
564 strcat(buffer, tmp); 688 } else {
565 strcat(buffer, ";"); 689 ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
566 offset += strlen(str) + 1;
567 if ((length - offset) < (ipv6_len + 1))
568 goto getaddr_done;
569 690
691 /*
692 * Get subnet info in CIDR format.
693 */
694 weight = 0;
695 sn_str = (char *)ip_buffer->sub_net;
696 addr6 = (struct sockaddr_in6 *)
697 curp->ifa_netmask;
698 w = addr6->sin6_addr.s6_addr32;
699
700 for (i = 0; i < 4; i++)
701 weight += hweight32(&w[i]);
702
703 sprintf(cidr_mask, "/%d", weight);
704 if ((length - sn_offset) <
705 (strlen(cidr_mask) + 1))
706 goto gather_ipaddr;
707
708 if (sn_offset == 0)
709 strcpy(sn_str, cidr_mask);
710 else
711 strcat(sn_str, cidr_mask);
712 strcat((char *)ip_buffer->sub_net, ";");
713 sn_offset += strlen(sn_str) + 1;
570 } 714 }
571 715
716 /*
717 * Collect other ip related configuration info.
718 */
719
720 kvp_get_ipconfig_info(if_name, ip_buffer);
572 } 721 }
722
723gather_ipaddr:
724 error = kvp_process_ip_address(curp->ifa_addr,
725 curp->ifa_addr->sa_family,
726 buffer,
727 length, &offset);
728 if (error)
729 goto getaddr_done;
730
573 curp = curp->ifa_next; 731 curp = curp->ifa_next;
574 } 732 }
575 733
@@ -646,6 +804,8 @@ int main(void)
646 char *p; 804 char *p;
647 char *key_value; 805 char *key_value;
648 char *key_name; 806 char *key_name;
807 int op;
808 int pool;
649 809
650 daemon(1, 0); 810 daemon(1, 0);
651 openlog("KVP", 0, LOG_USER); 811 openlog("KVP", 0, LOG_USER);
@@ -687,7 +847,7 @@ int main(void)
687 message->id.val = CN_KVP_VAL; 847 message->id.val = CN_KVP_VAL;
688 848
689 hv_msg = (struct hv_kvp_msg *)message->data; 849 hv_msg = (struct hv_kvp_msg *)message->data;
690 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; 850 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
691 message->ack = 0; 851 message->ack = 0;
692 message->len = sizeof(struct hv_kvp_msg); 852 message->len = sizeof(struct hv_kvp_msg);
693 853
@@ -721,12 +881,21 @@ int main(void)
721 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 881 incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
722 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; 882 hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
723 883
724 switch (hv_msg->kvp_hdr.operation) { 884 /*
725 case KVP_OP_REGISTER: 885 * We will use the KVP header information to pass back
886 * the error from this daemon. So, first copy the state
887 * and set the error code to success.
888 */
889 op = hv_msg->kvp_hdr.operation;
890 pool = hv_msg->kvp_hdr.pool;
891 hv_msg->error = HV_S_OK;
892
893 if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
726 /* 894 /*
727 * Driver is registering with us; stash away the version 895 * Driver is registering with us; stash away the version
728 * information. 896 * information.
729 */ 897 */
898 in_hand_shake = 0;
730 p = (char *)hv_msg->body.kvp_register.version; 899 p = (char *)hv_msg->body.kvp_register.version;
731 lic_version = malloc(strlen(p) + 1); 900 lic_version = malloc(strlen(p) + 1);
732 if (lic_version) { 901 if (lic_version) {
@@ -737,44 +906,39 @@ int main(void)
737 syslog(LOG_ERR, "malloc failed"); 906 syslog(LOG_ERR, "malloc failed");
738 } 907 }
739 continue; 908 continue;
909 }
740 910
741 /* 911 switch (op) {
742 * The current protocol with the kernel component uses a
743 * NULL key name to pass an error condition.
744 * For the SET, GET and DELETE operations,
745 * use the existing protocol to pass back error.
746 */
747
748 case KVP_OP_SET: 912 case KVP_OP_SET:
749 if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool, 913 if (kvp_key_add_or_modify(pool,
750 hv_msg->body.kvp_set.data.key, 914 hv_msg->body.kvp_set.data.key,
751 hv_msg->body.kvp_set.data.key_size, 915 hv_msg->body.kvp_set.data.key_size,
752 hv_msg->body.kvp_set.data.value, 916 hv_msg->body.kvp_set.data.value,
753 hv_msg->body.kvp_set.data.value_size)) 917 hv_msg->body.kvp_set.data.value_size))
754 strcpy(hv_msg->body.kvp_set.data.key, ""); 918 hv_msg->error = HV_S_CONT;
755 break; 919 break;
756 920
757 case KVP_OP_GET: 921 case KVP_OP_GET:
758 if (kvp_get_value(hv_msg->kvp_hdr.pool, 922 if (kvp_get_value(pool,
759 hv_msg->body.kvp_set.data.key, 923 hv_msg->body.kvp_set.data.key,
760 hv_msg->body.kvp_set.data.key_size, 924 hv_msg->body.kvp_set.data.key_size,
761 hv_msg->body.kvp_set.data.value, 925 hv_msg->body.kvp_set.data.value,
762 hv_msg->body.kvp_set.data.value_size)) 926 hv_msg->body.kvp_set.data.value_size))
763 strcpy(hv_msg->body.kvp_set.data.key, ""); 927 hv_msg->error = HV_S_CONT;
764 break; 928 break;
765 929
766 case KVP_OP_DELETE: 930 case KVP_OP_DELETE:
767 if (kvp_key_delete(hv_msg->kvp_hdr.pool, 931 if (kvp_key_delete(pool,
768 hv_msg->body.kvp_delete.key, 932 hv_msg->body.kvp_delete.key,
769 hv_msg->body.kvp_delete.key_size)) 933 hv_msg->body.kvp_delete.key_size))
770 strcpy(hv_msg->body.kvp_delete.key, ""); 934 hv_msg->error = HV_S_CONT;
771 break; 935 break;
772 936
773 default: 937 default:
774 break; 938 break;
775 } 939 }
776 940
777 if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE) 941 if (op != KVP_OP_ENUMERATE)
778 goto kvp_done; 942 goto kvp_done;
779 943
780 /* 944 /*
@@ -782,13 +946,14 @@ int main(void)
782 * both the key and the value; if not read from the 946 * both the key and the value; if not read from the
783 * appropriate pool. 947 * appropriate pool.
784 */ 948 */
785 if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) { 949 if (pool != KVP_POOL_AUTO) {
786 kvp_pool_enumerate(hv_msg->kvp_hdr.pool, 950 if (kvp_pool_enumerate(pool,
787 hv_msg->body.kvp_enum_data.index, 951 hv_msg->body.kvp_enum_data.index,
788 hv_msg->body.kvp_enum_data.data.key, 952 hv_msg->body.kvp_enum_data.data.key,
789 HV_KVP_EXCHANGE_MAX_KEY_SIZE, 953 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
790 hv_msg->body.kvp_enum_data.data.value, 954 hv_msg->body.kvp_enum_data.data.value,
791 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 955 HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
956 hv_msg->error = HV_S_CONT;
792 goto kvp_done; 957 goto kvp_done;
793 } 958 }
794 959
@@ -807,13 +972,13 @@ int main(void)
807 strcpy(key_value, lic_version); 972 strcpy(key_value, lic_version);
808 break; 973 break;
809 case NetworkAddressIPv4: 974 case NetworkAddressIPv4:
810 kvp_get_ip_address(AF_INET, key_value, 975 kvp_get_ip_address(AF_INET, NULL, KVP_OP_ENUMERATE,
811 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 976 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
812 strcpy(key_name, "NetworkAddressIPv4"); 977 strcpy(key_name, "NetworkAddressIPv4");
813 break; 978 break;
814 case NetworkAddressIPv6: 979 case NetworkAddressIPv6:
815 kvp_get_ip_address(AF_INET6, key_value, 980 kvp_get_ip_address(AF_INET6, NULL, KVP_OP_ENUMERATE,
816 HV_KVP_EXCHANGE_MAX_VALUE_SIZE); 981 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
817 strcpy(key_name, "NetworkAddressIPv6"); 982 strcpy(key_name, "NetworkAddressIPv6");
818 break; 983 break;
819 case OSBuildNumber: 984 case OSBuildNumber:
@@ -841,11 +1006,7 @@ int main(void)
841 strcpy(key_name, "ProcessorArchitecture"); 1006 strcpy(key_name, "ProcessorArchitecture");
842 break; 1007 break;
843 default: 1008 default:
844 strcpy(key_value, "Unknown Key"); 1009 hv_msg->error = HV_S_CONT;
845 /*
846 * We use a null key name to terminate enumeration.
847 */
848 strcpy(key_name, "");
849 break; 1010 break;
850 } 1011 }
851 /* 1012 /*