14e02588dSJohn Fastabend #ifndef __SOCKMAP_HELPERS__
24e02588dSJohn Fastabend #define __SOCKMAP_HELPERS__
34e02588dSJohn Fastabend
44e02588dSJohn Fastabend #include <linux/vm_sockets.h>
54e02588dSJohn Fastabend
64e02588dSJohn Fastabend #define IO_TIMEOUT_SEC 30
74e02588dSJohn Fastabend #define MAX_STRERR_LEN 256
84e02588dSJohn Fastabend #define MAX_TEST_NAME 80
94e02588dSJohn Fastabend
104e02588dSJohn Fastabend /* workaround for older vm_sockets.h */
114e02588dSJohn Fastabend #ifndef VMADDR_CID_LOCAL
124e02588dSJohn Fastabend #define VMADDR_CID_LOCAL 1
134e02588dSJohn Fastabend #endif
144e02588dSJohn Fastabend
154e02588dSJohn Fastabend #define __always_unused __attribute__((__unused__))
164e02588dSJohn Fastabend
174e02588dSJohn Fastabend #define _FAIL(errnum, fmt...) \
184e02588dSJohn Fastabend ({ \
194e02588dSJohn Fastabend error_at_line(0, (errnum), __func__, __LINE__, fmt); \
204e02588dSJohn Fastabend CHECK_FAIL(true); \
214e02588dSJohn Fastabend })
224e02588dSJohn Fastabend #define FAIL(fmt...) _FAIL(0, fmt)
234e02588dSJohn Fastabend #define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
244e02588dSJohn Fastabend #define FAIL_LIBBPF(err, msg) \
254e02588dSJohn Fastabend ({ \
264e02588dSJohn Fastabend char __buf[MAX_STRERR_LEN]; \
274e02588dSJohn Fastabend libbpf_strerror((err), __buf, sizeof(__buf)); \
284e02588dSJohn Fastabend FAIL("%s: %s", (msg), __buf); \
294e02588dSJohn Fastabend })
304e02588dSJohn Fastabend
314e02588dSJohn Fastabend /* Wrappers that fail the test on error and report it. */
324e02588dSJohn Fastabend
334e02588dSJohn Fastabend #define xaccept_nonblock(fd, addr, len) \
344e02588dSJohn Fastabend ({ \
354e02588dSJohn Fastabend int __ret = \
364e02588dSJohn Fastabend accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \
374e02588dSJohn Fastabend if (__ret == -1) \
384e02588dSJohn Fastabend FAIL_ERRNO("accept"); \
394e02588dSJohn Fastabend __ret; \
404e02588dSJohn Fastabend })
414e02588dSJohn Fastabend
424e02588dSJohn Fastabend #define xbind(fd, addr, len) \
434e02588dSJohn Fastabend ({ \
444e02588dSJohn Fastabend int __ret = bind((fd), (addr), (len)); \
454e02588dSJohn Fastabend if (__ret == -1) \
464e02588dSJohn Fastabend FAIL_ERRNO("bind"); \
474e02588dSJohn Fastabend __ret; \
484e02588dSJohn Fastabend })
494e02588dSJohn Fastabend
504e02588dSJohn Fastabend #define xclose(fd) \
514e02588dSJohn Fastabend ({ \
524e02588dSJohn Fastabend int __ret = close((fd)); \
534e02588dSJohn Fastabend if (__ret == -1) \
544e02588dSJohn Fastabend FAIL_ERRNO("close"); \
554e02588dSJohn Fastabend __ret; \
564e02588dSJohn Fastabend })
574e02588dSJohn Fastabend
584e02588dSJohn Fastabend #define xconnect(fd, addr, len) \
594e02588dSJohn Fastabend ({ \
604e02588dSJohn Fastabend int __ret = connect((fd), (addr), (len)); \
614e02588dSJohn Fastabend if (__ret == -1) \
624e02588dSJohn Fastabend FAIL_ERRNO("connect"); \
634e02588dSJohn Fastabend __ret; \
644e02588dSJohn Fastabend })
654e02588dSJohn Fastabend
664e02588dSJohn Fastabend #define xgetsockname(fd, addr, len) \
674e02588dSJohn Fastabend ({ \
684e02588dSJohn Fastabend int __ret = getsockname((fd), (addr), (len)); \
694e02588dSJohn Fastabend if (__ret == -1) \
704e02588dSJohn Fastabend FAIL_ERRNO("getsockname"); \
714e02588dSJohn Fastabend __ret; \
724e02588dSJohn Fastabend })
734e02588dSJohn Fastabend
744e02588dSJohn Fastabend #define xgetsockopt(fd, level, name, val, len) \
754e02588dSJohn Fastabend ({ \
764e02588dSJohn Fastabend int __ret = getsockopt((fd), (level), (name), (val), (len)); \
774e02588dSJohn Fastabend if (__ret == -1) \
784e02588dSJohn Fastabend FAIL_ERRNO("getsockopt(" #name ")"); \
794e02588dSJohn Fastabend __ret; \
804e02588dSJohn Fastabend })
814e02588dSJohn Fastabend
824e02588dSJohn Fastabend #define xlisten(fd, backlog) \
834e02588dSJohn Fastabend ({ \
844e02588dSJohn Fastabend int __ret = listen((fd), (backlog)); \
854e02588dSJohn Fastabend if (__ret == -1) \
864e02588dSJohn Fastabend FAIL_ERRNO("listen"); \
874e02588dSJohn Fastabend __ret; \
884e02588dSJohn Fastabend })
894e02588dSJohn Fastabend
904e02588dSJohn Fastabend #define xsetsockopt(fd, level, name, val, len) \
914e02588dSJohn Fastabend ({ \
924e02588dSJohn Fastabend int __ret = setsockopt((fd), (level), (name), (val), (len)); \
934e02588dSJohn Fastabend if (__ret == -1) \
944e02588dSJohn Fastabend FAIL_ERRNO("setsockopt(" #name ")"); \
954e02588dSJohn Fastabend __ret; \
964e02588dSJohn Fastabend })
974e02588dSJohn Fastabend
984e02588dSJohn Fastabend #define xsend(fd, buf, len, flags) \
994e02588dSJohn Fastabend ({ \
1004e02588dSJohn Fastabend ssize_t __ret = send((fd), (buf), (len), (flags)); \
1014e02588dSJohn Fastabend if (__ret == -1) \
1024e02588dSJohn Fastabend FAIL_ERRNO("send"); \
1034e02588dSJohn Fastabend __ret; \
1044e02588dSJohn Fastabend })
1054e02588dSJohn Fastabend
1064e02588dSJohn Fastabend #define xrecv_nonblock(fd, buf, len, flags) \
1074e02588dSJohn Fastabend ({ \
1084e02588dSJohn Fastabend ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \
1094e02588dSJohn Fastabend IO_TIMEOUT_SEC); \
1104e02588dSJohn Fastabend if (__ret == -1) \
1114e02588dSJohn Fastabend FAIL_ERRNO("recv"); \
1124e02588dSJohn Fastabend __ret; \
1134e02588dSJohn Fastabend })
1144e02588dSJohn Fastabend
1154e02588dSJohn Fastabend #define xsocket(family, sotype, flags) \
1164e02588dSJohn Fastabend ({ \
1174e02588dSJohn Fastabend int __ret = socket(family, sotype, flags); \
1184e02588dSJohn Fastabend if (__ret == -1) \
1194e02588dSJohn Fastabend FAIL_ERRNO("socket"); \
1204e02588dSJohn Fastabend __ret; \
1214e02588dSJohn Fastabend })
1224e02588dSJohn Fastabend
1234e02588dSJohn Fastabend #define xbpf_map_delete_elem(fd, key) \
1244e02588dSJohn Fastabend ({ \
1254e02588dSJohn Fastabend int __ret = bpf_map_delete_elem((fd), (key)); \
1264e02588dSJohn Fastabend if (__ret < 0) \
1274e02588dSJohn Fastabend FAIL_ERRNO("map_delete"); \
1284e02588dSJohn Fastabend __ret; \
1294e02588dSJohn Fastabend })
1304e02588dSJohn Fastabend
1314e02588dSJohn Fastabend #define xbpf_map_lookup_elem(fd, key, val) \
1324e02588dSJohn Fastabend ({ \
1334e02588dSJohn Fastabend int __ret = bpf_map_lookup_elem((fd), (key), (val)); \
1344e02588dSJohn Fastabend if (__ret < 0) \
1354e02588dSJohn Fastabend FAIL_ERRNO("map_lookup"); \
1364e02588dSJohn Fastabend __ret; \
1374e02588dSJohn Fastabend })
1384e02588dSJohn Fastabend
1394e02588dSJohn Fastabend #define xbpf_map_update_elem(fd, key, val, flags) \
1404e02588dSJohn Fastabend ({ \
1414e02588dSJohn Fastabend int __ret = bpf_map_update_elem((fd), (key), (val), (flags)); \
1424e02588dSJohn Fastabend if (__ret < 0) \
1434e02588dSJohn Fastabend FAIL_ERRNO("map_update"); \
1444e02588dSJohn Fastabend __ret; \
1454e02588dSJohn Fastabend })
1464e02588dSJohn Fastabend
1474e02588dSJohn Fastabend #define xbpf_prog_attach(prog, target, type, flags) \
1484e02588dSJohn Fastabend ({ \
1494e02588dSJohn Fastabend int __ret = \
1504e02588dSJohn Fastabend bpf_prog_attach((prog), (target), (type), (flags)); \
1514e02588dSJohn Fastabend if (__ret < 0) \
1524e02588dSJohn Fastabend FAIL_ERRNO("prog_attach(" #type ")"); \
1534e02588dSJohn Fastabend __ret; \
1544e02588dSJohn Fastabend })
1554e02588dSJohn Fastabend
1564e02588dSJohn Fastabend #define xbpf_prog_detach2(prog, target, type) \
1574e02588dSJohn Fastabend ({ \
1584e02588dSJohn Fastabend int __ret = bpf_prog_detach2((prog), (target), (type)); \
1594e02588dSJohn Fastabend if (__ret < 0) \
1604e02588dSJohn Fastabend FAIL_ERRNO("prog_detach2(" #type ")"); \
1614e02588dSJohn Fastabend __ret; \
1624e02588dSJohn Fastabend })
1634e02588dSJohn Fastabend
1644e02588dSJohn Fastabend #define xpthread_create(thread, attr, func, arg) \
1654e02588dSJohn Fastabend ({ \
1664e02588dSJohn Fastabend int __ret = pthread_create((thread), (attr), (func), (arg)); \
1674e02588dSJohn Fastabend errno = __ret; \
1684e02588dSJohn Fastabend if (__ret) \
1694e02588dSJohn Fastabend FAIL_ERRNO("pthread_create"); \
1704e02588dSJohn Fastabend __ret; \
1714e02588dSJohn Fastabend })
1724e02588dSJohn Fastabend
1734e02588dSJohn Fastabend #define xpthread_join(thread, retval) \
1744e02588dSJohn Fastabend ({ \
1754e02588dSJohn Fastabend int __ret = pthread_join((thread), (retval)); \
1764e02588dSJohn Fastabend errno = __ret; \
1774e02588dSJohn Fastabend if (__ret) \
1784e02588dSJohn Fastabend FAIL_ERRNO("pthread_join"); \
1794e02588dSJohn Fastabend __ret; \
1804e02588dSJohn Fastabend })
1814e02588dSJohn Fastabend
poll_connect(int fd,unsigned int timeout_sec)182*c1970e26SXu Kuohai static inline int poll_connect(int fd, unsigned int timeout_sec)
183*c1970e26SXu Kuohai {
184*c1970e26SXu Kuohai struct timeval timeout = { .tv_sec = timeout_sec };
185*c1970e26SXu Kuohai fd_set wfds;
186*c1970e26SXu Kuohai int r, eval;
187*c1970e26SXu Kuohai socklen_t esize = sizeof(eval);
188*c1970e26SXu Kuohai
189*c1970e26SXu Kuohai FD_ZERO(&wfds);
190*c1970e26SXu Kuohai FD_SET(fd, &wfds);
191*c1970e26SXu Kuohai
192*c1970e26SXu Kuohai r = select(fd + 1, NULL, &wfds, NULL, &timeout);
193*c1970e26SXu Kuohai if (r == 0)
194*c1970e26SXu Kuohai errno = ETIME;
195*c1970e26SXu Kuohai if (r != 1)
196*c1970e26SXu Kuohai return -1;
197*c1970e26SXu Kuohai
198*c1970e26SXu Kuohai if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
199*c1970e26SXu Kuohai return -1;
200*c1970e26SXu Kuohai if (eval != 0) {
201*c1970e26SXu Kuohai errno = eval;
202*c1970e26SXu Kuohai return -1;
203*c1970e26SXu Kuohai }
204*c1970e26SXu Kuohai
205*c1970e26SXu Kuohai return 0;
206*c1970e26SXu Kuohai }
207*c1970e26SXu Kuohai
poll_read(int fd,unsigned int timeout_sec)2084e02588dSJohn Fastabend static inline int poll_read(int fd, unsigned int timeout_sec)
2094e02588dSJohn Fastabend {
2104e02588dSJohn Fastabend struct timeval timeout = { .tv_sec = timeout_sec };
2114e02588dSJohn Fastabend fd_set rfds;
2124e02588dSJohn Fastabend int r;
2134e02588dSJohn Fastabend
2144e02588dSJohn Fastabend FD_ZERO(&rfds);
2154e02588dSJohn Fastabend FD_SET(fd, &rfds);
2164e02588dSJohn Fastabend
2174e02588dSJohn Fastabend r = select(fd + 1, &rfds, NULL, NULL, &timeout);
2184e02588dSJohn Fastabend if (r == 0)
2194e02588dSJohn Fastabend errno = ETIME;
2204e02588dSJohn Fastabend
2214e02588dSJohn Fastabend return r == 1 ? 0 : -1;
2224e02588dSJohn Fastabend }
2234e02588dSJohn Fastabend
accept_timeout(int fd,struct sockaddr * addr,socklen_t * len,unsigned int timeout_sec)2244e02588dSJohn Fastabend static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
2254e02588dSJohn Fastabend unsigned int timeout_sec)
2264e02588dSJohn Fastabend {
2274e02588dSJohn Fastabend if (poll_read(fd, timeout_sec))
2284e02588dSJohn Fastabend return -1;
2294e02588dSJohn Fastabend
2304e02588dSJohn Fastabend return accept(fd, addr, len);
2314e02588dSJohn Fastabend }
2324e02588dSJohn Fastabend
recv_timeout(int fd,void * buf,size_t len,int flags,unsigned int timeout_sec)2334e02588dSJohn Fastabend static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
2344e02588dSJohn Fastabend unsigned int timeout_sec)
2354e02588dSJohn Fastabend {
2364e02588dSJohn Fastabend if (poll_read(fd, timeout_sec))
2374e02588dSJohn Fastabend return -1;
2384e02588dSJohn Fastabend
2394e02588dSJohn Fastabend return recv(fd, buf, len, flags);
2404e02588dSJohn Fastabend }
2414e02588dSJohn Fastabend
init_addr_loopback4(struct sockaddr_storage * ss,socklen_t * len)2424e02588dSJohn Fastabend static inline void init_addr_loopback4(struct sockaddr_storage *ss,
2434e02588dSJohn Fastabend socklen_t *len)
2444e02588dSJohn Fastabend {
2454e02588dSJohn Fastabend struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
2464e02588dSJohn Fastabend
2474e02588dSJohn Fastabend addr4->sin_family = AF_INET;
2484e02588dSJohn Fastabend addr4->sin_port = 0;
2494e02588dSJohn Fastabend addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2504e02588dSJohn Fastabend *len = sizeof(*addr4);
2514e02588dSJohn Fastabend }
2524e02588dSJohn Fastabend
init_addr_loopback6(struct sockaddr_storage * ss,socklen_t * len)2534e02588dSJohn Fastabend static inline void init_addr_loopback6(struct sockaddr_storage *ss,
2544e02588dSJohn Fastabend socklen_t *len)
2554e02588dSJohn Fastabend {
2564e02588dSJohn Fastabend struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
2574e02588dSJohn Fastabend
2584e02588dSJohn Fastabend addr6->sin6_family = AF_INET6;
2594e02588dSJohn Fastabend addr6->sin6_port = 0;
2604e02588dSJohn Fastabend addr6->sin6_addr = in6addr_loopback;
2614e02588dSJohn Fastabend *len = sizeof(*addr6);
2624e02588dSJohn Fastabend }
2634e02588dSJohn Fastabend
init_addr_loopback_vsock(struct sockaddr_storage * ss,socklen_t * len)2644e02588dSJohn Fastabend static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
2654e02588dSJohn Fastabend socklen_t *len)
2664e02588dSJohn Fastabend {
2674e02588dSJohn Fastabend struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
2684e02588dSJohn Fastabend
2694e02588dSJohn Fastabend addr->svm_family = AF_VSOCK;
2704e02588dSJohn Fastabend addr->svm_port = VMADDR_PORT_ANY;
2714e02588dSJohn Fastabend addr->svm_cid = VMADDR_CID_LOCAL;
2724e02588dSJohn Fastabend *len = sizeof(*addr);
2734e02588dSJohn Fastabend }
2744e02588dSJohn Fastabend
init_addr_loopback(int family,struct sockaddr_storage * ss,socklen_t * len)2754e02588dSJohn Fastabend static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
2764e02588dSJohn Fastabend socklen_t *len)
2774e02588dSJohn Fastabend {
2784e02588dSJohn Fastabend switch (family) {
2794e02588dSJohn Fastabend case AF_INET:
2804e02588dSJohn Fastabend init_addr_loopback4(ss, len);
2814e02588dSJohn Fastabend return;
2824e02588dSJohn Fastabend case AF_INET6:
2834e02588dSJohn Fastabend init_addr_loopback6(ss, len);
2844e02588dSJohn Fastabend return;
2854e02588dSJohn Fastabend case AF_VSOCK:
2864e02588dSJohn Fastabend init_addr_loopback_vsock(ss, len);
2874e02588dSJohn Fastabend return;
2884e02588dSJohn Fastabend default:
2894e02588dSJohn Fastabend FAIL("unsupported address family %d", family);
2904e02588dSJohn Fastabend }
2914e02588dSJohn Fastabend }
2924e02588dSJohn Fastabend
sockaddr(struct sockaddr_storage * ss)2934e02588dSJohn Fastabend static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
2944e02588dSJohn Fastabend {
2954e02588dSJohn Fastabend return (struct sockaddr *)ss;
2964e02588dSJohn Fastabend }
2974e02588dSJohn Fastabend
add_to_sockmap(int sock_mapfd,int fd1,int fd2)298298970c8SJohn Fastabend static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
299298970c8SJohn Fastabend {
300298970c8SJohn Fastabend u64 value;
301298970c8SJohn Fastabend u32 key;
302298970c8SJohn Fastabend int err;
303298970c8SJohn Fastabend
304298970c8SJohn Fastabend key = 0;
305298970c8SJohn Fastabend value = fd1;
306298970c8SJohn Fastabend err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
307298970c8SJohn Fastabend if (err)
308298970c8SJohn Fastabend return err;
309298970c8SJohn Fastabend
310298970c8SJohn Fastabend key = 1;
311298970c8SJohn Fastabend value = fd2;
312298970c8SJohn Fastabend return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
313298970c8SJohn Fastabend }
314298970c8SJohn Fastabend
create_pair(int s,int family,int sotype,int * c,int * p)315298970c8SJohn Fastabend static inline int create_pair(int s, int family, int sotype, int *c, int *p)
316298970c8SJohn Fastabend {
317298970c8SJohn Fastabend struct sockaddr_storage addr;
318298970c8SJohn Fastabend socklen_t len;
319298970c8SJohn Fastabend int err = 0;
320298970c8SJohn Fastabend
321298970c8SJohn Fastabend len = sizeof(addr);
322298970c8SJohn Fastabend err = xgetsockname(s, sockaddr(&addr), &len);
323298970c8SJohn Fastabend if (err)
324298970c8SJohn Fastabend return err;
325298970c8SJohn Fastabend
326298970c8SJohn Fastabend *c = xsocket(family, sotype, 0);
327298970c8SJohn Fastabend if (*c < 0)
328298970c8SJohn Fastabend return errno;
329298970c8SJohn Fastabend err = xconnect(*c, sockaddr(&addr), len);
330298970c8SJohn Fastabend if (err) {
331298970c8SJohn Fastabend err = errno;
332298970c8SJohn Fastabend goto close_cli0;
333298970c8SJohn Fastabend }
334298970c8SJohn Fastabend
335298970c8SJohn Fastabend *p = xaccept_nonblock(s, NULL, NULL);
336298970c8SJohn Fastabend if (*p < 0) {
337298970c8SJohn Fastabend err = errno;
338298970c8SJohn Fastabend goto close_cli0;
339298970c8SJohn Fastabend }
340298970c8SJohn Fastabend return err;
341298970c8SJohn Fastabend close_cli0:
342298970c8SJohn Fastabend close(*c);
343298970c8SJohn Fastabend return err;
344298970c8SJohn Fastabend }
345298970c8SJohn Fastabend
create_socket_pairs(int s,int family,int sotype,int * c0,int * c1,int * p0,int * p1)346298970c8SJohn Fastabend static inline int create_socket_pairs(int s, int family, int sotype,
347298970c8SJohn Fastabend int *c0, int *c1, int *p0, int *p1)
348298970c8SJohn Fastabend {
349298970c8SJohn Fastabend int err;
350298970c8SJohn Fastabend
351298970c8SJohn Fastabend err = create_pair(s, family, sotype, c0, p0);
352298970c8SJohn Fastabend if (err)
353298970c8SJohn Fastabend return err;
354298970c8SJohn Fastabend
355298970c8SJohn Fastabend err = create_pair(s, family, sotype, c1, p1);
356298970c8SJohn Fastabend if (err) {
357298970c8SJohn Fastabend close(*c0);
358298970c8SJohn Fastabend close(*p0);
359298970c8SJohn Fastabend }
360298970c8SJohn Fastabend return err;
361298970c8SJohn Fastabend }
362298970c8SJohn Fastabend
enable_reuseport(int s,int progfd)363298970c8SJohn Fastabend static inline int enable_reuseport(int s, int progfd)
364298970c8SJohn Fastabend {
365298970c8SJohn Fastabend int err, one = 1;
366298970c8SJohn Fastabend
367298970c8SJohn Fastabend err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
368298970c8SJohn Fastabend if (err)
369298970c8SJohn Fastabend return -1;
370298970c8SJohn Fastabend err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
371298970c8SJohn Fastabend sizeof(progfd));
372298970c8SJohn Fastabend if (err)
373298970c8SJohn Fastabend return -1;
374298970c8SJohn Fastabend
375298970c8SJohn Fastabend return 0;
376298970c8SJohn Fastabend }
377298970c8SJohn Fastabend
socket_loopback_reuseport(int family,int sotype,int progfd)378298970c8SJohn Fastabend static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
379298970c8SJohn Fastabend {
380298970c8SJohn Fastabend struct sockaddr_storage addr;
381298970c8SJohn Fastabend socklen_t len;
382298970c8SJohn Fastabend int err, s;
383298970c8SJohn Fastabend
384298970c8SJohn Fastabend init_addr_loopback(family, &addr, &len);
385298970c8SJohn Fastabend
386298970c8SJohn Fastabend s = xsocket(family, sotype, 0);
387298970c8SJohn Fastabend if (s == -1)
388298970c8SJohn Fastabend return -1;
389298970c8SJohn Fastabend
390298970c8SJohn Fastabend if (progfd >= 0)
391298970c8SJohn Fastabend enable_reuseport(s, progfd);
392298970c8SJohn Fastabend
393298970c8SJohn Fastabend err = xbind(s, sockaddr(&addr), len);
394298970c8SJohn Fastabend if (err)
395298970c8SJohn Fastabend goto close;
396298970c8SJohn Fastabend
397298970c8SJohn Fastabend if (sotype & SOCK_DGRAM)
398298970c8SJohn Fastabend return s;
399298970c8SJohn Fastabend
400298970c8SJohn Fastabend err = xlisten(s, SOMAXCONN);
401298970c8SJohn Fastabend if (err)
402298970c8SJohn Fastabend goto close;
403298970c8SJohn Fastabend
404298970c8SJohn Fastabend return s;
405298970c8SJohn Fastabend close:
406298970c8SJohn Fastabend xclose(s);
407298970c8SJohn Fastabend return -1;
408298970c8SJohn Fastabend }
409298970c8SJohn Fastabend
socket_loopback(int family,int sotype)410298970c8SJohn Fastabend static inline int socket_loopback(int family, int sotype)
411298970c8SJohn Fastabend {
412298970c8SJohn Fastabend return socket_loopback_reuseport(family, sotype, -1);
413298970c8SJohn Fastabend }
414298970c8SJohn Fastabend
415298970c8SJohn Fastabend
4164e02588dSJohn Fastabend #endif // __SOCKMAP_HELPERS__
417