Commit 126519dd authored by Daniel Salzman's avatar Daniel Salzman

Use wire context where appropriate

parent a85c0355
......@@ -19,6 +19,7 @@
#include "dnssec/nsec.h"
#include "libknot/internal/base32hex.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/wire_ctx.h"
#include "knot/dnssec/nsec3-chain.h"
#include "libknot/dname.h"
#include "libknot/packet/wire.h"
......@@ -29,17 +30,6 @@
#include "knot/dnssec/zone-sign.h"
#include "knot/dnssec/zone-nsec.h"
/* - Forward declarations --------------------------------------------------- */
static int create_nsec3_rrset(knot_rrset_t *rrset,
knot_dname_t *dname,
const knot_nsec3_params_t *,
const dnssec_nsec_bitmap_t *,
const uint8_t *,
uint32_t);
/* - Helper functions ------------------------------------------------------- */
/* - NSEC3 node comparison -------------------------------------------------- */
/*!
......@@ -208,9 +198,10 @@ static size_t nsec3_rdata_size(const knot_nsec3_params_t *params,
*
* \note Content of next hash field is not changed.
*/
static void nsec3_fill_rdata(uint8_t *rdata, const knot_nsec3_params_t *params,
const dnssec_nsec_bitmap_t *rr_types,
const uint8_t *next_hashed, uint32_t ttl)
static int nsec3_fill_rdata(uint8_t *rdata, size_t rdata_len,
const knot_nsec3_params_t *params,
const dnssec_nsec_bitmap_t *rr_types,
const uint8_t *next_hashed)
{
assert(rdata);
assert(params);
......@@ -218,24 +209,28 @@ static void nsec3_fill_rdata(uint8_t *rdata, const knot_nsec3_params_t *params,
uint8_t hash_length = dnssec_nsec3_hash_length(params->algorithm);
*rdata = params->algorithm; // hash algorithm
rdata += 1;
*rdata = 0; // flags
rdata += 1;
wire_write_u16(rdata, params->iterations); // iterations
rdata += 2;
*rdata = params->salt_length; // salt length
rdata += 1;
memcpy(rdata, params->salt, params->salt_length); // salt
rdata += params->salt_length;
*rdata = hash_length; // hash length
rdata += 1;
/*memset(rdata, '\0', hash_len);*/ // hash (unknown)
if (next_hashed) {
memcpy(rdata, next_hashed, hash_length);
wire_ctx_t wire = wire_ctx_init(rdata, rdata_len);
wire_ctx_write_u8(&wire, params->algorithm); // hash algorithm
wire_ctx_write_u8(&wire, 0); // flags
wire_ctx_write_u16(&wire, params->iterations); // itertions
wire_ctx_write_u8(&wire, params->salt_length); // salt length
wire_ctx_write(&wire, params->salt, params->salt_length); // salt
wire_ctx_write_u8(&wire, hash_length); // hash length
if (next_hashed != NULL) {
wire_ctx_write(&wire, next_hashed, hash_length); // hash
} else {
wire_ctx_skip(&wire, hash_length);
}
rdata += hash_length;
dnssec_nsec_bitmap_write(rr_types, rdata); // RR types bit map
if (wire.error != KNOT_EOK) {
return wire.error;
}
dnssec_nsec_bitmap_write(rr_types, wire.position); // RR types bit map
return KNOT_EOK;
}
/*!
......@@ -265,7 +260,11 @@ static int create_nsec3_rrset(knot_rrset_t *rrset,
size_t rdata_size = nsec3_rdata_size(params, rr_types);
uint8_t rdata[rdata_size];
nsec3_fill_rdata(rdata, params, rr_types, next_hashed, ttl);
int ret = nsec3_fill_rdata(rdata, rdata_size, params, rr_types,
next_hashed);
if (ret != KNOT_EOK) {
return ret;
}
return knot_rrset_add_rdata(rrset, rdata, rdata_size, ttl, NULL);
}
......
......@@ -31,6 +31,7 @@
#include "libknot/rrset.h"
#include "libknot/rrtype/rrsig.h"
#include "libknot/packet/rrset-wire.h"
#include "libknot/internal/wire_ctx.h"
#define RRSIG_RDATA_SIGNER_OFFSET 18
......@@ -73,6 +74,7 @@ static size_t rrsig_rdata_header_size(const dnssec_key_t *key)
*
* \note This can be also used for SIG(0) if proper parameters are supplied.
*
* \param rdata_len Length of RDATA.
* \param rdata Pointer to RDATA.
* \param key Key used for signing.
* \param covered_type Type of the covered RR.
......@@ -80,10 +82,11 @@ static size_t rrsig_rdata_header_size(const dnssec_key_t *key)
* \param sig_incepted Timestamp of signature inception.
* \param sig_expires Timestamp of signature expiration.
*/
static int rrsig_write_rdata(uint8_t *rdata, const dnssec_key_t *key,
uint16_t covered_type, uint8_t owner_labels,
uint32_t owner_ttl, uint32_t sig_incepted,
uint32_t sig_expires)
static int rrsig_write_rdata(uint8_t *rdata, size_t rdata_len,
const dnssec_key_t *key,
uint16_t covered_type, uint8_t owner_labels,
uint32_t owner_ttl, uint32_t sig_incepted,
uint32_t sig_expires)
{
if (!rdata || !key || sig_incepted >= sig_expires) {
return KNOT_EINVAL;
......@@ -92,29 +95,21 @@ static int rrsig_write_rdata(uint8_t *rdata, const dnssec_key_t *key,
uint8_t algorithm = dnssec_key_get_algorithm(key);
uint16_t keytag = dnssec_key_get_keytag(key);
const uint8_t *signer = dnssec_key_get_dname(key);
uint8_t *w = rdata;
wire_write_u16(w, covered_type); // type covered
w += sizeof(uint16_t);
*w = algorithm; // algorithm
w += sizeof(uint8_t);
*w = owner_labels; // labels
w += sizeof(uint8_t);
wire_write_u32(w, owner_ttl); // original TTL
w += sizeof(uint32_t);
wire_write_u32(w, sig_expires); // signature expiration
w += sizeof(uint32_t);
wire_write_u32(w, sig_incepted); // signature inception
w += sizeof(uint32_t);
wire_write_u16(w, keytag); // key fingerprint
w += sizeof(uint16_t);
assert(w == rdata + RRSIG_RDATA_SIGNER_OFFSET);
assert(signer);
memcpy(w, signer, knot_dname_size(signer)); // signer
return KNOT_EOK;
wire_ctx_t wire = wire_ctx_init(rdata, rdata_len);
wire_ctx_write_u16(&wire, covered_type); // type covered
wire_ctx_write_u8(&wire, algorithm); // algorithm
wire_ctx_write_u8(&wire, owner_labels); // labels
wire_ctx_write_u32(&wire, owner_ttl); // original TTL
wire_ctx_write_u32(&wire, sig_expires); // signature expiration
wire_ctx_write_u32(&wire, sig_incepted); // signature inception
wire_ctx_write_u16(&wire, keytag); // key fingerprint
assert(wire_ctx_offset(&wire) == RRSIG_RDATA_SIGNER_OFFSET);
wire_ctx_write(&wire, signer, knot_dname_size(signer)); // signer
return wire.error;
}
/*- Computation of signatures ------------------------------------------------*/
......@@ -251,7 +246,8 @@ static int rrsigs_create_rdata(knot_rrset_t *rrsigs, dnssec_sign_ctx_t *ctx,
uint8_t header[header_size];
const knot_rdata_t *covered_data = knot_rdataset_at(&covered->rrs, 0);
int res = rrsig_write_rdata(header, key, covered->type, owner_labels,
int res = rrsig_write_rdata(header, header_size,
key, covered->type, owner_labels,
knot_rdata_ttl(covered_data),
sig_incepted, sig_expires);
assert(res == KNOT_EOK);
......
......@@ -18,6 +18,7 @@
#include "libknot/internal/namedb/namedb.h"
#include "libknot/internal/namedb/namedb_lmdb.h"
#include "libknot/internal/mem.h"
#include "libknot/internal/wire_ctx.h"
#include "knot/zone/timers.h"
#include "knot/zone/zonedb.h"
......@@ -70,19 +71,23 @@ static int store_timers(namedb_txn_t *txn, zone_t *zone)
// Create value
uint8_t packed_timer[EVENT_KEY_PAIR_SIZE * PERSISTENT_EVENT_COUNT];
size_t offset = 0;
wire_ctx_t w = wire_ctx_init(packed_timer, sizeof(packed_timer));
for (zone_event_type_t event = 0; event < ZONE_EVENT_COUNT; ++event) {
if (!event_persistent(event)) {
continue;
}
// Write event key and timer to buffer
packed_timer[offset] = event_id_to_key[event];
offset += 1;
wire_write_u64(packed_timer + offset,
(int64_t)zone_events_get_time(zone, event));
offset += sizeof(uint64_t);
wire_ctx_write_u8(&w, event_id_to_key[event]);
wire_ctx_write_u64(&w, zone_events_get_time(zone, event));
}
if (w.error != KNOT_EOK) {
return w.error;
}
namedb_val_t val = { .len = sizeof(packed_timer), .data = packed_timer };
// Store
......
......@@ -26,6 +26,7 @@
#include "libknot/packet/wire.h"
#include "libknot/packet/rrset-wire.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/wire_ctx.h"
/*! \brief Packet RR array growth step. */
#define NEXT_RR_ALIGN 16
......@@ -483,27 +484,28 @@ int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t q
assert(pkt->rrset_count == 0);
/* Copy name wireformat. */
uint8_t *dst = pkt->wire + KNOT_WIRE_HEADER_SIZE;
int qname_len = knot_dname_to_wire(dst, qname, pkt->max_size - pkt->size);
wire_ctx_t wire = wire_ctx_init(pkt->wire, pkt->max_size);
wire_ctx_set_offset(&wire, KNOT_WIRE_HEADER_SIZE);
int qname_len = knot_dname_to_wire(wire.position,
qname, wire_ctx_available(&wire));
if (qname_len < 0) {
return qname_len;
}
/* Check size limits. */
size_t question_len = 2 * sizeof(uint16_t) + qname_len;
if (qname_len < 0 || pkt->size + question_len > pkt->max_size) {
return KNOT_ESPACE;
}
wire_ctx_skip(&wire, qname_len);
/* Copy QTYPE & QCLASS */
dst += qname_len;
wire_write_u16(dst, qtype);
dst += sizeof(uint16_t);
wire_write_u16(dst, qclass);
wire_ctx_write_u16(&wire, qtype);
wire_ctx_write_u16(&wire, qclass);
/* Check errors. */
if (wire.error != KNOT_EOK) {
return wire.error;
}
/* Update question count and sizes. */
knot_wire_set_qdcount(pkt->wire, 1);
pkt->size += question_len;
pkt->size = wire_ctx_offset(&wire);
pkt->qname_size = qname_len;
/* Start writing ANSWER. */
......
......@@ -30,6 +30,7 @@
#include "libknot/rrset.h"
#include "libknot/rrtype/naptr.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/wire_ctx.h"
#define RR_HEADER_SIZE 10
......@@ -333,34 +334,25 @@ static int write_fixed_header(const knot_rrset_t *rrset, uint16_t rrset_index,
assert(dst && *dst);
assert(dst_avail);
/* Check capacity */
size_t size = sizeof(uint16_t) // type
+ sizeof(uint16_t) // class
+ sizeof(uint32_t); // ttl
if (size > *dst_avail) {
return KNOT_ESPACE;
}
/* Write result */
uint32_t ttl = knot_rdata_ttl(knot_rdataset_at(&rrset->rrs, rrset_index));
uint8_t *write = *dst;
wire_write_u16(write, rrset->type);
write += sizeof(uint16_t);
wire_write_u16(write, rrset->rclass);
write += sizeof(uint16_t);
wire_write_u32(write, ttl);
write += sizeof(uint32_t);
wire_ctx_t write = wire_ctx_init(*dst, *dst_avail);
assert(write == *dst + size);
wire_ctx_write_u16(&write, rrset->type);
wire_ctx_write_u16(&write, rrset->rclass);
wire_ctx_write_u32(&write, ttl);
/* Check write */
if (write.error != KNOT_EOK) {
return write.error;
}
/* Update buffer */
*dst = write;
*dst_avail -= size;
*dst = write.position;
*dst_avail = wire_ctx_available(&write);
return KNOT_EOK;
}
......@@ -544,16 +536,22 @@ static int parse_header(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
return KNOT_EMALF;
}
uint16_t type = wire_read_u16(pkt_wire + *pos);
*pos += sizeof(uint16_t);
uint16_t rclass = wire_read_u16(pkt_wire + *pos);
*pos += sizeof(uint16_t);
*ttl = wire_read_u32(pkt_wire + *pos);
*pos += sizeof(uint32_t);
*rdlen = wire_read_u16(pkt_wire + *pos);
*pos += sizeof(uint16_t);
wire_ctx_t wire = wire_ctx_init_const(pkt_wire, pkt_size);
wire_ctx_set_offset(&wire, *pos);
uint16_t type = wire_ctx_read_u16(&wire);
uint16_t rclass = wire_ctx_read_u16(&wire);
*ttl = wire_ctx_read_u32(&wire);
*rdlen = wire_ctx_read_u16(&wire);
*pos = wire_ctx_offset(&wire);
if (wire.error != KNOT_EOK) {
knot_dname_free(&owner, mm);
return wire.error;
}
if (pkt_size - *pos < *rdlen) {
if (wire_ctx_available(&wire) < *rdlen) {
knot_dname_free(&owner, mm);
return KNOT_EMALF;
}
......@@ -644,7 +642,7 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
if (buffer_size < 0) {
return buffer_size;
}
if (buffer_size > MAX_RDLENGTH) {
/* DNAME compression caused RDATA overflow. */
return KNOT_EMALF;
......@@ -680,7 +678,7 @@ static int parse_rdata(const uint8_t *pkt_wire, size_t *pos, size_t pkt_size,
knot_rdataset_unreserve(rrs, mm);
return ret;
}
/* Update position pointer. */
*pos += rdlength;
......
......@@ -35,6 +35,7 @@
#include "libknot/internal/base32hex.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/utils.h"
#include "libknot/internal/wire_ctx.h"
#define TAB_WIDTH 8
#define BLOCK_WIDTH 40
......@@ -931,30 +932,24 @@ static void wire_apl_to_str(rrset_dump_params_t *p)
static void wire_loc_to_str(rrset_dump_params_t *p)
{
int ret;
size_t in_len = 16;
// Check input size (1 LOC = 16 B).
if (in_len > p->in_max) {
// Read values.
wire_ctx_t wire = wire_ctx_init_const(p->in, p->in_max);
uint8_t version = wire_ctx_read_u8(&wire);
uint8_t size_w = wire_ctx_read_u8(&wire);
uint8_t hpre_w = wire_ctx_read_u8(&wire);
uint8_t vpre_w = wire_ctx_read_u8(&wire);
uint32_t lat_w = wire_ctx_read_u32(&wire);
uint32_t lon_w = wire_ctx_read_u32(&wire);
uint32_t alt_w = wire_ctx_read_u32(&wire);
// Check if all reads are correct.
if (wire.error != KNOT_EOK) {
return;
}
// Read values.
uint8_t version = *p->in;
p->in++;
uint8_t size_w = *p->in;
p->in++;
uint8_t hpre_w = *p->in;
p->in++;
uint8_t vpre_w = *p->in;
p->in++;
uint32_t lat_w = wire_read_u32(p->in);
p->in += 4;
uint32_t lon_w = wire_read_u32(p->in);
p->in += 4;
uint32_t alt_w = wire_read_u32(p->in);
p->in += 4;
p->in_max -= in_len;
p->in += wire_ctx_offset(&wire);
p->in_max = wire_ctx_available(&wire);
// Version check.
if (version != 0) {
......
......@@ -24,6 +24,7 @@
#include "libknot/errcode.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/sockaddr.h"
#include "libknot/internal/wire_ctx.h"
/*! \brief Some implementation-related constants. */
enum knot_edns_private_consts {
......@@ -107,16 +108,12 @@ _public_
uint8_t knot_edns_get_ext_rcode(const knot_rrset_t *opt_rr)
{
assert(opt_rr != NULL);
uint32_t ttl = 0;
uint8_t *ttl_ptr = (uint8_t *)&ttl;
wire_ctx_t w = wire_ctx_init((uint8_t *) &ttl, sizeof(ttl));
// TTL is stored in machine byte order. Convert it to wire order first.
wire_write_u32(ttl_ptr, knot_rrset_ttl(opt_rr));
uint8_t rcode;
memcpy(&rcode, ttl_ptr + EDNS_OFFSET_RCODE, sizeof(uint8_t));
return rcode;
wire_ctx_write_u32(&w, knot_rrset_ttl(opt_rr));
wire_ctx_set_offset(&w, EDNS_OFFSET_RCODE);
return wire_ctx_read_u8(&w);
}
/*----------------------------------------------------------------------------*/
......@@ -124,14 +121,15 @@ uint8_t knot_edns_get_ext_rcode(const knot_rrset_t *opt_rr)
static void set_value_to_ttl(knot_rrset_t *opt_rr, size_t offset, uint8_t value)
{
uint32_t ttl = 0;
uint8_t *ttl_ptr = (uint8_t *)&ttl;
wire_ctx_t w = wire_ctx_init((uint8_t*) &ttl, sizeof(ttl));
// TTL is stored in machine byte order. Convert it to wire order first.
wire_write_u32(ttl_ptr, knot_rrset_ttl(opt_rr));
wire_ctx_write_u32(&w, knot_rrset_ttl(opt_rr));
// Set the Extended RCODE in the converted TTL
memcpy(ttl_ptr + offset, &value, sizeof(uint8_t));
wire_ctx_set_offset(&w, offset);
wire_ctx_write_u8(&w, value);
// Convert it back to machine byte order
uint32_t ttl_local = wire_read_u32(ttl_ptr);
wire_ctx_set_offset(&w, 0);
uint32_t ttl_local = wire_ctx_read_u32(&w);
// Store the TTL to the RDATA
knot_rdata_set_ttl(knot_rdataset_at(&opt_rr->rrs, 0), ttl_local);
}
......@@ -149,16 +147,12 @@ _public_
uint8_t knot_edns_get_version(const knot_rrset_t *opt_rr)
{
assert(opt_rr != NULL);
uint32_t ttl = 0;
uint8_t *ttl_ptr = (uint8_t *)&ttl;
wire_ctx_t w = wire_ctx_init((uint8_t*) &ttl, sizeof(ttl));
// TTL is stored in machine byte order. Convert it to wire order first.
wire_write_u32(ttl_ptr, knot_rrset_ttl(opt_rr));
uint8_t version;
memcpy(&version, ttl_ptr + EDNS_OFFSET_VERSION, sizeof(uint8_t));
return version;
wire_ctx_write_u32(&w, knot_rrset_ttl(opt_rr));
wire_ctx_set_offset(&w, EDNS_OFFSET_VERSION);
return wire_ctx_read_u8(&w);
}
/*----------------------------------------------------------------------------*/
......@@ -174,7 +168,6 @@ _public_
bool knot_edns_do(const knot_rrset_t *opt_rr)
{
assert(opt_rr != NULL);
return knot_rrset_ttl(opt_rr) & EDNS_DO_MASK;
}
......@@ -202,26 +195,23 @@ void knot_edns_set_do(knot_rrset_t *opt_rr)
*/
static uint8_t *find_option(knot_rdata_t *rdata, uint16_t opt_code)
{
assert(rdata != NULL);
wire_ctx_t wire = wire_ctx_init_rdata(rdata);
uint8_t *data = knot_rdata_data(rdata);
uint16_t rdlength = knot_rdata_rdlen(rdata);
uint8_t *pos = NULL;
int i = 0;
while (i + KNOT_EDNS_OPTION_HDRLEN <= rdlength) {
uint16_t code = wire_read_u16(data + i);
if (opt_code == code) {
pos = data + i;
while (wire_ctx_available(&wire) > 0) {
uint16_t code = wire_ctx_read_u16(&wire);
if (wire.error != KNOT_EOK) {
break;
}
uint16_t opt_len = wire_read_u16(data + i
+ sizeof(uint16_t));
i += (KNOT_EDNS_OPTION_HDRLEN + opt_len);
if (code == opt_code) {
return wire.position;
}
uint16_t opt_len = wire_ctx_read_u16(&wire);
wire_ctx_skip(&wire, opt_len);
}
return pos;
return NULL;
}
/*----------------------------------------------------------------------------*/
......@@ -247,12 +237,17 @@ int knot_edns_add_option(knot_rrset_t *opt_rr, uint16_t code,
uint8_t new_data[new_data_len];
memcpy(new_data, old_data, old_data_len);
wire_ctx_t wire = wire_ctx_init(new_data, new_data_len);
wire_ctx_write(&wire, old_data, old_data_len);
// write length and code in wireformat (convert endian)
wire_write_u16(new_data + old_data_len, code);
wire_write_u16(new_data + old_data_len + sizeof(uint16_t), length);
wire_ctx_write_u16(&wire, code);
wire_ctx_write_u16(&wire, length);
// write the option data
memcpy(new_data + old_data_len + KNOT_EDNS_OPTION_HDRLEN, data, length);
wire_ctx_write(&wire, data, length);
if (wire.error != KNOT_EOK) {
return wire.error;
}
/* 2) Replace the RDATA in the RRSet. */
uint32_t old_ttl = knot_rdata_ttl(old_rdata);
......@@ -295,21 +290,17 @@ bool knot_edns_check_record(knot_rrset_t *opt_rr)
return false;
}
uint8_t *data = knot_rdata_data(rdata);
uint16_t rdlength = knot_rdata_rdlen(rdata);
uint32_t pos = 0;
wire_ctx_t wire = wire_ctx_init_rdata(rdata);
/* RFC2671 4.4: {uint16_t code, uint16_t len, data} */
while (pos + KNOT_EDNS_OPTION_HDRLEN <= rdlength) {
uint16_t opt_len = wire_read_u16(data + pos
+ sizeof(uint16_t));
pos += KNOT_EDNS_OPTION_HDRLEN + opt_len;
// read data to the end or error
while (wire_ctx_available(&wire) > 0 && wire.error == KNOT_EOK) {
wire_ctx_read_u16(&wire); // code
uint16_t opt_len = wire_ctx_read_u16(&wire); // length
wire_ctx_skip(&wire, opt_len); // data
}
/* If not at the end of the RDATA, there are either some redundant data
* (pos < rdlength) or the last OPTION is too long (pos > rdlength).
*/
return pos == rdlength;
return wire.error == KNOT_EOK;
}
/*----------------------------------------------------------------------------*/
......@@ -329,27 +320,26 @@ int knot_edns_client_subnet_create(const knot_addr_family_t family,
uint8_t addr_prefix_len = (src_mask + 7) / 8; // Ceiling operation.
uint8_t modulo = src_mask % 8;
uint16_t total = sizeof(uint16_t) + 2 * sizeof(uint8_t) + addr_prefix_len;
if (*data_len < total) {
return KNOT_ESPACE;
}
if (addr_prefix_len > addr_len) {
return KNOT_EINVAL;
}
wire_write_u16(data + EDNS_OFFSET_CLIENT_SUBNET_FAMILY, family);
data[EDNS_OFFSET_CLIENT_SUBNET_SRC_MASK] = src_mask;
data[EDNS_OFFSET_CLIENT_SUBNET_DST_MASK] = dst_mask;
memcpy(data + EDNS_OFFSET_CLIENT_SUBNET_ADDR, addr, addr_prefix_len);
wire_ctx_t wire = wire_ctx_init(data, *data_len);
wire_ctx_write_u16(&wire, family);
wire_ctx_write_u8(&wire, src_mask);
wire_ctx_write_u8(&wire, dst_mask);
wire_ctx_write(&wire, addr, addr_prefix_len);
if (wire.error != KNOT_EOK) {
return wire.error;
}
// Zeroize trailing bits in the last byte.
if (modulo > 0 && addr_prefix_len > 0) {
data[EDNS_OFFSET_CLIENT_SUBNET_ADDR + addr_prefix_len - 1] &=
0xFF << (8 - modulo);
wire.position[-1] &= 0xFF << (8 - modulo);
}
*data_len = total;
*data_len = wire_ctx_offset(&wire);
return KNOT_EOK;
}
......@@ -368,18 +358,17 @@ int knot_edns_client_subnet_parse(const uint8_t *data,
return KNOT_EINVAL;
}
int rest = data_len - sizeof(uint16_t) - 2 * sizeof(uint8_t);
if (rest < 0 || *addr_len < rest) {
return KNOT_ESPACE;
}
wire_ctx_t wire = wire_ctx_init_const(data, data_len);
*family = wire_read_u16(data + EDNS_OFFSET_CLIENT_SUBNET_FAMILY);
*src_mask = data[EDNS_OFFSET_CLIENT_SUBNET_SRC_MASK];
*dst_mask = data[EDNS_OFFSET_CLIENT_SUBNET_DST_MASK];
memcpy(addr, data + EDNS_OFFSET_CLIENT_SUBNET_ADDR, rest);
*family = wire_ctx_read_u16(&wire);
*src_mask = wire_ctx_read_u8(&wire);
*dst_mask = wire_ctx_read_u8(&wire);
*addr_len = wire_ctx_available(&wire);
wire_ctx_read(&wire, addr, *addr_len);
*addr_len = rest;
if (wire.error != KNOT_EOK) {
return wire.error;
}
return KNOT_EOK;
}
......@@ -29,6 +29,7 @@
#include "libknot/rrset.h"
#include "libknot/internal/macros.h"
#include "libknot/internal/utils.h"
#include "libknot/internal/wire_ctx.h"
/*! \brief TSIG field offsets. */
typedef enum tsig_off_t {
......@@ -63,49 +64,58 @@ static uint8_t* rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb)
return NULL;
}
uint8_t *rd = knot_rdata_data(rr_data);
assert(rd);
wire_ctx_t wire = wire_ctx_init_rdata(rr_data);
/* TSIG RR names should be already sanitized on parse. */
int alg_len = knot_dname_size(rd);
uint16_t lim = knot_rdata_rdlen(rr_data);
if (lim < alg_len + 5 * sizeof(uint16_t)) {
return NULL;
}
int alg_len = knot_dname_size(wire.wire);
/* Not pretty, but fast. */
uint8_t *bp = rd;
switch(id) {
case TSIG_ALGNAME_O: break;
case TSIG_TSIGNED_O: rd += alg_len; break;
case TSIG_FUDGE_O: rd += alg_len + 3 * sizeof(uint16_t); break;
case TSIG_MACLEN_O: rd += alg_len + 4 * sizeof(uint16_t); break;
case TSIG_MAC_O: rd += alg_len + 5 * sizeof(uint16_t); break;
case TSIG_TSIGNED_O:
wire_ctx_skip(&wire, alg_len); break;
case TSIG_FUDGE_O:
wire_ctx_skip(&wire, alg_len + 3 * sizeof(uint16_t));
break;
case TSIG_MACLEN_O:
wire_ctx_skip(&wire, alg_len + 4 * sizeof(uint16_t));
break;
case TSIG_MAC_O:
wire_ctx_skip(&wire, alg_len + 5 * sizeof(uint16_t));
break;
case TSIG_ORIGID_O:
rd += alg_len + 4 * sizeof(uint16_t);
rd += wire_read_u16(rd) + sizeof(uint16_t);
wire_ctx_skip(&wire, alg_len + 4 * sizeof(uint16_t));
wire_ctx_skip(&wire, wire_ctx_read_u16(&wire));
break;
case TSIG_ERROR_O:
rd += alg_len + 4 * sizeof(uint16_t);
rd += wire_read_u16(rd) + 2 * sizeof(uint16_t);
wire_ctx_skip(&wire, alg_len + 4 * sizeof(uint16_t));
wire_ctx_skip(&wire, wire_ctx_read_u16(&wire));
wire_ctx_skip(&wire, sizeof(uint16_t));
break;
case TSIG_OLEN_O:
rd += alg_len + 4 * sizeof(uint16_t);
rd += wire_read_u16(rd) + 3 * sizeof(uint16_t);
wire_ctx_skip(&wire, alg_len + 4 * sizeof(uint16_t));
wire_ctx_skip(&wire, wire_ctx_read_u16(&wire));
wire_ctx_skip(&wire, 2 * sizeof(uint16_t));
break;
case TSIG_OTHER_O:
rd += alg_len + 4 * sizeof(uint16_t);
rd += wire_read_u16(rd) + 4 * sizeof(uint16_t);
wire_ctx_skip(&wire, alg_len + 4 * sizeof(uint16_t));
wire_ctx_skip(&wire, wire_ctx_read_u16(&wire));
wire_ctx_skip(&wire, 3 * sizeof(uint16_t));
break;
}
if (wire.error != KNOT_EOK) {
return NULL;