hv_kvp.c (b47a81dcc5a806efb6d970608299129771588289) hv_kvp.c (03db7724af1315f644ddc26e9539789eac4a016a)
1/*
2 * An implementation of key value pair (KVP) functionality for Linux.
3 *
4 *
5 * Copyright (C) 2010, Novell, Inc.
6 * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it

--- 49 unchanged lines hidden (view full) ---

58/*
59 * This state maintains the version number registered by the daemon.
60 */
61static int dm_reg_value;
62
63static void kvp_send_key(struct work_struct *dummy);
64
65
1/*
2 * An implementation of key value pair (KVP) functionality for Linux.
3 *
4 *
5 * Copyright (C) 2010, Novell, Inc.
6 * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it

--- 49 unchanged lines hidden (view full) ---

58/*
59 * This state maintains the version number registered by the daemon.
60 */
61static int dm_reg_value;
62
63static void kvp_send_key(struct work_struct *dummy);
64
65
66static void kvp_respond_to_host(char *key, char *value, int error);
66static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
67static void kvp_work_func(struct work_struct *dummy);
68static void kvp_register(int);
69
70static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
71static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
72
73static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
74static const char kvp_name[] = "kvp_kernel_module";

--- 28 unchanged lines hidden (view full) ---

103}
104static void
105kvp_work_func(struct work_struct *dummy)
106{
107 /*
108 * If the timer fires, the user-mode component has not responded;
109 * process the pending transaction.
110 */
67static void kvp_work_func(struct work_struct *dummy);
68static void kvp_register(int);
69
70static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
71static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
72
73static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL };
74static const char kvp_name[] = "kvp_kernel_module";

--- 28 unchanged lines hidden (view full) ---

103}
104static void
105kvp_work_func(struct work_struct *dummy)
106{
107 /*
108 * If the timer fires, the user-mode component has not responded;
109 * process the pending transaction.
110 */
111 kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
111 kvp_respond_to_host(NULL, HV_E_FAIL);
112}
113
114static int kvp_handle_handshake(struct hv_kvp_msg *msg)
115{
116 int ret = 1;
117
118 switch (msg->kvp_hdr.operation) {
119 case KVP_OP_REGISTER:

--- 74 unchanged lines hidden (view full) ---

194 break;
195 }
196
197 /*
198 * Complete the transaction by forwarding the key value
199 * to the host. But first, cancel the timeout.
200 */
201 if (cancel_delayed_work_sync(&kvp_work))
112}
113
114static int kvp_handle_handshake(struct hv_kvp_msg *msg)
115{
116 int ret = 1;
117
118 switch (msg->kvp_hdr.operation) {
119 case KVP_OP_REGISTER:

--- 74 unchanged lines hidden (view full) ---

194 break;
195 }
196
197 /*
198 * Complete the transaction by forwarding the key value
199 * to the host. But first, cancel the timeout.
200 */
201 if (cancel_delayed_work_sync(&kvp_work))
202 kvp_respond_to_host(data->data.key, data->data.value, error);
202 kvp_respond_to_host(message, error);
203}
204
203}
204
205
206static int process_ob_ipinfo(void *in_msg, void *out_msg, int op)
207{
208 struct hv_kvp_msg *in = in_msg;
209 struct hv_kvp_ip_msg *out = out_msg;
210 int len;
211
212 switch (op) {
213 case KVP_OP_GET_IP_INFO:
214 /*
215 * Transform all parameters into utf16 encoding.
216 */
217 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr,
218 strlen((char *)in->body.kvp_ip_val.ip_addr),
219 UTF16_HOST_ENDIAN,
220 (wchar_t *)out->kvp_ip_val.ip_addr,
221 MAX_IP_ADDR_SIZE);
222 if (len < 0)
223 return len;
224
225 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net,
226 strlen((char *)in->body.kvp_ip_val.sub_net),
227 UTF16_HOST_ENDIAN,
228 (wchar_t *)out->kvp_ip_val.sub_net,
229 MAX_IP_ADDR_SIZE);
230 if (len < 0)
231 return len;
232
233 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way,
234 strlen((char *)in->body.kvp_ip_val.gate_way),
235 UTF16_HOST_ENDIAN,
236 (wchar_t *)out->kvp_ip_val.gate_way,
237 MAX_GATEWAY_SIZE);
238 if (len < 0)
239 return len;
240
241 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr,
242 strlen((char *)in->body.kvp_ip_val.dns_addr),
243 UTF16_HOST_ENDIAN,
244 (wchar_t *)out->kvp_ip_val.dns_addr,
245 MAX_IP_ADDR_SIZE);
246 if (len < 0)
247 return len;
248
249 len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id,
250 strlen((char *)in->body.kvp_ip_val.adapter_id),
251 UTF16_HOST_ENDIAN,
252 (wchar_t *)out->kvp_ip_val.adapter_id,
253 MAX_IP_ADDR_SIZE);
254 if (len < 0)
255 return len;
256
257 out->kvp_ip_val.dhcp_enabled =
258 in->body.kvp_ip_val.dhcp_enabled;
259 }
260
261 return 0;
262}
263
264static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
265{
266 struct hv_kvp_ip_msg *in = in_msg;
267 struct hv_kvp_msg *out = out_msg;
268
269 switch (op) {
270 case KVP_OP_SET_IP_INFO:
271 /*
272 * Transform all parameters into utf8 encoding.
273 */
274 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr,
275 MAX_IP_ADDR_SIZE,
276 UTF16_LITTLE_ENDIAN,
277 (__u8 *)out->body.kvp_ip_val.ip_addr,
278 MAX_IP_ADDR_SIZE);
279
280 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net,
281 MAX_IP_ADDR_SIZE,
282 UTF16_LITTLE_ENDIAN,
283 (__u8 *)out->body.kvp_ip_val.sub_net,
284 MAX_IP_ADDR_SIZE);
285
286 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way,
287 MAX_GATEWAY_SIZE,
288 UTF16_LITTLE_ENDIAN,
289 (__u8 *)out->body.kvp_ip_val.gate_way,
290 MAX_GATEWAY_SIZE);
291
292 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr,
293 MAX_IP_ADDR_SIZE,
294 UTF16_LITTLE_ENDIAN,
295 (__u8 *)out->body.kvp_ip_val.dns_addr,
296 MAX_IP_ADDR_SIZE);
297
298 out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
299
300 default:
301 utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
302 MAX_ADAPTER_ID_SIZE,
303 UTF16_LITTLE_ENDIAN,
304 (__u8 *)out->body.kvp_ip_val.adapter_id,
305 MAX_ADAPTER_ID_SIZE);
306
307 out->body.kvp_ip_val.addr_family = in->kvp_ip_val.addr_family;
308 }
309}
310
311
312
313
205static void
206kvp_send_key(struct work_struct *dummy)
207{
208 struct cn_msg *msg;
209 struct hv_kvp_msg *message;
210 struct hv_kvp_msg *in_msg;
211 __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
212 __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;

--- 19 unchanged lines hidden (view full) ---

232 * the max lengths specified. We will however, reserve room
233 * for the string terminating character - in the utf16s_utf8s()
234 * function we limit the size of the buffer where the converted
235 * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
236 * that the strings can be properly terminated!
237 */
238
239 switch (message->kvp_hdr.operation) {
314static void
315kvp_send_key(struct work_struct *dummy)
316{
317 struct cn_msg *msg;
318 struct hv_kvp_msg *message;
319 struct hv_kvp_msg *in_msg;
320 __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
321 __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;

--- 19 unchanged lines hidden (view full) ---

341 * the max lengths specified. We will however, reserve room
342 * for the string terminating character - in the utf16s_utf8s()
343 * function we limit the size of the buffer where the converted
344 * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
345 * that the strings can be properly terminated!
346 */
347
348 switch (message->kvp_hdr.operation) {
349 case KVP_OP_SET_IP_INFO:
350 process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
351 break;
352 case KVP_OP_GET_IP_INFO:
353 process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
354 break;
240 case KVP_OP_SET:
241 switch (in_msg->body.kvp_set.data.value_type) {
242 case REG_SZ:
243 /*
244 * The value is a string - utf16 encoding.
245 */
246 message->body.kvp_set.data.value_size =
247 utf16s_to_utf8s(

--- 60 unchanged lines hidden (view full) ---

308 return;
309}
310
311/*
312 * Send a response back to the host.
313 */
314
315static void
355 case KVP_OP_SET:
356 switch (in_msg->body.kvp_set.data.value_type) {
357 case REG_SZ:
358 /*
359 * The value is a string - utf16 encoding.
360 */
361 message->body.kvp_set.data.value_size =
362 utf16s_to_utf8s(

--- 60 unchanged lines hidden (view full) ---

423 return;
424}
425
426/*
427 * Send a response back to the host.
428 */
429
430static void
316kvp_respond_to_host(char *key, char *value, int error)
431kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
317{
318 struct hv_kvp_msg *kvp_msg;
319 struct hv_kvp_exchg_msg_value *kvp_data;
320 char *key_name;
432{
433 struct hv_kvp_msg *kvp_msg;
434 struct hv_kvp_exchg_msg_value *kvp_data;
435 char *key_name;
436 char *value;
321 struct icmsg_hdr *icmsghdrp;
322 int keylen = 0;
323 int valuelen = 0;
324 u32 buf_len;
325 struct vmbus_channel *channel;
326 u64 req_id;
437 struct icmsg_hdr *icmsghdrp;
438 int keylen = 0;
439 int valuelen = 0;
440 u32 buf_len;
441 struct vmbus_channel *channel;
442 u64 req_id;
443 int ret;
327
328 /*
329 * If a transaction is not active; log and return.
330 */
331
332 if (!kvp_transaction.active) {
333 /*
334 * This is a spurious call!

--- 36 unchanged lines hidden (view full) ---

371 goto response_done;
372 }
373
374 kvp_msg = (struct hv_kvp_msg *)
375 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
376 sizeof(struct icmsg_hdr)];
377
378 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
444
445 /*
446 * If a transaction is not active; log and return.
447 */
448
449 if (!kvp_transaction.active) {
450 /*
451 * This is a spurious call!

--- 36 unchanged lines hidden (view full) ---

488 goto response_done;
489 }
490
491 kvp_msg = (struct hv_kvp_msg *)
492 &recv_buffer[sizeof(struct vmbuspipe_hdr) +
493 sizeof(struct icmsg_hdr)];
494
495 switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
496 case KVP_OP_GET_IP_INFO:
497 ret = process_ob_ipinfo(msg_to_host,
498 (struct hv_kvp_ip_msg *)kvp_msg,
499 KVP_OP_GET_IP_INFO);
500 if (ret < 0)
501 icmsghdrp->status = HV_E_FAIL;
502
503 goto response_done;
504 case KVP_OP_SET_IP_INFO:
505 goto response_done;
379 case KVP_OP_GET:
380 kvp_data = &kvp_msg->body.kvp_get.data;
381 goto copy_value;
382
383 case KVP_OP_SET:
384 case KVP_OP_DELETE:
385 goto response_done;
386
387 default:
388 break;
389 }
390
391 kvp_data = &kvp_msg->body.kvp_enum_data.data;
506 case KVP_OP_GET:
507 kvp_data = &kvp_msg->body.kvp_get.data;
508 goto copy_value;
509
510 case KVP_OP_SET:
511 case KVP_OP_DELETE:
512 goto response_done;
513
514 default:
515 break;
516 }
517
518 kvp_data = &kvp_msg->body.kvp_enum_data.data;
392 key_name = key;
519 key_name = msg_to_host->body.kvp_enum_data.data.key;
393
394 /*
395 * The windows host expects the key/value pair to be encoded
396 * in utf16. Ensure that the key/value size reported to the host
397 * will be less than or equal to the MAX size (including the
398 * terminating character).
399 */
400 keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
401 (wchar_t *) kvp_data->key,
402 (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2);
403 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
404
405copy_value:
520
521 /*
522 * The windows host expects the key/value pair to be encoded
523 * in utf16. Ensure that the key/value size reported to the host
524 * will be less than or equal to the MAX size (including the
525 * terminating character).
526 */
527 keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
528 (wchar_t *) kvp_data->key,
529 (HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2);
530 kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
531
532copy_value:
533 value = msg_to_host->body.kvp_enum_data.data.value;
406 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
407 (wchar_t *) kvp_data->value,
408 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
409 kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */
410
411 /*
412 * If the utf8s to utf16s conversion failed; notify host
413 * of the error.

--- 36 unchanged lines hidden (view full) ---

450 /*
451 * We will defer processing this callback once
452 * the current transaction is complete.
453 */
454 kvp_transaction.kvp_context = context;
455 return;
456 }
457
534 valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
535 (wchar_t *) kvp_data->value,
536 (HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
537 kvp_data->value_size = 2*(valuelen + 1); /* utf16 encoding */
538
539 /*
540 * If the utf8s to utf16s conversion failed; notify host
541 * of the error.

--- 36 unchanged lines hidden (view full) ---

578 /*
579 * We will defer processing this callback once
580 * the current transaction is complete.
581 */
582 kvp_transaction.kvp_context = context;
583 return;
584 }
585
458 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
586 vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
587 &requestid);
459
460 if (recvlen > 0) {
461 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
462 sizeof(struct vmbuspipe_hdr)];
463
464 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
465 vmbus_prep_negotiate_resp(icmsghdrp, negop,
466 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);

--- 69 unchanged lines hidden ---
588
589 if (recvlen > 0) {
590 icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
591 sizeof(struct vmbuspipe_hdr)];
592
593 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) {
594 vmbus_prep_negotiate_resp(icmsghdrp, negop,
595 recv_buffer, MAX_SRV_VER, MAX_SRV_VER);

--- 69 unchanged lines hidden ---