1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * TCP-AO selftest library. Provides helpers to unshare network
4  * namespaces, create veth, assign ip addresses, set routes,
5  * manipulate socket options, read network counter and etc.
6  * Author: Dmitry Safonov <dima@arista.com>
7  */
8 #ifndef _AOLIB_H_
9 #define _AOLIB_H_
10 
11 #include <arpa/inet.h>
12 #include <errno.h>
13 #include <linux/snmp.h>
14 #include <linux/tcp.h>
15 #include <netinet/in.h>
16 #include <stdarg.h>
17 #include <stdbool.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/syscall.h>
22 #include <unistd.h>
23 
24 #include "../../../../../include/linux/stringify.h"
25 #include "../../../../../include/linux/bits.h"
26 
27 #ifndef SOL_TCP
28 /* can't include <netinet/tcp.h> as including <linux/tcp.h> */
29 # define SOL_TCP		6	/* TCP level */
30 #endif
31 
32 /* Working around ksft, see the comment in lib/setup.c */
33 extern void __test_msg(const char *buf);
34 extern void __test_ok(const char *buf);
35 extern void __test_fail(const char *buf);
36 extern void __test_xfail(const char *buf);
37 extern void __test_error(const char *buf);
38 extern void __test_skip(const char *buf);
39 
40 static inline char *test_snprintf(const char *fmt, va_list vargs)
41 {
42 	char *ret = NULL;
43 	size_t size = 0;
44 	va_list tmp;
45 	int n = 0;
46 
47 	va_copy(tmp, vargs);
48 	n = vsnprintf(ret, size, fmt, tmp);
49 	if (n < 0)
50 		return NULL;
51 
52 	size = n + 1;
53 	ret = malloc(size);
54 	if (!ret)
55 		return NULL;
56 
57 	n = vsnprintf(ret, size, fmt, vargs);
58 	if (n < 0 || n > size - 1) {
59 		free(ret);
60 		return NULL;
61 	}
62 	return ret;
63 }
64 
65 static __printf(1, 2) inline char *test_sprintf(const char *fmt, ...)
66 {
67 	va_list vargs;
68 	char *ret;
69 
70 	va_start(vargs, fmt);
71 	ret = test_snprintf(fmt, vargs);
72 	va_end(vargs);
73 
74 	return ret;
75 }
76 
77 static __printf(2, 3) inline void __test_print(void (*fn)(const char *),
78 					       const char *fmt, ...)
79 {
80 	va_list vargs;
81 	char *msg;
82 
83 	va_start(vargs, fmt);
84 	msg = test_snprintf(fmt, vargs);
85 	va_end(vargs);
86 
87 	if (!msg)
88 		return;
89 
90 	fn(msg);
91 	free(msg);
92 }
93 
94 #define test_print(fmt, ...)						\
95 	__test_print(__test_msg, "%ld[%s:%u] " fmt "\n",		\
96 		     syscall(SYS_gettid),				\
97 		     __FILE__, __LINE__, ##__VA_ARGS__)
98 
99 #define test_ok(fmt, ...)						\
100 	__test_print(__test_ok, fmt "\n", ##__VA_ARGS__)
101 #define test_skip(fmt, ...)						\
102 	__test_print(__test_skip, fmt "\n", ##__VA_ARGS__)
103 #define test_xfail(fmt, ...)						\
104 	__test_print(__test_xfail, fmt "\n", ##__VA_ARGS__)
105 
106 #define test_fail(fmt, ...)						\
107 do {									\
108 	if (errno)							\
109 		__test_print(__test_fail, fmt ": %m\n", ##__VA_ARGS__);	\
110 	else								\
111 		__test_print(__test_fail, fmt "\n", ##__VA_ARGS__);	\
112 	test_failed();							\
113 } while (0)
114 
115 #define KSFT_FAIL  1
116 #define test_error(fmt, ...)						\
117 do {									\
118 	if (errno)							\
119 		__test_print(__test_error, "%ld[%s:%u] " fmt ": %m\n",	\
120 			     syscall(SYS_gettid), __FILE__, __LINE__,	\
121 			     ##__VA_ARGS__);				\
122 	else								\
123 		__test_print(__test_error, "%ld[%s:%u] " fmt "\n",	\
124 			     syscall(SYS_gettid), __FILE__, __LINE__,	\
125 			     ##__VA_ARGS__);				\
126 	exit(KSFT_FAIL);						\
127 } while (0)
128 
129 enum test_fault {
130 	FAULT_TIMEOUT = 1,
131 	FAULT_KEYREJECT,
132 	FAULT_PREINSTALL_AO,
133 	FAULT_PREINSTALL_MD5,
134 	FAULT_POSTINSTALL,
135 	FAULT_BUSY,
136 	FAULT_CURRNEXT,
137 	FAULT_FIXME,
138 };
139 typedef enum test_fault fault_t;
140 
141 enum test_needs_kconfig {
142 	KCONFIG_NET_NS = 0,		/* required */
143 	KCONFIG_VETH,			/* required */
144 	KCONFIG_TCP_AO,			/* required */
145 	KCONFIG_TCP_MD5,		/* optional, for TCP-MD5 features */
146 	KCONFIG_NET_VRF,		/* optional, for L3/VRF testing */
147 	__KCONFIG_LAST__
148 };
149 extern bool kernel_config_has(enum test_needs_kconfig k);
150 extern const char *tests_skip_reason[__KCONFIG_LAST__];
151 static inline bool should_skip_test(const char *tst_name,
152 				    enum test_needs_kconfig k)
153 {
154 	if (kernel_config_has(k))
155 		return false;
156 	test_skip("%s: %s", tst_name, tests_skip_reason[k]);
157 	return true;
158 }
159 
160 union tcp_addr {
161 	struct in_addr a4;
162 	struct in6_addr a6;
163 };
164 
165 typedef void *(*thread_fn)(void *);
166 extern void test_failed(void);
167 extern void __test_init(unsigned int ntests, int family, unsigned int prefix,
168 			union tcp_addr addr1, union tcp_addr addr2,
169 			thread_fn peer1, thread_fn peer2);
170 
171 static inline void test_init2(unsigned int ntests,
172 			      thread_fn peer1, thread_fn peer2,
173 			      int family, unsigned int prefix,
174 			      const char *addr1, const char *addr2)
175 {
176 	union tcp_addr taddr1, taddr2;
177 
178 	if (inet_pton(family, addr1, &taddr1) != 1)
179 		test_error("Can't convert ip address %s", addr1);
180 	if (inet_pton(family, addr2, &taddr2) != 1)
181 		test_error("Can't convert ip address %s", addr2);
182 
183 	__test_init(ntests, family, prefix, taddr1, taddr2, peer1, peer2);
184 }
185 extern void test_add_destructor(void (*d)(void));
186 
187 /* To adjust optmem socket limit, approximately estimate a number,
188  * that is bigger than sizeof(struct tcp_ao_key).
189  */
190 #define KERNEL_TCP_AO_KEY_SZ_ROUND_UP	300
191 
192 extern void test_set_optmem(size_t value);
193 extern size_t test_get_optmem(void);
194 
195 extern const struct sockaddr_in6 addr_any6;
196 extern const struct sockaddr_in addr_any4;
197 
198 #ifdef IPV6_TEST
199 # define __TEST_CLIENT_IP(n)	("2001:db8:" __stringify(n) "::1")
200 # define TEST_CLIENT_IP	__TEST_CLIENT_IP(1)
201 # define TEST_WRONG_IP	"2001:db8:253::1"
202 # define TEST_SERVER_IP	"2001:db8:254::1"
203 # define TEST_NETWORK	"2001::"
204 # define TEST_PREFIX	128
205 # define TEST_FAMILY	AF_INET6
206 # define SOCKADDR_ANY	addr_any6
207 # define sockaddr_af	struct sockaddr_in6
208 #else
209 # define __TEST_CLIENT_IP(n)	("10.0." __stringify(n) ".1")
210 # define TEST_CLIENT_IP	__TEST_CLIENT_IP(1)
211 # define TEST_WRONG_IP	"10.0.253.1"
212 # define TEST_SERVER_IP	"10.0.254.1"
213 # define TEST_NETWORK	"10.0.0.0"
214 # define TEST_PREFIX	32
215 # define TEST_FAMILY	AF_INET
216 # define SOCKADDR_ANY	addr_any4
217 # define sockaddr_af	struct sockaddr_in
218 #endif
219 
220 static inline union tcp_addr gen_tcp_addr(union tcp_addr net, size_t n)
221 {
222 	union tcp_addr ret = net;
223 
224 #ifdef IPV6_TEST
225 	ret.a6.s6_addr32[3] = htonl(n & (BIT(32) - 1));
226 	ret.a6.s6_addr32[2] = htonl((n >> 32) & (BIT(32) - 1));
227 #else
228 	ret.a4.s_addr = htonl(ntohl(net.a4.s_addr) + n);
229 #endif
230 
231 	return ret;
232 }
233 
234 static inline void tcp_addr_to_sockaddr_in(void *dest,
235 					   const union tcp_addr *src,
236 					   unsigned int port)
237 {
238 	sockaddr_af *out = dest;
239 
240 	memset(out, 0, sizeof(*out));
241 #ifdef IPV6_TEST
242 	out->sin6_family = AF_INET6;
243 	out->sin6_port   = port;
244 	out->sin6_addr   = src->a6;
245 #else
246 	out->sin_family  = AF_INET;
247 	out->sin_port    = port;
248 	out->sin_addr    = src->a4;
249 #endif
250 }
251 
252 static inline void test_init(unsigned int ntests,
253 			     thread_fn peer1, thread_fn peer2)
254 {
255 	test_init2(ntests, peer1, peer2, TEST_FAMILY, TEST_PREFIX,
256 			TEST_SERVER_IP, TEST_CLIENT_IP);
257 }
258 extern void synchronize_threads(void);
259 extern void switch_ns(int fd);
260 
261 extern __thread union tcp_addr this_ip_addr;
262 extern __thread union tcp_addr this_ip_dest;
263 extern int test_family;
264 
265 extern void randomize_buffer(void *buf, size_t buflen);
266 extern int open_netns(void);
267 extern int unshare_open_netns(void);
268 extern const char veth_name[];
269 extern int add_veth(const char *name, int nsfda, int nsfdb);
270 extern int add_vrf(const char *name, uint32_t tabid, int ifindex, int nsfd);
271 extern int ip_addr_add(const char *intf, int family,
272 		       union tcp_addr addr, uint8_t prefix);
273 extern int ip_route_add(const char *intf, int family,
274 			union tcp_addr src, union tcp_addr dst);
275 extern int ip_route_add_vrf(const char *intf, int family,
276 			    union tcp_addr src, union tcp_addr dst,
277 			    uint8_t vrf);
278 extern int link_set_up(const char *intf);
279 
280 extern const unsigned int test_server_port;
281 extern int test_wait_fd(int sk, time_t sec, bool write);
282 extern int __test_connect_socket(int sk, const char *device,
283 				 void *addr, size_t addr_sz, time_t timeout);
284 extern int __test_listen_socket(int backlog, void *addr, size_t addr_sz);
285 
286 static inline int test_listen_socket(const union tcp_addr taddr,
287 				     unsigned int port, int backlog)
288 {
289 	sockaddr_af addr;
290 
291 	tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
292 	return __test_listen_socket(backlog, (void *)&addr, sizeof(addr));
293 }
294 
295 /*
296  * In order for selftests to work under CONFIG_CRYPTO_FIPS=y,
297  * the password should be loger than 14 bytes, see hmac_setkey()
298  */
299 #define TEST_TCP_AO_MINKEYLEN	14
300 #define DEFAULT_TEST_PASSWORD	"In this hour, I do not believe that any darkness will endure."
301 
302 #ifndef DEFAULT_TEST_ALGO
303 #define DEFAULT_TEST_ALGO	"cmac(aes128)"
304 #endif
305 
306 #ifdef IPV6_TEST
307 #define DEFAULT_TEST_PREFIX	128
308 #else
309 #define DEFAULT_TEST_PREFIX	32
310 #endif
311 
312 /*
313  * Timeout on syscalls where failure is not expected.
314  * You may want to rise it if the test machine is very busy.
315  */
316 #ifndef TEST_TIMEOUT_SEC
317 #define TEST_TIMEOUT_SEC	5
318 #endif
319 
320 /*
321  * Timeout on connect() where a failure is expected.
322  * If set to 0 - kernel will try to retransmit SYN number of times, set in
323  * /proc/sys/net/ipv4/tcp_syn_retries
324  * By default set to 1 to make tests pass faster on non-busy machine.
325  */
326 #ifndef TEST_RETRANSMIT_SEC
327 #define TEST_RETRANSMIT_SEC	1
328 #endif
329 
330 static inline int _test_connect_socket(int sk, const union tcp_addr taddr,
331 				       unsigned int port, time_t timeout)
332 {
333 	sockaddr_af addr;
334 
335 	tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
336 	return __test_connect_socket(sk, veth_name,
337 				     (void *)&addr, sizeof(addr), timeout);
338 }
339 
340 static inline int test_connect_socket(int sk, const union tcp_addr taddr,
341 				      unsigned int port)
342 {
343 	return _test_connect_socket(sk, taddr, port, TEST_TIMEOUT_SEC);
344 }
345 
346 extern int __test_set_md5(int sk, void *addr, size_t addr_sz,
347 			  uint8_t prefix, int vrf, const char *password);
348 static inline int test_set_md5(int sk, const union tcp_addr in_addr,
349 			       uint8_t prefix, int vrf, const char *password)
350 {
351 	sockaddr_af addr;
352 
353 	if (prefix > DEFAULT_TEST_PREFIX)
354 		prefix = DEFAULT_TEST_PREFIX;
355 
356 	tcp_addr_to_sockaddr_in(&addr, &in_addr, 0);
357 	return __test_set_md5(sk, (void *)&addr, sizeof(addr),
358 			prefix, vrf, password);
359 }
360 
361 extern int test_prepare_key_sockaddr(struct tcp_ao_add *ao, const char *alg,
362 		void *addr, size_t addr_sz, bool set_current, bool set_rnext,
363 		uint8_t prefix, uint8_t vrf,
364 		uint8_t sndid, uint8_t rcvid, uint8_t maclen,
365 		uint8_t keyflags, uint8_t keylen, const char *key);
366 
367 static inline int test_prepare_key(struct tcp_ao_add *ao,
368 		const char *alg, union tcp_addr taddr,
369 		bool set_current, bool set_rnext,
370 		uint8_t prefix, uint8_t vrf,
371 		uint8_t sndid, uint8_t rcvid, uint8_t maclen,
372 		uint8_t keyflags, uint8_t keylen, const char *key)
373 {
374 	sockaddr_af addr;
375 
376 	tcp_addr_to_sockaddr_in(&addr, &taddr, 0);
377 	return test_prepare_key_sockaddr(ao, alg, (void *)&addr, sizeof(addr),
378 			set_current, set_rnext, prefix, vrf, sndid, rcvid,
379 			maclen, keyflags, keylen, key);
380 }
381 
382 static inline int test_prepare_def_key(struct tcp_ao_add *ao,
383 		const char *key, uint8_t keyflags,
384 		union tcp_addr in_addr, uint8_t prefix, uint8_t vrf,
385 		uint8_t sndid, uint8_t rcvid)
386 {
387 	if (prefix > DEFAULT_TEST_PREFIX)
388 		prefix = DEFAULT_TEST_PREFIX;
389 
390 	return test_prepare_key(ao, DEFAULT_TEST_ALGO, in_addr, false, false,
391 				prefix, vrf, sndid, rcvid, 0, keyflags,
392 				strlen(key), key);
393 }
394 
395 extern int test_get_one_ao(int sk, struct tcp_ao_getsockopt *out,
396 			   void *addr, size_t addr_sz,
397 			   uint8_t prefix, uint8_t sndid, uint8_t rcvid);
398 extern int test_get_ao_info(int sk, struct tcp_ao_info_opt *out);
399 extern int test_set_ao_info(int sk, struct tcp_ao_info_opt *in);
400 extern int test_cmp_getsockopt_setsockopt(const struct tcp_ao_add *a,
401 					  const struct tcp_ao_getsockopt *b);
402 extern int test_cmp_getsockopt_setsockopt_ao(const struct tcp_ao_info_opt *a,
403 					     const struct tcp_ao_info_opt *b);
404 
405 static inline int test_verify_socket_key(int sk, struct tcp_ao_add *key)
406 {
407 	struct tcp_ao_getsockopt key2 = {};
408 	int err;
409 
410 	err = test_get_one_ao(sk, &key2, &key->addr, sizeof(key->addr),
411 			      key->prefix, key->sndid, key->rcvid);
412 	if (err)
413 		return err;
414 
415 	return test_cmp_getsockopt_setsockopt(key, &key2);
416 }
417 
418 static inline int test_add_key_vrf(int sk,
419 				   const char *key, uint8_t keyflags,
420 				   union tcp_addr in_addr, uint8_t prefix,
421 				   uint8_t vrf, uint8_t sndid, uint8_t rcvid)
422 {
423 	struct tcp_ao_add tmp = {};
424 	int err;
425 
426 	err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
427 				   vrf, sndid, rcvid);
428 	if (err)
429 		return err;
430 
431 	err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp));
432 	if (err < 0)
433 		return -errno;
434 
435 	return test_verify_socket_key(sk, &tmp);
436 }
437 
438 static inline int test_add_key(int sk, const char *key,
439 			      union tcp_addr in_addr, uint8_t prefix,
440 			      uint8_t sndid, uint8_t rcvid)
441 {
442 	return test_add_key_vrf(sk, key, 0, in_addr, prefix, 0, sndid, rcvid);
443 }
444 
445 static inline int test_verify_socket_ao(int sk, struct tcp_ao_info_opt *ao)
446 {
447 	struct tcp_ao_info_opt ao2 = {};
448 	int err;
449 
450 	err = test_get_ao_info(sk, &ao2);
451 	if (err)
452 		return err;
453 
454 	return test_cmp_getsockopt_setsockopt_ao(ao, &ao2);
455 }
456 
457 static inline int test_set_ao_flags(int sk, bool ao_required, bool accept_icmps)
458 {
459 	struct tcp_ao_info_opt ao = {};
460 	int err;
461 
462 	err = test_get_ao_info(sk, &ao);
463 	/* Maybe ao_info wasn't allocated yet */
464 	if (err && err != -ENOENT)
465 		return err;
466 
467 	ao.ao_required = !!ao_required;
468 	ao.accept_icmps = !!accept_icmps;
469 	err = test_set_ao_info(sk, &ao);
470 	if (err)
471 		return err;
472 
473 	return test_verify_socket_ao(sk, &ao);
474 }
475 
476 extern ssize_t test_server_run(int sk, ssize_t quota, time_t timeout_sec);
477 extern ssize_t test_client_loop(int sk, char *buf, size_t buf_sz,
478 				const size_t msg_len, time_t timeout_sec);
479 extern int test_client_verify(int sk, const size_t msg_len, const size_t nr,
480 			      time_t timeout_sec);
481 
482 struct tcp_ao_key_counters {
483 	uint8_t sndid;
484 	uint8_t rcvid;
485 	uint64_t pkt_good;
486 	uint64_t pkt_bad;
487 };
488 
489 struct tcp_ao_counters {
490 	/* per-netns */
491 	uint64_t netns_ao_good;
492 	uint64_t netns_ao_bad;
493 	uint64_t netns_ao_key_not_found;
494 	uint64_t netns_ao_required;
495 	uint64_t netns_ao_dropped_icmp;
496 	/* per-socket */
497 	uint64_t ao_info_pkt_good;
498 	uint64_t ao_info_pkt_bad;
499 	uint64_t ao_info_pkt_key_not_found;
500 	uint64_t ao_info_pkt_ao_required;
501 	uint64_t ao_info_pkt_dropped_icmp;
502 	/* per-key */
503 	size_t nr_keys;
504 	struct tcp_ao_key_counters *key_cnts;
505 };
506 extern int test_get_tcp_ao_counters(int sk, struct tcp_ao_counters *out);
507 
508 #define TEST_CNT_KEY_GOOD		BIT(0)
509 #define TEST_CNT_KEY_BAD		BIT(1)
510 #define TEST_CNT_SOCK_GOOD		BIT(2)
511 #define TEST_CNT_SOCK_BAD		BIT(3)
512 #define TEST_CNT_SOCK_KEY_NOT_FOUND	BIT(4)
513 #define TEST_CNT_SOCK_AO_REQUIRED	BIT(5)
514 #define TEST_CNT_SOCK_DROPPED_ICMP	BIT(6)
515 #define TEST_CNT_NS_GOOD		BIT(7)
516 #define TEST_CNT_NS_BAD			BIT(8)
517 #define TEST_CNT_NS_KEY_NOT_FOUND	BIT(9)
518 #define TEST_CNT_NS_AO_REQUIRED		BIT(10)
519 #define TEST_CNT_NS_DROPPED_ICMP	BIT(11)
520 typedef uint16_t test_cnt;
521 
522 #define TEST_CNT_AO_GOOD		(TEST_CNT_SOCK_GOOD | TEST_CNT_NS_GOOD)
523 #define TEST_CNT_AO_BAD			(TEST_CNT_SOCK_BAD | TEST_CNT_NS_BAD)
524 #define TEST_CNT_AO_KEY_NOT_FOUND	(TEST_CNT_SOCK_KEY_NOT_FOUND | \
525 					 TEST_CNT_NS_KEY_NOT_FOUND)
526 #define TEST_CNT_AO_REQUIRED		(TEST_CNT_SOCK_AO_REQUIRED | \
527 					 TEST_CNT_NS_AO_REQUIRED)
528 #define TEST_CNT_AO_DROPPED_ICMP	(TEST_CNT_SOCK_DROPPED_ICMP | \
529 					 TEST_CNT_NS_DROPPED_ICMP)
530 #define TEST_CNT_GOOD			(TEST_CNT_KEY_GOOD | TEST_CNT_AO_GOOD)
531 #define TEST_CNT_BAD			(TEST_CNT_KEY_BAD | TEST_CNT_AO_BAD)
532 
533 extern int __test_tcp_ao_counters_cmp(const char *tst_name,
534 		struct tcp_ao_counters *before, struct tcp_ao_counters *after,
535 		test_cnt expected);
536 extern int test_tcp_ao_key_counters_cmp(const char *tst_name,
537 		struct tcp_ao_counters *before, struct tcp_ao_counters *after,
538 		test_cnt expected, int sndid, int rcvid);
539 extern void test_tcp_ao_counters_free(struct tcp_ao_counters *cnts);
540 /*
541  * Frees buffers allocated in test_get_tcp_ao_counters().
542  * The function doesn't expect new keys or keys removed between calls
543  * to test_get_tcp_ao_counters(). Check key counters manually if they
544  * may change.
545  */
546 static inline int test_tcp_ao_counters_cmp(const char *tst_name,
547 					   struct tcp_ao_counters *before,
548 					   struct tcp_ao_counters *after,
549 					   test_cnt expected)
550 {
551 	int ret;
552 
553 	ret = __test_tcp_ao_counters_cmp(tst_name, before, after, expected);
554 	if (ret)
555 		goto out;
556 	ret = test_tcp_ao_key_counters_cmp(tst_name, before, after,
557 					   expected, -1, -1);
558 out:
559 	test_tcp_ao_counters_free(before);
560 	test_tcp_ao_counters_free(after);
561 	return ret;
562 }
563 
564 struct netstat;
565 extern struct netstat *netstat_read(void);
566 extern void netstat_free(struct netstat *ns);
567 extern void netstat_print_diff(struct netstat *nsa, struct netstat *nsb);
568 extern uint64_t netstat_get(struct netstat *ns,
569 			    const char *name, bool *not_found);
570 
571 static inline uint64_t netstat_get_one(const char *name, bool *not_found)
572 {
573 	struct netstat *ns = netstat_read();
574 	uint64_t ret;
575 
576 	ret = netstat_get(ns, name, not_found);
577 
578 	netstat_free(ns);
579 	return ret;
580 }
581 
582 struct tcp_sock_queue {
583 	uint32_t seq;
584 	void *buf;
585 };
586 
587 struct tcp_sock_state {
588 	struct tcp_info info;
589 	struct tcp_repair_window trw;
590 	struct tcp_sock_queue out;
591 	int outq_len;		/* output queue size (not sent + not acked) */
592 	int outq_nsd_len;	/* output queue size (not sent only) */
593 	struct tcp_sock_queue in;
594 	int inq_len;
595 	int mss;
596 	int timestamp;
597 };
598 
599 extern void __test_sock_checkpoint(int sk, struct tcp_sock_state *state,
600 				   void *addr, size_t addr_size);
601 static inline void test_sock_checkpoint(int sk, struct tcp_sock_state *state,
602 					sockaddr_af *saddr)
603 {
604 	__test_sock_checkpoint(sk, state, saddr, sizeof(*saddr));
605 }
606 extern void test_ao_checkpoint(int sk, struct tcp_ao_repair *state);
607 extern void __test_sock_restore(int sk, const char *device,
608 				struct tcp_sock_state *state,
609 				void *saddr, void *daddr, size_t addr_size);
610 static inline void test_sock_restore(int sk, struct tcp_sock_state *state,
611 				     sockaddr_af *saddr,
612 				     const union tcp_addr daddr,
613 				     unsigned int dport)
614 {
615 	sockaddr_af addr;
616 
617 	tcp_addr_to_sockaddr_in(&addr, &daddr, htons(dport));
618 	__test_sock_restore(sk, veth_name, state, saddr, &addr, sizeof(addr));
619 }
620 extern void test_ao_restore(int sk, struct tcp_ao_repair *state);
621 extern void test_sock_state_free(struct tcp_sock_state *state);
622 extern void test_enable_repair(int sk);
623 extern void test_disable_repair(int sk);
624 extern void test_kill_sk(int sk);
625 static inline int test_add_repaired_key(int sk,
626 					const char *key, uint8_t keyflags,
627 					union tcp_addr in_addr, uint8_t prefix,
628 					uint8_t sndid, uint8_t rcvid)
629 {
630 	struct tcp_ao_add tmp = {};
631 	int err;
632 
633 	err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
634 				   0, sndid, rcvid);
635 	if (err)
636 		return err;
637 
638 	tmp.set_current = 1;
639 	tmp.set_rnext = 1;
640 	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)) < 0)
641 		return -errno;
642 
643 	return test_verify_socket_key(sk, &tmp);
644 }
645 
646 #endif /* _AOLIB_H_ */
647