xref: /linux/tools/testing/vsock/util.c (revision 0e59523b440c90ed1899476f32ad4e949282f43e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * vsock test utilities
4  *
5  * Copyright (C) 2017 Red Hat, Inc.
6  *
7  * Author: Stefan Hajnoczi <stefanha@redhat.com>
8  */
9 
10 #include <ctype.h>
11 #include <errno.h>
12 #include <stdio.h>
13 #include <stdint.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <signal.h>
17 #include <unistd.h>
18 #include <assert.h>
19 #include <sys/epoll.h>
20 #include <sys/ioctl.h>
21 #include <sys/mman.h>
22 #include <linux/sockios.h>
23 
24 #include "timeout.h"
25 #include "control.h"
26 #include "util.h"
27 
28 #define KALLSYMS_PATH		"/proc/kallsyms"
29 #define KALLSYMS_LINE_LEN	512
30 
31 /* Install signal handlers */
32 void init_signals(void)
33 {
34 	struct sigaction act = {
35 		.sa_handler = sigalrm,
36 	};
37 
38 	sigaction(SIGALRM, &act, NULL);
39 	signal(SIGPIPE, SIG_IGN);
40 }
41 
42 static unsigned int parse_uint(const char *str, const char *err_str)
43 {
44 	char *endptr = NULL;
45 	unsigned long n;
46 
47 	errno = 0;
48 	n = strtoul(str, &endptr, 10);
49 	if (errno || *endptr != '\0') {
50 		fprintf(stderr, "malformed %s \"%s\"\n", err_str, str);
51 		exit(EXIT_FAILURE);
52 	}
53 	return n;
54 }
55 
56 /* Parse a CID in string representation */
57 unsigned int parse_cid(const char *str)
58 {
59 	return parse_uint(str, "CID");
60 }
61 
62 /* Parse a port in string representation */
63 unsigned int parse_port(const char *str)
64 {
65 	return parse_uint(str, "port");
66 }
67 
68 /* Wait for the remote to close the connection */
69 void vsock_wait_remote_close(int fd)
70 {
71 	struct epoll_event ev;
72 	int epollfd, nfds;
73 
74 	epollfd = epoll_create1(0);
75 	if (epollfd == -1) {
76 		perror("epoll_create1");
77 		exit(EXIT_FAILURE);
78 	}
79 
80 	ev.events = EPOLLRDHUP | EPOLLHUP;
81 	ev.data.fd = fd;
82 	if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
83 		perror("epoll_ctl");
84 		exit(EXIT_FAILURE);
85 	}
86 
87 	nfds = epoll_wait(epollfd, &ev, 1, TIMEOUT * 1000);
88 	if (nfds == -1) {
89 		perror("epoll_wait");
90 		exit(EXIT_FAILURE);
91 	}
92 
93 	if (nfds == 0) {
94 		fprintf(stderr, "epoll_wait timed out\n");
95 		exit(EXIT_FAILURE);
96 	}
97 
98 	assert(nfds == 1);
99 	assert(ev.events & (EPOLLRDHUP | EPOLLHUP));
100 	assert(ev.data.fd == fd);
101 
102 	close(epollfd);
103 }
104 
105 /* Wait until ioctl gives an expected int value.
106  * Return false if the op is not supported.
107  */
108 bool vsock_ioctl_int(int fd, unsigned long op, int expected)
109 {
110 	int actual, ret;
111 	char name[32];
112 
113 	snprintf(name, sizeof(name), "ioctl(%lu)", op);
114 
115 	timeout_begin(TIMEOUT);
116 	do {
117 		ret = ioctl(fd, op, &actual);
118 		if (ret < 0) {
119 			if (errno == EOPNOTSUPP || errno == ENOTTY)
120 				break;
121 
122 			perror(name);
123 			exit(EXIT_FAILURE);
124 		}
125 		timeout_check(name);
126 	} while (actual != expected);
127 	timeout_end();
128 
129 	return ret >= 0;
130 }
131 
132 /* Wait until transport reports no data left to be sent.
133  * Return false if transport does not implement the unsent_bytes() callback.
134  */
135 bool vsock_wait_sent(int fd)
136 {
137 	return vsock_ioctl_int(fd, SIOCOUTQ, 0);
138 }
139 
140 /* Create socket <type>, bind to <cid, port>.
141  * Return the file descriptor, or -1 on error.
142  */
143 int vsock_bind_try(unsigned int cid, unsigned int port, int type)
144 {
145 	struct sockaddr_vm sa = {
146 		.svm_family = AF_VSOCK,
147 		.svm_cid = cid,
148 		.svm_port = port,
149 	};
150 	int fd, saved_errno;
151 
152 	fd = socket(AF_VSOCK, type, 0);
153 	if (fd < 0) {
154 		perror("socket");
155 		exit(EXIT_FAILURE);
156 	}
157 
158 	if (bind(fd, (struct sockaddr *)&sa, sizeof(sa))) {
159 		saved_errno = errno;
160 		close(fd);
161 		errno = saved_errno;
162 		fd = -1;
163 	}
164 
165 	return fd;
166 }
167 
168 /* Create socket <type>, bind to <cid, port> and return the file descriptor. */
169 int vsock_bind(unsigned int cid, unsigned int port, int type)
170 {
171 	int fd;
172 
173 	fd = vsock_bind_try(cid, port, type);
174 	if (fd < 0) {
175 		perror("bind");
176 		exit(EXIT_FAILURE);
177 	}
178 
179 	return fd;
180 }
181 
182 int vsock_connect_fd(int fd, unsigned int cid, unsigned int port)
183 {
184 	struct sockaddr_vm sa = {
185 		.svm_family = AF_VSOCK,
186 		.svm_cid = cid,
187 		.svm_port = port,
188 	};
189 	int ret;
190 
191 	timeout_begin(TIMEOUT);
192 	do {
193 		ret = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
194 		timeout_check("connect");
195 	} while (ret < 0 && errno == EINTR);
196 	timeout_end();
197 
198 	return ret;
199 }
200 
201 /* Bind to <bind_port>, connect to <cid, port> and return the file descriptor. */
202 int vsock_bind_connect(unsigned int cid, unsigned int port, unsigned int bind_port, int type)
203 {
204 	int client_fd;
205 
206 	client_fd = vsock_bind(VMADDR_CID_ANY, bind_port, type);
207 
208 	if (vsock_connect_fd(client_fd, cid, port)) {
209 		perror("connect");
210 		exit(EXIT_FAILURE);
211 	}
212 
213 	return client_fd;
214 }
215 
216 /* Connect to <cid, port> and return the file descriptor. */
217 int vsock_connect(unsigned int cid, unsigned int port, int type)
218 {
219 	int fd;
220 
221 	control_expectln("LISTENING");
222 
223 	fd = socket(AF_VSOCK, type, 0);
224 	if (fd < 0) {
225 		perror("socket");
226 		exit(EXIT_FAILURE);
227 	}
228 
229 	if (vsock_connect_fd(fd, cid, port)) {
230 		int old_errno = errno;
231 
232 		close(fd);
233 		fd = -1;
234 		errno = old_errno;
235 	}
236 
237 	return fd;
238 }
239 
240 int vsock_stream_connect(unsigned int cid, unsigned int port)
241 {
242 	return vsock_connect(cid, port, SOCK_STREAM);
243 }
244 
245 int vsock_seqpacket_connect(unsigned int cid, unsigned int port)
246 {
247 	return vsock_connect(cid, port, SOCK_SEQPACKET);
248 }
249 
250 /* Listen on <cid, port> and return the file descriptor. */
251 static int vsock_listen(unsigned int cid, unsigned int port, int type)
252 {
253 	int fd;
254 
255 	fd = vsock_bind(cid, port, type);
256 
257 	if (listen(fd, 1) < 0) {
258 		perror("listen");
259 		exit(EXIT_FAILURE);
260 	}
261 
262 	return fd;
263 }
264 
265 /* Listen on <cid, port> and return the first incoming connection.  The remote
266  * address is stored to clientaddrp.  clientaddrp may be NULL.
267  */
268 int vsock_accept(unsigned int cid, unsigned int port,
269 		 struct sockaddr_vm *clientaddrp, int type)
270 {
271 	union {
272 		struct sockaddr sa;
273 		struct sockaddr_vm svm;
274 	} clientaddr;
275 	socklen_t clientaddr_len = sizeof(clientaddr.svm);
276 	int fd, client_fd, old_errno;
277 
278 	fd = vsock_listen(cid, port, type);
279 
280 	control_writeln("LISTENING");
281 
282 	timeout_begin(TIMEOUT);
283 	do {
284 		client_fd = accept(fd, &clientaddr.sa, &clientaddr_len);
285 		timeout_check("accept");
286 	} while (client_fd < 0 && errno == EINTR);
287 	timeout_end();
288 
289 	old_errno = errno;
290 	close(fd);
291 	errno = old_errno;
292 
293 	if (client_fd < 0)
294 		return client_fd;
295 
296 	if (clientaddr_len != sizeof(clientaddr.svm)) {
297 		fprintf(stderr, "unexpected addrlen from accept(2), %zu\n",
298 			(size_t)clientaddr_len);
299 		exit(EXIT_FAILURE);
300 	}
301 	if (clientaddr.sa.sa_family != AF_VSOCK) {
302 		fprintf(stderr, "expected AF_VSOCK from accept(2), got %d\n",
303 			clientaddr.sa.sa_family);
304 		exit(EXIT_FAILURE);
305 	}
306 
307 	if (clientaddrp)
308 		*clientaddrp = clientaddr.svm;
309 	return client_fd;
310 }
311 
312 int vsock_stream_accept(unsigned int cid, unsigned int port,
313 			struct sockaddr_vm *clientaddrp)
314 {
315 	return vsock_accept(cid, port, clientaddrp, SOCK_STREAM);
316 }
317 
318 int vsock_stream_listen(unsigned int cid, unsigned int port)
319 {
320 	return vsock_listen(cid, port, SOCK_STREAM);
321 }
322 
323 int vsock_seqpacket_accept(unsigned int cid, unsigned int port,
324 			   struct sockaddr_vm *clientaddrp)
325 {
326 	return vsock_accept(cid, port, clientaddrp, SOCK_SEQPACKET);
327 }
328 
329 /* Transmit bytes from a buffer and check the return value.
330  *
331  * expected_ret:
332  *  <0 Negative errno (for testing errors)
333  *   0 End-of-file
334  *  >0 Success (bytes successfully written)
335  */
336 void send_buf(int fd, const void *buf, size_t len, int flags,
337 	      ssize_t expected_ret)
338 {
339 	ssize_t nwritten = 0;
340 	ssize_t ret;
341 
342 	timeout_begin(TIMEOUT);
343 	do {
344 		ret = send(fd, buf + nwritten, len - nwritten, flags);
345 		timeout_check("send");
346 
347 		if (ret < 0 && errno == EINTR)
348 			continue;
349 		if (ret <= 0)
350 			break;
351 
352 		nwritten += ret;
353 	} while (nwritten < len);
354 	timeout_end();
355 
356 	if (expected_ret < 0) {
357 		if (ret != -1) {
358 			fprintf(stderr, "bogus send(2) return value %zd (expected %zd)\n",
359 				ret, expected_ret);
360 			exit(EXIT_FAILURE);
361 		}
362 		if (errno != -expected_ret) {
363 			perror("send");
364 			exit(EXIT_FAILURE);
365 		}
366 		return;
367 	}
368 
369 	if (ret < 0) {
370 		perror("send");
371 		exit(EXIT_FAILURE);
372 	}
373 
374 	if (nwritten != expected_ret) {
375 		if (ret == 0)
376 			fprintf(stderr, "unexpected EOF while sending bytes\n");
377 
378 		fprintf(stderr, "bogus send(2) bytes written %zd (expected %zd)\n",
379 			nwritten, expected_ret);
380 		exit(EXIT_FAILURE);
381 	}
382 }
383 
384 #define RECV_PEEK_RETRY_USEC (10 * 1000)
385 
386 /* Receive bytes in a buffer and check the return value.
387  *
388  * When MSG_PEEK is set, recv() is retried until it returns at least
389  * expected_ret bytes. The function returns on error, EOF, or timeout
390  * as usual.
391  *
392  * expected_ret:
393  *  <0 Negative errno (for testing errors)
394  *   0 End-of-file
395  *  >0 Success (bytes successfully read)
396  */
397 void recv_buf(int fd, void *buf, size_t len, int flags, ssize_t expected_ret)
398 {
399 	ssize_t nread = 0;
400 	ssize_t ret;
401 
402 	timeout_begin(TIMEOUT);
403 	do {
404 		ret = recv(fd, buf + nread, len - nread, flags);
405 		timeout_check("recv");
406 
407 		if (ret < 0 && errno == EINTR)
408 			continue;
409 		if (ret <= 0)
410 			break;
411 
412 		if (flags & MSG_PEEK) {
413 			if (ret >= expected_ret) {
414 				nread = ret;
415 				break;
416 			}
417 			timeout_usleep(RECV_PEEK_RETRY_USEC);
418 			continue;
419 		}
420 
421 		nread += ret;
422 	} while (nread < len);
423 	timeout_end();
424 
425 	if (expected_ret < 0) {
426 		if (ret != -1) {
427 			fprintf(stderr, "bogus recv(2) return value %zd (expected %zd)\n",
428 				ret, expected_ret);
429 			exit(EXIT_FAILURE);
430 		}
431 		if (errno != -expected_ret) {
432 			perror("recv");
433 			exit(EXIT_FAILURE);
434 		}
435 		return;
436 	}
437 
438 	if (ret < 0) {
439 		perror("recv");
440 		exit(EXIT_FAILURE);
441 	}
442 
443 	if (nread != expected_ret) {
444 		if (ret == 0)
445 			fprintf(stderr, "unexpected EOF while receiving bytes\n");
446 
447 		fprintf(stderr, "bogus recv(2) bytes read %zd (expected %zd)\n",
448 			nread, expected_ret);
449 		exit(EXIT_FAILURE);
450 	}
451 }
452 
453 /* Transmit one byte and check the return value.
454  *
455  * expected_ret:
456  *  <0 Negative errno (for testing errors)
457  *   0 End-of-file
458  *   1 Success
459  */
460 void send_byte(int fd, int expected_ret, int flags)
461 {
462 	static const uint8_t byte = 'A';
463 
464 	send_buf(fd, &byte, sizeof(byte), flags, expected_ret);
465 }
466 
467 /* Receive one byte and check the return value.
468  *
469  * expected_ret:
470  *  <0 Negative errno (for testing errors)
471  *   0 End-of-file
472  *   1 Success
473  */
474 void recv_byte(int fd, int expected_ret, int flags)
475 {
476 	uint8_t byte;
477 
478 	recv_buf(fd, &byte, sizeof(byte), flags, expected_ret);
479 
480 	if (byte != 'A') {
481 		fprintf(stderr, "unexpected byte read 0x%02x\n", byte);
482 		exit(EXIT_FAILURE);
483 	}
484 }
485 
486 void expect_res(int res, int expected, const char *what)
487 {
488 	if (res != expected) {
489 		fprintf(stderr, "%s: expected %d, got %d\n", what, expected,
490 			res);
491 		exit(EXIT_FAILURE);
492 	}
493 }
494 
495 /* Run test cases.  The program terminates if a failure occurs. */
496 void run_tests(const struct test_case *test_cases,
497 	       const struct test_opts *opts)
498 {
499 	int i;
500 
501 	for (i = 0; test_cases[i].name; i++) {
502 		void (*run)(const struct test_opts *opts);
503 		char *line;
504 
505 		printf("%d - %s...", i, test_cases[i].name);
506 		fflush(stdout);
507 
508 		/* Full barrier before executing the next test.  This
509 		 * ensures that client and server are executing the
510 		 * same test case.  In particular, it means whoever is
511 		 * faster will not see the peer still executing the
512 		 * last test.  This is important because port numbers
513 		 * can be used by multiple test cases.
514 		 */
515 		if (test_cases[i].skip)
516 			control_writeln("SKIP");
517 		else
518 			control_writeln("NEXT");
519 
520 		line = control_readln();
521 		if (control_cmpln(line, "SKIP", false) || test_cases[i].skip) {
522 
523 			printf("skipped\n");
524 
525 			free(line);
526 			continue;
527 		}
528 
529 		control_cmpln(line, "NEXT", true);
530 		free(line);
531 
532 		if (opts->mode == TEST_MODE_CLIENT)
533 			run = test_cases[i].run_client;
534 		else
535 			run = test_cases[i].run_server;
536 
537 		if (run)
538 			run(opts);
539 
540 		printf("ok\n");
541 	}
542 
543 	printf("All tests have been executed. Waiting other peer...");
544 	fflush(stdout);
545 
546 	/*
547 	 * Final full barrier, to ensure that all tests have been run and
548 	 * that even the last one has been successful on both sides.
549 	 */
550 	control_writeln("COMPLETED");
551 	control_expectln("COMPLETED");
552 
553 	printf("ok\n");
554 }
555 
556 void list_tests(const struct test_case *test_cases)
557 {
558 	int i;
559 
560 	printf("ID\tTest name\n");
561 
562 	for (i = 0; test_cases[i].name; i++)
563 		printf("%d\t%s\n", i, test_cases[i].name);
564 
565 	exit(EXIT_FAILURE);
566 }
567 
568 static unsigned long parse_test_id(const char *test_id_str, size_t test_cases_len)
569 {
570 	unsigned long test_id;
571 	char *endptr = NULL;
572 
573 	errno = 0;
574 	test_id = strtoul(test_id_str, &endptr, 10);
575 	if (errno || *endptr != '\0') {
576 		fprintf(stderr, "malformed test ID \"%s\"\n", test_id_str);
577 		exit(EXIT_FAILURE);
578 	}
579 
580 	if (test_id >= test_cases_len) {
581 		fprintf(stderr, "test ID (%lu) larger than the max allowed (%lu)\n",
582 			test_id, test_cases_len - 1);
583 		exit(EXIT_FAILURE);
584 	}
585 
586 	return test_id;
587 }
588 
589 void skip_test(struct test_case *test_cases, size_t test_cases_len,
590 	       const char *test_id_str)
591 {
592 	unsigned long test_id = parse_test_id(test_id_str, test_cases_len);
593 	test_cases[test_id].skip = true;
594 }
595 
596 void pick_test(struct test_case *test_cases, size_t test_cases_len,
597 	       const char *test_id_str)
598 {
599 	static bool skip_all = true;
600 	unsigned long test_id;
601 
602 	if (skip_all) {
603 		unsigned long i;
604 
605 		for (i = 0; i < test_cases_len; ++i)
606 			test_cases[i].skip = true;
607 
608 		skip_all = false;
609 	}
610 
611 	test_id = parse_test_id(test_id_str, test_cases_len);
612 	test_cases[test_id].skip = false;
613 }
614 
615 unsigned long hash_djb2(const void *data, size_t len)
616 {
617 	unsigned long hash = 5381;
618 	int i = 0;
619 
620 	while (i < len) {
621 		hash = ((hash << 5) + hash) + ((unsigned char *)data)[i];
622 		i++;
623 	}
624 
625 	return hash;
626 }
627 
628 size_t iovec_bytes(const struct iovec *iov, size_t iovnum)
629 {
630 	size_t bytes;
631 	int i;
632 
633 	for (bytes = 0, i = 0; i < iovnum; i++)
634 		bytes += iov[i].iov_len;
635 
636 	return bytes;
637 }
638 
639 unsigned long iovec_hash_djb2(const struct iovec *iov, size_t iovnum)
640 {
641 	unsigned long hash;
642 	size_t iov_bytes;
643 	size_t offs;
644 	void *tmp;
645 	int i;
646 
647 	iov_bytes = iovec_bytes(iov, iovnum);
648 
649 	tmp = malloc(iov_bytes);
650 	if (!tmp) {
651 		perror("malloc");
652 		exit(EXIT_FAILURE);
653 	}
654 
655 	for (offs = 0, i = 0; i < iovnum; i++) {
656 		memcpy(tmp + offs, iov[i].iov_base, iov[i].iov_len);
657 		offs += iov[i].iov_len;
658 	}
659 
660 	hash = hash_djb2(tmp, iov_bytes);
661 	free(tmp);
662 
663 	return hash;
664 }
665 
666 /* Allocates and returns new 'struct iovec *' according pattern
667  * in the 'test_iovec'. For each element in the 'test_iovec' it
668  * allocates new element in the resulting 'iovec'. 'iov_len'
669  * of the new element is copied from 'test_iovec'. 'iov_base' is
670  * allocated depending on the 'iov_base' of 'test_iovec':
671  *
672  * 'iov_base' == NULL -> valid buf: mmap('iov_len').
673  *
674  * 'iov_base' == MAP_FAILED -> invalid buf:
675  *               mmap('iov_len'), then munmap('iov_len').
676  *               'iov_base' still contains result of
677  *               mmap().
678  *
679  * 'iov_base' == number -> unaligned valid buf:
680  *               mmap('iov_len') + number.
681  *
682  * 'iovnum' is number of elements in 'test_iovec'.
683  *
684  * Returns new 'iovec' or calls 'exit()' on error.
685  */
686 struct iovec *alloc_test_iovec(const struct iovec *test_iovec, int iovnum)
687 {
688 	struct iovec *iovec;
689 	int i;
690 
691 	iovec = malloc(sizeof(*iovec) * iovnum);
692 	if (!iovec) {
693 		perror("malloc");
694 		exit(EXIT_FAILURE);
695 	}
696 
697 	for (i = 0; i < iovnum; i++) {
698 		iovec[i].iov_len = test_iovec[i].iov_len;
699 
700 		iovec[i].iov_base = mmap(NULL, iovec[i].iov_len,
701 					 PROT_READ | PROT_WRITE,
702 					 MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE,
703 					 -1, 0);
704 		if (iovec[i].iov_base == MAP_FAILED) {
705 			perror("mmap");
706 			exit(EXIT_FAILURE);
707 		}
708 
709 		if (test_iovec[i].iov_base != MAP_FAILED)
710 			iovec[i].iov_base += (uintptr_t)test_iovec[i].iov_base;
711 	}
712 
713 	/* Unmap "invalid" elements. */
714 	for (i = 0; i < iovnum; i++) {
715 		if (test_iovec[i].iov_base == MAP_FAILED) {
716 			if (munmap(iovec[i].iov_base, iovec[i].iov_len)) {
717 				perror("munmap");
718 				exit(EXIT_FAILURE);
719 			}
720 		}
721 	}
722 
723 	for (i = 0; i < iovnum; i++) {
724 		int j;
725 
726 		if (test_iovec[i].iov_base == MAP_FAILED)
727 			continue;
728 
729 		for (j = 0; j < iovec[i].iov_len; j++)
730 			((uint8_t *)iovec[i].iov_base)[j] = rand() & 0xff;
731 	}
732 
733 	return iovec;
734 }
735 
736 /* Frees 'iovec *', previously allocated by 'alloc_test_iovec()'.
737  * On error calls 'exit()'.
738  */
739 void free_test_iovec(const struct iovec *test_iovec,
740 		     struct iovec *iovec, int iovnum)
741 {
742 	int i;
743 
744 	for (i = 0; i < iovnum; i++) {
745 		if (test_iovec[i].iov_base != MAP_FAILED) {
746 			if (test_iovec[i].iov_base)
747 				iovec[i].iov_base -= (uintptr_t)test_iovec[i].iov_base;
748 
749 			if (munmap(iovec[i].iov_base, iovec[i].iov_len)) {
750 				perror("munmap");
751 				exit(EXIT_FAILURE);
752 			}
753 		}
754 	}
755 
756 	free(iovec);
757 }
758 
759 /* Set "unsigned long long" socket option and check that it's indeed set */
760 void setsockopt_ull_check(int fd, int level, int optname,
761 			  unsigned long long val, char const *errmsg)
762 {
763 	unsigned long long chkval;
764 	socklen_t chklen;
765 	int err;
766 
767 	err = setsockopt(fd, level, optname, &val, sizeof(val));
768 	if (err) {
769 		fprintf(stderr, "setsockopt err: %s (%d)\n",
770 			strerror(errno), errno);
771 		goto fail;
772 	}
773 
774 	chkval = ~val; /* just make storage != val */
775 	chklen = sizeof(chkval);
776 
777 	err = getsockopt(fd, level, optname, &chkval, &chklen);
778 	if (err) {
779 		fprintf(stderr, "getsockopt err: %s (%d)\n",
780 			strerror(errno), errno);
781 		goto fail;
782 	}
783 
784 	if (chklen != sizeof(chkval)) {
785 		fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
786 			chklen);
787 		goto fail;
788 	}
789 
790 	if (chkval != val) {
791 		fprintf(stderr, "value mismatch: set %llu got %llu\n", val,
792 			chkval);
793 		goto fail;
794 	}
795 	return;
796 fail:
797 	fprintf(stderr, "%s  val %llu\n", errmsg, val);
798 	exit(EXIT_FAILURE);
799 }
800 
801 /* Set "int" socket option and check that it's indeed set */
802 void setsockopt_int_check(int fd, int level, int optname, int val,
803 			  char const *errmsg)
804 {
805 	int chkval;
806 	socklen_t chklen;
807 	int err;
808 
809 	err = setsockopt(fd, level, optname, &val, sizeof(val));
810 	if (err) {
811 		fprintf(stderr, "setsockopt err: %s (%d)\n",
812 			strerror(errno), errno);
813 		goto fail;
814 	}
815 
816 	chkval = ~val; /* just make storage != val */
817 	chklen = sizeof(chkval);
818 
819 	err = getsockopt(fd, level, optname, &chkval, &chklen);
820 	if (err) {
821 		fprintf(stderr, "getsockopt err: %s (%d)\n",
822 			strerror(errno), errno);
823 		goto fail;
824 	}
825 
826 	if (chklen != sizeof(chkval)) {
827 		fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
828 			chklen);
829 		goto fail;
830 	}
831 
832 	if (chkval != val) {
833 		fprintf(stderr, "value mismatch: set %d got %d\n", val, chkval);
834 		goto fail;
835 	}
836 	return;
837 fail:
838 	fprintf(stderr, "%s val %d\n", errmsg, val);
839 	exit(EXIT_FAILURE);
840 }
841 
842 static void mem_invert(unsigned char *mem, size_t size)
843 {
844 	size_t i;
845 
846 	for (i = 0; i < size; i++)
847 		mem[i] = ~mem[i];
848 }
849 
850 /* Set "timeval" socket option and check that it's indeed set */
851 void setsockopt_timeval_check(int fd, int level, int optname,
852 			      struct timeval val, char const *errmsg)
853 {
854 	struct timeval chkval;
855 	socklen_t chklen;
856 	int err;
857 
858 	err = setsockopt(fd, level, optname, &val, sizeof(val));
859 	if (err) {
860 		fprintf(stderr, "setsockopt err: %s (%d)\n",
861 			strerror(errno), errno);
862 		goto fail;
863 	}
864 
865 	 /* just make storage != val */
866 	chkval = val;
867 	mem_invert((unsigned char *)&chkval, sizeof(chkval));
868 	chklen = sizeof(chkval);
869 
870 	err = getsockopt(fd, level, optname, &chkval, &chklen);
871 	if (err) {
872 		fprintf(stderr, "getsockopt err: %s (%d)\n",
873 			strerror(errno), errno);
874 		goto fail;
875 	}
876 
877 	if (chklen != sizeof(chkval)) {
878 		fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
879 			chklen);
880 		goto fail;
881 	}
882 
883 	if (memcmp(&chkval, &val, sizeof(val)) != 0) {
884 		fprintf(stderr, "value mismatch: set %ld:%ld got %ld:%ld\n",
885 			val.tv_sec, val.tv_usec, chkval.tv_sec, chkval.tv_usec);
886 		goto fail;
887 	}
888 	return;
889 fail:
890 	fprintf(stderr, "%s val %ld:%ld\n", errmsg, val.tv_sec, val.tv_usec);
891 	exit(EXIT_FAILURE);
892 }
893 
894 void enable_so_zerocopy_check(int fd)
895 {
896 	setsockopt_int_check(fd, SOL_SOCKET, SO_ZEROCOPY, 1,
897 			     "setsockopt SO_ZEROCOPY");
898 }
899 
900 void enable_so_linger(int fd, int timeout)
901 {
902 	struct linger optval = {
903 		.l_onoff = 1,
904 		.l_linger = timeout
905 	};
906 
907 	if (setsockopt(fd, SOL_SOCKET, SO_LINGER, &optval, sizeof(optval))) {
908 		perror("setsockopt(SO_LINGER)");
909 		exit(EXIT_FAILURE);
910 	}
911 }
912 
913 static int __get_transports(void)
914 {
915 	char buf[KALLSYMS_LINE_LEN];
916 	const char *ksym;
917 	int ret = 0;
918 	FILE *f;
919 
920 	f = fopen(KALLSYMS_PATH, "r");
921 	if (!f) {
922 		perror("Can't open " KALLSYMS_PATH);
923 		exit(EXIT_FAILURE);
924 	}
925 
926 	while (fgets(buf, sizeof(buf), f)) {
927 		char *match;
928 		int i;
929 
930 		assert(buf[strlen(buf) - 1] == '\n');
931 
932 		for (i = 0; i < TRANSPORT_NUM; ++i) {
933 			if (ret & BIT(i))
934 				continue;
935 
936 			/* Match should be followed by '\t' or '\n'.
937 			 * See kallsyms.c:s_show().
938 			 */
939 			ksym = transport_ksyms[i];
940 			match = strstr(buf, ksym);
941 			if (match && isspace(match[strlen(ksym)])) {
942 				ret |= BIT(i);
943 				break;
944 			}
945 		}
946 	}
947 
948 	fclose(f);
949 	return ret;
950 }
951 
952 /* Return integer with TRANSPORT_* bit set for every (known) registered vsock
953  * transport.
954  */
955 int get_transports(void)
956 {
957 	static int tr = -1;
958 
959 	if (tr == -1)
960 		tr = __get_transports();
961 
962 	return tr;
963 }
964