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 int settimeo(int fd, int timeout_ms) 56 { 57 struct timeval timeout = { .tv_sec = 3 }; 58 59 if (timeout_ms > 0) { 60 timeout.tv_sec = timeout_ms / 1000; 61 timeout.tv_usec = (timeout_ms % 1000) * 1000; 62 } 63 64 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, 65 sizeof(timeout))) { 66 log_err("Failed to set SO_RCVTIMEO"); 67 return -1; 68 } 69 70 if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, 71 sizeof(timeout))) { 72 log_err("Failed to set SO_SNDTIMEO"); 73 return -1; 74 } 75 76 return 0; 77 } 78 79 #define save_errno_close(fd) ({ int __save = errno; close(fd); errno = __save; }) 80 81 static int __start_server(int type, int protocol, const struct sockaddr *addr, 82 socklen_t addrlen, int timeout_ms, bool reuseport) 83 { 84 int on = 1; 85 int fd; 86 87 fd = socket(addr->sa_family, type, protocol); 88 if (fd < 0) { 89 log_err("Failed to create server socket"); 90 return -1; 91 } 92 93 if (settimeo(fd, timeout_ms)) 94 goto error_close; 95 96 if (reuseport && 97 setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) { 98 log_err("Failed to set SO_REUSEPORT"); 99 goto error_close; 100 } 101 102 if (bind(fd, addr, addrlen) < 0) { 103 log_err("Failed to bind socket"); 104 goto error_close; 105 } 106 107 if (type == SOCK_STREAM) { 108 if (listen(fd, 1) < 0) { 109 log_err("Failed to listed on socket"); 110 goto error_close; 111 } 112 } 113 114 return fd; 115 116 error_close: 117 save_errno_close(fd); 118 return -1; 119 } 120 121 static int start_server_proto(int family, int type, int protocol, 122 const char *addr_str, __u16 port, int timeout_ms) 123 { 124 struct sockaddr_storage addr; 125 socklen_t addrlen; 126 127 if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) 128 return -1; 129 130 return __start_server(type, protocol, (struct sockaddr *)&addr, 131 addrlen, timeout_ms, false); 132 } 133 134 int start_server(int family, int type, const char *addr_str, __u16 port, 135 int timeout_ms) 136 { 137 return start_server_proto(family, type, 0, addr_str, port, timeout_ms); 138 } 139 140 int start_mptcp_server(int family, const char *addr_str, __u16 port, 141 int timeout_ms) 142 { 143 return start_server_proto(family, SOCK_STREAM, IPPROTO_MPTCP, addr_str, 144 port, timeout_ms); 145 } 146 147 int *start_reuseport_server(int family, int type, const char *addr_str, 148 __u16 port, int timeout_ms, unsigned int nr_listens) 149 { 150 struct sockaddr_storage addr; 151 unsigned int nr_fds = 0; 152 socklen_t addrlen; 153 int *fds; 154 155 if (!nr_listens) 156 return NULL; 157 158 if (make_sockaddr(family, addr_str, port, &addr, &addrlen)) 159 return NULL; 160 161 fds = malloc(sizeof(*fds) * nr_listens); 162 if (!fds) 163 return NULL; 164 165 fds[0] = __start_server(type, 0, (struct sockaddr *)&addr, addrlen, 166 timeout_ms, true); 167 if (fds[0] == -1) 168 goto close_fds; 169 nr_fds = 1; 170 171 if (getsockname(fds[0], (struct sockaddr *)&addr, &addrlen)) 172 goto close_fds; 173 174 for (; nr_fds < nr_listens; nr_fds++) { 175 fds[nr_fds] = __start_server(type, 0, (struct sockaddr *)&addr, 176 addrlen, timeout_ms, true); 177 if (fds[nr_fds] == -1) 178 goto close_fds; 179 } 180 181 return fds; 182 183 close_fds: 184 free_fds(fds, nr_fds); 185 return NULL; 186 } 187 188 void free_fds(int *fds, unsigned int nr_close_fds) 189 { 190 if (fds) { 191 while (nr_close_fds) 192 close(fds[--nr_close_fds]); 193 free(fds); 194 } 195 } 196 197 int fastopen_connect(int server_fd, const char *data, unsigned int data_len, 198 int timeout_ms) 199 { 200 struct sockaddr_storage addr; 201 socklen_t addrlen = sizeof(addr); 202 struct sockaddr_in *addr_in; 203 int fd, ret; 204 205 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) { 206 log_err("Failed to get server addr"); 207 return -1; 208 } 209 210 addr_in = (struct sockaddr_in *)&addr; 211 fd = socket(addr_in->sin_family, SOCK_STREAM, 0); 212 if (fd < 0) { 213 log_err("Failed to create client socket"); 214 return -1; 215 } 216 217 if (settimeo(fd, timeout_ms)) 218 goto error_close; 219 220 ret = sendto(fd, data, data_len, MSG_FASTOPEN, (struct sockaddr *)&addr, 221 addrlen); 222 if (ret != data_len) { 223 log_err("sendto(data, %u) != %d\n", data_len, ret); 224 goto error_close; 225 } 226 227 return fd; 228 229 error_close: 230 save_errno_close(fd); 231 return -1; 232 } 233 234 static int connect_fd_to_addr(int fd, 235 const struct sockaddr_storage *addr, 236 socklen_t addrlen, const bool must_fail) 237 { 238 int ret; 239 240 errno = 0; 241 ret = connect(fd, (const struct sockaddr *)addr, addrlen); 242 if (must_fail) { 243 if (!ret) { 244 log_err("Unexpected success to connect to server"); 245 return -1; 246 } 247 if (errno != EPERM) { 248 log_err("Unexpected error from connect to server"); 249 return -1; 250 } 251 } else { 252 if (ret) { 253 log_err("Failed to connect to server"); 254 return -1; 255 } 256 } 257 258 return 0; 259 } 260 261 int connect_to_addr(const struct sockaddr_storage *addr, socklen_t addrlen, int type) 262 { 263 int fd; 264 265 fd = socket(addr->ss_family, type, 0); 266 if (fd < 0) { 267 log_err("Failed to create client socket"); 268 return -1; 269 } 270 271 if (connect_fd_to_addr(fd, addr, addrlen, false)) 272 goto error_close; 273 274 return fd; 275 276 error_close: 277 save_errno_close(fd); 278 return -1; 279 } 280 281 static const struct network_helper_opts default_opts; 282 283 int connect_to_fd_opts(int server_fd, const struct network_helper_opts *opts) 284 { 285 struct sockaddr_storage addr; 286 struct sockaddr_in *addr_in; 287 socklen_t addrlen, optlen; 288 int fd, type, protocol; 289 290 if (!opts) 291 opts = &default_opts; 292 293 optlen = sizeof(type); 294 295 if (opts->type) { 296 type = opts->type; 297 } else { 298 if (getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &type, &optlen)) { 299 log_err("getsockopt(SOL_TYPE)"); 300 return -1; 301 } 302 } 303 304 if (opts->proto) { 305 protocol = opts->proto; 306 } else { 307 if (getsockopt(server_fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen)) { 308 log_err("getsockopt(SOL_PROTOCOL)"); 309 return -1; 310 } 311 } 312 313 addrlen = sizeof(addr); 314 if (getsockname(server_fd, (struct sockaddr *)&addr, &addrlen)) { 315 log_err("Failed to get server addr"); 316 return -1; 317 } 318 319 addr_in = (struct sockaddr_in *)&addr; 320 fd = socket(addr_in->sin_family, type, protocol); 321 if (fd < 0) { 322 log_err("Failed to create client socket"); 323 return -1; 324 } 325 326 if (settimeo(fd, opts->timeout_ms)) 327 goto error_close; 328 329 if (opts->cc && opts->cc[0] && 330 setsockopt(fd, SOL_TCP, TCP_CONGESTION, opts->cc, 331 strlen(opts->cc) + 1)) 332 goto error_close; 333 334 if (!opts->noconnect) 335 if (connect_fd_to_addr(fd, &addr, addrlen, opts->must_fail)) 336 goto error_close; 337 338 return fd; 339 340 error_close: 341 save_errno_close(fd); 342 return -1; 343 } 344 345 int connect_to_fd(int server_fd, int timeout_ms) 346 { 347 struct network_helper_opts opts = { 348 .timeout_ms = timeout_ms, 349 }; 350 351 return connect_to_fd_opts(server_fd, &opts); 352 } 353 354 int connect_fd_to_fd(int client_fd, int server_fd, int timeout_ms) 355 { 356 struct sockaddr_storage addr; 357 socklen_t len = sizeof(addr); 358 359 if (settimeo(client_fd, timeout_ms)) 360 return -1; 361 362 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { 363 log_err("Failed to get server addr"); 364 return -1; 365 } 366 367 if (connect_fd_to_addr(client_fd, &addr, len, false)) 368 return -1; 369 370 return 0; 371 } 372 373 int make_sockaddr(int family, const char *addr_str, __u16 port, 374 struct sockaddr_storage *addr, socklen_t *len) 375 { 376 if (family == AF_INET) { 377 struct sockaddr_in *sin = (void *)addr; 378 379 memset(addr, 0, sizeof(*sin)); 380 sin->sin_family = AF_INET; 381 sin->sin_port = htons(port); 382 if (addr_str && 383 inet_pton(AF_INET, addr_str, &sin->sin_addr) != 1) { 384 log_err("inet_pton(AF_INET, %s)", addr_str); 385 return -1; 386 } 387 if (len) 388 *len = sizeof(*sin); 389 return 0; 390 } else if (family == AF_INET6) { 391 struct sockaddr_in6 *sin6 = (void *)addr; 392 393 memset(addr, 0, sizeof(*sin6)); 394 sin6->sin6_family = AF_INET6; 395 sin6->sin6_port = htons(port); 396 if (addr_str && 397 inet_pton(AF_INET6, addr_str, &sin6->sin6_addr) != 1) { 398 log_err("inet_pton(AF_INET6, %s)", addr_str); 399 return -1; 400 } 401 if (len) 402 *len = sizeof(*sin6); 403 return 0; 404 } else if (family == AF_UNIX) { 405 /* Note that we always use abstract unix sockets to avoid having 406 * to clean up leftover files. 407 */ 408 struct sockaddr_un *sun = (void *)addr; 409 410 memset(addr, 0, sizeof(*sun)); 411 sun->sun_family = family; 412 sun->sun_path[0] = 0; 413 strcpy(sun->sun_path + 1, addr_str); 414 if (len) 415 *len = offsetof(struct sockaddr_un, sun_path) + 1 + strlen(addr_str); 416 return 0; 417 } 418 return -1; 419 } 420 421 char *ping_command(int family) 422 { 423 if (family == AF_INET6) { 424 /* On some systems 'ping' doesn't support IPv6, so use ping6 if it is present. */ 425 if (!system("which ping6 >/dev/null 2>&1")) 426 return "ping6"; 427 else 428 return "ping -6"; 429 } 430 return "ping"; 431 } 432 433 struct nstoken { 434 int orig_netns_fd; 435 }; 436 437 struct nstoken *open_netns(const char *name) 438 { 439 int nsfd; 440 char nspath[PATH_MAX]; 441 int err; 442 struct nstoken *token; 443 444 token = calloc(1, sizeof(struct nstoken)); 445 if (!ASSERT_OK_PTR(token, "malloc token")) 446 return NULL; 447 448 token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY); 449 if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net")) 450 goto fail; 451 452 snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name); 453 nsfd = open(nspath, O_RDONLY | O_CLOEXEC); 454 if (!ASSERT_GE(nsfd, 0, "open netns fd")) 455 goto fail; 456 457 err = setns(nsfd, CLONE_NEWNET); 458 close(nsfd); 459 if (!ASSERT_OK(err, "setns")) 460 goto fail; 461 462 return token; 463 fail: 464 free(token); 465 return NULL; 466 } 467 468 void close_netns(struct nstoken *token) 469 { 470 if (!token) 471 return; 472 473 ASSERT_OK(setns(token->orig_netns_fd, CLONE_NEWNET), "setns"); 474 close(token->orig_netns_fd); 475 free(token); 476 } 477 478 int get_socket_local_port(int sock_fd) 479 { 480 struct sockaddr_storage addr; 481 socklen_t addrlen = sizeof(addr); 482 int err; 483 484 err = getsockname(sock_fd, (struct sockaddr *)&addr, &addrlen); 485 if (err < 0) 486 return err; 487 488 if (addr.ss_family == AF_INET) { 489 struct sockaddr_in *sin = (struct sockaddr_in *)&addr; 490 491 return sin->sin_port; 492 } else if (addr.ss_family == AF_INET6) { 493 struct sockaddr_in6 *sin = (struct sockaddr_in6 *)&addr; 494 495 return sin->sin6_port; 496 } 497 498 return -1; 499 } 500