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
