summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
7f59371)
All records in a particular answer are going to be the same size: that's
not going to change. The case we're dealing with here is that we're
going to want to include new information (e.g., new kinds of address
families) which will make the structures larger -- and would break old
binary clients.
The plan is for new clients to encode a flag saying that they understand
the extended structure in the type field (implicitly, through a header-
file change). But all of this means that just dredging `typei->rrsz'
out of the typeinfo structure isn't going to cut it any more, so we add
a type hook to compute the right size, and make sure that we use it by
renaming the slot containing the fixed value. Most places in the code
can avoid having to call the hook by grabbing the record size from the
answer structure.
This involves adding an extra parameter to the postsort hook, which
otherwise might not be able to determine the right size for itself.
Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
+int adns__getrrsz_default(const typeinfo *typei, adns_rrtype type)
+ { return typei->fixed_rrsz; }
+
adns_status adns_rr_info(adns_rrtype type,
const char **rrtname_r, const char **fmtname_r,
int *len_r,
adns_status adns_rr_info(adns_rrtype type,
const char **rrtname_r, const char **fmtname_r,
int *len_r,
if (rrtname_r) *rrtname_r= typei->rrtname;
if (fmtname_r) *fmtname_r= typei->fmtname;
if (rrtname_r) *rrtname_r= typei->rrtname;
if (fmtname_r) *fmtname_r= typei->fmtname;
- if (len_r) *len_r= typei->rrsz;
+ if (len_r) *len_r= typei->getrrsz(typei, type);
if (!datap) return adns_s_ok;
if (!datap) return adns_s_ok;
adns_rrtype typekey;
const char *rrtname;
const char *fmtname;
adns_rrtype typekey;
const char *rrtname;
const char *fmtname;
void (*makefinal)(adns_query qu, void *data);
/* Change memory management of *data.
void (*makefinal)(adns_query qu, void *data);
/* Change memory management of *data.
/* Parse one RR, in dgram of length dglen, starting at cbyte and
* extending until at most max.
*
/* Parse one RR, in dgram of length dglen, starting at cbyte and
* extending until at most max.
*
- * The RR should be stored at *store_r, of length qu->typei->rrsz.
+ * The RR should be stored at *store_r, of length qu->typei->getrrsz().
*
* If there is an overrun which might indicate truncation, it should set
* *rdstart to -1; otherwise it may set it to anything else positive.
*
* If there is an overrun which might indicate truncation, it should set
* *rdstart to -1; otherwise it may set it to anything else positive.
* because lablen is zero.
*/
* because lablen is zero.
*/
- void (*postsort)(adns_state ads, void *array, int nrrs,
+ void (*postsort)(adns_state ads, void *array, int nrrs,int rrsz,
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.
*/
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.
*/
+
+ int (*getrrsz)(const struct typeinfo *typei, adns_rrtype type);
+ /* Return the output resource-record element size; if this is null, then
+ * the rrsz member can be used.
+ */
} typeinfo;
adns_status adns__ckl_hostname(adns_state ads, adns_queryflags flags,
} typeinfo;
adns_status adns__ckl_hostname(adns_state ads, adns_queryflags flags,
* vb before using the return value.
*/
* vb before using the return value.
*/
+int adns__getrrsz_default(const typeinfo *typei, adns_rrtype type);
+/* Default function for the `getrrsz' type hook; returns the `fixed_rrsz'
+ * value from the typeinfo entry.
+ */
+
void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
int (*needswap)(void *context, const void *a, const void *b),
void *context);
void adns__isort(void *array, int nobjs, int sz, void *tempbuf,
int (*needswap)(void *context, const void *a, const void *b),
void *context);
qu->answer->expires= -1;
qu->answer->nrrs= 0;
qu->answer->rrs.untyped= 0;
qu->answer->expires= -1;
qu->answer->nrrs= 0;
qu->answer->rrs.untyped= 0;
- qu->answer->rrsz= typei->rrsz;
+ qu->answer->rrsz= typei->getrrsz(typei,type);
}
if (ans->nrrs && qu->typei->diff_needswap) {
}
if (ans->nrrs && qu->typei->diff_needswap) {
- if (!adns__vbuf_ensure(&qu->vb,qu->typei->rrsz)) {
+ if (!adns__vbuf_ensure(&qu->vb,qu->answer->rrsz)) {
adns__query_fail(qu,adns_s_nomemory);
return;
}
adns__query_fail(qu,adns_s_nomemory);
return;
}
qu->ads);
}
if (ans->nrrs && qu->typei->postsort) {
qu->ads);
}
if (ans->nrrs && qu->typei->postsort) {
- qu->typei->postsort(qu->ads, ans->rrs.bytes, ans->nrrs, qu->typei);
+ qu->typei->postsort(qu->ads, ans->rrs.bytes,
+ ans->nrrs,ans->rrsz, qu->typei);
}
ans->expires= qu->expires;
}
ans->expires= qu->expires;
/* Now, we have some RRs which we wanted. */
/* Now, we have some RRs which we wanted. */
- qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->typei->rrsz*wantedrrs);
+ qu->answer->rrs.untyped= adns__alloc_interim(qu,qu->answer->rrsz*wantedrrs);
if (!qu->answer->rrs.untyped) {
adns__query_fail(qu,adns_s_nomemory);
return;
if (!qu->answer->rrs.untyped) {
adns__query_fail(qu,adns_s_nomemory);
return;
!ownermatched)
continue;
adns__update_expires(qu,ttl,now);
!ownermatched)
continue;
adns__update_expires(qu,ttl,now);
- st= typei->parse(&pai, rdstart,rdstart+rdlength, rrsdata+nrrs*typei->rrsz);
+ st= typei->parse(&pai, rdstart,rdstart+rdlength,
+ rrsdata+nrrs*qu->answer->rrsz);
if (st) { adns__query_fail(qu,st); return; }
if (rdstart==-1) goto x_truncated;
nrrs++;
if (st) { adns__query_fail(qu,st); return; }
if (rdstart==-1) goto x_truncated;
nrrs++;
return csp_hostaddr(vb,&rrp->ha);
}
return csp_hostaddr(vb,&rrp->ha);
}
-static void postsort_srv(adns_state ads, void *array, int nrrs,
+static void postsort_srv(adns_state ads, void *array, int nrrs,int rrsz,
const struct typeinfo *typei) {
/* we treat everything in the array as if it were an adns_rr_srvha
* even though the array might be of adns_rr_srvraw. That's OK
* because they have the same prefix, which is all we access.
const struct typeinfo *typei) {
/* we treat everything in the array as if it were an adns_rr_srvha
* even though the array might be of adns_rr_srvraw. That's OK
* because they have the same prefix, which is all we access.
- * We use typei->rrsz, too, rather than naive array indexing, of course.
+ * We use rrsz, too, rather than naive array indexing, of course.
*/
char *workbegin, *workend, *search, *arrayend;
const adns_rr_srvha *rr;
*/
char *workbegin, *workend, *search, *arrayend;
const adns_rr_srvha *rr;
int cpriority, totalweight, runtotal;
long randval;
int cpriority, totalweight, runtotal;
long randval;
- for (workbegin= array, arrayend= workbegin + typei->rrsz * nrrs;
+ assert(rrsz <= sizeof(rrtmp));
+ for (workbegin= array, arrayend= workbegin + rrsz * nrrs;
workbegin < arrayend;
workbegin= workend) {
cpriority= (rr=(void*)workbegin)->priority;
for (workend= workbegin, totalweight= 0;
workend < arrayend && (rr=(void*)workend)->priority == cpriority;
workbegin < arrayend;
workbegin= workend) {
cpriority= (rr=(void*)workbegin)->priority;
for (workend= workbegin, totalweight= 0;
workend < arrayend && (rr=(void*)workend)->priority == cpriority;
- workend += typei->rrsz) {
totalweight += rr->weight;
}
totalweight += rr->weight;
}
* workbegin (swapping with the one that was there, and then
* advance workbegin. */
for (;
* workbegin (swapping with the one that was there, and then
* advance workbegin. */
for (;
- workbegin + typei->rrsz < workend; /* don't bother if just one */
- workbegin += typei->rrsz) {
+ workbegin + rrsz < workend; /* don't bother if just one */
+ workbegin += rrsz) {
randval= nrand48(ads->rand48xsubi);
randval %= (totalweight + 1);
randval= nrand48(ads->rand48xsubi);
randval %= (totalweight + 1);
for (search=workbegin, runtotal=0;
(runtotal += (rr=(void*)search)->weight) < randval;
for (search=workbegin, runtotal=0;
(runtotal += (rr=(void*)search)->weight) < randval;
- search += typei->rrsz);
assert(search < arrayend);
totalweight -= rr->weight;
if (search != workbegin) {
assert(search < arrayend);
totalweight -= rr->weight;
if (search != workbegin) {
- memcpy(&rrtmp, workbegin, typei->rrsz);
- memcpy(workbegin, search, typei->rrsz);
- memcpy(search, &rrtmp, typei->rrsz);
+ memcpy(&rrtmp, workbegin, rrsz);
+ memcpy(workbegin, search, rrsz);
+ memcpy(search, &rrtmp, rrsz);
#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...) \
{ adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_##memb, \
GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer, \
#define DEEP_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...) \
{ adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_##memb, \
GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer, \
- adns__ckl_hostname, CDR(__VA_ARGS__) }
+ adns__ckl_hostname, 0, adns__getrrsz_default, CDR(__VA_ARGS__) }
#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...) \
{ adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_flat, \
GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer, \
#define FLAT_TYPE(code,rrt,fmt,memb,parser,comparer,/*printer*/...) \
{ adns_r_##code&adns_rrt_reprmask, rrt,fmt,TYPESZ_M(memb), mf_flat, \
GLUE(cs_, CAR(__VA_ARGS__)),pa_##parser,di_##comparer, \
- adns__ckl_hostname, CDR(__VA_ARGS__) }
+ adns__ckl_hostname, 0, adns__getrrsz_default, CDR(__VA_ARGS__) }