else
numanswered6++;
- /* Set up iov and msgh structures. */
- memset(&msgh, 0, sizeof(struct msghdr));
- iov.iov_base = (void*)buffer.c_str();
- iov.iov_len = buffer.length();
- msgh.msg_iov = &iov;
- msgh.msg_iovlen = 1;
- msgh.msg_name = (struct sockaddr*)&p->d_remote;
- msgh.msg_namelen = p->d_remote.getSocklen();
+ fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)buffer.c_str(), buffer.length(), &p->d_remote);
if(p->d_anyLocal) {
addCMsgSrcAddr(&msgh, cbuf, p->d_anyLocal.get_ptr());
struct iovec iov;
char cbuf[256];
- iov.iov_base = mesg;
- iov.iov_len = sizeof(mesg);
-
- memset(&msgh, 0, sizeof(struct msghdr));
-
- msgh.msg_control = cbuf;
- msgh.msg_controllen = sizeof(cbuf);
- msgh.msg_name = &remote;
- msgh.msg_namelen = sizeof(remote);
- msgh.msg_iov = &iov;
- msgh.msg_iovlen = 1;
- msgh.msg_flags = 0;
+ remote.sin6.sin6_family=AF_INET6; // make sure it is big enough
+ fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), mesg, sizeof(mesg), &remote);
int err;
vector<struct pollfd> rfds= d_rfds;
d_remote=*sa;
}
+ void setLocal(const ComboAddress& sa)
+ {
+ d_local=sa;
+ }
+
+
void setSocket(int sock)
{
d_socket=sock;
}
struct timeval d_now;
- ComboAddress d_remote;
+ ComboAddress d_remote, d_local;
bool d_tcp;
int d_socket;
shared_ptr<TCPConnection> d_tcpConnection;
}
catch(ImmediateServFailException &e) {
L<<Logger::Error<<"Sending SERVFAIL to "<<dc->getRemote()<<" during resolve of '"<<dc->d_mdp.d_qname<<"' because: "<<e.reason<<endl;
-
res = RCode::ServFail;
}
g_rs.submitResponse(dc->d_mdp.d_qtype, packet.size(), !dc->d_tcp);
updateResponseStats(res, dc->d_remote, packet.size(), &dc->d_mdp.d_qname, dc->d_mdp.d_qtype);
if(!dc->d_tcp) {
- sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
+ struct msghdr msgh;
+ struct iovec iov;
+ char cbuf[256];
+ fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)&*packet.begin(), packet.size(), &dc->d_remote);
+ if(dc->d_local.sin4.sin_family)
+ addCMsgSrcAddr(&msgh, cbuf, &dc->d_local);
+ sendmsg(dc->d_socket, &msgh, 0);
if(!SyncRes::s_nopacketcache && !variableAnswer ) {
t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()),
g_now.tv_sec,
}
}
-string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, int fd)
+string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, const ComboAddress& destaddr, struct timeval tv, int fd)
{
+ struct timeval diff = g_now - tv;
+ double delta=(diff.tv_sec*1000 + diff.tv_usec/1000.0);
+
+ if(delta > 1000.0) {
+ g_stats.tooOldDrops++;
+ return 0;
+ }
+
++g_stats.qcounter;
if(fromaddr.sin4.sin_family==AF_INET6)
g_stats.ipv6qcounter++;
g_stats.packetCacheHits++;
SyncRes::s_queries++;
ageDNSPacket(response, age);
- sendto(fd, response.c_str(), response.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen());
+ struct msghdr msgh;
+ struct iovec iov;
+ char cbuf[256];
+ fillMSGHdr(&msgh, &iov, cbuf, 0, (char*)response.c_str(), response.length(), const_cast<ComboAddress*>(&fromaddr));
+ if(destaddr.sin4.sin_family) {
+ cerr<<"Add!"<<endl;
+ addCMsgSrcAddr(&msgh, cbuf, &destaddr);
+ }
+ sendmsg(fd, &msgh, 0);
+
if(response.length() >= sizeof(struct dnsheader)) {
struct dnsheader dh;
memcpy(&dh, response.c_str(), sizeof(dh));
DNSComboWriter* dc = new DNSComboWriter(question.c_str(), question.size(), g_now);
dc->setSocket(fd);
dc->setRemote(&fromaddr);
+ dc->setLocal(destaddr);
dc->d_tcp=false;
MT->makeThread(startDoResolve, (void*) dc); // deletes dc
return 0;
}
+
void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
{
int len;
char data[1500];
ComboAddress fromaddr;
- socklen_t addrlen=sizeof(fromaddr);
-
+ struct msghdr msgh;
+ struct iovec iov;
+ char cbuf[256];
+
+ fromaddr.sin6.sin6_family=AF_INET6; // this makes sure fromaddr is big enough
+ fillMSGHdr(&msgh, &iov, cbuf, sizeof(cbuf), data, sizeof(data), &fromaddr);
+
for(;;)
- if((len=recvfrom(fd, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) {
+ if((len=recvmsg(fd, &msgh, 0)) >= 0) {
if(t_remotes)
t_remotes->push_back(fromaddr);
}
else {
string question(data, len);
+ struct timeval tv={0,0};
+ HarvestTimestamp(&msgh, &tv);
+ ComboAddress dest;
+ memset(&dest, 0, sizeof(dest)); // this makes sure we igore this address if not returned by recvmsg above
+ HarvestDestinationAddress(&msgh, &dest);
if(g_weDistributeQueries)
- distributeAsyncFunction(question, boost::bind(doProcessUDPQuestion, question, fromaddr, fd));
+ distributeAsyncFunction(question, boost::bind(doProcessUDPQuestion, question, fromaddr, dest, tv, fd));
else
- doProcessUDPQuestion(question, fromaddr, fd);
+ doProcessUDPQuestion(question, fromaddr, dest, tv, fd);
}
}
catch(MOADNSException& mde) {
if(locals.empty())
throw PDNSException("No local address specified");
- if(::arg()["local-address"]=="0.0.0.0") {
- L<<Logger::Warning<<"It is advised to bind to explicit addresses with the --local-address option"<<endl;
- }
-
for(vector<string>::const_iterator i=locals.begin();i!=locals.end();++i) {
ServiceTuple st;
st.port=::arg().asNum("local-port");
if(fd < 0) {
throw PDNSException("Making a UDP server socket for resolver: "+netstringerror());
}
+ setSocketTimestamps(fd);
+ int one;
+ if(IsAnyAddress(sin)) {
+ setsockopt(fd, IPPROTO_IP, GEN_IP_PKTINFO, &one, sizeof(one)); // linux supports this, so why not - might fail on other systems
+ setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &one, sizeof(one));
+ }
Utility::setCloseOnExec(fd);