Commit Diff
Diff:
1c8eb9edfea9e9acd8909dd52a753903a3d8a0da
c8a9dee0e821a85320109a74c60bfc71e3a23eb1
Commit:
c8a9dee0e821a85320109a74c60bfc71e3a23eb1
Tree:
edbabfd72d5f8202eaddb808fb6fe72e7c94f27a
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Sat Sep 18 19:51:06 2010 UTC
Message:
* we're able to recurse an address with this, but there is some overhead that I'd like to cut out, still not working, work in progress
blob - ce3a5e9af87e7f6103b0e75f241b058b6ed722cd
blob + d1d64d9157118d0c9b1274a44ba9be0872e719ce
--- recurse.c
+++ recurse.c
@@ -37,6 +37,7 @@ extern void update_db(DB *, struct domain *);
extern in_addr_t getmask(int prefixlen);
extern int getmask6(int prefixlen, struct sockaddr_in6 *sin6);
extern struct question * build_question(char *buf, int len);
+extern struct question * build_fake_question(char *, int, u_int16_t);
extern int free_question(struct question *);
extern int lookup_zone(DB *db, struct question *question, struct domain *sd, int *lzerrno, char *replystring, int wildcard);
@@ -58,6 +59,7 @@ struct recurses {
char query[512]; /* the query we received */
int len; /* length of query */
+ int isfake; /* received or faked */
int af; /* address family */
int proto; /* protocol UDP/TCP */
struct sockaddr_storage source; /* source + port */
@@ -85,6 +87,7 @@ struct recurses {
struct question *question; /* question struct */
SLIST_ENTRY(recurses) entries;
+ struct recurses *callback; /* callback */
} *sr, *sr1;
int lookup_ns(DB *, struct recurses *);
@@ -92,8 +95,9 @@ 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);
int netlookup(DB *db, struct recurses *sr);
+int fakerecurse(DB *db, struct recurses *sr, struct ns *ns);
-static const char rcsid[] = "$Id: recurse.c,v 1.8 2010/09/17 13:24:38 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.9 2010/09/18 19:51:06 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -294,6 +298,8 @@ recurseloop(int sp, int *raw, DB *db)
sr->af = rh.af;
sr->proto = rh.proto;
sr->so = -1;
+ sr->callback = NULL;
+ sr->isfake = 0;
memcpy(&sr->source, &rh.source, sizeof(struct sockaddr_storage));
memcpy(&sr->dest, &rh.dest, sizeof(struct sockaddr_storage));
sr->received = time(NULL);
@@ -312,6 +318,7 @@ recurseloop(int sp, int *raw, DB *db)
SLIST_INSERT_HEAD(&recurseshead, sr, entries);
} else {
+ syslog(LOG_DEBUG, "we had the record in our cache, reply action");
#if 0
reply_raw(sr);
free(sr);
@@ -374,18 +381,27 @@ recurseloop(int sp, int *raw, DB *db)
recurse_parse(db, sr1, buf, len);
- type = lookup_zone(db, sr->question, &sd, &lzerrno, (char *)fakereplystring, wildcard);
+ type = lookup_zone(db, sr1->question, &sd, &lzerrno, (char *)fakereplystring, wildcard);
if (type < 0) {
if (netlookup(db, sr1) < 0) {
syslog(LOG_DEBUG, "subsequent netlookup failed");
- continue;
+ /* continue; XXX */
+
}
} else {
/* we've found the record we're looking
* for do something with it..
*/
- syslog(LOG_DEBUG, "record found but no action");
+ if (sr1->isfake) {
+ /* do another netlookup with the callback */
+
+ if (netlookup(db, sr1->callback) < 0) {
+ syslog(LOG_DEBUG, "callback netlookup failed");
+ }
+
+ } else
+ syslog(LOG_DEBUG, "record found but no action");
}
remove:
SLIST_REMOVE(&recurseshead, sr1, recurses, entries);
@@ -538,7 +554,7 @@ again:
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)
+ if (lookup_a(db, sr, sd->ns[(sd->ns_ptr + i) % sd->ns_count] ) < 0)
continue;
sr->a_count++;
}
@@ -576,6 +592,7 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
struct domain *sd;
in_addr_t tmp;
char buf[INET_ADDRSTRLEN];
+ int found = 0;
p = ns->nsserver;
plen = ns->nslen;
@@ -589,6 +606,8 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
data.data = NULL;
data.size = 0;
+ found = 0;
+
#if DB_VERSION_MAJOR > 3
ret = db->get(db, NULL, &key, &data, 0);
#else
@@ -602,17 +621,22 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
}
sd = (struct domain *)data.data;
-
- memcpy((char *)&sr->a[sr->a_count], (char *)&sd->a[0], sizeof(in_addr_t));
+
+ if ((sd->flags & DOMAIN_HAVE_A) == DOMAIN_HAVE_A) {
+ memcpy((char *)&sr->a[sr->a_count], (char *)&sd->a[0], sizeof(in_addr_t));
+ found = 1;
#if 0
tmp = sr->a[sr->a_count];
inet_ntop(AF_INET, (char*)&tmp, (char *)&buf, sizeof(buf));
syslog(LOG_DEBUG, "address %s\n", buf);
#endif
-
+ }
+ }
- } else
+ if (! found) {
+ fakerecurse(db, sr, ns);
return (-1);
+ }
return (0);
}
@@ -1179,8 +1203,6 @@ netlookup(DB *db, struct recurses *sr)
sr->so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sr->so < 0) {
syslog(LOG_ERR, "socket: %m");
- free_question(sr->question);
- free(sr); /* XXX */
return (-1);
}
@@ -1202,16 +1224,12 @@ netlookup(DB *db, struct recurses *sr)
if (bind(sr->so, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
syslog(LOG_ERR, "bind: %m");
close(sr->so);
- free_question(sr->question);
- free(sr);
return (-1);
}
if (lookup_ns(db, sr) <= 0) {
syslog(LOG_ERR, "can't establish any servers to reach for zone \"%s\"", sr->question->converted_name);
close(sr->so);
- free_question(sr->question);
- free(sr);
return (-1);
}
@@ -1239,13 +1257,82 @@ netlookup(DB *db, struct recurses *sr)
if (sendto(sr->so, buf, sr->len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
syslog(LOG_ERR, "sendto: %m");
close(sr->so);
- free_question(sr->question);
- free(sr);
return (-1);
}
sr->sent_last_query = time(NULL);
+ return (0);
+}
+
+/*
+ * FAKERECURSE - create a fake query of type A, for a nameserver that has
+ * no glued A record, attach a callback to the struct recurses
+ * that did the initiation for this...
+ */
+
+int
+fakerecurse(DB *db, struct recurses *sr, struct ns *ns)
+{
+ struct recurses *fakesr;
+ struct dns_header *dh;
+
+ char *p;
+ int len;
+ u_int16_t *type, *class;
+
+ /* place request on struct recurses linked list */
+
+ fakesr = calloc(sizeof(struct recurses), 1);
+ if (fakesr == NULL) {
+ syslog(LOG_ERR, "calloc: %m");
+ return (-1);
+ }
+
+
+ fakesr->af = sr->af;
+ fakesr->proto = sr->proto;
+ fakesr->so = -1;
+ fakesr->callback = sr;
+ fakesr->isfake = 1;
+ fakesr->received = time(NULL);
+
+ fakesr->question = build_fake_question(ns->nsserver, ns->nslen, htons(DNS_TYPE_A));
+ if (fakesr->question == NULL) {
+ syslog(LOG_ERR, "malformed question in recurse.c");
+ free(fakesr);
+ return (-1);
+ }
+
+ /* construct the question packet */
+
+ len = sizeof(struct dns_header);
+ dh = (struct dns_header *)fakesr->query;
+ dh->id = htons(1);
+ SET_DNS_QUERY(dh);
+ HTONS(dh->query);
+ dh->question = htons(1);
+ dh->answer = 0;
+ dh->nsrr = 0;
+ dh->additional = 0;
+
+ p = (char *)&fakesr->query[len];
+ memcpy(p, ns->nsserver, ns->nslen);
+ len += ns->nslen;
+ type = (u_int16_t *)&fakesr->query[len];
+ *type = fakesr->question->hdr->qtype;
+ len += sizeof(u_int16_t);
+ class = (u_int16_t *)&fakesr->query[len];
+ *class = fakesr->question->hdr->qclass;
+ len += sizeof(u_int16_t);
+
+ fakesr->len = len;
+
+ if (netlookup(db, fakesr) < 0)
+ return (-1);
+
+ SLIST_INSERT_HEAD(&recurseshead, fakesr, entries);
+
return (0);
}
repomaster@centroid.eu