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 --- |