From: Bert Hubert Date: Sun, 30 Nov 2003 11:18:49 +0000 (+0000) Subject: win32 errors X-Git-Tag: pdns-2.9.13~4 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8d69ac3abcb3454e16c1271c65ab50d2d00c5f3e;p=pdns win32 errors git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@205 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/docs/pdns.sgml b/pdns/docs/pdns.sgml index be53bcde4..2188d0417 100644 --- a/pdns/docs/pdns.sgml +++ b/pdns/docs/pdns.sgml @@ -11,7 +11,7 @@ - v2.1 $Date: 2003/11/30 10:53:00 $ + v2.1 $Date: 2003/11/30 11:18:49 $ @@ -84,7 +84,48 @@ Version 2.9.13 - Some bugfixes, some small features. Only one big bugfix, it appears we are heading for stability! + Big news! Windows is back! Our great friend Michel Stol found the time to update the PowerDNS code so it works + again under windows. + + + His changes: + + + + Generic SQLite support added + + + + + Removed the ODBC backend, replaced it by the Generic ODBC Backend, which has all the cool configurability + of the Generic MySQL and PostgreSQL backends. + + + + + The PowerDNS Recursor now runs as a Service. It defaults to running on port 5300, PowerDNS itself is configured + to expect the Recursor on port 5300 now. + + + + + The PowerDNS Service is now known as 'PowerDNS' to Windows. + + + + + The Installer was redone, this time with NSIS2. + + + + + General updates and fixes. + + + + + + Other news: diff --git a/pdns/recursorservice.cc b/pdns/recursorservice.cc new file mode 100644 index 000000000..2ed812fd3 --- /dev/null +++ b/pdns/recursorservice.cc @@ -0,0 +1,66 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002 PowerDNS.COM BV + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "common_startup.hh" +#include "recursorservice.hh" + +extern int serviceMain( int argc, char *argv[] ); + +// Control handler. +void RecursorService::ctrlHandler( DWORD controlCode ) +{ + if ( m_statusCode == SERVICE_STOPPED ) + exit( 0 ); + + switch ( controlCode ) + { + case SERVICE_CONTROL_STOP: + setStatus( SERVICE_STOP_PENDING ); + shutdown(); + setStatus( SERVICE_STOPPED ); + // FIXME: Add a cleaner way to do this: + break; + + case SERVICE_CONTROL_INTERROGATE: + setStatus( m_statusCode, m_errorCode ); + break; + + case SERVICE_CONTROL_SHUTDOWN: + setStatus( SERVICE_STOP_PENDING ); + shutdown(); + setStatus( SERVICE_STOPPED ); + // FIXME: Add a cleaner way to do this: + break; + } +} + + +// Returns the service name. +std::string RecursorService::getServiceName( void ) +{ + return "PowerDNS Recursor"; +} + + +// Main procedure. +int RecursorService::main( int argc, char *argv[] ) +{ + return serviceMain( argc, argv ); + +} diff --git a/pdns/recursorservice.hh b/pdns/recursorservice.hh new file mode 100644 index 000000000..128306f0f --- /dev/null +++ b/pdns/recursorservice.hh @@ -0,0 +1,46 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002 PowerDNS.COM BV + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef AHUDNSSERVICE_HH +#define AHUDNSSERVICE_HH + +#include +#include "ntservice.hh" + +class RecursorService : public NTService +{ +protected: + //! Main service procedure. + int main( int argc, char *argv[] ); + + //! Control handler. + void ctrlHandler( DWORD controlCode ); + +public: + //! Constructor. + RecursorService( void ) : NTService() + { + } + + //! Returns the service name. + std::string getServiceName( void ); + +}; + +#endif // AHUDNSSERVICE_HH diff --git a/pdns/win32_pdns_recursor.cc b/pdns/win32_pdns_recursor.cc new file mode 100644 index 000000000..bc5cc5893 --- /dev/null +++ b/pdns/win32_pdns_recursor.cc @@ -0,0 +1,728 @@ +/* + PowerDNS Versatile Database Driven Nameserver + Copyright (C) 2002 PowerDNS.COM BV + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "utility.hh" +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtasker.hh" +#include +#include "dnspacket.hh" +#include "statbag.hh" +#include "arguments.hh" +#include "syncres.hh" +#include +#include +#include "recursorservice.hh" + +string s_programname="pdns_recursor"; + +#ifndef WIN32 +extern "C" { + int sem_init(sem_t*, int, unsigned int){return 0;} + int sem_wait(sem_t*){return 0;} + int sem_trywait(sem_t*){return 0;} + int sem_post(sem_t*){return 0;} + int sem_getvalue(sem_t*, int*){return 0;} + pthread_t pthread_self(void){return (pthread_t) 0;} + int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr){ return 0; } + int pthread_mutex_lock(pthread_mutex_t *mutex){ return 0; } + int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; } + +} +#endif // WIN32 + +StatBag S; +ArgvMap &arg() +{ + static ArgvMap theArg; + return theArg; +} +int d_clientsock; +int d_serversock; +int d_tcpserversock; + +struct PacketID +{ + u_int16_t id; + struct sockaddr_in remote; +}; + +bool operator<(const PacketID& a, const PacketID& b) +{ + if(a.id* MT; + +/* these two functions are used by LWRes */ +int asendto(const char *data, int len, int flags, struct sockaddr *toaddr, int addrlen, int id) +{ + return sendto(d_clientsock, data, len, flags, toaddr, addrlen); +} + +int arecvfrom(char *data, int len, int flags, struct sockaddr *toaddr, Utility::socklen_t *addrlen, int *d_len, int id) +{ + PacketID pident; + pident.id=id; + memcpy(&pident.remote,toaddr,sizeof(pident.remote)); + + string packet; + if(!MT->waitEvent(pident,&packet,1)) { // timeout + return 0; + } + + *d_len=packet.size(); + memcpy(data,packet.c_str(),min(len,*d_len)); + + return 1; +} + +typedef map > cache_t; +static cache_t cache; +int cacheHits, cacheMisses; +int getCache(const string &qname, const QType& qt, set* res) +{ + cache_t::const_iterator j=cache.find(toLower(qname)+"|"+qt.getName()); + if(j!=cache.end() && j->first==toLower(qname)+"|"+qt.getName() && j->second.begin()->ttl>(unsigned int)time(0)) { + if(res) + *res=j->second; + + return (unsigned int)j->second.begin()->ttl-time(0); + } + + return -1; +} + +void replaceCache(const string &qname, const QType& qt, const set& content) +{ + + // bogus code to generate root with very low ttl + /* + if((0 && qname.empty()) || qname.rfind(".root-servers.net")==1) { + cout<<"qname: '"< changed; + for(set::const_iterator i=content.begin();i!=content.end();++i) { + DNSResourceRecord j=*i; + j.ttl=time(0)+20; + changed.insert(j); + } + cache[qname+"|"+qt.getName()]=changed; + } + else + */ + cache[toLower(qname)+"|"+qt.getName()]=content; +} + +void doPrune(void) +{ + unsigned int names=0, records=0; + + for(cache_t::iterator j=cache.begin();j!=cache.end();){ + for(set::iterator k=j->second.begin();k!=j->second.end();) + if((unsigned int)k->ttl < (unsigned int)time(0)) { + j->second.erase(k++); + records++; + } + else + ++k; + + if(j->second.empty()) { // everything is gone + cache.erase(j++); + names++; + + } + else { + ++j; + } + } +} + + +void primeHints(void) +{ + // prime root cache + static char*ips[]={"198.41.0.4", "128.9.0.107", "192.33.4.12", "128.8.10.90", "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53", + "192.36.148.17","192.58.128.30", "193.0.14.129", "198.32.64.12", "202.12.27.33"}; + DNSResourceRecord arr, nsrr; + arr.qtype=QType::A; + arr.ttl=time(0)+3600000; + nsrr.qtype=QType::NS; + nsrr.ttl=time(0)+3600000; + + setnsset; + for(char c='a';c<='m';++c) { + static char templ[40]; + strncpy(templ,"a.root-servers.net", sizeof(templ) - 1); + *templ=c; + arr.qname=nsrr.content=templ; + arr.content=ips[c-'a']; + setaset; + aset.insert(arr); + replaceCache(string(templ),QType(QType::A),aset); + + nsset.insert(nsrr); + } + replaceCache("",QType(QType::NS),nsset); +} + +void startDoResolve(void *p) +{ + try { + bool quiet=arg().mustDo("quiet"); + DNSPacket P=*(DNSPacket *)p; + + delete (DNSPacket *)p; + + vectorret; + DNSPacket *R=P.replyPacket(); + R->setA(false); + R->setRA(true); + + SyncRes sr; + if(!quiet) + L<getTid()<<"] question for '"<getTid()); + if(!P.d.rd) + sr.setCacheOnly(); + + int res=sr.beginResolve(P.qdomain, P.qtype, ret); + if(res<0) + R->setRcode(RCode::ServFail); + else { + R->setRcode(res); + for(vector::const_iterator i=ret.begin();i!=ret.end();++i) + R->addRecord(*i); + } + + const char *buffer=R->getData(); + if(!R->getSocket()) + sendto(d_serversock,buffer,R->len,0,(struct sockaddr *)(R->remote),R->d_socklen); + else { + char buf[2]; + buf[0]=R->len/256; + buf[1]=R->len%256; + if(send(R->getSocket(),buf,2,0)!=2 || send(R->getSocket(),buffer,R->len,0)!=R->len) + L<getTid()<<"] answer to "<<(P.d.rd?"":"non-rd ")<<"question '"<d.ancount)<<" answers, "<d.arcount)<<" additional, took "<= 0) + break; + + } + if(!tries) + throw AhuException("Resolver binding to local socket: "+stringerror()); +} + +void makeTCPServerSocket() +{ + d_tcpserversock=socket(AF_INET, SOCK_STREAM,0); + if(d_tcpserversock<0) + throw AhuException("Making a server socket for resolver: "+stringerror()); + + struct sockaddr_in sin; + memset((char *)&sin,0, sizeof(sin)); + + sin.sin_family = AF_INET; + + if(arg()["local-address"]=="0.0.0.0") { + sin.sin_addr.s_addr = INADDR_ANY; + } + else { + if(!IpToU32(arg()["local-address"], &sin.sin_addr.s_addr)) + throw AhuException("Unable to resolve local address"); + } + + sin.sin_port = htons(arg().asNum("local-port")); + + if (bind(d_tcpserversock, (struct sockaddr *)&sin, sizeof(sin))<0) + throw AhuException("TCP Resolver binding to server socket: "+stringerror()); + + int tmp=1; + if(setsockopt(d_tcpserversock,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) { + L<30) { + doPrune(); + last_prune=time(0); + } + if(time(0)-last_stat>1800) { + doStats(); + last_stat=time(0); + } + if(time(0)-last_rootupdate>7200) { + SyncRes sr; + vectorret; + + sr.setNoCache(); + int res=sr.beginResolve("", QType(QType::NS), ret); + if(!res) { + L<(100000); + + char data[1500]; + struct sockaddr_in fromaddr; + + PacketID pident; + primeHints(); + L< tcpconnections; + for(;;) { + while(MT->schedule()); // housekeeping, let threads do their thing + + if(!((counter++)%100)) + MT->makeThread(houseKeeping,0); + if(statsWanted) + doStats(); + + Utility::socklen_t addrlen=sizeof(fromaddr); + int d_len; + DNSPacket P; + + struct timeval tv; + tv.tv_sec=0; + tv.tv_usec=500000; + + fd_set readfds; + FD_ZERO( &readfds ); + FD_SET( d_clientsock, &readfds ); + FD_SET( d_serversock, &readfds ); + FD_SET( d_tcpserversock, &readfds ); + int fdmax=max(d_tcpserversock,max(d_clientsock,d_serversock)); + for(vector::const_iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) { + FD_SET(i->fd, &readfds); + fdmax=max(fdmax,i->fd); + } + + + /* this should listen on a TCP port as well for new connections, */ + int selret = select( fdmax + 1, &readfds, NULL, NULL, &tv ); + if(selret<=0) + if (selret == -1 && errno!=EINTR) + throw AhuException("Select returned: "+stringerror()); + else + continue; + + if(FD_ISSET(d_clientsock,&readfds)) { // do we have a question response? + d_len=recvfrom(d_clientsock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen); + if(d_len<0) + continue; + + P.setRemote((struct sockaddr *)&fromaddr, addrlen); + if(P.parse(data,d_len)<0) { + L<sendEvent(pident,&packet); + } + else + L<makeThread(startDoResolve,(void*)new DNSPacket(P)); + + } + } + } + + if(FD_ISSET(d_tcpserversock,&readfds)) { // do we have a new TCP connection + struct sockaddr_in addr; + Utility::socklen_t addrlen=sizeof(addr); + int newsock=accept(d_tcpserversock, (struct sockaddr*)&addr, &addrlen); + Utility::setNonBlocking(newsock); + + if(newsock>0) { + TCPConnection tc; + tc.fd=newsock; + tc.state=TCPConnection::BYTE0; + tc.remote=addr; + L<::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) { + if(FD_ISSET(i->fd, &readfds)) { + if(i->state==TCPConnection::BYTE0) { + int bytes=recv(i->fd,i->data,2,0); + if(bytes==1) + i->state=TCPConnection::BYTE1; + if(bytes==2) { + i->qlen=(i->data[0]<<8)+i->data[1]; + i->bytesread=0; + i->state=TCPConnection::GETQUESTION; + } + if(!bytes || bytes < 0) { + L<remote,sizeof(i->remote))<<" disconnected"<fd); + tcpconnections.erase(i); + break; + } + } + else if(i->state==TCPConnection::BYTE1) { + int bytes=recv(i->fd,i->data+1,1,0); + if(bytes==1) { + i->state=TCPConnection::GETQUESTION; + i->qlen=(i->data[0]<<8)+i->data[1]; + i->bytesread=0; + } + if(!bytes || bytes < 0) { + L<remote,sizeof(i->remote))<<" disconnected after first byte"<fd); + tcpconnections.erase(i); + break; + } + + } + else if(i->state==TCPConnection::GETQUESTION) { + int bytes=recv(i->fd,i->data + i->bytesread,i->qlen - i->bytesread,0); + if(!bytes || bytes < 0) { + L<remote,sizeof(i->remote))<<" disconnected while reading question body"<fd); + tcpconnections.erase(i); + break; + } + i->bytesread+=bytes; + if(i->bytesread==i->qlen) { + i->state=TCPConnection::BYTE0; + + if(P.parse(i->data,i->qlen)<0) { + L<fd); + tcpconnections.erase(i); + break; + } + else { + P.setSocket(i->fd); + P.setRemote((struct sockaddr *)&i->remote,sizeof(i->remote)); + if(P.d.qr) + L<makeThread(startDoResolve,(void*)new DNSPacket(P)); + } + } + } + } + } + } + } + } + catch(AhuException &ae) { + L<start( argc, argv, arg().mustDo( "ntservice" )); + + } + catch(AhuException &ae) { + L<