diff options
-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 |