1 // SPDX-License-Identifier: GPL-2.0-only
2 #define _GNU_SOURCE
3
4 #include <errno.h>
5 #include <stdbool.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sched.h>
10
11 #include <arpa/inet.h>
12 #include <sys/mount.h>
13 #include <sys/stat.h>
14 #include <sys/un.h>
15
16 #include <linux/err.h>
17 #include <linux/in.h>
18 #include <linux/in6.h>
19 #include <linux/limits.h>
20
21 #include "bpf_util.h"
22 #include "network_helpers.h"
23 #include "test_progs.h"
24
25 #ifndef IPPROTO_MPTCP
26 #define IPPROTO_MPTCP 262
27 #endif
28
29 #define clean_errno() (errno == 0 ? "None" : strerror(errno))
30 #define log_err(MSG, ...) ({ \
31 int __save = errno; \
32 fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
33 __FILE__, __LINE__, clean_errno(), \
34 ##__VA_ARGS__); \
35 errno = __save; \
36 })
37
38 struct ipv4_packet pkt_v4 = {
39 .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
40 .iph.ihl = 5,
41 .iph.protocol = IPPROTO_TCP,
42 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
43 .tcp.urg_ptr = 123,
44 .tcp.doff = 5,
45 };
46
47 struct ipv6_packet pkt_v6 = {
48 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
49 .iph.nexthdr = IPPROTO_TCP,
50 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
51 .tcp.urg_ptr = 123,
52 .tcp.doff = 5,
53 };
54
55 static const struct network_helper_opts default_opts;
56
settimeo(int fd,int timeout_ms)57 int settimeo(int fd, int timeout_ms)
58 {
59 struct timeval timeout = { .tv_sec = 3 };
60
61 if (timeout_ms > 0) {
62 timeout.tv_sec = timeout_ms / 1000;
63 timeout.tv_usec = (timeout_ms % 1000) * 1000;
64 }
65
66 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout,
67 sizeof(timeout))) {
68 log_err("Failed to set SO_RCVTIMEO");
69 return -1;
70 }
71
72 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout,
73 sizeof(timeout))) {
74 log_err("Failed to set SO_SNDTIMEO");
75 return -1;
76 }
77
78 return 0;
79 }
80
81 #define save_errno_close(fd) ({ int __save = errno; close(fd); errno = __save; })
82
__start_server(int type,const struct sockaddr * addr,socklen_t addrlen,const struct network_helper_opts * opts)83 static int __start_server(int type, const struct sockaddr *addr, socklen_t addrlen,
84 const struct network_helper_opts *opts)
85 {
86 int fd;
87
88 fd = socket(addr->sa_family, type, opts->proto);
89 if (fd < 0) {
90 log_err("Failed to create server socket");
91 return -1;
92 }
93
94 if (settimeo(fd, opts->timeout_ms))
95 goto error_close;
96
97 if (opts->post_socket_cb &&
98 opts->post_socket_cb(fd, opts->cb_opts)) {
99 log_err("Failed to call post_socket_cb");
100 goto error_close;
101 }
102
103 if (bind(fd, addr, addrlen) < 0) {
104 log_err("Failed to bind socket");
105 goto error_close;
106 }
107
108 if (type == SOCK_STREAM) {
109 if (listen(fd, opts->backlog ? MAX(opts->backlog, 0) : 1) < 0) {
110 log_err("Failed to listed on socket");
111 goto error_close;
112 }
113 }
114
115 return fd;
116
117 error_close:
118 save_errno_close(fd);
119 return -1;
120 }
121
start_server_str(int family,int type,const char * addr_str,__u16 port,const struct network_helper_opts * opts)122 int start_server_str(int family, int type, const char *addr_str, __u16 port,
123 const struct network_helper_opts *opts)
124 {
125 struct sockaddr_storage addr;
126 socklen_t addrlen;
127
128 if (!opts)
129 opts = &default_opts;
130
131 if (make_sockaddr(family, addr_str, port, &addr, &addrlen))
132 return -1;
133
134 return __start_server(type, (struct sockaddr *)&addr, addrlen, opts);
135 }
136
start_server(int family,int type,const char * addr_str,__u16 port,int timeout_ms)137 int start_server(int family, int type, const char *addr_str, __u16 port,
138 int timeout_ms)
139 {
140 struct network_helper_opts opts = {
141 .timeout_ms = timeout_ms,
142 };
143
144 return start_server_str(family, type, addr_str, port, &opts);
145 }
146
reuseport_cb(int fd,void * opts)147 static int reuseport_cb(int fd, void *opts)
148 {
149 int on = 1;
150
151 return setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on));
152 }
153
start_reuseport_server(int family,int type,const char * addr_str,__u16 port,int timeout_ms,unsigned int nr_listens)154 int *start_reuseport_server(int family, int type, const char *addr_str,
155 __u16 port, int timeout_ms, unsigned int nr_listens)
156 {
157 struct network_helper_opts opts = {
158 .timeout_ms = timeout_ms,
159 .post_socket_cb = reuseport_cb,
160 };
161 struct sockaddr_storage addr;
162 unsigned int nr_fds = 0;
163 socklen_t addrlen;
164 int *fds;
165
166 if (!nr_listens)
167 return NULL;
168
169 if (make_sockaddr(family, addr_str, port, &addr, &addrlen))
170 return NULL;
171
172 fds = malloc(sizeof(*fds) * nr_listens);
173 if (!fds)
174 return NULL;
175
176 fds[0] = __start_server(type, (struct sockaddr *)&addr, addrlen, &opts);
177 if (fds[0] == -1)
178 goto close_fds;
179 nr_fds = 1;
180
181 if (getsockname(fds[0], (struct sockaddr *)&addr, &addrlen))
182 goto close_fds;
183
184 for (; nr_fds < nr_listens; nr_fds++) {
185 fds[nr_fds] = __start_server(type, (struct sockaddr *)&addr, addrlen, &opts);
186 if (fds[nr_fds] == -1)
187 goto close_fds;
188 }
189
190 return fds;
191
192 close_fds:
193 free_fds(fds, nr_fds);
194 return NULL;
195 }
196
start_server_addr(int type,const struct sockaddr_storage * addr,socklen_t len,const struct network_helper_opts * opts)197 int start_server_addr(int type, const struct sockaddr_storage *addr, socklen_t len,
198 const struct network_helper_opts *opts)
199 {
200 if (!opts)
201 opts = &default_opts;
202
203 return __start_server(type, (struct sockaddr *)addr, len, opts);
204 }
205
free_fds(int * fds,unsigned int nr_close_fds)206 void free_fds(int *fds, unsigned int nr_close_fds)
207 {
208 if (fds) {
209 while (nr_close_fds)
210 close(fds[--nr_close_fds]);
211 free(fds);
212 }
213 }
214
fastopen_connect(int server_fd,const char * data,unsigned int data_len,int timeout_ms)215 int fastopen_connect(int server_fd, const char *data, unsigned int data_len,
216 int timeout_ms)
217 {
218 struct sockaddr_storage addr;
219 socklen_t addrlen = sizeof(addr);
220 struct sockaddr_in *addr_in;
221 int fd, ret;
222
223 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) {
224 log_err("Failed to get server addr");
225 return -1;
226 }
227
228 addr_in = (struct sockaddr_in *)&addr;
229 fd = socket(addr_in->sin_family, SOCK_STREAM, 0);
230 if (fd < 0) {
231 log_err("Failed to create client socket");
232 return -1;
233 }
234
235 if (settimeo(fd, timeout_ms))
236 goto error_close;
237
238 ret = sendto(fd, data, data_len, MSG_FASTOPEN, (struct sockaddr *)&addr,
239 addrlen);
240 if (ret != data_len) {
241 log_err("sendto(data, %u) != %d\n", data_len, ret);
242 goto error_close;
243 }
244
245 return fd;
246
247 error_close:
248 save_errno_close(fd);
249 return -1;
250 }
251
client_socket(int family,int type,const struct network_helper_opts * opts)252 int client_socket(int family, int type,
253 const struct network_helper_opts *opts)
254 {
255 int fd;
256
257 if (!opts)
258 opts = &default_opts;
259
260 fd = socket(family, type, opts->proto);
261 if (fd < 0) {
262 log_err("Failed to create client socket");
263 return -1;
264 }
265
266 if (settimeo(fd, opts->timeout_ms))
267 goto error_close;
268
269 if (opts->post_socket_cb &&
270 opts->post_socket_cb(fd, opts->cb_opts))
271 goto error_close;
272
273 return fd;
274
275 error_close:
276 save_errno_close(fd);
277 return -1;
278 }
279
connect_fd_to_addr(int fd,const struct sockaddr_storage * addr,socklen_t addrlen,const bool must_fail)280 static int connect_fd_to_addr(int fd,
281 const struct sockaddr_storage *addr,
282 socklen_t addrlen, const bool must_fail)
283 {
284 int ret;
285
286 errno = 0;
287 ret = connect(fd, (const struct sockaddr *)addr, addrlen);
288 if (must_fail) {
289 if (!ret) {
290 log_err("Unexpected success to connect to server");
291 return -1;
292 }
293 if (errno != EPERM) {
294 log_err("Unexpected error from connect to server");
295 return -1;
296 }
297 } else {
298 if (ret) {
299 log_err("Failed to connect to server");
300 return -1;
301 }
302 }
303
304 return 0;
305 }
306
connect_to_addr(int type,const struct sockaddr_storage * addr,socklen_t addrlen,const struct network_helper_opts * opts)307 int connect_to_addr(int type, const struct sockaddr_storage *addr, socklen_t addrlen,
308 const struct network_helper_opts *opts)
309 {
310 int fd;
311
312 if (!opts)
313 opts = &default_opts;
314
315 fd = client_socket(addr->ss_family, type, opts);
316 if (fd < 0) {
317 log_err("Failed to create client socket");
318 return -1;
319 }
320
321 if (connect_fd_to_addr(fd, addr, addrlen, opts->must_fail))
322 goto error_close;
323
324 return fd;
325
326 error_close:
327 save_errno_close(fd);
328 return -1;
329 }
330
connect_to_fd_opts(int server_fd,int type,const struct network_helper_opts * opts)331 int connect_to_fd_opts(int server_fd, int type, const struct network_helper_opts *opts)
332 {
333 struct sockaddr_storage addr;
334 socklen_t addrlen;
335
336 if (!opts)
337 opts = &default_opts;
338
339 addrlen = sizeof(addr);
340 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) {
341 log_err("Failed to get server addr");
342 return -1;
343 }
344
345 return connect_to_addr(type, &addr, addrlen, opts);
346 }
347
connect_to_fd(int server_fd,int timeout_ms)348 int connect_to_fd(int server_fd, int timeout_ms)
349 {
350 struct network_helper_opts opts = {
351 .timeout_ms = timeout_ms,
352 };
353 int type, protocol;
354 socklen_t optlen;
355
356 optlen = sizeof(type);
357 if (getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &type, &optlen)) {
358 log_err("getsockopt(SOL_TYPE)");
359 return -1;
360 }
361
362 optlen = sizeof(protocol);
363 if (getsockopt(server_fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen)) {
364 log_err("getsockopt(SOL_PROTOCOL)");
365 return -1;
366 }
367 opts.proto = protocol;
368
369 return connect_to_fd_opts(server_fd, type, &opts);
370 }
371
connect_fd_to_fd(int client_fd,int server_fd,int timeout_ms)372 int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms)
373 {
374 struct sockaddr_storage addr;
375 socklen_t len = sizeof(addr);
376
377 if (settimeo(client_fd, timeout_ms))
378 return -1;
379
380 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) {
381 log_err("Failed to get server addr");
382 return -1;
383 }
384
385 if (connect_fd_to_addr(client_fd, &addr, len, false))
386 return -1;
387
388 return 0;
389 }
390
make_sockaddr(int family,const char * addr_str,__u16 port,struct sockaddr_storage * addr,socklen_t * len)391 int make_sockaddr(int family, const char *addr_str, __u16 port,
392 struct sockaddr_storage *addr, socklen_t *len)
393 {
394 if (family == AF_INET) {
395 struct sockaddr_in *sin = (void *)addr;
396
397 memset(addr, 0, sizeof(*sin));
398 sin->sin_family = AF_INET;
399 sin->sin_port = htons(port);
400 if (addr_str &&
401 inet_pton(AF_INET, addr_str, &sin->sin_addr) != 1) {
402 log_err("inet_pton(AF_INET, %s)", addr_str);
403 return -1;
404 }
405 if (len)
406 *len = sizeof(*sin);
407 return 0;
408 } else if (family == AF_INET6) {
409 struct sockaddr_in6 *sin6 = (void *)addr;
410
411 memset(addr, 0, sizeof(*sin6));
412 sin6->sin6_family = AF_INET6;
413 sin6->sin6_port = htons(port);
414 if (addr_str &&
415 inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) != 1) {
416 log_err("inet_pton(AF_INET6, %s)", addr_str);
417 return -1;
418 }
419 if (len)
420 *len = sizeof(*sin6);
421 return 0;
422 } else if (family == AF_UNIX) {
423 /* Note that we always use abstract unix sockets to avoid having
424 * to clean up leftover files.
425 */
426 struct sockaddr_un *sun = (void *)addr;
427
428 memset(addr, 0, sizeof(*sun));
429 sun->sun_family = family;
430 sun->sun_path[0] = 0;
431 strcpy(sun->sun_path + 1, addr_str);
432 if (len)
433 *len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str);
434 return 0;
435 }
436 return -1;
437 }
438
ping_command(int family)439 char *ping_command(int family)
440 {
441 if (family == AF_INET6) {
442 /* On some systems 'ping' doesn't support IPv6, so use ping6 if it is present. */
443 if (!system("which ping6 >/dev/null 2>&1"))
444 return "ping6";
445 else
446 return "ping -6";
447 }
448 return "ping";
449 }
450
451 struct nstoken {
452 int orig_netns_fd;
453 };
454
open_netns(const char * name)455 struct nstoken *open_netns(const char *name)
456 {
457 int nsfd;
458 char nspath[PATH_MAX];
459 int err;
460 struct nstoken *token;
461
462 token = calloc(1, sizeof(struct nstoken));
463 if (!token) {
464 log_err("Failed to malloc token");
465 return NULL;
466 }
467
468 token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
469 if (token->orig_netns_fd == -1) {
470 log_err("Failed to open(/proc/self/ns/net)");
471 goto fail;
472 }
473
474 snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
475 nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
476 if (nsfd == -1) {
477 log_err("Failed to open(%s)", nspath);
478 goto fail;
479 }
480
481 err = setns(nsfd, CLONE_NEWNET);
482 close(nsfd);
483 if (err) {
484 log_err("Failed to setns(nsfd)");
485 goto fail;
486 }
487
488 return token;
489 fail:
490 if (token->orig_netns_fd != -1)
491 close(token->orig_netns_fd);
492 free(token);
493 return NULL;
494 }
495
close_netns(struct nstoken * token)496 void close_netns(struct nstoken *token)
497 {
498 if (!token)
499 return;
500
501 if (setns(token->orig_netns_fd, CLONE_NEWNET))
502 log_err("Failed to setns(orig_netns_fd)");
503 close(token->orig_netns_fd);
504 free(token);
505 }
506
get_socket_local_port(int sock_fd)507 int get_socket_local_port(int sock_fd)
508 {
509 struct sockaddr_storage addr;
510 socklen_t addrlen = sizeof(addr);
511 int err;
512
513 err = getsockname(sock_fd, (struct sockaddr *)&addr, &addrlen);
514 if (err < 0)
515 return err;
516
517 if (addr.ss_family == AF_INET) {
518 struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
519
520 return sin->sin_port;
521 } else if (addr.ss_family == AF_INET6) {
522 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&addr;
523
524 return sin->sin6_port;
525 }
526
527 return -1;
528 }
529
get_hw_ring_size(char * ifname,struct ethtool_ringparam * ring_param)530 int get_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param)
531 {
532 struct ifreq ifr = {0};
533 int sockfd, err;
534
535 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
536 if (sockfd < 0)
537 return -errno;
538
539 memcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
540
541 ring_param->cmd = ETHTOOL_GRINGPARAM;
542 ifr.ifr_data = (char *)ring_param;
543
544 if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) {
545 err = errno;
546 close(sockfd);
547 return -err;
548 }
549
550 close(sockfd);
551 return 0;
552 }
553
set_hw_ring_size(char * ifname,struct ethtool_ringparam * ring_param)554 int set_hw_ring_size(char *ifname, struct ethtool_ringparam *ring_param)
555 {
556 struct ifreq ifr = {0};
557 int sockfd, err;
558
559 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
560 if (sockfd < 0)
561 return -errno;
562
563 memcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
564
565 ring_param->cmd = ETHTOOL_SRINGPARAM;
566 ifr.ifr_data = (char *)ring_param;
567
568 if (ioctl(sockfd, SIOCETHTOOL, &ifr) < 0) {
569 err = errno;
570 close(sockfd);
571 return -err;
572 }
573
574 close(sockfd);
575 return 0;
576 }
577
578 struct send_recv_arg {
579 int fd;
580 uint32_t bytes;
581 int stop;
582 };
583
send_recv_server(void * arg)584 static void *send_recv_server(void *arg)
585 {
586 struct send_recv_arg *a = (struct send_recv_arg *)arg;
587 ssize_t nr_sent = 0, bytes = 0;
588 char batch[1500];
589 int err = 0, fd;
590
591 fd = accept(a->fd, NULL, NULL);
592 while (fd == -1) {
593 if (errno == EINTR)
594 continue;
595 err = -errno;
596 goto done;
597 }
598
599 if (settimeo(fd, 0)) {
600 err = -errno;
601 goto done;
602 }
603
604 while (bytes < a->bytes && !READ_ONCE(a->stop)) {
605 nr_sent = send(fd, &batch,
606 MIN(a->bytes - bytes, sizeof(batch)), 0);
607 if (nr_sent == -1 && errno == EINTR)
608 continue;
609 if (nr_sent == -1) {
610 err = -errno;
611 break;
612 }
613 bytes += nr_sent;
614 }
615
616 if (bytes != a->bytes) {
617 log_err("send %zd expected %u", bytes, a->bytes);
618 if (!err)
619 err = bytes > a->bytes ? -E2BIG : -EINTR;
620 }
621
622 done:
623 if (fd >= 0)
624 close(fd);
625 if (err) {
626 WRITE_ONCE(a->stop, 1);
627 return ERR_PTR(err);
628 }
629 return NULL;
630 }
631
send_recv_data(int lfd,int fd,uint32_t total_bytes)632 int send_recv_data(int lfd, int fd, uint32_t total_bytes)
633 {
634 ssize_t nr_recv = 0, bytes = 0;
635 struct send_recv_arg arg = {
636 .fd = lfd,
637 .bytes = total_bytes,
638 .stop = 0,
639 };
640 pthread_t srv_thread;
641 void *thread_ret;
642 char batch[1500];
643 int err = 0;
644
645 err = pthread_create(&srv_thread, NULL, send_recv_server, (void *)&arg);
646 if (err) {
647 log_err("Failed to pthread_create");
648 return err;
649 }
650
651 /* recv total_bytes */
652 while (bytes < total_bytes && !READ_ONCE(arg.stop)) {
653 nr_recv = recv(fd, &batch,
654 MIN(total_bytes - bytes, sizeof(batch)), 0);
655 if (nr_recv == -1 && errno == EINTR)
656 continue;
657 if (nr_recv == -1) {
658 err = -errno;
659 break;
660 }
661 bytes += nr_recv;
662 }
663
664 if (bytes != total_bytes) {
665 log_err("recv %zd expected %u", bytes, total_bytes);
666 if (!err)
667 err = bytes > total_bytes ? -E2BIG : -EINTR;
668 }
669
670 WRITE_ONCE(arg.stop, 1);
671 pthread_join(srv_thread, &thread_ret);
672 if (IS_ERR(thread_ret)) {
673 log_err("Failed in thread_ret %ld", PTR_ERR(thread_ret));
674 err = err ? : PTR_ERR(thread_ret);
675 }
676
677 return err;
678 }
679