Ejemplo n.º 1
0
/*----------------------------------------------------------------------------*/
_public_
int knot_edns_add_option(knot_rrset_t *opt_rr, uint16_t code,
                         uint16_t length, const uint8_t *data, mm_ctx_t *mm)
{
	if (opt_rr == NULL || (length != 0 && data == NULL)) {
		return KNOT_EINVAL;
	}

	/* We need to replace the RDATA currently in the OPT RR */

	/* 1) create new RDATA by appending the new option after the current
	 *    RDATA.
	 */
	assert(opt_rr->rrs.rr_count == 1);
	knot_rdata_t *old_rdata = knot_rdataset_at(&opt_rr->rrs, 0);

	uint8_t *old_data = knot_rdata_data(old_rdata);
	uint16_t old_data_len = knot_rdata_rdlen(old_rdata);
	uint16_t new_data_len = old_data_len + KNOT_EDNS_OPTION_HDRLEN + length;

	uint8_t new_data[new_data_len];

	memcpy(new_data, 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);
	// write the option data
	memcpy(new_data + old_data_len + KNOT_EDNS_OPTION_HDRLEN, data, length);

	/* 2) Replace the RDATA in the RRSet. */
	uint32_t old_ttl = knot_rdata_ttl(old_rdata);
	knot_rdataset_clear(&opt_rr->rrs, mm);
	return knot_rrset_add_rdata(opt_rr, new_data, new_data_len,
	                            old_ttl, mm);
}
Ejemplo n.º 2
0
Archivo: edns.c Proyecto: idtek/knot
static bool check_ttl(knot_rdata_t *rdata, uint8_t ext_rcode, uint8_t ver,
                      uint16_t flags, char *msg, int *done)
{
	/* TTL should be stored in machine byte order.
	   We need network byte order to compare its parts. */
	uint8_t ttl_wire[4] = { 0, 0, 0, 0 };
	wire_write_u32(ttl_wire, knot_rdata_ttl(rdata));

	/* Convert Flags from EDNS parameters to wire format for comparison. */
	uint8_t flags_wire[2] = { 0, 0 };
	wire_write_u16(flags_wire, flags);

	bool success = true;

	/* TTL = Ext RCODE + Version + Flags */
	bool check = (ttl_wire[OFFSET_ERCODE] == ext_rcode);
	ok(check, "%s: extended RCODE", msg);
	success &= check;
	(*done)++;

	check = (ttl_wire[OFFSET_VER] == ver);
	ok(check, "%s: version", msg);
	success &= check;
	(*done)++;

	check = (memcmp(flags_wire, ttl_wire + OFFSET_FLAGS, 2) == 0);
	ok(check, "%s: flags", msg);
	success &= check;
	(*done)++;

	return success;
}
Ejemplo n.º 3
0
_public_
int knot_pkt_put_question(knot_pkt_t *pkt, const knot_dname_t *qname, uint16_t qclass, uint16_t qtype)
{
	if (pkt == NULL || qname == NULL) {
		return KNOT_EINVAL;
	}

	assert(pkt->size == KNOT_WIRE_HEADER_SIZE);
	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);
	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;
	}

	/* Copy QTYPE & QCLASS */
	dst += qname_len;
	wire_write_u16(dst, qtype);
	dst += sizeof(uint16_t);
	wire_write_u16(dst, qclass);

	/* Update question count and sizes. */
	knot_wire_set_qdcount(pkt->wire, 1);
	pkt->size += question_len;
	pkt->qname_size = qname_len;

	/* Start writing ANSWER. */
	return knot_pkt_begin(pkt, KNOT_ANSWER);
}
Ejemplo n.º 4
0
/*----------------------------------------------------------------------------*/
_public_
int knot_edns_client_subnet_create(const knot_addr_family_t family,
                                   const uint8_t *addr,
                                   const uint16_t addr_len,
                                   uint8_t src_mask,
                                   uint8_t dst_mask,
                                   uint8_t *data,
                                   uint16_t *data_len)
{
	if (addr == NULL || data == NULL || data_len == NULL) {
		return KNOT_EINVAL;
	}

	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);

	// 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);
	}

	*data_len = total;

	return KNOT_EOK;
}
Ejemplo n.º 5
0
int main(void)
{
    plan_lazy();

    wire_ctx_t wire = { 0 };

    dnssec_binary_t buffer = { .size = 20, .data = (uint8_t []) {
        0xc8, 0x25, 0x19, 0x3c, 0x96, 0xe6, 0x59, 0xf7, 0x2b, 0x94,
              0x83, 0xb3, 0x3e, 0x6f, 0xb9, 0x01, 0xe2, 0x91, 0xa8, 0xa9,
    }
                             };

    wire = wire_init(buffer.data + 10, 10);
    ok(wire_read_u8(&wire) == 0x83, "wire_init()");

    wire = wire_init_binary(&buffer);
    ok(wire_read_u8(&wire) == 0xc8, "wire_init_binary()");

    // read operations

    wire_seek(&wire, 5);
    ok(wire_read_u8(&wire) == 0xe6, "wire_seek() forward");
    wire_seek(&wire, 3);
    ok(wire_read_u8(&wire) == 0x3c, "wire_seek() backward");

    wire_seek(&wire, 10);
    ok(wire_read_u8(&wire) == 0x83, "wire_read_u8()");
    ok(wire_read_u16(&wire) == 45886, "wire_read_u16()");
    ok(wire_tell(&wire) == 13, "wire_tell()");
    ok(wire_available(&wire) == 7, "wire_available()");

    dnssec_binary_t ref = { 0 };
    wire_available_binary(&wire, &ref);
    ok(ref.data == buffer.data + 13 && ref.size == 7, "wire_available_binary()");

    uint8_t in[6] = { 0 };
    wire_seek(&wire, 4);
    wire_read(&wire, in, 6);
    ok(memcmp(in, buffer.data + 4, 6) == 0 && wire_tell(&wire) == 10,
       "wire_read()");

    // write operations

    wire_seek(&wire, 0);

    wire_write_u8(&wire, 0x42);
    ok(buffer.data[0] == 0x42 && wire_tell(&wire) == 1,
       "wire_write_u8()");
    wire_write_u16(&wire, 44513);
    ok(memcmp(buffer.data + 1, "\xad\xe1", 2) == 0 && wire_tell(&wire) == 3,
       "wire_write_u16()");

    wire_seek(&wire, 12);
    const uint8_t out[7] = { 0xc0, 0x1d, 0xca, 0xfe, 0xde, 0xad, 0xbe };
    wire_write(&wire, out, 7);
    ok(memcmp(buffer.data + 12, out, 7) == 0 && wire_tell(&wire) == 19,
       "wire_write()");

    dnssec_binary_t bignum = { .data = (uint8_t *)out, .size = 4 };
    const uint8_t expect[8] = { 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1d, 0xca, 0xfe };
    wire_seek(&wire, 2);
    wire_write_bignum(&wire, 8, &bignum);
    ok(memcmp(buffer.data + 2, expect, 8) == 0 && wire_tell(&wire) == 10,
       "wire_write_ralign()");

    return 0;
}