Commit Diff
Diff:
d248a234af6d238722c91311d3843957f121f7c4
c7eceebaa542ec99df41742a7f97aae934305d62
Commit:
c7eceebaa542ec99df41742a7f97aae934305d62
Tree:
64400e9aecd20d515321092b2bc4e2f54948e434
Author:
pbug <pbug@delphinusdns.org>
Committer:
pbug <pbug@delphinusdns.org>
Date:
Thu Sep 16 20:24:53 2010 UTC
Message:
* add the beginning part of recurse_parse based on compress_label() * add more macros to unset flags in a packet
blob - dd16a38869c6d3a48c2b6a27d39b0b361d7b3d3f
blob + 318db88409cc1f8f9e65734820c84c08d04364de
--- dns.h
+++ dns.h
@@ -98,7 +98,7 @@ struct dns_question_hdr {
*/
#define SET_DNS_REPLY(x) ((x)->query |= (DNS_REPLY))
-#define SET_DNS_QUERY(x) ((x)->query &= (DNS_REPLY))
+#define SET_DNS_QUERY(x) ((x)->query &= ~(DNS_REPLY))
#define SET_DNS_STATUS_REQ(x) ((x)->query |= (DNS_SREQ))
#define SET_DNS_INVERSE_QUERY(x) ((x)->query |= (DNS_INV))
#define SET_DNS_AUTHORITATIVE(x) ((x)->query |= (DNS_AUTH))
@@ -111,6 +111,19 @@ struct dns_question_hdr {
#define SET_DNS_RCODE_SERVFAIL(x) ((x)->query |= (DNS_SERVFAIL))
#define SET_DNS_RCODE_FORMATERR(x) ((x)->query |= (DNS_FORMATERR))
#define SET_DNS_RCODE_NOERR(x) ((x)->query |= (DNS_NOERR))
+
+#define UNSET_DNS_STATUS_REQ(x) ((x)->query &= ~(DNS_SREQ))
+#define UNSET_DNS_INVERSE_QUERY(x) ((x)->query &= ~(DNS_INV))
+#define UNSET_DNS_AUTHORITATIVE(x) ((x)->query &= ~(DNS_AUTH))
+#define UNSET_DNS_TRUNCATION(x) ((x)->query &= ~(DNS_TRUNC))
+#define UNSET_DNS_RECURSION(x) ((x)->query &= ~(DNS_RECURSE))
+#define UNSET_DNS_RECURSION_AVAIL(x) ((x)->query &= ~(DNS_RECAVAIL))
+#define UNSET_DNS_RCODE_REFUSED(x) ((x)->query &= ~(DNS_REFUSED))
+#define UNSET_DNS_RCODE_NOTIMPL(x) ((x)->query &= ~(DNS_NOTIMPL))
+#define UNSET_DNS_RCODE_NAMEERR(x) ((x)->query &= ~(DNS_NAMEERR))
+#define UNSET_DNS_RCODE_SERVFAIL(x) ((x)->query &= ~(DNS_SERVFAIL))
+#define UNSET_DNS_RCODE_FORMATERR(x) ((x)->query &= ~(DNS_FORMATERR))
+#define UNSET_DNS_RCODE_NOERR(x) ((x)->query &= ~(DNS_NOERR))
/* DNS types - RFC 1035 page 12 */
blob - d99dbcc1ce82d4609ef3c9a8ad263c15cee87dc5
blob + f9cfeb87d9435ea02e08100f10072e006c79d571
--- recurse.c
+++ recurse.c
@@ -90,10 +90,10 @@ struct recurses {
int lookup_ns(DB *, struct recurses *);
int lookup_a(DB *, struct recurses *, struct ns *);
-int recurse_parse(DB *db, struct recurses *sr, char *buf, int len);
+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.5 2010/09/16 14:37:34 pbug Exp $";
+static const char rcsid[] = "$Id: recurse.c,v 1.6 2010/09/16 20:24:53 pbug Exp $";
/*
* INIT_RECURSE - initialize the recurse singly linked list
@@ -357,7 +357,14 @@ recurseloop(int sp, int *raw, DB *db)
#else
sin.sin_addr.s_addr = sr->a[0];
#endif
- dh = (struct dns_header *)sr->query;
+ /* 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
@@ -365,7 +372,7 @@ recurseloop(int sp, int *raw, DB *db)
#endif
- if (sendto(sr->so, sr->query, sr->len, 0, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
+ 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);
@@ -671,19 +678,11 @@ lookup_a(DB *db, struct recurses *sr, struct ns *ns)
return (0);
}
-int
-recurse_parse(DB *db, struct recurses *sr, char *buf, int len)
-{
- struct dns_header *dh;
- char *question;
- int i;
+/*
+ * NEGATIVE_CACHE - cache a lookup as negative (NXDOMAIN)
+ *
+ */
- dh = (struct dns_header *)buf;
-
-
- return (0);
-}
-
int
negative_cache(DB *db, struct recurses *sr)
{
@@ -725,4 +724,249 @@ negative_cache(DB *db, struct recurses *sr)
update_db(db, &sd);
return (0);
+}
+
+/*
+ * RECURSE_PARSE - based on compress_label.
+ *
+ */
+
+int
+recurse_parse(DB *db, struct recurses *sr, u_char *buf, u_int16_t offset)
+{
+ u_char *label[256]; /* should be enough */
+ u_char converted_name[256][256];
+ 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, k;
+ u_int16_t *compressor;
+ u_int16_t c;
+
+ int found = 0;
+
+ u_char *p, *q, *r;
+
+ 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);
+
+ 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++;
+
+ if (p > end)
+ goto end;
+ }
+
+ 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 *) */
+
+ /*
+ * go through our list of labels and expand them from possible
+ * compression, then we make our next pass..
+ */
+
+ for (j = 0; j <= i; j++) {
+ q = converted_name[j];
+ p = label[j];
+again:
+ for (; *p ; p += *p, p++) {
+ if ((*p & 0xc0) == 0xc0)
+ break;
+
+ r = (p + 1);
+
+ *q++ = *p;
+
+ for (k = 0; k < *p; k++)
+ *q++ = tolower(r[k]);
+ }
+
+ if ((*p & 0xc0) == 0xc0) {
+ compressor = (u_int16_t *)p;
+ c = (ntohs(*compressor) & ~(0xc000));
+ for (k = 0; k <= i; k++) {
+ found = 0;
+ for (r = label[k]; *r; r += *r, r++) {
+ if (r - buf == c) {
+ p = r;
+ found = 1;
+ }
+
+
+ /*
+ * we're searching for an offset in
+ * non-compressed form, but we
+ * encountered compression, so we
+ * break and go to the next label
+ */
+
+ if ((*r & 0xc0) == 0xc0) {
+ break;
+ }
+ }
+
+ if (found) {
+ /*
+ * pretend we found a match but we
+ * have compression inside pointing
+ * down, then break this, it's corrupt
+ * it's a possible loop attempt
+ */
+ if ((*r & 0xc0) == 0xc0) {
+ compressor = (u_int16_t *)r;
+ if ((ntohs(*compressor) & ~0xc000) >= c)
+ break;
+ }
+
+ goto again;
+ }
+ }
+
+ /*
+ * if we fall through the for loop, we didn't find the
+ * recursive label... corrupt.
+ */
+
+ syslog(LOG_ERR, "corrupt compression");
+ return (-1);
+ }
+
+ *q++ = '\0'; /* don't forget this */
+
+ } /* for (j .. */
+
+ for (j = 0; j <= i; j++) {
+ syslog(LOG_DEBUG, "%s", converted_name[j]);
+ }
+
+ return (0);
+
+end:
+ syslog(LOG_DEBUG, "mangled input packet");
+ return (-1);
+
}
repomaster@centroid.eu