pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/libosmocore/+/35276?usp=email )


Change subject: socket: Introduce API osmo_sock_sctp_get_peer_addr_info()
......................................................................

socket: Introduce API osmo_sock_sctp_get_peer_addr_info()

This is a convenience helper to reetrieve the whole set of remote
addresses and call getsockopt() on them, making it easy for users to
analyse the full set of remote addresses of a socket simply providing an
fd.

Related: SYS#6636
Change-Id: I3e1c84526b006baff435bbbca49dc6cf7d201cf5
---
M TODO-RELEASE
M include/osmocom/core/socket.h
M src/core/socket.c
3 files changed, 121 insertions(+), 0 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/76/35276/1

diff --git a/TODO-RELEASE b/TODO-RELEASE
index 316c0ec..9f5240f 100644
--- a/TODO-RELEASE
+++ b/TODO-RELEASE
@@ -9,6 +9,7 @@
 #library       what                    description / commit summary line
 core      ADD       osmo_sock_multiaddr_{add,del}_local_addr()
 core      ADD       osmo_sock_multiaddr_get_ip_and_port(), 
osmo_multiaddr_ip_and_port_snprintf(), osmo_sock_multiaddr_get_name_buf()
+core      ADD       osmo_sock_sctp_get_peer_addr_info()
 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
diff --git a/include/osmocom/core/socket.h b/include/osmocom/core/socket.h
index dd14556..cd9547a 100644
--- a/include/osmocom/core/socket.h
+++ b/include/osmocom/core/socket.h
@@ -211,5 +211,7 @@
 int osmo_sock_set_dscp(int fd, uint8_t dscp);
 int osmo_sock_set_priority(int fd, int prio);

+int osmo_sock_sctp_get_peer_addr_info(int fd, struct sctp_paddrinfo *pinfo, 
size_t *pinfo_cnt);
+
 #endif /* (!EMBEDDED) */
 /*! @} */
diff --git a/src/core/socket.c b/src/core/socket.c
index c600732..70b1885 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2653,6 +2653,109 @@
        return setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
 }

+/*! Get multiple IP addresses and/or port number on socket in separate string 
buffers
+ *  \param[in] fd file descriptor of socket.
+ *  \param[out] ip_proto IPPROTO of the socket, eg: IPPROTO_SCTP.
+ *  \param[out] ip Pointer to memory holding 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 filled in when not NULL).
+ *  \param[in] port_len length of the port buffer.
+ *  \param[in] local (true) or remote (false) name will get looked at.
+ *  \returns 0 on success; negative otherwise.
+ *
+ * Upon return, ip_cnt can be set to a higher value than the one set by the
+ * caller. This can be used by the caller to find out the required array length
+ * and then obtaining by calling the function twice. Only up to ip_cnt 
addresses
+ * are filed in, as per the value provided by the caller.
+ *
+ * Usage example retrieving all (up to OSMO_SOCK_MAX_ADDRS, 32) bound IP 
addresses and bound port:
+ * char hostbuf[OSMO_SOCK_MAX_ADDRS][INET6_ADDRSTRLEN];
+ * size_t num_hostbuf = ARRAY_SIZE(hostbuf);
+ * char portbuf[6];
+ * rc = osmo_sock_multiaddr_get_ip_and_port(fd, IPPROTO_SCTP, &hostbuf[0][0], 
&num_hostbuf,
+ *                                         sizeof(hostbuf[0]), portbuf, 
sizeof(portbuf), true);
+ * if (rc < 0)
+ *     goto error;
+ * if (num_hostbuf > ARRAY_SIZE(hostbuf))
+ *     goto not_enough_buffers;
+ */
+
+/*! Fill in array of struct sctp_paddrinfo with each of the remote addresses 
of an SCTP socket
+ *  \param[in] fd file descriptor of SCTP socket
+ *  \param[out] pinfo Pointer to memory holding an array of struct 
sctp_paddrinfo (pinfo_cnt length).
+ *  \param[out] pinfo_cnt length of pinfo array (in elements). On return it 
contains the number of addresses found.
+ *  \returns 0 on success; negative otherwise
+ *
+ * Upon return, pinfo_cnt can be set to a higher value than the one set by the
+ * caller. This can be used by the caller to find out the required array length
+ * and then obtaining by calling the function twice. Only up to pinfo_cnt 
addresses
+ * are filled in, as per the value provided by the caller.
+ *
+ * Usage example retrieving struct sctp_paddringo for all (up to 
OSMO_SOCK_MAX_ADDRS, 32) remote IP addresses:
+ * struct sctp_paddrinfo pinfo[OSMO_SOCK_MAX_ADDRS];
+ * size_t pinfo_cnt = ARRAY_SIZE(pinfo);
+ * rc = osmo_sock_sctp_get_peer_addr_info(fd, &pinfo[0], &num_hostbuf, 
pinfo_cnt);
+ * if (rc < 0)
+ *     goto error;
+ * if (pinfo_cnt > ARRAY_SIZE(hostbuf))
+ *     goto not_enough_buffers;
+ */
+int osmo_sock_sctp_get_peer_addr_info(int fd, struct sctp_paddrinfo *pinfo, 
size_t *pinfo_cnt)
+{
+       struct sockaddr *addrs = NULL;
+       unsigned int n_addrs, i;
+       void *addr_buf;
+       int rc;
+       socklen_t optlen;
+
+       rc = sctp_getpaddrs(fd, 0, &addrs);
+
+       if (rc < 0)
+               return rc;
+       if (rc == 0)
+               return -ENOTCONN;
+
+       n_addrs = rc;
+       addr_buf = (void *)addrs;
+       for (i = 0; i < n_addrs; i++) {
+               struct sockaddr *sa_addr = (struct sockaddr *)addr_buf;
+               size_t addrlen;
+
+               switch (sa_addr->sa_family) {
+               case AF_INET:
+                       addrlen = sizeof(struct sockaddr_in);
+                       break;
+               case AF_INET6:
+                       addrlen = sizeof(struct sockaddr_in6);
+                       break;
+               default:
+                       rc = -EINVAL;
+                       goto free_addrs_ret;
+               }
+
+               if (i >= *pinfo_cnt) {
+                       addr_buf += addrlen;
+                       continue;
+               }
+
+               memset(&pinfo[i], 0, sizeof(pinfo[0]));
+               memcpy(&pinfo[i].spinfo_address, sa_addr, addrlen);
+               optlen = sizeof(pinfo[0]);
+               rc = getsockopt(fd, SOL_SCTP, SCTP_GET_PEER_ADDR_INFO, 
&pinfo[i], &optlen);
+               if (rc < 0)
+                       goto free_addrs_ret;
+
+               addr_buf += addrlen;
+       }
+
+       *pinfo_cnt = n_addrs;
+       rc = 0;
+free_addrs_ret:
+       sctp_freepaddrs(addrs);
+       return rc;
+}
+
 #endif /* HAVE_SYS_SOCKET_H */

 /*! @} */

--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/35276?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: I3e1c84526b006baff435bbbca49dc6cf7d201cf5
Gerrit-Change-Number: 35276
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>
Gerrit-MessageType: newchange

Reply via email to