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