[Pdns-dev] Slaving from IPv6 host
Lionel Elie Mamane
lionel at mamane.lu
Tue Oct 12 16:37:26 CEST 2004
On Sat, Jul 17, 2004 at 05:12:13PM +0200, Lionel Elie Mamane wrote:
> (This is a continuation to
> http://mailman.powerdns.com/pipermail/pdns-users/2004-July/001766.html
> )
> pdsn 2.9.16 cannot slave from an IPv6 host. Here's a patch that
> implements this.
In case anyone is interested, a new version of the patch, that makes
IPv6 literals in masters (masters from which to slave from) work. In
this case, a "." is used as IP address-to-port separator.
--
Lionel
-------------- next part --------------
diff --recursive -u pdns-2.9.16/pdns/communicator.cc pdns-2.9.16.lio/pdns/communicator.cc
--- pdns-2.9.16/pdns/communicator.cc 2003-05-25 14:38:48.000000000 +0200
+++ pdns-2.9.16.lio/pdns/communicator.cc 2004-10-11 20:57:15.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 10-17 Jul 2004 for slaving from IPv6 host by
+ Lionel Elie Mamane <lionel at mamane.lu>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -241,7 +244,6 @@
" checking"<<endl;
Resolver resolver;
- resolver.makeUDPSocket();
for(vector<DomainInfo>::const_iterator i=sdomains.begin();i!=sdomains.end();++i) {
d_slaveschanged=true;
u_int32_t ourserial=i->serial,theirserial=0;
diff --recursive -u pdns-2.9.16/pdns/misc.cc pdns-2.9.16.lio/pdns/misc.cc
--- pdns-2.9.16/pdns/misc.cc 2004-02-04 21:20:23.000000000 +0100
+++ pdns-2.9.16.lio/pdns/misc.cc 2004-10-11 21:01:00.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 11 Oct 2004 for slaving from IPv6 host by
+ Lionel Elie Mamane <lionel at mamane.lu>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -139,9 +142,21 @@
void parseService(const string &descr, ServiceTuple &st)
{
-
+ // If descr contains at least two colons (:), it is an IPv6 address litteral.
+ // If not, it cannot be.
+ const string colon = ":";
+ string delimiter = colon;
+ {
+ string::size_type i;
+ i = descr.find_first_of(colon);
+ if (i != string::npos) {
+ if (descr.find_first_of(colon,i+1) != string::npos) {
+ delimiter = ".";
+ }
+ }
+ }
vector<string>parts;
- stringtok(parts,descr,":");
+ stringtok(parts,descr,delimiter.c_str());
if(parts.empty())
throw AhuException("Unable to parse '"+descr+"' as a service");
st.host=parts[0];
diff --recursive -u pdns-2.9.16/pdns/resolver.cc pdns-2.9.16.lio/pdns/resolver.cc
--- pdns-2.9.16/pdns/resolver.cc 2003-10-11 21:27:14.000000000 +0200
+++ pdns-2.9.16.lio/pdns/resolver.cc 2004-10-11 20:57:05.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 10-17 Jul 2004 for slaving from IPv6 host by
+ Lionel Elie Mamane <lionel at mamane.lu>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -35,36 +38,78 @@
#include "ahuexception.hh"
#include "statbag.hh"
#include "arguments.hh"
+#include <sstream>
+#include <cassert>
-void Resolver::makeUDPSocket()
+void Resolver::makeUDPSocket(int domain)
{
- makeSocket(SOCK_DGRAM);
+ makeSocket(domain, SOCK_DGRAM);
}
-void Resolver::makeSocket(int type)
+void Resolver::makeSocket(int domain, int type)
{
static u_int16_t port_counter=5000;
- if(d_sock>0)
- return;
+ struct sockaddr_storage ss;
+ socklen_t ss_size = sizeof(ss);
+ struct sockaddr &sa = *(struct sockaddr*)&ss;
+
+ memset((char *)&ss,0, sizeof(ss));
+
+ assert(AF_INET == PF_INET && AF_INET6 == PF_INET6);
+
+ if(d_sock > 0) {
+ int result;
+
+ result = getsockname(d_sock, &sa, &ss_size);
+ if (result != 0 || sa.sa_family != domain) {
+ memset((char *)&ss,0, sizeof(ss));
+ Utility::closesocket(d_sock);
+ }
+ else {
+ return;
+ }
+ }
- d_sock=socket(AF_INET, type,0);
+ d_sock=socket(domain, type,0);
if(d_sock<0)
throw AhuException("Making a socket for resolver: "+stringerror());
- struct sockaddr_in sin;
- memset((char *)&sin,0, sizeof(sin));
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
+ sa.sa_family = domain;
+
+ if (domain == PF_INET) {
+ struct sockaddr_in &sin = *(struct sockaddr_in*)&ss;
+
+ sin.sin_addr.s_addr = INADDR_ANY;
+ ss_size = sizeof(sin);
+ }
+ else if(domain == PF_INET6) {
+ struct sockaddr_in6 &sin = *(struct sockaddr_in6*)&ss;
+
+ sin.sin6_addr = in6addr_any;
+ ss_size = sizeof(sin);
+ }
+ else {
+ throw AhuException("Unkown socket domain: " + domain);
+ }
int tries=10;
while(--tries) {
- sin.sin_port = htons(10000+(port_counter++)%10000); // should be random!
+ if (domain == PF_INET) {
+ struct sockaddr_in &sin = *(struct sockaddr_in*)&ss;
+
+ sin.sin_port = htons(10000+(port_counter++)%10000); // should be random!
+ }
+ else if(domain == PF_INET6) {
+ struct sockaddr_in6 &sin = *(struct sockaddr_in6*)&ss;
+
+ sin.sin6_port = htons(10000+(port_counter++)%10000); // should be random!
+ }
- if (bind(d_sock, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ if (bind(d_sock, &sa, ss_size) >= 0)
break;
}
+
if(!tries)
throw AhuException("Resolver binding to local socket: "+stringerror());
}
@@ -159,8 +204,7 @@
d_type=type;
d_inaxfr=false;
- struct sockaddr_in toaddr;
- struct in_addr inp;
+ struct addrinfo *toaddrs;
ServiceTuple st;
st.port=53;
try {
@@ -170,15 +214,26 @@
throw ResolverException("Sending a dns question to '"+ip+"': "+ae.reason);
}
- Utility::inet_aton(st.host.c_str(),&inp);
- toaddr.sin_addr.s_addr=inp.s_addr;
-
- toaddr.sin_port=htons(st.port);
- toaddr.sin_family=AF_INET;
+ {
+ ostringstream ss;
+ ss << st.port;
+ toaddrs = Utility::resolve_hostname_to_ip(st.host.c_str(),ss.str(),AF_UNSPEC);
+ }
- if(sendto(d_sock, p.getData(), p.len, 0, (struct sockaddr*)(&toaddr), sizeof(toaddr))<0) {
- throw ResolverException("Unable to ask query of "+st.host+":"+itoa(st.port)+": "+stringerror());
+ for(struct addrinfo *toaddr = toaddrs;toaddr!=NULL;toaddr=toaddr->ai_next) {
+ makeUDPSocket(toaddr->ai_addr->sa_family);
+ if(sendto(d_sock, p.getData(), p.len, 0, toaddr->ai_addr, toaddr->ai_addrlen)<0) {
+ if (toaddr->ai_next == NULL) {
+ freeaddrinfo(toaddrs);
+ throw ResolverException("Unable to ask query of "+st.host+":"+itoa(st.port)+": "+stringerror());
+ }
+ }
+ else
+ break;
}
+
+ freeaddrinfo(toaddrs);
+
}
int Resolver::receiveResolve(struct sockaddr* fromaddr, Utility::socklen_t addrlen)
@@ -207,7 +262,6 @@
int Resolver::resolve(const string &ip, const char *domain, int type)
{
- makeUDPSocket();
sendResolve(ip,domain,type);
try {
struct sockaddr_in from;
@@ -220,23 +274,13 @@
}
-void Resolver::makeTCPSocket(const string &ip, u_int16_t port)
+void Resolver::makeTCPSocket_one_IP(const struct sockaddr *toaddr, const size_t toaddr_len)
{
- if(d_sock>=0)
- return;
- struct sockaddr_in toaddr;
- struct in_addr inp;
- Utility::inet_aton(ip.c_str(),&inp);
- toaddr.sin_addr.s_addr=inp.s_addr;
-
- toaddr.sin_port=htons(port);
- toaddr.sin_family=AF_INET;
-
-
- d_sock=socket(AF_INET,SOCK_STREAM,0);
+ d_sock=socket(toaddr->sa_family,SOCK_STREAM,0);
if(d_sock<0)
throw ResolverException("Unable to make a TCP socket for resolver: "+stringerror());
+ // TODO: Handle IPv6 here
// Use query-local-address as source IP for queries, if specified.
string querylocaladdress(arg()["query-local-address"]);
if (querylocaladdress!="") {
@@ -265,9 +309,9 @@
int err;
#ifndef WIN32
- if((err=connect(d_sock,(struct sockaddr*)&toaddr,sizeof(toaddr)))<0 && errno!=EINPROGRESS) {
+ if((err=connect(d_sock,toaddr,toaddr_len))<0 && errno!=EINPROGRESS) {
#else
- if((err=connect(d_sock,(struct sockaddr*)&toaddr,sizeof(toaddr)))<0 && WSAGetLastError() != WSAEWOULDBLOCK ) {
+ if((err=connect(d_sock,toaddr,toaddr_len))<0 && WSAGetLastError() != WSAEWOULDBLOCK ) {
#endif // WIN32
throw ResolverException("connect: "+stringerror());
}
@@ -310,6 +354,33 @@
// d_sock now connected
}
+void Resolver::makeTCPSocket(const string &ip, u_int16_t port)
+{
+ if(d_sock>=0)
+ return;
+ struct addrinfo *toaddrs;
+ {
+ ostringstream ss;
+ ss << port;
+ toaddrs = Utility::resolve_hostname_to_ip(ip,ss.str(),AF_UNSPEC);
+ }
+
+ if (toaddrs==NULL)
+ throw ResolverException("unable to resolve "+ip);
+
+ for(struct addrinfo *toaddr = toaddrs;toaddr!=NULL;toaddr=toaddr->ai_next) {
+ try {
+ makeTCPSocket_one_IP(toaddr->ai_addr, toaddr->ai_addrlen);
+ }
+ catch(...){
+ if (toaddr->ai_next==NULL) {
+ freeaddrinfo(toaddrs);
+ throw;
+ }
+ }
+ }
+ freeaddrinfo(toaddrs);
+}
//! returns -1 for permanent error, 0 for timeout, 1 for success
int Resolver::axfr(const string &ip, const char *domain)
diff --recursive -u pdns-2.9.16/pdns/resolver.hh pdns-2.9.16.lio/pdns/resolver.hh
--- pdns-2.9.16/pdns/resolver.hh 2003-05-25 13:46:07.000000000 +0200
+++ pdns-2.9.16.lio/pdns/resolver.hh 2004-07-17 16:47:49.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 10-17 Jul 2004 for slaving from IPv6 host by
+ Lionel Elie Mamane <lionel at mamane.lu>
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -16,25 +19,25 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-
+
#include <string>
#include <vector>
-#include <sys/types.h>
-
-#ifndef WIN32
-
-# include <arpa/nameser.h>
-# include <resolv.h>
-# include <netdb.h>
-# include <unistd.h>
-# include <sys/time.h>
-# include <sys/uio.h>
-# include <fcntl.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
+#include <sys/types.h>
+
+#ifndef WIN32
+
+# include <arpa/nameser.h>
+# include <resolv.h>
+# include <netdb.h>
+# include <unistd.h>
+# include <sys/time.h>
+# include <sys/uio.h>
+# include <fcntl.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
# undef res_mkquery
-#endif // WIN32
+#endif // WIN32
#include "ahuexception.hh"
#include "dns.hh"
@@ -55,8 +58,8 @@
string i;
typedef vector<DNSResourceRecord> res_t;
- void makeSocket(int type);
- void makeUDPSocket();
+ void makeSocket(int domain, int type);
+ void makeUDPSocket(int domain);
void makeTCPSocket(const string &ip, u_int16_t port=53);
int notify(int sock, const string &domain, const string &ip, u_int16_t id);
int resolve(const string &ip, const char *domain, int type);
@@ -74,6 +77,7 @@
int axfr(const string &ip, const char *domain);
private:
+ void Resolver::makeTCPSocket_one_IP(const struct sockaddr *toaddr, const size_t toaddr_len);
void timeoutReadn(char *buffer, int bytes);
int d_sock;
unsigned char *d_buf;
diff --recursive -u pdns-2.9.16/pdns/unix_utility.cc pdns-2.9.16.lio/pdns/unix_utility.cc
--- pdns-2.9.16/pdns/unix_utility.cc 2003-10-04 15:18:25.000000000 +0200
+++ pdns-2.9.16.lio/pdns/unix_utility.cc 2004-07-17 16:48:27.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 10-17 Jul 2004 by Lionel Elie Mamane <lionel at mamane.lu>
+ Added resolve_hostname_to_ip function.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -29,6 +32,7 @@
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
+#include <netdb.h>
#ifdef NEED_INET_NTOP_PROTO
extern "C" {
@@ -122,6 +126,27 @@
}
+struct addrinfo *Utility::resolve_hostname_to_ip( const string &host, const string &port, int pf )
+{
+ struct addrinfo hints, *res0;
+ int result;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pf;
+ hints.ai_socktype = SOCK_STREAM;
+
+ result = getaddrinfo(host.c_str(), port.c_str(), &hints, &res0);
+ if ( result != 0 ) {
+ theL()<<Logger::Error<<"Unable to resolve hostname '"<<host<<"': "<<gai_strerror(result)<<endl;
+ if (result == EAI_SYSTEM)
+ theL()<<Logger::Error<<"The system error is: "<<strerror(errno)<<endl;
+ return NULL;
+ }
+ else
+ if (res0==0)
+ theL()<<Logger::Error<<"Unable to resolve hostname '"<<host<<"': "<<"Success, but no information returned"<<endl;
+
+ return res0;
+}
// Converts an address from presentation format to network format.
int Utility::inet_pton( int af, const char *src, void *dst )
diff --recursive -u pdns-2.9.16/pdns/utility.hh pdns-2.9.16.lio/pdns/utility.hh
--- pdns-2.9.16/pdns/utility.hh 2003-11-30 11:53:06.000000000 +0100
+++ pdns-2.9.16.lio/pdns/utility.hh 2004-07-17 16:50:35.000000000 +0200
@@ -2,6 +2,9 @@
PowerDNS Versatile Database Driven Nameserver
Copyright (C) 2002 PowerDNS.COM BV
+ Modified 10-17 Jul 2004 by Lionel Elie Mamane <lionel at mamane.lu>
+ Added resolve_hostname_to_ip function.
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
@@ -188,6 +191,9 @@
//! Gets the current time.
static int gettimeofday( struct timeval *tv, void *tz = NULL );
+ //! Converts an address from any format to binary data.
+ static struct addrinfo *resolve_hostname_to_ip( const string &host, const string &port, int pf );
+
//! Converts an address from dot and numbers format to binary data.
static int inet_aton( const char *cp, struct in_addr *inp );
More information about the Pdns-dev
mailing list