[-]
[+]
|
Added |
pdns-recursor.changes
|
|
[-]
[+]
|
Changed |
pdns-recursor.spec
^
|
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.5-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.5_atomicity.patch
^
|
@@ -1,24 +0,0 @@
-Index: recursor_cache.cc
-===================================================================
---- recursor_cache.cc.orig 2006-11-12 17:56:13.000000000 +0100
-+++ recursor_cache.cc 2007-02-27 21:44:27.347571093 +0100
-@@ -9,9 +9,17 @@ using namespace std;
- using namespace boost;
-
- #include "config.h"
--
--#ifdef GCC_SKIP_LOCKING
-+#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && defined(GCC_SKIP_LOCKING)
-+#warning "using the optimized locking code on older gcc"
-+#if HAVE_BITS_ATOMICITY_H
- #include <bits/atomicity.h>
-+#endif
-+/*
-+this is just a reminder. in gcc 4.2 it seems atomicity.h was moved under ext/
-+#if HAVE_EXT_ATOMICITY_H
-+#include <ext/atomicity.h>
-+#endif
-+*/
- // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor
- namespace __gnu_cxx
- {
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.5_config.patch
^
|
@@ -1,12 +0,0 @@
-Index: config.h
-===================================================================
---- config.h.orig
-+++ config.h
-@@ -1,5 +1,5 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns/"
- #define VERSION "3.1.5"
- #define RECURSOR
- #ifndef WIN32
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.6-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.6_atomicity.patch
^
|
@@ -1,24 +0,0 @@
-Index: recursor_cache.cc
-===================================================================
---- recursor_cache.cc.orig 2006-11-12 17:56:13.000000000 +0100
-+++ recursor_cache.cc 2007-02-27 21:44:27.347571093 +0100
-@@ -9,9 +9,17 @@ using namespace std;
- using namespace boost;
-
- #include "config.h"
--
--#ifdef GCC_SKIP_LOCKING
-+#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && defined(GCC_SKIP_LOCKING)
-+#warning "using the optimized locking code on older gcc"
-+#if HAVE_BITS_ATOMICITY_H
- #include <bits/atomicity.h>
-+#endif
-+/*
-+this is just a reminder. in gcc 4.2 it seems atomicity.h was moved under ext/
-+#if HAVE_EXT_ATOMICITY_H
-+#include <ext/atomicity.h>
-+#endif
-+*/
- // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor
- namespace __gnu_cxx
- {
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.6_config.patch
^
|
@@ -1,12 +0,0 @@
-Index: config.h
-===================================================================
---- config.h.orig
-+++ config.h
-@@ -1,5 +1,5 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns/"
- #define VERSION "3.1.6"
- #define RECURSOR
- #ifndef WIN32
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7-makefile.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile.orig 2008-06-28 14:43:11.000000000 +0200
-+++ Makefile 2008-06-28 14:43:58.000000000 +0200
-@@ -42,7 +42,9 @@
- STATICFLAGS=-Wl,-Bstatic -lstdc++ $(LUALIBS) -lgcc -Wl,-Bdynamic -static-libgcc -lm -lc
- LINKCC=$(CC)
- LDFLAGS += malloc.o -ldl -lm
--else ifeq ($(STATIC),full)
-+endif
-+
-+ifeq ($(STATIC),full)
- STATICFLAGS=-lstdc++ $(LUALIBS) -ldl -lm -static
- LINKCC=$(CC)
- else
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.1-makefile.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile.orig 2008-06-28 14:43:11.000000000 +0200
-+++ Makefile 2008-06-28 14:43:58.000000000 +0200
-@@ -42,7 +42,9 @@
- STATICFLAGS=-Wl,-Bstatic -lstdc++ $(LUALIBS) -lgcc -Wl,-Bdynamic -static-libgcc -lm -lc
- LINKCC=$(CC)
- LDFLAGS += malloc.o -ldl -lm
--else ifeq ($(STATIC),full)
-+endif
-+
-+ifeq ($(STATIC),full)
- STATICFLAGS=-lstdc++ $(LUALIBS) -ldl -lm -static
- LINKCC=$(CC)
- else
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.1-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.1_atomicity.patch
^
|
@@ -1,24 +0,0 @@
-Index: recursor_cache.cc
-===================================================================
---- recursor_cache.cc.orig 2006-11-12 17:56:13.000000000 +0100
-+++ recursor_cache.cc 2007-02-27 21:44:27.347571093 +0100
-@@ -9,9 +9,17 @@ using namespace std;
- using namespace boost;
-
- #include "config.h"
--
--#ifdef GCC_SKIP_LOCKING
-+#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && defined(GCC_SKIP_LOCKING)
-+#warning "using the optimized locking code on older gcc"
-+#if HAVE_BITS_ATOMICITY_H
- #include <bits/atomicity.h>
-+#endif
-+/*
-+this is just a reminder. in gcc 4.2 it seems atomicity.h was moved under ext/
-+#if HAVE_EXT_ATOMICITY_H
-+#include <ext/atomicity.h>
-+#endif
-+*/
- // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor
- namespace __gnu_cxx
- {
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.1_config.patch
^
|
@@ -1,10 +0,0 @@
---- config.h.orig 2009-08-02 22:22:51.000000000 +0200
-+++ config.h 2009-08-03 09:16:59.000000000 +0200
-@@ -1,5 +1,5 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns/"
- #define VERSION "3.1.7.1"
- #define RECURSOR
- #ifndef WIN32
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.2-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.2_atomicity.patch
^
|
@@ -1,24 +0,0 @@
-Index: recursor_cache.cc
-===================================================================
---- recursor_cache.cc.orig 2006-11-12 17:56:13.000000000 +0100
-+++ recursor_cache.cc 2007-02-27 21:44:27.347571093 +0100
-@@ -9,9 +9,17 @@ using namespace std;
- using namespace boost;
-
- #include "config.h"
--
--#ifdef GCC_SKIP_LOCKING
-+#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && defined(GCC_SKIP_LOCKING)
-+#warning "using the optimized locking code on older gcc"
-+#if HAVE_BITS_ATOMICITY_H
- #include <bits/atomicity.h>
-+#endif
-+/*
-+this is just a reminder. in gcc 4.2 it seems atomicity.h was moved under ext/
-+#if HAVE_EXT_ATOMICITY_H
-+#include <ext/atomicity.h>
-+#endif
-+*/
- // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor
- namespace __gnu_cxx
- {
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7.2_config.patch
^
|
@@ -1,10 +0,0 @@
---- config.h.orig 2009-08-02 22:22:51.000000000 +0200
-+++ config.h 2009-08-03 09:16:59.000000000 +0200
-@@ -1,5 +1,5 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns/"
- #define VERSION "3.1.7.2"
- #define RECURSOR
- #ifndef WIN32
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7_atomicity.patch
^
|
@@ -1,24 +0,0 @@
-Index: recursor_cache.cc
-===================================================================
---- recursor_cache.cc.orig 2006-11-12 17:56:13.000000000 +0100
-+++ recursor_cache.cc 2007-02-27 21:44:27.347571093 +0100
-@@ -9,9 +9,17 @@ using namespace std;
- using namespace boost;
-
- #include "config.h"
--
--#ifdef GCC_SKIP_LOCKING
-+#if !(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) && defined(GCC_SKIP_LOCKING)
-+#warning "using the optimized locking code on older gcc"
-+#if HAVE_BITS_ATOMICITY_H
- #include <bits/atomicity.h>
-+#endif
-+/*
-+this is just a reminder. in gcc 4.2 it seems atomicity.h was moved under ext/
-+#if HAVE_EXT_ATOMICITY_H
-+#include <ext/atomicity.h>
-+#endif
-+*/
- // This code is ugly but does speedup the recursor tremendously on multi-processor systems, and even has a large effect (20, 30%) on uniprocessor
- namespace __gnu_cxx
- {
|
[-]
[+]
|
Deleted |
pdns-recursor-3.1.7_config.patch
^
|
@@ -1,12 +0,0 @@
-Index: config.h
-===================================================================
---- config.h.orig
-+++ config.h
-@@ -1,5 +1,5 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns/"
- #define VERSION "3.1.7"
- #define RECURSOR
- #ifndef WIN32
|
[-]
[+]
|
Deleted |
pdns-recursor-3.2-strip.patch
^
|
@@ -1,13 +0,0 @@
---- Makefile
-+++ Makefile
-@@ -54,10 +54,8 @@
- install: all
- -mkdir -p $(DESTDIR)/$(SBINDIR)
- mv pdns_recursor $(DESTDIR)/$(SBINDIR)
-- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
- mkdir -p $(DESTDIR)/$(BINDIR)
- mv rec_control $(DESTDIR)/$(BINDIR)
-- strip $(DESTDIR)/$(BINDIR)/rec_control
- -mkdir -p $(DESTDIR)/$(CONFIGDIR)
- $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
- -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Deleted |
pdns-recursor-3.2_config.patch
^
|
@@ -1,9 +0,0 @@
---- config.h.orig 2010-03-06 13:10:44.000000000 +0100
-+++ config.h 2010-03-08 07:04:56.000000000 +0100
-@@ -1,4 +1,4 @@
--#define SYSCONFDIR "/etc/powerdns/"
--#define LOCALSTATEDIR "/var/run/"
-+#define SYSCONFDIR "/etc/pdns/"
-+#define LOCALSTATEDIR "/var/run/pdns"
- #define VERSION "3.2"
- #define RECURSOR
|
[-]
[+]
|
Added |
pdns-recursor-3.3-strip.patch
^
|
@@ -0,0 +1,13 @@
+--- Makefile
++++ Makefile
+@@ -54,10 +54,8 @@
+ install: all
+ -mkdir -p $(DESTDIR)/$(SBINDIR)
+ mv pdns_recursor $(DESTDIR)/$(SBINDIR)
+- strip $(DESTDIR)/$(SBINDIR)/pdns_recursor
+ mkdir -p $(DESTDIR)/$(BINDIR)
+ mv rec_control $(DESTDIR)/$(BINDIR)
+- strip $(DESTDIR)/$(BINDIR)/rec_control
+ -mkdir -p $(DESTDIR)/$(CONFIGDIR)
+ $(DESTDIR)/$(SBINDIR)/pdns_recursor --config > $(DESTDIR)/$(CONFIGDIR)/recursor.conf-dist
+ -mkdir -p $(DESTDIR)/usr/share/man/man1
|
[-]
[+]
|
Added |
pdns-recursor-3.3_config.patch
^
|
@@ -0,0 +1,9 @@
+--- config.h.orig 2010-03-06 13:10:44.000000000 +0100
++++ config.h 2010-03-08 07:04:56.000000000 +0100
+@@ -1,4 +1,4 @@
+-#define SYSCONFDIR "/etc/powerdns/"
+-#define LOCALSTATEDIR "/var/run/"
++#define SYSCONFDIR "/etc/pdns/"
++#define LOCALSTATEDIR "/var/run/pdns"
+ #define VERSION "3.2"
+ #define RECURSOR
|
[-]
[+]
|
Added |
pdns-recursor-init-rh.patch
^
|
@@ -0,0 +1,38 @@
+--- pdns-recursor.init.d.orig 2011-01-20 23:58:11.527523104 +0100
++++ pdns-recursor.init.d 2011-01-20 23:59:08.827170729 +0100
+@@ -13,7 +13,7 @@
+
+ doPC()
+ {
+- ret=`$BINARYPATH/rec_control $EXTRAOPTS $1 $2 2> /dev/null`
++ ret=`$SBINARYPATH/rec_control $EXTRAOPTS $1 $2 2> /dev/null`
+ }
+
+
+@@ -22,7 +22,7 @@
+
+ case "$1" in
+ status)
+- if test "$NOTRUNNING" = "0"
++ if [ "$NOTRUNNING" == "0" ]
+ then
+ echo "running"
+ else
+@@ -32,7 +32,7 @@
+
+ stop)
+ echo -n "Stopping PowerDNS recursing nameserver: "
+- if test "$NOTRUNNING" = "0"
++ if [ "$NOTRUNNING" == "0" ]
+ then
+ doPC quit
+ echo $ret
+@@ -50,7 +50,7 @@
+
+ start)
+ echo -n "Starting PowerDNS recursing nameserver: "
+- if test "$NOTRUNNING" = "0"
++ if [ "$NOTRUNNING" == "0" ]
+ then
+ echo "already running"
+ else
|
|
Added |
boost_1_39_0.tar.bz2
^
|
[-]
[+]
|
Deleted |
pdns-recursor-3.2.tar.bz2/lua-pdns-recursor.cc
^
|
@@ -1,270 +0,0 @@
-#include "lua-pdns-recursor.hh"
-
-#if !defined(PDNS_ENABLE_LUA) && !defined(LIBDIR)
-
-// stub implementation
-
-PowerDNSLua::PowerDNSLua(const std::string& fname)
-{
- throw runtime_error("Lua support disabled");
-}
-
-bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
-{
- return false;
-}
-
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
-{
- return false;
-}
-
-PowerDNSLua::~PowerDNSLua()
-{
-
-}
-
-#else
-
-extern "C" {
-#undef L
-/* Include the Lua API header files. */
-#include <lua.h>
-#include <lauxlib.h>
-#include <lualib.h>
-}
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string>
-#include <vector>
-#include <stdexcept>
-#include "logger.hh"
-using namespace std;
-
-bool netmaskMatchTable(lua_State* lua, const std::string& ip)
-{
- lua_pushnil(lua); /* first key */
- while (lua_next(lua, 2) != 0) {
- string netmask=lua_tostring(lua, -1);
- Netmask nm(netmask);
- ComboAddress ca(ip);
- lua_pop(lua, 1);
-
- if(nm.match(ip))
- return true;
- }
- return false;
-}
-
-extern "C" {
-
-int netmaskMatchLua(lua_State *lua)
-{
- bool result=false;
- if(lua_gettop(lua) >= 2) {
- string ip=lua_tostring(lua, 1);
- if(lua_istable(lua, 2)) {
- result = netmaskMatchTable(lua, ip);
- }
- else {
- for(int n=2 ; n <= lua_gettop(lua); ++n) {
- string netmask=lua_tostring(lua, n);
- Netmask nm(netmask);
- ComboAddress ca(ip);
-
- result = nm.match(ip);
- if(result)
- break;
- }
- }
- }
-
- lua_pushboolean(lua, result);
- return 1;
-}
-
-int getLocalAddressLua(lua_State* lua)
-{
- lua_getfield(lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
- PowerDNSLua* pl = (PowerDNSLua*)lua_touserdata(lua, -1);
-
- lua_pushstring(lua, pl->getLocal().toString().c_str());
- return 1;
-}
-
-int logLua(lua_State *lua)
-{
- if(lua_gettop(lua) >= 1) {
- string message=lua_tostring(lua, 1);
- theL()<<Logger::Error<<"From Lua script: "<<message<<endl;
- }
- return 0;
-}
-}
-
-PowerDNSLua::PowerDNSLua(const std::string& fname)
-{
- d_lua = lua_open();
-
-#ifndef LUA_VERSION_NUM
- luaopen_base(d_lua);
- luaopen_string(d_lua);
-
- if(lua_dofile(d_lua, fname.c_str()))
-#else
- luaL_openlibs(d_lua);
- if(luaL_dofile(d_lua, fname.c_str()))
-#endif
- throw runtime_error(string("Error loading LUA file '")+fname+"': "+ string(lua_isstring(d_lua, -1) ? lua_tostring(d_lua, -1) : "unknown error"));
-
- lua_settop(d_lua, 0);
-
- lua_pushcfunction(d_lua, netmaskMatchLua);
- lua_setglobal(d_lua, "matchnetmask");
-
- lua_pushcfunction(d_lua, logLua);
- lua_setglobal(d_lua, "pdnslog");
-
- lua_pushcfunction(d_lua, getLocalAddressLua);
- lua_setglobal(d_lua, "getlocaladdress");
-
- lua_newtable(d_lua);
-
- for(vector<QType::namenum>::const_iterator iter = QType::names.begin(); iter != QType::names.end(); ++iter) {
- lua_pushnumber(d_lua, iter->second);
- lua_setfield(d_lua, -2, iter->first.c_str());
- }
- lua_pushnumber(d_lua, 3);
- lua_setfield(d_lua, -2, "NXDOMAIN");
- lua_setglobal(d_lua, "pdns");
-
- lua_pushlightuserdata(d_lua, (void*)this);
- lua_setfield(d_lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
-}
-
-bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
-{
- return passthrough("nxdomain", remote, local, query, qtype, ret, res);
-}
-
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
-{
- return passthrough("preresolve", remote, local, query, qtype, ret, res);
-}
-
-bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
-{
- lua_pushstring(d_lua, key.c_str()); // 4 is now '1'
- lua_gettable(d_lua, -2); // replace by the first entry of our table we hope
-
- bool ret=false;
- if(!lua_isnil(d_lua, -1)) {
- value = lua_tostring(d_lua, -1);
- ret=true;
- }
- lua_pop(d_lua, 1);
- return ret;
-}
-
-
-bool PowerDNSLua::getFromTable(const std::string& key, uint32_t& value)
-{
- lua_pushstring(d_lua, key.c_str()); // 4 is now '1'
- lua_gettable(d_lua, -2); // replace by the first entry of our table we hope
-
- bool ret=false;
- if(!lua_isnil(d_lua, -1)) {
- value = (uint32_t)lua_tonumber(d_lua, -1);
- ret=true;
- }
- lua_pop(d_lua, 1);
- return ret;
-}
-
-
-bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
-{
- lua_getglobal(d_lua, func.c_str());
- if(!lua_isfunction(d_lua, -1)) {
- // cerr<<"No such function '"<<func<<"'\n";
- lua_pop(d_lua, 1);
- return false;
- }
-
- d_local = local;
- /* the first argument */
- lua_pushstring(d_lua, remote.toString().c_str() );
- lua_pushstring(d_lua, query.c_str() );
- lua_pushnumber(d_lua, qtype.getCode() );
-
- if(lua_pcall(d_lua, 3, 2, 0)) { // error
- string error=string("lua error in '"+func+"': ")+lua_tostring(d_lua, -1);
- lua_pop(d_lua, 1);
- throw runtime_error(error);
- return false;
- }
- int newres = (int)lua_tonumber(d_lua, 1); // new rcode
- if(newres < 0) {
- // cerr << "handler did not handle"<<endl;
- lua_pop(d_lua, 2);
- return false;
- }
- res=newres;
-
- /* get the result */
- DNSResourceRecord rr;
- rr.qname = query;
- rr.d_place = DNSResourceRecord::ANSWER;
- rr.ttl = 3600;
-
- ret.clear();
-
- /* 1 2 3 4 */
- /* stack: boolean table key row */
-
-#ifndef LUA_VERSION_NUM
- int tableLen = luaL_getn(d_lua, 2);
-#else
- int tableLen = lua_objlen(d_lua, 2);
-#endif
-
- for(int n=1; n < tableLen + 1; ++n) {
- lua_pushnumber(d_lua, n);
- lua_gettable(d_lua, 2);
-
- uint32_t tmpnum=0;
- if(!getFromTable("qtype", tmpnum))
- rr.qtype=QType::A;
- else
- rr.qtype=tmpnum;
-
- getFromTable("content", rr.content);
- if(!getFromTable("ttl", rr.ttl))
- rr.ttl=3600;
-
- if(!getFromTable("qname", rr.qname))
- rr.qname = query;
-
- if(!getFromTable("place", tmpnum))
- rr.d_place = DNSResourceRecord::ANSWER;
- else
- rr.d_place = (DNSResourceRecord::Place) tmpnum;
-
- /* removes 'value'; keeps 'key' for next iteration */
- lua_pop(d_lua, 1); // table
-
- // cerr<<"Adding content '"<<rr.content<<"' with place "<<(int)rr.d_place<<" \n";
- ret.push_back(rr);
- }
-
- lua_pop(d_lua, 2);
-
- return true;
-}
-
-PowerDNSLua::~PowerDNSLua()
-{
- lua_close(d_lua);
-}
-#endif
|
[-]
[+]
|
Deleted |
pdns-recursor-3.2.tar.bz2/lua-pdns-recursor.hh
^
|
@@ -1,31 +0,0 @@
-#ifndef PDNS_LUA_PDNS_RECURSOR_HH
-#define PDNS_LUA_PDNS_RECURSOR_HH
-#include "dns.hh"
-#include "iputils.hh"
-
-struct lua_State;
-
-class PowerDNSLua
-{
-public:
- explicit PowerDNSLua(const std::string& fname);
- ~PowerDNSLua();
- void reload();
- bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
- bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
-
- ComboAddress getLocal()
- {
- return d_local;
- }
-private:
- lua_State* d_lua;
- bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res);
- bool getFromTable(const std::string& key, std::string& value);
- bool getFromTable(const std::string& key, uint32_t& value);
- bool d_failed;
-
- ComboAddress d_local;
-};
-
-#endif
|
|
Changed |
pdns-recursor-3.5.1.tar.bz2
^
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/COPYING
^
|
@@ -1,12 +1,12 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
- Preamble
+ Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -15,7 +15,7 @@
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
+the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@
The precise terms and conditions for copying, distribution and
modification follow.
-
- GNU GENERAL PUBLIC LICENSE
+
+ GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
-
+
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
-
+
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
-
+
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
- NO WARRANTY
+ NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -303,17 +303,16 @@
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
-
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
@@ -336,5 +335,5 @@
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
\ No newline at end of file
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/Makefile
^
|
@@ -3,9 +3,9 @@
BINDIR=/usr/bin/
CONFIGDIR="/etc/powerdns/"
OPTFLAGS?=-O3
-CXXFLAGS:= $(CXXFLAGS) -Wall $(OPTFLAGS) $(PROFILEFLAGS) -pthread
-CFLAGS:=$(CFLAGS) -Wall $(OPTFLAGS) $(PROFILEFLAGS) -pthread
-LDFLAGS:=$(LDFLAGS) -pthread
+CXXFLAGS:= $(CXXFLAGS) -Iext/rapidjson/include -Wall $(OPTFLAGS) $(PROFILEFLAGS) $(ARCHFLAGS) -pthread
+CFLAGS:=$(CFLAGS) -Wall $(OPTFLAGS) $(PROFILEFLAGS) $(ARCHFLAGS) -pthread
+LDFLAGS:=$(LDFLAGS) $(ARCHFLAGS) -pthread
LINKCC=$(CXX)
CC?=gcc
@@ -18,10 +18,12 @@
arguments.o lwres.o pdns_recursor.o recursor_cache.o dnsparser.o \
dnswriter.o dnsrecords.o rcpgenerator.o base64.o zoneparser-tng.o \
rec_channel.o rec_channel_rec.o selectmplexer.o sillyrecords.o \
-dns_random.o aescrypt.o aeskey.o aes_modes.o aestab.o lua-pdns-recursor.o \
-randomhelper.o recpacketcache.o dns.o reczones.o
+dns_random.o aescrypt.o aeskey.o aes_modes.o aestab.o dnslabeltext.o \
+lua-pdns.o lua-recursor.o randomhelper.o recpacketcache.o dns.o \
+reczones.o base32.o nsecrecords.o json.o json_ws.o
-REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o
+REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o misc.o \
+ unix_utility.o logger.o qtype.o
# what we need
all: message pdns_recursor rec_control
@@ -31,7 +33,7 @@
ifeq ($(LUA), 1)
LUALIBS=$(LUA_LIBS_CONFIG)
- CXXFLAGS+=$(LUA_CPPFLAGS_CONFIG) -DPDNS_ENABLE_LUA
+ CXXFLAGS+=$(LUA_CPPFLAGS_CONFIG) -DPDNS_ENABLE_LUA -DHAVE_LUA
endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/README
^
|
@@ -87,8 +87,3 @@
------------------------------
To prevent hassles with g++/c++ dependencies, you can build like this:
$ STATIC=semi make all
-
-PROBLEMS
---------
-If you have problems linking, try removing the GCC_SKIP_LOCKING line from
-config.h
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/aeskey.c
^
|
@@ -406,8 +406,10 @@
cx->ks[v(48,(3))] = ss[3] = word_in(key, 3);
#ifdef DEC_KS_UNROLL
- cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4));
- cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5));
+ ss[4] = word_in(key, 4);
+ cx->ks[v(48,(4))] = ff(ss[4]);
+ ss[5] = word_in(key, 5);
+ cx->ks[v(48,(5))] = ff(ss[5]);
kdf6(cx->ks, 0); kd6(cx->ks, 1);
kd6(cx->ks, 2); kd6(cx->ks, 3);
kd6(cx->ks, 4); kd6(cx->ks, 5);
@@ -486,6 +488,7 @@
ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \
}
+#if 0
AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1])
{ uint_32t ss[9];
#if defined( d_vars )
@@ -497,10 +500,14 @@
cx->ks[v(56,(3))] = ss[3] = word_in(key, 3);
#ifdef DEC_KS_UNROLL
- cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4));
- cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5));
- cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6));
- cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7));
+ ss[4] = word_in(key, 4);
+ cx->ks[v(56,(4))] = ff(ss[4]);
+ ss[4] = word_in(key, 5);
+ cx->ks[v(56,(5))] = ff(ss[5]);
+ ss[4] = word_in(key, 6);
+ cx->ks[v(56,(6))] = ff(ss[6]);
+ ss[4] = word_in(key, 7);
+ cx->ks[v(56,(7))] = ff(ss[7]);
kdf8(cx->ks, 0); kd8(cx->ks, 1);
kd8(cx->ks, 2); kd8(cx->ks, 3);
kd8(cx->ks, 4); kd8(cx->ks, 5);
@@ -530,11 +537,13 @@
#endif
return EXIT_SUCCESS;
}
+#endif
#endif
#if defined( AES_VAR )
+#if 0
AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1])
{
switch(key_len)
@@ -545,6 +554,7 @@
default: return EXIT_FAILURE;
}
}
+#endif
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/ahuexception.hh
^
|
@@ -22,7 +22,7 @@
#include<string>
-using namespace std;
+#include "namespaces.hh"
//! Generic Exception thrown
class AhuException
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/arguments.cc
^
|
@@ -327,6 +327,7 @@
void ArgvMap::parse(int &argc, char **argv, bool lax)
{
+ d_cmds.clear();
for(int n=1;n<argc;n++) {
parseOne(argv[n],"",lax);
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/arguments.hh
^
|
@@ -32,7 +32,7 @@
# include <grp.h>
#endif
-using namespace std;
+#include "namespaces.hh"
typedef AhuException ArgException;
@@ -94,7 +94,7 @@
bool mustDo(const string &var); //!< if a switch is given, if we must do something (--help)
int asNum(const string &var); //!< return a variable value as a number
#ifndef WIN32
- mode_t asMode(const string &var); //<!< return value interprepted as octal number
+ mode_t asMode(const string &var); //<!< return value interpreted as octal number
uid_t asUid(const string &var); //!< return user id, resolves if necessary
gid_t asGid(const string &var); //!< return group id, resolves if necessary
#endif
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/base32.cc
^
|
@@ -0,0 +1,143 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string>
+#include <cstring>
+#include <stdlib.h>
+#include <iostream>
+#include "base32.hh"
+#include "namespaces.hh"
+
+/* based on freebsd:src/contrib/opie/libopie/btoe.c extract: get bit ranges from a char* */
+/* NOTE: length should not exceed 8; all callers inside PowerDNS only pass length=5 though */
+unsigned char extract_bits(const char *s, int start, int length)
+{
+ uint16_t x;
+ unsigned char cl, cc;
+
+ if(!length)
+ return 0;
+
+ cl = s[start / 8];
+ if(start / 8 < (start + length-1)/8)
+ cc = s[start / 8 + 1];
+ else
+ cc = 0;
+
+ x = (uint16_t) (cl << 8 | cc);
+ x = x >> (16 - (length + (start % 8)));
+ x = (x & (0xffff >> (16 - length)));
+ return (x);
+}
+
+/* same, set bit ranges in a char* */
+static void set_bits(char* s, int x, int start, int length)
+{
+ unsigned char cl, cc, cr;
+ uint32_t y;
+ int shift;
+
+ shift = ((8 - ((start + length) % 8)) % 8);
+ y = (uint32_t) x << shift;
+ cl = (y >> 16) & 0xff;
+ cc = (y >> 8) & 0xff;
+ cr = y & 0xff;
+ if (shift + length > 16) {
+ s[start / 8] |= cl;
+ s[start / 8 + 1] |= cc;
+ s[start / 8 + 2] |= cr;
+ }
+ else {
+ if (shift + length > 8) {
+ s[start / 8] |= cc;
+ s[start / 8 + 1] |= cr;
+ } else {
+ s[start / 8] |= cr;
+ }
+ }
+}
+
+/* convert a base32 hex character to its decoded equivalent */
+static int unbase32hex(char c)
+{
+ if(c >= '0' && c<='9')
+ return c-'0';
+ if(c >= 'a' && c<='z')
+ return 10 + (c-'a');
+ if(c >= 'A' && c<='Z')
+ return 10 + (c-'A');
+ if(c=='=')
+ return '=';
+ return -1;
+}
+
+/* convert a binary string to base32hex */
+string toBase32Hex(const std::string& input)
+{
+ static const char base32hex[] = "0123456789ABCDEFGHIJKLMNOPQRSTUV=";
+ string ret;
+ ret.reserve(4+ 8*input.length()/5); // optimization
+ // process input in groups of 5 8-bit chunks, emit 8 5-bit chunks
+ for(string::size_type offset = 0 ; offset < input.length(); offset+=5) {
+ int todo = input.length() - offset;
+ int stuffing; // how much '=' to add at the end
+
+ switch(todo) {
+ case 1:
+ stuffing = 6; break;
+ case 2:
+ stuffing = 4; break;
+ case 3:
+ stuffing = 3; break;
+ case 4:
+ stuffing = 1; break;
+ default: // -> 0 or more than 5, no stuffing
+ stuffing = 0; break;
+ }
+
+ for(int n=0; n < 8 - stuffing; ++n)
+ ret.append(1, base32hex[extract_bits(input.c_str()+offset, n*5, 5)]);
+ ret.append(stuffing, '=');
+ }
+
+ return ret;
+}
+
+// convert base32hex encoded string to normal string
+string fromBase32Hex(const std::string& input)
+{
+ string ret;
+ char block[5]={0,0,0,0,0}; // we process 5 8-bit chunks at a time
+ string::size_type n, toWrite=0;
+ for(n = 0; n < input.length(); ++n) {
+ int c=unbase32hex(input[n]);
+ if(c == '=' || c < 0) // stop at stuffing or error
+ break;
+ set_bits(block, c , (n % 8) * 5, 5);
+ if(++toWrite == 8) {
+ ret.append(block, sizeof(block));
+ memset(block, 0, sizeof(block));
+ toWrite = 0;
+ }
+ }
+ ret.append(block, (toWrite*5)/8);
+
+ return ret;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+ if(argc!=3 || (argc==3 && strcmp(argv[1],"from") && strcmp(argv[1],"to"))) {
+ printf("syntax: base32 from|to string\n");
+ exit(0);
+ }
+ if(!strcmp(argv[1],"to")) {
+ printf("input: '%s'\noutput: '%s'\n",
+ argv[2],
+ toBase32Hex(argv[2]).c_str());
+ }
+ else {
+ cout<<"input: '"<<argv[2]<<"'\noutput: '"<<fromBase32Hex(argv[2])<<"'\n";
+ }
+}
+#endif
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/base32.hh
^
|
@@ -0,0 +1,8 @@
+#ifndef PDNS_BASE32_HH
+#define PDNS_BASE32_HH
+#include <string>
+
+std::string toBase32Hex(const std::string& input);
+std::string fromBase32Hex(const std::string& input);
+
+#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/base64.cc
^
|
@@ -109,7 +109,7 @@
// incoming Base64 character is first decoded, and
// then it is inserted into the decode buffer
// (with any relevant shifting, as required).
- // Later, after all 3 bytes have been reconsituted,
+ // Later, after all 3 bytes have been reconstituted,
// we assign them to the output string, ultimately
// to be returned as the original message.
int iInSize = strInput.size();
@@ -124,7 +124,8 @@
// Decode a character
if(strInput.at(iInNum)=='=')
pad++;
-
+ while(isspace(strInput.at(iInNum)))
+ iInNum++;
cChar = B64Decode1(strInput.at(iInNum++));
} // if
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/cachecleaner.hh
^
|
@@ -0,0 +1,83 @@
+#ifndef PDNS_CACHECLEANER_HH
+#define PDNS_CACHECLEANER_HH
+
+// this function can clean any cache that has a getTTD() method on its entries, and a 'sequence' index as its second index
+// the ritual is that the oldest entries are in *front* of the sequence collection, so on a hit, move an item to the end
+// on a miss, move it to the beginning
+template <typename T> void pruneCollection(T& collection, unsigned int maxCached, unsigned int scanFraction=1000)
+{
+ uint32_t now=(uint32_t)time(0);
+ unsigned int toTrim=0;
+
+ unsigned int cacheSize=collection.size();
+
+ if(cacheSize > maxCached) {
+ toTrim = cacheSize - maxCached;
+ }
+
+// cout<<"Need to trim "<<toTrim<<" from cache to meet target!\n";
+
+ typedef typename T::template nth_index<1>::type sequence_t;
+ sequence_t& sidx=collection.template get<1>();
+
+ unsigned int tried=0, lookAt, erased=0;
+
+ // two modes - if toTrim is 0, just look through 1/scanFraction of all records
+ // and nuke everything that is expired
+ // otherwise, scan first 5*toTrim records, and stop once we've nuked enough
+ if(toTrim)
+ lookAt=5*toTrim;
+ else
+ lookAt=cacheSize/scanFraction;
+
+ typename sequence_t::iterator iter=sidx.begin(), eiter;
+ for(; iter != sidx.end() && tried < lookAt ; ++tried) {
+ if(iter->getTTD() < now) {
+ sidx.erase(iter++);
+ erased++;
+ }
+ else
+ ++iter;
+
+ if(toTrim && erased > toTrim)
+ break;
+ }
+
+ //cout<<"erased "<<erased<<" records based on ttd\n";
+
+ if(erased >= toTrim) // done
+ return;
+
+ toTrim -= erased;
+
+ //if(toTrim)
+ // cout<<"Still have "<<toTrim - erased<<" entries left to erase to meet target\n";
+
+ eiter=iter=sidx.begin();
+ std::advance(eiter, toTrim);
+ sidx.erase(iter, eiter); // just lob it off from the beginning
+}
+
+
+template <typename T> void moveCacheItemToFrontOrBack(T& collection, typename T::iterator& iter, bool front)
+{
+ typedef typename T::template nth_index<1>::type sequence_t;
+ sequence_t& sidx=collection.template get<1>();
+ typename sequence_t::iterator si=collection.template project<1>(iter);
+ if(front)
+ sidx.relocate(sidx.begin(), si); // at the beginning of the delete queue
+ else
+ sidx.relocate(sidx.end(), si); // back
+}
+
+template <typename T> void moveCacheItemToFront(T& collection, typename T::iterator& iter)
+{
+ moveCacheItemToFrontOrBack(collection, iter, true);
+}
+
+template <typename T> void moveCacheItemToBack(T& collection, typename T::iterator& iter)
+{
+ moveCacheItemToFrontOrBack(collection, iter, false);
+}
+
+#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/config.h
^
|
@@ -1,4 +1,4 @@
#define SYSCONFDIR "/etc/powerdns/"
#define LOCALSTATEDIR "/var/run/"
-#define VERSION "3.2"
+#define VERSION "3.5.2"
#define RECURSOR
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/contrib
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/contrib/systemd-pdns-recursor.service
^
|
@@ -0,0 +1,11 @@
+[Unit]
+Description=PowerDNS recursing nameserver
+After=network.target
+
+[Service]
+Type=forking
+ExecStart=/usr/sbin/pdns_recursor --daemon
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/devpollmplexer.cc
^
|
@@ -8,7 +8,7 @@
#include "syncres.hh"
#include "namespaces.hh"
-using namespace std;
+#include "namespaces.hh"
class DevPollFDMultiplexer : public FDMultiplexer
{
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dns.cc
^
|
@@ -1,14 +1,16 @@
#include "dns.hh"
#include "misc.hh"
+#include "arguments.hh"
#include <stdexcept>
#include <iostream>
#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
static void appendEscapedLabel(string& ret, const char* begin, unsigned char labellen)
{
unsigned char n = 0;
for(n = 0 ; n < labellen; ++n)
- if(begin[n] == '.' || begin[n] == '\\')
+ if(begin[n] == '.' || begin[n] == '\\' || begin[n] == ' ')
break;
if( n == labellen) {
@@ -18,6 +20,7 @@
string label(begin, labellen);
boost::replace_all(label, "\\", "\\\\");
boost::replace_all(label, ".", "\\.");
+ boost::replace_all(label, " ", "\\032");
ret.append(label);
}
@@ -37,7 +40,7 @@
{
if(offset < d_length)
return d_ptr[offset];
- else throw runtime_error("out of bounds");
+ else throw runtime_error("out of bounds: "+boost::lexical_cast<string>(offset)+" >= " + boost::lexical_cast<string>(d_length));
}
private:
const char* d_ptr;
@@ -47,8 +50,9 @@
//! compares two dns packets, skipping the header, but including the question and the qtype
bool dnspacketLessThan(const std::string& a, const std::string& b)
{
- if(a.length() < 12 || b.length() < 12)
- throw runtime_error("Error parsing question in dnspacket comparison: packet too short");
+ if(a.length() <= 12 || b.length() <= 12)
+ return a.length() < b.length();
+// throw runtime_error("Error parsing question in dnspacket comparison: packet too short");
// we find: 3www4ds9a2nl0XXYY, where XX and YY are each 2 bytes describing class and type
@@ -84,7 +88,11 @@
uint16_t aQtype = aSafe[aPos]*256 + aSafe[aPos + 1];
uint16_t bQtype = bSafe[bPos]*256 + bSafe[bPos + 1];
- return aQtype < bQtype;
+
+ uint16_t aQclass = aSafe[aPos+2]*256 + aSafe[aPos + 3];
+ uint16_t bQclass = bSafe[bPos+2]*256 + bSafe[bPos + 3];
+
+ return boost::tie(aQtype, aQclass) < boost::tie(bQtype, bQclass);
}
@@ -117,3 +125,72 @@
// cerr << "returning: '"<<ret<<"'"<<endl;
return ret;
}
+
+void fillSOAData(const string &content, SOAData &data)
+{
+ // content consists of fields separated by spaces:
+ // nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
+
+ // fill out data with some plausible defaults:
+ // 10800 3600 604800 3600
+ vector<string>parts;
+ stringtok(parts,content);
+ int pleft=parts.size();
+
+ // cout<<"'"<<content<<"'"<<endl;
+
+ if(pleft)
+ data.nameserver=parts[0];
+
+ if(pleft>1)
+ data.hostmaster=attodot(parts[1]); // ahu@ds9a.nl -> ahu.ds9a.nl, piet.puk@ds9a.nl -> piet\.puk.ds9a.nl
+
+ data.serial = pleft > 2 ? strtoul(parts[2].c_str(), NULL, 10) : 0;
+
+ data.refresh = pleft > 3 ? atoi(parts[3].c_str())
+ : ::arg().asNum("soa-refresh-default");
+
+ data.retry = pleft > 4 ? atoi(parts[4].c_str())
+ : ::arg().asNum("soa-retry-default");
+
+ data.expire = pleft > 5 ? atoi(parts[5].c_str())
+ : ::arg().asNum("soa-expire-default");
+
+ data.default_ttl = pleft > 6 ?atoi(parts[6].c_str())
+ : ::arg().asNum("soa-minimum-ttl");
+}
+
+string serializeSOAData(const SOAData &d)
+{
+ ostringstream o;
+ // nameservername hostmaster serial-number [refresh [retry [expire [ minimum] ] ] ]
+ o<<d.nameserver<<" "<< d.hostmaster <<" "<< d.serial <<" "<< d.refresh << " "<< d.retry << " "<< d.expire << " "<< d.default_ttl;
+
+ return o.str();
+}
+// the functions below update the 'arcount' and 'ancount', plus they serialize themselves to the stringbuffer
+
+string& attodot(string &str)
+{
+ if(str.find_first_of("@")==string::npos)
+ return str;
+
+ for (unsigned int i = 0; i < str.length(); i++)
+ {
+ if (str[i] == '@') {
+ str[i] = '.';
+ break;
+ } else if (str[i] == '.') {
+ str.insert(i++, "\\");
+ }
+ }
+ return str;
+}
+
+string strrcode(unsigned char rcode)
+{
+ static const char* rcodes[]={"No Error", "FormErr", "SERVFAIL", "NXDOMAIN", "NotImp", "Refused", "", "", "", "Not Auth"};
+ if((rcode < sizeof(rcodes) / sizeof(*rcodes)) && *rcodes[rcode])
+ return rcodes[rcode];
+ return "Err#"+lexical_cast<string>((int)rcode);
+}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dns.hh
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 PowerDNS.COM BV
+ Copyright (C) 2002 - 2011 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 version 2
@@ -16,7 +16,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-// $Id: dns.hh 1478 2009-12-27 22:18:42Z ahu $
+// $Id$
/* (C) 2002 POWERDNS.COM BV */
#ifndef DNS_HH
#define DNS_HH
@@ -25,6 +25,10 @@
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/serialization/string.hpp>
+#include <boost/serialization/version.hpp>
+
+
#include "utility.hh"
#include "qtype.hh"
#include <time.h>
@@ -33,6 +37,8 @@
struct SOAData
{
+ SOAData() : scopeMask(0) {};
+
string qname;
string nameserver;
string hostmaster;
@@ -44,13 +50,14 @@
uint32_t default_ttl;
int domain_id;
DNSBackend *db;
+ uint8_t scopeMask;
};
class RCode
{
public:
- enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5 };
+ enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, NotAuth=9 };
};
class Opcode
@@ -63,25 +70,43 @@
class DNSResourceRecord
{
public:
- DNSResourceRecord() : qclass(1), priority(0), d_place(ANSWER) {};
+ DNSResourceRecord() : qclass(1), priority(0), signttl(0), last_modified(0), d_place(ANSWER), auth(1), scopeMask(0) {};
~DNSResourceRecord(){};
- string serialize() const;
- int unSerialize(const string &str);
-
// data
QType qtype; //!< qtype of this record, ie A, CNAME, MX etc
uint16_t qclass; //!< class of this record
string qname; //!< the name of this record, for example: www.powerdns.com
+ string wildcardname;
string content; //!< what this record points to. Example: 10.1.2.3
- uint16_t priority; //!< For qtype's that support a priority or preference. Currently only MX
+ uint16_t priority; //!< For qtypes that support a priority or preference (MX, SRV)
uint32_t ttl; //!< Time To Live of this record
+ uint32_t signttl; //!< If non-zero, use this TTL as original TTL in the RRSIG
int domain_id; //!< If a backend implements this, the domain_id of the zone this record is in
time_t last_modified; //!< For autocalculating SOA serial numbers - the backend needs to fill this in
enum Place {QUESTION=0, ANSWER=1, AUTHORITY=2, ADDITIONAL=3}; //!< Type describing the positioning of a DNSResourceRecord within, say, a DNSPacket
Place d_place; //!< This specifies where a record goes within the packet
+ bool auth;
+ uint8_t scopeMask;
+
+ template<class Archive>
+ void serialize(Archive & ar, const unsigned int version)
+ {
+ ar & qtype;
+ ar & qclass;
+ ar & qname;
+ ar & wildcardname;
+ ar & content;
+ ar & priority;
+ ar & ttl;
+ ar & domain_id;
+ ar & last_modified;
+ ar & d_place;
+ ar & auth;
+ }
+
bool operator<(const DNSResourceRecord &b) const
{
if(qname < b.qname)
@@ -90,9 +115,6 @@
return(content < b.content);
return false;
}
-
-private:
- string escape(const string &str) const;
};
#ifdef _MSC_VER
@@ -160,8 +182,15 @@
ns_t_cert = 37, /* Certification record */
ns_t_a6 = 38, /* IPv6 address (deprecates AAAA) */
ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */
- ns_t_sink = 40, /* Kitchen sink (experimentatl) */
+ ns_t_sink = 40, /* Kitchen sink (experimental) */
ns_t_opt = 41, /* EDNS0 option (meta-RR) */
+ ns_t_ds = 43, /* Delegation signer */
+ ns_t_rrsig = 46, /* Resoure Record signature */
+ ns_t_nsec = 47, /* Next Record */
+ ns_t_dnskey = 48, /* DNSKEY record */
+ ns_t_nsec3 = 50, /* Next Record v3 */
+ ns_t_nsec3param = 51, /* NSEC Parameters */
+ ns_t_tlsa = 52, /* TLSA */
ns_t_tsig = 250, /* Transaction signature. */
ns_t_ixfr = 251, /* Incremental zone transfer. */
ns_t_axfr = 252, /* Transfer zone of authority. */
@@ -173,7 +202,7 @@
#ifdef WIN32
#define BYTE_ORDER 1
#define LITTLE_ENDIAN 1
-#elif __FreeBSD__ || __APPLE__
+#elif __FreeBSD__ || __APPLE__ || __OpenBSD__
#include <machine/endian.h>
#elif __linux__
# include <endian.h>
@@ -250,4 +279,12 @@
extern time_t s_starttime;
std::string questionExpand(const char* packet, uint16_t len, uint16_t& type);
bool dnspacketLessThan(const std::string& a, const std::string& b);
+
+/** helper function for both DNSPacket and addSOARecord() - converts a line into a struct, for easier parsing */
+void fillSOAData(const string &content, SOAData &data);
+
+/** for use by DNSPacket, converts a SOAData class to a ascii line again */
+string serializeSOAData(const SOAData &data);
+string &attodot(string &str); //!< for when you need to insert an email address in the SOA
+string strrcode(unsigned char rcode);
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dns_random.cc
^
|
@@ -13,6 +13,8 @@
static unsigned char g_counter[16];
static uint32_t g_in;
+static bool g_initialized;
+
void dns_random_init(const char data[16])
{
aes_init();
@@ -24,6 +26,8 @@
memcpy(g_counter, &now.tv_usec, sizeof(now.tv_usec));
memcpy(g_counter+sizeof(now.tv_usec), &now.tv_sec, sizeof(now.tv_sec));
g_in = getpid() | (getppid()<<16);
+
+ g_initialized = true;
srandom(dns_random(numeric_limits<uint32_t>::max()));
}
@@ -50,6 +54,8 @@
unsigned int dns_random(unsigned int n)
{
+ if(!g_initialized)
+ abort();
uint32_t out;
aes_ctr_encrypt((unsigned char*) &g_in, (unsigned char*)& out, sizeof(g_in), g_counter, counterIncrement, &g_cx);
return out % n;
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/dnslabeltext.cc
^
|
@@ -0,0 +1,475 @@
+
+#line 1 "dnslabeltext.rl"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include "namespaces.hh"
+
+
+namespace {
+void appendSplit(vector<string>& ret, string& segment, char c)
+{
+ if(segment.size()>254) {
+ ret.push_back(segment);
+ segment.clear();
+ }
+ segment.append(1, c);
+}
+}
+
+vector<string> segmentDNSText(const string& input )
+{
+
+#line 26 "dnslabeltext.cc"
+static const char _dnstext_actions[] = {
+ 0, 1, 0, 1, 1, 1, 2, 1,
+ 3, 1, 4, 1, 5, 2, 0, 1,
+ 2, 4, 5
+};
+
+static const char _dnstext_key_offsets[] = {
+ 0, 0, 1, 7, 9, 11, 13, 19,
+ 23
+};
+
+static const char _dnstext_trans_keys[] = {
+ 34, 34, 92, 9, 10, 32, 126, 48,
+ 57, 48, 57, 48, 57, 34, 92, 9,
+ 10, 32, 126, 32, 34, 9, 13, 34,
+ 0
+};
+
+static const char _dnstext_single_lengths[] = {
+ 0, 1, 2, 0, 0, 0, 2, 2,
+ 1
+};
+
+static const char _dnstext_range_lengths[] = {
+ 0, 0, 2, 1, 1, 1, 2, 1,
+ 0
+};
+
+static const char _dnstext_index_offsets[] = {
+ 0, 0, 2, 7, 9, 11, 13, 18,
+ 22
+};
+
+static const char _dnstext_trans_targs[] = {
+ 2, 0, 7, 3, 2, 2, 0, 4,
+ 2, 5, 0, 6, 0, 7, 3, 2,
+ 2, 0, 8, 2, 8, 0, 2, 0,
+ 0
+};
+
+static const char _dnstext_trans_actions[] = {
+ 3, 0, 0, 0, 11, 11, 0, 7,
+ 5, 7, 0, 7, 0, 9, 9, 16,
+ 16, 0, 0, 13, 0, 0, 13, 0,
+ 0
+};
+
+static const char _dnstext_eof_actions[] = {
+ 0, 0, 0, 0, 0, 0, 0, 1,
+ 1
+};
+
+static const int dnstext_start = 1;
+static const int dnstext_first_final = 7;
+static const int dnstext_error = 0;
+
+static const int dnstext_en_main = 1;
+
+
+#line 25 "dnslabeltext.rl"
+
+ (void)dnstext_error; // silence warnings
+ (void)dnstext_en_main;
+ const char *p = input.c_str(), *pe = input.c_str() + input.length();
+ const char* eof = pe;
+ int cs;
+ char val = 0;
+
+ string segment;
+ vector<string> ret;
+
+
+#line 99 "dnslabeltext.cc"
+ {
+ cs = dnstext_start;
+ }
+
+#line 104 "dnslabeltext.cc"
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _dnstext_trans_keys + _dnstext_key_offsets[cs];
+ _trans = _dnstext_index_offsets[cs];
+
+ _klen = _dnstext_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _dnstext_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ cs = _dnstext_trans_targs[_trans];
+
+ if ( _dnstext_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _dnstext_actions + _dnstext_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+#line 37 "dnslabeltext.rl"
+ {
+ ret.push_back(segment);
+ segment.clear();
+ }
+ break;
+ case 1:
+#line 41 "dnslabeltext.rl"
+ {
+ segment.clear();
+ }
+ break;
+ case 2:
+#line 45 "dnslabeltext.rl"
+ {
+ char c = *p;
+ appendSplit(ret, segment, c);
+ }
+ break;
+ case 3:
+#line 49 "dnslabeltext.rl"
+ {
+ char c = *p;
+ val *= 10;
+ val += c-'0';
+
+ }
+ break;
+ case 4:
+#line 55 "dnslabeltext.rl"
+ {
+ appendSplit(ret, segment, val);
+ val=0;
+ }
+ break;
+ case 5:
+#line 60 "dnslabeltext.rl"
+ {
+ appendSplit(ret, segment, *(p));
+ }
+ break;
+#line 219 "dnslabeltext.cc"
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ if ( p == eof )
+ {
+ const char *__acts = _dnstext_actions + _dnstext_eof_actions[cs];
+ unsigned int __nacts = (unsigned int) *__acts++;
+ while ( __nacts-- > 0 ) {
+ switch ( *__acts++ ) {
+ case 0:
+#line 37 "dnslabeltext.rl"
+ {
+ ret.push_back(segment);
+ segment.clear();
+ }
+ break;
+#line 242 "dnslabeltext.cc"
+ }
+ }
+ }
+
+ _out: {}
+ }
+
+#line 73 "dnslabeltext.rl"
+
+
+ if ( cs < dnstext_first_final ) {
+ throw runtime_error("Unable to parse DNS TXT '"+input+"'");
+ }
+
+ return ret;
+};
+string segmentDNSLabel(const string& input )
+{
+
+#line 262 "dnslabeltext.cc"
+static const char _dnslabel_actions[] = {
+ 0, 1, 0, 1, 1, 1, 2, 1,
+ 3, 1, 4, 2, 3, 0, 2, 3,
+ 4
+};
+
+static const char _dnslabel_key_offsets[] = {
+ 0, 0, 4, 8, 10, 12, 16
+};
+
+static const char _dnslabel_trans_keys[] = {
+ 46, 92, 32, 126, 46, 92, 48, 57,
+ 48, 57, 48, 57, 46, 92, 32, 126,
+ 46, 92, 32, 126, 0
+};
+
+static const char _dnslabel_single_lengths[] = {
+ 0, 2, 2, 0, 0, 2, 2
+};
+
+static const char _dnslabel_range_lengths[] = {
+ 0, 1, 1, 1, 1, 1, 1
+};
+
+static const char _dnslabel_index_offsets[] = {
+ 0, 0, 4, 8, 10, 12, 16
+};
+
+static const char _dnslabel_trans_targs[] = {
+ 6, 2, 1, 0, 1, 1, 3, 0,
+ 4, 0, 5, 0, 6, 2, 1, 0,
+ 6, 2, 1, 0, 0
+};
+
+static const char _dnslabel_trans_actions[] = {
+ 1, 0, 9, 0, 3, 3, 5, 0,
+ 5, 0, 5, 0, 11, 7, 14, 0,
+ 1, 0, 9, 0, 0
+};
+
+static const int dnslabel_start = 1;
+static const int dnslabel_first_final = 6;
+static const int dnslabel_error = 0;
+
+static const int dnslabel_en_main = 1;
+
+
+#line 86 "dnslabeltext.rl"
+
+ (void)dnslabel_error; // silence warnings
+ (void)dnslabel_en_main;
+ const char *p = input.c_str(), *pe = input.c_str() + input.length();
+ //const char* eof = pe;
+ int cs;
+ char val = 0;
+
+ string ret;
+ string segment;
+
+
+#line 323 "dnslabeltext.cc"
+ {
+ cs = dnslabel_start;
+ }
+
+#line 328 "dnslabeltext.cc"
+ {
+ int _klen;
+ unsigned int _trans;
+ const char *_acts;
+ unsigned int _nacts;
+ const char *_keys;
+
+ if ( p == pe )
+ goto _test_eof;
+ if ( cs == 0 )
+ goto _out;
+_resume:
+ _keys = _dnslabel_trans_keys + _dnslabel_key_offsets[cs];
+ _trans = _dnslabel_index_offsets[cs];
+
+ _klen = _dnslabel_single_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + _klen - 1;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + ((_upper-_lower) >> 1);
+ if ( (*p) < *_mid )
+ _upper = _mid - 1;
+ else if ( (*p) > *_mid )
+ _lower = _mid + 1;
+ else {
+ _trans += (_mid - _keys);
+ goto _match;
+ }
+ }
+ _keys += _klen;
+ _trans += _klen;
+ }
+
+ _klen = _dnslabel_range_lengths[cs];
+ if ( _klen > 0 ) {
+ const char *_lower = _keys;
+ const char *_mid;
+ const char *_upper = _keys + (_klen<<1) - 2;
+ while (1) {
+ if ( _upper < _lower )
+ break;
+
+ _mid = _lower + (((_upper-_lower) >> 1) & ~1);
+ if ( (*p) < _mid[0] )
+ _upper = _mid - 2;
+ else if ( (*p) > _mid[1] )
+ _lower = _mid + 2;
+ else {
+ _trans += ((_mid - _keys)>>1);
+ goto _match;
+ }
+ }
+ _trans += _klen;
+ }
+
+_match:
+ cs = _dnslabel_trans_targs[_trans];
+
+ if ( _dnslabel_trans_actions[_trans] == 0 )
+ goto _again;
+
+ _acts = _dnslabel_actions + _dnslabel_trans_actions[_trans];
+ _nacts = (unsigned int) *_acts++;
+ while ( _nacts-- > 0 )
+ {
+ switch ( *_acts++ )
+ {
+ case 0:
+#line 98 "dnslabeltext.rl"
+ {
+ printf("Segment end, segment = '%s'\n", segment.c_str());
+ ret.append(1, (unsigned char)segment.size());
+ ret.append(segment);
+ segment.clear();
+ }
+ break;
+ case 1:
+#line 105 "dnslabeltext.rl"
+ {
+ printf("'\\%c' ", *p);
+ segment.append(1, *p);
+ }
+ break;
+ case 2:
+#line 109 "dnslabeltext.rl"
+ {
+ char c = *p;
+ val *= 10;
+ val += c-'0';
+
+ }
+ break;
+ case 3:
+#line 115 "dnslabeltext.rl"
+ {
+ printf("_%c_ ", val);
+ segment.append(1, val);
+ val=0;
+ }
+ break;
+ case 4:
+#line 121 "dnslabeltext.rl"
+ {
+ printf("'%c' ", *p);
+ segment.append(1, *p);
+ }
+ break;
+#line 441 "dnslabeltext.cc"
+ }
+ }
+
+_again:
+ if ( cs == 0 )
+ goto _out;
+ if ( ++p != pe )
+ goto _resume;
+ _test_eof: {}
+ _out: {}
+ }
+
+#line 136 "dnslabeltext.rl"
+
+
+ if ( cs < dnslabel_first_final ) {
+ throw runtime_error("Unable to parse DNS Label '"+input+"'");
+ }
+
+ if(ret.empty() || ret[0] != 0)
+ ret.append(1, 0);
+ return ret;
+};
+#if 0
+int main()
+{
+ //char blah[]="\"blah\" \"bleh\" \"bloeh\\\"bleh\" \"\\97enzo\"";
+ char blah[]="\"v=spf1 ip4:67.106.74.128/25 ip4:63.138.42.224/28 ip4:65.204.46.224/27 \\013\\010ip4:66.104.217.176/28 \\013\\010ip4:209.48.147.0/27 ~all\"";
+ //char blah[]="\"abc \\097\\098 def\"";
+ printf("Input: '%s'\n", blah);
+ vector<string> res=dnstext(blah);
+ cerr<<res.size()<<" segments"<<endl;
+ cerr<<res[0]<<endl;
+}
+#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnsparser.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2005 - 2009 PowerDNS.COM BV
+ Copyright (C) 2005 - 2011 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 version 2 as
@@ -20,6 +20,7 @@
#include "dnswriter.hh"
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
+#include <boost/format.hpp>
#include "namespaces.hh"
@@ -100,8 +101,6 @@
}
}
ret.append(1, 0);
-// cerr<<"Asked to encode '"<<input<<"', returning: '"<<makeHexDump(ret)<<endl;
-// cerr<<"parts length: "<<parts.size()<<endl;
return ret;
}
@@ -171,27 +170,31 @@
return i->second(content);
}
-
DNSRecordContent::typemap_t& DNSRecordContent::getTypemap()
{
static DNSRecordContent::typemap_t typemap;
return typemap;
}
-DNSRecordContent::namemap_t& DNSRecordContent::getNamemap()
+DNSRecordContent::n2typemap_t& DNSRecordContent::getN2Typemap()
+{
+ static DNSRecordContent::n2typemap_t n2typemap;
+ return n2typemap;
+}
+
+DNSRecordContent::t2namemap_t& DNSRecordContent::getT2Namemap()
{
- static DNSRecordContent::namemap_t namemap;
- return namemap;
+ static DNSRecordContent::t2namemap_t t2namemap;
+ return t2namemap;
}
+
DNSRecordContent::zmakermap_t& DNSRecordContent::getZmakermap()
{
static DNSRecordContent::zmakermap_t zmakermap;
return zmakermap;
}
-
-
void MOADNSParser::init(const char *packet, unsigned int len)
{
if(len < sizeof(dnsheader))
@@ -264,7 +267,7 @@
}
#endif
}
- catch(out_of_range &re) {
+ catch(std::out_of_range &re) {
if(validPacket && d_header.tc) { // don't sweat it over truncated packets, but do adjust an, ns and arcount
if(n < d_header.ancount) {
d_header.ancount=n; d_header.nscount = d_header.arcount = 0;
@@ -317,7 +320,7 @@
void PacketReader::copyRecord(unsigned char* dest, uint16_t len)
{
if(d_pos + len > d_content.size())
- throw MOADNSException("Attempt to copy outside of packet");
+ throw std::out_of_range("Attempt to copy outside of packet");
memcpy(dest, &d_content.at(d_pos), len);
d_pos+=len;
@@ -386,14 +389,23 @@
static string txtEscape(const string &name)
{
string ret;
+ char ebuf[5];
- for(string::const_iterator i=name.begin();i!=name.end();++i)
- if(*i=='"' || *i=='\\'){
+ for(string::const_iterator i=name.begin();i!=name.end();++i) {
+ if(*i=='\n') { // XXX FIXME this should do a way better job!
+ ret += "\\010";
+ }
+ else if((unsigned char) *i > 127) {
+ snprintf(ebuf, sizeof(ebuf), "\\%03u", (unsigned char)*i);
+ ret += ebuf;
+ }
+ else if(*i=='"' || *i=='\\'){
ret += '\\';
ret += *i;
}
else
ret += *i;
+ }
return ret;
}
@@ -425,7 +437,7 @@
void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs)
{
- if(recurs > 10)
+ if(recurs > 1000) // the forward reference-check below should make this test 100% obsolete
throw MOADNSException("Loop");
for(;;) {
@@ -439,15 +451,24 @@
if((labellen & 0xc0) == 0xc0) {
uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)content.at(frompos++) - sizeof(dnsheader);
// cout<<"This is an offset, need to go to: "<<offset<<endl;
+
+ if(offset >= frompos-2)
+ throw MOADNSException("forward reference during label decompression");
return getLabelFromContent(content, offset, ret, ++recurs);
}
else {
// XXX FIXME THIS MIGHT BE VERY SLOW!
ret.reserve(ret.size() + labellen + 2);
for(string::size_type n = 0 ; n < labellen; ++n, frompos++) {
- if(content.at(frompos)=='.' || content.at(frompos)=='\\')
+ if(content.at(frompos)=='.' || content.at(frompos)=='\\') {
ret.append(1, '\\');
- ret.append(1, content[frompos]);
+ ret.append(1, content[frompos]);
+ }
+ else if(content.at(frompos)==' ') {
+ ret+="\\032";
+ }
+ else
+ ret.append(1, content[frompos]);
}
ret.append(1,'.');
}
@@ -456,7 +477,7 @@
void PacketReader::xfrBlob(string& blob)
{
- if(d_recordlen)
+ if(d_recordlen && !(d_pos == (d_startrecordpos + d_recordlen)))
blob.assign(&d_content.at(d_pos), &d_content.at(d_startrecordpos + d_recordlen - 1 ) + 1);
else
blob.clear();
@@ -476,7 +497,7 @@
}
-void PacketReader::xfrHexBlob(string& blob)
+void PacketReader::xfrHexBlob(string& blob, bool keepReading)
{
xfrBlob(blob);
}
@@ -511,3 +532,112 @@
frompos+=labellen;
}
}
+
+/** Simple DNSPacketMangler. Ritual is: get a pointer into the packet and moveOffset() to beyond your needs
+ * If you survive that, feel free to read from the pointer */
+class DNSPacketMangler
+{
+public:
+ explicit DNSPacketMangler(std::string& packet)
+ : d_packet(packet), d_notyouroffset(12), d_offset(d_notyouroffset)
+ {}
+
+ void skipLabel()
+ {
+ uint8_t len;
+ while((len=get8BitInt())) {
+ if(len >= 0xc0) { // extended label
+ get8BitInt();
+ return;
+ }
+ skipBytes(len);
+ }
+ }
+ void skipBytes(uint16_t bytes)
+ {
+ moveOffset(bytes);
+ }
+ uint16_t get16BitInt()
+ {
+ const char* p = d_packet.c_str() + d_offset;
+ moveOffset(2);
+ uint16_t ret;
+ memcpy(&ret, (void*)p, 2);
+ return ntohs(ret);
+ }
+
+ uint8_t get8BitInt()
+ {
+ const char* p = d_packet.c_str() + d_offset;
+ moveOffset(1);
+ return *p;
+ }
+
+ void skipRData()
+ {
+ int toskip = get16BitInt();
+ moveOffset(toskip);
+ }
+ void decreaseAndSkip32BitInt(uint32_t decrease)
+ {
+ const char *p = (const char*)d_packet.c_str() + d_offset;
+ moveOffset(4);
+
+ uint32_t tmp;
+ memcpy(&tmp, (void*) p, sizeof(tmp));
+ tmp = ntohl(tmp);
+ tmp-=decrease;
+ tmp = htonl(tmp);
+ d_packet.replace(d_offset-4, sizeof(tmp), (const char*)&tmp, sizeof(tmp));
+ }
+private:
+ void moveOffset(uint16_t by)
+ {
+ d_notyouroffset += by;
+ if(d_notyouroffset > d_packet.length())
+ throw std::out_of_range("dns packet out of range: "+lexical_cast<string>(d_notyouroffset) +" > "
+ + lexical_cast<string>(d_packet.length()) );
+ }
+ std::string& d_packet;
+
+ uint32_t d_notyouroffset; // only 'moveOffset' can touch this
+ const uint32_t& d_offset; // look.. but don't touch
+
+};
+
+// method of operation: silently fail if it doesn't work - we're only trying to be nice, don't fall over on it
+void ageDNSPacket(std::string& packet, uint32_t seconds)
+{
+ if(packet.length() < sizeof(dnsheader))
+ return;
+ try
+ {
+ dnsheader dh;
+ memcpy((void*)&dh, (const dnsheader*)packet.c_str(), sizeof(dh));
+ int numrecords = ntohs(dh.ancount) + ntohs(dh.nscount) + ntohs(dh.arcount);
+ DNSPacketMangler dpm(packet);
+
+ int n;
+ for(n=0; n < ntohs(dh.qdcount) ; ++n) {
+ dpm.skipLabel();
+ dpm.skipBytes(4); // qtype, qclass
+ }
+ // cerr<<"Skipped "<<n<<" questions, now parsing "<<numrecords<<" records"<<endl;
+ for(n=0; n < numrecords; ++n) {
+ dpm.skipLabel();
+
+ uint16_t dnstype = dpm.get16BitInt();
+ /* uint16_t dnsclass = */ dpm.get16BitInt();
+
+ if(dnstype == QType::OPT) // not aging that one with a stick
+ break;
+
+ dpm.decreaseAndSkip32BitInt(seconds);
+ dpm.skipRData();
+ }
+ }
+ catch(...)
+ {
+ return;
+ }
+}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnsparser.hh
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2005 PowerDNS.COM BV
+ Copyright (C) 2005 - 2011 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 version 2 as
@@ -47,7 +47,7 @@
And we might be able to reverse 2 -> 3 as well
*/
-using namespace std;
+#include "namespaces.hh"
#include "namespaces.hh"
class MOADNSException : public runtime_error
@@ -64,8 +64,10 @@
{
public:
PacketReader(const vector<uint8_t>& content)
- : d_pos(0), d_content(content)
- {}
+ : d_pos(0), d_startrecordpos(0), d_content(content)
+ {
+ d_recordlen = content.size();
+ }
uint32_t get32BitInt();
uint16_t get16BitInt();
@@ -119,7 +121,7 @@
void xfrBlob(string& blob);
void xfrBlob(string& blob, int length);
- void xfrHexBlob(string& blob);
+ void xfrHexBlob(string& blob, bool keepReading=false);
static uint16_t get16BitInt(const vector<unsigned char>&content, uint16_t& pos);
static void getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs);
@@ -135,7 +137,7 @@
private:
uint16_t d_startrecordpos; // needed for getBlob later on
- uint16_t d_recordlen; // dito
+ uint16_t d_recordlen; // ditto
const vector<uint8_t>& d_content;
};
@@ -150,12 +152,17 @@
virtual std::string getZoneRepresentation() const = 0;
virtual ~DNSRecordContent() {}
virtual void toPacket(DNSPacketWriter& pw)=0;
- virtual string serialize(const string& qname) // it would rock if this were const, but it is too hard
+ virtual string serialize(const string& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard
{
vector<uint8_t> packet;
string empty;
DNSPacketWriter pw(packet, empty, 1);
-
+ if(canonic)
+ pw.setCanonic(true);
+
+ if(lowerCase)
+ pw.setLowercase(true);
+
pw.startRecord(qname, d_qtype);
this->toPacket(pw);
pw.commit();
@@ -182,7 +189,8 @@
if(z)
getZmakermap()[make_pair(cl,ty)]=z;
- getNamemap()[make_pair(cl,ty)]=name;
+ getT2Namemap().insert(make_pair(make_pair(cl,ty), name));
+ getN2Typemap().insert(make_pair(name, make_pair(cl,ty)));
}
static void unregist(uint16_t cl, uint16_t ty)
@@ -194,32 +202,48 @@
static uint16_t TypeToNumber(const string& name)
{
- for(namemap_t::const_iterator i=getNamemap().begin(); i!=getNamemap().end();++i)
- if(pdns_iequals(i->second, name))
- return i->first.second;
-
+ n2typemap_t::const_iterator iter = getN2Typemap().find(toUpper(name));
+ if(iter != getN2Typemap().end())
+ return iter->second.second;
+
+ if(boost::starts_with(name, "TYPE"))
+ return atoi(name.c_str()+4);
+
throw runtime_error("Unknown DNS type '"+name+"'");
}
static const string NumberToType(uint16_t num, uint16_t classnum=1)
{
- if(!getNamemap().count(make_pair(classnum,num)))
- return "#" + lexical_cast<string>(num);
+ t2namemap_t::const_iterator iter = getT2Namemap().find(make_pair(classnum, num));
+ if(iter == getT2Namemap().end())
+ return "TYPE" + lexical_cast<string>(num);
// throw runtime_error("Unknown DNS type with numerical id "+lexical_cast<string>(num));
- return getNamemap()[make_pair(classnum,num)];
+ return iter->second;
}
explicit DNSRecordContent(uint16_t type) : d_qtype(type)
{}
+
+
+ DNSRecordContent& operator=(const DNSRecordContent& orig)
+ {
+ const_cast<uint16_t&>(d_qtype) = orig.d_qtype; // **COUGH**
+ label = orig.label;
+ header = orig.header;
+ return *this;
+ }
+
+
const uint16_t d_qtype;
protected:
typedef std::map<std::pair<uint16_t, uint16_t>, makerfunc_t* > typemap_t;
typedef std::map<std::pair<uint16_t, uint16_t>, zmakerfunc_t* > zmakermap_t;
- typedef std::map<std::pair<uint16_t, uint16_t>, string > namemap_t;
-
+ typedef std::map<std::pair<uint16_t, uint16_t>, string > t2namemap_t;
+ typedef std::map<string, std::pair<uint16_t, uint16_t> > n2typemap_t;
static typemap_t& getTypemap();
- static namemap_t& getNamemap();
+ static t2namemap_t& getT2Namemap();
+ static n2typemap_t& getN2Typemap();
static zmakermap_t& getZmakermap();
};
@@ -285,7 +309,7 @@
dnsheader d_header;
string d_qname;
uint16_t d_qclass, d_qtype;
- uint8_t d_rcode;
+ //uint8_t d_rcode;
typedef vector<pair<DNSRecord, uint16_t > > answers_t;
@@ -312,5 +336,5 @@
string simpleCompress(const string& label, const string& root="");
void simpleExpandTo(const string& label, unsigned int frompos, string& ret);
-
+void ageDNSPacket(std::string& packet, uint32_t seconds);
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnsrecords.cc
^
|
@@ -18,6 +18,7 @@
#include "utility.hh"
#include "dnsrecords.hh"
+#include <boost/foreach.hpp>
boilerplate_conv(A, ns_t_a, conv.xfrIP(d_ip));
@@ -61,7 +62,7 @@
static DNSRecordContent* make(const string& zone)
{
AAAARecordContent *ar=new AAAARecordContent();
- if(Utility::inet_pton( AF_INET6, zone.c_str(), static_cast< void * >( ar->d_ip6 )) < 0)
+ if(Utility::inet_pton( AF_INET6, zone.c_str(), static_cast< void * >( ar->d_ip6 )) <= 0)
throw MOADNSException("Asked to encode '"+zone+"' as an IPv6 address, but does not parse");
return ar;
}
@@ -90,93 +91,6 @@
};
-void NSECRecordContent::report(void)
-{
- regist(1, 47, &make, &make, "NSEC");
-}
-
-DNSRecordContent* NSECRecordContent::make(const string& content)
-{
- return new NSECRecordContent(content);
-}
-
-NSECRecordContent::NSECRecordContent(const string& content, const string& zone) : DNSRecordContent(47)
-{
- RecordTextReader rtr(content, zone);
- rtr.xfrLabel(d_next);
-
- while(!rtr.eof()) {
- uint16_t type;
- rtr.xfrType(type);
- d_set.insert(type);
- }
-}
-
-void NSECRecordContent::toPacket(DNSPacketWriter& pw)
-{
- pw.xfrLabel(d_next);
-
- uint8_t res[34];
- memset(res, 0, sizeof(res));
-
- set<uint16_t>::const_iterator i;
- for(i=d_set.begin(); i != d_set.end() && *i<255; ++i){
- res[2+*i/8] |= 1 << (7-(*i%8));
- }
- int len=0;
- if(!d_set.empty())
- len=1+*--i/8;
-
- res[1]=len;
-
- string tmp;
- tmp.assign(res, res+len+2);
- pw.xfrBlob(tmp);
-}
-
-NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr)
-{
- NSECRecordContent* ret=new NSECRecordContent();
- pr.xfrLabel(ret->d_next);
- string bitmap;
- pr.xfrBlob(bitmap);
-
- // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left
-
- if(bitmap.size() < 2)
- throw MOADNSException("NSEC record with impossibly small bitmap");
-
- if(bitmap[0])
- throw MOADNSException("Can't deal with NSEC mappings > 255 yet");
-
- unsigned int len=bitmap[1];
- if(bitmap.size()!=2+len)
- throw MOADNSException("Can't deal with multi-part NSEC mappings yet");
-
- for(unsigned int n=0 ; n < len ; ++n) {
- uint8_t val=bitmap[2+n];
- for(int bit = 0; bit < 8 ; ++bit , val>>=1)
- if(val & 1) {
- ret->d_set.insert((7-bit) + 8*(n));
- }
- }
-
- return ret;
-}
-
-string NSECRecordContent::getZoneRepresentation() const
-{
- string ret;
- RecordTextWriter rtw(ret);
- rtw.xfrLabel(d_next);
-
- for(set<uint16_t>::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) {
- ret+=" ";
- ret+=NumberToType(*i);
- }
-
- return ret;
-}
boilerplate_conv(NS, ns_t_ns, conv.xfrLabel(d_content, true));
boilerplate_conv(PTR, ns_t_ptr, conv.xfrLabel(d_content, true));
@@ -201,8 +115,8 @@
string::size_type pos=0;
uint16_t code, len;
while(d_data.size() >= 4 + pos) {
- code = 0xff * d_data[pos] + d_data[pos+1];
- len = 0xff * d_data[pos+2] + d_data[pos+3];
+ code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1];
+ len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3];
pos+=4;
if(pos + len > d_data.size())
@@ -308,14 +222,32 @@
conv.xfr8BitInt(d_algorithm);
conv.xfrBlob(d_certificate);
)
+
+boilerplate_conv(TLSA, 52,
+ conv.xfr8BitInt(d_certusage);
+ conv.xfr8BitInt(d_selector);
+ conv.xfr8BitInt(d_matchtype);
+ conv.xfrHexBlob(d_cert, true);
+ )
+
#undef DS
+DSRecordContent::DSRecordContent() : DNSRecordContent(43) {}
boilerplate_conv(DS, 43,
conv.xfr16BitInt(d_tag);
conv.xfr8BitInt(d_algorithm);
conv.xfr8BitInt(d_digesttype);
- conv.xfrHexBlob(d_digest);
+ conv.xfrHexBlob(d_digest, true); // keep reading across spaces
+ )
+
+DLVRecordContent::DLVRecordContent() : DNSRecordContent(32769) {}
+boilerplate_conv(DLV,32769 ,
+ conv.xfr16BitInt(d_tag);
+ conv.xfr8BitInt(d_algorithm);
+ conv.xfr8BitInt(d_digesttype);
+ conv.xfrHexBlob(d_digest, true); // keep reading across spaces
)
+
boilerplate_conv(SSHFP, 44,
conv.xfr8BitInt(d_algorithm);
conv.xfr8BitInt(d_fptype);
@@ -326,7 +258,6 @@
conv.xfrType(d_type);
conv.xfr8BitInt(d_algorithm);
conv.xfr8BitInt(d_labels);
-
conv.xfr32BitInt(d_originalttl);
conv.xfrTime(d_sigexpire);
conv.xfrTime(d_siginception);
@@ -335,12 +266,30 @@
conv.xfrBlob(d_signature);
)
+RRSIGRecordContent::RRSIGRecordContent() : DNSRecordContent(46) {}
+
boilerplate_conv(DNSKEY, 48,
conv.xfr16BitInt(d_flags);
conv.xfr8BitInt(d_protocol);
conv.xfr8BitInt(d_algorithm);
conv.xfrBlob(d_key);
)
+DNSKEYRecordContent::DNSKEYRecordContent() : DNSRecordContent(48) {}
+
+uint16_t DNSKEYRecordContent::getTag()
+{
+ string data=this->serialize("");
+ const unsigned char* key=(const unsigned char*)data.c_str();
+ unsigned int keysize=data.length();
+
+ unsigned long ac; /* assumed to be 32 bits or larger */
+ unsigned int i; /* loop index */
+
+ for ( ac = 0, i = 0; i < keysize; ++i )
+ ac += (i & 1) ? key[i] : key[i] << 8;
+ ac += (ac >> 16) & 0xFFFF;
+ return ac & 0xFFFF;
+}
// "fancy records"
boilerplate_conv(URL, QType::URL,
@@ -351,29 +300,32 @@
conv.xfrLabel(d_mboxfw);
)
+
+
bool getEDNSOpts(const MOADNSParser& mdp, EDNSOpts* eo)
{
- if(mdp.d_header.arcount && !mdp.d_answers.empty() &&
- mdp.d_answers.back().first.d_type == QType::OPT) {
- eo->d_packetsize=mdp.d_answers.back().first.d_class;
-
- EDNS0Record stuff;
- uint32_t ttl=ntohl(mdp.d_answers.back().first.d_ttl);
- memcpy(&stuff, &ttl, sizeof(stuff));
-
- eo->d_extRCode=stuff.extRCode;
- eo->d_version=stuff.version;
- eo->d_Z = ntohs(stuff.Z);
- OPTRecordContent* orc =
- dynamic_cast<OPTRecordContent*>(mdp.d_answers.back().first.d_content.get());
- if(!orc)
- return false;
- orc->getData(eo->d_options);
-
- return true;
+ if(mdp.d_header.arcount && !mdp.d_answers.empty()) {
+ BOOST_FOREACH(const MOADNSParser::answers_t::value_type& val, mdp.d_answers) {
+ if(val.first.d_place == DNSRecord::Additional && val.first.d_type == QType::OPT) {
+ eo->d_packetsize=val.first.d_class;
+
+ EDNS0Record stuff;
+ uint32_t ttl=ntohl(val.first.d_ttl);
+ memcpy(&stuff, &ttl, sizeof(stuff));
+
+ eo->d_extRCode=stuff.extRCode;
+ eo->d_version=stuff.version;
+ eo->d_Z = ntohs(stuff.Z);
+ OPTRecordContent* orc =
+ dynamic_cast<OPTRecordContent*>(val.first.d_content.get());
+ if(!orc)
+ return false;
+ orc->getData(eo->d_options);
+ return true;
+ }
+ }
}
- else
- return false;
+ return false;
}
@@ -407,6 +359,10 @@
SSHFPRecordContent::report();
CERTRecordContent::report();
NSECRecordContent::report();
+ NSEC3RecordContent::report();
+ NSEC3PARAMRecordContent::report();
+ TLSARecordContent::report();
+ DLVRecordContent::report();
DNSRecordContent::regist(0xff, QType::TSIG, &TSIGRecordContent::make, &TSIGRecordContent::make, "TSIG");
OPTRecordContent::report();
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnsrecords.hh
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2005 - 2007 PowerDNS.COM BV
+ Copyright (C) 2005 - 2010 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 version 2 as
@@ -24,8 +24,9 @@
#include "rcpgenerator.hh"
#include <boost/lexical_cast.hpp>
#include <set>
+#include <bitset>
-using namespace std;
+#include "namespaces.hh"
#include "namespaces.hh"
#define includeboilerplate(RNAME) RNAME##RecordContent(const DNSRecord& dr, PacketReader& pr); \
@@ -227,9 +228,10 @@
class DNSKEYRecordContent : public DNSRecordContent
{
public:
+ DNSKEYRecordContent();
includeboilerplate(DNSKEY)
+ uint16_t getTag();
-private:
uint16_t d_flags;
uint8_t d_protocol;
uint8_t d_algorithm;
@@ -239,14 +241,26 @@
class DSRecordContent : public DNSRecordContent
{
public:
+ DSRecordContent();
includeboilerplate(DS)
-private:
uint16_t d_tag;
uint8_t d_algorithm, d_digesttype;
string d_digest;
};
+class DLVRecordContent : public DNSRecordContent
+{
+public:
+ DLVRecordContent();
+ includeboilerplate(DLV)
+
+ uint16_t d_tag;
+ uint8_t d_algorithm, d_digesttype;
+ string d_digest;
+};
+
+
class SSHFPRecordContent : public DNSRecordContent
{
public:
@@ -290,12 +304,23 @@
string d_certificate;
};
+class TLSARecordContent : public DNSRecordContent
+{
+public:
+ includeboilerplate(TLSA)
+
+private:
+ uint8_t d_certusage, d_selector, d_matchtype;
+ string d_cert;
+};
+
+
class RRSIGRecordContent : public DNSRecordContent
{
public:
+ RRSIGRecordContent();
includeboilerplate(RRSIG)
-private:
uint16_t d_type;
uint8_t d_algorithm, d_labels;
uint32_t d_originalttl, d_sigexpire, d_siginception;
@@ -328,14 +353,6 @@
struct soatimes d_st;
};
-class HIPRecordContent : public DNSRecordContent
-{
-public:
- includeboilerplate(HIP)
- HIPRecordContent(uint8_t algorithm, const string& hit, const string& key);
-};
-
-
class NSECRecordContent : public DNSRecordContent
{
public:
@@ -353,6 +370,52 @@
private:
};
+class NSEC3RecordContent : public DNSRecordContent
+{
+public:
+ static void report(void);
+ NSEC3RecordContent() : DNSRecordContent(50)
+ {}
+ NSEC3RecordContent(const string& content, const string& zone="");
+
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr);
+ static DNSRecordContent* make(const string& content);
+ string getZoneRepresentation() const;
+ void toPacket(DNSPacketWriter& pw);
+
+ uint8_t d_algorithm, d_flags;
+ uint16_t d_iterations;
+ uint8_t d_saltlength;
+ string d_salt;
+ uint8_t d_nexthashlength;
+ string d_nexthash;
+ std::set<uint16_t> d_set;
+
+private:
+};
+
+
+class NSEC3PARAMRecordContent : public DNSRecordContent
+{
+public:
+ static void report(void);
+ NSEC3PARAMRecordContent() : DNSRecordContent(51)
+ {}
+ NSEC3PARAMRecordContent(const string& content, const string& zone="");
+
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr);
+ static DNSRecordContent* make(const string& content);
+ string getZoneRepresentation() const;
+ void toPacket(DNSPacketWriter& pw);
+
+
+ uint8_t d_algorithm, d_flags;
+ uint16_t d_iterations;
+ uint8_t d_saltlength;
+ string d_salt;
+};
+
+
class LOCRecordContent : public DNSRecordContent
{
public:
@@ -372,6 +435,26 @@
private:
};
+
+class WKSRecordContent : public DNSRecordContent
+{
+public:
+ static void report(void);
+ WKSRecordContent() : DNSRecordContent(ns_t_wks)
+ {}
+ WKSRecordContent(const string& content, const string& zone="");
+
+ static DNSRecordContent* make(const DNSRecord &dr, PacketReader& pr);
+ static DNSRecordContent* make(const string& content);
+ string getZoneRepresentation() const;
+ void toPacket(DNSPacketWriter& pw);
+
+ uint32_t d_ip;
+ std::bitset<65535> d_services;
+private:
+};
+
+
class URLRecordContent : public DNSRecordContent // Fake, 'fancy record' with type 256
{
public:
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnswriter.cc
^
|
@@ -1,12 +1,11 @@
#include "dnswriter.hh"
#include "misc.hh"
#include "dnsparser.hh"
-#include <boost/tokenizer.hpp>
-#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
#include <limits.h>
DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode)
- : d_pos(0), d_content(content), d_qname(qname), d_qtype(qtype), d_qclass(qclass), d_canonic(false)
+ : d_pos(0), d_content(content), d_qname(qname), d_qtype(qtype), d_qclass(qclass), d_canonic(false), d_lowerCase(false)
{
d_content.clear();
dnsheader dnsheader;
@@ -107,7 +106,7 @@
void DNSPacketWriter::xfr48BitInt(uint64_t val)
{
unsigned char bytes[6];
- uint16_t theLeft = htons(val >> 32);
+ uint16_t theLeft = htons((val >> 32)&0xffffU);
uint32_t theRight = htonl(val & 0xffffffffU);
memcpy(bytes, (void*)&theLeft, 2);
memcpy(bytes+2, (void*)&theRight, 4);
@@ -135,30 +134,26 @@
d_record.push_back(val);
}
+
+/* input:
+ "" -> 0
+ "blah" -> 4blah
+ "blah" "blah" -> output 4blah4blah
+ "verylongstringlongerthan256....characters" \xffverylongstring\x23characters (autosplit)
+ "blah\"blah" -> 9blah"blah
+ "blah\97" -> 5blahb
+ */
void DNSPacketWriter::xfrText(const string& text, bool)
{
- using boost::escaped_list_separator;
- using boost::tokenizer;
-
- escaped_list_separator<char> sep('\\', ' ' , '"');
- tokenizer<escaped_list_separator<char> > tok(text, sep);
-
- tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin();
-
- if(beg==tok.end()) {
+ if(text.empty()) {
d_record.push_back(0);
+ return;
+ }
+ vector<string> segments = segmentDNSText(text);
+ BOOST_FOREACH(const string& str, segments) {
+ d_record.push_back(str.length());
+ d_record.insert(d_record.end(), str.c_str(), str.c_str() + str.length());
}
- else
- for(; beg!=tok.end(); ++beg){
- if(beg->empty())
- d_record.push_back(0);
- else
- for (unsigned int i = 0; i < beg->length(); i += 0xff){
- d_record.push_back(min((string::size_type)0xffU, beg->length()-i));
- const uint8_t* ptr=(uint8_t*)(beg->c_str()) + i;
- d_record.insert(d_record.end(), ptr, ptr+min((string::size_type)0xffU, beg->length()-i));
- }
- }
}
DNSPacketWriter::lmap_t::iterator find(DNSPacketWriter::lmap_t& lmap, const string& label)
@@ -197,8 +192,9 @@
}
// this is the absolute hottest function in the pdns recursor
-void DNSPacketWriter::xfrLabel(const string& label, bool compress)
+void DNSPacketWriter::xfrLabel(const string& Label, bool compress)
{
+ string label = d_lowerCase ? toLower(Label) : Label;
labelparts_t parts;
if(d_canonic)
@@ -209,7 +205,6 @@
d_record.push_back(0);
return;
}
-
bool unescaped=labeltokUnescape(parts, label);
// d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
@@ -243,6 +238,7 @@
if(unescaped) {
string part(label.c_str() + i -> first, i->second - i->first);
boost::replace_all(part, "\\.", ".");
+ boost::replace_all(part, "\\032", " ");
boost::replace_all(part, "\\\\", "\\");
if(part.size() > 255)
throw MOADNSException("DNSPacketWriter::xfrLabel() tried to write an overly large label");
@@ -254,7 +250,10 @@
pos+=(part.size())+1;
}
else {
- d_record.push_back((char)(i->second - i->first));
+ char labelsize=(char)(i->second - i->first);
+ if(!labelsize) // empty label in the middle of name
+ throw MOADNSException("DNSPacketWriter::xfrLabel() found empty label in the middle of name");
+ d_record.push_back(labelsize);
unsigned int len=d_record.size();
d_record.resize(len + i->second - i->first);
memcpy(((&*d_record.begin()) + len), label.c_str() + i-> first, i->second - i->first);
@@ -269,22 +268,20 @@
void DNSPacketWriter::xfrBlob(const string& blob, int )
{
const uint8_t* ptr=reinterpret_cast<const uint8_t*>(blob.c_str());
-
d_record.insert(d_record.end(), ptr, ptr+blob.size());
}
-void DNSPacketWriter::xfrHexBlob(const string& blob)
+void DNSPacketWriter::xfrHexBlob(const string& blob, bool keepReading)
{
xfrBlob(blob);
}
-
void DNSPacketWriter::getRecords(string& records)
{
records.assign(d_content.begin() + d_sor, d_content.end());
}
-uint16_t DNSPacketWriter::size()
+uint32_t DNSPacketWriter::size()
{
return d_content.size() + d_stuff + d_record.size();
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/dnswriter.hh
^
|
@@ -10,7 +10,7 @@
#include "utility.hh"
#endif
#include "dns.hh"
-using namespace std;
+#include "namespaces.hh"
/** this class can be used to write DNS packets. It knows about DNS in the sense that it makes
the packet header and record headers.
@@ -61,7 +61,7 @@
*/
void commit();
- uint16_t size();
+ uint32_t size(); // needs to be 32 bit because otherwise we don't see the wrap coming when it happened!
/** Should the packet have grown too big for the writer's liking, rollback removes the record currently being written */
void rollback();
@@ -87,7 +87,7 @@
void xfrLabel(const string& label, bool compress=false);
void xfrText(const string& text, bool multi=false);
void xfrBlob(const string& blob, int len=-1);
- void xfrHexBlob(const string& blob);
+ void xfrHexBlob(const string& blob, bool keepReading=false);
uint16_t d_pos;
@@ -100,6 +100,15 @@
d_canonic=val;
}
+ void setLowercase(bool val)
+ {
+ d_lowerCase=val;
+ }
+ vector <uint8_t>& getContent()
+ {
+ return d_content;
+ }
+
private:
vector <uint8_t>& d_content;
vector <uint8_t> d_record;
@@ -113,9 +122,10 @@
uint16_t d_sor;
uint16_t d_rollbackmarker; // start of last complete packet, for rollback
Place d_recordplace;
- bool d_canonic;
+ bool d_canonic, d_lowerCase;
};
typedef vector<pair<string::size_type, string::size_type> > labelparts_t;
bool labeltokUnescape(labelparts_t& parts, const string& label);
+std::vector<string> segmentDNSText(const string& text); // from dnslabeltext.rl
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/epollmplexer.cc
^
|
@@ -10,7 +10,7 @@
#endif
#include "namespaces.hh"
-using namespace std;
+#include "namespaces.hh"
class EpollFDMultiplexer : public FDMultiplexer
{
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/document.h
^
|
@@ -0,0 +1,821 @@
+#ifndef RAPIDJSON_DOCUMENT_H_
+#define RAPIDJSON_DOCUMENT_H_
+
+#include "reader.h"
+#include "internal/strfunc.h"
+#include <new> // placement new
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace rapidjson {
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericValue
+
+//! Represents a JSON value. Use Value for UTF8 encoding and default allocator.
+/*!
+ A JSON value can be one of 7 types. This class is a variant type supporting
+ these types.
+
+ Use the Value if UTF8 and default allocator
+
+ \tparam Encoding Encoding of the value. (Even non-string values need to have the same encoding in a document)
+ \tparam Allocator Allocator type for allocating memory of object, array and string.
+*/
+#pragma pack (push, 4)
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericValue {
+public:
+ //! Name-value pair in an object.
+ struct Member {
+ GenericValue<Encoding, Allocator> name; //!< name of member (must be a string)
+ GenericValue<Encoding, Allocator> value; //!< value of member.
+ };
+
+ typedef Encoding EncodingType; //!< Encoding type from template parameter.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef Member* MemberIterator; //!< Member iterator for iterating in object.
+ typedef const Member* ConstMemberIterator; //!< Constant member iterator for iterating in object.
+ typedef GenericValue* ValueIterator; //!< Value iterator for iterating in array.
+ typedef const GenericValue* ConstValueIterator; //!< Constant value iterator for iterating in array.
+
+ //!@name Constructors and destructor.
+ //@{
+
+ //! Default constructor creates a null value.
+ GenericValue() : flags_(kNullFlag) {}
+
+ //! Copy constructor is not permitted.
+private:
+ GenericValue(const GenericValue& rhs);
+
+public:
+
+ //! Constructor with JSON value type.
+ /*! This creates a Value of specified type with default content.
+ \param type Type of the value.
+ \note Default content for number is zero.
+ */
+ GenericValue(Type type) {
+ static const unsigned defaultFlags[7] = {
+ kNullFlag, kFalseFlag, kTrueFlag, kObjectFlag, kArrayFlag, kConstStringFlag,
+ kNumberFlag | kIntFlag | kUintFlag | kInt64Flag | kUint64Flag | kDoubleFlag
+ };
+ RAPIDJSON_ASSERT(type <= kNumberType);
+ flags_ = defaultFlags[type];
+ memset(&data_, 0, sizeof(data_));
+ }
+
+ //! Constructor for boolean value.
+ GenericValue(bool b) : flags_(b ? kTrueFlag : kFalseFlag) {}
+
+ //! Constructor for int value.
+ GenericValue(int i) : flags_(kNumberIntFlag) {
+ data_.n.i64 = i;
+ if (i >= 0)
+ flags_ |= kUintFlag | kUint64Flag;
+ }
+
+ //! Constructor for unsigned value.
+ GenericValue(unsigned u) : flags_(kNumberUintFlag) {
+ data_.n.u64 = u;
+ if (!(u & 0x80000000))
+ flags_ |= kIntFlag | kInt64Flag;
+ }
+
+ //! Constructor for int64_t value.
+ GenericValue(int64_t i64) : flags_(kNumberInt64Flag) {
+ data_.n.i64 = i64;
+ if (i64 >= 0) {
+ flags_ |= kNumberUint64Flag;
+ if (!(i64 & 0xFFFFFFFF00000000LL))
+ flags_ |= kUintFlag;
+ if (!(i64 & 0xFFFFFFFF80000000LL))
+ flags_ |= kIntFlag;
+ }
+ else if (i64 >= -2147483648LL)
+ flags_ |= kIntFlag;
+ }
+
+ //! Constructor for uint64_t value.
+ GenericValue(uint64_t u64) : flags_(kNumberUint64Flag) {
+ data_.n.u64 = u64;
+ if (!(u64 & 0x8000000000000000ULL))
+ flags_ |= kInt64Flag;
+ if (!(u64 & 0xFFFFFFFF00000000ULL))
+ flags_ |= kUintFlag;
+ if (!(u64 & 0xFFFFFFFF80000000ULL))
+ flags_ |= kIntFlag;
+ }
+
+ //! Constructor for double value.
+ GenericValue(double d) : flags_(kNumberDoubleFlag) { data_.n.d = d; }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s, SizeType length) {
+ RAPIDJSON_ASSERT(s != NULL);
+ flags_ = kConstStringFlag;
+ data_.s.str = s;
+ data_.s.length = length;
+ }
+
+ //! Constructor for constant string (i.e. do not make a copy of string)
+ GenericValue(const Ch* s) { SetStringRaw(s, internal::StrLen(s)); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch* s, SizeType length, Allocator& allocator) { SetStringRaw(s, length, allocator); }
+
+ //! Constructor for copy-string (i.e. do make a copy of string)
+ GenericValue(const Ch*s, Allocator& allocator) { SetStringRaw(s, internal::StrLen(s), allocator); }
+
+ //! Destructor.
+ /*! Need to destruct elements of array, members of object, or copy-string.
+ */
+ ~GenericValue() {
+ if (Allocator::kNeedFree) { // Shortcut by Allocator's trait
+ switch(flags_) {
+ case kArrayFlag:
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ v->~GenericValue();
+ Allocator::Free(data_.a.elements);
+ break;
+
+ case kObjectFlag:
+ for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
+ m->name.~GenericValue();
+ m->value.~GenericValue();
+ }
+ Allocator::Free(data_.o.members);
+ break;
+
+ case kCopyStringFlag:
+ Allocator::Free(const_cast<Ch*>(data_.s.str));
+ break;
+ }
+ }
+ }
+
+ //@}
+
+ //!@name Assignment operators
+ //@{
+
+ //! Assignment with move semantics.
+ /*! \param rhs Source of the assignment. It will become a null value after assignment.
+ */
+ GenericValue& operator=(GenericValue& rhs) {
+ RAPIDJSON_ASSERT(this != &rhs);
+ this->~GenericValue();
+ memcpy(this, &rhs, sizeof(GenericValue));
+ rhs.flags_ = kNullFlag;
+ return *this;
+ }
+
+ //! Assignment with primitive types.
+ /*! \tparam T Either Type, int, unsigned, int64_t, uint64_t, const Ch*
+ \param value The value to be assigned.
+ */
+ template <typename T>
+ GenericValue& operator=(T value) {
+ this->~GenericValue();
+ new (this) GenericValue(value);
+ return *this;
+ }
+ //@}
+
+ //!@name Type
+ //@{
+
+ Type GetType() const { return static_cast<Type>(flags_ & kTypeMask); }
+ bool IsNull() const { return flags_ == kNullFlag; }
+ bool IsFalse() const { return flags_ == kFalseFlag; }
+ bool IsTrue() const { return flags_ == kTrueFlag; }
+ bool IsBool() const { return (flags_ & kBoolFlag) != 0; }
+ bool IsObject() const { return flags_ == kObjectFlag; }
+ bool IsArray() const { return flags_ == kArrayFlag; }
+ bool IsNumber() const { return (flags_ & kNumberFlag) != 0; }
+ bool IsInt() const { return (flags_ & kIntFlag) != 0; }
+ bool IsUint() const { return (flags_ & kUintFlag) != 0; }
+ bool IsInt64() const { return (flags_ & kInt64Flag) != 0; }
+ bool IsUint64() const { return (flags_ & kUint64Flag) != 0; }
+ bool IsDouble() const { return (flags_ & kDoubleFlag) != 0; }
+ bool IsString() const { return (flags_ & kStringFlag) != 0; }
+
+ //@}
+
+ //!@name Null
+ //@{
+
+ GenericValue& SetNull() { this->~GenericValue(); new (this) GenericValue(); return *this; }
+
+ //@}
+
+ //!@name Bool
+ //@{
+
+ bool GetBool() const { RAPIDJSON_ASSERT(IsBool()); return flags_ == kTrueFlag; }
+ GenericValue& SetBool(bool b) { this->~GenericValue(); new (this) GenericValue(b); return *this; }
+
+ //@}
+
+ //!@name Object
+ //@{
+
+ //! Set this value as an empty object.
+ GenericValue& SetObject() { this->~GenericValue(); new (this) GenericValue(kObjectType); return *this; }
+
+ //! Get the value associated with the object's name.
+ GenericValue& operator[](const Ch* name) {
+ if (Member* member = FindMember(name))
+ return member->value;
+ else {
+ static GenericValue NullValue;
+ return NullValue;
+ }
+ }
+ const GenericValue& operator[](const Ch* name) const { return const_cast<GenericValue&>(*this)[name]; }
+
+ //! Member iterators.
+ ConstMemberIterator MemberBegin() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
+ ConstMemberIterator MemberEnd() const { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
+ MemberIterator MemberBegin() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members; }
+ MemberIterator MemberEnd() { RAPIDJSON_ASSERT(IsObject()); return data_.o.members + data_.o.size; }
+
+ //! Check whether a member exists in the object.
+ bool HasMember(const Ch* name) const { return FindMember(name) != 0; }
+
+ //! Add a member (name-value pair) to the object.
+ /*! \param name A string value as name of member.
+ \param value Value of any type.
+ \param allocator Allocator for reallocating memory.
+ \return The value itself for fluent API.
+ \note The ownership of name and value will be transfered to this object if success.
+ */
+ GenericValue& AddMember(GenericValue& name, GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsObject());
+ RAPIDJSON_ASSERT(name.IsString());
+ Object& o = data_.o;
+ if (o.size >= o.capacity) {
+ if (o.capacity == 0) {
+ o.capacity = kDefaultObjectCapacity;
+ o.members = (Member*)allocator.Malloc(o.capacity * sizeof(Member));
+ }
+ else {
+ SizeType oldCapacity = o.capacity;
+ o.capacity *= 2;
+ o.members = (Member*)allocator.Realloc(o.members, oldCapacity * sizeof(Member), o.capacity * sizeof(Member));
+ }
+ }
+ o.members[o.size].name.RawAssign(name);
+ o.members[o.size].value.RawAssign(value);
+ o.size++;
+ return *this;
+ }
+
+ GenericValue& AddMember(const Ch* name, Allocator& nameAllocator, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name, internal::StrLen(name), nameAllocator);
+ return AddMember(n, value, allocator);
+ }
+
+ GenericValue& AddMember(const Ch* name, GenericValue& value, Allocator& allocator) {
+ GenericValue n(name, internal::StrLen(name));
+ return AddMember(n, value, allocator);
+ }
+
+ template <typename T>
+ GenericValue& AddMember(const Ch* name, T value, Allocator& allocator) {
+ GenericValue n(name, internal::StrLen(name));
+ GenericValue v(value);
+ return AddMember(n, v, allocator);
+ }
+
+ //! Remove a member in object by its name.
+ /*! \param name Name of member to be removed.
+ \return Whether the member existed.
+ \note Removing member is implemented by moving the last member. So the ordering of members is changed.
+ */
+ bool RemoveMember(const Ch* name) {
+ RAPIDJSON_ASSERT(IsObject());
+ if (Member* m = FindMember(name)) {
+ RAPIDJSON_ASSERT(data_.o.size > 0);
+ RAPIDJSON_ASSERT(data_.o.members != 0);
+
+ Member* last = data_.o.members + (data_.o.size - 1);
+ if (data_.o.size > 1 && m != last) {
+ // Move the last one to this place
+ m->name = last->name;
+ m->value = last->value;
+ }
+ else {
+ // Only one left, just destroy
+ m->name.~GenericValue();
+ m->value.~GenericValue();
+ }
+ --data_.o.size;
+ return true;
+ }
+ return false;
+ }
+
+ //@}
+
+ //!@name Array
+ //@{
+
+ //! Set this value as an empty array.
+ GenericValue& SetArray() { this->~GenericValue(); new (this) GenericValue(kArrayType); return *this; }
+
+ //! Get the number of elements in array.
+ SizeType Size() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size; }
+
+ //! Get the capacity of array.
+ SizeType Capacity() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.capacity; }
+
+ //! Check whether the array is empty.
+ bool Empty() const { RAPIDJSON_ASSERT(IsArray()); return data_.a.size == 0; }
+
+ //! Remove all elements in the array.
+ /*! This function do not deallocate memory in the array, i.e. the capacity is unchanged.
+ */
+ void Clear() {
+ RAPIDJSON_ASSERT(IsArray());
+ for (SizeType i = 0; i < data_.a.size; ++i)
+ data_.a.elements[i].~GenericValue();
+ data_.a.size = 0;
+ }
+
+ //! Get an element from array by index.
+ /*! \param index Zero-based index of element.
+ \note
+\code
+Value a(kArrayType);
+a.PushBack(123);
+int x = a[0].GetInt(); // Error: operator[ is ambiguous, as 0 also mean a null pointer of const char* type.
+int y = a[SizeType(0)].GetInt(); // Cast to SizeType will work.
+int z = a[0u].GetInt(); // This works too.
+\endcode
+ */
+ GenericValue& operator[](SizeType index) {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(index < data_.a.size);
+ return data_.a.elements[index];
+ }
+ const GenericValue& operator[](SizeType index) const { return const_cast<GenericValue&>(*this)[index]; }
+
+ //! Element iterator
+ ValueIterator Begin() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements; }
+ ValueIterator End() { RAPIDJSON_ASSERT(IsArray()); return data_.a.elements + data_.a.size; }
+ ConstValueIterator Begin() const { return const_cast<GenericValue&>(*this).Begin(); }
+ ConstValueIterator End() const { return const_cast<GenericValue&>(*this).End(); }
+
+ //! Request the array to have enough capacity to store elements.
+ /*! \param newCapacity The capacity that the array at least need to have.
+ \param allocator The allocator for allocating memory. It must be the same one use previously.
+ \return The value itself for fluent API.
+ */
+ GenericValue& Reserve(SizeType newCapacity, Allocator &allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (newCapacity > data_.a.capacity) {
+ data_.a.elements = (GenericValue*)allocator.Realloc(data_.a.elements, data_.a.capacity * sizeof(GenericValue), newCapacity * sizeof(GenericValue));
+ data_.a.capacity = newCapacity;
+ }
+ return *this;
+ }
+
+ //! Append a value at the end of the array.
+ /*! \param value The value to be appended.
+ \param allocator The allocator for allocating memory. It must be the same one use previously.
+ \return The value itself for fluent API.
+ \note The ownership of the value will be transfered to this object if success.
+ \note If the number of elements to be appended is known, calls Reserve() once first may be more efficient.
+ */
+ GenericValue& PushBack(GenericValue& value, Allocator& allocator) {
+ RAPIDJSON_ASSERT(IsArray());
+ if (data_.a.size >= data_.a.capacity)
+ Reserve(data_.a.capacity == 0 ? kDefaultArrayCapacity : data_.a.capacity * 2, allocator);
+ data_.a.elements[data_.a.size++].RawAssign(value);
+ return *this;
+ }
+
+ template <typename T>
+ GenericValue& PushBack(T value, Allocator& allocator) {
+ GenericValue v(value);
+ return PushBack(v, allocator);
+ }
+
+ //! Remove the last element in the array.
+ GenericValue& PopBack() {
+ RAPIDJSON_ASSERT(IsArray());
+ RAPIDJSON_ASSERT(!Empty());
+ data_.a.elements[--data_.a.size].~GenericValue();
+ return *this;
+ }
+ //@}
+
+ //!@name Number
+ //@{
+
+ int GetInt() const { RAPIDJSON_ASSERT(flags_ & kIntFlag); return data_.n.i.i; }
+ unsigned GetUint() const { RAPIDJSON_ASSERT(flags_ & kUintFlag); return data_.n.u.u; }
+ int64_t GetInt64() const { RAPIDJSON_ASSERT(flags_ & kInt64Flag); return data_.n.i64; }
+ uint64_t GetUint64() const { RAPIDJSON_ASSERT(flags_ & kUint64Flag); return data_.n.u64; }
+
+ double GetDouble() const {
+ RAPIDJSON_ASSERT(IsNumber());
+ if ((flags_ & kDoubleFlag) != 0) return data_.n.d; // exact type, no conversion.
+ if ((flags_ & kIntFlag) != 0) return data_.n.i.i; // int -> double
+ if ((flags_ & kUintFlag) != 0) return data_.n.u.u; // unsigned -> double
+ if ((flags_ & kInt64Flag) != 0) return (double)data_.n.i64; // int64_t -> double (may lose precision)
+ RAPIDJSON_ASSERT((flags_ & kUint64Flag) != 0); return (double)data_.n.u64; // uint64_t -> double (may lose precision)
+ }
+
+ GenericValue& SetInt(int i) { this->~GenericValue(); new (this) GenericValue(i); return *this; }
+ GenericValue& SetUint(unsigned u) { this->~GenericValue(); new (this) GenericValue(u); return *this; }
+ GenericValue& SetInt64(int64_t i64) { this->~GenericValue(); new (this) GenericValue(i64); return *this; }
+ GenericValue& SetUint64(uint64_t u64) { this->~GenericValue(); new (this) GenericValue(u64); return *this; }
+ GenericValue& SetDouble(double d) { this->~GenericValue(); new (this) GenericValue(d); return *this; }
+
+ //@}
+
+ //!@name String
+ //@{
+
+ const Ch* GetString() const { RAPIDJSON_ASSERT(IsString()); return data_.s.str; }
+
+ //! Get the length of string.
+ /*! Since rapidjson permits "\u0000" in the json string, strlen(v.GetString()) may not equal to v.GetStringLength().
+ */
+ SizeType GetStringLength() const { RAPIDJSON_ASSERT(IsString()); return data_.s.length; }
+
+ //! Set this value as a string without copying source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string pointer.
+ \param length The length of source string, excluding the trailing null terminator.
+ \return The value itself for fluent API.
+ */
+ GenericValue& SetString(const Ch* s, SizeType length) { this->~GenericValue(); SetStringRaw(s, length); return *this; }
+
+ //! Set this value as a string without copying source string.
+ /*! \param s source string pointer.
+ \return The value itself for fluent API.
+ */
+ GenericValue& SetString(const Ch* s) { return SetString(s, internal::StrLen(s)); }
+
+ //! Set this value as a string by copying from source string.
+ /*! This version has better performance with supplied length, and also support string containing null character.
+ \param s source string.
+ \param length The length of source string, excluding the trailing null terminator.
+ \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
+ \return The value itself for fluent API.
+ */
+ GenericValue& SetString(const Ch* s, SizeType length, Allocator& allocator) { this->~GenericValue(); SetStringRaw(s, length, allocator); return *this; }
+
+ //! Set this value as a string by copying from source string.
+ /*! \param s source string.
+ \param allocator Allocator for allocating copied buffer. Commonly use document.GetAllocator().
+ \return The value itself for fluent API.
+ */
+ GenericValue& SetString(const Ch* s, Allocator& allocator) { SetString(s, internal::StrLen(s), allocator); return *this; }
+
+ //@}
+
+ //! Generate events of this value to a Handler.
+ /*! This function adopts the GoF visitor pattern.
+ Typical usage is to output this JSON value as JSON text via Writer, which is a Handler.
+ It can also be used to deep clone this value via GenericDocument, which is also a Handler.
+ \tparam Handler type of handler.
+ \param handler An object implementing concept Handler.
+ */
+ template <typename Handler>
+ const GenericValue& Accept(Handler& handler) const {
+ switch(GetType()) {
+ case kNullType: handler.Null(); break;
+ case kFalseType: handler.Bool(false); break;
+ case kTrueType: handler.Bool(true); break;
+
+ case kObjectType:
+ handler.StartObject();
+ for (Member* m = data_.o.members; m != data_.o.members + data_.o.size; ++m) {
+ handler.String(m->name.data_.s.str, m->name.data_.s.length, false);
+ m->value.Accept(handler);
+ }
+ handler.EndObject(data_.o.size);
+ break;
+
+ case kArrayType:
+ handler.StartArray();
+ for (GenericValue* v = data_.a.elements; v != data_.a.elements + data_.a.size; ++v)
+ v->Accept(handler);
+ handler.EndArray(data_.a.size);
+ break;
+
+ case kStringType:
+ handler.String(data_.s.str, data_.s.length, false);
+ break;
+
+ case kNumberType:
+ if (IsInt()) handler.Int(data_.n.i.i);
+ else if (IsUint()) handler.Uint(data_.n.u.u);
+ else if (IsInt64()) handler.Int64(data_.n.i64);
+ else if (IsUint64()) handler.Uint64(data_.n.u64);
+ else handler.Double(data_.n.d);
+ break;
+ }
+ return *this;
+ }
+
+private:
+ template <typename, typename>
+ friend class GenericDocument;
+
+ enum {
+ kBoolFlag = 0x100,
+ kNumberFlag = 0x200,
+ kIntFlag = 0x400,
+ kUintFlag = 0x800,
+ kInt64Flag = 0x1000,
+ kUint64Flag = 0x2000,
+ kDoubleFlag = 0x4000,
+ kStringFlag = 0x100000,
+ kCopyFlag = 0x200000,
+
+ // Initial flags of different types.
+ kNullFlag = kNullType,
+ kTrueFlag = kTrueType | kBoolFlag,
+ kFalseFlag = kFalseType | kBoolFlag,
+ kNumberIntFlag = kNumberType | kNumberFlag | kIntFlag | kInt64Flag,
+ kNumberUintFlag = kNumberType | kNumberFlag | kUintFlag | kUint64Flag | kInt64Flag,
+ kNumberInt64Flag = kNumberType | kNumberFlag | kInt64Flag,
+ kNumberUint64Flag = kNumberType | kNumberFlag | kUint64Flag,
+ kNumberDoubleFlag = kNumberType | kNumberFlag | kDoubleFlag,
+ kConstStringFlag = kStringType | kStringFlag,
+ kCopyStringFlag = kStringType | kStringFlag | kCopyFlag,
+ kObjectFlag = kObjectType,
+ kArrayFlag = kArrayType,
+
+ kTypeMask = 0xFF // bitwise-and with mask of 0xFF can be optimized by compiler
+ };
+
+ static const SizeType kDefaultArrayCapacity = 16;
+ static const SizeType kDefaultObjectCapacity = 16;
+
+ struct String {
+ const Ch* str;
+ SizeType length;
+ unsigned hashcode; //!< reserved
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ // By using proper binary layout, retrieval of different integer types do not need conversions.
+ union Number {
+#if RAPIDJSON_ENDIAN == RAPIDJSON_LITTLEENDIAN
+ struct I {
+ int i;
+ char padding[4];
+ }i;
+ struct U {
+ unsigned u;
+ char padding2[4];
+ }u;
+#else
+ struct I {
+ char padding[4];
+ int i;
+ }i;
+ struct U {
+ char padding2[4];
+ unsigned u;
+ }u;
+#endif
+ int64_t i64;
+ uint64_t u64;
+ double d;
+ }; // 8 bytes
+
+ struct Object {
+ Member* members;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ struct Array {
+ GenericValue<Encoding, Allocator>* elements;
+ SizeType size;
+ SizeType capacity;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ union Data {
+ String s;
+ Number n;
+ Object o;
+ Array a;
+ }; // 12 bytes in 32-bit mode, 16 bytes in 64-bit mode
+
+ //! Find member by name.
+ Member* FindMember(const Ch* name) {
+ RAPIDJSON_ASSERT(name);
+ RAPIDJSON_ASSERT(IsObject());
+
+ SizeType length = internal::StrLen(name);
+
+ Object& o = data_.o;
+ for (Member* member = o.members; member != data_.o.members + data_.o.size; ++member)
+ if (length == member->name.data_.s.length && memcmp(member->name.data_.s.str, name, length * sizeof(Ch)) == 0)
+ return member;
+
+ return 0;
+ }
+ const Member* FindMember(const Ch* name) const { return const_cast<GenericValue&>(*this).FindMember(name); }
+
+ // Initialize this value as array with initial data, without calling destructor.
+ void SetArrayRaw(GenericValue* values, SizeType count, Allocator& alloctaor) {
+ flags_ = kArrayFlag;
+ data_.a.elements = (GenericValue*)alloctaor.Malloc(count * sizeof(GenericValue));
+ memcpy(data_.a.elements, values, count * sizeof(GenericValue));
+ data_.a.size = data_.a.capacity = count;
+ }
+
+ //! Initialize this value as object with initial data, without calling destructor.
+ void SetObjectRaw(Member* members, SizeType count, Allocator& alloctaor) {
+ flags_ = kObjectFlag;
+ data_.o.members = (Member*)alloctaor.Malloc(count * sizeof(Member));
+ memcpy(data_.o.members, members, count * sizeof(Member));
+ data_.o.size = data_.o.capacity = count;
+ }
+
+ //! Initialize this value as constant string, without calling destructor.
+ void SetStringRaw(const Ch* s, SizeType length) {
+ RAPIDJSON_ASSERT(s != NULL);
+ flags_ = kConstStringFlag;
+ data_.s.str = s;
+ data_.s.length = length;
+ }
+
+ //! Initialize this value as copy string with initial data, without calling destructor.
+ void SetStringRaw(const Ch* s, SizeType length, Allocator& allocator) {
+ RAPIDJSON_ASSERT(s != NULL);
+ flags_ = kCopyStringFlag;
+ data_.s.str = (Ch *)allocator.Malloc((length + 1) * sizeof(Ch));
+ data_.s.length = length;
+ memcpy(const_cast<Ch*>(data_.s.str), s, length * sizeof(Ch));
+ const_cast<Ch*>(data_.s.str)[length] = '\0';
+ }
+
+ //! Assignment without calling destructor
+ void RawAssign(GenericValue& rhs) {
+ memcpy(this, &rhs, sizeof(GenericValue));
+ rhs.flags_ = kNullFlag;
+ }
+
+ Data data_;
+ unsigned flags_;
+};
+#pragma pack (pop)
+
+//! Value with UTF8 encoding.
+typedef GenericValue<UTF8<> > Value;
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericDocument
+
+//! A document for parsing JSON text as DOM.
+/*!
+ \implements Handler
+ \tparam Encoding encoding for both parsing and string storage.
+ \tparam Alloactor allocator for allocating memory for the DOM, and the stack during parsing.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericDocument : public GenericValue<Encoding, Allocator> {
+public:
+ typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
+ typedef GenericValue<Encoding, Allocator> ValueType; //!< Value type of the document.
+ typedef Allocator AllocatorType; //!< Allocator type from template parameter.
+
+ //! Constructor
+ /*! \param allocator Optional allocator for allocating stack memory.
+ \param stackCapacity Initial capacity of stack in bytes.
+ */
+ GenericDocument(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
+
+ //! Parse JSON text from an input stream.
+ /*! \tparam parseFlags Combination of ParseFlag.
+ \param stream Input stream to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags, typename Stream>
+ GenericDocument& ParseStream(Stream& stream) {
+ ValueType::SetNull(); // Remove existing root if exist
+ GenericReader<Encoding, Allocator> reader;
+ if (reader.template Parse<parseFlags>(stream, *this)) {
+ RAPIDJSON_ASSERT(stack_.GetSize() == sizeof(ValueType)); // Got one and only one root object
+ this->RawAssign(*stack_.template Pop<ValueType>(1)); // Add this-> to prevent issue 13.
+ parseError_ = 0;
+ errorOffset_ = 0;
+ }
+ else {
+ parseError_ = reader.GetParseError();
+ errorOffset_ = reader.GetErrorOffset();
+ ClearStack();
+ }
+ return *this;
+ }
+
+ //! Parse JSON text from a mutable string.
+ /*! \tparam parseFlags Combination of ParseFlag.
+ \param str Mutable zero-terminated string to be parsed.
+ \return The document itself for fluent API.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& ParseInsitu(Ch* str) {
+ GenericInsituStringStream<Encoding> s(str);
+ return ParseStream<parseFlags | kParseInsituFlag>(s);
+ }
+
+ //! Parse JSON text from a read-only string.
+ /*! \tparam parseFlags Combination of ParseFlag (must not contain kParseInsituFlag).
+ \param str Read-only zero-terminated string to be parsed.
+ */
+ template <unsigned parseFlags>
+ GenericDocument& Parse(const Ch* str) {
+ RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
+ GenericStringStream<Encoding> s(str);
+ return ParseStream<parseFlags>(s);
+ }
+
+ //! Whether a parse error was occured in the last parsing.
+ bool HasParseError() const { return parseError_ != 0; }
+
+ //! Get the message of parsing error.
+ const char* GetParseError() const { return parseError_; }
+
+ //! Get the offset in character of the parsing error.
+ size_t GetErrorOffset() const { return errorOffset_; }
+
+ //! Get the allocator of this document.
+ Allocator& GetAllocator() { return stack_.GetAllocator(); }
+
+ //! Get the capacity of stack in bytes.
+ size_t GetStackCapacity() const { return stack_.GetCapacity(); }
+
+private:
+ // Prohibit assignment
+ GenericDocument& operator=(const GenericDocument&);
+
+ friend class GenericReader<Encoding, Allocator>; // for Reader to call the following private handler functions
+
+ // Implementation of Handler
+ void Null() { new (stack_.template Push<ValueType>()) ValueType(); }
+ void Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); }
+ void Int(int i) { new (stack_.template Push<ValueType>()) ValueType(i); }
+ void Uint(unsigned i) { new (stack_.template Push<ValueType>()) ValueType(i); }
+ void Int64(int64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
+ void Uint64(uint64_t i) { new (stack_.template Push<ValueType>()) ValueType(i); }
+ void Double(double d) { new (stack_.template Push<ValueType>()) ValueType(d); }
+
+ void String(const Ch* str, SizeType length, bool copy) {
+ if (copy)
+ new (stack_.template Push<ValueType>()) ValueType(str, length, GetAllocator());
+ else
+ new (stack_.template Push<ValueType>()) ValueType(str, length);
+ }
+
+ void StartObject() { new (stack_.template Push<ValueType>()) ValueType(kObjectType); }
+
+ void EndObject(SizeType memberCount) {
+ typename ValueType::Member* members = stack_.template Pop<typename ValueType::Member>(memberCount);
+ stack_.template Top<ValueType>()->SetObjectRaw(members, (SizeType)memberCount, GetAllocator());
+ }
+
+ void StartArray() { new (stack_.template Push<ValueType>()) ValueType(kArrayType); }
+
+ void EndArray(SizeType elementCount) {
+ ValueType* elements = stack_.template Pop<ValueType>(elementCount);
+ stack_.template Top<ValueType>()->SetArrayRaw(elements, elementCount, GetAllocator());
+ }
+
+ void ClearStack() {
+ if (Allocator::kNeedFree)
+ while (stack_.GetSize() > 0) // Here assumes all elements in stack array are GenericValue (Member is actually 2 GenericValue objects)
+ (stack_.template Pop<ValueType>(1))->~ValueType();
+ else
+ stack_.Clear();
+ }
+
+ static const size_t kDefaultStackCapacity = 1024;
+ internal::Stack<Allocator> stack_;
+ const char* parseError_;
+ size_t errorOffset_;
+};
+
+typedef GenericDocument<UTF8<> > Document;
+
+} // namespace rapidjson
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // RAPIDJSON_DOCUMENT_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/filestream.h
^
|
@@ -0,0 +1,46 @@
+#ifndef RAPIDJSON_FILESTREAM_H_
+#define RAPIDJSON_FILESTREAM_H_
+
+#include <cstdio>
+
+namespace rapidjson {
+
+//! Wrapper of C file stream for input or output.
+/*!
+ This simple wrapper does not check the validity of the stream.
+ \implements Stream
+*/
+class FileStream {
+public:
+ typedef char Ch; //!< Character type. Only support char.
+
+ FileStream(FILE* fp) : fp_(fp), count_(0) { Read(); }
+ char Peek() const { return current_; }
+ char Take() { char c = current_; Read(); return c; }
+ size_t Tell() const { return count_; }
+ void Put(char c) { fputc(c, fp_); }
+
+ // Not implemented
+ char* PutBegin() { return 0; }
+ size_t PutEnd(char*) { return 0; }
+
+private:
+ void Read() {
+ RAPIDJSON_ASSERT(fp_ != 0);
+ int c = fgetc(fp_);
+ if (c != EOF) {
+ current_ = (char)c;
+ count_++;
+ }
+ else
+ current_ = '\0';
+ }
+
+ FILE* fp_;
+ char current_;
+ size_t count_;
+};
+
+} // namespace rapidjson
+
+#endif // RAPIDJSON_FILESTREAM_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/internal
^
|
+(directory)
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/internal/pow10.h
^
|
@@ -0,0 +1,54 @@
+#ifndef RAPIDJSON_POW10_
+#define RAPIDJSON_POW10_
+
+namespace rapidjson {
+namespace internal {
+
+//! Computes integer powers of 10 in double (10.0^n).
+/*! This function uses lookup table for fast and accurate results.
+ \param n positive/negative exponent. Must <= 308.
+ \return 10.0^n
+*/
+inline double Pow10(int n) {
+ static const double e[] = { // 1e-308...1e308: 617 * 8 bytes = 4936 bytes
+ 1e-308,1e-307,1e-306,1e-305,1e-304,1e-303,1e-302,1e-301,1e-300,
+ 1e-299,1e-298,1e-297,1e-296,1e-295,1e-294,1e-293,1e-292,1e-291,1e-290,1e-289,1e-288,1e-287,1e-286,1e-285,1e-284,1e-283,1e-282,1e-281,1e-280,
+ 1e-279,1e-278,1e-277,1e-276,1e-275,1e-274,1e-273,1e-272,1e-271,1e-270,1e-269,1e-268,1e-267,1e-266,1e-265,1e-264,1e-263,1e-262,1e-261,1e-260,
+ 1e-259,1e-258,1e-257,1e-256,1e-255,1e-254,1e-253,1e-252,1e-251,1e-250,1e-249,1e-248,1e-247,1e-246,1e-245,1e-244,1e-243,1e-242,1e-241,1e-240,
+ 1e-239,1e-238,1e-237,1e-236,1e-235,1e-234,1e-233,1e-232,1e-231,1e-230,1e-229,1e-228,1e-227,1e-226,1e-225,1e-224,1e-223,1e-222,1e-221,1e-220,
+ 1e-219,1e-218,1e-217,1e-216,1e-215,1e-214,1e-213,1e-212,1e-211,1e-210,1e-209,1e-208,1e-207,1e-206,1e-205,1e-204,1e-203,1e-202,1e-201,1e-200,
+ 1e-199,1e-198,1e-197,1e-196,1e-195,1e-194,1e-193,1e-192,1e-191,1e-190,1e-189,1e-188,1e-187,1e-186,1e-185,1e-184,1e-183,1e-182,1e-181,1e-180,
+ 1e-179,1e-178,1e-177,1e-176,1e-175,1e-174,1e-173,1e-172,1e-171,1e-170,1e-169,1e-168,1e-167,1e-166,1e-165,1e-164,1e-163,1e-162,1e-161,1e-160,
+ 1e-159,1e-158,1e-157,1e-156,1e-155,1e-154,1e-153,1e-152,1e-151,1e-150,1e-149,1e-148,1e-147,1e-146,1e-145,1e-144,1e-143,1e-142,1e-141,1e-140,
+ 1e-139,1e-138,1e-137,1e-136,1e-135,1e-134,1e-133,1e-132,1e-131,1e-130,1e-129,1e-128,1e-127,1e-126,1e-125,1e-124,1e-123,1e-122,1e-121,1e-120,
+ 1e-119,1e-118,1e-117,1e-116,1e-115,1e-114,1e-113,1e-112,1e-111,1e-110,1e-109,1e-108,1e-107,1e-106,1e-105,1e-104,1e-103,1e-102,1e-101,1e-100,
+ 1e-99, 1e-98, 1e-97, 1e-96, 1e-95, 1e-94, 1e-93, 1e-92, 1e-91, 1e-90, 1e-89, 1e-88, 1e-87, 1e-86, 1e-85, 1e-84, 1e-83, 1e-82, 1e-81, 1e-80,
+ 1e-79, 1e-78, 1e-77, 1e-76, 1e-75, 1e-74, 1e-73, 1e-72, 1e-71, 1e-70, 1e-69, 1e-68, 1e-67, 1e-66, 1e-65, 1e-64, 1e-63, 1e-62, 1e-61, 1e-60,
+ 1e-59, 1e-58, 1e-57, 1e-56, 1e-55, 1e-54, 1e-53, 1e-52, 1e-51, 1e-50, 1e-49, 1e-48, 1e-47, 1e-46, 1e-45, 1e-44, 1e-43, 1e-42, 1e-41, 1e-40,
+ 1e-39, 1e-38, 1e-37, 1e-36, 1e-35, 1e-34, 1e-33, 1e-32, 1e-31, 1e-30, 1e-29, 1e-28, 1e-27, 1e-26, 1e-25, 1e-24, 1e-23, 1e-22, 1e-21, 1e-20,
+ 1e-19, 1e-18, 1e-17, 1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1e+0,
+ 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20,
+ 1e+21, 1e+22, 1e+23, 1e+24, 1e+25, 1e+26, 1e+27, 1e+28, 1e+29, 1e+30, 1e+31, 1e+32, 1e+33, 1e+34, 1e+35, 1e+36, 1e+37, 1e+38, 1e+39, 1e+40,
+ 1e+41, 1e+42, 1e+43, 1e+44, 1e+45, 1e+46, 1e+47, 1e+48, 1e+49, 1e+50, 1e+51, 1e+52, 1e+53, 1e+54, 1e+55, 1e+56, 1e+57, 1e+58, 1e+59, 1e+60,
+ 1e+61, 1e+62, 1e+63, 1e+64, 1e+65, 1e+66, 1e+67, 1e+68, 1e+69, 1e+70, 1e+71, 1e+72, 1e+73, 1e+74, 1e+75, 1e+76, 1e+77, 1e+78, 1e+79, 1e+80,
+ 1e+81, 1e+82, 1e+83, 1e+84, 1e+85, 1e+86, 1e+87, 1e+88, 1e+89, 1e+90, 1e+91, 1e+92, 1e+93, 1e+94, 1e+95, 1e+96, 1e+97, 1e+98, 1e+99, 1e+100,
+ 1e+101,1e+102,1e+103,1e+104,1e+105,1e+106,1e+107,1e+108,1e+109,1e+110,1e+111,1e+112,1e+113,1e+114,1e+115,1e+116,1e+117,1e+118,1e+119,1e+120,
+ 1e+121,1e+122,1e+123,1e+124,1e+125,1e+126,1e+127,1e+128,1e+129,1e+130,1e+131,1e+132,1e+133,1e+134,1e+135,1e+136,1e+137,1e+138,1e+139,1e+140,
+ 1e+141,1e+142,1e+143,1e+144,1e+145,1e+146,1e+147,1e+148,1e+149,1e+150,1e+151,1e+152,1e+153,1e+154,1e+155,1e+156,1e+157,1e+158,1e+159,1e+160,
+ 1e+161,1e+162,1e+163,1e+164,1e+165,1e+166,1e+167,1e+168,1e+169,1e+170,1e+171,1e+172,1e+173,1e+174,1e+175,1e+176,1e+177,1e+178,1e+179,1e+180,
+ 1e+181,1e+182,1e+183,1e+184,1e+185,1e+186,1e+187,1e+188,1e+189,1e+190,1e+191,1e+192,1e+193,1e+194,1e+195,1e+196,1e+197,1e+198,1e+199,1e+200,
+ 1e+201,1e+202,1e+203,1e+204,1e+205,1e+206,1e+207,1e+208,1e+209,1e+210,1e+211,1e+212,1e+213,1e+214,1e+215,1e+216,1e+217,1e+218,1e+219,1e+220,
+ 1e+221,1e+222,1e+223,1e+224,1e+225,1e+226,1e+227,1e+228,1e+229,1e+230,1e+231,1e+232,1e+233,1e+234,1e+235,1e+236,1e+237,1e+238,1e+239,1e+240,
+ 1e+241,1e+242,1e+243,1e+244,1e+245,1e+246,1e+247,1e+248,1e+249,1e+250,1e+251,1e+252,1e+253,1e+254,1e+255,1e+256,1e+257,1e+258,1e+259,1e+260,
+ 1e+261,1e+262,1e+263,1e+264,1e+265,1e+266,1e+267,1e+268,1e+269,1e+270,1e+271,1e+272,1e+273,1e+274,1e+275,1e+276,1e+277,1e+278,1e+279,1e+280,
+ 1e+281,1e+282,1e+283,1e+284,1e+285,1e+286,1e+287,1e+288,1e+289,1e+290,1e+291,1e+292,1e+293,1e+294,1e+295,1e+296,1e+297,1e+298,1e+299,1e+300,
+ 1e+301,1e+302,1e+303,1e+304,1e+305,1e+306,1e+307,1e+308
+ };
+ RAPIDJSON_ASSERT(n <= 308);
+ return n < -308 ? 0.0 : e[n + 308];
+}
+
+} // namespace internal
+} // namespace rapidjson
+
+#endif // RAPIDJSON_POW10_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/internal/stack.h
^
|
@@ -0,0 +1,82 @@
+#ifndef RAPIDJSON_INTERNAL_STACK_H_
+#define RAPIDJSON_INTERNAL_STACK_H_
+
+namespace rapidjson {
+namespace internal {
+
+///////////////////////////////////////////////////////////////////////////////
+// Stack
+
+//! A type-unsafe stack for storing different types of data.
+/*! \tparam Allocator Allocator for allocating stack memory.
+*/
+template <typename Allocator>
+class Stack {
+public:
+ Stack(Allocator* allocator, size_t stack_capacity) : allocator_(allocator), own_allocator_(0), stack_(0), stack_top_(0), stack_end_(0), stack_capacity_(stack_capacity) {
+ RAPIDJSON_ASSERT(stack_capacity_ > 0);
+ if (!allocator_)
+ own_allocator_ = allocator_ = new Allocator();
+ stack_top_ = stack_ = (char*)allocator_->Malloc(stack_capacity_);
+ stack_end_ = stack_ + stack_capacity_;
+ }
+
+ ~Stack() {
+ Allocator::Free(stack_);
+ delete own_allocator_; // Only delete if it is owned by the stack
+ }
+
+ void Clear() { /*stack_top_ = 0;*/ stack_top_ = stack_; }
+
+ template<typename T>
+ T* Push(size_t count = 1) {
+ // Expand the stack if needed
+ if (stack_top_ + sizeof(T) * count >= stack_end_) {
+ size_t new_capacity = stack_capacity_ * 2;
+ size_t size = GetSize();
+ size_t new_size = GetSize() + sizeof(T) * count;
+ if (new_capacity < new_size)
+ new_capacity = new_size;
+ stack_ = (char*)allocator_->Realloc(stack_, stack_capacity_, new_capacity);
+ stack_capacity_ = new_capacity;
+ stack_top_ = stack_ + size;
+ stack_end_ = stack_ + stack_capacity_;
+ }
+ T* ret = (T*)stack_top_;
+ stack_top_ += sizeof(T) * count;
+ return ret;
+ }
+
+ template<typename T>
+ T* Pop(size_t count) {
+ RAPIDJSON_ASSERT(GetSize() >= count * sizeof(T));
+ stack_top_ -= count * sizeof(T);
+ return (T*)stack_top_;
+ }
+
+ template<typename T>
+ T* Top() {
+ RAPIDJSON_ASSERT(GetSize() >= sizeof(T));
+ return (T*)(stack_top_ - sizeof(T));
+ }
+
+ template<typename T>
+ T* Bottom() { return (T*)stack_; }
+
+ Allocator& GetAllocator() { return *allocator_; }
+ size_t GetSize() const { return stack_top_ - stack_; }
+ size_t GetCapacity() const { return stack_capacity_; }
+
+private:
+ Allocator* allocator_;
+ Allocator* own_allocator_;
+ char *stack_;
+ char *stack_top_;
+ char *stack_end_;
+ size_t stack_capacity_;
+};
+
+} // namespace internal
+} // namespace rapidjson
+
+#endif // RAPIDJSON_STACK_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/internal/strfunc.h
^
|
@@ -0,0 +1,24 @@
+#ifndef RAPIDJSON_INTERNAL_STRFUNC_H_
+#define RAPIDJSON_INTERNAL_STRFUNC_H_
+
+namespace rapidjson {
+namespace internal {
+
+//! Custom strlen() which works on different character types.
+/*! \tparam Ch Character type (e.g. char, wchar_t, short)
+ \param s Null-terminated input string.
+ \return Number of characters in the string.
+ \note This has the same semantics as strlen(), the return value is not number of Unicode codepoints.
+*/
+template <typename Ch>
+inline SizeType StrLen(const Ch* s) {
+ const Ch* p = s;
+ while (*p != '\0')
+ ++p;
+ return SizeType(p - s);
+}
+
+} // namespace internal
+} // namespace rapidjson
+
+#endif // RAPIDJSON_INTERNAL_STRFUNC_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/prettywriter.h
^
|
@@ -0,0 +1,156 @@
+#ifndef RAPIDJSON_PRETTYWRITER_H_
+#define RAPIDJSON_PRETTYWRITER_H_
+
+#include "writer.h"
+
+namespace rapidjson {
+
+//! Writer with indentation and spacing.
+/*!
+ \tparam Stream Type of ouptut stream.
+ \tparam Encoding Encoding of both source strings and output.
+ \tparam Allocator Type of allocator for allocating memory of stack.
+*/
+template<typename Stream, typename Encoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
+class PrettyWriter : public Writer<Stream, Encoding, Allocator> {
+public:
+ typedef Writer<Stream, Encoding, Allocator> Base;
+ typedef typename Base::Ch Ch;
+
+ //! Constructor
+ /*! \param stream Output stream.
+ \param allocator User supplied allocator. If it is null, it will create a private one.
+ \param levelDepth Initial capacity of
+ */
+ PrettyWriter(Stream& stream, Allocator* allocator = 0, size_t levelDepth = Base::kDefaultLevelDepth) :
+ Base(stream, allocator, levelDepth), indentChar_(' '), indentCharCount_(4) {}
+
+ //! Set custom indentation.
+ /*! \param indentChar Character for indentation. Must be whitespace character (' ', '\t', '\n', '\r').
+ \param indentCharCount Number of indent characters for each indentation level.
+ \note The default indentation is 4 spaces.
+ */
+ PrettyWriter& SetIndent(Ch indentChar, unsigned indentCharCount) {
+ RAPIDJSON_ASSERT(indentChar == ' ' || indentChar == '\t' || indentChar == '\n' || indentChar == '\r');
+ indentChar_ = indentChar;
+ indentCharCount_ = indentCharCount;
+ return *this;
+ }
+
+ //@name Implementation of Handler.
+ //@{
+
+ PrettyWriter& Null() { PrettyPrefix(kNullType); Base::WriteNull(); return *this; }
+ PrettyWriter& Bool(bool b) { PrettyPrefix(b ? kTrueType : kFalseType); Base::WriteBool(b); return *this; }
+ PrettyWriter& Int(int i) { PrettyPrefix(kNumberType); Base::WriteInt(i); return *this; }
+ PrettyWriter& Uint(unsigned u) { PrettyPrefix(kNumberType); Base::WriteUint(u); return *this; }
+ PrettyWriter& Int64(int64_t i64) { PrettyPrefix(kNumberType); Base::WriteInt64(i64); return *this; }
+ PrettyWriter& Uint64(uint64_t u64) { PrettyPrefix(kNumberType); Base::WriteUint64(u64); return *this; }
+ PrettyWriter& Double(double d) { PrettyPrefix(kNumberType); Base::WriteDouble(d); return *this; }
+
+ PrettyWriter& String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ PrettyPrefix(kStringType);
+ Base::WriteString(str, length);
+ return *this;
+ }
+
+ PrettyWriter& StartObject() {
+ PrettyPrefix(kObjectType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(false);
+ Base::WriteStartObject();
+ return *this;
+ }
+
+ PrettyWriter& EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(!Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::stream_.Put('\n');
+ WriteIndent();
+ }
+ Base::WriteEndObject();
+ return *this;
+ }
+
+ PrettyWriter& StartArray() {
+ PrettyPrefix(kArrayType);
+ new (Base::level_stack_.template Push<typename Base::Level>()) typename Base::Level(true);
+ Base::WriteStartArray();
+ return *this;
+ }
+
+ PrettyWriter& EndArray(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(Base::level_stack_.GetSize() >= sizeof(typename Base::Level));
+ RAPIDJSON_ASSERT(Base::level_stack_.template Top<typename Base::Level>()->inArray);
+ bool empty = Base::level_stack_.template Pop<typename Base::Level>(1)->valueCount == 0;
+
+ if (!empty) {
+ Base::stream_.Put('\n');
+ WriteIndent();
+ }
+ Base::WriteEndArray();
+ return *this;
+ }
+
+ //@}
+
+ //! Simpler but slower overload.
+ PrettyWriter& String(const Ch* str) { return String(str, internal::StrLen(str)); }
+
+protected:
+ void PrettyPrefix(Type type) {
+ (void)type;
+ if (Base::level_stack_.GetSize() != 0) { // this value is not at root
+ typename Base::Level* level = Base::level_stack_.template Top<typename Base::Level>();
+
+ if (level->inArray) {
+ if (level->valueCount > 0) {
+ Base::stream_.Put(','); // add comma if it is not the first element in array
+ Base::stream_.Put('\n');
+ }
+ else
+ Base::stream_.Put('\n');
+ WriteIndent();
+ }
+ else { // in object
+ if (level->valueCount > 0) {
+ if (level->valueCount % 2 == 0) {
+ Base::stream_.Put(',');
+ Base::stream_.Put('\n');
+ }
+ else {
+ Base::stream_.Put(':');
+ Base::stream_.Put(' ');
+ }
+ }
+ else
+ Base::stream_.Put('\n');
+
+ if (level->valueCount % 2 == 0)
+ WriteIndent();
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else
+ RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
+ }
+
+ void WriteIndent() {
+ size_t count = (Base::level_stack_.GetSize() / sizeof(typename Base::Level)) * indentCharCount_;
+ PutN(Base::stream_, indentChar_, count);
+ }
+
+ Ch indentChar_;
+ unsigned indentCharCount_;
+};
+
+} // namespace rapidjson
+
+#endif // RAPIDJSON_RAPIDJSON_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/rapidjson.h
^
|
@@ -0,0 +1,525 @@
+#ifndef RAPIDJSON_RAPIDJSON_H_
+#define RAPIDJSON_RAPIDJSON_H_
+
+// Copyright (c) 2011-2012 Milo Yip (miloyip@gmail.com)
+// Version 0.11
+
+#include <cstdlib> // malloc(), realloc(), free()
+#include <cstring> // memcpy()
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_INT64DEFINE
+
+// Here defines int64_t and uint64_t types in global namespace.
+// If user have their own definition, can define RAPIDJSON_NO_INT64DEFINE to disable this.
+#ifndef RAPIDJSON_NO_INT64DEFINE
+#ifdef _MSC_VER
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+#else
+#include <inttypes.h>
+#endif
+#endif // RAPIDJSON_NO_INT64TYPEDEF
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ENDIAN
+#define RAPIDJSON_LITTLEENDIAN 0 //!< Little endian machine
+#define RAPIDJSON_BIGENDIAN 1 //!< Big endian machine
+
+//! Endianness of the machine.
+/*! GCC provided macro for detecting endianness of the target machine. But other
+ compilers may not have this. User can define RAPIDJSON_ENDIAN to either
+ RAPIDJSON_LITTLEENDIAN or RAPIDJSON_BIGENDIAN.
+*/
+#ifndef RAPIDJSON_ENDIAN
+#ifdef __BYTE_ORDER__
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN
+#else
+#define RAPIDJSON_ENDIAN RAPIDJSON_BIGENDIAN
+#endif // __BYTE_ORDER__
+#else
+#define RAPIDJSON_ENDIAN RAPIDJSON_LITTLEENDIAN // Assumes little endian otherwise.
+#endif
+#endif // RAPIDJSON_ENDIAN
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_SSE2/RAPIDJSON_SSE42/RAPIDJSON_SIMD
+
+// Enable SSE2 optimization.
+//#define RAPIDJSON_SSE2
+
+// Enable SSE4.2 optimization.
+//#define RAPIDJSON_SSE42
+
+#if defined(RAPIDJSON_SSE2) || defined(RAPIDJSON_SSE42)
+#define RAPIDJSON_SIMD
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_NO_SIZETYPEDEFINE
+
+#ifndef RAPIDJSON_NO_SIZETYPEDEFINE
+namespace rapidjson {
+//! Use 32-bit array/string indices even for 64-bit platform, instead of using size_t.
+/*! User may override the SizeType by defining RAPIDJSON_NO_SIZETYPEDEFINE.
+*/
+typedef unsigned SizeType;
+} // namespace rapidjson
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// RAPIDJSON_ASSERT
+
+//! Assertion.
+/*! By default, rapidjson uses C assert() for assertion.
+ User can override it by defining RAPIDJSON_ASSERT(x) macro.
+*/
+#ifndef RAPIDJSON_ASSERT
+#include <cassert>
+#define RAPIDJSON_ASSERT(x) assert(x)
+#endif // RAPIDJSON_ASSERT
+
+///////////////////////////////////////////////////////////////////////////////
+// Helpers
+
+#define RAPIDJSON_MULTILINEMACRO_BEGIN do {
+#define RAPIDJSON_MULTILINEMACRO_END \
+} while((void)0, 0)
+
+namespace rapidjson {
+
+///////////////////////////////////////////////////////////////////////////////
+// Allocator
+
+/*! \class rapidjson::Allocator
+ \brief Concept for allocating, resizing and freeing memory block.
+
+ Note that Malloc() and Realloc() are non-static but Free() is static.
+
+ So if an allocator need to support Free(), it needs to put its pointer in
+ the header of memory block.
+
+\code
+concept Allocator {
+ static const bool kNeedFree; //!< Whether this allocator needs to call Free().
+
+ // Allocate a memory block.
+ // \param size of the memory block in bytes.
+ // \returns pointer to the memory block.
+ void* Malloc(size_t size);
+
+ // Resize a memory block.
+ // \param originalPtr The pointer to current memory block. Null pointer is permitted.
+ // \param originalSize The current size in bytes. (Design issue: since some allocator may not book-keep this, explicitly pass to it can save memory.)
+ // \param newSize the new size in bytes.
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize);
+
+ // Free a memory block.
+ // \param pointer to the memory block. Null pointer is permitted.
+ static void Free(void *ptr);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// CrtAllocator
+
+//! C-runtime library allocator.
+/*! This class is just wrapper for standard C library memory routines.
+ \implements Allocator
+*/
+class CrtAllocator {
+public:
+ static const bool kNeedFree = true;
+ void* Malloc(size_t size) { return malloc(size); }
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) { (void)originalSize; return realloc(originalPtr, newSize); }
+ static void Free(void *ptr) { free(ptr); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// MemoryPoolAllocator
+
+//! Default memory allocator used by the parser and DOM.
+/*! This allocator allocate memory blocks from pre-allocated memory chunks.
+
+ It does not free memory blocks. And Realloc() only allocate new memory.
+
+ The memory chunks are allocated by BaseAllocator, which is CrtAllocator by default.
+
+ User may also supply a buffer as the first chunk.
+
+ If the user-buffer is full then additional chunks are allocated by BaseAllocator.
+
+ The user-buffer is not deallocated by this allocator.
+
+ \tparam BaseAllocator the allocator type for allocating memory chunks. Default is CrtAllocator.
+ \implements Allocator
+*/
+template <typename BaseAllocator = CrtAllocator>
+class MemoryPoolAllocator {
+public:
+ static const bool kNeedFree = false; //!< Tell users that no need to call Free() with this allocator. (concept Allocator)
+
+ //! Constructor with chunkSize.
+ /*! \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(0), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ if (!baseAllocator_)
+ ownBaseAllocator_ = baseAllocator_ = new BaseAllocator();
+ AddChunk(chunk_capacity_);
+ }
+
+ //! Constructor with user-supplied buffer.
+ /*! The user buffer will be used firstly. When it is full, memory pool allocates new chunk with chunk size.
+
+ The user buffer will not be deallocated when this allocator is destructed.
+
+ \param buffer User supplied buffer.
+ \param size Size of the buffer in bytes. It must at least larger than sizeof(ChunkHeader).
+ \param chunkSize The size of memory chunk. The default is kDefaultChunkSize.
+ \param baseAllocator The allocator for allocating memory chunks.
+ */
+ MemoryPoolAllocator(char *buffer, size_t size, size_t chunkSize = kDefaultChunkCapacity, BaseAllocator* baseAllocator = 0) :
+ chunkHead_(0), chunk_capacity_(chunkSize), userBuffer_(buffer), baseAllocator_(baseAllocator), ownBaseAllocator_(0)
+ {
+ RAPIDJSON_ASSERT(buffer != 0);
+ RAPIDJSON_ASSERT(size > sizeof(ChunkHeader));
+ chunkHead_ = (ChunkHeader*)buffer;
+ chunkHead_->capacity = size - sizeof(ChunkHeader);
+ chunkHead_->size = 0;
+ chunkHead_->next = 0;
+ }
+
+ //! Destructor.
+ /*! This deallocates all memory chunks, excluding the user-supplied buffer.
+ */
+ ~MemoryPoolAllocator() {
+ Clear();
+ delete ownBaseAllocator_;
+ }
+
+ //! Deallocates all memory chunks, excluding the user-supplied buffer.
+ void Clear() {
+ while(chunkHead_ != 0 && chunkHead_ != (ChunkHeader *)userBuffer_) {
+ ChunkHeader* next = chunkHead_->next;
+ baseAllocator_->Free(chunkHead_);
+ chunkHead_ = next;
+ }
+ }
+
+ //! Computes the total capacity of allocated memory chunks.
+ /*! \return total capacity in bytes.
+ */
+ size_t Capacity() {
+ size_t capacity = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ capacity += c->capacity;
+ return capacity;
+ }
+
+ //! Computes the memory blocks allocated.
+ /*! \return total used bytes.
+ */
+ size_t Size() {
+ size_t size = 0;
+ for (ChunkHeader* c = chunkHead_; c != 0; c = c->next)
+ size += c->size;
+ return size;
+ }
+
+ //! Allocates a memory block. (concept Allocator)
+ void* Malloc(size_t size) {
+ size = (size + 3) & ~3; // Force aligning size to 4
+
+ if (chunkHead_->size + size > chunkHead_->capacity)
+ AddChunk(chunk_capacity_ > size ? chunk_capacity_ : size);
+
+ char *buffer = (char *)(chunkHead_ + 1) + chunkHead_->size;
+ RAPIDJSON_ASSERT(((uintptr_t)buffer & 3) == 0); // returned buffer is aligned to 4
+ chunkHead_->size += size;
+
+ return buffer;
+ }
+
+ //! Resizes a memory block (concept Allocator)
+ void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
+ if (originalPtr == 0)
+ return Malloc(newSize);
+
+ // Do not shrink if new size is smaller than original
+ if (originalSize >= newSize)
+ return originalPtr;
+
+ // Simply expand it if it is the last allocation and there is sufficient space
+ if (originalPtr == (char *)(chunkHead_ + 1) + chunkHead_->size - originalSize) {
+ size_t increment = newSize - originalSize;
+ increment = (increment + 3) & ~3; // Force aligning size to 4
+ if (chunkHead_->size + increment <= chunkHead_->capacity) {
+ chunkHead_->size += increment;
+ RAPIDJSON_ASSERT(((uintptr_t)originalPtr & 3) == 0); // returned buffer is aligned to 4
+ return originalPtr;
+ }
+ }
+
+ // Realloc process: allocate and copy memory, do not free original buffer.
+ void* newBuffer = Malloc(newSize);
+ RAPIDJSON_ASSERT(newBuffer != 0); // Do not handle out-of-memory explicitly.
+ return memcpy(newBuffer, originalPtr, originalSize);
+ }
+
+ //! Frees a memory block (concept Allocator)
+ static void Free(void *) {} // Do nothing
+
+private:
+ //! Creates a new chunk.
+ /*! \param capacity Capacity of the chunk in bytes.
+ */
+ void AddChunk(size_t capacity) {
+ ChunkHeader* chunk = (ChunkHeader*)baseAllocator_->Malloc(sizeof(ChunkHeader) + capacity);
+ chunk->capacity = capacity;
+ chunk->size = 0;
+ chunk->next = chunkHead_;
+ chunkHead_ = chunk;
+ }
+
+ static const int kDefaultChunkCapacity = 64 * 1024; //!< Default chunk capacity.
+
+ //! Chunk header for perpending to each chunk.
+ /*! Chunks are stored as a singly linked list.
+ */
+ struct ChunkHeader {
+ size_t capacity; //!< Capacity of the chunk in bytes (excluding the header itself).
+ size_t size; //!< Current size of allocated memory in bytes.
+ ChunkHeader *next; //!< Next chunk in the linked list.
+ };
+
+ ChunkHeader *chunkHead_; //!< Head of the chunk linked-list. Only the head chunk serves allocation.
+ size_t chunk_capacity_; //!< The minimum capacity of chunk when they are allocated.
+ char *userBuffer_; //!< User supplied buffer.
+ BaseAllocator* baseAllocator_; //!< base allocator for allocating memory chunks.
+ BaseAllocator* ownBaseAllocator_; //!< base allocator created by this object.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Encoding
+
+/*! \class rapidjson::Encoding
+ \brief Concept for encoding of Unicode characters.
+
+\code
+concept Encoding {
+ typename Ch; //! Type of character.
+
+ //! \brief Encode a Unicode codepoint to a buffer.
+ //! \param buffer pointer to destination buffer to store the result. It should have sufficient size of encoding one character.
+ //! \param codepoint An unicode codepoint, ranging from 0x0 to 0x10FFFF inclusively.
+ //! \returns the pointer to the next character after the encoded data.
+ static Ch* Encode(Ch *buffer, unsigned codepoint);
+};
+\endcode
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF8
+
+//! UTF-8 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-8
+ \tparam CharType Type for storing 8-bit UTF-8 data. Default is char.
+ \implements Encoding
+*/
+template<typename CharType = char>
+struct UTF8 {
+ typedef CharType Ch;
+
+ static Ch* Encode(Ch *buffer, unsigned codepoint) {
+ if (codepoint <= 0x7F)
+ *buffer++ = codepoint & 0xFF;
+ else if (codepoint <= 0x7FF) {
+ *buffer++ = 0xC0 | ((codepoint >> 6) & 0xFF);
+ *buffer++ = 0x80 | ((codepoint & 0x3F));
+ }
+ else if (codepoint <= 0xFFFF) {
+ *buffer++ = 0xE0 | ((codepoint >> 12) & 0xFF);
+ *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F);
+ *buffer++ = 0x80 | (codepoint & 0x3F);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ *buffer++ = 0xF0 | ((codepoint >> 18) & 0xFF);
+ *buffer++ = 0x80 | ((codepoint >> 12) & 0x3F);
+ *buffer++ = 0x80 | ((codepoint >> 6) & 0x3F);
+ *buffer++ = 0x80 | (codepoint & 0x3F);
+ }
+ return buffer;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF16
+
+//! UTF-16 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-16
+ \tparam CharType Type for storing 16-bit UTF-16 data. Default is wchar_t. C++11 may use char16_t instead.
+ \implements Encoding
+*/
+template<typename CharType = wchar_t>
+struct UTF16 {
+ typedef CharType Ch;
+
+ static Ch* Encode(Ch* buffer, unsigned codepoint) {
+ if (codepoint <= 0xFFFF) {
+ RAPIDJSON_ASSERT(codepoint < 0xD800 || codepoint > 0xDFFF); // Code point itself cannot be surrogate pair
+ *buffer++ = static_cast<Ch>(codepoint);
+ }
+ else {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ unsigned v = codepoint - 0x10000;
+ *buffer++ = static_cast<Ch>((v >> 10) + 0xD800);
+ *buffer++ = (v & 0x3FF) + 0xDC00;
+ }
+ return buffer;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// UTF32
+
+//! UTF-32 encoding.
+/*! http://en.wikipedia.org/wiki/UTF-32
+ \tparam Ch Type for storing 32-bit UTF-32 data. Default is unsigned. C++11 may use char32_t instead.
+ \implements Encoding
+*/
+template<typename CharType = unsigned>
+struct UTF32 {
+ typedef CharType Ch;
+
+ static Ch *Encode(Ch* buffer, unsigned codepoint) {
+ RAPIDJSON_ASSERT(codepoint <= 0x10FFFF);
+ *buffer++ = codepoint;
+ return buffer;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Stream
+
+/*! \class rapidjson::Stream
+ \brief Concept for reading and writing characters.
+
+ For read-only stream, no need to implement PutBegin(), Put() and PutEnd().
+
+ For write-only stream, only need to implement Put().
+
+\code
+concept Stream {
+ typename Ch; //!< Character type of the stream.
+
+ //! Read the current character from stream without moving the read cursor.
+ Ch Peek() const;
+
+ //! Read the current character from stream and moving the read cursor to next character.
+ Ch Take();
+
+ //! Get the current read cursor.
+ //! \return Number of characters read from start.
+ size_t Tell();
+
+ //! Begin writing operation at the current read pointer.
+ //! \return The begin writer pointer.
+ Ch* PutBegin();
+
+ //! Write a character.
+ void Put(Ch c);
+
+ //! End the writing operation.
+ //! \param begin The begin write pointer returned by PutBegin().
+ //! \return Number of characters written.
+ size_t PutEnd(Ch* begin);
+}
+\endcode
+*/
+
+//! Put N copies of a character to a stream.
+template<typename Stream, typename Ch>
+inline void PutN(Stream& stream, Ch c, size_t n) {
+ for (size_t i = 0; i < n; i++)
+ stream.Put(c);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// StringStream
+
+//! Read-only string stream.
+/*! \implements Stream
+*/
+template <typename Encoding>
+struct GenericStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringStream(const Ch *src) : src_(src), head_(src) {}
+
+ Ch Peek() const { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() const { return src_ - head_; }
+
+ Ch* PutBegin() { RAPIDJSON_ASSERT(false); return 0; }
+ void Put(Ch) { RAPIDJSON_ASSERT(false); }
+ size_t PutEnd(Ch*) { RAPIDJSON_ASSERT(false); return 0; }
+
+ const Ch* src_; //!< Current read position.
+ const Ch* head_; //!< Original head of the string.
+};
+
+typedef GenericStringStream<UTF8<> > StringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// InsituStringStream
+
+//! A read-write string stream.
+/*! This string stream is particularly designed for in-situ parsing.
+ \implements Stream
+*/
+template <typename Encoding>
+struct GenericInsituStringStream {
+ typedef typename Encoding::Ch Ch;
+
+ GenericInsituStringStream(Ch *src) : src_(src), dst_(0), head_(src) {}
+
+ // Read
+ Ch Peek() { return *src_; }
+ Ch Take() { return *src_++; }
+ size_t Tell() { return src_ - head_; }
+
+ // Write
+ Ch* PutBegin() { return dst_ = src_; }
+ void Put(Ch c) { RAPIDJSON_ASSERT(dst_ != 0); *dst_++ = c; }
+ size_t PutEnd(Ch* begin) { return dst_ - begin; }
+
+ Ch* src_;
+ Ch* dst_;
+ Ch* head_;
+};
+
+typedef GenericInsituStringStream<UTF8<> > InsituStringStream;
+
+///////////////////////////////////////////////////////////////////////////////
+// Type
+
+//! Type of JSON value
+enum Type {
+ kNullType = 0, //!< null
+ kFalseType = 1, //!< false
+ kTrueType = 2, //!< true
+ kObjectType = 3, //!< object
+ kArrayType = 4, //!< array
+ kStringType = 5, //!< string
+ kNumberType = 6, //!< number
+};
+
+} // namespace rapidjson
+
+#endif // RAPIDJSON_RAPIDJSON_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/reader.h
^
|
@@ -0,0 +1,683 @@
+#ifndef RAPIDJSON_READER_H_
+#define RAPIDJSON_READER_H_
+
+// Copyright (c) 2011 Milo Yip (miloyip@gmail.com)
+// Version 0.1
+
+#include "rapidjson.h"
+#include "internal/pow10.h"
+#include "internal/stack.h"
+#include <csetjmp>
+
+#ifdef RAPIDJSON_SSE42
+#include <nmmintrin.h>
+#elif defined(RAPIDJSON_SSE2)
+#include <emmintrin.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+#ifndef RAPIDJSON_PARSE_ERROR
+#define RAPIDJSON_PARSE_ERROR(msg, offset) \
+ RAPIDJSON_MULTILINEMACRO_BEGIN \
+ parseError_ = msg; \
+ errorOffset_ = offset; \
+ longjmp(jmpbuf_, 1); \
+ RAPIDJSON_MULTILINEMACRO_END
+#endif
+
+namespace rapidjson {
+
+///////////////////////////////////////////////////////////////////////////////
+// ParseFlag
+
+//! Combination of parseFlags
+enum ParseFlag {
+ kParseDefaultFlags = 0, //!< Default parse flags. Non-destructive parsing. Text strings are decoded into allocated buffer.
+ kParseInsituFlag = 1 //!< In-situ(destructive) parsing.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Handler
+
+/*! \class rapidjson::Handler
+ \brief Concept for receiving events from GenericReader upon parsing.
+\code
+concept Handler {
+ typename Ch;
+
+ void Null();
+ void Bool(bool b);
+ void Int(int i);
+ void Uint(unsigned i);
+ void Int64(int64_t i);
+ void Uint64(uint64_t i);
+ void Double(double d);
+ void String(const Ch* str, SizeType length, bool copy);
+ void StartObject();
+ void EndObject(SizeType memberCount);
+ void StartArray();
+ void EndArray(SizeType elementCount);
+};
+\endcode
+*/
+///////////////////////////////////////////////////////////////////////////////
+// BaseReaderHandler
+
+//! Default implementation of Handler.
+/*! This can be used as base class of any reader handler.
+ \implements Handler
+*/
+template<typename Encoding = UTF8<> >
+struct BaseReaderHandler {
+ typedef typename Encoding::Ch Ch;
+
+ void Default() {}
+ void Null() { Default(); }
+ void Bool(bool) { Default(); }
+ void Int(int) { Default(); }
+ void Uint(unsigned) { Default(); }
+ void Int64(int64_t) { Default(); }
+ void Uint64(uint64_t) { Default(); }
+ void Double(double) { Default(); }
+ void String(const Ch*, SizeType, bool) { Default(); }
+ void StartObject() { Default(); }
+ void EndObject(SizeType) { Default(); }
+ void StartArray() { Default(); }
+ void EndArray(SizeType) { Default(); }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// SkipWhitespace
+
+//! Skip the JSON white spaces in a stream.
+/*! \param stream A input stream for skipping white spaces.
+ \note This function has SSE2/SSE4.2 specialization.
+*/
+template<typename Stream>
+void SkipWhitespace(Stream& stream) {
+ Stream s = stream; // Use a local copy for optimization
+ while (s.Peek() == ' ' || s.Peek() == '\n' || s.Peek() == '\r' || s.Peek() == '\t')
+ s.Take();
+ stream = s;
+}
+
+#ifdef RAPIDJSON_SSE42
+//! Skip whitespace with SSE 4.2 pcmpistrm instruction, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ static const char whitespace[16] = " \n\r\t";
+ __m128i w = _mm_loadu_si128((const __m128i *)&whitespace[0]);
+
+ for (;;) {
+ __m128i s = _mm_loadu_si128((const __m128i *)p);
+ unsigned r = _mm_cvtsi128_si32(_mm_cmpistrm(w, s, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_BIT_MASK | _SIDD_NEGATIVE_POLARITY));
+ if (r == 0) // all 16 characters are whitespace
+ p += 16;
+ else { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ if (_BitScanForward(&offset, r))
+ return p + offset;
+#else
+ if (r != 0)
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+#elif defined(RAPIDJSON_SSE2)
+
+//! Skip whitespace with SSE2 instructions, testing 16 8-byte characters at once.
+inline const char *SkipWhitespace_SIMD(const char* p) {
+ static const char whitespaces[4][17] = {
+ " ",
+ "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",
+ "\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r",
+ "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
+
+ __m128i w0 = _mm_loadu_si128((const __m128i *)&whitespaces[0][0]);
+ __m128i w1 = _mm_loadu_si128((const __m128i *)&whitespaces[1][0]);
+ __m128i w2 = _mm_loadu_si128((const __m128i *)&whitespaces[2][0]);
+ __m128i w3 = _mm_loadu_si128((const __m128i *)&whitespaces[3][0]);
+
+ for (;;) {
+ __m128i s = _mm_loadu_si128((const __m128i *)p);
+ __m128i x = _mm_cmpeq_epi8(s, w0);
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w1));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w2));
+ x = _mm_or_si128(x, _mm_cmpeq_epi8(s, w3));
+ unsigned short r = ~_mm_movemask_epi8(x);
+ if (r == 0) // all 16 characters are whitespace
+ p += 16;
+ else { // some of characters may be non-whitespace
+#ifdef _MSC_VER // Find the index of first non-whitespace
+ unsigned long offset;
+ if (_BitScanForward(&offset, r))
+ return p + offset;
+#else
+ if (r != 0)
+ return p + __builtin_ffs(r) - 1;
+#endif
+ }
+ }
+}
+
+#endif // RAPIDJSON_SSE2
+
+#ifdef RAPIDJSON_SIMD
+//! Template function specialization for InsituStringStream
+template<> inline void SkipWhitespace(InsituStringStream& stream) {
+ stream.src_ = const_cast<char*>(SkipWhitespace_SIMD(stream.src_));
+}
+
+//! Template function specialization for StringStream
+template<> inline void SkipWhitespace(StringStream& stream) {
+ stream.src_ = SkipWhitespace_SIMD(stream.src_);
+}
+#endif // RAPIDJSON_SIMD
+
+///////////////////////////////////////////////////////////////////////////////
+// GenericReader
+
+//! SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
+/*! GenericReader parses JSON text from a stream, and send events synchronously to an
+ object implementing Handler concept.
+
+ It needs to allocate a stack for storing a single decoded string during
+ non-destructive parsing.
+
+ For in-situ parsing, the decoded string is directly written to the source
+ text string, no temporary buffer is required.
+
+ A GenericReader object can be reused for parsing multiple JSON text.
+
+ \tparam Encoding Encoding of both the stream and the parse output.
+ \tparam Allocator Allocator type for stack.
+*/
+template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
+class GenericReader {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ //! Constructor.
+ /*! \param allocator Optional allocator for allocating stack memory. (Only use for non-destructive parsing)
+ \param stackCapacity stack capacity in bytes for storing a single decoded string. (Only use for non-destructive parsing)
+ */
+ GenericReader(Allocator* allocator = 0, size_t stackCapacity = kDefaultStackCapacity) : stack_(allocator, stackCapacity), parseError_(0), errorOffset_(0) {}
+
+ //! Parse JSON text.
+ /*! \tparam parseFlags Combination of ParseFlag.
+ \tparam Stream Type of input stream.
+ \tparam Handler Type of handler which must implement Handler concept.
+ \param stream Input stream to be parsed.
+ \param handler The handler to receive events.
+ \return Whether the parsing is successful.
+ */
+ template <unsigned parseFlags, typename Stream, typename Handler>
+ bool Parse(Stream& stream, Handler& handler) {
+ parseError_ = 0;
+ errorOffset_ = 0;
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4611) // interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+ if (setjmp(jmpbuf_)) {
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+ stack_.Clear();
+ return false;
+ }
+
+ SkipWhitespace(stream);
+
+ if (stream.Peek() == '\0')
+ RAPIDJSON_PARSE_ERROR("Text only contains white space(s)", stream.Tell());
+ else {
+ switch (stream.Peek()) {
+ case '{': ParseObject<parseFlags>(stream, handler); break;
+ case '[': ParseArray<parseFlags>(stream, handler); break;
+ default: RAPIDJSON_PARSE_ERROR("Expect either an object or array at root", stream.Tell());
+ }
+ SkipWhitespace(stream);
+
+ if (stream.Peek() != '\0')
+ RAPIDJSON_PARSE_ERROR("Nothing should follow the root object or array.", stream.Tell());
+ }
+
+ return true;
+ }
+
+ bool HasParseError() const { return parseError_ != 0; }
+ const char* GetParseError() const { return parseError_; }
+ size_t GetErrorOffset() const { return errorOffset_; }
+
+private:
+ // Parse object: { string : value, ... }
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseObject(Stream& stream, Handler& handler) {
+ RAPIDJSON_ASSERT(stream.Peek() == '{');
+ stream.Take(); // Skip '{'
+ handler.StartObject();
+ SkipWhitespace(stream);
+
+ if (stream.Peek() == '}') {
+ stream.Take();
+ handler.EndObject(0); // empty object
+ return;
+ }
+
+ for (SizeType memberCount = 0;;) {
+ if (stream.Peek() != '"') {
+ RAPIDJSON_PARSE_ERROR("Name of an object member must be a string", stream.Tell());
+ break;
+ }
+
+ ParseString<parseFlags>(stream, handler);
+ SkipWhitespace(stream);
+
+ if (stream.Take() != ':') {
+ RAPIDJSON_PARSE_ERROR("There must be a colon after the name of object member", stream.Tell());
+ break;
+ }
+ SkipWhitespace(stream);
+
+ ParseValue<parseFlags>(stream, handler);
+ SkipWhitespace(stream);
+
+ ++memberCount;
+
+ switch(stream.Take()) {
+ case ',': SkipWhitespace(stream); break;
+ case '}': handler.EndObject(memberCount); return;
+ default: RAPIDJSON_PARSE_ERROR("Must be a comma or '}' after an object member", stream.Tell());
+ }
+ }
+ }
+
+ // Parse array: [ value, ... ]
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseArray(Stream& stream, Handler& handler) {
+ RAPIDJSON_ASSERT(stream.Peek() == '[');
+ stream.Take(); // Skip '['
+ handler.StartArray();
+ SkipWhitespace(stream);
+
+ if (stream.Peek() == ']') {
+ stream.Take();
+ handler.EndArray(0); // empty array
+ return;
+ }
+
+ for (SizeType elementCount = 0;;) {
+ ParseValue<parseFlags>(stream, handler);
+ ++elementCount;
+ SkipWhitespace(stream);
+
+ switch (stream.Take()) {
+ case ',': SkipWhitespace(stream); break;
+ case ']': handler.EndArray(elementCount); return;
+ default: RAPIDJSON_PARSE_ERROR("Must be a comma or ']' after an array element.", stream.Tell());
+ }
+ }
+ }
+
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseNull(Stream& stream, Handler& handler) {
+ RAPIDJSON_ASSERT(stream.Peek() == 'n');
+ stream.Take();
+
+ if (stream.Take() == 'u' && stream.Take() == 'l' && stream.Take() == 'l')
+ handler.Null();
+ else
+ RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
+ }
+
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseTrue(Stream& stream, Handler& handler) {
+ RAPIDJSON_ASSERT(stream.Peek() == 't');
+ stream.Take();
+
+ if (stream.Take() == 'r' && stream.Take() == 'u' && stream.Take() == 'e')
+ handler.Bool(true);
+ else
+ RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell());
+ }
+
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseFalse(Stream& stream, Handler& handler) {
+ RAPIDJSON_ASSERT(stream.Peek() == 'f');
+ stream.Take();
+
+ if (stream.Take() == 'a' && stream.Take() == 'l' && stream.Take() == 's' && stream.Take() == 'e')
+ handler.Bool(false);
+ else
+ RAPIDJSON_PARSE_ERROR("Invalid value", stream.Tell() - 1);
+ }
+
+ // Helper function to parse four hexidecimal digits in \uXXXX in ParseString().
+ template<typename Stream>
+ unsigned ParseHex4(Stream& stream) {
+ Stream s = stream; // Use a local copy for optimization
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; i++) {
+ Ch c = s.Take();
+ codepoint <<= 4;
+ codepoint += c;
+ if (c >= '0' && c <= '9')
+ codepoint -= '0';
+ else if (c >= 'A' && c <= 'F')
+ codepoint -= 'A' - 10;
+ else if (c >= 'a' && c <= 'f')
+ codepoint -= 'a' - 10;
+ else
+ RAPIDJSON_PARSE_ERROR("Incorrect hex digit after \\u escape", s.Tell() - 1);
+ }
+ stream = s; // Restore stream
+ return codepoint;
+ }
+
+ // Parse string, handling the prefix and suffix double quotes and escaping.
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseString(Stream& stream, Handler& handler) {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ static const Ch escape[256] = {
+ Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
+ Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
+ 0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
+ 0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
+ };
+#undef Z16
+
+ Stream s = stream; // Use a local copy for optimization
+ RAPIDJSON_ASSERT(s.Peek() == '\"');
+ s.Take(); // Skip '\"'
+ Ch *head;
+ SizeType len;
+ if (parseFlags & kParseInsituFlag)
+ head = s.PutBegin();
+ else
+ len = 0;
+
+#define RAPIDJSON_PUT(x) \
+ do { \
+ if (parseFlags & kParseInsituFlag) \
+ s.Put(x); \
+ else { \
+ *stack_.template Push<Ch>() = x; \
+ ++len; \
+ } \
+ } while(false)
+
+ for (;;) {
+ Ch c = s.Take();
+ if (c == '\\') { // Escape
+ Ch e = s.Take();
+ if ((sizeof(Ch) == 1 || e < 256) && escape[(unsigned char)e])
+ RAPIDJSON_PUT(escape[(unsigned char)e]);
+ else if (e == 'u') { // Unicode
+ unsigned codepoint = ParseHex4(s);
+ if (codepoint >= 0xD800 && codepoint <= 0xDBFF) { // Handle UTF-16 surrogate pair
+ if (s.Take() != '\\' || s.Take() != 'u') {
+ RAPIDJSON_PARSE_ERROR("Missing the second \\u in surrogate pair", s.Tell() - 2);
+ return;
+ }
+ unsigned codepoint2 = ParseHex4(s);
+ if (codepoint2 < 0xDC00 || codepoint2 > 0xDFFF) {
+ RAPIDJSON_PARSE_ERROR("The second \\u in surrogate pair is invalid", s.Tell() - 2);
+ return;
+ }
+ codepoint = (((codepoint - 0xD800) << 10) | (codepoint2 - 0xDC00)) + 0x10000;
+ }
+
+ Ch buffer[4];
+ SizeType count = SizeType(Encoding::Encode(buffer, codepoint) - &buffer[0]);
+
+ if (parseFlags & kParseInsituFlag)
+ for (SizeType i = 0; i < count; i++)
+ s.Put(buffer[i]);
+ else {
+ memcpy(stack_.template Push<Ch>(count), buffer, count * sizeof(Ch));
+ len += count;
+ }
+ }
+ else {
+ RAPIDJSON_PARSE_ERROR("Unknown escape character", stream.Tell() - 1);
+ return;
+ }
+ }
+ else if (c == '"') { // Closing double quote
+ if (parseFlags & kParseInsituFlag) {
+ size_t length = s.PutEnd(head);
+ RAPIDJSON_ASSERT(length <= 0xFFFFFFFF);
+ RAPIDJSON_PUT('\0'); // null-terminate the string
+ handler.String(head, SizeType(length), false);
+ }
+ else {
+ RAPIDJSON_PUT('\0');
+ handler.String(stack_.template Pop<Ch>(len), len - 1, true);
+ }
+ stream = s; // restore stream
+ return;
+ }
+ else if (c == '\0') {
+ RAPIDJSON_PARSE_ERROR("lacks ending quotation before the end of string", stream.Tell() - 1);
+ return;
+ }
+ else if ((unsigned)c < 0x20) { // RFC 4627: unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
+ RAPIDJSON_PARSE_ERROR("Incorrect unescaped character in string", stream.Tell() - 1);
+ return;
+ }
+ else
+ RAPIDJSON_PUT(c); // Normal character, just copy
+ }
+#undef RAPIDJSON_PUT
+ }
+
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseNumber(Stream& stream, Handler& handler) {
+ Stream s = stream; // Local copy for optimization
+ // Parse minus
+ bool minus = false;
+ if (s.Peek() == '-') {
+ minus = true;
+ s.Take();
+ }
+
+ // Parse int: zero / ( digit1-9 *DIGIT )
+ unsigned i;
+ bool try64bit = false;
+ if (s.Peek() == '0') {
+ i = 0;
+ s.Take();
+ }
+ else if (s.Peek() >= '1' && s.Peek() <= '9') {
+ i = s.Take() - '0';
+
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 214748364) { // 2^31 = 2147483648
+ if (i != 214748364 || s.Peek() > '8') {
+ try64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + (s.Take() - '0');
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i >= 429496729) { // 2^32 - 1 = 4294967295
+ if (i != 429496729 || s.Peek() > '5') {
+ try64bit = true;
+ break;
+ }
+ }
+ i = i * 10 + (s.Take() - '0');
+ }
+ }
+ else {
+ RAPIDJSON_PARSE_ERROR("Expect a value here.", stream.Tell());
+ return;
+ }
+
+ // Parse 64bit int
+ uint64_t i64 = 0;
+ bool useDouble = false;
+ if (try64bit) {
+ i64 = i;
+ if (minus)
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= 922337203685477580uLL) // 2^63 = 9223372036854775808
+ if (i64 != 922337203685477580uLL || s.Peek() > '8') {
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + (s.Take() - '0');
+ }
+ else
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (i64 >= 1844674407370955161uLL) // 2^64 - 1 = 18446744073709551615
+ if (i64 != 1844674407370955161uLL || s.Peek() > '5') {
+ useDouble = true;
+ break;
+ }
+ i64 = i64 * 10 + (s.Take() - '0');
+ }
+ }
+
+ // Force double for big integer
+ double d = 0.0;
+ if (useDouble) {
+ d = (double)i64;
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (d >= 1E307) {
+ RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
+ return;
+ }
+ d = d * 10 + (s.Take() - '0');
+ }
+ }
+
+ // Parse frac = decimal-point 1*DIGIT
+ int expFrac = 0;
+ if (s.Peek() == '.') {
+ if (!useDouble) {
+ d = try64bit ? (double)i64 : (double)i;
+ useDouble = true;
+ }
+ s.Take();
+
+ if (s.Peek() >= '0' && s.Peek() <= '9') {
+ d = d * 10 + (s.Take() - '0');
+ --expFrac;
+ }
+ else {
+ RAPIDJSON_PARSE_ERROR("At least one digit in fraction part", stream.Tell());
+ return;
+ }
+
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ if (expFrac > -16) {
+ d = d * 10 + (s.Peek() - '0');
+ --expFrac;
+ }
+ s.Take();
+ }
+ }
+
+ // Parse exp = e [ minus / plus ] 1*DIGIT
+ int exp = 0;
+ if (s.Peek() == 'e' || s.Peek() == 'E') {
+ if (!useDouble) {
+ d = try64bit ? (double)i64 : (double)i;
+ useDouble = true;
+ }
+ s.Take();
+
+ bool expMinus = false;
+ if (s.Peek() == '+')
+ s.Take();
+ else if (s.Peek() == '-') {
+ s.Take();
+ expMinus = true;
+ }
+
+ if (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = s.Take() - '0';
+ while (s.Peek() >= '0' && s.Peek() <= '9') {
+ exp = exp * 10 + (s.Take() - '0');
+ if (exp > 308) {
+ RAPIDJSON_PARSE_ERROR("Number too big to store in double", stream.Tell());
+ return;
+ }
+ }
+ }
+ else {
+ RAPIDJSON_PARSE_ERROR("At least one digit in exponent", s.Tell());
+ return;
+ }
+
+ if (expMinus)
+ exp = -exp;
+ }
+
+ // Finish parsing, call event according to the type of number.
+ if (useDouble) {
+ d *= internal::Pow10(exp + expFrac);
+ handler.Double(minus ? -d : d);
+ }
+ else {
+ if (try64bit) {
+ if (minus)
+ handler.Int64(-(int64_t)i64);
+ else
+ handler.Uint64(i64);
+ }
+ else {
+ if (minus)
+ handler.Int(-(int)i);
+ else
+ handler.Uint(i);
+ }
+ }
+
+ stream = s; // restore stream
+ }
+
+ // Parse any JSON value
+ template<unsigned parseFlags, typename Stream, typename Handler>
+ void ParseValue(Stream& stream, Handler& handler) {
+ switch (stream.Peek()) {
+ case 'n': ParseNull <parseFlags>(stream, handler); break;
+ case 't': ParseTrue <parseFlags>(stream, handler); break;
+ case 'f': ParseFalse <parseFlags>(stream, handler); break;
+ case '"': ParseString<parseFlags>(stream, handler); break;
+ case '{': ParseObject<parseFlags>(stream, handler); break;
+ case '[': ParseArray <parseFlags>(stream, handler); break;
+ default : ParseNumber<parseFlags>(stream, handler);
+ }
+ }
+
+ static const size_t kDefaultStackCapacity = 256; //!< Default stack capacity in bytes for storing a single decoded string.
+ internal::Stack<Allocator> stack_; //!< A stack for storing decoded string temporarily during non-destructive parsing.
+ jmp_buf jmpbuf_; //!< setjmp buffer for fast exit from nested parsing function calls.
+ const char* parseError_;
+ size_t errorOffset_;
+}; // class GenericReader
+
+//! Reader with UTF8 encoding and default allocator.
+typedef GenericReader<UTF8<> > Reader;
+
+} // namespace rapidjson
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // RAPIDJSON_READER_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/stringbuffer.h
^
|
@@ -0,0 +1,49 @@
+#ifndef RAPIDJSON_STRINGBUFFER_H_
+#define RAPIDJSON_STRINGBUFFER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+
+namespace rapidjson {
+
+//! Represents an in-memory output stream.
+/*!
+ \tparam Encoding Encoding of the stream.
+ \tparam Allocator type for allocating memory buffer.
+ \implements Stream
+*/
+template <typename Encoding, typename Allocator = CrtAllocator>
+struct GenericStringBuffer {
+ typedef typename Encoding::Ch Ch;
+
+ GenericStringBuffer(Allocator* allocator = 0, size_t capacity = kDefaultCapacity) : stack_(allocator, capacity) {}
+
+ void Put(Ch c) { *stack_.template Push<Ch>() = c; }
+
+ void Clear() { stack_.Clear(); }
+
+ const char* GetString() const {
+ // Push and pop a null terminator. This is safe.
+ *stack_.template Push<Ch>() = '\0';
+ stack_.template Pop<Ch>(1);
+
+ return stack_.template Bottom<Ch>();
+ }
+
+ size_t Size() const { return stack_.GetSize(); }
+
+ static const size_t kDefaultCapacity = 256;
+ mutable internal::Stack<Allocator> stack_;
+};
+
+typedef GenericStringBuffer<UTF8<> > StringBuffer;
+
+//! Implement specialized version of PutN() with memset() for better performance.
+template<>
+inline void PutN(GenericStringBuffer<UTF8<> >& stream, char c, size_t n) {
+ memset(stream.stack_.Push<char>(n), c, n * sizeof(c));
+}
+
+} // namespace rapidjson
+
+#endif // RAPIDJSON_STRINGBUFFER_H_
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/ext/rapidjson/include/rapidjson/writer.h
^
|
@@ -0,0 +1,241 @@
+#ifndef RAPIDJSON_WRITER_H_
+#define RAPIDJSON_WRITER_H_
+
+#include "rapidjson.h"
+#include "internal/stack.h"
+#include "internal/strfunc.h"
+#include <cstdio> // snprintf() or _sprintf_s()
+#include <new> // placement new
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4127) // conditional expression is constant
+#endif
+
+namespace rapidjson {
+
+//! JSON writer
+/*! Writer implements the concept Handler.
+ It generates JSON text by events to an output stream.
+
+ User may programmatically calls the functions of a writer to generate JSON text.
+
+ On the other side, a writer can also be passed to objects that generates events,
+
+ for example Reader::Parse() and Document::Accept().
+
+ \tparam Stream Type of ouptut stream.
+ \tparam Encoding Encoding of both source strings and output.
+ \implements Handler
+*/
+template<typename Stream, typename Encoding = UTF8<>, typename Allocator = MemoryPoolAllocator<> >
+class Writer {
+public:
+ typedef typename Encoding::Ch Ch;
+
+ Writer(Stream& stream, Allocator* allocator = 0, size_t levelDepth = kDefaultLevelDepth) :
+ stream_(stream), level_stack_(allocator, levelDepth * sizeof(Level)) {}
+
+ //@name Implementation of Handler
+ //@{
+ Writer& Null() { Prefix(kNullType); WriteNull(); return *this; }
+ Writer& Bool(bool b) { Prefix(b ? kTrueType : kFalseType); WriteBool(b); return *this; }
+ Writer& Int(int i) { Prefix(kNumberType); WriteInt(i); return *this; }
+ Writer& Uint(unsigned u) { Prefix(kNumberType); WriteUint(u); return *this; }
+ Writer& Int64(int64_t i64) { Prefix(kNumberType); WriteInt64(i64); return *this; }
+ Writer& Uint64(uint64_t u64) { Prefix(kNumberType); WriteUint64(u64); return *this; }
+ Writer& Double(double d) { Prefix(kNumberType); WriteDouble(d); return *this; }
+
+ Writer& String(const Ch* str, SizeType length, bool copy = false) {
+ (void)copy;
+ Prefix(kStringType);
+ WriteString(str, length);
+ return *this;
+ }
+
+ Writer& StartObject() {
+ Prefix(kObjectType);
+ new (level_stack_.template Push<Level>()) Level(false);
+ WriteStartObject();
+ return *this;
+ }
+
+ Writer& EndObject(SizeType memberCount = 0) {
+ (void)memberCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(!level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ WriteEndObject();
+ return *this;
+ }
+
+ Writer& StartArray() {
+ Prefix(kArrayType);
+ new (level_stack_.template Push<Level>()) Level(true);
+ WriteStartArray();
+ return *this;
+ }
+
+ Writer& EndArray(SizeType elementCount = 0) {
+ (void)elementCount;
+ RAPIDJSON_ASSERT(level_stack_.GetSize() >= sizeof(Level));
+ RAPIDJSON_ASSERT(level_stack_.template Top<Level>()->inArray);
+ level_stack_.template Pop<Level>(1);
+ WriteEndArray();
+ return *this;
+ }
+ //@}
+
+ //! Simpler but slower overload.
+ Writer& String(const Ch* str) { return String(str, internal::StrLen(str)); }
+
+protected:
+ //! Information for each nested level
+ struct Level {
+ Level(bool inArray_) : inArray(inArray_), valueCount(0) {}
+ bool inArray; //!< true if in array, otherwise in object
+ size_t valueCount; //!< number of values in this level
+ };
+
+ static const size_t kDefaultLevelDepth = 32;
+
+ void WriteNull() {
+ stream_.Put('n'); stream_.Put('u'); stream_.Put('l'); stream_.Put('l');
+ }
+
+ void WriteBool(bool b) {
+ if (b) {
+ stream_.Put('t'); stream_.Put('r'); stream_.Put('u'); stream_.Put('e');
+ }
+ else {
+ stream_.Put('f'); stream_.Put('a'); stream_.Put('l'); stream_.Put('s'); stream_.Put('e');
+ }
+ }
+
+ void WriteInt(int i) {
+ if (i < 0) {
+ stream_.Put('-');
+ i = -i;
+ }
+ WriteUint((unsigned)i);
+ }
+
+ void WriteUint(unsigned u) {
+ char buffer[10];
+ char *p = buffer;
+ do {
+ *p++ = (u % 10) + '0';
+ u /= 10;
+ } while (u > 0);
+
+ do {
+ --p;
+ stream_.Put(*p);
+ } while (p != buffer);
+ }
+
+ void WriteInt64(int64_t i64) {
+ if (i64 < 0) {
+ stream_.Put('-');
+ i64 = -i64;
+ }
+ WriteUint64((uint64_t)i64);
+ }
+
+ void WriteUint64(uint64_t u64) {
+ char buffer[20];
+ char *p = buffer;
+ do {
+ *p++ = char(u64 % 10) + '0';
+ u64 /= 10;
+ } while (u64 > 0);
+
+ do {
+ --p;
+ stream_.Put(*p);
+ } while (p != buffer);
+ }
+
+ //! \todo Optimization with custom double-to-string converter.
+ void WriteDouble(double d) {
+ char buffer[100];
+#if _MSC_VER
+ int ret = sprintf_s(buffer, sizeof(buffer), "%g", d);
+#else
+ int ret = snprintf(buffer, sizeof(buffer), "%g", d);
+#endif
+ RAPIDJSON_ASSERT(ret >= 1);
+ for (int i = 0; i < ret; i++)
+ stream_.Put(buffer[i]);
+ }
+
+ void WriteString(const Ch* str, SizeType length) {
+ static const char hexDigits[] = "0123456789ABCDEF";
+ static const char escape[256] = {
+#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ //0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00
+ 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10
+ 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20
+ Z16, Z16, // 30~4F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50
+ Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF
+#undef Z16
+ };
+
+ stream_.Put('\"');
+ for (const Ch* p = str; p != str + length; ++p) {
+ if ((sizeof(Ch) == 1 || *p < 256) && escape[(unsigned char)*p]) {
+ stream_.Put('\\');
+ stream_.Put(escape[(unsigned char)*p]);
+ if (escape[(unsigned char)*p] == 'u') {
+ stream_.Put('0');
+ stream_.Put('0');
+ stream_.Put(hexDigits[(*p) >> 4]);
+ stream_.Put(hexDigits[(*p) & 0xF]);
+ }
+ }
+ else
+ stream_.Put(*p);
+ }
+ stream_.Put('\"');
+ }
+
+ void WriteStartObject() { stream_.Put('{'); }
+ void WriteEndObject() { stream_.Put('}'); }
+ void WriteStartArray() { stream_.Put('['); }
+ void WriteEndArray() { stream_.Put(']'); }
+
+ void Prefix(Type type) {
+ (void)type;
+ if (level_stack_.GetSize() != 0) { // this value is not at root
+ Level* level = level_stack_.template Top<Level>();
+ if (level->valueCount > 0) {
+ if (level->inArray)
+ stream_.Put(','); // add comma if it is not the first element in array
+ else // in object
+ stream_.Put((level->valueCount % 2 == 0) ? ',' : ':');
+ }
+ if (!level->inArray && level->valueCount % 2 == 0)
+ RAPIDJSON_ASSERT(type == kStringType); // if it's in object, then even number should be a name
+ level->valueCount++;
+ }
+ else
+ RAPIDJSON_ASSERT(type == kObjectType || type == kArrayType);
+ }
+
+ Stream& stream_;
+ internal::Stack<Allocator> level_stack_;
+
+private:
+ // Prohibit assignment for VC C4512 warning
+ Writer& operator=(const Writer& w);
+};
+
+} // namespace rapidjson
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif // RAPIDJSON_RAPIDJSON_H_
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/iputils.hh
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 - 2008 PowerDNS.COM BV
+ Copyright (C) 2002 - 2011 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 version 2
@@ -32,11 +32,14 @@
#include <functional>
#include "ahuexception.hh"
#include "misc.hh"
+#include <sys/socket.h>
+#include <netdb.h>
+
#include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/lexical_cast.hpp>
-using namespace std;
+#include "namespaces.hh"
union ComboAddress {
struct sockaddr_in sin4;
@@ -78,7 +81,7 @@
return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, 16) > 0;
}
- struct addressOnlyLessThan: public binary_function<string, string, bool>
+ struct addressOnlyLessThan: public std::binary_function<string, string, bool>
{
bool operator()(const ComboAddress& a, const ComboAddress& b) const
{
@@ -108,16 +111,20 @@
sin4.sin_port=0;
}
+ // 'port' sets a default value in case 'str' does not set a port
explicit ComboAddress(const string& str, uint16_t port=0)
{
memset(&sin6, 0, sizeof(sin6));
sin4.sin_family = AF_INET;
- sin4.sin_port=htons(port);
- if(!IpToU32(str, (uint32_t*)&sin4.sin_addr.s_addr)) {
+ sin4.sin_port = 0;
+ if(makeIPv4sockaddr(str, &sin4)) {
sin6.sin6_family = AF_INET6;
- if(Utility::inet_pton(AF_INET6, str.c_str(), &sin6.sin6_addr) <= 0)
+ if(makeIPv6sockaddr(str, &sin6) < 0)
throw AhuException("Unable to convert presentation address '"+ str +"'");
+
}
+ if(!sin4.sin_port) // 'str' overrides port!
+ sin4.sin_port=htons(port);
}
bool isMappedIPv4() const
@@ -154,14 +161,10 @@
string toString() const
{
- char tmp[128];
- if(sin4.sin_family==AF_INET && !Utility::inet_ntop(AF_INET, ( const char * ) &sin4.sin_addr, tmp, sizeof(tmp)))
- return tmp;
-
- if(sin4.sin_family==AF_INET6 && !Utility::inet_ntop(AF_INET6, ( const char * ) &sin6.sin6_addr, tmp, sizeof(tmp)))
- return tmp;
+ char host[1024];
+ getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST);
- return tmp;
+ return host;
}
string toStringWithPort() const
@@ -186,7 +189,7 @@
address.sin4.sin_family=AF_INET;
if(Utility::inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
address.sin4.sin_family=AF_INET6;
- if(Utility::inet_pton(AF_INET6, str.c_str(), &address.sin6.sin6_addr) <= 0)
+ if(makeIPv6sockaddr(str, &address.sin6) < 0)
throw NetmaskException("Unable to convert '"+str+"' to a netmask");
}
return address;
@@ -197,6 +200,25 @@
class Netmask
{
public:
+ Netmask()
+ {
+ d_network.sin4.sin_family=0; // disable this doing anything useful
+ }
+
+ Netmask(const ComboAddress& network, uint8_t bits=0xff)
+ {
+ d_network = network;
+
+ if(bits == 0xff)
+ bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
+
+ d_bits = bits;
+ if(d_bits<32)
+ d_mask=~(0xFFFFFFFF>>d_bits);
+ else
+ d_mask=0xFFFFFFFF; // not actually used for IPv6
+ }
+
//! Constructor supplies the mask, which cannot be changed
Netmask(const string &mask)
{
@@ -204,7 +226,7 @@
d_network=makeComboAddress(split.first);
if(!split.second.empty()) {
- d_bits = (uint8_t) atoi(split.second.c_str());
+ d_bits = lexical_cast<unsigned int>(split.second);
if(d_bits<32)
d_mask=~(0xFFFFFFFF>>d_bits);
else
@@ -268,9 +290,21 @@
string toString() const
{
- return d_network.toString()+"/"+boost::lexical_cast<string>(d_bits);
+ return d_network.toString()+"/"+boost::lexical_cast<string>((unsigned int)d_bits);
}
+ string toStringNoMask() const
+ {
+ return d_network.toString();
+ }
+ const ComboAddress& getNetwork() const
+ {
+ return d_network;
+ }
+ int getBits() const
+ {
+ return d_bits;
+ }
private:
ComboAddress d_network;
uint32_t d_mask;
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/json.cc
^
|
@@ -0,0 +1,119 @@
+#include "json.hh"
+#include "namespaces.hh"
+#include <stdio.h>
+#include <boost/circular_buffer.hpp>
+#include <boost/tokenizer.hpp>
+#include "namespaces.hh"
+#include "misc.hh"
+#include <boost/foreach.hpp>
+#include "rapidjson/document.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+#include "config.h"
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#ifndef HAVE_STRCASESTR
+
+/*
+ * strcasestr() locates the first occurrence in the string s1 of the
+ * sequence of characters (excluding the terminating null character)
+ * in the string s2, ignoring case. strcasestr() returns a pointer
+ * to the located string, or a null pointer if the string is not found.
+ * If s2 is empty, the function returns s1.
+ */
+
+static char *
+strcasestr(const char *s1, const char *s2)
+{
+ int *cm = __trans_lower;
+ const uchar_t *us1 = (const uchar_t *)s1;
+ const uchar_t *us2 = (const uchar_t *)s2;
+ const uchar_t *tptr;
+ int c;
+
+ if (us2 == NULL || *us2 == '\0')
+ return ((char *)us1);
+
+ c = cm[*us2];
+ while (*us1 != '\0') {
+ if (c == cm[*us1++]) {
+ tptr = us1;
+ while (cm[c = *++us2] == cm[*us1++] && c != '\0')
+ continue;
+ if (c == '\0')
+ return ((char *)tptr - 1);
+ us1 = tptr;
+ us2 = (const uchar_t *)s2;
+ c = cm[*us2];
+ }
+ }
+
+ return (NULL);
+}
+
+#endif // HAVE_STRCASESTR
+
+using namespace rapidjson;
+
+string makeStringFromDocument(const Document& doc)
+{
+ StringBuffer output;
+ Writer<StringBuffer> w(output);
+ doc.Accept(w);
+ return string(output.GetString(), output.Size());
+}
+
+string returnJSONObject(const map<string, string>& items)
+{
+ Document doc;
+ doc.SetObject();
+ typedef map<string, string> items_t;
+ BOOST_FOREACH(const items_t::value_type& val, items) {
+ doc.AddMember(val.first.c_str(), val.second.c_str(), doc.GetAllocator());
+ }
+ return makeStringFromDocument(doc);
+}
+
+string makeLogGrepJSON(map<string, string>& varmap, const string& fname, const string& prefix)
+{
+ FILE* ptr = fopen(fname.c_str(), "r");
+ if(!ptr) {
+ return "[]";
+ }
+ boost::shared_ptr<FILE> fp(ptr, fclose);
+
+ string line;
+ string needle=varmap["needle"];
+ trim_right(needle);
+
+ boost::replace_all(needle, "%20", " ");
+ boost::replace_all(needle, "%22", "\"");
+
+ boost::tokenizer<boost::escaped_list_separator<char> > t(needle, boost::escaped_list_separator<char>("\\", " ", "\""));
+ vector<string> matches(t.begin(), t.end());
+ matches.push_back(prefix);
+
+ boost::circular_buffer<string> lines(200);
+ while(stringfgets(fp.get(), line)) {
+ vector<string>::const_iterator iter;
+ for(iter = matches.begin(); iter != matches.end(); ++iter) {
+ if(!strcasestr(line.c_str(), iter->c_str()))
+ break;
+ }
+ if(iter == matches.end()) {
+ trim_right(line);
+ lines.push_front(line);
+ }
+ }
+
+ Document doc;
+ doc.SetArray();
+ if(!lines.empty()) {
+ BOOST_FOREACH(const string& line, lines) {
+ doc.PushBack(line.c_str(), doc.GetAllocator());
+ }
+ }
+ return makeStringFromDocument(doc);
+}
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/json.hh
^
|
@@ -0,0 +1,26 @@
+/*
+ PowerDNS Versatile Database Driven Nameserver
+ Copyright (C) 2002-2012 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 version 2
+ as published by the Free Software Foundation
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#pragma once // it is 2012, deal with it
+
+#include <string>
+#include <map>
+#include "rapidjson/document.h"
+
+std::string returnJSONObject(const std::map<std::string, std::string>& items);
+std::string makeLogGrepJSON(std::map<std::string, std::string>& varmap, const std::string& fname, const std::string& prefix="");
+std::string makeStringFromDocument(const rapidjson::Document& doc);
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/json_ws.cc
^
|
@@ -0,0 +1,163 @@
+/*
+ PowerDNS Versatile Database Driven Nameserver
+ Copyright (C) 2003 - 2012 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 version 2
+ as published by the Free Software Foundation
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include "json_ws.hh"
+#include "json.hh"
+#include <boost/foreach.hpp>
+#include <string>
+#include "namespaces.hh"
+#include <iostream>
+#include "iputils.hh"
+#include "rec_channel.hh"
+#include "arguments.hh"
+#include "misc.hh"
+#include "syncres.hh"
+#include "config.h"
+
+JWebserver::JWebserver(FDMultiplexer* fdm) : d_fdm(fdm)
+{
+ RecursorControlParser rcp; // inits
+ d_socket = socket(AF_INET6, SOCK_STREAM, 0);
+ setSocketReusable(d_socket);
+ ComboAddress local("::", 8082);
+ bind(d_socket, (struct sockaddr*)&local, local.getSocklen());
+ listen(d_socket, 5);
+
+ d_fdm->addReadFD(d_socket, boost::bind(&JWebserver::newConnection, this));
+}
+
+void JWebserver::readRequest(int fd)
+{
+ char buffer[16384];
+ int res = read(fd, buffer, sizeof(buffer));
+ if(res <= 0) {
+ d_fdm->removeReadFD(fd);
+ close(fd);
+ cerr<<"Lost connection"<<endl;
+ return;
+ }
+ buffer[res]=0;
+ cerr<< buffer << endl;
+
+ char * p = strchr(buffer, '\r');
+ if(p) *p = 0;
+ if(strstr(buffer, "GET ") != buffer) {
+ d_fdm->removeReadFD(fd);
+ close(fd);
+ cerr<<"Invalid request"<<endl;
+ return;
+ }
+
+
+ map<string, string> varmap;
+ if((p = strchr(buffer, '?'))) {
+ vector<string> variables;
+ string line(p+1);
+ line.resize(line.length() - strlen(" HTTP/1.0"));
+
+ stringtok(variables, line, "&");
+ BOOST_FOREACH(const string& var, variables) {
+ varmap.insert(splitField(var, '='));
+ cout<<"Variable: '"<<var<<"'"<<endl;
+ }
+ }
+
+ string callback=varmap["callback"];
+ cout <<"Callback: '"<<callback<<"'\n";
+
+ char response[]="HTTP/1.1 200 OK\r\n"
+ "Date: Wed, 30 Nov 2011 22:01:15 GMT\r\n"
+ "Server: PowerDNS Recursor "VERSION"\r\n"
+ "Connection: keep-alive\r\n"
+ "Content-Length: %d\r\n"
+ "Access-Control-Allow-Origin: *\r\n"
+ "Content-Type: application/json\r\n"
+ "\r\n" ;
+
+
+ string content;
+ if(!callback.empty())
+ content=callback+"(";
+
+ map<string, string> stats;
+ if(varmap["command"] =="domains") {
+ content += "[";
+ bool first=1;
+ BOOST_FOREACH(const SyncRes::domainmap_t::value_type& val, *t_sstorage->domainmap) {
+ if(!first) content+= ", ";
+ first=false;
+ stats.clear();
+ stats["name"] = val.first;
+ stats["type"] = val.second.d_servers.empty() ? "Native" : "Forwarded";
+ stats["servers"];
+ BOOST_FOREACH(const ComboAddress& server, val.second.d_servers) {
+ stats["servers"]+= server.toStringWithPort() + " ";
+ }
+ stats["rdbit"] = lexical_cast<string>(val.second.d_servers.empty() ? 0 : val.second.d_rdForward);
+ // fill out forwarders too one day, and rdrequired
+ content += returnJSONObject(stats);
+ }
+ content += "]";
+ }
+ else if(varmap["command"]=="flush-cache") {
+ string canon=toCanonic("", varmap["domain"]);
+ cerr<<"Canon: '"<<canon<<"'\n";
+ int count = broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, canon));
+ count+=broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeAndCountNegCache, canon));
+ stats["number"]=lexical_cast<string>(count);
+ content += returnJSONObject(stats);
+ }
+ else if(varmap["command"] == "config") {
+ vector<string> items = ::arg().list();
+ BOOST_FOREACH(const string& var, items) {
+ stats[var] = ::arg()[var];
+ }
+ content += returnJSONObject(stats);
+ }
+ else if(varmap["command"]=="log-grep") {
+ content += makeLogGrepJSON(varmap, ::arg()["experimental-logfile"], " pdns_recursor[");
+ }
+ else { // if(varmap["command"] == "stats") {
+ stats = getAllStatsMap();
+ content += returnJSONObject(stats);
+ }
+
+ if(!callback.empty())
+ content += ");";
+
+ string tot = (boost::format(response) % content.length()).str();
+ tot += content;
+ cout << "Starting write"<<endl;
+ Utility::setBlocking(fd);
+ writen2(fd, tot.c_str(), tot.length());
+ Utility::setNonBlocking(fd);
+ cout <<"And done"<<endl;
+}
+
+void JWebserver::newConnection()
+{
+ ComboAddress remote;
+ remote.sin4.sin_family=AF_INET6;
+ socklen_t remlen = remote.getSocklen();
+ int sock = accept(d_socket, (struct sockaddr*) &remote, &remlen);
+ if(sock < 0)
+ return;
+
+ cerr<<"Connection from "<< remote.toStringWithPort() <<endl;
+ Utility::setNonBlocking(sock);
+ d_fdm->addReadFD(sock, boost::bind(&JWebserver::readRequest, this, _1));
+}
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/json_ws.hh
^
|
@@ -0,0 +1,33 @@
+/*
+ PowerDNS Versatile Database Driven Nameserver
+ Copyright (C) 2003 - 2011 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 version 2
+ as published by the Free Software Foundation
+
+ 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+#include <boost/utility.hpp>
+#include "namespaces.hh"
+#include "mplexer.hh"
+
+class JWebserver : public boost::noncopyable
+{
+ public:
+ explicit JWebserver(FDMultiplexer* fdm);
+ void newConnection();
+ void readRequest(int fd);
+ private:
+ FDMultiplexer* d_fdm;
+ int d_socket;
+};
+
+string returnJSONStats(const map<string, string>& items);
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/kqueuemplexer.cc
^
|
@@ -12,7 +12,7 @@
#include <sys/time.h>
#include "namespaces.hh"
-using namespace std;
+#include "namespaces.hh"
class KqueueFDMultiplexer : public FDMultiplexer
{
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/logger.cc
^
|
@@ -23,7 +23,7 @@
extern StatBag S;
#endif
-using namespace std;
+#include "namespaces.hh"
Logger &theL(const string &pname)
{
@@ -125,6 +125,14 @@
return *this;
}
+Logger& Logger::operator<<(double i)
+{
+ ostringstream tmp;
+ tmp<<i;
+ *this<<tmp.str();
+ return *this;
+}
+
Logger& Logger::operator<<(unsigned int i)
{
ostringstream tmp;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/logger.hh
^
|
@@ -36,7 +36,7 @@
typedef int pthread_t;
#endif // WIN32
-using namespace std;
+#include "namespaces.hh"
//! The Logger class can be used to log messages in various ways.
class Logger
@@ -110,6 +110,7 @@
*/
Logger& operator<<(const string &s); //!< log a string
Logger& operator<<(int); //!< log an int
+ Logger& operator<<(double); //!< log a double
Logger& operator<<(unsigned int); //!< log an unsigned int
Logger& operator<<(long); //!< log an unsigned int
Logger& operator<<(unsigned long); //!< log an unsigned int
@@ -117,7 +118,7 @@
Logger& operator<<(Urgency); //!< set the urgency, << style
#ifndef WIN32
- Logger& operator<<(ostream & (&)(ostream &)); //!< this is to recognise the endl, and to commit the log
+ Logger& operator<<(std::ostream & (&)(std::ostream &)); //!< this is to recognise the endl, and to commit the log
#else
// This is a hack to keep MSVC from generating a internal compiler error.
Logger& operator<<(ostream & (hack)(ostream &)); //!< this is to recognise the endl, and to commit the log
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/lua-pdns.cc
^
|
@@ -0,0 +1,286 @@
+#include "lua-pdns.hh"
+// #include "syncres.hh"
+#include <boost/foreach.hpp>
+#include "config.h"
+
+#if !defined(HAVE_LUA)
+
+// stub implementation
+
+PowerDNSLua::PowerDNSLua(const std::string& fname)
+{
+ throw runtime_error("Lua support disabled");
+}
+
+
+PowerDNSLua::~PowerDNSLua()
+{
+
+}
+
+#else
+
+extern "C" {
+#undef L
+/* Include the Lua API header files. */
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include "logger.hh"
+#include "namespaces.hh"
+
+bool netmaskMatchTable(lua_State* lua, const std::string& ip)
+{
+ lua_pushnil(lua); /* first key */
+ while (lua_next(lua, 2) != 0) {
+ string netmask=lua_tostring(lua, -1);
+ Netmask nm(netmask);
+ ComboAddress ca(ip);
+ lua_pop(lua, 1);
+
+ if(nm.match(ip))
+ return true;
+ }
+ return false;
+}
+
+static bool getFromTable(lua_State *lua, const std::string &key, std::string& value)
+{
+ lua_pushstring(lua, key.c_str()); // 4 is now '1'
+ lua_gettable(lua, -2); // replace by the first entry of our table we hope
+
+ bool ret=false;
+ if(!lua_isnil(lua, -1)) {
+ value = lua_tostring(lua, -1);
+ ret=true;
+ }
+ lua_pop(lua, 1);
+ return ret;
+}
+
+static bool getFromTable(lua_State *lua, const std::string &key, uint32_t& value)
+{
+ lua_pushstring(lua, key.c_str()); // 4 is now '1'
+ lua_gettable(lua, -2); // replace by the first entry of our table we hope
+
+ bool ret=false;
+ if(!lua_isnil(lua, -1)) {
+ value = (uint32_t)lua_tonumber(lua, -1);
+ ret=true;
+ }
+ lua_pop(lua, 1);
+ return ret;
+}
+
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSResourceRecord>& records)
+{
+ // make a table of tables
+ lua_newtable(lua);
+
+ int pos=0;
+ BOOST_FOREACH(const DNSResourceRecord& rr, records)
+ {
+ // row number, used by 'lua_settable' below
+ lua_pushnumber(lua, ++pos);
+ // "row" table
+ lua_newtable(lua);
+
+ lua_pushstring(lua, rr.qname.c_str());
+ lua_setfield(lua, -2, "qname"); // pushes value at the top of the stack to the table immediately below that (-1 = top, -2 is below)
+
+ lua_pushstring(lua, rr.content.c_str());
+ lua_setfield(lua, -2, "content");
+
+ lua_pushnumber(lua, rr.qtype.getCode());
+ lua_setfield(lua, -2, "qtype");
+
+ lua_pushnumber(lua, rr.ttl);
+ lua_setfield(lua, -2, "ttl");
+
+ lua_pushnumber(lua, rr.d_place);
+ lua_setfield(lua, -2, "place");
+
+ lua_settable(lua, -3); // pushes the table we just built into the master table at position pushed above
+ }
+}
+
+void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSResourceRecord>& ret)
+{
+ /* get the result */
+ DNSResourceRecord rr;
+ rr.qname = query;
+ rr.d_place = DNSResourceRecord::ANSWER;
+ rr.ttl = 3600;
+
+// cerr<<"Lua stacksize "<<lua_gettop(lua)<<endl;
+#ifndef LUA_VERSION_NUM
+ int tableLen = luaL_getn(lua, 2);
+#else
+ int tableLen = lua_objlen(lua, 2);
+#endif
+// cerr<<"Got back "<<tableLen<< " answers from Lua"<<endl;
+
+ for(int n=1; n < tableLen + 1; ++n) {
+ lua_pushnumber(lua, n);
+ lua_gettable(lua, 2);
+
+ uint32_t tmpnum=0;
+ if(!getFromTable(lua, "qtype", tmpnum))
+ rr.qtype=QType::A;
+ else
+ rr.qtype=tmpnum;
+
+ getFromTable(lua, "content", rr.content);
+ if(!getFromTable(lua, "ttl", rr.ttl))
+ rr.ttl=3600;
+
+ if(!getFromTable(lua, "qname", rr.qname))
+ rr.qname = query;
+
+ if(!getFromTable(lua, "place", tmpnum))
+ rr.d_place = DNSResourceRecord::ANSWER;
+ else {
+ rr.d_place = (DNSResourceRecord::Place) tmpnum;
+ if(rr.d_place > DNSResourceRecord::ADDITIONAL)
+ rr.d_place = DNSResourceRecord::ADDITIONAL;
+ }
+
+ /* removes 'value'; keeps 'key' for next iteration */
+ lua_pop(lua, 1); // table
+
+ // cerr<<"Adding content '"<<rr.content<<"' with place "<<(int)rr.d_place<<" \n";
+ ret.push_back(rr);
+ }
+}
+
+extern "C" {
+
+int netmaskMatchLua(lua_State *lua)
+{
+ bool result=false;
+ if(lua_gettop(lua) >= 2) {
+ string ip=lua_tostring(lua, 1);
+ if(lua_istable(lua, 2)) {
+ result = netmaskMatchTable(lua, ip);
+ }
+ else {
+ for(int n=2 ; n <= lua_gettop(lua); ++n) {
+ string netmask=lua_tostring(lua, n);
+ Netmask nm(netmask);
+ ComboAddress ca(ip);
+
+ result = nm.match(ip);
+ if(result)
+ break;
+ }
+ }
+ }
+
+ lua_pushboolean(lua, result);
+ return 1;
+}
+
+int getLocalAddressLua(lua_State* lua)
+{
+ lua_getfield(lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
+ PowerDNSLua* pl = (PowerDNSLua*)lua_touserdata(lua, -1);
+
+ lua_pushstring(lua, pl->getLocal().toString().c_str());
+ return 1;
+}
+
+// called by lua to indicate that this answer is 'variable' and should not be cached
+int setVariableLua(lua_State* lua)
+{
+ lua_getfield(lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
+ PowerDNSLua* pl = (PowerDNSLua*)lua_touserdata(lua, -1);
+ pl->setVariable();
+ return 0;
+}
+
+int logLua(lua_State *lua)
+{
+ if(lua_gettop(lua) >= 1) {
+ string message=lua_tostring(lua, 1);
+ theL()<<Logger::Error<<"From Lua script: "<<message<<endl;
+ }
+ return 0;
+}
+}
+
+PowerDNSLua::PowerDNSLua(const std::string& fname)
+{
+ d_lua = lua_open();
+
+#ifndef LUA_VERSION_NUM
+ luaopen_base(d_lua);
+ luaopen_string(d_lua);
+
+ if(lua_dofile(d_lua, fname.c_str()))
+#else
+ luaL_openlibs(d_lua);
+ if(luaL_dofile(d_lua, fname.c_str()))
+#endif
+ throw runtime_error(string("Error loading Lua file '")+fname+"': "+ string(lua_isstring(d_lua, -1) ? lua_tostring(d_lua, -1) : "unknown error"));
+
+ lua_settop(d_lua, 0);
+
+ lua_pushcfunction(d_lua, netmaskMatchLua);
+ lua_setglobal(d_lua, "matchnetmask");
+
+ lua_pushcfunction(d_lua, logLua);
+ lua_setglobal(d_lua, "pdnslog");
+
+ lua_pushcfunction(d_lua, setVariableLua);
+ lua_setglobal(d_lua, "setvariable");
+
+ lua_pushcfunction(d_lua, getLocalAddressLua);
+ lua_setglobal(d_lua, "getlocaladdress");
+
+ lua_newtable(d_lua);
+
+ for(vector<QType::namenum>::const_iterator iter = QType::names.begin(); iter != QType::names.end(); ++iter) {
+ lua_pushnumber(d_lua, iter->second);
+ lua_setfield(d_lua, -2, iter->first.c_str());
+ }
+ lua_pushnumber(d_lua, 0);
+ lua_setfield(d_lua, -2, "NOERROR");
+ lua_pushnumber(d_lua, 1);
+ lua_setfield(d_lua, -2, "FORMERR");
+ lua_pushnumber(d_lua, 2);
+ lua_setfield(d_lua, -2, "SERVFAIL");
+ lua_pushnumber(d_lua, 3);
+ lua_setfield(d_lua, -2, "NXDOMAIN");
+ lua_pushnumber(d_lua, 4);
+ lua_setfield(d_lua, -2, "NOTIMP");
+ lua_pushnumber(d_lua, 5);
+ lua_setfield(d_lua, -2, "REFUSED");
+ lua_setglobal(d_lua, "pdns");
+
+ lua_pushlightuserdata(d_lua, (void*)this);
+ lua_setfield(d_lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
+}
+
+bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
+{
+ return ::getFromTable(d_lua, key, value);
+}
+
+bool PowerDNSLua::getFromTable(const std::string& key, uint32_t& value)
+{
+ return ::getFromTable(d_lua, key, value);
+}
+
+
+PowerDNSLua::~PowerDNSLua()
+{
+ lua_close(d_lua);
+}
+#endif
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/lua-pdns.hh
^
|
@@ -0,0 +1,37 @@
+#ifndef PDNS_LUA_PDNS_HH
+#define PDNS_LUA_PDNS_HH
+#include "dns.hh"
+#include "iputils.hh"
+
+struct lua_State;
+
+class PowerDNSLua
+{
+public:
+ explicit PowerDNSLua(const std::string& fname);
+ ~PowerDNSLua();
+ void reload();
+ ComboAddress getLocal()
+ {
+ return d_local;
+ }
+
+ void setVariable()
+ {
+ d_variable=true;
+ }
+
+protected: // FIXME?
+ lua_State* d_lua;
+ bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
+ bool getFromTable(const std::string& key, std::string& value);
+ bool getFromTable(const std::string& key, uint32_t& value);
+ bool d_failed;
+ bool d_variable;
+ ComboAddress d_local;
+};
+
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSResourceRecord>& records);
+void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSResourceRecord>& ret);
+
+#endif
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/lua-recursor.cc
^
|
@@ -0,0 +1,173 @@
+#include "lua-recursor.hh"
+
+// to avoid including all of syncres.hh
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
+
+#if !defined(HAVE_LUA)
+
+RecursorLua::RecursorLua(const std::string &fname)
+ : PowerDNSLua(fname)
+{
+ // empty
+}
+
+bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return false;
+}
+
+bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return false;
+}
+
+bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return false;
+}
+
+
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return false;
+}
+
+
+#else
+
+extern "C" {
+#undef L
+/* Include the Lua API header files. */
+#include <lua.h>
+#include <lauxlib.h>
+#include <lualib.h>
+}
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string>
+#include <vector>
+#include <stdexcept>
+#include <boost/foreach.hpp>
+#include "logger.hh"
+#include "namespaces.hh"
+
+RecursorLua::RecursorLua(const std::string &fname)
+ : PowerDNSLua(fname)
+{
+ // empty
+}
+
+int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
+{
+ int rcode=directResolve(qname, QType(QType::A), 1, ret);
+
+ ComboAddress prefixAddress(prefix);
+
+ BOOST_FOREACH(DNSResourceRecord& rr, ret)
+ {
+ if(rr.qtype.getCode() == QType::A && rr.d_place==DNSResourceRecord::ANSWER) {
+ ComboAddress ipv4(rr.content);
+ uint32_t tmp;
+ memcpy((void*)&tmp, &ipv4.sin4.sin_addr.s_addr, 4);
+ // tmp=htonl(tmp);
+ memcpy(((char*)&prefixAddress.sin6.sin6_addr.s6_addr)+12, &tmp, 4);
+ rr.content = prefixAddress.toString();
+ rr.qtype = QType(QType::AAAA);
+ }
+ }
+ return rcode;
+}
+
+bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return passthrough("nxdomain", remote, local, query, qtype, ret, res, variable);
+}
+
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return passthrough("preresolve", remote, local, query, qtype, ret, res, variable);
+}
+
+bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return passthrough("nodata", remote, local, query, qtype, ret, res, variable);
+}
+
+bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+{
+ return passthrough("postresolve", remote, local, query, qtype, ret, res, variable);
+}
+
+
+bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret,
+ int& res, bool* variable)
+{
+ d_variable = false;
+ lua_getglobal(d_lua, func.c_str());
+ if(!lua_isfunction(d_lua, -1)) {
+ // cerr<<"No such function '"<<func<<"'\n";
+ lua_pop(d_lua, 1);
+ return false;
+ }
+
+ d_local = local;
+ /* the first argument */
+ lua_pushstring(d_lua, remote.toString().c_str() );
+ lua_pushstring(d_lua, query.c_str() );
+ lua_pushnumber(d_lua, qtype.getCode() );
+
+ int extraParameter = 0;
+ if(!strcmp(func.c_str(),"nodata")) {
+ pushResourceRecordsTable(d_lua, ret);
+ extraParameter++;
+ }
+ else if(!strcmp(func.c_str(),"postresolve")) {
+ pushResourceRecordsTable(d_lua, ret);
+ lua_pushnumber(d_lua, res);
+ extraParameter+=2;
+ }
+
+ if(lua_pcall(d_lua, 3 + extraParameter, 3, 0)) {
+ string error=string("lua error in '"+func+"' while processing query for '"+query+"|"+qtype.getName()+": ")+lua_tostring(d_lua, -1);
+ lua_pop(d_lua, 1);
+ throw runtime_error(error);
+ return false;
+ }
+
+ *variable |= d_variable;
+
+
+ if(!lua_isnumber(d_lua, 1)) {
+ string tocall = lua_tostring(d_lua,1);
+ string luaqname = lua_tostring(d_lua,2);
+ string luaprefix = lua_tostring(d_lua, 3);
+ lua_pop(d_lua, 3);
+ // cerr<<"should call '"<<tocall<<"' to finish off"<<endl;
+ ret.clear();
+ res=getFakeAAAARecords(luaqname, luaprefix, ret);
+ return true;
+ // returned a followup
+ }
+
+ int newres = (int)lua_tonumber(d_lua, 1); // new rcode
+ if(newres < 0) {
+ // cerr << "handler did not handle"<<endl;
+ lua_pop(d_lua, 3);
+ return false;
+ }
+ res=newres;
+
+ ret.clear();
+
+ /* 1 2 3 4 */
+ /* stack: boolean table key row */
+
+ popResourceRecordsTable(d_lua, query, ret);
+
+ lua_pop(d_lua, 3);
+
+ return true;
+}
+
+#endif
\ No newline at end of file
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/lua-recursor.hh
^
|
@@ -0,0 +1,21 @@
+#ifndef PDNS_LUA_RECURSOR_HH
+#define PDNS_LUA_RECURSOR_HH
+#include "dns.hh"
+#include "iputils.hh"
+#include "lua-pdns.hh"
+
+class RecursorLua : public PowerDNSLua
+{
+public:
+ explicit RecursorLua(const std::string& fname);
+ // ~RecursorLua();
+ bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+ bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+ bool nodata(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+ bool postresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+
+private:
+ bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
+};
+
+#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/lwres.cc
^
|
@@ -164,6 +164,7 @@
lwr->d_result.clear();
try {
+ lwr->d_tcbit=0;
MOADNSParser mdp((const char*)buf.get(), len);
lwr->d_aabit=mdp.d_header.aa;
lwr->d_tcbit=mdp.d_header.tc;
@@ -186,7 +187,6 @@
rr.priority = 0;
rr.qtype=i->first.d_type;
rr.qname=i->first.d_label;
-
rr.ttl=i->first.d_ttl;
rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form
rr.d_place=(DNSResourceRecord::Place) i->first.d_place;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/lwres.hh
^
|
@@ -38,7 +38,7 @@
#include "ahuexception.hh"
#include "dns.hh"
-using namespace std;
+#include "namespaces.hh"
int asendto(const char *data, int len, int flags, const ComboAddress& ip, uint16_t id,
const string& domain, uint16_t qtype, int* fd);
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/misc.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 - 2006 PowerDNS.COM BV
+ Copyright (C) 2002 - 2010 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 version 2
@@ -317,11 +317,45 @@
ret = poll(&pfd, 1, seconds * 1000 + useconds/1000);
if ( ret == -1 )
- errno = ETIMEDOUT;
+ errno = ETIMEDOUT; // ???
return ret;
}
+// returns -1 in case of error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
+int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int*fd)
+{
+ int ret;
+
+ struct pollfd pfds[2];
+ memset(&pfds[0], 0, 2*sizeof(struct pollfd));
+ pfds[0].fd = fd1;
+ pfds[1].fd = fd2;
+
+ pfds[0].events= pfds[1].events = POLLIN;
+
+ int nsocks = 1 + (fd2 >= 0); // fd2 can optionally be -1
+
+ if(seconds >= 0)
+ ret = poll(pfds, nsocks, seconds * 1000 + useconds/1000);
+ else
+ ret = poll(pfds, nsocks, -1);
+ if(!ret || ret < 0)
+ return ret;
+
+ if((pfds[0].revents & POLLIN) && !(pfds[1].revents & POLLIN))
+ *fd = pfds[0].fd;
+ else if((pfds[1].revents & POLLIN) && !(pfds[0].revents & POLLIN))
+ *fd = pfds[1].fd;
+ else if(ret == 2) {
+ *fd = pfds[random()%2].fd;
+ }
+ else
+ *fd = -1; // should never happen
+
+ return 1;
+}
+
string humanDuration(time_t passed)
{
@@ -329,13 +363,13 @@
if(passed<60)
ret<<passed<<" seconds";
else if(passed<3600)
- ret<<setprecision(2)<<passed/60.0<<" minutes";
+ ret<<std::setprecision(2)<<passed/60.0<<" minutes";
else if(passed<86400)
- ret<<setprecision(3)<<passed/3600.0<<" hours";
+ ret<<std::setprecision(3)<<passed/3600.0<<" hours";
else if(passed<(86400*30.41))
- ret<<setprecision(3)<<passed/86400.0<<" days";
+ ret<<std::setprecision(3)<<passed/86400.0<<" days";
else
- ret<<setprecision(3)<<passed/(86400*30.41)<<" months";
+ ret<<std::setprecision(3)<<passed/(86400*30.41)<<" months";
return ret.str();
}
@@ -393,6 +427,9 @@
#ifdef WIN32
# define MAXHOSTNAMELEN 1025
#endif // WIN32
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 255
+#endif
char tmp[MAXHOSTNAMELEN];
if(gethostname(tmp, MAXHOSTNAMELEN))
@@ -481,23 +518,6 @@
}
-const string sockAddrToString(struct sockaddr_in *remote)
-{
- if(remote->sin_family == AF_INET) {
- struct sockaddr_in sip;
- memcpy(&sip,(struct sockaddr_in*)remote,sizeof(sip));
- return inet_ntoa(sip.sin_addr);
- }
- else {
- char tmp[128];
-
- if(!Utility::inet_ntop(AF_INET6, ( const char * ) &((struct sockaddr_in6 *)remote)->sin6_addr, tmp, sizeof(tmp)))
- return "IPv6 untranslateable";
-
- return tmp;
- }
-}
-
string makeHexDump(const string& str)
{
char tmp[5];
@@ -511,8 +531,6 @@
return ret;
}
-
-
// shuffle, maintaining some semblance of order
void shuffle(vector<DNSResourceRecord>& rrs)
{
@@ -541,6 +559,18 @@
// we don't shuffle the rest
}
+static bool comparePlace(DNSResourceRecord a, DNSResourceRecord b)
+{
+ return (a.d_place < b.d_place);
+}
+
+// make sure rrs is sorted in d_place order to avoid surprises later
+// then shuffle the parts that desire shuffling
+void orderAndShuffle(vector<DNSResourceRecord>& rrs)
+{
+ std::stable_sort(rrs.begin(), rrs.end(), comparePlace);
+ shuffle(rrs);
+}
void normalizeTV(struct timeval& tv)
{
@@ -585,10 +615,8 @@
return ret;
}
-boost::optional<int> logFacilityToLOG(unsigned int facility)
+int logFacilityToLOG(unsigned int facility)
{
- boost::optional<int> ret;
-
switch(facility) {
case 0:
return LOG_LOCAL0;
@@ -607,7 +635,7 @@
case 7:
return(LOG_LOCAL7);
default:
- return ret;
+ return -1;
}
}
@@ -621,3 +649,137 @@
return dom.substr(0,dom.size()-1);
}
+
+
+string labelReverse(const std::string& qname)
+{
+ if(qname.empty())
+ return qname;
+
+ bool dotName = qname.find('.') != string::npos;
+
+ vector<string> labels;
+ stringtok(labels, qname, ". ");
+ if(labels.size()==1)
+ return qname;
+
+ string ret; // vv const_reverse_iter http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11729
+ for(vector<string>::reverse_iterator iter = labels.rbegin(); iter != labels.rend(); ++iter) {
+ if(iter != labels.rbegin())
+ ret.append(1, dotName ? ' ' : '.');
+ ret+=*iter;
+ }
+ return ret;
+}
+
+// do NOT feed trailing dots!
+// www.powerdns.com, powerdns.com -> www
+string makeRelative(const std::string& fqdn, const std::string& zone)
+{
+ if(zone.empty())
+ return fqdn;
+ if(fqdn != zone)
+ return fqdn.substr(0, fqdn.size() - zone.length() - 1); // strip domain name
+ return "";
+}
+
+string dotConcat(const std::string& a, const std::string &b)
+{
+ if(a.empty() || b.empty())
+ return a+b;
+ else
+ return a+"."+b;
+}
+
+int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
+{
+ if(addr.empty())
+ return -1;
+ string ourAddr(addr);
+ int port = -1;
+ if(addr[0]=='[') { // [::]:53 style address
+ string::size_type pos = addr.find(']');
+ if(pos == string::npos || pos + 2 > addr.size() || addr[pos+1]!=':')
+ return -1;
+ ourAddr.assign(addr.c_str() + 1, pos-1);
+ port = atoi(addr.c_str()+pos+2);
+ }
+
+ struct addrinfo* res;
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+
+ int error;
+ if((error=getaddrinfo(ourAddr.c_str(), 0, &hints, &res))) { // this is correct
+ /*
+ cerr<<"Error translating IPv6 address '"<<addr<<"': ";
+ if(error==EAI_SYSTEM)
+ cerr<<strerror(errno)<<endl;
+ else
+ cerr<<gai_strerror(error)<<endl;
+ */
+ return -1;
+ }
+
+ memcpy(ret, res->ai_addr, res->ai_addrlen);
+ if(port >= 0)
+ ret->sin6_port = htons(port);
+ freeaddrinfo(res);
+ return 0;
+}
+
+int makeIPv4sockaddr(const string &str, struct sockaddr_in* ret)
+{
+ if(str.empty()) {
+ return -1;
+ }
+ struct in_addr inp;
+
+ string::size_type pos = str.find(':');
+ if(pos == string::npos) { // no port specified, not touching the port
+ if(Utility::inet_aton(str.c_str(), &inp)) {
+ ret->sin_addr.s_addr=inp.s_addr;
+ return 0;
+ }
+ return -1;
+ }
+ if(!*(str.c_str() + pos + 1)) // trailing :
+ return -1;
+
+ char *eptr = (char*)str.c_str() + str.size();
+ int port = strtol(str.c_str() + pos + 1, &eptr, 10);
+ if(*eptr)
+ return -1;
+
+ ret->sin_port = htons(port);
+ if(Utility::inet_aton(str.substr(0, pos).c_str(), &inp)) {
+ ret->sin_addr.s_addr=inp.s_addr;
+ return 0;
+ }
+ return -1;
+}
+
+
+//! read a line of text from a FILE* to a std::string, returns false on 'no data'
+bool stringfgets(FILE* fp, std::string& line)
+{
+ char buffer[1024];
+ line.clear();
+
+ do {
+ if(!fgets(buffer, sizeof(buffer), fp))
+ return !line.empty();
+
+ line.append(buffer);
+ } while(!strchr(buffer, '\n'));
+ return true;
+}
+
+Regex::Regex(const string &expr)
+{
+ if(regcomp(&d_preg, expr.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED))
+ throw AhuException("Regular expression did not compile");
+}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/misc.hh
^
|
@@ -1,12 +1,11 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002-2009 PowerDNS.COM BV
+ Copyright (C) 2002-2012 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 version 2
as published by the Free Software Foundation
-
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
@@ -21,7 +20,14 @@
#include <inttypes.h>
#include <cstring>
#include <cstdio>
+#include <regex.h>
#include <boost/algorithm/string.hpp>
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+#include <boost/multi_index/key_extractors.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+using namespace ::boost::multi_index;
#if 0
#include <iostream>
using std::cout;
@@ -61,9 +67,8 @@
#include <string>
#include <ctype.h>
#include <vector>
-#include <boost/optional.hpp>
-using namespace std;
+#include "namespaces.hh"
bool chopOff(string &domain);
bool chopOffDotted(string &domain);
@@ -72,38 +77,18 @@
string nowTime();
const string unquotify(const string &item);
string humanDuration(time_t passed);
-void chomp(string &line, const string &delim);
bool stripDomainSuffix(string *qname, const string &domain);
void stripLine(string &line);
string getHostname();
string urlEncode(const string &text);
int waitForData(int fd, int seconds, int useconds=0);
+int waitFor2Data(int fd1, int fd2, int seconds, int useconds, int* fd);
int waitForRWData(int fd, bool waitForRead, int seconds, int useconds);
uint16_t getShort(const unsigned char *p);
uint16_t getShort(const char *p);
uint32_t getLong(const unsigned char *p);
uint32_t getLong(const char *p);
-boost::optional<int> logFacilityToLOG(unsigned int facility);
-
-inline void putLong(unsigned char* p, uint32_t val)
-{
- *p++=(val>>24)&0xff;
- *p++=(val>>16)&0xff;
- *p++=(val>>8)&0xff;
- *p++=(val )&0xff;
-
-}
-inline void putLong(char* p, uint32_t val)
-{
- putLong((unsigned char *)p,val);
-}
-
-
-inline uint32_t getLong(unsigned char *p)
-{
- return (p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
-}
-
+int logFacilityToLOG(unsigned int facility);
struct ServiceTuple
{
@@ -198,6 +183,7 @@
time_t time();
inline void set(); //!< Reset the timer
inline int udiff(); //!< Return the number of microseconds since the timer was last set.
+ inline int udiffNoReset(); //!< Return the number of microseconds since the timer was last set.
void setTimeval(const struct timeval& tv)
{
d_set=tv;
@@ -209,7 +195,7 @@
private:
struct timeval d_set;
};
-const string sockAddrToString(struct sockaddr_in *remote);
+
int sendData(const char *buffer, int replen, int outsock);
inline void DTime::set()
@@ -219,14 +205,21 @@
inline int DTime::udiff()
{
+ int res=udiffNoReset();
+ Utility::gettimeofday(&d_set,0);
+ return res;
+}
+
+inline int DTime::udiffNoReset()
+{
struct timeval now;
Utility::gettimeofday(&now,0);
int ret=1000000*(now.tv_sec-d_set.tv_sec)+(now.tv_usec-d_set.tv_usec);
- d_set=now;
return ret;
}
+
inline bool dns_isspace(char c)
{
return c==' ' || c=='\t' || c=='\r' || c=='\n';
@@ -296,6 +289,7 @@
string makeHexDump(const string& str);
void shuffle(vector<DNSResourceRecord>& rrs);
+void orderAndShuffle(vector<DNSResourceRecord>& rrs);
void normalizeTV(struct timeval& tv);
const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
@@ -343,8 +337,65 @@
return aLen == bLen; // strings are equal (in length)
}
+// lifted from boost, with thanks
+class AtomicCounter
+{
+public:
+
+ explicit AtomicCounter( unsigned int v = 0) : value_( v ) {}
+
+ unsigned int operator++()
+ {
+ return atomic_exchange_and_add( &value_, +1 ) + 1;
+ }
+
+ unsigned int operator--()
+ {
+ return atomic_exchange_and_add( &value_, -1 ) - 1;
+ }
+
+ operator unsigned int() const
+ {
+ return atomic_exchange_and_add( &value_, 0);
+ }
+
+private:
+ AtomicCounter(AtomicCounter const &);
+ AtomicCounter &operator=(AtomicCounter const &);
+
+ mutable unsigned int value_;
+
+ // the below is necessary because __sync_fetch_and_add is not universally available on i386.. I 3> RHEL5.
+ #if defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
+ static int atomic_exchange_and_add( unsigned int * pw, int dv )
+ {
+ // int r = *pw;
+ // *pw += dv;
+ // return r;
+
+ int r;
+
+ __asm__ __volatile__
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "+m"( *pw ), "=r"( r ): // outputs (%0, %1)
+ "1"( dv ): // inputs (%2 == %1)
+ "memory", "cc" // clobbers
+ );
+
+ return r;
+ }
+ #else
+ static int atomic_exchange_and_add( unsigned int * pw, int dv )
+ {
+ return __sync_fetch_and_add(pw, dv);
+ }
+ #endif
+};
-struct CIStringCompare: public binary_function<string, string, bool>
+
+struct CIStringCompare: public std::binary_function<string, string, bool>
{
bool operator()(const string& a, const string& b) const
{
@@ -352,6 +403,19 @@
}
};
+struct CIStringPairCompare: public std::binary_function<pair<string, uint16_t>, pair<string,uint16_t>, bool>
+{
+ bool operator()(const pair<string, uint16_t>& a, const pair<string, uint16_t>& b) const
+ {
+ if(pdns_ilexicographical_compare(a.first, b.first))
+ return true;
+ if(pdns_ilexicographical_compare(b.first, a.first))
+ return false;
+ return a.second < b.second;
+ }
+};
+
+
pair<string, string> splitField(const string& inp, char sepa);
inline bool isCanonical(const string& dom)
@@ -363,6 +427,9 @@
inline string toCanonic(const string& zone, const string& domain)
{
+ if(domain.length()==1 && domain[0]=='@')
+ return zone;
+
if(isCanonical(domain))
return domain;
string ret=domain;
@@ -380,4 +447,41 @@
string stripDot(const string& dom);
void seedRandom(const string& source);
+string makeRelative(const std::string& fqdn, const std::string& zone);
+string labelReverse(const std::string& qname);
+std::string dotConcat(const std::string& a, const std::string &b);
+int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret);
+int makeIPv4sockaddr(const string &str, struct sockaddr_in* ret);
+bool stringfgets(FILE* fp, std::string& line);
+
+template<typename Index>
+std::pair<typename Index::iterator,bool>
+replacing_insert(Index& i,const typename Index::value_type& x)
+{
+ std::pair<typename Index::iterator,bool> res=i.insert(x);
+ if(!res.second)res.second=i.replace(res.first,x);
+ return res;
+}
+
+/** very small regex wrapper */
+class Regex
+{
+public:
+ /** constructor that accepts the expression to regex */
+ Regex(const string &expr);
+
+ ~Regex()
+ {
+ regfree(&d_preg);
+ }
+ /** call this to find out if 'line' matches your expression */
+ bool match(const string &line)
+ {
+ return regexec(&d_preg,line.c_str(),0,0,0)==0;
+ }
+
+private:
+ regex_t d_preg;
+};
+
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/mplexer.hh
^
|
@@ -1,3 +1,5 @@
+#ifndef PDNS_MPLEXER_HH
+#define PDNS_MPLEXER_HH
#include <boost/function.hpp>
#include <boost/any.hpp>
#include <boost/shared_array.hpp>
@@ -156,3 +158,4 @@
}
};
+#endif
\ No newline at end of file
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/mtasker.cc
^
|
@@ -40,7 +40,7 @@
MTasker is designed to offer the performance of statemachines while maintaining simple thread semantics. It is not
a replacement for a full threading system.
- \section compatability Compatability
+ \section compatibility Compatibility
MTasker is only guaranteed to work on Linux with glibc 2.2.5 and higher. It does not work on FreeBSD and notably,
not on Red Hat 6.0. It may work on Solaris, please test.
@@ -71,7 +71,7 @@
\section events Events
By default, Events are recognized by an int and their value is also an int.
- This can be overriden by specifying the EventKey and EventVal template parameters.
+ This can be overridden by specifying the EventKey and EventVal template parameters.
An event can be a keypress, but also a UDP packet, or a bit of data from a TCP socket. The
sample code provided works with keypresses, but that is just a not very useful example.
@@ -144,7 +144,7 @@
//! puts a thread to sleep waiting until a specified event arrives
/** Threads can call waitEvent to register that they are waiting on an event with a certain key.
- If so desidered, the event can carry data which is returned in val in case that is non-zero.
+ If so desired, the event can carry data which is returned in val in case that is non-zero.
Furthermore, a timeout can be specified in seconds.
@@ -192,6 +192,9 @@
if(val && d_waitstatus==Answer)
*val=d_waitval;
d_tid=w.tid;
+ if((char*)&w < d_threads[d_tid].highestStackSeen) {
+ d_threads[d_tid].highestStackSeen = (char*)&w;
+ }
key=d_eventkey;
return d_waitstatus;
}
@@ -202,7 +205,7 @@
template<class Key, class Val>void MTasker<Key,Val>::yield()
{
d_runQueue.push(d_tid);
- if(swapcontext(d_threads[d_tid] ,&d_kernel) < 0) { // give control to the kernel
+ if(swapcontext(d_threads[d_tid].context ,&d_kernel) < 0) { // give control to the kernel
perror("swapcontext in yield");
exit(EXIT_FAILURE);
}
@@ -271,7 +274,7 @@
makecontext (uc, (void (*)(void))threadWrapper, 6, thispair.first, thispair.second, start, d_maxtid, valpair.first, valpair.second);
- d_threads[d_maxtid]=uc;
+ d_threads[d_maxtid].context = uc;
d_runQueue.push(d_maxtid++); // will run at next schedule invocation
}
@@ -290,7 +293,7 @@
{
if(!d_runQueue.empty()) {
d_tid=d_runQueue.front();
- if(swapcontext(&d_kernel, d_threads[d_tid])) {
+ if(swapcontext(&d_kernel, d_threads[d_tid].context)) {
perror("swapcontext in schedule");
exit(EXIT_FAILURE);
}
@@ -299,8 +302,8 @@
return true;
}
if(!d_zombiesQueue.empty()) {
- delete[] (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
- delete d_threads[d_zombiesQueue.front()];
+ delete[] (char *)d_threads[d_zombiesQueue.front()].context->uc_stack.ss_sp;
+ delete d_threads[d_zombiesQueue.front()].context;
d_threads.erase(d_zombiesQueue.front());
d_zombiesQueue.pop();
return true;
@@ -369,11 +372,11 @@
}
}
-
template<class Key, class Val>void MTasker<Key,Val>::threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2)
{
void* val = joinPtr(val1, val2);
MTasker* self = (MTasker*) joinPtr(self1, self2);
+ self->d_threads[self->d_tid].startOfStack = self->d_threads[self->d_tid].highestStackSeen = (char*)&val;
(*tf)(val);
self->d_zombiesQueue.push(tid);
@@ -388,3 +391,10 @@
{
return d_tid;
}
+
+
+//! Returns the maximum stack usage so far of this MThread
+template<class Key, class Val>unsigned int MTasker<Key,Val>::getMaxStackUsage()
+{
+ return d_threads[d_tid].startOfStack - d_threads[d_tid].highestStackSeen;
+}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/mtasker.hh
^
|
@@ -50,8 +50,14 @@
std::queue<int> d_runQueue;
std::queue<int> d_zombiesQueue;
+ struct ThreadInfo
+ {
+ ucontext_t* context;
+ char* startOfStack;
+ char* highestStackSeen;
+ };
- typedef std::map<int, ucontext_t*> mthreads_t;
+ typedef std::map<int, ThreadInfo> mthreads_t;
mthreads_t d_threads;
int d_tid;
int d_maxtid;
@@ -66,7 +72,7 @@
EventKey key;
ucontext_t *context;
struct timeval ttd;
- int tid;
+ int tid;
};
typedef multi_index_container<
@@ -99,6 +105,7 @@
bool noProcesses();
unsigned int numProcesses();
int getTid();
+ unsigned int getMaxStackUsage();
private:
static void threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2);
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/namespaces.hh
^
|
@@ -10,6 +10,36 @@
#include <boost/function.hpp>
#include <boost/format.hpp>
#include <boost/algorithm/string.hpp>
+#include <vector>
+#include <map>
+#include <set>
+#include <deque>
+#include <string>
+#include <iostream>
+
+using std::vector;
+using std::map;
+using std::pair;
+using std::make_pair;
+using std::runtime_error;
+using std::ostringstream;
+using std::set;
+using std::deque;
+using std::cerr;
+using std::cout;
+using std::clog;
+using std::endl;
+using std::ifstream;
+using std::ofstream;
+using std::ostream;
+using std::min; // these are a bit scary, everybody uses 'min'
+using std::max;
+
+namespace pdns {
+ typedef std::string string;
+};
+
+typedef pdns::string string;
using boost::lexical_cast;
using boost::tie;
|
[-]
[+]
|
Added |
pdns-recursor-3.5.2.tar.bz2/nsecrecords.cc
^
|
@@ -0,0 +1,297 @@
+#include "dnsrecords.hh"
+
+void NSECRecordContent::report(void)
+{
+ regist(1, 47, &make, &make, "NSEC");
+}
+
+DNSRecordContent* NSECRecordContent::make(const string& content)
+{
+ return new NSECRecordContent(content);
+}
+
+NSECRecordContent::NSECRecordContent(const string& content, const string& zone) : DNSRecordContent(47)
+{
+ RecordTextReader rtr(content, zone);
+ rtr.xfrLabel(d_next);
+
+ while(!rtr.eof()) {
+ uint16_t type;
+ rtr.xfrType(type);
+ d_set.insert(type);
+ }
+}
+
+void NSECRecordContent::toPacket(DNSPacketWriter& pw)
+{
+ pw.xfrLabel(d_next);
+
+ uint8_t res[34];
+ set<uint16_t>::const_iterator i;
+ int oldWindow = -1;
+ int window = 0;
+ int len = 0;
+ string tmp;
+
+ for(i=d_set.begin(); i != d_set.end(); ++i){
+ uint16_t bit = (*i)%256;
+ window = static_cast<int>((*i) / 256);
+
+ if (window != oldWindow) {
+ if (oldWindow > -1) {
+ res[0] = static_cast<unsigned char>(oldWindow);
+ res[1] = static_cast<unsigned char>(len);
+ tmp.assign(res, res+len+2);
+ pw.xfrBlob(tmp);
+ }
+ memset(res, 0, 34);
+ oldWindow = window;
+ }
+ res[2+bit/8] |= 1 << (7-(bit%8));
+ len=1+bit/8;
+ }
+
+ res[0] = static_cast<unsigned char>(window);
+ res[1] = static_cast<unsigned char>(len);
+ tmp.assign(res, res+len+2);
+ pw.xfrBlob(tmp);
+}
+
+NSECRecordContent::DNSRecordContent* NSECRecordContent::make(const DNSRecord &dr, PacketReader& pr)
+{
+ NSECRecordContent* ret=new NSECRecordContent();
+ pr.xfrLabel(ret->d_next);
+ string bitmap;
+ pr.xfrBlob(bitmap);
+
+ // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left
+ if(bitmap.empty())
+ return ret;
+
+ if(bitmap.size() < 2)
+ throw MOADNSException("NSEC record with impossibly small bitmap");
+
+ for(unsigned int n = 0; n+1 < bitmap.size();) {
+ unsigned int window=static_cast<unsigned char>(bitmap[n++]);
+ unsigned int len=static_cast<unsigned char>(bitmap[n++]);
+
+ // end if zero padding and ensure packet length
+ if(window == 0&&len == 0) break;
+ if(n+len>bitmap.size())
+ throw MOADNSException("NSEC record with bitmap length > packet length");
+
+ for(unsigned int k=0; k < len; k++) {
+ uint8_t val=bitmap[n++];
+ for(int bit = 0; bit < 8 ; ++bit , val>>=1)
+ if(val & 1) {
+ ret->d_set.insert((7-bit) + 8*(k) + 256*window);
+ }
+ }
+ }
+ return ret;
+}
+
+string NSECRecordContent::getZoneRepresentation() const
+{
+ string ret;
+ RecordTextWriter rtw(ret);
+ rtw.xfrLabel(d_next);
+
+ for(set<uint16_t>::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) {
+ ret+=" ";
+ ret+=NumberToType(*i);
+ }
+
+ return ret;
+}
+
+////// begin of NSEC3
+
+void NSEC3RecordContent::report(void)
+{
+ regist(1, 50, &make, &make, "NSEC3");
+}
+
+DNSRecordContent* NSEC3RecordContent::make(const string& content)
+{
+ return new NSEC3RecordContent(content);
+}
+
+NSEC3RecordContent::NSEC3RecordContent(const string& content, const string& zone) : DNSRecordContent(50)
+{
+ RecordTextReader rtr(content, zone);
+ rtr.xfr8BitInt(d_algorithm);
+ rtr.xfr8BitInt(d_flags);
+ rtr.xfr16BitInt(d_iterations);
+
+ rtr.xfrHexBlob(d_salt);
+ rtr.xfrBase32HexBlob(d_nexthash);
+
+ while(!rtr.eof()) {
+ uint16_t type;
+ rtr.xfrType(type);
+ d_set.insert(type);
+ }
+}
+
+void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
+{
+ pw.xfr8BitInt(d_algorithm);
+ pw.xfr8BitInt(d_flags);
+ pw.xfr16BitInt(d_iterations);
+ pw.xfr8BitInt(d_salt.length());
+ pw.xfrBlob(d_salt);
+
+ pw.xfr8BitInt(d_nexthash.length());
+ pw.xfrBlob(d_nexthash);
+
+ uint8_t res[34];
+ set<uint16_t>::const_iterator i;
+ int oldWindow = -1;
+ int window = 0;
+ int len = 0;
+ string tmp;
+
+ for(i=d_set.begin(); i != d_set.end(); ++i){
+ uint16_t bit = (*i)%256;
+ window = static_cast<int>((*i) / 256);
+
+ if (window != oldWindow) {
+ if (oldWindow > -1) {
+ res[0] = static_cast<unsigned char>(oldWindow);
+ res[1] = static_cast<unsigned char>(len);
+ tmp.assign(res, res+len+2);
+ pw.xfrBlob(tmp);
+ }
+ memset(res, 0, 34);
+ oldWindow = window;
+ }
+ res[2+bit/8] |= 1 << (7-(bit%8));
+ len=1+bit/8;
+ }
+
+ res[0] = static_cast<unsigned char>(window);
+ res[1] = static_cast<unsigned char>(len);
+
+ if (len) {
+ tmp.assign(res, res+len+2);
+ pw.xfrBlob(tmp);
+ }
+}
+
+NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr)
+{
+ NSEC3RecordContent* ret=new NSEC3RecordContent();
+ pr.xfr8BitInt(ret->d_algorithm);
+ pr.xfr8BitInt(ret->d_flags);
+ pr.xfr16BitInt(ret->d_iterations);
+ uint8_t len;
+ pr.xfr8BitInt(len);
+ pr.xfrBlob(ret->d_salt, len);
+
+ pr.xfr8BitInt(len);
+
+ pr.xfrBlob(ret->d_nexthash, len);
+
+ string bitmap;
+ pr.xfrBlob(bitmap);
+
+ // 00 06 20 00 00 00 00 03 -> NS RRSIG NSEC ( 2, 46, 47 ) counts from left
+
+ if(bitmap.empty())
+ return ret;
+
+ if(bitmap.size() < 2)
+ throw MOADNSException("NSEC3 record with impossibly small bitmap");
+
+ for(unsigned int n = 0; n+1 < bitmap.size();) {
+ unsigned int window=static_cast<unsigned char>(bitmap[n++]);
+ unsigned int len=static_cast<unsigned char>(bitmap[n++]);
+
+ // end if zero padding and ensure packet length
+ if(window == 0&&len == 0) break;
+ if(n+len>bitmap.size())
+ throw MOADNSException("NSEC record with bitmap length > packet length");
+
+ for(unsigned int k=0; k < len; k++) {
+ uint8_t val=bitmap[n++];
+ for(int bit = 0; bit < 8 ; ++bit , val>>=1)
+ if(val & 1) {
+ ret->d_set.insert((7-bit) + 8*(k) + 256*window);
+ }
+ }
+ }
+ return ret;
+}
+
+string NSEC3RecordContent::getZoneRepresentation() const
+{
+ string ret;
+ RecordTextWriter rtw(ret);
+ rtw.xfr8BitInt(d_algorithm);
+ rtw.xfr8BitInt(d_flags);
+ rtw.xfr16BitInt(d_iterations);
+
+ rtw.xfrHexBlob(d_salt);
+ rtw.xfrBase32HexBlob(d_nexthash);
+ for(set<uint16_t>::const_iterator i=d_set.begin(); i!=d_set.end(); ++i) {
+ ret+=" ";
+ ret+=NumberToType(*i);
+ }
+
+ return ret;
+}
+
+
+void NSEC3PARAMRecordContent::report(void)
+{
+ regist(1, 51, &make, &make, "NSEC3PARAM");
+}
+
+DNSRecordContent* NSEC3PARAMRecordContent::make(const string& content)
+{
+ return new NSEC3PARAMRecordContent(content);
+}
+
+NSEC3PARAMRecordContent::NSEC3PARAMRecordContent(const string& content, const string& zone) : DNSRecordContent(51)
+{
+ RecordTextReader rtr(content, zone);
+ rtr.xfr8BitInt(d_algorithm);
+ rtr.xfr8BitInt(d_flags);
+ rtr.xfr16BitInt(d_iterations);
+ rtr.xfrHexBlob(d_salt);
+}
+
+void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
+{
+ pw.xfr8BitInt(d_algorithm);
+ pw.xfr8BitInt(d_flags);
+ pw.xfr16BitInt(d_iterations);
+ pw.xfr8BitInt(d_salt.length());
+ // cerr<<"salt: '"<<makeHexDump(d_salt)<<"', "<<d_salt.length()<<endl;
+ pw.xfrBlob(d_salt);
+}
+
+NSEC3PARAMRecordContent::DNSRecordContent* NSEC3PARAMRecordContent::make(const DNSRecord &dr, PacketReader& pr)
+{
+ NSEC3PARAMRecordContent* ret=new NSEC3PARAMRecordContent();
+ pr.xfr8BitInt(ret->d_algorithm);
+ pr.xfr8BitInt(ret->d_flags);
+ pr.xfr16BitInt(ret->d_iterations);
+ pr.xfr8BitInt(ret->d_saltlength);
+ pr.xfrHexBlob(ret->d_salt);
+
+ return ret;
+}
+
+string NSEC3PARAMRecordContent::getZoneRepresentation() const
+{
+ string ret;
+ RecordTextWriter rtw(ret);
+ rtw.xfr8BitInt(d_algorithm);
+ rtw.xfr8BitInt(d_flags);
+ rtw.xfr16BitInt(d_iterations);
+ rtw.xfrHexBlob(d_salt);
+ return ret;
+}
+
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/pdns-recursor.init.d
^
|
@@ -1,4 +1,12 @@
#!/bin/sh
+### BEGIN INIT INFO
+# Provides: pdns-recursor
+# Required-Start: $network $remote_fs $syslog
+# Required-Stop: $network $remote_fs $syslog
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Start the recursor at boot time.
+### END INIT INFO
# chkconfig: - 80 75
# description: pdns_recursor is a versatile high performance recursing nameserver
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/pdns_hw.cc
^
|
@@ -4,13 +4,14 @@
#include <boost/tuple/tuple_comparison.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/foreach.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sstream>
-using namespace std;
+#include "namespaces.hh"
int main()
{
ostringstream str;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/pdns_recursor.1
^
|
@@ -1,53 +1,82 @@
+'\" t
.\" Title: pdns_recursor
-.\" Author:
-.\" Generator: DocBook XSL Stylesheets v1.72.0 <http://docbook.sf.net/>
-.\" Date: 03/22/2008
-.\" Manual:
-.\" Source:
+.\" Author: [see the "AUTHOR" section]
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Date: 06/07/2013
+.\" Manual: \ \&
+.\" Source: \ \& 3.0
+.\" Language: English
.\"
-.TH "PDNS_RECURSOR" "1" "03/22/2008" "" ""
+.TH "PDNS_RECURSOR" "1" "06/07/2013" "\ \& 3\&.0" "\ \&"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
.SH "NAME"
pdns_recursor \- high\-performance, simple and secure recursing nameserver
.SH "SYNOPSIS"
-\fIpdns_recursor\fR [\-\-daemon] [\-\-local\-address] [\-\-help, \-h] [\-\-allow\-from]
.sp
+\fIpdns_recursor\fR [\-\-daemon] [\-\-local\-address] [\-\-help, \-h] [\-\-allow\-from]
.SH "DESCRIPTION"
-pdns_recursor(1) is a high performance, simple and secure recursing nameserver. It currently powers over two million internet connections.
.sp
-The recursor is configured via a configuration file, but each item in that file can be overridden on the command line.
+pdns_recursor(1) is a high performance, simple and secure recursing nameserver\&. It currently powers over two million internet connections\&.
.sp
-This manpage lists the core set of features needed to get the PowerDNS recursor working, for full and up to date details head to http://doc.powerdns.com/built\-in\-recursor.html
+The recursor is configured via a configuration file, but each item in that file can be overridden on the command line\&.
.sp
+This manpage lists the core set of features needed to get the PowerDNS recursor working, for full and up to date details head to \m[blue]\fBhttp://doc\&.powerdns\&.com/built\-in\-recursor\&.html\fR\m[]
.SH "EXAMPLES"
-To listen on 1.2.3.4 and allow the 1.2.3.0/8 subnet to recurse, and run as a daemon, execute:
.sp
+To listen on 1\&.2\&.3\&.4 and allow the 1\&.2\&.3\&.0/8 subnet to recurse, and run as a daemon, execute:
.sp
+.if n \{\
.RS 4
+.\}
.nf
-# pdns_recursor \-\-local\-address=1.2.3.4 \-\-allow\-from=1.2.3.0/8 \-\-daemon
+# pdns_recursor \-\-local\-address=1\&.2\&.3\&.4 \-\-allow\-from=1\&.2\&.3\&.0/8 \-\-daemon
.fi
+.if n \{\
.RE
-To stop the recursor by hand, run:
+.\}
.sp
+To stop the recursor by hand, run:
.sp
+.if n \{\
.RS 4
+.\}
.nf
# rec_control quit
.fi
+.if n \{\
.RE
+.\}
.sp
+.if n \{\
.RS 4
+.\}
.nf
-Alternatively, use the init.d script provided.
+Alternatively, use the init\&.d script provided\&.
.fi
+.if n \{\
.RE
+.\}
.SH "OPTIONS"
-For authoritative listing of options, consult the documentation referenced above.
.sp
+For authoritative listing of options, consult the documentation referenced above\&.
.PP
\-\-aaaa\-additional\-processing
.RS 4
@@ -61,17 +90,17 @@
.PP
\-\-auth\-can\-lower\-ttl
.RS 4
-Authoritative zones can transmit a TTL value that is lower than that specified in the parent zone. This is called a
-\fIdelegation inconsistency\fR. To follow RFC 2181 paragraphs 5.2 and 5.4 to the letter, enable this feature. This will mean a slight deterioration of performance, and it will not solve any problems, but does make the recursor more standards compliant. Not recommended unless you have to tick an
+Authoritative zones can transmit a TTL value that is lower than that specified in the parent zone\&. This is called a
+\fIdelegation inconsistency\fR\&. To follow RFC 2181 paragraphs 5\&.2 and 5\&.4 to the letter, enable this feature\&. This will mean a slight deterioration of performance, and it will not solve any problems, but does make the recursor more standards compliant\&. Not recommended unless you have to tick an
\fIRFC 2181 compliant\fR
-box. Off by default.
+box\&. Off by default\&.
.RE
.PP
\-\-auth\-zones
.RS 4
Comma separated list of
\fIzonename=filename\fR
-pairs. Zones read from these files are served authoritatively. Example: auth\-zones= ds9a.nl=/var/zones/ds9a.nl, powerdns.com=/var/zones/powerdns.com. Available since 3.1.
+pairs\&. Zones read from these files are served authoritatively\&. Example: auth\-zones= ds9a\&.nl=/var/zones/ds9a\&.nl, powerdns\&.com=/var/zones/powerdns\&.com\&. Available since 3\&.1\&.
.RE
.PP
\-\-chroot
@@ -86,7 +115,7 @@
.PP
\-\-config\-dir
.RS 4
-Location of configuration directory (recursor.conf)
+Location of configuration directory (recursor\&.conf)
.RE
.PP
\-\-daemon
@@ -101,12 +130,12 @@
.PP
\-\-entropy\-source
.RS 4
-Where to read new entropy from, defaults to /dev/urandom.
+Where to read new entropy from, defaults to /dev/urandom\&.
.RE
.PP
\-\-export\-etc\-hosts
.RS 4
-If set, this flag will export the host names and IP addresses mentioned in /etc/hosts. Available since 3.1.
+If set, this flag will export the host names and IP addresses mentioned in /etc/hosts\&. Available since 3\&.1\&.
.RE
.PP
\-\-fork
@@ -118,12 +147,12 @@
.RS 4
Comma separated list of
\fIzonename=IP\fR
-pairs. Queries for zones listed here will be forwarded to the IP address listed. forward\-zones= ds9a.nl=213.244.168.210, powerdns.com=127.0.0.1. Available since 3.1. For more details, see the manual.
+pairs\&. Queries for zones listed here will be forwarded to the IP address listed\&. forward\-zones= ds9a\&.nl=213\&.244\&.168\&.210, powerdns\&.com=127\&.0\&.0\&.1\&. Available since 3\&.1\&. For more details, see the manual\&.
.RE
.PP
\-\-forward\-zones\-file
.RS 4
-listed here will be forwarded to the IP address listed. One zone per line, like: ds9a.nl=213.244.168.210 Available since 3.1.5. For more details, see the manual.
+listed here will be forwarded to the IP address listed\&. One zone per line, like: ds9a\&.nl=213\&.244\&.168\&.210 Available since 3\&.1\&.5\&. For more details, see the manual\&.
.RE
.PP
\-\-hint\-file
@@ -173,8 +202,8 @@
.PP
\-\-query\-local\-address6
.RS 4
-Send out local IPv6 queries from this address. Disabled by default, which also disables outgoing IPv6 support. A useful setting is
-\fI::0\fR.
+Send out local IPv6 queries from this address\&. Disabled by default, which also disables outgoing IPv6 support\&. A useful setting is
+\fI::0\fR\&.
.RE
.PP
\-\-quiet
@@ -190,13 +219,13 @@
\-\-server\-id
.RS 4
Returned when queried for
-\fIserver.id\fR
+\fIserver\&.id\fR
TXT, defaults to hostname
.RE
.PP
\-\-serve\-rfc1918
.RS 4
-On by default, this makes the server authoritatively aware of: 10.in\-addr.arpa, 168.192.in\-addr.arpa and 16\-31.172.in\-addr.arpa, which saves load on the AS112 servers. Individual parts of these zones can still be loaded or forwarded.
+On by default, this makes the server authoritatively aware of: 10\&.in\-addr\&.arpa, 168\&.192\&.in\-addr\&.arpa and 16\-31\&.172\&.in\-addr\&.arpa, which saves load on the AS112 servers\&. Individual parts of these zones can still be loaded or forwarded\&.
.RE
.PP
\-\-setgid
@@ -231,20 +260,26 @@
.PP
\-\-version\-string
.RS 4
-string reported on version.pdns or version.bind
+string reported on version\&.pdns or version\&.bind
.RE
.SH "BUGS"
-None known. File new ones at http://wiki.powerdns.com.
.sp
+None known\&. File new ones at \m[blue]\fBhttp://wiki\&.powerdns\&.com\fR\m[]\&.
.SH "AUTHOR"
-Written by PowerDNS.COM BV, bert hubert, <bert.hubert@netherlabs.nl>
.sp
+Written by PowerDNS\&.COM BV, bert hubert, <\m[blue]\fBbert\&.hubert@netherlabs\&.nl\fR\m[]\&\s-2\u[1]\d\s+2>
.SH "RESOURCES"
-Website: http://wiki.powerdns.com, http://www.powerdns.com
.sp
+Website: \m[blue]\fBhttp://wiki\&.powerdns\&.com\fR\m[], \m[blue]\fBhttp://www\&.powerdns\&.com\fR\m[]
.SH "SEE ALSO"
-rec_control(1)
.sp
+rec_control(1)
.SH "COPYING"
-Copyright \(co 2006 PowerDNS.COM BV. Free use of this software is granted under the terms of the GNU General Public License (GPL) version 2.
.sp
+Copyright \(co 2006 PowerDNS\&.COM BV\&. Free use of this software is granted under the terms of the GNU General Public License (GPL) version 2\&.
+.SH "NOTES"
+.IP " 1." 4
+bert.hubert@netherlabs.nl
+.RS 4
+\%mailto:bert.hubert@netherlabs.nl
+.RE
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/pdns_recursor.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2003 - 2010 PowerDNS.COM BV
+ Copyright (C) 2003 - 2013 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 version 2
@@ -26,6 +26,7 @@
#endif // WIN32
#include <boost/foreach.hpp>
+#include "json_ws.hh"
#include <pthread.h>
#include "recpacketcache.hh"
#include "utility.hh"
@@ -35,6 +36,7 @@
#include <map>
#include <set>
#include "recursor_cache.hh"
+#include "cachecleaner.hh"
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
@@ -62,7 +64,7 @@
#include "iputils.hh"
#include "mplexer.hh"
#include "config.h"
-#include "lua-pdns-recursor.hh"
+#include "lua-recursor.hh"
#ifndef RECURSOR
#include "statbag.hh"
@@ -74,8 +76,9 @@
unsigned int g_maxTCPPerClient;
unsigned int g_networkTimeoutMsec;
bool g_logCommonErrors;
-__thread shared_ptr<PowerDNSLua>* t_pdl;
+__thread shared_ptr<RecursorLua>* t_pdl;
__thread RemoteKeeper* t_remotes;
+__thread shared_ptr<Regex>* t_traceRegex;
RecursorControlChannel s_rcc; // only active in thread 0
@@ -99,6 +102,8 @@
RecursorStats g_stats;
bool g_quiet;
+bool g_weDistributeQueries; // if true, only 1 thread listens on the incoming query sockets
+
static __thread NetmaskGroup* t_allowFrom;
static NetmaskGroup* g_initialAllowFrom; // new thread needs to be setup with this
@@ -116,7 +121,7 @@
unsigned int g_numThreads;
-#define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10"
+#define LOCAL_NETS "127.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10, 169.254.0.0/16, 192.168.0.0/16, 172.16.0.0/12, ::1/128, fe80::/10"
//! used to send information to a newborn mthread
struct DNSComboWriter {
@@ -124,7 +129,7 @@
d_tcp(false), d_socket(-1)
{}
MOADNSParser d_mdp;
- void setRemote(ComboAddress* sa)
+ void setRemote(const ComboAddress* sa)
{
d_remote=*sa;
}
@@ -143,6 +148,7 @@
ComboAddress d_remote;
bool d_tcp;
int d_socket;
+ shared_ptr<TCPConnection> d_tcpConnection;
};
@@ -199,7 +205,7 @@
}
vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
-ComboAddress g_local4("0.0.0.0"), g_local6("::");
+const ComboAddress g_local4("0.0.0.0"), g_local6("::");
//! pick a random query local address
ComboAddress getQueryLocalAddress(int family, uint16_t port)
@@ -318,13 +324,15 @@
static int makeClientSocket(int family)
{
int ret=(int)socket(family, SOCK_DGRAM, 0);
+
if(ret < 0 && errno==EMFILE) // this is not a catastrophic error
return ret;
if(ret<0)
- throw AhuException("Making a socket for resolver: "+stringerror());
+ throw AhuException("Making a socket for resolver (family =)"+lexical_cast<string>(family)+"): "+stringerror());
+
+ Utility::setCloseOnExec(ret);
-
int tries=10;
while(--tries) {
uint16_t port;
@@ -436,41 +444,32 @@
string s_pidfname;
static void writePid(void)
{
- ofstream of(s_pidfname.c_str(), ios_base::app);
+ ofstream of(s_pidfname.c_str(), std::ios_base::app);
if(of)
of<< Utility::getpid() <<endl;
else
L<<Logger::Error<<"Requested to write pid for "<<Utility::getpid()<<" to "<<s_pidfname<<" failed: "<<strerror(errno)<<endl;
}
+typedef map<ComboAddress, uint32_t, ComboAddress::addressOnlyLessThan> tcpClientCounts_t;
+tcpClientCounts_t __thread* t_tcpClientCounts;
-map<ComboAddress, uint32_t> g_tcpClientCounts;
+TCPConnection::TCPConnection(int fd, const ComboAddress& addr) : d_remote(addr), d_fd(fd)
+{
+ ++s_currentConnections;
+ (*t_tcpClientCounts)[d_remote]++;
+}
-struct TCPConnection
+TCPConnection::~TCPConnection()
{
- int fd;
- enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state;
- int qlen;
- int bytesread;
- ComboAddress remote;
- char data[65535];
- time_t startTime;
-
- static void closeAndCleanup(int fd, const ComboAddress& remote)
- {
- Utility::closesocket(fd);
- if(!g_tcpClientCounts[remote]--)
- g_tcpClientCounts.erase(remote);
- s_currentConnections--;
- }
- void closeAndCleanup()
- {
- closeAndCleanup(fd, remote);
- }
- static unsigned int s_currentConnections; //!< total number of current TCP connections
-};
+ if(Utility::closesocket(d_fd) < 0)
+ unixDie("closing socket for TCPConnection");
+ if(t_tcpClientCounts->count(d_remote) && !(*t_tcpClientCounts)[d_remote]--)
+ t_tcpClientCounts->erase(d_remote);
+ --s_currentConnections;
+}
-unsigned int TCPConnection::s_currentConnections;
+AtomicCounter TCPConnection::s_currentConnections;
void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var);
void updateRcodeStats(int res)
@@ -491,12 +490,15 @@
void startDoResolve(void *p)
{
DNSComboWriter* dc=(DNSComboWriter *)p;
+ string loginfo="";
try {
- uint16_t maxudpsize=512;
+ loginfo=" (while setting loginfo)";
+ loginfo=" ("+dc->d_mdp.d_qname+"/"+lexical_cast<string>(dc->d_mdp.d_qtype)+" from "+(dc->d_remote.toString())+")";
+ uint32_t maxanswersize= dc->d_tcp ? 65535 : 512;
EDNSOpts edo;
if(getEDNSOpts(dc->d_mdp, &edo)) {
- maxudpsize=max(edo.d_packetsize, (uint16_t)1280);
+ maxanswersize = min(edo.d_packetsize, (uint16_t) (dc->d_tcp ? 65535 : 1680));
}
vector<DNSResourceRecord> ret;
@@ -512,8 +514,14 @@
pw.getHeader()->rd=dc->d_mdp.d_header.rd;
SyncRes sr(dc->d_now);
- if(!g_quiet)
- L<<Logger::Error<<t_id<<" ["<<MT->getTid()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
+ bool tracedQuery=false; // we could consider letting Lua know about this too
+ if(t_traceRegex->get() && (*t_traceRegex)->match(dc->d_mdp.d_qname)) {
+ sr.setLogMode(SyncRes::Store);
+ tracedQuery=true;
+ }
+
+ if(!g_quiet || tracedQuery)
+ L<<Logger::Warning<<t_id<<" ["<<MT->getTid()<<"] " << (dc->d_tcp ? "TCP " : "") << "question for '"<<dc->d_mdp.d_qname<<"|"
<<DNSRecordContent::NumberToType(dc->d_mdp.d_qtype)<<"' from "<<dc->getRemote()<<endl;
sr.setId(MT->getTid());
@@ -522,16 +530,43 @@
int res;
- if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res)) {
+ bool variableAnswer = false;
+ // if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
+ if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
if(t_pdl->get()) {
- if(res == RCode::NXDomain)
- (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res);
+ if(res == RCode::NoError) {
+ vector<DNSResourceRecord>::const_iterator i;
+ for(i=ret.begin(); i!=ret.end(); ++i)
+ if(i->qtype.getCode() == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
+ break;
+ if(i == ret.end())
+ (*t_pdl)->nodata(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
+ }
+ else if(res == RCode::NXDomain)
+ (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
+
+ (*t_pdl)->postresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
+ }
+ }
+
+ uint32_t minTTL=std::numeric_limits<uint32_t>::max();
+
+ if(tracedQuery || res < 0 || res == RCode::ServFail || pw.getHeader()->rcode == RCode::ServFail)
+ {
+ string trace(sr.getTrace());
+ if(!trace.empty()) {
+ vector<string> lines;
+ boost::split(lines, trace, boost::is_any_of("\n"));
+ BOOST_FOREACH(const string& line, lines) {
+ if(!line.empty())
+ L<<Logger::Warning<< line << endl;
+ }
}
}
- uint32_t minTTL=numeric_limits<uint32_t>::max();
- if(res<0) {
+
+ if(res < 0) {
pw.getHeader()->rcode=RCode::ServFail;
// no commit here, because no record
g_stats.servFails++;
@@ -539,9 +574,9 @@
else {
pw.getHeader()->rcode=res;
updateRcodeStats(res);
-
+
if(ret.size()) {
- shuffle(ret);
+ orderAndShuffle(ret);
for(vector<DNSResourceRecord>::const_iterator i=ret.begin(); i!=ret.end(); ++i) {
pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place);
@@ -554,7 +589,7 @@
shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content));
drc->toPacket(pw);
}
- if(!dc->d_tcp && pw.size() > maxudpsize) {
+ if(pw.size() > maxanswersize) {
pw.rollback();
if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer
pw.getHeader()->tc=1;
@@ -568,11 +603,11 @@
sendit:;
if(!dc->d_tcp) {
sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
- if(!SyncRes::s_nopacketcache) {
+ if(!SyncRes::s_nopacketcache && !variableAnswer ) {
t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()), g_now.tv_sec,
min(minTTL,
- pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
- )
+ (pw.getHeader()->rcode == RCode::ServFail) ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
+ )
);
}
}
@@ -602,17 +637,13 @@
if(hadError) {
// no need to remove us from FDM, we weren't there
- TCPConnection::closeAndCleanup(dc->d_socket, dc->d_remote);
+ dc->d_socket = -1;
}
else {
- TCPConnection tc;
- tc.fd=dc->d_socket;
- tc.state=TCPConnection::BYTE0;
- tc.remote=dc->d_remote;
+ dc->d_tcpConnection->state=TCPConnection::BYTE0;
Utility::gettimeofday(&g_now, 0); // needs to be updated
- tc.startTime=g_now.tv_sec;
- t_fdm->addReadFD(tc.fd, handleRunningTCPQuestion, tc);
- t_fdm->setReadTTD(tc.fd, g_now, g_tcpTimeout);
+ t_fdm->addReadFD(dc->d_socket, handleRunningTCPQuestion, dc->d_tcpConnection);
+ t_fdm->setReadTTD(dc->d_socket, g_now, g_tcpTimeout);
}
}
@@ -640,24 +671,33 @@
g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0.0001*newLat);
delete dc;
+ dc=0;
}
catch(AhuException &ae) {
- L<<Logger::Error<<"startDoResolve problem: "<<ae.reason<<endl;
+ L<<Logger::Error<<"startDoResolve problem"<<loginfo<<": "<<ae.reason<<endl;
+ delete dc;
}
catch(MOADNSException& e) {
- L<<Logger::Error<<"DNS parser error: "<<dc->d_mdp.d_qname<<", "<<e.what()<<endl;
+ L<<Logger::Error<<"DNS parser error"<<loginfo<<": "<<dc->d_mdp.d_qname<<", "<<e.what()<<endl;
+ delete dc;
}
catch(std::exception& e) {
- L<<Logger::Error<<"STL error: "<<e.what()<<endl;
+ L<<Logger::Error<<"STL error"<<loginfo<<": "<<e.what()<<endl;
+ delete dc;
}
catch(...) {
- L<<Logger::Error<<"Any other exception in a resolver context"<<endl;
+ L<<Logger::Error<<"Any other exception in a resolver context"<<loginfo<<endl;
}
+
+ g_stats.maxMThreadStackUsage = max(MT->getMaxStackUsage(), g_stats.maxMThreadStackUsage);
}
-void makeControlChannelSocket()
+void makeControlChannelSocket(int processNum=-1)
{
- string sockname=::arg()["socket-dir"]+"/pdns_recursor.controlsocket";
+ string sockname=::arg()["socket-dir"]+"/pdns_recursor";
+ if(processNum >= 0)
+ sockname += "."+lexical_cast<string>(processNum);
+ sockname+=".controlsocket";
s_rcc.listen(sockname);
#ifndef WIN32
@@ -685,10 +725,10 @@
void handleRunningTCPQuestion(int fd, FDMultiplexer::funcparam_t& var)
{
- TCPConnection* conn=any_cast<TCPConnection>(&var);
+ shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(var);
if(conn->state==TCPConnection::BYTE0) {
- int bytes=recv(conn->fd, conn->data, 2, 0);
+ int bytes=recv(conn->getFD(), conn->data, 2, 0);
if(bytes==1)
conn->state=TCPConnection::BYTE1;
if(bytes==2) {
@@ -697,14 +737,12 @@
conn->state=TCPConnection::GETQUESTION;
}
if(!bytes || bytes < 0) {
- TCPConnection tmp(*conn);
t_fdm->removeReadFD(fd);
- tmp.closeAndCleanup();
return;
}
}
else if(conn->state==TCPConnection::BYTE1) {
- int bytes=recv(conn->fd, conn->data+1, 1, 0);
+ int bytes=recv(conn->getFD(), conn->data+1, 1, 0);
if(bytes==1) {
conn->state=TCPConnection::GETQUESTION;
conn->qlen=(((unsigned char)conn->data[0]) << 8)+ (unsigned char)conn->data[1];
@@ -712,53 +750,45 @@
}
if(!bytes || bytes < 0) {
if(g_logCommonErrors)
- L<<Logger::Error<<"TCP client "<< conn->remote.toString() <<" disconnected after first byte"<<endl;
- TCPConnection tmp(*conn);
+ L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected after first byte"<<endl;
t_fdm->removeReadFD(fd);
- tmp.closeAndCleanup(); // conn loses validity here..
return;
}
}
else if(conn->state==TCPConnection::GETQUESTION) {
- int bytes=recv(conn->fd, conn->data + conn->bytesread, conn->qlen - conn->bytesread, 0);
+ int bytes=recv(conn->getFD(), conn->data + conn->bytesread, conn->qlen - conn->bytesread, 0);
if(!bytes || bytes < 0) {
- L<<Logger::Error<<"TCP client "<< conn->remote.toString() <<" disconnected while reading question body"<<endl;
- TCPConnection tmp(*conn);
+ L<<Logger::Error<<"TCP client "<< conn->d_remote.toString() <<" disconnected while reading question body"<<endl;
t_fdm->removeReadFD(fd);
- tmp.closeAndCleanup(); // conn loses validity here..
-
return;
}
conn->bytesread+=bytes;
if(conn->bytesread==conn->qlen) {
- TCPConnection tconn(*conn);
t_fdm->removeReadFD(fd); // should no longer awake ourselves when there is data to read
DNSComboWriter* dc=0;
try {
- dc=new DNSComboWriter(tconn.data, tconn.qlen, g_now);
+ dc=new DNSComboWriter(conn->data, conn->qlen, g_now);
}
catch(MOADNSException &mde) {
g_stats.clientParseError++;
if(g_logCommonErrors)
- L<<Logger::Error<<"Unable to parse packet from TCP client "<< tconn.remote.toString() <<endl;
- tconn.closeAndCleanup();
+ L<<Logger::Error<<"Unable to parse packet from TCP client "<< conn->d_remote.toString() <<endl;
return;
}
-
- dc->setSocket(tconn.fd);
+ dc->d_tcpConnection = conn; // carry the torch
+ dc->setSocket(conn->getFD()); // this is the only time a copy is made of the actual fd
dc->d_tcp=true;
- dc->setRemote(&tconn.remote);
+ dc->setRemote(&conn->d_remote);
if(dc->d_mdp.d_header.qr) {
delete dc;
L<<Logger::Error<<"Ignoring answer on server socket!"<<endl;
- tconn.closeAndCleanup();
return;
}
else {
++g_stats.qcounter;
++g_stats.tcpqcounter;
- MT->makeThread(startDoResolve, dc); // deletes dc
+ MT->makeThread(startDoResolve, dc); // deletes dc, will set state to BYTE0 again
return;
}
}
@@ -787,28 +817,70 @@
Utility::closesocket(newsock);
return;
}
-
- if(g_maxTCPPerClient && g_tcpClientCounts.count(addr) && g_tcpClientCounts[addr] >= g_maxTCPPerClient) {
+ if(g_maxTCPPerClient && t_tcpClientCounts->count(addr) && (*t_tcpClientCounts)[addr] >= g_maxTCPPerClient) {
g_stats.tcpClientOverflow++;
Utility::closesocket(newsock); // don't call TCPConnection::closeAndCleanup here - did not enter it in the counts yet!
return;
}
- g_tcpClientCounts[addr]++;
+
Utility::setNonBlocking(newsock);
- TCPConnection tc;
- tc.fd=newsock;
- tc.state=TCPConnection::BYTE0;
- tc.remote=addr;
- tc.startTime=g_now.tv_sec;
- TCPConnection::s_currentConnections++;
- t_fdm->addReadFD(tc.fd, handleRunningTCPQuestion, tc);
+ shared_ptr<TCPConnection> tc(new TCPConnection(newsock, addr));
+ tc->state=TCPConnection::BYTE0;
+
+ t_fdm->addReadFD(tc->getFD(), handleRunningTCPQuestion, tc);
struct timeval now;
Utility::gettimeofday(&now, 0);
- t_fdm->setReadTTD(tc.fd, now, g_tcpTimeout);
+ t_fdm->setReadTTD(tc->getFD(), now, g_tcpTimeout);
}
}
+string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fromaddr, int fd)
+{
+ ++g_stats.qcounter;
+ if(fromaddr.sin4.sin_family==AF_INET6)
+ g_stats.ipv6qcounter++;
+
+ string response;
+ try {
+ uint32_t age;
+ if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(question, g_now.tv_sec, &response, &age)) {
+ if(!g_quiet)
+ L<<Logger::Error<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl;
+
+ g_stats.packetCacheHits++;
+ SyncRes::s_queries++;
+ ageDNSPacket(response, age);
+ sendto(fd, response.c_str(), response.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen());
+ if(response.length() >= sizeof(struct dnsheader)) {
+ struct dnsheader dh;
+ memcpy(&dh, response.c_str(), sizeof(dh));
+ updateRcodeStats(dh.rcode);
+ }
+ g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0); // we assume 0 usec
+ return 0;
+ }
+ }
+ catch(std::exception& e) {
+ L<<Logger::Error<<"Error processing or aging answer packet: "<<e.what()<<endl;
+ return 0;
+ }
+
+
+ if(MT->numProcesses() > g_maxMThreads) {
+ g_stats.overCapacityDrops++;
+ return 0;
+ }
+
+ DNSComboWriter* dc = new DNSComboWriter(question.c_str(), question.size(), g_now);
+ dc->setSocket(fd);
+ dc->setRemote(&fromaddr);
+
+ dc->d_tcp=false;
+ MT->makeThread(startDoResolve, (void*) dc); // deletes dc
+ return 0;
+}
+
void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
{
int len;
@@ -834,38 +906,11 @@
L<<Logger::Error<<"Ignoring answer from "<<fromaddr.toString()<<" on server socket!"<<endl;
}
else {
- ++g_stats.qcounter;
-
- string response;
- try {
- if(!SyncRes::s_nopacketcache && t_packetCache->getResponsePacket(string(data, len), g_now.tv_sec, &response)) {
- if(!g_quiet)
- L<<Logger::Error<<t_id<< " question answered from packet cache from "<<fromaddr.toString()<<endl;
-
- g_stats.packetCacheHits++;
- SyncRes::s_queries++;
- sendto(fd, response.c_str(), response.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen());
- if(response.length() >= sizeof(struct dnsheader))
- updateRcodeStats(((struct dnsheader*)response.c_str())->rcode);
- g_stats.avgLatencyUsec=(uint64_t)((1-0.0001)*g_stats.avgLatencyUsec + 0); // we assume 0 usec
- return;
- }
- }
- catch(std::exception& e) {
- throw MOADNSException(e.what()); // translate
- }
- if(MT->numProcesses() > g_maxMThreads) {
- g_stats.overCapacityDrops++;
- return;
- }
-
- DNSComboWriter* dc = new DNSComboWriter(data, len, g_now);
- dc->setSocket(fd);
- dc->setRemote(&fromaddr);
-
- dc->d_tcp=false;
-
- MT->makeThread(startDoResolve, (void*) dc); // deletes dc
+ string question(data, len);
+ if(g_weDistributeQueries)
+ distributeAsyncFunction(boost::bind(doProcessUDPQuestion, question, fromaddr, fd));
+ else
+ doProcessUDPQuestion(question, fromaddr, fd);
}
}
catch(MOADNSException& mde) {
@@ -881,6 +926,7 @@
}
}
+
typedef vector<pair<int, function< void(int, any&) > > > deferredAdd_t;
deferredAdd_t deferredAdd;
@@ -904,11 +950,13 @@
sin.sin4.sin_family = AF_INET;
if(!IpToU32(st.host, (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
sin.sin6.sin6_family = AF_INET6;
- if(Utility::inet_pton(AF_INET6, st.host.c_str(), &sin.sin6.sin6_addr) <= 0)
+ if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
throw AhuException("Unable to resolve local address for TCP server on '"+ st.host +"'");
}
fd=socket(sin.sin6.sin6_family, SOCK_STREAM, 0);
+ Utility::setCloseOnExec(fd);
+
if(fd<0)
throw AhuException("Making a TCP server socket for resolver: "+stringerror());
@@ -968,11 +1016,12 @@
sin.sin4.sin_family = AF_INET;
if(!IpToU32(st.host.c_str() , (uint32_t*)&sin.sin4.sin_addr.s_addr)) {
sin.sin6.sin6_family = AF_INET6;
- if(Utility::inet_pton(AF_INET6, st.host.c_str(), &sin.sin6.sin6_addr) <= 0)
+ if(makeIPv6sockaddr(st.host, &sin.sin6) < 0)
throw AhuException("Unable to resolve local address for UDP server on '"+ st.host +"'");
}
int fd=socket(sin.sin4.sin_family, SOCK_DGRAM, 0);
+ Utility::setCloseOnExec(fd);
if(fd < 0) {
throw AhuException("Making a UDP server socket for resolver: "+netstringerror());
@@ -1027,7 +1076,7 @@
void usr2Handler(int)
{
- SyncRes::setLog(true);
+ SyncRes::setDefaultLogMode(SyncRes::Log);
g_quiet=false;
::arg().set("quiet")="no";
@@ -1083,7 +1132,7 @@
struct timeval now;
Utility::gettimeofday(&now, 0);
-// clog<<"* "<<t_id<<" "<<(void*)&last_stat<<"\t"<<(unsigned int)last_stat<<endl;
+ // clog<<"* "<<t_id<<" "<<(void*)&last_stat<<"\t"<<(unsigned int)last_stat<<endl;
if(now.tv_sec - last_prune > (time_t)(5 + t_id)) {
DTime dt;
@@ -1091,11 +1140,7 @@
t_RC->doPrune(); // this function is local to a thread, so fine anyhow
t_packetCache->doPruneTo(::arg().asNum("max-packetcache-entries") / g_numThreads);
- typedef SyncRes::negcache_t::nth_index<1>::type negcache_by_ttd_index_t;
- negcache_by_ttd_index_t& ttdindex=boost::multi_index::get<1>(t_sstorage->negcache);
-
- negcache_by_ttd_index_t::iterator i=ttdindex.lower_bound(now.tv_sec);
- ttdindex.erase(ttdindex.begin(), i);
+ pruneCollection(t_sstorage->negcache, ::arg().asNum("max-cache-entries") / (g_numThreads * 10), 200);
if(!((cleanCounter++)%40)) { // this is a full scan!
time_t limit=now.tv_sec-300;
@@ -1158,6 +1203,12 @@
}
}
+struct ThreadMSG
+{
+ pipefunc_t func;
+ bool wantAnswer;
+};
+
void broadcastFunction(const pipefunc_t& func, bool skipSelf)
{
unsigned int n = 0;
@@ -1168,9 +1219,11 @@
func(); // don't write to ourselves!
continue;
}
-
- pipefunc_t *funcptr = new pipefunc_t(func);
- if(write(tps.writeToThread, &funcptr, sizeof(funcptr)) != sizeof(funcptr))
+
+ ThreadMSG* tmsg = new ThreadMSG();
+ tmsg->func = func;
+ tmsg->wantAnswer = true;
+ if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
unixDie("write to thread pipe returned wrong size or error");
string* resp;
@@ -1183,22 +1236,39 @@
}
}
}
-
-
+void distributeAsyncFunction(const pipefunc_t& func)
+{
+ static unsigned int counter;
+ unsigned int target = 1 + (++counter % (g_pipes.size()-1));
+ // cerr<<"Sending to: "<<target<<endl;
+ if(target == t_id) {
+ func();
+ return;
+ }
+ ThreadPipeSet& tps = g_pipes[target];
+ ThreadMSG* tmsg = new ThreadMSG();
+ tmsg->func = func;
+ tmsg->wantAnswer = false;
+
+ if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
+ unixDie("write to thread pipe returned wrong size or error");
+
+}
void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
{
- pipefunc_t* func;
- if(read(fd, &func, sizeof(func)) != sizeof(func)) { // fd == readToThread
+ ThreadMSG* tmsg;
+
+ if(read(fd, &tmsg, sizeof(tmsg)) != sizeof(tmsg)) { // fd == readToThread
unixDie("read from thread pipe returned wrong size or error");
}
- void *resp = (*func)();
-
- if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
- unixDie("write to thread pipe returned wrong size or error");
+ void *resp = tmsg->func();
+ if(tmsg->wantAnswer)
+ if(write(g_pipes[t_id].writeFromThread, &resp, sizeof(resp)) != sizeof(resp))
+ unixDie("write to thread pipe returned wrong size or error");
- delete func;
+ delete tmsg;
}
template<class T> void *voider(const boost::function<T*()>& func)
@@ -1212,8 +1282,6 @@
return a;
}
-
-
template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf)
{
unsigned int n = 0;
@@ -1232,9 +1300,13 @@
continue;
}
- pipefunc_t *funcptr = new pipefunc_t(boost::bind(voider<T>, func));
- if(write(tps.writeToThread, &funcptr, sizeof(funcptr)) != sizeof(funcptr))
+ ThreadMSG* tmsg = new ThreadMSG();
+ tmsg->func = boost::bind(voider<T>, func);
+ tmsg->wantAnswer = true;
+
+ if(write(tps.writeToThread, &tmsg, sizeof(tmsg)) != sizeof(tmsg))
unixDie("write to thread pipe returned wrong size or error");
+
T* resp;
if(read(tps.readFromThread, &resp, sizeof(resp)) != sizeof(resp))
@@ -1259,6 +1331,7 @@
string msg=s_rcc.recv(&remote);
RecursorControlParser rcp;
RecursorControlParser::func_t* command;
+
string answer=rcp.getAnswer(msg, &command);
try {
s_rcc.send(answer, &remote);
@@ -1355,7 +1428,7 @@
else {
g_stats.serverParseError++;
if(g_logCommonErrors)
- L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< sockAddrToString((struct sockaddr_in*) &fromaddr) <<
+ L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< fromaddr.toString() <<
": packet smalller than DNS header"<<endl;
}
@@ -1373,63 +1446,65 @@
dnsheader dh;
memcpy(&dh, data, sizeof(dh));
- if(dh.qr) {
- PacketID pident;
- pident.remote=fromaddr;
- pident.id=dh.id;
- pident.fd=fd;
- if(!dh.qdcount) { // UPC, Nominum, very old BIND on FormErr, NSD
- pident.domain.clear();
- pident.type = 0;
+ PacketID pident;
+ pident.remote=fromaddr;
+ pident.id=dh.id;
+ pident.fd=fd;
+
+ if(!dh.qr) {
+ L<<Logger::Warning<<"Not taking data from question on outgoing socket from "<< fromaddr.toStringWithPort() <<endl;
+ }
+
+ if(!dh.qdcount || // UPC, Nominum, very old BIND on FormErr, NSD
+ !dh.qr) { // one weird server
+ pident.domain.clear();
+ pident.type = 0;
+ }
+ else {
+ try {
+ pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
}
- else {
- try {
- pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
- }
- catch(std::exception& e) {
- g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
- L<<Logger::Warning<<"Error in packet from "<<sockAddrToString((struct sockaddr_in*) &fromaddr) << ": "<<e.what() << endl;
- return;
- }
+ catch(std::exception& e) {
+ g_stats.serverParseError++; // won't be fed to lwres.cc, so we have to increment
+ L<<Logger::Warning<<"Error in packet from "<< fromaddr.toStringWithPort() << ": "<<e.what() << endl;
+ return;
}
- string packet;
- packet.assign(data, len);
+ }
+ string packet;
+ packet.assign(data, len);
- MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
- if(iter != MT->d_waiters.end()) {
- doResends(iter, pident, packet);
- }
+ MT_t::waiters_t::iterator iter=MT->d_waiters.find(pident);
+ if(iter != MT->d_waiters.end()) {
+ doResends(iter, pident, packet);
+ }
- retryWithName:
+retryWithName:
- if(!MT->sendEvent(pident, &packet)) {
-
- // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
- for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
- if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
- pdns_iequals(pident.domain, mthread->key.domain)) {
- mthread->key.nearMisses++;
- }
+ if(!MT->sendEvent(pident, &packet)) {
+ // we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
+ for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
+ if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
+ pdns_iequals(pident.domain, mthread->key.domain)) {
+ mthread->key.nearMisses++;
+ }
- // be a bit paranoid here since we're weakening our matching
- if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
- pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
- // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
- pident.domain = mthread->key.domain;
- pident.type = mthread->key.type;
- goto retryWithName;
- }
+ // be a bit paranoid here since we're weakening our matching
+ if(pident.domain.empty() && !mthread->key.domain.empty() && !pident.type && mthread->key.type &&
+ pident.id == mthread->key.id && mthread->key.remote == pident.remote) {
+ // cerr<<"Empty response, rest matches though, sending to a waiter"<<endl;
+ pident.domain = mthread->key.domain;
+ pident.type = mthread->key.type;
+ goto retryWithName; // note that this only passes on an error, lwres will still reject the packet
}
- g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
- if(g_logCommonErrors)
- L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toString()<<": "<<pident.domain<<", "<<pident.type<<endl;
}
- else if(fd >= 0) {
- t_udpclientsocks->returnSocket(fd);
+ g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
+ if(g_logCommonErrors) {
+ L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<", "<<MT->d_waiters.size()<<" waiters"<<endl;
}
}
- else
- L<<Logger::Warning<<"Ignoring question on outgoing socket from "<< sockAddrToString((struct sockaddr_in*) &fromaddr) <<endl;
+ else if(fd >= 0) {
+ t_udpclientsocks->returnSocket(fd);
+ }
}
FDMultiplexer* getMultiplexer()
@@ -1453,24 +1528,26 @@
}
-void* doReloadLuaScript()
+string* doReloadLuaScript()
{
string fname= ::arg()["lua-dns-script"];
try {
if(fname.empty()) {
t_pdl->reset();
L<<Logger::Error<<t_id<<" Unloaded current lua script"<<endl;
+ return new string("unloaded\n");
}
else {
- *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname));
+ *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(fname));
}
}
catch(std::exception& e) {
L<<Logger::Error<<t_id<<" Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
+ return new string("retaining current script, error from '"+fname+"': "+e.what()+"\n");
}
L<<Logger::Warning<<t_id<<" (Re)loaded lua script from '"<<fname<<"'"<<endl;
- return 0;
+ return new string("(re)loaded '"+fname+"'\n");
}
string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
@@ -1478,11 +1555,32 @@
if(begin != end)
::arg().set("lua-dns-script") = *begin;
- broadcastFunction(doReloadLuaScript);
-
- return "ok, reload/unload queued\n";
+ return broadcastAccFunction<string>(doReloadLuaScript);
}
+string* pleaseUseNewTraceRegex(const std::string& newRegex)
+try
+{
+ if(newRegex.empty()) {
+ t_traceRegex->reset();
+ return new string("unset\n");
+ }
+ else {
+ (*t_traceRegex) = shared_ptr<Regex>(new Regex(newRegex));
+ return new string("ok\n");
+ }
+}
+catch(AhuException& ae)
+{
+ return new string(ae.reason+"\n");
+}
+
+string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end)
+{
+ return broadcastAccFunction<string>(boost::bind(pleaseUseNewTraceRegex, begin!=end ? *begin : ""));
+}
+
+
void* recursorThread(void*);
void* pleaseSupplantACLs(NetmaskGroup *ng)
@@ -1491,6 +1589,9 @@
return 0;
}
+int g_argc;
+char** g_argv;
+
void parseACLs()
{
static bool l_initialized;
@@ -1501,8 +1602,9 @@
if(!::arg().preParseFile(configname.c_str(), "allow-from-file"))
L<<Logger::Warning<<"Unable to re-parse configuration file '"<<configname<<"'"<<endl;
-
+ ::arg().preParse(g_argc, g_argv, "allow-from-file");
::arg().preParseFile(configname.c_str(), "allow-from", LOCAL_NETS);
+ ::arg().preParse(g_argc, g_argv, "allow-from");
}
NetmaskGroup* oldAllowFrom = t_allowFrom, *allowFrom=new NetmaskGroup;
@@ -1531,6 +1633,7 @@
else if(!::arg()["allow-from"].empty()) {
vector<string> ips;
stringtok(ips, ::arg()["allow-from"], ", ");
+
L<<Logger::Warning<<"Only allowing queries from: ";
for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
allowFrom->addMask(*i);
@@ -1561,14 +1664,14 @@
L.setLoglevel((Logger::Urgency)(6)); // info and up
if(!::arg()["logging-facility"].empty()) {
- boost::optional<int> val=logFacilityToLOG(::arg().asNum("logging-facility") );
- if(val)
- theL().setFacility(*val);
+ int val=logFacilityToLOG(::arg().asNum("logging-facility") );
+ if(val >= 0)
+ theL().setFacility(val);
else
L<<Logger::Error<<"Unknown logging facility "<<::arg().asNum("logging-facility") <<endl;
}
- L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2010 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
+ L<<Logger::Warning<<"PowerDNS recursor "<<VERSION<<" (C) 2001-2013 PowerDNS.COM BV ("<<__DATE__", "__TIME__;
#ifdef __GNUC__
L<<", gcc "__VERSION__;
#endif // add other compilers here
@@ -1598,6 +1701,9 @@
g_dontQuery=new NetmaskGroup;
vector<string> ips;
stringtok(ips, ::arg()["dont-query"], ", ");
+ ips.push_back("0.0.0.0");
+ ips.push_back("::");
+
L<<Logger::Warning<<"Will not send queries to: ";
for(vector<string>::const_iterator i = ips.begin(); i!= ips.end(); ++i) {
g_dontQuery->addMask(*i);
@@ -1609,23 +1715,35 @@
}
g_quiet=::arg().mustDo("quiet");
- if(::arg().mustDo("trace")) {
- SyncRes::setLog(true);
+ g_weDistributeQueries = ::arg().mustDo("pdns-distributes-queries");
+ if(g_weDistributeQueries) {
+ L<<Logger::Warning<<"PowerDNS Recursor itself will distribute queries over threads"<<endl;
+ }
+
+ if(::arg()["trace"]=="fail") {
+ SyncRes::setDefaultLogMode(SyncRes::Store);
+ }
+ else if(::arg().mustDo("trace")) {
+ SyncRes::setDefaultLogMode(SyncRes::Log);
::arg().set("quiet")="no";
g_quiet=false;
}
+
try {
vector<string> addrs;
if(!::arg()["query-local-address6"].empty()) {
SyncRes::s_doIPv6=true;
- L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl;
+ L<<Logger::Warning<<"Enabling IPv6 transport for outgoing queries"<<endl;
stringtok(addrs, ::arg()["query-local-address6"], ", ;");
BOOST_FOREACH(const string& addr, addrs) {
g_localQueryAddresses6.push_back(ComboAddress(addr));
}
}
+ else {
+ L<<Logger::Warning<<"NOT using IPv6 for outgoing queries - set 'query-local-address6=::' to enable"<<endl;
+ }
addrs.clear();
stringtok(addrs, ::arg()["query-local-address"], ", ;");
BOOST_FOREACH(const string& addr, addrs) {
@@ -1636,6 +1754,9 @@
L<<Logger::Error<<"Assigning local query addresses: "<<e.what();
exit(99);
}
+
+ SyncRes::s_doAAAAAdditionalProcessing = ::arg().mustDo("aaaa-additional-processing");
+ SyncRes::s_doAdditionalProcessing = ::arg().mustDo("additional-processing") | SyncRes::s_doAAAAAdditionalProcessing;
SyncRes::s_noEDNSPing = ::arg().mustDo("disable-edns-ping");
SyncRes::s_noEDNS = ::arg().mustDo("disable-edns");
@@ -1663,6 +1784,12 @@
makeUDPServerSockets();
makeTCPServerSockets();
+ int forks;
+ for(forks = 0; forks < ::arg().asNum("processes") - 1; ++forks) {
+ if(!fork()) // we are child
+ break;
+ }
+
s_pidfname=::arg()["socket-dir"]+"/"+s_programname+".pid";
if(!s_pidfname.empty())
unlink(s_pidfname.c_str()); // remove possible old pid file
@@ -1678,7 +1805,7 @@
signal(SIGPIPE,SIG_IGN);
writePid();
#endif
- makeControlChannelSocket();
+ makeControlChannelSocket( ::arg().asNum("processes") > 1 ? forks : -1);
int newgid=0;
if(!::arg()["setgid"].empty())
@@ -1687,7 +1814,6 @@
if(!::arg()["setuid"].empty())
newuid=Utility::makeUidNumeric(::arg()["setuid"]);
-#ifndef WIN32
if (!::arg()["chroot"].empty()) {
if (chroot(::arg()["chroot"].c_str())<0 || chdir("/") < 0) {
L<<Logger::Error<<"Unable to chroot to '"+::arg()["chroot"]+"': "<<strerror (errno)<<", exiting"<<endl;
@@ -1696,9 +1822,7 @@
}
Utility::dropPrivs(newuid, newgid);
-
-
- g_numThreads = ::arg().asNum("threads");
+ g_numThreads = ::arg().asNum("threads") + ::arg().mustDo("pdns-distributes-queries");
makeThreadPipes();
@@ -1714,7 +1838,7 @@
pthread_t tid;
L<<Logger::Warning<<"Launching "<< g_numThreads <<" threads"<<endl;
for(unsigned int n=0; n < g_numThreads; ++n) {
- pthread_create(&tid, 0, recursorThread, (void*)n);
+ pthread_create(&tid, 0, recursorThread, (void*)(long)n);
}
void* res;
@@ -1732,18 +1856,18 @@
t_sstorage->domainmap = g_initialDomainMap;
t_allowFrom = g_initialAllowFrom;
t_udpclientsocks = new UDPClientSocks();
+ t_tcpClientCounts = new tcpClientCounts_t();
primeHints();
t_packetCache = new RecursorPacketCache();
L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
- t_RC->d_followRFC2181=::arg().mustDo("auth-can-lower-ttl");
- t_pdl = new shared_ptr<PowerDNSLua>();
+ t_pdl = new shared_ptr<RecursorLua>();
try {
if(!::arg()["lua-dns-script"].empty()) {
- *t_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(::arg()["lua-dns-script"]));
+ *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(::arg()["lua-dns-script"]));
L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
}
@@ -1753,6 +1877,9 @@
exit(99);
}
+ t_traceRegex = new shared_ptr<Regex>();
+
+
t_remotes = new RemoteKeeper();
t_remotes->remotes.resize(::arg().asNum("remotes-ringbuffer-entries") / g_numThreads);
@@ -1765,20 +1892,24 @@
PacketID pident;
t_fdm=getMultiplexer();
- if(!t_id)
+ if(!t_id) {
+ if(::arg().mustDo("experimental-json-interface")) {
+ L<<Logger::Warning << "Enabling JSON interface" << endl;
+ new JWebserver(t_fdm);
+ }
L<<Logger::Error<<"Enabled '"<< t_fdm->getName() << "' multiplexer"<<endl;
+ }
t_fdm->addReadFD(g_pipes[t_id].readToThread, handlePipeRequest);
- for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)
- t_fdm->addReadFD(i->first, i->second);
+ if(!g_weDistributeQueries || !t_id) // if we distribute queries, only t_id = 0 listens
+ for(deferredAdd_t::const_iterator i=deferredAdd.begin(); i!=deferredAdd.end(); ++i)
+ t_fdm->addReadFD(i->first, i->second);
if(!t_id) {
-
t_fdm->addReadFD(s_rcc.d_fd, handleRCC); // control channel
}
-#endif
-
+
unsigned int maxTcpClients=::arg().asNum("max-tcp-clients");
bool listenOnTCP(true);
@@ -1796,11 +1927,10 @@
expired_t expired=t_fdm->getTimeouts(g_now);
for(expired_t::iterator i=expired.begin() ; i != expired.end(); ++i) {
- TCPConnection conn=any_cast<TCPConnection>(i->second);
+ shared_ptr<TCPConnection> conn=any_cast<shared_ptr<TCPConnection> >(i->second);
if(g_logCommonErrors)
- L<<Logger::Warning<<"Timeout from remote TCP client "<< conn.remote.toString() <<endl;
+ L<<Logger::Warning<<"Timeout from remote TCP client "<< conn->d_remote.toString() <<endl;
t_fdm->removeReadFD(i->first);
- conn.closeAndCleanup();
}
}
@@ -1815,14 +1945,14 @@
// 'run' updates g_now for us
if(listenOnTCP) {
- if(TCPConnection::s_currentConnections > maxTcpClients) { // shutdown, too many connections
+ if(TCPConnection::getCurrentConnections() > maxTcpClients) { // shutdown, too many connections
for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
t_fdm->removeReadFD(*i);
listenOnTCP=false;
}
}
else {
- if(TCPConnection::s_currentConnections <= maxTcpClients) { // reenable
+ if(TCPConnection::getCurrentConnections() <= maxTcpClients) { // reenable
for(tcpListenSockets_t::iterator i=g_tcpListenSockets.begin(); i != g_tcpListenSockets.end(); ++i)
t_fdm->addReadFD(*i, handleNewTCPQuestion);
listenOnTCP=true;
@@ -1865,8 +1995,11 @@
int main(int argc, char **argv)
{
+ g_argc = argc;
+ g_argv = argv;
g_stats.startupTime=time(0);
reportBasicTypes();
+ reportOtherTypes();
int ret = EXIT_SUCCESS;
#ifdef WIN32
@@ -1883,10 +2016,11 @@
::arg().set("soa-minimum-ttl","Don't change")="0";
::arg().set("soa-serial-offset","Don't change")="0";
::arg().set("no-shuffle","Don't change")="off";
+ ::arg().set("additional-processing","turn on to do additional processing")="off";
::arg().set("aaaa-additional-processing","turn on to do AAAA additional processing (slow)")="off";
::arg().set("local-port","port to listen on")="53";
::arg().set("local-address","IP addresses to listen on, separated by spaces or commas. Also accepts ports.")="127.0.0.1";
- ::arg().set("trace","if we should output heaps of logging")="off";
+ ::arg().set("trace","if we should output heaps of logging. set to 'fail' to only log failing domains")="off";
::arg().set("daemon","Operate as a daemon")="yes";
::arg().set("log-common-errors","If we should log rather common errors")="yes";
::arg().set("chroot","switch to chroot jail")="";
@@ -1894,6 +2028,7 @@
::arg().set("setuid","If set, change user id to this uid for more security")="";
::arg().set("network-timeout", "Wait this nummer of milliseconds for network i/o")="1500";
::arg().set("threads", "Launch this number of threads")="2";
+ ::arg().set("processes", "Launch this number of processes (EXPERIMENTAL, DO NOT CHANGE)")="1";
#ifdef WIN32
::arg().set("quiet","Suppress logging of questions and answers")="off";
::arg().setSwitch( "register-service", "Register the service" )= "no";
@@ -1901,8 +2036,9 @@
::arg().setSwitch( "ntservice", "Run as service" )= "no";
::arg().setSwitch( "use-ntlog", "Use the NT logging facilities" )= "yes";
::arg().setSwitch( "use-logfile", "Use a log file" )= "no";
- ::arg().setSwitch( "logfile", "Filename of the log file" )= "recursor.log";
#else
+ ::arg().set( "experimental-logfile", "Filename of the log file for JSON parser" )= "/var/log/pdns.log";
+ ::arg().setSwitch( "experimental-json-interface", "If we should run a JSON webserver") = "no";
::arg().set("quiet","Suppress logging of questions and answers")="";
::arg().set("logging-facility","Facility to log messages as. 0 corresponds to local0")="";
#endif
@@ -1916,7 +2052,7 @@
::arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
::arg().set("delegation-only","Which domains we only accept delegations from")="";
::arg().set("query-local-address","Source IP address for sending queries")="0.0.0.0";
- ::arg().set("query-local-address6","Source IPv6 address for sending queries")="";
+ ::arg().set("query-local-address6","Source IPv6 address for sending queries. IF UNSET, IPv6 WILL NOT BE USED FOR OUTGOING QUERIES")="";
::arg().set("client-tcp-timeout","Timeout in seconds when talking to TCP clients")="2";
::arg().set("max-mthreads", "Maximum number of simultaneous Mtasker threads")="2048";
::arg().set("max-tcp-clients","Maximum number of simultaneous TCP clients")="128";
@@ -1929,7 +2065,7 @@
::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache")="60";
::arg().set("server-id", "Returned when queried for 'server.id' TXT or NSID, defaults to hostname")="";
::arg().set("remotes-ringbuffer-entries", "maximum number of packets to store statistics for")="0";
- ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Recursor "VERSION" $Id: pdns_recursor.cc 1538 2010-03-06 11:39:03Z ahu $";
+ ::arg().set("version-string", "string reported on version.pdns or version.bind")="PowerDNS Recursor "VERSION" $Id$";
::arg().set("allow-from", "If set, only allow these comma separated netmasks to recurse")=LOCAL_NETS;
::arg().set("allow-from-file", "If set, load allowed netmasks from this file")="";
::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
@@ -1942,14 +2078,16 @@
::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
::arg().set("forward-zones-file", "File with (+)domain=ip pairs for forwarding")="";
::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
+ ::arg().set("export-etc-hosts-search-suffix", "Also serve up the contents of /etc/hosts with this suffix")="";
::arg().set("etc-hosts-file", "Path to 'hosts' file")="/etc/hosts";
::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="";
- ::arg().set("auth-can-lower-ttl", "If we follow RFC 2181 to the letter, an authoritative server can lower the TTL of NS records")="off";
::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
- ::arg().setSwitch( "ignore-rd-bit", "Assume each packet requires recursion, for compatability" )= "off";
+ ::arg().setSwitch( "ignore-rd-bit", "Assume each packet requires recursion, for compatibility" )= "off";
::arg().setSwitch( "disable-edns-ping", "Disable EDNSPing" )= "no";
::arg().setSwitch( "disable-edns", "Disable EDNS" )= "";
- ::arg().setSwitch( "disable-packetcache", "Disable packetcahe" )= "no";
+ ::arg().setSwitch( "disable-packetcache", "Disable packetcache" )= "no";
+ ::arg().setSwitch( "pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads (EXPERIMENTAL)")="no";
+
::arg().setCmd("help","Provide a helpful message");
::arg().setCmd("version","Print version string ("VERSION")");
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/portsmplexer.cc
^
|
@@ -12,7 +12,7 @@
#include "syncres.hh"
#include "namespaces.hh"
-using namespace std;
+#include "namespaces.hh"
class PortsFDMultiplexer : public FDMultiplexer
{
@@ -88,8 +88,6 @@
timeout.tv_sec=0; timeout.tv_nsec=500000000;
unsigned int numevents=1;
int ret= port_getn(d_portfd, d_pevents.get(), min(PORT_MAX_LIST, s_maxevents), &numevents, &timeout);
-
- gettimeofday(now,0);
/* port_getn has an unusual API - (ret == -1, errno == ETIME) can
mean partial success; you must check (*numevents) in this case
@@ -97,13 +95,14 @@
events from that object again. We don't care about pure timeouts
(ret == -1, errno == ETIME, *numevents == 0) so we don't bother
with that case. */
- if(ret < 0 && errno!=ETIME) {
+ if(ret == -1 && errno!=ETIME) {
if(errno!=EINTR)
throw FDMultiplexerException("completion port_getn returned error: "+stringerror());
// EINTR is not really an error
+ gettimeofday(now,0);
return 0;
}
-
+ gettimeofday(now,0);
if(!numevents) // nothing
return 0;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/powerdns-example-script.lua
^
|
@@ -1,6 +1,14 @@
function preresolve ( remoteip, domain, qtype )
print ("prequery handler called for: ", remoteip, getlocaladdress(), domain, qtype)
pdnslog("a test message.. received query from "..remoteip.." on "..getlocaladdress());
+
+ if domain == "www.donotcache.org."
+ then
+ print("making sure www.donotcache.org will never end up in the cache")
+ setvariable()
+ return -1, {}
+ end
+
if domain == "www.powerdns.org."
then
ret={}
@@ -30,6 +38,7 @@
if qtype ~= pdns.A then return -1, {} end -- only A records
if not string.find(domain, "^www%.") then return -1, {} end -- only things that start with www.
+ setvariable()
if matchnetmask(remoteip, {"127.0.0.1/32", "10.1.0.0/16"})
then
print "dealing"
@@ -44,3 +53,68 @@
return -1, ret
end
end
+
+function axfrfilter(remoteip, zone, qname, qtype, ttl, priority, content)
+ if qtype ~= pdns.SOA or zone ~= "secured-by-gost.org"
+ then
+ ret = {}
+ return -1, ret
+ end
+
+ print "got soa!"
+ ret={}
+ ret[1]={qname=qname, qtype=qtype, content=content, ttl=ttl}
+ ret[2]={qname=qname, qtype=pdns.TXT, content=os.date("Retrieved at %Y-%m-%d %H:%M"), ttl=ttl}
+ return 0, ret
+end
+
+function nodata ( remoteip, domain, qtype, records )
+ print ("nodata called for: ", remoteip, getlocaladdress(), domain, qtype)
+ if qtype ~= pdns.AAAA then return -1, {} end -- only AAAA records
+
+ setvariable()
+ return "getFakeAAAARecords", domain, "fe80::21b:77ff:0:0"
+end
+
+-- records contains the entire packet, ready for your modifying pleasure
+function postresolve ( remoteip, domain, qtype, records, origrcode )
+ print ("postresolve called for: ", remoteip, getlocaladdress(), domain, qtype, origrcode)
+
+ for key,val in ipairs(records)
+ do
+ if(val.content == '173.201.188.46' and val.qtype == pdns.A)
+ then
+ val.content = '127.0.0.1'
+ setvariable()
+ end
+ if val.qtype == pdns.A and matchnetmask(remoteip, "192.168.0.0/16") and matchnetmask(val.content, "85.17.219.0/24")
+ then
+ val.content = string.gsub(val.content, "^85.17.219.", "192.168.219.", 1)
+ setvariable()
+ end
+
+ -- print(val.content)
+ end
+ return origrcode, records
+end
+
+function prequery ( dnspacket )
+ -- pdnslog ("prequery called for ".. tostring(dnspacket) )
+ qname, qtype = dnspacket:getQuestion()
+ pdnslog ("q: ".. qname.." "..qtype)
+ if qtype == pdns.A and qname == "www.domain.com"
+ then
+ pdnslog ("calling dnspacket:setRcode")
+ dnspacket:setRcode(pdns.NXDOMAIN)
+ pdnslog ("called dnspacket:setRcode")
+ pdnslog ("adding records")
+ ret = {}
+ ret[1] = {qname=qname, qtype=qtype, content="1.2.3.4", place=2}
+ ret[2] = {qname=qname, qtype=pdns.TXT, content=os.date("Retrieved at %Y-%m-%d %H:%M"), ttl=ttl}
+ dnspacket:addRecords(ret)
+ pdnslog ("returning true")
+ return true
+ end
+ pdnslog ("returning false")
+ return false
+end
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/qtype.cc
^
|
@@ -25,59 +25,17 @@
#include <sstream>
#include "qtype.hh"
#include "misc.hh"
+#include "lock.hh"
-bool QType::uninit=true;
vector<QType::namenum> QType::names;
-
-void QType::insert(const char *p, int n)
-{
- names.push_back(make_pair(string(p),n));
-}
-
+// XXX FIXME we need to do something with initializer order here!
+QType::init QType::initializer;
QType::QType()
{
- if(uninit)
- {
- uninit=false;
- insert("A",1);
- insert("NS",2);
- insert("CNAME",5);
- insert("SOA",6);
- insert("MR",9);
- insert("PTR",12);
- insert("HINFO",13);
- insert("MX",15);
- insert("TXT",16);
- insert("RP",17);
- insert("AFSDB", 18);
- insert("SIG",24);
- insert("KEY",25);
- insert("AAAA",28);
- insert("LOC",29);
- insert("SRV",33);
- insert("CERT", 37);
- insert("A6",38);
- insert("NAPTR",35);
- insert("DS", 43);
- insert("SSHFP", 44);
- insert("RRSIG", 46);
- insert("NSEC", 47);
- insert("DNSKEY", 48);
- insert("NSEC3", 50);
- insert("NSEC3PARAM", 51);
- insert("SPF",99);
- insert("IXFR",251);
- insert("AXFR",252);
- insert("ANY",255);
- insert("URL",256);
- insert("MBOXFW",257);
- insert("CURL",258);
- insert("ADDR",259);
- }
}
-int QType::getCode() const
+uint16_t QType::getCode() const
{
return code;
}
@@ -89,10 +47,10 @@
if(pos->second==code)
return pos->first;
- return "#"+itoa(code);
+ return "TYPE"+itoa(code);
}
-QType &QType::operator=(int n)
+QType &QType::operator=(uint16_t n)
{
code=n;
return *this;
@@ -102,10 +60,17 @@
{
static QType qt;
vector<namenum>::iterator pos;
- for(pos=names.begin();pos<names.end();++pos)
- if(pos->first==p)
+ for(pos=names.begin(); pos < names.end(); ++pos)
+ if(pos->first == p)
return pos->second;
+
+ if(*p=='#') {
+ return atoi(p+1);
+ }
+ if(boost::starts_with(p, "TYPE"))
+ return atoi(p+4);
+
return 0;
}
@@ -127,108 +92,8 @@
}
-QType::QType(int n)
+QType::QType(uint16_t n)
{
QType();
code=n;
}
-
-QType::QType(const char *p)
-{
- QType();
- code=chartocode(p);
-}
-
-string DNSResourceRecord::serialize() const
-{
- ostringstream ostr;
- ostr<<escape(qname)<<"|"<<qtype.getName()<<"|"<<escape(content)<<"|"<<ttl<<"|"<<priority<<"|"<<domain_id
- <<"|"<<last_modified;
- return ostr.str();
-}
-
-string DNSResourceRecord::escape(const string &name) const
-{
- string a;
-
- for(string::const_iterator i=name.begin();i!=name.end();++i)
- if(*i=='|' || *i=='\\'){
- a+='\\';
- a+=*i;
- }
- else
- a+=*i;
-
- return a;
-}
-
-int DNSResourceRecord::unSerialize(const string &source)
-{
- // qname|qtype|content|ttl|priority|domain_id|last_modified;
- string chunk;
- unsigned int m=0;
- for(int n=0;n<7;++n) {
- chunk="";
- for(;m<source.size();++m) {
- if(source[m]=='\\' && m+1<source.size())
- chunk.append(1,source[++m]);
- else if(source[m]=='|') {
- ++m;
- break;
- }
- else
- chunk.append(1,source[m]);
- }
- switch(n) {
- case 0:
- qname=chunk;
- break;
- case 1:
- qtype=chunk;
- break;
- case 2:
- content=chunk;
- break;
- case 3:
- ttl=atoi(chunk.c_str());
- break;
- case 4:
- priority=atoi(chunk.c_str());
- break;
- case 5:
- domain_id=atoi(chunk.c_str());
- break;
- case 6:
- last_modified=atoi(chunk.c_str());
- break;
- }
- }
- return m;
-}
-
-
-#if 0
-int main(int argc, char **argv)
-{
- QType t;
-
- cout << endl;
- cout << "Assiging a '6'" << endl;
- t=6;
- cout << "Code is now " << t.getCode() << endl;
- cout << "Name is now " << t.getName() << endl;
-
- cout << endl;
-
- cout << "Assiging a 'CNAME'" << endl;
- t="CNAME";
- cout << "Code is now " << t.getCode() << endl;
- cout << "Name is now " << t.getName() << endl;
-
- QType u;
- u="SOA";
- cout << u.getCode() << endl;
-
-
-}
-#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/qtype.hh
^
|
@@ -19,15 +19,14 @@
#ifndef QTYPE_HH
#define QTYPE_HH
/* (C) 2002 POWERDNS.COM BV */
-// $Id: qtype.hh 1472 2009-12-24 16:57:03Z ahu $
+// $Id$
#include <string>
#include <vector>
#include <utility>
-
-using namespace std;
+#include "namespaces.hh"
/** The QType class is meant to deal easily with the different kind of resource types, like 'A', 'NS',
- * 'CNAME' etcetera. These types have both a name and a number. This class can seemlessly move between
+ * 'CNAME' etcetera. These types have both a name and a number. This class can seamlessly move between
* them. Use it like this:
\code
@@ -46,12 +45,11 @@
{
public:
QType(); //!< Naked constructor
- explicit QType(int); //!< convert from an integer to a QType
- QType(const char *p); //!< convert from a char* to a QType
+ explicit QType(uint16_t); //!< convert from an integer to a QType
QType(const QType& orig) : code(orig.code)
{
}
- QType &operator=(int); //!< Assigns integers to us
+ QType &operator=(uint16_t); //!< Assigns integers to us
QType &operator=(const char *); //!< Assings strings to us
QType &operator=(const string &); //!< Assings strings to us
QType &operator=(const QType&rhs) //!< Assings strings to us
@@ -65,26 +63,80 @@
return code < rhs.code;
}
+ template<class Archive>
+ void serialize(Archive &ar, const unsigned int version)
+ {
+ ar & code;
+ }
+
bool operator==(const QType &) const; //!< equality operator
const string getName() const; //!< Get a string representation of this type
- int getCode() const; //!< Get the integer representation of this type
+ uint16_t getCode() const; //!< Get the integer representation of this type
static int chartocode(const char *p); //!< convert a character string to a code
// more solaris fun
#undef DS
enum typeenum {A=1,NS=2,CNAME=5,SOA=6, MR=9, PTR=12,HINFO=13,MX=15,TXT=16,RP=17,AFSDB=18,KEY=25,AAAA=28,LOC=29,SRV=33,NAPTR=35, KX=36,
- CERT=37,OPT=41, DS=43, SSHDP=44, IPSECKEY=45, RRSIG=46, NSEC=47, DNSKEY=48, DHCID=49,
- SPF=99, TSIG=250, AXFR=252, IXFR=251, ANY=255, URL=256, MBOXFW=257, CURL=258, ADDR=259} types;
- typedef pair<string,int> namenum;
+ CERT=37,OPT=41, DS=43, SSHFP=44, IPSECKEY=45, RRSIG=46, NSEC=47, DNSKEY=48, DHCID=49, NSEC3=50, NSEC3PARAM=51,
+ TLSA=52, SPF=99, TSIG=250, AXFR=252, IXFR=251, ANY=255, URL=256, MBOXFW=257, CURL=258, ADDR=259, DLV=32769} types;
+ typedef pair<string,uint16_t> namenum;
static vector<namenum> names;
-private:
- short int code;
- void insert(const char *p, int n);
+private:
+ static class init {
+ public:
+ void qtype_insert(const char* a, uint16_t num)
+ {
+ names.push_back(make_pair(string(a), num));
+ }
+
+ init()
+ {
+ qtype_insert("A",1);
+ qtype_insert("NS",2);
+ qtype_insert("CNAME",5);
+ qtype_insert("SOA",6);
+ qtype_insert("MR",9);
+ qtype_insert("PTR",12);
+ qtype_insert("HINFO",13);
+ qtype_insert("MX",15);
+ qtype_insert("TXT",16);
+ qtype_insert("RP",17);
+ qtype_insert("AFSDB", 18);
+ qtype_insert("SIG",24);
+ qtype_insert("KEY",25);
+ qtype_insert("AAAA",28);
+ qtype_insert("LOC",29);
+ qtype_insert("SRV",33);
+ qtype_insert("CERT", 37);
+ qtype_insert("A6",38);
+ qtype_insert("NAPTR",35);
+ qtype_insert("DS", 43);
+ qtype_insert("SSHFP", 44);
+ qtype_insert("RRSIG", 46);
+ qtype_insert("NSEC", 47);
+ qtype_insert("DNSKEY", 48);
+ qtype_insert("NSEC3", 50);
+ qtype_insert("NSEC3PARAM", 51);
+ qtype_insert("TLSA",52);
+ qtype_insert("SPF",99);
+ qtype_insert("IXFR",251);
+ qtype_insert("AXFR",252);
+ qtype_insert("ANY",255);
+ qtype_insert("URL",256);
+ qtype_insert("MBOXFW",257);
+ qtype_insert("CURL",258);
+ qtype_insert("ADDR",259);
+ qtype_insert("DLV",32769);
+ }
+ } initializer;
- static bool uninit;
+ uint16_t code;
};
-
+struct QClass
+{
+ enum QClassEnum {IN=1, CHAOS=3};
+};
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rcpgenerator.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2005 - 2007 PowerDNS.COM BV
+ Copyright (C) 2005 - 2011 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 version 2 as
@@ -22,6 +22,7 @@
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
+#include "base32.hh"
#include "base64.hh"
#include "namespaces.hh"
@@ -77,7 +78,7 @@
tm.tm_year-=1900;
tm.tm_mon-=1;
-// val=(uint32_t)timegm(&tm); XXX FIXME disabled for Solaris
+ val=(uint32_t)Utility::timegm(&tm);
}
void RecordTextReader::xfrIP(uint32_t &val)
@@ -146,6 +147,7 @@
throw RecordTextException("Overflow reading 8 bit integer from record content"); // fixme improve
}
+// this code should leave all the escapes around
void RecordTextReader::xfrLabel(string& val, bool)
{
skipSpaces();
@@ -157,13 +159,9 @@
while(d_pos < d_end) {
if(strptr[d_pos]!='\r' && dns_isspace(strptr[d_pos]))
break;
-
- if(strptr[d_pos]=='\\' && d_pos < d_end - 1 && strptr[d_pos+1]!='.') // leave the \. escape around
- d_pos++;
-
+
d_pos++;
}
-
val.append(strptr+begin_pos, strptr+d_pos);
if(val.empty())
@@ -222,28 +220,63 @@
}
-void HEXDecode(const char* begin, const char* end, string& val)
+void HEXDecode(const char* begin, const char* end, string& out)
{
- if((end - begin)%2)
- throw RecordTextException("Hexadecimal blob with odd number of characters");
-
- int limit=(int)(end-begin)/2;
- val.resize(limit);
- for(int n=0; n < limit; ++n) {
- val[n] = hextodec(begin[2*n])*16 + hextodec(begin[2*n+1]);
+ if(end - begin == 1 && *begin=='-') {
+ out.clear();
+ return;
}
+ out.clear();
+ out.reserve((end-begin)/2);
+ uint8_t mode=0, val=0;
+ for(; begin != end; ++begin) {
+ if(!isalnum(*begin))
+ continue;
+ if(mode==0) {
+ val = 16*hextodec(*begin);
+ mode=1;
+ } else {
+ val += hextodec(*begin);
+ out.append(1, (char) val);
+ mode = 0;
+ val = 0;
+ }
+ }
+ if(mode)
+ out.append(1, (char) val);
+
}
-void RecordTextReader::xfrHexBlob(string& val)
+void RecordTextReader::xfrHexBlob(string& val, bool keepReading)
{
skipSpaces();
int pos=(int)d_pos;
- while(d_pos < d_end && !dns_isspace(d_string[d_pos]))
+ while(d_pos < d_end && (keepReading || !dns_isspace(d_string[d_pos])))
d_pos++;
HEXDecode(d_string.c_str()+pos, d_string.c_str() + d_pos, val);
}
+void RecordTextReader::xfrBase32HexBlob(string& val)
+{
+ skipSpaces();
+ int pos=(int)d_pos;
+ while(d_pos < d_end && !dns_isspace(d_string[d_pos]))
+ d_pos++;
+
+ val=fromBase32Hex(string(d_string.c_str()+pos, d_pos-pos));
+}
+
+
+void RecordTextWriter::xfrBase32HexBlob(const string& val)
+{
+ if(!d_string.empty())
+ d_string.append(1,' ');
+
+ d_string.append(toBase32Hex(val));
+}
+
+
void RecordTextReader::xfrText(string& val, bool multi)
{
val.clear();
@@ -254,9 +287,19 @@
val.append(1, ' ');
skipSpaces();
- if(d_string[d_pos]!='"')
+ if(d_string[d_pos]!='"') { // special case 'plenus' - without quotes
+ string::size_type pos = d_pos;
+ while(pos != d_end && isalnum(d_string[pos]))
+ pos++;
+ if(pos == d_end) {
+ val.append(1, '"');
+ val.append(d_string.c_str() + d_pos, d_end - d_pos);
+ val.append(1, '"');
+ d_pos = d_end;
+ break;
+ }
throw RecordTextException("Data field in DNS should start with quote (\") at position "+lexical_cast<string>(d_pos)+" of '"+d_string+"'");
-
+ }
val.append(1, '"');
while(++d_pos < d_end && d_string[d_pos]!='"') {
if(d_string[d_pos]=='\\' && d_pos+1!=d_end) {
@@ -394,24 +437,13 @@
xfr32BitInt(val);
}
-
+// should not mess with the escapes
void RecordTextWriter::xfrLabel(const string& val, bool)
{
if(!d_string.empty())
d_string.append(1,' ');
- if(val.find(' ')==string::npos)
- d_string+=val;
- else {
- d_string.reserve(d_string.size()+val.size()+3);
- for(string::size_type pos=0; pos < val.size() ; ++pos)
- if(dns_isspace(val[pos]))
- d_string+="\\ ";
- else if(val[pos]=='\\')
- d_string.append(1,'\\');
- else
- d_string.append(1,val[pos]);
- }
- // d_string.append(1,'.');
+
+ d_string+=val;
}
void RecordTextWriter::xfrBlob(const string& val, int)
@@ -422,11 +454,16 @@
d_string+=Base64Encode(val);
}
-void RecordTextWriter::xfrHexBlob(const string& val)
+void RecordTextWriter::xfrHexBlob(const string& val, bool)
{
if(!d_string.empty())
d_string.append(1,' ');
+ if(val.empty()) {
+ d_string.append(1,'-');
+ return;
+ }
+
string::size_type limit=val.size();
char tmp[5];
for(string::size_type n = 0; n < limit; ++n) {
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rcpgenerator.hh
^
|
@@ -28,7 +28,7 @@
# include "utility.hh"
#endif
-using namespace std;
+#include "namespaces.hh"
class RecordTextException : public runtime_error
{
@@ -53,7 +53,9 @@
void xfrLabel(string& val, bool compress=false);
void xfrText(string& val, bool multi=false);
- void xfrHexBlob(string& val);
+ void xfrHexBlob(string& val, bool keepReading=false);
+ void xfrBase32HexBlob(string& val);
+
void xfrBlob(string& val, int len=-1);
bool eof();
@@ -75,16 +77,17 @@
void xfr8BitInt(const uint8_t& val);
void xfrIP(const uint32_t& val);
void xfrTime(const uint32_t& val);
+ void xfrBase32HexBlob(const string& val);
void xfrType(const uint16_t& val);
void xfrLabel(const string& val, bool compress=false);
void xfrText(const string& val, bool multi=false);
void xfrBlob(const string& val, int len=-1);
- void xfrHexBlob(const string& val);
+ void xfrHexBlob(const string& val, bool keepReading=false);
private:
string& d_string;
};
-
+string segmentDNSLabel(const string& input );
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rec_channel.cc
^
|
@@ -1,6 +1,7 @@
#include "rec_channel.hh"
#include <sys/socket.h>
#include <cerrno>
+#include "misc.hh"
#include <string.h>
#include <cstdlib>
#include <unistd.h>
@@ -10,7 +11,7 @@
#include "ahuexception.hh"
-using namespace std;
+#include "namespaces.hh"
RecursorControlChannel::RecursorControlChannel()
{
@@ -29,7 +30,8 @@
int RecursorControlChannel::listen(const string& fname)
{
d_fd=socket(AF_UNIX,SOCK_DGRAM,0);
-
+ Utility::setCloseOnExec(d_fd);
+
if(d_fd < 0)
throw AhuException("Creating UNIX domain socket: "+string(strerror(errno)));
@@ -56,7 +58,8 @@
struct sockaddr_un remote;
d_fd=socket(AF_UNIX,SOCK_DGRAM,0);
-
+ Utility::setCloseOnExec(d_fd);
+
if(d_fd < 0)
throw AhuException("Creating UNIX domain socket: "+string(strerror(errno)));
@@ -121,27 +124,6 @@
throw AhuException("Unable to send message over control channel: "+string(strerror(errno)));
}
-// returns -1 in case if error, 0 if no data is available, 1 if there is. In the first two cases, errno is set
-static int waitForData(int fd, int seconds, int useconds)
-{
- struct timeval tv;
- int ret;
-
- tv.tv_sec = seconds;
- tv.tv_usec = useconds;
-
- fd_set readfds;
- FD_ZERO( &readfds );
- FD_SET( fd, &readfds );
-
- ret = select( fd + 1, &readfds, NULL, NULL, (seconds + useconds) ? &tv : 0 );
- if ( ret == 0 )
- errno = ETIMEDOUT;
-
- return ret;
-}
-
-
string RecursorControlChannel::recv(std::string* remote, unsigned int timeout)
{
char buffer[16384];
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rec_channel.hh
^
|
@@ -46,5 +46,6 @@
std::string getAnswer(const std::string& question, func_t** func);
};
+std::map<std::string, std::string> getAllStatsMap();
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rec_channel_rec.cc
^
|
@@ -23,7 +23,7 @@
#include <sys/time.h>
#endif
-using namespace std;
+#include "namespaces.hh"
#include "namespaces.hh"
map<string, const uint32_t*> d_get32bitpointers;
map<string, const uint64_t*> d_get64bitpointers;
@@ -56,20 +56,33 @@
return ret;
}
-string getAllStats()
+map<string,string> getAllStatsMap()
{
- string ret;
+ map<string,string> ret;
+
pair<string, const uint32_t*> the32bits;
pair<string, const uint64_t*> the64bits;
pair<string, function< uint32_t() > > the32bitmembers;
+
BOOST_FOREACH(the32bits, d_get32bitpointers) {
- ret += the32bits.first + "\t" + lexical_cast<string>(*the32bits.second) + "\n";
+ ret.insert(make_pair(the32bits.first, lexical_cast<string>(*the32bits.second)));
}
BOOST_FOREACH(the64bits, d_get64bitpointers) {
- ret += the64bits.first + "\t" + lexical_cast<string>(*the64bits.second) + "\n";
+ ret.insert(make_pair(the64bits.first, lexical_cast<string>(*the64bits.second)));
}
BOOST_FOREACH(the32bitmembers, d_get32bitmembers) {
- ret += the32bitmembers.first + "\t" + lexical_cast<string>(the32bitmembers.second()) + "\n";
+ ret.insert(make_pair(the32bitmembers.first, lexical_cast<string>(the32bitmembers.second())));
+ }
+ return ret;
+}
+
+string getAllStats()
+{
+ typedef map<string, string> varmap_t;
+ varmap_t varmap = getAllStatsMap();
+ string ret;
+ BOOST_FOREACH(varmap_t::value_type& tup, varmap) {
+ ret += tup.first + "\t" + tup.second +"\n";
}
return ret;
}
@@ -110,9 +123,58 @@
}
+static uint64_t dumpNegCache(SyncRes::negcache_t& negcache, int fd)
+{
+ FILE* fp=fdopen(dup(fd), "w");
+ if(!fp) { // dup probably failed
+ return 0;
+ }
+ fprintf(fp, "; negcache dump from thread follows\n;\n");
+ time_t now = time(0);
+
+ typedef SyncRes::negcache_t::nth_index<1>::type sequence_t;
+ sequence_t& sidx=negcache.get<1>();
+
+ uint64_t count=0;
+ BOOST_FOREACH(const NegCacheEntry& neg, sidx)
+ {
+ ++count;
+ fprintf(fp, "%s IN %s %d VIA %s\n", neg.d_name.c_str(), neg.d_qtype.getName().c_str(), (unsigned int) (neg.d_ttd - now), neg.d_qname.c_str());
+ }
+ fclose(fp);
+ return count;
+}
+
static uint64_t* pleaseDump(int fd)
{
- return new uint64_t(t_RC->doDump(fd));
+ return new uint64_t(t_RC->doDump(fd) + dumpNegCache(t_sstorage->negcache, fd));
+}
+
+static uint64_t* pleaseDumpNSSpeeds(int fd)
+{
+ return new uint64_t(t_RC->doDumpNSSpeeds(fd));
+}
+
+template<typename T>
+string doDumpNSSpeeds(T begin, T end)
+{
+ T i=begin;
+ string fname;
+
+ if(i!=end)
+ fname=*i;
+
+ int fd=open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
+ if(fd < 0)
+ return "Error opening dump file for writing: "+string(strerror(errno))+"\n";
+ uint64_t total = 0;
+ try {
+ total = broadcastAccFunction<uint64_t>(boost::bind(pleaseDumpNSSpeeds, fd));
+ }
+ catch(...){}
+
+ close(fd);
+ return "dumped "+lexical_cast<string>(total)+" records\n";
}
template<typename T>
@@ -155,13 +217,14 @@
return "done\n";
}
-static uint64_t* pleaseWipeCache(const std::string& canon)
+uint64_t* pleaseWipeCache(const std::string& canon)
{
- return new uint64_t(t_RC->doWipeCache(canon));
+ // clear packet cache too
+ return new uint64_t(t_RC->doWipeCache(canon) + t_packetCache->doWipePacketCache(canon));
}
-static uint64_t* pleaseWipeAndCountNegCache(const std::string& canon)
+uint64_t* pleaseWipeAndCountNegCache(const std::string& canon)
{
uint64_t res = t_sstorage->negcache.count(tie(canon));
pair<SyncRes::negcache_t::iterator, SyncRes::negcache_t::iterator> range=t_sstorage->negcache.equal_range(tie(canon));
@@ -276,11 +339,22 @@
return new uint64_t(t_RC->size());
}
+uint64_t* pleaseGetCacheBytes()
+{
+ return new uint64_t(t_RC->bytes());
+}
+
+
uint64_t doGetCacheSize()
{
return broadcastAccFunction<uint64_t>(pleaseGetCacheSize);
}
+uint64_t doGetCacheBytes()
+{
+ return broadcastAccFunction<uint64_t>(pleaseGetCacheBytes);
+}
+
uint64_t* pleaseGetCacheHits()
{
return new uint64_t(t_RC->cacheHits);
@@ -302,18 +376,28 @@
}
-
-
uint64_t* pleaseGetPacketCacheSize()
{
return new uint64_t(t_packetCache->size());
}
+uint64_t* pleaseGetPacketCacheBytes()
+{
+ return new uint64_t(t_packetCache->bytes());
+}
+
+
uint64_t doGetPacketCacheSize()
{
return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
}
+uint64_t doGetPacketCacheBytes()
+{
+ return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheBytes);
+}
+
+
uint64_t* pleaseGetPacketCacheHits()
{
return new uint64_t(t_packetCache->d_hits);
@@ -334,21 +418,31 @@
return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheMisses);
}
+uint64_t doGetMallocated()
+{
+ // this turned out to be broken
+/* struct mallinfo mi = mallinfo();
+ return mi.uordblks; */
+ return 0;
+}
RecursorControlParser::RecursorControlParser()
{
addGetStat("questions", &g_stats.qcounter);
+ addGetStat("ipv6-questions", &g_stats.ipv6qcounter);
addGetStat("tcp-questions", &g_stats.tcpqcounter);
addGetStat("cache-hits", doGetCacheHits);
addGetStat("cache-misses", doGetCacheMisses);
addGetStat("cache-entries", doGetCacheSize);
+ addGetStat("cache-bytes", doGetCacheBytes);
addGetStat("packetcache-hits", doGetPacketCacheHits);
addGetStat("packetcache-misses", doGetPacketCacheMisses);
addGetStat("packetcache-entries", doGetPacketCacheSize);
+ addGetStat("packetcache-bytes", doGetPacketCacheBytes);
-
+ addGetStat("malloc-bytes", doGetMallocated);
addGetStat("servfail-answers", &g_stats.servFails);
addGetStat("nxdomain-answers", &g_stats.nxDomains);
@@ -378,6 +472,7 @@
addGetStat("over-capacity-drops", &g_stats.overCapacityDrops);
addGetStat("no-packet-error", &g_stats.noPacketError);
addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
+ addGetStat("max-mthread-stack", &g_stats.maxMThreadStackUsage);
addGetStat("negcache-entries", boost::bind(getNegCacheSize));
addGetStat("throttle-entries", boost::bind(getThrottleSize));
@@ -390,9 +485,11 @@
addGetStat("all-outqueries", &SyncRes::s_outqueries);
addGetStat("ipv6-outqueries", &g_stats.ipv6queries);
addGetStat("throttled-outqueries", &SyncRes::s_throttledqueries);
+ addGetStat("dont-outqueries", &SyncRes::s_dontqueries);
addGetStat("throttled-out", &SyncRes::s_throttledqueries);
addGetStat("unreachables", &SyncRes::s_unreachables);
addGetStat("chain-resends", &g_stats.chainResends);
+ addGetStat("tcp-clients", boost::bind(TCPConnection::getCurrentConnections));
addGetStat("edns-ping-matches", &g_stats.ednsPingMatches);
addGetStat("edns-ping-mismatches", &g_stats.ednsPingMismatches);
@@ -431,6 +528,8 @@
static void doExitNicely()
{
+ //extern void printCallers();
+ // printCallers();
doExitGeneric(true);
}
@@ -453,7 +552,7 @@
counts[*i]++;
}
- typedef multimap<int, ComboAddress> rcounts_t;
+ typedef std::multimap<int, ComboAddress> rcounts_t;
rcounts_t rcounts;
for(counts_t::const_iterator i=counts.begin(); i != counts.end(); ++i)
@@ -487,6 +586,28 @@
string cmd=toLower(words[0]);
vector<string>::const_iterator begin=words.begin()+1, end=words.end();
+ // should probably have a smart dispatcher here, like auth has
+ if(cmd=="help")
+ return
+"current-queries show currently active queries\n"
+"dump-cache <filename> dump cache contents to the named file\n"
+"dump-edns[status] <filename> dump EDNS status to the named file\n"
+"dump-nsspeeds <filename> dump nsspeeds statistics to the named file\n"
+"get [key1] [key2] .. get specific statistics\n"
+"get-all get all statistics\n"
+"get-parameter [key1] [key2] .. get configuration parameters\n"
+"help get this list\n"
+"ping check that all threads are alive\n"
+"quit stop the recursor daemon\n"
+"quit-nicely stop the recursor daemon nicely\n"
+"reload-acls reload ACLS\n"
+"reload-lua-script [filename] (re)load Lua script\n"
+"reload-zones reload all auth and forward zones\n"
+"trace-regex regex emit resolution trace for matching queries\n"
+"top-remotes show top remotes\n"
+"unload-lua-script unload Lua script\n"
+"wipe-cache domain0 [domain1] .. wipe domain data from cache\n";
+
if(cmd=="get-all")
return getAllStats();
@@ -496,7 +617,6 @@
if(cmd=="get-parameter")
return doGetParameter(begin, end);
-
if(cmd=="quit") {
*command=&doExit;
return "bye\n";
@@ -505,8 +625,7 @@
if(cmd=="quit-nicely") {
*command=&doExitNicely;
return "bye nicely\n";
- }
-
+ }
if(cmd=="dump-cache")
return doDumpCache(begin, end);
@@ -514,13 +633,18 @@
if(cmd=="dump-ednsstatus" || cmd=="dump-edns")
return doDumpEDNSStatus(begin, end);
+ if(cmd=="dump-nsspeeds")
+ return doDumpNSSpeeds(begin, end);
- if(cmd=="wipe-cache")
+ if(cmd=="wipe-cache" || cmd=="flushname")
return doWipeCache(begin, end);
if(cmd=="reload-lua-script")
return doQueueReloadLuaScript(begin, end);
+ if(cmd=="trace-regex")
+ return doTraceRegex(begin, end);
+
if(cmd=="unload-lua-script") {
vector<string> empty;
empty.push_back(string());
@@ -531,10 +655,16 @@
try {
parseACLs();
}
- catch(exception& e)
+ catch(std::exception& e)
{
+ L<<Logger::Error<<"reloading ACLs failed (Exception: "<<e.what()<<")"<<endl;
return e.what() + string("\n");
}
+ catch(AhuException& ae)
+ {
+ L<<Logger::Error<<"reloading ACLs failed (AhuException: "<<ae.reason<<")"<<endl;
+ return ae.reason + string("\n");
+ }
return "ok\n";
}
@@ -552,6 +682,6 @@
if(cmd=="reload-zones") {
return reloadAuthAndForwards();
}
-
- return "Unknown command '"+cmd+"'\n";
+
+ return "Unknown command '"+cmd+"', try 'help'\n";
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rec_control.1
^
|
@@ -1,42 +1,67 @@
+'\" t
.\" Title: rec_control
-.\" Author:
-.\" Generator: DocBook XSL Stylesheets v1.73.2 <http://docbook.sf.net/>
-.\" Date: 09/22/2009
-.\" Manual:
-.\" Source:
+.\" Author: [see the "AUTHOR" section]
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Date: 06/07/2013
+.\" Manual: \ \&
+.\" Source: \ \& 3.0
+.\" Language: English
.\"
-.TH "REC_CONTROL" "1" "09/22/2009" "" ""
+.TH "REC_CONTROL" "1" "06/07/2013" "\ \& 3\&.0" "\ \&"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
.\" disable hyphenation
.nh
.\" disable justification (adjust text to left margin only)
.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
.SH "NAME"
rec_control \- control pdns_recursor
.SH "SYNOPSIS"
-\fIrec_control\fR [\-\-help] [\-\-socket\-dir] [\-\-socket\-pid] command \&.\&.
.sp
+\fIrec_control\fR [\-\-help] [\-\-socket\-dir] [\-\-socket\-pid] command \&.\&.
.SH "DESCRIPTION"
-rec_control(1) allows the operator to control a running instance of the pdns_recursor\&.
.sp
-The commands that can be passed to the recursor are described on http://doc\&.powerdns\&.com/rec\-control\&.html
+rec_control(1) allows the operator to control a running instance of the pdns_recursor\&.
.sp
+The commands that can be passed to the recursor are described on \m[blue]\fBhttp://doc\&.powerdns\&.com/rec\-control\&.html\fR\m[]
.SH "EXAMPLES"
-To stop the recursor by hand, run:
.sp
+To stop the recursor by hand, run:
.sp
+.if n \{\
.RS 4
+.\}
.nf
# rec_control quit
.fi
+.if n \{\
.RE
-To dump the cache to disk, execute:
+.\}
.sp
+To dump the cache to disk, execute:
.sp
+.if n \{\
.RS 4
+.\}
.nf
# rec_control dump\-cache /tmp/the\-cache
.fi
+.if n \{\
.RE
+.\}
.SH "OPTIONS"
.PP
\-\-help
@@ -67,7 +92,13 @@
.PP
get statistic
.RS 4
-Retrieve a statistic\&. For items that can be queried, see http://doc\&.powerdns\&.com/recursor\-stats\&.html
+Retrieve a statistic\&. For items that can be queried, see
+\m[blue]\fBhttp://doc\&.powerdns\&.com/recursor\-stats\&.html\fR\m[]
+.RE
+.PP
+get\-all
+.RS 4
+Retrieve all known statistics\&.
.RE
.PP
ping
@@ -95,23 +126,29 @@
wipe\-cache domain0 [domain1]
.RS 4
Wipe entries from the cache\&. This is useful if, for example, an important server has a new IP address, but the TTL has not yet expired\&. Multiple domain names can be passed\&. Note that you must terminate a domain with a \&.! So to wipe powerdns\&.org, issue
-\fIrec_control wipe\-cache powerdns\&.org\&.\fR\&. Versions beyond 3\&.1 don\'t need the trailing dot\&. Consider not only wiping
+\fIrec_control wipe\-cache powerdns\&.org\&.\fR\&. Versions beyond 3\&.1 don\(cqt need the trailing dot\&. Consider not only wiping
\fIwww\&.domain\&.com\&.\fR
but also
\fIdomain\&.com\&.\fR, as the cached nameservers or target of CNAME may continue to be undesired\&.
.RE
.SH "BUGS"
-None known\&. File new ones at http://wiki\&.powerdns\&.com\&.
.sp
+None known\&. File new ones at \m[blue]\fBhttp://wiki\&.powerdns\&.com\fR\m[]\&.
.SH "AUTHOR"
-Written by PowerDNS\&.COM BV, bert hubert, <bert\&.hubert@netherlabs\&.nl>
.sp
+Written by PowerDNS\&.COM BV, bert hubert, <\m[blue]\fBbert\&.hubert@netherlabs\&.nl\fR\m[]\&\s-2\u[1]\d\s+2>
.SH "RESOURCES"
-Website: http://wiki\&.powerdns\&.com, http://www\&.powerdns\&.com
.sp
+Website: \m[blue]\fBhttp://wiki\&.powerdns\&.com\fR\m[], \m[blue]\fBhttp://www\&.powerdns\&.com\fR\m[]
.SH "SEE ALSO"
-pdns_recursor(1)
.sp
+pdns_recursor(1)
.SH "COPYING"
-Copyright \(co 2006 PowerDNS\&.COM BV\&. Free use of this software is granted under the terms of the GNU General Public License (GPL) version 2\&.
.sp
+Copyright \(co 2006 PowerDNS\&.COM BV\&. Free use of this software is granted under the terms of the GNU General Public License (GPL) version 2\&.
+.SH "NOTES"
+.IP " 1." 4
+bert.hubert@netherlabs.nl
+.RS 4
+\%mailto:bert.hubert@netherlabs.nl
+.RE
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/rec_control.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2006 PowerDNS.COM BV
+ Copyright (C) 2006 - 2011 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 version 2 as
@@ -21,7 +21,12 @@
#include "arguments.hh"
#include "config.h"
-using namespace std;
+#include "namespaces.hh"
+
+#ifndef RECURSOR
+#include "statbag.hh"
+StatBag S;
+#endif
ArgvMap &arg()
{
@@ -31,10 +36,10 @@
static void initArguments(int argc, char** argv)
{
- arg().set("config-dir","Location of configuration directory (pdns.conf)")=SYSCONFDIR;
+ arg().set("config-dir","Location of configuration directory (recursor.conf)")=SYSCONFDIR;
arg().set("socket-dir","Where the controlsocket will live")=LOCALSTATEDIR;
- arg().set("socket-pid","When controlling multiple recursors, the target pid")="";
+ arg().set("process","When controlling multiple recursors, the target process number")="";
arg().set("timeout", "Number of seconds to wait for the recursor to respond")="5";
arg().setCmd("help","Provide this helpful message");
@@ -44,18 +49,24 @@
cerr<<arg().helpstring(arg()["help"])<<endl;
exit(99);
}
+ string configname=::arg()["config-dir"]+"/recursor.conf";
+ cleanSlashes(configname);
+ if(!::arg().preParseFile(configname.c_str(), "socket-dir", LOCALSTATEDIR))
+ cerr<<"Warning: unable to parse configuration file '"<<configname<<"'"<<endl;
+ arg().laxParse(argc,argv); // make sure the commandline wins
}
int main(int argc, char** argv)
try
{
initArguments(argc, argv);
-
RecursorControlChannel rccS;
- string sockname="pdns_recursor.controlsocket";
- if(!arg()["socket-pid"].empty())
- sockname+="."+arg()["socket-pid"];
+ string sockname="pdns_recursor";
+ if(!arg()["process"].empty())
+ sockname+="."+arg()["process"];
+
+ sockname.append(".controlsocket");
rccS.connect(arg()["socket-dir"], sockname);
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/recpacketcache.cc
^
|
@@ -1,5 +1,7 @@
#include <iostream>
+#include <boost/foreach.hpp>
#include "recpacketcache.hh"
+#include "cachecleaner.hh"
#include "dns.hh"
#include "namespaces.hh"
#include "lock.hh"
@@ -10,33 +12,54 @@
d_hits = d_misses = 0;
}
-bool RecursorPacketCache::getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket)
+int RecursorPacketCache::doWipePacketCache(const string& name, uint16_t qtype)
+{
+ int count=0;
+ for(packetCache_t::iterator iter = d_packetCache.begin(); iter != d_packetCache.end();)
+ {
+ const struct dnsheader* packet = reinterpret_cast<const struct dnsheader*>((*iter).d_packet.c_str());
+ if (packet->qdcount > 0)
+ {
+ // find out type
+ const struct dnsrecordheader *header = reinterpret_cast<const struct dnsrecordheader*>((*iter).d_packet.c_str()+sizeof(struct dnsheader));
+ uint16_t type = header->d_type;
+ std::string domain=questionExpand((*iter).d_packet.c_str(), (*iter).d_packet.size(), type);
+ if (pdns_iequals(name,domain))
+ {
+ iter = d_packetCache.erase(iter);
+ count++;
+ } else iter++;
+ }
+ }
+ return count;
+}
+
+bool RecursorPacketCache::getResponsePacket(const std::string& queryPacket, time_t now,
+ std::string* responsePacket, uint32_t* age)
{
struct Entry e;
e.d_packet=queryPacket;
-
packetCache_t::const_iterator iter = d_packetCache.find(e);
if(iter == d_packetCache.end()) {
d_misses++;
return false;
}
- typedef packetCache_t::nth_index<1>::type sequence_t;
- sequence_t& sidx=d_packetCache.get<1>();
- sequence_t::iterator si=d_packetCache.project<1>(iter);
if((uint32_t)now < iter->d_ttd) { // it is fresh!
- uint16_t id = ((struct dnsheader*)queryPacket.c_str())->id;
+// cerr<<"Fresh for another "<<iter->d_ttd - now<<" seconds!"<<endl;
+ *age = now - iter->d_creation;
+ uint16_t id;
+ memcpy(&id, queryPacket.c_str(), 2);
*responsePacket = iter->d_packet;
- ((struct dnsheader*)responsePacket->c_str())->id=id;
+ responsePacket->replace(0, 2, (char*)&id, 2);
d_hits++;
-
- sidx.relocate(sidx.end(), si); // put it at the end of the delete queue
+ moveCacheItemToBack(d_packetCache, iter);
return true;
}
- sidx.relocate(sidx.begin(), si); // at the beginning of the delete queue
+ moveCacheItemToFront(d_packetCache, iter);
d_misses++;
return false;
}
@@ -46,11 +69,13 @@
struct Entry e;
e.d_packet = responsePacket;
e.d_ttd = now+ttl;
+ e.d_creation = now;
packetCache_t::iterator iter = d_packetCache.find(e);
if(iter != d_packetCache.end()) {
iter->d_packet = responsePacket;
iter->d_ttd = now + ttl;
+ iter->d_creation = now;
}
else
d_packetCache.insert(e);
@@ -61,59 +86,18 @@
return d_packetCache.size();
}
-// this code is almost a copy of the one in recursor_cache.cc
-void RecursorPacketCache::doPruneTo(unsigned int maxCached)
+uint64_t RecursorPacketCache::bytes()
{
- uint32_t now=(uint32_t)time(0);
- unsigned int toTrim=0;
-
- unsigned int cacheSize=d_packetCache.size();
-
- if(maxCached && cacheSize > maxCached) {
- toTrim = cacheSize - maxCached;
- }
-
-// cout<<"Need to trim "<<toTrim<<" from cache to meet target!\n";
-
- typedef packetCache_t::nth_index<1>::type sequence_t;
- sequence_t& sidx=d_packetCache.get<1>();
-
- unsigned int tried=0, lookAt, erased=0;
-
- // two modes - if toTrim is 0, just look through 10000 records and nuke everything that is expired
- // otherwise, scan first 5*toTrim records, and stop once we've nuked enough
- if(toTrim)
- lookAt=5*toTrim;
- else
- lookAt=cacheSize/1000;
-
-
- sequence_t::iterator iter=sidx.begin(), eiter;
- for(; iter != sidx.end() && tried < lookAt ; ++tried) {
- if(iter->d_ttd < now) {
- sidx.erase(iter++);
- erased++;
- }
- else
- ++iter;
-
- if(toTrim && erased > toTrim)
- break;
+ uint64_t sum=0;
+ BOOST_FOREACH(const struct Entry& e, d_packetCache) {
+ sum += sizeof(e) + e.d_packet.length() + 4;
}
+ return sum;
+}
- //cout<<"erased "<<erased<<" records based on ttd\n";
-
- if(erased >= toTrim) // done
- return;
-
-
- toTrim -= erased;
-
- //if(toTrim)
- // cout<<"Still have "<<toTrim - erased<<" entries left to erase to meet target\n";
- eiter=iter=sidx.begin();
- std::advance(eiter, toTrim);
- sidx.erase(iter, eiter); // just lob it off from the beginning
+void RecursorPacketCache::doPruneTo(unsigned int maxCached)
+{
+ pruneCollection(d_packetCache, maxCached);
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/recpacketcache.hh
^
|
@@ -19,26 +19,32 @@
{
public:
RecursorPacketCache();
- bool getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket);
+ bool getResponsePacket(const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age);
void insertResponsePacket(const std::string& responsePacket, time_t now, uint32_t ttd);
void doPruneTo(unsigned int maxSize=250000);
+ int doWipePacketCache(const string& name, uint16_t qtype=0xffff);
void prune();
uint64_t d_hits, d_misses;
uint64_t size();
+ uint64_t bytes();
private:
struct Entry
{
mutable uint32_t d_ttd;
+ mutable uint32_t d_creation;
mutable std::string d_packet; // "I know what I am doing"
inline bool operator<(const struct Entry& rhs) const;
+
+ uint32_t getTTD() const
+ {
+ return d_ttd;
+ }
};
-
-
typedef multi_index_container<
Entry,
indexed_by <
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/recursor_cache.cc
^
|
@@ -6,8 +6,9 @@
#include "arguments.hh"
#include "syncres.hh"
#include "recursor_cache.hh"
+#include "cachecleaner.hh"
-using namespace std;
+#include "namespaces.hh"
#include "namespaces.hh"
#include "config.h"
@@ -26,6 +27,7 @@
}
else if(rr.qtype.getCode()==QType::AAAA && serial.size()==16) {
ComboAddress tmp;
+ memset(&tmp, 0, sizeof(tmp));
tmp.sin4.sin_family=AF_INET6;
memcpy(tmp.sin6.sin6_addr.s6_addr, serial.c_str(), 16);
rr.content=tmp.toString();
@@ -94,6 +96,7 @@
unsigned int ret=0;
for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
+ ret+=sizeof(struct CacheEntry);
ret+=(unsigned int)i->d_qname.length();
for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j)
ret+=j->size();
@@ -123,11 +126,7 @@
for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i)
if(i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY ||
(qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) )
- ) {
- typedef cache_t::nth_index<1>::type sequence_t;
- sequence_t& sidx=d_cache.get<1>();
- sequence_t::iterator si=d_cache.project<1>(i);
-
+ ) {
for(vector<StoredRecord>::const_iterator k=i->d_records.begin(); k != i->d_records.end(); ++k) {
if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) { // FIXME what does the 100000000 number mean?
ttd=k->d_ttd;
@@ -139,9 +138,9 @@
}
if(res) {
if(res->empty())
- sidx.relocate(sidx.begin(), si);
+ moveCacheItemToFront(d_cache, i);
else
- sidx.relocate(sidx.end(), si);
+ moveCacheItemToBack(d_cache, i);
}
if(qt.getCode()!=QType::ANY && qt.getCode()!=QType::ADDR) // normally if we have a hit, we are done
break;
@@ -158,28 +157,28 @@
bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored)
{
if(!stored.d_auth) {
-// cerr<<"feel free to scribble non-auth data!"<<endl;
+ //~ cerr<<"feel free to scribble non-auth data!"<<endl;
return false;
}
if(qt.getCode()!=QType::NS) {
- // cerr<<"Not NS record"<<endl;
+ //~ cerr<<"Not NS record"<<endl;
return false;
}
if(content.size()!=stored.d_records.size()) {
- // cerr<<"Not equal number of records"<<endl;
+ //~ cerr<<"Not equal number of records"<<endl;
return false;
}
if(stored.d_records.empty())
return false;
if(stored.d_records.begin()->d_ttd > content.begin()->ttl) {
- // cerr<<"attempt to LOWER TTL - fine by us"<<endl;
+ //~ cerr<<"attempt to LOWER TTL - fine by us"<<endl;
return false;
}
- // cerr<<"Returning true - update attempt!\n";
+// cerr<<"Returning true - update attempt!\n";
return true;
}
@@ -191,6 +190,7 @@
d_cachecachevalid=false;
tuple<string, uint16_t> key=make_tuple(qname, qt.getCode());
cache_t::iterator stored=d_cache.find(key);
+ uint32_t maxTTD=UINT_MAX;
bool isNew=false;
if(stored == d_cache.end()) {
@@ -202,7 +202,7 @@
StoredRecord dr;
CacheEntry ce=*stored;
- // cerr<<"storing "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"', isnew="<<isNew<<", auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
+ //~ cerr<<"asked to store "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"', isnew="<<isNew<<", auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
if(qt.getCode()==QType::SOA || qt.getCode()==QType::CNAME) { // you can only have one (1) each of these
// cerr<<"\tCleaning out existing store because of SOA and CNAME\n";
@@ -222,17 +222,30 @@
ce.d_auth = false; // new data won't be auth
}
}
-#if 0
- if(auth && !attemptToRefreshNSTTL(qt, content, ce) ) {
- cerr<<"\tGot auth data, and it was not refresh attempt of an NS record, nuking storage"<<endl;
+
+ // limit TTL of auth->auth NSset update if needed, except for root
+ if(ce.d_auth && auth && qt.getCode()==QType::NS && !((qname.length()==1 && qname[0]=='.'))) {
+ // cerr<<"\tLimiting TTL of auth->auth NS set replace"<<endl;
+ vector<StoredRecord>::iterator j;
+ for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) {
+ maxTTD=min(maxTTD, j->d_ttd);
+ }
+ }
+
+ // make sure that we CAN refresh the root
+ if(auth && ((qname.length()==1 && qname[0]=='.') || !attemptToRefreshNSTTL(qt, content, ce) ) ) {
+ // cerr<<"\tGot auth data, and it was not refresh attempt of an unchanged NS set, nuking storage"<<endl;
ce.d_records.clear(); // clear non-auth data
ce.d_auth = true;
isNew=true; // data should be sorted again
}
-#endif
- // cerr<<"\tHave "<<content.size()<<" records to store\n";
+ else
+ ; //cerr<<"\tNot nuking"<<endl;
+
+ // cerr<<"\tHave "<<content.size()<<" records to store\n";
for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) {
- dr.d_ttd=i->ttl;
+ // cerr<<"To store: "<<i->content<<" with ttl/ttd "<<i->ttl<<endl;
+ dr.d_ttd=min(maxTTD, i->ttl);
dr.d_string=DNSRR2String(*i);
if(isNew)
@@ -240,31 +253,25 @@
else {
range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr);
- if(range.first != range.second && (range.first != ce.d_records.begin() || range.second != ce.d_records.end())) {
- // cerr<<"\t\tIncomplete match! Must nuke"<<endl;
- ce.d_records.clear();
- range.first = range.second = ce.d_records.begin();
- }
-
if(range.first != range.second) {
- // cerr<<"\t\tMay need to modify TTL of stored record\n";
+ // cerr<<"\t\tMay need to modify TTL of stored record\n";
for(vector<StoredRecord>::iterator j=range.first ; j!=range.second; ++j) {
/* see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html */
- if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS recor
- // cerr<<"\t\tNot doing so, trying to raise TTL NS\n";
+ if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS record
+ //~ cerr<<"\t\tNot doing so, trying to raise TTL NS\n";
continue;
}
- if(i->ttl > j->d_ttd || (auth && d_followRFC2181) ) { // authoritative packets can override the TTL to be lower
- // cerr<<"\t\tUpdating the ttl, diff="<<j->d_ttd - i->ttl<<endl;;
+ if(i->ttl > j->d_ttd || (auth) ) { // authoritative packets can override the TTL to be lower
+ //~ cerr<<"\t\tUpdating the ttl, diff="<<j->d_ttd - i->ttl<<endl;;
j->d_ttd=i->ttl;
}
else {
- // cerr<<"\t\tNOT updating the ttl, old= " <<j->d_ttd - now <<", new: "<<i->ttl - now <<endl;
+ //~ cerr<<"\t\tNOT updating the ttl, old= " <<j->d_ttd - now <<", new: "<<i->ttl - now <<endl;
}
}
}
else {
- // cerr<<"\t\tThere was no exact copy of this record, so adding & sorting\n";
+ //~ cerr<<"\t\tThere was no exact copy of this record, so adding & sorting\n";
ce.d_records.push_back(dr);
sort(ce.d_records.begin(), ce.d_records.end());
}
@@ -302,22 +309,34 @@
bool MemRecursorCache::doAgeCache(time_t now, const string& name, uint16_t qtype, int32_t newTTL)
{
cache_t::iterator iter = d_cache.find(tie(name, qtype));
- if(iter == d_cache.end())
+ uint32_t maxTTD=std::numeric_limits<uint32_t>::min();
+ if(iter == d_cache.end()) {
return false;
+ }
+
+ CacheEntry ce = *iter;
- int32_t ttl = iter->getTTD() - now;
- if(ttl < 0)
+ if(ce.d_records.size()==1) {
+ maxTTD=ce.d_records.begin()->d_ttd;
+ }
+ else { // find the LATEST ttd
+ for(vector<StoredRecord>::const_iterator i=ce.d_records.begin(); i != ce.d_records.end(); ++i)
+ maxTTD=max(maxTTD, i->d_ttd);
+ }
+
+ int32_t maxTTL = maxTTD - now;
+
+ if(maxTTL < 0)
return false; // would be dead anyhow
- if(ttl > newTTL) {
+ if(maxTTL > newTTL) {
d_cachecachevalid=false;
- ttl = newTTL;
- uint32_t newTTD = now + ttl;
+ uint32_t newTTD = now + newTTL;
- CacheEntry ce = *iter;
for(vector<StoredRecord>::iterator j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) {
- j->d_ttd = newTTD;
+ if(j->d_ttd>newTTD) // do never renew expired or older TTLs
+ j->d_ttd = newTTD;
}
d_cache.replace(iter, ce);
@@ -326,6 +345,28 @@
return false;
}
+uint64_t MemRecursorCache::doDumpNSSpeeds(int fd)
+{
+ FILE* fp=fdopen(dup(fd), "w");
+ if(!fp)
+ return 0;
+ fprintf(fp, "; nsspeed dump from thread follows\n;\n");
+ uint64_t count=0;
+
+ for(SyncRes::nsspeeds_t::iterator i = t_sstorage->nsSpeeds.begin() ; i!= t_sstorage->nsSpeeds.end(); ++i)
+ {
+ count++;
+ fprintf(fp, "%s -> ", i->first.c_str());
+ for(SyncRes::DecayingEwmaCollection::collection_t::iterator j = i->second.d_collection.begin(); j!= i->second.d_collection.end(); ++j)
+ {
+ // typedef vector<pair<ComboAddress, DecayingEwma> > collection_t;
+ fprintf(fp, "%s/%f ", j->first.toString().c_str(), j->second.peek());
+ }
+ fprintf(fp, "\n");
+ }
+ fclose(fp);
+ return count;
+}
uint64_t MemRecursorCache::doDump(int fd)
{
@@ -333,7 +374,7 @@
if(!fp) { // dup probably failed
return 0;
}
- fprintf(fp, "; dump from thread follows\n;\n");
+ fprintf(fp, "; main record cache dump from thread follows\n;\n");
typedef cache_t::nth_index<1>::type sequence_t;
sequence_t& sidx=d_cache.get<1>();
@@ -357,58 +398,9 @@
void MemRecursorCache::doPrune(void)
{
- uint32_t now=(uint32_t)time(0);
d_cachecachevalid=false;
unsigned int maxCached=::arg().asNum("max-cache-entries") / g_numThreads;
- unsigned int toTrim=0;
-
- unsigned int cacheSize=d_cache.size();
-
- if(maxCached && cacheSize > maxCached) {
- toTrim = cacheSize - maxCached;
- }
-
- // cout<<"Need to trim "<<toTrim<<" from cache to meet target!\n";
-
- typedef cache_t::nth_index<1>::type sequence_t;
- sequence_t& sidx=d_cache.get<1>();
-
- unsigned int tried=0, lookAt, erased=0;
-
- // two modes - if toTrim is 0, just look through 0.1% of all records and nuke everything that is expired
- // otherwise, scan first 5*toTrim records, and stop once we've nuked enough
- if(toTrim)
- lookAt=5*toTrim;
- else
- lookAt=cacheSize/1000;
-
- sequence_t::iterator iter=sidx.begin(), eiter;
- for(; iter != sidx.end() && tried < lookAt ; ++tried) {
- unsigned int ttd=iter->getTTD();
- if(ttd < now) {
- sidx.erase(iter++);
- erased++;
- }
- else
- ++iter;
-
- if(toTrim && erased > toTrim)
- break;
- }
-
- // cout<<"erased "<<erased<<" records based on ttd\n";
-
- if(erased >= toTrim)
- return;
-
- // if(toTrim)
- // cout<<"Still have "<<toTrim - erased<<" entries left to erase to meet target\n";
-
- toTrim -= erased;
-
- eiter=iter=sidx.begin();
- std::advance(eiter, toTrim);
- sidx.erase(iter, eiter);
+ pruneCollection(d_cache, maxCached);
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/recursor_cache.hh
^
|
@@ -25,7 +25,7 @@
class MemRecursorCache : public boost::noncopyable // : public RecursorCache
{
public:
- MemRecursorCache() : d_followRFC2181(false), d_cachecachevalid(false)
+ MemRecursorCache() : d_cachecachevalid(false)
{
cacheHits = cacheMisses = 0;
}
@@ -38,10 +38,11 @@
void doPrune(void);
void doSlash(int perc);
uint64_t doDump(int fd);
+ uint64_t doDumpNSSpeeds(int fd);
+
int doWipeCache(const string& name, uint16_t qtype=0xffff);
bool doAgeCache(time_t now, const string& name, uint16_t qtype, int32_t newTTL);
uint64_t cacheHits, cacheMisses;
- bool d_followRFC2181;
private:
struct StoredRecord
@@ -57,7 +58,7 @@
unsigned int size() const
{
- return ( unsigned int ) 4+d_string.size();
+ return sizeof(*this) + d_string.size();
}
};
@@ -75,7 +76,7 @@
if(d_records.size()==1)
return d_records.begin()->d_ttd;
- uint32_t earliest=numeric_limits<uint32_t>::max();
+ uint32_t earliest=std::numeric_limits<uint32_t>::max();
for(records_t::const_iterator i=d_records.begin(); i != d_records.end(); ++i)
earliest=min(earliest, i->d_ttd);
return earliest;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/reczones.cc
^
|
@@ -30,14 +30,15 @@
t_RC = new MemRecursorCache();
if(::arg()["hint-file"].empty()) {
- static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "128.8.10.90", "192.203.230.10", "192.5.5.241",
+ static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "199.7.91.13", "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", "199.7.83.42", "202.12.27.33"};
static const char *ip6s[]={
"2001:503:ba3e::2:30", NULL, NULL, NULL, NULL,
- "2001:500:2f::f", NULL, "2001:500:1::803f:235", NULL,
- "2001:503:c27::2:30", NULL, NULL, NULL
+ "2001:500:2f::f", NULL, "2001:500:1::803f:235", "2001:7fe::53",
+ "2001:503:c27::2:30", "2001:7fd::1", "2001:500:3::42", "2001:dc3::35"
};
+
DNSResourceRecord arr, aaaarr, nsrr;
arr.qtype=QType::A;
aaaarr.qtype=QType::AAAA;
@@ -212,12 +213,6 @@
L<<endl;
}
-void* pleaseWipeCache(const std::string& qname)
-{
- t_RC->doWipeCache(qname);
- return 0;
-}
-
void* pleaseWipeNegCache()
{
t_sstorage->negcache.clear();
@@ -239,7 +234,7 @@
for(SyncRes::domainmap_t::const_iterator i = t_sstorage->domainmap->begin(); i != t_sstorage->domainmap->end(); ++i) {
for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j)
- broadcastFunction(boost::bind(pleaseWipeCache, j->qname));
+ broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
}
string configname=::arg()["config-dir"]+"/recursor.conf";
@@ -258,7 +253,7 @@
// purge again - new zones need to blank out the cache
for(SyncRes::domainmap_t::const_iterator i = newDomainMap->begin(); i != newDomainMap->end(); ++i) {
for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j)
- broadcastFunction(boost::bind(pleaseWipeCache, j->qname));
+ broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
}
// this is pretty blunt
@@ -308,11 +303,11 @@
rr=String2DNSRR(rr.qname, rr.qtype, tmp, rr.ttl);
}
catch(std::exception &e) {
- delete newMap;
+ delete newMap;
throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"': "+e.what());
}
catch(...) {
- delete newMap;
+ delete newMap;
throw AhuException("Error parsing record '"+rr.qname+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
}
@@ -350,10 +345,10 @@
shared_ptr<FILE> fp=shared_ptr<FILE>(rfp, fclose);
- char line[1024];
+ string line;
int linenum=0;
uint64_t before = newMap->size();
- while(linenum++, fgets(line, sizeof(line)-1, fp.get())) {
+ while(linenum++, stringfgets(fp.get(), line)) {
string domain, instructions;
tie(domain, instructions)=splitField(line, '=');
trim(domain);
@@ -394,6 +389,7 @@
L<<Logger::Warning<<"Could not open /etc/hosts for reading"<<endl;
}
else {
+ string searchSuffix = ::arg()["export-etc-hosts-search-suffix"];
string::size_type pos;
while(getline(ifs,line)) {
pos=line.find('#');
@@ -407,8 +403,16 @@
if(parts[0].find(':')!=string::npos)
continue;
- for(unsigned int n=1; n < parts.size(); ++n)
- makeNameToIPZone(newMap, parts[n], parts[0]);
+ for(unsigned int n=1; n < parts.size(); ++n) {
+ if(searchSuffix.empty() || parts[n].find('.') != string::npos)
+ makeNameToIPZone(newMap, parts[n], parts[0]);
+ else {
+ string canonic=toCanonic(searchSuffix, parts[n]);
+ if(canonic != parts[n]) {
+ makeNameToIPZone(newMap, canonic, parts[0]);
+ }
+ }
+ }
makeIPToNamesZone(newMap, parts);
}
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/selectmplexer.cc
^
|
@@ -8,7 +8,7 @@
#include "namespaces.hh"
-using namespace std;
+#include "namespaces.hh"
static FDMultiplexer* make()
{
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sillyrecords.cc
^
|
@@ -293,7 +293,7 @@
double latitude= ((int32_t)d_latitude - (1<<31))/3600000.0;
double longitude=((int32_t)d_longitude - (1<<31))/3600000.0;
- double altitude= ((int32_t)d_altitude )/100 - 100000;
+ double altitude= ((int32_t)d_altitude )/100.0 - 100000;
double size=0.01*((d_size>>4)&0xf);
int count=d_size & 0xf;
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sstuff.hh
^
|
@@ -19,7 +19,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <csignal>
-using namespace std;
+#include "namespaces.hh"
#include "namespaces.hh"
@@ -54,6 +54,8 @@
d_family=af;
if((d_socket=(int)socket(af,st, pt))<0)
throw NetworkError(strerror(errno));
+ Utility::setCloseOnExec(d_socket);
+
d_buflen=4096;
d_buffer=new char[d_buflen];
}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/syncres.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2003 - 2009 PowerDNS.COM BV
+ Copyright (C) 2003 - 2013 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 version 2 as published
@@ -17,6 +17,7 @@
*/
#include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
#include "utility.hh"
#include "syncres.hh"
#include <iostream>
@@ -36,6 +37,7 @@
#include "dnsparser.hh"
#include "dns_random.hh"
#include "lock.hh"
+#include "cachecleaner.hh"
__thread SyncRes::StaticStorage* t_sstorage;
@@ -48,22 +50,26 @@
unsigned int SyncRes::s_outqueries;
unsigned int SyncRes::s_tcpoutqueries;
unsigned int SyncRes::s_throttledqueries;
+unsigned int SyncRes::s_dontqueries;
unsigned int SyncRes::s_nodelegated;
unsigned int SyncRes::s_unreachables;
bool SyncRes::s_doIPv6;
bool SyncRes::s_nopacketcache;
string SyncRes::s_serverID;
-bool SyncRes::s_log;
+SyncRes::LogMode SyncRes::s_lm;
-#define LOG if(s_log) L<<Logger::Warning
+#define LOG(x) if(d_lm == Log) { L <<Logger::Warning << x; } else if(d_lm == Store) { d_trace << x; }
bool SyncRes::s_noEDNSPing;
bool SyncRes::s_noEDNS;
+bool SyncRes::s_doAdditionalProcessing;
+bool SyncRes::s_doAAAAAdditionalProcessing;
SyncRes::SyncRes(const struct timeval& now) : d_outqueries(0), d_tcpoutqueries(0), d_throttledqueries(0), d_timeouts(0), d_unreachables(0),
d_now(now),
- d_cacheonly(false), d_nocache(false), d_doEDNS0(false)
+ d_cacheonly(false), d_nocache(false), d_doEDNS0(false), d_lm(s_lm)
+
{
if(!t_sstorage) {
t_sstorage = new StaticStorage();
@@ -74,6 +80,10 @@
int SyncRes::beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret)
{
s_queries++;
+
+ if( (qtype.getCode() == QType::AXFR))
+ return -1;
+
if( (qtype.getCode()==QType::PTR && pdns_iequals(qname, "1.0.0.127.in-addr.arpa.")) ||
(qtype.getCode()==QType::A && qname.length()==10 && pdns_iequals(qname, "localhost."))) {
ret.clear();
@@ -114,7 +124,7 @@
set<GetBestNSAnswer> beenthere;
int res=doResolve(qname, qtype, ret, 0, beenthere);
- if(!res)
+ if(!res && s_doAdditionalProcessing)
addCruft(qname, ret);
return res;
}
@@ -123,20 +133,20 @@
bool SyncRes::doOOBResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int& res)
{
string prefix;
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
- LOG<<prefix<<qname<<": checking auth storage for '"<<qname<<"|"<<qtype.getName()<<"'"<<endl;
+ LOG(prefix<<qname<<": checking auth storage for '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
string authdomain(qname);
domainmap_t::const_iterator iter=getBestAuthZone(&authdomain);
if(iter==t_sstorage->domainmap->end()) {
- LOG<<prefix<<qname<<": auth storage has no zone for this query!"<<endl;
+ LOG(prefix<<qname<<": auth storage has no zone for this query!"<<endl);
return false;
}
- LOG<<prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl;
+ LOG(prefix<<qname<<": auth storage has data, zone='"<<authdomain<<"'"<<endl);
pair<AuthDomain::records_t::const_iterator, AuthDomain::records_t::const_iterator> range;
range=iter->second.d_records.equal_range(tie(qname)); // partial lookup
@@ -150,12 +160,12 @@
ret.push_back(*ziter);
}
if(!ret.empty()) {
- LOG<<prefix<<qname<<": exact match in zone '"<<authdomain<<"'"<<endl;
+ LOG(prefix<<qname<<": exact match in zone '"<<authdomain<<"'"<<endl);
res=0;
return true;
}
if(somedata) {
- LOG<<prefix<<qname<<": found record in '"<<authdomain<<"', but nothing of the right type, sending SOA"<<endl;
+ LOG(prefix<<qname<<": found record in '"<<authdomain<<"', but nothing of the right type, sending SOA"<<endl);
ziter=iter->second.d_records.find(make_tuple(authdomain, QType(QType::SOA)));
if(ziter!=iter->second.d_records.end()) {
DNSResourceRecord rr=*ziter;
@@ -163,7 +173,28 @@
ret.push_back(rr);
}
else
- LOG<<prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl;
+ LOG(prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl);
+ res=RCode::NoError;
+ return true;
+ }
+
+ LOG(prefix<<qname<<": nothing found so far in '"<<authdomain<<"', trying wildcards"<<endl);
+ string wcarddomain(qname);
+ while(!pdns_iequals(wcarddomain, iter->first) && chopOffDotted(wcarddomain)) {
+ LOG(prefix<<qname<<": trying '*."+wcarddomain+"' in "<<authdomain<<endl);
+ range=iter->second.d_records.equal_range(make_tuple("*."+wcarddomain));
+ if(range.first==range.second)
+ continue;
+
+ for(ziter=range.first; ziter!=range.second; ++ziter) {
+ DNSResourceRecord rr=*ziter;
+ if(rr.qtype == qtype || qtype.getCode() == QType::ANY) {
+ rr.qname = qname;
+ rr.d_place=DNSResourceRecord::ANSWER;
+ ret.push_back(rr);
+ }
+ }
+ LOG(prefix<<qname<<": in '"<<authdomain<<"', had wildcard match on '*."+wcarddomain+"'"<<endl);
res=RCode::NoError;
return true;
}
@@ -182,7 +213,7 @@
}
}
if(ret.empty()) {
- LOG<<prefix<<qname<<": no NS match in zone '"<<authdomain<<"' either, handing out SOA"<<endl;
+ LOG(prefix<<qname<<": no NS match in zone '"<<authdomain<<"' either, handing out SOA"<<endl);
ziter=iter->second.d_records.find(make_tuple(authdomain, QType(QType::SOA)));
if(ziter!=iter->second.d_records.end()) {
DNSResourceRecord rr=*ziter;
@@ -190,7 +221,7 @@
ret.push_back(rr);
}
else
- LOG<<prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl;
+ LOG(prefix<<qname<<": can't find SOA record '"<<authdomain<<"' in our zone!"<<endl);
res=RCode::NXDomain;
}
else
@@ -199,8 +230,6 @@
return true;
}
-
-
void SyncRes::doEDNSDumpAndClose(int fd)
{
FILE* fp=fdopen(fd, "w");
@@ -255,7 +284,7 @@
if(ednsstatus->modeSetAt && ednsstatus->modeSetAt + 3600 < d_now.tv_sec) {
*ednsstatus=SyncRes::EDNSStatus();
- // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl;
+ // cerr<<"Resetting EDNS Status for "<<ip.toString()<<endl);
}
if(s_noEDNSPing && ednsstatus->mode == EDNSStatus::UNKNOWN)
@@ -267,7 +296,7 @@
int ret;
for(int tries = 0; tries < 3; ++tries) {
- // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
+ // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl);
if(mode==EDNSStatus::CONFIRMEDPINGER || mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSPINGOK || mode==EDNSStatus::EDNSIGNORANT)
EDNSLevel = 2;
@@ -282,7 +311,7 @@
ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, res);
if(ret == 0 || ret < 0) {
- // cerr<<"Transport error or timeout (ret="<<ret<<"), no change in mode"<<endl;
+ // cerr<<"Transport error or timeout (ret="<<ret<<"), no change in mode"<<endl);
return ret;
}
@@ -301,7 +330,7 @@
}
else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSPINGOK || mode == EDNSStatus::EDNSIGNORANT ) {
if(res->d_rcode == RCode::FormErr) {
- // cerr<<"Downgrading to EDNSNOPING because of FORMERR!"<<endl;
+ // cerr<<"Downgrading to EDNSNOPING because of FORMERR!"<<endl);
mode = EDNSStatus::EDNSNOPING;
continue;
}
@@ -320,13 +349,13 @@
else if(!res->d_haveEDNS) {
if(mode != EDNSStatus::EDNSIGNORANT) {
mode = EDNSStatus::EDNSIGNORANT;
- // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer, moving to mode 3"<<endl;
+ // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer, moving to mode 3"<<endl);
}
}
}
else if(mode==EDNSStatus::EDNSNOPING) {
if(res->d_rcode == RCode::FormErr) {
- // cerr<<"Downgrading to mode 4, FORMERR!"<<endl;
+ // cerr<<"Downgrading to mode 4, FORMERR!"<<endl);
mode = EDNSStatus::NOEDNS;
continue;
}
@@ -340,7 +369,7 @@
}
if(oldmode != mode)
ednsstatus->modeSetAt=d_now.tv_sec;
- // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", EDNS-PING correct: "<<res->d_pingCorrect<<", new mode: "<<mode<<endl;
+ // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", EDNS-PING correct: "<<res->d_pingCorrect<<", new mode: "<<mode<<endl);
return ret;
}
@@ -350,7 +379,7 @@
int SyncRes::doResolve(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix;
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
@@ -359,7 +388,7 @@
if(!(d_nocache && qtype.getCode()==QType::NS && qname==".")) {
if(d_cacheonly) { // very limited OOB support
LWResult lwr;
- LOG<<prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl;
+ LOG(prefix<<qname<<": Recursion not requested for '"<<qname<<"|"<<qtype.getName()<<"', peeking at auth/forward zones"<<endl);
string authname(qname);
domainmap_t::const_iterator iter=getBestAuthZone(&authname);
if(iter != t_sstorage->domainmap->end()) {
@@ -371,7 +400,7 @@
}
else {
const ComboAddress remoteIP = servers.front();
- LOG<<prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl;
+ LOG(prefix<<qname<<": forwarding query to hardcoded nameserver '"<< remoteIP.toStringWithPort()<<"' for zone '"<<authname<<"'"<<endl);
res=asyncresolveWrapper(remoteIP, qname, qtype.getCode(), false, false, &d_now, &lwr);
// filter out the good stuff from lwr.result()
@@ -395,45 +424,37 @@
if(d_cacheonly)
return 0;
- LOG<<prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl;
+ LOG(prefix<<qname<<": No cache hit for '"<<qname<<"|"<<qtype.getName()<<"', trying to find an appropriate NS record"<<endl);
string subdomain(qname);
set<string, CIStringCompare> nsset;
bool flawedNSSet=false;
+
+ // the two retries allow getBestNSNamesFromCache&co to reprime the root
+ // hints, in case they ever go missing
for(int tries=0;tries<2 && nsset.empty();++tries) {
subdomain=getBestNSNamesFromCache(subdomain, nsset, &flawedNSSet, depth, beenthere); // pass beenthere to both occasions
-
- if(nsset.empty()) { // must've lost root records
- set<DNSResourceRecord> rootset;
- /* this additional test is needed since getBestNSNamesFromCache sometimes returns that no
- useful NS records were found, even without the root being expired. This might for example
- be the case when the . records are not acceptable because they are part of a loop, a loop
- caused by the invalidation of an nsset during the resolution algorithm */
- if(t_RC->get(d_now.tv_sec, ".", QType(QType::NS), &rootset) <= 0) {
- L<<Logger::Warning<<prefix<<qname<<": our root expired, repriming from hints and retrying"<<endl;
- primeHints();
- }
- }
}
if(!(res=doResolveAt(nsset, subdomain, flawedNSSet, qname, qtype, ret, depth, beenthere)))
return 0;
- LOG<<prefix<<qname<<": failed (res="<<res<<")"<<endl;
+ LOG(prefix<<qname<<": failed (res="<<res<<")"<<endl);
return res<0 ? RCode::ServFail : res;
}
+#if 0
// for testing purpoises
static bool ipv6First(const ComboAddress& a, const ComboAddress& b)
{
return !(a.sin4.sin_family < a.sin4.sin_family);
}
+#endif
-/** This function explicitly goes out for A addresses, but if configured to use IPv6 as well, will also return any IPv6 addresses in the cache
- Additionally, it will return the 'best' address up front, and the rest shufled
+/** This function explicitly goes out for A or AAAA addresses
*/
-vector<ComboAddress> SyncRes::getAs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere)
+vector<ComboAddress> SyncRes::getAddrs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere)
{
typedef vector<DNSResourceRecord> res_t;
res_t res;
@@ -441,19 +462,25 @@
typedef vector<ComboAddress> ret_t;
ret_t ret;
- if(!doResolve(qname, s_doIPv6 ? QType(QType::ADDR) : QType(QType::A), res,depth+1,beenthere) && !res.empty()) { // this consults cache, OR goes out
- for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
- if(i->qtype.getCode()==QType::A || i->qtype.getCode()==QType::AAAA) {
- ret.push_back(ComboAddress(i->content, 53));
+ QType type;
+ for(int j=0; j<1+s_doIPv6; j++)
+ {
+ type = j ? QType::AAAA : QType::A;
+
+ if(!doResolve(qname, type, res,depth+1,beenthere) && !res.empty()) { // this consults cache, OR goes out
+ for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
+ if(i->qtype.getCode()==QType::A || i->qtype.getCode()==QType::AAAA) {
+ ret.push_back(ComboAddress(i->content, 53));
+ }
}
}
}
-
+
if(ret.size() > 1) {
random_shuffle(ret.begin(), ret.end(), dns_random);
// move 'best' address for this nameserver name up front
- nsspeeds_t::iterator best = t_sstorage->nsSpeeds.find(qname);
+ nsspeeds_t::iterator best = t_sstorage->nsSpeeds.find(qname);
if(best != t_sstorage->nsSpeeds.end())
for(ret_t::iterator i=ret.begin(); i != ret.end(); ++i) {
@@ -473,14 +500,14 @@
void SyncRes::getBestNSFromCache(const string &qname, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix, subdomain(qname);
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
bestns.clear();
do {
- LOG<<prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl;
+ LOG(prefix<<qname<<": Checking if we have NS in cache for '"<<subdomain<<"'"<<endl);
set<DNSResourceRecord> ns;
*flawedNSSet = false;
if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
@@ -491,20 +518,20 @@
DNSResourceRecord rr=*k;
rr.content=k->content;
if(!dottedEndsOn(rr.content, subdomain) || t_RC->get(d_now.tv_sec, rr.content, s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
- s_log ? &aset : 0) > 5) {
+ doLog() ? &aset : 0) > 5) {
bestns.insert(rr);
- LOG<<prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<rr.content<<"'"<<endl;
- LOG<<prefix<<qname<<": within bailiwick: "<<dottedEndsOn(rr.content, subdomain);
+ LOG(prefix<<qname<<": NS (with ip, or non-glue) in cache for '"<<subdomain<<"' -> '"<<rr.content<<"'"<<endl);
+ LOG(prefix<<qname<<": within bailiwick: "<<dottedEndsOn(rr.content, subdomain));
if(!aset.empty()) {
- LOG<<", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl;
+ LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl);
}
else {
- LOG<<", not in cache / did not look at cache"<<endl;
+ LOG(", not in cache / did not look at cache"<<endl);
}
}
else {
*flawedNSSet=true;
- LOG<<prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl;
+ LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl);
}
}
}
@@ -512,20 +539,22 @@
GetBestNSAnswer answer;
answer.qname=qname; answer.bestns=bestns;
if(beenthere.count(answer)) {
- LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP! Trying less specific NS"<<endl;
- if(s_log)
- for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j)
- LOG<<prefix<<qname<<": beenthere: "<<j->qname<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl;
+ LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' but part of LOOP (already seen "<<answer.qname<<")! Trying less specific NS"<<endl);
+ if(doLog())
+ for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
+ LOG(prefix<<qname<<": beenthere: "<<j->qname<<" ("<<(unsigned int)j->bestns.size()<<")"<<endl);
+ }
bestns.clear();
}
else {
beenthere.insert(answer);
- LOG<<prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl;
+ LOG(prefix<<qname<<": We have NS in cache for '"<<subdomain<<"' (flawedNSSet="<<*flawedNSSet<<")"<<endl);
return;
}
}
}
- LOG<<prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl;
+ LOG(prefix<<qname<<": no valid/useful NS in cache for '"<<subdomain<<"'"<<endl);
+ if(subdomain==".") { primeHints(); }
}while(chopOffDotted(subdomain));
}
@@ -572,24 +601,24 @@
bool SyncRes::doCNAMECacheCheck(const string &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
{
string prefix;
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
- if(depth>10) {
- LOG<<prefix<<qname<<": CNAME loop too deep, depth="<<depth<<endl;
+ if((depth>9 && d_outqueries>10 && d_throttledqueries>5) || depth > 15) {
+ LOG(prefix<<qname<<": recursing (CNAME or other indirection) too deep, depth="<<depth<<endl);
res=RCode::ServFail;
return true;
}
- LOG<<prefix<<qname<<": Looking for CNAME cache hit of '"<<(qname+"|CNAME")<<"'"<<endl;
+ LOG(prefix<<qname<<": Looking for CNAME cache hit of '"<<(qname+"|CNAME")<<"'"<<endl);
set<DNSResourceRecord> cset;
if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) {
for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
if(j->ttl>(unsigned int) d_now.tv_sec) {
- LOG<<prefix<<qname<<": Found cache CNAME hit for '"<< (qname+"|CNAME") <<"' to '"<<j->content<<"'"<<endl;
+ LOG(prefix<<qname<<": Found cache CNAME hit for '"<< (qname+"|CNAME") <<"' to '"<<j->content<<"'"<<endl);
DNSResourceRecord rr=*j;
rr.ttl-=d_now.tv_sec;
ret.push_back(rr);
@@ -603,7 +632,7 @@
}
}
}
- LOG<<prefix<<qname<<": No CNAME cache hit of '"<< (qname+"|CNAME") <<"' found"<<endl;
+ LOG(prefix<<qname<<": No CNAME cache hit of '"<< (qname+"|CNAME") <<"' found"<<endl);
return false;
}
@@ -615,7 +644,7 @@
bool giveNegative=false;
string prefix;
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
@@ -634,32 +663,33 @@
if((uint32_t)d_now.tv_sec < ni->d_ttd) {
sttl=ni->d_ttd - d_now.tv_sec;
if(ni->d_qtype.getCode()) {
- LOG<<prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl;
+ LOG(prefix<<qname<<": "<<qtype.getName()<<" is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
res = RCode::NoError;
}
else {
- LOG<<prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl;
+ LOG(prefix<<qname<<": Entire record '"<<qname<<"', is negatively cached via '"<<ni->d_qname<<"' for another "<<sttl<<" seconds"<<endl);
res= RCode::NXDomain;
}
giveNegative=true;
sqname=ni->d_qname;
sqt=QType::SOA;
+ moveCacheItemToBack(t_sstorage->negcache, ni);
break;
}
else {
- LOG<<prefix<<qname<<": Entire record '"<<qname<<"' was negatively cached, but entry expired"<<endl;
+ LOG(prefix<<qname<<": Entire record '"<<qname<<"' or type was negatively cached, but entry expired"<<endl);
+ moveCacheItemToFront(t_sstorage->negcache, ni);
}
}
}
-
set<DNSResourceRecord> cset;
bool found=false, expired=false;
if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset) > 0) {
- LOG<<prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ";
+ LOG(prefix<<sqname<<": Found cache hit for "<<sqt.getName()<<": ");
for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
- LOG<<j->content;
+ LOG(j->content);
if(j->ttl>(unsigned int) d_now.tv_sec) {
DNSResourceRecord rr=*j;
rr.ttl-=d_now.tv_sec;
@@ -668,23 +698,23 @@
rr.ttl=sttl;
}
ret.push_back(rr);
- LOG<<"[ttl="<<rr.ttl<<"] ";
+ LOG("[ttl="<<rr.ttl<<"] ");
found=true;
}
else {
- LOG<<"[expired] ";
+ LOG("[expired] ");
expired=true;
}
}
- LOG<<endl;
+ LOG(endl);
if(found && !expired) {
if(!giveNegative)
res=0;
return true;
}
else
- LOG<<prefix<<qname<<": cache had only stale entries"<<endl;
+ LOG(prefix<<qname<<": cache had only stale entries"<<endl);
}
return false;
@@ -711,36 +741,38 @@
{
return d_speeds[a] < d_speeds[b];
}
- map<string,double>& d_speeds;
+ map<string, double>& d_speeds;
};
-inline vector<string> SyncRes::shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix)
+inline vector<string> SyncRes::shuffleInSpeedOrder(set<string, CIStringCompare> &tnameservers, const string &prefix)
{
vector<string> rnameservers;
- rnameservers.reserve(nameservers.size());
- map<string,double> speeds;
-
- for(set<string, CIStringCompare>::const_iterator i=nameservers.begin();i!=nameservers.end();++i) {
- rnameservers.push_back(*i);
+ rnameservers.reserve(tnameservers.size());
+ BOOST_FOREACH(const string& str, tnameservers) {
+ rnameservers.push_back(str);
+ }
+ map<string, double> speeds;
+ BOOST_FOREACH(const string& val, rnameservers) {
double speed;
- speed=t_sstorage->nsSpeeds[*i].get(&d_now);
- speeds[*i]=speed;
+ speed=t_sstorage->nsSpeeds[val].get(&d_now);
+ speeds[val]=speed;
}
random_shuffle(rnameservers.begin(),rnameservers.end(), dns_random);
speedOrder so(speeds);
stable_sort(rnameservers.begin(),rnameservers.end(), so);
- if(s_log) {
- L<<Logger::Warning<<prefix<<"Nameservers: ";
+ if(doLog()) {
+ LOG(prefix<<"Nameservers: ");
for(vector<string>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
if(i!=rnameservers.begin()) {
- L<<", ";
- if(!((i-rnameservers.begin())%3))
- L<<endl<<Logger::Warning<<prefix<<" ";
+ LOG(", ");
+ if(!((i-rnameservers.begin())%3)) {
+ LOG(endl<<prefix<<" ");
+ }
}
- L<<*i<<"(" << (int)(speeds[*i]/1000.0) <<"ms)";
+ LOG(*i<<"(" << (boost::format("%0.2f") % (speeds[*i]/1000.0)).str() <<"ms)");
}
- L<<endl;
+ LOG(endl);
}
return rnameservers;
}
@@ -765,36 +797,35 @@
return answer.getCode() == QType::A || answer.getCode() == QType::AAAA;
}
-double g_avgLatency;
-
/** returns -1 in case of no results, rcode otherwise */
int SyncRes::doResolveAt(set<string, CIStringCompare> nameservers, string auth, bool flawedNSSet, const string &qname, const QType &qtype,
vector<DNSResourceRecord>&ret,
int depth, set<GetBestNSAnswer>&beenthere)
{
string prefix;
- if(s_log) {
+ if(doLog()) {
prefix=d_prefix;
prefix.append(depth, ' ');
}
- LOG<<prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl;
+ LOG(prefix<<qname<<": Cache consultations done, have "<<(unsigned int)nameservers.size()<<" NS to contact"<<endl);
for(;;) { // we may get more specific nameservers
- vector<string> rnameservers=shuffleInSpeedOrder(nameservers, s_log ? (prefix+qname+": ") : string() );
-
- for(vector<string>::const_iterator tns=rnameservers.begin();;++tns) {
+ vector<string > rnameservers = shuffleInSpeedOrder(nameservers, doLog() ? (prefix+qname+": ") : string() );
+
+ for(vector<string >::const_iterator tns=rnameservers.begin();;++tns) {
if(tns==rnameservers.end()) {
- LOG<<prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl;
+ LOG(prefix<<qname<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth<<"'"<<endl);
if(auth!="." && flawedNSSet) {
- LOG<<prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl;
+ LOG(prefix<<qname<<": Ageing nameservers for level '"<<auth<<"', next query might succeed"<<endl);
if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
g_stats.nsSetInvalidations++;
}
return -1;
}
- if(qname==*tns && qtype.getCode()==QType::A) {
- LOG<<prefix<<qname<<": Not using NS to resolve itself!"<<endl;
+ // this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
+ if(pdns_iequals(qname, *tns) && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) {
+ LOG(prefix<<qname<<": Not using NS to resolve itself!"<<endl);
continue;
}
@@ -807,16 +838,16 @@
bool sendRDQuery=false;
LWResult lwr;
if(tns->empty()) {
- LOG<<prefix<<qname<<": Domain is out-of-band"<<endl;
+ LOG(prefix<<qname<<": Domain is out-of-band"<<endl);
doOOBResolve(qname, qtype, lwr.d_result, depth, lwr.d_rcode);
lwr.d_tcbit=false;
lwr.d_aabit=true;
}
else {
- LOG<<prefix<<qname<<": Trying to resolve NS '"<<*tns<<"' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl;
+ LOG(prefix<<qname<<": Trying to resolve NS '"<<*tns<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
if(!isCanonical(*tns)) {
- LOG<<prefix<<qname<<": Domain has hardcoded nameserver(s)"<<endl;
+ LOG(prefix<<qname<<": Domain has hardcoded nameserver(s)"<<endl);
string txtAddr = *tns;
if(!tns->empty()) {
@@ -829,63 +860,65 @@
pierceDontQuery=true;
}
else {
- remoteIPs=getAs(*tns, depth+1, beenthere);
+ remoteIPs=getAddrs(*tns, depth+2, beenthere);
pierceDontQuery=false;
}
if(remoteIPs.empty()) {
- LOG<<prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl;
+ LOG(prefix<<qname<<": Failed to get IP for NS "<<*tns<<", trying next if available"<<endl);
flawedNSSet=true;
continue;
}
else {
- LOG<<prefix<<qname<<": Resolved '"+auth+"' NS "<<*tns<<" to: ";
+
+ LOG(prefix<<qname<<": Resolved '"+auth+"' NS "<<*tns<<" to: ");
for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
- if(remoteIP != remoteIPs.begin())
- LOG<<", ";
- LOG<<remoteIP->toString();
+ if(remoteIP != remoteIPs.begin()) {
+ LOG(", ");
+ }
+ LOG(remoteIP->toString());
}
- LOG<<endl;
+ LOG(endl);
}
for(remoteIP = remoteIPs.begin(); remoteIP != remoteIPs.end(); ++remoteIP) {
- LOG<<prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl;
+ LOG(prefix<<qname<<": Trying IP "<< remoteIP->toStringWithPort() <<", asking '"<<qname<<"|"<<qtype.getName()<<"'"<<endl);
extern NetmaskGroup* g_dontQuery;
if(t_sstorage->throttle.shouldThrottle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()))) {
- LOG<<prefix<<qname<<": query throttled "<<endl;
+ LOG(prefix<<qname<<": query throttled "<<endl);
s_throttledqueries++; d_throttledqueries++;
continue;
}
else if(!pierceDontQuery && g_dontQuery && g_dontQuery->match(&*remoteIP)) {
- LOG<<prefix<<qname<<": not sending query to " << remoteIP->toString() << ", blocked by 'dont-query' setting" << endl;
+ LOG(prefix<<qname<<": not sending query to " << remoteIP->toString() << ", blocked by 'dont-query' setting" << endl);
+ s_dontqueries++;
continue;
}
else {
s_outqueries++; d_outqueries++;
TryTCP:
if(doTCP) {
- LOG<<prefix<<qname<<": using TCP with "<< remoteIP->toStringWithPort() <<endl;
+ LOG(prefix<<qname<<": using TCP with "<< remoteIP->toStringWithPort() <<endl);
s_tcpoutqueries++; d_tcpoutqueries++;
}
- resolveret=asyncresolveWrapper(*remoteIP, qname,
- (qtype.getCode() == QType::ADDR ? QType::ANY : qtype.getCode()),
+ resolveret=asyncresolveWrapper(*remoteIP, qname, qtype.getCode(),
doTCP, sendRDQuery, &d_now, &lwr); // <- we go out on the wire!
if(resolveret != 1) {
if(resolveret==0) {
- LOG<<prefix<<qname<<": timeout resolving "<< (doTCP ? "over TCP" : "")<<endl;
+ LOG(prefix<<qname<<": timeout resolving "<< (doTCP ? "over TCP" : "")<<endl);
d_timeouts++;
s_outgoingtimeouts++;
}
else if(resolveret==-2) {
- LOG<<prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl;
+ LOG(prefix<<qname<<": hit a local resource limit resolving"<< (doTCP ? " over TCP" : "")<<", probable error: "<<stringerror()<<endl);
g_stats.resourceLimits++;
}
else {
s_unreachables++; d_unreachables++;
- LOG<<prefix<<qname<<": error resolving"<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl;
+ LOG(prefix<<qname<<": error resolving"<< (doTCP ? " over TCP" : "") <<", possible error: "<<strerror(errno)<< endl);
}
if(resolveret!=-2) { // don't account for resource limits, they are our own fault
@@ -894,17 +927,23 @@
t_sstorage->nsSpeeds[*tns].submit(*remoteIP, 1000000, &d_now); // 1 sec
}
if(resolveret==-1)
- t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable
+ t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // unreachable, 1 minute or 100 queries
else
- t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 20, 5); // timeout
+ t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 10, 5); // timeout
}
continue;
}
+
+ if(lwr.d_rcode==RCode::ServFail || lwr.d_rcode==RCode::Refused) {
+ LOG(prefix<<qname<<": "<<*tns<<" returned a "<< (lwr.d_rcode==RCode::ServFail ? "ServFail" : "Refused") << ", trying sibling IP or NS"<<endl);
+ t_sstorage->throttle.throttle(d_now.tv_sec,make_tuple(*remoteIP, qname, qtype.getCode()),60,3); // servfail or refused
+ continue;
+ }
break; // this IP address worked!
wasLame:; // well, it didn't
- LOG<<prefix<<qname<<": status=NS "<<*tns<<" ("<< remoteIP->toString() <<") is lame for '"<<auth<<"', trying sibling IP or NS"<<endl;
- t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100);
+ LOG(prefix<<qname<<": status=NS "<<*tns<<" ("<< remoteIP->toString() <<") is lame for '"<<auth<<"', trying sibling IP or NS"<<endl);
+ t_sstorage->throttle.throttle(d_now.tv_sec, make_tuple(*remoteIP, qname, qtype.getCode()), 60, 100); // lame
}
}
@@ -914,27 +953,20 @@
if(lwr.d_tcbit) {
if(!doTCP) {
doTCP=true;
- LOG<<prefix<<qname<<": truncated bit set, retrying via TCP"<<endl;
+ LOG(prefix<<qname<<": truncated bit set, retrying via TCP"<<endl);
goto TryTCP;
}
- LOG<<prefix<<qname<<": truncated bit set, over TCP?"<<endl;
+ LOG(prefix<<qname<<": truncated bit set, over TCP?"<<endl);
return RCode::ServFail;
}
- if(lwr.d_rcode==RCode::ServFail) {
- LOG<<prefix<<qname<<": "<<*tns<<" returned a ServFail, trying sibling IP or NS"<<endl;
- t_sstorage->throttle.throttle(d_now.tv_sec,make_tuple(*remoteIP, qname, qtype.getCode()),60,3);
- continue;
- }
- LOG<<prefix<<qname<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<", in "<<lwr.d_usec/1000<<"ms"<<endl;
+ LOG(prefix<<qname<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<*tns<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<", aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
/* // for you IPv6 fanatics :-)
if(remoteIP->sin4.sin_family==AF_INET6)
lwr.d_usec/=3;
*/
// cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
- double fract = 0.001;
- g_avgLatency = (1-fract) * g_avgLatency + fract * lwr.d_usec;
t_sstorage->nsSpeeds[*tns].submit(*remoteIP, lwr.d_usec, &d_now);
}
@@ -945,23 +977,23 @@
// reap all answers from this packet that are acceptable
for(LWResult::res_t::iterator i=lwr.d_result.begin();i != lwr.d_result.end();++i) {
if(i->qtype.getCode() == QType::OPT) {
- LOG<<prefix<<qname<<": skipping OPT answer '"<<i->qname<<"' from '"<<auth<<"' nameservers" <<endl;
+ LOG(prefix<<qname<<": skipping OPT answer '"<<i->qname<<"' from '"<<auth<<"' nameservers" <<endl);
continue;
}
- LOG<<prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ";
+ LOG(prefix<<qname<<": accept answer '"<<i->qname<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth<<"' nameservers? ");
if(i->qtype.getCode()==QType::ANY) {
- LOG<<"NO! - we don't accept 'ANY' data"<<endl;
+ LOG("NO! - we don't accept 'ANY' data"<<endl);
continue;
}
if(dottedEndsOn(i->qname, auth)) {
if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth)) {
- LOG<<"NO! Is from delegation-only zone"<<endl;
+ LOG("NO! Is from delegation-only zone"<<endl);
s_nodelegated++;
return RCode::NXDomain;
}
else {
- LOG<<"YES!"<<endl;
+ LOG("YES!"<<endl);
i->ttl=min(s_maxcachettl, i->ttl);
@@ -977,13 +1009,13 @@
}
}
else
- LOG<<"NO!"<<endl;
+ LOG("NO!"<<endl);
}
// supplant
for(tcache_t::iterator i=tcache.begin();i!=tcache.end();++i) {
if(i->second.size() > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
- uint32_t lowestTTL=numeric_limits<uint32_t>::max();
+ uint32_t lowestTTL=std::numeric_limits<uint32_t>::max();
for(tcache_t::value_type::second_type::iterator j=i->second.begin(); j != i->second.end(); ++j)
lowestTTL=min(lowestTTL, j->ttl);
@@ -994,21 +1026,26 @@
t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second, lwr.d_aabit);
}
set<string, CIStringCompare> nsset;
- LOG<<prefix<<qname<<": determining status after receiving this packet"<<endl;
+ LOG(prefix<<qname<<": determining status after receiving this packet"<<endl);
bool done=false, realreferral=false, negindic=false;
string newauth, soaname, newtarget;
- for(LWResult::res_t::const_iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) {
- if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
- lwr.d_rcode==RCode::NXDomain) {
- LOG<<prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"'"<<endl;
- ret.push_back(*i);
+ for(LWResult::res_t::iterator i=lwr.d_result.begin();i!=lwr.d_result.end();++i) {
+ if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::SOA &&
+ lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,i->qname) && dottedEndsOn(i->qname, auth)) {
+ LOG(prefix<<qname<<": got negative caching indication for RECORD '"<<qname+"' (accept="<<dottedEndsOn(i->qname, auth)<<"), newtarget='"<<newtarget<<"'"<<endl);
+
+ i->ttl = min(i->ttl, s_maxnegttl);
+ if(!newtarget.length()) // only add a SOA if we're not going anywhere after this
+ ret.push_back(*i);
NegCacheEntry ne;
ne.d_qname=i->qname;
- ne.d_ttd=d_now.tv_sec + min(i->ttl, s_maxnegttl); // controversial
+
+ ne.d_ttd=d_now.tv_sec + i->ttl;
+
ne.d_name=qname;
ne.d_qtype=QType(0); // this encodes 'whole record'
@@ -1020,15 +1057,15 @@
ret.push_back(*i);
newtarget=i->content;
}
- // for ANY answers we *must* have an authoritive answer
+ // for ANY answers we *must* have an authoritive answer, unless we are forwarding recursively
else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) &&
(
- i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) )
+ i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) ) || sendRDQuery
)
)
{
- LOG<<prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl;
+ LOG(prefix<<qname<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
done=true;
ret.push_back(*i);
@@ -1036,64 +1073,69 @@
else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::NS) {
if(moreSpecificThan(i->qname,auth)) {
newauth=i->qname;
- LOG<<prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl;
+ LOG(prefix<<qname<<": got NS record '"<<i->qname<<"' -> '"<<i->content<<"'"<<endl);
realreferral=true;
}
else
- LOG<<prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl;
+ LOG(prefix<<qname<<": got upwards/level NS record '"<<i->qname<<"' -> '"<<i->content<<"', had '"<<auth<<"'"<<endl);
nsset.insert(i->content);
}
else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
lwr.d_rcode==RCode::NoError) {
- LOG<<prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+i->qtype.getName()+"'") <<endl;
- if(!newtarget.empty())
- ret.push_back(*i);
+ LOG(prefix<<qname<<": got negative caching indication for '"<< (qname+"|"+qtype.getName()+"'") <<endl);
- NegCacheEntry ne;
- ne.d_qname=i->qname;
- ne.d_ttd=d_now.tv_sec + min(s_maxnegttl, i->ttl);
- ne.d_name=qname;
- ne.d_qtype=qtype;
- if(qtype.getCode()) { // prevents us from blacking out a whole domain
- replacing_insert(t_sstorage->negcache, ne);
+ if(!newtarget.empty()) {
+ LOG(prefix<<qname<<": Hang on! Got a redirect to '"<<newtarget<<"' already"<<endl);
+ }
+ else {
+ i-> ttl = min(s_maxnegttl, i->ttl);
+ ret.push_back(*i);
+ NegCacheEntry ne;
+ ne.d_qname=i->qname;
+ ne.d_ttd=d_now.tv_sec + i->ttl;
+ ne.d_name=qname;
+ ne.d_qtype=qtype;
+ if(qtype.getCode()) { // prevents us from blacking out a whole domain
+ replacing_insert(t_sstorage->negcache, ne);
+ }
+ negindic=true;
}
- negindic=true;
}
}
if(done){
- LOG<<prefix<<qname<<": status=got results, this level of recursion done"<<endl;
+ LOG(prefix<<qname<<": status=got results, this level of recursion done"<<endl);
return 0;
}
- if(lwr.d_rcode==RCode::NXDomain) {
- LOG<<prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl;
- return RCode::NXDomain;
- }
if(!newtarget.empty()) {
if(pdns_iequals(newtarget,qname)) {
- LOG<<prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl;
+ LOG(prefix<<qname<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
return RCode::ServFail;
}
if(depth > 10) {
- LOG<<prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl;
+ LOG(prefix<<qname<<": status=got a CNAME referral, but recursing too deep, returning SERVFAIL"<<endl);
return RCode::ServFail;
}
- LOG<<prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl;
+ LOG(prefix<<qname<<": status=got a CNAME referral, starting over with "<<newtarget<<endl);
set<GetBestNSAnswer> beenthere2;
return doResolve(newtarget, qtype, ret, depth + 1, beenthere2);
}
- if(nsset.empty() && !lwr.d_rcode) {
- LOG<<prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA)" : "")<<endl;
+ if(lwr.d_rcode==RCode::NXDomain) {
+ LOG(prefix<<qname<<": status=NXDOMAIN, we are done "<<(negindic ? "(have negative SOA)" : "")<<endl);
+ return RCode::NXDomain;
+ }
+ if(nsset.empty() && !lwr.d_rcode && (negindic || lwr.d_aabit)) {
+ LOG(prefix<<qname<<": status=noerror, other types may exist, but we are done "<<(negindic ? "(have negative SOA) " : "")<<(lwr.d_aabit ? "(have aa bit) " : "")<<endl);
return 0;
}
else if(realreferral) {
- LOG<<prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl;
+ LOG(prefix<<qname<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl);
auth=newauth;
nameservers=nsset;
break;
}
- else if(isCanonical(*tns)) {
+ else if(isCanonical(*tns)) { // means: not OOB (I think)
goto wasLame;
}
}
@@ -1112,20 +1154,17 @@
if(k->d_place==DNSResourceRecord::AUTHORITY && k->qtype==QType(QType::SOA))
return;
- // LOG<<qname<<": Adding best authority records from cache"<<endl;
+ // LOG(qname<<": Adding best authority records from cache"<<endl);
// addAuthorityRecords(qname,ret,0);
- // LOG<<qname<<": Done adding best authority records."<<endl;
+ // LOG(qname<<": Done adding best authority records."<<endl);
- LOG<<d_prefix<<qname<<": Starting additional processing"<<endl;
+ LOG(d_prefix<<qname<<": Starting additional processing"<<endl);
vector<DNSResourceRecord> addit;
- static optional<bool> l_doIPv6AP;
- if(!l_doIPv6AP)
- l_doIPv6AP=::arg().mustDo("aaaa-additional-processing");
for(vector<DNSResourceRecord>::const_iterator k=ret.begin();k!=ret.end();++k)
if( (k->d_place==DNSResourceRecord::ANSWER && (k->qtype==QType(QType::MX) || k->qtype==QType(QType::SRV))) ||
((k->d_place==DNSResourceRecord::AUTHORITY || k->d_place==DNSResourceRecord::ANSWER) && k->qtype==QType(QType::NS))) {
- LOG<<d_prefix<<qname<<": record '"<<k->content<<"|"<<k->qtype.getName()<<"' needs IP for additional processing"<<endl;
+ LOG(d_prefix<<qname<<": record '"<<k->content<<"|"<<k->qtype.getName()<<"' needs IP for additional processing"<<endl);
set<GetBestNSAnswer> beenthere;
vector<pair<string::size_type, string::size_type> > fields;
vstringtok(fields, k->content, " ");
@@ -1138,7 +1177,8 @@
host=string(k->content.c_str() + fields[3].first, fields[3].second - fields[3].first);
else
continue;
- doResolve(host, *l_doIPv6AP ? QType(QType::ADDR) : QType(QType::A), addit, 1, beenthere);
+ // we used to do additional processing here.. no more
+ // doResolve(host, QType(QType::A), addit, 1, beenthere);
}
if(!addit.empty()) {
@@ -1151,7 +1191,7 @@
}
}
}
- LOG<<d_prefix<<qname<<": Done with additional processing"<<endl;
+ LOG(d_prefix<<qname<<": Done with additional processing"<<endl);
}
void SyncRes::addAuthorityRecords(const string& qname, vector<DNSResourceRecord>& ret, int depth)
@@ -1168,3 +1208,15 @@
ret.push_back(ns);
}
}
+
+// used by PowerDNSLua
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret)
+{
+ struct timeval now;
+ gettimeofday(&now, 0);
+
+ SyncRes sr(now);
+
+ int res = sr.beginResolve(qname, QType(qtype), qclass, ret);
+ return res;
+}
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/syncres.hh
^
|
@@ -29,6 +29,10 @@
QType d_qtype;
string d_qname;
uint32_t d_ttd;
+ uint32_t getTTD() const
+ {
+ return d_ttd;
+ }
};
@@ -60,6 +64,7 @@
return false;
if(now > i->second.ttd || i->second.count-- < 0) {
d_cont.erase(i);
+ return false;
}
return true; // still listed, still blocked
@@ -129,14 +134,17 @@
if(d_needinit) {
d_last=now;
+ d_lastget=now;
d_needinit=false;
+ d_val = val;
}
+ else {
+ float diff= makeFloat(d_last - now);
- float diff= makeFloat(d_last - now);
-
- d_last=now;
- double factor=exp(diff)/2.0; // might be '0.5', or 0.0001
- d_val=(float)((1-factor)*val+ (float)factor*d_val);
+ d_last=now;
+ double factor=exp(diff)/2.0; // might be '0.5', or 0.0001
+ d_val=(float)((1-factor)*val+ (float)factor*d_val);
+ }
}
double get(struct timeval* tv)
@@ -148,6 +156,11 @@
return d_val*=factor;
}
+ double peek(void)
+ {
+ return d_val;
+ }
+
bool stale(time_t limit) const
{
return limit > d_lastget.tv_sec;
@@ -164,18 +177,31 @@
class SyncRes : public boost::noncopyable
{
public:
+ enum LogMode { LogNone, Log, Store};
+
explicit SyncRes(const struct timeval& now);
int beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
void setId(int id)
{
- if(s_log)
+ if(doLog())
d_prefix="["+itoa(id)+"] ";
}
- static void setLog(bool log)
+ static void setDefaultLogMode(LogMode lm)
+ {
+ s_lm = lm;
+ }
+
+ void setLogMode(LogMode lm)
+ {
+ d_lm = lm;
+ }
+
+ bool doLog()
{
- s_log=log;
+ return d_lm != LogNone;
}
+
void setCacheOnly(bool state=true)
{
d_cacheonly=state;
@@ -190,7 +216,10 @@
d_doEDNS0=state;
}
-
+ string getTrace() const
+ {
+ return d_trace.str();
+ }
int asyncresolveWrapper(const ComboAddress& ip, const string& domain, int type, bool doTCP, bool sendRDQuery, struct timeval* now, LWResult* res);
@@ -199,10 +228,13 @@
static unsigned int s_queries;
static unsigned int s_outgoingtimeouts;
static unsigned int s_throttledqueries;
+ static unsigned int s_dontqueries;
static unsigned int s_outqueries;
static unsigned int s_tcpoutqueries;
static unsigned int s_nodelegated;
static unsigned int s_unreachables;
+ static bool s_doAAAAAdditionalProcessing;
+ static bool s_doAdditionalProcessing;
static bool s_doIPv6;
unsigned int d_outqueries;
unsigned int d_tcpoutqueries;
@@ -223,13 +255,11 @@
>,
composite_key_compare<CIStringCompare, std::less<QType> >
>,
- ordered_non_unique<
- member<NegCacheEntry, uint32_t, &NegCacheEntry::d_ttd>
- >
+ sequenced<>
>
> negcache_t;
- //! This represents a number of decaying Ewmas, used to store performance per namerserver-name.
+ //! This represents a number of decaying Ewmas, used to store performance per nameserver-name.
/** Modelled to work mostly like the underlying DecayingEwma. After you've called get,
d_best is filled out with the best address for this collection */
struct DecayingEwmaCollection
@@ -254,7 +284,7 @@
{
if(d_collection.empty())
return 0;
- double ret=numeric_limits<double>::max();
+ double ret=std::numeric_limits<double>::max();
double tmp;
for(collection_t::iterator pos=d_collection.begin(); pos != d_collection.end(); ++pos) {
if((tmp=pos->second.get(now)) < ret) {
@@ -279,8 +309,7 @@
ComboAddress d_best;
};
- typedef map<string, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;
-
+ typedef map<string, DecayingEwmaCollection, CIStringCompare> nsspeeds_t;
struct EDNSStatus
{
@@ -292,8 +321,6 @@
typedef map<ComboAddress, EDNSStatus> ednsstatus_t;
-
-
static bool s_noEDNSPing;
static bool s_noEDNS;
@@ -329,7 +356,8 @@
static unsigned int s_packetcacheservfailttl;
static bool s_nopacketcache;
static string s_serverID;
-
+
+
struct StaticStorage {
negcache_t negcache;
nsspeeds_t nsSpeeds;
@@ -354,14 +382,16 @@
inline vector<string> shuffleInSpeedOrder(set<string, CIStringCompare> &nameservers, const string &prefix);
bool moreSpecificThan(const string& a, const string &b);
- vector<ComboAddress> getAs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);
+ vector<ComboAddress> getAddrs(const string &qname, int depth, set<GetBestNSAnswer>& beenthere);
private:
+ ostringstream d_trace;
string d_prefix;
- static bool s_log;
bool d_cacheonly;
bool d_nocache;
bool d_doEDNS0;
+ static LogMode s_lm;
+ LogMode d_lm;
struct GetBestNSAnswer
{
@@ -428,7 +458,7 @@
}
};
-struct PacketIDBirthdayCompare: public binary_function<PacketID, PacketID, bool>
+struct PacketIDBirthdayCompare: public std::binary_function<PacketID, PacketID, bool>
{
bool operator()(const PacketID& a, const PacketID& b) const
{
@@ -456,6 +486,7 @@
uint64_t answers0_1, answers1_10, answers10_100, answers100_1000, answersSlow;
uint64_t avgLatencyUsec;
uint64_t qcounter;
+ uint64_t ipv6qcounter;
uint64_t tcpqcounter;
uint64_t unauthorizedUDP;
uint64_t unauthorizedTCP;
@@ -476,8 +507,33 @@
uint64_t packetCacheHits;
uint64_t noPacketError;
time_t startupTime;
+ unsigned int maxMThreadStackUsage;
};
+//! represents a running TCP/IP client session
+class TCPConnection : public boost::noncopyable
+{
+public:
+ TCPConnection(int fd, const ComboAddress& addr);
+ ~TCPConnection();
+
+ int getFD()
+ {
+ return d_fd;
+ }
+ enum stateenum {BYTE0, BYTE1, GETQUESTION, DONE} state;
+ int qlen;
+ int bytesread;
+ const ComboAddress d_remote;
+ char data[65535]; // damn
+
+ static unsigned int getCurrentConnections() { return s_currentConnections; }
+private:
+ const int d_fd;
+ static AtomicCounter s_currentConnections; //!< total number of current TCP connections
+};
+
+
struct RemoteKeeper
{
typedef vector<ComboAddress> remotes_t;
@@ -493,26 +549,19 @@
};
extern __thread RemoteKeeper* t_remotes;
string doQueueReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
+string doTraceRegex(vector<string>::const_iterator begin, vector<string>::const_iterator end);
void parseACLs();
extern RecursorStats g_stats;
extern unsigned int g_numThreads;
-template<typename Index>
-std::pair<typename Index::iterator,bool>
-replacing_insert(Index& i,const typename Index::value_type& x)
-{
- std::pair<typename Index::iterator,bool> res=i.insert(x);
- if(!res.second)res.second=i.replace(res.first,x);
- return res;
-}
-
-
std::string reloadAuthAndForwards();
ComboAddress parseIPAndPort(const std::string& input, uint16_t port);
ComboAddress getQueryLocalAddress(int family, uint16_t port);
typedef boost::function<void*(void)> pipefunc_t;
void broadcastFunction(const pipefunc_t& func, bool skipSelf = false);
+void distributeAsyncFunction(const pipefunc_t& func);
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
@@ -527,5 +576,7 @@
uint64_t* pleaseGetThrottleSize();
uint64_t* pleaseGetPacketCacheHits();
uint64_t* pleaseGetPacketCacheSize();
+uint64_t* pleaseWipeCache(const std::string& canon);
+uint64_t* pleaseWipeAndCountNegCache(const std::string& canon);
#endif
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sysdeps/Darwin.inc
^
|
@@ -1,4 +1,4 @@
-CXXFLAGS+=-D_XOPEN_SOURCE
+CXXFLAGS+=-D_XOPEN_SOURCE -DHAVE_STRCASESTR
LUA_CPPFLAGS_CONFIG ?= -I/usr/include/lua5.1
LUA_LIBS_CONFIG ?= -llua5.1 -rdynamic
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sysdeps/FreeBSD.inc
^
|
@@ -1,4 +1,4 @@
-CXXFLAGS+=-I/usr/local/include/
+CXXFLAGS+=-I/usr/local/include/ -DHAVE_STRCASESTR
OPTIONALS:=optional/kqueuemplexer.o
optional/kqueuemplexer.o: kqueuemplexer.cc
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sysdeps/Linux.inc
^
|
@@ -5,7 +5,7 @@
CC:=gcc
endif
-CXXFLAGS := $(CXXFLAGS) -D_GNU_SOURCE
+CXXFLAGS := $(CXXFLAGS) -D_GNU_SOURCE -DHAVE_STRCASESTR
CFLAGS := $(CFLAGS) -D_GNU_SOURCE
LUA_CPPFLAGS_CONFIG ?= -I/usr/include/lua5.1
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/sysdeps/SunOS.inc
^
|
@@ -2,13 +2,17 @@
CC:=gcc
endif
-LDFLAGS+=-lresolv -lsocket -lnsl -ldl
+LDFLAGS+=-lresolv -lsocket -lnsl -ldl
OS_SPECIFIC_INSTALL=mkdir -p $(DESTDIR)/etc/init.d ; cp pdns-recursor.init.d $(DESTDIR)/etc/init.d/pdns-recursor
LUA_LIBS_CONFIG ?= -llua
CXXFLAGS+= -D__MAKECONTEXT_V2_SOURCE
+ifeq ($(shell uname -r),5.11)
+ CXXFLAGS+= -DHAVE_STRCASESTR
+endif
+
OPTIONALS:=optional/portsmplexer.o optional/devpollmplexer.o
optional/portsmplexer.o: portsmplexer.cc
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/unix_utility.cc
^
|
@@ -1,6 +1,6 @@
/*
PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002 - 2009 PowerDNS.COM BV
+ Copyright (C) 2002 - 2011 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 version 2 as
@@ -35,7 +35,7 @@
#endif
-using namespace std;
+#include "namespaces.hh"
// Closes a socket.
int Utility::closesocket( Utility::sock_t socket )
@@ -64,6 +64,14 @@
return true;
}
+bool Utility::setCloseOnExec(sock_t sock)
+{
+ int flags=fcntl(sock,F_GETFD,0);
+ if(flags<0 || fcntl(sock, F_SETFD,flags|FD_CLOEXEC) <0)
+ return false;
+ return true;
+}
+
const char *Utility::inet_ntop(int af, const char *src, char *dst, size_t size)
{
return ::inet_ntop(af,src,dst,size);
@@ -91,6 +99,11 @@
else
theL()<<Logger::Info<<"Set effective group id to "<<gid<<endl;
+ if(setgroups(0, NULL)<0) {
+ theL()<<Logger::Critical<<"Unable to drop supplementary gids: "<<stringerror()<<endl;
+ exit(1);
+ }
+
}
if(uid) {
@@ -137,9 +150,10 @@
{
int newgid;
if(!(newgid=atoi(group.c_str()))) {
+ errno=0;
struct group *gr=getgrnam(group.c_str());
if(!gr) {
- theL()<<Logger::Critical<<"Unable to look up gid of group '"<<group<<"': "<<strerror(errno)<<endl;
+ theL()<<Logger::Critical<<"Unable to look up gid of group '"<<group<<"': "<< (errno ? strerror(errno) : "not found") <<endl;
exit(1);
}
newgid=gr->gr_gid;
@@ -155,7 +169,7 @@
if(!(newuid=atoi(username.c_str()))) {
struct passwd *pw=getpwnam(username.c_str());
if(!pw) {
- theL()<<Logger::Critical<<"Unable to look up uid of user '"<<username<<"': "<<strerror(errno)<<endl;
+ theL()<<Logger::Critical<<"Unable to look up uid of user '"<<username<<"': "<< (errno ? strerror(errno) : "not found") <<endl;
exit(1);
}
newuid=pw->pw_uid;
@@ -183,3 +197,75 @@
return ::writev(socket,vector,count);
}
+/* this is cut and pasted from dietlibc, gratefully copied! */
+static int isleap(int year) {
+ /* every fourth year is a leap year except for century years that are
+ * not divisible by 400. */
+ return (!(year%4) && ((year%100) || !(year%400)));
+}
+
+time_t Utility::timegm(struct tm *const t)
+{
+ const static short spm[13] = /* days per month -- nonleap! */
+ { 0,
+ (31),
+ (31+28),
+ (31+28+31),
+ (31+28+31+30),
+ (31+28+31+30+31),
+ (31+28+31+30+31+30),
+ (31+28+31+30+31+30+31),
+ (31+28+31+30+31+30+31+31),
+ (31+28+31+30+31+30+31+31+30),
+ (31+28+31+30+31+30+31+31+30+31),
+ (31+28+31+30+31+30+31+31+30+31+30),
+ (31+28+31+30+31+30+31+31+30+31+30+31),
+ };
+
+ time_t day;
+ time_t i;
+ time_t years = t->tm_year - 70;
+
+ if (t->tm_sec>60) { t->tm_min += t->tm_sec/60; t->tm_sec%=60; }
+ if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; }
+ if (t->tm_hour>60) { t->tm_mday += t->tm_hour/60; t->tm_hour%=60; }
+ if (t->tm_mon>12) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; }
+
+ while (t->tm_mday>spm[1+t->tm_mon]) {
+ if (t->tm_mon==1 && isleap(t->tm_year+1900)) {
+ if (t->tm_mon==31+29) break;
+ --t->tm_mday;
+ }
+ t->tm_mday-=spm[t->tm_mon];
+ ++t->tm_mon;
+ if (t->tm_mon>11) { t->tm_mon=0; ++t->tm_year; }
+ }
+
+ if (t->tm_year < 70)
+ return (time_t) -1;
+ /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
+ day = years * 365 + (years + 1) / 4;
+
+ /* After 2100 we have to substract 3 leap years for every 400 years
+ This is not intuitive. Most mktime implementations do not support
+ dates after 2059, anyway, so we might leave this out for it's
+ bloat. */
+ if ((years -= 131) >= 0) {
+ years /= 100;
+ day -= (years >> 2) * 3 + 1;
+ if ((years &= 3) == 3) years--;
+ day -= years;
+ }
+
+ day += t->tm_yday = spm [t->tm_mon] + t->tm_mday-1 + ( isleap (t->tm_year+1900) & (t->tm_mon > 1) );
+
+ /* day is now the number of days since 'Jan 1 1970' */
+ i = 7;
+ t->tm_wday = (day + 4) % i; /* Sunday=0, Monday=1, ..., Saturday=6 */
+
+ i = 24;
+ day *= i;
+ i = 60;
+ return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
+}
+
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/utility.hh
^
|
@@ -71,7 +71,7 @@
#endif // WIN32
#include <string>
-using namespace std;
+#include "namespaces.hh"
//! A semaphore class.
class Semaphore
@@ -196,11 +196,16 @@
//! Sets the socket into non-blocking mode.
static bool setNonBlocking( Utility::sock_t socket );
+ //! Marks the socket to be closed on exec().
+ static bool setCloseOnExec ( Utility::sock_t socket );
+
//! Sleeps for a number of seconds.
static unsigned int sleep( unsigned int seconds );
//! Sleeps for a number of microseconds.
static void usleep( unsigned long usec );
+
+ static time_t timegm(struct tm *tm);
};
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/win32_logger.cc
^
|
@@ -21,7 +21,7 @@
#include "logger.hh"
#include "ntservice.hh"
#include "pdnsmsg.hh"
-using namespace std;
+#include "namespaces.hh"
Logger &theL(const string &pname)
{
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/win32_mtasker.cc
^
|
@@ -52,7 +52,7 @@
\section events Events
By default, Events are recognized by an int and their value is also an int.
- This can be overriden by specifying the EventKey and EventVal template parameters.
+ This can be overridden by specifying the EventKey and EventVal template parameters.
An event can be a keypress, but also a UDP packet, or a bit of data from a TCP socket. The
sample code provided works with keypresses, but that is just a not very useful example.
@@ -126,7 +126,7 @@
//! puts a thread to sleep waiting until a specified event arrives
/** Threads can call waitEvent to register that they are waiting on an event with a certain key.
- If so desidered, the event can carry data which is returned in val in case that is non-zero.
+ If so desired, the event can carry data which is returned in val in case that is non-zero.
Furthermore, a timeout can be specified in seconds.
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/win32_rec_channel.cc
^
|
@@ -6,7 +6,7 @@
#include "ahuexception.hh"
-using namespace std;
+#include "namespaces.hh"
RecursorControlChannel::RecursorControlChannel()
{
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/win32_utility.cc
^
|
@@ -364,6 +364,12 @@
return true;
}
+// Marks the socket to be closed on exec().
+// No-op on Windows.
+bool Utility::setCloseOnExec(sock_t sock)
+{
+ return true;
+}
// Sleeps for a number of seconds.
unsigned int Utility::sleep( unsigned int seconds )
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/zoneparser-tng.cc
^
|
@@ -225,6 +225,7 @@
return "on line "+lexical_cast<string>(d_filestates.top().d_lineno)+" of file '"+d_filestates.top().d_filename+"'";
}
+// ODD: this function never fills out the prio field! rest of pdns compensates though
bool ZoneParserTNG::get(DNSResourceRecord& rr)
{
retry:;
@@ -365,35 +366,59 @@
}
}
- vector<string> soaparts;
+ vector<string> recparts;
switch(rr.qtype.getCode()) {
case QType::MX:
+ stringtok(recparts, rr.content);
+ if(recparts.size()==2) {
+ recparts[1] = stripDot(toCanonic(d_zonename, recparts[1]));
+ rr.content=recparts[0]+" "+recparts[1];
+ }
+ break;
+
+ case QType::RP:
+ stringtok(recparts, rr.content);
+ if(recparts.size()==2) {
+ recparts[0] = stripDot(toCanonic(d_zonename, recparts[0]));
+ recparts[1] = stripDot(toCanonic(d_zonename, recparts[1]));
+ rr.content=recparts[0]+" "+recparts[1];
+ }
+ break;
+
+ case QType::SRV:
+ stringtok(recparts, rr.content);
+ if(recparts.size()==4) {
+ recparts[3] = stripDot(toCanonic(d_zonename, recparts[3]));
+ rr.content=recparts[0]+" "+recparts[1]+" "+recparts[2]+" "+recparts[3];
+ }
+ break;
+
+
case QType::NS:
case QType::CNAME:
case QType::PTR:
- case QType::SRV:
case QType::AFSDB:
- rr.content=toCanonic(d_zonename, rr.content);
+ rr.content=stripDot(toCanonic(d_zonename, rr.content));
break;
case QType::SOA:
- stringtok(soaparts, rr.content);
- if(soaparts.size() > 1) {
- soaparts[0]=toCanonic(d_zonename, soaparts[0]);
- soaparts[1]=toCanonic(d_zonename, soaparts[1]);
+ stringtok(recparts, rr.content);
+ if(recparts.size() > 1) {
+ recparts[0]=toCanonic(d_zonename, recparts[0]);
+ recparts[1]=toCanonic(d_zonename, recparts[1]);
}
rr.content.clear();
- for(string::size_type n = 0; n < soaparts.size(); ++n) {
+ for(string::size_type n = 0; n < recparts.size(); ++n) {
if(n)
rr.content.append(1,' ');
if(n > 1)
- rr.content+=lexical_cast<string>(makeTTLFromZone(soaparts[n]));
+ rr.content+=lexical_cast<string>(makeTTLFromZone(recparts[n]));
else
- rr.content+=soaparts[n];
+ rr.content+=recparts[n];
if(n==6 && !d_havedollarttl)
- d_defaultttl=makeTTLFromZone(soaparts[n]);
+ d_defaultttl=makeTTLFromZone(recparts[n]);
}
break;
default:;
@@ -403,13 +428,12 @@
return true;
}
+
bool ZoneParserTNG::getLine()
{
while(!d_filestates.empty()) {
- char buffer[1024];
- if(fgets(buffer, 1024, d_filestates.top().d_fp)) {
+ if(stringfgets(d_filestates.top().d_fp, d_line)) {
d_filestates.top().d_lineno++;
- d_line=buffer;
return true;
}
fclose(d_filestates.top().d_fp);
|
[-]
[+]
|
Changed |
pdns-recursor-3.5.2.tar.bz2/zoneparser-tng.hh
^
|
@@ -23,7 +23,7 @@
#include <stdexcept>
#include <stack>
-using namespace std;
+#include "namespaces.hh"
class ZoneParserTNG
{
@@ -57,7 +57,7 @@
string d_filename;
int d_lineno;
};
- stack<filestate> d_filestates;
+ std::stack<filestate> d_filestates;
};
#endif
|
|
Changed |
pdns-recursor-3.5.3.tar.bz2
^
|
|
Added |
pdns-recursor-3.6.0.tar.bz2
^
|
|
Changed |
pdns-recursor-3.6.1.tar.bz2
^
|
|
Changed |
pdns-recursor-3.6.2.tar.bz2
^
|
|
Changed |
pdns-recursor-3.7.1.tar.bz2
^
|