MT#55283 extend test preload .so

Support PKTINFO, even though no info is actually attached yet.

Prefix fake socket addresses with the type (udp/tcp) so that both can be
used at the same time.

Change-Id: Ia72e28c9a0fe07d74ec473b5288b30b82c6c8113
pull/1938/head
Richard Fuchs 8 months ago
parent 636c9f193f
commit 94b1eced71

@ -26,7 +26,8 @@ typedef struct {
peername;
unsigned int open:1,
bound:1,
connected:1;
connected:1,
pktinfo:1;
} socket_t;
typedef struct {
@ -90,7 +91,7 @@ int socket(int domain, int type, int protocol) {
real_sockets[fd] = (socket_t) {
.used_domain = use_domain,
.wanted_domain = domain,
.type = type,
.type = type & 0xff,
.used_protocol = use_protocol,
.wanted_protocol = protocol,
.open = 1,
@ -101,12 +102,23 @@ 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)
{
const char *err;
char sockname[64];
const char *any_name;
unsigned int port;
const char *prefix = "unk";
switch (type) {
case SOCK_STREAM:
prefix = "tcp";
break;
case SOCK_DGRAM:
prefix = "udp";
break;
}
switch (addr->sa_family) {
case AF_INET:;
@ -139,7 +151,8 @@ static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr
if (allow_anon) {
err = "Unix socket path truncated";
if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/[%s]:%u", path_prefix(), any_name, port)
if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s:[%s]:%u", path_prefix(),
prefix, any_name, port)
>= sizeof(sun->sun_path))
goto err;
@ -151,7 +164,8 @@ static const char *addr_translate(struct sockaddr_un *sun, const struct sockaddr
if (do_specific) {
err = "Unix socket path truncated";
if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/[%s]:%u", path_prefix(), sockname, port)
if (snprintf(sun->sun_path, sizeof(sun->sun_path), "%s/%s:[%s]:%u", path_prefix(),
prefix, sockname, port)
>= sizeof(sun->sun_path))
goto err;
}
@ -182,6 +196,12 @@ void addr_translate_reverse(struct sockaddr_storage *sst, socklen_t *socklen, in
}
path++;
if (path[0] == '\0' || path[1] == '\0' || path[2] == '\0' || path[3] != ':') {
fprintf(stderr, "preload addr_translate_reverse(): missing prefix '%s'\n", path);
return;
}
path += 4;
struct sockaddr_in sin = {0,};
struct sockaddr_in6 sin6 = {0,};
socklen_t addrlen;
@ -258,7 +278,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, 0);
err = addr_translate(&sun, addr, addrlen, s->type, 0);
if (err) {
if (!err[0])
goto do_bind;
@ -315,6 +335,7 @@ static socklen_t anon_addr(int domain, struct sockaddr_storage *sst, unsigned in
}
static void check_bind(int fd) {
const char *prefix = "unk";
// to make inspecting the peer address on the receiving end possible, we must bind
// to some unix path name
@ -328,13 +349,23 @@ static void check_bind(int fd) {
if (s->wanted_domain == AF_UNIX || s->used_domain != AF_UNIX)
return;
switch (s->type) {
case SOCK_STREAM:
prefix = "tcp";
break;
case SOCK_DGRAM:
prefix = "udp";
break;
}
struct sockaddr_storage sst;
unsigned int auto_inc = __sync_fetch_and_add(&anon_sock_inc, 1);
anon_addr(s->wanted_domain, &sst, auto_inc, getpid());
struct sockaddr_un sun;
sun.sun_family = AF_UNIX;
if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/ANON.%u.%u", path_prefix(), getpid(),
if (snprintf(sun.sun_path, sizeof(sun.sun_path), "%s/%s:ANON.%u.%u", path_prefix(), prefix,
getpid(),
auto_inc)
>= sizeof(sun.sun_path))
fprintf(stderr, "preload socket(): failed to print anon (fd %i)\n", fd);
@ -475,7 +506,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, 1);
err = addr_translate(&sun, addr, addrlen, s->type, 1);
if (err) {
if (!err[0])
goto do_connect;
@ -721,13 +752,13 @@ static const struct sockaddr *addr_find(const struct sockaddr *addr, socklen_t *
return NULL;
}
static const struct sockaddr *addr_send_translate(const struct sockaddr *addr, socklen_t *addrlen) {
static const struct sockaddr *addr_send_translate(const struct sockaddr *addr, int type, socklen_t *addrlen) {
const struct sockaddr *ret = addr_find(addr, addrlen);
if (ret)
return ret;
static __thread struct sockaddr_un sun;
const char *err = addr_translate(&sun, addr, *addrlen, 0);
const char *err = addr_translate(&sun, addr, *addrlen, type, 0);
if (!err) {
*addrlen = sizeof(sun);
return (void *) &sun;
@ -740,19 +771,43 @@ static const struct sockaddr *addr_send_translate(const struct sockaddr *addr, s
}
ssize_t sendto(int fd, const void *buf, size_t len, int flags, const struct sockaddr *addr, socklen_t addrlen) {
const char *err;
check_bind(fd);
ssize_t (*real_sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t)
= dlsym(RTLD_NEXT, "sendto");
addr = addr_send_translate(addr, &addrlen);
err = "fd out of bounds";
if (fd < 0 || fd >= MAX_SOCKETS)
goto do_send_warn;
socket_t *s = &real_sockets[fd];
err = "fd not open";
if (!s->open)
goto do_send_warn;
addr = addr_send_translate(addr, s->type, &addrlen);
goto do_send;
do_send_warn:
fprintf(stderr, "preload sendto(): %s (fd %i)\n", err, fd);
do_send:
return real_sendto(fd, buf, len, flags, addr, addrlen);
}
ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
const char *err;
check_bind(fd);
ssize_t (*real_sendmsg)(int, const struct msghdr *, int) = dlsym(RTLD_NEXT, "sendmsg");
err = "fd out of bounds";
if (fd < 0 || fd >= MAX_SOCKETS)
goto do_send_warn;
socket_t *s = &real_sockets[fd];
err = "fd not open";
if (!s->open)
goto do_send_warn;
struct msghdr msg2 = *msg;
if (msg2.msg_name)
msg2.msg_name = (void *) addr_send_translate(msg2.msg_name, &msg2.msg_namelen);
msg2.msg_name = (void *) addr_send_translate(msg2.msg_name, s->type, &msg2.msg_namelen);
goto do_send;
do_send_warn:
fprintf(stderr, "preload sendmsg(): %s (fd %i)\n", err, fd);
do_send:
return real_sendmsg(fd, &msg2, flags);
}
@ -775,6 +830,10 @@ int setsockopt(int fd, int level, int optname, const void *optval, socklen_t opt
return 0;
if (level == IPPROTO_TCP && optname == TCP_NODELAY)
return 0;
if (level == SOL_IP && optname == IP_PKTINFO) {
s->pktinfo = 1;
return 0;
}
break;
case AF_INET6:
@ -784,6 +843,10 @@ int setsockopt(int fd, int level, int optname, const void *optval, socklen_t opt
return 0;
if (level == IPPROTO_TCP && optname == TCP_NODELAY)
return 0;
if (level == SOL_IPV6 && optname == IPV6_RECVPKTINFO) {
s->pktinfo = 1;
return 0;
}
break;
}

Loading…
Cancel
Save