diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 17:51:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-06-26 17:51:15 -0400 |
commit | d87823813fe498fdd47894bd28e460a9dee8d771 (patch) | |
tree | 214eaf3babd0d61f08022fc1edd99a5128616548 /tools | |
parent | e382608254e06c8109f40044f5e693f2e04f3899 (diff) | |
parent | 3dc196eae1db548f05e53e5875ff87b8ff79f249 (diff) |
Merge tag 'char-misc-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH:
"Here's the big char/misc driver pull request for 4.2-rc1.
Lots of mei, extcon, coresight, uio, mic, and other driver updates in
here. Full details in the shortlog. All of these have been in
linux-next for some time with no reported problems"
* tag 'char-misc-4.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (176 commits)
mei: me: wait for power gating exit confirmation
mei: reset flow control on the last client disconnection
MAINTAINERS: mei: add mei_cl_bus.h to maintained file list
misc: sram: sort and clean up included headers
misc: sram: move reserved block logic out of probe function
misc: sram: add private struct device and virt_base members
misc: sram: report correct SRAM pool size
misc: sram: bump error message level on unclean driver unbinding
misc: sram: fix device node reference leak on error
misc: sram: fix enabled clock leak on error path
misc: mic: Fix reported static checker warning
misc: mic: Fix randconfig build error by including errno.h
uio: pruss: Drop depends on ARCH_DAVINCI_DA850 from config
uio: pruss: Add CONFIG_HAS_IOMEM dependence
uio: pruss: Include <linux/sizes.h>
extcon: Redefine the unique id of supported external connectors without 'enum extcon' type
char:xilinx_hwicap:buffer_icap - change 1/0 to true/false for bool type variable in function buffer_icap_set_configuration().
Drivers: hv: vmbus: Allocate ring buffer memory in NUMA aware fashion
parport: check exclusive access before register
w1: use correct lock on error in w1_seq_show()
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/hv/hv_fcopy_daemon.c | 15 | ||||
-rw-r--r-- | tools/hv/hv_kvp_daemon.c | 166 | ||||
-rw-r--r-- | tools/hv/hv_vss_daemon.c | 149 |
3 files changed, 83 insertions, 247 deletions
diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 9445d8f264a4..5480e4e424eb 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c | |||
@@ -137,6 +137,8 @@ int main(int argc, char *argv[]) | |||
137 | int version = FCOPY_CURRENT_VERSION; | 137 | int version = FCOPY_CURRENT_VERSION; |
138 | char *buffer[4096 * 2]; | 138 | char *buffer[4096 * 2]; |
139 | struct hv_fcopy_hdr *in_msg; | 139 | struct hv_fcopy_hdr *in_msg; |
140 | int in_handshake = 1; | ||
141 | __u32 kernel_modver; | ||
140 | 142 | ||
141 | static struct option long_options[] = { | 143 | static struct option long_options[] = { |
142 | {"help", no_argument, 0, 'h' }, | 144 | {"help", no_argument, 0, 'h' }, |
@@ -191,6 +193,19 @@ int main(int argc, char *argv[]) | |||
191 | syslog(LOG_ERR, "pread failed: %s", strerror(errno)); | 193 | syslog(LOG_ERR, "pread failed: %s", strerror(errno)); |
192 | exit(EXIT_FAILURE); | 194 | exit(EXIT_FAILURE); |
193 | } | 195 | } |
196 | |||
197 | if (in_handshake) { | ||
198 | if (len != sizeof(kernel_modver)) { | ||
199 | syslog(LOG_ERR, "invalid version negotiation"); | ||
200 | exit(EXIT_FAILURE); | ||
201 | } | ||
202 | kernel_modver = *(__u32 *)buffer; | ||
203 | in_handshake = 0; | ||
204 | syslog(LOG_INFO, "HV_FCOPY: kernel module version: %d", | ||
205 | kernel_modver); | ||
206 | continue; | ||
207 | } | ||
208 | |||
194 | in_msg = (struct hv_fcopy_hdr *)buffer; | 209 | in_msg = (struct hv_fcopy_hdr *)buffer; |
195 | 210 | ||
196 | switch (in_msg->operation) { | 211 | switch (in_msg->operation) { |
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 408bb076a234..0d9f48ec42bb 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <ctype.h> | 33 | #include <ctype.h> |
34 | #include <errno.h> | 34 | #include <errno.h> |
35 | #include <arpa/inet.h> | 35 | #include <arpa/inet.h> |
36 | #include <linux/connector.h> | ||
37 | #include <linux/hyperv.h> | 36 | #include <linux/hyperv.h> |
38 | #include <linux/netlink.h> | 37 | #include <linux/netlink.h> |
39 | #include <ifaddrs.h> | 38 | #include <ifaddrs.h> |
@@ -79,7 +78,6 @@ enum { | |||
79 | DNS | 78 | DNS |
80 | }; | 79 | }; |
81 | 80 | ||
82 | static struct sockaddr_nl addr; | ||
83 | static int in_hand_shake = 1; | 81 | static int in_hand_shake = 1; |
84 | 82 | ||
85 | static char *os_name = ""; | 83 | static char *os_name = ""; |
@@ -1387,34 +1385,6 @@ kvp_get_domain_name(char *buffer, int length) | |||
1387 | freeaddrinfo(info); | 1385 | freeaddrinfo(info); |
1388 | } | 1386 | } |
1389 | 1387 | ||
1390 | static int | ||
1391 | netlink_send(int fd, struct cn_msg *msg) | ||
1392 | { | ||
1393 | struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; | ||
1394 | unsigned int size; | ||
1395 | struct msghdr message; | ||
1396 | struct iovec iov[2]; | ||
1397 | |||
1398 | size = sizeof(struct cn_msg) + msg->len; | ||
1399 | |||
1400 | nlh.nlmsg_pid = getpid(); | ||
1401 | nlh.nlmsg_len = NLMSG_LENGTH(size); | ||
1402 | |||
1403 | iov[0].iov_base = &nlh; | ||
1404 | iov[0].iov_len = sizeof(nlh); | ||
1405 | |||
1406 | iov[1].iov_base = msg; | ||
1407 | iov[1].iov_len = size; | ||
1408 | |||
1409 | memset(&message, 0, sizeof(message)); | ||
1410 | message.msg_name = &addr; | ||
1411 | message.msg_namelen = sizeof(addr); | ||
1412 | message.msg_iov = iov; | ||
1413 | message.msg_iovlen = 2; | ||
1414 | |||
1415 | return sendmsg(fd, &message, 0); | ||
1416 | } | ||
1417 | |||
1418 | void print_usage(char *argv[]) | 1388 | void print_usage(char *argv[]) |
1419 | { | 1389 | { |
1420 | fprintf(stderr, "Usage: %s [options]\n" | 1390 | fprintf(stderr, "Usage: %s [options]\n" |
@@ -1425,22 +1395,17 @@ void print_usage(char *argv[]) | |||
1425 | 1395 | ||
1426 | int main(int argc, char *argv[]) | 1396 | int main(int argc, char *argv[]) |
1427 | { | 1397 | { |
1428 | int fd, len, nl_group; | 1398 | int kvp_fd, len; |
1429 | int error; | 1399 | int error; |
1430 | struct cn_msg *message; | ||
1431 | struct pollfd pfd; | 1400 | struct pollfd pfd; |
1432 | struct nlmsghdr *incoming_msg; | 1401 | char *p; |
1433 | struct cn_msg *incoming_cn_msg; | 1402 | struct hv_kvp_msg hv_msg[1]; |
1434 | struct hv_kvp_msg *hv_msg; | ||
1435 | char *p; | ||
1436 | char *key_value; | 1403 | char *key_value; |
1437 | char *key_name; | 1404 | char *key_name; |
1438 | int op; | 1405 | int op; |
1439 | int pool; | 1406 | int pool; |
1440 | char *if_name; | 1407 | char *if_name; |
1441 | struct hv_kvp_ipaddr_value *kvp_ip_val; | 1408 | struct hv_kvp_ipaddr_value *kvp_ip_val; |
1442 | char *kvp_recv_buffer; | ||
1443 | size_t kvp_recv_buffer_len; | ||
1444 | int daemonize = 1, long_index = 0, opt; | 1409 | int daemonize = 1, long_index = 0, opt; |
1445 | 1410 | ||
1446 | static struct option long_options[] = { | 1411 | static struct option long_options[] = { |
@@ -1468,12 +1433,14 @@ int main(int argc, char *argv[]) | |||
1468 | openlog("KVP", 0, LOG_USER); | 1433 | openlog("KVP", 0, LOG_USER); |
1469 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); | 1434 | syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); |
1470 | 1435 | ||
1471 | kvp_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_kvp_msg); | 1436 | kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR); |
1472 | kvp_recv_buffer = calloc(1, kvp_recv_buffer_len); | 1437 | |
1473 | if (!kvp_recv_buffer) { | 1438 | if (kvp_fd < 0) { |
1474 | syslog(LOG_ERR, "Failed to allocate netlink buffer"); | 1439 | syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s", |
1440 | errno, strerror(errno)); | ||
1475 | exit(EXIT_FAILURE); | 1441 | exit(EXIT_FAILURE); |
1476 | } | 1442 | } |
1443 | |||
1477 | /* | 1444 | /* |
1478 | * Retrieve OS release information. | 1445 | * Retrieve OS release information. |
1479 | */ | 1446 | */ |
@@ -1489,100 +1456,44 @@ int main(int argc, char *argv[]) | |||
1489 | exit(EXIT_FAILURE); | 1456 | exit(EXIT_FAILURE); |
1490 | } | 1457 | } |
1491 | 1458 | ||
1492 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); | ||
1493 | if (fd < 0) { | ||
1494 | syslog(LOG_ERR, "netlink socket creation failed; error: %d %s", errno, | ||
1495 | strerror(errno)); | ||
1496 | exit(EXIT_FAILURE); | ||
1497 | } | ||
1498 | addr.nl_family = AF_NETLINK; | ||
1499 | addr.nl_pad = 0; | ||
1500 | addr.nl_pid = 0; | ||
1501 | addr.nl_groups = 0; | ||
1502 | |||
1503 | |||
1504 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); | ||
1505 | if (error < 0) { | ||
1506 | syslog(LOG_ERR, "bind failed; error: %d %s", errno, strerror(errno)); | ||
1507 | close(fd); | ||
1508 | exit(EXIT_FAILURE); | ||
1509 | } | ||
1510 | nl_group = CN_KVP_IDX; | ||
1511 | |||
1512 | if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { | ||
1513 | syslog(LOG_ERR, "setsockopt failed; error: %d %s", errno, strerror(errno)); | ||
1514 | close(fd); | ||
1515 | exit(EXIT_FAILURE); | ||
1516 | } | ||
1517 | |||
1518 | /* | 1459 | /* |
1519 | * Register ourselves with the kernel. | 1460 | * Register ourselves with the kernel. |
1520 | */ | 1461 | */ |
1521 | message = (struct cn_msg *)kvp_recv_buffer; | ||
1522 | message->id.idx = CN_KVP_IDX; | ||
1523 | message->id.val = CN_KVP_VAL; | ||
1524 | |||
1525 | hv_msg = (struct hv_kvp_msg *)message->data; | ||
1526 | hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1; | 1462 | hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1; |
1527 | message->ack = 0; | 1463 | len = write(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); |
1528 | message->len = sizeof(struct hv_kvp_msg); | 1464 | if (len != sizeof(struct hv_kvp_msg)) { |
1529 | 1465 | syslog(LOG_ERR, "registration to kernel failed; error: %d %s", | |
1530 | len = netlink_send(fd, message); | 1466 | errno, strerror(errno)); |
1531 | if (len < 0) { | 1467 | close(kvp_fd); |
1532 | syslog(LOG_ERR, "netlink_send failed; error: %d %s", errno, strerror(errno)); | ||
1533 | close(fd); | ||
1534 | exit(EXIT_FAILURE); | 1468 | exit(EXIT_FAILURE); |
1535 | } | 1469 | } |
1536 | 1470 | ||
1537 | pfd.fd = fd; | 1471 | pfd.fd = kvp_fd; |
1538 | 1472 | ||
1539 | while (1) { | 1473 | while (1) { |
1540 | struct sockaddr *addr_p = (struct sockaddr *) &addr; | ||
1541 | socklen_t addr_l = sizeof(addr); | ||
1542 | pfd.events = POLLIN; | 1474 | pfd.events = POLLIN; |
1543 | pfd.revents = 0; | 1475 | pfd.revents = 0; |
1544 | 1476 | ||
1545 | if (poll(&pfd, 1, -1) < 0) { | 1477 | if (poll(&pfd, 1, -1) < 0) { |
1546 | syslog(LOG_ERR, "poll failed; error: %d %s", errno, strerror(errno)); | 1478 | syslog(LOG_ERR, "poll failed; error: %d %s", errno, strerror(errno)); |
1547 | if (errno == EINVAL) { | 1479 | if (errno == EINVAL) { |
1548 | close(fd); | 1480 | close(kvp_fd); |
1549 | exit(EXIT_FAILURE); | 1481 | exit(EXIT_FAILURE); |
1550 | } | 1482 | } |
1551 | else | 1483 | else |
1552 | continue; | 1484 | continue; |
1553 | } | 1485 | } |
1554 | 1486 | ||
1555 | len = recvfrom(fd, kvp_recv_buffer, kvp_recv_buffer_len, 0, | 1487 | len = read(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); |
1556 | addr_p, &addr_l); | ||
1557 | |||
1558 | if (len < 0) { | ||
1559 | int saved_errno = errno; | ||
1560 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", | ||
1561 | addr.nl_pid, errno, strerror(errno)); | ||
1562 | 1488 | ||
1563 | if (saved_errno == ENOBUFS) { | 1489 | if (len != sizeof(struct hv_kvp_msg)) { |
1564 | syslog(LOG_ERR, "receive error: ignored"); | 1490 | syslog(LOG_ERR, "read failed; error:%d %s", |
1565 | continue; | 1491 | errno, strerror(errno)); |
1566 | } | ||
1567 | 1492 | ||
1568 | close(fd); | 1493 | close(kvp_fd); |
1569 | return -1; | 1494 | return EXIT_FAILURE; |
1570 | } | 1495 | } |
1571 | 1496 | ||
1572 | if (addr.nl_pid) { | ||
1573 | syslog(LOG_WARNING, "Received packet from untrusted pid:%u", | ||
1574 | addr.nl_pid); | ||
1575 | continue; | ||
1576 | } | ||
1577 | |||
1578 | incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; | ||
1579 | |||
1580 | if (incoming_msg->nlmsg_type != NLMSG_DONE) | ||
1581 | continue; | ||
1582 | |||
1583 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); | ||
1584 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; | ||
1585 | |||
1586 | /* | 1497 | /* |
1587 | * We will use the KVP header information to pass back | 1498 | * We will use the KVP header information to pass back |
1588 | * the error from this daemon. So, first copy the state | 1499 | * the error from this daemon. So, first copy the state |
@@ -1603,7 +1514,7 @@ int main(int argc, char *argv[]) | |||
1603 | if (lic_version) { | 1514 | if (lic_version) { |
1604 | strcpy(lic_version, p); | 1515 | strcpy(lic_version, p); |
1605 | syslog(LOG_INFO, "KVP LIC Version: %s", | 1516 | syslog(LOG_INFO, "KVP LIC Version: %s", |
1606 | lic_version); | 1517 | lic_version); |
1607 | } else { | 1518 | } else { |
1608 | syslog(LOG_ERR, "malloc failed"); | 1519 | syslog(LOG_ERR, "malloc failed"); |
1609 | } | 1520 | } |
@@ -1702,7 +1613,6 @@ int main(int argc, char *argv[]) | |||
1702 | goto kvp_done; | 1613 | goto kvp_done; |
1703 | } | 1614 | } |
1704 | 1615 | ||
1705 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; | ||
1706 | key_name = (char *)hv_msg->body.kvp_enum_data.data.key; | 1616 | key_name = (char *)hv_msg->body.kvp_enum_data.data.key; |
1707 | key_value = (char *)hv_msg->body.kvp_enum_data.data.value; | 1617 | key_value = (char *)hv_msg->body.kvp_enum_data.data.value; |
1708 | 1618 | ||
@@ -1753,31 +1663,17 @@ int main(int argc, char *argv[]) | |||
1753 | hv_msg->error = HV_S_CONT; | 1663 | hv_msg->error = HV_S_CONT; |
1754 | break; | 1664 | break; |
1755 | } | 1665 | } |
1756 | /* | ||
1757 | * Send the value back to the kernel. The response is | ||
1758 | * already in the receive buffer. Update the cn_msg header to | ||
1759 | * reflect the key value that has been added to the message | ||
1760 | */ | ||
1761 | kvp_done: | ||
1762 | |||
1763 | incoming_cn_msg->id.idx = CN_KVP_IDX; | ||
1764 | incoming_cn_msg->id.val = CN_KVP_VAL; | ||
1765 | incoming_cn_msg->ack = 0; | ||
1766 | incoming_cn_msg->len = sizeof(struct hv_kvp_msg); | ||
1767 | |||
1768 | len = netlink_send(fd, incoming_cn_msg); | ||
1769 | if (len < 0) { | ||
1770 | int saved_errno = errno; | ||
1771 | syslog(LOG_ERR, "net_link send failed; error: %d %s", errno, | ||
1772 | strerror(errno)); | ||
1773 | |||
1774 | if (saved_errno == ENOMEM || saved_errno == ENOBUFS) { | ||
1775 | syslog(LOG_ERR, "send error: ignored"); | ||
1776 | continue; | ||
1777 | } | ||
1778 | 1666 | ||
1667 | /* Send the value back to the kernel. */ | ||
1668 | kvp_done: | ||
1669 | len = write(kvp_fd, hv_msg, sizeof(struct hv_kvp_msg)); | ||
1670 | if (len != sizeof(struct hv_kvp_msg)) { | ||
1671 | syslog(LOG_ERR, "write failed; error: %d %s", errno, | ||
1672 | strerror(errno)); | ||
1779 | exit(EXIT_FAILURE); | 1673 | exit(EXIT_FAILURE); |
1780 | } | 1674 | } |
1781 | } | 1675 | } |
1782 | 1676 | ||
1677 | close(kvp_fd); | ||
1678 | exit(0); | ||
1783 | } | 1679 | } |
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c index 506dd0148828..96234b638249 100644 --- a/tools/hv/hv_vss_daemon.c +++ b/tools/hv/hv_vss_daemon.c | |||
@@ -19,7 +19,6 @@ | |||
19 | 19 | ||
20 | 20 | ||
21 | #include <sys/types.h> | 21 | #include <sys/types.h> |
22 | #include <sys/socket.h> | ||
23 | #include <sys/poll.h> | 22 | #include <sys/poll.h> |
24 | #include <sys/ioctl.h> | 23 | #include <sys/ioctl.h> |
25 | #include <fcntl.h> | 24 | #include <fcntl.h> |
@@ -30,21 +29,11 @@ | |||
30 | #include <string.h> | 29 | #include <string.h> |
31 | #include <ctype.h> | 30 | #include <ctype.h> |
32 | #include <errno.h> | 31 | #include <errno.h> |
33 | #include <arpa/inet.h> | ||
34 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
35 | #include <linux/connector.h> | ||
36 | #include <linux/hyperv.h> | 33 | #include <linux/hyperv.h> |
37 | #include <linux/netlink.h> | ||
38 | #include <syslog.h> | 34 | #include <syslog.h> |
39 | #include <getopt.h> | 35 | #include <getopt.h> |
40 | 36 | ||
41 | static struct sockaddr_nl addr; | ||
42 | |||
43 | #ifndef SOL_NETLINK | ||
44 | #define SOL_NETLINK 270 | ||
45 | #endif | ||
46 | |||
47 | |||
48 | /* Don't use syslog() in the function since that can cause write to disk */ | 37 | /* Don't use syslog() in the function since that can cause write to disk */ |
49 | static int vss_do_freeze(char *dir, unsigned int cmd) | 38 | static int vss_do_freeze(char *dir, unsigned int cmd) |
50 | { | 39 | { |
@@ -143,33 +132,6 @@ out: | |||
143 | return error; | 132 | return error; |
144 | } | 133 | } |
145 | 134 | ||
146 | static int netlink_send(int fd, struct cn_msg *msg) | ||
147 | { | ||
148 | struct nlmsghdr nlh = { .nlmsg_type = NLMSG_DONE }; | ||
149 | unsigned int size; | ||
150 | struct msghdr message; | ||
151 | struct iovec iov[2]; | ||
152 | |||
153 | size = sizeof(struct cn_msg) + msg->len; | ||
154 | |||
155 | nlh.nlmsg_pid = getpid(); | ||
156 | nlh.nlmsg_len = NLMSG_LENGTH(size); | ||
157 | |||
158 | iov[0].iov_base = &nlh; | ||
159 | iov[0].iov_len = sizeof(nlh); | ||
160 | |||
161 | iov[1].iov_base = msg; | ||
162 | iov[1].iov_len = size; | ||
163 | |||
164 | memset(&message, 0, sizeof(message)); | ||
165 | message.msg_name = &addr; | ||
166 | message.msg_namelen = sizeof(addr); | ||
167 | message.msg_iov = iov; | ||
168 | message.msg_iovlen = 2; | ||
169 | |||
170 | return sendmsg(fd, &message, 0); | ||
171 | } | ||
172 | |||
173 | void print_usage(char *argv[]) | 135 | void print_usage(char *argv[]) |
174 | { | 136 | { |
175 | fprintf(stderr, "Usage: %s [options]\n" | 137 | fprintf(stderr, "Usage: %s [options]\n" |
@@ -180,17 +142,14 @@ void print_usage(char *argv[]) | |||
180 | 142 | ||
181 | int main(int argc, char *argv[]) | 143 | int main(int argc, char *argv[]) |
182 | { | 144 | { |
183 | int fd, len, nl_group; | 145 | int vss_fd, len; |
184 | int error; | 146 | int error; |
185 | struct cn_msg *message; | ||
186 | struct pollfd pfd; | 147 | struct pollfd pfd; |
187 | struct nlmsghdr *incoming_msg; | ||
188 | struct cn_msg *incoming_cn_msg; | ||
189 | int op; | 148 | int op; |
190 | struct hv_vss_msg *vss_msg; | 149 | struct hv_vss_msg vss_msg[1]; |
191 | char *vss_recv_buffer; | ||
192 | size_t vss_recv_buffer_len; | ||
193 | int daemonize = 1, long_index = 0, opt; | 150 | int daemonize = 1, long_index = 0, opt; |
151 | int in_handshake = 1; | ||
152 | __u32 kernel_modver; | ||
194 | 153 | ||
195 | static struct option long_options[] = { | 154 | static struct option long_options[] = { |
196 | {"help", no_argument, 0, 'h' }, | 155 | {"help", no_argument, 0, 'h' }, |
@@ -217,98 +176,62 @@ int main(int argc, char *argv[]) | |||
217 | openlog("Hyper-V VSS", 0, LOG_USER); | 176 | openlog("Hyper-V VSS", 0, LOG_USER); |
218 | syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); | 177 | syslog(LOG_INFO, "VSS starting; pid is:%d", getpid()); |
219 | 178 | ||
220 | vss_recv_buffer_len = NLMSG_LENGTH(0) + sizeof(struct cn_msg) + sizeof(struct hv_vss_msg); | 179 | vss_fd = open("/dev/vmbus/hv_vss", O_RDWR); |
221 | vss_recv_buffer = calloc(1, vss_recv_buffer_len); | 180 | if (vss_fd < 0) { |
222 | if (!vss_recv_buffer) { | 181 | syslog(LOG_ERR, "open /dev/vmbus/hv_vss failed; error: %d %s", |
223 | syslog(LOG_ERR, "Failed to allocate netlink buffers"); | 182 | errno, strerror(errno)); |
224 | exit(EXIT_FAILURE); | ||
225 | } | ||
226 | |||
227 | fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); | ||
228 | if (fd < 0) { | ||
229 | syslog(LOG_ERR, "netlink socket creation failed; error:%d %s", | ||
230 | errno, strerror(errno)); | ||
231 | exit(EXIT_FAILURE); | ||
232 | } | ||
233 | addr.nl_family = AF_NETLINK; | ||
234 | addr.nl_pad = 0; | ||
235 | addr.nl_pid = 0; | ||
236 | addr.nl_groups = 0; | ||
237 | |||
238 | |||
239 | error = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); | ||
240 | if (error < 0) { | ||
241 | syslog(LOG_ERR, "bind failed; error:%d %s", errno, strerror(errno)); | ||
242 | close(fd); | ||
243 | exit(EXIT_FAILURE); | ||
244 | } | ||
245 | nl_group = CN_VSS_IDX; | ||
246 | if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &nl_group, sizeof(nl_group)) < 0) { | ||
247 | syslog(LOG_ERR, "setsockopt failed; error:%d %s", errno, strerror(errno)); | ||
248 | close(fd); | ||
249 | exit(EXIT_FAILURE); | 183 | exit(EXIT_FAILURE); |
250 | } | 184 | } |
251 | /* | 185 | /* |
252 | * Register ourselves with the kernel. | 186 | * Register ourselves with the kernel. |
253 | */ | 187 | */ |
254 | message = (struct cn_msg *)vss_recv_buffer; | 188 | vss_msg->vss_hdr.operation = VSS_OP_REGISTER1; |
255 | message->id.idx = CN_VSS_IDX; | ||
256 | message->id.val = CN_VSS_VAL; | ||
257 | message->ack = 0; | ||
258 | vss_msg = (struct hv_vss_msg *)message->data; | ||
259 | vss_msg->vss_hdr.operation = VSS_OP_REGISTER; | ||
260 | 189 | ||
261 | message->len = sizeof(struct hv_vss_msg); | 190 | len = write(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
262 | |||
263 | len = netlink_send(fd, message); | ||
264 | if (len < 0) { | 191 | if (len < 0) { |
265 | syslog(LOG_ERR, "netlink_send failed; error:%d %s", errno, strerror(errno)); | 192 | syslog(LOG_ERR, "registration to kernel failed; error: %d %s", |
266 | close(fd); | 193 | errno, strerror(errno)); |
194 | close(vss_fd); | ||
267 | exit(EXIT_FAILURE); | 195 | exit(EXIT_FAILURE); |
268 | } | 196 | } |
269 | 197 | ||
270 | pfd.fd = fd; | 198 | pfd.fd = vss_fd; |
271 | 199 | ||
272 | while (1) { | 200 | while (1) { |
273 | struct sockaddr *addr_p = (struct sockaddr *) &addr; | ||
274 | socklen_t addr_l = sizeof(addr); | ||
275 | pfd.events = POLLIN; | 201 | pfd.events = POLLIN; |
276 | pfd.revents = 0; | 202 | pfd.revents = 0; |
277 | 203 | ||
278 | if (poll(&pfd, 1, -1) < 0) { | 204 | if (poll(&pfd, 1, -1) < 0) { |
279 | syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); | 205 | syslog(LOG_ERR, "poll failed; error:%d %s", errno, strerror(errno)); |
280 | if (errno == EINVAL) { | 206 | if (errno == EINVAL) { |
281 | close(fd); | 207 | close(vss_fd); |
282 | exit(EXIT_FAILURE); | 208 | exit(EXIT_FAILURE); |
283 | } | 209 | } |
284 | else | 210 | else |
285 | continue; | 211 | continue; |
286 | } | 212 | } |
287 | 213 | ||
288 | len = recvfrom(fd, vss_recv_buffer, vss_recv_buffer_len, 0, | 214 | len = read(vss_fd, vss_msg, sizeof(struct hv_vss_msg)); |
289 | addr_p, &addr_l); | ||
290 | 215 | ||
291 | if (len < 0) { | 216 | if (in_handshake) { |
292 | syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", | 217 | if (len != sizeof(kernel_modver)) { |
293 | addr.nl_pid, errno, strerror(errno)); | 218 | syslog(LOG_ERR, "invalid version negotiation"); |
294 | close(fd); | 219 | exit(EXIT_FAILURE); |
295 | return -1; | 220 | } |
296 | } | 221 | kernel_modver = *(__u32 *)vss_msg; |
297 | 222 | in_handshake = 0; | |
298 | if (addr.nl_pid) { | 223 | syslog(LOG_INFO, "VSS: kernel module version: %d", |
299 | syslog(LOG_WARNING, | 224 | kernel_modver); |
300 | "Received packet from untrusted pid:%u", | ||
301 | addr.nl_pid); | ||
302 | continue; | 225 | continue; |
303 | } | 226 | } |
304 | 227 | ||
305 | incoming_msg = (struct nlmsghdr *)vss_recv_buffer; | 228 | if (len != sizeof(struct hv_vss_msg)) { |
306 | 229 | syslog(LOG_ERR, "read failed; error:%d %s", | |
307 | if (incoming_msg->nlmsg_type != NLMSG_DONE) | 230 | errno, strerror(errno)); |
308 | continue; | 231 | close(vss_fd); |
232 | return EXIT_FAILURE; | ||
233 | } | ||
309 | 234 | ||
310 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); | ||
311 | vss_msg = (struct hv_vss_msg *)incoming_cn_msg->data; | ||
312 | op = vss_msg->vss_hdr.operation; | 235 | op = vss_msg->vss_hdr.operation; |
313 | error = HV_S_OK; | 236 | error = HV_S_OK; |
314 | 237 | ||
@@ -331,12 +254,14 @@ int main(int argc, char *argv[]) | |||
331 | syslog(LOG_ERR, "Illegal op:%d\n", op); | 254 | syslog(LOG_ERR, "Illegal op:%d\n", op); |
332 | } | 255 | } |
333 | vss_msg->error = error; | 256 | vss_msg->error = error; |
334 | len = netlink_send(fd, incoming_cn_msg); | 257 | len = write(vss_fd, &error, sizeof(struct hv_vss_msg)); |
335 | if (len < 0) { | 258 | if (len != sizeof(struct hv_vss_msg)) { |
336 | syslog(LOG_ERR, "net_link send failed; error:%d %s", | 259 | syslog(LOG_ERR, "write failed; error: %d %s", errno, |
337 | errno, strerror(errno)); | 260 | strerror(errno)); |
338 | exit(EXIT_FAILURE); | 261 | exit(EXIT_FAILURE); |
339 | } | 262 | } |
340 | } | 263 | } |
341 | 264 | ||
265 | close(vss_fd); | ||
266 | exit(0); | ||
342 | } | 267 | } |