diff --git a/t/tests-preload.c b/t/tests-preload.c index 101a5625f..4661bd59e 100644 --- a/t/tests-preload.c +++ b/t/tests-preload.c @@ -103,12 +103,14 @@ int socket(int domain, int type, int protocol) { static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr *addr, socklen_t addrlen, int type, - int allow_anon) + int allow_anon, + int alloc_port) { const char *err; char sockname[64]; const char *any_name; unsigned int port; + uint16_t *set_port = NULL; const char *prefix = "unk"; switch (type) { @@ -131,6 +133,7 @@ static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr goto err; any_name = "0.0.0.0"; port = ntohs(sin->sin_port); + set_port = &sin->sin_port; break; case AF_INET6:; struct sockaddr_in6 *sin6 = (void *) addr; @@ -142,6 +145,7 @@ static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr goto err; any_name = "::"; port = ntohs(sin6->sin6_port); + set_port = &sin6->sin6_port; break; default: goto skip; @@ -149,27 +153,51 @@ static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr int do_specific = 1; + if (allow_anon) { +retry_anon: err = "Unix socket path truncated"; + unsigned int use_port = port; + if (!use_port && alloc_port) + use_port = rand() % 1000 + 63000; if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s:[%s]:%u", path_prefix(), - prefix, any_name, port) + prefix, any_name, use_port) >= sizeof(sun->sun_path)) goto err; struct stat sb; int ret = stat(sun->sun_path, &sb); - if (ret == 0 && sb.st_mode & S_IFSOCK) + if (ret == 0 && sb.st_mode & S_IFSOCK) { + if (!port && alloc_port) + goto retry_anon; do_specific = 0; + } + port = use_port; } if (do_specific) { +retry_specific: err = "Unix socket path truncated"; + unsigned int use_port = port; + if (!use_port && alloc_port) + use_port = rand() % 1000 + 63000; if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s:[%s]:%u", path_prefix(), - prefix, sockname, port) + prefix, sockname, use_port) >= sizeof(sun->sun_path)) goto err; + + if (!port && alloc_port) { + struct stat sb; + int ret = stat(sun->sun_path, &sb); + if (ret == 0 && sb.st_mode & S_IFSOCK) + goto retry_specific; + } + port = use_port; } + if (alloc_port) + *set_port = htons(port); + sun->sun_family = AF_UNIX; return NULL; skip: @@ -278,7 +306,7 @@ int bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { assert(s->wanted_domain == addr->sa_family); struct sockaddr_un sun; - err = addr_translate(&sun, addr, addrlen, s->type, 0); + err = addr_translate(&sun, addr, addrlen, s->type, 0, 1); if (err) { if (!err[0]) goto do_bind; @@ -506,7 +534,7 @@ int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) { assert(s->wanted_domain == addr->sa_family); struct sockaddr_un sun; - err = addr_translate(&sun, addr, addrlen, s->type, 1); + err = addr_translate(&sun, addr, addrlen, s->type, 1, 0); if (err) { if (!err[0]) goto do_connect; @@ -758,7 +786,7 @@ static const struct sockaddr *addr_send_translate(const struct sockaddr *addr, i return ret; static __thread struct sockaddr_un sun; - const char *err = addr_translate(&sun, addr, *addrlen, type, 0); + const char *err = addr_translate(&sun, addr, *addrlen, type, 0, 0); if (!err) { *addrlen = sizeof(sun); return (void *) &sun;