mirror of https://gerrit.osmocom.org/libosmocore
Add osmo_sock_get_name_multiaddr()
It's similar to osmo_sock_get_name() but supports multi-homed SCTP sockets bound to several addresses. Related: OS#5581 Change-Id: If76595ebd1cf26ba904887a36c4cc14a1b5c4521
This commit is contained in:
parent
a322fa47d1
commit
f04dea0308
|
@ -105,6 +105,7 @@ int osmo_sock_unix_init_ofd(struct osmo_fd *ofd, uint16_t type, uint8_t proto,
|
|||
const char *socket_path, unsigned int flags);
|
||||
|
||||
char *osmo_sock_get_name(const void *ctx, int fd);
|
||||
char *osmo_sock_get_name_multiaddr(const void *ctx, int fd);
|
||||
const char *osmo_sock_get_name2(int fd);
|
||||
char *osmo_sock_get_name2_c(const void *ctx, int fd);
|
||||
int osmo_sock_get_name_buf(char *str, size_t str_len, int fd);
|
||||
|
|
98
src/socket.c
98
src/socket.c
|
@ -230,6 +230,104 @@ static int multiaddr_snprintf(char* buf, size_t buf_len, const char **hosts, siz
|
|||
talloc_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sctp_addr_count_helper(int addr_count, bool local)
|
||||
{
|
||||
if (addr_count == -1) { /* We expect this to fail if corresponding side of the socket is not connected */
|
||||
LOGP(DLGLOBAL, LOGL_DEBUG, "Error occured while calling sctp_get%caddrs()\n", local ? 'l' : 'p');
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (addr_count == 0) {
|
||||
LOGP(DLGLOBAL, LOGL_DEBUG, "Calling sctp_get%caddrs() on unbound socket\n", local ? 'l' : 'p');
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
if (addr_count > OSMO_SOCK_MAX_ADDRS) {
|
||||
LOGP(DLGLOBAL, LOGL_NOTICE, "Got more than %u addresses from sctp_get%caddrs(): result will be truncated\n",
|
||||
OSMO_SOCK_MAX_ADDRS, local ? 'l' : 'p');
|
||||
}
|
||||
|
||||
return addr_count;
|
||||
}
|
||||
|
||||
static int sctp_multiaddr_print_ctx_helper(const void *ctx, int fd, char *str, size_t strlen, bool local)
|
||||
{
|
||||
struct sockaddr *addrs = NULL;
|
||||
|
||||
/* 2nd parameter 0 for sctp_get?addrs() means "disregard any particular association" */
|
||||
int i, addr_count = sctp_addr_count_helper(local ? sctp_getladdrs(fd, 0, &addrs) : sctp_getpaddrs(fd, 0, &addrs),
|
||||
local);
|
||||
if (addr_count < 0) {
|
||||
local ? sctp_freeladdrs(addrs) : sctp_freepaddrs(addrs);
|
||||
return addr_count;
|
||||
}
|
||||
|
||||
if (addr_count > OSMO_SOCK_MAX_ADDRS)
|
||||
addr_count = OSMO_SOCK_MAX_ADDRS;
|
||||
|
||||
struct osmo_sockaddr_str *sa_strs[addr_count];
|
||||
|
||||
for (i = 0; i < addr_count; i++) {
|
||||
sa_strs[i] = talloc_zero(ctx, struct osmo_sockaddr_str);
|
||||
int rc = osmo_sockaddr_str_from_sockaddr(sa_strs[i], (const struct sockaddr_storage *)&addrs[i]);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
local ? sctp_freeladdrs(addrs) : sctp_freepaddrs(addrs);
|
||||
|
||||
return osmo_sockaddr_strs_to_str(str, strlen, (const struct osmo_sockaddr_str **)sa_strs, addr_count);
|
||||
}
|
||||
|
||||
/*! Get address/port information on socket in dyn-alloc string like "r=1.2.3.4:5<->l=(6.7.8.9|4.3.2.1):10".
|
||||
* Multiple addresses (e. g. SCTP) are properly supported.
|
||||
* \param[in] ctx talloc context from which to allocate string buffer
|
||||
* \param[in] fd file descriptor of socket
|
||||
* \returns string identifying the connection of this socket, talloc'd from ctx.
|
||||
*/
|
||||
char *osmo_sock_get_name_multiaddr(const void *ctx, int fd)
|
||||
{
|
||||
char portbuf_l[6], portbuf_r[6],
|
||||
hostbuf_l[OSMO_SOCK_MAX_ADDRS * OSMO_SOCK_NAME_MAXLEN],
|
||||
hostbuf_r[OSMO_SOCK_MAX_ADDRS * OSMO_SOCK_NAME_MAXLEN];
|
||||
int rc;
|
||||
char *str = NULL;
|
||||
|
||||
/* get local */
|
||||
|
||||
rc = sctp_multiaddr_print_ctx_helper(ctx, fd, hostbuf_l, sizeof(hostbuf_l), true);
|
||||
if (rc < 0) {
|
||||
osmo_talloc_asprintf(ctx, str, "<error-in-sctp_getladdrs>");
|
||||
return str;
|
||||
}
|
||||
|
||||
/* according to https://datatracker.ietf.org/doc/html/rfc4960 multi-homed SCTP has to use the same port number */
|
||||
rc = osmo_sock_get_local_ip_port(fd, portbuf_l, sizeof(portbuf_l));
|
||||
if (rc < 0) {
|
||||
osmo_talloc_asprintf(ctx, str, "<error-in-osmo_sock_get_local_ip_port>");
|
||||
return str;
|
||||
}
|
||||
|
||||
/* get remote */
|
||||
|
||||
rc = sctp_multiaddr_print_ctx_helper(ctx, fd, hostbuf_r, sizeof(hostbuf_r), false);
|
||||
if (rc < 0) {
|
||||
osmo_talloc_asprintf(ctx, str, "r=NULL<->l=%s:%s", hostbuf_l, portbuf_l);
|
||||
return str;
|
||||
}
|
||||
|
||||
rc = osmo_sock_get_remote_ip_port(fd, portbuf_r, sizeof(portbuf_r));
|
||||
if (rc < 0) {
|
||||
osmo_talloc_asprintf(ctx, str, "<error-in-osmo_sock_get_local_ip_port>");
|
||||
return str;
|
||||
}
|
||||
|
||||
osmo_talloc_asprintf(ctx, str, "r=%s:%s<->l=%s:%s", hostbuf_r, portbuf_r, hostbuf_l, portbuf_l);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBSCTP */
|
||||
|
||||
static int osmo_sock_init_tail(int fd, uint16_t type, unsigned int flags)
|
||||
|
|
|
@ -61,7 +61,8 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
int listen_fd_v4, listen_fd_v6;
|
||||
int listen_port_v4, listen_port_v6;
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port:\n",
|
||||
addrv4_size);
|
||||
|
||||
listen_fd_v4 = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv4_loc, addrv4_size, 0,
|
||||
|
@ -71,9 +72,12 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
rc = fcntl(listen_fd_v4, F_GETFL);
|
||||
OSMO_ASSERT(!(rc & O_NONBLOCK));
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, listen_fd_v4));
|
||||
|
||||
listen_port_v4 = sock_get_local_port(listen_fd_v4, false);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port:\n",
|
||||
addrv6_size);
|
||||
|
||||
listen_fd_v6 = osmo_sock_init2_multiaddr(AF_INET6, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv6_loc, addrv6_size, 0,
|
||||
|
@ -83,9 +87,11 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
rc = fcntl(listen_fd_v6, F_GETFL);
|
||||
OSMO_ASSERT(!(rc & O_NONBLOCK));
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, listen_fd_v6));
|
||||
|
||||
listen_port_v6 = sock_get_local_port(listen_fd_v6, true);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK:\n", addrv4_size);
|
||||
fd = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv4_loc, addrv4_size, 0,
|
||||
NULL, 0, 0, OSMO_SOCK_F_BIND|OSMO_SOCK_F_NONBLOCK);
|
||||
|
@ -93,6 +99,9 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
/* expect it to be blocking */
|
||||
rc = fcntl(fd, F_GETFL);
|
||||
OSMO_ASSERT(rc & O_NONBLOCK);
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, fd));
|
||||
|
||||
close(fd);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr() for invalid flags\n");
|
||||
|
@ -101,13 +110,15 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
NULL, 0, 0, 0);
|
||||
OSMO_ASSERT(fd < 0);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT:\n", addrv4_size);
|
||||
fd = osmo_sock_init2_multiaddr(AF_INET, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv4_rem, addrv4_size, 0,
|
||||
addrv4_rem, addrv4_size, listen_port_v4,
|
||||
OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
|
||||
OSMO_ASSERT(fd >= 0);
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, fd));
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv4 & IPv6\n");
|
||||
fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv4_rem, addrv4_size, 0,
|
||||
|
@ -122,23 +133,27 @@ static int test_sockinit2_multiaddr(const char **addrv4_loc, const char **addrv6
|
|||
OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
|
||||
OSMO_ASSERT(fd < 0);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4:\n", addrv4_size);
|
||||
fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv4_rem, addrv4_size, 0,
|
||||
addrv4_rem, addrv4_size, listen_port_v4,
|
||||
OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
|
||||
OSMO_ASSERT(fd >= 0);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6\n");
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, fd));
|
||||
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6:\n", addrv6_size);
|
||||
fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addrv6_rem, addrv6_size, 0,
|
||||
addrv6_rem, addrv6_size, listen_port_v6,
|
||||
OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
|
||||
OSMO_ASSERT(fd >= 0);
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, fd));
|
||||
|
||||
close(listen_fd_v4);
|
||||
close(listen_fd_v6);
|
||||
printf("Done\n");
|
||||
printf("Done\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -184,20 +199,24 @@ static int test_sockinit2_multiaddr_mixed(void)
|
|||
NULL, 0, 0, OSMO_SOCK_F_BIND);
|
||||
OSMO_ASSERT(listen_fd < 0);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_UNSPEC IPv4+v6 succeeds\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_UNSPEC IPv4+v6 succeeds:\n", addr_size);
|
||||
listen_fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addr_localhost, addr_size, 0,
|
||||
NULL, 0, 0, OSMO_SOCK_F_BIND);
|
||||
OSMO_ASSERT(listen_fd >= 0);
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, listen_fd));
|
||||
|
||||
listen_port = sock_get_local_port(listen_fd, true);
|
||||
|
||||
printf("Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4\n");
|
||||
printf("\n[%zu] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4:\n", addr_size);
|
||||
fd = osmo_sock_init2_multiaddr(AF_UNSPEC, SOCK_STREAM, IPPROTO_SCTP,
|
||||
addr_localhost, addr_size, 0,
|
||||
addr_localhost, addr_size, listen_port,
|
||||
OSMO_SOCK_F_BIND|OSMO_SOCK_F_CONNECT);
|
||||
OSMO_ASSERT(fd >= 0);
|
||||
|
||||
printf("Bound on %s\n", osmo_sock_get_name_multiaddr(ctx, fd));
|
||||
close(fd);
|
||||
|
||||
close(listen_fd);
|
||||
|
@ -222,6 +241,7 @@ int main(int argc, char *argv[])
|
|||
log_set_print_category(osmo_stderr_target, 0);
|
||||
log_set_print_category_hex(osmo_stderr_target, 0);
|
||||
#ifdef HAVE_LIBSCTP
|
||||
srand(666);
|
||||
test_sockinit2_multiaddr_simple();
|
||||
test_sockinit2_multiaddr_several();
|
||||
test_sockinit2_multiaddr_mixed();
|
||||
|
|
|
@ -1,24 +1,54 @@
|
|||
Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port
|
||||
Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port
|
||||
Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port:
|
||||
Bound on r=NULL<->l=(127.0.0.1|192.168.43.112):37678
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port:
|
||||
Bound on r=NULL<->l=([::ffff:127.0.0.1]|[0:0:a00:c59e::]|[::1:100:0]|[a00:c59e:0:0:fe80::]):50590
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK:
|
||||
Bound on r=NULL<->l=(127.0.0.1|192.168.43.112):52990
|
||||
Checking osmo_sock_init2_multiaddr() for invalid flags
|
||||
Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT:
|
||||
Bound on r=(127.0.0.1|192.168.43.112):37678<->l=127.0.0.1:49762
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv4 & IPv6
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv6 & IPv4
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4:
|
||||
Bound on r=(127.0.0.1|192.168.43.112):37678<->l=127.0.0.1:47727
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6:
|
||||
Bound on r=NULL<->l=[::1]:38193
|
||||
Done
|
||||
Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port
|
||||
Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port
|
||||
Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK
|
||||
|
||||
|
||||
[2] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv4 port:
|
||||
Bound on r=NULL<->l=(127.0.0.1|127.0.0.2):37742
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr() with bind to a random local SCTP IPv6 port:
|
||||
Bound on r=NULL<->l=[::1]:48810
|
||||
|
||||
[2] Checking osmo_sock_init2_multiaddr() for OSMO_SOCK_F_NONBLOCK:
|
||||
Bound on r=NULL<->l=(127.0.0.1|127.0.0.2):59017
|
||||
Checking osmo_sock_init2_multiaddr() for invalid flags
|
||||
Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT
|
||||
|
||||
[2] Checking osmo_sock_init2_multiaddr() for combined BIND + CONNECT:
|
||||
Bound on r=(127.0.0.1|127.0.0.2):37742<->l=(127.0.0.1|127.0.0.2):38654
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv4 & IPv6
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) must fail on mixed IPv6 & IPv4
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6
|
||||
|
||||
[2] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4:
|
||||
Bound on r=(127.0.0.1|127.0.0.2):37742<->l=(127.0.0.1|127.0.0.2):40892
|
||||
|
||||
[1] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv6:
|
||||
Bound on r=[::1]:48810<->l=[::1]:41262
|
||||
Done
|
||||
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_INET IPv4+v6 fails
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_INET6 IPv4+v6 fails
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_UNSPEC IPv4+v6 succeeds
|
||||
Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4
|
||||
|
||||
[3] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND on AF_UNSPEC IPv4+v6 succeeds:
|
||||
Bound on r=NULL<->l=([::ffff:127.0.0.1]|[0:0:a00:92de::]|[::ffff:7f00:2:0:0]):37598
|
||||
|
||||
[3] Checking osmo_sock_init2_multiaddr(AF_UNSPEC) BIND + CONNECT on IPv4:
|
||||
Bound on r=([::ffff:127.0.0.1]|[0:0:a00:92de::]|[::ffff:7f00:2:0:0]):37598<->l=([::ffff:127.0.0.1]|[0:0:a00:95bd::]|[::ffff:7f00:2:0:0]):38333
|
||||
|
|
Loading…
Reference in New Issue