Logo Search packages:      
Sourcecode: farsight version File versions  Download package

farsight-interfaces.c

/*
 * farsight-interfaces.c - Source for interface discovery code
 *
 * Farsight Helper functions
 * Copyright (C) 2006 Youness Alaoui <kakaroto@kakaroto.homelinux.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "farsight-interfaces.h"

#ifdef G_OS_UNIX 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#if defined(__APPLE__) && defined(__MACH__)
#include <sys/socket.h>
#endif
#include <net/if.h>
#include <net/if_arp.h>
#include <arpa/inet.h>

/**
 * farsight_get_local_interfaces:
 *
 * Get the list of local interfaces
 *
 * Returns: a #GList of strings.
 */
GList * farsight_get_local_interfaces() {
  gint sockfd;
  gint size = 0;
  struct ifreq *ifr;
  struct ifconf ifc;
  GList *interfaces = NULL;

  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
    g_warning("Cannot open socket to retreive interface list");
    return NULL;
  }

  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))) {
      g_warning ("Out of memory while allocation interface configuration structure");
      close(sockfd);
      return NULL;
    }
    ifc.ifc_len = size;

    if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
      perror("ioctl SIOCFIFCONF");
      close(sockfd);
      return NULL;
    }
  } 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) {
    g_debug("Found interface : %s", ifr->ifr_name);
    interfaces = g_list_prepend(interfaces, g_strdup(ifr->ifr_name));
  }

  close(sockfd);

  return interfaces;
}


static gboolean farsight_is_private_ip (const struct in_addr in)
{
  if (in.s_addr >> 24 == 0x0A) /* 10.x.x.x/8 */
    return TRUE;

  if (in.s_addr >> 22 == 0x2B0) /* 172.16.0.0 - 172.31.255.255  = 172.16.0.0/10 */
    return TRUE;

  if (in.s_addr >> 16 == 0xc0A8) /* 192.168.x.x/16 */
    return TRUE;

  if (in.s_addr >> 16 == 0xA9FE) /* 169.254.x.x/16  (for APIPA) */
    return TRUE;


  return FALSE;
}

/**
 * farsight_get_local_ips:
 * @include_loopback: Include any loopback devices
 *
 * Get a list of local ip4 interface addresses
 *
 * Returns: A #GList of strings
 */
GList * farsight_get_local_ips(gboolean include_loopback)
{
  gint sockfd;
  gint size = 0;
  struct ifreq *ifr;
  struct ifconf ifc;
  struct sockaddr_in *sa;
  GList *ips = NULL;

  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
    g_warning("Cannot open socket to retreive interface list");
    return NULL;
  }

  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))) {
      g_warning ("Out of memory while allocation interface configuration structure");
      close(sockfd);
      return NULL;
    }
    ifc.ifc_len = size;

    if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
      perror("ioctl SIOCFIFCONF");
      close(sockfd);
      return NULL;
    }
  } 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) {

    if (ioctl(sockfd, SIOCGIFFLAGS, ifr)) {
      g_warning("Unable to get IP information for interface %s. Skipping...", ifr->ifr_name);
      continue;  /* failed to get flags, skip it */
    }
    sa = (struct sockaddr_in *) &ifr->ifr_addr;
    g_debug("Interface:  %s", ifr->ifr_name);
    g_debug("IP Address: %s", inet_ntoa(sa->sin_addr));
    if ( !include_loopback && (ifr->ifr_flags & IFF_LOOPBACK) == IFF_LOOPBACK) {
      g_debug("Ignoring loopback interface");
    } else {
      if (farsight_is_private_ip (sa->sin_addr)) {
        ips = g_list_append(ips, g_strdup(inet_ntoa(sa->sin_addr)));
      } else {
        ips = g_list_prepend(ips, g_strdup(inet_ntoa(sa->sin_addr)));
      }
    }
  }

  close(sockfd);

  return ips;
}

/**
 * farsight_get_ip_for_interface:
 * @interface_name: name of local interface
 *
 * Retreives the IP Address of an interface by its name
 *
 * Returns:
 **/
gchar * farsight_get_ip_for_interface(gchar *interface_name) {
  struct ifreq ifr;
  struct sockaddr_in *sa;
  gint sockfd;


  ifr.ifr_addr.sa_family = AF_INET;
  memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name));
  strcpy(ifr.ifr_name, interface_name);

  if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
    g_warning("Cannot open socket to retreive interface list");
    return NULL;
  }

  if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
    g_warning("Unable to get IP information for interface %s",interface_name );
    close(sockfd);
    return NULL;
  }

  close(sockfd);
  sa = (struct sockaddr_in *) &ifr.ifr_addr;
  g_debug("Address for %s: %s", interface_name, inet_ntoa(sa->sin_addr));
  return inet_ntoa(sa->sin_addr);
  
}

#else /* G_OS_UNIX */
#ifdef G_OS_WIN32

#include <windows.h>
#include <winsock.h>

static gboolean started_wsa_engine = FALSE;

/**
 * private function that initializes the WinSock engine and returns a prebuilt socket
 **/
SOCKET farsight_get_WSA_socket() {

  WORD wVersionRequested;
  WSADATA wsaData;
  int err;
  SOCKET sock;
  
  if (started_wsa_engine == FALSE) { 
    wVersionRequested = MAKEWORD( 2, 0 );
    
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
      g_warning("Could not start the winsocket engine");
      return INVALID_SOCKET;
    }
    started_wsa_engine = TRUE;
  }


  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
    g_warning("Could not open socket to retreive interface list, error no : %d", WSAGetLastError());
    return INVALID_SOCKET;
  }
  
  return sock;
}

/**
 * Returns the list of local interfaces
 **/
GList * farsight_get_local_interfaces() 
{
  return NULL;
}


/**
 * Returns the list of local ips
 **/
GList * farsight_get_local_ips()
{
  return NULL;
}

/**
 * retreives the IP Address of an interface by its name
 **/
gchar * farsight_get_ip_for_interface(gchar *interface_name) 
{
  return NULL;

}


#else /* G_OS_WIN32 */
#error Can\'t use this method for retreiving ip list from OS other than unix or windows
#endif /* G_OS_WIN32 */
#endif /* G_OS_UNIX */

Generated by  Doxygen 1.6.0   Back to index