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

Author: Raphael Coeffic <[email protected]>
Committer: Raphael Coeffic <[email protected]>
Date:   Sun Feb 13 15:20:08 2011 +0100

functions to detect the local IP to use

the mechanism used is very simple:
 - create a temporary UDP socket
 - connect it to the remote destination
 - use getsockname to read the local IP

---

 core/AmUtils.cpp |   79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 core/AmUtils.h   |   14 +++++++++
 2 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/core/AmUtils.cpp b/core/AmUtils.cpp
index 8a77377..94e6b69 100644
--- a/core/AmUtils.cpp
+++ b/core/AmUtils.cpp
@@ -847,6 +847,85 @@ int write_to_socket(int sd, const char* to_addr, const 
char * buf, unsigned int
   return ret;
 }
 
+int get_local_addr_for_dest(sockaddr_storage* remote_ip, sockaddr_storage* 
local)
+{
+  int temp_sock = socket(remote_ip->ss_family, SOCK_DGRAM, 0 );
+  if (temp_sock == -1) {
+    ERROR("socket() failed: %s\n",
+         strerror(errno));
+    return -1;
+  }
+
+  socklen_t len=sizeof(sockaddr_storage);
+  if (connect(temp_sock, (sockaddr*)remote_ip, 
+             remote_ip->ss_family == AF_INET ? 
+             sizeof(sockaddr_in) : sizeof(sockaddr_in6))==-1) {
+
+      ERROR("connect failed: %s\n",
+           strerror(errno));
+      goto error;
+  }
+
+  if (getsockname(temp_sock, (sockaddr*)local, &len)==-1) {
+      ERROR("getsockname failed: %s\n",
+           strerror(errno));
+      goto error;
+  }
+
+  close(temp_sock);
+  return 0;
+
+ error:
+  close(temp_sock);
+  return -1;
+}
+
+int get_local_addr_for_dest(const string& remote_ip, string& local)
+{
+  sockaddr_storage remote_ip_ss;
+  sockaddr_storage local_ss;
+
+  int err = 
inet_pton(AF_INET,remote_ip.c_str(),&((sockaddr_in*)&remote_ip_ss)->sin_addr);
+  if(err == 1){
+    remote_ip_ss.ss_family = AF_INET;
+  }
+  else if(err == 0){
+    err = 
inet_pton(AF_INET6,remote_ip.c_str(),&((sockaddr_in6*)&remote_ip_ss)->sin6_addr);
+    if(err == 1){
+      remote_ip_ss.ss_family = AF_INET6;
+    }
+  }
+
+  if(err == 0){
+    ERROR("Wrong address format: '%s'",remote_ip.c_str());
+    return -1;
+  }
+  else if(err == -1){
+    ERROR("While converting address: %s",strerror(errno));
+    return -1;
+  }
+
+  err = get_local_addr_for_dest(&remote_ip_ss, &local_ss);
+  if(err < 0){
+    return -1;
+  }
+
+  return ip_addr_to_str(&local_ss,local);
+}
+
+int ip_addr_to_str(sockaddr_storage* ss, string& addr)
+{
+  char ntop_buffer[INET6_ADDRSTRLEN];
+
+  if(!inet_ntop(ss->ss_family, &((sockaddr_in*)ss)->sin_addr,
+               ntop_buffer,INET6_ADDRSTRLEN)) {
+    ERROR("Could not convert address to string: %s",strerror(errno));
+    return -1;
+  }
+
+  addr = string(ntop_buffer);
+  return 0;
+}
 
 string extract_tag(const string& addr)
 {
diff --git a/core/AmUtils.h b/core/AmUtils.h
index 8d90db9..8db3687 100644
--- a/core/AmUtils.h
+++ b/core/AmUtils.h
@@ -33,6 +33,7 @@
 #include <errno.h>
 #include <sys/types.h>
 #include <regex.h>
+#include <sys/socket.h>
 
 #include <string>
 using std::string;
@@ -308,6 +309,19 @@ short get_port_v6(struct sockaddr_storage* ss);
 int write_to_fifo(const string& fifo, const char * buf, unsigned int len);
 int write_to_socket(int sd, const char* to_addr, const char * buf, unsigned 
int len);
 
+/*
+ * Computes the local address for a specific destination address.
+ * This is done by opening a connected UDP socket and reading the
+ * local address with getsockname().
+ */
+int get_local_addr_for_dest(sockaddr_storage* remote_ip, sockaddr_storage* 
local);
+int get_local_addr_for_dest(const string& remote_ip, string& local);
+
+/**
+ * Converts an IP address contained in a sockaddr_storage into a string.
+ */
+int ip_addr_to_str(sockaddr_storage* ss, string& addr);
+
 string extract_tag(const string& addr);
 
 /** returns true if key is in s_list, a list of items delimited by list_delim

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

Reply via email to