diff options
author | Olivier Crête <olivier.crete@collabora.com> | 2022-07-22 16:39:36 -0400 |
---|---|---|
committer | Olivier Crête <olivier.crete@collabora.com> | 2022-07-25 14:10:00 -0400 |
commit | a667957f7b23502da111dc2b314a6ad4120c590d (patch) | |
tree | dd382e0db731e57465581380ba79b427b26dde98 | |
parent | 15c8feae5516079aafec4134e823f7c927183fa5 (diff) | |
download | libnice-a667957f7b23502da111dc2b314a6ad4120c590d.tar.gz |
interfaces: Add API to find the interface index from a local address
This will find some interface that has the address and will not work
correctly if multiple interfaces have the same address. But in any
case, nothing in libnice expects that and we would need to break the
API to make that work.
-rw-r--r-- | agent/interfaces.c | 150 | ||||
-rw-r--r-- | agent/interfaces.h | 16 | ||||
-rw-r--r-- | docs/reference/libnice/libnice-sections.txt | 1 | ||||
-rw-r--r-- | nice/libnice.sym | 1 |
4 files changed, 168 insertions, 0 deletions
diff --git a/agent/interfaces.c b/agent/interfaces.c index 67f260c..4cd988c 100644 --- a/agent/interfaces.c +++ b/agent/interfaces.c @@ -370,6 +370,65 @@ get_local_ips_ioctl (gboolean include_loopback) return ips; } +static guint +get_local_if_index_by_addr_ioctl (NiceAddress *addr) +{ + gint sockfd; + gint size = 0; + struct ifreq *ifr; + struct ifconf ifc; + guint if_index = 0; + + if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) { + nice_debug ("error : Cannot open socket to retrieve interface list"); + return 0; + } + + ifc.ifc_len = 0; + ifc.ifc_req = NULL; + + /* Loop and get each interface the system has, one by one... */ + do { + size += sizeof (struct ifreq); + /* realloc buffer size until no overflow occurs */ + if (NULL == (ifc.ifc_req = realloc (ifc.ifc_req, size))) { + nice_debug ("Error : Out of memory while allocation interface" + "configuration structure"); + close (sockfd); + return 0; + } + ifc.ifc_len = size; + + if (ioctl (sockfd, SIOCGIFCONF, &ifc)) { + perror ("ioctl SIOCFIFCONF"); + close (sockfd); + free (ifc.ifc_req); + return 0; + } + } while (size <= ifc.ifc_len); + + + /* Loop throught the interface list and get the IP address of each IF */ + for (ifr = ifc.ifc_req; + (gchar *) ifr < (gchar *) ifc.ifc_req + ifc.ifc_len; + ++ifr) { + NiceAddress *myaddr = (NiceAddress *) &ifr->ifr_addr; + + if (!nice_address_equal_no_port (myaddr, addr)) + continue; + if (ifr->ifr_ifindex == 0) + continue; + + if_index = ifr->ifr_ifindex; + break; + } + + free (ifc.ifc_req); + close (sockfd); + + return if_index; +} + #ifdef HAVE_GETIFADDRS GList * @@ -498,6 +557,47 @@ nice_interfaces_get_local_ips (gboolean include_loopback) return ips; } +guint +nice_interfaces_get_if_index_by_addr (NiceAddress *addr) +{ + struct ifaddrs *ifa, *results; + guint if_index = 0; + + if (getifaddrs (&results) < 0) { + nice_debug ("Failed to retrieve list of network interfaces with \"getifaddrs\": %s." + "Trying to use fallback ...", strerror (errno)); + return get_local_if_index_by_addr_ioctl (addr); + } + + /* Loop through the interface list and get the IP address of each IF */ + for (ifa = results; ifa; ifa = ifa->ifa_next) { + NiceAddress *ifa_addr = (NiceAddress *) ifa->ifa_addr; + + /* no ip address from interface that is down */ + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + + /* no ip address from interface that isn't running */ + if ((ifa->ifa_flags & IFF_RUNNING) == 0) + continue; + + if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL) + continue; + + if (!nice_address_equal_no_port (ifa_addr, addr)) + continue; + + if_index = if_nametoindex (ifa->ifa_name); + + if (if_index != 0) + break; + } + + freeifaddrs (results); + + return if_index; +} + #else /* ! HAVE_GETIFADDRS */ GList * @@ -506,6 +606,13 @@ nice_interfaces_get_local_ips (gboolean include_loopback) return get_local_ips_ioctl (include_loopback); } + +guint +nice_interfaces_get_if_index_by_addr (NiceAddress *addr) +{ + return get_local_if_index_by_addr_ioctl (addr); +} + #endif /* HAVE_GETIFADDRS */ gchar * @@ -788,6 +895,49 @@ out: } +guint +nice_interfaces_get_if_index_by_addr (NiceAddress *addr) +{ + IP_ADAPTER_ADDRESSES *addresses, *a; + IP_ADAPTER_UNICAST_ADDRESS *unicast; + guint if_index = 0; + + addresses = _nice_get_adapters_addresses (); + if (!addresses) + return NULL; + + for (a = addresses; a != NULL; a = a->Next) { + /* Various conditions for ignoring the interface. */ + if (a->OperStatus == IfOperStatusDown || + a->OperStatus == IfOperStatusNotPresent || + a->OperStatus == IfOperStatusLowerLayerDown) { + continue; + } + + /* Grab the interface’s ipv4 unicast addresses. */ + for (unicast = a->FirstUnicastAddress; + unicast != NULL; unicast = unicast->Next) { + NiceAddress *uni_addr = (NiceAddress *) unicast->Address.lpSockaddr; + + if (nice_address_equal_no_port (uni_addr, addr)) { + if (unicast->Address.lpSockaddr->sa_family == AF_INET) + if_index = a->IfIndex; + else if (unicast->Address.lpSockaddr->sa_family == AF_INET6) + if_index = a->Ipv6IfIndex; + goto out; + } + } + } + +out: + g_free (addresses); + + return if_index; +} + + + + #else /* G_OS_WIN32 */ #error Can not use this method for retreiving ip list from OS other than unix or windows #endif /* G_OS_WIN32 */ diff --git a/agent/interfaces.h b/agent/interfaces.h index 50c627e..1bb3603 100644 --- a/agent/interfaces.h +++ b/agent/interfaces.h @@ -37,6 +37,7 @@ */ #include <glib.h> +#include <address.h> G_BEGIN_DECLS @@ -77,6 +78,21 @@ GList * nice_interfaces_get_local_ips (gboolean include_loopback); */ GList * nice_interfaces_get_local_interfaces (void); + +/** + * nice_interfaces_get_if_index_by_addr: + * @addr: A #NiceAddress for a local interface + * + * Returns the interface index match the local address passed. This can + * by used for APIs that need a specific address. + * + * Returns: The interface index or 0 on error + * + * Since: 0.1.20 + */ + +guint nice_interfaces_get_if_index_by_addr (NiceAddress *addr); + G_END_DECLS #endif /* __LIBNICE_INTERFACES_H__ */ diff --git a/docs/reference/libnice/libnice-sections.txt b/docs/reference/libnice/libnice-sections.txt index ad94a34..1ae06de 100644 --- a/docs/reference/libnice/libnice-sections.txt +++ b/docs/reference/libnice/libnice-sections.txt @@ -168,6 +168,7 @@ nice_debug_disable nice_interfaces_get_ip_for_interface nice_interfaces_get_local_interfaces nice_interfaces_get_local_ips +nice_interfaces_get_if_index_by_addr </SECTION> <SECTION> diff --git a/nice/libnice.sym b/nice/libnice.sym index e82cd0d..472c677 100644 --- a/nice/libnice.sym +++ b/nice/libnice.sym @@ -81,6 +81,7 @@ nice_component_state_to_string nice_component_type_get_type nice_debug_disable nice_debug_enable +nice_interfaces_get_if_index_by_addr nice_interfaces_get_ip_for_interface nice_interfaces_get_local_interfaces nice_interfaces_get_local_ips |