Commit Diff
Diff:
e87eb338da1429e5d65995434991579eb66cc598
aded9c8069fc4443b6044dacbb6544d7f79d01ac
Commit:
aded9c8069fc4443b6044dacbb6544d7f79d01ac
Tree:
5aed928482a3692b50dcddf9f344bcf157229886
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Wed Sep 15 11:35:32 2010 UTC
Message:
* commit early, commit often... * this is just a commit of work I've done today, nothing works yet on the recursing end...
blob - b5ae8478413f101a8fd683a07440abb9391cccbc
blob + 5e57b151f9feecfd339e910e5dd4b420e73b052b
--- recurse.c
+++ recurse.c
@@ -33,9 +33,14 @@ 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 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 int lookup_zone(DB *db, struct question *question, struct domain *sd, int *lzerrno, char *replystring, int wildcard);
+
+
SLIST_HEAD(listhead, recurseentry) recursehead;
struct recurseentry {
@@ -63,14 +68,29 @@ struct recurses {
char upperlower[32]; /* uppercase / lowercase bitmap */
int so; /* the socket we did a lookup with */
+ u_short port; /* port used on outgoing */
u_int16_t id; /* last id used */
+ /* the below get loaded from the database upon each lookup */
+ in_addr_t a[RECORD_COUNT]; /* IPv4 addresses of nameservers */
+ int a_count; /* IPv4 address count */
+ int a_ptr; /* pointer to last used address */
+ struct in6_addr aaaa[RECORD_COUNT]; /* IPv6 addresses of nameservers */
+ int aaaa_count; /* IPv6 address count */
+ int aaaa_ptr; /* pointer to last used IPv6 address */
+
+ /* the below is our indicator which part of the lookup we're at */
+
+ int indicator; /* indicator of ns lookup */
+
struct question *question; /* question struct */
SLIST_ENTRY(recurses) entries;
};
+int lookup_ns(DB *, struct recurses *);
+int lookup_a(DB *, struct recurses *, struct ns *);
-static const char rcsid[] = "$Id: recurse.c,v 1.2 2010/05/26 18:42:25 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.3 2010/09/15 11:35:32 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -212,7 +232,16 @@ recurseloop(int sp, int *raw, DB *db)
fd_set rset;
struct timeval tv;
struct srecurseheader rh;
+ struct recurses *sr;
+ struct domain sd;
+ struct sockaddr_in sin;
+ struct dns_header *dh;
+ int type, lzerrno, wildcard = 0;
+
+ char fakereplystring[DNS_MAXNAME + 1];
+
+
SLIST_INIT(&recurseshead);
@@ -239,7 +268,94 @@ recurseloop(int sp, int *raw, DB *db)
continue;
}
+ /* place request on struct recurses linked list */
+
+ sr = calloc(sizeof(struct recurses), 1);
+ if (sr == NULL) {
+ syslog(LOG_ERR, "calloc: %m");
+ continue;
+ }
+
+ memcpy(&sr->query, &rh.buf, 512);
+ sr->len = rh.len;
+ sr->af = rh.af;
+ sr->proto = rh.proto;
+ memcpy(&sr->source, &rh.source, sizeof(struct sockaddr_storage));
+ memcpy(&sr->dest, &rh.dest, sizeof(struct sockaddr_storage));
+ sr->received = time(NULL);
+
+ sr->question = build_question(sr->query, sr->len);
+ if (sr->question == NULL) {
+ syslog(LOG_ERR, "malformed question in recurse.c");
+ free(sr);
+ continue;
+ }
+
+ type = lookup_zone(db, sr->question, &sd, &lzerrno, (char *)fakereplystring, wildcard);
+ if (type < 0) {
+ /* do the network stuff then */
+ /* XXX should be IPv6 ready */
+ sr->so = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sr->so < 0) {
+ syslog(LOG_ERR, "socket: %m");
+ free(sr); /* XXX */
+ continue;
+ }
+
+ sr->port = arc4random() & 0xffff;
+ sr->id = arc4random() & 0xffff;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(sr->port);
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(sr->so, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ close(sr->so);
+ free(sr);
+ continue;
+ }
+
+ lookup_ns(db, sr);
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(53);
+ sin.sin_addr.s_addr = inet_addr("192.168.0.2");
+
+ dh = (struct dns_header *)sr->query;
+ dh->id = htons(sr->id);
+
+#if 1
+ syslog(LOG_INFO, "sending request with id %u\n", sr->id);
+
+#endif
+
+ if (sendto(sr->so, sr->query, sr->len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ syslog(LOG_ERR, "sendto: %m");
+ close(sr->so);
+ free(sr);
+ continue;
+ }
+
+ /*
+ * add to our linked list of outstanding
+ * lookups
+ */
+ SLIST_INSERT_HEAD(&recurseshead, sr, entries);
+
+ } else {
#if 0
+ reply_raw(sr);
+ free(sr);
+ continue;
+#endif
+ }
+
+ } /* FD_ISSET(sp) */
+
+#if 0
sd = lookup_cache(rh);
if (sd == NULL) {
@@ -289,9 +405,155 @@ recurseloop(int sp, int *raw, DB *db)
#endif
- } /* FD_ISSET(sp) */
}
+}
+
+/*
+ * LOOKUP_NS - given an address try to look up the nameservers anywhere along
+ * its path.
+ */
+
+int
+lookup_ns(DB *db, struct recurses *sr)
+{
+ int ret, plen, i;
+ int onemore = 0;
+ char *p;
+
+ DBT key, data;
+
+ struct domain *sd, mydomain;
+
+ p = sr->question->hdr->name;
+ plen = sr->question->hdr->namelen;
+
+ do {
+again:
+ memset(&key, 0, sizeof(key));
+ memset(&data, 0, sizeof(data));
+
+ key.data = (char *)p;
+ key.size = plen;
+
+ data.data = NULL;
+ data.size = 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 (*p != 0) {
+ plen -= (*p + 1);
+ p = (p + (*p + 1));
+ sr->indicator++;
+ }
+
+ /* XXX this is different from lookup_zone(), not
+ * sure how it even works there...
+ */
+ if (*p == 0 && ! onemore) {
+ plen = 1;
+ onemore = 1;
+ sr->indicator++;
+ goto again; /* XXX */
+ }
+ } else {
+ /* we have a lookup */
+
+ if (data.size != sizeof(struct domain)) {
+ syslog(LOG_ERR, "btree db is damaged");
+ return (-1);
+ }
+
+#if 0
+ syslog(LOG_DEBUG, "we gots a lookup, yay!\n");
+#endif
+
+
+ memcpy((char *)&mydomain, (char *)data.data, sizeof(struct domain));
+ sd = (struct domain *)&mydomain;
+ 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++;
+ }
+
+ sd->ns_ptr = (sd->ns_ptr + 1) % sd->ns_count;
+ update_db(db, sd);
+
+ break;
+ }
+
+ } while (*p != 0 && ret != 0);
+
+ syslog(LOG_DEBUG, "got %d addresses for %s, indicator %d\n", sr->a_count, sr->question->converted_name, sr->indicator);
+
+ return (0);
+}
+
+
+/*
+ * LOOKUP_A - given a path, lookup the A record in that record
+ *
+ */
+
+int
+lookup_a(DB *db, struct recurses *sr, struct ns *ns)
+{
+ int ret, plen;
+ char *p;
+
+ DBT key, data;
+
+ struct domain *sd;
+ in_addr_t tmp;
+ char buf[INET_ADDRSTRLEN];
+
+ 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;
+
+#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);
+ }
+
+ sd = (struct domain *)data.data;
+
+ memcpy((char *)&sr->a[sr->a_count], (char *)&sd->a[0], sizeof(in_addr_t));
+#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
+ return (-1);
+
+ return (0);
}
repomaster@centroid.eu