1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <errno.h> 3 #include <stdbool.h> 4 #include <stdio.h> 5 #include <string.h> 6 #include <unistd.h> 7 8 #include <sys/epoll.h> 9 10 #include <linux/err.h> 11 #include <linux/in.h> 12 #include <linux/in6.h> 13 14 #include "bpf_util.h" 15 #include "network_helpers.h" 16 17 #define clean_errno() (errno == 0 ? "None" : strerror(errno)) 18 #define log_err(MSG, ...) fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \ 19 __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) 20 21 struct ipv4_packet pkt_v4 = { 22 .eth.h_proto = __bpf_constant_htons(ETH_P_IP), 23 .iph.ihl = 5, 24 .iph.protocol = IPPROTO_TCP, 25 .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), 26 .tcp.urg_ptr = 123, 27 .tcp.doff = 5, 28 }; 29 30 struct ipv6_packet pkt_v6 = { 31 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6), 32 .iph.nexthdr = IPPROTO_TCP, 33 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES), 34 .tcp.urg_ptr = 123, 35 .tcp.doff = 5, 36 }; 37 38 int start_server(int family, int type) 39 { 40 struct sockaddr_storage addr = {}; 41 socklen_t len; 42 int fd; 43 44 if (family == AF_INET) { 45 struct sockaddr_in *sin = (void *)&addr; 46 47 sin->sin_family = AF_INET; 48 len = sizeof(*sin); 49 } else { 50 struct sockaddr_in6 *sin6 = (void *)&addr; 51 52 sin6->sin6_family = AF_INET6; 53 len = sizeof(*sin6); 54 } 55 56 fd = socket(family, type | SOCK_NONBLOCK, 0); 57 if (fd < 0) { 58 log_err("Failed to create server socket"); 59 return -1; 60 } 61 62 if (bind(fd, (const struct sockaddr *)&addr, len) < 0) { 63 log_err("Failed to bind socket"); 64 close(fd); 65 return -1; 66 } 67 68 if (type == SOCK_STREAM) { 69 if (listen(fd, 1) < 0) { 70 log_err("Failed to listed on socket"); 71 close(fd); 72 return -1; 73 } 74 } 75 76 return fd; 77 } 78 79 static const struct timeval timeo_sec = { .tv_sec = 3 }; 80 static const size_t timeo_optlen = sizeof(timeo_sec); 81 82 int connect_to_fd(int family, int type, int server_fd) 83 { 84 int fd, save_errno; 85 86 fd = socket(family, type, 0); 87 if (fd < 0) { 88 log_err("Failed to create client socket"); 89 return -1; 90 } 91 92 if (connect_fd_to_fd(fd, server_fd) < 0 && errno != EINPROGRESS) { 93 save_errno = errno; 94 close(fd); 95 errno = save_errno; 96 return -1; 97 } 98 99 return fd; 100 } 101 102 int connect_fd_to_fd(int client_fd, int server_fd) 103 { 104 struct sockaddr_storage addr; 105 socklen_t len = sizeof(addr); 106 int save_errno; 107 108 if (setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeo_sec, 109 timeo_optlen)) { 110 log_err("Failed to set SO_RCVTIMEO"); 111 return -1; 112 } 113 114 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) { 115 log_err("Failed to get server addr"); 116 return -1; 117 } 118 119 if (connect(client_fd, (const struct sockaddr *)&addr, len) < 0) { 120 if (errno != EINPROGRESS) { 121 save_errno = errno; 122 log_err("Failed to connect to server"); 123 errno = save_errno; 124 } 125 return -1; 126 } 127 128 return 0; 129 } 130 131 int connect_wait(int fd) 132 { 133 struct epoll_event ev = {}, events[2]; 134 int timeout_ms = 1000; 135 int efd, nfd; 136 137 efd = epoll_create1(EPOLL_CLOEXEC); 138 if (efd < 0) { 139 log_err("Failed to open epoll fd"); 140 return -1; 141 } 142 143 ev.events = EPOLLRDHUP | EPOLLOUT; 144 ev.data.fd = fd; 145 146 if (epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev) < 0) { 147 log_err("Failed to register fd=%d on epoll fd=%d", fd, efd); 148 close(efd); 149 return -1; 150 } 151 152 nfd = epoll_wait(efd, events, ARRAY_SIZE(events), timeout_ms); 153 if (nfd < 0) 154 log_err("Failed to wait for I/O event on epoll fd=%d", efd); 155 156 close(efd); 157 return nfd; 158 } 159