0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <getopt.h>
0011 #include <stdio.h>
0012 #include <stdlib.h>
0013 #include <string.h>
0014 #include <errno.h>
0015 #include <unistd.h>
0016 #include <linux/kernel.h>
0017 #include <sys/types.h>
0018 #include <sys/socket.h>
0019 #include <time.h>
0020 #include <sys/mman.h>
0021
0022 #include "timeout.h"
0023 #include "control.h"
0024 #include "util.h"
0025
0026 static void test_stream_connection_reset(const struct test_opts *opts)
0027 {
0028 union {
0029 struct sockaddr sa;
0030 struct sockaddr_vm svm;
0031 } addr = {
0032 .svm = {
0033 .svm_family = AF_VSOCK,
0034 .svm_port = 1234,
0035 .svm_cid = opts->peer_cid,
0036 },
0037 };
0038 int ret;
0039 int fd;
0040
0041 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
0042
0043 timeout_begin(TIMEOUT);
0044 do {
0045 ret = connect(fd, &addr.sa, sizeof(addr.svm));
0046 timeout_check("connect");
0047 } while (ret < 0 && errno == EINTR);
0048 timeout_end();
0049
0050 if (ret != -1) {
0051 fprintf(stderr, "expected connect(2) failure, got %d\n", ret);
0052 exit(EXIT_FAILURE);
0053 }
0054 if (errno != ECONNRESET) {
0055 fprintf(stderr, "unexpected connect(2) errno %d\n", errno);
0056 exit(EXIT_FAILURE);
0057 }
0058
0059 close(fd);
0060 }
0061
0062 static void test_stream_bind_only_client(const struct test_opts *opts)
0063 {
0064 union {
0065 struct sockaddr sa;
0066 struct sockaddr_vm svm;
0067 } addr = {
0068 .svm = {
0069 .svm_family = AF_VSOCK,
0070 .svm_port = 1234,
0071 .svm_cid = opts->peer_cid,
0072 },
0073 };
0074 int ret;
0075 int fd;
0076
0077
0078 control_expectln("BIND");
0079
0080 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
0081
0082 timeout_begin(TIMEOUT);
0083 do {
0084 ret = connect(fd, &addr.sa, sizeof(addr.svm));
0085 timeout_check("connect");
0086 } while (ret < 0 && errno == EINTR);
0087 timeout_end();
0088
0089 if (ret != -1) {
0090 fprintf(stderr, "expected connect(2) failure, got %d\n", ret);
0091 exit(EXIT_FAILURE);
0092 }
0093 if (errno != ECONNRESET) {
0094 fprintf(stderr, "unexpected connect(2) errno %d\n", errno);
0095 exit(EXIT_FAILURE);
0096 }
0097
0098
0099 control_writeln("DONE");
0100
0101 close(fd);
0102 }
0103
0104 static void test_stream_bind_only_server(const struct test_opts *opts)
0105 {
0106 union {
0107 struct sockaddr sa;
0108 struct sockaddr_vm svm;
0109 } addr = {
0110 .svm = {
0111 .svm_family = AF_VSOCK,
0112 .svm_port = 1234,
0113 .svm_cid = VMADDR_CID_ANY,
0114 },
0115 };
0116 int fd;
0117
0118 fd = socket(AF_VSOCK, SOCK_STREAM, 0);
0119
0120 if (bind(fd, &addr.sa, sizeof(addr.svm)) < 0) {
0121 perror("bind");
0122 exit(EXIT_FAILURE);
0123 }
0124
0125
0126 control_writeln("BIND");
0127
0128
0129 control_expectln("DONE");
0130
0131 close(fd);
0132 }
0133
0134 static void test_stream_client_close_client(const struct test_opts *opts)
0135 {
0136 int fd;
0137
0138 fd = vsock_stream_connect(opts->peer_cid, 1234);
0139 if (fd < 0) {
0140 perror("connect");
0141 exit(EXIT_FAILURE);
0142 }
0143
0144 send_byte(fd, 1, 0);
0145 close(fd);
0146 }
0147
0148 static void test_stream_client_close_server(const struct test_opts *opts)
0149 {
0150 int fd;
0151
0152 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
0153 if (fd < 0) {
0154 perror("accept");
0155 exit(EXIT_FAILURE);
0156 }
0157
0158
0159
0160
0161 vsock_wait_remote_close(fd);
0162
0163 send_byte(fd, -EPIPE, 0);
0164 recv_byte(fd, 1, 0);
0165 recv_byte(fd, 0, 0);
0166 close(fd);
0167 }
0168
0169 static void test_stream_server_close_client(const struct test_opts *opts)
0170 {
0171 int fd;
0172
0173 fd = vsock_stream_connect(opts->peer_cid, 1234);
0174 if (fd < 0) {
0175 perror("connect");
0176 exit(EXIT_FAILURE);
0177 }
0178
0179
0180
0181
0182 vsock_wait_remote_close(fd);
0183
0184 send_byte(fd, -EPIPE, 0);
0185 recv_byte(fd, 1, 0);
0186 recv_byte(fd, 0, 0);
0187 close(fd);
0188 }
0189
0190 static void test_stream_server_close_server(const struct test_opts *opts)
0191 {
0192 int fd;
0193
0194 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
0195 if (fd < 0) {
0196 perror("accept");
0197 exit(EXIT_FAILURE);
0198 }
0199
0200 send_byte(fd, 1, 0);
0201 close(fd);
0202 }
0203
0204
0205
0206
0207 #define MULTICONN_NFDS 100
0208
0209 static void test_stream_multiconn_client(const struct test_opts *opts)
0210 {
0211 int fds[MULTICONN_NFDS];
0212 int i;
0213
0214 for (i = 0; i < MULTICONN_NFDS; i++) {
0215 fds[i] = vsock_stream_connect(opts->peer_cid, 1234);
0216 if (fds[i] < 0) {
0217 perror("connect");
0218 exit(EXIT_FAILURE);
0219 }
0220 }
0221
0222 for (i = 0; i < MULTICONN_NFDS; i++) {
0223 if (i % 2)
0224 recv_byte(fds[i], 1, 0);
0225 else
0226 send_byte(fds[i], 1, 0);
0227 }
0228
0229 for (i = 0; i < MULTICONN_NFDS; i++)
0230 close(fds[i]);
0231 }
0232
0233 static void test_stream_multiconn_server(const struct test_opts *opts)
0234 {
0235 int fds[MULTICONN_NFDS];
0236 int i;
0237
0238 for (i = 0; i < MULTICONN_NFDS; i++) {
0239 fds[i] = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
0240 if (fds[i] < 0) {
0241 perror("accept");
0242 exit(EXIT_FAILURE);
0243 }
0244 }
0245
0246 for (i = 0; i < MULTICONN_NFDS; i++) {
0247 if (i % 2)
0248 send_byte(fds[i], 1, 0);
0249 else
0250 recv_byte(fds[i], 1, 0);
0251 }
0252
0253 for (i = 0; i < MULTICONN_NFDS; i++)
0254 close(fds[i]);
0255 }
0256
0257 static void test_stream_msg_peek_client(const struct test_opts *opts)
0258 {
0259 int fd;
0260
0261 fd = vsock_stream_connect(opts->peer_cid, 1234);
0262 if (fd < 0) {
0263 perror("connect");
0264 exit(EXIT_FAILURE);
0265 }
0266
0267 send_byte(fd, 1, 0);
0268 close(fd);
0269 }
0270
0271 static void test_stream_msg_peek_server(const struct test_opts *opts)
0272 {
0273 int fd;
0274
0275 fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
0276 if (fd < 0) {
0277 perror("accept");
0278 exit(EXIT_FAILURE);
0279 }
0280
0281 recv_byte(fd, 1, MSG_PEEK);
0282 recv_byte(fd, 1, 0);
0283 close(fd);
0284 }
0285
0286 #define MESSAGES_CNT 7
0287 #define MSG_EOR_IDX (MESSAGES_CNT / 2)
0288 static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
0289 {
0290 int fd;
0291
0292 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
0293 if (fd < 0) {
0294 perror("connect");
0295 exit(EXIT_FAILURE);
0296 }
0297
0298
0299 for (int i = 0; i < MESSAGES_CNT; i++)
0300 send_byte(fd, 1, (i == MSG_EOR_IDX) ? MSG_EOR : 0);
0301
0302 control_writeln("SENDDONE");
0303 close(fd);
0304 }
0305
0306 static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
0307 {
0308 int fd;
0309 char buf[16];
0310 struct msghdr msg = {0};
0311 struct iovec iov = {0};
0312
0313 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
0314 if (fd < 0) {
0315 perror("accept");
0316 exit(EXIT_FAILURE);
0317 }
0318
0319 control_expectln("SENDDONE");
0320 iov.iov_base = buf;
0321 iov.iov_len = sizeof(buf);
0322 msg.msg_iov = &iov;
0323 msg.msg_iovlen = 1;
0324
0325 for (int i = 0; i < MESSAGES_CNT; i++) {
0326 if (recvmsg(fd, &msg, 0) != 1) {
0327 perror("message bound violated");
0328 exit(EXIT_FAILURE);
0329 }
0330
0331 if ((i == MSG_EOR_IDX) ^ !!(msg.msg_flags & MSG_EOR)) {
0332 perror("MSG_EOR");
0333 exit(EXIT_FAILURE);
0334 }
0335 }
0336
0337 close(fd);
0338 }
0339
0340 #define MESSAGE_TRUNC_SZ 32
0341 static void test_seqpacket_msg_trunc_client(const struct test_opts *opts)
0342 {
0343 int fd;
0344 char buf[MESSAGE_TRUNC_SZ];
0345
0346 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
0347 if (fd < 0) {
0348 perror("connect");
0349 exit(EXIT_FAILURE);
0350 }
0351
0352 if (send(fd, buf, sizeof(buf), 0) != sizeof(buf)) {
0353 perror("send failed");
0354 exit(EXIT_FAILURE);
0355 }
0356
0357 control_writeln("SENDDONE");
0358 close(fd);
0359 }
0360
0361 static void test_seqpacket_msg_trunc_server(const struct test_opts *opts)
0362 {
0363 int fd;
0364 char buf[MESSAGE_TRUNC_SZ / 2];
0365 struct msghdr msg = {0};
0366 struct iovec iov = {0};
0367
0368 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
0369 if (fd < 0) {
0370 perror("accept");
0371 exit(EXIT_FAILURE);
0372 }
0373
0374 control_expectln("SENDDONE");
0375 iov.iov_base = buf;
0376 iov.iov_len = sizeof(buf);
0377 msg.msg_iov = &iov;
0378 msg.msg_iovlen = 1;
0379
0380 ssize_t ret = recvmsg(fd, &msg, MSG_TRUNC);
0381
0382 if (ret != MESSAGE_TRUNC_SZ) {
0383 printf("%zi\n", ret);
0384 perror("MSG_TRUNC doesn't work");
0385 exit(EXIT_FAILURE);
0386 }
0387
0388 if (!(msg.msg_flags & MSG_TRUNC)) {
0389 fprintf(stderr, "MSG_TRUNC expected\n");
0390 exit(EXIT_FAILURE);
0391 }
0392
0393 close(fd);
0394 }
0395
0396 static time_t current_nsec(void)
0397 {
0398 struct timespec ts;
0399
0400 if (clock_gettime(CLOCK_REALTIME, &ts)) {
0401 perror("clock_gettime(3) failed");
0402 exit(EXIT_FAILURE);
0403 }
0404
0405 return (ts.tv_sec * 1000000000ULL) + ts.tv_nsec;
0406 }
0407
0408 #define RCVTIMEO_TIMEOUT_SEC 1
0409 #define READ_OVERHEAD_NSEC 250000000
0410
0411 static void test_seqpacket_timeout_client(const struct test_opts *opts)
0412 {
0413 int fd;
0414 struct timeval tv;
0415 char dummy;
0416 time_t read_enter_ns;
0417 time_t read_overhead_ns;
0418
0419 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
0420 if (fd < 0) {
0421 perror("connect");
0422 exit(EXIT_FAILURE);
0423 }
0424
0425 tv.tv_sec = RCVTIMEO_TIMEOUT_SEC;
0426 tv.tv_usec = 0;
0427
0428 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) {
0429 perror("setsockopt 'SO_RCVTIMEO'");
0430 exit(EXIT_FAILURE);
0431 }
0432
0433 read_enter_ns = current_nsec();
0434
0435 if (read(fd, &dummy, sizeof(dummy)) != -1) {
0436 fprintf(stderr,
0437 "expected 'dummy' read(2) failure\n");
0438 exit(EXIT_FAILURE);
0439 }
0440
0441 if (errno != EAGAIN) {
0442 perror("EAGAIN expected");
0443 exit(EXIT_FAILURE);
0444 }
0445
0446 read_overhead_ns = current_nsec() - read_enter_ns -
0447 1000000000ULL * RCVTIMEO_TIMEOUT_SEC;
0448
0449 if (read_overhead_ns > READ_OVERHEAD_NSEC) {
0450 fprintf(stderr,
0451 "too much time in read(2), %lu > %i ns\n",
0452 read_overhead_ns, READ_OVERHEAD_NSEC);
0453 exit(EXIT_FAILURE);
0454 }
0455
0456 control_writeln("WAITDONE");
0457 close(fd);
0458 }
0459
0460 static void test_seqpacket_timeout_server(const struct test_opts *opts)
0461 {
0462 int fd;
0463
0464 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
0465 if (fd < 0) {
0466 perror("accept");
0467 exit(EXIT_FAILURE);
0468 }
0469
0470 control_expectln("WAITDONE");
0471 close(fd);
0472 }
0473
0474 #define BUF_PATTERN_1 'a'
0475 #define BUF_PATTERN_2 'b'
0476
0477 static void test_seqpacket_invalid_rec_buffer_client(const struct test_opts *opts)
0478 {
0479 int fd;
0480 unsigned char *buf1;
0481 unsigned char *buf2;
0482 int buf_size = getpagesize() * 3;
0483
0484 fd = vsock_seqpacket_connect(opts->peer_cid, 1234);
0485 if (fd < 0) {
0486 perror("connect");
0487 exit(EXIT_FAILURE);
0488 }
0489
0490 buf1 = malloc(buf_size);
0491 if (!buf1) {
0492 perror("'malloc()' for 'buf1'");
0493 exit(EXIT_FAILURE);
0494 }
0495
0496 buf2 = malloc(buf_size);
0497 if (!buf2) {
0498 perror("'malloc()' for 'buf2'");
0499 exit(EXIT_FAILURE);
0500 }
0501
0502 memset(buf1, BUF_PATTERN_1, buf_size);
0503 memset(buf2, BUF_PATTERN_2, buf_size);
0504
0505 if (send(fd, buf1, buf_size, 0) != buf_size) {
0506 perror("send failed");
0507 exit(EXIT_FAILURE);
0508 }
0509
0510 if (send(fd, buf2, buf_size, 0) != buf_size) {
0511 perror("send failed");
0512 exit(EXIT_FAILURE);
0513 }
0514
0515 close(fd);
0516 }
0517
0518 static void test_seqpacket_invalid_rec_buffer_server(const struct test_opts *opts)
0519 {
0520 int fd;
0521 unsigned char *broken_buf;
0522 unsigned char *valid_buf;
0523 int page_size = getpagesize();
0524 int buf_size = page_size * 3;
0525 ssize_t res;
0526 int prot = PROT_READ | PROT_WRITE;
0527 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
0528 int i;
0529
0530 fd = vsock_seqpacket_accept(VMADDR_CID_ANY, 1234, NULL);
0531 if (fd < 0) {
0532 perror("accept");
0533 exit(EXIT_FAILURE);
0534 }
0535
0536
0537 broken_buf = mmap(NULL, buf_size, prot, flags, -1, 0);
0538 if (broken_buf == MAP_FAILED) {
0539 perror("mmap for 'broken_buf'");
0540 exit(EXIT_FAILURE);
0541 }
0542
0543
0544 if (munmap(broken_buf + page_size, page_size)) {
0545 perror("'broken_buf' setup");
0546 exit(EXIT_FAILURE);
0547 }
0548
0549 valid_buf = mmap(NULL, buf_size, prot, flags, -1, 0);
0550 if (valid_buf == MAP_FAILED) {
0551 perror("mmap for 'valid_buf'");
0552 exit(EXIT_FAILURE);
0553 }
0554
0555
0556 res = read(fd, broken_buf, buf_size);
0557 if (res != -1) {
0558 fprintf(stderr,
0559 "expected 'broken_buf' read(2) failure, got %zi\n",
0560 res);
0561 exit(EXIT_FAILURE);
0562 }
0563
0564 if (errno != ENOMEM) {
0565 perror("unexpected errno of 'broken_buf'");
0566 exit(EXIT_FAILURE);
0567 }
0568
0569
0570 res = read(fd, valid_buf, buf_size);
0571 if (res < 0) {
0572 perror("unexpected 'valid_buf' read(2) failure");
0573 exit(EXIT_FAILURE);
0574 }
0575
0576 if (res != buf_size) {
0577 fprintf(stderr,
0578 "invalid 'valid_buf' read(2), expected %i, got %zi\n",
0579 buf_size, res);
0580 exit(EXIT_FAILURE);
0581 }
0582
0583 for (i = 0; i < buf_size; i++) {
0584 if (valid_buf[i] != BUF_PATTERN_2) {
0585 fprintf(stderr,
0586 "invalid pattern for 'valid_buf' at %i, expected %hhX, got %hhX\n",
0587 i, BUF_PATTERN_2, valid_buf[i]);
0588 exit(EXIT_FAILURE);
0589 }
0590 }
0591
0592
0593 munmap(broken_buf, page_size);
0594 munmap(broken_buf + page_size * 2, page_size);
0595 munmap(valid_buf, buf_size);
0596 close(fd);
0597 }
0598
0599 static struct test_case test_cases[] = {
0600 {
0601 .name = "SOCK_STREAM connection reset",
0602 .run_client = test_stream_connection_reset,
0603 },
0604 {
0605 .name = "SOCK_STREAM bind only",
0606 .run_client = test_stream_bind_only_client,
0607 .run_server = test_stream_bind_only_server,
0608 },
0609 {
0610 .name = "SOCK_STREAM client close",
0611 .run_client = test_stream_client_close_client,
0612 .run_server = test_stream_client_close_server,
0613 },
0614 {
0615 .name = "SOCK_STREAM server close",
0616 .run_client = test_stream_server_close_client,
0617 .run_server = test_stream_server_close_server,
0618 },
0619 {
0620 .name = "SOCK_STREAM multiple connections",
0621 .run_client = test_stream_multiconn_client,
0622 .run_server = test_stream_multiconn_server,
0623 },
0624 {
0625 .name = "SOCK_STREAM MSG_PEEK",
0626 .run_client = test_stream_msg_peek_client,
0627 .run_server = test_stream_msg_peek_server,
0628 },
0629 {
0630 .name = "SOCK_SEQPACKET msg bounds",
0631 .run_client = test_seqpacket_msg_bounds_client,
0632 .run_server = test_seqpacket_msg_bounds_server,
0633 },
0634 {
0635 .name = "SOCK_SEQPACKET MSG_TRUNC flag",
0636 .run_client = test_seqpacket_msg_trunc_client,
0637 .run_server = test_seqpacket_msg_trunc_server,
0638 },
0639 {
0640 .name = "SOCK_SEQPACKET timeout",
0641 .run_client = test_seqpacket_timeout_client,
0642 .run_server = test_seqpacket_timeout_server,
0643 },
0644 {
0645 .name = "SOCK_SEQPACKET invalid receive buffer",
0646 .run_client = test_seqpacket_invalid_rec_buffer_client,
0647 .run_server = test_seqpacket_invalid_rec_buffer_server,
0648 },
0649 {},
0650 };
0651
0652 static const char optstring[] = "";
0653 static const struct option longopts[] = {
0654 {
0655 .name = "control-host",
0656 .has_arg = required_argument,
0657 .val = 'H',
0658 },
0659 {
0660 .name = "control-port",
0661 .has_arg = required_argument,
0662 .val = 'P',
0663 },
0664 {
0665 .name = "mode",
0666 .has_arg = required_argument,
0667 .val = 'm',
0668 },
0669 {
0670 .name = "peer-cid",
0671 .has_arg = required_argument,
0672 .val = 'p',
0673 },
0674 {
0675 .name = "list",
0676 .has_arg = no_argument,
0677 .val = 'l',
0678 },
0679 {
0680 .name = "skip",
0681 .has_arg = required_argument,
0682 .val = 's',
0683 },
0684 {
0685 .name = "help",
0686 .has_arg = no_argument,
0687 .val = '?',
0688 },
0689 {},
0690 };
0691
0692 static void usage(void)
0693 {
0694 fprintf(stderr, "Usage: vsock_test [--help] [--control-host=<host>] --control-port=<port> --mode=client|server --peer-cid=<cid> [--list] [--skip=<test_id>]\n"
0695 "\n"
0696 " Server: vsock_test --control-port=1234 --mode=server --peer-cid=3\n"
0697 " Client: vsock_test --control-host=192.168.0.1 --control-port=1234 --mode=client --peer-cid=2\n"
0698 "\n"
0699 "Run vsock.ko tests. Must be launched in both guest\n"
0700 "and host. One side must use --mode=client and\n"
0701 "the other side must use --mode=server.\n"
0702 "\n"
0703 "A TCP control socket connection is used to coordinate tests\n"
0704 "between the client and the server. The server requires a\n"
0705 "listen address and the client requires an address to\n"
0706 "connect to.\n"
0707 "\n"
0708 "The CID of the other side must be given with --peer-cid=<cid>.\n"
0709 "\n"
0710 "Options:\n"
0711 " --help This help message\n"
0712 " --control-host <host> Server IP address to connect to\n"
0713 " --control-port <port> Server port to listen on/connect to\n"
0714 " --mode client|server Server or client mode\n"
0715 " --peer-cid <cid> CID of the other side\n"
0716 " --list List of tests that will be executed\n"
0717 " --skip <test_id> Test ID to skip;\n"
0718 " use multiple --skip options to skip more tests\n"
0719 );
0720 exit(EXIT_FAILURE);
0721 }
0722
0723 int main(int argc, char **argv)
0724 {
0725 const char *control_host = NULL;
0726 const char *control_port = NULL;
0727 struct test_opts opts = {
0728 .mode = TEST_MODE_UNSET,
0729 .peer_cid = VMADDR_CID_ANY,
0730 };
0731
0732 init_signals();
0733
0734 for (;;) {
0735 int opt = getopt_long(argc, argv, optstring, longopts, NULL);
0736
0737 if (opt == -1)
0738 break;
0739
0740 switch (opt) {
0741 case 'H':
0742 control_host = optarg;
0743 break;
0744 case 'm':
0745 if (strcmp(optarg, "client") == 0)
0746 opts.mode = TEST_MODE_CLIENT;
0747 else if (strcmp(optarg, "server") == 0)
0748 opts.mode = TEST_MODE_SERVER;
0749 else {
0750 fprintf(stderr, "--mode must be \"client\" or \"server\"\n");
0751 return EXIT_FAILURE;
0752 }
0753 break;
0754 case 'p':
0755 opts.peer_cid = parse_cid(optarg);
0756 break;
0757 case 'P':
0758 control_port = optarg;
0759 break;
0760 case 'l':
0761 list_tests(test_cases);
0762 break;
0763 case 's':
0764 skip_test(test_cases, ARRAY_SIZE(test_cases) - 1,
0765 optarg);
0766 break;
0767 case '?':
0768 default:
0769 usage();
0770 }
0771 }
0772
0773 if (!control_port)
0774 usage();
0775 if (opts.mode == TEST_MODE_UNSET)
0776 usage();
0777 if (opts.peer_cid == VMADDR_CID_ANY)
0778 usage();
0779
0780 if (!control_host) {
0781 if (opts.mode != TEST_MODE_SERVER)
0782 usage();
0783 control_host = "0.0.0.0";
0784 }
0785
0786 control_init(control_host, control_port,
0787 opts.mode == TEST_MODE_SERVER);
0788
0789 run_tests(test_cases, &opts);
0790
0791 control_cleanup();
0792 return EXIT_SUCCESS;
0793 }