From: Andreas Gustafsson Date: Mon, 11 Dec 2000 21:17:09 +0000 (+0000) Subject: pullup: X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16c708dbbbae5828ac8ff12d5d4eaa7e07d2b23c;p=thirdparty%2Fbind9.git pullup: Cope with the possibility that the prefix of a name split within a bitstring label might have been compacted to have fewer labels than what was expected --- diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 070c6551f38..6c938bfc9a5 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: rbt.c,v 1.83.2.1 2000/07/10 23:54:33 gson Exp $ */ +/* $Id: rbt.c,v 1.83.2.2 2000/12/11 21:17:09 gson Exp $ */ /* Principal Authors: DCL */ @@ -560,40 +560,70 @@ dns_rbt_addnode(dns_rbt_t *rbt, dns_name_t *name, dns_rbtnode_t **nodep) { * end of the truncated name, and then * updating PADBYTES to reflect the truncation. * - * When bitstring labels are involved, things - * are just a tad more complicated (aren't - * they always?) because the splitting - * has shifted the bits that this name needs, - * as well as adjusted the bit count. - * So there are convolutions to deal with it. - * There are compromises here between - * abstraction and efficiency. - */ + * When bitstring labels are involved, things + * are just a tad more complicated (aren't + * they always?) because the splitting + * has shifted the bits that this name needs + * from the end of the label they were in + * to either the beginning of the label or + * even to the previous (lesser significance) + * label if the split was done in a maximally + * sized bitstring label. The bit count has + * been adjusted too, so there are convolutions + * to deal with all the bit movement. Yay, + * I *love* bit labels. Grumble grumble. + */ + if (common_bits > 0) { + unsigned char *p; + unsigned int skip_width; + unsigned int start_label = + FAST_COUNTLABELS(¤t_name) + - common_labels; + + /* + * If it is not the first label which + * was split, also copy the label + * before it -- which will essentially + * be a NO-OP unless the preceding + * label is a bitstring and the split + * label was 256 bits. Testing for + * that case is probably roughly + * as expensive as just unconditionally + * copying the preceding label. + */ + if (start_label > 0) + start_label--; - if (common_bits > 0) { - dns_label_t label; + skip_width = + prefix->offsets[start_label]; - dns_name_getlabel(prefix, - FAST_COUNTLABELS(¤t_name) - - common_labels, - &label); + memcpy(NAME(current) + skip_width, + prefix->ndata + skip_width, + prefix->length - skip_width); - INSIST(dns_label_type(&label) == - dns_labeltype_bitstring); + /* + * Now add_bits is set to the total + * number of bits in the split label of + * the name being added, and used later + * to determine if the job was + * completed by pushing the + * not-in-common bits down one level. + */ + start_label = + FAST_COUNTLABELS(add_name) + - common_labels; - memcpy(NAME(current) + - (label.base - prefix->ndata), - label.base, - label.length); + p = add_name->ndata + + add_name->offsets[start_label]; + INSIST(*p == DNS_LABELTYPE_BITSTRING); - dns_name_getlabel(add_name, - FAST_COUNTLABELS(add_name) - - common_labels, - &label); - INSIST(dns_label_type(&label) == - dns_labeltype_bitstring); + add_bits = *(p + 1); - add_bits = dns_label_countbits(&label); + /* + * A bitstring that was split would not + * result in a part of maximal length. + */ + INSIST(add_bits != 0); } else add_bits = 0;