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