diff -Naur ./djbdns-1.05.orig/dnscache.c ./djbdns-1.05/dnscache.c --- ./djbdns-1.05.orig/dnscache.c 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/dnscache.c 2011-07-13 00:23:19.000000000 +0200 @@ -24,6 +24,9 @@ #include "okclient.h" #include "droproot.h" #include "maxclient.h" +#include "openreadclose.h" +#include "open.h" +#include "cdb.h" long interface; @@ -473,6 +476,18 @@ if (socket_listen(tcp53,20) == -1) strerr_die2sys(111,FATAL,"unable to listen on TCP socket: "); + int fd = open_read("rewrite.cdb"); + if (fd > -1) { + cdb_init(&c, fd); + query_rewrite_enabled = 1; + } + log_rewrite(query_rewrite_enabled); + log_startup(); doit(); + + if (query_rewrite_enabled) { + cdb_free(&c); + close(fd); + } } diff -Naur ./djbdns-1.05.orig/log.c ./djbdns-1.05/log.c --- ./djbdns-1.05.orig/log.c 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/log.c 2011-07-13 00:17:20.000000000 +0200 @@ -292,3 +292,10 @@ number(tactive); line(); } + +void log_rewrite(unsigned enabled) +{ + string("rewrite "); + string((enabled) ? "enabled" : "disabled"); + line(); +} diff -Naur ./djbdns-1.05.orig/log.h ./djbdns-1.05/log.h --- ./djbdns-1.05.orig/log.h 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/log.h 2011-07-13 00:22:05.000000000 +0200 @@ -33,5 +33,6 @@ extern void log_rrsoa(const char *,const char *,const char *,const char *,const char *,unsigned int); extern void log_stats(void); +extern void log_rewrite(unsigned enabled); #endif diff -Naur ./djbdns-1.05.orig/Makefile ./djbdns-1.05/Makefile --- ./djbdns-1.05.orig/Makefile 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/Makefile 2011-07-13 00:21:52.000000000 +0200 @@ -344,10 +344,10 @@ dnscache: \ load dnscache.o droproot.o okclient.o log.o cache.o query.o qmerge.o \ response.o dd.o roots.o iopause.o prot.o dns.a env.a alloc.a buffer.a \ -libtai.a unix.a byte.a socket.lib +libtai.a cdb.a unix.a byte.a socket.lib ./load dnscache droproot.o okclient.o log.o cache.o \ query.o qmerge.o response.o dd.o roots.o iopause.o prot.o dns.a \ - env.a alloc.a buffer.a libtai.a unix.a byte.a `cat \ + env.a alloc.a buffer.a libtai.a cdb.a unix.a byte.a `cat \ socket.lib` dnscache-conf: \ diff -Naur ./djbdns-1.05.orig/query.c ./djbdns-1.05/query.c --- ./djbdns-1.05.orig/query.c 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/query.c 2011-07-13 00:24:01.000000000 +0200 @@ -13,6 +13,53 @@ #include "response.h" #include "query.h" #include "ip6.h" +#include "cdb.h" + +struct cdb c; +int query_rewrite_enabled = 0; +static char cdb_data[32767]; +static uint32 cdb_dlen; +static char cdb_type[2]; +static unsigned int cdb_dpos; +static char *cdb_domain; + +int query_rewrite_name(char **name, unsigned from_client) +{ + int r; + unsigned int pos, len; + char *newname, *tmp; + unsigned char x; + const char *type = (from_client) ? DNS_T_CNAME : DNS_T_PTR; + + if (!query_rewrite_enabled) return 1; + + tmp = *name; + while (x = *tmp++) { + tmp += (unsigned int) x; + r = cdb_find(&c, tmp, dns_domain_length(tmp)); + if (r <= 0) continue; + cdb_dlen = cdb_datalen(&c); + if (cdb_dlen > sizeof cdb_data) continue; + if (cdb_read(&c, cdb_data, cdb_dlen, cdb_datapos(&c)) == -1) continue; + cdb_dpos = dns_packet_copy(cdb_data, cdb_dlen, 0, cdb_type, 2); + if (!byte_equal(cdb_type, 2, type)) continue; + cdb_dpos += 1 + 4 + 8; + cdb_dpos = dns_packet_getname(cdb_data, cdb_dlen, cdb_dpos, &cdb_domain); + if (!cdb_dpos) continue; + + len = dns_domain_length(cdb_domain); + pos = tmp - *name; + newname = alloc(pos + len); + if (!newname) return 0; + byte_copy(newname, pos, *name); // copy name prefix + byte_copy(newname + pos, len, cdb_domain); // copy new name suffix + if (*name) alloc_free(*name); + *name = newname; + break; + } + + return 1; +} extern stralloc ignoreip; @@ -97,6 +144,7 @@ static int rqa(struct query *z) { int i; + char *namecpy = 0; for (i = QUERY_MAXALIAS - 1;i >= 0;--i) if (z->alias[i]) { @@ -109,7 +157,13 @@ return 1; } - if (!response_query(z->name[0],z->type,z->class)) return 0; + if (query_rewrite_enabled) { + if (!dns_domain_copy(&namecpy,z->name[0])) return 0; + if (!query_rewrite_name(&namecpy, 0)) return 0; + if (!response_query(namecpy,z->type,z->class)) return 0; + alloc_free(namecpy); + } else + if (!response_query(z->name[0],z->type,z->class)) return 0; return 1; } @@ -643,6 +697,8 @@ dns_sortip6(z->servers[z->level],256); dtype = z->level ? DNS_T_A : z->type; + + if (!query_rewrite_name(&z->name[z->level], 1)) goto DIE; if (qmerge_start(&z->qm,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip,z->control[z->level]) == -1) goto DIE; return 0; @@ -786,6 +842,7 @@ if (!dns_domain_suffix(t1,control)) { i = j; continue; } if (!roots_same(t1,control)) { i = j; continue; } + if (!query_rewrite_name(&t1, 0)) goto DIE; if (byte_equal(type,2,DNS_T_ANY)) ; @@ -983,6 +1040,7 @@ if (dns_domain_equal(t1,d)) if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */ if (typematch(header,dtype)) { + if (!query_rewrite_name(&t1, 0)) goto DIE; if (!response_rstart(t1,header,ttl)) goto DIE; if (typematch(header,DNS_T_NS) || typematch(header,DNS_T_CNAME) || typematch(header,DNS_T_PTR)) { diff -Naur ./djbdns-1.05.orig/query.h ./djbdns-1.05/query.h --- ./djbdns-1.05.orig/query.h 2011-07-12 15:32:50.000000000 +0200 +++ ./djbdns-1.05/query.h 2011-07-12 23:57:12.000000000 +0200 @@ -30,4 +30,7 @@ extern void query_forwardonly(void); +extern struct cdb c; +extern int query_rewrite_enabled; + #endif