1 /*-
2 * Copyright (c) 2014 Microsoft Corp.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/poll.h>
30 #include <sys/utsname.h>
31 #include <sys/stat.h>
32 #include <sys/un.h>
33
34 #include <arpa/inet.h>
35 #include <ifaddrs.h>
36 #include <netdb.h>
37
38 #include <netinet/in.h>
39 #include <net/ethernet.h>
40 #include <net/if_dl.h>
41 #include <net/if_types.h>
42
43 #include <assert.h>
44
45 #include <ctype.h>
46 #include <dirent.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <poll.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <syslog.h>
54 #include <unistd.h>
55 #include <assert.h>
56
57 #include "hv_kvp.h"
58 #include "hv_utilreg.h"
59 typedef uint8_t __u8;
60 typedef uint16_t __u16;
61 typedef uint32_t __u32;
62 typedef uint64_t __u64;
63
64 #define POOL_FILE_MODE (S_IRUSR | S_IWUSR)
65 #define POOL_DIR_MODE (POOL_FILE_MODE | S_IXUSR)
66 #define POOL_DIR "/var/db/hyperv/pool"
67
68 /*
69 * ENUM Data
70 */
71
72 enum key_index {
73 FullyQualifiedDomainName = 0,
74 IntegrationServicesVersion, /*This key is serviced in the kernel*/
75 NetworkAddressIPv4,
76 NetworkAddressIPv6,
77 OSBuildNumber,
78 OSName,
79 OSMajorVersion,
80 OSMinorVersion,
81 OSVersion,
82 ProcessorArchitecture
83 };
84
85
86 enum {
87 IPADDR = 0,
88 NETMASK,
89 GATEWAY,
90 DNS
91 };
92
93
94 /* Global Variables */
95
96 /*
97 * The structure for operation handlers.
98 */
99 struct kvp_op_hdlr {
100 int kvp_op_key;
101 void (*kvp_op_init)(void);
102 int (*kvp_op_exec)(struct hv_kvp_msg *kvp_op_msg, void *data);
103 };
104
105 static struct kvp_op_hdlr kvp_op_hdlrs[HV_KVP_OP_COUNT];
106
107 /* OS information */
108
109 static const char *os_name = "";
110 static const char *os_major = "";
111 static const char *os_minor = "";
112 static const char *processor_arch;
113 static const char *os_build;
114 static const char *lic_version = "BSD Pre-Release version";
115 static struct utsname uts_buf;
116
117 /* Global flags */
118 static int is_daemon = 1;
119 static int is_debugging = 0;
120
121 #define KVP_LOG(priority, format, args...) do { \
122 if (is_debugging == 1) { \
123 if (is_daemon == 1) \
124 syslog(priority, format, ## args); \
125 else \
126 printf(format, ## args); \
127 } else { \
128 if (priority < LOG_DEBUG) { \
129 if (is_daemon == 1) \
130 syslog(priority, format, ## args); \
131 else \
132 printf(format, ## args); \
133 } \
134 } \
135 } while(0)
136
137 /*
138 * For KVP pool file
139 */
140
141 #define MAX_FILE_NAME 100
142 #define ENTRIES_PER_BLOCK 50
143
144 struct kvp_record {
145 char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE];
146 char value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE];
147 };
148
149 struct kvp_pool {
150 int pool_fd;
151 int num_blocks;
152 struct kvp_record *records;
153 int num_records;
154 char fname[MAX_FILE_NAME];
155 };
156
157 static struct kvp_pool kvp_pools[HV_KVP_POOL_COUNT];
158
159
160 static void
kvp_acquire_lock(int pool)161 kvp_acquire_lock(int pool)
162 {
163 struct flock fl = { 0, 0, 0, F_WRLCK, SEEK_SET, 0 };
164
165 fl.l_pid = getpid();
166
167 if (fcntl(kvp_pools[pool].pool_fd, F_SETLKW, &fl) == -1) {
168 KVP_LOG(LOG_ERR, "Failed to acquire the lock pool: %d", pool);
169 exit(EXIT_FAILURE);
170 }
171 }
172
173
174 static void
kvp_release_lock(int pool)175 kvp_release_lock(int pool)
176 {
177 struct flock fl = { 0, 0, 0, F_UNLCK, SEEK_SET, 0 };
178
179 fl.l_pid = getpid();
180
181 if (fcntl(kvp_pools[pool].pool_fd, F_SETLK, &fl) == -1) {
182 perror("fcntl");
183 KVP_LOG(LOG_ERR, "Failed to release the lock pool: %d\n", pool);
184 exit(EXIT_FAILURE);
185 }
186 }
187
188
189 /*
190 * Write in-memory copy of KVP to pool files
191 */
192 static void
kvp_update_file(int pool)193 kvp_update_file(int pool)
194 {
195 FILE *filep;
196 size_t bytes_written;
197
198 kvp_acquire_lock(pool);
199
200 filep = fopen(kvp_pools[pool].fname, "w");
201 if (!filep) {
202 kvp_release_lock(pool);
203 KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool);
204 exit(EXIT_FAILURE);
205 }
206
207 bytes_written = fwrite(kvp_pools[pool].records,
208 sizeof(struct kvp_record),
209 kvp_pools[pool].num_records, filep);
210
211 if (ferror(filep) || fclose(filep)) {
212 kvp_release_lock(pool);
213 KVP_LOG(LOG_ERR, "Failed to write file, pool: %d\n", pool);
214 exit(EXIT_FAILURE);
215 }
216
217 kvp_release_lock(pool);
218 }
219
220
221 /*
222 * Read KVPs from pool files and store in memory
223 */
224 static void
kvp_update_mem_state(int pool)225 kvp_update_mem_state(int pool)
226 {
227 FILE *filep;
228 size_t records_read = 0;
229 struct kvp_record *record = kvp_pools[pool].records;
230 struct kvp_record *readp;
231 int num_blocks = kvp_pools[pool].num_blocks;
232 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
233
234 kvp_acquire_lock(pool);
235
236 filep = fopen(kvp_pools[pool].fname, "r");
237 if (!filep) {
238 kvp_release_lock(pool);
239 KVP_LOG(LOG_ERR, "Failed to open file, pool: %d\n", pool);
240 exit(EXIT_FAILURE);
241 }
242 for ( ; ; )
243 {
244 readp = &record[records_read];
245 records_read += fread(readp, sizeof(struct kvp_record),
246 ENTRIES_PER_BLOCK * num_blocks,
247 filep);
248
249 if (ferror(filep)) {
250 KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n", pool);
251 exit(EXIT_FAILURE);
252 }
253
254 if (!feof(filep)) {
255 /*
256 * Have more data to read. Expand the memory.
257 */
258 num_blocks++;
259 record = realloc(record, alloc_unit * num_blocks);
260
261 if (record == NULL) {
262 KVP_LOG(LOG_ERR, "malloc failed\n");
263 exit(EXIT_FAILURE);
264 }
265 continue;
266 }
267 break;
268 }
269
270 kvp_pools[pool].num_blocks = num_blocks;
271 kvp_pools[pool].records = record;
272 kvp_pools[pool].num_records = records_read;
273
274 fclose(filep);
275 kvp_release_lock(pool);
276 }
277
278
279 static int
kvp_file_init(void)280 kvp_file_init(void)
281 {
282 int fd;
283 FILE *filep;
284 size_t records_read;
285 char *fname;
286 struct kvp_record *record;
287 struct kvp_record *readp;
288 int num_blocks;
289 int i;
290 int alloc_unit = sizeof(struct kvp_record) * ENTRIES_PER_BLOCK;
291
292 if (mkdir(POOL_DIR, POOL_DIR_MODE) < 0 &&
293 (errno != EEXIST && errno != EISDIR)) {
294 KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n");
295 exit(EXIT_FAILURE);
296 }
297 chmod(POOL_DIR, POOL_DIR_MODE); /* fix old mistake */
298
299 for (i = 0; i < HV_KVP_POOL_COUNT; i++)
300 {
301 fname = kvp_pools[i].fname;
302 records_read = 0;
303 num_blocks = 1;
304 snprintf(fname, MAX_FILE_NAME, "/var/db/hyperv/pool/.kvp_pool_%d", i);
305 fd = open(fname, O_RDWR | O_CREAT, POOL_FILE_MODE);
306
307 if (fd == -1) {
308 return (1);
309 }
310 fchmod(fd, POOL_FILE_MODE); /* fix old mistake */
311
312
313 filep = fopen(fname, "r");
314 if (!filep) {
315 close(fd);
316 return (1);
317 }
318
319 record = malloc(alloc_unit * num_blocks);
320 if (record == NULL) {
321 close(fd);
322 fclose(filep);
323 return (1);
324 }
325 for ( ; ; )
326 {
327 readp = &record[records_read];
328 records_read += fread(readp, sizeof(struct kvp_record),
329 ENTRIES_PER_BLOCK,
330 filep);
331
332 if (ferror(filep)) {
333 KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n",
334 i);
335 exit(EXIT_FAILURE);
336 }
337
338 if (!feof(filep)) {
339 /*
340 * More data to read.
341 */
342 num_blocks++;
343 record = realloc(record, alloc_unit *
344 num_blocks);
345 if (record == NULL) {
346 close(fd);
347 fclose(filep);
348 return (1);
349 }
350 continue;
351 }
352 break;
353 }
354 kvp_pools[i].pool_fd = fd;
355 kvp_pools[i].num_blocks = num_blocks;
356 kvp_pools[i].records = record;
357 kvp_pools[i].num_records = records_read;
358 fclose(filep);
359 }
360
361 return (0);
362 }
363
364
365 static int
kvp_key_delete(int pool,__u8 * key,int key_size)366 kvp_key_delete(int pool, __u8 *key, int key_size)
367 {
368 int i;
369 int j, k;
370 int num_records;
371 struct kvp_record *record;
372
373 KVP_LOG(LOG_DEBUG, "kvp_key_delete: pool = %d, "
374 "key = %s\n", pool, key);
375
376 /* Update in-memory state */
377 kvp_update_mem_state(pool);
378
379 num_records = kvp_pools[pool].num_records;
380 record = kvp_pools[pool].records;
381
382 for (i = 0; i < num_records; i++)
383 {
384 if (memcmp(key, record[i].key, key_size)) {
385 continue;
386 }
387
388 KVP_LOG(LOG_DEBUG, "Found delete key in pool %d.\n",
389 pool);
390 /*
391 * We found a match at the end; Just update the number of
392 * entries and we are done.
393 */
394 if (i == num_records) {
395 kvp_pools[pool].num_records--;
396 kvp_update_file(pool);
397 return (0);
398 }
399
400 /*
401 * We found a match in the middle; Move the remaining
402 * entries up.
403 */
404 j = i;
405 k = j + 1;
406 for ( ; k < num_records; k++)
407 {
408 strcpy(record[j].key, record[k].key);
409 strcpy(record[j].value, record[k].value);
410 j++;
411 }
412 kvp_pools[pool].num_records--;
413 kvp_update_file(pool);
414 return (0);
415 }
416 KVP_LOG(LOG_DEBUG, "Not found delete key in pool %d.\n",
417 pool);
418 return (1);
419 }
420
421
422 static int
kvp_key_add_or_modify(int pool,__u8 * key,__u32 key_size,__u8 * value,__u32 value_size)423 kvp_key_add_or_modify(int pool, __u8 *key, __u32 key_size, __u8 *value,
424 __u32 value_size)
425 {
426 int i;
427 int num_records;
428 struct kvp_record *record;
429 int num_blocks;
430
431 KVP_LOG(LOG_DEBUG, "kvp_key_add_or_modify: pool = %d, "
432 "key = %s, value = %s\n,", pool, key, value);
433
434 if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
435 (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
436 KVP_LOG(LOG_ERR, "kvp_key_add_or_modify: returning 1\n");
437 return (1);
438 }
439
440 /* Update the in-memory state. */
441 kvp_update_mem_state(pool);
442
443 num_records = kvp_pools[pool].num_records;
444 record = kvp_pools[pool].records;
445 num_blocks = kvp_pools[pool].num_blocks;
446
447 for (i = 0; i < num_records; i++)
448 {
449 if (memcmp(key, record[i].key, key_size)) {
450 continue;
451 }
452
453 /*
454 * Key exists. Just update the value and we are done.
455 */
456 memcpy(record[i].value, value, value_size);
457 kvp_update_file(pool);
458 return (0);
459 }
460
461 /*
462 * Key doesn't exist; Add a new KVP.
463 */
464 if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
465 /* Increase the size of the recodrd array. */
466 record = realloc(record, sizeof(struct kvp_record) *
467 ENTRIES_PER_BLOCK * (num_blocks + 1));
468
469 if (record == NULL) {
470 return (1);
471 }
472 kvp_pools[pool].num_blocks++;
473 }
474 memcpy(record[i].value, value, value_size);
475 memcpy(record[i].key, key, key_size);
476 kvp_pools[pool].records = record;
477 kvp_pools[pool].num_records++;
478 kvp_update_file(pool);
479 return (0);
480 }
481
482
483 static int
kvp_get_value(int pool,__u8 * key,int key_size,__u8 * value,int value_size)484 kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
485 int value_size)
486 {
487 int i;
488 int num_records;
489 struct kvp_record *record;
490
491 KVP_LOG(LOG_DEBUG, "kvp_get_value: pool = %d, key = %s\n,",
492 pool, key);
493
494 if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
495 (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
496 return (1);
497 }
498
499 /* Update the in-memory state first. */
500 kvp_update_mem_state(pool);
501
502 num_records = kvp_pools[pool].num_records;
503 record = kvp_pools[pool].records;
504
505 for (i = 0; i < num_records; i++)
506 {
507 if (memcmp(key, record[i].key, key_size)) {
508 continue;
509 }
510
511 /* Found the key */
512 memcpy(value, record[i].value, value_size);
513 return (0);
514 }
515
516 return (1);
517 }
518
519
520 static int
kvp_pool_enumerate(int pool,int idx,__u8 * key,int key_size,__u8 * value,int value_size)521 kvp_pool_enumerate(int pool, int idx, __u8 *key, int key_size,
522 __u8 *value, int value_size)
523 {
524 struct kvp_record *record;
525
526 KVP_LOG(LOG_DEBUG, "kvp_pool_enumerate: pool = %d, index = %d\n,",
527 pool, idx);
528
529 /* First update our in-memory state first. */
530 kvp_update_mem_state(pool);
531 record = kvp_pools[pool].records;
532
533 /* Index starts with 0 */
534 if (idx >= kvp_pools[pool].num_records) {
535 return (1);
536 }
537
538 memcpy(key, record[idx].key, key_size);
539 memcpy(value, record[idx].value, value_size);
540 return (0);
541 }
542
543
544 static void
kvp_get_os_info(void)545 kvp_get_os_info(void)
546 {
547 char *p;
548
549 uname(&uts_buf);
550 os_build = uts_buf.release;
551 os_name = uts_buf.sysname;
552 processor_arch = uts_buf.machine;
553
554 /*
555 * Win7 host expects the build string to be of the form: x.y.z
556 * Strip additional information we may have.
557 */
558 p = strchr(os_build, '-');
559 if (p) {
560 *p = '\0';
561 }
562
563 /*
564 * We don't have any other information about the FreeBSD os.
565 */
566 return;
567 }
568
569 /*
570 * Given the interface name, return the MAC address.
571 */
572 static char *
kvp_if_name_to_mac(char * if_name)573 kvp_if_name_to_mac(char *if_name)
574 {
575 char *mac_addr = NULL;
576 struct ifaddrs *ifaddrs_ptr;
577 struct ifaddrs *head_ifaddrs_ptr;
578 struct sockaddr_dl *sdl;
579 int status;
580
581 status = getifaddrs(&ifaddrs_ptr);
582
583 if (status >= 0) {
584 head_ifaddrs_ptr = ifaddrs_ptr;
585 do {
586 sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
587 if ((sdl->sdl_type == IFT_ETHER) &&
588 (strcmp(ifaddrs_ptr->ifa_name, if_name) == 0)) {
589 mac_addr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
590 break;
591 }
592 } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
593 freeifaddrs(head_ifaddrs_ptr);
594 }
595
596 return (mac_addr);
597 }
598
599
600 /*
601 * Given the MAC address, return the interface name.
602 */
603 static char *
kvp_mac_to_if_name(char * mac)604 kvp_mac_to_if_name(char *mac)
605 {
606 char *if_name = NULL;
607 struct ifaddrs *ifaddrs_ptr;
608 struct ifaddrs *head_ifaddrs_ptr;
609 struct sockaddr_dl *sdl;
610 int status;
611 char *buf_ptr, *p;
612
613 status = getifaddrs(&ifaddrs_ptr);
614
615 if (status >= 0) {
616 head_ifaddrs_ptr = ifaddrs_ptr;
617 do {
618 sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
619 if (sdl->sdl_type == IFT_ETHER) {
620 buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
621 if (buf_ptr != NULL) {
622 for (p = buf_ptr; *p != '\0'; p++)
623 *p = toupper(*p);
624
625 if (strncmp(buf_ptr, mac, strlen(mac)) == 0) {
626 /* Caller will free the memory */
627 if_name = strdup(ifaddrs_ptr->ifa_name);
628 free(buf_ptr);
629 break;
630 } else
631 free(buf_ptr);
632 }
633 }
634 } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
635 freeifaddrs(head_ifaddrs_ptr);
636 }
637 return (if_name);
638 }
639
640
641 static void
kvp_process_ipconfig_file(char * cmd,char * config_buf,size_t len,size_t element_size,int offset)642 kvp_process_ipconfig_file(char *cmd,
643 char *config_buf, size_t len,
644 size_t element_size, int offset)
645 {
646 char buf[256];
647 char *p;
648 char *x;
649 FILE *file;
650
651 /*
652 * First execute the command.
653 */
654 file = popen(cmd, "r");
655 if (file == NULL) {
656 return;
657 }
658
659 if (offset == 0) {
660 memset(config_buf, 0, len);
661 }
662 while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
663 if ((len - strlen(config_buf)) < (element_size + 1)) {
664 break;
665 }
666
667 x = strchr(p, '\n');
668 *x = '\0';
669 strlcat(config_buf, p, len);
670 strlcat(config_buf, ";", len);
671 }
672 pclose(file);
673 }
674
675
676 static void
kvp_get_ipconfig_info(char * if_name,struct hv_kvp_ipaddr_value * buffer)677 kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer)
678 {
679 char cmd[512];
680 char dhcp_info[128];
681 char *p;
682 FILE *file;
683
684 /*
685 * Retrieve the IPV4 address of default gateway.
686 */
687 snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name);
688
689 /*
690 * Execute the command to gather gateway IPV4 info.
691 */
692 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
693 (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
694 /*
695 * Retrieve the IPV6 address of default gateway.
696 */
697 snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }'", if_name);
698
699 /*
700 * Execute the command to gather gateway IPV6 info.
701 */
702 kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
703 (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
704 /*
705 * we just invoke an external script to get the DNS info.
706 *
707 * Following is the expected format of the information from the script:
708 *
709 * ipaddr1 (nameserver1)
710 * ipaddr2 (nameserver2)
711 * .
712 * .
713 */
714 /* Scripts are stored in /usr/libexec/hyperv/ directory */
715 snprintf(cmd, sizeof(cmd), "%s", "sh /usr/libexec/hyperv/hv_get_dns_info");
716
717 /*
718 * Execute the command to get DNS info.
719 */
720 kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr,
721 (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0);
722
723 /*
724 * Invoke an external script to get the DHCP state info.
725 * The parameter to the script is the interface name.
726 * Here is the expected output:
727 *
728 * Enabled: DHCP enabled.
729 */
730
731
732 snprintf(cmd, sizeof(cmd), "%s %s",
733 "sh /usr/libexec/hyperv/hv_get_dhcp_info", if_name);
734
735 file = popen(cmd, "r");
736 if (file == NULL) {
737 return;
738 }
739
740 p = fgets(dhcp_info, sizeof(dhcp_info), file);
741 if (p == NULL) {
742 pclose(file);
743 return;
744 }
745
746 if (!strncmp(p, "Enabled", 7)) {
747 buffer->dhcp_enabled = 1;
748 } else{
749 buffer->dhcp_enabled = 0;
750 }
751
752 pclose(file);
753 }
754
755
756 static unsigned int
hweight32(unsigned int * w)757 hweight32(unsigned int *w)
758 {
759 unsigned int res = *w - ((*w >> 1) & 0x55555555);
760
761 res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
762 res = (res + (res >> 4)) & 0x0F0F0F0F;
763 res = res + (res >> 8);
764 return ((res + (res >> 16)) & 0x000000FF);
765 }
766
767
768 static int
kvp_process_ip_address(void * addrp,int family,char * buffer,int length,int * offset)769 kvp_process_ip_address(void *addrp,
770 int family, char *buffer,
771 int length, int *offset)
772 {
773 struct sockaddr_in *addr;
774 struct sockaddr_in6 *addr6;
775 int addr_length;
776 char tmp[50];
777 const char *str;
778
779 if (family == AF_INET) {
780 addr = (struct sockaddr_in *)addrp;
781 str = inet_ntop(family, &addr->sin_addr, tmp, 50);
782 addr_length = INET_ADDRSTRLEN;
783 } else {
784 addr6 = (struct sockaddr_in6 *)addrp;
785 str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
786 addr_length = INET6_ADDRSTRLEN;
787 }
788
789 if ((length - *offset) < addr_length + 1) {
790 return (EINVAL);
791 }
792 if (str == NULL) {
793 strlcpy(buffer, "inet_ntop failed\n", length);
794 return (errno);
795 }
796 if (*offset == 0) {
797 strlcpy(buffer, tmp, length);
798 } else{
799 strlcat(buffer, tmp, length);
800 }
801 strlcat(buffer, ";", length);
802
803 *offset += strlen(str) + 1;
804 return (0);
805 }
806
807
808 static int
kvp_get_ip_info(int family,char * if_name,int op,void * out_buffer,size_t length)809 kvp_get_ip_info(int family, char *if_name, int op,
810 void *out_buffer, size_t length)
811 {
812 struct ifaddrs *ifap;
813 struct ifaddrs *curp;
814 int offset = 0;
815 int sn_offset = 0;
816 int error = 0;
817 char *buffer;
818 size_t buffer_length;
819 struct hv_kvp_ipaddr_value *ip_buffer = NULL;
820 char cidr_mask[5];
821 int weight;
822 int i;
823 unsigned int *w = NULL;
824 char *sn_str;
825 size_t sn_str_length;
826 struct sockaddr_in6 *addr6;
827
828 if (op == HV_KVP_OP_ENUMERATE) {
829 buffer = out_buffer;
830 buffer_length = length;
831 } else {
832 ip_buffer = out_buffer;
833 buffer = (char *)ip_buffer->ip_addr;
834 buffer_length = sizeof(ip_buffer->ip_addr);
835 ip_buffer->addr_family = 0;
836 }
837
838 if (getifaddrs(&ifap)) {
839 strlcpy(buffer, "getifaddrs failed\n", buffer_length);
840 return (errno);
841 }
842
843 curp = ifap;
844 while (curp != NULL) {
845 if (curp->ifa_addr == NULL) {
846 curp = curp->ifa_next;
847 continue;
848 }
849
850 if ((if_name != NULL) &&
851 (strncmp(curp->ifa_name, if_name, strlen(if_name)))) {
852 /*
853 * We want info about a specific interface;
854 * just continue.
855 */
856 curp = curp->ifa_next;
857 continue;
858 }
859
860 /*
861 * We support two address families: AF_INET and AF_INET6.
862 * If family value is 0, we gather both supported
863 * address families; if not we gather info on
864 * the specified address family.
865 */
866 if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
867 curp = curp->ifa_next;
868 continue;
869 }
870 if ((curp->ifa_addr->sa_family != AF_INET) &&
871 (curp->ifa_addr->sa_family != AF_INET6)) {
872 curp = curp->ifa_next;
873 continue;
874 }
875
876 if (op == HV_KVP_OP_GET_IP_INFO) {
877 /*
878 * Get the info other than the IP address.
879 */
880 if (curp->ifa_addr->sa_family == AF_INET) {
881 ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
882
883 /*
884 * Get subnet info.
885 */
886 error = kvp_process_ip_address(
887 curp->ifa_netmask,
888 AF_INET,
889 (char *)
890 ip_buffer->sub_net,
891 length,
892 &sn_offset);
893 if (error) {
894 goto kvp_get_ip_info_ipaddr;
895 }
896 } else {
897 ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
898
899 /*
900 * Get subnet info in CIDR format.
901 */
902 weight = 0;
903 sn_str = (char *)ip_buffer->sub_net;
904 sn_str_length = sizeof(ip_buffer->sub_net);
905 addr6 = (struct sockaddr_in6 *)(uintptr_t)
906 curp->ifa_netmask;
907 w = (unsigned int *)(uintptr_t)addr6->sin6_addr.s6_addr;
908
909 for (i = 0; i < 4; i++)
910 {
911 weight += hweight32(&w[i]);
912 }
913
914 snprintf(cidr_mask, sizeof(cidr_mask), "/%d", weight);
915 if ((length - sn_offset) <
916 (strlen(cidr_mask) + 1)) {
917 goto kvp_get_ip_info_ipaddr;
918 }
919
920 if (sn_offset == 0) {
921 strlcpy(sn_str, cidr_mask, sn_str_length);
922 } else{
923 strlcat(sn_str, cidr_mask, sn_str_length);
924 }
925 strlcat((char *)ip_buffer->sub_net, ";", sn_str_length);
926 sn_offset += strlen(sn_str) + 1;
927 }
928
929 /*
930 * Collect other ip configuration info.
931 */
932 kvp_get_ipconfig_info(if_name, ip_buffer);
933 }
934
935 kvp_get_ip_info_ipaddr:
936 error = kvp_process_ip_address(curp->ifa_addr,
937 curp->ifa_addr->sa_family,
938 buffer,
939 length, &offset);
940 if (error) {
941 goto kvp_get_ip_info_done;
942 }
943
944 curp = curp->ifa_next;
945 }
946
947 kvp_get_ip_info_done:
948 freeifaddrs(ifap);
949 return (error);
950 }
951
952
953 static int
kvp_write_file(FILE * f,const char * s1,const char * s2,const char * s3)954 kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3)
955 {
956 int ret;
957
958 ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3);
959
960 if (ret < 0) {
961 return (EIO);
962 }
963
964 return (0);
965 }
966
967
968 static int
kvp_set_ip_info(char * if_name,struct hv_kvp_ipaddr_value * new_val)969 kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
970 {
971 int error = 0;
972 char if_file[128];
973 FILE *file;
974 char cmd[512];
975 char *mac_addr;
976
977 /*
978 * FreeBSD - Configuration File
979 */
980 snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv",
981 "hv_set_ip_data");
982 file = fopen(if_file, "w");
983
984 if (file == NULL) {
985 KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n");
986 return (errno);
987 }
988
989 /*
990 * Write out the MAC address.
991 */
992
993 mac_addr = kvp_if_name_to_mac(if_name);
994 if (mac_addr == NULL) {
995 error = EINVAL;
996 goto kvp_set_ip_info_error;
997 }
998 /* MAC Address */
999 error = kvp_write_file(file, "HWADDR", "", mac_addr);
1000 if (error) {
1001 goto kvp_set_ip_info_error;
1002 }
1003
1004 /* Interface Name */
1005 error = kvp_write_file(file, "IF_NAME", "", if_name);
1006 if (error) {
1007 goto kvp_set_ip_info_error;
1008 }
1009
1010 /* IP Address */
1011 error = kvp_write_file(file, "IP_ADDR", "",
1012 (char *)new_val->ip_addr);
1013 if (error) {
1014 goto kvp_set_ip_info_error;
1015 }
1016
1017 /* Subnet Mask */
1018 error = kvp_write_file(file, "SUBNET", "",
1019 (char *)new_val->sub_net);
1020 if (error) {
1021 goto kvp_set_ip_info_error;
1022 }
1023
1024
1025 /* Gateway */
1026 error = kvp_write_file(file, "GATEWAY", "",
1027 (char *)new_val->gate_way);
1028 if (error) {
1029 goto kvp_set_ip_info_error;
1030 }
1031
1032 /* DNS */
1033 error = kvp_write_file(file, "DNS", "", (char *)new_val->dns_addr);
1034 if (error) {
1035 goto kvp_set_ip_info_error;
1036 }
1037
1038 /* DHCP */
1039 if (new_val->dhcp_enabled) {
1040 error = kvp_write_file(file, "DHCP", "", "1");
1041 } else{
1042 error = kvp_write_file(file, "DHCP", "", "0");
1043 }
1044
1045 if (error) {
1046 goto kvp_set_ip_info_error;
1047 }
1048
1049 free(mac_addr);
1050 fclose(file);
1051
1052 /*
1053 * Invoke the external script with the populated
1054 * configuration file.
1055 */
1056
1057 snprintf(cmd, sizeof(cmd), "%s %s",
1058 "sh /usr/libexec/hyperv/hv_set_ifconfig", if_file);
1059 system(cmd);
1060 return (0);
1061
1062 kvp_set_ip_info_error:
1063 KVP_LOG(LOG_ERR, "Failed to write config file\n");
1064 free(mac_addr);
1065 fclose(file);
1066 return (error);
1067 }
1068
1069
1070 static int
kvp_get_domain_name(char * buffer,int length)1071 kvp_get_domain_name(char *buffer, int length)
1072 {
1073 struct addrinfo hints, *info;
1074 int error = 0;
1075
1076 gethostname(buffer, length);
1077 memset(&hints, 0, sizeof(hints));
1078 hints.ai_family = AF_INET; /* Get only ipv4 addrinfo. */
1079 hints.ai_socktype = SOCK_STREAM;
1080 hints.ai_flags = AI_CANONNAME;
1081
1082 error = getaddrinfo(buffer, NULL, &hints, &info);
1083 if (error != 0) {
1084 strlcpy(buffer, "getaddrinfo failed\n", length);
1085 return (error);
1086 }
1087 strlcpy(buffer, info->ai_canonname, length);
1088 freeaddrinfo(info);
1089 return (error);
1090 }
1091
1092
1093 static int
kvp_op_getipinfo(struct hv_kvp_msg * op_msg,void * data __unused)1094 kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1095 {
1096 struct hv_kvp_ipaddr_value *ip_val;
1097 char *if_name;
1098 int error = 0;
1099
1100 assert(op_msg != NULL);
1101 KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n");
1102
1103 ip_val = &op_msg->body.kvp_ip_val;
1104 op_msg->hdr.error = HV_S_OK;
1105
1106 if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id);
1107
1108 if (if_name == NULL) {
1109 /* No interface found with the mac address. */
1110 op_msg->hdr.error = HV_E_FAIL;
1111 goto kvp_op_getipinfo_done;
1112 }
1113
1114 error = kvp_get_ip_info(0, if_name,
1115 HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2));
1116 if (error)
1117 op_msg->hdr.error = HV_E_FAIL;
1118 free(if_name);
1119
1120 kvp_op_getipinfo_done:
1121 return (error);
1122 }
1123
1124
1125 static int
kvp_op_setipinfo(struct hv_kvp_msg * op_msg,void * data __unused)1126 kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1127 {
1128 struct hv_kvp_ipaddr_value *ip_val;
1129 char *if_name;
1130 int error = 0;
1131
1132 assert(op_msg != NULL);
1133 KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n");
1134
1135 ip_val = &op_msg->body.kvp_ip_val;
1136 op_msg->hdr.error = HV_S_OK;
1137
1138 if_name = (char *)ip_val->adapter_id;
1139
1140 if (if_name == NULL) {
1141 /* No adapter provided. */
1142 op_msg->hdr.error = HV_GUID_NOTFOUND;
1143 goto kvp_op_setipinfo_done;
1144 }
1145
1146 error = kvp_set_ip_info(if_name, ip_val);
1147 if (error)
1148 op_msg->hdr.error = HV_E_FAIL;
1149 kvp_op_setipinfo_done:
1150 return (error);
1151 }
1152
1153
1154 static int
kvp_op_setgetdel(struct hv_kvp_msg * op_msg,void * data)1155 kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data)
1156 {
1157 struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data;
1158 int error = 0;
1159 int op_pool;
1160
1161 assert(op_msg != NULL);
1162 assert(op_hdlr != NULL);
1163
1164 op_pool = op_msg->hdr.kvp_hdr.pool;
1165 op_msg->hdr.error = HV_S_OK;
1166
1167 switch(op_hdlr->kvp_op_key) {
1168 case HV_KVP_OP_SET:
1169 if (op_pool == HV_KVP_POOL_AUTO) {
1170 /* Auto Pool is not writeable from host side. */
1171 error = 1;
1172 KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n",
1173 op_pool);
1174 } else {
1175 error = kvp_key_add_or_modify(op_pool,
1176 op_msg->body.kvp_set.data.key,
1177 op_msg->body.kvp_set.data.key_size,
1178 op_msg->body.kvp_set.data.msg_value.value,
1179 op_msg->body.kvp_set.data.value_size);
1180 }
1181 break;
1182
1183 case HV_KVP_OP_GET:
1184 error = kvp_get_value(op_pool,
1185 op_msg->body.kvp_get.data.key,
1186 op_msg->body.kvp_get.data.key_size,
1187 op_msg->body.kvp_get.data.msg_value.value,
1188 op_msg->body.kvp_get.data.value_size);
1189 break;
1190
1191 case HV_KVP_OP_DELETE:
1192 if (op_pool == HV_KVP_POOL_AUTO) {
1193 /* Auto Pool is not writeable from host side. */
1194 error = 1;
1195 KVP_LOG(LOG_ERR, "Ilegal to change pool %d from host\n",
1196 op_pool);
1197 } else {
1198 error = kvp_key_delete(op_pool,
1199 op_msg->body.kvp_delete.key,
1200 op_msg->body.kvp_delete.key_size);
1201 }
1202 break;
1203
1204 default:
1205 break;
1206 }
1207
1208 if (error != 0)
1209 op_msg->hdr.error = HV_S_CONT;
1210 return(error);
1211 }
1212
1213
1214 static int
kvp_op_enumerate(struct hv_kvp_msg * op_msg,void * data __unused)1215 kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused)
1216 {
1217 char *key_name, *key_value;
1218 int error = 0;
1219 int op_pool;
1220 int op;
1221
1222 assert(op_msg != NULL);
1223
1224 op = op_msg->hdr.kvp_hdr.operation;
1225 op_pool = op_msg->hdr.kvp_hdr.pool;
1226 op_msg->hdr.error = HV_S_OK;
1227
1228 /*
1229 * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate
1230 * pool and return the KVP according to the index requested.
1231 */
1232 if (op_pool != HV_KVP_POOL_AUTO) {
1233 if (kvp_pool_enumerate(op_pool,
1234 op_msg->body.kvp_enum_data.index,
1235 op_msg->body.kvp_enum_data.data.key,
1236 HV_KVP_EXCHANGE_MAX_KEY_SIZE,
1237 op_msg->body.kvp_enum_data.data.msg_value.value,
1238 HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
1239 op_msg->hdr.error = HV_S_CONT;
1240 error = -1;
1241 }
1242 goto kvp_op_enumerate_done;
1243 }
1244
1245 key_name = (char *)op_msg->body.kvp_enum_data.data.key;
1246 key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value;
1247
1248 switch (op_msg->body.kvp_enum_data.index)
1249 {
1250 case FullyQualifiedDomainName:
1251 kvp_get_domain_name(key_value,
1252 HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1253 strcpy(key_name, "FullyQualifiedDomainName");
1254 break;
1255
1256 case IntegrationServicesVersion:
1257 strcpy(key_name, "IntegrationServicesVersion");
1258 strlcpy(key_value, lic_version, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1259 break;
1260
1261 case NetworkAddressIPv4:
1262 kvp_get_ip_info(AF_INET, NULL, HV_KVP_OP_ENUMERATE,
1263 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1264 strcpy(key_name, "NetworkAddressIPv4");
1265 break;
1266
1267 case NetworkAddressIPv6:
1268 kvp_get_ip_info(AF_INET6, NULL, HV_KVP_OP_ENUMERATE,
1269 key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1270 strcpy(key_name, "NetworkAddressIPv6");
1271 break;
1272
1273 case OSBuildNumber:
1274 strlcpy(key_value, os_build, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1275 strcpy(key_name, "OSBuildNumber");
1276 break;
1277
1278 case OSName:
1279 strlcpy(key_value, os_name, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1280 strcpy(key_name, "OSName");
1281 break;
1282
1283 case OSMajorVersion:
1284 strlcpy(key_value, os_major, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1285 strcpy(key_name, "OSMajorVersion");
1286 break;
1287
1288 case OSMinorVersion:
1289 strlcpy(key_value, os_minor, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1290 strcpy(key_name, "OSMinorVersion");
1291 break;
1292
1293 case OSVersion:
1294 strlcpy(key_value, os_build, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1295 strcpy(key_name, "OSVersion");
1296 break;
1297
1298 case ProcessorArchitecture:
1299 strlcpy(key_value, processor_arch, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1300 strcpy(key_name, "ProcessorArchitecture");
1301 break;
1302
1303 default:
1304 #ifdef DEBUG
1305 KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n",
1306 op_msg->body.kvp_enum_data.index);
1307 #endif
1308 op_msg->hdr.error = HV_S_CONT;
1309 error = -1;
1310 break;
1311 }
1312
1313 kvp_op_enumerate_done:
1314 if (error != 0)
1315 op_msg->hdr.error = HV_S_CONT;
1316 return(error);
1317 }
1318
1319
1320 /*
1321 * Load handler, and call init routine if provided.
1322 */
1323 static int
kvp_op_load(int key,void (* init)(void),int (* exec)(struct hv_kvp_msg *,void *))1324 kvp_op_load(int key, void (*init)(void),
1325 int (*exec)(struct hv_kvp_msg *, void *))
1326 {
1327 int error = 0;
1328
1329 if (key < 0 || key >= HV_KVP_OP_COUNT) {
1330 KVP_LOG(LOG_ERR, "Operation key out of supported range\n");
1331 error = -1;
1332 goto kvp_op_load_done;
1333 }
1334
1335 kvp_op_hdlrs[key].kvp_op_key = key;
1336 kvp_op_hdlrs[key].kvp_op_init = init;
1337 kvp_op_hdlrs[key].kvp_op_exec = exec;
1338
1339 if (kvp_op_hdlrs[key].kvp_op_init != NULL)
1340 kvp_op_hdlrs[key].kvp_op_init();
1341
1342 kvp_op_load_done:
1343 return(error);
1344 }
1345
1346
1347 /*
1348 * Initialize the operation hanlders.
1349 */
1350 static int
kvp_ops_init(void)1351 kvp_ops_init(void)
1352 {
1353 int i;
1354
1355 /* Set the initial values. */
1356 for (i = 0; i < HV_KVP_OP_COUNT; i++) {
1357 kvp_op_hdlrs[i].kvp_op_key = -1;
1358 kvp_op_hdlrs[i].kvp_op_init = NULL;
1359 kvp_op_hdlrs[i].kvp_op_exec = NULL;
1360 }
1361
1362 return(kvp_op_load(HV_KVP_OP_GET, NULL, kvp_op_setgetdel) |
1363 kvp_op_load(HV_KVP_OP_SET, NULL, kvp_op_setgetdel) |
1364 kvp_op_load(HV_KVP_OP_DELETE, NULL, kvp_op_setgetdel) |
1365 kvp_op_load(HV_KVP_OP_ENUMERATE, kvp_get_os_info,
1366 kvp_op_enumerate) |
1367 kvp_op_load(HV_KVP_OP_GET_IP_INFO, NULL, kvp_op_getipinfo) |
1368 kvp_op_load(HV_KVP_OP_SET_IP_INFO, NULL, kvp_op_setipinfo));
1369 }
1370
1371
1372 int
main(int argc,char * argv[])1373 main(int argc, char *argv[])
1374 {
1375 struct hv_kvp_msg *hv_kvp_dev_buf;
1376 struct hv_kvp_msg *hv_msg;
1377 struct pollfd hv_kvp_poll_fd[1];
1378 int op, pool;
1379 int hv_kvp_dev_fd, error, len, r;
1380 int ch;
1381
1382 while ((ch = getopt(argc, argv, "dn")) != -1) {
1383 switch (ch) {
1384 case 'n':
1385 /* Run as regular process for debugging purpose. */
1386 is_daemon = 0;
1387 break;
1388 case 'd':
1389 /* Generate debugging output */
1390 is_debugging = 1;
1391 break;
1392 default:
1393 break;
1394 }
1395 }
1396
1397 openlog("HV_KVP", 0, LOG_USER);
1398
1399 /* Become daemon first. */
1400 if (is_daemon == 1)
1401 daemon(1, 0);
1402 else
1403 KVP_LOG(LOG_DEBUG, "Run as regular process.\n");
1404
1405 KVP_LOG(LOG_INFO, "HV_KVP starting; pid is: %d\n", getpid());
1406
1407 /* Communication buffer hv_kvp_dev_buf */
1408 hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf));
1409 /* Buffer for daemon internal use */
1410 hv_msg = malloc(sizeof(*hv_msg));
1411
1412 /* Memory allocation failed */
1413 if (hv_kvp_dev_buf == NULL || hv_msg == NULL) {
1414 KVP_LOG(LOG_ERR, "Failed to allocate memory for hv buffer\n");
1415 exit(EXIT_FAILURE);
1416 }
1417
1418 /* Initialize op handlers */
1419 if (kvp_ops_init() != 0) {
1420 KVP_LOG(LOG_ERR, "Failed to initizlize operation handlers\n");
1421 exit(EXIT_FAILURE);
1422 }
1423
1424 if (kvp_file_init()) {
1425 KVP_LOG(LOG_ERR, "Failed to initialize the pools\n");
1426 exit(EXIT_FAILURE);
1427 }
1428
1429 /* Open the Character Device */
1430 hv_kvp_dev_fd = open("/dev/hv_kvp_dev", O_RDWR);
1431
1432 if (hv_kvp_dev_fd < 0) {
1433 KVP_LOG(LOG_ERR, "open /dev/hv_kvp_dev failed; error: %d %s\n",
1434 errno, strerror(errno));
1435 exit(EXIT_FAILURE);
1436 }
1437
1438 /* Initialize the struct for polling the char device */
1439 hv_kvp_poll_fd[0].fd = hv_kvp_dev_fd;
1440 hv_kvp_poll_fd[0].events = (POLLIN | POLLRDNORM);
1441
1442 /* Register the daemon to the KVP driver */
1443 memset(hv_kvp_dev_buf, 0, sizeof(*hv_kvp_dev_buf));
1444 hv_kvp_dev_buf->hdr.kvp_hdr.operation = HV_KVP_OP_REGISTER;
1445 len = write(hv_kvp_dev_fd, hv_kvp_dev_buf, sizeof(*hv_kvp_dev_buf));
1446
1447
1448 for (;;) {
1449 r = poll (hv_kvp_poll_fd, 1, INFTIM);
1450
1451 KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n",
1452 r, hv_kvp_poll_fd[0].revents);
1453
1454 if (r == 0 || (r < 0 && errno == EAGAIN) ||
1455 (r < 0 && errno == EINTR)) {
1456 /* Nothing to read */
1457 continue;
1458 }
1459
1460 if (r < 0) {
1461 /*
1462 * For pread return failure other than EAGAIN,
1463 * we want to exit.
1464 */
1465 KVP_LOG(LOG_ERR, "Poll failed.\n");
1466 perror("poll");
1467 exit(EIO);
1468 }
1469
1470 /* Read from character device */
1471 len = pread(hv_kvp_dev_fd, hv_kvp_dev_buf,
1472 sizeof(*hv_kvp_dev_buf), 0);
1473
1474 if (len < 0) {
1475 KVP_LOG(LOG_ERR, "Read failed.\n");
1476 perror("pread");
1477 exit(EIO);
1478 }
1479
1480 if (len != sizeof(struct hv_kvp_msg)) {
1481 KVP_LOG(LOG_ERR, "read len is: %d\n", len);
1482 continue;
1483 }
1484
1485 /* Copy hv_kvp_dev_buf to hv_msg */
1486 memcpy(hv_msg, hv_kvp_dev_buf, sizeof(*hv_msg));
1487
1488 /*
1489 * We will use the KVP header information to pass back
1490 * the error from this daemon. So, first save the op
1491 * and pool info to local variables.
1492 */
1493
1494 op = hv_msg->hdr.kvp_hdr.operation;
1495 pool = hv_msg->hdr.kvp_hdr.pool;
1496
1497 if (op < 0 || op >= HV_KVP_OP_COUNT ||
1498 kvp_op_hdlrs[op].kvp_op_exec == NULL) {
1499 KVP_LOG(LOG_WARNING,
1500 "Unsupported operation OP = %d\n", op);
1501 hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED;
1502 } else {
1503 /*
1504 * Call the operateion handler's execution routine.
1505 */
1506 error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg,
1507 (void *)&kvp_op_hdlrs[op]);
1508 if (error != 0) {
1509 assert(hv_msg->hdr.error != HV_S_OK);
1510 if (hv_msg->hdr.error != HV_S_CONT)
1511 KVP_LOG(LOG_WARNING,
1512 "Operation failed OP = %d, error = 0x%x\n",
1513 op, error);
1514 }
1515 }
1516
1517 /*
1518 * Send the value back to the kernel. The response is
1519 * already in the receive buffer.
1520 */
1521 hv_kvp_done:
1522 len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0);
1523
1524 if (len != sizeof(struct hv_kvp_msg)) {
1525 KVP_LOG(LOG_ERR, "write len is: %d\n", len);
1526 goto hv_kvp_done;
1527 }
1528 }
1529 }
1530