mirror of https://gerrit.osmocom.org/libosmocore
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
This commit is contained in:
parent
9c603e64bf
commit
19f27bb551
|
@ -9,6 +9,7 @@
|
||||||
#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(), osmo_multiaddr_ip_and_port_snprintf(), osmo_sock_multiaddr_get_name_buf()
|
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()
|
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
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
struct sockaddr_in;
|
struct sockaddr_in;
|
||||||
struct sockaddr;
|
struct sockaddr;
|
||||||
struct osmo_fd;
|
struct osmo_fd;
|
||||||
|
struct sctp_paddrinfo;
|
||||||
|
|
||||||
struct osmo_sockaddr {
|
struct osmo_sockaddr {
|
||||||
union {
|
union {
|
||||||
|
@ -211,5 +212,7 @@ int osmo_sock_local_ip(char *local_ip, const char *remote_ip);
|
||||||
int osmo_sock_set_dscp(int fd, uint8_t dscp);
|
int osmo_sock_set_dscp(int fd, uint8_t dscp);
|
||||||
int osmo_sock_set_priority(int fd, int prio);
|
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) */
|
#endif /* (!EMBEDDED) */
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
|
@ -439,6 +439,7 @@ 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_multiaddr_get_name_buf;
|
||||||
|
osmo_sock_sctp_get_peer_addr_info;
|
||||||
osmo_sock_set_dscp;
|
osmo_sock_set_dscp;
|
||||||
osmo_sock_set_priority;
|
osmo_sock_set_priority;
|
||||||
osmo_sock_unix_init;
|
osmo_sock_unix_init;
|
||||||
|
|
|
@ -2653,6 +2653,83 @@ int osmo_sock_set_priority(int fd, int prio)
|
||||||
return setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
|
return setsockopt(fd, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBSCTP
|
||||||
|
/*! 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[in,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_paddrinfo 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
|
||||||
|
|
||||||
#endif /* HAVE_SYS_SOCKET_H */
|
#endif /* HAVE_SYS_SOCKET_H */
|
||||||
|
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
Loading…
Reference in New Issue