]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/hyperv/tools/hv_kvp_daemon.c
Revert r272149, which introduces obscure vestiges from the
[FreeBSD/stable/10.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 (access("/var/db/hyperv/pool", F_OK)) {
288                 if (mkdir("/var/db/hyperv/pool",
289                     S_IRUSR | S_IWUSR | S_IROTH)) {
290                         KVP_LOG(LOG_ERR, " Failed to create /var/db/hyperv/pool\n");
291                         exit(EXIT_FAILURE);
292                 }
293         }
294
295         for (i = 0; i < HV_KVP_POOL_COUNT; i++)
296         {
297                 fname = kvp_pools[i].fname;
298                 records_read = 0;
299                 num_blocks = 1;
300                 snprintf(fname, MAX_FILE_NAME, "/var/db/hyperv/pool/.kvp_pool_%d", i);
301                 fd = open(fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH);
302
303                 if (fd == -1) {
304                         return (1);
305                 }
306
307
308                 filep = fopen(fname, "r");
309                 if (!filep) {
310                         return (1);
311                 }
312
313                 record = malloc(alloc_unit * num_blocks);
314                 if (record == NULL) {
315                         fclose(filep);
316                         return (1);
317                 }
318                 for ( ; ; )
319                 {
320                         readp = &record[records_read];
321                         records_read += fread(readp, sizeof(struct kvp_record),
322                                 ENTRIES_PER_BLOCK,
323                                 filep);
324
325                         if (ferror(filep)) {
326                                 KVP_LOG(LOG_ERR, "Failed to read file, pool: %d\n",
327                                     i);
328                                 exit(EXIT_FAILURE);
329                         }
330
331                         if (!feof(filep)) {
332                                 /*
333                                  * More data to read.
334                                  */
335                                 num_blocks++;
336                                 record = realloc(record, alloc_unit *
337                                         num_blocks);
338                                 if (record == NULL) {
339                                         fclose(filep);
340                                         return (1);
341                                 }
342                                 continue;
343                         }
344                         break;
345                 }
346                 kvp_pools[i].pool_fd = fd;
347                 kvp_pools[i].num_blocks = num_blocks;
348                 kvp_pools[i].records = record;
349                 kvp_pools[i].num_records = records_read;
350                 fclose(filep);
351         }
352
353         return (0);
354 }
355
356
357 static int
358 kvp_key_delete(int pool, __u8 *key, int key_size)
359 {
360         int i;
361         int j, k;
362         int num_records;
363         struct kvp_record *record;
364
365         KVP_LOG(LOG_DEBUG, "kvp_key_delete: pool =  %d, "
366             "key = %s\n", pool, key);
367
368         /* Update in-memory state */
369         kvp_update_mem_state(pool);
370
371         num_records = kvp_pools[pool].num_records;
372         record = kvp_pools[pool].records;
373
374         for (i = 0; i < num_records; i++)
375         {
376                 if (memcmp(key, record[i].key, key_size)) {
377                         continue;
378                 }
379
380                 KVP_LOG(LOG_DEBUG, "Found delete key in pool %d.\n",
381                     pool);
382                 /*
383                  * We found a match at the end; Just update the number of
384                  * entries and we are done.
385                  */
386                 if (i == num_records) {
387                         kvp_pools[pool].num_records--;
388                         kvp_update_file(pool);
389                         return (0);
390                 }
391
392                 /*
393                  * We found a match in the middle; Move the remaining
394                  * entries up.
395                  */
396                 j = i;
397                 k = j + 1;
398                 for ( ; k < num_records; k++)
399                 {
400                         strcpy(record[j].key, record[k].key);
401                         strcpy(record[j].value, record[k].value);
402                         j++;
403                 }
404                 kvp_pools[pool].num_records--;
405                 kvp_update_file(pool);
406                 return (0);
407         }
408         KVP_LOG(LOG_DEBUG, "Not found delete key in pool %d.\n",
409             pool);
410         return (1);
411 }
412
413
414 static int
415 kvp_key_add_or_modify(int pool, __u8 *key, __u32 key_size, __u8 *value,
416     __u32 value_size)
417 {
418         int i;
419         int num_records;
420         struct kvp_record *record;
421         int num_blocks;
422
423         KVP_LOG(LOG_DEBUG, "kvp_key_add_or_modify: pool =  %d, "
424             "key = %s, value = %s\n,", pool, key, value);
425
426         if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
427             (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
428                 KVP_LOG(LOG_ERR, "kvp_key_add_or_modify: returning 1\n");
429                 return (1);
430         }
431
432         /* Update the in-memory state. */
433         kvp_update_mem_state(pool);
434
435         num_records = kvp_pools[pool].num_records;
436         record = kvp_pools[pool].records;
437         num_blocks = kvp_pools[pool].num_blocks;
438
439         for (i = 0; i < num_records; i++)
440         {
441                 if (memcmp(key, record[i].key, key_size)) {
442                         continue;
443                 }
444
445                 /*
446                  * Key exists. Just update the value and we are done.
447                  */
448                 memcpy(record[i].value, value, value_size);
449                 kvp_update_file(pool);
450                 return (0);
451         }
452
453         /*
454          * Key doesn't exist; Add a new KVP.
455          */
456         if (num_records == (ENTRIES_PER_BLOCK * num_blocks)) {
457                 /* Increase the size of the recodrd array. */
458                 record = realloc(record, sizeof(struct kvp_record) *
459                         ENTRIES_PER_BLOCK * (num_blocks + 1));
460
461                 if (record == NULL) {
462                         return (1);
463                 }
464                 kvp_pools[pool].num_blocks++;
465         }
466         memcpy(record[i].value, value, value_size);
467         memcpy(record[i].key, key, key_size);
468         kvp_pools[pool].records = record;
469         kvp_pools[pool].num_records++;
470         kvp_update_file(pool);
471         return (0);
472 }
473
474
475 static int
476 kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
477     int value_size)
478 {
479         int i;
480         int num_records;
481         struct kvp_record *record;
482
483         KVP_LOG(LOG_DEBUG, "kvp_get_value: pool =  %d, key = %s\n,",
484             pool, key);
485
486         if ((key_size > HV_KVP_EXCHANGE_MAX_KEY_SIZE) ||
487             (value_size > HV_KVP_EXCHANGE_MAX_VALUE_SIZE)) {
488                 return (1);
489         }
490
491         /* Update the in-memory state first. */
492         kvp_update_mem_state(pool);
493
494         num_records = kvp_pools[pool].num_records;
495         record = kvp_pools[pool].records;
496
497         for (i = 0; i < num_records; i++)
498         {
499                 if (memcmp(key, record[i].key, key_size)) {
500                         continue;
501                 }
502
503                 /* Found the key */
504                 memcpy(value, record[i].value, value_size);
505                 return (0);
506         }
507
508         return (1);
509 }
510
511
512 static int
513 kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
514     __u8 *value, int value_size)
515 {
516         struct kvp_record *record;
517
518         KVP_LOG(LOG_DEBUG, "kvp_pool_enumerate: pool = %d, index = %d\n,",
519             pool, index);
520
521         /* First update our in-memory state first. */
522         kvp_update_mem_state(pool);
523         record = kvp_pools[pool].records;
524
525         /* Index starts with 0 */
526         if (index >= kvp_pools[pool].num_records) {
527                 return (1);
528         }
529
530         memcpy(key, record[index].key, key_size);
531         memcpy(value, record[index].value, value_size);
532         return (0);
533 }
534
535
536 static void
537 kvp_get_os_info(void)
538 {
539         char *p;
540
541         uname(&uts_buf);
542         os_build = uts_buf.release;
543         os_name = uts_buf.sysname;
544         processor_arch = uts_buf.machine;
545
546         /*
547          * Win7 host expects the build string to be of the form: x.y.z
548          * Strip additional information we may have.
549          */
550         p = strchr(os_build, '-');
551         if (p) {
552                 *p = '\0';
553         }
554
555         /*
556          * We don't have any other information about the FreeBSD os.
557          */
558         return;
559 }
560
561 /*
562  * Given the interface name, return the MAC address.
563  */
564 static char *
565 kvp_if_name_to_mac(char *if_name)
566 {
567         char *mac_addr = NULL;
568         struct ifaddrs *ifaddrs_ptr;
569         struct ifaddrs *head_ifaddrs_ptr;
570         struct sockaddr_dl *sdl;
571         int status;
572
573         status = getifaddrs(&ifaddrs_ptr);
574
575         if (status >= 0) {
576                 head_ifaddrs_ptr = ifaddrs_ptr;
577                 do {
578                         sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
579                         if ((sdl->sdl_type == IFT_ETHER) &&
580                             (strcmp(ifaddrs_ptr->ifa_name, if_name) == 0)) {
581                                 mac_addr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
582                                 break;
583                         }
584                 } while ((ifaddrs_ptr = ifaddrs_ptr->ifa_next) != NULL);
585                 freeifaddrs(head_ifaddrs_ptr);
586         }
587
588         return (mac_addr);
589 }
590
591
592 /*
593  * Given the MAC address, return the interface name.
594  */
595 static char *
596 kvp_mac_to_if_name(char *mac)
597 {
598         char *if_name = NULL;
599         struct ifaddrs *ifaddrs_ptr;
600         struct ifaddrs *head_ifaddrs_ptr;
601         struct sockaddr_dl *sdl;
602         int status;
603         size_t i;
604         char *buf_ptr;
605
606         status = getifaddrs(&ifaddrs_ptr);
607
608         if (status >= 0) {
609                 head_ifaddrs_ptr = ifaddrs_ptr;
610                 do {
611                         sdl = (struct sockaddr_dl *)(uintptr_t)ifaddrs_ptr->ifa_addr;
612                         if (sdl->sdl_type == IFT_ETHER) {
613                                 buf_ptr = strdup(ether_ntoa((struct ether_addr *)(LLADDR(sdl))));
614                                 for (i = 0; i < strlen(buf_ptr); i++)
615                                 {
616                                         buf_ptr[i] = toupper(buf_ptr[i]);
617                                 }
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 if (buf_ptr != NULL) {
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         /*
690          * Retrieve the IPV6 address of default gateway.
691          */
692         snprintf(cmd, sizeof(cmd), "netstat -rn inet6 | grep %s | awk '/default/ {print $2 }", if_name);
693
694         /*
695          * Execute the command to gather gateway IPV6 info.
696          */
697         kvp_process_ipconfig_file(cmd, (char *)buffer->gate_way,
698             (MAX_GATEWAY_SIZE * 2), INET6_ADDRSTRLEN, 1);
699
700         /*
701          * we just invoke an external script to get the DNS info.
702          *
703          * Following is the expected format of the information from the script:
704          *
705          * ipaddr1 (nameserver1)
706          * ipaddr2 (nameserver2)
707          * .
708          * .
709          */
710         /* Scripts are stored in /usr/libexec/hyperv/ directory */
711         snprintf(cmd, sizeof(cmd), "%s", "sh /usr/libexec/hyperv/hv_get_dns_info");
712
713         /*
714          * Execute the command to get DNS info.
715          */
716         kvp_process_ipconfig_file(cmd, (char *)buffer->dns_addr,
717             (MAX_IP_ADDR_SIZE * 2), INET_ADDRSTRLEN, 0);
718
719         /*
720          * Invoke an external script to get the DHCP state info.
721          * The parameter to the script is the interface name.
722          * Here is the expected output:
723          *
724          * Enabled: DHCP enabled.
725          */
726
727
728         snprintf(cmd, sizeof(cmd), "%s %s",
729             "sh /usr/libexec/hyperv/hv_get_dhcp_info", if_name);
730
731         file = popen(cmd, "r");
732         if (file == NULL) {
733                 return;
734         }
735
736         p = fgets(dhcp_info, sizeof(dhcp_info), file);
737         if (p == NULL) {
738                 pclose(file);
739                 return;
740         }
741
742         if (!strncmp(p, "Enabled", 7)) {
743                 buffer->dhcp_enabled = 1;
744         } else{
745                 buffer->dhcp_enabled = 0;
746         }
747
748         pclose(file);
749 }
750
751
752 static unsigned int
753 hweight32(unsigned int *w)
754 {
755         unsigned int res = *w - ((*w >> 1) & 0x55555555);
756
757         res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
758         res = (res + (res >> 4)) & 0x0F0F0F0F;
759         res = res + (res >> 8);
760         return ((res + (res >> 16)) & 0x000000FF);
761 }
762
763
764 static int
765 kvp_process_ip_address(void *addrp,
766     int family, char *buffer,
767     int length, int *offset)
768 {
769         struct sockaddr_in *addr;
770         struct sockaddr_in6 *addr6;
771         int addr_length;
772         char tmp[50];
773         const char *str;
774
775         if (family == AF_INET) {
776                 addr = (struct sockaddr_in *)addrp;
777                 str = inet_ntop(family, &addr->sin_addr, tmp, 50);
778                 addr_length = INET_ADDRSTRLEN;
779         } else {
780                 addr6 = (struct sockaddr_in6 *)addrp;
781                 str = inet_ntop(family, &addr6->sin6_addr.s6_addr, tmp, 50);
782                 addr_length = INET6_ADDRSTRLEN;
783         }
784
785         if ((length - *offset) < addr_length + 1) {
786                 return (HV_KVP_E_FAIL);
787         }
788         if (str == NULL) {
789                 strlcpy(buffer, "inet_ntop failed\n", length);
790                 return (HV_KVP_E_FAIL);
791         }
792         if (*offset == 0) {
793                 strlcpy(buffer, tmp, length);
794         } else{
795                 strlcat(buffer, tmp, length);
796         }
797         strlcat(buffer, ";", length);
798
799         *offset += strlen(str) + 1;
800         return (0);
801 }
802
803
804 static int
805 kvp_get_ip_info(int family, char *if_name, int op,
806     void *out_buffer, size_t length)
807 {
808         struct ifaddrs *ifap;
809         struct ifaddrs *curp;
810         int offset = 0;
811         int sn_offset = 0;
812         int error = 0;
813         char *buffer;
814         size_t buffer_length;
815         struct hv_kvp_ipaddr_value *ip_buffer;
816         char cidr_mask[5];
817         int weight;
818         int i;
819         unsigned int *w = NULL;
820         char *sn_str;
821         size_t sn_str_length;
822         struct sockaddr_in6 *addr6;
823
824         if (op == HV_KVP_OP_ENUMERATE) {
825                 buffer = out_buffer;
826                 buffer_length = length;
827         } else {
828                 ip_buffer = out_buffer;
829                 buffer = (char *)ip_buffer->ip_addr;
830                 buffer_length = sizeof(ip_buffer->ip_addr);
831                 ip_buffer->addr_family = 0;
832         }
833
834         if (getifaddrs(&ifap)) {
835                 strlcpy(buffer, "getifaddrs failed\n", buffer_length);
836                 return (HV_KVP_E_FAIL);
837         }
838
839         curp = ifap;
840         while (curp != NULL) {
841                 if (curp->ifa_addr == NULL) {
842                         curp = curp->ifa_next;
843                         continue;
844                 }
845
846                 if ((if_name != NULL) &&
847                     (strncmp(curp->ifa_name, if_name, strlen(if_name)))) {
848                         /*
849                          * We want info about a specific interface;
850                          * just continue.
851                          */
852                         curp = curp->ifa_next;
853                         continue;
854                 }
855
856                 /*
857                  * We support two address families: AF_INET and AF_INET6.
858                  * If family value is 0, we gather both supported
859                  * address families; if not we gather info on
860                  * the specified address family.
861                  */
862                 if ((family != 0) && (curp->ifa_addr->sa_family != family)) {
863                         curp = curp->ifa_next;
864                         continue;
865                 }
866                 if ((curp->ifa_addr->sa_family != AF_INET) &&
867                     (curp->ifa_addr->sa_family != AF_INET6)) {
868                         curp = curp->ifa_next;
869                         continue;
870                 }
871
872                 if (op == HV_KVP_OP_GET_IP_INFO) {
873                         /*
874                          * Get the info other than the IP address.
875                          */
876                         if (curp->ifa_addr->sa_family == AF_INET) {
877                                 ip_buffer->addr_family |= ADDR_FAMILY_IPV4;
878
879                                 /*
880                                  * Get subnet info.
881                                  */
882                                 error = kvp_process_ip_address(
883                                         curp->ifa_netmask,
884                                         AF_INET,
885                                         (char *)
886                                         ip_buffer->sub_net,
887                                         length,
888                                         &sn_offset);
889                                 if (error) {
890                                         goto kvp_get_ip_info_ipaddr;
891                                 }
892                         } else {
893                                 ip_buffer->addr_family |= ADDR_FAMILY_IPV6;
894
895                                 /*
896                                  * Get subnet info in CIDR format.
897                                  */
898                                 weight = 0;
899                                 sn_str = (char *)ip_buffer->sub_net;
900                                 sn_str_length = sizeof(ip_buffer->sub_net);
901                                 addr6 = (struct sockaddr_in6 *)(uintptr_t)
902                                     curp->ifa_netmask;
903                                 w = (unsigned int *)(uintptr_t)addr6->sin6_addr.s6_addr;
904
905                                 for (i = 0; i < 4; i++)
906                                 {
907                                         weight += hweight32(&w[i]);
908                                 }
909
910                                 snprintf(cidr_mask, sizeof(cidr_mask), "/%d", weight);
911                                 if ((length - sn_offset) <
912                                     (strlen(cidr_mask) + 1)) {
913                                         goto kvp_get_ip_info_ipaddr;
914                                 }
915
916                                 if (sn_offset == 0) {
917                                         strlcpy(sn_str, cidr_mask, sn_str_length);
918                                 } else{
919                                         strlcat(sn_str, cidr_mask, sn_str_length);
920                                 }
921                                 strlcat((char *)ip_buffer->sub_net, ";", sn_str_length);
922                                 sn_offset += strlen(sn_str) + 1;
923                         }
924
925                         /*
926                          * Collect other ip configuration info.
927                          */
928
929                         kvp_get_ipconfig_info(if_name, ip_buffer);
930                 }
931
932 kvp_get_ip_info_ipaddr:
933                 error = kvp_process_ip_address(curp->ifa_addr,
934                         curp->ifa_addr->sa_family,
935                         buffer,
936                         length, &offset);
937                 if (error) {
938                         goto kvp_get_ip_info_done;
939                 }
940
941                 curp = curp->ifa_next;
942         }
943
944 kvp_get_ip_info_done:
945         freeifaddrs(ifap);
946         return (error);
947 }
948
949
950 static int
951 kvp_write_file(FILE *f, const char *s1, const char *s2, const char *s3)
952 {
953         int ret;
954
955         ret = fprintf(f, "%s%s%s%s\n", s1, s2, "=", s3);
956
957         if (ret < 0) {
958                 return (HV_KVP_E_FAIL);
959         }
960
961         return (0);
962 }
963
964
965 static int
966 kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
967 {
968         int error = 0;
969         char if_file[128];
970         FILE *file;
971         char cmd[512];
972         char *mac_addr;
973
974         /*
975          * FreeBSD - Configuration File
976          */
977         snprintf(if_file, sizeof(if_file), "%s%s", "/var/db/hyperv",
978             "hv_set_ip_data");
979         file = fopen(if_file, "w");
980
981         if (file == NULL) {
982                 KVP_LOG(LOG_ERR, "FreeBSD Failed to open config file\n");
983                 return (HV_KVP_E_FAIL);
984         }
985
986         /*
987          * Write out the MAC address.
988          */
989
990         mac_addr = kvp_if_name_to_mac(if_name);
991         if (mac_addr == NULL) {
992                 error = HV_KVP_E_FAIL;
993                 goto kvp_set_ip_info_error;
994         }
995         /* MAC Address */
996         error = kvp_write_file(file, "HWADDR", "", mac_addr);
997         if (error) {
998                 goto kvp_set_ip_info_error;
999         }
1000
1001         /* Interface Name  */
1002         error = kvp_write_file(file, "IF_NAME", "", if_name);
1003         if (error) {
1004                 goto kvp_set_ip_info_error;
1005         }
1006
1007         /* IP Address  */
1008         error = kvp_write_file(file, "IP_ADDR", "",
1009             (char *)new_val->ip_addr);
1010         if (error) {
1011                 goto kvp_set_ip_info_error;
1012         }
1013
1014         /* Subnet Mask */
1015         error = kvp_write_file(file, "SUBNET", "",
1016             (char *)new_val->sub_net);
1017         if (error) {
1018                 goto kvp_set_ip_info_error;
1019         }
1020
1021
1022         /* Gateway */
1023         error = kvp_write_file(file, "GATEWAY", "",
1024             (char *)new_val->gate_way);
1025         if (error) {
1026                 goto kvp_set_ip_info_error;
1027         }
1028
1029         /* DNS */
1030         error = kvp_write_file(file, "DNS", "", (char *)new_val->dns_addr);
1031         if (error) {
1032                 goto kvp_set_ip_info_error;
1033         }
1034
1035         /* DHCP */
1036         if (new_val->dhcp_enabled) {
1037                 error = kvp_write_file(file, "DHCP", "", "1");
1038         } else{
1039                 error = kvp_write_file(file, "DHCP", "", "0");
1040         }
1041
1042         if (error) {
1043                 goto kvp_set_ip_info_error;
1044         }
1045
1046         free(mac_addr);
1047         fclose(file);
1048
1049         /*
1050          * Invoke the external script with the populated
1051          * configuration file.
1052          */
1053
1054         snprintf(cmd, sizeof(cmd), "%s %s",
1055             "sh /usr/libexec/hyperv/hv_set_ifconfig", if_file);
1056         system(cmd);
1057         return (0);
1058
1059 kvp_set_ip_info_error:
1060         KVP_LOG(LOG_ERR, "Failed to write config file\n");
1061         free(mac_addr);
1062         fclose(file);
1063         return (error);
1064 }
1065
1066
1067 static int
1068 kvp_get_domain_name(char *buffer, int length)
1069 {
1070         struct addrinfo hints, *info;
1071         int error = 0;
1072
1073         gethostname(buffer, length);
1074         memset(&hints, 0, sizeof(hints));
1075         hints.ai_family = AF_INET;    /* Get only ipv4 addrinfo. */
1076         hints.ai_socktype = SOCK_STREAM;
1077         hints.ai_flags = AI_CANONNAME;
1078
1079         error = getaddrinfo(buffer, NULL, &hints, &info);
1080         if (error != 0) {
1081                 strlcpy(buffer, "getaddrinfo failed\n", length);
1082                 return (error);
1083         }
1084         strlcpy(buffer, info->ai_canonname, length);
1085         freeaddrinfo(info);
1086         return (error);
1087 }
1088
1089
1090 static int
1091 kvp_op_getipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1092 {
1093         struct hv_kvp_ipaddr_value *ip_val;
1094         char *if_name;
1095
1096         assert(op_msg != NULL);
1097         KVP_LOG(LOG_DEBUG, "In kvp_op_getipinfo.\n");
1098
1099         ip_val = &op_msg->body.kvp_ip_val;
1100         op_msg->hdr.error = HV_KVP_S_OK;
1101
1102         if_name = kvp_mac_to_if_name((char *)ip_val->adapter_id);
1103
1104         if (if_name == NULL) {
1105                 /* No interface found with the mac address. */
1106                 op_msg->hdr.error = HV_KVP_E_FAIL;
1107                 goto kvp_op_getipinfo_done;
1108         }
1109
1110         op_msg->hdr.error = kvp_get_ip_info(0, if_name,
1111             HV_KVP_OP_GET_IP_INFO, ip_val, (MAX_IP_ADDR_SIZE * 2));
1112
1113         free(if_name);
1114
1115 kvp_op_getipinfo_done:
1116         return(op_msg->hdr.error);
1117 }
1118
1119
1120 static int
1121 kvp_op_setipinfo(struct hv_kvp_msg *op_msg, void *data __unused)
1122 {
1123         struct hv_kvp_ipaddr_value *ip_val;
1124         char *if_name;
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_KVP_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_KVP_GUID_NOTFOUND;
1137                 goto kvp_op_setipinfo_done;
1138         }
1139
1140         op_msg->hdr.error = kvp_set_ip_info(if_name, ip_val);
1141
1142 kvp_op_setipinfo_done:
1143         return(op_msg->hdr.error);
1144 }
1145
1146
1147 static int
1148 kvp_op_setgetdel(struct hv_kvp_msg *op_msg, void *data)
1149 {
1150         struct kvp_op_hdlr *op_hdlr = (struct kvp_op_hdlr *)data;
1151         int error = 0;
1152         int op_pool;
1153
1154         assert(op_msg != NULL);
1155         assert(op_hdlr != NULL);
1156
1157         op_pool = op_msg->hdr.kvp_hdr.pool;
1158         op_msg->hdr.error = HV_KVP_S_OK;
1159
1160         switch(op_hdlr->kvp_op_key) {
1161         case HV_KVP_OP_SET:
1162                 if (op_pool == HV_KVP_POOL_AUTO) {
1163                         /* Auto Pool is not writeable from host side. */
1164                         error = 1;
1165                         KVP_LOG(LOG_ERR, "Ilegal to write to pool %d from host\n",
1166                             op_pool);
1167                 } else {
1168                         error = kvp_key_add_or_modify(op_pool,
1169                             op_msg->body.kvp_set.data.key,
1170                             op_msg->body.kvp_set.data.key_size,
1171                             op_msg->body.kvp_set.data.msg_value.value,
1172                             op_msg->body.kvp_set.data.value_size);
1173                 }
1174                 break;
1175
1176         case HV_KVP_OP_GET:
1177                 error = kvp_get_value(op_pool,
1178                     op_msg->body.kvp_get.data.key,
1179                     op_msg->body.kvp_get.data.key_size,
1180                     op_msg->body.kvp_get.data.msg_value.value,
1181                     op_msg->body.kvp_get.data.value_size);
1182                 break;
1183
1184         case HV_KVP_OP_DELETE:
1185                 if (op_pool == HV_KVP_POOL_AUTO) {
1186                         /* Auto Pool is not writeable from host side. */
1187                         error = 1;
1188                         KVP_LOG(LOG_ERR, "Ilegal to change pool %d from host\n",
1189                             op_pool);
1190                 } else {
1191                         error = kvp_key_delete(op_pool,
1192                             op_msg->body.kvp_delete.key,
1193                             op_msg->body.kvp_delete.key_size);
1194                 }
1195                 break;
1196
1197         default:
1198                 break;
1199         }
1200
1201         if (error != 0)
1202                 op_msg->hdr.error = HV_KVP_S_CONT;
1203
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_KVP_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_KVP_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                 strcpy(key_value, lic_version);
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                 strcpy(key_value, os_build);
1269                 strcpy(key_name, "OSBuildNumber");
1270                 break;
1271
1272         case OSName:
1273                 strcpy(key_value, os_name);
1274                 strcpy(key_name, "OSName");
1275                 break;
1276
1277         case OSMajorVersion:
1278                 strcpy(key_value, os_major);
1279                 strcpy(key_name, "OSMajorVersion");
1280                 break;
1281
1282         case OSMinorVersion:
1283                 strcpy(key_value, os_minor);
1284                 strcpy(key_name, "OSMinorVersion");
1285                 break;
1286
1287         case OSVersion:
1288                 strcpy(key_value, os_build);
1289                 strcpy(key_name, "OSVersion");
1290                 break;
1291
1292         case ProcessorArchitecture:
1293                 strcpy(key_value, processor_arch);
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_KVP_S_CONT;
1303                 error = -1;
1304                 break;
1305         }
1306
1307 kvp_op_enumerate_done:
1308         return(error);
1309 }
1310
1311
1312 /*
1313  * Load handler, and call init routine if provided.
1314  */
1315 static int
1316 kvp_op_load(int key, void (*init)(void),
1317             int (*exec)(struct hv_kvp_msg *, void *))
1318 {
1319         int error = 0;
1320
1321         if (key < 0 || key >= HV_KVP_OP_COUNT) {
1322                 KVP_LOG(LOG_ERR, "Operation key out of supported range\n");
1323                 error = -1;
1324                 goto kvp_op_load_done;
1325         }
1326
1327         kvp_op_hdlrs[key].kvp_op_key = key;
1328         kvp_op_hdlrs[key].kvp_op_init = init;
1329         kvp_op_hdlrs[key].kvp_op_exec = exec;
1330
1331         if (kvp_op_hdlrs[key].kvp_op_init != NULL)
1332                 kvp_op_hdlrs[key].kvp_op_init();
1333
1334 kvp_op_load_done:
1335         return(error);
1336 }
1337
1338
1339 /*
1340  * Initialize the operation hanlders.
1341  */
1342 static int
1343 kvp_ops_init(void)
1344 {
1345         int i;
1346
1347         /* Set the initial values. */
1348         for (i = 0; i < HV_KVP_OP_COUNT; i++) {
1349                 kvp_op_hdlrs[i].kvp_op_key = -1;
1350                 kvp_op_hdlrs[i].kvp_op_init = NULL;
1351                 kvp_op_hdlrs[i].kvp_op_exec = NULL;
1352         }
1353
1354         return(kvp_op_load(HV_KVP_OP_GET, NULL, kvp_op_setgetdel) |
1355             kvp_op_load(HV_KVP_OP_SET, NULL, kvp_op_setgetdel) |
1356             kvp_op_load(HV_KVP_OP_DELETE, NULL, kvp_op_setgetdel) |
1357             kvp_op_load(HV_KVP_OP_ENUMERATE, kvp_get_os_info,
1358                 kvp_op_enumerate) |
1359             kvp_op_load(HV_KVP_OP_GET_IP_INFO, NULL, kvp_op_getipinfo) |
1360             kvp_op_load(HV_KVP_OP_SET_IP_INFO, NULL, kvp_op_setipinfo));
1361 }
1362
1363
1364 int
1365 main(int argc, char *argv[])
1366 {
1367         struct hv_kvp_msg *hv_kvp_dev_buf;
1368         struct hv_kvp_msg *hv_msg;
1369         struct pollfd hv_kvp_poll_fd[1];
1370         int op, pool;
1371         int hv_kvp_dev_fd, error, len, r;
1372         int ch;
1373
1374         while ((ch = getopt(argc, argv, "dn")) != -1) {
1375                 switch (ch) {
1376                 case 'n':
1377                         /* Run as regular process for debugging purpose. */
1378                         is_daemon = 0;
1379                         break;
1380                 case 'd':
1381                         /* Generate debugging output */
1382                         is_debugging = 1;
1383                         break;
1384                 default:
1385                         break;
1386                 }
1387         }
1388
1389         openlog("HV_KVP", 0, LOG_USER);
1390
1391         /* Become daemon first. */
1392         if (is_daemon == 1)
1393                 daemon(1, 0);
1394         else
1395                 KVP_LOG(LOG_DEBUG, "Run as regular process.\n");
1396
1397         KVP_LOG(LOG_INFO, "HV_KVP starting; pid is: %d\n", getpid());
1398
1399         /* Communication buffer hv_kvp_dev_buf */
1400         hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf));
1401         /* Buffer for daemon internal use */
1402         hv_msg = malloc(sizeof(*hv_msg));
1403
1404         /* Memory allocation failed */
1405         if (hv_kvp_dev_buf == NULL || hv_msg == NULL) {
1406                 KVP_LOG(LOG_ERR, "Failed to allocate memory for hv buffer\n");
1407                 exit(EXIT_FAILURE);
1408         }
1409
1410         /* Initialize op handlers */
1411         if (kvp_ops_init() != 0) {
1412                 KVP_LOG(LOG_ERR, "Failed to initizlize operation handlers\n");
1413                 exit(EXIT_FAILURE);
1414         }
1415
1416         if (kvp_file_init()) {
1417                 KVP_LOG(LOG_ERR, "Failed to initialize the pools\n");
1418                 exit(EXIT_FAILURE);
1419         }
1420
1421         /* Open the Character Device */
1422         hv_kvp_dev_fd = open("/dev/hv_kvp_dev", O_RDWR);
1423
1424         if (hv_kvp_dev_fd < 0) {
1425                 KVP_LOG(LOG_ERR, "open /dev/hv_kvp_dev failed; error: %d %s\n",
1426                     errno, strerror(errno));
1427                 exit(EXIT_FAILURE);
1428         }
1429
1430         /* Initialize the struct for polling the char device */
1431         hv_kvp_poll_fd[0].fd = hv_kvp_dev_fd;
1432         hv_kvp_poll_fd[0].events = (POLLIN | POLLRDNORM);
1433
1434         /* Register the daemon to the KVP driver */
1435         memset(hv_kvp_dev_buf, 0, sizeof(*hv_kvp_dev_buf));
1436         hv_kvp_dev_buf->hdr.kvp_hdr.operation = HV_KVP_OP_REGISTER;
1437         len = write(hv_kvp_dev_fd, hv_kvp_dev_buf, sizeof(*hv_kvp_dev_buf));
1438
1439
1440         for (;;) {
1441                 r = poll (hv_kvp_poll_fd, 1, 100);
1442
1443                 KVP_LOG(LOG_DEBUG, "poll returned r = %d, revent = 0x%x\n",
1444                     r, hv_kvp_poll_fd[0].revents);
1445
1446                 if (r == 0 || (r < 0 && errno == EAGAIN) ||
1447                     (r < 0 && errno == EINTR)) {
1448                         /* Nothing to read */
1449                         continue;
1450                 }
1451
1452                 if (r < 0) {
1453                         /*
1454                          * For pread return failure other than EAGAIN,
1455                          * we want to exit.
1456                          */
1457                         KVP_LOG(LOG_ERR, "Poll failed.\n");
1458                         perror("poll");
1459                         exit(EIO);
1460                 }
1461
1462                 /* Read from character device */
1463                 len = pread(hv_kvp_dev_fd, hv_kvp_dev_buf,
1464                     sizeof(*hv_kvp_dev_buf), 0);
1465
1466                 if (len < 0) {
1467                         KVP_LOG(LOG_ERR, "Read failed.\n");
1468                         perror("pread");
1469                         exit(EIO);
1470                 }
1471
1472                 if (len != sizeof(struct hv_kvp_msg)) {
1473                         KVP_LOG(LOG_ERR, "read len is: %d\n", len);
1474                         continue;
1475                 }
1476
1477                 /* Copy hv_kvp_dev_buf to hv_msg */
1478                 memcpy(hv_msg, hv_kvp_dev_buf, sizeof(*hv_msg));
1479
1480                 /*
1481                  * We will use the KVP header information to pass back
1482                  * the error from this daemon. So, first save the op
1483                  * and pool info to local variables.
1484                  */
1485
1486                 op = hv_msg->hdr.kvp_hdr.operation;
1487                 pool = hv_msg->hdr.kvp_hdr.pool;
1488
1489                 if (op < 0 || op >= HV_KVP_OP_COUNT ||
1490                     kvp_op_hdlrs[op].kvp_op_exec == NULL) {
1491                         KVP_LOG(LOG_WARNING,
1492                             "Unsupported operation OP = %d\n", op);
1493                         hv_msg->hdr.error = HV_ERROR_NOT_SUPPORTED;
1494                 } else {
1495                         /*
1496                          * Call the operateion handler's execution routine.
1497                          */
1498                         error = kvp_op_hdlrs[op].kvp_op_exec(hv_msg,
1499                             (void *)&kvp_op_hdlrs[op]);
1500                         if (error != 0 && hv_msg->hdr.error != HV_KVP_S_CONT)
1501                                 KVP_LOG(LOG_WARNING,
1502                                     "Operation failed OP = %d, error = 0x%x\n",
1503                                     op, error);
1504                 }
1505
1506                 /*
1507                  * Send the value back to the kernel. The response is
1508                  * already in the receive buffer.
1509                  */
1510 hv_kvp_done:
1511                 len = pwrite(hv_kvp_dev_fd, hv_msg, sizeof(*hv_kvp_dev_buf), 0);
1512
1513                 if (len != sizeof(struct hv_kvp_msg)) {
1514                         KVP_LOG(LOG_ERR, "write len is: %d\n", len);
1515                         goto hv_kvp_done;
1516                 }
1517         }
1518 }