static int str_label( const knot_dname_t *zone, char *buff, size_t buff_len, uint8_t right_index) { int labels = knot_dname_labels(zone, NULL); // Check for root label of the root zone. if (labels == 0 && right_index == 0) { return str_zone(zone, buff, buff_len); // Check for labels error or for an exceeded index. } else if (labels < 1 || labels <= right_index) { buff[0] = '\0'; return KNOT_EOK; } // ~ Label length + label + root label. knot_dname_t label[1 + KNOT_DNAME_MAXLABELLEN + 1]; // Compute the index from the left. assert(labels > right_index); uint8_t index = labels - right_index - 1; // Create a dname from the single label. int prefix = (index > 0) ? knot_dname_prefixlen(zone, index, NULL) : 0; uint8_t label_len = *(zone + prefix); memcpy(label, zone + prefix, 1 + label_len); label[1 + label_len] = '\0'; return str_zone(label, buff, buff_len); }
/*----------------------------------------------------------------------------*/ _public_ knot_dname_t *knot_dname_replace_suffix(const knot_dname_t *name, unsigned labels, const knot_dname_t *suffix) { if (name == NULL) return NULL; /* Calculate prefix and suffix lengths. */ int dname_lbs = knot_dname_labels(name, NULL); assert(dname_lbs >= labels); unsigned prefix_lbs = dname_lbs - labels; /* Trim 1 octet from prefix, as it is measured as FQDN. */ int prefix_len = knot_dname_prefixlen(name, prefix_lbs, NULL) - 1; int suffix_len = knot_dname_size(suffix); if (prefix_len < 0 || suffix_len < 0) return NULL; /* Create target name. */ int new_len = prefix_len + suffix_len; knot_dname_t *out = malloc(new_len); if (out == NULL) return NULL; /* Copy prefix. */ uint8_t *dst = out; while (prefix_lbs > 0) { memcpy(dst, name, *name + 1); dst += *name + 1; name = knot_wire_next_label(name, NULL); --prefix_lbs; } /* Copy suffix. */ while (*suffix != '\0') { memcpy(dst, suffix, *suffix + 1); dst += *suffix + 1; suffix = knot_wire_next_label(suffix, NULL); } *dst = '\0'; return out; }
/*----------------------------------------------------------------------------*/ _public_ int knot_dname_realsize(const knot_dname_t *name, const uint8_t *pkt) { return knot_dname_prefixlen(name, KNOT_DNAME_MAXLABELS, pkt); }