[Pdns-dev] query-local-address configuration option (patch included)

mark at nedworks.org mark at nedworks.org
Thu Feb 20 19:24:54 CET 2003


Although pdns does have support for IP aliases through configuration
options for binding listening sockets to specific IPs, it always uses
INADDR_ANY for sending queries and AXFR requests (so it lets the OS
decide which IP address to use).

This was causing me problems, because pdns isn't listening on my 'main'
ip on one of my boxes. The OS would choose it's main IP for sending
notifies etc. to my masters/slaves, which did not recognize the notifies
as coming from my server. There are some ways to circumvent this
behaviour, but I figured that being able to specify a source IP address
for queries in pdns would be the best solution to this problem.

The patch attached to this message does exactly that. It adds a
'query-local-source' configuration option that accepts a single IP
address or hostname, which would then be used for both udp and tcp
queries (notifies, AXFRs...).

I did a few quick tests and it seems to work fine. No guarantees, though ;)

-- 
Mark

<mark at nedworks.org>
-------------- next part --------------
diff -ur pdns-2.9.6/pdns/common_startup.cc pdns-2.9.6-mark1/pdns/common_startup.cc
--- pdns-2.9.6/pdns/common_startup.cc	Mon Jan 20 14:09:42 2003
+++ pdns-2.9.6-mark1/pdns/common_startup.cc	Thu Feb 20 18:44:16 2003
@@ -46,6 +46,7 @@
   arg().set("smtpredirector","Our smtpredir MX host")="a.misconfigured.powerdns.smtp.server";
   arg().set("local-address","Local IP address to which we bind")="0.0.0.0";
   arg().set("local-ipv6","Local IP address to which we bind")="";
+  arg().set("query-local-address","Source IP address for sending queries")="";
   arg().set("max-queue-length","Maximum queuelength before considering situation lost")="5000";
   arg().set("soa-serial-offset","Make sure that no SOA serial is less than this number")="0";
   arg().set("only-soa","Make sure that no SOA serial is less than this number")="org";
diff -ur pdns-2.9.6/pdns/communicator.cc pdns-2.9.6-mark1/pdns/communicator.cc
--- pdns-2.9.6/pdns/communicator.cc	Mon Feb 10 14:36:10 2003
+++ pdns-2.9.6-mark1/pdns/communicator.cc	Thu Feb 20 18:44:16 2003
@@ -345,7 +345,25 @@
   memset((char *)&sin,0, sizeof(sin));
   
   sin.sin_family = AF_INET;
-  sin.sin_addr.s_addr = INADDR_ANY;
+
+  // Bind to a specific IP (query-local-address) if specified
+  string querylocaladdress(arg()["query-local-address"]);
+  if (querylocaladdress=="") {
+    sin.sin_addr.s_addr = INADDR_ANY;
+  }
+  else
+  {
+    struct hostent *h=0;
+    h=gethostbyname(querylocaladdress.c_str());
+    if(!h) {
+      Utility::closesocket(d_nsock);
+      d_nsock=-1;	
+      throw AhuException("Unable to resolve query local address");
+    }
+
+    sin.sin_addr.s_addr = *(int*)h->h_addr;
+  }
+  
   int n=0;
   for(;n<10;n++) {
     sin.sin_port = htons(10000+(Utility::random()%50000));
@@ -356,7 +374,7 @@
   if(n==10) {
     Utility::closesocket(d_nsock);
     d_nsock=-1;
-    throw AhuException(string("binding dnsproxy socket: ")+strerror(errno));
+    throw AhuException(string("binding notify socket: ")+strerror(errno));
   }
   if( !Utility::setNonBlocking( d_nsock ))
     throw AhuException(string("error getting or setting notify socket non-blocking: ")+strerror(errno));
diff -ur pdns-2.9.6/pdns/resolver.cc pdns-2.9.6-mark1/pdns/resolver.cc
--- pdns-2.9.6/pdns/resolver.cc	Tue Feb 11 08:55:33 2003
+++ pdns-2.9.6-mark1/pdns/resolver.cc	Thu Feb 20 18:44:16 2003
@@ -216,7 +216,37 @@
   d_sock=socket(AF_INET,SOCK_STREAM,0);
   if(d_sock<0)
     throw ResolverException("Unable to make a TCP socket for resolver: "+stringerror());
-  
+
+  // Use query-local-address as source IP for queries, if specified.
+  string querylocaladdress(arg()["query-local-address"]);
+  if (querylocaladdress!="") {
+    struct sockaddr_in fromaddr;
+    struct hostent *h=0;
+
+    h = gethostbyname(querylocaladdress.c_str());
+    if(!h) {
+      Utility::closesocket(d_sock);
+      d_sock=-1;
+      throw ResolverException("Unable to resolve query local address");
+    }
+
+    fromaddr.sin_family = AF_INET;
+    fromaddr.sin_addr.s_addr = *(int*)h->h_addr;
+        
+    // Find a random free port
+    int n=0;
+    for(;n<10;n++) {
+      fromaddr.sin_port = htons(10000+(Utility::random()%50000));
+      if(bind(d_sock, (struct sockaddr *)&fromaddr, sizeof(fromaddr)) >= 0)
+        break;
+    }
+    if(n==10) {
+      Utility::closesocket(d_sock);
+      d_sock=-1;
+      throw ResolverException("Binding to query-local-address: "+stringerror());
+    }
+  }  
+    
   Utility::setNonBlocking( d_sock );
 
   int err;


More information about the Pdns-dev mailing list