Update multiaddr helper

* use osmo_strbuf instead of plain buffer
* properly handle OOM
* fix missing trailing ')'

Related: OS#5581
Change-Id: Icef53fe4b6e51563d97a1bc48001d67679b3b6e9
This commit is contained in:
Max 2022-09-08 18:45:07 +07:00
parent e816ac673a
commit e2ac1a1b4c
1 changed files with 43 additions and 22 deletions

View File

@ -202,37 +202,57 @@ static int socket_helper_osa(const struct osmo_sockaddr *addr, uint16_t type, ui
}
#ifdef HAVE_LIBSCTP
/* Fill buf with a string representation of the address set, in the form:
/* Fill osmo_strbuf with a string representation of the address set, in the form:
* buf_len == 0: "()"
* buf_len == 1: "hostA"
* buf_len >= 2: (hostA|hostB|...|...)
*/
static int multiaddr_snprintf(char* buf, size_t buf_len, const char **hosts, size_t host_cnt)
static int multiaddr_strbuf(struct osmo_strbuf *sb,
const char **hosts, size_t host_count,
struct sockaddr **addrs, size_t addrs_count)
{
int len = 0, offset = 0, rem = buf_len;
size_t i;
int ret;
bool use_hosts = hosts ? true : false;
size_t i, count = use_hosts ? host_count : addrs_count;
struct osmo_sockaddr_str t;
struct osmo_sockaddr_str *oss = &t;
char *after;
int rc;
if (buf_len < 3)
return -EINVAL;
if (sb->len < 3)
return -ENOMEM;
if (host_cnt != 1) {
ret = snprintf(buf, rem, "(");
if (ret < 0)
return ret;
OSMO_SNPRINTF_RET(ret, rem, offset, len);
}
for (i = 0; i < host_cnt; i++) {
if (host_cnt == 1)
if (count != 1)
OSMO_STRBUF_PRINTF(*sb, "(");
for (i = 0; i < count; i++) {
const struct sockaddr *addr = &(*addrs)[i];
if (count == 1)
after = "";
else
after = (i == (host_cnt - 1)) ? ")" : "|";
ret = snprintf(buf + offset, rem, "%s%s", hosts[i] ? : "0.0.0.0", after);
OSMO_SNPRINTF_RET(ret, rem, offset, len);
after = (i == (count - 1)) ? ")" : "|";
if (use_hosts) {
if (hosts[i])
OSMO_STRBUF_PRINTF(*sb, "%s%s", hosts[i], after);
} else {
rc = osmo_sockaddr_str_from_sockaddr(oss, (const struct sockaddr_storage *)addr);
if (rc < 0) {
LOGP(DLGLOBAL, LOGL_DEBUG, "Conversion failure in multiaddr_strbuf(): %s\n", strerror(-rc));
return rc;
}
OSMO_STRBUF_PRINTF(*sb, OSMO_SOCKADDR_STR_NO_PORT_FMT "%s",
OSMO_SOCKADDR_STR_NO_PORT_FMT_ARGS(oss), after);
}
}
return len;
if (count == 0)
OSMO_STRBUF_PRINTF(*sb, ")");
if (sb->chars_needed >= sb->len)
return -ENOSPC;
return sb->chars_needed;
}
#endif /* HAVE_LIBSCTP */
@ -726,6 +746,7 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
bool loc_has_v6addr, rem_has_v6addr;
struct sockaddr_in6 addrs_buf[OSMO_SOCK_MAX_ADDRS];
char strbuf[512];
struct osmo_strbuf sb = { .buf = strbuf, .len = 512 };
/* updated later in case of AF_UNSPEC */
loc_has_v4addr = rem_has_v4addr = (family == AF_INET);
@ -794,7 +815,7 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR,
&on, sizeof(on));
if (rc < 0) {
multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt);
multiaddr_strbuf(&sb, local_hosts, local_hosts_cnt, NULL, 0);
LOGP(DLGLOBAL, LOGL_ERROR,
"cannot setsockopt socket:"
" %s:%u: %s\n",
@ -817,7 +838,7 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
rc = sctp_bindx(sfd, (struct sockaddr *)addrs_buf, local_hosts_cnt, SCTP_BINDX_ADD_ADDR);
if (rc == -1) {
multiaddr_snprintf(strbuf, sizeof(strbuf), local_hosts, local_hosts_cnt);
multiaddr_strbuf(&sb, local_hosts, local_hosts_cnt, NULL, 0);
LOGP(DLGLOBAL, LOGL_NOTICE, "unable to bind socket: %s:%u: %s\n",
strbuf, local_port, strerror(errno));
rc = -ENODEV;
@ -839,7 +860,7 @@ int osmo_sock_init2_multiaddr(uint16_t family, uint16_t type, uint8_t proto,
rc = sctp_connectx(sfd, (struct sockaddr *)addrs_buf, remote_hosts_cnt, NULL);
if (rc != 0 && errno != EINPROGRESS) {
multiaddr_snprintf(strbuf, sizeof(strbuf), remote_hosts, remote_hosts_cnt);
multiaddr_strbuf(&sb, remote_hosts, remote_hosts_cnt, NULL, 0);
LOGP(DLGLOBAL, LOGL_ERROR, "unable to connect socket: %s:%u: %s\n",
strbuf, remote_port, strerror(errno));
rc = -ENODEV;