xref: /openbmc/linux/tools/testing/selftests/bpf/test_sock_addr.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1  // SPDX-License-Identifier: GPL-2.0
2  // Copyright (c) 2018 Facebook
3  
4  #define _GNU_SOURCE
5  
6  #include <stdio.h>
7  #include <stdlib.h>
8  #include <unistd.h>
9  
10  #include <arpa/inet.h>
11  #include <netinet/in.h>
12  #include <sys/types.h>
13  #include <sys/select.h>
14  #include <sys/socket.h>
15  
16  #include <linux/filter.h>
17  
18  #include <bpf/bpf.h>
19  #include <bpf/libbpf.h>
20  
21  #include "cgroup_helpers.h"
22  #include "bpf_util.h"
23  
24  #ifndef ENOTSUPP
25  # define ENOTSUPP 524
26  #endif
27  
28  #define CG_PATH	"/foo"
29  #define CONNECT4_PROG_PATH	"./connect4_prog.bpf.o"
30  #define CONNECT6_PROG_PATH	"./connect6_prog.bpf.o"
31  #define SENDMSG4_PROG_PATH	"./sendmsg4_prog.bpf.o"
32  #define SENDMSG6_PROG_PATH	"./sendmsg6_prog.bpf.o"
33  #define RECVMSG4_PROG_PATH	"./recvmsg4_prog.bpf.o"
34  #define RECVMSG6_PROG_PATH	"./recvmsg6_prog.bpf.o"
35  #define BIND4_PROG_PATH		"./bind4_prog.bpf.o"
36  #define BIND6_PROG_PATH		"./bind6_prog.bpf.o"
37  
38  #define SERV4_IP		"192.168.1.254"
39  #define SERV4_REWRITE_IP	"127.0.0.1"
40  #define SRC4_IP			"172.16.0.1"
41  #define SRC4_REWRITE_IP		"127.0.0.4"
42  #define SERV4_PORT		4040
43  #define SERV4_REWRITE_PORT	4444
44  
45  #define SERV6_IP		"face:b00c:1234:5678::abcd"
46  #define SERV6_REWRITE_IP	"::1"
47  #define SERV6_V4MAPPED_IP	"::ffff:192.168.0.4"
48  #define SRC6_IP			"::1"
49  #define SRC6_REWRITE_IP		"::6"
50  #define WILDCARD6_IP		"::"
51  #define SERV6_PORT		6060
52  #define SERV6_REWRITE_PORT	6666
53  
54  #define INET_NTOP_BUF	40
55  
56  struct sock_addr_test;
57  
58  typedef int (*load_fn)(const struct sock_addr_test *test);
59  typedef int (*info_fn)(int, struct sockaddr *, socklen_t *);
60  
61  char bpf_log_buf[BPF_LOG_BUF_SIZE];
62  
63  struct sock_addr_test {
64  	const char *descr;
65  	/* BPF prog properties */
66  	load_fn loadfn;
67  	enum bpf_attach_type expected_attach_type;
68  	enum bpf_attach_type attach_type;
69  	/* Socket properties */
70  	int domain;
71  	int type;
72  	/* IP:port pairs for BPF prog to override */
73  	const char *requested_ip;
74  	unsigned short requested_port;
75  	const char *expected_ip;
76  	unsigned short expected_port;
77  	const char *expected_src_ip;
78  	/* Expected test result */
79  	enum {
80  		LOAD_REJECT,
81  		ATTACH_REJECT,
82  		ATTACH_OKAY,
83  		SYSCALL_EPERM,
84  		SYSCALL_ENOTSUPP,
85  		SUCCESS,
86  	} expected_result;
87  };
88  
89  static int bind4_prog_load(const struct sock_addr_test *test);
90  static int bind6_prog_load(const struct sock_addr_test *test);
91  static int connect4_prog_load(const struct sock_addr_test *test);
92  static int connect6_prog_load(const struct sock_addr_test *test);
93  static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
94  static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
95  static int recvmsg_allow_prog_load(const struct sock_addr_test *test);
96  static int recvmsg_deny_prog_load(const struct sock_addr_test *test);
97  static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
98  static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test);
99  static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
100  static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
101  static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test);
102  static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
103  static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
104  static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
105  
106  static struct sock_addr_test tests[] = {
107  	/* bind */
108  	{
109  		"bind4: load prog with wrong expected attach type",
110  		bind4_prog_load,
111  		BPF_CGROUP_INET6_BIND,
112  		BPF_CGROUP_INET4_BIND,
113  		AF_INET,
114  		SOCK_STREAM,
115  		NULL,
116  		0,
117  		NULL,
118  		0,
119  		NULL,
120  		LOAD_REJECT,
121  	},
122  	{
123  		"bind4: attach prog with wrong attach type",
124  		bind4_prog_load,
125  		BPF_CGROUP_INET4_BIND,
126  		BPF_CGROUP_INET6_BIND,
127  		AF_INET,
128  		SOCK_STREAM,
129  		NULL,
130  		0,
131  		NULL,
132  		0,
133  		NULL,
134  		ATTACH_REJECT,
135  	},
136  	{
137  		"bind4: rewrite IP & TCP port in",
138  		bind4_prog_load,
139  		BPF_CGROUP_INET4_BIND,
140  		BPF_CGROUP_INET4_BIND,
141  		AF_INET,
142  		SOCK_STREAM,
143  		SERV4_IP,
144  		SERV4_PORT,
145  		SERV4_REWRITE_IP,
146  		SERV4_REWRITE_PORT,
147  		NULL,
148  		SUCCESS,
149  	},
150  	{
151  		"bind4: rewrite IP & UDP port in",
152  		bind4_prog_load,
153  		BPF_CGROUP_INET4_BIND,
154  		BPF_CGROUP_INET4_BIND,
155  		AF_INET,
156  		SOCK_DGRAM,
157  		SERV4_IP,
158  		SERV4_PORT,
159  		SERV4_REWRITE_IP,
160  		SERV4_REWRITE_PORT,
161  		NULL,
162  		SUCCESS,
163  	},
164  	{
165  		"bind6: load prog with wrong expected attach type",
166  		bind6_prog_load,
167  		BPF_CGROUP_INET4_BIND,
168  		BPF_CGROUP_INET6_BIND,
169  		AF_INET6,
170  		SOCK_STREAM,
171  		NULL,
172  		0,
173  		NULL,
174  		0,
175  		NULL,
176  		LOAD_REJECT,
177  	},
178  	{
179  		"bind6: attach prog with wrong attach type",
180  		bind6_prog_load,
181  		BPF_CGROUP_INET6_BIND,
182  		BPF_CGROUP_INET4_BIND,
183  		AF_INET,
184  		SOCK_STREAM,
185  		NULL,
186  		0,
187  		NULL,
188  		0,
189  		NULL,
190  		ATTACH_REJECT,
191  	},
192  	{
193  		"bind6: rewrite IP & TCP port in",
194  		bind6_prog_load,
195  		BPF_CGROUP_INET6_BIND,
196  		BPF_CGROUP_INET6_BIND,
197  		AF_INET6,
198  		SOCK_STREAM,
199  		SERV6_IP,
200  		SERV6_PORT,
201  		SERV6_REWRITE_IP,
202  		SERV6_REWRITE_PORT,
203  		NULL,
204  		SUCCESS,
205  	},
206  	{
207  		"bind6: rewrite IP & UDP port in",
208  		bind6_prog_load,
209  		BPF_CGROUP_INET6_BIND,
210  		BPF_CGROUP_INET6_BIND,
211  		AF_INET6,
212  		SOCK_DGRAM,
213  		SERV6_IP,
214  		SERV6_PORT,
215  		SERV6_REWRITE_IP,
216  		SERV6_REWRITE_PORT,
217  		NULL,
218  		SUCCESS,
219  	},
220  
221  	/* connect */
222  	{
223  		"connect4: load prog with wrong expected attach type",
224  		connect4_prog_load,
225  		BPF_CGROUP_INET6_CONNECT,
226  		BPF_CGROUP_INET4_CONNECT,
227  		AF_INET,
228  		SOCK_STREAM,
229  		NULL,
230  		0,
231  		NULL,
232  		0,
233  		NULL,
234  		LOAD_REJECT,
235  	},
236  	{
237  		"connect4: attach prog with wrong attach type",
238  		connect4_prog_load,
239  		BPF_CGROUP_INET4_CONNECT,
240  		BPF_CGROUP_INET6_CONNECT,
241  		AF_INET,
242  		SOCK_STREAM,
243  		NULL,
244  		0,
245  		NULL,
246  		0,
247  		NULL,
248  		ATTACH_REJECT,
249  	},
250  	{
251  		"connect4: rewrite IP & TCP port",
252  		connect4_prog_load,
253  		BPF_CGROUP_INET4_CONNECT,
254  		BPF_CGROUP_INET4_CONNECT,
255  		AF_INET,
256  		SOCK_STREAM,
257  		SERV4_IP,
258  		SERV4_PORT,
259  		SERV4_REWRITE_IP,
260  		SERV4_REWRITE_PORT,
261  		SRC4_REWRITE_IP,
262  		SUCCESS,
263  	},
264  	{
265  		"connect4: rewrite IP & UDP port",
266  		connect4_prog_load,
267  		BPF_CGROUP_INET4_CONNECT,
268  		BPF_CGROUP_INET4_CONNECT,
269  		AF_INET,
270  		SOCK_DGRAM,
271  		SERV4_IP,
272  		SERV4_PORT,
273  		SERV4_REWRITE_IP,
274  		SERV4_REWRITE_PORT,
275  		SRC4_REWRITE_IP,
276  		SUCCESS,
277  	},
278  	{
279  		"connect6: load prog with wrong expected attach type",
280  		connect6_prog_load,
281  		BPF_CGROUP_INET4_CONNECT,
282  		BPF_CGROUP_INET6_CONNECT,
283  		AF_INET6,
284  		SOCK_STREAM,
285  		NULL,
286  		0,
287  		NULL,
288  		0,
289  		NULL,
290  		LOAD_REJECT,
291  	},
292  	{
293  		"connect6: attach prog with wrong attach type",
294  		connect6_prog_load,
295  		BPF_CGROUP_INET6_CONNECT,
296  		BPF_CGROUP_INET4_CONNECT,
297  		AF_INET,
298  		SOCK_STREAM,
299  		NULL,
300  		0,
301  		NULL,
302  		0,
303  		NULL,
304  		ATTACH_REJECT,
305  	},
306  	{
307  		"connect6: rewrite IP & TCP port",
308  		connect6_prog_load,
309  		BPF_CGROUP_INET6_CONNECT,
310  		BPF_CGROUP_INET6_CONNECT,
311  		AF_INET6,
312  		SOCK_STREAM,
313  		SERV6_IP,
314  		SERV6_PORT,
315  		SERV6_REWRITE_IP,
316  		SERV6_REWRITE_PORT,
317  		SRC6_REWRITE_IP,
318  		SUCCESS,
319  	},
320  	{
321  		"connect6: rewrite IP & UDP port",
322  		connect6_prog_load,
323  		BPF_CGROUP_INET6_CONNECT,
324  		BPF_CGROUP_INET6_CONNECT,
325  		AF_INET6,
326  		SOCK_DGRAM,
327  		SERV6_IP,
328  		SERV6_PORT,
329  		SERV6_REWRITE_IP,
330  		SERV6_REWRITE_PORT,
331  		SRC6_REWRITE_IP,
332  		SUCCESS,
333  	},
334  
335  	/* sendmsg */
336  	{
337  		"sendmsg4: load prog with wrong expected attach type",
338  		sendmsg4_rw_asm_prog_load,
339  		BPF_CGROUP_UDP6_SENDMSG,
340  		BPF_CGROUP_UDP4_SENDMSG,
341  		AF_INET,
342  		SOCK_DGRAM,
343  		NULL,
344  		0,
345  		NULL,
346  		0,
347  		NULL,
348  		LOAD_REJECT,
349  	},
350  	{
351  		"sendmsg4: attach prog with wrong attach type",
352  		sendmsg4_rw_asm_prog_load,
353  		BPF_CGROUP_UDP4_SENDMSG,
354  		BPF_CGROUP_UDP6_SENDMSG,
355  		AF_INET,
356  		SOCK_DGRAM,
357  		NULL,
358  		0,
359  		NULL,
360  		0,
361  		NULL,
362  		ATTACH_REJECT,
363  	},
364  	{
365  		"sendmsg4: rewrite IP & port (asm)",
366  		sendmsg4_rw_asm_prog_load,
367  		BPF_CGROUP_UDP4_SENDMSG,
368  		BPF_CGROUP_UDP4_SENDMSG,
369  		AF_INET,
370  		SOCK_DGRAM,
371  		SERV4_IP,
372  		SERV4_PORT,
373  		SERV4_REWRITE_IP,
374  		SERV4_REWRITE_PORT,
375  		SRC4_REWRITE_IP,
376  		SUCCESS,
377  	},
378  	{
379  		"sendmsg4: rewrite IP & port (C)",
380  		sendmsg4_rw_c_prog_load,
381  		BPF_CGROUP_UDP4_SENDMSG,
382  		BPF_CGROUP_UDP4_SENDMSG,
383  		AF_INET,
384  		SOCK_DGRAM,
385  		SERV4_IP,
386  		SERV4_PORT,
387  		SERV4_REWRITE_IP,
388  		SERV4_REWRITE_PORT,
389  		SRC4_REWRITE_IP,
390  		SUCCESS,
391  	},
392  	{
393  		"sendmsg4: deny call",
394  		sendmsg_deny_prog_load,
395  		BPF_CGROUP_UDP4_SENDMSG,
396  		BPF_CGROUP_UDP4_SENDMSG,
397  		AF_INET,
398  		SOCK_DGRAM,
399  		SERV4_IP,
400  		SERV4_PORT,
401  		SERV4_REWRITE_IP,
402  		SERV4_REWRITE_PORT,
403  		SRC4_REWRITE_IP,
404  		SYSCALL_EPERM,
405  	},
406  	{
407  		"sendmsg6: load prog with wrong expected attach type",
408  		sendmsg6_rw_asm_prog_load,
409  		BPF_CGROUP_UDP4_SENDMSG,
410  		BPF_CGROUP_UDP6_SENDMSG,
411  		AF_INET6,
412  		SOCK_DGRAM,
413  		NULL,
414  		0,
415  		NULL,
416  		0,
417  		NULL,
418  		LOAD_REJECT,
419  	},
420  	{
421  		"sendmsg6: attach prog with wrong attach type",
422  		sendmsg6_rw_asm_prog_load,
423  		BPF_CGROUP_UDP6_SENDMSG,
424  		BPF_CGROUP_UDP4_SENDMSG,
425  		AF_INET6,
426  		SOCK_DGRAM,
427  		NULL,
428  		0,
429  		NULL,
430  		0,
431  		NULL,
432  		ATTACH_REJECT,
433  	},
434  	{
435  		"sendmsg6: rewrite IP & port (asm)",
436  		sendmsg6_rw_asm_prog_load,
437  		BPF_CGROUP_UDP6_SENDMSG,
438  		BPF_CGROUP_UDP6_SENDMSG,
439  		AF_INET6,
440  		SOCK_DGRAM,
441  		SERV6_IP,
442  		SERV6_PORT,
443  		SERV6_REWRITE_IP,
444  		SERV6_REWRITE_PORT,
445  		SRC6_REWRITE_IP,
446  		SUCCESS,
447  	},
448  	{
449  		"sendmsg6: rewrite IP & port (C)",
450  		sendmsg6_rw_c_prog_load,
451  		BPF_CGROUP_UDP6_SENDMSG,
452  		BPF_CGROUP_UDP6_SENDMSG,
453  		AF_INET6,
454  		SOCK_DGRAM,
455  		SERV6_IP,
456  		SERV6_PORT,
457  		SERV6_REWRITE_IP,
458  		SERV6_REWRITE_PORT,
459  		SRC6_REWRITE_IP,
460  		SUCCESS,
461  	},
462  	{
463  		"sendmsg6: IPv4-mapped IPv6",
464  		sendmsg6_rw_v4mapped_prog_load,
465  		BPF_CGROUP_UDP6_SENDMSG,
466  		BPF_CGROUP_UDP6_SENDMSG,
467  		AF_INET6,
468  		SOCK_DGRAM,
469  		SERV6_IP,
470  		SERV6_PORT,
471  		SERV6_REWRITE_IP,
472  		SERV6_REWRITE_PORT,
473  		SRC6_REWRITE_IP,
474  		SYSCALL_ENOTSUPP,
475  	},
476  	{
477  		"sendmsg6: set dst IP = [::] (BSD'ism)",
478  		sendmsg6_rw_wildcard_prog_load,
479  		BPF_CGROUP_UDP6_SENDMSG,
480  		BPF_CGROUP_UDP6_SENDMSG,
481  		AF_INET6,
482  		SOCK_DGRAM,
483  		SERV6_IP,
484  		SERV6_PORT,
485  		SERV6_REWRITE_IP,
486  		SERV6_REWRITE_PORT,
487  		SRC6_REWRITE_IP,
488  		SUCCESS,
489  	},
490  	{
491  		"sendmsg6: preserve dst IP = [::] (BSD'ism)",
492  		sendmsg_allow_prog_load,
493  		BPF_CGROUP_UDP6_SENDMSG,
494  		BPF_CGROUP_UDP6_SENDMSG,
495  		AF_INET6,
496  		SOCK_DGRAM,
497  		WILDCARD6_IP,
498  		SERV6_PORT,
499  		SERV6_REWRITE_IP,
500  		SERV6_PORT,
501  		SRC6_IP,
502  		SUCCESS,
503  	},
504  	{
505  		"sendmsg6: deny call",
506  		sendmsg_deny_prog_load,
507  		BPF_CGROUP_UDP6_SENDMSG,
508  		BPF_CGROUP_UDP6_SENDMSG,
509  		AF_INET6,
510  		SOCK_DGRAM,
511  		SERV6_IP,
512  		SERV6_PORT,
513  		SERV6_REWRITE_IP,
514  		SERV6_REWRITE_PORT,
515  		SRC6_REWRITE_IP,
516  		SYSCALL_EPERM,
517  	},
518  
519  	/* recvmsg */
520  	{
521  		"recvmsg4: return code ok",
522  		recvmsg_allow_prog_load,
523  		BPF_CGROUP_UDP4_RECVMSG,
524  		BPF_CGROUP_UDP4_RECVMSG,
525  		AF_INET,
526  		SOCK_DGRAM,
527  		NULL,
528  		0,
529  		NULL,
530  		0,
531  		NULL,
532  		ATTACH_OKAY,
533  	},
534  	{
535  		"recvmsg4: return code !ok",
536  		recvmsg_deny_prog_load,
537  		BPF_CGROUP_UDP4_RECVMSG,
538  		BPF_CGROUP_UDP4_RECVMSG,
539  		AF_INET,
540  		SOCK_DGRAM,
541  		NULL,
542  		0,
543  		NULL,
544  		0,
545  		NULL,
546  		LOAD_REJECT,
547  	},
548  	{
549  		"recvmsg6: return code ok",
550  		recvmsg_allow_prog_load,
551  		BPF_CGROUP_UDP6_RECVMSG,
552  		BPF_CGROUP_UDP6_RECVMSG,
553  		AF_INET6,
554  		SOCK_DGRAM,
555  		NULL,
556  		0,
557  		NULL,
558  		0,
559  		NULL,
560  		ATTACH_OKAY,
561  	},
562  	{
563  		"recvmsg6: return code !ok",
564  		recvmsg_deny_prog_load,
565  		BPF_CGROUP_UDP6_RECVMSG,
566  		BPF_CGROUP_UDP6_RECVMSG,
567  		AF_INET6,
568  		SOCK_DGRAM,
569  		NULL,
570  		0,
571  		NULL,
572  		0,
573  		NULL,
574  		LOAD_REJECT,
575  	},
576  	{
577  		"recvmsg4: rewrite IP & port (C)",
578  		recvmsg4_rw_c_prog_load,
579  		BPF_CGROUP_UDP4_RECVMSG,
580  		BPF_CGROUP_UDP4_RECVMSG,
581  		AF_INET,
582  		SOCK_DGRAM,
583  		SERV4_REWRITE_IP,
584  		SERV4_REWRITE_PORT,
585  		SERV4_REWRITE_IP,
586  		SERV4_REWRITE_PORT,
587  		SERV4_IP,
588  		SUCCESS,
589  	},
590  	{
591  		"recvmsg6: rewrite IP & port (C)",
592  		recvmsg6_rw_c_prog_load,
593  		BPF_CGROUP_UDP6_RECVMSG,
594  		BPF_CGROUP_UDP6_RECVMSG,
595  		AF_INET6,
596  		SOCK_DGRAM,
597  		SERV6_REWRITE_IP,
598  		SERV6_REWRITE_PORT,
599  		SERV6_REWRITE_IP,
600  		SERV6_REWRITE_PORT,
601  		SERV6_IP,
602  		SUCCESS,
603  	},
604  };
605  
mk_sockaddr(int domain,const char * ip,unsigned short port,struct sockaddr * addr,socklen_t addr_len)606  static int mk_sockaddr(int domain, const char *ip, unsigned short port,
607  		       struct sockaddr *addr, socklen_t addr_len)
608  {
609  	struct sockaddr_in6 *addr6;
610  	struct sockaddr_in *addr4;
611  
612  	if (domain != AF_INET && domain != AF_INET6) {
613  		log_err("Unsupported address family");
614  		return -1;
615  	}
616  
617  	memset(addr, 0, addr_len);
618  
619  	if (domain == AF_INET) {
620  		if (addr_len < sizeof(struct sockaddr_in))
621  			return -1;
622  		addr4 = (struct sockaddr_in *)addr;
623  		addr4->sin_family = domain;
624  		addr4->sin_port = htons(port);
625  		if (inet_pton(domain, ip, (void *)&addr4->sin_addr) != 1) {
626  			log_err("Invalid IPv4: %s", ip);
627  			return -1;
628  		}
629  	} else if (domain == AF_INET6) {
630  		if (addr_len < sizeof(struct sockaddr_in6))
631  			return -1;
632  		addr6 = (struct sockaddr_in6 *)addr;
633  		addr6->sin6_family = domain;
634  		addr6->sin6_port = htons(port);
635  		if (inet_pton(domain, ip, (void *)&addr6->sin6_addr) != 1) {
636  			log_err("Invalid IPv6: %s", ip);
637  			return -1;
638  		}
639  	}
640  
641  	return 0;
642  }
643  
load_insns(const struct sock_addr_test * test,const struct bpf_insn * insns,size_t insns_cnt)644  static int load_insns(const struct sock_addr_test *test,
645  		      const struct bpf_insn *insns, size_t insns_cnt)
646  {
647  	LIBBPF_OPTS(bpf_prog_load_opts, opts);
648  	int ret;
649  
650  	opts.expected_attach_type = test->expected_attach_type;
651  	opts.log_buf = bpf_log_buf;
652  	opts.log_size = BPF_LOG_BUF_SIZE;
653  
654  	ret = bpf_prog_load(BPF_PROG_TYPE_CGROUP_SOCK_ADDR, NULL, "GPL", insns, insns_cnt, &opts);
655  	if (ret < 0 && test->expected_result != LOAD_REJECT) {
656  		log_err(">>> Loading program error.\n"
657  			">>> Verifier output:\n%s\n-------\n", bpf_log_buf);
658  	}
659  
660  	return ret;
661  }
662  
load_path(const struct sock_addr_test * test,const char * path)663  static int load_path(const struct sock_addr_test *test, const char *path)
664  {
665  	struct bpf_object *obj;
666  	struct bpf_program *prog;
667  	int err;
668  
669  	obj = bpf_object__open_file(path, NULL);
670  	err = libbpf_get_error(obj);
671  	if (err) {
672  		log_err(">>> Opening BPF object (%s) error.\n", path);
673  		return -1;
674  	}
675  
676  	prog = bpf_object__next_program(obj, NULL);
677  	if (!prog)
678  		goto err_out;
679  
680  	bpf_program__set_type(prog, BPF_PROG_TYPE_CGROUP_SOCK_ADDR);
681  	bpf_program__set_expected_attach_type(prog, test->expected_attach_type);
682  	bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32);
683  
684  	err = bpf_object__load(obj);
685  	if (err) {
686  		if (test->expected_result != LOAD_REJECT)
687  			log_err(">>> Loading program (%s) error.\n", path);
688  		goto err_out;
689  	}
690  
691  	return bpf_program__fd(prog);
692  err_out:
693  	bpf_object__close(obj);
694  	return -1;
695  }
696  
bind4_prog_load(const struct sock_addr_test * test)697  static int bind4_prog_load(const struct sock_addr_test *test)
698  {
699  	return load_path(test, BIND4_PROG_PATH);
700  }
701  
bind6_prog_load(const struct sock_addr_test * test)702  static int bind6_prog_load(const struct sock_addr_test *test)
703  {
704  	return load_path(test, BIND6_PROG_PATH);
705  }
706  
connect4_prog_load(const struct sock_addr_test * test)707  static int connect4_prog_load(const struct sock_addr_test *test)
708  {
709  	return load_path(test, CONNECT4_PROG_PATH);
710  }
711  
connect6_prog_load(const struct sock_addr_test * test)712  static int connect6_prog_load(const struct sock_addr_test *test)
713  {
714  	return load_path(test, CONNECT6_PROG_PATH);
715  }
716  
xmsg_ret_only_prog_load(const struct sock_addr_test * test,int32_t rc)717  static int xmsg_ret_only_prog_load(const struct sock_addr_test *test,
718  				   int32_t rc)
719  {
720  	struct bpf_insn insns[] = {
721  		/* return rc */
722  		BPF_MOV64_IMM(BPF_REG_0, rc),
723  		BPF_EXIT_INSN(),
724  	};
725  	return load_insns(test, insns, ARRAY_SIZE(insns));
726  }
727  
sendmsg_allow_prog_load(const struct sock_addr_test * test)728  static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
729  {
730  	return xmsg_ret_only_prog_load(test, /*rc*/ 1);
731  }
732  
sendmsg_deny_prog_load(const struct sock_addr_test * test)733  static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
734  {
735  	return xmsg_ret_only_prog_load(test, /*rc*/ 0);
736  }
737  
recvmsg_allow_prog_load(const struct sock_addr_test * test)738  static int recvmsg_allow_prog_load(const struct sock_addr_test *test)
739  {
740  	return xmsg_ret_only_prog_load(test, /*rc*/ 1);
741  }
742  
recvmsg_deny_prog_load(const struct sock_addr_test * test)743  static int recvmsg_deny_prog_load(const struct sock_addr_test *test)
744  {
745  	return xmsg_ret_only_prog_load(test, /*rc*/ 0);
746  }
747  
sendmsg4_rw_asm_prog_load(const struct sock_addr_test * test)748  static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
749  {
750  	struct sockaddr_in dst4_rw_addr;
751  	struct in_addr src4_rw_ip;
752  
753  	if (inet_pton(AF_INET, SRC4_REWRITE_IP, (void *)&src4_rw_ip) != 1) {
754  		log_err("Invalid IPv4: %s", SRC4_REWRITE_IP);
755  		return -1;
756  	}
757  
758  	if (mk_sockaddr(AF_INET, SERV4_REWRITE_IP, SERV4_REWRITE_PORT,
759  			(struct sockaddr *)&dst4_rw_addr,
760  			sizeof(dst4_rw_addr)) == -1)
761  		return -1;
762  
763  	struct bpf_insn insns[] = {
764  		BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
765  
766  		/* if (sk.family == AF_INET && */
767  		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
768  			    offsetof(struct bpf_sock_addr, family)),
769  		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET, 8),
770  
771  		/*     sk.type == SOCK_DGRAM)  { */
772  		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
773  			    offsetof(struct bpf_sock_addr, type)),
774  		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, SOCK_DGRAM, 6),
775  
776  		/*      msg_src_ip4 = src4_rw_ip */
777  		BPF_MOV32_IMM(BPF_REG_7, src4_rw_ip.s_addr),
778  		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
779  			    offsetof(struct bpf_sock_addr, msg_src_ip4)),
780  
781  		/*      user_ip4 = dst4_rw_addr.sin_addr */
782  		BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_addr.s_addr),
783  		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
784  			    offsetof(struct bpf_sock_addr, user_ip4)),
785  
786  		/*      user_port = dst4_rw_addr.sin_port */
787  		BPF_MOV32_IMM(BPF_REG_7, dst4_rw_addr.sin_port),
788  		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
789  			    offsetof(struct bpf_sock_addr, user_port)),
790  		/* } */
791  
792  		/* return 1 */
793  		BPF_MOV64_IMM(BPF_REG_0, 1),
794  		BPF_EXIT_INSN(),
795  	};
796  
797  	return load_insns(test, insns, ARRAY_SIZE(insns));
798  }
799  
recvmsg4_rw_c_prog_load(const struct sock_addr_test * test)800  static int recvmsg4_rw_c_prog_load(const struct sock_addr_test *test)
801  {
802  	return load_path(test, RECVMSG4_PROG_PATH);
803  }
804  
sendmsg4_rw_c_prog_load(const struct sock_addr_test * test)805  static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test)
806  {
807  	return load_path(test, SENDMSG4_PROG_PATH);
808  }
809  
sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test * test,const char * rw_dst_ip)810  static int sendmsg6_rw_dst_asm_prog_load(const struct sock_addr_test *test,
811  					 const char *rw_dst_ip)
812  {
813  	struct sockaddr_in6 dst6_rw_addr;
814  	struct in6_addr src6_rw_ip;
815  
816  	if (inet_pton(AF_INET6, SRC6_REWRITE_IP, (void *)&src6_rw_ip) != 1) {
817  		log_err("Invalid IPv6: %s", SRC6_REWRITE_IP);
818  		return -1;
819  	}
820  
821  	if (mk_sockaddr(AF_INET6, rw_dst_ip, SERV6_REWRITE_PORT,
822  			(struct sockaddr *)&dst6_rw_addr,
823  			sizeof(dst6_rw_addr)) == -1)
824  		return -1;
825  
826  	struct bpf_insn insns[] = {
827  		BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
828  
829  		/* if (sk.family == AF_INET6) { */
830  		BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_6,
831  			    offsetof(struct bpf_sock_addr, family)),
832  		BPF_JMP_IMM(BPF_JNE, BPF_REG_7, AF_INET6, 18),
833  
834  #define STORE_IPV6_WORD_N(DST, SRC, N)					       \
835  		BPF_MOV32_IMM(BPF_REG_7, SRC[N]),			       \
836  		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,		       \
837  			    offsetof(struct bpf_sock_addr, DST[N]))
838  
839  #define STORE_IPV6(DST, SRC)						       \
840  		STORE_IPV6_WORD_N(DST, SRC, 0),				       \
841  		STORE_IPV6_WORD_N(DST, SRC, 1),				       \
842  		STORE_IPV6_WORD_N(DST, SRC, 2),				       \
843  		STORE_IPV6_WORD_N(DST, SRC, 3)
844  
845  		STORE_IPV6(msg_src_ip6, src6_rw_ip.s6_addr32),
846  		STORE_IPV6(user_ip6, dst6_rw_addr.sin6_addr.s6_addr32),
847  
848  		/*      user_port = dst6_rw_addr.sin6_port */
849  		BPF_MOV32_IMM(BPF_REG_7, dst6_rw_addr.sin6_port),
850  		BPF_STX_MEM(BPF_W, BPF_REG_6, BPF_REG_7,
851  			    offsetof(struct bpf_sock_addr, user_port)),
852  
853  		/* } */
854  
855  		/* return 1 */
856  		BPF_MOV64_IMM(BPF_REG_0, 1),
857  		BPF_EXIT_INSN(),
858  	};
859  
860  	return load_insns(test, insns, ARRAY_SIZE(insns));
861  }
862  
sendmsg6_rw_asm_prog_load(const struct sock_addr_test * test)863  static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test)
864  {
865  	return sendmsg6_rw_dst_asm_prog_load(test, SERV6_REWRITE_IP);
866  }
867  
recvmsg6_rw_c_prog_load(const struct sock_addr_test * test)868  static int recvmsg6_rw_c_prog_load(const struct sock_addr_test *test)
869  {
870  	return load_path(test, RECVMSG6_PROG_PATH);
871  }
872  
sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test * test)873  static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
874  {
875  	return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
876  }
877  
sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test * test)878  static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
879  {
880  	return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
881  }
882  
sendmsg6_rw_c_prog_load(const struct sock_addr_test * test)883  static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
884  {
885  	return load_path(test, SENDMSG6_PROG_PATH);
886  }
887  
cmp_addr(const struct sockaddr_storage * addr1,const struct sockaddr_storage * addr2,int cmp_port)888  static int cmp_addr(const struct sockaddr_storage *addr1,
889  		    const struct sockaddr_storage *addr2, int cmp_port)
890  {
891  	const struct sockaddr_in *four1, *four2;
892  	const struct sockaddr_in6 *six1, *six2;
893  
894  	if (addr1->ss_family != addr2->ss_family)
895  		return -1;
896  
897  	if (addr1->ss_family == AF_INET) {
898  		four1 = (const struct sockaddr_in *)addr1;
899  		four2 = (const struct sockaddr_in *)addr2;
900  		return !((four1->sin_port == four2->sin_port || !cmp_port) &&
901  			 four1->sin_addr.s_addr == four2->sin_addr.s_addr);
902  	} else if (addr1->ss_family == AF_INET6) {
903  		six1 = (const struct sockaddr_in6 *)addr1;
904  		six2 = (const struct sockaddr_in6 *)addr2;
905  		return !((six1->sin6_port == six2->sin6_port || !cmp_port) &&
906  			 !memcmp(&six1->sin6_addr, &six2->sin6_addr,
907  				 sizeof(struct in6_addr)));
908  	}
909  
910  	return -1;
911  }
912  
cmp_sock_addr(info_fn fn,int sock1,const struct sockaddr_storage * addr2,int cmp_port)913  static int cmp_sock_addr(info_fn fn, int sock1,
914  			 const struct sockaddr_storage *addr2, int cmp_port)
915  {
916  	struct sockaddr_storage addr1;
917  	socklen_t len1 = sizeof(addr1);
918  
919  	memset(&addr1, 0, len1);
920  	if (fn(sock1, (struct sockaddr *)&addr1, (socklen_t *)&len1) != 0)
921  		return -1;
922  
923  	return cmp_addr(&addr1, addr2, cmp_port);
924  }
925  
cmp_local_ip(int sock1,const struct sockaddr_storage * addr2)926  static int cmp_local_ip(int sock1, const struct sockaddr_storage *addr2)
927  {
928  	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 0);
929  }
930  
cmp_local_addr(int sock1,const struct sockaddr_storage * addr2)931  static int cmp_local_addr(int sock1, const struct sockaddr_storage *addr2)
932  {
933  	return cmp_sock_addr(getsockname, sock1, addr2, /*cmp_port*/ 1);
934  }
935  
cmp_peer_addr(int sock1,const struct sockaddr_storage * addr2)936  static int cmp_peer_addr(int sock1, const struct sockaddr_storage *addr2)
937  {
938  	return cmp_sock_addr(getpeername, sock1, addr2, /*cmp_port*/ 1);
939  }
940  
start_server(int type,const struct sockaddr_storage * addr,socklen_t addr_len)941  static int start_server(int type, const struct sockaddr_storage *addr,
942  			socklen_t addr_len)
943  {
944  	int fd;
945  
946  	fd = socket(addr->ss_family, type, 0);
947  	if (fd == -1) {
948  		log_err("Failed to create server socket");
949  		goto out;
950  	}
951  
952  	if (bind(fd, (const struct sockaddr *)addr, addr_len) == -1) {
953  		log_err("Failed to bind server socket");
954  		goto close_out;
955  	}
956  
957  	if (type == SOCK_STREAM) {
958  		if (listen(fd, 128) == -1) {
959  			log_err("Failed to listen on server socket");
960  			goto close_out;
961  		}
962  	}
963  
964  	goto out;
965  close_out:
966  	close(fd);
967  	fd = -1;
968  out:
969  	return fd;
970  }
971  
connect_to_server(int type,const struct sockaddr_storage * addr,socklen_t addr_len)972  static int connect_to_server(int type, const struct sockaddr_storage *addr,
973  			     socklen_t addr_len)
974  {
975  	int domain;
976  	int fd = -1;
977  
978  	domain = addr->ss_family;
979  
980  	if (domain != AF_INET && domain != AF_INET6) {
981  		log_err("Unsupported address family");
982  		goto err;
983  	}
984  
985  	fd = socket(domain, type, 0);
986  	if (fd == -1) {
987  		log_err("Failed to create client socket");
988  		goto err;
989  	}
990  
991  	if (connect(fd, (const struct sockaddr *)addr, addr_len) == -1) {
992  		log_err("Fail to connect to server");
993  		goto err;
994  	}
995  
996  	goto out;
997  err:
998  	close(fd);
999  	fd = -1;
1000  out:
1001  	return fd;
1002  }
1003  
init_pktinfo(int domain,struct cmsghdr * cmsg)1004  int init_pktinfo(int domain, struct cmsghdr *cmsg)
1005  {
1006  	struct in6_pktinfo *pktinfo6;
1007  	struct in_pktinfo *pktinfo4;
1008  
1009  	if (domain == AF_INET) {
1010  		cmsg->cmsg_level = SOL_IP;
1011  		cmsg->cmsg_type = IP_PKTINFO;
1012  		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
1013  		pktinfo4 = (struct in_pktinfo *)CMSG_DATA(cmsg);
1014  		memset(pktinfo4, 0, sizeof(struct in_pktinfo));
1015  		if (inet_pton(domain, SRC4_IP,
1016  			      (void *)&pktinfo4->ipi_spec_dst) != 1)
1017  			return -1;
1018  	} else if (domain == AF_INET6) {
1019  		cmsg->cmsg_level = SOL_IPV6;
1020  		cmsg->cmsg_type = IPV6_PKTINFO;
1021  		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
1022  		pktinfo6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
1023  		memset(pktinfo6, 0, sizeof(struct in6_pktinfo));
1024  		if (inet_pton(domain, SRC6_IP,
1025  			      (void *)&pktinfo6->ipi6_addr) != 1)
1026  			return -1;
1027  	} else {
1028  		return -1;
1029  	}
1030  
1031  	return 0;
1032  }
1033  
sendmsg_to_server(int type,const struct sockaddr_storage * addr,socklen_t addr_len,int set_cmsg,int flags,int * syscall_err)1034  static int sendmsg_to_server(int type, const struct sockaddr_storage *addr,
1035  			     socklen_t addr_len, int set_cmsg, int flags,
1036  			     int *syscall_err)
1037  {
1038  	union {
1039  		char buf[CMSG_SPACE(sizeof(struct in6_pktinfo))];
1040  		struct cmsghdr align;
1041  	} control6;
1042  	union {
1043  		char buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
1044  		struct cmsghdr align;
1045  	} control4;
1046  	struct msghdr hdr;
1047  	struct iovec iov;
1048  	char data = 'a';
1049  	int domain;
1050  	int fd = -1;
1051  
1052  	domain = addr->ss_family;
1053  
1054  	if (domain != AF_INET && domain != AF_INET6) {
1055  		log_err("Unsupported address family");
1056  		goto err;
1057  	}
1058  
1059  	fd = socket(domain, type, 0);
1060  	if (fd == -1) {
1061  		log_err("Failed to create client socket");
1062  		goto err;
1063  	}
1064  
1065  	memset(&iov, 0, sizeof(iov));
1066  	iov.iov_base = &data;
1067  	iov.iov_len = sizeof(data);
1068  
1069  	memset(&hdr, 0, sizeof(hdr));
1070  	hdr.msg_name = (void *)addr;
1071  	hdr.msg_namelen = addr_len;
1072  	hdr.msg_iov = &iov;
1073  	hdr.msg_iovlen = 1;
1074  
1075  	if (set_cmsg) {
1076  		if (domain == AF_INET) {
1077  			hdr.msg_control = &control4;
1078  			hdr.msg_controllen = sizeof(control4.buf);
1079  		} else if (domain == AF_INET6) {
1080  			hdr.msg_control = &control6;
1081  			hdr.msg_controllen = sizeof(control6.buf);
1082  		}
1083  		if (init_pktinfo(domain, CMSG_FIRSTHDR(&hdr))) {
1084  			log_err("Fail to init pktinfo");
1085  			goto err;
1086  		}
1087  	}
1088  
1089  	if (sendmsg(fd, &hdr, flags) != sizeof(data)) {
1090  		log_err("Fail to send message to server");
1091  		*syscall_err = errno;
1092  		goto err;
1093  	}
1094  
1095  	goto out;
1096  err:
1097  	close(fd);
1098  	fd = -1;
1099  out:
1100  	return fd;
1101  }
1102  
fastconnect_to_server(const struct sockaddr_storage * addr,socklen_t addr_len)1103  static int fastconnect_to_server(const struct sockaddr_storage *addr,
1104  				 socklen_t addr_len)
1105  {
1106  	int sendmsg_err;
1107  
1108  	return sendmsg_to_server(SOCK_STREAM, addr, addr_len, /*set_cmsg*/0,
1109  				 MSG_FASTOPEN, &sendmsg_err);
1110  }
1111  
recvmsg_from_client(int sockfd,struct sockaddr_storage * src_addr)1112  static int recvmsg_from_client(int sockfd, struct sockaddr_storage *src_addr)
1113  {
1114  	struct timeval tv;
1115  	struct msghdr hdr;
1116  	struct iovec iov;
1117  	char data[64];
1118  	fd_set rfds;
1119  
1120  	FD_ZERO(&rfds);
1121  	FD_SET(sockfd, &rfds);
1122  
1123  	tv.tv_sec = 2;
1124  	tv.tv_usec = 0;
1125  
1126  	if (select(sockfd + 1, &rfds, NULL, NULL, &tv) <= 0 ||
1127  	    !FD_ISSET(sockfd, &rfds))
1128  		return -1;
1129  
1130  	memset(&iov, 0, sizeof(iov));
1131  	iov.iov_base = data;
1132  	iov.iov_len = sizeof(data);
1133  
1134  	memset(&hdr, 0, sizeof(hdr));
1135  	hdr.msg_name = src_addr;
1136  	hdr.msg_namelen = sizeof(struct sockaddr_storage);
1137  	hdr.msg_iov = &iov;
1138  	hdr.msg_iovlen = 1;
1139  
1140  	return recvmsg(sockfd, &hdr, 0);
1141  }
1142  
init_addrs(const struct sock_addr_test * test,struct sockaddr_storage * requested_addr,struct sockaddr_storage * expected_addr,struct sockaddr_storage * expected_src_addr)1143  static int init_addrs(const struct sock_addr_test *test,
1144  		      struct sockaddr_storage *requested_addr,
1145  		      struct sockaddr_storage *expected_addr,
1146  		      struct sockaddr_storage *expected_src_addr)
1147  {
1148  	socklen_t addr_len = sizeof(struct sockaddr_storage);
1149  
1150  	if (mk_sockaddr(test->domain, test->expected_ip, test->expected_port,
1151  			(struct sockaddr *)expected_addr, addr_len) == -1)
1152  		goto err;
1153  
1154  	if (mk_sockaddr(test->domain, test->requested_ip, test->requested_port,
1155  			(struct sockaddr *)requested_addr, addr_len) == -1)
1156  		goto err;
1157  
1158  	if (test->expected_src_ip &&
1159  	    mk_sockaddr(test->domain, test->expected_src_ip, 0,
1160  			(struct sockaddr *)expected_src_addr, addr_len) == -1)
1161  		goto err;
1162  
1163  	return 0;
1164  err:
1165  	return -1;
1166  }
1167  
run_bind_test_case(const struct sock_addr_test * test)1168  static int run_bind_test_case(const struct sock_addr_test *test)
1169  {
1170  	socklen_t addr_len = sizeof(struct sockaddr_storage);
1171  	struct sockaddr_storage requested_addr;
1172  	struct sockaddr_storage expected_addr;
1173  	int clientfd = -1;
1174  	int servfd = -1;
1175  	int err = 0;
1176  
1177  	if (init_addrs(test, &requested_addr, &expected_addr, NULL))
1178  		goto err;
1179  
1180  	servfd = start_server(test->type, &requested_addr, addr_len);
1181  	if (servfd == -1)
1182  		goto err;
1183  
1184  	if (cmp_local_addr(servfd, &expected_addr))
1185  		goto err;
1186  
1187  	/* Try to connect to server just in case */
1188  	clientfd = connect_to_server(test->type, &expected_addr, addr_len);
1189  	if (clientfd == -1)
1190  		goto err;
1191  
1192  	goto out;
1193  err:
1194  	err = -1;
1195  out:
1196  	close(clientfd);
1197  	close(servfd);
1198  	return err;
1199  }
1200  
run_connect_test_case(const struct sock_addr_test * test)1201  static int run_connect_test_case(const struct sock_addr_test *test)
1202  {
1203  	socklen_t addr_len = sizeof(struct sockaddr_storage);
1204  	struct sockaddr_storage expected_src_addr;
1205  	struct sockaddr_storage requested_addr;
1206  	struct sockaddr_storage expected_addr;
1207  	int clientfd = -1;
1208  	int servfd = -1;
1209  	int err = 0;
1210  
1211  	if (init_addrs(test, &requested_addr, &expected_addr,
1212  		       &expected_src_addr))
1213  		goto err;
1214  
1215  	/* Prepare server to connect to */
1216  	servfd = start_server(test->type, &expected_addr, addr_len);
1217  	if (servfd == -1)
1218  		goto err;
1219  
1220  	clientfd = connect_to_server(test->type, &requested_addr, addr_len);
1221  	if (clientfd == -1)
1222  		goto err;
1223  
1224  	/* Make sure src and dst addrs were overridden properly */
1225  	if (cmp_peer_addr(clientfd, &expected_addr))
1226  		goto err;
1227  
1228  	if (cmp_local_ip(clientfd, &expected_src_addr))
1229  		goto err;
1230  
1231  	if (test->type == SOCK_STREAM) {
1232  		/* Test TCP Fast Open scenario */
1233  		clientfd = fastconnect_to_server(&requested_addr, addr_len);
1234  		if (clientfd == -1)
1235  			goto err;
1236  
1237  		/* Make sure src and dst addrs were overridden properly */
1238  		if (cmp_peer_addr(clientfd, &expected_addr))
1239  			goto err;
1240  
1241  		if (cmp_local_ip(clientfd, &expected_src_addr))
1242  			goto err;
1243  	}
1244  
1245  	goto out;
1246  err:
1247  	err = -1;
1248  out:
1249  	close(clientfd);
1250  	close(servfd);
1251  	return err;
1252  }
1253  
run_xmsg_test_case(const struct sock_addr_test * test,int max_cmsg)1254  static int run_xmsg_test_case(const struct sock_addr_test *test, int max_cmsg)
1255  {
1256  	socklen_t addr_len = sizeof(struct sockaddr_storage);
1257  	struct sockaddr_storage expected_addr;
1258  	struct sockaddr_storage server_addr;
1259  	struct sockaddr_storage sendmsg_addr;
1260  	struct sockaddr_storage recvmsg_addr;
1261  	int clientfd = -1;
1262  	int servfd = -1;
1263  	int set_cmsg;
1264  	int err = 0;
1265  
1266  	if (test->type != SOCK_DGRAM)
1267  		goto err;
1268  
1269  	if (init_addrs(test, &sendmsg_addr, &server_addr, &expected_addr))
1270  		goto err;
1271  
1272  	/* Prepare server to sendmsg to */
1273  	servfd = start_server(test->type, &server_addr, addr_len);
1274  	if (servfd == -1)
1275  		goto err;
1276  
1277  	for (set_cmsg = 0; set_cmsg <= max_cmsg; ++set_cmsg) {
1278  		if (clientfd >= 0)
1279  			close(clientfd);
1280  
1281  		clientfd = sendmsg_to_server(test->type, &sendmsg_addr,
1282  					     addr_len, set_cmsg, /*flags*/0,
1283  					     &err);
1284  		if (err)
1285  			goto out;
1286  		else if (clientfd == -1)
1287  			goto err;
1288  
1289  		/* Try to receive message on server instead of using
1290  		 * getpeername(2) on client socket, to check that client's
1291  		 * destination address was rewritten properly, since
1292  		 * getpeername(2) doesn't work with unconnected datagram
1293  		 * sockets.
1294  		 *
1295  		 * Get source address from recvmsg(2) as well to make sure
1296  		 * source was rewritten properly: getsockname(2) can't be used
1297  		 * since socket is unconnected and source defined for one
1298  		 * specific packet may differ from the one used by default and
1299  		 * returned by getsockname(2).
1300  		 */
1301  		if (recvmsg_from_client(servfd, &recvmsg_addr) == -1)
1302  			goto err;
1303  
1304  		if (cmp_addr(&recvmsg_addr, &expected_addr, /*cmp_port*/0))
1305  			goto err;
1306  	}
1307  
1308  	goto out;
1309  err:
1310  	err = -1;
1311  out:
1312  	close(clientfd);
1313  	close(servfd);
1314  	return err;
1315  }
1316  
run_test_case(int cgfd,const struct sock_addr_test * test)1317  static int run_test_case(int cgfd, const struct sock_addr_test *test)
1318  {
1319  	int progfd = -1;
1320  	int err = 0;
1321  
1322  	printf("Test case: %s .. ", test->descr);
1323  
1324  	progfd = test->loadfn(test);
1325  	if (test->expected_result == LOAD_REJECT && progfd < 0)
1326  		goto out;
1327  	else if (test->expected_result == LOAD_REJECT || progfd < 0)
1328  		goto err;
1329  
1330  	err = bpf_prog_attach(progfd, cgfd, test->attach_type,
1331  			      BPF_F_ALLOW_OVERRIDE);
1332  	if (test->expected_result == ATTACH_REJECT && err) {
1333  		err = 0; /* error was expected, reset it */
1334  		goto out;
1335  	} else if (test->expected_result == ATTACH_REJECT || err) {
1336  		goto err;
1337  	} else if (test->expected_result == ATTACH_OKAY) {
1338  		err = 0;
1339  		goto out;
1340  	}
1341  
1342  	switch (test->attach_type) {
1343  	case BPF_CGROUP_INET4_BIND:
1344  	case BPF_CGROUP_INET6_BIND:
1345  		err = run_bind_test_case(test);
1346  		break;
1347  	case BPF_CGROUP_INET4_CONNECT:
1348  	case BPF_CGROUP_INET6_CONNECT:
1349  		err = run_connect_test_case(test);
1350  		break;
1351  	case BPF_CGROUP_UDP4_SENDMSG:
1352  	case BPF_CGROUP_UDP6_SENDMSG:
1353  		err = run_xmsg_test_case(test, 1);
1354  		break;
1355  	case BPF_CGROUP_UDP4_RECVMSG:
1356  	case BPF_CGROUP_UDP6_RECVMSG:
1357  		err = run_xmsg_test_case(test, 0);
1358  		break;
1359  	default:
1360  		goto err;
1361  	}
1362  
1363  	if (test->expected_result == SYSCALL_EPERM && err == EPERM) {
1364  		err = 0; /* error was expected, reset it */
1365  		goto out;
1366  	}
1367  
1368  	if (test->expected_result == SYSCALL_ENOTSUPP && err == ENOTSUPP) {
1369  		err = 0; /* error was expected, reset it */
1370  		goto out;
1371  	}
1372  
1373  	if (err || test->expected_result != SUCCESS)
1374  		goto err;
1375  
1376  	goto out;
1377  err:
1378  	err = -1;
1379  out:
1380  	/* Detaching w/o checking return code: best effort attempt. */
1381  	if (progfd != -1)
1382  		bpf_prog_detach(cgfd, test->attach_type);
1383  	close(progfd);
1384  	printf("[%s]\n", err ? "FAIL" : "PASS");
1385  	return err;
1386  }
1387  
run_tests(int cgfd)1388  static int run_tests(int cgfd)
1389  {
1390  	int passes = 0;
1391  	int fails = 0;
1392  	int i;
1393  
1394  	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
1395  		if (run_test_case(cgfd, &tests[i]))
1396  			++fails;
1397  		else
1398  			++passes;
1399  	}
1400  	printf("Summary: %d PASSED, %d FAILED\n", passes, fails);
1401  	return fails ? -1 : 0;
1402  }
1403  
main(int argc,char ** argv)1404  int main(int argc, char **argv)
1405  {
1406  	int cgfd = -1;
1407  	int err = 0;
1408  
1409  	if (argc < 2) {
1410  		fprintf(stderr,
1411  			"%s has to be run via %s.sh. Skip direct run.\n",
1412  			argv[0], argv[0]);
1413  		exit(err);
1414  	}
1415  
1416  	cgfd = cgroup_setup_and_join(CG_PATH);
1417  	if (cgfd < 0)
1418  		goto err;
1419  
1420  	/* Use libbpf 1.0 API mode */
1421  	libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
1422  
1423  	if (run_tests(cgfd))
1424  		goto err;
1425  
1426  	goto out;
1427  err:
1428  	err = -1;
1429  out:
1430  	close(cgfd);
1431  	cleanup_cgroup_environment();
1432  	return err;
1433  }
1434