summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Crête <olivier.crete@collabora.com>2022-07-22 16:39:36 -0400
committerOlivier Crête <olivier.crete@collabora.com>2022-07-25 14:10:00 -0400
commita667957f7b23502da111dc2b314a6ad4120c590d (patch)
treedd382e0db731e57465581380ba79b427b26dde98
parent15c8feae5516079aafec4134e823f7c927183fa5 (diff)
downloadlibnice-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.c150
-rw-r--r--agent/interfaces.h16
-rw-r--r--docs/reference/libnice/libnice-sections.txt1
-rw-r--r--nice/libnice.sym1
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