quoted-names are allowed or not.
adns_r_mx_raw,
adns_r_rp_raw,
adns_r_txt,
+ adns_r_addr,
adns_r_none
};
} adns_initflags;
typedef enum {
- adns_qf_search= 0x0001, /* use the searchlist */
- adns_qf_usevc= 0x0002, /* use a virtual circuit (TCP connection) */
- adns_qf_anyquote= 0x0004,
- adns_qf_loosecname= 0x0008, /* allow refs to CNAMEs - without, get _s_cname */
- adns_qf_nocname= 0x0010, /* don't follow CNAMEs, instead give _s_cname */
+ adns_qf_search= 0x000001, /* use the searchlist */
+ adns_qf_usevc= 0x000002, /* use a virtual circuit (TCP connection) */
+ adns_qf_quoteok_query= 0x000010, /* allow quote-requiring chars in query domain */
+ adns_qf_quoteok_cname= 0x000020, /* allow ... in CNAME we go via */
+ adns_qf_quoteok_anshost= 0x000040, /* allow ... in answers expected to be hostnames */
+ adns_qf_cname_loose= 0x000100, /* allow refs to CNAMEs - without, get _s_cname */
+ adns_qf_cname_forbid= 0x000200, /* don't follow CNAMEs, instead give _s_cname */
+ adns__qf_internalmask= 0x0ff000
} adns_queryflags;
typedef enum {
adns_r_rp_raw= 17,
adns_r_rp= adns_r_rp_raw|adns__qtf_mail822,
+
+ adns_r_addr= adns_r_a|adns__qtf_deref
} adns_rrtype;
adns_s_domaintoolong,
} adns_status;
+typedef struct {
+ int len;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in inet;
+ } addr;
+} adns_addr;
+
typedef struct {
char *dm;
adns_status astatus;
int naddrs; /* temp fail => -1, perm fail => 0, s_ok => >0 */
- struct in_addr *addrs;
+ adns_addr *addrs;
} adns_rr_dmaddr;
typedef struct {
unsigned char *bytes;
char *(*str); /* ns_raw, cname, ptr, ptr_raw */
adns_rr_intstr *(*manyistr); /* txt (list of strings ends with i=-1, str=0) */
+ adns_addr *addr; /* addr */
struct in_addr *inaddr; /* a */
adns_rr_dmaddr *dmaddr; /* ns */
adns_rr_strpair *strpair; /* hinfo ??fixme, rp, rp_raw */
adns__vbuf_init(&vb);
fprintf(stderr,"%sQNAME=%s, QTYPE=%s",
bef,
- adns__diag_domain(qu->ads,-1,0, &vb,qu->flags,
+ adns__diag_domain(qu->ads,-1,0, &vb,
qu->query_dgram,qu->query_dglen,DNS_HDRSIZE),
qu->typei ? qu->typei->rrtname : "<unknown>");
if (qu->typei && qu->typei->fmtname)
/* Additional diagnostic functions */
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
- int flags, const byte *dgram, int dglen, int cbyte) {
+const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
+ vbuf *vb, const byte *dgram, int dglen, int cbyte) {
adns_status st;
- st= adns__parse_domain(ads,serv,qu,vb, flags,dgram,dglen,&cbyte,dglen);
+ st= adns__parse_domain(ads,serv,qu,vb, pdf_quoteok, dgram,dglen,&cbyte,dglen);
if (st == adns_s_nolocalmem) {
return "<cannot report domain... out of memory>";
}
void adns__vbuf_init(vbuf *vb);
void adns__vbuf_free(vbuf *vb);
-const char *adns__diag_domain(adns_state ads, int serv, adns_query qu, vbuf *vb,
- int flags, const byte *dgram, int dglen, int cbyte);
+const char *adns__diag_domain(adns_state ads, int serv, adns_query qu,
+ vbuf *vb, const byte *dgram, int dglen, int cbyte);
/* Unpicks a domain in a datagram and returns a string suitable for
* printing it as. Never fails - if an error occurs, it will
* return some kind of string describing the error.
* Do not then call findlabel_next again.
*/
+typedef enum {
+ pdf_quoteok= 0x001
+} parsedomain_flags;
+
adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, int flags,
+ vbuf *vb, parsedomain_flags flags,
const byte *dgram, int dglen, int *cbyte_io, int max);
/* vb must already have been initialised; it will be reset if necessary.
* If there is truncation, vb->used will be set to 0; otherwise
}
adns_status adns__parse_domain(adns_state ads, int serv, adns_query qu,
- vbuf *vb, int flags,
+ vbuf *vb, adns_queryflags flags,
const byte *dgram, int dglen, int *cbyte_io, int max) {
findlabel_state fls;
if (!lablen) break;
if (vb->used)
if (!adns__vbuf_append(vb,".",1)) return adns_s_nolocalmem;
- if (flags & adns_qf_anyquote) {
+ if (flags & pdf_quoteok) {
if (!vbuf__append_quoted1035(vb,dgram+labstart,lablen))
return adns_s_nolocalmem;
} else {
if (ads->iflags & adns_if_debug) {
adns__vbuf_init(&tempvb);
adns__debug(ads,serv,0,"reply not found, id %02x, query owner %s",
- id, adns__diag_domain(ads,serv,0,&tempvb,adns_qf_anyquote,
- dgram,dglen,DNS_HDRSIZE));
+ id, adns__diag_domain(ads,serv,0,&tempvb,dgram,dglen,DNS_HDRSIZE));
adns__vbuf_free(&tempvb);
}
return;
if (!ownermatched) {
if (ads->iflags & adns_if_debug) {
adns__debug(ads,serv,qu,"ignoring RR with an unexpected owner %s",
- adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
- dgram,dglen,rrstart));
+ adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rrstart));
}
continue;
}
if (!qu->cname_dgram) { /* Ignore second and subsequent CNAMEs */
qu->cname_begin= rdstart;
qu->cname_dglen= dglen;
- st= adns__parse_domain(ads,serv,qu, &qu->vb,qu->flags,
+ st= adns__parse_domain(ads,serv,qu, &qu->vb,
+ qu->flags & adns_qf_quoteok_cname ? pdf_quoteok : 0,
dgram,dglen, &rdstart,rdstart+rdlength);
if (!qu->vb.used) goto x_truncated;
if (st) { adns__query_fail(qu,st); return; }
*/
} else {
adns__debug(ads,serv,qu,"ignoring duplicate CNAME (%s, as well as %s)",
- adns__diag_domain(ads,serv,qu, &qu->vb,qu->flags,
- dgram,dglen,rdstart),
+ adns__diag_domain(ads,serv,qu, &qu->vb, dgram,dglen,rdstart),
qu->answer->cname);
}
} else if (rrtype == (qu->typei->type & adns__rrt_typemask)) {
ll= 0;
while (p!=pe && (c= *p++)!='.') {
if (c=='\\') {
- if (!(flags & adns_qf_anyquote)) return adns_s_invalidquerydomain;
+ if (!(flags & adns_qf_quoteok_query)) return adns_s_invalidquerydomain;
if (ctype_digit(p[0])) {
if (ctype_digit(p[1]) && ctype_digit(p[2])) {
c= (*p++ - '0')*100 + (*p++ - '0')*10 + (*p++ - '0');
return adns_s_invalidquerydomain;
}
}
- if (!(flags & adns_qf_anyquote)) {
+ if (!(flags & adns_qf_quoteok_query)) {
if (c == '-') {
if (!ll) return adns_s_invalidquerydomain;
} else if (!ctype_alpha(c) && !ctype_digit(c)) {
*/
#include <stdlib.h>
+#include <string.h>
#include <arpa/inet.h>
#include "internal.h"
+static int dip_inaddr(struct in_addr a, struct in_addr b) {
+ /* fixme implement sortlist */
+ return 0;
+}
+
static adns_status pa_inaddr(adns_query qu, int serv,
const byte *dgram, int dglen, int cbyte, int max,
void *datap) {
return adns_s_ok;
}
-static int dip_inaddr(struct in_addr a, struct in_addr b) {
- /* fixme implement sortlist */
- return 0;
-}
-
static int di_inaddr(const void *datap_a, const void *datap_b) {
const struct in_addr *ap= datap_a, *bp= datap_b;
return adns__vbuf_appendstr(vb,ia) ? adns_s_ok : adns_s_nolocalmem;
}
-static adns_status pap_domain(adns_query qu, int serv,
+static adns_status pa_addr(adns_query qu, int serv,
+ const byte *dgram, int dglen, int cbyte, int max,
+ void *datap) {
+ adns_addr *storeto= datap;
+
+ if (max-cbyte != 4) return adns_s_invaliddata;
+ storeto->len= sizeof(storeto->addr.inet);
+ memset(&storeto->addr,0,sizeof(storeto->addr.inet));
+ storeto->addr.inet.sin_family= AF_INET;
+ storeto->addr.inet.sin_port= 0;
+ memcpy(&storeto->addr.inet.sin_addr,dgram+cbyte,4);
+ return adns_s_ok;
+}
+
+static int di_addr(const void *datap_a, const void *datap_b) {
+ const adns_addr *ap= datap_a, *bp= datap_b;
+
+ return dip_inaddr(ap->addr.inet.sin_addr,bp->addr.inet.sin_addr);
+}
+
+static adns_status cs_addr(vbuf *vb, const void *datap) {
+ const adns_addr *rrp= datap;
+ const char *ia;
+ static char buf[30];
+
+ switch (rrp->addr.inet.sin_family) {
+ case AF_INET:
+ if (!adns__vbuf_appendstr(vb,"AF_INET ")) return adns_s_nolocalmem;
+ ia= inet_ntoa(rrp->addr.inet.sin_addr); assert(ia);
+ if (!adns__vbuf_appendstr(vb,ia)) return adns_s_nolocalmem;
+ break;
+ default:
+ sprintf(buf,"AF=%u",rrp->addr.sa.sa_family);
+ if (!adns__vbuf_appendstr(vb,buf)) return adns_s_nolocalmem;
+ break;
+ }
+ return adns_s_ok;
+}
+
+static adns_status pap_domain(adns_query qu, int serv, parsedomain_flags flags,
const byte *dgram, int dglen, int *cbyte_io, int max,
char **domain_r) {
adns_status st;
char *dm;
- st= adns__parse_domain(qu->ads,serv,qu,&qu->vb,qu->flags,
- dgram,dglen, cbyte_io,max);
+ st= adns__parse_domain(qu->ads,serv,qu,&qu->vb,flags, dgram,dglen, cbyte_io,max);
if (st) return st;
if (!qu->vb.used) return adns_s_invaliddata;
return adns_s_ok;
}
-static adns_status pa_domain_raw(adns_query qu, int serv,
- const byte *dgram, int dglen, int cbyte, int max,
- void *datap) {
+static adns_status pa_host_raw(adns_query qu, int serv,
+ const byte *dgram, int dglen, int cbyte, int max,
+ void *datap) {
char **rrp= datap;
adns_status st;
- st= pap_domain(qu,serv,dgram,dglen,&cbyte,max,rrp);
+ st= pap_domain(qu,serv,
+ qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0,
+ dgram,dglen,&cbyte,max,rrp);
if (st) return st;
if (cbyte != max) return adns_s_invaliddata;
if (cbyte+2 > max) return adns_s_invaliddata;
GET_W(cbyte,pref);
rrp->i= pref;
- st= pap_domain(qu,serv,dgram,dglen,&cbyte,max,&rrp->str);
+ st= pap_domain(qu,serv,
+ qu->flags & adns_qf_quoteok_anshost ? pdf_quoteok : 0,
+ dgram,dglen,&cbyte,max,&rrp->str);
if (st) return st;
if (cbyte != max) return adns_s_invaliddata;
/* rr type code rrt fmt mem.mgmt member parser comparer */
{ adns_r_a, "A", 0, FLAT_MEMB(inaddr), pa_inaddr, di_inaddr },
- { adns_r_ns_raw, "NS", "raw", DEEP_MEMB(str), pa_domain_raw, 0 },
- { adns_r_cname, "CNAME", 0, DEEP_MEMB(str), pa_domain_raw, 0 },
+ { adns_r_ns_raw, "NS", "raw", DEEP_MEMB(str), pa_host_raw, 0 },
+ { adns_r_cname, "CNAME", 0, DEEP_MEMB(str), pa_host_raw, 0 },
#if 0 /*fixme*/
{ adns_r_soa_raw, "SOA", "raw", DEEP_MEMB(soa), pa_soa, 0 },
#endif
- { adns_r_ptr_raw, "PTR", "raw", DEEP_MEMB(str), pa_domain_raw, 0 },
+ { adns_r_ptr_raw, "PTR", "raw", DEEP_MEMB(str), pa_host_raw, 0 },
#if 0 /*fixme*/
{ adns_r_hinfo, "HINFO", 0, DEEP_MEMB(strpair), pa_hinfo, 0 },
#endif
#if 0 /*fixme*/
{ adns_r_rp_raw, "RP", "raw", DEEP_MEMB(strpair), pa_rp, 0 },
#endif
-#if 0 /*fixme*/
+ { adns_r_addr, "A", "addr", FLAT_MEMB(addr), pa_addr, di_addr },
+#if 0 /*fixme*/
{ adns_r_ns, "NS", "+addr", DEEP_MEMB(dmaddr), pa_dmaddr, di_dmaddr },
{ adns_r_ptr, "PTR","checked", DEEP_MEMB(str), pa_ptr, 0 },
{ adns_r_mx, "MX", "+addr", DEEP_MEMB(intdmaddr), pa_mx, di_mx },