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