Commit Diff
Diff:
c7eceebaa542ec99df41742a7f97aae934305d62
1f90620722f1f45e54ba8438f57a88c1aa036d73
Commit:
1f90620722f1f45e54ba8438f57a88c1aa036d73
Tree:
16e7270fc00dc4793a91795dc920c5b336240c44
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Fri Sep 17 10:50:23 2010 UTC
Message:
* we parse A and NS records now * we switched from a temporary nameserver live to the root servers (use with utmost care!), we're nowhere near finished, it just gets harder now..
blob - f9cfeb87d9435ea02e08100f10072e006c79d571
blob + bb07e0e3071a246f8a3edbaa6bc8e68993dd5bb4
--- recurse.c
+++ recurse.c
@@ -41,7 +41,6 @@ extern int free_question(struct question *);
extern int lookup_zone(DB *db, struct question *question, struct domain *sd, int *lzerrno, char *replystring, int wildcard);
-
SLIST_HEAD(listhead, recurseentry) recursehead;
struct recurseentry {
@@ -93,7 +92,7 @@ int lookup_a(DB *, struct recurses *, struct ns *);
int recurse_parse(DB *db, struct recurses *sr, u_char *buf, u_int16_t offset);
int negative_cache(DB *db, struct recurses *sr);
-static const char rcsid[] = "$Id: recurse.c,v 1.6 2010/09/16 20:24:53 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.7 2010/09/17 10:50:23 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -351,12 +350,9 @@ recurseloop(int sp, int *raw, DB *db)
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(53);
-#if 1
- /* use dummy root server for now */
- sin.sin_addr.s_addr = inet_addr("192.168.0.2");
-#else
+
sin.sin_addr.s_addr = sr->a[0];
-#endif
+
/* XXX we use buf here in order to preserve
* the state of query...
*/
@@ -410,11 +406,13 @@ recurseloop(int sp, int *raw, DB *db)
continue;
}
+#if 1
/* XXX do some checking of expected IP address */
- if (sin.sin_addr.s_addr != inet_addr("192.168.0.2")) {
- syslog(LOG_ERR, "address is not 192.168.0.2");
+ if (sin.sin_addr.s_addr != sr1->a[0]) {
+ syslog(LOG_ERR, "return address is not from right nameserver");
continue;
}
+#endif
if (len < sizeof(struct dns_header)) {
syslog(LOG_ERR, "size malformed on reply len=%d", len);
@@ -612,7 +610,7 @@ again:
} while (*p != 0 && ret != 0);
-#if 0
+#if 1
syslog(LOG_DEBUG, "got %d addresses for %s, indicator %d\n", sr->a_count, sr->question->converted_name, sr->indicator);
#endif
@@ -736,7 +734,15 @@ recurse_parse(DB *db, struct recurses *sr, u_char *buf
{
u_char *label[256]; /* should be enough */
u_char converted_name[256][256];
+ u_int8_t cn_len[256];
u_char *end = &buf[offset];
+ int update;
+
+ char abuf[INET6_ADDRSTRLEN];
+
+ DBT key, data;
+
+ struct domain sdomain;
struct question {
u_int16_t type;
u_int16_t class;
@@ -956,12 +962,253 @@ again:
}
*q++ = '\0'; /* don't forget this */
+ cn_len[j] = (q - converted_name[j]);
} /* for (j .. */
+#if 0
for (j = 0; j <= i; j++) {
- syslog(LOG_DEBUG, "%s", converted_name[j]);
+ syslog(LOG_DEBUG, "%s with length %u", converted_name[j], cn_len[j]);
}
+#endif
+
+ 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
+ */
+
+ if (p > end)
+ return (-1);
+
+ p += sizeof(struct question);
+ p++; /* one more */
+ /* start of answer/additional/authoritative */
+
+ for (i = 1; i < 100; i++) {
+ label[i] = p;
+
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
+
+ if (p > end)
+ goto end;
+ }
+
+ p++; /* one more */
+
+
+ a = (struct answer *)p;
+ p += sizeof(struct answer);
+
+ /* load our record */
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)converted_name[i];
+ key.size = cn_len[i];
+
+ data.data = NULL;
+ data.size = 0;
+
+ memset((char *)&sdomain, 0, sizeof(struct domain));
+#if DB_VERSION_MAJOR > 3
+ if (db->get(db, NULL, &key, &data, 0) == 0) {
+#else
+ if (db->get(db, &key, &data, 0) == 0) {
+#endif
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_INFO, "damaged btree database");
+ return -1;
+ }
+
+ memcpy((char *)&sdomain, (char *)data.data, data.size);
+
+ }
+
+
+ if (sdomain.zone == NULL) {
+ sdomain.zone = (char *) malloc(cn_len[i]);
+ if (sdomain.zone == NULL) {
+ syslog(LOG_INFO, "malloc(1): %m");
+ return (-1);
+ }
+
+
+ memcpy(sdomain.zone, converted_name[i], cn_len[i]);
+ sdomain.zonelen = cn_len[i];
+ }
+
+
+ switch (ntohs(a->type)) {
+ case DNS_TYPE_A:
+ /*
+ * scan addresses in this struct domain and check if
+ * this one exists already...
+ */
+
+ update = 1;
+ for (j = 0; j < sdomain.a_count; j++) {
+ if (memcmp(&sdomain.a[j], p, sizeof(in_addr_t)) == 0) {
+ syslog(LOG_INFO, "record exists already");
+ update = 0;
+ }
+ }
+
+ if (j >= RECORD_COUNT) {
+ syslog(LOG_INFO, "db can't hold any more records\n");
+ update = 0;
+ }
+
+ if (update) {
+ memcpy(&sdomain.a[j], p, sizeof(in_addr_t));
+ sdomain.a_count++;
+ sdomain.a_ptr = 0;
+ sdomain.flags |= DOMAIN_HAVE_A;
+ sdomain.flags &= ~(DOMAIN_NEGATIVE_CACHE);
+ sdomain.created = time(NULL);
+ sdomain.ttl = ntohl(a->ttl);
+
+ if (! (sdomain.flags & DOMAIN_STATIC_ZONE)) {
+ update_db(db, &sdomain);
+ inet_ntop(AF_INET, p, abuf, sizeof(abuf));
+ syslog(LOG_DEBUG, "updateing zone %s with address %s ttl= %u\n", converted_name[i], abuf, sdomain.ttl);
+ }
+ }
+
+ 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++;
+
+ if (p > end)
+ goto end;
+ }
+
+
+ if (ntohs(a->type) == DNS_TYPE_NS) {
+ update = 1;
+ for (j = 0; j < sdomain.ns_count; j++) {
+#if 0
+ syslog(LOG_DEBUG, "nameserver record %s", sdomain.ns[j]->nsserver);
+#endif
+ if (memcmp(sdomain.ns[j]->nsserver, converted_name[i], cn_len[i]) == 0) {
+ syslog(LOG_INFO, "record exists already");
+ update = 0;
+ }
+ }
+
+ if (j >= RECORD_COUNT) {
+ syslog(LOG_INFO, "db can't hold any more records\n");
+ update = 0;
+ }
+
+ if (update) {
+ sdomain.ns[j] = malloc(sizeof(struct ns));
+ if (sdomain.ns[j] == NULL) {
+ syslog(LOG_ERR, "malloc: %m");
+ return (-1);
+ }
+
+ memcpy(&sdomain.ns[j]->nsserver, converted_name[i], cn_len[i]);
+ sdomain.ns[j]->nslen = cn_len[i];
+
+ sdomain.ns_count++;
+ sdomain.ns_ptr = 0;
+ sdomain.flags |= DOMAIN_HAVE_NS;
+ sdomain.flags &= ~(DOMAIN_NEGATIVE_CACHE);
+ sdomain.created = time(NULL);
+ sdomain.ttl = ntohl(a->ttl);
+
+ if (! (sdomain.flags & DOMAIN_STATIC_ZONE)) {
+ update_db(db, &sdomain);
+#if 0
+ syslog(LOG_DEBUG, "updateing zone %s with NS name %s ttl= %u\n", converted_name[i - 1], converted_name[i], sdomain.ttl);
+#endif
+ }
+ } /* if update */
+
+ } /* if type ns */
+
+ 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)
+ goto end;
+
+ /* responsible person */
+ label[++i] = p;
+ while (p <= end && *p) {
+ if ((*p & 0xc0) == 0xc0) {
+ p++;
+ break;
+ }
+ p += *p;
+ p++;
+ }
+
+ p++; /* one more */
+
+ if (p > end)
+ goto end;
+
+ p += sizeof(struct soa); /* advance struct soa */
+
+ break;
+ default:
+ break;
+ /* XXX */
+ } /* switch */
+
+ if (p >= end)
+ break;
+ } /* for (i *) */
+
return (0);
repomaster@centroid.eu