socket: Introduce API osmo_sock_multiaddr_get_name_buf()

An extra osmo_multiaddr_ip_and_port_snprintf() API is introduced which
is used by osmo_sock_multiaddr_get_name_buf() but which will also be
used by other app uers willing to use
osmo_sock_multiaddr_get_ip_and_port() according to its needs (eg. only
printing the local side).

Related: SYS#6636
Change-Id: I48950754ed6f61ee5ffa04a447fab8903f10acc0
This commit is contained in:
Pau Espin 2023-11-30 19:12:16 +01:00 committed by laforge
parent 6a2975c858
commit 5ac8aa5852
4 changed files with 113 additions and 1 deletions

View File

@ -8,7 +8,7 @@
# If any interfaces have been removed or changed since the last public release: c:r:0. # If any interfaces have been removed or changed since the last public release: c:r:0.
#library what description / commit summary line #library what description / commit summary line
core ADD osmo_sock_multiaddr_{add,del}_local_addr() core ADD osmo_sock_multiaddr_{add,del}_local_addr()
core ADD osmo_sock_multiaddr_get_ip_and_port() core ADD osmo_sock_multiaddr_get_ip_and_port(), osmo_multiaddr_ip_and_port_snprintf(), osmo_sock_multiaddr_get_name_buf()
core ADD gsmtap_inst_fd2() core, DEPRECATE gsmtap_inst_fd() core ADD gsmtap_inst_fd2() core, DEPRECATE gsmtap_inst_fd()
isdn ABI change add states and flags for external T200 handling isdn ABI change add states and flags for external T200 handling
gsm ABI change add T200 timer states to lapdm_datalink gsm ABI change add T200 timer states to lapdm_datalink

View File

@ -193,6 +193,10 @@ int osmo_sock_get_remote_ip_port(int fd, char *port, size_t len);
int osmo_sock_multiaddr_get_ip_and_port(int fd, int ip_proto, char *ip, size_t *ip_cnt, size_t ip_len, int osmo_sock_multiaddr_get_ip_and_port(int fd, int ip_proto, char *ip, size_t *ip_cnt, size_t ip_len,
char *port, size_t port_len, bool local); char *port, size_t port_len, bool local);
int osmo_multiaddr_ip_and_port_snprintf(char *str, size_t str_len,
const char *ip, size_t ip_cnt, size_t ip_len,
const char *portbuf);
int osmo_sock_multiaddr_get_name_buf(char *str, size_t str_len, int fd, int sk_proto);
int osmo_sock_multiaddr_add_local_addr(int sfd, const char **addrs, size_t addrs_cnt); int osmo_sock_multiaddr_add_local_addr(int sfd, const char **addrs, size_t addrs_cnt);
int osmo_sock_multiaddr_del_local_addr(int sfd, const char **addrs, size_t addrs_cnt); int osmo_sock_multiaddr_del_local_addr(int sfd, const char **addrs, size_t addrs_cnt);

View File

@ -298,6 +298,7 @@ osmo_luhn;
osmo_macaddr_parse; osmo_macaddr_parse;
osmo_mnl_destroy; osmo_mnl_destroy;
osmo_mnl_init; osmo_mnl_init;
osmo_multiaddr_ip_and_port_snprintf;
osmo_netdev_add_addr; osmo_netdev_add_addr;
osmo_netdev_add_route; osmo_netdev_add_route;
osmo_netdev_alloc; osmo_netdev_alloc;
@ -437,6 +438,7 @@ osmo_sock_mcast_ttl_set;
osmo_sock_multiaddr_add_local_addr; osmo_sock_multiaddr_add_local_addr;
osmo_sock_multiaddr_del_local_addr; osmo_sock_multiaddr_del_local_addr;
osmo_sock_multiaddr_get_ip_and_port; osmo_sock_multiaddr_get_ip_and_port;
osmo_sock_multiaddr_get_name_buf;
osmo_sock_set_dscp; osmo_sock_set_dscp;
osmo_sock_set_priority; osmo_sock_set_priority;
osmo_sock_unix_init; osmo_sock_unix_init;

View File

@ -2018,6 +2018,112 @@ char *osmo_sock_get_name(const void *ctx, int fd)
return talloc_asprintf(ctx, "(%s)", str); return talloc_asprintf(ctx, "(%s)", str);
} }
/*! Format multiple IP addresses and/or port number into a combined string buffer
* \param[out] str Destination string buffer.
* \param[in] str_len sizeof(str).
* \param[out] ip Pointer to memory holding ip_cnt consecutive buffers of size ip_len.
* \param[out] ip_cnt length ip array pointer. on return it contains the number of addresses found.
* \param[in] ip_len length of each of the string buffer in the the ip array.
* \param[out] port number (will be printed in when not NULL).
* \return String length as returned by snprintf(), or negative on error.
*
* This API expectes an ip array as the one filled in by
* osmo_sock_multiaddr_get_ip_and_port(), and hence it's a good companion for
* that API.
*/
int osmo_multiaddr_ip_and_port_snprintf(char *str, size_t str_len,
const char *ip, size_t ip_cnt, size_t ip_len,
const char *portbuf)
{
struct osmo_strbuf sb = { .buf = str, .len = str_len };
bool is_v6 = false;
unsigned int i;
if (ip_cnt == 0) {
OSMO_STRBUF_PRINTF(sb, "NULL:%s", portbuf);
return sb.chars_needed;
}
if (ip_cnt > 1)
OSMO_STRBUF_PRINTF(sb, "(");
else if ((is_v6 = !!strchr(&ip[0], ':'))) /* IPv6, add [] to separate from port. */
OSMO_STRBUF_PRINTF(sb, "[");
for (i = 0; i < ip_cnt - 1; i++)
OSMO_STRBUF_PRINTF(sb, "%s|", &ip[i * ip_len]);
OSMO_STRBUF_PRINTF(sb, "%s", &ip[i * ip_len]);
if (ip_cnt > 1)
OSMO_STRBUF_PRINTF(sb, ")");
else if (is_v6)
OSMO_STRBUF_PRINTF(sb, "]");
if (portbuf)
OSMO_STRBUF_PRINTF(sb, ":%s", portbuf);
return sb.chars_needed;
}
/*! Get address/port information on socket in provided string buffer, like "r=1.2.3.4:5<->l=6.7.8.9:10".
* This does not include braces like osmo_sock_get_name().
* \param[out] str Destination string buffer.
* \param[in] str_len sizeof(str).
* \param[in] fd File descriptor of socket.
* \param[in] fd IPPROTO of the socket, eg: IPPROTO_SCTP.
* \return String length as returned by snprintf(), or negative on error.
*/
int osmo_sock_multiaddr_get_name_buf(char *str, size_t str_len, int fd, int sk_proto)
{
char hostbuf[OSMO_SOCK_MAX_ADDRS][INET6_ADDRSTRLEN];
size_t num_hostbuf = ARRAY_SIZE(hostbuf);
char portbuf[6];
struct osmo_strbuf sb = { .buf = str, .len = str_len };
if (fd < 0) {
osmo_strlcpy(str, "<error-bad-fd>", str_len);
return sb.chars_needed;
}
switch (sk_proto) {
case IPPROTO_SCTP:
break; /* continue below */
default:
return osmo_sock_get_name_buf(str, str_len, fd);
}
/* get remote */
OSMO_STRBUF_PRINTF(sb, "r=");
if (osmo_sock_multiaddr_get_ip_and_port(fd, sk_proto, &hostbuf[0][0], &num_hostbuf,
sizeof(hostbuf[0]), portbuf, sizeof(portbuf), false) != 0) {
OSMO_STRBUF_PRINTF(sb, "NULL");
} else {
const bool need_more_bufs = num_hostbuf > ARRAY_SIZE(hostbuf);
if (need_more_bufs)
num_hostbuf = ARRAY_SIZE(hostbuf);
OSMO_STRBUF_APPEND(sb, osmo_multiaddr_ip_and_port_snprintf,
&hostbuf[0][0], num_hostbuf, sizeof(hostbuf[0]), portbuf);
if (need_more_bufs)
OSMO_STRBUF_PRINTF(sb, "<need-more-bufs!>");
}
OSMO_STRBUF_PRINTF(sb, "<->l=");
/* get local */
num_hostbuf = ARRAY_SIZE(hostbuf);
if (osmo_sock_multiaddr_get_ip_and_port(fd, sk_proto, &hostbuf[0][0], &num_hostbuf,
sizeof(hostbuf[0]), portbuf, sizeof(portbuf), true) != 0) {
OSMO_STRBUF_PRINTF(sb, "NULL");
} else {
const bool need_more_bufs = num_hostbuf > ARRAY_SIZE(hostbuf);
if (need_more_bufs)
num_hostbuf = ARRAY_SIZE(hostbuf);
OSMO_STRBUF_APPEND(sb, osmo_multiaddr_ip_and_port_snprintf,
&hostbuf[0][0], num_hostbuf, sizeof(hostbuf[0]), portbuf);
if (need_more_bufs)
OSMO_STRBUF_PRINTF(sb, "<need-more-bufs!>");
}
return sb.chars_needed;
}
/*! Get address/port information on socket in provided string buffer, like "r=1.2.3.4:5<->l=6.7.8.9:10". /*! Get address/port information on socket in provided string buffer, like "r=1.2.3.4:5<->l=6.7.8.9:10".
* This does not include braces like osmo_sock_get_name(). * This does not include braces like osmo_sock_get_name().
* \param[out] str Destination string buffer. * \param[out] str Destination string buffer.