struct timeval now;
} parseinfo;
-typedef struct {
+typedef struct typeinfo {
adns_rrtype type;
const char *rrtname;
const char *fmtname;
/* Returns !0 if RR a should be strictly after RR b in the sort order,
* 0 otherwise. Must not fail.
*/
+
+ adns_status (*qdparselabel)(adns_state ads,
+ const char **p_io, const char *pe, int labelnum,
+ char label_r[DNS_MAXDOMAIN], int *ll_io,
+ adns_queryflags flags,
+ const struct typeinfo *typei);
+ /* Parses one label from the query domain string. On entry, *p_io
+ * points to the next character to parse and *ll_io is the size of
+ * the buffer. pe points just after the end of the query domain
+ * string. On successful return, label_r[] and *ll_io are filled in
+ * and *p_io points to *pe or just after the label-ending `.'. */
+
+ void (*postsort)(adns_state ads, void *array, int nobjs,
+ const struct typeinfo *typei);
+ /* Called immediately after the RRs have been sorted, and may rearrange
+ * them. (This is really for the benefit of SRV's bizarre weighting
+ * stuff.) May be 0 to mean nothing needs to be done.
+ */
} typeinfo;
+adns_status adns__qdpl_normal(adns_state ads,
+ const char **p_io, const char *pe, int labelnum,
+ char label_r[], int *ll_io,
+ adns_queryflags flags,
+ const typeinfo *typei);
+ /* implemented in transmit.c, used by types.c as default
+ * and as part of implementation for some fancier types */
+
typedef struct allocnode {
struct allocnode *next, *back;
} allocnode;
return adns_s_ok;
}
+adns_status adns__qdpl_normal(adns_state ads,
+ const char **p_io, const char *pe, int labelnum,
+ char label_r[], int *ll_io,
+ adns_queryflags flags,
+ const typeinfo *typei) {
+ int ll, c;
+ const char *p;
+
+ ll= 0;
+ p= *p_io;
+
+ while (p!=pe && (c= *p++)!='.') {
+ if (c=='\\') {
+ if (!(flags & adns_qf_quoteok_query)) return adns_s_querydomaininvalid;
+ if (ctype_digit(p[0])) {
+ if (p+1==pe || p+2==pe) return adns_s_querydomaininvalid;
+ if (ctype_digit(p[1]) && ctype_digit(p[2])) {
+ c= (*p++ - '0')*100;
+ c += (*p++ - '0')*10;
+ c += (*p++ - '0');
+ if (c >= 256) return adns_s_querydomaininvalid;
+ } else {
+ return adns_s_querydomaininvalid;
+ }
+ } else if (!(c= *p++)) {
+ return adns_s_querydomaininvalid;
+ }
+ }
+ if (!(flags & adns_qf_quoteok_query)) {
+ if (c == '-') {
+ if (!ll) return adns_s_querydomaininvalid;
+ } else if (!ctype_alpha(c) && !ctype_digit(c)) {
+ return adns_s_querydomaininvalid;
+ }
+ }
+ if (ll == *ll_io) return adns_s_querydomaininvalid;
+ label_r[ll++]= c;
+ }
+
+ *p_io= p;
+ *ll_io= ll;
+ return adns_s_ok;
+}
+
adns_status adns__mkquery(adns_state ads, vbuf *vb, int *id_r,
const char *owner, int ol,
const typeinfo *typei, adns_queryflags flags) {
- int ll, c, nbytes;
- byte label[255], *rqp;
+ int labelnum, ll, nbytes;
+ byte label[255];
+ byte *rqp;
const char *p, *pe;
adns_status st;
p= owner; pe= owner+ol;
nbytes= 0;
+ labelnum= 0;
while (p!=pe) {
- ll= 0;
- while (p!=pe && (c= *p++)!='.') {
- if (c=='\\') {
- if (!(flags & adns_qf_quoteok_query)) return adns_s_querydomaininvalid;
- if (ctype_digit(p[0])) {
- if (ctype_digit(p[1]) && ctype_digit(p[2])) {
- c= (*p++ - '0')*100;
- c += (*p++ - '0')*10;
- c += (*p++ - '0');
- if (c >= 256) return adns_s_querydomaininvalid;
- } else {
- return adns_s_querydomaininvalid;
- }
- } else if (!(c= *p++)) {
- return adns_s_querydomaininvalid;
- }
- }
- if (!(flags & adns_qf_quoteok_query)) {
- if (c == '-') {
- if (!ll) return adns_s_querydomaininvalid;
- } else if (!ctype_alpha(c) && !ctype_digit(c)) {
- return adns_s_querydomaininvalid;
- }
- }
- if (ll == sizeof(label)) return adns_s_querydomaininvalid;
- label[ll++]= c;
- }
+ ll= sizeof(label);
+ st= typei->qdparselabel(ads, &p,pe, labelnum++, label, &ll, flags, typei);
+ if (st) return st;
if (!ll) return adns_s_querydomaininvalid;
if (ll > DNS_MAXLABEL) return adns_s_querydomaintoolong;
nbytes+= ll+1;
return adns_s_ok;
}
+/*
+ * _srv* (pa*2,di,cs*2,qdpl,postsort)
+ */
+
+static adns_status qdpl_srv(adns_state ads,
+ const char **p_io, const char *pe, int labelnum,
+ char label_r[DNS_MAXDOMAIN], int *ll_io,
+ adns_queryflags flags,
+ const typeinfo *typei) {
+ int useflags;
+ const char *p_orig;
+ adns_status st;
+
+ if (labelnum < 2 && !(flags & adns_qf_quoteok_query)) {
+ useflags= adns_qf_quoteok_query;
+ p_orig= *p_io;
+ } else {
+ useflags= flags;
+ p_orig= 0;
+ }
+ st= adns__qdpl_normal(ads, p_io,pe, labelnum,label_r, ll_io, useflags,typei);
+ if (st) return st;
+
+ if (p_orig) {
+ int ll= *ll_io;
+ if (!ll || label_r[0]!='_')
+ return adns_s_querydomaininvalid;
+ if (memchr(p_orig+1, '\\', pe - (p_orig+1)))
+ return adns_s_querydomaininvalid;
+ }
+ return adns_s_ok;
+}
+
/*
* _flat (mf)
*/
#define DEEP_MEMB(memb) TYPESZ_M(memb), mf_##memb, cs_##memb
#define FLAT_MEMB(memb) TYPESZ_M(memb), mf_flat, cs_##memb
-#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
- { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb, printer,parser,comparer }
-#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
- { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_flat, printer,parser,comparer }
+#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
+ { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb, \
+ printer,parser,comparer, adns__qdpl_normal,0 }
+#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,printer) \
+ { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_flat, \
+ printer,parser,comparer, adns__qdpl_normal,0 }
+#define XTRA_TYPE(code,rrt,fmt,memb,parser,comparer,printer,qdpl,postsort) \
+ { adns_r_##code, rrt,fmt,TYPESZ_M(memb), mf_##memb, \
+ printer,parser,comparer,qdpl,postsort }
static const typeinfo typeinfos[] = {
/* Must be in ascending order of rrtype ! */
DEEP_TYPE(mx_raw, "MX", "raw",intstr, pa_mx_raw, di_mx_raw,cs_inthost ),
DEEP_TYPE(txt, "TXT", 0, manyistr,pa_txt, 0, cs_txt ),
DEEP_TYPE(rp_raw, "RP", "raw",strpair, pa_rp, 0, cs_rp ),
+#if 0
+XTRA_TYPE(srv_raw,"SRV", "raw",srvraw , pa_srvraw, di_srv, cs_srvraw,
+ qdpl_srv, postsort_srv),
+#endif
FLAT_TYPE(addr, "A", "addr", addr, pa_addr, di_addr, cs_addr ),
DEEP_TYPE(ns, "NS", "+addr",hostaddr,pa_hostaddr,di_hostaddr,cs_hostaddr ),
DEEP_TYPE(ptr, "PTR","checked",str, pa_ptr, 0, cs_domain ),
DEEP_TYPE(mx, "MX", "+addr",inthostaddr,pa_mx, di_mx, cs_inthostaddr),
-
+#if 0
+XTRA_TYPE(srv, "SRV","+addr",srvhostaddr,pa_srvaddr,di_srv, cs_srvhostaddr,
+ qdpl_srv, postsort_srv),
+#endif
+
DEEP_TYPE(soa, "SOA","822", soa, pa_soa, 0, cs_soa ),
DEEP_TYPE(rp, "RP", "822", strpair, pa_rp, 0, cs_rp ),
};