]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - sys/dev/hyperv/utilities/hv_kvp.c
o Fix OpenSSH xauth(1) command injection. [SA-16:14]
[FreeBSD/releng/10.1.git] / sys / dev / hyperv / utilities / hv_kvp.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 /*
28  *      Author: Sainath Varanasi.
29  *      Date:   4/2012
30  *      Email:  bsdic@microsoft.com
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/conf.h>
39 #include <sys/uio.h>
40 #include <sys/bus.h>
41 #include <sys/malloc.h>
42 #include <sys/mbuf.h>
43 #include <sys/module.h>
44 #include <sys/reboot.h>
45 #include <sys/lock.h>
46 #include <sys/taskqueue.h>
47 #include <sys/selinfo.h>
48 #include <sys/sysctl.h>
49 #include <sys/poll.h>
50 #include <sys/proc.h>
51 #include <sys/kthread.h>
52 #include <sys/syscallsubr.h>
53 #include <sys/sysproto.h>
54 #include <sys/un.h>
55 #include <sys/endian.h>
56 #include <sys/_null.h>
57 #include <sys/signal.h>
58 #include <sys/syslog.h>
59 #include <sys/mutex.h>
60 #include <net/if_arp.h>
61
62 #include <dev/hyperv/include/hyperv.h>
63 #include <dev/hyperv/netvsc/hv_net_vsc.h>
64
65 #include "unicode.h"
66 #include "hv_kvp.h"
67
68 /* hv_kvp defines */
69 #define BUFFERSIZE      sizeof(struct hv_kvp_msg)
70 #define KVP_SUCCESS     0
71 #define KVP_ERROR       1
72 #define kvp_hdr         hdr.kvp_hdr
73
74 /* hv_kvp debug control */
75 static int hv_kvp_log = 0;
76 SYSCTL_INT(_dev, OID_AUTO, hv_kvp_log, CTLFLAG_RW, &hv_kvp_log, 0,
77         "hv_kvp log");
78
79 #define hv_kvp_log_error(...)   do {                            \
80         if (hv_kvp_log > 0)                             \
81                 log(LOG_ERR, "hv_kvp: " __VA_ARGS__);   \
82 } while (0)
83
84 #define hv_kvp_log_info(...) do {                               \
85         if (hv_kvp_log > 1)                             \
86                 log(LOG_INFO, "hv_kvp: " __VA_ARGS__);          \
87 } while (0)
88
89 /* character device prototypes */
90 static d_open_t         hv_kvp_dev_open;
91 static d_close_t        hv_kvp_dev_close;
92 static d_read_t         hv_kvp_dev_daemon_read;
93 static d_write_t        hv_kvp_dev_daemon_write;
94 static d_poll_t         hv_kvp_dev_daemon_poll;
95
96 /* hv_kvp prototypes */
97 static int      hv_kvp_req_in_progress(void);
98 static void     hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *);
99 static void     hv_kvp_send_msg_to_daemon(void);
100 static void     hv_kvp_process_request(void *context);
101
102 /* hv_kvp character device structure */
103 static struct cdevsw hv_kvp_cdevsw =
104 {
105         .d_version      = D_VERSION,
106         .d_open         = hv_kvp_dev_open,
107         .d_close        = hv_kvp_dev_close,
108         .d_read         = hv_kvp_dev_daemon_read,
109         .d_write        = hv_kvp_dev_daemon_write,
110         .d_poll         = hv_kvp_dev_daemon_poll,
111         .d_name         = "hv_kvp_dev",
112 };
113 static struct cdev *hv_kvp_dev;
114 static struct hv_kvp_msg *hv_kvp_dev_buf;
115 struct proc *daemon_task;
116
117 static struct selinfo hv_kvp_selinfo;
118
119 /*
120  * Global state to track and synchronize multiple
121  * KVP transaction requests from the host.
122  */
123 static struct {
124
125         /* Pre-allocated work item for queue */
126         hv_work_item            work_item;      
127
128         /* Unless specified the pending mutex should be 
129          * used to alter the values of the following paramters:
130          * 1. req_in_progress
131          * 2. req_timed_out
132          * 3. pending_reqs.
133          */
134         struct mtx              pending_mutex;    
135         
136         /* To track if transaction is active or not */
137         boolean_t               req_in_progress;    
138         /* Tracks if daemon did not reply back in time */
139         boolean_t               req_timed_out;    
140         /* Tracks if daemon is serving a request currently */
141         boolean_t               daemon_busy;
142         /* Count of KVP requests from Hyper-V. */
143         uint64_t                pending_reqs;       
144         
145         
146         /* Length of host message */
147         uint32_t                host_msg_len;       
148
149         /* Pointer to channel */
150         hv_vmbus_channel        *channelp;          
151
152         /* Host message id */
153         uint64_t                host_msg_id;       
154         
155         /* Current kvp message from the host */
156         struct hv_kvp_msg       *host_kvp_msg;      
157         
158          /* Current kvp message for daemon */
159         struct hv_kvp_msg       daemon_kvp_msg;    
160         
161         /* Rcv buffer for communicating with the host*/
162         uint8_t                 *rcv_buf;           
163         
164         /* Device semaphore to control communication */
165         struct sema             dev_sema;          
166         
167         /* Indicates if daemon registered with driver */
168         boolean_t               register_done;      
169         
170         /* Character device status */
171         boolean_t               dev_accessed;       
172 } kvp_globals;
173
174 /* global vars */
175 MALLOC_DECLARE(M_HV_KVP_DEV_BUF);
176 MALLOC_DEFINE(M_HV_KVP_DEV_BUF, "hv_kvp_dev buffer", "buffer for hv_kvp_dev module");
177
178 /*
179  * hv_kvp low level functions
180  */
181
182 /*
183  * Check if kvp transaction is in progres
184  */
185 static int
186 hv_kvp_req_in_progress(void)
187 {
188
189         return (kvp_globals.req_in_progress);
190 }
191
192
193 /*
194  * This routine is called whenever a message is received from the host
195  */
196 static void
197 hv_kvp_transaction_init(uint32_t rcv_len, hv_vmbus_channel *rcv_channel,
198                         uint64_t request_id, uint8_t *rcv_buf)
199 {
200         
201         /* Store all the relevant message details in the global structure */
202         /* Do not need to use mutex for req_in_progress here */
203         kvp_globals.req_in_progress = true;
204         kvp_globals.host_msg_len = rcv_len;
205         kvp_globals.channelp = rcv_channel;
206         kvp_globals.host_msg_id = request_id;
207         kvp_globals.rcv_buf = rcv_buf;
208         kvp_globals.host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[
209                 sizeof(struct hv_vmbus_pipe_hdr) +
210                 sizeof(struct hv_vmbus_icmsg_hdr)];
211 }
212
213
214 /*
215  * hv_kvp - version neogtiation function
216  */
217 static void
218 hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp,
219                          struct hv_vmbus_icmsg_negotiate *negop,
220                          uint8_t *buf)
221 {
222         int icframe_vercnt;
223         int icmsg_vercnt;
224
225         icmsghdrp->icmsgsize = 0x10;
226
227         negop = (struct hv_vmbus_icmsg_negotiate *)&buf[
228                 sizeof(struct hv_vmbus_pipe_hdr) +
229                 sizeof(struct hv_vmbus_icmsg_hdr)];
230         icframe_vercnt = negop->icframe_vercnt;
231         icmsg_vercnt = negop->icmsg_vercnt;
232
233         /*
234          * Select the framework version number we will support
235          */
236         if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) {
237                 icframe_vercnt = 3;
238                 if (icmsg_vercnt >= 2)
239                         icmsg_vercnt = 4;
240                 else
241                         icmsg_vercnt = 3;
242         } else {
243                 icframe_vercnt = 1;
244                 icmsg_vercnt = 1;
245         }
246
247         negop->icframe_vercnt = 1;
248         negop->icmsg_vercnt = 1;
249         negop->icversion_data[0].major = icframe_vercnt;
250         negop->icversion_data[0].minor = 0;
251         negop->icversion_data[1].major = icmsg_vercnt;
252         negop->icversion_data[1].minor = 0;
253 }
254
255
256 /*
257  * Convert ip related info in umsg from utf8 to utf16 and store in hmsg
258  */
259 static int
260 hv_kvp_convert_utf8_ipinfo_to_utf16(struct hv_kvp_msg *umsg, 
261                                     struct hv_kvp_ip_msg *host_ip_msg)
262 {
263         int err_ip, err_subnet, err_gway, err_dns, err_adap;
264         int UNUSED_FLAG = 1;
265                 
266         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.ip_addr,
267             MAX_IP_ADDR_SIZE,
268             (char *)umsg->body.kvp_ip_val.ip_addr,
269             strlen((char *)umsg->body.kvp_ip_val.ip_addr),
270             UNUSED_FLAG,
271             &err_ip);
272         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.sub_net,
273             MAX_IP_ADDR_SIZE,
274             (char *)umsg->body.kvp_ip_val.sub_net,
275             strlen((char *)umsg->body.kvp_ip_val.sub_net),
276             UNUSED_FLAG,
277             &err_subnet);
278         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.gate_way,
279             MAX_GATEWAY_SIZE,
280             (char *)umsg->body.kvp_ip_val.gate_way,
281             strlen((char *)umsg->body.kvp_ip_val.gate_way),
282             UNUSED_FLAG,
283             &err_gway);
284         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.dns_addr,
285             MAX_IP_ADDR_SIZE,
286             (char *)umsg->body.kvp_ip_val.dns_addr,
287             strlen((char *)umsg->body.kvp_ip_val.dns_addr),
288             UNUSED_FLAG,
289             &err_dns);
290         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
291             MAX_IP_ADDR_SIZE,
292             (char *)umsg->body.kvp_ip_val.adapter_id,
293             strlen((char *)umsg->body.kvp_ip_val.adapter_id),
294             UNUSED_FLAG,
295             &err_adap);
296         
297         host_ip_msg->kvp_ip_val.dhcp_enabled = umsg->body.kvp_ip_val.dhcp_enabled;
298         host_ip_msg->kvp_ip_val.addr_family = umsg->body.kvp_ip_val.addr_family;
299
300         return (err_ip | err_subnet | err_gway | err_dns | err_adap);
301 }
302
303
304 /*
305  * Convert ip related info in hmsg from utf16 to utf8 and store in umsg
306  */
307 static int
308 hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
309                                     struct hv_kvp_msg *umsg)
310 {
311         int err_ip, err_subnet, err_gway, err_dns, err_adap;
312         int UNUSED_FLAG = 1;
313         int guid_index;
314         struct hv_device *hv_dev;       /* GUID Data Structure */
315         hn_softc_t *sc;                 /* hn softc structure  */
316         char if_name[4];
317         unsigned char guid_instance[40];
318         char *guid_data = NULL;
319         char buf[39];
320
321         struct guid_extract {
322                 char    a1[2];
323                 char    a2[2];
324                 char    a3[2];
325                 char    a4[2];
326                 char    b1[2];
327                 char    b2[2];
328                 char    c1[2];
329                 char    c2[2];
330                 char    d[4];
331                 char    e[12];
332         };
333
334         struct guid_extract *id;
335         device_t *devs;
336         int devcnt;
337
338         /* IP Address */
339         utf16_to_utf8((char *)umsg->body.kvp_ip_val.ip_addr,
340             MAX_IP_ADDR_SIZE,
341             (uint16_t *)host_ip_msg->kvp_ip_val.ip_addr,
342             MAX_IP_ADDR_SIZE,
343             UNUSED_FLAG,
344             &err_ip);
345
346         /* Adapter ID : GUID */
347         utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id,
348             MAX_ADAPTER_ID_SIZE,
349             (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
350             MAX_ADAPTER_ID_SIZE,
351             UNUSED_FLAG,
352             &err_adap);
353
354         if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) {
355                 for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) {
356                         sc = device_get_softc(devs[devcnt]);
357
358                         /* Trying to find GUID of Network Device */
359                         hv_dev = sc->hn_dev_obj;
360
361                         for (guid_index = 0; guid_index < 16; guid_index++) {
362                                 sprintf(&guid_instance[guid_index * 2], "%02x",
363                                     hv_dev->device_id.data[guid_index]);
364                         }
365
366                         guid_data = (char *)guid_instance;
367                         id = (struct guid_extract *)guid_data;
368                         snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}",
369                             id->a4, id->a3, id->a2, id->a1,
370                             id->b2, id->b1, id->c2, id->c1, id->d, id->e);
371                         guid_data = NULL;
372                         sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt]));
373
374                         if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) {
375                                 strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name);
376                                 break;
377                         }
378                 }
379                 free(devs, M_TEMP);
380         }
381
382         /* Address Family , DHCP , SUBNET, Gateway, DNS */
383         umsg->kvp_hdr.operation = host_ip_msg->operation;
384         umsg->body.kvp_ip_val.addr_family = host_ip_msg->kvp_ip_val.addr_family;
385         umsg->body.kvp_ip_val.dhcp_enabled = host_ip_msg->kvp_ip_val.dhcp_enabled;
386         utf16_to_utf8((char *)umsg->body.kvp_ip_val.sub_net, MAX_IP_ADDR_SIZE,
387             (uint16_t *)host_ip_msg->kvp_ip_val.sub_net,
388             MAX_IP_ADDR_SIZE,
389             UNUSED_FLAG,
390             &err_subnet);
391         
392         utf16_to_utf8((char *)umsg->body.kvp_ip_val.gate_way, MAX_GATEWAY_SIZE,
393             (uint16_t *)host_ip_msg->kvp_ip_val.gate_way,
394             MAX_GATEWAY_SIZE,
395             UNUSED_FLAG,
396             &err_gway);
397
398         utf16_to_utf8((char *)umsg->body.kvp_ip_val.dns_addr, MAX_IP_ADDR_SIZE,
399             (uint16_t *)host_ip_msg->kvp_ip_val.dns_addr,
400             MAX_IP_ADDR_SIZE,
401             UNUSED_FLAG,
402             &err_dns);
403
404         return (err_ip | err_subnet | err_gway | err_dns | err_adap);
405 }
406
407
408 /*
409  * Prepare a user kvp msg based on host kvp msg (utf16 to utf8)
410  * Ensure utf16_utf8 takes care of the additional string terminating char!!
411  */
412 static void
413 hv_kvp_convert_hostmsg_to_usermsg(void)
414 {
415         int utf_err = 0;
416         uint32_t value_type;
417         struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)
418                 kvp_globals.host_kvp_msg;
419
420         struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg;
421         struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg;
422
423         memset(umsg, 0, sizeof(struct hv_kvp_msg));
424
425         umsg->kvp_hdr.operation = hmsg->kvp_hdr.operation;
426         umsg->kvp_hdr.pool = hmsg->kvp_hdr.pool;
427
428         switch (umsg->kvp_hdr.operation) {
429         case HV_KVP_OP_SET_IP_INFO:
430                 hv_kvp_convert_utf16_ipinfo_to_utf8(host_ip_msg, umsg);
431                 break;
432
433         case HV_KVP_OP_GET_IP_INFO:
434                 utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id,
435                     MAX_ADAPTER_ID_SIZE,
436                     (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
437                     MAX_ADAPTER_ID_SIZE, 1, &utf_err);
438
439                 umsg->body.kvp_ip_val.addr_family =
440                     host_ip_msg->kvp_ip_val.addr_family;
441                 break;
442
443         case HV_KVP_OP_SET:
444                 value_type = hmsg->body.kvp_set.data.value_type;
445
446                 switch (value_type) {
447                 case HV_REG_SZ:
448                         umsg->body.kvp_set.data.value_size =
449                             utf16_to_utf8(
450                                 (char *)umsg->body.kvp_set.data.msg_value.value,
451                                 HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1,
452                                 (uint16_t *)hmsg->body.kvp_set.data.msg_value.value,
453                                 hmsg->body.kvp_set.data.value_size,
454                                 1, &utf_err);
455                         /* utf8 encoding */
456                         umsg->body.kvp_set.data.value_size =
457                             umsg->body.kvp_set.data.value_size / 2;
458                         break;
459
460                 case HV_REG_U32:
461                         umsg->body.kvp_set.data.value_size =
462                             sprintf(umsg->body.kvp_set.data.msg_value.value, "%d",
463                                 hmsg->body.kvp_set.data.msg_value.value_u32) + 1;
464                         break;
465
466                 case HV_REG_U64:
467                         umsg->body.kvp_set.data.value_size =
468                             sprintf(umsg->body.kvp_set.data.msg_value.value, "%llu",
469                                 (unsigned long long)
470                                 hmsg->body.kvp_set.data.msg_value.value_u64) + 1;
471                         break;
472                 }
473
474                 umsg->body.kvp_set.data.key_size =
475                     utf16_to_utf8(
476                         umsg->body.kvp_set.data.key,
477                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
478                         (uint16_t *)hmsg->body.kvp_set.data.key,
479                         hmsg->body.kvp_set.data.key_size,
480                         1, &utf_err);
481
482                 /* utf8 encoding */
483                 umsg->body.kvp_set.data.key_size =
484                     umsg->body.kvp_set.data.key_size / 2;
485                 break;
486
487         case HV_KVP_OP_GET:
488                 umsg->body.kvp_get.data.key_size =
489                     utf16_to_utf8(umsg->body.kvp_get.data.key,
490                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
491                         (uint16_t *)hmsg->body.kvp_get.data.key,
492                         hmsg->body.kvp_get.data.key_size,
493                         1, &utf_err);
494                 /* utf8 encoding */
495                 umsg->body.kvp_get.data.key_size =
496                     umsg->body.kvp_get.data.key_size / 2;
497                 break;
498
499         case HV_KVP_OP_DELETE:
500                 umsg->body.kvp_delete.key_size =
501                     utf16_to_utf8(umsg->body.kvp_delete.key,
502                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
503                         (uint16_t *)hmsg->body.kvp_delete.key,
504                         hmsg->body.kvp_delete.key_size,
505                         1, &utf_err);
506                 /* utf8 encoding */
507                 umsg->body.kvp_delete.key_size =
508                     umsg->body.kvp_delete.key_size / 2;
509                 break;
510
511         case HV_KVP_OP_ENUMERATE:
512                 umsg->body.kvp_enum_data.index =
513                     hmsg->body.kvp_enum_data.index;
514                 break;
515
516         default:
517                 hv_kvp_log_info("%s: daemon_kvp_msg: Invalid operation : %d\n",
518                     __func__, umsg->kvp_hdr.operation);
519         }
520 }
521
522
523 /*
524  * Prepare a host kvp msg based on user kvp msg (utf8 to utf16)
525  */
526 static int
527 hv_kvp_convert_usermsg_to_hostmsg(void)
528 {
529         int hkey_len = 0, hvalue_len = 0, utf_err = 0;
530         struct hv_kvp_exchg_msg_value *host_exchg_data;
531         char *key_name, *value;
532
533         struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg;
534         struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg;
535         struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)hmsg;
536
537         switch (hmsg->kvp_hdr.operation) {
538         case HV_KVP_OP_GET_IP_INFO:
539                 return (hv_kvp_convert_utf8_ipinfo_to_utf16(umsg, host_ip_msg));
540
541         case HV_KVP_OP_SET_IP_INFO:
542         case HV_KVP_OP_SET:
543         case HV_KVP_OP_DELETE:
544                 return (KVP_SUCCESS);
545
546         case HV_KVP_OP_ENUMERATE:
547                 host_exchg_data = &hmsg->body.kvp_enum_data.data;
548                 key_name = umsg->body.kvp_enum_data.data.key;
549                 hkey_len = utf8_to_utf16((uint16_t *)host_exchg_data->key,
550                                 ((HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2),
551                                 key_name, strlen(key_name),
552                                 1, &utf_err);
553                 /* utf16 encoding */
554                 host_exchg_data->key_size = 2 * (hkey_len + 1);
555                 value = umsg->body.kvp_enum_data.data.msg_value.value;
556                 hvalue_len = utf8_to_utf16(
557                                 (uint16_t *)host_exchg_data->msg_value.value,
558                                 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2),
559                                 value, strlen(value),
560                                 1, &utf_err);
561                 host_exchg_data->value_size = 2 * (hvalue_len + 1);
562                 host_exchg_data->value_type = HV_REG_SZ;
563
564                 if ((hkey_len < 0) || (hvalue_len < 0))
565                         return (HV_KVP_E_FAIL);
566                         
567                 return (KVP_SUCCESS);
568
569         case HV_KVP_OP_GET:
570                 host_exchg_data = &hmsg->body.kvp_get.data;
571                 value = umsg->body.kvp_get.data.msg_value.value;
572                 hvalue_len = utf8_to_utf16(
573                                 (uint16_t *)host_exchg_data->msg_value.value,
574                                 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2),
575                                 value, strlen(value),
576                                 1, &utf_err);
577                 /* Convert value size to uft16 */
578                 host_exchg_data->value_size = 2 * (hvalue_len + 1);
579                 /* Use values by string */
580                 host_exchg_data->value_type = HV_REG_SZ;
581
582                 if ((hkey_len < 0) || (hvalue_len < 0)) 
583                         return (HV_KVP_E_FAIL);
584                         
585                 return (KVP_SUCCESS);
586
587         default:
588                 return (HV_KVP_E_FAIL);
589         }
590 }
591
592
593 /*
594  * Send the response back to the host.
595  */
596 static void
597 hv_kvp_respond_host(int error)
598 {
599         struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp;
600
601         hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *)
602             &kvp_globals.rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)];
603
604         if (error)
605                 error = HV_KVP_E_FAIL;
606
607         hv_icmsg_hdrp->status = error;
608         hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE;
609         
610         error = hv_vmbus_channel_send_packet(kvp_globals.channelp,
611                         kvp_globals.rcv_buf,
612                         kvp_globals.host_msg_len, kvp_globals.host_msg_id,
613                         HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0);
614
615         if (error)
616                 hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n",
617                         __func__, error);
618 }
619
620
621 /*
622  * This is the main kvp kernel process that interacts with both user daemon
623  * and the host
624  */
625 static void
626 hv_kvp_send_msg_to_daemon(void)
627 {
628         /* Prepare kvp_msg to be sent to user */
629         hv_kvp_convert_hostmsg_to_usermsg();
630
631         /* Send the msg to user via function deamon_read - setting sema */
632         sema_post(&kvp_globals.dev_sema);
633
634         /* We should wake up the daemon, in case it's doing poll() */
635         selwakeup(&hv_kvp_selinfo);
636 }
637
638
639 /*
640  * Function to read the kvp request buffer from host
641  * and interact with daemon
642  */
643 static void
644 hv_kvp_process_request(void *context)
645 {
646         uint8_t *kvp_buf;
647         hv_vmbus_channel *channel = context;
648         uint32_t recvlen = 0;
649         uint64_t requestid;
650         struct hv_vmbus_icmsg_hdr *icmsghdrp;
651         int ret = 0;
652         uint64_t pending_cnt = 1;
653         
654         hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
655         kvp_buf = receive_buffer[HV_KVP];
656         ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
657                 &recvlen, &requestid);
658
659         /*
660          * We start counting only after the daemon registers
661          * and therefore there could be requests pending in 
662          * the VMBus that are not reflected in pending_cnt.
663          * Therefore we continue reading as long as either of
664          * the below conditions is true.
665          */
666
667         while ((pending_cnt>0) || ((ret == 0) && (recvlen > 0))) {
668
669                 if ((ret == 0) && (recvlen>0)) {
670                         
671                         icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
672                                         &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
673         
674                         hv_kvp_transaction_init(recvlen, channel, requestid, kvp_buf);
675                         if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
676                                 hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf);
677                                 hv_kvp_respond_host(ret);
678                                         
679                                 /*
680                                  * It is ok to not acquire the mutex before setting 
681                                  * req_in_progress here because negotiation is the
682                                  * first thing that happens and hence there is no
683                                  * chance of a race condition.
684                                  */
685                                 
686                                 kvp_globals.req_in_progress = false;
687                                 hv_kvp_log_info("%s :version negotiated\n", __func__);
688
689                         } else {
690                                 if (!kvp_globals.daemon_busy) {
691
692                                         hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
693                                         mtx_lock(&kvp_globals.pending_mutex);
694                                         kvp_globals.req_timed_out = false;
695                                         kvp_globals.daemon_busy = true;
696                                         mtx_unlock(&kvp_globals.pending_mutex);
697
698                                         hv_kvp_send_msg_to_daemon();
699                                         hv_kvp_log_info("%s: waiting for daemon\n", __func__);
700                                 }
701                                 
702                                 /* Wait 5 seconds for daemon to respond back */
703                                 tsleep(&kvp_globals, 0, "kvpworkitem", 5 * hz);
704                                 hv_kvp_log_info("%s: came out of wait\n", __func__);
705                         }
706                 }
707
708                 mtx_lock(&kvp_globals.pending_mutex);
709                 
710                 /* Notice that once req_timed_out is set to true
711                  * it will remain true until the next request is
712                  * sent to the daemon. The response from daemon
713                  * is forwarded to host only when this flag is 
714                  * false. 
715                  */
716                 kvp_globals.req_timed_out = true;
717
718                 /*
719                  * Cancel request if so need be.
720                  */
721                 if (hv_kvp_req_in_progress()) {
722                         hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
723                         hv_kvp_respond_host(HV_KVP_E_FAIL);
724                         kvp_globals.req_in_progress = false;    
725                 }
726         
727                 /*
728                 * Decrement pending request count and
729                 */
730                 if (kvp_globals.pending_reqs>0) {
731                         kvp_globals.pending_reqs = kvp_globals.pending_reqs - 1;
732                 }
733                 pending_cnt = kvp_globals.pending_reqs;
734                 
735                 mtx_unlock(&kvp_globals.pending_mutex);
736
737                 /*
738                  * Try reading next buffer
739                  */
740                 recvlen = 0;
741                 ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE,
742                         &recvlen, &requestid);
743                 hv_kvp_log_info("%s: read: context %p, pending_cnt %ju ret =%d, recvlen=%d\n",
744                         __func__, context, pending_cnt, ret, recvlen);
745         } 
746 }
747
748
749 /*
750  * Callback routine that gets called whenever there is a message from host
751  */
752 void
753 hv_kvp_callback(void *context)
754 {
755         uint64_t pending_cnt = 0;
756
757         if (kvp_globals.register_done == false) {
758                 
759                 kvp_globals.channelp = context;
760         } else {
761                 
762                 mtx_lock(&kvp_globals.pending_mutex);
763                 kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1;
764                 pending_cnt = kvp_globals.pending_reqs;
765                 mtx_unlock(&kvp_globals.pending_mutex);
766                 if (pending_cnt == 1) {
767                         hv_kvp_log_info("%s: Queuing work item\n", __func__);
768                         hv_queue_work_item(
769                                         service_table[HV_KVP].work_queue,
770                                         hv_kvp_process_request,
771                                         context
772                                         );
773                 }
774         }       
775 }
776
777
778 /*
779  * This function is called by the hv_kvp_init -
780  * creates character device hv_kvp_dev 
781  * allocates memory to hv_kvp_dev_buf
782  *
783  */
784 static int
785 hv_kvp_dev_init(void)
786 {
787         int error = 0;
788
789         /* initialize semaphore */
790         sema_init(&kvp_globals.dev_sema, 0, "hv_kvp device semaphore");
791         /* create character device */
792         error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
793                         &hv_kvp_dev,
794                         &hv_kvp_cdevsw,
795                         0,
796                         UID_ROOT,
797                         GID_WHEEL,
798                         0640,
799                         "hv_kvp_dev");
800                                            
801         if (error != 0)
802                 return (error);
803
804         /*
805          * Malloc with M_WAITOK flag will never fail.
806          */
807         hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_HV_KVP_DEV_BUF, M_WAITOK |
808                                 M_ZERO);
809
810         return (0);
811 }
812
813
814 /*
815  * This function is called by the hv_kvp_deinit -
816  * destroy character device
817  */
818 static void
819 hv_kvp_dev_destroy(void)
820 {
821
822         if (daemon_task != NULL) {
823                 PROC_LOCK(daemon_task);
824                 kern_psignal(daemon_task, SIGKILL);
825                 PROC_UNLOCK(daemon_task);
826         }
827         
828         destroy_dev(hv_kvp_dev);
829         free(hv_kvp_dev_buf, M_HV_KVP_DEV_BUF);
830         return;
831 }
832
833
834 static int
835 hv_kvp_dev_open(struct cdev *dev, int oflags, int devtype,
836                                 struct thread *td)
837 {
838         
839         hv_kvp_log_info("%s: Opened device \"hv_kvp_device\" successfully.\n", __func__);
840         if (kvp_globals.dev_accessed)
841                 return (-EBUSY);
842         
843         daemon_task = curproc;
844         kvp_globals.dev_accessed = true;
845         kvp_globals.daemon_busy = false;
846         return (0);
847 }
848
849
850 static int
851 hv_kvp_dev_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,
852                                  struct thread *td __unused)
853 {
854
855         hv_kvp_log_info("%s: Closing device \"hv_kvp_device\".\n", __func__);
856         kvp_globals.dev_accessed = false;
857         kvp_globals.register_done = false;
858         return (0);
859 }
860
861
862 /*
863  * hv_kvp_daemon read invokes this function
864  * acts as a send to daemon
865  */
866 static int
867 hv_kvp_dev_daemon_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
868 {
869         size_t amt;
870         int error = 0;
871
872         /* Check hv_kvp daemon registration status*/
873         if (!kvp_globals.register_done)
874                 return (KVP_ERROR);
875
876         sema_wait(&kvp_globals.dev_sema);
877
878         memcpy(hv_kvp_dev_buf, &kvp_globals.daemon_kvp_msg, sizeof(struct hv_kvp_msg));
879
880         amt = MIN(uio->uio_resid, uio->uio_offset >= BUFFERSIZE + 1 ? 0 :
881                 BUFFERSIZE + 1 - uio->uio_offset);
882
883         if ((error = uiomove(hv_kvp_dev_buf, amt, uio)) != 0)
884                 hv_kvp_log_info("%s: hv_kvp uiomove read failed!\n", __func__);
885
886         return (error);
887 }
888
889
890 /*
891  * hv_kvp_daemon write invokes this function
892  * acts as a recieve from daemon
893  */
894 static int
895 hv_kvp_dev_daemon_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused)
896 {
897         size_t amt;
898         int error = 0;
899
900         uio->uio_offset = 0;
901
902         amt = MIN(uio->uio_resid, BUFFERSIZE);
903         error = uiomove(hv_kvp_dev_buf, amt, uio);
904
905         if (error != 0)
906                 return (error);
907
908         memcpy(&kvp_globals.daemon_kvp_msg, hv_kvp_dev_buf, sizeof(struct hv_kvp_msg));
909
910         if (kvp_globals.register_done == false) {
911                 if (kvp_globals.daemon_kvp_msg.kvp_hdr.operation == HV_KVP_OP_REGISTER) {
912
913                         kvp_globals.register_done = true;
914                         if (kvp_globals.channelp) {
915                         
916                                 hv_kvp_callback(kvp_globals.channelp);
917                         }
918                 }
919                 else {
920                         hv_kvp_log_info("%s, KVP Registration Failed\n", __func__);
921                         return (KVP_ERROR);
922                 }
923         } else {
924
925                 mtx_lock(&kvp_globals.pending_mutex);
926
927                 if(!kvp_globals.req_timed_out) {
928
929                         hv_kvp_convert_usermsg_to_hostmsg();
930                         hv_kvp_respond_host(KVP_SUCCESS);
931                         wakeup(&kvp_globals);
932                         kvp_globals.req_in_progress = false;
933                 }
934
935                 kvp_globals.daemon_busy = false;
936                 mtx_unlock(&kvp_globals.pending_mutex);
937         }
938
939         return (error);
940 }
941
942
943 /*
944  * hv_kvp_daemon poll invokes this function to check if data is available
945  * for daemon to read.
946  */
947 static int
948 hv_kvp_dev_daemon_poll(struct cdev *dev __unused, int events, struct thread *td)
949 {
950         int revents = 0;
951
952         mtx_lock(&kvp_globals.pending_mutex);
953         /*
954          * We check global flag daemon_busy for the data availiability for
955          * userland to read. Deamon_busy is set to true before driver has data
956          * for daemon to read. It is set to false after daemon sends
957          * then response back to driver.
958          */
959         if (kvp_globals.daemon_busy == true)
960                 revents = POLLIN;
961         else
962                 selrecord(td, &hv_kvp_selinfo);
963
964         mtx_unlock(&kvp_globals.pending_mutex);
965
966         return (revents);
967 }
968
969
970 /* 
971  * hv_kvp initialization function 
972  * called from hv_util service.
973  *
974  */
975 int
976 hv_kvp_init(hv_vmbus_service *srv)
977 {
978         int error = 0;
979         hv_work_queue *work_queue = NULL;
980         
981         memset(&kvp_globals, 0, sizeof(kvp_globals));
982
983         work_queue = hv_work_queue_create("KVP Service");
984         if (work_queue == NULL) {
985                 hv_kvp_log_info("%s: Work queue alloc failed\n", __func__);
986                 error = ENOMEM;
987                 hv_kvp_log_error("%s: ENOMEM\n", __func__);
988                 goto Finish;
989         }
990         srv->work_queue = work_queue;
991
992         error = hv_kvp_dev_init();
993         mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex",
994                         NULL, MTX_DEF); 
995         kvp_globals.pending_reqs = 0;
996
997
998 Finish:
999         return (error);
1000 }
1001
1002
1003 void
1004 hv_kvp_deinit(void)
1005 {
1006         hv_kvp_dev_destroy();
1007         mtx_destroy(&kvp_globals.pending_mutex);
1008
1009         return;
1010 }