Free Web Hosting Provider - Web Hosting - E-commerce - High Speed Internet - Free Web Page
Search the Web


#include "netif.h"


// --- Floyd Davidson's macro  ---
#define inaddrr(x) (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
#define IFRSIZE   ((int)(size * sizeof (struct ifreq)))
// -------------------------------


// ---------------------------------------------
// ---------------------------------------------
uint NetInterface::request_counter_s (0);

// ---------------------------------------------
// ---------------------------------------------
NetInterface::NetInterface ()
   :
   interface_name_max_len_(0),
   property_name_max_len_ (0)
{
  set_property_names_ ();
  floyd_davidson_get_net_interfaces_ ();
}


// ---------------------------------------------
void NetInterface::set_property_names_ ()
{
  // ---------------------------------------------------
  property_names_.push_back (IP_ADDRESS_NAME);
  property_names_.push_back (HW_ADDRESS_NAME);
  property_names_.push_back (NETMASK_NAME);
  property_names_.push_back (BROADCAST_NAME);
  property_names_.push_back (MTU_NAME);
  property_names_.push_back (METRIC_NAME);

  // ---------------------------------------------------
  assert (property_name_max_len_ == 0);
  for (unsigned int i = 0; i < property_names_.size(); i++)
  {
    property_name_max_len_ = MAX_VALUE(property_name_max_len_, property_names_[i].size());
  }
}


// ---------------------------------------------
string NetInterface::return_property_name_(const string& property_name_i) const
{
  assert (!(find (property_names_.begin(), property_names_.end(), property_name_i) == property_names_.end()));
  return property_name_i;
}



// ---------------------------------------------
string NetInterface::get_net_interface (const string& interface_name_i, const string& property_name_i) const
{
  if (net_interfaces_.count (interface_name_i) == 0)     return string();
  if (net_interfaces_.find(interface_name_i)->second.count(property_name_i) == 0)   return string();

  assert (net_interfaces_.count(interface_name_i) == 1);
  assert (net_interfaces_.find(interface_name_i)->second.count(property_name_i) == 1);

  return net_interfaces_.find(interface_name_i)->second.find(property_name_i)->second;
}


// ---------------------------------------------
void NetInterface::show_net_interface (const string& interface_name_i, const string& property_name_i) const
{
  request_counter_s++;

  cout << endl;
  cout << endl;
  cout.setf (ios::right, ios::adjustfield);
  cout   << "  ###### Request#"
   << setw (2)
   << setfill ('0')
   << request_counter_s
   << setfill (' ')
   << " ::: "
   << (interface_name_i.empty() ? "All Interfaces" :  interface_name_i)
   << " -> "
   << (property_name_i.empty() ? "All Properties" :  property_name_i)
   << " ######"
   << endl;
  cout.setf (ios::left, ios::adjustfield);

vector<string> interface_vect;
vector<string> property_vect;
bool     flag = false;

  if (interface_name_i.empty())
  {
    interface_vect = vector<string> (interface_names_);
  }
  else
  {
    interface_vect.push_back (interface_name_i);
  }

  if (property_name_i.empty())
  {
    property_vect = vector<string> (property_names_);
  }
  else
  {
    flag = true;
    property_vect.push_back (property_name_i);
  }

  show_net_interface_ (interface_vect, property_vect, flag);

}

// ---------------------------------------------
void NetInterface::show_net_interface_ (const string& interface_name_i, const string& property_name_i, bool flag_i) const
{
  assert (!interface_name_i.empty());
  assert (!property_name_i.empty());

  if (net_interfaces_.count (interface_name_i) == 0)
  {
    cout << "Interface - " << setw (interface_name_max_len_) << interface_name_i.c_str()  << " : " << "Invalid Interface Name" << endl;
    return;
  }

  if (find (property_names_.begin(), property_names_.end(), property_name_i) == property_names_.end())
  {
    cout << "Property  - " << setw (property_name_max_len_) << property_name_i.c_str()  << " : " << "Invalid Property Name" << endl;
    return;
  }



string   if_property_value = get_net_interface(interface_name_i, property_name_i);

  if (flag_i)  cout << setw (interface_name_max_len_) << interface_name_i.c_str() << " ---> ";
  cout << setw (property_name_max_len_) << property_name_i.c_str() << " : ";
  cout << (if_property_value.empty() ? "<Missing>" : if_property_value) << endl;
}

// ---------------------------------------------
void NetInterface::show_net_interface_ (const vector<string>& interface_names_i, const vector<string>& property_names_i, bool flag_i) const
{

  cout.setf (ios::left, ios::adjustfield);
  for (unsigned int i = 0; i < interface_names_i.size(); i++)
  {
    if (!flag_i)
    {
      if (i)   cout << endl;
      cout << "   ------ Interface  ::: " << interface_names_i [i] << " ------" << endl;
    }
    for (unsigned j = 0; j < property_names_i.size(); j++)
    {
      show_net_interface_ (interface_names_i[i], property_names_i[j], flag_i);
    } // for (j = 0; j < property_names_i.size(); j++)
  } // for (int i = 0; i < interface_names_i.size(); i++)

}



// ---------------------------------------------
// - - - - - - - - - - - - - - - - - - - - - - -
// ### From: Floyd Davidson <floyd@ptialaska.net>
// ### Newsgroups: comp.unix.programmer
// ### Subject: Re: netdb: getaddrinfo()/getnameinfo()
// ### Date: 27 Aug 2002 14:17:56 -0800
// The Floyd Davidson's article contains function
// that enables to get info about network interfaces
// - - - - - - - - - - - - - - - - - - - - - - -
// Function floyd_davidson_get_net_interfaces_() below
// is the Floyd Davidson's function with minimal changes
// related to C++-wrapping
// ---------------------------------------------
bool NetInterface::floyd_davidson_get_net_interfaces_ ()
{
int      sockfd;
int      size = 1;
ifreq*      ifr;
ifconf      ifc;
sockaddr_in sa;
string      cur_interface_name;

  errno = 0;
  sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  if(sockfd ==-1)
  {
    CERR << "Cannot open socket : " << strerror(errno) << endl;
    return false;
  }


  ifc.ifc_len = IFRSIZE;
  ifc.ifc_req = NULL;

  do
  {
    ++size;
    // --- realloc buffer size until no overflow occurs ---

    errno = 0;
    ifc.ifc_req = static_cast<ifreq*>(realloc(ifc.ifc_req, IFRSIZE));
    if (ifc.ifc_req == NULL)
    {
       CERR << "Out of memory : " << strerror(errno) << endl;
       return false;
    }

    ifc.ifc_len = IFRSIZE;
    errno = 0;
    if (ioctl(sockfd, SIOCGIFCONF, &ifc))
    {
      CERR << "Error ioctl SIOCFIFCONF : " << strerror(errno) << endl;
      return false;
    }
  } while  (IFRSIZE <= ifc.ifc_len);


  ifr = ifc.ifc_req;
  for(; (ifr - ifc.ifc_req) * sizeof(ifreq) < static_cast<ulong>(ifc.ifc_len); ++ifr)
  {
    if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) continue;  // duplicate, skip it

    if (ioctl(sockfd, SIOCGIFFLAGS, ifr))       continue;  // failed to get flags, skip it

    cur_interface_name = to_string (ifr->ifr_name);
    assert (find (interface_names_.begin(), interface_names_.end(), cur_interface_name) == interface_names_.end());
    interface_names_.push_back (cur_interface_name);

    assert (net_interfaces_.count (cur_interface_name) == 0);
    net_interfaces_[cur_interface_name] = map<string, string> ();
    assert (net_interfaces_.count (cur_interface_name) == 1);

    // ------ get IP_ADDRESS ------
    assert (net_interfaces_[cur_interface_name].count (IP_ADDRESS_NAME) == 0);
    net_interfaces_[cur_interface_name] [return_property_name_ (IP_ADDRESS_NAME)] = to_string(inet_ntoa(inaddrr(ifr_addr.sa_data)));
    assert (net_interfaces_[cur_interface_name].count (IP_ADDRESS_NAME) == 1);

    // ------ get HW_ADDRESS ------
    if (ioctl(sockfd, SIOCGIFHWADDR, ifr) == 0)
    {

      // --- Select which  hardware types to process. ---
      assert (ifr->ifr_hwaddr.sa_family < AF_MAX);

      vector<uchar>  v;
      uint     sum = 0;
      assert (MAC_ADDRESS_CHAR_LEN <= (sizeof (ifr->ifr_addr.sa_data)/sizeof(char)));
      for (int i = 0; i < MAC_ADDRESS_CHAR_LEN; i++)
      {
        v.push_back(ifr->ifr_addr.sa_data[i]);
        sum += static_cast<uint>(v[i]);
      }

      if(sum)
      {
        ostringstream osstr;
        for (unsigned int i = 0; i < v.size(); i++)
        {
          if (i)  osstr << "-";
          osstr << hex << setw(2) << setfill ('0') << static_cast<uint>(v[i]) << dec;
        }
        assert (net_interfaces_[cur_interface_name].count (HW_ADDRESS_NAME) == 0);
        net_interfaces_[cur_interface_name] [return_property_name_ (HW_ADDRESS_NAME)] = to_string(osstr.str());
        assert (net_interfaces_[cur_interface_name].count (HW_ADDRESS_NAME) == 1);
      }
    }

    // ------ get NETMASK ------
    if (
         (ioctl(sockfd, SIOCGIFNETMASK, ifr) == 0)
         &&
         strcmp("255.255.255.255", inet_ntoa(inaddrr(ifr_addr.sa_data)))
       )
    {
      assert (net_interfaces_[cur_interface_name].count (NETMASK_NAME) == 0);
      net_interfaces_[cur_interface_name] [return_property_name_ (NETMASK_NAME)] = to_string(inet_ntoa(inaddrr(ifr_addr.sa_data)));
      assert (net_interfaces_[cur_interface_name].count (NETMASK_NAME) == 1);
    }

    // ------ get BROADCAST ------
    if (ifr->ifr_flags & IFF_BROADCAST)
    {
      if (
           (ioctl(sockfd, SIOCGIFBRDADDR, ifr) == 0)
           &&
           strcmp("0.0.0.0", inet_ntoa(inaddrr(ifr_addr.sa_data)))
         )
      {
        assert (net_interfaces_[cur_interface_name].count (BROADCAST_NAME) == 0);
        net_interfaces_[cur_interface_name] [return_property_name_ (BROADCAST_NAME)] = to_string(inet_ntoa(inaddrr(ifr_addr.sa_data)));
        assert (net_interfaces_[cur_interface_name].count (BROADCAST_NAME) == 1);
      }
    }

    // ------ get MTU ------
    if (ioctl(sockfd, SIOCGIFMTU, ifr) == 0)
    {
      assert (net_interfaces_[cur_interface_name].count (MTU_NAME) == 0);
      net_interfaces_[cur_interface_name] [return_property_name_ (MTU_NAME)] = to_string(ifr->ifr_mtu);
      assert (net_interfaces_[cur_interface_name].count (MTU_NAME) == 1);
    }

    // ------ get METRIC ------
    if (ioctl(sockfd, SIOCGIFMETRIC, ifr) == 0)
    {
      assert (net_interfaces_[cur_interface_name].count (METRIC_NAME) == 0);
      net_interfaces_[cur_interface_name] [return_property_name_ (METRIC_NAME)] = to_string(ifr->ifr_metric);
      assert (net_interfaces_[cur_interface_name].count (METRIC_NAME) == 1);
    }

    // --------------------------------------
    assert (net_interfaces_[cur_interface_name].size() <= property_names_.size());
  } // for(; (ifr - ifc.ifc_req) * sizeof(ifreq) < static_cast<ulong>(ifc.ifc_len); ++ifr)

  //-------------------------------
  assert (interface_name_max_len_ == 0);
  for (unsigned int i = 0; i < interface_names_.size(); i++)
  {
    interface_name_max_len_ = MAX_VALUE(interface_name_max_len_, interface_names_[i].size());
  }


int ret_code = close(sockfd);
  assert (ret_code == 0);
  return true;
} // get_net_interfaces_