b0068a9d2cfe9ece70ac434daa3e25cafa32beed
[linux-block.git] / tools / testing / selftests / bpf / test_sock_addr.c
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
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
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
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 | BPF_F_TEST_REG_INVARIANTS);
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
697 static int bind4_prog_load(const struct sock_addr_test *test)
698 {
699         return load_path(test, BIND4_PROG_PATH);
700 }
701
702 static int bind6_prog_load(const struct sock_addr_test *test)
703 {
704         return load_path(test, BIND6_PROG_PATH);
705 }
706
707 static int connect4_prog_load(const struct sock_addr_test *test)
708 {
709         return load_path(test, CONNECT4_PROG_PATH);
710 }
711
712 static int connect6_prog_load(const struct sock_addr_test *test)
713 {
714         return load_path(test, CONNECT6_PROG_PATH);
715 }
716
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }