summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian <ian>2006-04-07 00:25:14 +0000
committerian <ian>2006-04-07 00:25:14 +0000
commit2c6eb096dd80e37c12ec5a301b771ff011fc00ce (patch)
treefc813c2279e0bcca8298a9d380540dee4604104e
parent2bd4b9f4167fa254b424385ee430d1402ef087b7 (diff)
unknown rr types seem to work
-rw-r--r--TODO1
-rw-r--r--changelog3
-rw-r--r--client/adh-main.c8
-rw-r--r--client/adh-opts.c1
-rw-r--r--client/adh-query.c23
-rw-r--r--client/adnshost.h6
-rw-r--r--client/adnstest.c2
-rw-r--r--src/adns.h35
-rw-r--r--src/internal.h5
-rw-r--r--src/query.c12
-rw-r--r--src/reply.c8
-rw-r--r--src/transmit.c7
-rw-r--r--src/types.c63
13 files changed, 135 insertions, 39 deletions
diff --git a/TODO b/TODO
index 7d1b81f..596ce28 100644
--- a/TODO
+++ b/TODO
@@ -1,5 +1,4 @@
WISHLIST:
-* Support for as-yet-unrecognised query types.
* Make timeouts configurable.
* `fake' reverse queries (give nnn.nnn.nnn.nnn either always or on error)
* `fake' forward queries (allow nnn.nnn.nnn.nnn -> A)
diff --git a/changelog b/changelog
index 8c245b1..e1fff88 100644
--- a/changelog
+++ b/changelog
@@ -18,7 +18,8 @@ adns (1.1.999.0.2); urgency=medium
* Provide adns_if_none and adns_qf_none (which will help with compilers
which complain about plain `0' being passed where an enum is wanted).
- * Support for SRV RRs.
+ * Support for SRV RRs.
+ * Support for unknown RR types (according to RFC3597).
--
diff --git a/client/adh-main.c b/client/adh-main.c
index 7065d58..49df6f5 100644
--- a/client/adh-main.c
+++ b/client/adh-main.c
@@ -111,6 +111,14 @@ void of_type(const struct optioninfo *oi, const char *arg, const char *arg2) {
};
const struct typename *tnp;
+ unsigned long unknowntype;
+ char *ep;
+
+ if (strlen(arg) > 4 && !memcmp(arg,"type",4) &&
+ (unknowntype= strtoul(arg+4, &ep, 10), !*ep) && unknowntype < 65536) {
+ ov_type= unknowntype | adns_r_unknown;
+ return;
+ }
for (tnp=typenames;
tnp->type && strcmp(arg,tnp->desc);
diff --git a/client/adh-opts.c b/client/adh-opts.c
index a649037..1a46bae 100644
--- a/client/adh-opts.c
+++ b/client/adh-opts.c
@@ -266,6 +266,7 @@ static void printusage(void) {
" ns soa ptr mx rp srv addr - enhanced versions\n"
" cname hinfo txt - types with only one version\n"
" a ns- soa- ptr- mx- rp- srv- - _raw versions\n"
+ " type<number> - `unknown' type, RFC3597\n"
"Default is addr, or ptr for -i/--ptr queries\n",
stdout);
if (ferror(stdout)) sysfail("write usage message",errno);
diff --git a/client/adh-query.c b/client/adh-query.c
index d17beab..b366697 100644
--- a/client/adh-query.c
+++ b/client/adh-query.c
@@ -55,6 +55,20 @@ void ensure_adns_init(void) {
ov_format= ov_asynch ? fmt_asynch : fmt_simple;
}
+void type_info(adns_rrtype type, const char **typename_r,
+ const void *datap, char **data_r) {
+ static char buf[12];
+ adns_status st;
+
+ st= adns_rr_info(type, typename_r, 0,0, datap,data_r);
+ if (st == adns_s_nomemory) sysfail("adns_rr_info failed",ENOMEM);
+ assert(!st);
+ if (typename_r && !*typename_r) {
+ sprintf(buf,"TYPE%d", (int)(type & adns_rrt_typemask));
+ *typename_r= buf;
+ }
+}
+
static void prep_query(struct query_node **qun_r, int *quflags_r) {
struct query_node *qun;
char idbuf[20];
@@ -221,7 +235,6 @@ static void print_status(adns_status st, struct query_node *qun, adns_answer *an
static void print_dnsfail(adns_status st, struct query_node *qun, adns_answer *answer) {
int r;
const char *typename, *statusstring;
- adns_status ist;
if (ov_format == fmt_inline) {
if (fputs("; failed ",stdout) == EOF) outerr();
@@ -232,7 +245,7 @@ static void print_dnsfail(adns_status st, struct query_node *qun, adns_answer *a
if (st == adns_s_nxdomain) {
r= fprintf(stderr,"%s does not exist\n", owner_show(qun,answer));
} else {
- ist= adns_rr_info(answer->type, &typename, 0,0,0,0);
+ type_info(answer->type, &typename, 0,0);
if (st == adns_s_nodata) {
r= fprintf(stderr,"%s has no %s record\n", owner_show(qun,answer), typename);
} else {
@@ -245,7 +258,7 @@ static void print_dnsfail(adns_status st, struct query_node *qun, adns_answer *a
}
void query_done(struct query_node *qun, adns_answer *answer) {
- adns_status st, ist;
+ adns_status st;
int rrn, nrrs;
const char *rrp, *realowner, *typename;
char *datastr;
@@ -279,9 +292,7 @@ void query_done(struct query_node *qun, adns_answer *answer) {
rrn++, rrp += answer->rrsz) {
if (realowner) print_withspace(realowner);
print_ttl(qun,answer);
- ist= adns_rr_info(answer->type, &typename, 0, 0, rrp, &datastr);
- if (ist == adns_s_nomemory) sysfail("adns_rr_info failed",ENOMEM);
- assert(!ist);
+ type_info(answer->type,&typename, rrp,&datastr);
if (qun->pqfr.show_type) print_withspace(typename);
if (printf("%s\n",datastr) == EOF) outerr();
free(datastr);
diff --git a/client/adnshost.h b/client/adnshost.h
index a8da4ff..30dd481 100644
--- a/client/adnshost.h
+++ b/client/adnshost.h
@@ -108,6 +108,12 @@ void ensure_adns_init(void);
void query_do(const char *domain);
void query_done(struct query_node *qun, adns_answer *answer);
+void type_info(adns_rrtype type, const char **typename_r,
+ const void *datap, char **data_r);
+ /* wrapper for adns_rr_info which uses a static buffer to provide
+ * *typename_r for adns_r_unknown */
+
+
/* declarations related to main program and useful utility functions */
void sysfail(const char *what, int errnoval) NONRETURNING;
diff --git a/client/adnstest.c b/client/adnstest.c
index 36d7ffe..cbc87bb 100644
--- a/client/adnstest.c
+++ b/client/adnstest.c
@@ -136,7 +136,7 @@ static const adns_rrtype defaulttypes[]= {
static void dumptype(adns_status ri, const char *rrtn, const char *fmtn) {
fprintf(stdout, "%s(%s)%s%s",
- ri ? "?" : rrtn, ri ? "?" : fmtn ? fmtn : "-",
+ rrtn ? "?" : rrtn, ri ? "?" : fmtn ? fmtn : "-",
ri ? " " : "", ri ? adns_strerror(ri) : "");
}
diff --git a/src/adns.h b/src/adns.h
index 65edbd8..a29b568 100644
--- a/src/adns.h
+++ b/src/adns.h
@@ -104,25 +104,28 @@ typedef enum { /* In general, or together the desired flags: */
} adns_queryflags;
typedef enum {
- adns__rrt_typemask=0x0ffff,
+ adns_rrt_typemask= 0x0ffff,
adns__qtf_deref= 0x10000,/* dereference domains; perhaps get extra data */
adns__qtf_mail822= 0x20000,/* return mailboxes in RFC822 rcpt field fmt */
adns_r_unknown= 0x40000,
/* To use this, ask for records of type <rr-type-code>|adns_r_unknown.
- * adns will not process the RDATA at all - you'll get intstr's, where
- * the int is the length and the char* points to the data. String
- * representation of the RR data is as in RFC3597. adns_rr_info
- * will not return the type name in *rrtname_r (due to memory management
- * problems); *fmtname_r will be set to "unknown".
+ * adns will not process the RDATA - you'll get adns_rr_byteblocks,
+ * where the int is the length and the unsigned char* points to the
+ * data. String representation of the RR data (by adns_rrinfo) is as in
+ * RFC3597. adns_rr_info will not return the type name in *rrtname_r
+ * (due to memory management problems); *fmtname_r will be set to
+ * "unknown".
*
* Do not specify adns_r_unknown along with a known RR type which
- * requires domain name uncompression. Domain names will not be
- * uncompressed and the resulting data will be useless. Asking for
- * meta-RR types via adns_r_unknown will not work properly either
- * and may make adns complain about server misbehaviour.
- */
-
+ * requires domain name uncompression (see RFC3597 s4); domain names
+ * will not be uncompressed and the resulting data would be useless.
+ * Asking for meta-RR types via adns_r_unknown will not work properly
+ * either and may make adns complain about server misbehaviour, so don't
+ * do that.
+ *
+ * Don't forget adns_qf_quoteok if that's what you want. */
+
adns_r_none= 0,
adns_r_a= 1,
@@ -333,6 +336,11 @@ typedef struct {
} adns_rr_srvha;
typedef struct {
+ int len;
+ unsigned char *data;
+} adns_rr_byteblock;
+
+typedef struct {
adns_status status;
char *cname; /* always NULL if query was for CNAME records */
char *owner; /* only set if req'd in query flags; maybe 0 on error anyway */
@@ -350,10 +358,11 @@ typedef struct {
adns_rr_intstrpair *intstrpair; /* hinfo */
adns_rr_strpair *strpair; /* rp, rp_raw */
adns_rr_inthostaddr *inthostaddr;/* mx */
- adns_rr_intstr *intstr; /* mx_raw, ...|unknown */
+ adns_rr_intstr *intstr; /* mx_raw */
adns_rr_soa *soa; /* soa, soa_raw */
adns_rr_srvraw *srvraw; /* srv_raw */
adns_rr_srvha *srvha;/* srv */
+ adns_rr_byteblock *byteblock; /* ...|unknown */
} rrs;
} adns_answer;
diff --git a/src/internal.h b/src/internal.h
index e4ec09e..eebf2a0 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -114,7 +114,7 @@ typedef struct {
} parseinfo;
typedef struct typeinfo {
- adns_rrtype type;
+ adns_rrtype typekey;
const char *rrtname;
const char *fmtname;
int rrsz;
@@ -404,7 +404,8 @@ void adns__sigpipe_unprotect(adns_state);
adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags);
+ const typeinfo *typei, adns_rrtype type,
+ adns_queryflags flags);
/* Assembles a query packet in vb. A new id is allocated and returned.
*/
diff --git a/src/query.c b/src/query.c
index 0b62ff6..4b24a30 100644
--- a/src/query.c
+++ b/src/query.c
@@ -37,7 +37,8 @@
#include "internal.h"
-static adns_query query_alloc(adns_state ads, const typeinfo *typei,
+static adns_query query_alloc(adns_state ads,
+ const typeinfo *typei, adns_rrtype type,
adns_queryflags flags, struct timeval now) {
/* Allocate a virgin query and return it. */
adns_query qu;
@@ -79,7 +80,7 @@ static adns_query query_alloc(adns_state ads, const typeinfo *typei,
qu->answer->status= adns_s_ok;
qu->answer->cname= qu->answer->owner= 0;
- qu->answer->type= typei->type;
+ qu->answer->type= type;
qu->answer->expires= -1;
qu->answer->nrrs= 0;
qu->answer->rrs.untyped= 0;
@@ -115,7 +116,7 @@ adns_status adns__internal_submit(adns_state ads, adns_query *query_r,
const qcontext *ctx) {
adns_query qu;
- qu= query_alloc(ads,typei,flags,now);
+ qu= query_alloc(ads,typei,typei->typekey,flags,now);
if (!qu) { adns__vbuf_free(qumsg_vb); return adns_s_nomemory; }
*query_r= qu;
@@ -133,7 +134,8 @@ static void query_simple(adns_state ads, adns_query qu,
int id;
adns_status stat;
- stat= adns__mkquery(ads,&qu->vb,&id, owner,ol, typei,flags);
+ stat= adns__mkquery(ads,&qu->vb,&id, owner,ol,
+ typei,qu->answer->type, flags);
if (stat) {
if (stat == adns_s_querydomaintoolong && (flags & adns_qf_search)) {
adns__search_next(ads,qu,now);
@@ -225,7 +227,7 @@ int adns_submit(adns_state ads,
if (!typei) return ENOSYS;
r= gettimeofday(&now,0); if (r) goto x_errno;
- qu= query_alloc(ads,typei,flags,now); if (!qu) goto x_errno;
+ qu= query_alloc(ads,typei,type,flags,now); if (!qu) goto x_errno;
qu->ctx.ext= context;
qu->ctx.callback= 0;
diff --git a/src/reply.c b/src/reply.c
index 4e7f8f7..199746c 100644
--- a/src/reply.c
+++ b/src/reply.c
@@ -187,7 +187,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
continue;
}
if (rrtype == adns_r_cname &&
- (qu->typei->type & adns__rrt_typemask) != adns_r_cname) {
+ (qu->answer->type & adns_rrt_typemask) != adns_r_cname) {
if (qu->flags & adns_qf_cname_forbid) {
adns__query_fail(qu,adns_s_prohibitedcname);
return;
@@ -230,7 +230,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
* it contains the relevant info.
*/
}
- } else if (rrtype == (qu->typei->type & adns__rrt_typemask)) {
+ } else if (rrtype == (qu->answer->type & adns_rrt_typemask)) {
wantedrrs++;
} else {
adns__debug(ads,serv,qu,"ignoring answer RR"
@@ -339,7 +339,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
&ownermatched);
assert(!st); assert(rrtype != -1);
if (rrclass != DNS_CLASS_IN ||
- rrtype != (qu->typei->type & adns__rrt_typemask) ||
+ rrtype != (qu->answer->type & adns_rrt_typemask) ||
!ownermatched)
continue;
adns__update_expires(qu,ttl,now);
@@ -373,7 +373,7 @@ void adns__procdgram(adns_state ads, const byte *dgram, int dglen,
if (qu->cname_dgram) {
st= adns__mkquery_frdgram(qu->ads,&qu->vb,&qu->id,
qu->cname_dgram,qu->cname_dglen,qu->cname_begin,
- qu->typei->type, qu->flags);
+ qu->answer->type, qu->flags);
if (st) { adns__query_fail(qu,st); return; }
newquery= realloc(qu->query_dgram,qu->vb.used);
diff --git a/src/transmit.c b/src/transmit.c
index 6136bf9..c7dcdb4 100644
--- a/src/transmit.c
+++ b/src/transmit.c
@@ -67,7 +67,7 @@ static adns_status mkquery_footer(vbuf *vb, adns_rrtype type) {
byte *rqp;
MKQUERY_START(vb);
- MKQUERY_ADDW(type & adns__rrt_typemask); /* QTYPE */
+ MKQUERY_ADDW(type & adns_rrt_typemask); /* QTYPE */
MKQUERY_ADDW(DNS_CLASS_IN); /* QCLASS=IN */
MKQUERY_STOP(vb);
assert(vb->used <= vb->avail);
@@ -121,7 +121,8 @@ adns_status adns__qdpl_normal(adns_state ads,
adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
const char *owner, int ol,
- const typeinfo *typei, adns_queryflags flags) {
+ const typeinfo *typei, adns_rrtype type,
+ adns_queryflags flags) {
int labelnum, ll, nbytes;
byte label[255];
byte *rqp;
@@ -150,7 +151,7 @@ adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
MKQUERY_STOP(vb);
- st= mkquery_footer(vb,typei->type);
+ st= mkquery_footer(vb,type);
return adns_s_ok;
}
diff --git a/src/types.c b/src/types.c
index 14afc90..e0b9698 100644
--- a/src/types.c
+++ b/src/types.c
@@ -64,6 +64,8 @@
* _rp (pa)
* _soa (pa,mf,cs)
* _srv* (qdpl,(pap),pa,mf,di,(csp),cs,postsort)
+ * _byteblock (mf)
+ * _opaque (pa,cs)
* _flat (mf)
*
* within each section:
@@ -908,7 +910,7 @@ static adns_status pap_mailbox822(const parseinfo *pai,
static adns_status pap_mailbox(const parseinfo *pai, int *cbyte_io, int max,
char **mb_r) {
- if (pai->qu->typei->type & adns__qtf_mail822) {
+ if (pai->qu->typei->typekey & adns__qtf_mail822) {
return pap_mailbox822(pai, cbyte_io, max, mb_r);
} else {
return pap_domain(pai, cbyte_io, max, mb_r, pdf_quoteok);
@@ -1183,6 +1185,56 @@ static void postsort_srv(adns_state ads, void *array, int nrrs,
}
/*
+ * _byteblock (mf)
+ */
+
+static void mf_byteblock(adns_query qu, void *datap) {
+ adns_rr_byteblock *rrp= datap;
+ void *bytes= rrp->data;
+ adns__makefinal_block(qu,&bytes,rrp->len);
+ rrp->data= bytes;
+}
+
+/*
+ * _opaque (pa,cs)
+ */
+
+static adns_status pa_opaque(const parseinfo *pai, int cbyte,
+ int max, void *datap) {
+ adns_rr_byteblock *rrp= datap;
+
+ rrp->len= max - cbyte;
+ rrp->data= adns__alloc_interim(pai->qu, rrp->len);
+ if (!rrp->data) R_NOMEM;
+ memcpy(rrp->data, pai->dgram + cbyte, rrp->len);
+ return adns_s_ok;
+}
+
+static adns_status cs_opaque(vbuf *vb, const void *datap) {
+ const adns_rr_byteblock *rrp= datap;
+ char buf[10];
+ int l;
+ unsigned char *p;
+
+ sprintf(buf,"\\# %d",rrp->len);
+ CSP_ADDSTR(buf);
+
+ for (l= rrp->len, p= rrp->data;
+ l>=4;
+ l -= 4, p += 4) {
+ sprintf(buf," %02x%02x%02x%02x",p[0],p[1],p[2],p[3]);
+ CSP_ADDSTR(buf);
+ }
+ for (;
+ l>0;
+ l--, p++) {
+ sprintf(buf," %02x",*p);
+ CSP_ADDSTR(buf);
+ }
+ return adns_s_ok;
+}
+
+/*
* _flat (mf)
*/
@@ -1234,15 +1286,20 @@ DEEP_TYPE(soa, "SOA","822", soa, pa_soa, 0, cs_soa ),
DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0, cs_rp ),
};
+static const typeinfo typeinfo_unknown=
+DEEP_TYPE(unknown,0, "unknown",byteblock,pa_opaque, 0, cs_opaque );
+
const typeinfo *adns__findtype(adns_rrtype type) {
const typeinfo *begin, *end, *mid;
+ if (type & adns_r_unknown) return &typeinfo_unknown;
+
begin= typeinfos; end= typeinfos+(sizeof(typeinfos)/sizeof(typeinfo));
while (begin < end) {
mid= begin + ((end-begin)>>1);
- if (mid->type == type) return mid;
- if (type > mid->type) begin= mid+1;
+ if (mid->typekey == type) return mid;
+ if (type > mid->typekey) begin= mid+1;
else end= mid;
}
return 0;