|  | 
| 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