Commit Diff
Diff:
f1e825ef04c852d71ae660b0ab8736ac66ece115
518aa971b285deb7dc15454a7270a832a041ca7f
Commit:
518aa971b285deb7dc15454a7270a832a041ca7f
Tree:
8a7c95b3784b5ab77faa0201a953719a9deb8adf
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Thu Sep 30 09:12:32 2010 UTC
Message:
* IPv6 recurse code, broken at the moment compiles on OpenBSD Wildcarddnsd has surpassed 10,000 lines of C code with this commit.
blob - 4e42843478ac0e398843617d78179c372430c54b
blob + 12aac33b6a8bc9804971e8693e92c1e5244fc136
--- include.h
+++ include.h
@@ -41,6 +41,9 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
+#define _KERNEL 1
+#include <netinet/ip6.h>
+#undef _KERNEL
#include <arpa/inet.h>
#include <netdb.h>
blob - 23214233a687b24f0d7f3918ad9e3ae5bc30ba3c
blob + 27ec2cfffa4076737fe702ebd762aaa0ec067722
--- main.c
+++ main.c
@@ -112,7 +112,7 @@ struct tcps {
} *tn1, *tn2, *tnp;
-static const char rcsid[] = "$Id: main.c,v 1.55 2010/09/19 11:39:38 pbug Exp $";
+static const char rcsid[] = "$Id: main.c,v 1.56 2010/09/30 09:12:32 pbug Exp $";
/*
* MAIN - set up arguments, set up database, set up sockets, call mainloop
@@ -443,7 +443,7 @@ main(int argc, char *argv[])
exit(1);
}
- if ((raw[1] = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW)) < 0) {
+ if ((raw[1] = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP)) < 0) {
syslog(LOG_INFO, "raw socket[1]: %m");
exit(1);
}
blob - c3768ed1bacc398ac226ac26c6d25bceeb446380
blob + e962f68c47f8c57bd5d92c219fdd59208d38cb80
--- recurse.c
+++ recurse.c
@@ -66,6 +66,8 @@ extern void reply_noerror(struct sreply *);
void remove_zone(DB *db, struct domain *sd);
int contains(u_char *a, u_char *b);
int level(u_char *p);
+int lookup_aaaa(DB *db, struct recurses *sr, struct ns *ns);
+int netlookup6(DB *db, struct recurses *sr);
#ifndef MIN
#define MIN(a,b) ((a < b) ? a : b)
@@ -83,7 +85,7 @@ struct recurseentry {
} *rn1, *rn2, *rnp;
-static const char rcsid[] = "$Id: recurse.c,v 1.25 2010/09/28 08:13:00 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.26 2010/09/30 09:12:32 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -654,13 +656,20 @@ again:
return (-1);
}
+ sr->aaaa_count = 0;
sr->a_count = 0;
sr->a_ptr = 0;
for (i = 0; i < sd->ns_count; i++) {
- if (lookup_a(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
- continue;
- sr->a_count++;
+ if (sr->af == AF_INET6) {
+ if (lookup_aaaa(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
+ continue;
+ sr->aaaa_count++;
+ } else {
+ if (lookup_a(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
+ continue;
+ sr->a_count++;
+ }
}
if (sd->ns_count)
@@ -680,7 +689,7 @@ again:
#endif
- return (sr->a_count);
+ return ((sr->af == AF_INET6) ? sr->aaaa_count : sr->a_count);
}
@@ -1635,6 +1644,10 @@ netlookup(DB *db, struct recurses *sr)
/* do the network stuff then */
/* XXX should be IPv6 ready */
+
+ if (sr->af == AF_INET6)
+ return (netlookup6(db, sr));
+
if (sr->so != -1) {
if (close(sr->so) < 0)
syslog(LOG_ERR, "close: %m");
@@ -2100,6 +2113,175 @@ contains(u_char *a, u_char *b)
qlen -= ((*q) + 1);
q += ((*q) + 1);
+ }
+
+ return (0);
+}
+
+/*
+ * NETLOOKUP6 - do an ipv6 lookup of the requested internet record
+ *
+ */
+
+int
+netlookup6(DB *db, struct recurses *sr)
+{
+ struct sockaddr_in6 sin6;
+ struct dns_header *dh;
+
+ char buf[2048];
+ int flag;
+
+ if (sr->so != -1) {
+ if (close(sr->so) < 0)
+ syslog(LOG_ERR, "close: %m");
+ }
+
+ sr->so = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (sr->so < 0) {
+ syslog(LOG_ERR, "socket6: %m");
+ sr->so = -1;
+ return (-1);
+ }
+
+ sr->port = arc4random() & 0xffff;
+ /*
+ * we have to avoid picking servers already
+ * running ..
+ */
+ if (sr->port < 1024)
+ sr->port += 1024;
+
+ sr->id = arc4random() & 0xffff;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(sr->port);
+
+ if (bind(sr->so, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ if (close(sr->so) < 0) {
+ syslog(LOG_ERR, "close: %m");
+ }
+ sr->so = -1;
+ return (-1);
+ }
+
+ /*
+ * make this socket nonblocking
+ */
+
+ if ((flag = fcntl(sr->so, F_GETFL)) < 0) {
+ syslog(LOG_INFO, "fcntl 3: %m");
+ }
+ flag |= O_NONBLOCK;
+ if (fcntl(sr->so, F_SETFL, flag) < 0) {
+ syslog(LOG_INFO, "fcntl 4: %m");
+ }
+
+ if (lookup_ns(db, sr) <= 0) {
+ syslog(LOG_ERR, "can't establish any servers to reach for zone \"%s\"", sr->question->converted_name);
+ if (close(sr->so) < 0) {
+ syslog(LOG_ERR, "close: %m");
+ }
+ sr->so = -1;
+ return (-1);
+ }
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_port = htons(53);
+
+ memcpy(&sin6.sin6_addr, &sr->aaaa[0], sizeof(struct in6_addr));
+
+ /* XXX we use buf here in order to preserve
+ * the state of query...
+ */
+ memcpy(buf, sr->query, sr->len);
+ dh = (struct dns_header *)&buf[0];
+ NTOHS(dh->query);
+ UNSET_DNS_RECURSION(dh);
+ HTONS(dh->query);
+ dh->id = htons(sr->id);
+
+#if 1
+ syslog(LOG_INFO, "sending request with id %u\n", sr->id);
+
+#endif
+
+ if (sendto(sr->so, buf, sr->len, 0, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
+ syslog(LOG_ERR, "sendto6: %m");
+ if (close(sr->so) < 0) {
+ syslog(LOG_ERR, "close: %m");
+ }
+ sr->so = -1;
+ return (-1);
+ }
+
+ sr->sent_last_query = time(NULL);
+ sr->packetcount++;
+
+
+ return (0);
+}
+
+/*
+ * LOOKUP_AAAA - given a path, lookup the AAAA record in that record
+ *
+ */
+
+int
+lookup_aaaa(DB *db, struct recurses *sr, struct ns *ns)
+{
+ int ret, plen;
+ char *p;
+
+ DBT key, data;
+
+ struct domain *sd, sdomain;
+ int found = 0;
+
+ p = ns->nsserver;
+ plen = ns->nslen;
+
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)p;
+ key.size = plen;
+
+ data.data = NULL;
+ data.size = 0;
+
+ found = 0;
+
+#if DB_VERSION_MAJOR > 3
+ ret = db->get(db, NULL, &key, &data, 0);
+#else
+ ret = db->get(db, &key, &data, 0);
+#endif
+
+ if (ret == 0) {
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_ERR, "btree db is damaged");
+ return (-1);
+ }
+
+ memcpy((char*)&sdomain, data.data, sizeof(struct domain));
+ sd = &sdomain;
+
+ if ((sd->flags & DOMAIN_HAVE_AAAA) == DOMAIN_HAVE_AAAA) {
+ memcpy((char *)&sr->aaaa[sr->aaaa_count], (char *)&sd->aaaa[0], sizeof(struct in6_addr));
+ sd->a_count++;
+ found = 1;
+
+ }
+ }
+
+ if (! found) {
+ syslog(LOG_DEBUG, "calling fakerecurse");
+ fakerecurse(db, sr, ns, DNS_TYPE_AAAA);
+ return (-1);
}
return (0);
blob - 5f4d27804cdf07340788a6cdaa69da8c5c00d9fd
blob + 2675956a615bc51bc46b14730d6b570789f725bc
--- reply.c
+++ reply.c
@@ -42,6 +42,7 @@ void reply_txt(struct sreply *sreply);
void reply_cname(struct sreply *);
void reply_fmterror(struct sreply *);
void reply_raw2(int so, char *reply, int outlen, struct recurses *sr);
+void reply_raw6(int so, char *reply, int outlen, struct recurses *sr);
extern int compress_label(u_char *, int, int);
extern int additional_a(char *, int, struct domain *, char *, int, int, int *);
@@ -76,7 +77,7 @@ struct collects {
} *cn1, *cn2, *cnp;
-static const char rcsid[] = "$Id: reply.c,v 1.35 2010/09/26 16:20:08 pbug Exp $";
+static const char rcsid[] = "$Id: reply.c,v 1.36 2010/09/30 09:12:32 pbug Exp $";
/*
* REPLY_A() - replies a DNS question (*q) on socket (so)
@@ -2198,6 +2199,11 @@ reply_raw2(int so, char *reply, int outlen, struct rec
int udplen = outlen + sizeof(struct udphdr);
struct sockaddr_in *sin_src, *sin_dst;
+ if (sr->af == AF_INET6) {
+ reply_raw6(so, reply, outlen, sr);
+ return;
+ }
+
#ifdef __linux__
ip = (struct iphdr *)&buf[0];
#else
@@ -2282,6 +2288,67 @@ reply_raw2(int so, char *reply, int outlen, struct rec
syslog(LOG_ERR, "sendto: %m");
}
}
+
+/*
+ * REPLY_RAW6 - do an ipv6 raw reply
+ *
+ */
+
+void
+reply_raw6(int so, char *reply, int outlen, struct recurses *sr)
+{
+ char buf[2048];
+ char csum[2048];
+
+ struct udphdr *udp;
+ int udplen = outlen + sizeof(struct udphdr);
+ struct sockaddr_in6 *sin_src, *sin_dst;
+ struct sockaddr_in6 sin6;
+
+ struct ip6_hdr_pseudo *pseudo;
+
+ udp = (struct udphdr *)&buf[0];
+ memcpy(&buf[sizeof(struct udphdr)], reply, outlen);
+
+ sin_src = (struct sockaddr_in6 *)(&sr->source);
+ sin_dst = (struct sockaddr_in6 *)(&sr->dest);
+
+ udp->uh_sport = sin_dst->sin6_port;
+ udp->uh_dport = sin_src->sin6_port;
+ udp->uh_ulen = htons(udplen);
+ udp->uh_sum = 0;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, sin_dst, sizeof(struct in6_addr));
+
+ if (bind(so, (struct sockaddr *)&sin6, sizeof(sin6)) < 0) {
+ syslog(LOG_ERR, "bind6: %m");
+ return;
+ }
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ memcpy(&sin6.sin6_addr, sin_src, sizeof(struct in6_addr));
+ sin6.sin6_port = sin_src->sin6_port;
+
+ pseudo = (struct ip6_hdr_pseudo *)&csum[0];
+ pseudo->ip6ph_nxt = IPPROTO_UDP;
+ pseudo->ip6ph_len = htons(sizeof(struct udphdr));
+ memcpy((char *)&pseudo->ip6ph_src, &sin_dst->sin6_addr, sizeof(struct in6_addr));
+ memcpy((char *)&pseudo->ip6ph_dst, &sin_src->sin6_addr, sizeof(struct in6_addr));
+
+ memcpy((char *)&csum[sizeof(struct ip6_hdr_pseudo)], udp, sizeof(struct udphdr));
+
+ udp->uh_sum = in_cksum((u_short *)&csum[0], sizeof(struct ip6_hdr_pseudo) + sizeof(struct udphdr), 0);
+
+
+ if (sendto(so, buf, udplen, 0, (struct sockaddr *)(&sr->dest), sizeof(struct sockaddr)) < 0) {
+ syslog(LOG_ERR, "sendto: %m");
+ }
+}
+
+
repomaster@centroid.eu