From: ian Date: Fri, 7 Apr 2006 00:25:14 +0000 (+0000) Subject: unknown rr types seem to work X-Git-Tag: wip.base.getaddrinfo~53 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/adns/commitdiff_plain/7d0aaee4dc7c78c81b609d678c63e194a3cbcbc7 unknown rr types seem to work --- 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 - `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 0494124..bc7bf24 100644 --- a/src/adns.h +++ b/src/adns.h @@ -51,7 +51,7 @@ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * - * $Id: adns.h,v 1.93 2006/04/06 18:59:53 ian Exp $ + * $Id: adns.h,v 1.94 2006/04/07 00:25:14 ian Exp $ */ #ifndef ADNS_H_INCLUDED @@ -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 |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, @@ -332,6 +335,11 @@ typedef struct { adns_rr_hostaddr ha; } 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 */ @@ -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); @@ -1182,6 +1184,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;