Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Tools: hv: kvp: use misc char device to communicate with kernel

Use /dev/vmbus/hv_kvp instead of netlink.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Tested-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vitaly Kuznetsov and committed by
Greg Kroah-Hartman
8ddca808 11bc3a5f

+31 -135
+31 -135
tools/hv/hv_kvp_daemon.c
··· 33 33 #include <ctype.h> 34 34 #include <errno.h> 35 35 #include <arpa/inet.h> 36 - #include <linux/connector.h> 37 36 #include <linux/hyperv.h> 38 37 #include <linux/netlink.h> 39 38 #include <ifaddrs.h> ··· 78 79 DNS 79 80 }; 80 81 81 - static struct sockaddr_nl addr; 82 82 static int in_hand_shake = 1; 83 83 84 84 static char *os_name = ""; ··· 1385 1387 freeaddrinfo(info); 1386 1388 } 1387 1389 1388 - static int 1389 - netlink_send(int fd, struct cn_msg *msg) 1390 - { 1391 - struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; 1392 - unsigned int size; 1393 - struct msghdr message; 1394 - struct iovec iov[2]; 1395 - 1396 - size = sizeof(struct cn_msg) + msg->len; 1397 - 1398 - nlh.nlmsg_pid = getpid(); 1399 - nlh.nlmsg_len = NLMSG_LENGTH(size); 1400 - 1401 - iov[0].iov_base = &nlh; 1402 - iov[0].iov_len = sizeof(nlh); 1403 - 1404 - iov[1].iov_base = msg; 1405 - iov[1].iov_len = size; 1406 - 1407 - memset(&message, 0, sizeof(message)); 1408 - message.msg_name = &addr; 1409 - message.msg_namelen = sizeof(addr); 1410 - message.msg_iov = iov; 1411 - message.msg_iovlen = 2; 1412 - 1413 - return sendmsg(fd, &message, 0); 1414 - } 1415 - 1416 1390 void print_usage(char *argv[]) 1417 1391 { 1418 1392 fprintf(stderr, "Usage: %s [options]\n" ··· 1395 1425 1396 1426 int main(int argc, char *argv[]) 1397 1427 { 1398 - int fd, len, nl_group; 1428 + int kvp_fd, len; 1399 1429 int error; 1400 - struct cn_msg *message; 1401 1430 struct pollfd pfd; 1402 - struct nlmsghdr *incoming_msg; 1403 - struct cn_msg *incoming_cn_msg; 1404 - struct hv_kvp_msg *hv_msg; 1405 - char *p; 1431 + char *p; 1432 + struct hv_kvp_msg hv_msg[1]; 1406 1433 char *key_value; 1407 1434 char *key_name; 1408 1435 int op; 1409 1436 int pool; 1410 1437 char *if_name; 1411 1438 struct hv_kvp_ipaddr_value *kvp_ip_val; 1412 - char *kvp_recv_buffer; 1413 - size_t kvp_recv_buffer_len; 1414 1439 int daemonize = 1, long_index = 0, opt; 1415 1440 1416 1441 static struct option long_options[] = { ··· 1433 1468 openlog("KVP", 0, LOG_USER); 1434 1469 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); 1435 1470 1436 - kvp_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg); 1437 - kvp_recv_buffer = calloc(1, kvp_recv_buffer_len); 1438 - if (!kvp_recv_buffer) { 1439 - syslog(LOG_ERR, "Failed to allocate netlink buffer"); 1471 + kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR); 1472 + 1473 + if (kvp_fd < 0) { 1474 + syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s", 1475 + errno, strerror(errno)); 1440 1476 exit(EXIT_FAILURE); 1441 1477 } 1478 + 1442 1479 /* 1443 1480 * Retrieve OS release information. 1444 1481 */ ··· 1456 1489 exit(EXIT_FAILURE); 1457 1490 } 1458 1491 1459 - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); 1460 - if (fd < 0) { 1461 - syslog(LOG_ERR, "netlink socket creation failed; error: %d %s", errno, 1462 - strerror(errno)); 1463 - exit(EXIT_FAILURE); 1464 - } 1465 - addr.nl_family = AF_NETLINK; 1466 - addr.nl_pad = 0; 1467 - addr.nl_pid = 0; 1468 - addr.nl_groups = 0; 1469 - 1470 - 1471 - error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 1472 - if (error < 0) { 1473 - syslog(LOG_ERR, "bind failed; error: %d %s", errno, strerror(errno)); 1474 - close(fd); 1475 - exit(EXIT_FAILURE); 1476 - } 1477 - nl_group = CN_KVP_IDX; 1478 - 1479 - if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { 1480 - syslog(LOG_ERR, "setsockopt failed; error: %d %s", errno, strerror(errno)); 1481 - close(fd); 1482 - exit(EXIT_FAILURE); 1483 - } 1484 - 1485 1492 /* 1486 1493 * Register ourselves with the kernel. 1487 1494 */ 1488 - message = (struct cn_msg *)kvp_recv_buffer; 1489 - message->id.idx = CN_KVP_IDX; 1490 - message->id.val = CN_KVP_VAL; 1491 - 1492 - hv_msg = (struct hv_kvp_msg *)message->data; 1493 1495 hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1; 1494 - message->ack = 0; 1495 - message->len = sizeof(struct hv_kvp_msg); 1496 - 1497 - len = netlink_send(fd, message); 1498 - if (len < 0) { 1499 - syslog(LOG_ERR, "netlink_send failed; error: %d %s", errno, strerror(errno)); 1500 - close(fd); 1496 + len = write(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); 1497 + if (len != sizeof(struct hv_kvp_msg)) { 1498 + syslog(LOG_ERR, "registration to kernel failed; error: %d %s", 1499 + errno, strerror(errno)); 1500 + close(kvp_fd); 1501 1501 exit(EXIT_FAILURE); 1502 1502 } 1503 1503 1504 - pfd.fd = fd; 1504 + pfd.fd = kvp_fd; 1505 1505 1506 1506 while (1) { 1507 - struct sockaddr *addr_p = (struct sockaddr *) &addr; 1508 - socklen_t addr_l = sizeof(addr); 1509 1507 pfd.events = POLLIN; 1510 1508 pfd.revents = 0; 1511 1509 1512 1510 if (poll(&pfd, 1, -1) < 0) { 1513 1511 syslog(LOG_ERR, "poll failed; error: %d %s", errno, strerror(errno)); 1514 1512 if (errno == EINVAL) { 1515 - close(fd); 1513 + close(kvp_fd); 1516 1514 exit(EXIT_FAILURE); 1517 1515 } 1518 1516 else 1519 1517 continue; 1520 1518 } 1521 1519 1522 - len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0, 1523 - addr_p, &addr_l); 1520 + len = read(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); 1524 1521 1525 - if (len < 0) { 1526 - int saved_errno = errno; 1527 - syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", 1528 - addr.nl_pid, errno, strerror(errno)); 1522 + if (len != sizeof(struct hv_kvp_msg)) { 1523 + syslog(LOG_ERR, "read failed; error:%d %s", 1524 + errno, strerror(errno)); 1529 1525 1530 - if (saved_errno == ENOBUFS) { 1531 - syslog(LOG_ERR, "receive error: ignored"); 1532 - continue; 1533 - } 1534 - 1535 - close(fd); 1536 - return -1; 1526 + close(kvp_fd); 1527 + return EXIT_FAILURE; 1537 1528 } 1538 - 1539 - if (addr.nl_pid) { 1540 - syslog(LOG_WARNING, "Received packet from untrusted pid:%u", 1541 - addr.nl_pid); 1542 - continue; 1543 - } 1544 - 1545 - incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; 1546 - 1547 - if (incoming_msg->nlmsg_type != NLMSG_DONE) 1548 - continue; 1549 - 1550 - incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); 1551 - hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; 1552 1529 1553 1530 /* 1554 1531 * We will use the KVP header information to pass back ··· 1514 1603 if (lic_version) { 1515 1604 strcpy(lic_version, p); 1516 1605 syslog(LOG_INFO, "KVP LIC Version: %s", 1517 - lic_version); 1606 + lic_version); 1518 1607 } else { 1519 1608 syslog(LOG_ERR, "malloc failed"); 1520 1609 } ··· 1613 1702 goto kvp_done; 1614 1703 } 1615 1704 1616 - hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; 1617 1705 key_name = (char *)hv_msg->body.kvp_enum_data.data.key; 1618 1706 key_value = (char *)hv_msg->body.kvp_enum_data.data.value; 1619 1707 ··· 1663 1753 hv_msg->error = HV_S_CONT; 1664 1754 break; 1665 1755 } 1666 - /* 1667 - * Send the value back to the kernel. The response is 1668 - * already in the receive buffer. Update the cn_msg header to 1669 - * reflect the key value that has been added to the message 1670 - */ 1756 + 1757 + /* Send the value back to the kernel. */ 1671 1758 kvp_done: 1672 - 1673 - incoming_cn_msg->id.idx = CN_KVP_IDX; 1674 - incoming_cn_msg->id.val = CN_KVP_VAL; 1675 - incoming_cn_msg->ack = 0; 1676 - incoming_cn_msg->len = sizeof(struct hv_kvp_msg); 1677 - 1678 - len = netlink_send(fd, incoming_cn_msg); 1679 - if (len < 0) { 1680 - int saved_errno = errno; 1681 - syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, 1682 - strerror(errno)); 1683 - 1684 - if (saved_errno == ENOMEM || saved_errno == ENOBUFS) { 1685 - syslog(LOG_ERR, "send error: ignored"); 1686 - continue; 1687 - } 1688 - 1759 + len = write(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); 1760 + if (len != sizeof(struct hv_kvp_msg)) { 1761 + syslog(LOG_ERR, "write failed; error: %d %s", errno, 1762 + strerror(errno)); 1689 1763 exit(EXIT_FAILURE); 1690 1764 } 1691 1765 } 1692 1766 1767 + close(kvp_fd); 1768 + exit(0); 1693 1769 }