diff --git a/src/libknot/edns.c b/src/libknot/edns.c
index 7a286be41bd4f7c71236935c690a0f22bf14fd87..e1f68018d57d70581374211375b4ab535cc3cee8 100644
--- a/src/libknot/edns.c
+++ b/src/libknot/edns.c
@@ -46,18 +46,10 @@ knot_rrset_t *knot_edns_new(uint16_t max_pld, uint8_t ext_rcode,
                             uint8_t ver, uint16_t flags, mm_ctx_t *mm)
 {
 	/* Owner: root label. */
-	/*! \todo Maybe later modify dname_from_str() to use memory pool. */
-	size_t pos = 0;
-	knot_dname_t *owner = knot_dname_parse((uint8_t *)"\0", &pos, 1, mm);
-	if (owner == NULL) {
-		ERR_ALLOC_FAILED;
-		return NULL;
-	}
-
+	uint8_t owner[1] = "\0";
 	knot_rrset_t *opt_rr = knot_rrset_new(owner, KNOT_RRTYPE_OPT, max_pld,
 	                                      mm);
 	if (opt_rr == NULL) {
-		knot_dname_free(&owner, mm);
 		ERR_ALLOC_FAILED;
 		return NULL;
 	}
@@ -226,7 +218,7 @@ static void find_option(knot_rdata_t *rdata, uint16_t opt_code, uint8_t **pos)
 	*pos = NULL;
 
 	int i = 0;
-	while (i + 4 < rdlength) {
+	while (i + 4 <= rdlength) {
 		uint16_t code = knot_wire_read_u16(data + i);
 		if (opt_code == code) {
 			*pos = data + i;
diff --git a/tests/edns.c b/tests/edns.c
index 066126b9ae1e296815ab551465ad33f14f138f2c..dfba4689de3cfbceedb0cf7ece2b0b574dfdb6aa 100644
--- a/tests/edns.c
+++ b/tests/edns.c
@@ -26,15 +26,16 @@ static const uint16_t E_FLAGS = (uint16_t)1 << 13;
 static const uint16_t E_MAX_PLD = 10000;
 static const uint16_t E_MAX_PLD2 = 20000;
 static const uint8_t E_VERSION = 1;
-static const uint8_t E_VERSION2 = 1;
+static const uint8_t E_VERSION2 = 2;
 static const uint8_t E_RCODE = 0;
 static const uint8_t E_RCODE2 = 200;
+
+static const uint16_t E_HEADER_SIZE = 11;
+
 static const char *E_NSID_STR = "FooBar";
 static const uint16_t E_NSID_LEN = 6;
 
-static const uint16_t E_OPT2_CODE = 23;
-static const char *E_OPT2_DATA = "Deadbeef";
-static const uint16_t E_OPT2_LEN = 8;
+#define E_NSID_SIZE (4 + E_NSID_LEN)
 
 static const uint16_t E_OPT3_CODE = 15;
 static const char *E_OPT3_FAKE_DATA = "Not used";
@@ -42,10 +43,14 @@ static const char *E_OPT3_DATA = NULL;
 static const uint16_t E_OPT3_LEN = 0;
 static const uint16_t E_OPT3_FAKE_LEN = 8;
 
+#define E_OPT3_SIZE (4 + E_OPT3_LEN)
+
 static const uint16_t E_OPT4_CODE = 30;
 static const char *E_OPT4_DATA = NULL;
 static const uint16_t E_OPT4_LEN = 0;
 
+#define E_OPT4_SIZE (4 + E_OPT4_LEN)
+
 enum offsets {
 	/*! \brief Offset of Extended RCODE in wire order of TTL. */
 	OFFSET_ERCODE = 0,
@@ -106,7 +111,7 @@ static bool check_option(knot_rdata_t *rdata, uint16_t opt_code,
 
 	/* Check RDLENGTH according to given data length. */
 	bool check = (data_len >= 4 + opt_len);
-	ok(check, "%s: RDLENGTH", msg);
+	ok(check, "%s: RDLENGTH (%u)", msg, data_len);
 	success &= check;
 	(*done)++;
 
@@ -177,68 +182,73 @@ static bool check_header(knot_rrset_t *opt_rr, uint16_t payload, uint8_t ver,
 	return success;
 }
 
-static bool opt_rr_check(knot_rrset_t *opt_rr, uint16_t payload, uint8_t ver,
-                         uint16_t flags, uint8_t ext_rcode, uint16_t opt_code,
-                         uint16_t opt_len, uint8_t *opt_data, char *msg,
-                         int *done)
-{
-	bool success = true;
-
-	/* RR header */
-	success &= check_header(opt_rr, payload, ver, flags, ext_rcode, msg,
-	                        done);
-
-	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
-	if (rdata == NULL) {
-		skip_block(4, "No RDATA in OPT RR.");
-		return false;
-	}
-
-	/* OPTION in RDATA = Code + Length + Data. */
-	success &= check_option(rdata, opt_code, opt_len, opt_data, msg, done);
-
-	return success;
-}
-
-static bool test_getters(knot_rrset_t *opt_rr, knot_edns_params_t *params,
-                         int *done)
+static bool test_getters(knot_rrset_t *opt_rr, int *done)
 {
 	assert(opt_rr != NULL);
-	assert(params != NULL);
 	assert(done != NULL);
 	bool success = true;
 
+	/* These values should be set from the setters test:
+	 * Max UDP payload: E_MAX_PLD2
+	 * Version:         E_VERSION2
+	 * RCODE:           E_RCODE2
+	 * Flags:           E_FLAGS | KNOT_EDNS_FLAG_DO
+	 * OPTIONs:         1) KNOT_EDNS_OPTION_NSID, E_NSID_LEN, E_NSID_STR
+	 *                  2) E_OPT3_CODE, 0, 0
+	 *                  3) E_OPT4_CODE, 0, 0
+	 */
+
 	/* Payload */
-	bool check = (knot_edns_get_payload(opt_rr) == params->payload);
+	bool check = (knot_edns_get_payload(opt_rr) == E_MAX_PLD2);
 	ok(check, "OPT RR getters: payload");
 	success &= check;
 	(*done)++;
 
 	/* Extended RCODE */
-	check = (knot_edns_get_ext_rcode(opt_rr) == E_RCODE);
+	check = (knot_edns_get_ext_rcode(opt_rr) == E_RCODE2);
 	ok(check, "OPT RR getters: extended RCODE");
 	success &= check;
 	(*done)++;
 
 	/* Extended RCODE */
-	check = (knot_edns_get_version(opt_rr) == params->version);
+	check = (knot_edns_get_version(opt_rr) == E_VERSION2);
 	ok(check, "OPT RR getters: version");
 	success &= check;
 	(*done)++;
 
 	/* DO bit */
-	check = !knot_edns_do(opt_rr);
+	check = knot_edns_do(opt_rr);
 	ok(check, "OPT RR getters: DO bit check");
 	success &= check;
 	(*done)++;
 
+	/* Wire size */
+	size_t total_size = KNOT_EDNS_MIN_SIZE
+	                    + E_NSID_SIZE + E_OPT3_SIZE + E_OPT4_SIZE;
+	size_t actual_size = knot_edns_wire_size(opt_rr);
+	check = actual_size == total_size;
+	ok(check, "OPT RR getters: wire size (expected: %zu, actual: %zu)",
+	   total_size, actual_size);
+	success &= check;
+	(*done)++;
+
 	/* NSID */
-	check = (knot_edns_has_option(opt_rr, KNOT_EDNS_OPTION_NSID) ==
-	                (params->nsid != NULL && params->nsid_len > 0));
+	check = knot_edns_has_option(opt_rr, KNOT_EDNS_OPTION_NSID);
 	ok(check, "OPT RR getters: NSID check");
 	success &= check;
 	(*done)++;
 
+	/* Other OPTIONs */
+	check = knot_edns_has_option(opt_rr, E_OPT3_CODE);
+	ok(check, "OPT RR getters: empty option 1");
+	success &= check;
+	(*done)++;
+
+	check = knot_edns_has_option(opt_rr, E_OPT4_CODE);
+	ok(check, "OPT RR getters: empty option 2");
+	success &= check;
+	(*done)++;
+
 	return success;
 }
 
@@ -262,8 +272,8 @@ static bool test_setters(knot_rrset_t *opt_rr, int *done)
 	/* OPTION(RDATA)-related setters. */
 
 	/* Proper option. */
-	int ret = knot_edns_add_option(opt_rr, E_OPT2_CODE, E_OPT2_LEN,
-	                           (uint8_t *)E_OPT2_DATA, NULL);
+	int ret = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_NSID,
+	                           E_NSID_LEN, (uint8_t *)E_NSID_STR, NULL);
 	ok(ret == KNOT_EOK, "OPT RR setters: add option with data (ret = %s)",
 	   knot_strerror(ret));
 	(*done)++;
@@ -291,175 +301,131 @@ static bool test_setters(knot_rrset_t *opt_rr, int *done)
 
 	/* Empty OPTION (length 0, data == NULL). */
 	ret = knot_edns_add_option(opt_rr, E_OPT4_CODE, E_OPT4_LEN,
-	                           (uint8_t *)E_OPT4_DATA,
-	                           NULL);
+	                           (uint8_t *)E_OPT4_DATA, NULL);
 	ok(ret == KNOT_EOK, "OPT RR setters: add empty option 2 (ret = %s)",
 	   knot_strerror(ret));
 	(*done)++;
 
-	/* Check empty option 1 */
+
 	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
 	if (rdata == NULL) {
 		skip_block(2, "No RDATA in OPT RR.");
 		return false;
 	}
 
+	/* Check proper option */
+	check = check_option(rdata, KNOT_EDNS_OPTION_NSID, E_NSID_LEN,
+	                     (uint8_t *)E_NSID_STR,
+	                     "OPT RR setters (proper option)", done);
+	success &= check;
+
+	/* Check empty option 1 */
 	check = check_option(rdata, E_OPT3_CODE, E_OPT3_LEN,
 	                     (uint8_t *)E_OPT3_DATA,
 	                     "OPT RR setters (empty option 1)", done);
 	success &= check;
-	(*done)++;
 
 	/* Check empty option 2 */
 	check = check_option(rdata, E_OPT4_CODE, E_OPT4_LEN,
 	                     (uint8_t *)E_OPT4_DATA,
 	                     "OPT RR setters (empty option 2)", done);
 	success &= check;
-	(*done)++;
 
 	return success;
 }
 
-#define TEST_COUNT 44
-
-static inline int remaining(int done) {
-	return TEST_COUNT - done - 1;
-}
-
-int main(int argc, char *argv[])
+static bool test_options(knot_rrset_t *opt_rr, int *done)
 {
-	plan(TEST_COUNT);
-	int done = 0;
+	bool check;
+	bool success = true;
 
-	/*! \todo [OPT] REWRITE */
+	/* Clear options, leave NSID */
+	check = knot_edns_clear_options(opt_rr, true) == KNOT_EOK;
+	ok(check, "OPT RR: clear OPTIONs (leave NSID)");
+	success &= check;
+	(*done)++;
 
-	knot_dname_t *root = knot_dname_from_str(".");
-	knot_rrset_t *opt_rr = knot_rrset_new(root, KNOT_RRTYPE_OPT,
-	                                      KNOT_CLASS_IN, NULL);
-	if (opt_rr == NULL) {
-		skip_block(TEST_COUNT, "EDNS: Could not allocate OPT RR.\n");
-		return 0;
+	knot_rdata_t *rdata = knot_rdataset_at(&opt_rr->rrs, 0);
+	if (rdata == NULL) {
+		skip_block(2, "No RDATA in OPT RR.");
+		return false;
 	}
 
-	/* Creating EDNS params structure with proper data + NSID. */
-
-	knot_edns_params_t *p1 = knot_edns_new_params(E_MAX_PLD, E_VERSION,
-	                                              E_FLAGS, E_NSID_LEN,
-	                                              (uint8_t *)E_NSID_STR);
-	ok(p1 != NULL, "EDNS params: new");
-	done++;
-	/* NOTE: if this fails, the test should probably not continue, otherwise
-	 *       it would give bad results.
-	 */
-
-	/* Creating EDNS params with no NSID. */
-	knot_edns_params_t *p2 = knot_edns_new_params(E_MAX_PLD, E_VERSION,
-	                                              E_FLAGS, 0,
-	                                              (uint8_t *)E_NSID_STR);
-	ok(p2 != NULL, "EDNS params: new with NSID length = 0");
-	done++;
-
-	knot_edns_params_t *p3 = knot_edns_new_params(E_MAX_PLD, E_VERSION,
-	                                              E_FLAGS, E_NSID_LEN,
-	                                              NULL);
-	ok(p3 != NULL, "EDNS params: new with NSID = NULL");
-	done++;
-
-	if (p1 == NULL || p2 == NULL || p3 == NULL) {
-		skip_block(remaining(done), "Failed to initialize EDNS params.");
-		goto exit;
-	}
+	check = check_option(rdata, KNOT_EDNS_OPTION_NSID, E_NSID_LEN,
+	                     (uint8_t *)E_NSID_STR,
+	                     "OPT RR: clear OPTIONs (NSID check)", done);
+	success &= check;
 
-	bool success = true;
-	bool check;
-	/* Check that all parameters are properly set. */
-	check = (p1->payload == E_MAX_PLD
-	         && p1->version == E_VERSION
-	         && p1->flags == E_FLAGS
-	         && p1->nsid_len == E_NSID_LEN
-	         && memcmp(p1->nsid, E_NSID_STR, E_NSID_LEN) == 0);
-	ok(check, "EDNS params: parameter values (with NSID)");
+	check = !knot_edns_has_option(opt_rr, E_OPT3_CODE);
+	ok(check, "OPT RR: clear options (other OPTION");
 	success &= check;
-	done++;
+	(*done)++;
 
-	check = (p2->payload == E_MAX_PLD
-	         && p2->version == E_VERSION
-	         && p2->flags == E_FLAGS
-	         && p2->nsid_len == 0
-	         && p2->nsid == 0);
+	check = !knot_edns_has_option(opt_rr, E_OPT4_CODE);
+	ok(check, "OPT RR: clear options (other OPTION");
+	success &= check;
+	(*done)++;
 
-	ok(check, "EDNS params: parameter values (NSID length = 0)");
+	/* Clear options, leave NSID */
+	check = knot_edns_clear_options(opt_rr, false) == KNOT_EOK;
+	ok(check, "OPT RR: clear OPTIONs (all)");
 	success &= check;
-	done++;
+	(*done)++;
 
-	check = (p3->payload == E_MAX_PLD
-	         && p3->version == E_VERSION
-	         && p3->flags == E_FLAGS
-	         && p3->nsid_len == 0
-	         && p3->nsid == 0);
-	ok(check, "EDNS params: parameter values (NSID = NULL)");
+	check = !knot_edns_has_option(opt_rr, KNOT_EDNS_OPTION_NSID);
+	ok(check, "OPT RR: clear options (NSID removed)");
 	success &= check;
-	done++;
+	(*done)++;
 
-	if (!success) {
-		skip_block(remaining(done), "EDNS params have wrong values.");
-		goto exit;
-	}
+	return success;
+}
 
-	/* Creating OPT RR from params. */
-	int ret = knot_edns_init_from_params(NULL, p1, true, NULL);
-	ok(ret == KNOT_EINVAL, "OPT RR: init (no OPT) (ret = %s)",
-	   knot_strerror(ret));
-	done++;
+#define TEST_COUNT 47
 
-	ret = knot_edns_init_from_params(opt_rr, NULL, true, NULL);
-	ok(ret == KNOT_EINVAL, "OPT RR: init (no EDNS params) (ret = %s)",
-	   knot_strerror(ret));
-	done++;
+static inline int remaining(int done) {
+	return TEST_COUNT - done - 1;
+}
 
-	ret = knot_edns_init_from_params(opt_rr, p1, true, NULL);
-	ok(ret == KNOT_EOK, "OPT RR: init (correct) (ret = %s)",
-	   knot_strerror(ret));
+int main(int argc, char *argv[])
+{
+	plan(TEST_COUNT);
+	int done = 0;
+
+	knot_rrset_t *opt_rr = knot_edns_new(E_MAX_PLD, E_RCODE, E_VERSION,
+	                                     E_FLAGS, NULL);
+	ok(opt_rr != NULL, "OPT RR: new");
 	done++;
 
-	if (ret != KNOT_EOK) {
-		skip_block(remaining(done), "OPT RR not initialized.");
-		goto exit;
-	}
+	bool success;
 
-	/* Check initialized values. */
-	success = opt_rr_check(opt_rr, p1->payload, p1->version, p1->flags,
-	                       E_RCODE, KNOT_EDNS_OPTION_NSID, p1->nsid_len,
-	                       p1->nsid, "OPT RR init", &done);
+	/* Check initialized values (no NSID yet). */
+	success = check_header(opt_rr, E_MAX_PLD, E_VERSION, E_FLAGS, E_RCODE,
+	                       "OPT RR: new", &done);
 	if (!success) {
 		skip_block(remaining(done), "OPT RR not initialized properly");
 		goto exit;
 	}
 
-	/* Getters
-	   Note: NULL parameters are not supported, so no test for that. */
-	success = test_getters(opt_rr, p1, &done);
+	/* Setters */
+	success = test_setters(opt_rr, &done);
 
 	if (!success) {
-		skip_block(remaining(done), "OPT RR: getters error");
+		skip_block(remaining(done), "OPT RR: setters error");
 		goto exit;
 	}
 
-	/* Setters */
-	success = test_setters(opt_rr, &done);
+	/* Getters
+	   Note: NULL parameters are not supported, so no test for that. */
+	success = test_getters(opt_rr, &done);
 
 	if (!success) {
-		skip_block(remaining(done), "OPT RR: setters error");
+		skip_block(remaining(done), "OPT RR: getters error");
 		goto exit;
 	}
 
-exit:
-	/* Free the parameters. */
-	knot_edns_free_params(&p1);
-	knot_edns_free_params(&p2);
-	knot_edns_free_params(&p3);
-	ok(p1 == NULL && p2 == NULL && p3 == NULL, "EDNS params: free (all)");
+	(void)test_options(opt_rr, &done);
 
+exit:
 	knot_rrset_free(&opt_rr, NULL);
 
 	return 0;
diff --git a/tests/fake_server.h b/tests/fake_server.h
index 12fcad965b50441d9ae295655400409fc5cced6f..829898bd0420588f793eca97630f57b57c3a4b3c 100644
--- a/tests/fake_server.h
+++ b/tests/fake_server.h
@@ -56,11 +56,11 @@ static inline int create_fake_server(server_t *server, mm_ctx_t *mm)
 		return ret;
 	}
 
-	server->edns = knot_edns_new_params(KNOT_EDNS_MAX_UDP_PAYLOAD,
-	                                    KNOT_EDNS_VERSION,
-	                                    KNOT_EDNS_DEFAULT_FLAGS,
-	                                    0, NULL);
-	if (server->edns == NULL) {
+	server->opt_rr = knot_edns_new(KNOT_EDNS_MAX_UDP_PAYLOAD,
+	                               KNOT_EDNS_VERSION,
+	                               KNOT_EDNS_DEFAULT_FLAGS, 0, NULL);
+
+	if (server->opt_rr == NULL) {
 		server_deinit(server);
 		return KNOT_ENOMEM;
 	}
diff --git a/tests/pkt.c b/tests/pkt.c
index 43ded1828ee713fcbd1f75c351436e2e6584b082..70b34758d128674e044f2e6480dfc6d6f467cabc 100644
--- a/tests/pkt.c
+++ b/tests/pkt.c
@@ -81,14 +81,19 @@ int main(int argc, char *argv[])
 	}
 
 	uint8_t *edns_str = (uint8_t *)"ab";
-	/* Create EDNS parameters. */
-	knot_edns_params_t edns_params = {
-		.payload = 1024,
-		.version = 0,
-		.nsid_len = 2,
-		.nsid = edns_str,
-		.flags = KNOT_EDNS_FLAG_DO
-	};
+	/* Create OPT RR. */
+	knot_rrset_t *opt_rr = knot_edns_new(1024, 0, 0, KNOT_EDNS_FLAG_DO, &mm);
+	if (opt_rr != NULL) {
+		skip_block(25, "Failed to allocate OPT RR.");
+		return 0;
+	}
+	/* Add NSID */
+	ret = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_NSID,
+	                           strlen((char *)edns_str), edns_str, &mm);
+	if (ret != KNOT_EOK) {
+		skip_block(25, "Failed to add NSID to OPT RR.");
+		return 0;
+	}
 
 	/*
 	 * Packet writer tests.
@@ -116,7 +121,7 @@ int main(int argc, char *argv[])
 	ok(ret == KNOT_EOK, "pkt: put question");
 
 	/* Add OPT to packet (empty NSID). */
-	ret = knot_pkt_reserve(out, knot_edns_wire_size(&edns_params));
+	ret = knot_pkt_reserve(out, knot_edns_wire_size(opt_rr));
 	ok(ret == KNOT_EOK, "pkt: reserve OPT RR");
 
 	/* Begin ANSWER section. */
@@ -149,7 +154,7 @@ int main(int argc, char *argv[])
 	ok(ret == KNOT_EOK, "pkt: begin ADDITIONALS");
 
 	/* Encode OPT RR. */
-	ret = knot_pkt_write_opt(out, &edns_params, true);
+	ret = knot_pkt_put(out, COMPR_HINT_NONE, opt_rr, 0);
 	ok(ret == KNOT_EOK, "pkt: write OPT RR");
 
 	/*