qed: Fix static checker warning
[linux/fpc-iii.git] / tools / testing / vsock / vsock_diag_test.c
blobe896a4af52f4025b5905175d84c0d0c1d5aa0c6b
1 /*
2 * vsock_diag_test - vsock_diag.ko test suite
4 * Copyright (C) 2017 Red Hat, Inc.
6 * Author: Stefan Hajnoczi <stefanha@redhat.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
14 #include <getopt.h>
15 #include <stdio.h>
16 #include <stdbool.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <signal.h>
22 #include <sys/socket.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <linux/list.h>
26 #include <linux/net.h>
27 #include <linux/netlink.h>
28 #include <linux/sock_diag.h>
29 #include <netinet/tcp.h>
31 #include "../../../include/uapi/linux/vm_sockets.h"
32 #include "../../../include/uapi/linux/vm_sockets_diag.h"
34 #include "timeout.h"
35 #include "control.h"
37 enum test_mode {
38 TEST_MODE_UNSET,
39 TEST_MODE_CLIENT,
40 TEST_MODE_SERVER
43 /* Per-socket status */
44 struct vsock_stat {
45 struct list_head list;
46 struct vsock_diag_msg msg;
49 static const char *sock_type_str(int type)
51 switch (type) {
52 case SOCK_DGRAM:
53 return "DGRAM";
54 case SOCK_STREAM:
55 return "STREAM";
56 default:
57 return "INVALID TYPE";
61 static const char *sock_state_str(int state)
63 switch (state) {
64 case TCP_CLOSE:
65 return "UNCONNECTED";
66 case TCP_SYN_SENT:
67 return "CONNECTING";
68 case TCP_ESTABLISHED:
69 return "CONNECTED";
70 case TCP_CLOSING:
71 return "DISCONNECTING";
72 case TCP_LISTEN:
73 return "LISTEN";
74 default:
75 return "INVALID STATE";
79 static const char *sock_shutdown_str(int shutdown)
81 switch (shutdown) {
82 case 1:
83 return "RCV_SHUTDOWN";
84 case 2:
85 return "SEND_SHUTDOWN";
86 case 3:
87 return "RCV_SHUTDOWN | SEND_SHUTDOWN";
88 default:
89 return "0";
93 static void print_vsock_addr(FILE *fp, unsigned int cid, unsigned int port)
95 if (cid == VMADDR_CID_ANY)
96 fprintf(fp, "*:");
97 else
98 fprintf(fp, "%u:", cid);
100 if (port == VMADDR_PORT_ANY)
101 fprintf(fp, "*");
102 else
103 fprintf(fp, "%u", port);
106 static void print_vsock_stat(FILE *fp, struct vsock_stat *st)
108 print_vsock_addr(fp, st->msg.vdiag_src_cid, st->msg.vdiag_src_port);
109 fprintf(fp, " ");
110 print_vsock_addr(fp, st->msg.vdiag_dst_cid, st->msg.vdiag_dst_port);
111 fprintf(fp, " %s %s %s %u\n",
112 sock_type_str(st->msg.vdiag_type),
113 sock_state_str(st->msg.vdiag_state),
114 sock_shutdown_str(st->msg.vdiag_shutdown),
115 st->msg.vdiag_ino);
118 static void print_vsock_stats(FILE *fp, struct list_head *head)
120 struct vsock_stat *st;
122 list_for_each_entry(st, head, list)
123 print_vsock_stat(fp, st);
126 static struct vsock_stat *find_vsock_stat(struct list_head *head, int fd)
128 struct vsock_stat *st;
129 struct stat stat;
131 if (fstat(fd, &stat) < 0) {
132 perror("fstat");
133 exit(EXIT_FAILURE);
136 list_for_each_entry(st, head, list)
137 if (st->msg.vdiag_ino == stat.st_ino)
138 return st;
140 fprintf(stderr, "cannot find fd %d\n", fd);
141 exit(EXIT_FAILURE);
144 static void check_no_sockets(struct list_head *head)
146 if (!list_empty(head)) {
147 fprintf(stderr, "expected no sockets\n");
148 print_vsock_stats(stderr, head);
149 exit(1);
153 static void check_num_sockets(struct list_head *head, int expected)
155 struct list_head *node;
156 int n = 0;
158 list_for_each(node, head)
159 n++;
161 if (n != expected) {
162 fprintf(stderr, "expected %d sockets, found %d\n",
163 expected, n);
164 print_vsock_stats(stderr, head);
165 exit(EXIT_FAILURE);
169 static void check_socket_state(struct vsock_stat *st, __u8 state)
171 if (st->msg.vdiag_state != state) {
172 fprintf(stderr, "expected socket state %#x, got %#x\n",
173 state, st->msg.vdiag_state);
174 exit(EXIT_FAILURE);
178 static void send_req(int fd)
180 struct sockaddr_nl nladdr = {
181 .nl_family = AF_NETLINK,
183 struct {
184 struct nlmsghdr nlh;
185 struct vsock_diag_req vreq;
186 } req = {
187 .nlh = {
188 .nlmsg_len = sizeof(req),
189 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
190 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
192 .vreq = {
193 .sdiag_family = AF_VSOCK,
194 .vdiag_states = ~(__u32)0,
197 struct iovec iov = {
198 .iov_base = &req,
199 .iov_len = sizeof(req),
201 struct msghdr msg = {
202 .msg_name = &nladdr,
203 .msg_namelen = sizeof(nladdr),
204 .msg_iov = &iov,
205 .msg_iovlen = 1,
208 for (;;) {
209 if (sendmsg(fd, &msg, 0) < 0) {
210 if (errno == EINTR)
211 continue;
213 perror("sendmsg");
214 exit(EXIT_FAILURE);
217 return;
221 static ssize_t recv_resp(int fd, void *buf, size_t len)
223 struct sockaddr_nl nladdr = {
224 .nl_family = AF_NETLINK,
226 struct iovec iov = {
227 .iov_base = buf,
228 .iov_len = len,
230 struct msghdr msg = {
231 .msg_name = &nladdr,
232 .msg_namelen = sizeof(nladdr),
233 .msg_iov = &iov,
234 .msg_iovlen = 1,
236 ssize_t ret;
238 do {
239 ret = recvmsg(fd, &msg, 0);
240 } while (ret < 0 && errno == EINTR);
242 if (ret < 0) {
243 perror("recvmsg");
244 exit(EXIT_FAILURE);
247 return ret;
250 static void add_vsock_stat(struct list_head *sockets,
251 const struct vsock_diag_msg *resp)
253 struct vsock_stat *st;
255 st = malloc(sizeof(*st));
256 if (!st) {
257 perror("malloc");
258 exit(EXIT_FAILURE);
261 st->msg = *resp;
262 list_add_tail(&st->list, sockets);
266 * Read vsock stats into a list.
268 static void read_vsock_stat(struct list_head *sockets)
270 long buf[8192 / sizeof(long)];
271 int fd;
273 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
274 if (fd < 0) {
275 perror("socket");
276 exit(EXIT_FAILURE);
279 send_req(fd);
281 for (;;) {
282 const struct nlmsghdr *h;
283 ssize_t ret;
285 ret = recv_resp(fd, buf, sizeof(buf));
286 if (ret == 0)
287 goto done;
288 if (ret < sizeof(*h)) {
289 fprintf(stderr, "short read of %zd bytes\n", ret);
290 exit(EXIT_FAILURE);
293 h = (struct nlmsghdr *)buf;
295 while (NLMSG_OK(h, ret)) {
296 if (h->nlmsg_type == NLMSG_DONE)
297 goto done;
299 if (h->nlmsg_type == NLMSG_ERROR) {
300 const struct nlmsgerr *err = NLMSG_DATA(h);
302 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
303 fprintf(stderr, "NLMSG_ERROR\n");
304 else {
305 errno = -err->error;
306 perror("NLMSG_ERROR");
309 exit(EXIT_FAILURE);
312 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
313 fprintf(stderr, "unexpected nlmsg_type %#x\n",
314 h->nlmsg_type);
315 exit(EXIT_FAILURE);
317 if (h->nlmsg_len <
318 NLMSG_LENGTH(sizeof(struct vsock_diag_msg))) {
319 fprintf(stderr, "short vsock_diag_msg\n");
320 exit(EXIT_FAILURE);
323 add_vsock_stat(sockets, NLMSG_DATA(h));
325 h = NLMSG_NEXT(h, ret);
329 done:
330 close(fd);
333 static void free_sock_stat(struct list_head *sockets)
335 struct vsock_stat *st;
336 struct vsock_stat *next;
338 list_for_each_entry_safe(st, next, sockets, list)
339 free(st);
342 static void test_no_sockets(unsigned int peer_cid)
344 LIST_HEAD(sockets);
346 read_vsock_stat(&sockets);
348 check_no_sockets(&sockets);
350 free_sock_stat(&sockets);
353 static void test_listen_socket_server(unsigned int peer_cid)
355 union {
356 struct sockaddr sa;
357 struct sockaddr_vm svm;
358 } addr = {
359 .svm = {
360 .svm_family = AF_VSOCK,
361 .svm_port = 1234,
362 .svm_cid = VMADDR_CID_ANY,
365 LIST_HEAD(sockets);
366 struct vsock_stat *st;
367 int fd;
369 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
371 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
372 perror("bind");
373 exit(EXIT_FAILURE);
376 if (listen(fd, 1) < 0) {
377 perror("listen");
378 exit(EXIT_FAILURE);
381 read_vsock_stat(&sockets);
383 check_num_sockets(&sockets, 1);
384 st = find_vsock_stat(&sockets, fd);
385 check_socket_state(st, TCP_LISTEN);
387 close(fd);
388 free_sock_stat(&sockets);
391 static void test_connect_client(unsigned int peer_cid)
393 union {
394 struct sockaddr sa;
395 struct sockaddr_vm svm;
396 } addr = {
397 .svm = {
398 .svm_family = AF_VSOCK,
399 .svm_port = 1234,
400 .svm_cid = peer_cid,
403 int fd;
404 int ret;
405 LIST_HEAD(sockets);
406 struct vsock_stat *st;
408 control_expectln("LISTENING");
410 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
412 timeout_begin(TIMEOUT);
413 do {
414 ret = connect(fd, &addr.sa, sizeof(addr.svm));
415 timeout_check("connect");
416 } while (ret < 0 && errno == EINTR);
417 timeout_end();
419 if (ret < 0) {
420 perror("connect");
421 exit(EXIT_FAILURE);
424 read_vsock_stat(&sockets);
426 check_num_sockets(&sockets, 1);
427 st = find_vsock_stat(&sockets, fd);
428 check_socket_state(st, TCP_ESTABLISHED);
430 control_expectln("DONE");
431 control_writeln("DONE");
433 close(fd);
434 free_sock_stat(&sockets);
437 static void test_connect_server(unsigned int peer_cid)
439 union {
440 struct sockaddr sa;
441 struct sockaddr_vm svm;
442 } addr = {
443 .svm = {
444 .svm_family = AF_VSOCK,
445 .svm_port = 1234,
446 .svm_cid = VMADDR_CID_ANY,
449 union {
450 struct sockaddr sa;
451 struct sockaddr_vm svm;
452 } clientaddr;
453 socklen_t clientaddr_len = sizeof(clientaddr.svm);
454 LIST_HEAD(sockets);
455 struct vsock_stat *st;
456 int fd;
457 int client_fd;
459 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
461 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
462 perror("bind");
463 exit(EXIT_FAILURE);
466 if (listen(fd, 1) < 0) {
467 perror("listen");
468 exit(EXIT_FAILURE);
471 control_writeln("LISTENING");
473 timeout_begin(TIMEOUT);
474 do {
475 client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
476 timeout_check("accept");
477 } while (client_fd < 0 && errno == EINTR);
478 timeout_end();
480 if (client_fd < 0) {
481 perror("accept");
482 exit(EXIT_FAILURE);
484 if (clientaddr.sa.sa_family != AF_VSOCK) {
485 fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
486 clientaddr.sa.sa_family);
487 exit(EXIT_FAILURE);
489 if (clientaddr.svm.svm_cid != peer_cid) {
490 fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
491 peer_cid, clientaddr.svm.svm_cid);
492 exit(EXIT_FAILURE);
495 read_vsock_stat(&sockets);
497 check_num_sockets(&sockets, 2);
498 find_vsock_stat(&sockets, fd);
499 st = find_vsock_stat(&sockets, client_fd);
500 check_socket_state(st, TCP_ESTABLISHED);
502 control_writeln("DONE");
503 control_expectln("DONE");
505 close(client_fd);
506 close(fd);
507 free_sock_stat(&sockets);
510 static struct {
511 const char *name;
512 void (*run_client)(unsigned int peer_cid);
513 void (*run_server)(unsigned int peer_cid);
514 } test_cases[] = {
516 .name = "No sockets",
517 .run_server = test_no_sockets,
520 .name = "Listen socket",
521 .run_server = test_listen_socket_server,
524 .name = "Connect",
525 .run_client = test_connect_client,
526 .run_server = test_connect_server,
531 static void init_signals(void)
533 struct sigaction act = {
534 .sa_handler = sigalrm,
537 sigaction(SIGALRM, &act, NULL);
538 signal(SIGPIPE, SIG_IGN);
541 static unsigned int parse_cid(const char *str)
543 char *endptr = NULL;
544 unsigned long int n;
546 errno = 0;
547 n = strtoul(str, &endptr, 10);
548 if (errno || *endptr != '\0') {
549 fprintf(stderr, "malformed CID \"%s\"\n", str);
550 exit(EXIT_FAILURE);
552 return n;
555 static const char optstring[] = "";
556 static const struct option longopts[] = {
558 .name = "control-host",
559 .has_arg = required_argument,
560 .val = 'H',
563 .name = "control-port",
564 .has_arg = required_argument,
565 .val = 'P',
568 .name = "mode",
569 .has_arg = required_argument,
570 .val = 'm',
573 .name = "peer-cid",
574 .has_arg = required_argument,
575 .val = 'p',
578 .name = "help",
579 .has_arg = no_argument,
580 .val = '?',
585 static void usage(void)
587 fprintf(stderr, "Usage: vsock_diag_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n"
588 "\n"
589 " Server: vsock_diag_test --control-port=1234 --mode=server --peer-cid=3\n"
590 " Client: vsock_diag_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
591 "\n"
592 "Run vsock_diag.ko tests. Must be launched in both\n"
593 "guest and host. One side must use --mode=client and\n"
594 "the other side must use --mode=server.\n"
595 "\n"
596 "A TCP control socket connection is used to coordinate tests\n"
597 "between the client and the server. The server requires a\n"
598 "listen address and the client requires an address to\n"
599 "connect to.\n"
600 "\n"
601 "The CID of the other side must be given with --peer-cid=<cid>.\n");
602 exit(EXIT_FAILURE);
605 int main(int argc, char **argv)
607 const char *control_host = NULL;
608 const char *control_port = NULL;
609 int mode = TEST_MODE_UNSET;
610 unsigned int peer_cid = VMADDR_CID_ANY;
611 int i;
613 init_signals();
615 for (;;) {
616 int opt = getopt_long(argc, argv, optstring, longopts, NULL);
618 if (opt == -1)
619 break;
621 switch (opt) {
622 case 'H':
623 control_host = optarg;
624 break;
625 case 'm':
626 if (strcmp(optarg, "client") == 0)
627 mode = TEST_MODE_CLIENT;
628 else if (strcmp(optarg, "server") == 0)
629 mode = TEST_MODE_SERVER;
630 else {
631 fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
632 return EXIT_FAILURE;
634 break;
635 case 'p':
636 peer_cid = parse_cid(optarg);
637 break;
638 case 'P':
639 control_port = optarg;
640 break;
641 case '?':
642 default:
643 usage();
647 if (!control_port)
648 usage();
649 if (mode == TEST_MODE_UNSET)
650 usage();
651 if (peer_cid == VMADDR_CID_ANY)
652 usage();
654 if (!control_host) {
655 if (mode != TEST_MODE_SERVER)
656 usage();
657 control_host = "0.0.0.0";
660 control_init(control_host, control_port, mode == TEST_MODE_SERVER);
662 for (i = 0; test_cases[i].name; i++) {
663 void (*run)(unsigned int peer_cid);
665 printf("%s...", test_cases[i].name);
666 fflush(stdout);
668 if (mode == TEST_MODE_CLIENT)
669 run = test_cases[i].run_client;
670 else
671 run = test_cases[i].run_server;
673 if (run)
674 run(peer_cid);
676 printf("ok\n");
679 control_cleanup();
680 return EXIT_SUCCESS;