]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/hyperv/tools/hv_kvp_daemon.c
Being able to access a path do not necessarily mean we have access
[FreeBSD/FreeBSD.git] / contrib / hyperv / tools / hv_kvp_daemon.c
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 != 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                         return (1);
309                 }
310
311                 record = malloc(alloc_unit * num_blocks);
312                 if (record == NULL) {
313                         fclose(filep);
314                         return (1);
315                 }
316                 for ( ; ; )
317                 {
318                         readp = &record[records_read];
319                         records_read += fread(readp, sizeof(struct kvp_record),
320                                 ENTRIES_PER_BLOCK,
321                                 filep);
322
323                         if (ferror(filep)) {
324                                 KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n",
325                                     i);
326                                 exit(EXIT_FAILURE);
327                         }
328
329                         if (!feof(filep)) {
330                                 /*
331                                  * More data to read.
332                                  */
333                                 num_blocks++;
334                                 record = realloc(record, alloc_unit *
335                                         num_blocks);
336                                 if (record == NULL) {
337                                         fclose(filep);
338                                         return (1);
339                                 }
340                                 continue;
341                         }
342                         break;
343                 }
344                 kvp_pools[i].pool_fd = fd;
345                 kvp_pools[i].num_blocks = num_blocks;
346                 kvp_pools[i].records = record;
347                 kvp_pools[i].num_records = records_read;
348                 fclose(filep);
349         }
350
351         return (0);
352 }
353
354
355 static int
356 kvp_key_delete(int pool, __u8 *key, int key_size)
357 {
358         int i;
359         int j, k;
360         int num_records;
361         struct kvp_record *record;
362
363         KVP_LOG(LOG_DEBUG, "kvp_key_delete: pool =  %d, "
364             "key = %s\n", pool, key);
365
366         /* Update in-memory state */
367         kvp_update_mem_state(pool);
368
369         num_records = kvp_pools[pool].num_records;
370         record = kvp_pools[pool].records;
371
372         for (i = 0; i < num_records; i++)
373         {
374                 if (memcmp(key, record[i].key, key_size)) {
375                         continue;
376                 }
377
378                 KVP_LOG(LOG_DEBUG, "Found delete key in pool %d.\n",
379                     pool);
380                 /*
381                  * We found a match at the end; Just update the number of
382                  * entries and we are done.
383                  */
384                 if (i == num_records) {
385                         kvp_pools[pool].num_records--;
386                         kvp_update_file(pool);
387                         return (0);
388                 }
389
390                 /*
391                  * We found a match in the middle; Move the remaining
392                  * entries up.
393                  */
394                 j = i;
395                 k = j + 1;
396                 for ( ; k < num_records; k++)
397                 {
398                         strcpy(record[j].key, record[k].key);
399                         strcpy(record[j].value, record[k].value);
400                         j++;
401                 }
402                 kvp_pools[pool].num_records--;
403                 kvp_update_file(pool);
404                 return (0);
405         }
406         KVP_LOG(LOG_DEBUG, "Not found delete key in pool %d.\n",
407             pool);
408         return (1);
409 }
410
411
412 static int
413 kvp_key_add_or_modify(int pool, __u8 *key, __u32 key_size, __u8 *value,
414     __u32 value_size)
415 {
416         int i;
417         int num_records;
418         struct kvp_record *record;
419         int num_blocks;
420
421         KVP_LOG(LOG_DEBUG, "kvp_key_add_or_modify: pool =  %d, "
422             "key = %s, value = %s\n,", pool, key, value);
423
424         if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
425             (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
426                 KVP_LOG(LOG_ERR, "kvp_key_add_or_modify: returning 1\n");
427                 return (1);
428         }
429
430         /* Update the in-memory state. */
431         kvp_update_mem_state(pool);
432
433         num_records = kvp_pools[pool].num_records;
434         record = kvp_pools[pool].records;
435         num_blocks = kvp_pools[pool].num_blocks;
436
437         for (i = 0; i < num_records; i++)
438         {
439                 if (memcmp(key, record[i].key, key_size)) {
440                         continue;
441                 }
442
443                 /*
444                  * Key exists. Just update the value and we are done.
445                  */
446                 memcpy(record[i].value, value, value_size);
447                 kvp_update_file(pool);
448                 return (0);
449         }
450
451         /*
452          * Key doesn't exist; Add a new KVP.
453          */
454         if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
455                 /* Increase the size of the recodrd array. */
456                 record = realloc(record, sizeof(struct kvp_record) *
457                         ENTRIES_PER_BLOCK * (num_blocks + 1));
458
459                 if (record == NULL) {
460                         return (1);
461                 }
462                 kvp_pools[pool].num_blocks++;
463         }
464         memcpy(record[i].value, value, value_size);
465         memcpy(record[i].key, key, key_size);
466         kvp_pools[pool].records = record;
467         kvp_pools[pool].num_records++;
468         kvp_update_file(pool);
469         return (0);
470 }
471
472
473 static int
474 kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
475     int value_size)
476 {
477         int i;
478         int num_records;
479         struct kvp_record *record;
480
481         KVP_LOG(LOG_DEBUG, "kvp_get_value: pool =  %d, key = %s\n,",
482             pool, key);
483
484         if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
485             (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
486                 return (1);
487         }
488
489         /* Update the in-memory state first. */
490         kvp_update_mem_state(pool);
491
492         num_records = kvp_pools[pool].num_records;
493         record = kvp_pools[pool].records;
494
495         for (i = 0; i < num_records; i++)
496         {
497                 if (memcmp(key, record[i].key, key_size)) {
498                         continue;
499                 }
500
501                 /* Found the key */
502                 memcpy(value, record[i].value, value_size);
503                 return (0);
504         }
505
506         return (1);
507 }
508
509
510 static int
511 kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
512     __u8 *value, int value_size)
513 {
514         struct kvp_record *record;
515
516         KVP_LOG(LOG_DEBUG, "kvp_pool_enumerate: pool = %d, index = %d\n,",
517             pool, index);
518
519         /* First update our in-memory state first. */
520         kvp_update_mem_state(pool);
521         record = kvp_pools[pool].records;
522
523         /* Index starts with 0 */
524         if (index >= kvp_pools[pool].num_records) {
525                 return (1);
526         }
527
528         memcpy(key, record[index].key, key_size);
529         memcpy(value, record[index].value, value_size);
530         return (0);
531 }
532
533
534 static void
535 kvp_get_os_info(void)
536 {
537         char *p;
538
539         uname(&uts_buf);
540         os_build = uts_buf.release;
541         os_name = uts_buf.sysname;
542         processor_arch = uts_buf.machine;
543
544         /*
545          * Win7 host expects the build string to be of the form: x.y.z
546          * Strip additional information we may have.
547          */
548         p = strchr(os_build, '-');
549         if (p) {
550                 *p = '\0';
551         }
552
553         /*
554          * We don't have any other information about the FreeBSD os.
555          */
556         return;
557 }
558
559 /*
560  * Given the interface name, return the MAC address.
561  */
562 static char *
563 kvp_if_name_to_mac(char *if_name)
564 {
565         char *mac_addr = NULL;
566         struct ifaddrs *ifaddrs_ptr;
567         struct ifaddrs *head_ifaddrs_ptr;
568         struct sockaddr_dl *sdl;
569         int status;
570
571         status = getifaddrs(&ifaddrs_ptr);
572
573         if (status >= 0) {
574                 head_ifaddrs_ptr = ifaddrs_ptr;
575                 do {
576                         sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
577                         if ((sdl->sdl_type == IFT_ETHER) &&
578                             (strcmp(ifaddrs_ptr->ifa_name, if_name) == 0)) {
579                                 mac_addr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
580                                 break;
581                         }
582                 } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
583                 freeifaddrs(head_ifaddrs_ptr);
584         }
585
586         return (mac_addr);
587 }
588
589
590 /*
591  * Given the MAC address, return the interface name.
592  */
593 static char *
594 kvp_mac_to_if_name(char *mac)
595 {
596         char *if_name = NULL;
597         struct ifaddrs *ifaddrs_ptr;
598         struct ifaddrs *head_ifaddrs_ptr;
599         struct sockaddr_dl *sdl;
600         int status;
601         size_t i;
602         char *buf_ptr;
603
604         status = getifaddrs(&ifaddrs_ptr);
605
606         if (status >= 0) {
607                 head_ifaddrs_ptr = ifaddrs_ptr;
608                 do {
609                         sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
610                         if (sdl->sdl_type == IFT_ETHER) {
611                                 buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
612                                 for (i = 0; i < strlen(buf_ptr); i++)
613                                 {
614                                         buf_ptr[i] = toupper(buf_ptr[i]);
615                                 }
616
617                                 if (strncmp(buf_ptr, mac, strlen(mac)) == 0) {
618                                         /* Caller will free the memory */
619                                         if_name = strdup(ifaddrs_ptr->ifa_name);
620                                         free(buf_ptr);
621                                         break;
622                                 }else if (buf_ptr != NULL) {
623                                         free(buf_ptr);
624                                 }
625                         }
626                 } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
627                 freeifaddrs(head_ifaddrs_ptr);
628         }
629         return (if_name);
630 }
631
632
633 static void
634 kvp_process_ipconfig_file(char *cmd,
635     char *config_buf, size_t len,
636     size_t element_size, int offset)
637 {
638         char buf[256];
639         char *p;
640         char *x;
641         FILE *file;
642
643         /*
644          * First execute the command.
645          */
646         file = popen(cmd, "r");
647         if (file == NULL) {
648                 return;
649         }
650
651         if (offset == 0) {
652                 memset(config_buf, 0, len);
653         }
654         while ((p = fgets(buf, sizeof(buf), file)) != NULL) {
655                 if ((len - strlen(config_buf)) < (element_size + 1)) {
656                         break;
657                 }
658
659                 x = strchr(p, '\n');
660                 *x = '\0';
661                 strlcat(config_buf, p, len);
662                 strlcat(config_buf, ";", len);
663         }
664         pclose(file);
665 }
666
667
668 static void
669 kvp_get_ipconfig_info(char *if_name, struct hv_kvp_ipaddr_value *buffer)
670 {
671         char cmd[512];
672         char dhcp_info[128];
673         char *p;
674         FILE *file;
675
676         /*
677          * Retrieve the IPV4 address of default gateway.
678          */
679         snprintf(cmd, sizeof(cmd), "netstat -rn | grep %s | awk '/default/ {print $2 }'", if_name);
680
681         /*
682          * Execute the command to gather gateway IPV4 info.
683          */
684         kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
685             (MAX_GATEWAY_SIZE * 2), INET_ADDRSTRLEN, 0);
686
687         /*
688          * Retrieve the IPV6 address of default gateway.
689          */
690         snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name);
691
692         /*
693          * Execute the command to gather gateway IPV6 info.
694          */
695         kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
696             (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
697
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 (HV_KVP_E_FAIL);
785         }
786         if (str == NULL) {
787                 strlcpy(buffer, "inet_ntop failed\n", length);
788                 return (HV_KVP_E_FAIL);
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;
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 (HV_KVP_E_FAIL);
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
927                         kvp_get_ipconfig_info(if_name, ip_buffer);
928                 }
929
930 kvp_get_ip_info_ipaddr:
931                 error = kvp_process_ip_address(curp->ifa_addr,
932                         curp->ifa_addr->sa_family,
933                         buffer,
934                         length, &offset);
935                 if (error) {
936                         goto kvp_get_ip_info_done;
937                 }
938
939                 curp = curp->ifa_next;
940         }
941
942 kvp_get_ip_info_done:
943         freeifaddrs(ifap);
944         return (error);
945 }
946
947
948 static int
949 kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3)
950 {
951         int ret;
952
953         ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3);
954
955         if (ret < 0) {
956                 return (HV_KVP_E_FAIL);
957         }
958
959         return (0);
960 }
961
962
963 static int
964 kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
965 {
966         int error = 0;
967         char if_file[128];
968         FILE *file;
969         char cmd[512];
970         char *mac_addr;
971
972         /*
973          * FreeBSD - Configuration File
974          */
975         snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv",
976             "hv_set_ip_data");
977         file = fopen(if_file, "w");
978
979         if (file == NULL) {
980                 KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n");
981                 return (HV_KVP_E_FAIL);
982         }
983
984         /*
985          * Write out the MAC address.
986          */
987
988         mac_addr = kvp_if_name_to_mac(if_name);
989         if (mac_addr == NULL) {
990                 error = HV_KVP_E_FAIL;
991                 goto kvp_set_ip_info_error;
992         }
993         /* MAC Address */
994         error = kvp_write_file(file, "HWADDR", "", mac_addr);
995         if (error) {
996                 goto kvp_set_ip_info_error;
997         }
998
999         /* Interface Name  */
1000         error = kvp_write_file(file, "IF_NAME", "", if_name);
1001         if (error) {
1002                 goto kvp_set_ip_info_error;
1003         }
1004
1005         /* IP Address  */
1006         error = kvp_write_file(file, "IP_ADDR", "",
1007             (char *)new_val->ip_addr);
1008         if (error) {
1009                 goto kvp_set_ip_info_error;
1010         }
1011
1012         /* Subnet Mask */
1013         error = kvp_write_file(file, "SUBNET", "",
1014             (char *)new_val->sub_net);
1015         if (error) {
1016                 goto kvp_set_ip_info_error;
1017         }
1018
1019
1020         /* Gateway */
1021         error = kvp_write_file(file, "GATEWAY", "",
1022             (char *)new_val->gate_way);
1023         if (error) {
1024                 goto kvp_set_ip_info_error;
1025         }
1026
1027         /* DNS */
1028         error = kvp_write_file(file, "DNS", "", (char *)new_val->dns_addr);
1029         if (error) {
1030                 goto kvp_set_ip_info_error;
1031         }
1032
1033         /* DHCP */
1034         if (new_val->dhcp_enabled) {
1035                 error = kvp_write_file(file, "DHCP", "", "1");
1036         } else{
1037                 error = kvp_write_file(file, "DHCP", "", "0");
1038         }
1039
1040         if (error) {
1041                 goto kvp_set_ip_info_error;
1042         }
1043
1044         free(mac_addr);
1045         fclose(file);
1046
1047         /*
1048          * Invoke the external script with the populated
1049          * configuration file.
1050          */
1051
1052         snprintf(cmd, sizeof(cmd), "%s %s",
1053             "sh /usr/libexec/hyperv/hv_set_ifconfig", if_file);
1054         system(cmd);
1055         return (0);
1056
1057 kvp_set_ip_info_error:
1058         KVP_LOG(LOG_ERR, "Failed to write config file\n");
1059         free(mac_addr);
1060         fclose(file);
1061         return (error);
1062 }
1063
1064
1065 static int
1066 kvp_get_domain_name(char *buffer, int length)
1067 {
1068         struct addrinfo hints, *info;
1069         int error = 0;
1070
1071         gethostname(buffer, length);
1072         memset(&hints, 0, sizeof(hints));
1073         hints.ai_family = AF_INET;    /* Get only ipv4 addrinfo. */
1074         hints.ai_socktype = SOCK_STREAM;
1075         hints.ai_flags = AI_CANONNAME;
1076
1077         error = getaddrinfo(buffer, NULL, &hints, &info);
1078         if (error != 0) {
1079                 strlcpy(buffer, "getaddrinfo failed\n", length);
1080                 return (error);
1081         }
1082         strlcpy(buffer, info->ai_canonname, length);
1083         freeaddrinfo(info);
1084         return (error);
1085 }
1086
1087
1088 static int
1089 kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1090 {
1091         struct hv_kvp_ipaddr_value *ip_val;
1092         char *if_name;
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_KVP_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_KVP_E_FAIL;
1105                 goto kvp_op_getipinfo_done;
1106         }
1107
1108         op_msg->hdr.error = kvp_get_ip_info(0, if_name,
1109             HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2));
1110
1111         free(if_name);
1112
1113 kvp_op_getipinfo_done:
1114         return(op_msg->hdr.error);
1115 }
1116
1117
1118 static int
1119 kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1120 {
1121         struct hv_kvp_ipaddr_value *ip_val;
1122         char *if_name;
1123
1124         assert(op_msg != NULL);
1125         KVP_LOG(LOG_DEBUG, "In kvp_op_setipinfo.\n");
1126
1127         ip_val = &op_msg->body.kvp_ip_val;
1128         op_msg->hdr.error = HV_KVP_S_OK;
1129
1130         if_name = (char *)ip_val->adapter_id;
1131
1132         if (if_name == NULL) {
1133                 /* No adapter provided. */
1134                 op_msg->hdr.error = HV_KVP_GUID_NOTFOUND;
1135                 goto kvp_op_setipinfo_done;
1136         }
1137
1138         op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val);
1139
1140 kvp_op_setipinfo_done:
1141         return(op_msg->hdr.error);
1142 }
1143
1144
1145 static int
1146 kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data)
1147 {
1148         struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data;
1149         int error = 0;
1150         int op_pool;
1151
1152         assert(op_msg != NULL);
1153         assert(op_hdlr != NULL);
1154
1155         op_pool = op_msg->hdr.kvp_hdr.pool;
1156         op_msg->hdr.error = HV_KVP_S_OK;
1157
1158         switch(op_hdlr->kvp_op_key) {
1159         case HV_KVP_OP_SET:
1160                 if (op_pool == HV_KVP_POOL_AUTO) {
1161                         /* Auto Pool is not writeable from host side. */
1162                         error = 1;
1163                         KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n",
1164                             op_pool);
1165                 } else {
1166                         error = kvp_key_add_or_modify(op_pool,
1167                             op_msg->body.kvp_set.data.key,
1168                             op_msg->body.kvp_set.data.key_size,
1169                             op_msg->body.kvp_set.data.msg_value.value,
1170                             op_msg->body.kvp_set.data.value_size);
1171                 }
1172                 break;
1173
1174         case HV_KVP_OP_GET:
1175                 error = kvp_get_value(op_pool,
1176                     op_msg->body.kvp_get.data.key,
1177                     op_msg->body.kvp_get.data.key_size,
1178                     op_msg->body.kvp_get.data.msg_value.value,
1179                     op_msg->body.kvp_get.data.value_size);
1180                 break;
1181
1182         case HV_KVP_OP_DELETE:
1183                 if (op_pool == HV_KVP_POOL_AUTO) {
1184                         /* Auto Pool is not writeable from host side. */
1185                         error = 1;
1186                         KVP_LOG(LOG_ERR, "Ilegal to change pool %d from host\n",
1187                             op_pool);
1188                 } else {
1189                         error = kvp_key_delete(op_pool,
1190                             op_msg->body.kvp_delete.key,
1191                             op_msg->body.kvp_delete.key_size);
1192                 }
1193                 break;
1194
1195         default:
1196                 break;
1197         }
1198
1199         if (error != 0)
1200                 op_msg->hdr.error = HV_KVP_S_CONT;
1201
1202         return(error);
1203 }
1204
1205
1206 static int
1207 kvp_op_enumerate(struct hv_kvp_msg *op_msg, void *data __unused)
1208 {
1209         char *key_name, *key_value;
1210         int error = 0;
1211         int op_pool;
1212         int op;
1213
1214         assert(op_msg != NULL);
1215
1216         op = op_msg->hdr.kvp_hdr.operation;
1217         op_pool = op_msg->hdr.kvp_hdr.pool;
1218         op_msg->hdr.error = HV_KVP_S_OK;
1219
1220         /*
1221          * If the pool is not HV_KVP_POOL_AUTO, read from the appropriate
1222          * pool and return the KVP according to the index requested.
1223          */
1224         if (op_pool != HV_KVP_POOL_AUTO) {
1225                 if (kvp_pool_enumerate(op_pool,
1226                     op_msg->body.kvp_enum_data.index,
1227                     op_msg->body.kvp_enum_data.data.key,
1228                     HV_KVP_EXCHANGE_MAX_KEY_SIZE,
1229                     op_msg->body.kvp_enum_data.data.msg_value.value,
1230                     HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
1231                         op_msg->hdr.error = HV_KVP_S_CONT;
1232                         error = -1;
1233                 }
1234                 goto kvp_op_enumerate_done;
1235         }
1236
1237         key_name = (char *)op_msg->body.kvp_enum_data.data.key;
1238         key_value = (char *)op_msg->body.kvp_enum_data.data.msg_value.value;
1239
1240         switch (op_msg->body.kvp_enum_data.index)
1241         {
1242         case FullyQualifiedDomainName:
1243                 kvp_get_domain_name(key_value,
1244                     HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1245                 strcpy(key_name, "FullyQualifiedDomainName");
1246                 break;
1247
1248         case IntegrationServicesVersion:
1249                 strcpy(key_name, "IntegrationServicesVersion");
1250                 strcpy(key_value, lic_version);
1251                 break;
1252
1253         case NetworkAddressIPv4:
1254                 kvp_get_ip_info(AF_INET, NULL, HV_KVP_OP_ENUMERATE,
1255                     key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1256                 strcpy(key_name, "NetworkAddressIPv4");
1257                 break;
1258
1259         case NetworkAddressIPv6:
1260                 kvp_get_ip_info(AF_INET6, NULL, HV_KVP_OP_ENUMERATE,
1261                     key_value, HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
1262                 strcpy(key_name, "NetworkAddressIPv6");
1263                 break;
1264
1265         case OSBuildNumber:
1266                 strcpy(key_value, os_build);
1267                 strcpy(key_name, "OSBuildNumber");
1268                 break;
1269
1270         case OSName:
1271                 strcpy(key_value, os_name);
1272                 strcpy(key_name, "OSName");
1273                 break;
1274
1275         case OSMajorVersion:
1276                 strcpy(key_value, os_major);
1277                 strcpy(key_name, "OSMajorVersion");
1278                 break;
1279
1280         case OSMinorVersion:
1281                 strcpy(key_value, os_minor);
1282                 strcpy(key_name, "OSMinorVersion");
1283                 break;
1284
1285         case OSVersion:
1286                 strcpy(key_value, os_build);
1287                 strcpy(key_name, "OSVersion");
1288                 break;
1289
1290         case ProcessorArchitecture:
1291                 strcpy(key_value, processor_arch);
1292                 strcpy(key_name, "ProcessorArchitecture");
1293                 break;
1294
1295         default:
1296 #ifdef DEBUG
1297                 KVP_LOG(LOG_ERR, "Auto pool Index %d not found.\n",
1298                     op_msg->body.kvp_enum_data.index);
1299 #endif
1300                 op_msg->hdr.error = HV_KVP_S_CONT;
1301                 error = -1;
1302                 break;
1303         }
1304
1305 kvp_op_enumerate_done:
1306         return(error);
1307 }
1308
1309
1310 /*
1311  * Load handler, and call init routine if provided.
1312  */
1313 static int
1314 kvp_op_load(int key, void (*init)(void),
1315             int (*exec)(struct hv_kvp_msg *, void *))
1316 {
1317         int error = 0;
1318
1319         if (key < 0 || key >= HV_KVP_OP_COUNT) {
1320                 KVP_LOG(LOG_ERR, "Operation key out of supported range\n");
1321                 error = -1;
1322                 goto kvp_op_load_done;
1323         }
1324
1325         kvp_op_hdlrs[key].kvp_op_key = key;
1326         kvp_op_hdlrs[key].kvp_op_init = init;
1327         kvp_op_hdlrs[key].kvp_op_exec = exec;
1328
1329         if (kvp_op_hdlrs[key].kvp_op_init != NULL)
1330                 kvp_op_hdlrs[key].kvp_op_init();
1331
1332 kvp_op_load_done:
1333         return(error);
1334 }
1335
1336
1337 /*
1338  * Initialize the operation hanlders.
1339  */
1340 static int
1341 kvp_ops_init(void)
1342 {
1343         int i;
1344
1345         /* Set the initial values. */
1346         for (i = 0; i < HV_KVP_OP_COUNT; i++) {
1347                 kvp_op_hdlrs[i].kvp_op_key = -1;
1348                 kvp_op_hdlrs[i].kvp_op_init = NULL;
1349                 kvp_op_hdlrs[i].kvp_op_exec = NULL;
1350         }
1351
1352         return(kvp_op_load(HV_KVP_OP_GET, NULL, kvp_op_setgetdel) |
1353             kvp_op_load(HV_KVP_OP_SET, NULL, kvp_op_setgetdel) |
1354             kvp_op_load(HV_KVP_OP_DELETE, NULL, kvp_op_setgetdel) |
1355             kvp_op_load(HV_KVP_OP_ENUMERATE, kvp_get_os_info,
1356                 kvp_op_enumerate) |
1357             kvp_op_load(HV_KVP_OP_GET_IP_INFO, NULL, kvp_op_getipinfo) |
1358             kvp_op_load(HV_KVP_OP_SET_IP_INFO, NULL, kvp_op_setipinfo));
1359 }
1360
1361
1362 int
1363 main(int argc, char *argv[])
1364 {
1365         struct hv_kvp_msg *hv_kvp_dev_buf;
1366         struct hv_kvp_msg *hv_msg;
1367         struct pollfd hv_kvp_poll_fd[1];
1368         int op, pool;
1369         int hv_kvp_dev_fd, error, len, r;
1370         int ch;
1371
1372         while ((ch = getopt(argc, argv, "dn")) != -1) {
1373                 switch (ch) {
1374                 case 'n':
1375                         /* Run as regular process for debugging purpose. */
1376                         is_daemon = 0;
1377                         break;
1378                 case 'd':
1379                         /* Generate debugging output */
1380                         is_debugging = 1;
1381                         break;
1382                 default:
1383                         break;
1384                 }
1385         }
1386
1387         openlog("HV_KVP", 0, LOG_USER);
1388
1389         /* Become daemon first. */
1390         if (is_daemon == 1)
1391                 daemon(1, 0);
1392         else
1393                 KVP_LOG(LOG_DEBUG, "Run as regular process.\n");
1394
1395         KVP_LOG(LOG_INFO, "HV_KVP starting; pid is: %d\n", getpid());
1396
1397         /* Communication buffer hv_kvp_dev_buf */
1398         hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf));
1399         /* Buffer for daemon internal use */
1400         hv_msg = malloc(sizeof(*hv_msg));
1401
1402         /* Memory allocation failed */
1403         if (hv_kvp_dev_buf == NULL || hv_msg == NULL) {
1404                 KVP_LOG(LOG_ERR, "Failed to allocate memory for hv buffer\n");
1405                 exit(EXIT_FAILURE);
1406         }
1407
1408         /* Initialize op handlers */
1409         if (kvp_ops_init() != 0) {
1410                 KVP_LOG(LOG_ERR, "Failed to initizlize operation handlers\n");
1411                 exit(EXIT_FAILURE);
1412         }
1413
1414         if (kvp_file_init()) {
1415                 KVP_LOG(LOG_ERR, "Failed to initialize the pools\n");
1416                 exit(EXIT_FAILURE);
1417         }
1418
1419         /* Open the Character Device */
1420         hv_kvp_dev_fd = open("/dev/hv_kvp_dev", O_RDWR);
1421
1422         if (hv_kvp_dev_fd < 0) {
1423                 KVP_LOG(LOG_ERR, "open /dev/hv_kvp_dev failed; error: %d %s\n",
1424                     errno, strerror(errno));
1425                 exit(EXIT_FAILURE);
1426         }
1427
1428         /* Initialize the struct for polling the char device */
1429         hv_kvp_poll_fd[0].fd = hv_kvp_dev_fd;
1430         hv_kvp_poll_fd[0].events = (POLLIN | POLLRDNORM);
1431
1432         /* Register the daemon to the KVP driver */
1433         memset(hv_kvp_dev_buf, 0, sizeof(*hv_kvp_dev_buf));
1434         hv_kvp_dev_buf->hdr.kvp_hdr.operation = HV_KVP_OP_REGISTER;
1435         len = write(hv_kvp_dev_fd, hv_kvp_dev_buf, sizeof(*hv_kvp_dev_buf));
1436
1437
1438         for (;;) {
1439                 r = poll (hv_kvp_poll_fd, 1, 100);
1440
1441                 KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n",
1442                     r, hv_kvp_poll_fd[0].revents);
1443
1444                 if (r == 0 || (r < 0 && errno == EAGAIN) ||
1445                     (r < 0 && errno == EINTR)) {
1446                         /* Nothing to read */
1447                         continue;
1448                 }
1449
1450                 if (r < 0) {
1451                         /*
1452                          * For pread return failure other than EAGAIN,
1453                          * we want to exit.
1454                          */
1455                         KVP_LOG(LOG_ERR, "Poll failed.\n");
1456                         perror("poll");
1457                         exit(EIO);
1458                 }
1459
1460                 /* Read from character device */
1461                 len = pread(hv_kvp_dev_fd, hv_kvp_dev_buf,
1462                     sizeof(*hv_kvp_dev_buf), 0);
1463
1464                 if (len < 0) {
1465                         KVP_LOG(LOG_ERR, "Read failed.\n");
1466                         perror("pread");
1467                         exit(EIO);
1468                 }
1469
1470                 if (len != sizeof(struct hv_kvp_msg)) {
1471                         KVP_LOG(LOG_ERR, "read len is: %d\n", len);
1472                         continue;
1473                 }
1474
1475                 /* Copy hv_kvp_dev_buf to hv_msg */
1476                 memcpy(hv_msg, hv_kvp_dev_buf, sizeof(*hv_msg));
1477
1478                 /*
1479                  * We will use the KVP header information to pass back
1480                  * the error from this daemon. So, first save the op
1481                  * and pool info to local variables.
1482                  */
1483
1484                 op = hv_msg->hdr.kvp_hdr.operation;
1485                 pool = hv_msg->hdr.kvp_hdr.pool;
1486
1487                 if (op < 0 || op >= HV_KVP_OP_COUNT ||
1488                     kvp_op_hdlrs[op].kvp_op_exec == NULL) {
1489                         KVP_LOG(LOG_WARNING,
1490                             "Unsupported operation OP = %d\n", op);
1491                         hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED;
1492                 } else {
1493                         /*
1494                          * Call the operateion handler's execution routine.
1495                          */
1496                         error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg,
1497                             (void *)&kvp_op_hdlrs[op]);
1498                         if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT)
1499                                 KVP_LOG(LOG_WARNING,
1500                                     "Operation failed OP = %d, error = 0x%x\n",
1501                                     op, error);
1502                 }
1503
1504                 /*
1505                  * Send the value back to the kernel. The response is
1506                  * already in the receive buffer.
1507                  */
1508 hv_kvp_done:
1509                 len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0);
1510
1511                 if (len != sizeof(struct hv_kvp_msg)) {
1512                         KVP_LOG(LOG_ERR, "write len is: %d\n", len);
1513                         goto hv_kvp_done;
1514                 }
1515         }
1516 }