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