]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
blah
authorBert Hubert <bert.hubert@netherlabs.nl>
Wed, 27 Nov 2002 15:29:50 +0000 (15:29 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Wed, 27 Nov 2002 15:29:50 +0000 (15:29 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@7 d19b8d6e-7fed-0310-83ef-9ca221ded41b

modules/mysqlbackend/INSTALL [new file with mode: 0644]
modules/mysqlbackend/Makefile.am [new file with mode: 0644]
modules/mysqlbackend/bootstrap [new file with mode: 0755]
modules/mysqlbackend/configure.in [new file with mode: 0644]
modules/mysqlbackend/mysqlcbackend.cc [new file with mode: 0644]
modules/mysqlbackend/mysqlcbackend.hh [new file with mode: 0644]

diff --git a/modules/mysqlbackend/INSTALL b/modules/mysqlbackend/INSTALL
new file mode 100644 (file)
index 0000000..931a973
--- /dev/null
@@ -0,0 +1,7 @@
+First run ./configure and point it at your powerdns sources. Furthermore,
+tell it where it should install the produced .so file so it can be found at
+runtime.
+
+Example and probable line:
+
+./configure --with-pdns-includes=../pdns-2.9 --libdir=/usr/lib/powerdns/
diff --git a/modules/mysqlbackend/Makefile.am b/modules/mysqlbackend/Makefile.am
new file mode 100644 (file)
index 0000000..83e0d6b
--- /dev/null
@@ -0,0 +1,5 @@
+lib_LTLIBRARIES = libmysqlbackend.la 
+
+libmysqlbackend_la_SOURCES=mysqlcbackend.cc mysqlcbackend.hh 
+libmysqlbackend_la_LDFLAGS=-lmysqlclient
+
diff --git a/modules/mysqlbackend/bootstrap b/modules/mysqlbackend/bootstrap
new file mode 100755 (executable)
index 0000000..ab9da12
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/sh
+echo You may have to run this twice
+aclocal
+autoconf
+autoheader
+automake --add-missing --foreign
+
diff --git a/modules/mysqlbackend/configure.in b/modules/mysqlbackend/configure.in
new file mode 100644 (file)
index 0000000..47f6cb6
--- /dev/null
@@ -0,0 +1,236 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(mysqlcbackend.cc)
+AC_CANONICAL_SYSTEM
+AM_INIT_AUTOMAKE(mysqlbackend, 2.9)
+
+AC_PREFIX_DEFAULT(/usr)
+AC_PROG_CC
+AC_PROG_CXX
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+AC_DISABLE_STATIC
+AM_PROG_LIBTOOL
+AC_LANG_CPLUSPLUS
+
+#
+# Location of MySQL installation
+#
+AC_ARG_WITH(mysql,
+    [  --with-mysql=<path>     root directory path of MySQL installation],
+    [MYSQL_lib_check="$withval/lib/mysql $with_mysql/lib"
+MYSQL_inc_check="$withval/include/mysql"],
+    [MYSQL_lib_check="/usr/local/mysql/lib/mysql /usr/local/lib/mysql /opt/mysql/lib/mysql /usr/lib/mysql /usr/local/mysql/lib /usr/local/lib /opt/mysql/lib /usr/lib"
+MYSQL_inc_check="/usr/local/mysql/include/mysql /usr/local/include/mysql /opt/mysql/include/mysql /opt/mysql/include /usr/include/mysql"])
+
+AC_ARG_WITH(mysql-lib,
+    [  --with-mysql-lib=<path> directory path of MySQL library installation],
+    [MYSQL_lib_check="$withval/lib/mysql $withval/mysql $withval"])
+
+AC_ARG_WITH(mysql-includes,
+    [  --with-mysql-includes=<path>
+                          directory path of MySQL header installation],
+    [MYSQL_inc_check="$withval/include/mysql $withval/mysql $withval"])
+
+AC_MSG_CHECKING([for MySQL library directory])
+MYSQL_libdir=
+for m in $MYSQL_lib_check; do
+        if test -d "$m" && \
+          (test -f "$m/libmysqlclient.so" || test -f "$m/libmysqlclient.a")
+        then
+                MYSQL_libdir=$m
+                break
+        fi
+done
+
+if test -z "$MYSQL_libdir"; then
+        AC_MSG_ERROR([Didn't find the mysql library dir in '$MYSQL_lib_check'])
+fi
+
+case "$MYSQL_libdir" in
+  /* ) ;;
+  * )  AC_MSG_ERROR([The MySQL library directory ($MYSQL_libdir) must be an absolute path.]) ;;
+esac
+
+AC_MSG_RESULT([$MYSQL_libdir])
+
+case "$MYSQL_libdir" in
+  /usr/lib) ;;
+  *) LDFLAGS="$LDFLAGS -L${MYSQL_libdir}" ;;
+esac
+
+AC_MSG_CHECKING([for MySQL include directory])
+MYSQL_incdir=
+for m in $MYSQL_inc_check; do
+        if test -d "$m" && test -f "$m/mysql.h"
+        then
+                MYSQL_incdir=$m
+                break
+        fi
+done
+
+if test -z "$MYSQL_incdir"; then
+        AC_MSG_ERROR([Didn't find the mysql include dir in '$MYSQL_inc_check'])
+fi
+
+case "$MYSQL_incdir" in
+  /* ) ;;
+  * )  AC_MSG_ERROR([The MySQL include directory ($MYSQL_incdir) must be an absolute path.]) ;;
+esac
+
+AC_MSG_RESULT([$MYSQL_incdir])
+
+CPPFLAGS="$CPPFLAGS -I${MYSQL_incdir}"
+
+dnl Checks for programs.
+
+dnl Checks for libraries.
+dnl Replace `main' with a function in -ldl:
+AC_CHECK_LIB(dl, main)
+AC_CHECK_LIB(z, main)
+AC_CHECK_LIB(mysqlclient, mysql_store_result)
+dnl Replace `main' with a function in -lpthread:
+AC_CHECK_LIB(pthread, main)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(unistd.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+
+dnl Checks for pdns functions
+dnl Check for pdns
+
+search_pdns=1
+
+AC_ARG_WITH(pdns-includes, [  --with-pdns-includes=PATH Specify location of pdns headers],
+[ if test x"$withval" = x"no"; then
+    search_pdns=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      PDNS_INCLUDES="-I$withval"
+      search_pdns=0
+      has_pdns=1
+    fi
+  fi
+])
+
+
+AC_DEFUN(AC_CHECK_PDNS,
+[ if test x"$search_pdns" != x"0"; then
+    if test -f "$1/$2"; then
+      AC_MSG_RESULT($5)
+      PDNS_LIBS="$3"
+      PDNS_INCLUDES="$4"
+      search_pdns=0
+      has_pdns=1
+    fi
+  fi
+])
+
+AC_DEFUN(AC_SEARCH_PDNS,
+[ AC_MSG_CHECKING("location of pdns logger.hh include")
+  AC_CHECK_PDNS($HOME/programming/pdns, logger.hh,,-I$HOME/programming/pdns, "found in $HOME/programming/pdns")
+  AC_CHECK_PDNS(../pdns, logger.hh,,-I../pdns, "found in ../pdns")
+  AC_CHECK_PDNS(../pdns-1.2, logger.hh,,-I../pdns-1.2, "found in ../pdns-1.2")
+])
+
+if test x"$search_pdns" != x"0"; then
+  AC_SEARCH_PDNS()
+fi
+
+if test x"$has_pdns" = x"1"; then
+       echo Found pdns include file, assuming working and compliant pdns
+else
+       echo
+       echo Did not find pdns include file
+       echo
+       exit 1 
+fi
+
+CPPFLAGS="$CPPFLAGS $PDNS_INCLUDES"
+
+
+dnl Checks for library functions.
+
+dnl Check for STL
+AC_CHECK_HEADER(sstream,dontneedstl=1)
+
+if test "$dontneedstl" != "1" 
+then
+search_stl=1
+
+AC_ARG_WITH(stl-includes, [  --with-stl-includes=PATH Specify location of STL headers],
+[ if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_INCLUDES="-I$withval"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+
+
+AC_ARG_WITH(stl-libs, [  --with-stl-libs=PATH    Specify location of STL libs],
+[ if test x"$withval" = x"no"; then
+    search_stl=0
+  else
+    #if test x"$withval" != x"yes"; then
+    if test -d "$withval"; then
+      STL_LIBS="$LIBS -L$withval -lstlport_gcc"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+AC_DEFUN(AC_CHECK_STL,
+[ if test x"$search_stl" != x"0"; then
+    if test -f "$1/$2"; then
+      AC_MSG_RESULT($5)
+      STL_LIBS="$3"
+      STL_INCLUDES="$4"
+      search_stl=0
+      has_stl=1
+    fi
+  fi
+])
+
+AC_DEFUN(AC_SEARCH_STL,
+[ AC_MSG_CHECKING("location of sstream")
+  AC_CHECK_STL(/usr/include, sstream, -lstlport_gcc,, "found in /usr/include")
+  AC_CHECK_STL(/usr/include/stlport, sstream, -lstlport_gcc, -I/usr/include/stlport, "found in /usr/include/stlport")
+  AC_CHECK_STL(/usr/include, sstream, -lstlport_gcc,, "found in /usr/include")
+  AC_CHECK_STL(/usr/local/include, sstream, -L/usr/local/lib -lstlport_gcc, -I/usr/local/include, "found in /usr/local")
+  AC_CHECK_STL(/usr/local/include/stl, sstream, -L/usr/local/lib -L/usr/local/lib/stl -lstlport_gcc, -I/usr/local/include/stl, "found in /usr/local/include/stl")
+  AC_CHECK_STL(/home/ahu/download/STLport-4.0/stlport, sstream,-L/home/ahu/download/STLport-4.0/lib/ -lstlport_gcc, -I/home/ahu/download/STLport-4.0/stlport/, "found in /home/ahu/download/STLport-4.0/stlport")
+  AC_CHECK_STL($HOME/STLport-4.0/stlport, sstream,-L$HOME/STLport-4.0/lib/ -lstlport_gcc, -I$HOME/STLport-4.0/stlport/, "found in $HOME/STLport-4.0/stlport")
+])
+
+if test x"$search_stl" != x"0"; then
+  AC_SEARCH_STL()
+fi
+
+if test x"$has_stl" = x"1"; then
+       echo Found sstream include file, assuming working and compliant STL
+else
+       echo
+       echo Did not find sstream include file, this probably means that your STL is not
+       echo compliant - the default gcc libstdc++ isn\'t. Download STLport-4.0 from
+       echo http://www.stlport.org, or use --with-stl-includes and --with-stl-libs
+       echo to specify the location of your STL.
+       echo
+       exit 1 
+fi
+
+CPPFLAGS="$CPPFLAGS $STL_INCLUDES $MYSQLPP_INCLUDES"
+LIBS="$LIBS $STL_LIBS"
+fi
+
+AM_CONFIG_HEADER(config.h)
+AC_OUTPUT(Makefile buildroot.sh)
diff --git a/modules/mysqlbackend/mysqlcbackend.cc b/modules/mysqlbackend/mysqlcbackend.cc
new file mode 100644 (file)
index 0000000..004534c
--- /dev/null
@@ -0,0 +1,194 @@
+// $Id: mysqlcbackend.cc,v 1.1 2002/11/27 15:29:50 ahu Exp $ 
+#include <string>
+#include <map>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sstream>
+
+using namespace std;
+
+#include <dns.hh>
+#include <dnsbackend.hh>
+#include <mysqlcbackend.hh>
+#include <dnspacket.hh>
+#include <ueberbackend.hh>
+#include <ahuexception.hh>
+#include <logger.hh>
+#include <arguments.hh>
+
+static string backendName="[MySQLbackend]";
+
+string MySQLBackend::sqlEscape(const string &name)
+{
+  string a;
+
+  for(string::const_iterator i=name.begin();i!=name.end();++i)
+
+    if(*i=='\'' || *i=='\\'){
+      a+='\\';
+      a+=*i;
+    }
+    else
+      a+=*i;
+  return a;
+      
+}
+
+MySQLBackend::MySQLBackend(const string &suffix)
+{
+  mysql_init(&db);
+  setArgPrefix("mysql"+suffix);
+  if (!mysql_real_connect(&db,getArg("host").c_str(),
+                         getArg("user").c_str(),
+                         getArg("password").c_str(),
+                         getArg("dbname").c_str(),
+                         0,
+                         getArg("socket").empty() ? 
+                         NULL : getArg("socket").c_str(),0)) {
+    L<<Logger::Error<<backendName<<" Failed to connect to database: Error: "<<mysql_error(&db)<<endl;
+    throw(AhuException(backendName+string(" Failed to connect to database: Error: ")+mysql_error(&db)));
+  }
+  d_table=getArg("table");
+  L<<Logger::Warning<<backendName<<" MySQL connection succeeded"<<endl;
+}
+
+MySQLBackend::~MySQLBackend()
+{
+  L<<Logger::Warning<<backendName<<" MySQL connection closed"<<endl;
+  mysql_close(&db);
+}
+
+void MySQLBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int zoneId )
+{
+  string query;
+  
+  // suport wildcard searches
+  if(qname[0]!='%')
+    query="select content,ttl,prio,type,domain_id,name,change_date from "+d_table+" where name='";
+  else
+    query="select content,ttl,prio,type,domain_id,name,change_date from "+d_table+" where name like '";
+
+  if(qname.find_first_of("'\\")!=string::npos)
+    query+=sqlEscape(qname);
+  else
+    query+=qname;
+
+  query+="'";
+  if(qtype.getCode()!=255) {  // ANY
+    query+=" and type='";
+    query+=qtype.getName();
+    query+="'";
+  }
+
+  if(zoneId>0) {
+    query+=" and domain_id=";
+    ostringstream o;
+    o<<zoneId;
+    query+=o.str();
+  }
+    
+  DLOG(L<< backendName<<" Query: '" << query << "'"<<endl);
+
+  if(arg().mustDo("query-logging"))
+    L<<Logger::Error<<"Query: '"<<query<<"'"<<endl;
+
+  if(mysql_query(&db,query.c_str())) 
+    throw AhuException("Failed to execute mysql_query '"+query+"'. Error: "+string(mysql_error(&db)));
+    
+  if(!(d_res = mysql_use_result(&db))) 
+    throw AhuException("mysql_use_result failed. Error: "+string(mysql_error(&db)));
+  d_qname=qname;
+  d_qtype=qtype;
+}
+
+bool MySQLBackend::list(int domain_id )
+{
+  DLOG(L<<backendName<<" MySQLBackend constructing handle for list of domain id '"<<domain_id<<"'"<<endl);
+
+  ostringstream o;
+  o<<"select content,ttl,prio,type,domain_id,name,change_date from "+d_table+" where domain_id="<<domain_id;
+  
+  if(mysql_query(&db, o.str().c_str()))
+    throw AhuException("Failed to execute mysql_query '"+o.str()+"'. Error: "+string(mysql_error(&db)));
+  
+  if(!(d_res=mysql_use_result(&db))) 
+    throw AhuException("mysql_use_result failed. Error: "+string(mysql_error(&db)));
+
+  d_qname=""; // this tells 'get' what to do
+  return true;
+}
+
+bool MySQLBackend::get(DNSResourceRecord &r)
+{
+  //  L << "MySQLBackend get() was called for "<<qtype.getName() << " record: "<<qname<<endl;
+  MYSQL_ROW row;
+
+  if(!(row = mysql_fetch_row(d_res))) { // end
+      mysql_free_result(d_res);
+    return false;
+  }
+  
+  r.content=row[0];  // content
+  
+  if(!row[1])  // ttl
+    r.ttl=0;
+  else
+    r.ttl=atoi(row[1]);
+  
+  
+  if(row[2])
+    r.priority=atoi(row[2]);;
+  
+  if(!d_qname.empty()) // use this to distinguish between select with 'name' field (list()) and one without
+    r.qname=d_qname;
+  else
+    r.qname=row[5];
+  
+  r.qtype=(const char *)row[3];
+  
+  r.domain_id=atoi(row[4]);
+  if(!row[6])
+    r.last_modified=0;
+  else
+    r.last_modified=atoi(row[6]);
+  
+      //L << "MySQLBackend get() returning a rr"<<endl;
+
+  return true;
+}
+
+class MySQLFactory : public BackendFactory
+{
+public:
+  MySQLFactory() : BackendFactory("mysql") {}
+  
+  void declareArguments(const string &suffix="")
+  {
+    declare(suffix,"dbname","Pdns backend database name to connect to","powerdns");
+    declare(suffix,"user","Pdns backend user to connect as","powerdns");
+    declare(suffix,"host","Pdns backend host to connect to","");
+    declare(suffix,"password","Pdns backend password to connect with","");
+    declare(suffix,"socket","Pdns backend socket to connect to","");
+    declare(suffix,"table","Name of table to use","records");
+  }
+  
+  DNSBackend *make(const string &suffix="")
+  {
+    return new MySQLBackend(suffix);
+  }
+};
+
+
+//! Magic class that is activated when the dynamic library is loaded
+class Loader
+{
+public:
+  //! This reports us to the main UeberBackend class
+  Loader()
+  {
+    BackendMakers().report(new MySQLFactory);
+    L<<Logger::Notice<<backendName<<" This is the mysql module version "VERSION" ("__DATE__", "__TIME__") reporting"<<endl;
+  }
+};
+static Loader loader;
diff --git a/modules/mysqlbackend/mysqlcbackend.hh b/modules/mysqlbackend/mysqlcbackend.hh
new file mode 100644 (file)
index 0000000..3fbc410
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef MYSQLCBACKEND_HH
+#define MYSQLCBACKEND_HH
+
+#include <string>
+#include <map>
+
+using namespace std;
+
+#include <mysql.h>
+
+
+
+/** The MySQLBackend is a DNSBackend that can answer DNS related questions. It looks up data
+    in MySQL */
+class MySQLBackend : public DNSBackend
+{
+public:
+  MySQLBackend(const string &suffix="");
+  ~MySQLBackend();
+  MYSQL_RES *d_res;
+  MySQLBackend *parent;
+  string d_qname;
+  QType d_qtype;
+  
+  void lookup(const QType &, const string &qdomain, DNSPacket *p=0, int zoneId=-1);
+  bool list(int domain_id);
+  bool get(DNSResourceRecord &r);
+    
+private:
+  MYSQL db; 
+
+  string sqlEscape(const string &nanme); //!< Escape ' and \ for SQL purposes
+  string d_table;
+};
+#endif /* MYSQLCBACKEND_HH */