|
3 | 3 |
|
4 | 4 | #include <linux/vm_sockets.h>
|
5 | 5 |
|
| 6 | +/* include/linux/net.h */ |
| 7 | +#define SOCK_TYPE_MASK 0xf |
| 8 | + |
6 | 9 | #define IO_TIMEOUT_SEC 30
|
7 | 10 | #define MAX_STRERR_LEN 256
|
8 | 11 | #define MAX_TEST_NAME 80
|
|
14 | 17 |
|
15 | 18 | #define __always_unused __attribute__((__unused__))
|
16 | 19 |
|
| 20 | +/* include/linux/cleanup.h */ |
| 21 | +#define __get_and_null(p, nullvalue) \ |
| 22 | + ({ \ |
| 23 | + __auto_type __ptr = &(p); \ |
| 24 | + __auto_type __val = *__ptr; \ |
| 25 | + *__ptr = nullvalue; \ |
| 26 | + __val; \ |
| 27 | + }) |
| 28 | + |
| 29 | +#define take_fd(fd) __get_and_null(fd, -EBADF) |
| 30 | + |
17 | 31 | #define _FAIL(errnum, fmt...) \
|
18 | 32 | ({ \
|
19 | 33 | error_at_line(0, (errnum), __func__, __LINE__, fmt); \
|
|
179 | 193 | __ret; \
|
180 | 194 | })
|
181 | 195 |
|
| 196 | +static inline void close_fd(int *fd) |
| 197 | +{ |
| 198 | + if (*fd >= 0) |
| 199 | + xclose(*fd); |
| 200 | +} |
| 201 | + |
| 202 | +#define __close_fd __attribute__((cleanup(close_fd))) |
| 203 | + |
182 | 204 | static inline int poll_connect(int fd, unsigned int timeout_sec)
|
183 | 205 | {
|
184 | 206 | struct timeval timeout = { .tv_sec = timeout_sec };
|
@@ -312,54 +334,6 @@ static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
|
312 | 334 | return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
|
313 | 335 | }
|
314 | 336 |
|
315 |
| -static inline int create_pair(int s, int family, int sotype, int *c, int *p) |
316 |
| -{ |
317 |
| - struct sockaddr_storage addr; |
318 |
| - socklen_t len; |
319 |
| - int err = 0; |
320 |
| - |
321 |
| - len = sizeof(addr); |
322 |
| - err = xgetsockname(s, sockaddr(&addr), &len); |
323 |
| - if (err) |
324 |
| - return err; |
325 |
| - |
326 |
| - *c = xsocket(family, sotype, 0); |
327 |
| - if (*c < 0) |
328 |
| - return errno; |
329 |
| - err = xconnect(*c, sockaddr(&addr), len); |
330 |
| - if (err) { |
331 |
| - err = errno; |
332 |
| - goto close_cli0; |
333 |
| - } |
334 |
| - |
335 |
| - *p = xaccept_nonblock(s, NULL, NULL); |
336 |
| - if (*p < 0) { |
337 |
| - err = errno; |
338 |
| - goto close_cli0; |
339 |
| - } |
340 |
| - return err; |
341 |
| -close_cli0: |
342 |
| - close(*c); |
343 |
| - return err; |
344 |
| -} |
345 |
| - |
346 |
| -static inline int create_socket_pairs(int s, int family, int sotype, |
347 |
| - int *c0, int *c1, int *p0, int *p1) |
348 |
| -{ |
349 |
| - int err; |
350 |
| - |
351 |
| - err = create_pair(s, family, sotype, c0, p0); |
352 |
| - if (err) |
353 |
| - return err; |
354 |
| - |
355 |
| - err = create_pair(s, family, sotype, c1, p1); |
356 |
| - if (err) { |
357 |
| - close(*c0); |
358 |
| - close(*p0); |
359 |
| - } |
360 |
| - return err; |
361 |
| -} |
362 |
| - |
363 | 337 | static inline int enable_reuseport(int s, int progfd)
|
364 | 338 | {
|
365 | 339 | int err, one = 1;
|
@@ -412,5 +386,84 @@ static inline int socket_loopback(int family, int sotype)
|
412 | 386 | return socket_loopback_reuseport(family, sotype, -1);
|
413 | 387 | }
|
414 | 388 |
|
| 389 | +static inline int create_pair(int family, int sotype, int *p0, int *p1) |
| 390 | +{ |
| 391 | + __close_fd int s, c = -1, p = -1; |
| 392 | + struct sockaddr_storage addr; |
| 393 | + socklen_t len = sizeof(addr); |
| 394 | + int err; |
| 395 | + |
| 396 | + s = socket_loopback(family, sotype); |
| 397 | + if (s < 0) |
| 398 | + return s; |
| 399 | + |
| 400 | + err = xgetsockname(s, sockaddr(&addr), &len); |
| 401 | + if (err) |
| 402 | + return err; |
| 403 | + |
| 404 | + c = xsocket(family, sotype, 0); |
| 405 | + if (c < 0) |
| 406 | + return c; |
| 407 | + |
| 408 | + err = connect(c, sockaddr(&addr), len); |
| 409 | + if (err) { |
| 410 | + if (errno != EINPROGRESS) { |
| 411 | + FAIL_ERRNO("connect"); |
| 412 | + return err; |
| 413 | + } |
| 414 | + |
| 415 | + err = poll_connect(c, IO_TIMEOUT_SEC); |
| 416 | + if (err) { |
| 417 | + FAIL_ERRNO("poll_connect"); |
| 418 | + return err; |
| 419 | + } |
| 420 | + } |
| 421 | + |
| 422 | + switch (sotype & SOCK_TYPE_MASK) { |
| 423 | + case SOCK_DGRAM: |
| 424 | + err = xgetsockname(c, sockaddr(&addr), &len); |
| 425 | + if (err) |
| 426 | + return err; |
| 427 | + |
| 428 | + err = xconnect(s, sockaddr(&addr), len); |
| 429 | + if (err) |
| 430 | + return err; |
| 431 | + |
| 432 | + *p0 = take_fd(s); |
| 433 | + break; |
| 434 | + case SOCK_STREAM: |
| 435 | + case SOCK_SEQPACKET: |
| 436 | + p = xaccept_nonblock(s, NULL, NULL); |
| 437 | + if (p < 0) |
| 438 | + return p; |
| 439 | + |
| 440 | + *p0 = take_fd(p); |
| 441 | + break; |
| 442 | + default: |
| 443 | + FAIL("Unsupported socket type %#x", sotype); |
| 444 | + return -EOPNOTSUPP; |
| 445 | + } |
| 446 | + |
| 447 | + *p1 = take_fd(c); |
| 448 | + return 0; |
| 449 | +} |
| 450 | + |
| 451 | +static inline int create_socket_pairs(int family, int sotype, int *c0, int *c1, |
| 452 | + int *p0, int *p1) |
| 453 | +{ |
| 454 | + int err; |
| 455 | + |
| 456 | + err = create_pair(family, sotype, c0, p0); |
| 457 | + if (err) |
| 458 | + return err; |
| 459 | + |
| 460 | + err = create_pair(family, sotype, c1, p1); |
| 461 | + if (err) { |
| 462 | + close(*c0); |
| 463 | + close(*p0); |
| 464 | + } |
| 465 | + |
| 466 | + return err; |
| 467 | +} |
415 | 468 |
|
416 | 469 | #endif // __SOCKMAP_HELPERS__
|
0 commit comments