Commit Diff
Diff:
d9a2aaa34932bcba1f8a4d3509b3272ba92b3d86
b6dc64dc1db61d755de1808df54a715167eb0c92
Commit:
b6dc64dc1db61d755de1808df54a715167eb0c92
Tree:
a18c2041f556fcb332a4d45e113fe57eb50d17f4
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Thu Apr 15 17:56:39 2010 UTC
Message:
* start development towards recursive lookups, the -r flag (for now) turns on the recursive mode and the "recurse-for" access list allows clients to be recursed. This doesn't work yet but I like the philosophy of commit early and commit often, till the next BETA tag anyhow. * this has the new compress_label() function in it
blob - 351f05b67bd2e94eec793bc45115c9ab56973910
blob + a44be98b665464d827f74e2a334bb77da83aa4ad
--- Makefile.bsd
+++ Makefile.bsd
@@ -1,5 +1,5 @@
PROG=wildcarddnsd
-SRCS=main.c parse.c reply.c additional.c region.c wildcard.c
+SRCS=main.c parse.c reply.c additional.c region.c wildcard.c recurse.c
#CFLAGS= -DDEBUG -g -Wall
CFLAGS= -Wall -g
blob - 43fc25cf0edc3da1af49c2e0c50c965a5577bb0b
blob + ab840d70e4c64c140c9b27886a6c557ddf80e280
--- additional.c
+++ additional.c
@@ -34,9 +34,9 @@ int additional_aaaa(char *, int, struct domain *, char
int additional_mx(char *, int, struct domain *, char *, int, int, int *);
int additional_ptr(char *, int, struct domain *, char *, int, int, int *);
-extern int compress_label(char *, int, int);
+extern int compress_label(u_char *, int, int);
-static const char rcsid[] = "$Id: additional.c,v 1.8 2010/03/28 20:18:26 pbug Exp $";
+static const char rcsid[] = "$Id: additional.c,v 1.9 2010/04/15 17:56:39 pbug Exp $";
/*
blob - cd0117b4a726f529a51a7e55b3958e2a655c408f
blob + a959d73e1a6e97bf259105c52e6ae9aa9151d9d4
--- db.h
+++ db.h
@@ -74,8 +74,10 @@ struct domain {
#define DOMAIN_HAVE_AAAA 0x20
#define DOMAIN_HAVE_NS 0x40
#define DOMAIN_HAVE_TXT 0x80
+#define DOMAIN_STATIC_ZONE 0x100
struct soa *soa; /* start of authority */
u_int32_t ttl; /* time to live */
+ time_t created; /* time created, for dynamic zones */
in_addr_t a[RECORD_COUNT]; /* IP addresses */
u_int8_t region[RECORD_COUNT]; /* region of IP address */
int a_count; /* IP address count (max 10) */
@@ -113,6 +115,16 @@ struct sreply {
int istcp; /* when set it's tcp */
int wildcard; /* wildcarding boolean */
};
+
+struct srecurseheader {
+ int af; /* address family */
+ int proto; /* protocol UDP/TCP */
+ struct sockaddr_storage source; /* source + port */
+ struct sockaddr_storage dest; /* dest + port */
+ int len; /* length of question */
+ char buf[512]; /* question buffer */
+};
+
int parse_file(DB *db, char *);
DB * opendatabase(DB *);
blob - aae9d19b7b027337917ab10c669c758ccc13aede
blob + b537057ca6e599bf1748948092f0587419a6706a
--- example7.conf
+++ example7.conf
@@ -178,3 +178,39 @@ zone "reverse dns" {
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.7.0.f.0.6.a.0.1.0.0.2.ip6.arpa.,ptr,3600,uranus.centroid.eu.
2.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.7.0.f.0.6.a.0.1.0.0.2.ip6.arpa.,ptr,3600,setebos.centroid.eu.
}
+
+zone "root hints" {
+ .,hint,3600000,A.ROOT-SERVERS.NET.
+ A.ROOT-SERVERS.NET.,a,3600000,198.41.0.4
+ A.ROOT-SERVERS.NET.,aaaa,3600000,2001:503:BA3E::2:30
+ .,hint,3600000,B.ROOT-SERVERS.NET.
+ B.ROOT-SERVERS.NET.,a,3600000,192.228.79.201
+ .,hint,3600000,C.ROOT-SERVERS.NET.
+ C.ROOT-SERVERS.NET.,a,3600000,192.33.4.12
+ .,hint,3600000,D.ROOT-SERVERS.NET.
+ D.ROOT-SERVERS.NET.,a,3600000,128.8.10.90
+ .,hint,3600000,E.ROOT-SERVERS.NET.
+ E.ROOT-SERVERS.NET.,a,3600000,192.203.230.10
+ .,hint,3600000,F.ROOT-SERVERS.NET.
+ F.ROOT-SERVERS.NET.,a,3600000,192.5.5.241
+ F.ROOT-SERVERS.NET.,aaaa,3600000,2001:500:2f::f
+ .,hint,3600000,G.ROOT-SERVERS.NET.
+ G.ROOT-SERVERS.NET.,a,3600000,192.112.36.4
+ .,hint,3600000,H.ROOT-SERVERS.NET.
+ H.ROOT-SERVERS.NET.,a,3600000,128.63.2.53
+ H.ROOT-SERVERS.NET.,aaaa,3600000,2001:500:1::803f:235
+ .,hint,3600000,I.ROOT-SERVERS.NET.
+ I.ROOT-SERVERS.NET.,a,3600000,192.36.148.17
+ .,hint,3600000,J.ROOT-SERVERS.NET.
+ J.ROOT-SERVERS.NET.,a,3600000,192.58.128.30
+ J.ROOT-SERVERS.NET.,aaaa,3600000,2001:503:C27::2:30
+ .,hint,3600000,K.ROOT-SERVERS.NET.
+ K.ROOT-SERVERS.NET.,a,3600000,193.0.14.129
+ K.ROOT-SERVERS.NET.,aaaa,3600000,2001:7fd::1
+ .,hint,3600000,L.ROOT-SERVERS.NET.
+ L.ROOT-SERVERS.NET.,a,3600000,199.7.83.42
+ L.ROOT-SERVERS.NET.,aaaa,3600000,2001:500:3::42
+ .,hint,3600000,M.ROOT-SERVERS.NET.
+ M.ROOT-SERVERS.NET.,a,3600000,202.12.27.33
+ M.ROOT-SERVERS.NET.,aaaa,3600000,2001:dc3::35
+}
blob - 52c16d5aa42b860e7a61a496e4f06dc5b355b9d3
blob + 1ec65d87f492681b9f9f28eaafc11553da749b2a
--- main.c
+++ main.c
@@ -33,7 +33,7 @@
struct question * build_question(char *, int);
struct question * build_fake_question(char *, int, u_int16_t);
-void mainloop(int *, int *, int, char **, DB *);
+void mainloop(int *, int *, int, char **, DB *, int);
int free_question(struct question *);
int lookup_zone(DB *, struct question *, struct domain *, int *, char *, int);
int get_soa(DB *, struct question *, struct domain *, int);
@@ -54,13 +54,16 @@ extern u_int8_t find_region(struct sockaddr_storage *s
extern int find_wildcard(struct sockaddr_storage *sst, int family);
extern void init_wildcard(void);
extern void collects_init(void);
+extern void recurseloop(int sp, int *raw, DB *db);
+extern int find_recurse(struct sockaddr_storage *, int);
+extern void init_recurse(void);
char * dns_label(char *, int *);
-int compress_label(char *, int, int);
+int compress_label(u_char *, u_int16_t, int);
int memcasecmp(char *, char *, int);
char * get_dns_type(int dnstype);
void build_reply(struct sreply *reply, int so, char *buf, int len, struct question *q, struct sockaddr *sa, socklen_t slen, struct domain *sd1, struct domain *sd2, u_int8_t region, int istcp, int wildcard);
-
+void recurseheader(struct srecurseheader *, int, struct sockaddr_storage *, struct sockaddr_storage *, int);
/* aliases */
#define DEFAULT_PRIVILEGE "named"
@@ -87,6 +90,8 @@ struct typetable {
extern char *__progname;
static int lflag = 0;
+static int rflag = 0;
+static u_int16_t port = 53;
/* singly linked list for tcp operations */
SLIST_HEAD(listhead, tcps) tcpshead;
@@ -107,7 +112,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.50 2010/04/05 11:54:13 pbug Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.51 2010/04/15 17:56:39 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -119,6 +124,7 @@ main(int argc, char *argv[])
{
int udp[DEFAULT_SOCKET];
int tcp[DEFAULT_SOCKET];
+ int raw[2];
int ch, i, j;
int gai_error;
@@ -126,9 +132,11 @@ main(int argc, char *argv[])
int bflag = 0, iflag = 0;
int bcount = 0, icount = 0;
int found = 0;
- u_int16_t port = 53;
int on = 1;
+ int sp[2];
+ pid_t pid;
+
static char *ident[DEFAULT_SOCKET];
char *conffile = CONFFILE;
char buf[512];
@@ -148,7 +156,7 @@ main(int argc, char *argv[])
exit(1);
}
- while ((ch = getopt(argc, argv, "b:f:i:lp:")) != -1) {
+ while ((ch = getopt(argc, argv, "b:f:i:lp:r")) != -1) {
switch (ch) {
case 'b':
bflag = 1;
@@ -175,8 +183,11 @@ main(int argc, char *argv[])
case 'p':
port = atoi(optarg) & 0xffff;
break;
+ case 'r':
+ rflag = 1;
+ break;
default:
- fprintf(stderr, "usage: wildcarddnsd [-i interface] [-b bindaddress] [-f configfile] [-p portnumber]\n");
+ fprintf(stderr, "usage: wildcarddnsd [-i interface] [-b bindaddress] [-f configfile] [-p portnumber] [-r]\n");
exit (1);
}
}
@@ -227,6 +238,7 @@ main(int argc, char *argv[])
#endif
init_wildcard();
+ init_recurse();
if (parse_file(db, conffile) < 0) {
syslog(LOG_INFO, "parsing config file failed");
@@ -364,13 +376,7 @@ main(int argc, char *argv[])
sin6->sin6_port = htons(port);
/* no address bound to this interface */
salen = sizeof(struct sockaddr_in6);
-
- /*
- if (IN6_IS_ADDR_UNSPECIFIED(*(sin6->sin6_addr))) {
- i--;
- continue;
- }
- */
+
} else {
#ifdef DEBUG
syslog(LOG_INFO, "unknown address family %d\n", pifap->ifa_addr->sa_family);
@@ -418,7 +424,7 @@ main(int argc, char *argv[])
exit(1);
}
- }
+ } /* AF_INET */
if (i >= DEFAULT_SOCKET) {
syslog(LOG_INFO, "not enough sockets available\n");
@@ -426,6 +432,23 @@ main(int argc, char *argv[])
}
}
+ if (rflag == 1) {
+ if ((raw[0] = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
+ syslog(LOG_INFO, "raw socket: %m");
+ exit(1);
+ }
+
+ if (setsockopt(raw[0], IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)) < 0) {
+ syslog(LOG_INFO, "raw setsockopt: %m");
+ exit(1);
+ }
+
+ if ((raw[1] = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0) {
+ syslog(LOG_INFO, "raw socket[1]: %m");
+ exit(1);
+ }
+
+ } /* rflag */
#ifndef DEBUG
/* chroot to the drop priv user home directory */
if (chroot(pw->pw_dir) < 0) {
@@ -483,9 +506,43 @@ main(int argc, char *argv[])
}
#endif
- (void)mainloop((int *)&udp, (int *)&tcp, i, ident, db);
+ if (rflag) {
+ /*
+ * set up socket pair
+ */
+
+ if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (int *)&sp) < 0) {
+ syslog(LOG_INFO, "socketpair: %m");
+ exit(1);
+ }
+
+ switch (pid = fork()) {
+ case -1:
+ syslog(LOG_INFO, "fork: %m");
+ exit(1);
+ case 0:
+ for (j = 0; j < i; j++) {
+ close(tcp[j]);
+ close(udp[j]);
+ }
+ close (sp[1]);
+ recurseloop(sp[0], (int *)&raw, db);
+ /* NOTREACHED */
+ break;
+
+ default:
+ close(raw[0]);
+ close(raw[1]);
+ close (sp[0]);
+ break;
+ } /* switch */
+ } /* rflag */
+
+ (void)mainloop((int *)&udp, (int *)&tcp, i, ident, db, (rflag ? sp[1] : -1));
+
+
/* NOTREACHED */
return 0;
}
@@ -767,71 +824,178 @@ dns_label(char *name, int *returnlen)
* that reply.
*/
-int
-compress_label(char *buf, int offset, int labellen)
+int
+compress_label(u_char *buf, u_int16_t offset, int labellen)
{
- int i, j;
- int checklen;
- int expandlen, expandoffset;
+ u_char *label[256]; /* should be enough */
+ u_char *end = &buf[offset];
+ struct question {
+ u_int16_t type;
+ u_int16_t class;
+ } __attribute__((packed));
+ struct answer {
+ u_int16_t type;
+ u_int16_t class;
+ u_int32_t ttl;
+ u_int16_t rdlength;
+ } __attribute__((packed));
+ struct soa {
+ u_int32_t serial;
+ u_int32_t refresh;
+ u_int32_t retry;
+ u_int32_t expire;
+ u_int32_t minttl;
+ } __attribute__((packed));
+
+ struct answer *a;
+
+ u_int i, j;
+ u_int checklen;
u_int16_t *compressor;
- u_int16_t *checkcompress;
- char expandbuf[512];
- char *p, *e;
- char *compressmark;
+ u_char *p, *e;
+ u_char *compressmark;
- p = &buf[offset - labellen];
- checklen = labellen;
- for (;*p != 0;) {
+ p = &buf[sizeof(struct dns_header)];
+ label[0] = p;
+
+ while (p <= end && *p) {
+ p += *p;
+ p++;
+ }
+
+ /*
+ * the question label was bogus, we'll just get out of there, return 0
+ */
- for (i = sizeof(struct dns_header); i < (offset - labellen); i++) {
+ if (p >= end)
+ return (0);
- /*
- * fill in and expand a buffer with data from the
- * packet
- */
+ p += sizeof(struct question);
+ p++; /* one more */
+ /* start of answer/additional/authoritative */
- memcpy(expandbuf, &buf[i], checklen); /* XXX expensive */
- e = &expandbuf[0];
- /*
- * check this entire name, expanding compression as we go
- */
+ for (i = 1; i < 100; i++) {
+ label[i] = p;
- for (j = 0; j < checklen; j++) {
- if (expandbuf[j] == 0)
- break; /* end of lookup */
- checkcompress = (u_int16_t *)&expandbuf[j];
- if ((ntohs(*checkcompress) & 0xc000) == 0xc000){
- expandoffset = (ntohs(*checkcompress) & ~(0xc000));
- expandlen = checklen - j;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
- if (offset < (expandlen + expandoffset)) {
- /* can't expand this, it's bogus, ie beyond our buffer offset */
- break;
- }
+ if (p >= end)
+ goto end;
+ }
+
+ p++; /* one more */
- memcpy((char*)&expandbuf[j], (char*)&buf[expandoffset], expandlen); /* XXX expensive */
- /* check once more that our search does not terminate */
- if (expandbuf[j] == 0) {
- e = &expandbuf[j];
- break;
- }
+ a = (struct answer *)p;
+ p += sizeof(struct answer);
+
+ switch (ntohs(a->type)) {
+ case DNS_TYPE_A:
+ p += sizeof(in_addr_t);
+ break;
+ case DNS_TYPE_AAAA:
+ p += 16; /* sizeof 4 * 32 bit */
+ break;
+ case DNS_TYPE_TXT:
+ p += *p;
+ p++;
+ break;
+ case DNS_TYPE_MX:
+ p += sizeof(u_int16_t); /* mx_priority */
+ /* FALLTHROUGH */
+ case DNS_TYPE_NS:
+ case DNS_TYPE_PTR:
+ case DNS_TYPE_CNAME:
+ label[++i] = p;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
}
+ p += *p;
+ p++;
- j += *e;
- e = &expandbuf[j];
- e++;
- }
+ if (p >= end)
+ goto end;
+ }
- /* check packet for a matching name */
- if (*e == 0 && memcasecmp(&expandbuf[0], p, checklen) == 0) {
- compressmark = &buf[i];
- goto out; /* found one */
- }
- }
+ p++; /* one more */
+ break;
+ case DNS_TYPE_SOA:
+ /* nsserver */
+ label[++i] = p;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
+ if (p >= end)
+ goto end;
+ }
+ p++; /* one more */
+
+ if (p >= end)
+ break;
+
+ /* responsible person */
+ label[++i] = p;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
+ }
+
+ p++; /* one more */
+
+ if (p >= end)
+ break;
+
+ p += sizeof(struct soa); /* advance struct soa */
+
+ break;
+ default:
+ break;
+ /* XXX */
+ } /* switch */
+
+ if (p >= end)
+ break;
+ } /* for (i *) */
+
+end:
+
+ p = &buf[offset - labellen];
+ checklen = labellen;
+
+ for (;*p != 0;) {
+ for (j = 0; j < i; j++) {
+ for (e = label[j]; *e; e += *e, e++) {
+ if ((*e & 0xc0) == 0xc0)
+ break;
+
+ if (memcasecmp(e, p, checklen) == 0) {
+ /* e is now our compress offset */
+ compressmark = e;
+ goto out; /* found one */
+ }
+ } /* for (e .. */
+
+ } /* for (j .. */
+
if (*p > DNS_MAXLABEL)
return 0; /* totally bogus label */
@@ -839,10 +1003,9 @@ compress_label(char *buf, int offset, int labellen)
p += *p;
checklen--;
p++;
-
}
- return 0; /* no compression possible */
+ return (0); /* no compression possible */
out:
/* take off our compress length */
@@ -861,7 +1024,6 @@ out:
return (offset);
}
-
/*
* MEMCASECMP - check if buffer is identical to another buffer with
* one exception if a character is alphabetic it's
@@ -1360,7 +1522,7 @@ get_dns_type(int dnstype)
*/
void
-mainloop(int *udp, int *tcp, int sockcount, char **ident, DB *db)
+mainloop(int *udp, int *tcp, int sockcount, char **ident, DB *db, int sp)
{
fd_set rset;
int sel;
@@ -1399,16 +1561,19 @@ mainloop(int *udp, int *tcp, int sockcount, char **ide
} sockaddr_large;
socklen_t fromlen = sizeof(sockaddr_large);
+ socklen_t namelen = sizeof(struct sockaddr_storage);
struct sockaddr *from = (void *)&sockaddr_large;
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
+ struct sockaddr_storage sto;
struct dns_header *dh;
struct question *question, *fakequestion;
struct domain sd0, sd1;
struct sreply sreply;
+ struct srecurseheader rh;
struct timeval tv = { 10, 0};
struct msghdr msgh;
@@ -1416,6 +1581,7 @@ mainloop(int *udp, int *tcp, int sockcount, char **ide
struct iovec iov;
int flag;
+ int recursion = 0;
SLIST_INIT(&tcpshead);
collects_init();
@@ -1970,7 +2136,14 @@ tcpnxdomain:
break;
}
}
-
+
+ if (rflag) {
+ if (getsockname(so, (struct sockaddr*)&sto, &namelen) < 0) {
+ syslog(LOG_INFO, "getsockname failed: %m");
+ }
+
+ memset(&rh, 0, sizeof(rh));
+ }
if (from->sa_family == AF_INET6) {
is_ipv6 = 1;
@@ -1980,9 +2153,10 @@ tcpnxdomain:
inet_ntop(AF_INET6, (void *)&sin6->sin6_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin6, AF_INET6);
wildcard = find_wildcard((struct sockaddr_storage *)sin6, AF_INET6);
-#if 0
- syslog(LOG_INFO, "wildcarding is %s", (wildcard ? "on" : "off"));
-#endif
+ if (rflag) {
+ recursion = find_recurse((struct sockaddr_storage *)sin6, AF_INET6);
+ recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin6, &sto, AF_INET6);
+ }
} else if (from->sa_family == AF_INET) {
is_ipv6 = 0;
@@ -1991,6 +2165,10 @@ tcpnxdomain:
inet_ntop(AF_INET, (void *)&sin->sin_addr, (char *)&address, sizeof(address));
aregion = find_region((struct sockaddr_storage *)sin, AF_INET);
wildcard = find_wildcard((struct sockaddr_storage *)sin, AF_INET);
+ if (rflag) {
+ recursion = find_recurse((struct sockaddr_storage *)sin, AF_INET);
+ recurseheader(&rh, IPPROTO_UDP, (struct sockaddr_storage*)sin, &sto, AF_INET);
+ }
} else {
syslog(LOG_INFO, "packet received on descriptor %u interface \"%s\" had weird address family (%u), drop", so, ident[i], from->sa_family);
goto drop;
@@ -2024,6 +2202,10 @@ tcpnxdomain:
goto drop;
}
+ if (rflag && recursion) {
+ memcpy(&rh.buf, buf, len);
+ rh.len = len;
+ }
if ((question = build_question(buf, len)) == NULL) {
syslog(LOG_INFO, "on descriptor %u interface \"%s\" malformed question from %s, drop", so, ident[i], address);
@@ -2045,48 +2227,66 @@ tcpnxdomain:
case ERR_NXDOMAIN:
goto udpnxdomain;
case ERR_NOERROR:
- /*
- * this is hackish not sure if this should be here
- */
+ if (rflag && recursion) {
+ snprintf(replystring, DNS_MAXNAME, "RECURSE");
+ if (send(sp, (char *)&rh, sizeof(rh), 0) < 0) {
+ syslog(LOG_INFO, "send sp: %m");
+ }
- snprintf(replystring, DNS_MAXNAME, "NOERROR");
+ goto udpout;
+ } else {
+ /*
+ * this is hackish not sure if this should be here
+ */
- /*
- * lookup an authoritative soa
- */
+ snprintf(replystring, DNS_MAXNAME, "NOERROR");
- memset(&sd0, 0, sizeof(sd0));
- (void)get_soa(db, question, &sd0, wildcard);
+ /*
+ * lookup an authoritative soa
+ */
- build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard);
+ memset(&sd0, 0, sizeof(sd0));
+ (void)get_soa(db, question, &sd0, wildcard);
- reply_noerror(&sreply);
- goto udpout;
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard);
+ reply_noerror(&sreply);
+ goto udpout;
+ } /* else rflag */
}
}
switch (type0) {
case 0:
- /*
- * lookup_zone could not find an RR for the
- * question at all -> nxdomain
- */
udpnxdomain:
- snprintf(replystring, DNS_MAXNAME, "NXDOMAIN");
+ if (rflag && recursion) {
+ snprintf(replystring, DNS_MAXNAME, "RECURSE");
+ if (send(sp, (char *)&rh, sizeof(rh), 0) < 0) {
+ syslog(LOG_INFO, "send sp: %m");
+ }
- /*
- * lookup an authoritative soa
- */
+ goto udpout;
+ } else {
+
+ /*
+ * lookup_zone could not find an RR for the
+ * question at all -> nxdomain
+ */
+ snprintf(replystring, DNS_MAXNAME, "NXDOMAIN");
+
+ /*
+ * lookup an authoritative soa
+ */
- memset(&sd0, 0, sizeof(sd0));
- (void)get_soa(db, question, &sd0, wildcard);
-
- build_reply(&sreply, so, buf, len, question, from, \
- fromlen, &sd0, NULL, aregion, istcp, wildcard);
- reply_nxdomain(&sreply);
- goto udpout;
+ memset(&sd0, 0, sizeof(sd0));
+ (void)get_soa(db, question, &sd0, wildcard);
+
+ build_reply(&sreply, so, buf, len, question, from, \
+ fromlen, &sd0, NULL, aregion, istcp, wildcard);
+ reply_nxdomain(&sreply);
+ goto udpout;
+ } /* else rflag */
case DNS_TYPE_CNAME:
fakequestion = build_fake_question(sd0.cname, sd0.cnamelen, question->hdr->qtype);
if (fakequestion == NULL) {
@@ -2312,3 +2512,53 @@ build_reply(struct sreply *reply, int so, char *buf, i
return;
}
+
+void
+recurseheader(struct srecurseheader *rh, int proto, struct sockaddr_storage *src, struct sockaddr_storage *dst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60;
+
+ rh->af = family;
+ rh->proto = proto;
+
+ if (family == AF_INET) {
+ sin = (struct sockaddr_in *)&rh->dest;
+ sin0 = (struct sockaddr_in *)dst;
+ sin->sin_family = sin0->sin_family;
+ sin->sin_port = sin0->sin_port;
+ memcpy((char *)&sin->sin_addr.s_addr,
+ (char *)&sin0->sin_addr.s_addr,
+ sizeof(sin->sin_addr.s_addr));
+ sin = (struct sockaddr_in *)&rh->source;
+ sin0 = (struct sockaddr_in *)src;
+ sin->sin_family = sin0->sin_family;
+ sin->sin_port = sin0->sin_port;
+ memcpy((char *)&sin->sin_addr.s_addr,
+ (char *)&sin0->sin_addr.s_addr,
+ sizeof(sin->sin_addr.s_addr));
+ } else if (family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)&rh->dest;
+ sin60 = (struct sockaddr_in6 *)dst;
+
+ sin6->sin6_family = sin60->sin6_family;
+ sin6->sin6_port = sin60->sin6_port;
+
+ memcpy((char *)&sin6->sin6_addr,
+ (char *)&sin60->sin6_addr,
+ sizeof(sin6->sin6_addr));
+
+ sin6 = (struct sockaddr_in6 *)&rh->source;
+ sin60 = (struct sockaddr_in6 *)src;
+
+ sin6->sin6_family = sin60->sin6_family;
+ sin6->sin6_port = sin60->sin6_port;
+
+ memcpy((char *)&sin6->sin6_addr,
+ (char *)&sin60->sin6_addr,
+ sizeof(sin6->sin6_addr));
+ }
+
+
+ return;
+}
blob - fc9d5e8105f524f5fc1095ac7300fdc609f7e749
blob + 111bf40d0d442ea8bef827d7147b5a4521b1e760
--- parse.c
+++ parse.c
@@ -34,6 +34,7 @@ extern u_int8_t find_region(struct sockaddr_storage *s
extern void init_region(void);
extern int insert_region(char *address, char *prefix, u_int8_t region);
extern int insert_wildcard(char *address, char *prefixlen);
+extern int insert_recurse(char *, char *);
struct myrr_lookup {
char *name;
@@ -55,7 +56,7 @@ struct myrr_lookup {
enum { CMD_TYPE_VERSION = 1, CMD_TYPE_REGION,
CMD_TYPE_ZONE, CMD_TYPE_INCLUDE,
- CMD_TYPE_WILDCARDONLYFOR };
+ CMD_TYPE_WILDCARDONLYFOR, CMD_TYPE_RECURSEFOR };
struct cmd_lookup {
char *name;
@@ -66,6 +67,7 @@ struct cmd_lookup {
{ "zone ", CMD_TYPE_ZONE },
{ "include ", CMD_TYPE_INCLUDE },
{ "wildcard-only-for ", CMD_TYPE_WILDCARDONLYFOR },
+ { "recurse-for ", CMD_TYPE_RECURSEFOR },
{ NULL, 0},
};
@@ -75,12 +77,13 @@ struct cmd_lookup {
#define CONFIG_ZONE 0x8
#define CONFIG_INCLUDE 0x10
#define CONFIG_WILDCARDONLYFOR 0x20
+#define CONFIG_RECURSEFOR 0x40
#define WILDCARDVERSION 3
static u_int32_t config = 0;
-static const char rcsid[] = "$Id: parse.c,v 1.24 2010/04/05 11:54:13 pbug Exp $";
+static const char rcsid[] = "$Id: parse.c,v 1.25 2010/04/15 17:56:39 pbug Exp $";
/*
* PARSE_FILE - parse the configfile XXX rewrite me in yacc :(
@@ -281,6 +284,22 @@ parse_file(DB *db, char *file)
confstatus |= CONFIG_WILDCARDONLYFOR;
confstatus &= ~CONFIG_START;
goto loop;
+ case CMD_TYPE_RECURSEFOR:
+ if ((config & CONFIG_VERSION) != CONFIG_VERSION) {
+ syslog(LOG_INFO, "must have version at top of config\n");
+ fclose(f);
+ return (-1);
+ }
+ if (strchr(starttoken, '{') == NULL) {
+ syslog(LOG_INFO, "must have opening brace ('{') in recurse-for entry on line %d", line);
+ fclose(f);
+ return (-1);
+ }
+ config |= CONFIG_RECURSEFOR;
+
+ confstatus |= CONFIG_RECURSEFOR;
+ confstatus &= ~CONFIG_START;
+ goto loop;
} /* switch */
break;
@@ -1150,6 +1169,43 @@ skip:
return (-1);
}
} /* CONFIG_WILDCARDONLYFOR */
+ if (confstatus & CONFIG_RECURSEFOR) {
+ if (*starttoken == '}') {
+ confstatus &= ~(CONFIG_RECURSEFOR);
+ confstatus |= CONFIG_START;
+ region++;
+ goto loop;
+ }
+
+ p = strchr(starttoken, '/');
+ if (p == NULL) {
+ if (*starttoken == '\n')
+ goto loop;
+
+ syslog(LOG_INFO, "(31) malformed line, line %d", line);
+ fclose(f);
+ return (-1);
+ }
+
+ *p++ = '\0';
+
+ address = starttoken;
+ starttoken = p;
+
+ p = strchr(starttoken, ';');
+ if (p == NULL) {
+ syslog(LOG_INFO, "(32) malformed line, line %d, must have closing semi-colon", line);
+ fclose(f);
+ return (-1);
+ }
+
+ *p = '\0';
+ if (insert_recurse(address, starttoken) < 0) {
+ syslog(LOG_INFO, "address on line %d, is malformed", line);
+ fclose(f);
+ return (-1);
+ }
+ } /* CONFIG_RECURSEFOR */
loop:
continue;
blob - /dev/null
blob + 61ea6cc18a27329ed53a000053adc02eb51e9588 (mode 644)
--- /dev/null
+++ recurse.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2010 Peter J. Philipp
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ */
+#include "include.h"
+#include "dns.h"
+#include "db.h"
+
+void init_recurse(void);
+int find_recurse(struct sockaddr_storage *sst, int family);
+int insert_recurse(char *address, char *prefixlen);
+void recurseloop(int sp, int *raw, DB *db);
+extern in_addr_t getmask(int prefixlen);
+extern int getmask6(int prefixlen, struct sockaddr_in6 *sin6);
+
+SLIST_HEAD(listhead, recurseentry) recursehead;
+
+struct recurseentry {
+ char name[INET6_ADDRSTRLEN];
+ int family;
+ struct sockaddr_storage hostmask;
+ struct sockaddr_storage netmask;
+ u_int8_t prefixlen;
+ SLIST_ENTRY(recurseentry) entries;
+} *rn1, *rn2, *rnp;
+
+
+static const char rcsid[] = "$Id: recurse.c,v 1.1 2010/04/15 17:56:39 pbug Exp $";
+
+/*
+ * INIT_RECURSE - initialize the recurse singly linked list
+ */
+
+void
+init_recurse(void)
+{
+ SLIST_INIT(&recursehead);
+ return;
+}
+
+/*
+ * INSERT_RECURSE - insert an address and prefixlen into the recurse slist
+ */
+
+int
+insert_recurse(char *address, char *prefixlen)
+{
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int pnum;
+ int ret;
+
+ pnum = atoi(prefixlen);
+ rn2 = malloc(sizeof(struct recurseentry)); /* Insert after. */
+
+ if (strchr(address, ':') != NULL) {
+ rn2->family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&rn2->hostmask;
+ if ((ret = inet_pton(AF_INET6, address, &sin6->sin6_addr.s6_addr)) != 1)
+ return (-1);
+ sin6->sin6_family = AF_INET6;
+ sin6 = (struct sockaddr_in6 *)&rn2->netmask;
+ sin6->sin6_family = AF_INET6;
+ if (getmask6(pnum, sin6) < 0)
+ return(-1);
+ rn2->prefixlen = pnum;
+ } else {
+
+ rn2->family = AF_INET;
+ sin = (struct sockaddr_in *)&rn2->hostmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = inet_addr(address);
+ sin = (struct sockaddr_in *)&rn2->netmask;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = getmask(pnum);
+ rn2->prefixlen = pnum;
+
+ }
+
+ SLIST_INSERT_HEAD(&recursehead, rn2, entries);
+
+ return (0);
+}
+
+/*
+ * FIND_RECURSE - walk the recurse list and find the correponding network
+ * if a network matches return 1, if no match is found return
+ * 0.
+ */
+
+int
+find_recurse(struct sockaddr_storage *sst, int family)
+{
+ struct sockaddr_in *sin, *sin0;
+ struct sockaddr_in6 *sin6, *sin60, *sin61;
+ u_int32_t hostmask, netmask;
+ u_int32_t a;
+#ifdef __amd64
+ u_int64_t *hm[2], *nm[2], *a6[2];
+#else
+ u_int32_t *hm[4], *nm[4], *a6[4];
+#endif
+
+ SLIST_FOREACH(rnp, &recursehead, entries) {
+ if (rnp->family == AF_INET) {
+ if (family != AF_INET)
+ continue;
+ sin = (struct sockaddr_in *)sst;
+ a = sin->sin_addr.s_addr;
+ sin = (struct sockaddr_in *)&rnp->hostmask;
+ sin0 = (struct sockaddr_in *)&rnp->netmask;
+ hostmask = sin->sin_addr.s_addr;
+ netmask = sin0->sin_addr.s_addr;
+ if ((hostmask & netmask) == (a & netmask)) {
+ return (1);
+ } /* if hostmask */
+ } else if (rnp->family == AF_INET6) {
+ if (family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)sst;
+ sin60 = (struct sockaddr_in6 *)&rnp->hostmask;
+ sin61 = (struct sockaddr_in6 *)&rnp->netmask;
+#ifdef __amd64
+ /*
+ * If this is on a 64 bit machine, we'll benefit
+ * by using 64 bit registers, this should make it
+ * a tad faster...
+ */
+ hm[0] = (u_int64_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1);
+ nm[0] = (u_int64_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1);
+ a6[0] = (u_int64_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1);
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))) {
+#else
+ hm[0] = (u_int32_t *)&sin60->sin6_addr.s6_addr;
+ hm[1] = (hm[0] + 1); hm[2] = (hm[1] + 1);
+ hm[3] = (hm[2] + 1);
+ nm[0] = (u_int32_t *)&sin61->sin6_addr.s6_addr;
+ nm[1] = (nm[0] + 1); nm[2] = (nm[1] + 1);
+ nm[3] = (nm[2] + 1);
+ a6[0] = (u_int32_t *)&sin6->sin6_addr.s6_addr;
+ a6[1] = (a6[0] + 1); a6[2] = (a6[1] + 1);
+ a6[3] = (a6[2] + 1);
+
+ if ( ((*hm[0] & *nm[0]) == (*a6[0] & *nm[0]))&&
+ ((*hm[1] & *nm[1]) == (*a6[1] & *nm[1]))&&
+ ((*hm[2] & *nm[2]) == (*a6[2] & *nm[2]))&&
+ ((*hm[3] & *nm[3]) == (*a6[3] & *nm[3]))) {
+#endif
+
+ return (1);
+ } /* if ip6 address */
+
+ } /* if AF_INET6 */
+ } /* SLIST */
+
+ return (0);
+}
+
+void
+recurseloop(int sp, int *raw, DB *db)
+{
+ int sel, ret;
+ fd_set rset;
+ struct timeval tv;
+ struct srecurseheader rh;
+
+
+ for (;;) {
+ FD_ZERO(&rset);
+
+ FD_SET(sp, &rset);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ sel = select(sp + 1, &rset, NULL, NULL, &tv);
+ if (sel < 0) {
+ syslog(LOG_INFO, "select: %m");
+ continue;
+ } else if (sel == 0) {
+ /* timeout */
+ continue;
+ }
+
+ if (FD_ISSET(sp, &rset)) {
+ ret = recv(sp, (char *)&rh, sizeof(rh), 0);
+ if (ret < 0) {
+ syslog(LOG_INFO, "recv: %m");
+ continue;
+ }
+
+#if 0
+ sd = lookup_cache(rh);
+ if (sd == NULL) {
+
+ fd = lookup_net(rh);
+
+ put on linked list, select the descriptor
+ } else {
+ reply_raw(rh);
+ }
+
+#endif
+
+ } /* FD_ISSET(sp) */
+
+ }
+
+
+}
blob - 900e7ad635780288b4e33b086730cc06ca7c850f
blob + c3b5960c8cbe998c7a1c5b1c050f2dcf49141e8f
--- reply.c
+++ reply.c
@@ -41,7 +41,7 @@ void reply_ptr(struct sreply *);
void reply_cname(struct sreply *);
void reply_fmterror(struct sreply *);
-extern int compress_label(char *, int, int);
+extern int compress_label(u_char *, int, int);
extern int additional_a(char *, int, struct domain *, char *, int, int, int *);
extern int additional_aaaa(char *, int, struct domain *, char *, int, int, int *);
extern int additional_mx(char *, int, struct domain *, char *, int, int, int *);
@@ -52,7 +52,7 @@ extern int free_question(struct question *);
extern int lookup_zone(DB *, struct question *, struct domain *, int *, char *, int);
void update_db(DB *, struct domain *);
-struct domain * Lookup_zone(DB *db, char *name, int namelen, u_int16_t type, int);
+struct domain * Lookup_zone(DB *db, char *name, u_int16_t namelen, u_int16_t type, int);
void collects_init(void);
@@ -60,14 +60,14 @@ SLIST_HEAD(listhead, collects) collectshead;
struct collects {
char *name;
- int namelen;
+ u_int16_t namelen;
u_int16_t type;
struct domain *sd;
SLIST_ENTRY(collects) entries;
} *cn1, *cn2, *cnp;
-static const char rcsid[] = "$Id: reply.c,v 1.22 2010/04/05 11:54:13 pbug Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.23 2010/04/15 17:56:39 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -79,7 +79,7 @@ reply_a(struct sreply *sreply, DB *db)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
int a_count;
int mod, pos;
int ttlhack = 0;
@@ -231,7 +231,7 @@ reply_aaaa(struct sreply *sreply, DB *db)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
int aaaa_count;
int mod, pos;
@@ -356,11 +356,11 @@ reply_mx(struct sreply *sreply, DB *db)
char reply[512];
struct dns_header *odh;
struct domain *sd0;
- int outlen;
int mx_count;
u_int16_t *plen;
char *name;
- int namelen;
+ u_int16_t outlen;
+ u_int16_t namelen;
int additional = 0;
struct answer {
@@ -542,13 +542,13 @@ reply_ns(struct sreply *sreply, DB *db)
char reply[512];
struct dns_header *odh;
struct domain *sd0;
- int outlen;
int tmplen;
int ns_count;
int mod, pos;
u_int16_t *plen;
char *name;
- int namelen;
+ u_int16_t outlen;
+ u_int16_t namelen;
int additional = 0;
struct answer {
@@ -771,7 +771,7 @@ reply_cname(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
int i, tmplen;
int labellen;
@@ -939,7 +939,7 @@ reply_ptr(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
int i, tmplen;
int labellen;
@@ -1066,7 +1066,7 @@ reply_soa(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
u_int32_t *soa_val;
int i, tmplen;
@@ -1274,7 +1274,7 @@ reply_txt(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
struct answer {
@@ -1378,7 +1378,7 @@ reply_notimpl(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
int so = sreply->so;
char *buf = sreply->buf;
@@ -1446,7 +1446,7 @@ reply_nxdomain(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
u_int32_t *soa_val;
int i, tmplen;
@@ -1691,7 +1691,7 @@ reply_fmterror(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
int so = sreply->so;
int len = sreply->len;
@@ -1755,7 +1755,7 @@ reply_noerror(struct sreply *sreply)
{
char reply[512];
struct dns_header *odh;
- int outlen;
+ u_int16_t outlen;
char *p;
u_int32_t *soa_val;
int i, tmplen;
@@ -2029,7 +2029,7 @@ update_db(DB *db, struct domain *sd)
*/
struct domain *
-Lookup_zone(DB *db, char *name, int namelen, u_int16_t type, int wildcard)
+Lookup_zone(DB *db, char *name, u_int16_t namelen, u_int16_t type, int wildcard)
{
struct domain *sd;
struct question *fakequestion;
repomaster@centroid.eu