]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsproxy uses sendmsg instead of sendto
authorKonstantinos Natsakis <github.com@aleph-0.net>
Wed, 13 Nov 2013 21:59:13 +0000 (23:59 +0200)
committerKonstantinos Natsakis <github.com@aleph-0.net>
Wed, 13 Nov 2013 21:59:13 +0000 (23:59 +0200)
pdns/dnsproxy.cc
pdns/dnsproxy.hh

index da80598fc81943fc9f1f505ad3029d81b1878d99..8d586c90d6bd31040701658ab0ae62e0e571286b 100644 (file)
@@ -110,6 +110,7 @@ bool DNSProxy::sendPacket(DNSPacket *p)
     ce.created  = time( NULL );
     ce.qtype = p->qtype.getCode();
     ce.qname = p->qdomain;
+    ce.anyLocal = p->d_anyLocal;
     d_conntrack[id]=ce;
   }
   p->d.id=id^d_xor;
@@ -194,7 +195,72 @@ void DNSProxy::mainloop(void)
             ", qname or qtype mismatch"<<endl;
           continue;
         }
-        sendto(i->second.outsock, buffer, len, 0, (struct sockaddr*)&i->second.remote, i->second.remote.getSocklen());
+        {
+          struct msghdr msgh;
+          struct cmsghdr *cmsg;
+          struct iovec iov;
+          char cbuf[256];
+
+          /* Set up iov and msgh structures. */
+          memset(&msgh, 0, sizeof(struct msghdr));
+          iov.iov_base = buffer;
+          iov.iov_len = len;
+          msgh.msg_iov = &iov;
+          msgh.msg_iovlen = 1;
+          msgh.msg_name = (struct sockaddr*)&i->second.remote;
+          msgh.msg_namelen = i->second.remote.getSocklen();
+
+          if(i->second.anyLocal) {
+            if(i->second.anyLocal->sin4.sin_family == AF_INET6) {
+              struct in6_pktinfo *pkt;
+
+              msgh.msg_control = cbuf;
+              msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
+
+              cmsg = CMSG_FIRSTHDR(&msgh);
+              cmsg->cmsg_level = IPPROTO_IPV6;
+              cmsg->cmsg_type = IPV6_PKTINFO;
+              cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
+
+              pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
+              memset(pkt, 0, sizeof(*pkt));
+              pkt->ipi6_addr = i->second.anyLocal->sin6.sin6_addr;
+              msgh.msg_controllen = cmsg->cmsg_len; // makes valgrind happy and is slightly better style
+            }
+            else {
+#ifdef IP_PKTINFO
+              struct in_pktinfo *pkt;
+              msgh.msg_control = cbuf;
+              msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));
+
+              cmsg = CMSG_FIRSTHDR(&msgh);
+              cmsg->cmsg_level = IPPROTO_IP;
+              cmsg->cmsg_type = IP_PKTINFO;
+              cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));
+
+              pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
+              memset(pkt, 0, sizeof(*pkt));
+              pkt->ipi_spec_dst = i->second.anyLocal->sin4.sin_addr;
+#endif
+#ifdef IP_SENDSRCADDR
+              struct in_addr *in;
+
+              msgh.msg_control = cbuf;
+              msgh.msg_controllen = CMSG_SPACE(sizeof(*in));
+
+              cmsg = CMSG_FIRSTHDR(&msgh);
+              cmsg->cmsg_level = IPPROTO_IP;
+              cmsg->cmsg_type = IP_SENDSRCADDR;
+              cmsg->cmsg_len = CMSG_LEN(sizeof(*in));
+
+              in = (struct in_addr *) CMSG_DATA(cmsg);
+              *in = i->second.anyLocal->sin4.sin_addr;
+#endif
+              msgh.msg_controllen = cmsg->cmsg_len;
+            }
+          }
+          sendmsg(i->second.outsock, &msgh, 0);
+        }
         
         PC.insert(&q, &p);
         i->second.created=0;
index 0b4efa4d6472a19782303ca9ae750bde26ac6387..95ba9ab01d7f394834809c7f5bf625fbcf22b48d 100644 (file)
@@ -80,6 +80,7 @@ private:
     time_t created;
     string qname;
     uint16_t qtype;
+    boost::optional<ComboAddress> anyLocal;
   };
 
   typedef map<int,ConntrackEntry> map_t;