📄 name.c
字号:
} count = tailbits / 8; if (tailbits % 8 != 0) count++; last = tail; while (count > 0) { *curr++ = *last++; count--; } last = name->ndata + name->length; while (head != last) *curr++ = *head++; name->length = (curr - name->ndata); /* * The offsets table may now be invalid. */ set_offsets(name, offsets, NULL); goto again; } } n--; }}isc_result_tdns_name_fromwire(dns_name_t *name, isc_buffer_t *source, dns_decompress_t *dctx, isc_boolean_t downcase, isc_buffer_t *target){ unsigned char *cdata, *ndata; unsigned int cused; /* Bytes of compressed name data used */ unsigned int hops, nused, labels, n, nmax; unsigned int current, new_current, biggest_pointer; isc_boolean_t saw_bitstring, done; fw_state state = fw_start; unsigned int c; unsigned char *offsets; dns_offsets_t odata; /* * Copy the possibly-compressed name at source into target, * decompressing it. */ REQUIRE(VALID_NAME(name)); REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || (target == NULL && ISC_BUFFER_VALID(name->buffer))); if (target == NULL && name->buffer != NULL) { target = name->buffer; isc_buffer_clear(target); } REQUIRE(dctx != NULL); REQUIRE(BINDABLE(name)); INIT_OFFSETS(name, offsets, odata); /* * Make 'name' empty in case of failure. */ MAKE_EMPTY(name); /* * Initialize things to make the compiler happy; they're not required. */ n = 0; new_current = 0; /* * Set up. */ labels = 0; hops = 0; saw_bitstring = ISC_FALSE; done = ISC_FALSE; ndata = isc_buffer_used(target); nused = 0; /* * Find the maximum number of uncompressed target name * bytes we are willing to generate. This is the smaller * of the available target buffer length and the * maximum legal domain name length (255). */ nmax = isc_buffer_availablelength(target); if (nmax > DNS_NAME_MAXWIRE) nmax = DNS_NAME_MAXWIRE; cdata = isc_buffer_current(source); cused = 0; current = source->current; biggest_pointer = current; /* * Note: The following code is not optimized for speed, but * rather for correctness. Speed will be addressed in the future. */ while (current < source->active && !done) { c = *cdata++; current++; if (hops == 0) cused++; switch (state) { case fw_start: if (c < 64) { offsets[labels] = nused; labels++; if (nused + c + 1 > nmax) goto full; nused += c + 1; *ndata++ = c; if (c == 0) done = ISC_TRUE; n = c; state = fw_ordinary; } else if (c >= 128 && c < 192) { /* * 14 bit local compression pointer. * Local compression is no longer an * IETF draft. */ return (DNS_R_BADLABELTYPE); } else if (c >= 192) { /* * Ordinary 14-bit pointer. */ if ((dctx->allowed & DNS_COMPRESS_GLOBAL14) == 0) return (DNS_R_DISALLOWED); new_current = c & 0x3F; n = 1; state = fw_newcurrent; } else if (c == DNS_LABELTYPE_BITSTRING) { offsets[labels] = nused; labels++; if (nused == nmax) goto full; nused++; *ndata++ = c; saw_bitstring = ISC_TRUE; state = fw_bitstring; } else return (DNS_R_BADLABELTYPE); break; case fw_ordinary: if (downcase) c = maptolower[c]; /* FALLTHROUGH */ case fw_copy: *ndata++ = c; n--; if (n == 0) state = fw_start; break; case fw_bitstring: if (c == 0) n = 256 / 8; else n = c / 8; if ((c % 8) != 0) n++; if (nused + n + 1 > nmax) goto full; nused += n + 1; *ndata++ = c; state = fw_copy; break; case fw_newcurrent: new_current *= 256; new_current += c; n--; if (n != 0) break; if (new_current >= biggest_pointer) return (DNS_R_BADPOINTER); biggest_pointer = new_current; current = new_current; cdata = (unsigned char *)source->base + current; hops++; if (hops > DNS_POINTER_MAXHOPS) return (DNS_R_TOOMANYHOPS); state = fw_start; break; default: FATAL_ERROR(__FILE__, __LINE__, "Unknown state %d", state); /* Does not return. */ } } if (!done) return (ISC_R_UNEXPECTEDEND); name->ndata = (unsigned char *)target->base + target->used; name->labels = labels; name->length = nused; name->attributes |= DNS_NAMEATTR_ABSOLUTE; if (saw_bitstring) compact(name, offsets); isc_buffer_forward(source, cused); isc_buffer_add(target, name->length); return (ISC_R_SUCCESS); full: if (nmax == DNS_NAME_MAXWIRE) /* * The name did not fit even though we had a buffer * big enough to fit a maximum-length name. */ return (DNS_R_NAMETOOLONG); else /* * The name might fit if only the caller could give us a * big enough buffer. */ return (ISC_R_NOSPACE);}isc_result_tdns_name_towire(dns_name_t *name, dns_compress_t *cctx, isc_buffer_t *target) { unsigned int methods; isc_uint16_t offset; dns_name_t gp; /* Global compression prefix */ isc_boolean_t gf; /* Global compression target found */ isc_uint16_t go; /* Global compression offset */ dns_offsets_t clo; dns_name_t clname; /* * Convert 'name' into wire format, compressing it as specified by the * compression context 'cctx', and storing the result in 'target'. */ REQUIRE(VALID_NAME(name)); REQUIRE(cctx != NULL); REQUIRE(ISC_BUFFER_VALID(target)); /* * If 'name' doesn't have an offsets table, make a clone which * has one. */ if (name->offsets == NULL) { DNS_NAME_INIT(&clname, clo); dns_name_clone(name, &clname); name = &clname; } DNS_NAME_INIT(&gp, NULL); offset = target->used; /*XXX*/ methods = dns_compress_getmethods(cctx); if ((methods & DNS_COMPRESS_GLOBAL14) != 0) gf = dns_compress_findglobal(cctx, name, &gp, &go); else gf = ISC_FALSE; /* * If the offset is too high for 14 bit global compression, we're * out of luck. */ if (gf && go >= 0x4000) gf = ISC_FALSE; /* * Will the compression pointer reduce the message size? */ if (gf && (gp.length + 2) >= name->length) gf = ISC_FALSE; if (gf) { if (target->length - target->used < gp.length) return (ISC_R_NOSPACE); (void)memcpy((unsigned char *)target->base + target->used, gp.ndata, (size_t)gp.length); isc_buffer_add(target, gp.length); go |= 0xc000; if (target->length - target->used < 2) return (ISC_R_NOSPACE); isc_buffer_putuint16(target, go); if (gp.length != 0) dns_compress_add(cctx, name, &gp, offset); } else { if (target->length - target->used < name->length) return (ISC_R_NOSPACE); (void)memcpy((unsigned char *)target->base + target->used, name->ndata, (size_t)name->length); isc_buffer_add(target, name->length); dns_compress_add(cctx, name, name, offset); } return (ISC_R_SUCCESS);}isc_result_tdns_name_concatenate(dns_name_t *prefix, dns_name_t *suffix, dns_name_t *name, isc_buffer_t *target){ unsigned char *ndata, *offsets; unsigned int nrem, labels, prefix_length, length, offset; isc_boolean_t copy_prefix = ISC_TRUE; isc_boolean_t copy_suffix = ISC_TRUE; isc_boolean_t saw_bitstring = ISC_FALSE; isc_boolean_t absolute = ISC_FALSE; dns_name_t tmp_name; dns_offsets_t odata; /* * Concatenate 'prefix' and 'suffix'. */ REQUIRE(prefix == NULL || VALID_NAME(prefix)); REQUIRE(suffix == NULL || VALID_NAME(suffix)); REQUIRE(name == NULL || VALID_NAME(name)); REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) || (target == NULL && name != NULL && ISC_BUFFER_VALID(name->buffer))); if (prefix == NULL || prefix->labels == 0) copy_prefix = ISC_FALSE; if (suffix == NULL || suffix->labels == 0) copy_suffix = ISC_FALSE; if (copy_prefix && (prefix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) { absolute = ISC_TRUE; REQUIRE(!copy_suffix); } if (name == NULL) { DNS_NAME_INIT(&tmp_name, odata); name = &tmp_name; } if (target == NULL) { INSIST(name->buffer != NULL); target = name->buffer; isc_buffer_clear(name->buffer); } REQUIRE(BINDABLE(name)); /* * XXX IMPORTANT NOTE * * If the most-signficant label in prefix is a bitstring, * and the least-signficant label in suffix is a bitstring, * it's possible that compaction could convert them into * one label. If this happens, then the final size will * be three bytes less than nrem. * * We do not check for this special case, and handling it is * a little messy; we can't just concatenate and compact, * because we may only have 255 bytes but might need 258 bytes * temporarily. There are ways to do this with only 255 bytes, * which will be implemented later. * * For now, we simply reject these few cases as being too * long. */ /* * Set up. */ nrem = target->length - target->used; ndata = (unsigned char *)target->base + target->used; if (nrem > DNS_NAME_MAXWIRE) nrem = DNS_NAME_MAXWIRE; length = 0; prefix_length = 0; labels = 0; if (copy_prefix) { prefix_length = prefix->length; length += prefix_length; labels += prefix->labels; } if (copy_suffix) { length += suffix->length; labels += suffix->labels; } if (length > DNS_NAME_MAXWIRE) { MAKE_EMPTY(name); return (DNS_R_NAMETOOLONG); } if (length > nrem) { MAKE_EMPTY(name); return (ISC_R_NOSPACE); } if (copy_suffix) { if ((suffix->attributes & DNS_NAMEATTR_ABSOLUTE) != 0) absolute = ISC_TRUE; if (copy_prefix && suffix->ndata[0] == DNS_LABELTYPE_BITSTRING) { /* * We only need to call compact() if both the * least-significant label of the suffix and the * most-significant label of the prefix are both * bitstrings. * * A further possible optimization, which we don't do, * is to not compact() if the suffix bitstring is * full. It will usually not be full, so I don't * think this is worth it. */ if (prefix->offsets != NULL) { offset = prefix->offsets[prefix->labels - 1]; if (prefix->ndata[offset] == DNS_LABELTYPE_BITSTRING) saw_bitstring = ISC_TRUE; } else { /* * We don't have an offsets table for prefix, * and rather than spend the effort to make it * we'll just compact(), which doesn't cost * more than computing the offsets table if * there is no bitstring in prefix. */ saw_bitstring = ISC_TRUE; } } if (suffix == name && suffix->buffer == target) memmove(ndata + prefix_length, suffix->ndata, suffix->length); else memcpy(ndata + prefix_length, suffix->ndata, suffix->length); } /* * If 'prefix' and 'name' are the same object, and the object has * a dedicated buffer, and we're using it, then we don't have to * copy anything. */ if (copy_prefix && (prefix != name || prefix->buffer != target)) memcpy(ndata, prefix->ndata, prefix_length); name->ndata = ndata; name->labels = labels; name->length = length; if (absolute) name->attributes = DNS_NAMEATTR_ABSOLUTE; else name->attributes = 0; if (name->labels > 0 && (name->offsets != NULL || saw_bitstring)) { INIT_OFFSETS(name, offsets, odata); set_offsets(name, offsets, NULL); if (saw_bitstring) compact(name, offsets); } isc_buffer_add(target, name->length); return (ISC_R_SUCCESS);}isc_result_tdns_name_split(dns_name_t *name, unsigned int suffixlabels, unsigned int nbits, dns_name_t *prefix, dns_name_t *suffix){ dns_offsets_t name_odata, prefix_odata, suffix_odata; unsigned char *offsets, *prefix_offsets = NULL, *suffix_offsets; isc_result_t result = ISC_R_SUCCESS; unsigned int splitlabel, bitbytes, mod, len; unsigned char *p, *src, *dst; isc_boolean_t maybe_compact_prefix = ISC_FALSE; REQUIRE(VALID_NAME(name)); REQUIRE(suffixlabels > 0); REQUIRE((nbits == 0 && suffixlabels < name->labels) || (nbits != 0 && suffixlabels <= name->labels)); REQUIRE(prefix != NULL || suffix != NULL); REQUIRE(prefix == NULL || (VALID_NAME(prefix) && prefix->buffer != NULL && BINDABLE(prefix))); REQUIRE(suffix == NULL || (VALID_NAME(suffix) && suffix->buffer != NULL && BINDABLE(suffix))); /* * When splitting bitstring labels, if prefix and suffix have the same * buffer, suffix will overwrite the ndata of prefix, corrupting it. * If prefix has the ndata of name, then it modifies the bitstring * label and suffix doesn't have the original available. This latter * problem could be worked around if it is ever deemed desirable. */ REQUIRE(nbits == 0 || prefix == NULL || suffix == NULL || (prefix->buffer->base != suffix->buffer->base && prefix->buffer->base != name->ndata)); SETUP_OFFSETS(name, offsets, name_odata); splitlabel = name->labels - suffixlabels; /* * Make p point at the count byte of the bitstring label, * if there is one (p will not be used if we are not * splitting bits). */ p = &name->ndata[offsets[splitlabel] + 1]; /* * When a bit count is specified, ensure that the label is a bitstring * label and it has more bits than the requested slice. */ REQUIRE(nbits == 0 || (*(p - 1) == DNS_LABELTYPE_BITSTRING && nbits < 256 && (*p == 0 || *p > nbits))); mod = nbits % 8; if (prefix != NULL) { if (nbits > 0) { isc_buffer_clear(prefix->buffer); /* * '2' is for the DNS_LABELTYPE_BITSTRING id * plus the existing number of bits byte. */ len = offsets[splitlabel] + 2; src = name->ndata; dst = prefix->buffer->base; if (src != dst) { /* * If these are overlapping names ... * wow. How bizarre could that be? */ INSIST(! (src <= dst && src + len > dst) || (dst <= src && dst + len > src)); memcpy(dst, src, len); p = dst + len - 1; } /* * Set the new bit count. Also, when a bitstring * label being split is maximal length, compaction * might be necessary on the prefix. */ if (*p == 0) { maybe_compact_prefix = ISC_TRUE; *p = 256 - nbits; } else *p = *p - nbits; /* * Calculate the number of bytes necessary to hold * all of the bits left in the prefix. */ bitbytes = (*p - 1) / 8 + 1; prefix->length = len + bitbytes; if (prefix->length > prefix->buffer->length ) { dns_name_invalidate(prefix); return (ISC_R_NOSPACE); } /* * All of the bits now need to be shifted to the left * to fill in the space taken by the removed bit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -