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.
#library what description / commit summary line
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()
isdn ABI change add states and flags for external T200 handling
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,
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_del_local_addr(int sfd, const char **addrs, size_t addrs_cnt);

View File

@ -298,6 +298,7 @@ osmo_luhn;
osmo_macaddr_parse;
osmo_mnl_destroy;
osmo_mnl_init;
osmo_multiaddr_ip_and_port_snprintf;
osmo_netdev_add_addr;
osmo_netdev_add_route;
osmo_netdev_alloc;
@ -437,6 +438,7 @@ osmo_sock_mcast_ttl_set;
osmo_sock_multiaddr_add_local_addr;
osmo_sock_multiaddr_del_local_addr;
osmo_sock_multiaddr_get_ip_and_port;
osmo_sock_multiaddr_get_name_buf;
osmo_sock_set_dscp;
osmo_sock_set_priority;
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);
}
/*! 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".
* This does not include braces like osmo_sock_get_name().
* \param[out] str Destination string buffer.