1 /*  Copyright (C) 2018 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
2 
3     This program is free software: you can redistribute it and/or modify
4     it under the terms of the GNU General Public License as published by
5     the Free Software Foundation, either version 3 of the License, or
6     (at your option) any later version.
7 
8     This program is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11     GNU General Public License for more details.
12 
13     You should have received a copy of the GNU General Public License
14     along with this program.  If not, see <https://www.gnu.org/licenses/>.
15  */
16 
17 #include <tap/basic.h>
18 
19 #include <assert.h>
20 #include "libknot/libknot.h"
21 #include "libknot/rrtype/opt.h"
22 #include "libknot/descriptor.h"
23 #include "libknot/wire.h"
24 #include "contrib/sockaddr.h"
25 
26 static const uint16_t E_MAX_PLD = 10000;
27 static const uint16_t E_MAX_PLD2 = 20000;
28 static const uint8_t E_VERSION = 1;
29 static const uint8_t E_VERSION2 = 2;
30 static const uint8_t E_RCODE = 0;
31 static const uint8_t E_RCODE2 = 200;
32 
33 static const char *E_NSID_STR = "FooBar";
34 static const char *E_NSID_STR2 = "BarFoo";
35 static const uint16_t E_NSID_LEN = 6;
36 
37 #define E_NSID_SIZE (4 + E_NSID_LEN)
38 
39 static const uint16_t E_OPT3_CODE = 15;
40 static const char *E_OPT3_FAKE_DATA = "Not used";
41 static const char *E_OPT3_DATA = NULL;
42 static const uint16_t E_OPT3_LEN = 0;
43 static const uint16_t E_OPT3_FAKE_LEN = 8;
44 
45 #define E_OPT3_SIZE (4 + E_OPT3_LEN)
46 
47 static const uint16_t E_OPT4_CODE = 30;
48 static const char *E_OPT4_DATA = NULL;
49 static const uint16_t E_OPT4_LEN = 0;
50 
51 #define E_OPT4_SIZE (4 + E_OPT4_LEN)
52 
53 enum offsets {
54 	/*! \brief Offset of Extended RCODE in wire order of TTL. */
55 	OFFSET_ERCODE = 0,
56 	/*! \brief Offset of Version in wire order of TTL. */
57 	OFFSET_VER = 1,
58 	/*! \brief Offset of Flags in wire order of TTL. */
59 	OFFSET_FLAGS = 2,
60 	/*! \brief Offset of OPTION code in one OPTION in RDATA. */
61 	OFFSET_OPT_CODE = 0,
62 	/*! \brief Offset of OPTION size in one OPTION in RDATA. */
63 	OFFSET_OPT_SIZE = 2,
64 	/*! \brief Offset of OPTION data in one OPTION in RDATA. */
65 	OFFSET_OPT_DATA = 4
66 };
67 
68 static const uint16_t DO_FLAG = (uint16_t)1 << 15;
69 
check_ttl(knot_rrset_t * rrset,uint8_t ext_rcode,uint8_t ver,uint16_t flags,char * msg)70 static void check_ttl(knot_rrset_t *rrset, uint8_t ext_rcode, uint8_t ver,
71                       uint16_t flags, char *msg)
72 {
73 	if (rrset == NULL) {
74 		return;
75 	}
76 
77 	/* TTL should be stored in machine byte order.
78 	   We need network byte order to compare its parts. */
79 	uint8_t ttl_wire[4] = { 0, 0, 0, 0 };
80 	knot_wire_write_u32(ttl_wire, rrset->ttl);
81 
82 	/* Convert Flags from EDNS parameters to wire format for comparison. */
83 	uint8_t flags_wire[2] = { 0, 0 };
84 	knot_wire_write_u16(flags_wire, flags);
85 
86 	/* TTL = Ext RCODE + Version + Flags */
87 	bool check = (ttl_wire[OFFSET_ERCODE] == ext_rcode);
88 	ok(check, "%s: extended RCODE", msg);
89 
90 	check = (ttl_wire[OFFSET_VER] == ver);
91 	ok(check, "%s: version", msg);
92 
93 	check = (memcmp(flags_wire, ttl_wire + OFFSET_FLAGS, 2) == 0);
94 	ok(check, "%s: flags", msg);
95 }
96 
check_option(knot_rdata_t * rdata,uint16_t opt_code,uint16_t opt_len,uint8_t * opt_data,char * msg)97 static void check_option(knot_rdata_t *rdata, uint16_t opt_code,
98                          uint16_t opt_len, uint8_t *opt_data, char *msg)
99 {
100 	assert(rdata != NULL);
101 
102 	uint8_t *data = rdata->data;
103 	uint16_t data_len = rdata->len;
104 
105 	/* Check RDLENGTH according to given data length. */
106 	bool check = (data_len >= 4 + opt_len);
107 	ok(check, "%s: RDLENGTH (%u)", msg, data_len);
108 
109 	/* Find the desired option. */
110 	bool found = false;
111 	int pos = 0;
112 	while (pos <= data_len - 4) {
113 		uint16_t code = knot_wire_read_u16(data + pos + OFFSET_OPT_CODE);
114 		if (code == opt_code) {
115 			found = true;
116 			break;
117 		}
118 		uint16_t len = knot_wire_read_u16(data + pos + OFFSET_OPT_SIZE);
119 		pos += 4 + len;
120 	}
121 
122 	/* Check that the option is present. */
123 	ok(found, "%s: find OPTION %u in OPT RR", msg, opt_code);
124 
125 	/* Check that the first OPTION's size si the size of the option data. */
126 	uint16_t opt_size = knot_wire_read_u16(data + pos + OFFSET_OPT_SIZE);
127 	check = (opt_size == opt_len);
128 	ok(check, "%s: OPTION data size", msg);
129 
130 	/* Check the actual NSID data. */
131 	check = (opt_data == 0 || memcmp(data + pos + OFFSET_OPT_DATA, opt_data, opt_len) == 0);
132 	ok(check, "%s: OPTION data", msg);
133 }
134 
check_header(knot_rrset_t * opt_rr,uint16_t payload,uint8_t ver,uint16_t flags,uint8_t ext_rcode,char * msg)135 static void check_header(knot_rrset_t *opt_rr, uint16_t payload, uint8_t ver,
136                          uint16_t flags, uint8_t ext_rcode, char *msg)
137 {
138 	assert(opt_rr != NULL);
139 	bool check;
140 
141 	/* Check values in OPT RR by hand. */
142 	/* CLASS == Max UDP payload */
143 	check = (opt_rr->rclass == payload);
144 	ok(check, "%s: max payload", msg);
145 
146 	/* The OPT RR should have exactly one RDATA. */
147 	check = (opt_rr->rrs.count == 1);
148 	ok(check, "%s: RR count == 1", msg);
149 
150 	knot_rdata_t *rdata = opt_rr->rrs.rdata;
151 	check = (rdata != NULL);
152 	ok(check, "%s: RDATA exists", msg);
153 
154 	check_ttl(opt_rr, ext_rcode, ver, flags, msg);
155 }
156 
test_getters(knot_rrset_t * opt_rr)157 static void test_getters(knot_rrset_t *opt_rr)
158 {
159 	assert(opt_rr != NULL);
160 
161 	/* These values should be set from the setters test:
162 	 * Max UDP payload: E_MAX_PLD2
163 	 * Version:         E_VERSION2
164 	 * RCODE:           E_RCODE2
165 	 * Flags:           E_FLAGS | KNOT_EDNS_FLAG_DO
166 	 * OPTIONs:         1) KNOT_EDNS_OPTION_NSID, E_NSID_LEN, E_NSID_STR
167 	 *                  2) E_OPT3_CODE, 0, 0
168 	 *                  3) E_OPT4_CODE, 0, 0
169 	 *                  4) KNOT_EDNS_OPTION_NSID, E_NSID_LEN, E_NSID_STR2
170 	 */
171 
172 	/* Payload */
173 	bool check = (knot_edns_get_payload(opt_rr) == E_MAX_PLD2);
174 	ok(check, "OPT RR getters: payload");
175 
176 	/* Extended RCODE */
177 	check = (knot_edns_get_ext_rcode(opt_rr) == E_RCODE2);
178 	ok(check, "OPT RR getters: extended RCODE");
179 
180 	/* Extended RCODE */
181 	check = (knot_edns_get_version(opt_rr) == E_VERSION2);
182 	ok(check, "OPT RR getters: version");
183 
184 	/* DO bit */
185 	check = knot_edns_do(opt_rr);
186 	ok(check, "OPT RR getters: DO bit check");
187 
188 	/* Wire size */
189 	size_t total_size = KNOT_EDNS_MIN_SIZE
190 	                    + 2 * E_NSID_SIZE + E_OPT3_SIZE + E_OPT4_SIZE;
191 	size_t actual_size = knot_edns_wire_size(opt_rr);
192 	check = actual_size == total_size;
193 	ok(check, "OPT RR getters: wire size (expected: %zu, actual: %zu)",
194 	   total_size, actual_size);
195 
196 	/* NSID */
197 	uint8_t *nsid1 = knot_edns_get_option(opt_rr, KNOT_EDNS_OPTION_NSID, NULL);
198 	check = nsid1 != NULL;
199 	ok(check, "OPT RR getters: NSID check");
200 	check = memcmp(knot_edns_opt_get_data(nsid1), E_NSID_STR, knot_edns_opt_get_length(nsid1)) == 0;
201 	ok(check, "OPT RR getters: NSID value check");
202 
203 	/* Another NSID */
204 	uint8_t *nsid2 = knot_edns_get_option(opt_rr, KNOT_EDNS_OPTION_NSID, nsid1);
205 	check = nsid2 != NULL;
206 	ok(check, "OPT RR getters: another NSID check");
207 	check = memcmp(knot_edns_opt_get_data(nsid2), E_NSID_STR2, knot_edns_opt_get_length(nsid2)) == 0;
208 	ok(check, "OPT RR getters: another NSID value check");
209 
210 	/* Other OPTIONs */
211 	check = knot_edns_get_option(opt_rr, E_OPT3_CODE, NULL) != NULL;
212 	ok(check, "OPT RR getters: empty option 1");
213 
214 	check = knot_edns_get_option(opt_rr, E_OPT4_CODE, NULL) != NULL;
215 	ok(check, "OPT RR getters: empty option 2");
216 
217 	uint16_t code = knot_edns_opt_get_code((const uint8_t *)"\x00\x0a" "\x00\x00");
218 	ok(code == KNOT_EDNS_OPTION_COOKIE, "OPT RR getters: EDNS OPT code");
219 }
220 
test_setters(knot_rrset_t * opt_rr)221 static void test_setters(knot_rrset_t *opt_rr)
222 {
223 	assert(opt_rr != NULL);
224 
225 	/* Header-related setters. */
226 	knot_edns_set_payload(opt_rr, E_MAX_PLD2);
227 	knot_edns_set_ext_rcode(opt_rr, E_RCODE2);
228 	knot_edns_set_version(opt_rr, E_VERSION2);
229 	knot_edns_set_do(opt_rr);
230 
231 	check_header(opt_rr, E_MAX_PLD2, E_VERSION2, DO_FLAG, E_RCODE2,
232 	             "OPT RR setters");
233 
234 	/* OPTION(RDATA)-related setters. */
235 
236 	/* Proper option NSID. */
237 	int ret = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_NSID,
238 	                               E_NSID_LEN, (uint8_t *)E_NSID_STR, NULL);
239 	is_int(KNOT_EOK, ret, "OPT RR setters: add option with data (ret = %s)",
240 	   knot_strerror(ret));
241 
242 	/* Wrong argument: no OPT RR. */
243 	ret = knot_edns_add_option(NULL, E_OPT3_CODE, E_OPT3_FAKE_LEN,
244 	                           (uint8_t *)E_OPT3_FAKE_DATA, NULL);
245 	is_int(KNOT_EINVAL, ret, "OPT RR setters: add option (rr == NULL) "
246 	   "(ret = %s)", knot_strerror(ret));
247 
248 	/* Wrong argument: option length != 0 && data == NULL. */
249 	ret = knot_edns_add_option(opt_rr, E_OPT3_CODE, E_OPT3_FAKE_LEN, NULL,
250 	                           NULL);
251 	is_int(KNOT_EINVAL, ret, "OPT RR setters: add option (data == NULL, "
252 	   "len != 0) (ret = %s)", knot_strerror(ret));
253 
254 	/* Empty OPTION (length 0, data != NULL). */
255 	ret = knot_edns_add_option(opt_rr, E_OPT3_CODE, E_OPT3_LEN,
256 	                           (uint8_t *)E_OPT3_FAKE_DATA, NULL);
257 	is_int(KNOT_EOK, ret, "OPT RR setters: add empty option 1 (ret = %s)",
258 	   knot_strerror(ret));
259 
260 	/* Empty OPTION (length 0, data == NULL). */
261 	ret = knot_edns_add_option(opt_rr, E_OPT4_CODE, E_OPT4_LEN,
262 	                           (uint8_t *)E_OPT4_DATA, NULL);
263 	is_int(KNOT_EOK, ret, "OPT RR setters: add empty option 2 (ret = %s)",
264 	   knot_strerror(ret));
265 
266 	/* Another option NSID. */
267 	ret = knot_edns_add_option(opt_rr, KNOT_EDNS_OPTION_NSID,
268 	                           E_NSID_LEN, (uint8_t *)E_NSID_STR2, NULL);
269 	is_int(KNOT_EOK, ret, "OPT RR setters: add option with data (ret = %s)",
270 	   knot_strerror(ret));
271 
272 	knot_rdata_t *rdata = opt_rr->rrs.rdata;
273 	ok(rdata != NULL, "OPT RR setters: non-empty RDATA");
274 
275 	/* Check proper option NSID */
276 	check_option(rdata, KNOT_EDNS_OPTION_NSID, E_NSID_LEN,
277 	             (uint8_t *)E_NSID_STR, "OPT RR setters (proper option)");
278 
279 	/* Check empty option 1 */
280 	check_option(rdata, E_OPT3_CODE, E_OPT3_LEN,
281 	             (uint8_t *)E_OPT3_DATA, "OPT RR setters (empty option 1)");
282 
283 	/* Check empty option 2 */
284 	check_option(rdata, E_OPT4_CODE, E_OPT4_LEN,
285 	             (uint8_t *)E_OPT4_DATA, "OPT RR setters (empty option 2)");
286 }
287 
test_alignment(void)288 static void test_alignment(void)
289 {
290 	int ret;
291 
292 	ret = knot_edns_alignment_size(1, 1, 1);
293 	ok(ret == -1, "no alignment");
294 
295 	ret = knot_edns_alignment_size(1, 1, 2);
296 	ok(ret == -1, "no alignment");
297 
298 	ret = knot_edns_alignment_size(1, 1, 3);
299 	ok(ret == (6 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
300 
301 	ret = knot_edns_alignment_size(1, 1, 4);
302 	ok(ret == (8 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
303 
304 	ret = knot_edns_alignment_size(1, 1, 512);
305 	ok(ret == (512 - (1 + 1 + KNOT_EDNS_OPTION_HDRLEN)), "%i-Byte alignment", ret);
306 }
307 
test_keepalive(void)308 static void test_keepalive(void)
309 {
310 	typedef struct {
311 		char *msg;
312 		uint16_t opt_len;
313 		char *opt;
314 		uint16_t val;
315 	} test_t;
316 
317 	// OK tests.
318 
319 	static const test_t TESTS[] = {
320 		{ "ok 0",     0, "",         0 },
321 		{ "ok 1",     2, "\x00\x01", 1 },
322 		{ "ok 258",   2, "\x01\x02", 258 },
323 		{ "ok 65535", 2, "\xFF\xFF", 65535 },
324 		{ NULL }
325 	};
326 
327 	for (const test_t *t = TESTS; t->msg != NULL; t++) {
328 		uint16_t len = knot_edns_keepalive_size(t->val);
329 		ok(len == t->opt_len, "%s: %s, size", __func__, t->msg);
330 
331 		uint8_t wire[8] = { 0 };
332 		int ret = knot_edns_keepalive_write(wire, sizeof(wire), t->val);
333 		is_int(KNOT_EOK, ret, "%s: %s, write, return", __func__, t->msg);
334 		ok(memcmp(wire, t->opt, t->opt_len) == 0, "%s: %s, write, value",
335 		                                          __func__, t->msg);
336 
337 		uint16_t timeout = 0;
338 		ret = knot_edns_keepalive_parse(&timeout, (uint8_t *)t->opt, t->opt_len);
339 		is_int(KNOT_EOK, ret, "%s: %s, parse, return", __func__, t->msg);
340 		ok(timeout == t->val, "%s: %s, parse, value", __func__, t->msg);
341 	}
342 
343 	// Error tests.
344 
345 	uint8_t wire[8] = { 0 };
346 	ok(knot_edns_keepalive_write(NULL, 0, 0) == KNOT_EINVAL,
347 	   "%s: write, NULL", __func__);
348 	ok(knot_edns_keepalive_write(wire, 1, 1) == KNOT_ESPACE,
349 	   "%s: write, no room", __func__);
350 
351 	uint16_t timeout = 0;
352 	ok(knot_edns_keepalive_parse(NULL, (const uint8_t *)"", 0) == KNOT_EINVAL,
353 	   "%s: parse, NULL", __func__);
354 	ok(knot_edns_keepalive_parse(&timeout, NULL, 0) == KNOT_EINVAL,
355 	   "%s: parse, NULL", __func__);
356 	ok(knot_edns_keepalive_parse(&timeout, (const uint8_t *)"\x01", 1) == KNOT_EMALF,
357 	   "%s: parse, malformed", __func__);
358 }
359 
test_chain(void)360 static void test_chain(void)
361 {
362 	typedef struct {
363 		char *msg;
364 		uint16_t opt_len;
365 		knot_dname_t *dname;
366 	} test_t;
367 
368 	// OK tests.
369 
370 	static const test_t TESTS[] = {
371 		{ ".",  1, (knot_dname_t *)"" },
372 		{ "a.", 3, (knot_dname_t *)"\x01" "a" },
373 		{ NULL }
374 	};
375 
376 	for (const test_t *t = TESTS; t->msg != NULL; t++) {
377 		uint16_t len = knot_edns_chain_size(t->dname);
378 		ok(len == t->opt_len, "%s: dname %s, size", __func__, t->msg);
379 
380 		uint8_t wire[8] = { 0 };
381 		int ret = knot_edns_chain_write(wire, sizeof(wire), t->dname);
382 		is_int(KNOT_EOK, ret, "%s: dname %s, write, return", __func__, t->msg);
383 		ok(memcmp(wire, t->dname, t->opt_len) == 0, "%s: dname %s, write, value",
384 		                                            __func__, t->msg);
385 
386 		knot_dname_t *dname = NULL;
387 		ret = knot_edns_chain_parse(&dname, (uint8_t *)t->dname, t->opt_len, NULL);
388 		is_int(KNOT_EOK, ret, "%s: dname %s, parse, return", __func__, t->msg);
389 		ok(knot_dname_is_equal(dname, t->dname), "%s: dname %s, parse, value",
390 		                                         __func__, t->msg);
391 		knot_dname_free(dname, NULL);
392 	}
393 
394 	// Error tests.
395 
396 	ok(knot_edns_chain_size(NULL) == 0, "%s: size, NULL", __func__);
397 
398 	uint8_t wire[8] = { 0 };
399 	ok(knot_edns_chain_write(NULL, 0, wire) == KNOT_EINVAL,
400 	   "%s: write, NULL", __func__);
401 	ok(knot_edns_chain_write(wire, 0, NULL) == KNOT_EINVAL,
402 	   "%s: write, NULL", __func__);
403 	ok(knot_edns_chain_write(wire, 0, (const knot_dname_t *)"") == KNOT_ESPACE,
404 	   "%s: write, no room", __func__);
405 
406 	knot_dname_t *dname = NULL;
407 	ok(knot_edns_chain_parse(NULL, wire, 0, NULL) == KNOT_EINVAL && dname == NULL,
408 	   "%s: parse, NULL", __func__);
409 	ok(knot_edns_chain_parse(&dname, NULL, 0, NULL) == KNOT_EINVAL && dname == NULL,
410 	   "%s: parse, NULL", __func__);
411 	ok(knot_edns_chain_parse(&dname, (const uint8_t *)"\x01", 1, NULL) == KNOT_EMALF &&
412 	   dname == NULL, "%s: parse, malformed", __func__);
413 }
414 
check_cookie_parse(const char * opt,knot_edns_cookie_t * cc,knot_edns_cookie_t * sc,int code,const char * msg)415 static void check_cookie_parse(const char *opt, knot_edns_cookie_t *cc,
416                                knot_edns_cookie_t *sc, int code, const char *msg)
417 {
418 	const uint8_t *data = NULL;
419 	uint16_t data_len = 0;
420 	if (opt != NULL) {
421 		data = knot_edns_opt_get_data((uint8_t *)opt);
422 		data_len = knot_edns_opt_get_length((uint8_t *)opt);
423 	}
424 
425 	int ret = knot_edns_cookie_parse(cc, sc, data, data_len);
426 	is_int(code, ret, "cookie parse ret: %s", msg);
427 }
428 
ok_cookie_check(const char * opt,knot_edns_cookie_t * cc,knot_edns_cookie_t * sc,uint16_t cc_len,uint16_t sc_len,const char * msg)429 static void ok_cookie_check(const char *opt, knot_edns_cookie_t *cc,
430                             knot_edns_cookie_t *sc, uint16_t cc_len, uint16_t sc_len,
431                             const char *msg)
432 {
433 	check_cookie_parse(opt, cc, sc, KNOT_EOK, msg);
434 
435 	is_int(cc->len, cc_len, "cookie parse cc len: %s", msg);
436 	is_int(sc->len, sc_len, "cookie parse cc len: %s", msg);
437 
438 	uint16_t size = knot_edns_cookie_size(cc, sc);
439 	is_int(size, cc_len + sc_len, "cookie len: %s", msg);
440 
441 	uint8_t buf[64];
442 	int ret = knot_edns_cookie_write(buf, sizeof(buf), cc, sc);
443 	is_int(KNOT_EOK, ret, "cookie write ret: %s", msg);
444 }
445 
test_cookie(void)446 static void test_cookie(void)
447 {
448 	const char *good[] = {
449 		"\x00\x0a" "\x00\x08" "\x00\x01\x02\x03\x04\x05\x06\x07", /* Only client cookie. */
450 		"\x00\x0a" "\x00\x10" "\x00\x01\x02\x03\x04\x05\x06\x07" "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f", /* 8 octets long server cookie. */
451 		"\x00\x0a" "\x00\x28" "\x00\x01\x02\x03\x04\x05\x06\x07" "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27" /* 32 octets long server cookie. */
452 	};
453 
454 	const char *bad[] = {
455 		"\x00\x0a" "\x00\x00", /* Zero length cookie. */
456 		"\x00\x0a" "\x00\x01" "\x00", /* Short client cookie. */
457 		"\x00\x0a" "\x00\x07" "\x00\x01\x02\x03\x04\x05\x06", /* Short client cookie. */
458 		"\x00\x0a" "\x00\x09" "\x00\x01\x02\x03\x04\x05\x06\x07" "\x08", /* Short server cookie. */
459 		"\x00\x0a" "\x00\x0f" "\x00\x01\x02\x03\x04\x05\x06\x07" "\x08\x09\x0a\x0b\x0c\x0d\x0e", /* Short server cookie. */
460 		"\x00\x0a" "\x00\x29" "\x00\x01\x02\x03\x04\x05\x06\x07" "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28", /* Long server cookie. */
461 	};
462 
463 	knot_edns_cookie_t cc, sc;
464 
465 	ok_cookie_check(good[0], &cc,  &sc, 8, 0,  "good cookie 0");
466 	ok_cookie_check(good[1], &cc,  &sc, 8, 8,  "good cookie 1");
467 	ok_cookie_check(good[2], &cc,  &sc, 8, 32, "good cookie 2");
468 
469 	check_cookie_parse(NULL,    &cc,  &sc,  KNOT_EINVAL, "no data");
470 	check_cookie_parse(good[0], NULL, &sc,  KNOT_EINVAL, "no client cookie");
471 	check_cookie_parse(good[1], &cc,  NULL, KNOT_EINVAL, "no server cookie");
472 
473 	check_cookie_parse(bad[0],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 0");
474 	check_cookie_parse(bad[1],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 1");
475 	check_cookie_parse(bad[2],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 2");
476 	check_cookie_parse(bad[3],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 3");
477 	check_cookie_parse(bad[4],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 4");
478 	check_cookie_parse(bad[5],  &cc,  &sc,  KNOT_EMALF,  "bad cookie 5");
479 }
480 
main(int argc,char * argv[])481 int main(int argc, char *argv[])
482 {
483 	plan_lazy();
484 
485 	knot_rrset_t opt_rr;
486 	int ret = knot_edns_init(&opt_rr, E_MAX_PLD, E_RCODE, E_VERSION, NULL);
487 	is_int(KNOT_EOK, ret, "OPT RR: init");
488 
489 	/* Check initialized values (no NSID yet). */
490 	check_header(&opt_rr, E_MAX_PLD, E_VERSION, 0, E_RCODE, "OPT RR: check header");
491 
492 	test_setters(&opt_rr);
493 	test_getters(&opt_rr);
494 	test_alignment();
495 	test_keepalive();
496 	test_chain();
497 	test_cookie();
498 
499 	knot_rrset_clear(&opt_rr, NULL);
500 
501 	return 0;
502 }
503