From e2ac1a1b4c0f2b2674bf69a1ef0ee94dd4c404b0 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 8 Sep 2022 18:45:07 +0700 Subject: [PATCH] Update multiaddr helper * use osmo_strbuf instead of plain buffer * properly handle OOM * fix missing trailing ')' Related: OS#5581 Change-Id: Icef53fe4b6e51563d97a1bc48001d67679b3b6e9 --- src/socket.c | 65 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/socket.c b/src/socket.c index 4605db4c0..77d0901a6 100644 --- a/src/socket.c +++ b/src/socket.c @@ -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;