xref: /freebsd/contrib/hyperv/tools/hv_kvp_daemon.c (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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