Module: sems
Branch: master
Commit: 1d82032c33b13ccce715826a0aa991aed2cbc36f
URL:    
http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=1d82032c33b13ccce715826a0aa991aed2cbc36f

Author: Raphael Coeffic <[email protected]>
Committer: Raphael Coeffic <[email protected]>
Date:   Thu Jan 26 09:54:38 2012 +0100

core: interfaces fetching overhaul.

---

 core/AmConfig.cpp |  158 +++++++++++++++++++++++++---------------------------
 core/AmConfig.h   |   15 ++++-
 2 files changed, 88 insertions(+), 85 deletions(-)

diff --git a/core/AmConfig.cpp b/core/AmConfig.cpp
index a6a6021..2294607 100644
--- a/core/AmConfig.cpp
+++ b/core/AmConfig.cpp
@@ -32,7 +32,9 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <netdb.h>
+#include <ifaddrs.h>
 #include <stdio.h>
+
 #include "AmConfig.h"
 #include "sems.h"
 #include "log.h"
@@ -57,7 +59,8 @@ bool         AmConfig::LogStderr               = false;
 
 vector<AmConfig::IP_interface>  AmConfig::Ifs;
 map<string,unsigned short>      AmConfig::If_names;
-multimap<string,unsigned short> AmConfig::LocalSIPIP2If;
+map<string,unsigned short>      AmConfig::LocalSIPIP2If;
+list<AmConfig::SysIntf>         AmConfig::SysIfs;
 
 #ifndef DISABLE_DAEMON_MODE
 bool         AmConfig::DaemonMode              = DEFAULT_DAEMON_MODE;
@@ -679,48 +682,62 @@ static int readInterfaces(AmConfigReader& cfg)
   return ret;
 }
 
-/** Get the list of network interfaces with the associated PF_INET addresses */
-static bool getInterfaceList(int sd, std::vector<std::pair<string,string> >& 
if_list)
+/** Get the list of network interfaces with the associated addresses & flags */
+static bool fillSysIntfList()
 {
-  struct ifconf ifc;
-  struct ifreq ifrs[MAX_NET_DEVICES];
-
-  ifc.ifc_len = sizeof(struct ifreq) * MAX_NET_DEVICES;
-  ifc.ifc_req = ifrs;
-  memset(ifrs, 0, ifc.ifc_len);
-
-  if(ioctl(sd, SIOCGIFCONF, &ifc)!=0){
-    ERROR("getInterfaceList: ioctl: %s.\n", strerror(errno));
+  struct ifaddrs *ifap = NULL;
+  
+  if(getifaddrs(&ifap) < 0){
+    ERROR("getifaddrs() failed: %s",strerror(errno));
     return false;
   }
 
-#if !defined(BSD44SOCKETS)
-  int n_dev = ifc.ifc_len / sizeof(struct ifreq);
-  for(int i=0; i<n_dev; i++){
-    if(ifrs[i].ifr_addr.sa_family==PF_INET){
-      struct sockaddr_in* sa = (struct sockaddr_in*)&ifrs[i].ifr_addr;
+  char host[NI_MAXHOST];
+  for(struct ifaddrs *p_if = ifap; p_if != NULL; p_if = p_if->ifa_next) {
 
-      // avoid dereferencing type-punned pointer below
-      struct sockaddr_in sa4;
-      memcpy(&sa4, sa, sizeof(struct sockaddr_in));
-      if_list.push_back(make_pair((char*)ifrs[i].ifr_name,
-                                  inet_ntoa(sa4.sin_addr)));
+    if(p_if->ifa_addr == NULL)
+      continue;
+    
+    if( (p_if->ifa_addr->sa_family != AF_INET) //&&
+        //(p_if->ifa_addr->sa_family != AF_INET6) 
+       )
+      continue;
+
+    if( !(p_if->ifa_flags & IFF_UP) || !(p_if->ifa_flags & IFF_RUNNING) )
+      continue;
+
+    int s = getnameinfo(p_if->ifa_addr,
+                       (p_if->ifa_addr->sa_family == AF_INET) ? 
+                       sizeof(struct sockaddr_in) : sizeof(struct 
sockaddr_in6),
+                       host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
+    if (s != 0) {
+      ERROR("getnameinfo() failed: %s\n", gai_strerror(s));
+      freeifaddrs(ifap);
+      return false;
     }
-  }
-#else // defined(BSD44SOCKETS)
-  struct ifreq* p_ifr = ifc.ifc_req;
-  while((char*)p_ifr - (char*)ifc.ifc_req < ifc.ifc_len){
 
-    if(p_ifr->ifr_addr.sa_family == PF_INET){
-      struct sockaddr_in* sa = (struct sockaddr_in*)&p_ifr->ifr_addr;
-      if_list.push_back(make_pair((const char*)p_ifr->ifr_name,
-                                  inet_ntoa(sa->sin_addr)));
+    DBG("iface='%s';ip='%s'\n",p_if->ifa_name,host);
+
+    string iface_name(p_if->ifa_name);
+    list<AmConfig::SysIntf>::iterator intf_it;
+    for(intf_it = AmConfig::SysIfs.begin();
+       intf_it != AmConfig::SysIfs.end(); ++intf_it) {
+
+      if(intf_it->name == iface_name)
+       break;
+    }
+
+    if(intf_it == AmConfig::SysIfs.end()){
+      intf_it = AmConfig::SysIfs.insert(AmConfig::SysIfs.end(),
+                                       AmConfig::SysIntf());
+      intf_it->name  = iface_name;
+      intf_it->flags = p_if->ifa_flags;
     }
 
-    p_ifr = (struct ifreq*)(((char*)p_ifr) + IFNAMSIZ + 
p_ifr->ifr_addr.sa_len);
+    intf_it->addrs.push_back(host);
   }
-#endif
 
+  freeifaddrs(ifap);
   return true;
 }
 
@@ -728,8 +745,6 @@ static bool getInterfaceList(int sd, 
std::vector<std::pair<string,string> >& if_
 string fixIface2IP(const string& dev_name)
 {
   string local_ip;
-  struct ifreq ifr;
-  std::vector<std::pair<string,string> > if_list;
 
 #ifdef SUPPORT_IPV6
   struct sockaddr_storage ss;
@@ -742,61 +757,30 @@ string fixIface2IP(const string& dev_name)
       return dev_name;
     }
 
-  int sd = socket(PF_INET, SOCK_DGRAM, 0);
-  if(sd == -1){
-    ERROR("socket: %s.\n", strerror(errno));
-    goto error;
-  }
+  for(list<AmConfig::SysIntf>::iterator intf_it = AmConfig::SysIfs.begin();
+      intf_it != AmConfig::SysIfs.end(); ++intf_it) {
+      
+    if((!dev_name.empty() && (intf_it->name == dev_name))
+       || !(intf_it->flags & IFF_LOOPBACK)) {
 
-  if(dev_name.empty()) {
-    if (!getInterfaceList(sd, if_list)) {
-      goto error;
-    }
-  }
-  else {
-    memset(&ifr, 0, sizeof(struct ifreq));
-    strncpy(ifr.ifr_name, dev_name.c_str(), IFNAMSIZ-1);
-
-    if(ioctl(sd, SIOCGIFADDR, &ifr)!=0){
-      ERROR("ioctl(SIOCGIFADDR): %s.\n", strerror(errno));
-      goto error;
-    }
-
-    if(ifr.ifr_addr.sa_family==PF_INET){
-      struct sockaddr_in* sa = (struct sockaddr_in*)&ifr.ifr_addr;
-
-      // avoid dereferencing type-punned pointer below
-      struct sockaddr_in sa4;
-      memcpy(&sa4, sa, sizeof(struct sockaddr_in));
-      if_list.push_back(make_pair((char*)ifr.ifr_name,
-                                 inet_ntoa(sa4.sin_addr)));
-    }
-  }
-
-  for( std::vector<std::pair<string,string> >::iterator it = if_list.begin();
-       it != if_list.end(); ++it) {
-    memset(&ifr, 0, sizeof(struct ifreq));
-    strncpy(ifr.ifr_name, it->first.c_str(), IFNAMSIZ-1);
-
-    if(ioctl(sd, SIOCGIFFLAGS, &ifr)!=0){
-      ERROR("ioctl(SIOCGIFFLAGS): %s.\n", strerror(errno));
-      goto error;
-    }
-
-    if( (ifr.ifr_flags & IFF_UP) &&
-        (!dev_name.empty() || !(ifr.ifr_flags & IFF_LOOPBACK)) ) {
-      local_ip = it->second;
+      if(intf_it->addrs.empty()){
+       ERROR("No IP address for interface '%s'\n",intf_it->name.c_str());
+       return "";
+      }
+      
+      DBG("dev_name = '%s'\n",dev_name.c_str());
+      local_ip = intf_it->addrs.front();
       break;
     }
-  }
+  }    
 
- error:
-  close(sd);
   return local_ip;
 }
 
 int AmConfig::finalizeIPConfig()
 {
+  fillSysIntfList();
+
   for(int i=0; i < (int)AmConfig::Ifs.size(); i++) {
 
     AmConfig::Ifs[i].LocalIP = fixIface2IP(AmConfig::Ifs[i].LocalIP);
@@ -813,7 +797,17 @@ int AmConfig::finalizeIPConfig()
       AmConfig::Ifs[i].LocalSIPIP = fixIface2IP(AmConfig::Ifs[i].LocalSIPIP);
     }
     
-    
AmConfig::LocalSIPIP2If.insert(std::make_pair(AmConfig::Ifs[i].LocalSIPIP,i));
+    if(AmConfig::LocalSIPIP2If.find(AmConfig::Ifs[i].LocalSIPIP) == 
AmConfig::LocalSIPIP2If.end()) {
+      
AmConfig::LocalSIPIP2If.insert(std::make_pair(AmConfig::Ifs[i].LocalSIPIP,i));
+    }
+    else {
+      map<string,unsigned short>::iterator it = 
AmConfig::LocalSIPIP2If.find(AmConfig::Ifs[i].LocalSIPIP);
+      const AmConfig::IP_interface& new_intf = AmConfig::Ifs[i];
+      const AmConfig::IP_interface& old_intf = AmConfig::Ifs[it->second];
+      ERROR("Configuration for interface '%s' uses the same IP address as 
'%s'\n",
+           new_intf.name.empty() ? "default" : new_intf.name.c_str(),
+           old_intf.name.empty() ? "default" : old_intf.name.c_str() );
+    }
   }
 
   return 0;
@@ -835,7 +829,7 @@ void AmConfig::dump_Ifs()
   }
   
   INFO("Signaling address map:");
-  for(multimap<string,unsigned short>::iterator it = LocalSIPIP2If.begin();
+  for(map<string,unsigned short>::iterator it = LocalSIPIP2If.begin();
       it != LocalSIPIP2If.end(); ++it) {
 
     if(Ifs[it->second].name.empty()){
diff --git a/core/AmConfig.h b/core/AmConfig.h
index eba9e77..1ad9bfc 100644
--- a/core/AmConfig.h
+++ b/core/AmConfig.h
@@ -108,9 +108,18 @@ struct AmConfig
     AmMutex next_rtp_port_mut;
   };
 
-  static vector<IP_interface>            Ifs;
-  static map<string,unsigned short>      If_names;
-  static multimap<string,unsigned short> LocalSIPIP2If;
+  static vector<IP_interface>       Ifs;
+  static map<string,unsigned short> If_names;
+  static map<string,unsigned short> LocalSIPIP2If;
+
+  struct SysIntf {
+    string       name;
+    list<string> addrs;
+    // identical to those returned by SIOCGIFFLAGS
+    unsigned int flags;
+  };
+
+  static list<SysIntf> SysIfs;
 
   static int finalizeIPConfig();
 

_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to