staging: rtl8192u: remove redundant assignment to pointer crypt
[linux/fpc-iii.git] / tools / testing / vsock / vsock_diag_test.c
blobc481101364a4d07c06d1059544333765a436c671
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * vsock_diag_test - vsock_diag.ko test suite
5 * Copyright (C) 2017 Red Hat, Inc.
7 * Author: Stefan Hajnoczi <stefanha@redhat.com>
8 */
10 #include <getopt.h>
11 #include <stdio.h>
12 #include <stdbool.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <unistd.h>
17 #include <signal.h>
18 #include <sys/socket.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <linux/list.h>
22 #include <linux/net.h>
23 #include <linux/netlink.h>
24 #include <linux/sock_diag.h>
25 #include <netinet/tcp.h>
27 #include "../../../include/uapi/linux/vm_sockets.h"
28 #include "../../../include/uapi/linux/vm_sockets_diag.h"
30 #include "timeout.h"
31 #include "control.h"
33 enum test_mode {
34 TEST_MODE_UNSET,
35 TEST_MODE_CLIENT,
36 TEST_MODE_SERVER
39 /* Per-socket status */
40 struct vsock_stat {
41 struct list_head list;
42 struct vsock_diag_msg msg;
45 static const char *sock_type_str(int type)
47 switch (type) {
48 case SOCK_DGRAM:
49 return "DGRAM";
50 case SOCK_STREAM:
51 return "STREAM";
52 default:
53 return "INVALID TYPE";
57 static const char *sock_state_str(int state)
59 switch (state) {
60 case TCP_CLOSE:
61 return "UNCONNECTED";
62 case TCP_SYN_SENT:
63 return "CONNECTING";
64 case TCP_ESTABLISHED:
65 return "CONNECTED";
66 case TCP_CLOSING:
67 return "DISCONNECTING";
68 case TCP_LISTEN:
69 return "LISTEN";
70 default:
71 return "INVALID STATE";
75 static const char *sock_shutdown_str(int shutdown)
77 switch (shutdown) {
78 case 1:
79 return "RCV_SHUTDOWN";
80 case 2:
81 return "SEND_SHUTDOWN";
82 case 3:
83 return "RCV_SHUTDOWN | SEND_SHUTDOWN";
84 default:
85 return "0";
89 static void print_vsock_addr(FILE *fp, unsigned int cid, unsigned int port)
91 if (cid == VMADDR_CID_ANY)
92 fprintf(fp, "*:");
93 else
94 fprintf(fp, "%u:", cid);
96 if (port == VMADDR_PORT_ANY)
97 fprintf(fp, "*");
98 else
99 fprintf(fp, "%u", port);
102 static void print_vsock_stat(FILE *fp, struct vsock_stat *st)
104 print_vsock_addr(fp, st->msg.vdiag_src_cid, st->msg.vdiag_src_port);
105 fprintf(fp, " ");
106 print_vsock_addr(fp, st->msg.vdiag_dst_cid, st->msg.vdiag_dst_port);
107 fprintf(fp, " %s %s %s %u\n",
108 sock_type_str(st->msg.vdiag_type),
109 sock_state_str(st->msg.vdiag_state),
110 sock_shutdown_str(st->msg.vdiag_shutdown),
111 st->msg.vdiag_ino);
114 static void print_vsock_stats(FILE *fp, struct list_head *head)
116 struct vsock_stat *st;
118 list_for_each_entry(st, head, list)
119 print_vsock_stat(fp, st);
122 static struct vsock_stat *find_vsock_stat(struct list_head *head, int fd)
124 struct vsock_stat *st;
125 struct stat stat;
127 if (fstat(fd, &stat) < 0) {
128 perror("fstat");
129 exit(EXIT_FAILURE);
132 list_for_each_entry(st, head, list)
133 if (st->msg.vdiag_ino == stat.st_ino)
134 return st;
136 fprintf(stderr, "cannot find fd %d\n", fd);
137 exit(EXIT_FAILURE);
140 static void check_no_sockets(struct list_head *head)
142 if (!list_empty(head)) {
143 fprintf(stderr, "expected no sockets\n");
144 print_vsock_stats(stderr, head);
145 exit(1);
149 static void check_num_sockets(struct list_head *head, int expected)
151 struct list_head *node;
152 int n = 0;
154 list_for_each(node, head)
155 n++;
157 if (n != expected) {
158 fprintf(stderr, "expected %d sockets, found %d\n",
159 expected, n);
160 print_vsock_stats(stderr, head);
161 exit(EXIT_FAILURE);
165 static void check_socket_state(struct vsock_stat *st, __u8 state)
167 if (st->msg.vdiag_state != state) {
168 fprintf(stderr, "expected socket state %#x, got %#x\n",
169 state, st->msg.vdiag_state);
170 exit(EXIT_FAILURE);
174 static void send_req(int fd)
176 struct sockaddr_nl nladdr = {
177 .nl_family = AF_NETLINK,
179 struct {
180 struct nlmsghdr nlh;
181 struct vsock_diag_req vreq;
182 } req = {
183 .nlh = {
184 .nlmsg_len = sizeof(req),
185 .nlmsg_type = SOCK_DIAG_BY_FAMILY,
186 .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
188 .vreq = {
189 .sdiag_family = AF_VSOCK,
190 .vdiag_states = ~(__u32)0,
193 struct iovec iov = {
194 .iov_base = &req,
195 .iov_len = sizeof(req),
197 struct msghdr msg = {
198 .msg_name = &nladdr,
199 .msg_namelen = sizeof(nladdr),
200 .msg_iov = &iov,
201 .msg_iovlen = 1,
204 for (;;) {
205 if (sendmsg(fd, &msg, 0) < 0) {
206 if (errno == EINTR)
207 continue;
209 perror("sendmsg");
210 exit(EXIT_FAILURE);
213 return;
217 static ssize_t recv_resp(int fd, void *buf, size_t len)
219 struct sockaddr_nl nladdr = {
220 .nl_family = AF_NETLINK,
222 struct iovec iov = {
223 .iov_base = buf,
224 .iov_len = len,
226 struct msghdr msg = {
227 .msg_name = &nladdr,
228 .msg_namelen = sizeof(nladdr),
229 .msg_iov = &iov,
230 .msg_iovlen = 1,
232 ssize_t ret;
234 do {
235 ret = recvmsg(fd, &msg, 0);
236 } while (ret < 0 && errno == EINTR);
238 if (ret < 0) {
239 perror("recvmsg");
240 exit(EXIT_FAILURE);
243 return ret;
246 static void add_vsock_stat(struct list_head *sockets,
247 const struct vsock_diag_msg *resp)
249 struct vsock_stat *st;
251 st = malloc(sizeof(*st));
252 if (!st) {
253 perror("malloc");
254 exit(EXIT_FAILURE);
257 st->msg = *resp;
258 list_add_tail(&st->list, sockets);
262 * Read vsock stats into a list.
264 static void read_vsock_stat(struct list_head *sockets)
266 long buf[8192 / sizeof(long)];
267 int fd;
269 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
270 if (fd < 0) {
271 perror("socket");
272 exit(EXIT_FAILURE);
275 send_req(fd);
277 for (;;) {
278 const struct nlmsghdr *h;
279 ssize_t ret;
281 ret = recv_resp(fd, buf, sizeof(buf));
282 if (ret == 0)
283 goto done;
284 if (ret < sizeof(*h)) {
285 fprintf(stderr, "short read of %zd bytes\n", ret);
286 exit(EXIT_FAILURE);
289 h = (struct nlmsghdr *)buf;
291 while (NLMSG_OK(h, ret)) {
292 if (h->nlmsg_type == NLMSG_DONE)
293 goto done;
295 if (h->nlmsg_type == NLMSG_ERROR) {
296 const struct nlmsgerr *err = NLMSG_DATA(h);
298 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
299 fprintf(stderr, "NLMSG_ERROR\n");
300 else {
301 errno = -err->error;
302 perror("NLMSG_ERROR");
305 exit(EXIT_FAILURE);
308 if (h->nlmsg_type != SOCK_DIAG_BY_FAMILY) {
309 fprintf(stderr, "unexpected nlmsg_type %#x\n",
310 h->nlmsg_type);
311 exit(EXIT_FAILURE);
313 if (h->nlmsg_len <
314 NLMSG_LENGTH(sizeof(struct vsock_diag_msg))) {
315 fprintf(stderr, "short vsock_diag_msg\n");
316 exit(EXIT_FAILURE);
319 add_vsock_stat(sockets, NLMSG_DATA(h));
321 h = NLMSG_NEXT(h, ret);
325 done:
326 close(fd);
329 static void free_sock_stat(struct list_head *sockets)
331 struct vsock_stat *st;
332 struct vsock_stat *next;
334 list_for_each_entry_safe(st, next, sockets, list)
335 free(st);
338 static void test_no_sockets(unsigned int peer_cid)
340 LIST_HEAD(sockets);
342 read_vsock_stat(&sockets);
344 check_no_sockets(&sockets);
346 free_sock_stat(&sockets);
349 static void test_listen_socket_server(unsigned int peer_cid)
351 union {
352 struct sockaddr sa;
353 struct sockaddr_vm svm;
354 } addr = {
355 .svm = {
356 .svm_family = AF_VSOCK,
357 .svm_port = 1234,
358 .svm_cid = VMADDR_CID_ANY,
361 LIST_HEAD(sockets);
362 struct vsock_stat *st;
363 int fd;
365 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
367 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
368 perror("bind");
369 exit(EXIT_FAILURE);
372 if (listen(fd, 1) < 0) {
373 perror("listen");
374 exit(EXIT_FAILURE);
377 read_vsock_stat(&sockets);
379 check_num_sockets(&sockets, 1);
380 st = find_vsock_stat(&sockets, fd);
381 check_socket_state(st, TCP_LISTEN);
383 close(fd);
384 free_sock_stat(&sockets);
387 static void test_connect_client(unsigned int peer_cid)
389 union {
390 struct sockaddr sa;
391 struct sockaddr_vm svm;
392 } addr = {
393 .svm = {
394 .svm_family = AF_VSOCK,
395 .svm_port = 1234,
396 .svm_cid = peer_cid,
399 int fd;
400 int ret;
401 LIST_HEAD(sockets);
402 struct vsock_stat *st;
404 control_expectln("LISTENING");
406 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
408 timeout_begin(TIMEOUT);
409 do {
410 ret = connect(fd, &addr.sa, sizeof(addr.svm));
411 timeout_check("connect");
412 } while (ret < 0 && errno == EINTR);
413 timeout_end();
415 if (ret < 0) {
416 perror("connect");
417 exit(EXIT_FAILURE);
420 read_vsock_stat(&sockets);
422 check_num_sockets(&sockets, 1);
423 st = find_vsock_stat(&sockets, fd);
424 check_socket_state(st, TCP_ESTABLISHED);
426 control_expectln("DONE");
427 control_writeln("DONE");
429 close(fd);
430 free_sock_stat(&sockets);
433 static void test_connect_server(unsigned int peer_cid)
435 union {
436 struct sockaddr sa;
437 struct sockaddr_vm svm;
438 } addr = {
439 .svm = {
440 .svm_family = AF_VSOCK,
441 .svm_port = 1234,
442 .svm_cid = VMADDR_CID_ANY,
445 union {
446 struct sockaddr sa;
447 struct sockaddr_vm svm;
448 } clientaddr;
449 socklen_t clientaddr_len = sizeof(clientaddr.svm);
450 LIST_HEAD(sockets);
451 struct vsock_stat *st;
452 int fd;
453 int client_fd;
455 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
457 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
458 perror("bind");
459 exit(EXIT_FAILURE);
462 if (listen(fd, 1) < 0) {
463 perror("listen");
464 exit(EXIT_FAILURE);
467 control_writeln("LISTENING");
469 timeout_begin(TIMEOUT);
470 do {
471 client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
472 timeout_check("accept");
473 } while (client_fd < 0 && errno == EINTR);
474 timeout_end();
476 if (client_fd < 0) {
477 perror("accept");
478 exit(EXIT_FAILURE);
480 if (clientaddr.sa.sa_family != AF_VSOCK) {
481 fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
482 clientaddr.sa.sa_family);
483 exit(EXIT_FAILURE);
485 if (clientaddr.svm.svm_cid != peer_cid) {
486 fprintf(stderr, "expected peer CID %u from accept(2), got %u\n",
487 peer_cid, clientaddr.svm.svm_cid);
488 exit(EXIT_FAILURE);
491 read_vsock_stat(&sockets);
493 check_num_sockets(&sockets, 2);
494 find_vsock_stat(&sockets, fd);
495 st = find_vsock_stat(&sockets, client_fd);
496 check_socket_state(st, TCP_ESTABLISHED);
498 control_writeln("DONE");
499 control_expectln("DONE");
501 close(client_fd);
502 close(fd);
503 free_sock_stat(&sockets);
506 static struct {
507 const char *name;
508 void (*run_client)(unsigned int peer_cid);
509 void (*run_server)(unsigned int peer_cid);
510 } test_cases[] = {
512 .name = "No sockets",
513 .run_server = test_no_sockets,
516 .name = "Listen socket",
517 .run_server = test_listen_socket_server,
520 .name = "Connect",
521 .run_client = test_connect_client,
522 .run_server = test_connect_server,
527 static void init_signals(void)
529 struct sigaction act = {
530 .sa_handler = sigalrm,
533 sigaction(SIGALRM, &act, NULL);
534 signal(SIGPIPE, SIG_IGN);
537 static unsigned int parse_cid(const char *str)
539 char *endptr = NULL;
540 unsigned long int n;
542 errno = 0;
543 n = strtoul(str, &endptr, 10);
544 if (errno || *endptr != '\0') {
545 fprintf(stderr, "malformed CID \"%s\"\n", str);
546 exit(EXIT_FAILURE);
548 return n;
551 static const char optstring[] = "";
552 static const struct option longopts[] = {
554 .name = "control-host",
555 .has_arg = required_argument,
556 .val = 'H',
559 .name = "control-port",
560 .has_arg = required_argument,
561 .val = 'P',
564 .name = "mode",
565 .has_arg = required_argument,
566 .val = 'm',
569 .name = "peer-cid",
570 .has_arg = required_argument,
571 .val = 'p',
574 .name = "help",
575 .has_arg = no_argument,
576 .val = '?',
581 static void usage(void)
583 fprintf(stderr, "Usage: vsock_diag_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid>\n"
584 "\n"
585 " Server: vsock_diag_test --control-port=1234 --mode=server --peer-cid=3\n"
586 " Client: vsock_diag_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
587 "\n"
588 "Run vsock_diag.ko tests. Must be launched in both\n"
589 "guest and host. One side must use --mode=client and\n"
590 "the other side must use --mode=server.\n"
591 "\n"
592 "A TCP control socket connection is used to coordinate tests\n"
593 "between the client and the server. The server requires a\n"
594 "listen address and the client requires an address to\n"
595 "connect to.\n"
596 "\n"
597 "The CID of the other side must be given with --peer-cid=<cid>.\n");
598 exit(EXIT_FAILURE);
601 int main(int argc, char **argv)
603 const char *control_host = NULL;
604 const char *control_port = NULL;
605 int mode = TEST_MODE_UNSET;
606 unsigned int peer_cid = VMADDR_CID_ANY;
607 int i;
609 init_signals();
611 for (;;) {
612 int opt = getopt_long(argc, argv, optstring, longopts, NULL);
614 if (opt == -1)
615 break;
617 switch (opt) {
618 case 'H':
619 control_host = optarg;
620 break;
621 case 'm':
622 if (strcmp(optarg, "client") == 0)
623 mode = TEST_MODE_CLIENT;
624 else if (strcmp(optarg, "server") == 0)
625 mode = TEST_MODE_SERVER;
626 else {
627 fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
628 return EXIT_FAILURE;
630 break;
631 case 'p':
632 peer_cid = parse_cid(optarg);
633 break;
634 case 'P':
635 control_port = optarg;
636 break;
637 case '?':
638 default:
639 usage();
643 if (!control_port)
644 usage();
645 if (mode == TEST_MODE_UNSET)
646 usage();
647 if (peer_cid == VMADDR_CID_ANY)
648 usage();
650 if (!control_host) {
651 if (mode != TEST_MODE_SERVER)
652 usage();
653 control_host = "0.0.0.0";
656 control_init(control_host, control_port, mode == TEST_MODE_SERVER);
658 for (i = 0; test_cases[i].name; i++) {
659 void (*run)(unsigned int peer_cid);
661 printf("%s...", test_cases[i].name);
662 fflush(stdout);
664 if (mode == TEST_MODE_CLIENT)
665 run = test_cases[i].run_client;
666 else
667 run = test_cases[i].run_server;
669 if (run)
670 run(peer_cid);
672 printf("ok\n");
675 control_cleanup();
676 return EXIT_SUCCESS;