Add ability to retrieve External IP using DNS server.

IPV6 compatible.
This commit is contained in:
Phenom 2020-04-25 12:55:45 +02:00
parent 56d34a8a2c
commit a09db6717b
8 changed files with 444 additions and 135 deletions

View File

@ -41,8 +41,6 @@
const rstime_t MAX_TIME_BEFORE_RETRY = 300 ; /* seconds before retrying an ip address */
const rstime_t MAX_KEEP_DNS_ENTRY = 3600 ; /* seconds during which a DNS entry is considered valid */
static const std::string ADDR_AGENT = "Mozilla/5.0";
void *solveDNSEntries(void *p)
{
bool more_to_go = true ;

View File

@ -38,132 +38,10 @@
#include <stdio.h>
#include "util/rstime.h"
const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */
const uint32_t MAX_IP_STORE = 300; /* seconds ip address timeout */
//#define EXTADDRSEARCH_DEBUG
static const std::string ADDR_AGENT = "Mozilla/5.0";
static std::string scan_ip(const std::string& text)
{
std::set<unsigned char> digits ;
digits.insert('0') ; digits.insert('3') ; digits.insert('6') ;
digits.insert('1') ; digits.insert('4') ; digits.insert('7') ;
digits.insert('2') ; digits.insert('5') ; digits.insert('8') ;
digits.insert('9') ;
for(int i=0;i<(int)text.size();++i)
{
while(i < (int)text.size() && digits.find(text[i])==digits.end()) ++i ;
if(i>=(int)text.size())
return "" ;
unsigned int a,b,c,d ;
if(sscanf(text.c_str()+i,"%u.%u.%u.%u",&a,&b,&c,&d) != 4)
continue ;
if(a < 256 && b<256 && c<256 && d<256)
{
std::string s ;
rs_sprintf(s, "%u.%u.%u.%u", a, b, c, d) ;
return s;
}
}
return "" ;
}
static void getPage(const std::string& server_name,std::string& page)
{
page = "" ;
int sockfd,n=0; // socket descriptor
struct sockaddr_in serveur; // server's parameters
memset(&serveur.sin_zero, 0, sizeof(serveur.sin_zero));
char buf[1024];
char request[1024];
#ifdef EXTADDRSEARCH_DEBUG
std::cout << "ExtAddrFinder: connecting to " << server_name << std::endl ;
#endif
// socket creation
sockfd = unix_socket(PF_INET,SOCK_STREAM,0);
if (sockfd < 0)
{
std::cerr << "ExtAddrFinder: Failed to create socket" << std::endl;
return ;
}
serveur.sin_family = AF_INET;
// get server's ipv4 adress
in_addr in ;
if(!rsGetHostByName(server_name.c_str(),in)) /* l'hôte n'existe pas */
{
std::cerr << "ExtAddrFinder: Unknown host " << server_name << std::endl;
unix_close(sockfd);
return ;
}
serveur.sin_addr = in ;
serveur.sin_port = htons(80);
#ifdef EXTADDRSEARCH_DEBUG
printf("Connection attempt\n");
#endif
std::cerr << "ExtAddrFinder: resolved hostname " << server_name << " to " << rs_inet_ntoa(in) << std::endl;
sockaddr_storage server;
sockaddr_storage_setipv4(server, &serveur);
sockaddr_storage_setport(server, 80);
if(unix_connect(sockfd, server) == -1)
{
std::cerr << "ExtAddrFinder: Connection error to " << server_name << std::endl ;
unix_close(sockfd);
return ;
}
#ifdef EXTADDRSEARCH_DEBUG
std::cerr << "ExtAddrFinder: Connection established to " << server_name << std::endl ;
#endif
// envoi
if(snprintf( request,
1024,
"GET / HTTP/1.0\r\n"
"Host: %s:%d\r\n"
"Connection: Close\r\n"
"\r\n",
server_name.c_str(), 80) > 1020)
{
std::cerr << "ExtAddrFinder: buffer overrun. The server name \"" << server_name << "\" is too long. This is quite unexpected." << std::endl;
unix_close(sockfd);
return ;
}
if(send(sockfd,request,strlen(request),0)== -1)
{
std::cerr << "ExtAddrFinder: Could not send request to " << server_name << std::endl ;
unix_close(sockfd);
return ;
}
// recéption
while((n = recv(sockfd, buf, sizeof buf - 1, 0)) > 0)
{
buf[n] = '\0';
page += std::string(buf,n) ;
}
// fermeture de la socket
unix_close(sockfd);
#ifdef EXTADDRSEARCH_DEBUG
std::cerr << "ExtAddrFinder: Got full page from " << server_name << std::endl ;
#endif
}
void* doExtAddrSearch(void *p)
{
@ -173,15 +51,12 @@ void* doExtAddrSearch(void *p)
for(std::list<std::string>::const_iterator it(af->_ip_servers.begin());it!=af->_ip_servers.end();++it)
{
std::string page ;
getPage(*it,page) ;
std::string ip = scan_ip(page) ;
std::string ip = "";
rsGetHostByNameSpecDNS(*it,"myip.opendns.com",ip);
if(ip != "")
res.push_back(ip) ;
#ifdef EXTADDRSEARCH_DEBUG
std::cout << "ip found through " << *it << ": \"" << ip << "\"" << std::endl ;
std::cout << "ip found through DNS " << *it << ": \"" << ip << "\"" << std::endl ;
#endif
}
@ -315,9 +190,15 @@ ExtAddrFinder::ExtAddrFinder() : mAddrMtx("ExtAddrFinder")
mFoundTS = time(NULL) - MAX_IP_STORE;
sockaddr_storage_clear(mAddr);
_ip_servers.push_back(std::string( "checkip.dyndns.org" )) ;
_ip_servers.push_back(std::string( "www.myip.dk" )) ;
_ip_servers.push_back(std::string( "showip.net" )) ;
_ip_servers.push_back(std::string( "www.displaymyip.com")) ;
//https://unix.stackexchange.com/questions/22615/how-can-i-get-my-external-ip-address-in-a-shell-script
//Enter direct ip so local DNS cannot change it.
//DNS servers must recognize "myip.opendns.com"
_ip_servers.push_back(std::string( "208.67.222.222" )) ;//resolver1.opendns.com
_ip_servers.push_back(std::string( "208.67.220.220" )) ;//resolver2.opendns.com
_ip_servers.push_back(std::string( "208.67.222.220" )) ;//resolver3.opendns.com
_ip_servers.push_back(std::string( "208.67.220.222" )) ;//resolver4.opendns.com
//Ipv6 server disabled as Current ip only manage ipv4 for now.
//_ip_servers.push_back(std::string( "2620:119:35::35" )) ;//resolver1.opendns.com
//_ip_servers.push_back(std::string( "2620:119:53::53" )) ;//resolver2.opendns.com
}

View File

@ -40,6 +40,51 @@ std::error_condition rs_errno_to_condition(int errno_code)
{ return std::make_error_condition(static_cast<std::errc>(errno_code)); }
std::ostream& hex_dump(std::ostream& os, const void *buffer,
std::size_t bufsize, bool showPrintableChars /*= true*/)
{
if (buffer == nullptr) {
return os;
}
auto oldFormat = os.flags();
auto oldFillChar = os.fill();
constexpr std::size_t maxline{8};
// create a place to store text version of string
char renderString[maxline+1];
char *rsptr{renderString};
// convenience cast
const unsigned char *buf{reinterpret_cast<const unsigned char *>(buffer)};
for (std::size_t linecount=maxline; bufsize; --bufsize, ++buf) {
os << std::setw(2) << std::setfill('0') << std::hex
<< static_cast<unsigned>(*buf) << ' ';
*rsptr++ = std::isprint(*buf) ? *buf : '.';
if (--linecount == 0) {
*rsptr++ = '\0'; // terminate string
if (showPrintableChars) {
os << " | " << renderString;
}
os << '\n';
rsptr = renderString;
linecount = std::min(maxline, bufsize);
}
}
// emit newline if we haven't already
if (rsptr != renderString) {
if (showPrintableChars) {
for (*rsptr++ = '\0'; rsptr != &renderString[maxline+1]; ++rsptr) {
os << " ";
}
os << " | " << renderString;
}
os << '\n';
}
os.fill(oldFillChar);
os.flags(oldFormat);
return os;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
@ -211,3 +256,7 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg
lineCount++;
}
}
/// All the lines before are DEPRECATED!!
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

View File

@ -318,3 +318,47 @@ void rslog(const RsLog::logLvl lvl, RsLog::logInfo *info, const std::string &msg
#define PQL_DEBUG_ALERT RSL_DEBUG_ALERT
#define PQL_DEBUG_BASIC RSL_DEBUG_BASIC
#define PQL_DEBUG_ALL RSL_DEBUG_ALL
//From https://codereview.stackexchange.com/a/165162
/**
* @brief hex_dump: Send Hexadecimal Dump to stream
* @param os: Output Stream
* @param buffer: Buffer to send
* @param bufsize: Buffer's size
* @param showPrintableChars: If must send printable Char too
* @return
* basic string:
* 61 62 63 64 65 66 31 32 | abcdef12
* 33 34 35 36 00 7a 79 78 | 3456.zyx
* 77 76 75 39 38 37 36 35 | wvu98765
* 34 45 64 77 61 72 64 00 | 4Edward.
*
* wide string:
* 41 00 00 00 20 00 00 00 | A... ...
* 77 00 00 00 69 00 00 00 | w...i...
* 64 00 00 00 65 00 00 00 | d...e...
* 20 00 00 00 73 00 00 00 | ...s...
* 74 00 00 00 72 00 00 00 | t...r...
* 69 00 00 00 6e 00 00 00 | i...n...
* 67 00 00 00 2e 00 00 00 | g.......
*
* a double
* 49 92 24 49 92 24 09 40 | I.$I.$.@
*/
std::ostream& hex_dump(std::ostream& os, const void *buffer,
std::size_t bufsize, bool showPrintableChars = true);
/**
* @brief The hexDump struct
* Enable to print dump calling like that:
* const char test[] = "abcdef123456\0zyxwvu987654Edward";
* RsDbg()<<hexDump(test, sizeof(test))<<std::endl;
*/
struct hexDump {
const void *buffer;
std::size_t bufsize;
hexDump(const void *buf, std::size_t bufsz) : buffer{buf}, bufsize{bufsz} {}
friend std::ostream &operator<<(std::ostream &out, const hexDump &hd) {
return hex_dump(out, hd.buffer, hd.bufsize, true);
}
};

View File

@ -21,6 +21,9 @@
* *
*******************************************************************************/
//#define DEBUG_SPEC_DNS 1
#include "util/rsdebug.h"
#include "util/rsnet.h"
#include "util/rsthreads.h"
#include "util/rsstring.h"
@ -40,6 +43,72 @@
#define BIG_ENDIAN 4321
#endif
//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
constexpr uint16_t DNSC_IN = 1; //Internet (IN)
//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
constexpr uint16_t DNST_A = 1; //Ipv4 address
constexpr uint16_t DNST_AAAA =28; //Ipv6 address
///Need to pack as we use sizeof them. (avoid padding)
#pragma pack(1)
//DNS header structure
struct DNS_HEADER
{
unsigned short id; // identification number
//Header flags https://www.bind9.net/dns-header-flags
unsigned char rd :1; //bit 07 Recursion Desired, indicates if the client means a recursive query
unsigned char tc :1; //bit 06 TrunCation, indicates that this message was truncated due to excessive length
unsigned char aa :1; //bit 05 Authoritative Answer, in a response, indicates if the DNS server is authoritative for the queried hostname
unsigned char opcode :4;//bit 01-04 The type can be QUERY (standard query, 0), IQUERY (inverse query, 1), or STATUS (server status request, 2)
unsigned char qr :1; //bit 00 Indicates if the message is a query (0) or a reply (1)
unsigned char rcode :4; //bit 12-15 Response Code can be NOERROR (0), FORMERR (1, Format error), SERVFAIL (2), NXDOMAIN (3, Nonexistent domain), etc.
unsigned char cd :1; //bit 11 Checking Disabled [RFC 4035][RFC 6840][RFC Errata 4927] used by DNSSEC
unsigned char ad :1; //bit 10 Authentic Data [RFC 4035][RFC 6840][RFC Errata 4924] used by DNSSEC
unsigned char z :1; //bit 09 Zero, reserved for future use
unsigned char ra :1; //bit 08 Recursion Available [RFC 1035] in a response, indicates if the replying DNS server supports recursion
unsigned short q_count; // number of question entries
unsigned short ans_count; // number of answer entries
unsigned short auth_count; // number of authority resource records entries
unsigned short add_count; // number of additional resource record entries
};
//// OpCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-5
//static const char *opcodetext[] = { "QUERY", "IQUERY", "STATUS",
// "RESERVED3", "NOTIFY", "UPDATE",
// "STATEFUL", "RESERVED7", "RESERVED8",
// "RESERVED9", "RESERVED10", "RESERVED11",
// "RESERVED12", "RESERVED13", "RESERVED14",
// "RESERVED15" };
//// RCode text https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6
//static const char *rcodetext[] = { "NOERROR", "FORMERR", "SERVFAIL",
// "NXDOMAIN", "NOTIMP", "REFUSED",
// "YXDOMAIN", "YXRRSET", "NXRRSET",
// "NOTAUTH", "NOTZONE", "DSOTYPENI",
// "RESERVED12", "RESERVED13", "RESERVED14",
// "RESERVED15", "BADVERS", "BADKEY",
// "BADTIME", "BADMODE", "BADNAME",
// "BADALG", "BADTRUNC", "BADCOOKIE"};
//Constant sized fields of query structure
//https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
struct QUESTION
{
unsigned short qtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
unsigned short qclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
};
//Constant sized fields of the resource record structure
struct RR_DATA
{
unsigned short rtype; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
unsigned short rclass; //https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2
unsigned int rttl; //Time To Live is the number of seconds left before the information expires. (32bits integer, so maximum 140 years)
unsigned short data_len;//Lenght of following data
};
#pragma pack()
#ifndef ntohll
uint64_t ntohll(uint64_t x)
{
@ -99,6 +168,248 @@ bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr)
return ok;
}
bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr)
{
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<<" servername="<< servername << " hostname=" << hostname << std::endl;
#endif
if (strlen(servername.c_str()) > 256)
{
RsErr()<<__PRETTY_FUNCTION__<<": servername is too long > 256 chars:"<<servername<<std::endl;
return false;
}
if (strlen(hostname.c_str()) > 256)
{
RsErr()<<__PRETTY_FUNCTION__<<": hostname is too long > 256 chars:"<<hostname<<std::endl;
return false;
}
bool isIPV4 = false;
in_addr dns_server_4; in6_addr dns_server_6;
if (inet_pton(AF_INET, servername.c_str(), &dns_server_4))
isIPV4 = true;
else if (inet_pton(AF_INET6, servername.c_str(), &dns_server_6))
isIPV4 = false;
else if (rsGetHostByName(servername, dns_server_4))
isIPV4 = true;
else
{
RsErr()<<__PRETTY_FUNCTION__<<": servername is on an unknow format: "<<servername<<std::endl;
return false;
}
unsigned char buf[65536];
struct sockaddr_in dest4;struct sockaddr_in6 dest6;
if (isIPV4)
{
dest4.sin_family = AF_INET;
dest4.sin_port = htons(53);
dest4.sin_addr.s_addr = dns_server_4.s_addr;
} else {
dest6.sin6_family = AF_INET6;
dest6.sin6_port = htons(53);
dest6.sin6_flowinfo = 0;
dest6.sin6_addr = dns_server_6;
dest6.sin6_scope_id = 0;
}
//Set the DNS structure to standard queries
struct DNS_HEADER* dns = (struct DNS_HEADER *)&buf;
dns->id = static_cast<unsigned short>(htons(getpid())); //Transaction Id
//dns flags = 0x0100 Standard Query
dns->qr = 0; //Query/Response: Message is a query
dns->opcode = 0; //OpCode: Standard query
dns->aa = 0; //Authoritative: Server is not an authority for domain
dns->tc = 0; //TrunCated: Message is not truncated
dns->rd = 1; //Recursion Desired: Do query recursively
dns->ra = 0; //Recursion Available: Server cannot do recursive queries
dns->z = 0; //Z: reserved
dns->ad = 0; //Authentic Data: Answer/authority portion was not authenticated by the server
dns->cd = 0; //Checking Disabled: Unacceptable
dns->rcode = 0; //Response Code: No error
dns->q_count = htons(1); //1 Question
dns->ans_count = 0; //0 Answer
dns->auth_count = 0; //0 Authority RRs
dns->add_count = 0; //0 Additional RRs
size_t curSendSize = sizeof(struct DNS_HEADER);
//Point to the query server name portion
unsigned char* qname =static_cast<unsigned char*>(&buf[curSendSize]);
//First byte is Label Type: https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-10
qname[0] = 0x04; //One Label with Normal label lower 6 bits is the length of the label
memcpy(&qname[1],hostname.c_str(),strlen(hostname.c_str()));
size_t qnameSize = strlen((const char*)qname);
// Format Hostname like www.google.com to 3www6google3com
{
size_t last = qnameSize;
for(size_t i = qnameSize-1 ; i > 0 ; i--)
if(qname[i]=='.')
{
qname[i]=last-i-1;
last = i;
}
}
curSendSize += qnameSize +1; //With \0 terminator
//Point to the query constant portion
struct QUESTION* qinfo =(struct QUESTION*)&buf[curSendSize];
qinfo->qtype = htons(isIPV4 ? DNST_A : DNST_AAAA); //Type: A / AAAA(Host Address)
qinfo->qclass = htons(DNSC_IN); //Class: IN
curSendSize += sizeof(struct QUESTION);
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<< " Sending Packet: " << std::endl << hexDump(buf, curSendSize) << std::endl;
#endif
int s = isIPV4 ? socket(AF_INET , SOCK_DGRAM , IPPROTO_UDP)
: socket(AF_INET6 , SOCK_DGRAM , IPPROTO_UDP) ; //UDP packet for DNS queries
ssize_t send_size = sendto(s, (char*)buf, curSendSize, 0
,isIPV4 ? (struct sockaddr*)&dest4
: (struct sockaddr*)&dest6
,isIPV4 ? sizeof(dest4)
: sizeof(dest6)
);
if( send_size < 0)
{
RsErr()<<__PRETTY_FUNCTION__<<": Send Failed with size = " << send_size << std::endl;
return false;
}
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<< " Waiting answer..." << std::endl;
#endif
//****************************************************************************************//
//--- Receive the answer ---//
//****************************************************************************************//
socklen_t dest_size = static_cast<socklen_t>(sizeof dest4);
ssize_t rec_size=recvfrom(s,(char*)buf , 65536 , 0 , (struct sockaddr*)&dest4 , &dest_size );
if(rec_size <= 0)
{
RsErr()<<__PRETTY_FUNCTION__<<": Receive Failed"<<std::endl;
return false;
}
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<< " Received: " << hexDump(buf, rec_size) << std::endl;
#endif
if (rec_size< static_cast<ssize_t>(sizeof(struct DNS_HEADER)) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get DNSHeader."<<std::endl;
return false;
}
#ifdef DEBUG_SPEC_DNS
//Point to the header portion
dns = (struct DNS_HEADER*) buf;
RsDbg()<<__PRETTY_FUNCTION__<<" The response contains : " << std::endl
<<ntohs(dns->q_count) << " Questions." << std::endl
<<ntohs(dns->ans_count) << " Answers." << std::endl
<<ntohs(dns->auth_count) << " Authoritative Servers." << std::endl
<<ntohs(dns->add_count) << " Additional records." << std::endl;
#endif
size_t curRecSize = sizeof(struct DNS_HEADER);
if (rec_size< static_cast<ssize_t>(curRecSize + 1 + sizeof(struct QUESTION)) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Question return."<<std::endl;
return false;
}
//Point to the query portion
unsigned char* qnameRecv =static_cast<unsigned char*>(&buf[curRecSize]);
if (memcmp(qname,qnameRecv,qnameSize + 1 + sizeof(struct QUESTION)) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received different from that sent."<<std::endl;
return false;
}
curRecSize += qnameSize + 1 + sizeof(struct QUESTION);
if (rec_size< static_cast<ssize_t>(curRecSize + 2) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Answer return."<<std::endl;
return false;
}
//Point to the Answer portion
unsigned char* reader = &buf[curRecSize];
size_t rLabelSize=0;
if((reader[0]&0xC0) == 0)
{
//Normal label lower 6 bits is the length of the label
rLabelSize=(reader[0]&~(0xC0)*256) + reader[1];
}
else if ((reader[0]&0xC0) == 0xC0)
{
//Compressed label the lower 6 bits and the 8 bits from next octet form a pointer to the compression target.
//Don't need to read it, maybe the same as in Query
rLabelSize=0;
}
else
{
RsErr()<<__PRETTY_FUNCTION__<<": Answer received with unmanaged label format."<<std::endl;
return false;
}
curRecSize += 2 + rLabelSize;
if (rec_size< static_cast<ssize_t>(curRecSize + sizeof(struct RR_DATA)) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Data return."<<std::endl;
return false;
}
//Point to the query portion
struct RR_DATA* rec_data = (struct RR_DATA *)&buf[curRecSize];
if (rec_data->rtype!=qinfo->qtype)
{
RsErr()<<__PRETTY_FUNCTION__<<": Answer's type received different from query sent."<<std::endl;
return false;
}
if (rec_data->rclass!=qinfo->qclass)
{
RsErr()<<__PRETTY_FUNCTION__<<": Answer's class received different from query sent."<<std::endl;
return false;
}
curRecSize += sizeof(struct RR_DATA);
if (rec_size< static_cast<ssize_t>(curRecSize + ntohs(rec_data->data_len)) )
{
RsErr()<<__PRETTY_FUNCTION__<<": Request received too small to get Full Data return."<<std::endl;
return false;
}
//Retrieve Address
if(ntohs(rec_data->data_len)==4)
{
if (isIPV4)
{
in_addr ipv4Add;
ipv4Add.s_addr=*(in_addr_t*)&buf[curRecSize];
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv4Add) << std::endl;
#endif
returned_addr = rs_inet_ntoa(ipv4Add);
return true;
}
}
else if(ntohs(rec_data->data_len)==16)
{
if (!isIPV4)
{
in6_addr ipv6Add;
ipv6Add =*(in6_addr*)&buf[curRecSize];
#ifdef DEBUG_SPEC_DNS
RsDbg()<<__PRETTY_FUNCTION__<< " Retrieve address: " << rs_inet_ntoa(ipv6Add) << std::endl;
#endif
returned_addr = rs_inet_ntoa(ipv6Add);
return true;
}
}
RsErr()<<__PRETTY_FUNCTION__<< " Retrieve unmanaged data size=" << ntohs(rec_data->data_len) << std::endl;
return false;
}
bool isValidNet(const struct in_addr *addr)
{
// invalid address.
@ -174,3 +485,18 @@ std::string rs_inet_ntoa(struct in_addr in)
rs_sprintf(str, "%u.%u.%u.%u", (int) bytes[0], (int) bytes[1], (int) bytes[2], (int) bytes[3]);
return str;
}
std::string rs_inet_ntoa(const in6_addr& in)
{
std::string str;
rs_sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
(int)in.s6_addr[0] , (int)in.s6_addr[1],
(int)in.s6_addr[2] , (int)in.s6_addr[3],
(int)in.s6_addr[4] , (int)in.s6_addr[5],
(int)in.s6_addr[6] , (int)in.s6_addr[7],
(int)in.s6_addr[8] , (int)in.s6_addr[9],
(int)in.s6_addr[10], (int)in.s6_addr[11],
(int)in.s6_addr[12], (int)in.s6_addr[13],
(int)in.s6_addr[14], (int)in.s6_addr[15]);
return str;
}

View File

@ -84,11 +84,17 @@ bool isExternalNet(const struct in_addr *addr);
// uses a re-entrant version of gethostbyname
bool rsGetHostByName(const std::string& hostname, in_addr& returned_addr) ;
// Get hostName address using specific DNS server
// Using it allow to direct ask our Address to IP, so no need to have a DNS (IPv4 or IPv6 ???).
// If we ask to a IPv6 DNS Server, it respond for our IPv6 address.
bool rsGetHostByNameSpecDNS(const std::string& servername, const std::string& hostname, std::string& returned_addr);
std::ostream& operator<<(std::ostream& o, const sockaddr_in&);
std::ostream& operator<<(std::ostream& o, const sockaddr_storage&);
/* thread-safe version of inet_ntoa */
std::string rs_inet_ntoa(struct in_addr in);
std::string rs_inet_ntoa(const in6_addr &in);
/***************************/

View File

@ -262,6 +262,7 @@ bool sockaddr_storage_setipv6(struct sockaddr_storage &addr, const sockaddr_in6
}
#ifdef WINDOWS_SYS
#ifndef InetPtonA
int inet_pton(int af, const char *src, void *dst)
{
sockaddr_storage ss;
@ -288,6 +289,7 @@ int inet_pton(int af, const char *src, void *dst)
return 0;
}
#endif
#endif
bool sockaddr_storage_inet_pton( sockaddr_storage &addr,
const std::string& ipStr )

View File

@ -719,6 +719,9 @@ behind a firewall or a VPN.</string>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>List of OpenDns servers used.</string>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>