diff options
Diffstat (limited to 'agent/interfaces.c')
-rw-r--r-- | agent/interfaces.c | 150 |
1 files changed, 150 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 */ |