diff --git a/configure.ac b/configure.ac
index ff832aa..646c28c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -529,6 +529,20 @@ if test x$ldap = xyes || test x$ldapcrypto = xyes ; then
     fi
 fi
 
+# DBI Support
+AC_ARG_WITH(dbi,
+    AC_HELP_STRING([--with-dbi],
+                   [enable DBI support in dhcpd (default is no)]),
+    [dbi=$withval],
+    [dbi=no])
+
+# DBI support is disabled by default
+if test x$dbi = xyes ; then
+    AC_SEARCH_LIBS(dbi_initialize, [dbi], ,
+		   AC_MSG_FAILURE([*** Cannot find dbi_initialize with -ldbi - do you need to install a dbi-devel package?]))
+    AC_SUBST(DBI_CFLAGS, ["-DDBI_CONFIGURATION"])
+fi
+
 # Append selected warning levels to CFLAGS before substitution (but after
 # AC_TRY_COMPILE & etc).
 CFLAGS="$CFLAGS $STD_CWARNINGS"
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
index cd7d962..4f16273 100644
--- a/includes/dhcpd.h
+++ b/includes/dhcpd.h
@@ -735,6 +735,16 @@ struct lease_state {
 #endif
 #endif
 
+#if defined(DBI_CONFIGURATION)
+# define SV_DBI_PATH                    78
+# define SV_DBI_HOST                    79
+# define SV_DBI_DRIVER                  80
+# define SV_DBI_USERNAME                81
+# define SV_DBI_PASSWORD                82
+# define SV_DBI_DBNAME                  83
+# define SV_DBI_QUERY                   84
+#endif
+
 #if !defined (DEFAULT_DEFAULT_LEASE_TIME)
 # define DEFAULT_DEFAULT_LEASE_TIME 43200
 #endif
@@ -3435,6 +3445,13 @@ int find_subclass_in_ldap (struct class *, struct class **,
                            struct data_string *);
 #endif
 
+/* dbi.c */
+#if defined(DBI_CONFIGURATION)
+int find_haddr_in_dbi (struct host_decl **, int, unsigned,
+                       const unsigned char *, const char *, int);
+void dbi_read_config (void);
+#endif
+
 /* mdb6.c */
 HASH_FUNCTIONS_DECL(ia, unsigned char *, struct ia_xx, ia_hash_t)
 HASH_FUNCTIONS_DECL(iasubopt, struct in6_addr *, struct iasubopt,
diff --git a/server/Makefile.am b/server/Makefile.am
index cdfaf47..dc4db31 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -4,9 +4,9 @@ dist_sysconf_DATA = dhcpd.conf
 sbin_PROGRAMS = dhcpd
 dhcpd_SOURCES = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
 		omapi.c mdb.c stables.c salloc.c ddns.c dhcpleasequery.c \
-		dhcpv6.c mdb6.c ldap.c ldap_casa.c
+		dhcpv6.c mdb6.c ldap.c ldap_casa.c dbi.c
 
-dhcpd_CFLAGS = $(LDAP_CFLAGS)
+dhcpd_CFLAGS = $(LDAP_CFLAGS) $(DBI_CFLAGS)
 dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \
 	      ../dhcpctl/libdhcpctl.a ../bind/lib/libdns.a \
 	      ../bind/lib/libisc.a
diff --git a/server/confpars.c b/server/confpars.c
index e022acf..dd11a39 100644
--- a/server/confpars.c
+++ b/server/confpars.c
@@ -64,6 +64,9 @@ isc_result_t readconf ()
 	isc_result_t res;
 
 	res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
+#if defined(DBI_CONFIGURATION)
+	dbi_read_config ();
+#endif
 #if defined(LDAP_CONFIGURATION)
 	if (res != ISC_R_SUCCESS)
 		return (res);
diff --git a/server/dbi.c b/server/dbi.c
new file mode 100644
index 0000000..66639bb
--- /dev/null
+++ b/server/dbi.c
@@ -0,0 +1,663 @@
+/* dbi.c
+
+   Routines for interface with libdbi */
+
+/*
+ * Copyright (c) 2010 Flexiant Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of The Internet Software Consortium nor the names
+ *    of its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * This file provides a generalised interface to libdbi. The following
+ * configuration elements can be set (all are strings):
+ *    dbi-host:     host on which database resides
+ *    dbi-driver:   name of driver (e.g. mysql)
+ *    dbi-username: database username
+ *    dbi-password: database password
+ *    dbi-dbname:   name of database
+ *    dbi-query:    database query
+ *
+ * The file allows dynamic configuration of dhcp parameters looked up by
+ * hardware address. The user can specify a statement (likely to be SELECT
+ * in an SQL environment) which returns data providing the dhcp paramaters
+ * associated with that particular hardware address.
+ *
+ * The query is the SELECT statement passed to the SQL backend, into which
+ * the following are substituted:
+ *     %h : the hardware address
+ *     %t : the media type
+ *     %% : a percent sign
+ *
+ * The query does not need a trailing semicolon. Be careful that quotes in the
+ * query do not interfere with quotes in the config file.
+ *
+ * Columns returned are processed in order, with column names corresponding
+ * to entries in the file. The values in the first row are appended after a
+ * " " and terminated with a ";".
+ *
+ * For example, if the table 'dhcp' contained columns haddr, ipv4,
+ * droute corresponding to hardware address, IPv4 address and
+ * default routes for IPv4,  the following query might be used:
+ *
+ *     SELECT ipv4 AS 'fixed-address', droute AS 'option routers'
+ *            FROM dhcp WHERE haddr = '%h'
+ *
+ * If ipv4 were returned as 192.200.0.15, and droute as 192.200.0.1, this
+ * would generate a host block equivalent to:
+ *     host dummyhostname {
+ *          fixed-address 192.200.0.15;
+ *          option routers 192.200.0.1;
+ *     };
+ *
+ * The following column names have special significance:
+ *     name:      the name of the host block (should be irrelevant)
+ *     entry:     an string to be copied verbatim into the configuration
+ *                (including the relevant semi-colon)
+ *
+ * An example of the use of 'entry' on MySQL is as follows, and has
+ * the same effect as the above example:
+ *     SELECT CONCAT('fixed-address ',ipv4,'; ',
+ *                   'option routers ',droute,';') AS 'entry'
+ *            FROM dhcp WHERE haddr = '%h'
+ *
+ * This allows for more flexible (if less legible) queries, and avoids
+ * problems with databases which are unhappy returning column names
+ * containing non-alphanumeric characters.
+ */
+
+#include "dhcpd.h"
+#include <signal.h>
+#include <errno.h>
+
+#if defined(DBI_CONFIGURATION)
+
+#include <dbi/dbi.h>
+
+/* Pointer to the DBI connection and an indication we have been initialized */
+static dbi_conn dbi = NULL;
+
+static char *dbi_path = NULL,
+  *dbi_host = NULL,
+  *dbi_drivername = NULL,
+  *dbi_username = NULL,
+  *dbi_password = NULL,
+  *dbi_dbname = NULL,
+  *dbi_query = NULL;
+
+static int dbi_enabled = 0;
+
+static void
+log_dbi_error (void)
+{
+  const char * err = NULL;
+  if (dbi && (-1 != dbi_conn_error(dbi, &err)) && err)
+    log_info("DBI error: %s", err);
+  return;
+}
+
+/* dbi_conn_ping unreliable in some version - SEGVs with mysql */
+static int
+fake_dbi_conn_ping (dbi_conn Conn)
+{
+#if defined(DBI_UNRELIABLE_PING)
+  return 1;
+#else
+  return dbi_conn_ping(Conn);
+#endif
+}
+
+static char *
+_do_lookup_dhcp_string_option (struct option_state *options, int option_name)
+{
+  struct option_cache *oc;
+  struct data_string db;
+  char *ret;
+
+  memset (&db, 0, sizeof (db));
+  oc = lookup_option (&server_universe, options, option_name);
+  if (oc &&
+      evaluate_option_cache (&db, (struct packet*) NULL,
+                             (struct lease *) NULL,
+                             (struct client_state *) NULL, options,
+                             (struct option_state *) NULL,
+                             &global_scope, oc, MDL) &&
+      db.data != NULL && *db.data != '\0')
+    {
+      ret = dmalloc (db.len + 1, MDL);
+      if (ret == NULL)
+        log_fatal ("no memory for dbi option %d value", option_name);
+
+      memcpy (ret, db.data, db.len);
+      ret[db.len] = 0;
+      data_string_forget (&db, MDL);
+    }
+  else
+    ret = NULL;
+
+  return (ret);
+}
+
+
+/* shut down connection to database if it is open */
+static void
+dbi_stop()
+{
+  struct sigaction old, new;
+
+  if (dbi == NULL)
+    return;
+
+  /*
+  ** We think some of these things may
+  ** cause a SIGPIPE and dhcpd gets terminated,
+  ** since it doesn't handle it...
+  */
+
+  new.sa_flags   = 0;
+  new.sa_handler = SIG_IGN;
+  sigemptyset (&new.sa_mask);
+  sigaction (SIGPIPE, &new, &old);
+
+  dbi_conn_close(dbi);
+  dbi = NULL;
+  dbi_shutdown();
+
+  sigaction (SIGPIPE, &old, &new);
+}
+
+/* open connection to database */
+static void
+dbi_start (void)
+{
+  int drivercount;
+
+  if (!dbi_enabled)
+    return;
+
+  /* return if already started */
+  if (dbi)
+    return;
+
+  /* If DBI is going to work, all the params, must have a value. If not, reread the config file */
+  if (dbi_drivername == NULL) {
+    dbi_enabled = 0;
+    
+    struct option_state *options = NULL;
+    option_state_allocate (&options, MDL);
+    
+    execute_statements_in_scope ((struct binding_value **) NULL,
+				 (struct packet *) NULL, (struct lease *) NULL,
+				 (struct client_state *) NULL, (struct option_state *) NULL,
+				 options, &global_scope, root_group, (struct group *) NULL);
+    
+    dbi_path = _do_lookup_dhcp_string_option (options, SV_DBI_PATH);
+    dbi_drivername = _do_lookup_dhcp_string_option (options, SV_DBI_DRIVER);
+    dbi_host = _do_lookup_dhcp_string_option (options, SV_DBI_HOST);
+    dbi_username = _do_lookup_dhcp_string_option (options, SV_DBI_USERNAME);
+    dbi_password = _do_lookup_dhcp_string_option (options, SV_DBI_PASSWORD);
+    dbi_dbname = _do_lookup_dhcp_string_option (options, SV_DBI_DBNAME);
+    dbi_query = _do_lookup_dhcp_string_option (options, SV_DBI_QUERY);
+    
+    option_state_dereference (&options, MDL);
+    
+    /* If no DBI config is specified, return right away without logging */
+    if (!dbi_path && !dbi_drivername && !dbi_host && !dbi_username &&
+	!dbi_password && !dbi_dbname && !dbi_query)
+	return;
+    
+    dbi_enabled = 1; /* They want us to do dbi, as at least one directive exists in the config */
+  }
+  
+  /* Check all DBI config is there, except for dbi_path which is optional */
+  if (dbi_drivername == NULL || dbi_host == NULL || dbi_username == NULL ||
+      dbi_password == NULL || dbi_dbname == NULL || dbi_query == NULL ) {
+    log_info ("Not searching DBI since config file needs all of dbi_driver, dbi_host, dbi_username, dbi_password, dbi_dbname and dbi_query");
+    return;
+  }
+  
+#if defined (DEBUG_DBI)
+  log_info ("Connecting to DBI server driver=%s, host=%s, dbname=%s", dbi_drivername, dbi_host, dbi_dbname);
+#endif
+
+  drivercount = dbi_initialize(dbi_path); /* may be NULL - default path */
+  if (drivercount<0) {
+    log_error ("DBI error: dbi_initialize() failed");
+    return;
+  }
+  
+  if (drivercount == 0) {
+    log_error ("DBI error: no drivers available. Is dbi_path set correctly?");
+    dbi_shutdown();
+    return;
+  }
+  
+  dbi = dbi_conn_new(dbi_drivername);
+  if (dbi == NULL) {
+    log_error("DBI error: dbi_conn_new() failed");
+    dbi_shutdown();
+    return;
+  }
+  
+  if (dbi_conn_set_option(dbi, "host", dbi_host) < 0) {
+    log_error("DBI error: cannot set host option");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+  
+  if (dbi_conn_set_option(dbi, "username", dbi_username) < 0) {
+    log_error("DBI error: cannot set username option");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+  
+  if (dbi_conn_set_option(dbi, "password", dbi_password) < 0) {
+    log_error("DBI error: cannot set password option");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+  
+  if (dbi_conn_connect(dbi) < 0) {
+    log_error("DBI error: cannot connect");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+  
+  if (!fake_dbi_conn_ping(dbi)) {
+    log_error("DBI error: cannot ping db");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+
+  if (dbi_conn_select_db(dbi, dbi_dbname) < 0) {
+    log_error("DBI error: cannot select database");
+    log_dbi_error();
+    dbi_stop();
+    return;
+  }
+
+#if defined (DEBUG_DBI)
+  log_info ("Successfully connected to DBI server driver=%s, host=%s, dbname=%s", dbi_drivername, dbi_host, dbi_dbname);
+#endif
+
+}
+
+/* This function will parse the dhcpOption and dhcpStatements field in the DBI
+   entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL.
+   If we are parsing a HOST_DECL, this always returns 0. If we are parsing a
+   CLASS_DECL, this will return what the current lease limit is in DBI. If
+   there is no lease limit specified, we return 0 */
+
+static int
+dbi_parse_options (char * options, struct group *group,
+		    int type, struct host_decl *host,
+		    struct class **class)
+{
+  int declaration, lease_limit;
+  enum dhcp_token token;
+  struct parse *cfile;
+  isc_result_t res;
+  const char *val;
+
+  lease_limit = 0;
+
+  if (*options == '\0')
+    return (lease_limit);
+
+  cfile = (struct parse *) NULL;
+  res = new_parse (&cfile, -1, options, strlen (options),
+                   type == HOST_DECL ? "DBI-HOST" : "DBI-SUBCLASS", 0);
+  if (res != ISC_R_SUCCESS)
+    return (lease_limit);
+
+#if defined (DEBUG_DBI)
+  log_info ("Sending the following options: '%s'", options);
+#endif
+
+  declaration = 0;
+  do {
+    token = peek_token (&val, NULL, cfile);
+    if (token == END_OF_FILE)
+      break;
+    declaration = parse_statement (cfile, group, type, host, declaration);
+  } while (1);
+
+  end_parse (&cfile);
+
+  return (lease_limit);
+}
+
+static char *
+dbi_concat_string (char * orig, int * size, const char * add, const char * file, int line)
+{
+  const int space = 8;
+  char * ret = NULL;
+
+  int olen;
+  int alen = 0;
+
+  if (!add)
+    add="";
+
+  alen = strlen(add);
+
+  if (!orig) {
+    orig = dmalloc(*size = alen + 1 + space, file, line);
+    if (!orig) {
+      *size = 0;
+      return NULL;
+    }
+    *orig = '\0';
+  }
+  
+  olen = strlen(orig);
+
+  /* Can we fit the string in now? */
+  if (olen + alen + 1 <= *size) {
+    memcpy (orig+olen, add, alen+1); /* copy \0 too */
+    return orig;
+  }
+  
+  ret = dmalloc(*size = olen + alen + 1 + space, file, line);
+  if (!ret) {
+    dfree(orig, file, line);
+    *size = 0;
+    return NULL;
+  }
+
+  memcpy (ret, orig, olen);
+  memcpy (ret+olen, add, alen+1); /* copy \0 too */
+  return ret;
+}
+
+int
+find_haddr_in_dbi (struct host_decl **hp, int htype, unsigned hlen,
+		   const unsigned char *haddr, const char *file, int line)
+{
+  dbi_result result;
+  const int space = 8; /* extra space to allocate to avoid reallocs */
+  char * qbuf = NULL;
+  int qbufsize = 0;
+  int qsize = 0;
+  int in = 0, out = 0;
+  char c;
+
+  if (dbi == NULL)
+    dbi_start ();
+  if (!dbi_enabled || (dbi == NULL))
+    return (0);
+
+
+  if (!fake_dbi_conn_ping(dbi)) {
+    dbi_stop();
+    dbi_start();
+    if (dbi == NULL)
+      return(0);
+    if (!fake_dbi_conn_ping(dbi)) {
+      log_error ("DBI error: reconnection to database failed to give live connection");
+      log_dbi_error();
+      return (0);
+    }
+  }
+
+  /* Now build query up */
+
+  qsize = strlen (dbi_query) + 1 /*the NULL*/;
+  qbufsize = qsize + space;
+  qbuf = dmalloc(qbufsize, MDL);
+  if (!qbuf) {
+    log_error("DBI error: cannot malloc() query");
+    return (0);
+  }
+
+  do {
+    c = dbi_query[in++];
+    if (c != '%')
+      /* We know we ALWAYS keep enough room for the remaining untranslated string */
+      qbuf[out++] = c;
+    else {
+      char * newstring;
+      char cc;
+      switch (dbi_query[in++]) {
+      case 'h' :
+	newstring = print_hw_addr (htype, hlen, haddr);
+	break;
+      case 't': {
+	switch (htype) {
+	case HTYPE_ETHER:
+	  newstring = "ethernet";
+	  break;
+	case HTYPE_IEEE802:
+	  newstring = "token-ring";
+	  break;
+	case HTYPE_FDDI:
+	  newstring = "fddi";
+	  break;
+	default:
+	  newstring = "unknown";
+	  break;
+	}
+      }
+      case '%':
+	newstring = "%";
+	break;
+      default: /* including terminating NULL */
+	log_error ("DBI error: bad escape code in query");
+	dfree(qbuf, MDL);
+	return (0);
+      }
+      
+      qsize = qsize - 1 /* the '%' */ + strlen(newstring);
+      
+      if (qbufsize <= qsize) {
+	char * nqbuf = NULL;
+	qbufsize = qsize + space;
+	nqbuf = dmalloc(qbufsize, MDL);
+	if (!nqbuf) {
+	  log_error("DBI error: cannot realloc() query");
+	  free(qbuf);
+	  return (0);
+	}
+	strcpy(nqbuf, qbuf);
+	free(qbuf);
+	qbuf=nqbuf;
+      }
+      /* copy in the new string */
+      while ((cc=*(newstring++))!='\0') {
+	qbuf[out++]=cc;
+      }
+    }
+  }
+  while (c); /* NULL byte copied too */
+  
+#if defined (DEBUG_DBI)
+  log_info ("DBI query: '%s'", qbuf);
+#endif
+  result = dbi_conn_query(dbi, qbuf);
+  if (!result) {
+    /* dbi_conn_ping might not have worked - we disable it so manually retry */
+    dbi_stop();
+    dbi_start();
+    if (dbi == NULL) {
+	dfree(qbuf, MDL);
+	log_error ("DBI error: query returned error status, could not reinitialize");
+	log_dbi_error();
+	return(0);
+      }
+    result = dbi_conn_query(dbi, qbuf);
+    if (!result) {
+      dfree(qbuf, MDL);
+      log_error ("DBI error: query returned error status after reinitialize");
+      log_dbi_error();
+      return(0);
+    }
+  }
+  dfree(qbuf, MDL);
+
+  while (dbi_result_next_row(result)) {
+    /* though this is a while loop, we are actually looking only at the first row */
+    const char *name = NULL;
+    struct host_decl *host = NULL;
+    isc_result_t status;
+    char * hentry = NULL;
+    int hentrysize = 0;
+    int field;
+    int havename = 0;
+
+    status = host_allocate (&host, MDL);
+    if (status != ISC_R_SUCCESS) {
+      log_fatal ("can't allocate host decl struct: %s",
+		 isc_result_totext (status));
+      dbi_result_free(result);
+      dfree(hentry, MDL);
+      return (0);
+    }
+    
+    /* now we work through the fields - if dbi_result_get_numfields returns 0 or error this is skipped */
+    /* field numbers start at 1 for some reason */
+    for (field = 1; field <= dbi_result_get_numfields(result); field++) {
+      const char * fieldname;
+      const char * fieldvalue;
+      
+      fieldname = dbi_result_get_field_name(result, field);
+      if (!fieldname) {
+	log_info ("can't get dbi field name");
+	log_dbi_error();
+	host_dereference (&host, MDL);
+	dbi_result_free(result);
+	dfree(hentry, MDL);
+	return (0);
+      }
+
+      fieldvalue = dbi_result_get_string_idx(result, field); /* DBI is responsible for freeing this */
+      if (!fieldvalue) /* skip non-strings */
+	continue;
+
+      if (!strcmp(fieldname, "name")) { /* skip name field */
+	havename = 1;
+      } else if (!strcmp(fieldname, "entry")) { /* copy literal*/
+	hentry = dbi_concat_string(hentry, &hentrysize, fieldvalue, MDL);
+	if (hentry == NULL) {
+	  host_dereference (&host, MDL);
+	  dbi_result_free(result);
+	  /* hentry already freed */
+	  return (0);
+	}
+      } else { /* a normal field */
+	hentry = dbi_concat_string(hentry, &hentrysize, fieldname, MDL);
+	if (hentry == NULL) {
+	  host_dereference (&host, MDL);
+	  dbi_result_free(result);
+	  /* hentry already freed */
+	  return (0);
+	}
+	hentry = dbi_concat_string(hentry, &hentrysize, " ", MDL);
+	if (hentry == NULL) {
+	  host_dereference (&host, MDL);
+	  dbi_result_free(result);
+	  /* hentry already freed */
+	  return (0);
+	}
+	hentry = dbi_concat_string(hentry, &hentrysize, fieldvalue, MDL);
+	if (hentry == NULL) {
+	  host_dereference (&host, MDL);
+	  dbi_result_free(result);
+	  /* hentry already freed */
+	  return (0);
+	}
+	hentry = dbi_concat_string(hentry, &hentrysize, ";\n", MDL);
+	if (hentry == NULL) {
+	  host_dereference (&host, MDL);
+	  dbi_result_free(result);
+	  /* hentry already freed */
+	  return (0);
+	}
+      }
+    }
+	
+    /* Now deal with the name field - libdbi provides returns may be overwritten so need to get again*/
+    if (havename)
+      name = dbi_result_get_string(result, "name"); /* DBI is responsible for freeing this */
+    if (!name)
+      name = print_hw_addr (htype, hlen, haddr);
+    host->name = dmalloc (strlen (name) + 1, MDL);
+    if (host->name == NULL) {
+      host_dereference (&host, MDL);
+      dbi_result_free(result);
+      dfree(hentry, MDL);
+      return (0);
+    }
+    strcpy(host->name, name);
+
+#if defined (DEBUG_DBI)
+    log_info ("Found dhcpHWAddress DBI name %s entry %s", name?name:"NULL", hentry?hentry:"NULL");
+#endif
+
+    if (!clone_group (&host->group, root_group, MDL)) {
+      log_fatal ("can't clone group for host %s", host->name);
+      host_dereference (&host, MDL);
+      dbi_result_free(result);
+      dfree(hentry, MDL);
+      return (0);
+    }
+    
+    dbi_parse_options (hentry, host->group, HOST_DECL, host, NULL);
+    dfree(hentry, MDL);
+    
+    *hp = host;
+    dbi_result_free(result);
+    return (1);
+  
+  }
+
+  dbi_result_free(result);
+
+#if defined (DEBUG_DBI)
+  log_info ("DBI got no results");
+#endif
+
+  return (0);
+}
+
+void
+dbi_read_config (void)
+{
+  dbi_enabled = 1;
+  dbi_start();
+  return;
+}
+
+
+#endif
diff --git a/server/mdb.c b/server/mdb.c
index 85d0bac..37a813b 100644
--- a/server/mdb.c
+++ b/server/mdb.c
@@ -607,6 +607,13 @@ int find_hosts_by_haddr (struct host_decl **hp, int htype,
 		return ret;
 #endif
 
+#if defined(DBI_CONFIGURATION)
+	int ret1;
+
+	if ((ret1 = find_haddr_in_dbi (hp, htype, hlen, haddr, file, line)))
+		return ret1;
+#endif
+
 	h.hlen = hlen + 1;
 	h.hbuf [0] = htype;
 	memcpy (&h.hbuf [1], haddr, hlen);
diff --git a/server/stables.c b/server/stables.c
index 8294527..a5a458c 100644
--- a/server/stables.c
+++ b/server/stables.c
@@ -266,6 +266,15 @@ static struct option server_options[] = {
 	{ "ldap-tls-randfile", "t",		&server_universe,  77, 1 },
 #endif /* LDAP_USE_SSL */
 #endif /* LDAP_CONFIGURATION */
+#if defined(DBI_CONFIGURATION)
+	{ "dbi-path", "t",			&server_universe,  78, 1 },
+	{ "dbi-host", "t",			&server_universe,  79, 1 },
+	{ "dbi-driver", "t",			&server_universe,  80, 1 },
+	{ "dbi-username", "t",			&server_universe,  81, 1 },
+	{ "dbi-password", "t",			&server_universe,  82, 1 },
+	{ "dbi-dbname", "t",			&server_universe,  83, 1 },
+	{ "dbi-query", "t",			&server_universe,  84, 1 },
+#endif /* DBI_CONFIGURATION */
 	{ NULL, NULL, NULL, 0, 0 }
 };
 

