const dname_type * dname_replace(region_type* region, const dname_type* name, const dname_type* src, const dname_type* dest) { /* nomenclature: name is said to be <x>.<src>. x can be null. */ dname_type* res; int x_labels = name->label_count - src->label_count; int x_len = name->name_size - src->name_size; int i; assert(dname_is_subdomain(name, src)); /* check if final size is acceptable */ if(x_len+dest->name_size > MAXDOMAINLEN) return NULL; res = (dname_type*)region_alloc(region, sizeof(dname_type) + (x_labels+dest->label_count + x_len+dest->name_size) *sizeof(uint8_t)); res->name_size = x_len+dest->name_size; res->label_count = x_labels+dest->label_count; for(i=0; i<dest->label_count; i++) ((uint8_t*)dname_label_offsets(res))[i] = dname_label_offsets(dest)[i] + x_len; for(i=dest->label_count; i<res->label_count; i++) ((uint8_t*)dname_label_offsets(res))[i] = dname_label_offsets(name)[i - dest->label_count + src->label_count]; memcpy((uint8_t*)dname_name(res), dname_name(name), x_len); memcpy((uint8_t*)dname_name(res)+x_len, dname_name(dest), dest->name_size); assert(dname_is_subdomain(res, dest)); return res; }
/** * Make wildcard synthesis. * */ int dname_make_wildcard(struct region *region, struct dname const *dname, struct dname const **wildcard) { uint8_t name_size; uint8_t label_count; uint8_t *names; uint8_t *labels; struct dname *new_dname; unsigned int i; /* * Checks: * dname label_count + 1 < MAXLABELS * dname size + 2 < MAXDOMAINLEN */ if (dname->label_count > (MAXLABELS - 1)) { return EINVAL; } if (dname->name_size > (MAXDOMAINLEN - 2)) { return EINVAL; } label_count = dname->label_count + 1; name_size = dname->name_size + 2; new_dname = (struct dname *) region_alloc(region, sizeof(dname_type) + (label_count * sizeof(uint8_t)) + (name_size * sizeof(uint8_t))); if (new_dname == NULL) { return ENOMEM; } new_dname->label_count = label_count; new_dname->name_size = name_size; labels = (uint8_t *) dname_label_offsets(new_dname); memcpy(labels, dname_label_offsets(dname), dname->label_count * sizeof(uint8_t)); for (i = 0; i < dname->label_count; i++) { labels[i] += 2; } labels[i] = 0; names = (uint8_t *) dname_name(new_dname); *names++ = '\001'; *names++ = '*'; memcpy(names, dname_name(dname), dname->name_size * sizeof(uint8_t)); *wildcard = new_dname; return 0; }
/** * Create new domain name. * */ dname_type* dname_create(region_type* r, const char* str) { uint8_t wire[DNAME_MAXLEN]; uint8_t label_offsets[DNAME_MAXLEN]; uint8_t label_count = 0; size_t size = 0; const uint8_t* label = wire; dname_type *dname; ssize_t i; assert(r); assert(str); if (!dname_str2wire(wire, str)) { fprintf(stderr, "[%s] error: parse dname %s failed", logstr, str); return NULL; } while (1) { if (label_is_pointer(label)) { return NULL; } label_offsets[label_count] = (uint8_t) (label - wire); ++label_count; size += label_length(label) + 1; if (label_is_root(label)) { break; } label = label_next(label); } if (size > DNAME_MAXLEN) { return NULL; } assert(label_count <= DNAME_MAXLEN / 2 + 1); /* reverse label offsets. */ /* reverse label offsets. */ for (i = 0; i < label_count / 2; ++i) { uint8_t tmp = label_offsets[i]; label_offsets[i] = label_offsets[label_count - i - 1]; label_offsets[label_count - i - 1] = tmp; } dname = (dname_type *) region_alloc(r, (sizeof(dname_type) + (label_count + size) * sizeof(uint8_t))); dname->size = size; dname->label_count = label_count; memcpy((uint8_t *) dname_label_offsets(dname), label_offsets, label_count * sizeof(uint8_t)); memcpy((uint8_t *) dname_name(dname), wire, size * sizeof(uint8_t)); return dname; }
const dname_type * dname_make(region_type *region, const uint8_t *name, int normalize) { size_t name_size = 0; uint8_t label_offsets[MAXDOMAINLEN]; uint8_t label_count = 0; const uint8_t *label = name; dname_type *result; ssize_t i; assert(name); while (1) { if (label_is_pointer(label)) return NULL; label_offsets[label_count] = (uint8_t) (label - name); ++label_count; name_size += label_length(label) + 1; if (label_is_root(label)) break; label = label_next(label); } if (name_size > MAXDOMAINLEN) return NULL; assert(label_count <= MAXDOMAINLEN / 2 + 1); /* Reverse label offsets. */ for (i = 0; i < label_count / 2; ++i) { uint8_t tmp = label_offsets[i]; label_offsets[i] = label_offsets[label_count - i - 1]; label_offsets[label_count - i - 1] = tmp; } result = (dname_type *) region_alloc( region, (sizeof(dname_type) + (label_count + name_size) * sizeof(uint8_t))); result->name_size = name_size; result->label_count = label_count; memcpy((uint8_t *) dname_label_offsets(result), label_offsets, label_count * sizeof(uint8_t)); if (normalize) { uint8_t *dst = (uint8_t *) dname_name(result); const uint8_t *src = name; while (!label_is_root(src)) { ssize_t len = label_length(src); *dst++ = *src++; for (i = 0; i < len; ++i) { *dst++ = DNAME_NORMALIZE(*src++); } } *dst = *src; } else { memcpy((uint8_t *) dname_name(result), name, name_size * sizeof(uint8_t)); } return result; }