diff -NubBE /root/build/d/djbdns-1.05/byte_chr.c ./byte_chr.c
--- /root/build/d/djbdns-1.05/byte_chr.c	2001-02-11 23:11:45.000000000 +0200
+++ ./byte_chr.c	2008-03-18 16:57:42.000000000 +0200
@@ -1,5 +1,23 @@
 #include "byte.h"
 
+unsigned int byte_rchr(s,n,c)
+char *s;
+register unsigned int n;
+int c;
+{
+	register char ch;
+	register char *t;
+	ch = c;
+	t = s + n;
+	for (;;) {
+		if (!n) break; if (*t == ch) break; --t; --n;
+		if (!n) break; if (*t == ch) break; --t; --n;
+		if (!n) break; if (*t == ch) break; --t; --n;
+		if (!n) break; if (*t == ch) break; --t; --n;
+	}
+	return s - t;
+}
+
 unsigned int byte_chr(s,n,c)
 char *s;
 register unsigned int n;
diff -NubBE /root/build/d/djbdns-1.05/conf-cc ./conf-cc
--- /root/build/d/djbdns-1.05/conf-cc	2001-02-11 23:11:45.000000000 +0200
+++ ./conf-cc	2008-03-18 22:16:01.000000000 +0200
@@ -1,3 +1,3 @@
-gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
+gcc -O2 -I. -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings $LOCAL_CFLAGS
 
 This will be used to compile .c files.
diff -NubBE /root/build/d/djbdns-1.05/conf-ld ./conf-ld
--- /root/build/d/djbdns-1.05/conf-ld	2001-02-11 23:11:45.000000000 +0200
+++ ./conf-ld	2008-03-18 22:15:46.000000000 +0200
@@ -1,3 +1,3 @@
-gcc -s
+gcc -s $LOCAL_LDFLAGS 
 
 This will be used to link .o files into an executable.
diff -NubBE /root/build/d/djbdns-1.05/error.h ./error.h
--- /root/build/d/djbdns-1.05/error.h	2001-02-11 23:11:45.000000000 +0200
+++ ./error.h	2008-03-18 16:57:42.000000000 +0200
@@ -1,8 +1,7 @@
 #ifndef ERROR_H
 #define ERROR_H
 
-extern int errno;
-
+#include <errno.h>
 extern int error_intr;
 extern int error_nomem;
 extern int error_noent;
diff -NubBE /root/build/d/djbdns-1.05/FILES ./FILES
--- /root/build/d/djbdns-1.05/FILES	2001-02-11 23:11:45.000000000 +0200
+++ ./FILES	2008-03-18 16:57:42.000000000 +0200
@@ -241,3 +241,7 @@
 warn-shsgr
 buffer_read.c
 buffer_write.c
+ip4_num.c
+ip4_deaggregate.c
+ipdb.h
+ipdb.c
diff -NubBE /root/build/d/djbdns-1.05/ip4_deaggregate.c ./ip4_deaggregate.c
--- /root/build/d/djbdns-1.05/ip4_deaggregate.c	1970-01-01 02:00:00.000000000 +0200
+++ ./ip4_deaggregate.c	2008-03-18 22:21:18.000000000 +0200
@@ -0,0 +1,38 @@
+#include "ip4.h"
+#include <string.h>
+#include <stdlib.h>
+#include "alloc.h"
+#include <stdio.h>
+#include <unistd.h>
+#define FULL_MASK 4294967295
+
+int ip4_deaggregate (unsigned int hostmin, unsigned int hostmax, ip4_cidr_t **subnets,unsigned int *slen)
+{
+	unsigned int step;
+	unsigned int mask = 0;
+	unsigned int i = 0;
+	unsigned int base = hostmin;
+	unsigned int test1 = hostmin + 1;
+	unsigned int test2 = hostmax - 2;
+	while (base <= hostmax) {
+		step = 0;
+		while ( (base | ( 1 << step)) != base) {
+			if ((base | (((~0) & FULL_MASK) >> (31-step))) > hostmax) break;
+			step++;
+		}
+		mask = 32 - step;
+		if (*slen == 0) {
+			*subnets = (ip4_cidr_t *)alloc(sizeof(ip4_cidr_t));
+			if (!*subnets) return -1;
+			(*subnets)[0].subnet = 0;
+			(*subnets)[0].mask = 0;
+		} else {
+			if (alloc_re(subnets, (*slen)*sizeof(ip4_cidr_t), ((*slen) + 1)*sizeof(ip4_cidr_t)) == 0) return -1;
+		}
+		(*subnets)[*slen].subnet = base;
+		(*subnets)[*slen].mask = mask;
+		base += 1 << step;
+		(*slen)++;
+	}
+	return 1;
+}
diff -NubBE /root/build/d/djbdns-1.05/ip4.h ./ip4.h
--- /root/build/d/djbdns-1.05/ip4.h	2001-02-11 23:11:45.000000000 +0200
+++ ./ip4.h	2008-03-18 16:57:42.000000000 +0200
@@ -1,9 +1,18 @@
 #ifndef IP4_H
 #define IP4_H
 
-extern unsigned int ip4_scan(const char *,char *);
+extern unsigned int ip4_scan(const char *,unsigned char *);
 extern unsigned int ip4_fmt(char *,const char *);
 
+extern void ip4_num(unsigned int *u,unsigned char ip[4]);
+
 #define IP4_FMT 20
 
+typedef struct {
+	unsigned int subnet;
+	unsigned char mask;
+} ip4_cidr_t;
+
+int ip4_deaggregate (unsigned int ,unsigned int, ip4_cidr_t **, unsigned int *);
+
 #endif
diff -NubBE /root/build/d/djbdns-1.05/ip4_num.c ./ip4_num.c
--- /root/build/d/djbdns-1.05/ip4_num.c	1970-01-01 02:00:00.000000000 +0200
+++ ./ip4_num.c	2008-03-18 16:57:42.000000000 +0200
@@ -0,0 +1,9 @@
+#include <unistd.h>
+void ip4_num(unsigned int *u,unsigned char ip[4])
+{ 
+	*u |= ip[0]<<24;
+	*u |= ip[1]<<16;
+	*u |= ip[2]<<8;
+	*u |= ip[3];
+}
+
diff -NubBE /root/build/d/djbdns-1.05/ip4_scan.c ./ip4_scan.c
--- /root/build/d/djbdns-1.05/ip4_scan.c	2001-02-11 23:11:45.000000000 +0200
+++ ./ip4_scan.c	2008-03-18 16:57:42.000000000 +0200
@@ -1,7 +1,7 @@
 #include "scan.h"
 #include "ip4.h"
 
-unsigned int ip4_scan(const char *s,char ip[4])
+unsigned int ip4_scan(const char *s,unsigned char ip[4])
 {
   unsigned int i;
   unsigned int len;
diff -NubBE /root/build/d/djbdns-1.05/ipdb.c ./ipdb.c
--- /root/build/d/djbdns-1.05/ipdb.c	1970-01-01 02:00:00.000000000 +0200
+++ ./ipdb.c	2008-03-18 22:22:20.000000000 +0200
@@ -0,0 +1,113 @@
+#include "uint16.h"
+#include "alloc.h"
+#include "str.h"
+#include <string.h>
+#include <stdlib.h>
+#include "ip4.h"
+#include "open.h"
+#include "tai.h"
+#include "cdb.h"
+#include "byte.h"
+#include "case.h"
+#include "dns.h"
+#include "seek.h"
+#include "response.h"
+#include "ipdb.h"
+#include "env.h"
+#include "scan.h"
+#include "prot.h"
+#include "strerr.h"
+#include "stralloc.h"
+#include "qlog.h"
+
+#define FATAL "ipdbops: fatal: "
+
+
+
+int ipdb_key_from_uint (stralloc *key, unsigned int ipuint,unsigned char mask, char *uid, int ulen, int applymask)
+{
+	char ch;
+	char x[255];
+	int i;
+	unsigned int netmask = 0;
+	if (!stralloc_copyb(key,"\0%",2)) strerr_die1sys(111,FATAL);;
+	if (applymask) {
+		for (i = 0; i < mask; i++) netmask |= 1 << (31 - i);
+		ipuint = ipuint & netmask;
+	}
+#ifdef IPDB_DEBUG
+	byte_copy(x,ulen,uid);
+	x[ulen] = '\0';
+	fprintf(stderr,"usekey %u.%u.%u.%u/%u/%s\n", (ipuint>>24)&0xff,(ipuint>>16)&0xff,(ipuint>>8)&0xff,ipuint&0xff,mask,x);
+#endif
+	ch = (ipuint >> 24) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
+	ch = (ipuint >> 16) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
+	ch = (ipuint >> 8) & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
+	ch = ipuint  & 0xff; if (!stralloc_catb(key,&ch,1)) strerr_die1sys(111,FATAL);;
+	if (!stralloc_catb(key,&mask,1)) strerr_die1sys(111,FATAL);;
+	if (uid ) {
+		if (!stralloc_catb(key,uid,ulen)) strerr_die1sys(111,FATAL);;
+	}
+	return 1;
+}
+
+int ipdb_key_from_str (stralloc *key, const char *ipstr, unsigned char mask, char *uid, int ulen, int applymask)
+{
+	unsigned char ip[4];
+	unsigned int j;
+	ip4_scan(ipstr,ip);
+	ip4_num(&j,ip);
+	return ipdb_key_from_uint(key,j,mask,uid,ulen,applymask);
+}
+
+int ipdb_key_from_bytes (stralloc *key, unsigned char ip[4],unsigned char mask, char *uid, int ulen, int applymask)
+{
+	unsigned int j;
+	ip4_num(&j,ip);
+	return ipdb_key_from_uint(key, j,mask,uid,ulen,applymask);
+}
+
+
+void ipdb_make_key(unsigned char ip[4],unsigned char mask,char *key)
+{
+	register unsigned char i;
+	unsigned int j = 0;
+	unsigned int netmask = 0;
+	for (i = 0; i < mask; i++) {
+		netmask |= 1 << (31 - i);
+	}
+	ip4_num(&j,ip);
+	j = j & netmask;
+	key[0] = 0;
+	key[1] = '%';
+	key[2] = (j>>24)&0xff;
+	key[3] = (j>>16)&0xff;
+	key[4] = (j>>8)&0xff;
+	key[5] = j&0xff;
+	key[6] = mask;
+#ifdef IPDB_DEBUG
+	fprintf(stderr,"trykey %u.%u.%u.%u/%u\n", (j>>24)&0xff,(j>>16)&0xff,(j>>8)&0xff,j&0xff,mask);
+#endif
+}
+
+int ipdb_get (struct cdb *c, unsigned char ip[4], char *uid, int ulen, char *cc)
+{
+	stralloc key;
+	unsigned char intmask;
+	int r = -1;
+
+	key.s = NULL;
+	key.len = 0;
+	for(intmask = 32; intmask >=1 ; intmask--) {
+		ipdb_key_from_bytes(&key,ip,intmask,uid, ulen,1);
+		r = cdb_find(c,key.s,key.len);
+		if (r) break;
+	}
+	if (r == -1) return 0;
+
+	if (r && (cdb_datalen(c) == 2)) {
+		if (cdb_read(c,cc,2,cdb_datapos(c)) == -1) return 0;
+	}
+	return 1;
+}
+
diff -NubBE /root/build/d/djbdns-1.05/ipdb.h ./ipdb.h
--- /root/build/d/djbdns-1.05/ipdb.h	1970-01-01 02:00:00.000000000 +0200
+++ ./ipdb.h	2008-03-18 22:23:58.000000000 +0200
@@ -0,0 +1,13 @@
+#ifndef IPDB_H
+#include <stdio.h>
+#include <unistd.h>
+#define IPDB_H
+#include "stralloc.h"
+#include "cdb.h"
+int ipdb_key_from_uint (stralloc *, unsigned int ,unsigned char , char *, int, int );
+int ipdb_key_from_str (stralloc *, const char *, unsigned char , char *,int, int );
+int ipdb_key_from_bytes (stralloc *, unsigned char *,unsigned char , char *,int, int );
+
+int ipdb_get (struct cdb *, unsigned char ip[4], char *u, int ulen, char *);
+
+#endif
Binary files /root/build/d/djbdns-1.05/.makedata.pl.swp and ./.makedata.pl.swp differ
diff -NubBE /root/build/d/djbdns-1.05/Makefile ./Makefile
--- /root/build/d/djbdns-1.05/Makefile	2001-02-11 23:11:45.000000000 +0200
+++ ./Makefile	2008-03-18 16:57:42.000000000 +0200
@@ -3,7 +3,8 @@
 SHELL=/bin/sh
 
 default: it
-
+clean:
+	rm -f `cat TARGETS`
 alloc.a: \
 makelib alloc.o alloc_re.o getln.o getln2.o stralloc_cat.o \
 stralloc_catb.o stralloc_cats.o stralloc_copy.o stralloc_eady.o \
@@ -13,6 +14,10 @@
 	stralloc_copy.o stralloc_eady.o stralloc_num.o \
 	stralloc_opyb.o stralloc_opys.o stralloc_pend.o
 
+ipdb.o: \
+compile ipdb.c ipdb.h
+	./compile ipdb.c
+
 alloc.o: \
 compile alloc.c alloc.h error.h
 	./compile alloc.c
@@ -52,10 +57,12 @@
 
 axfrdns: \
 load axfrdns.o iopause.o droproot.o tdlookup.o response.o qlog.o \
+ip4_num.o ip4_deaggregate.o ipdb.o \
 prot.o timeoutread.o timeoutwrite.o dns.a libtai.a alloc.a env.a \
 cdb.a buffer.a unix.a byte.a
 	./load axfrdns iopause.o droproot.o tdlookup.o response.o \
 	qlog.o prot.o timeoutread.o timeoutwrite.o dns.a libtai.a \
+	ip4_num.o ip4_deaggregate.o ipdb.o \
 	alloc.a env.a cdb.a buffer.a unix.a byte.a 
 
 axfrdns-conf: \
@@ -118,12 +125,12 @@
 byte.a: \
 makelib byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_zero.o \
 case_diffb.o case_diffs.o case_lowerb.o fmt_ulong.o ip4_fmt.o \
-ip4_scan.o scan_ulong.o str_chr.o str_diff.o str_len.o str_rchr.o \
+ip4_scan.o scan_ulong.o scan_ushort.o str_chr.o str_diff.o str_len.o str_rchr.o \
 str_start.o uint16_pack.o uint16_unpack.o uint32_pack.o \
 uint32_unpack.o
 	./makelib byte.a byte_chr.o byte_copy.o byte_cr.o \
 	byte_diff.o byte_zero.o case_diffb.o case_diffs.o \
-	case_lowerb.o fmt_ulong.o ip4_fmt.o ip4_scan.o scan_ulong.o \
+	case_lowerb.o fmt_ulong.o ip4_fmt.o ip4_scan.o scan_ushort.o scan_ulong.o \
 	str_chr.o str_diff.o str_len.o str_rchr.o str_start.o \
 	uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o
 
@@ -550,6 +557,10 @@
 compile ip4_scan.c scan.h ip4.h
 	./compile ip4_scan.c
 
+ip4_deaggregate.o: \
+compile ip4_deaggregate.c ip4.h
+	./compile ip4_deaggregate.c
+
 it: \
 prog install instcheck
 
@@ -762,6 +773,10 @@
 compile scan_ulong.c scan.h
 	./compile scan_ulong.c
 
+scan_ushort.o: \
+compile scan_ushort.c scan.h
+	./compile scan_ushort.c
+
 seek_set.o: \
 compile seek_set.c seek.h
 	./compile seek_set.c
@@ -964,8 +979,8 @@
 
 tdlookup.o: \
 compile tdlookup.c uint16.h open.h tai.h uint64.h cdb.h uint32.h \
-byte.h case.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h \
-taia.h seek.h response.h uint32.h
+byte.h case.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h qlog.h \
+taia.h seek.h response.h uint32.h ipdb.h
 	./compile tdlookup.c
 
 timeoutread.o: \
@@ -978,11 +993,18 @@
 timeoutwrite.h
 	./compile timeoutwrite.c
 
+ip4_num.o: \
+compile ip4_num.c
+	./compile ip4_num.c
+
+
 tinydns: \
 load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \
+ip4_num.o ip4_deaggregate.o ipdb.o \
 prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
 socket.lib
 	./load tinydns server.o droproot.o tdlookup.o response.o \
+	ip4_num.o ip4_deaggregate.o ipdb.o \
 	qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
 	unix.a byte.a  `cat socket.lib`
 
@@ -997,10 +1019,22 @@
 	./compile tinydns-conf.c
 
 tinydns-data: \
-load tinydns-data.o cdb.a dns.a alloc.a buffer.a unix.a byte.a
-	./load tinydns-data cdb.a dns.a alloc.a buffer.a unix.a \
+load tinydns-data.o ip4_deaggregate.o ip4_num.o ipdb.o cdb.a dns.a alloc.a buffer.a unix.a byte.a
+	./load tinydns-data ip4_deaggregate.o ip4_num.o ipdb.o cdb.a dns.a alloc.a buffer.a unix.a \
 	byte.a 
 
+ipdb-make: \
+load ipdb-make.o ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+	./load ipdb-make ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+
+ipdb-get: \
+load ipdb-get.o ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+	./load ipdb-get ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+
+ipdb-get-test: \
+load ipdb-get-test.o ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+	./load ipdb-get-test ip4_num.o ip4_deaggregate.o ipdb.o alloc.a cdb.a buffer.a unix.a byte.a
+
 tinydns-data.o: \
 compile tinydns-data.c uint16.h uint32.h str.h byte.h fmt.h ip4.h \
 exit.h case.h scan.h buffer.h strerr.h getln.h buffer.h stralloc.h \
@@ -1019,10 +1053,12 @@
 	./compile tinydns-edit.c
 
 tinydns-get: \
-load tinydns-get.o tdlookup.o response.o printpacket.o printrecord.o \
-parsetype.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
-	./load tinydns-get tdlookup.o response.o printpacket.o \
-	printrecord.o parsetype.o dns.a libtai.a cdb.a buffer.a \
+load tinydns-get.o qlog.o tdlookup.o response.o printpacket.o printrecord.o \
+ip4_num.o ipdb.o \
+parsetype.o env.a dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a env.a
+	./load tinydns-get qlog.o tdlookup.o response.o printpacket.o \
+	ip4_num.o ipdb.o \
+	printrecord.o parsetype.o env.a dns.a libtai.a cdb.a buffer.a \
 	alloc.a unix.a byte.a 
 
 tinydns-get.o: \
diff -NubBE /root/build/d/djbdns-1.05/qlog.c ./qlog.c
--- /root/build/d/djbdns-1.05/qlog.c	2001-02-11 23:11:45.000000000 +0200
+++ ./qlog.c	2008-03-18 22:24:24.000000000 +0200
@@ -1,6 +1,7 @@
 #include "buffer.h"
 #include "qlog.h"
-
+#include <stdio.h>
+#include <unistd.h>
 static void put(char c)
 {
   buffer_put(buffer_2,&c,1);
@@ -20,6 +21,78 @@
   put('0' + (c & 7));
 }
 
+char * fqdn_read (char *out, int *label_idx, int *len, const char *q)
+{
+	char ch;
+	int maxlen = *len;
+	char ch2;
+	int cur_len = 0;
+	register int i = 0;
+	//int last = -1;
+	register int j = 0;
+  if (!*q) {
+		out[0] = '.';
+		label_idx[0] = -1;
+		*len = 1;
+		return out;
+  } else {
+		label_idx[0] = 0;
+    for (;;) {
+      ch = *q++;
+			cur_len+=ch;
+			if (cur_len >= maxlen) break;
+      while (ch--) {
+        ch2 = *q++;
+        if ((ch2 >= 'A') && (ch2 <= 'Z'))
+	  			ch2 += 32;
+        if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_')) {
+					out[j++] = ch2;
+        } else {
+					out[j] = '\\';j++;
+					out[j+1] = '0' + ((ch2 >> 6) & 7);
+					out[j+2] = '0' + ((ch2 >> 3) & 7);
+					out[j+3] = '0' + (ch2 & 7);
+					j+=4;
+				}
+      }
+      if (!*q) break;
+			out[j++] = '.';
+			i+=1;
+			if (i == 32) break;
+			label_idx[i] = j;
+			cur_len+=1;
+    }
+	}
+	out[j]='\0';
+	*len = cur_len;
+	return out;
+}
+
+void dlog(const char *q)
+{
+	char ch;
+	char ch2;
+  if (!*q)
+    put('.');
+  else
+    for (;;) {
+      ch = *q++;
+      while (ch--) {
+        ch2 = *q++;
+        if ((ch2 >= 'A') && (ch2 <= 'Z'))
+	  			ch2 += 32;
+        if (((ch2 >= 'a') && (ch2 <= 'z')) || ((ch2 >= '0') && (ch2 <= '9')) || (ch2 == '-') || (ch2 == '_'))
+	  			put(ch2);
+        else
+	  			octal(ch2);
+      }
+      if (!*q) break;
+      put('.');
+    }
+  put('\n');
+  buffer_flush(buffer_2);
+}
+
 void qlog(const char ip[4],uint16 port,const char id[2],const char *q,const char qtype[2],const char *result)
 {
   char ch;
diff -NubBE /root/build/d/djbdns-1.05/qlog.h ./qlog.h
--- /root/build/d/djbdns-1.05/qlog.h	2001-02-11 23:11:45.000000000 +0200
+++ ./qlog.h	2008-03-18 16:57:42.000000000 +0200
@@ -4,5 +4,6 @@
 #include "uint16.h"
 
 extern void qlog(const char *,uint16,const char *,const char *,const char *,const char *);
-
+extern void dlog(const char *);
+extern char * fqdn_read (char *, int *, int *, const char *);
 #endif
diff -NubBE /root/build/d/djbdns-1.05/README ./README
--- /root/build/d/djbdns-1.05/README	2001-02-11 23:11:45.000000000 +0200
+++ ./README	2008-03-18 22:25:16.000000000 +0200
@@ -5,3 +5,8 @@
 
 djbdns home page: http://cr.yp.to/djbdns.html
 Installation instructions: http://cr.yp.to/djbdns/install.html
+
+geoipdns home page: http://www.geoipdns.com
+Installation instructions: http://code.google.com/p/geoipdns
+
+
diff -NubBE /root/build/d/djbdns-1.05/scan_ushort.c ./scan_ushort.c
--- /root/build/d/djbdns-1.05/scan_ushort.c	1970-01-01 02:00:00.000000000 +0200
+++ ./scan_ushort.c	2008-03-18 16:57:42.000000000 +0200
@@ -0,0 +1,14 @@
+#include "scan.h"
+
+unsigned int scan_ushort(register const char *s,register unsigned short *u)
+{
+  register unsigned int pos = 0;
+  register unsigned short result = 0;
+  register unsigned short c;
+  while ((c = (unsigned short) (unsigned char) (s[pos] - '0')) < 10) {
+    result = result * 10 + c;
+    ++pos;
+  }
+  *u = result;
+  return pos;
+}
diff -NubBE /root/build/d/djbdns-1.05/server.c ./server.c
--- /root/build/d/djbdns-1.05/server.c	2001-02-11 23:11:45.000000000 +0200
+++ ./server.c	2008-03-18 22:25:37.000000000 +0200
@@ -1,4 +1,5 @@
 #include "byte.h"
+#include <stdio.h>
 #include "case.h"
 #include "env.h"
 #include "buffer.h"
Common subdirectories: /root/build/d/djbdns-1.05/.svn and ./.svn
diff -NubBE /root/build/d/djbdns-1.05/TARGETS ./TARGETS
--- /root/build/d/djbdns-1.05/TARGETS	2001-02-11 23:11:45.000000000 +0200
+++ ./TARGETS	2008-03-18 16:57:42.000000000 +0200
@@ -48,8 +48,11 @@
 case_lowerb.o
 fmt_ulong.o
 ip4_fmt.o
+ip4_deaggregate.o
 ip4_scan.o
 scan_ulong.o
+scan_ushort.o
+ip4_num.o
 str_chr.o
 str_diff.o
 str_len.o
@@ -214,3 +217,4 @@
 it
 setup
 check
+ipdb.o
diff -NubBE /root/build/d/djbdns-1.05/tdlookup.c ./tdlookup.c
--- /root/build/d/djbdns-1.05/tdlookup.c	2001-02-11 23:11:45.000000000 +0200
+++ ./tdlookup.c	2008-03-18 22:27:29.000000000 +0200
@@ -1,5 +1,8 @@
-#include <unistd.h>
 #include "uint16.h"
+#include <alloc.h>
+#include "str.h"
+#include <string.h>
+#include <stdlib.h>
 #include "open.h"
 #include "tai.h"
 #include "cdb.h"
@@ -8,6 +11,13 @@
 #include "dns.h"
 #include "seek.h"
 #include "response.h"
+#include "ipdb.h"
+#include "env.h"
+#include "scan.h"
+#include "prot.h"
+#include "strerr.h"
+#include "qlog.h"
+#define FATAL "tdlookup: fatal: "
 
 static int want(const char *owner,const char type[2])
 {
@@ -281,9 +290,20 @@
 int respond(char *q,char qtype[2],char ip[4])
 {
   int fd;
-  int r;
-  char key[6];
-
+  int r = 0;
+	//replace char t[] with stralloc t ?
+	char t[256];
+	char u[64];
+	char *z = NULL;
+	int l_idx[32]; //labels indexed in fqdn,including first pos (0)
+	register int i;
+	int l = 256;
+	stralloc fqdn_map;
+	int len;
+	unsigned short multimode = 0;
+	unsigned short ipmap = 0;
+	unsigned short multicdb = 0;
+	unsigned short multiuser = 0;
   tai_now(&now);
   fd = open_read("data.cdb");
   if (fd == -1) return 0;
@@ -288,22 +308,78 @@
   fd = open_read("data.cdb");
   if (fd == -1) return 0;
   cdb_init(&c,fd);
-
   byte_zero(clientloc,2);
-  key[0] = 0;
-  key[1] = '%';
-  byte_copy(key + 2,4,ip);
-  r = cdb_find(&c,key,6);
-  if (!r) r = cdb_find(&c,key,5);
-  if (!r) r = cdb_find(&c,key,4);
-  if (!r) r = cdb_find(&c,key,3);
-  if (!r) r = cdb_find(&c,key,2);
+	fqdn_map.s = NULL;
+	fqdn_map.len = 0;
+	// OPMODE: MULTICDB == 2; MULTIUSER == 1
+	z = env_get("IPMAP"); if (z) scan_ushort((const char *)z,&ipmap);
+	z = env_get("MULTICDB"); if (z) scan_ushort((const char *)z, &multicdb);
+	z = env_get("MULTIUSER"); if (z) scan_ushort((const char *)z, &multiuser);
+	multimode = multicdb | multiuser;
+	if (multimode) {
+#ifdef TESTMODE
+		fprintf(stderr,"multimode: lookup fqdn map in progress\n");
+#endif
+		fqdn_read(t,l_idx,&l,q);
+		for (i = 0; i < 32 && l_idx[i] != -1; i++) {
+#ifdef TESTMODE
+			fprintf(stderr,"check: %s\n", t+l_idx[i]);
+#endif
+			stralloc_copyb(&fqdn_map,"\0?",2);
+			stralloc_catb(&fqdn_map,t+l_idx[i],l-l_idx[i]);
+			r = cdb_find(&c,fqdn_map.s,fqdn_map.len);
+			if (r) break;
   if (r == -1) return 0;
-  if (r && (cdb_datalen(&c) == 2))
-    if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0;
+		}
+		if (!r) return 0;
+	}
 
+	if (!r) {
+#ifdef TESTMODE
+		fprintf(stderr,"singlemode: lookup_ipdbmap? %s\n", (ipmap)?"yes":"no");
+#endif
+		if ( ipmap &&  !ipdb_get(&c,ip,NULL,0,clientloc)) return 0;
+	} else {
+		len = cdb_datalen(&c);
+		if (len > 63) return 0;
+		if (cdb_read(&c,u,len,cdb_datapos(&c)) == -1) return 0;
+		u[len] = '\0';
+#ifdef TESTMODE
+		fprintf(stderr,"multimode: use_map %s <-> %s, use_cdb_mapping: %s\n", t+l_idx[i], u+1, 
+			(u[0] == '1' && ipmap)?"yes":"no");
+#endif
+		if (u[0] == '1' && ipmap ) {
+			clientloc[0] = 'X';
+			clientloc[1] = 'X';
+		} 
+		if (multicdb) {
+#ifdef TESTMODE
+			fprintf(stderr,"MULTICDB mode: reopen(data.cdb,%s)\n", u+1);
+#endif
+			cdb_free(&c);
+			close(fd);
+			fd = open_read(u+1);
+			if (fd == -1) return 0;
+			cdb_init(&c,fd);
+			if (u[0] == '1' && ipmap ) {
+#ifdef TESTMODE
+				fprintf(stderr,"using multicdb multimode with ipdbmap\n");
+#endif
+				if (!ipdb_get(&c,ip,NULL,0,clientloc)) return 0;
+			}
+		} else {
+#ifdef TESTMODE
+			fprintf(stderr,"get data from same cdb for ukey %s (%c) %d\n", u+1, u[0],len);
+#endif
+			if (u[0] == '1' && ipmap && multiuser) {
+				if (!ipdb_get(&c,ip,u+1,len-1,clientloc)) return 0;
+#ifdef TESTMODE
+				fprintf(stderr,"got clientloc as %c%c\n", clientloc[0],clientloc[1]);
+#endif
+			}
+		}
+	}
   r = doit(q,qtype);
-
   cdb_free(&c);
   close(fd);
   return r;
diff -NubBE /root/build/d/djbdns-1.05/tinydns-data.c ./tinydns-data.c
--- /root/build/d/djbdns-1.05/tinydns-data.c	2001-02-11 23:11:45.000000000 +0200
+++ ./tinydns-data.c	2008-03-18 22:30:03.000000000 +0200
@@ -2,6 +2,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include "alloc.h"
 #include "uint16.h"
 #include "uint32.h"
 #include "str.h"
@@ -12,6 +13,7 @@
 #include "case.h"
 #include "scan.h"
 #include "buffer.h"
+#include "ipdb.h"
 #include "strerr.h"
 #include "getln.h"
 #include "cdb_make.h"
@@ -181,9 +183,16 @@
   strerr_die4x(111,FATAL,"unable to parse data line ",strnum,why);
 }
 
-int main()
+int main(int argc, char **argv)
 {
   int fddata;
+	int v;
+	char ipa[4];
+	char ipb[4];
+	ip4_cidr_t *subnets = (ip4_cidr_t *)NULL;
+	unsigned int slen = 0;
+	unsigned int ipinta = 0;
+	unsigned int ipintb = 0;
   int i;
   int j;
   int k;
@@ -196,18 +205,21 @@
   char type[2];
   char soa[20];
   char buf[4];
-
   umask(022);
-
+	fddata = STDIN_FILENO;
+	if (argc != 3) {
   fddata = open_read("data");
-  if (fddata == -1)
-    strerr_die2sys(111,FATAL,"unable to open data: ");
+		if (fddata == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
+		if ( (fdcdb = open_trunc("data.tmp")) == -1) die_datatmp();
+	} else {
+		fddata = STDIN_FILENO;
+		if ( (fdcdb = open_trunc(argv[1])) == -1) die_datatmp();
+	}
+	
   defaultsoa_init(fddata);
 
   buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace);
 
-  fdcdb = open_trunc("data.tmp");
-  if (fdcdb == -1) die_datatmp();
   if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();
 
   while (match) {
@@ -237,14 +248,32 @@
     }
 
     switch(line.s[0]) {
-
+	case '?':
+		if (!stralloc_copyb(&key,"\0?",2)) nomem();
+		if (!stralloc_cat(&key,&f[0])) nomem();
+		if (!f[1].s) nomem();
+		if (!f[2].s || f[2].len != 1) nomem();
+		if (!stralloc_cat(&f[2],&f[1])) nomem();
+		cdb_make_add(&cdb,key.s,key.len,f[2].s,f[2].len);
+		break;
       case '%':
 	locparse(&f[0],loc);
-	if (!stralloc_copyb(&key,"\0%",2)) nomem();
 	if (!stralloc_0(&f[1])) nomem();
-	ipprefix_cat(&key,f[1].s);
-        if (cdb_make_add(&cdb,key.s,key.len,loc,2) == -1)
-          die_datatmp();
+	if (!stralloc_0(&f[2])) nomem();
+	ip4_scan(f[1].s,ipa);
+	ip4_scan(f[2].s,ipb);
+	ip4_num(&ipinta,ipa);
+	ip4_num(&ipintb,ipb);
+	if (ipintb<ipinta) nomem();
+	if (ip4_deaggregate(ipinta,ipintb,&subnets,&slen) <= 0) nomem();
+	for (v = 0; v < slen; v++) {
+		ipdb_key_from_uint(&key,subnets[v].subnet,subnets[v].mask,f[3].s,f[3].len,0);
+		cdb_make_add(&cdb,key.s,key.len,loc,2);
+	}
+	alloc_free(subnets);
+	subnets = NULL;
+	slen = 0;
+	byte_zero(ipa,4);byte_zero(ipb,4);ipinta=0;ipintb=0;
 	break;
 
       case 'Z':
@@ -449,8 +478,11 @@
   if (cdb_make_finish(&cdb) == -1) die_datatmp();
   if (fsync(fdcdb) == -1) die_datatmp();
   if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
-  if (rename("data.tmp","data.cdb") == -1)
-    strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
+	if (argc  == 3) {
+		if (rename(argv[1],argv[2]) == -1) strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
+	} else {
+		if (rename("data.tmp","data.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
+	}
 
   _exit(0);
 }
