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