1 /*
2 * Copyright (c) 2016-2021, OARC, Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include "config.h"
36
37 #include "dump_cds.h"
38 #include "dnscap.h"
39 #include "hashtbl.h"
40 #include "iaddr.h"
41
42 #if HAVE_LIBTINYCBOR
43
44 #include <stdlib.h>
45 #if HAVE_TINYCBOR_CBOR_H
46 #include <tinycbor/cbor.h>
47 #endif
48 #if HAVE_CBOR_H
49 #include <cbor.h>
50 #endif
51 #include <assert.h>
52
53 #define need8(v, p, l, d) \
54 if (l < 1) { \
55 if (sizeof(d) > 1) \
56 fprintf(stderr, "cds need 1B/8b, had %lu: %s\n", l, d); \
57 return 1; \
58 } \
59 v = *p; \
60 p += 1; \
61 l -= 1
62
63 #define need16(v, p, l, d) \
64 if (l < 2) { \
65 if (sizeof(d) > 1) \
66 fprintf(stderr, "cds need 2B/16b, had %lu: %s\n", l, d); \
67 return 1; \
68 } \
69 v = (*p << 8) + *(p + 1); \
70 p += 2; \
71 l -= 2
72
73 #define need32(v, p, l, d) \
74 if (l < 4) { \
75 if (sizeof(d) > 1) \
76 fprintf(stderr, "cds need 4B/32b, had %lu: %s\n", l, d); \
77 return 1; \
78 } \
79 v = (*p << 24) + (*(p + 1) << 16) + (*(p + 2) << 8) + *(p + 3); \
80 p += 4; \
81 l -= 4
82
83 #define need64(v, p, l, d) \
84 if (l < 8) { \
85 if (sizeof(d) > 1) \
86 fprintf(stderr, "cds need 8B/64b, had %lu: %s\n", l, d); \
87 return 1; \
88 } \
89 v = (*p << 56) + (*(p + 1) << 48) + (*(p + 2) << 40) + (*(p + 3) << 32) + (*(p + 4) << 24) + (*(p + 5) << 16) + (*(p + 6) << 8) + *(p + 7); \
90 p += 8; \
91 l -= 8
92
93 #define needxb(b, x, p, l, d) \
94 if (l < x) { \
95 if (sizeof(d) > 1) \
96 fprintf(stderr, "cds need %d bytes, had %lu: %s\n", x, l, d); \
97 return 1; \
98 } \
99 memcpy(b, p, x); \
100 p += x; \
101 l -= x
102
103 #define advancexb(x, p, l, d) \
104 if (l < x) { \
105 if (sizeof(d) > 1) \
106 fprintf(stderr, "cds needed to advance %d bytes, had %lu: %s\n", x, l, d); \
107 return 1; \
108 } \
109 p += x; \
110 l -= x
111
112 static uint8_t* cbor_buf = 0;
113 static uint8_t* cbor_buf_p = 0;
114 static size_t cbor_size = 1024 * 1024;
115 static uint8_t* message_buf = 0;
116 static size_t message_size = 64 * 1024;
117 static int cbor_flushed = 1;
118 static hashtbl* rdata_tbl = 0;
119 static size_t MAX_RLABELS = CDS_DEFAULT_MAX_RLABELS;
120 static size_t MIN_RLABEL_SIZE = CDS_DEFAULT_MIN_RLABEL_SIZE;
121 static int use_rdata_index = 0;
122 static int use_rdata_rindex = 0;
123 static size_t RDATA_RINDEX_SIZE = CDS_DEFAULT_RDATA_RINDEX_SIZE;
124 static size_t RDATA_RINDEX_MIN_SIZE = CDS_DEFAULT_RDATA_RINDEX_MIN_SIZE;
125 static size_t RDATA_INDEX_MIN_SIZE = CDS_DEFAULT_RDATA_INDEX_MIN_SIZE;
126
127 struct rdata;
128 struct rdata {
129 struct rdata* prev;
130 struct rdata* next;
131 uint8_t* data;
132 size_t len;
133 size_t idx;
134 };
135
136 struct last {
137 my_bpftimeval ts;
138 ip_header_t ip;
139
140 uint16_t dns_type;
141 uint16_t dns_class;
142 uint32_t dns_ttl;
143
144 dns_rlabel_t* dns_rlabel;
145 dns_rlabel_t* dns_rlabel_last;
146 size_t dns_rlabels;
147
148 size_t rdata_index;
149 size_t rdata_num;
150 struct rdata* rdata;
151 struct rdata* rdata_last;
152 };
153 static struct last last;
154
155 /*
156 * Set/Get
157 */
158
cds_set_cbor_size(size_t size)159 int cds_set_cbor_size(size_t size)
160 {
161 if (!size) {
162 return DUMP_CDS_EINVAL;
163 }
164
165 cbor_size = size;
166 if (message_size > cbor_size) {
167 message_size = cbor_size;
168 }
169
170 return DUMP_CDS_OK;
171 }
172
cds_set_message_size(size_t size)173 int cds_set_message_size(size_t size)
174 {
175 if (!size) {
176 return DUMP_CDS_EINVAL;
177 }
178
179 message_size = size;
180 if (message_size > cbor_size) {
181 message_size = cbor_size;
182 }
183
184 return DUMP_CDS_OK;
185 }
186
cds_set_max_rlabels(size_t size)187 int cds_set_max_rlabels(size_t size)
188 {
189 if (!size) {
190 return DUMP_CDS_EINVAL;
191 }
192
193 MAX_RLABELS = size;
194
195 return DUMP_CDS_OK;
196 }
197
cds_set_min_rlabel_size(size_t size)198 int cds_set_min_rlabel_size(size_t size)
199 {
200 if (!size) {
201 return DUMP_CDS_EINVAL;
202 }
203
204 MIN_RLABEL_SIZE = size;
205
206 return DUMP_CDS_OK;
207 }
208
cds_set_use_rdata_index(int use)209 int cds_set_use_rdata_index(int use)
210 {
211 use_rdata_index = use ? 1 : 0;
212
213 return DUMP_CDS_OK;
214 }
215
cds_set_use_rdata_rindex(int use)216 int cds_set_use_rdata_rindex(int use)
217 {
218 use_rdata_rindex = use ? 1 : 0;
219
220 return DUMP_CDS_OK;
221 }
222
cds_set_rdata_index_min_size(size_t size)223 int cds_set_rdata_index_min_size(size_t size)
224 {
225 if (!size) {
226 return DUMP_CDS_EINVAL;
227 }
228
229 RDATA_INDEX_MIN_SIZE = size;
230
231 return DUMP_CDS_OK;
232 }
233
cds_set_rdata_rindex_min_size(size_t size)234 int cds_set_rdata_rindex_min_size(size_t size)
235 {
236 if (!size) {
237 return DUMP_CDS_EINVAL;
238 }
239
240 RDATA_RINDEX_MIN_SIZE = size;
241
242 return DUMP_CDS_OK;
243 }
244
cds_set_rdata_rindex_size(size_t size)245 int cds_set_rdata_rindex_size(size_t size)
246 {
247 if (!size) {
248 return DUMP_CDS_EINVAL;
249 }
250
251 RDATA_RINDEX_SIZE = size;
252
253 return DUMP_CDS_OK;
254 }
255
256 /*
257 * DNS
258 */
259
check_dns_label(size_t * labels,uint8_t ** p,size_t * l)260 static int check_dns_label(size_t* labels, uint8_t** p, size_t* l)
261 {
262 uint8_t len;
263
264 while (1) {
265 need8(len, *p, *l, "");
266 *labels += 1;
267
268 if ((len & 0xc0) == 0xc0) {
269 advancexb(1, *p, *l, "");
270 break;
271 } else if (len & 0xc0) {
272 break;
273 } else if (len) {
274 advancexb(len, *p, *l, "");
275 } else {
276 break;
277 }
278 }
279
280 return 0;
281 }
282
rdata_hash(const void * _item)283 static unsigned int rdata_hash(const void* _item)
284 {
285 const struct rdata* item = (const struct rdata*)_item;
286 size_t n, o, p;
287 unsigned int key = 0;
288
289 for (n = 0, o = 0, p = 0; n < item->len; n++) {
290 p |= item->data[n] << (o * 8);
291 o++;
292 if (o > 3) {
293 key ^= p;
294 p = 0;
295 o = 0;
296 }
297 }
298 if (o) {
299 key ^= p;
300 }
301
302 return key;
303 }
304
rdata_cmp(const void * _a,const void * _b)305 static int rdata_cmp(const void* _a, const void* _b)
306 {
307 const struct rdata *a = (const struct rdata*)_a, *b = (const struct rdata*)_b;
308
309 if (a->len == b->len) {
310 return memcmp(a->data, b->data, a->len);
311 } else if (a->len < b->len)
312 return -1;
313 return 1;
314 }
315
rdata_free(void * d)316 static void rdata_free(void* d)
317 {
318 struct rdata* item = (struct rdata*)d;
319
320 if (item) {
321 if (item->data) {
322 free(item->data);
323 }
324 free(item);
325 }
326 }
327
rdata_add(uint8_t * p,size_t len)328 static int rdata_add(uint8_t* p, size_t len)
329 {
330 struct rdata* key;
331
332 if (len < RDATA_INDEX_MIN_SIZE)
333 return 1;
334
335 if (!(key = calloc(1, sizeof(struct rdata)))) {
336 return 0;
337 }
338 if (!(key->data = calloc(1, len))) {
339 free(key);
340 return 0;
341 }
342
343 key->len = len;
344 memcpy(key->data, p, len);
345 key->idx = last.rdata_index++;
346
347 /* printf("rdata_add %u: ", rdata_hash(key));*/
348 /* {*/
349 /* size_t n = len;*/
350 /* uint8_t* x = p;*/
351 /* while (n--) {*/
352 /* printf("%02x", *x);*/
353 /* x++;*/
354 /* }*/
355 /* }*/
356 /* printf("\n");*/
357 hash_add(key, key, rdata_tbl);
358
359 return 0;
360 }
361
rdata_find(uint8_t * p,size_t len,size_t * found)362 static size_t rdata_find(uint8_t* p, size_t len, size_t* found)
363 {
364 struct rdata key;
365 struct rdata* r;
366
367 if (len < RDATA_INDEX_MIN_SIZE)
368 return 1;
369
370 key.data = p;
371 key.len = len;
372
373 /* printf("rdata_find %u: ", rdata_hash(&key));*/
374 /* {*/
375 /* size_t n = len;*/
376 /* uint8_t* x = p;*/
377 /* while (n--) {*/
378 /* printf("%02x", *x);*/
379 /* x++;*/
380 /* }*/
381 /* }*/
382 /* printf("\n");*/
383
384 if ((r = hash_find(&key, rdata_tbl))) {
385 /* printf("rdata found %lu at %lu\n", len, found->idx);*/
386 *found = r->idx;
387 return 0;
388 }
389
390 return 1;
391 }
392
rdata_find2(uint8_t * p,size_t len,size_t * found)393 int rdata_find2(uint8_t* p, size_t len, size_t* found)
394 {
395 struct rdata* r = last.rdata;
396 size_t n = 0;
397
398 if (len < RDATA_RINDEX_MIN_SIZE)
399 return 1;
400
401 while (r) {
402 if (r->len == len && !memcmp(p, r->data, len)) {
403 break;
404 }
405 r = r->next;
406 n++;
407 }
408 if (r) {
409 /* printf("rdata found at %lu: ", n);*/
410 /* {*/
411 /* size_t n = len;*/
412 /* uint8_t* x = p;*/
413 /* while (n--) {*/
414 /* printf("%02x", *x);*/
415 /* x++;*/
416 /* }*/
417 /* }*/
418 /* printf("\n");*/
419
420 if (last.rdata != r) {
421 struct rdata *prev = r->prev, *next = r->next;
422
423 if (prev) {
424 prev->next = next;
425 }
426 if (next) {
427 next->prev = prev;
428 }
429
430 r->prev = 0;
431 r->next = last.rdata;
432 last.rdata->prev = r;
433 last.rdata = r;
434 }
435
436 *found = n;
437 return 0;
438 }
439
440 return 1;
441 }
442
rdata_add2(uint8_t * p,size_t len)443 int rdata_add2(uint8_t* p, size_t len)
444 {
445 struct rdata* r;
446
447 if (len < RDATA_RINDEX_MIN_SIZE)
448 return 1;
449
450 if (!(r = calloc(1, sizeof(struct rdata)))) {
451 return -1;
452 }
453 if (!(r->data = calloc(1, len))) {
454 free(r);
455 return -1;
456 }
457
458 r->len = len;
459 memcpy(r->data, p, len);
460
461 /* printf("rdata_add: ");*/
462 /* {*/
463 /* size_t n = len;*/
464 /* uint8_t* x = p;*/
465 /* while (n--) {*/
466 /* printf("%02x", *x);*/
467 /* x++;*/
468 /* }*/
469 /* }*/
470 /* printf("\n");*/
471
472 if (last.rdata) {
473 last.rdata->prev = r;
474 }
475 r->next = last.rdata;
476 last.rdata = r;
477 last.rdata_num++;
478
479 if (last.rdata_last) {
480 if (last.rdata_num >= RDATA_RINDEX_SIZE) {
481 r = last.rdata_last;
482
483 last.rdata_last = r->prev;
484 last.rdata_last->next = 0;
485 last.rdata_num--;
486 free(r->data);
487 free(r);
488 }
489 } else {
490 last.rdata_last = r;
491 }
492
493 return 0;
494 }
495
parse_dns_rr(char is_q,dns_rr_t * rr,size_t expected_rrs,size_t * actual_rrs,uint8_t ** p,size_t * l)496 static int parse_dns_rr(char is_q, dns_rr_t* rr, size_t expected_rrs, size_t* actual_rrs, uint8_t** p, size_t* l)
497 {
498 uint8_t len;
499 uint8_t* p2;
500 size_t l2, idx;
501 dns_label_t* label;
502 size_t num_labels, offset;
503
504 while (expected_rrs--) {
505 /* first pass check number of labels */
506 p2 = *p;
507 l2 = *l;
508
509 if (check_dns_label(&(rr->labels), &p2, &l2)) {
510 if (!rr->labels) {
511 fprintf(stderr, "cds no labels\n");
512 return 1;
513 }
514 }
515
516 /* second pass, allocate labels and fill */
517 if (!(rr->label = calloc(rr->labels, sizeof(dns_label_t)))) {
518 fprintf(stderr, "cds out of memory\n");
519 return -1;
520 }
521
522 *actual_rrs += 1;
523
524 label = rr->label;
525 rr->have_labels = 1;
526
527 while (1) {
528 need8(len, *p, *l, "name length");
529
530 if ((len & 0xc0) == 0xc0) {
531 label->offset_p = *p;
532 need8(label->offset, *p, *l, "name offset");
533 label->offset |= (len & 0x3f) << 8;
534 label->have_offset = 1;
535 label->is_complete = 1;
536 break;
537 } else if (len & 0xc0) {
538 label->extension_bits = len;
539 label->have_extension_bits = 1;
540 label->is_complete = 1;
541 break;
542 } else if (len) {
543 label->size = len;
544 label->have_size = 1;
545 label->label = *p;
546 advancexb(len, *p, *l, "name label");
547 label->have_label = 1;
548 } else {
549 label->have_size = 1;
550 label->is_complete = 1;
551 break;
552 }
553
554 label->is_complete = 1;
555 label++;
556 }
557
558 need16(rr->type, *p, *l, "type");
559 rr->have_type = 1;
560 need16(rr->class, *p, *l, "class");
561 rr->have_class = 1;
562
563 if (!is_q) {
564 need32(rr->ttl, *p, *l, "ttl");
565 rr->have_ttl = 1;
566 need16(rr->rdlength, *p, *l, "rdlength");
567 rr->have_rdlength = 1;
568 rr->rdata = *p;
569 advancexb(rr->rdlength, *p, *l, "rdata");
570
571 if (use_rdata_index) {
572 if (!rdata_find(rr->rdata, rr->rdlength, &(rr->rdata_index))) {
573 rr->have_rdata_index = 1;
574 } else {
575 rdata_add(rr->rdata, rr->rdlength);
576 }
577 } else if (use_rdata_rindex) {
578 if (!rdata_find2(rr->rdata, rr->rdlength, &(rr->rdata_rindex))) {
579 rr->have_rdata_rindex = 1;
580 } else {
581 rdata_add2(rr->rdata, rr->rdlength);
582 }
583 }
584
585 num_labels = offset = 0;
586 switch (rr->type) {
587 case 2: /* NS */
588 case 3: /* MD */
589 case 4: /* MF */
590 case 5: /* CNAME */
591 case 7: /* MB */
592 case 8: /* MG */
593 case 9: /* MR */
594 case 12: /* PTR */
595 case 30: /* NXT */
596 case 39: /* DNAME */
597 case 47: /* NSEC */
598 case 249: /* TKEY */
599 case 250: /* TSIG */
600 num_labels = 1;
601 break;
602
603 case 6: /* SOA */
604 case 14: /* MINFO */
605 case 17: /* RP */
606 case 58: /* TALINK */
607 num_labels = 2;
608 break;
609
610 case 15: /* MX */
611 case 18: /* AFSDB */
612 case 21: /* RT */
613 case 36: /* KX */
614 case 107: /* LP */
615 num_labels = 1;
616 offset = 2;
617 break;
618
619 case 26: /* PX */
620 num_labels = 2;
621 offset = 2;
622 break;
623
624 case 24: /* SIG */
625 case 46: /* RRSIG */
626 num_labels = 1;
627 offset = 18;
628 break;
629
630 case 33: /* SRV */
631 num_labels = 1;
632 offset = 6;
633 break;
634
635 case 35: /* NAPTR */
636 num_labels = 1;
637 p2 = *p;
638 l2 = *l;
639 advancexb(2, p2, l2, "naptr int16 #1");
640 advancexb(2, p2, l2, "naptr int16 #2");
641 need8(len, p2, l2, "naptr str len #1");
642 advancexb(len, p2, l2, "naptr str #1");
643 need8(len, p2, l2, "naptr str len #2");
644 advancexb(len, p2, l2, "naptr str #2");
645 need8(len, p2, l2, "naptr str len #3");
646 advancexb(len, p2, l2, "naptr str #3");
647 offset = p2 - *p;
648 break;
649
650 case 55: /* HIP TODO */
651 break;
652 }
653
654 if (num_labels) {
655 dns_rdata_t* rdata;
656
657 rr->mixed_rdatas = num_labels + (offset ? 1 : 0) + 1;
658 if (!(rr->mixed_rdata = calloc(rr->mixed_rdatas, sizeof(dns_rdata_t)))) {
659 fprintf(stderr, "cds out of memory\n");
660 return -1;
661 }
662
663 p2 = rr->rdata;
664 l2 = rr->rdlength;
665 rdata = rr->mixed_rdata;
666 rr->have_mixed_rdata = 1;
667
668 if (offset) {
669 rdata->rdata_len = offset;
670 rdata->rdata = p2;
671 advancexb((int)offset, p2, l2, "mixed rdata");
672 rdata->have_rdata = 1;
673 rdata->is_complete = 1;
674 rdata++;
675 }
676 while (num_labels--) {
677 uint8_t* p3;
678 size_t l3;
679
680 /* first pass check number of rdata labels */
681
682 p3 = p2;
683 l3 = l2;
684
685 if (check_dns_label(&(rdata->labels), &p3, &l3)) {
686 if (!rdata->labels) {
687 fprintf(stderr, "cds mixed rdata no labels\n");
688 return 1;
689 }
690 }
691
692 /* second pass, allocate mixed rdata */
693 if (!(rdata->label = calloc(rdata->labels, sizeof(dns_label_t)))) {
694 fprintf(stderr, "cds out of memory\n");
695 return -1;
696 }
697
698 label = rdata->label;
699 rdata->have_labels = 1;
700 while (1) {
701 need8(len, p2, l2, "name length");
702
703 if ((len & 0xc0) == 0xc0) {
704 label->offset_p = p2;
705 need8(label->offset, p2, l2, "name offset");
706 label->offset |= (len & 0x3f) << 8;
707 label->have_offset = 1;
708 label->is_complete = 1;
709 break;
710 } else if (len & 0xc0) {
711 label->extension_bits = len;
712 label->have_extension_bits = 1;
713 label->is_complete = 1;
714 break;
715 } else if (len) {
716 label->size = len;
717 label->have_size = 1;
718 label->label = p2;
719 advancexb(len, p2, l2, "name label");
720 label->have_label = 1;
721 } else {
722 label->have_size = 1;
723 label->is_complete = 1;
724 break;
725 }
726
727 label->is_complete = 1;
728 label++;
729 }
730 rdata->is_complete = 1;
731 rdata++;
732 }
733 if (l2) {
734 /*printf("last rdata %lu\n", l2);*/
735 rdata->rdata_len = l2;
736 rdata->rdata = p2;
737 advancexb((int)l2, p2, l2, "mixed rdata");
738 rdata->have_rdata = 1;
739 rdata->is_complete = 1;
740 } else {
741 rr->mixed_rdatas--;
742 }
743 }
744 rr->have_rdata = 1;
745 }
746
747 rr->is_complete = 1;
748 rr++;
749 }
750
751 return 0;
752 }
753
754 int print_cbor = 0;
755
parse_dns(dns_t * dns,uint8_t ** p,size_t * l)756 static int parse_dns(dns_t* dns, uint8_t** p, size_t* l)
757 {
758 int ret;
759
760 need16(dns->id, *p, *l, "dns id");
761 dns->have_id = 1;
762 need16(dns->raw, *p, *l, "raw dns bits");
763 dns->have_raw = 1;
764 need16(dns->qdcount, *p, *l, "qdcount");
765 dns->have_qdcount = 1;
766 need16(dns->ancount, *p, *l, "ancount");
767 dns->have_ancount = 1;
768 need16(dns->nscount, *p, *l, "nscount");
769 dns->have_nscount = 1;
770 need16(dns->arcount, *p, *l, "arcount");
771 dns->have_arcount = 1;
772
773 dns->header_is_complete = 1;
774
775 if (dns->qdcount) {
776 if (!(dns->question = calloc(dns->qdcount, sizeof(dns_rr_t)))) {
777 fprintf(stderr, "cds out of memory\n");
778 return -1;
779 }
780 ret = parse_dns_rr(1, dns->question, dns->qdcount, &(dns->questions), p, l);
781 /*if (ret) printf("qr %d\n", ret);*/
782 if (ret > -1 && dns->questions) {
783 dns->have_questions = 1;
784 }
785 if (ret) {
786 return ret;
787 }
788 }
789
790 if (dns->ancount) {
791 if (!(dns->answer = calloc(dns->ancount, sizeof(dns_rr_t)))) {
792 fprintf(stderr, "cds out of memory\n");
793 return -1;
794 }
795 ret = parse_dns_rr(0, dns->answer, dns->ancount, &(dns->answers), p, l);
796 /*if (ret) printf("an %d\n", ret);*/
797 if (ret > -1 && dns->answers) {
798 dns->have_answers = 1;
799 }
800 if (ret) {
801 return ret;
802 }
803 }
804
805 if (dns->nscount) {
806 if (!(dns->authority = calloc(dns->nscount, sizeof(dns_rr_t)))) {
807 fprintf(stderr, "cds out of memory\n");
808 return -1;
809 }
810 ret = parse_dns_rr(0, dns->authority, dns->nscount, &(dns->authorities), p, l);
811 /*if (ret) { printf("ns %d %lu\n", ret, dns->authorities);*/
812 /*{*/
813 /* size_t n;*/
814 /* for (n = 0; n < dns->authorities; n++) {*/
815 /* printf("%lu %d\n", n, dns->authority[n].is_complete);*/
816 /* if (!dns->authority[n].is_complete) print_cbor = 1;*/
817 /* }*/
818 /*} }*/
819 if (ret > -1 && dns->authorities) {
820 dns->have_authorities = 1;
821 }
822 if (ret) {
823 return ret;
824 }
825 }
826
827 if (dns->arcount) {
828 if (!(dns->additional = calloc(dns->arcount, sizeof(dns_rr_t)))) {
829 fprintf(stderr, "cds out of memory\n");
830 return -1;
831 }
832 ret = parse_dns_rr(0, dns->additional, dns->arcount, &(dns->additionals), p, l);
833 /*if (ret) printf("ar %d\n", ret);*/
834 if (ret > -1 && dns->additionals) {
835 dns->have_additionals = 1;
836 }
837 if (ret) {
838 return ret;
839 }
840 }
841
842 return 0;
843 }
844
encode_label(CborEncoder * encoder,dns_label_t * label,size_t labels)845 static CborError encode_label(CborEncoder* encoder, dns_label_t* label, size_t labels)
846 {
847 CborError cbor_err = CborNoError;
848 CborEncoder array;
849
850 if (labels && label[labels - 1].have_size && !label[labels - 1].size) {
851 labels--;
852 }
853
854 cbor_err = cbor_encoder_create_array(encoder, &array, labels);
855 while (labels--) {
856 if (label->have_offset) {
857 if (label->have_n_offset) {
858 if (cbor_err == CborNoError)
859 cbor_err = cbor_encode_uint(&array, label->n_offset);
860 } else {
861 if (cbor_err == CborNoError)
862 cbor_err = cbor_encode_negative_int(&array, label->offset);
863 }
864 } else if (label->have_extension_bits) {
865 if (cbor_err == CborNoError)
866 cbor_err = cbor_encode_simple_value(&array, label->extension_bits >> 6);
867 } else if (label->have_label) {
868 if (cbor_err == CborNoError)
869 cbor_err = cbor_encode_text_string(&array, (const char*)label->label, label->size);
870 } else {
871 if (cbor_err == CborNoError)
872 cbor_err = cbor_encode_null(&array);
873 }
874
875 label++;
876 }
877 if (cbor_err == CborNoError)
878 cbor_err = cbor_encoder_close_container_checked(encoder, &array);
879
880 return cbor_err;
881 }
882
883 /*
884 * OUTPUT
885 */
886
print_label(dns_label_t * label,size_t labels)887 int print_label(dns_label_t* label, size_t labels)
888 {
889 size_t n;
890
891 for (n = 0; n < labels; n++) {
892 if (label[n].have_offset) {
893 if (label[n].have_n_offset) {
894 printf(" %lu", label[n].n_offset);
895 } else {
896 printf(" %d", -label[n].offset);
897 }
898 } else if (label[n].have_extension_bits) {
899 printf(" %x", label[n].extension_bits);
900 } else if (label[n].have_label) {
901 printf(" %.*s", label[n].size, label[n].label);
902 } else {
903 printf(" $");
904 }
905 }
906 return 0;
907 }
908
print_rlabel(dns_rlabel_t * label)909 int print_rlabel(dns_rlabel_t* label)
910 {
911 size_t n;
912
913 for (n = 0; n < label->labels; n++) {
914 if (label->label[n].size) {
915 printf(" %.*s", label->label[n].size, label->label[n].label);
916 } else if (label->label[n].have_n_offset) {
917 printf(" %lu", label->label[n].n_offset);
918 } else {
919 printf(" $");
920 }
921 }
922 return 0;
923 }
924
dns_rlabel_add(dns_label_t * label,size_t labels)925 int dns_rlabel_add(dns_label_t* label, size_t labels)
926 {
927 dns_rlabel_t* copy;
928 size_t n, size = 0;
929
930 for (n = 0; n < labels; n++) {
931 if ((label[n].have_offset && !label[n].have_n_offset)
932 || label[n].have_extension_bits) {
933 return 1;
934 }
935 if (label[n].have_size) {
936 size += label[n].size;
937 }
938 }
939 /*printf("label size: %lu\n", size);*/
940 if (size < MIN_RLABEL_SIZE) {
941 return 1;
942 }
943
944 if (!(copy = calloc(1, sizeof(dns_rlabel_t)))) {
945 return -1;
946 }
947
948 assert(labels <= CDS_RLABEL_T_LABELS);
949 copy->labels = labels;
950
951 for (n = 0; n < labels; n++) {
952 if (label[n].have_n_offset) {
953 copy->label[n].have_n_offset = 1;
954 copy->label[n].n_offset = label[n].n_offset;
955 continue;
956 }
957 if (label[n].size) {
958 assert(label[n].size <= CDS_RLABEL_LABEL_T_LABEL);
959
960 copy->label[n].size = label[n].size;
961 memcpy(&(copy->label[n].label), label[n].label, label[n].size);
962 }
963 }
964
965 /*printf("add"); print_label(label, labels); printf("\n");*/
966
967 if (last.dns_rlabel) {
968 last.dns_rlabel->prev = copy;
969 }
970 copy->next = last.dns_rlabel;
971 last.dns_rlabel = copy;
972 last.dns_rlabels++;
973 if (last.dns_rlabel_last) {
974 if (last.dns_rlabels >= MAX_RLABELS) {
975 dns_rlabel_t* remove = last.dns_rlabel_last;
976
977 /*printf("remove %p %p\n", remove, remove->prev);*/
978
979 last.dns_rlabel_last = remove->prev;
980 last.dns_rlabel_last->next = 0;
981 free(remove);
982 last.dns_rlabels--;
983 }
984 } else {
985 last.dns_rlabel_last = copy;
986 }
987
988 return 0;
989 }
990
dns_rlabel_find(dns_label_t * label,size_t labels,size_t * rlabel_idx)991 static size_t dns_rlabel_find(dns_label_t* label, size_t labels, size_t* rlabel_idx)
992 {
993 size_t n, n2, size = 0;
994 dns_rlabel_t* rlabel;
995
996 for (n = 0; n < labels; n++) {
997 if ((label[n].have_offset && !label[n].have_n_offset)
998 || label[n].have_extension_bits) {
999 return 1;
1000 }
1001 if (label[n].have_size) {
1002 size += label[n].size;
1003 }
1004 }
1005 /*printf("label size: %lu\n", size);*/
1006 if (size < MIN_RLABEL_SIZE) {
1007 return 1;
1008 }
1009
1010 /*printf("find"); print_label(label, labels); printf("\n");*/
1011
1012 n = 0;
1013 rlabel = last.dns_rlabel;
1014 while (rlabel) {
1015 if (rlabel->labels == labels) {
1016 /*printf("check"); print_rlabel(rlabel); printf("\n");*/
1017
1018 for (n2 = 0; n2 < labels; n2++) {
1019 /*printf("%d %lu <> %d %lu\n", label[n2].have_n_offset, label[n2].n_offset, rlabel->label[n2].have_n_offset, rlabel->label[n2].n_offset);*/
1020 if (label[n2].have_n_offset
1021 || rlabel->label[n2].have_n_offset) {
1022 if (label[n2].n_offset == rlabel->label[n2].n_offset)
1023 continue;
1024 } else if (label[n2].size == rlabel->label[n2].size
1025 && !memcmp(label[n2].label, rlabel->label[n2].label, label[n2].size)) {
1026 continue;
1027 }
1028 break;
1029 }
1030
1031 if (n2 == labels) {
1032 /*printf("found at %lu: ", n); print_rlabel(rlabel); printf("\n");*/
1033 break;
1034 }
1035 }
1036 rlabel = rlabel->next;
1037 n++;
1038 }
1039 if (rlabel) {
1040 if (last.dns_rlabel != rlabel) {
1041 dns_rlabel_t *prev = rlabel->prev, *next = rlabel->next;
1042
1043 if (prev) {
1044 prev->next = next;
1045 }
1046 if (next) {
1047 next->prev = prev;
1048 }
1049
1050 rlabel->prev = 0;
1051 rlabel->next = last.dns_rlabel;
1052 last.dns_rlabel->prev = rlabel;
1053 last.dns_rlabel = rlabel;
1054 }
1055
1056 *rlabel_idx = n;
1057 return 0;
1058 }
1059
1060 return 1;
1061 }
1062
free_rdata(dns_rdata_t * rdata)1063 static void free_rdata(dns_rdata_t* rdata)
1064 {
1065 if (rdata->label) {
1066 free(rdata->label);
1067 }
1068 }
1069
free_rr(dns_rr_t * rr)1070 static void free_rr(dns_rr_t* rr)
1071 {
1072 size_t n;
1073
1074 if (rr->label) {
1075 free(rr->label);
1076 }
1077 for (n = 0; n < rr->mixed_rdatas; n++) {
1078 free_rdata(&(rr->mixed_rdata[n]));
1079 }
1080 if (rr->mixed_rdata) {
1081 free(rr->mixed_rdata);
1082 }
1083 }
1084
free_dns(dns_t * dns)1085 static void free_dns(dns_t* dns)
1086 {
1087 size_t n;
1088
1089 for (n = 0; n < dns->questions; n++) {
1090 free_rr(&(dns->question[n]));
1091 }
1092 for (n = 0; n < dns->answers; n++) {
1093 free_rr(&(dns->answer[n]));
1094 }
1095 for (n = 0; n < dns->authorities; n++) {
1096 free_rr(&(dns->authority[n]));
1097 }
1098 for (n = 0; n < dns->additionals; n++) {
1099 free_rr(&(dns->additional[n]));
1100 }
1101 }
1102
dns_rr_build_offset(dns_rr_t * rr_list,size_t count,uint16_t * offset,size_t offsets,size_t * n_offset,const u_char * payload)1103 void dns_rr_build_offset(dns_rr_t* rr_list, size_t count, uint16_t* offset, size_t offsets, size_t* n_offset, const u_char* payload)
1104 {
1105 dns_rr_t* rrp;
1106 size_t rr, n, n2;
1107
1108 for (rr = 0; rr < count && *n_offset < offsets; rr++) {
1109 rrp = &(rr_list[rr]);
1110
1111 for (n = 0; n < rrp->labels && *n_offset < offsets; n++) {
1112 if (rrp->label[n].size) {
1113 rrp->label[n].offset = rrp->label[n].label - payload - 1;
1114 offset[*n_offset] = rrp->label[n].offset;
1115 *n_offset += 1;
1116 } else if (rrp->label[n].have_offset) {
1117 offset[*n_offset] = rrp->label[n].offset_p - payload - 1;
1118 *n_offset += 1;
1119 }
1120
1121 /* printf("%u %u %u %.*s\n",*/
1122 /* rrp->label[n].size,*/
1123 /* rrp->label[n].extension_bits,*/
1124 /* rrp->label[n].offset,*/
1125 /* rrp->label[n].size ? rrp->label[n].size : 0,*/
1126 /* rrp->label[n].size ? (char*)rrp->label[n].label : ""*/
1127 /* );*/
1128 }
1129 for (n = 0; n < rrp->mixed_rdatas && *n_offset < offsets; n++) {
1130 for (n2 = 0; n2 < rrp->mixed_rdata[n].labels; n2++) {
1131 if (rrp->mixed_rdata[n].label[n2].size) {
1132 rrp->mixed_rdata[n].label[n2].offset = rrp->mixed_rdata[n].label[n2].label - payload - 1;
1133 offset[*n_offset] = rrp->mixed_rdata[n].label[n2].offset;
1134 *n_offset += 1;
1135 } else if (rrp->mixed_rdata[n].label[n2].have_offset) {
1136 offset[*n_offset] = rrp->mixed_rdata[n].label[n2].offset_p - payload - 1;
1137 *n_offset += 1;
1138 }
1139
1140 /* printf(" %u %u %u %.*s\n",*/
1141 /* rrp->mixed_rdata[n].label[n2].size,*/
1142 /* rrp->mixed_rdata[n].label[n2].extension_bits,*/
1143 /* rrp->mixed_rdata[n].label[n2].offset,*/
1144 /* rrp->mixed_rdata[n].label[n2].size ? rrp->mixed_rdata[n].label[n2].size : 0,*/
1145 /* rrp->mixed_rdata[n].label[n2].size ? (char*)rrp->mixed_rdata[n].label[n2].label : ""*/
1146 /* );*/
1147 }
1148 }
1149 }
1150 }
1151
dns_rr_set_offset(dns_rr_t * rr_list,size_t count,uint16_t * offset,size_t n_offset)1152 void dns_rr_set_offset(dns_rr_t* rr_list, size_t count, uint16_t* offset, size_t n_offset)
1153 {
1154 dns_rr_t* rrp;
1155 size_t rr, n, n2, n3;
1156
1157 for (rr = 0; rr < count; rr++) {
1158 rrp = &(rr_list[rr]);
1159
1160 for (n = 0; n < rrp->labels; n++) {
1161 if (!rrp->label[n].size && rrp->label[n].offset) {
1162 for (n3 = 0; n3 < n_offset; n3++) {
1163 if (rrp->label[n].offset == offset[n3]) {
1164 /* printf("%u => %lu\n", rrp->label[n].offset, n3);*/
1165 rrp->label[n].n_offset = n3;
1166 rrp->label[n].have_n_offset = 1;
1167 break;
1168 }
1169 }
1170 }
1171 }
1172 for (n = 0; n < rrp->mixed_rdatas; n++) {
1173 for (n2 = 0; n2 < rrp->mixed_rdata[n].labels; n2++) {
1174 if (!rrp->mixed_rdata[n].label[n2].size && rrp->mixed_rdata[n].label[n2].offset) {
1175 for (n3 = 0; n3 < n_offset; n3++) {
1176 if (rrp->mixed_rdata[n].label[n2].offset == offset[n3]) {
1177 /* printf("%u => %lu\n", rrp->mixed_rdata[n].label[n2].offset, n3);*/
1178 rrp->mixed_rdata[n].label[n2].n_offset = n3;
1179 rrp->mixed_rdata[n].label[n2].have_n_offset = 1;
1180 break;
1181 }
1182 }
1183 }
1184 }
1185 }
1186 }
1187 }
1188
dns_rr_build_rlabel(dns_rr_t * rr_list,size_t count)1189 void dns_rr_build_rlabel(dns_rr_t* rr_list, size_t count)
1190 {
1191 dns_rr_t* rrp;
1192 size_t rr, n;
1193
1194 for (rr = 0; rr < count; rr++) {
1195 rrp = &(rr_list[rr]);
1196
1197 if (rrp->labels) {
1198 if (!dns_rlabel_find(rrp->label, rrp->labels, &(rrp->rlabel_idx))) {
1199 rrp->have_rlabel_idx = 1;
1200 } else {
1201 dns_rlabel_add(rrp->label, rrp->labels);
1202 }
1203 }
1204
1205 for (n = 0; n < rrp->mixed_rdatas; n++) {
1206 if (rrp->mixed_rdata[n].labels) {
1207 if (!dns_rlabel_find(rrp->mixed_rdata[n].label, rrp->mixed_rdata[n].labels, &(rrp->mixed_rdata[n].rlabel_idx))) {
1208 rrp->mixed_rdata[n].have_rlabel_idx = 1;
1209 } else {
1210 dns_rlabel_add(rrp->mixed_rdata[n].label, rrp->mixed_rdata[n].labels);
1211 }
1212 }
1213 }
1214 }
1215 }
1216
dns_build_rrs(CborEncoder * message,dns_rr_t * rr_list,size_t count)1217 CborError dns_build_rrs(CborEncoder* message, dns_rr_t* rr_list, size_t count)
1218 {
1219 CborError cbor_err = CborNoError;
1220 CborEncoder rrs;
1221 dns_rr_t* rr = rr_list;
1222 size_t n = count;
1223
1224 if (cbor_err == CborNoError)
1225 cbor_err = cbor_encoder_create_array(message, &rrs, n);
1226 while (n--) {
1227 CborEncoder item;
1228 if (!(rr->have_type && rr->type == 41)) {
1229 if (rr->have_type && rr->type == last.dns_type) {
1230 rr->have_type = 0;
1231 }
1232 if (rr->have_class && rr->class == last.dns_class) {
1233 rr->have_class = 0;
1234 }
1235 if (rr->have_ttl && rr->ttl == last.dns_ttl) {
1236 rr->have_ttl = 0;
1237 }
1238 }
1239 if (rr->have_rdlength && rr->have_rdata) {
1240 rr->have_rdlength = 0;
1241 }
1242
1243 rr->bits = rr->have_type
1244 | rr->have_class << 1
1245 | rr->have_ttl << 2
1246 | rr->have_rdlength << 3;
1247 if (rr->bits && rr->bits != 0xf) {
1248 rr->have_bits = 1;
1249 }
1250
1251 if (cbor_err == CborNoError)
1252 cbor_err = cbor_encoder_create_array(&rrs, &item,
1253 (rr->is_complete ? 0 : 1) + rr->have_labels
1254 + rr->have_bits + rr->have_type + rr->have_class + rr->have_ttl + rr->have_rdlength
1255 + rr->have_rdata);
1256 if (!rr->is_complete) {
1257 if (cbor_err == CborNoError)
1258 cbor_err = cbor_encode_boolean(&item, false);
1259 }
1260 if (rr->have_labels) {
1261 if (rr->have_rlabel_idx) {
1262 if (cbor_err == CborNoError)
1263 cbor_err = cbor_encode_negative_int(&item, rr->rlabel_idx);
1264 } else {
1265 if (cbor_err == CborNoError)
1266 cbor_err = encode_label(&item, rr->label, rr->labels);
1267 }
1268 }
1269 if (rr->have_bits && cbor_err == CborNoError)
1270 cbor_err = cbor_encode_simple_value(&item, rr->bits);
1271 if (rr->have_type && cbor_err == CborNoError)
1272 cbor_err = cbor_encode_uint(&item, rr->type);
1273 if (rr->have_class && cbor_err == CborNoError)
1274 cbor_err = cbor_encode_uint(&item, rr->class);
1275 if (rr->have_ttl && cbor_err == CborNoError)
1276 cbor_err = cbor_encode_uint(&item, rr->ttl);
1277 if (rr->have_rdlength && cbor_err == CborNoError)
1278 cbor_err = cbor_encode_uint(&item, rr->rdlength);
1279 if (rr->have_rdata_index) {
1280 if (cbor_err == CborNoError)
1281 cbor_err = cbor_encode_uint(&item, rr->rdata_index);
1282 } else if (rr->have_rdata_rindex) {
1283 if (cbor_err == CborNoError)
1284 cbor_err = cbor_encode_negative_int(&item, rr->rdata_rindex);
1285 } else if (rr->have_mixed_rdata) {
1286 CborEncoder rdatas;
1287 size_t n2 = rr->mixed_rdatas;
1288 dns_rdata_t* rdata = rr->mixed_rdata;
1289
1290 if (cbor_err == CborNoError)
1291 cbor_err = cbor_encoder_create_array(&item, &rdatas, rr->mixed_rdatas);
1292 while (n2--) {
1293 if (rdata->have_labels) {
1294 if (rdata->have_rlabel_idx) {
1295 if (cbor_err == CborNoError)
1296 cbor_err = cbor_encode_negative_int(&rdatas, rdata->rlabel_idx);
1297 } else {
1298 if (cbor_err == CborNoError)
1299 cbor_err = encode_label(&rdatas, rdata->label, rdata->labels);
1300 }
1301 } else if (rdata->have_rdata) {
1302 if (cbor_err == CborNoError)
1303 cbor_err = cbor_encode_byte_string(&rdatas, rdata->rdata, rdata->rdata_len);
1304 }
1305
1306 rdata++;
1307 }
1308 if (cbor_err == CborNoError)
1309 cbor_err = cbor_encoder_close_container_checked(&item, &rdatas);
1310 } else if (rr->have_rdata && cbor_err == CborNoError)
1311 cbor_err = cbor_encode_byte_string(&item, rr->rdata, rr->rdlength);
1312 if (cbor_err == CborNoError)
1313 cbor_err = cbor_encoder_close_container_checked(&rrs, &item);
1314
1315 if (!(rr->have_type && rr->type == 41)) {
1316 if (rr->have_type) {
1317 last.dns_type = rr->type;
1318 }
1319 if (rr->have_class) {
1320 last.dns_class = rr->class;
1321 }
1322 if (rr->have_ttl) {
1323 last.dns_ttl = rr->ttl;
1324 }
1325 }
1326 rr++;
1327 }
1328 if (cbor_err == CborNoError)
1329 cbor_err = cbor_encoder_close_container_checked(message, &rrs);
1330
1331 return cbor_err;
1332 }
1333
output_cds(iaddr from,iaddr to,uint8_t proto,unsigned flags,unsigned sport,unsigned dport,my_bpftimeval ts,const u_char * pkt_copy,size_t olen,const u_char * payload,size_t payloadlen)1334 int output_cds(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char* pkt_copy, size_t olen, const u_char* payload, size_t payloadlen)
1335 {
1336 CborEncoder cbor, message;
1337 CborError cbor_err = CborNoError;
1338 ip_header_t ip;
1339 dns_t dns;
1340 uint8_t* malformed = 0;
1341 size_t malformed_size = 0;
1342 size_t dns_parts = 0;
1343
1344 if (!payload) {
1345 return DUMP_CDS_EINVAL;
1346 }
1347 if (!payloadlen) {
1348 return DUMP_CDS_EINVAL;
1349 }
1350
1351 if (!cbor_buf) {
1352 memset(&last, 0, sizeof(last));
1353 if (!(cbor_buf = calloc(1, cbor_size + message_size))) {
1354 return DUMP_CDS_ENOMEM;
1355 }
1356 }
1357 if (!cbor_buf_p) {
1358 cbor_buf_p = cbor_buf;
1359 }
1360 if (!message_buf) {
1361 if (!(message_buf = calloc(1, message_size))) {
1362 return DUMP_CDS_ENOMEM;
1363 }
1364 }
1365 if (cbor_flushed) {
1366 dns_rlabel_t* rlabel;
1367 struct rdata* r;
1368
1369 cbor_buf_p = cbor_buf;
1370 while ((rlabel = last.dns_rlabel)) {
1371 last.dns_rlabel = rlabel->next;
1372 free(rlabel);
1373 }
1374 while ((r = last.rdata)) {
1375 last.rdata = r->next;
1376 rdata_free(r);
1377 }
1378 memset(&last, 0, sizeof(last));
1379 if (rdata_tbl) {
1380 hash_free(rdata_tbl);
1381 rdata_tbl = 0;
1382 }
1383
1384 cbor_encoder_init(&cbor, message_buf, message_size, 0);
1385 cbor_err = cbor_encoder_create_array(&cbor, &message, 5 + (use_rdata_index ? 3 : 0) + (use_rdata_rindex ? 4 : 0));
1386 if (cbor_err == CborNoError)
1387 cbor_err = cbor_encode_text_stringz(&message, "CDSv1");
1388 if (cbor_err == CborNoError)
1389 cbor_err = cbor_encode_uint(&message, CDS_OPTION_RLABELS);
1390 if (cbor_err == CborNoError)
1391 cbor_err = cbor_encode_uint(&message, MAX_RLABELS);
1392 if (cbor_err == CborNoError)
1393 cbor_err = cbor_encode_uint(&message, CDS_OPTION_RLABEL_MIN_SIZE);
1394 if (cbor_err == CborNoError)
1395 cbor_err = cbor_encode_uint(&message, MIN_RLABEL_SIZE);
1396 if (use_rdata_index) {
1397 if (cbor_err == CborNoError)
1398 cbor_err = cbor_encode_uint(&message, CDS_OPTION_USE_RDATA_INDEX);
1399 if (cbor_err == CborNoError)
1400 cbor_err = cbor_encode_uint(&message, CDS_OPTION_RDATA_INDEX_MIN_SIZE);
1401 if (cbor_err == CborNoError)
1402 cbor_err = cbor_encode_uint(&message, RDATA_INDEX_MIN_SIZE);
1403 } else if (use_rdata_rindex) {
1404 if (cbor_err == CborNoError)
1405 cbor_err = cbor_encode_uint(&message, CDS_OPTION_RDATA_RINDEX_SIZE);
1406 if (cbor_err == CborNoError)
1407 cbor_err = cbor_encode_uint(&message, RDATA_RINDEX_SIZE);
1408 if (cbor_err == CborNoError)
1409 cbor_err = cbor_encode_uint(&message, CDS_OPTION_RDATA_RINDEX_MIN_SIZE);
1410 if (cbor_err == CborNoError)
1411 cbor_err = cbor_encode_uint(&message, RDATA_RINDEX_MIN_SIZE);
1412 }
1413 if (cbor_err == CborNoError)
1414 cbor_err = cbor_encoder_close_container_checked(&cbor, &message);
1415 if (cbor_err != CborNoError) {
1416 fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
1417 return DUMP_CDS_ECBOR;
1418 }
1419
1420 /* *cbor_buf_p = 0x9f;*/
1421 /* cbor_buf_p++;*/
1422
1423 if ((cbor_size - (cbor_buf_p - cbor_buf)) < cbor_encoder_get_buffer_size(&cbor, message_buf)) {
1424 return DUMP_CDS_EBUF;
1425 }
1426 memcpy(cbor_buf_p, message_buf, cbor_encoder_get_buffer_size(&cbor, message_buf));
1427 cbor_buf_p += cbor_encoder_get_buffer_size(&cbor, message_buf);
1428
1429 cbor_flushed = 0;
1430 }
1431 if (!rdata_tbl) {
1432 if (!(rdata_tbl = hash_create(64 * 1024, rdata_hash, rdata_cmp, rdata_free))) {
1433 return DUMP_CDS_ENOMEM;
1434 }
1435 }
1436
1437 /*
1438 * IP Header
1439 */
1440
1441 memset(&ip, 0, sizeof(ip_header_t));
1442
1443 /* fill ip */
1444 if (from.af == AF_INET6) {
1445 ip.is_v6 = 1;
1446 memcpy(&(ip.src_addr6), &(from.u.a6), sizeof(struct in6_addr));
1447 memcpy(&(ip.dest_addr6), &(to.u.a6), sizeof(struct in6_addr));
1448 ip.src_port6 = sport;
1449 ip.dest_port6 = dport;
1450 } else {
1451 memcpy(&(ip.src_addr4), &(from.u.a4), sizeof(struct in_addr));
1452 memcpy(&(ip.dest_addr4), &(to.u.a4), sizeof(struct in_addr));
1453 ip.src_port4 = sport;
1454 ip.dest_port4 = dport;
1455 }
1456
1457 /* deduplicate */
1458 {
1459 int dedup = 0;
1460 ip_header_t reverse;
1461
1462 reverse = ip;
1463
1464 /* check last.ip */
1465 if (ip.is_v6) {
1466 if (!memcmp(&(ip.src_addr6), &(last.ip.src_addr6), sizeof(struct in6_addr)))
1467 dedup++;
1468 else
1469 ip.have_src_addr = 1;
1470
1471 if (!memcmp(&(ip.dest_addr6), &(last.ip.dest_addr6), sizeof(struct in6_addr)))
1472 dedup++;
1473 else
1474 ip.have_dest_addr = 1;
1475
1476 if (ip.src_port6 == last.ip.src_port6)
1477 dedup++;
1478 else
1479 ip.have_src_port = 1;
1480
1481 if (ip.dest_port6 == last.ip.dest_port6)
1482 dedup++;
1483 else
1484 ip.have_dest_port = 1;
1485 } else {
1486 if (!memcmp(&(ip.src_addr4), &(last.ip.src_addr4), sizeof(struct in_addr)))
1487 dedup++;
1488 else
1489 ip.have_src_addr = 1;
1490
1491 if (!memcmp(&(ip.dest_addr4), &(last.ip.dest_addr4), sizeof(struct in_addr)))
1492 dedup++;
1493 else
1494 ip.have_dest_addr = 1;
1495
1496 if (ip.src_port4 == last.ip.src_port4)
1497 dedup++;
1498 else
1499 ip.have_src_port = 1;
1500
1501 if (ip.dest_port4 == last.ip.dest_port4)
1502 dedup++;
1503 else
1504 ip.have_dest_port = 1;
1505 }
1506
1507 /* check reverse last.ip */
1508 if (ip.is_v6) {
1509 if (!memcmp(&(ip.src_addr6), &(last.ip.dest_addr6), sizeof(struct in6_addr)))
1510 dedup--;
1511 else
1512 reverse.have_src_addr = 1;
1513
1514 if (!memcmp(&(ip.dest_addr6), &(last.ip.src_addr6), sizeof(struct in6_addr)))
1515 dedup--;
1516 else
1517 reverse.have_dest_addr = 1;
1518
1519 if (ip.src_port6 == last.ip.dest_port6)
1520 dedup--;
1521 else
1522 reverse.have_src_port = 1;
1523
1524 if (ip.dest_port6 == last.ip.src_port6)
1525 dedup--;
1526 else
1527 reverse.have_dest_port = 1;
1528 } else {
1529 if (!memcmp(&(ip.src_addr4), &(last.ip.dest_addr4), sizeof(struct in_addr)))
1530 dedup--;
1531 else
1532 reverse.have_src_addr = 1;
1533
1534 if (!memcmp(&(ip.dest_addr4), &(last.ip.src_addr4), sizeof(struct in_addr)))
1535 dedup--;
1536 else
1537 reverse.have_dest_addr = 1;
1538
1539 if (ip.src_port4 == last.ip.dest_port4)
1540 dedup--;
1541 else
1542 reverse.have_src_port = 1;
1543
1544 if (ip.dest_port4 == last.ip.src_port4)
1545 dedup--;
1546 else
1547 reverse.have_dest_port = 1;
1548 }
1549
1550 if (dedup < 0) {
1551 ip = reverse;
1552 ip.is_reverse = 1;
1553 /*fprintf(stderr, "reverse of last ip ");*/
1554 }
1555 /*fprintf(stderr, "v6:%d src:%d dest:%d sport:%d dport:%d\n", ip.is_v6, ip.have_src_addr, ip.have_dest_addr, ip.have_src_port, ip.have_dest_port);*/
1556
1557 ip.bits = ip.is_v6
1558 | ip.have_src_addr << 1
1559 | ip.have_dest_addr << 2
1560 | (ip.have_src_port | ip.have_dest_port) << 3;
1561
1562 if (ip.is_v6) {
1563 last.ip.src_addr6 = ip.src_addr6;
1564 last.ip.dest_addr6 = ip.dest_addr6;
1565 last.ip.src_port6 = ip.src_port6;
1566 last.ip.dest_port6 = ip.dest_port6;
1567 } else {
1568 last.ip.src_addr4 = ip.src_addr4;
1569 last.ip.dest_addr4 = ip.dest_addr4;
1570 last.ip.src_port4 = ip.src_port4;
1571 last.ip.dest_port4 = ip.dest_port4;
1572 }
1573 }
1574
1575 /*
1576 * DNS Message
1577 */
1578
1579 if (flags & DNSCAP_OUTPUT_ISDNS) {
1580 uint8_t* p = (uint8_t*)payload;
1581 size_t l = payloadlen, rr, n, n2, n3;
1582 int ret;
1583 dns_rr_t* rrp;
1584
1585 size_t n_offset = 0;
1586 uint16_t offset[256]; /* TODO: Handle offsets better */
1587
1588 memset(&dns, 0, sizeof(dns));
1589 ret = parse_dns(&dns, &p, &l);
1590
1591 if (ret < 0) {
1592 free_dns(&dns);
1593 return DUMP_CDS_ENOMEM;
1594 } else if (ret > 0) {
1595 malformed = p;
1596 malformed_size = l;
1597 }
1598
1599 if (dns.have_qdcount && dns.qdcount == dns.questions) {
1600 dns.have_qdcount = 0;
1601 }
1602 if (dns.have_ancount && dns.ancount == dns.answers) {
1603 dns.have_ancount = 0;
1604 }
1605 if (dns.have_nscount && dns.nscount == dns.authorities) {
1606 dns.have_nscount = 0;
1607 }
1608 if (dns.have_arcount && dns.arcount == dns.additionals) {
1609 dns.have_arcount = 0;
1610 }
1611
1612 dns.cnt_bits = dns.have_qdcount
1613 | dns.have_ancount << 1
1614 | dns.have_nscount << 2
1615 | dns.have_arcount << 3;
1616 if (dns.cnt_bits && dns.cnt_bits != 0xf) {
1617 dns.have_cnt_bits = 1;
1618 }
1619
1620 dns.rr_bits = dns.have_questions
1621 | dns.have_answers << 1
1622 | dns.have_authorities << 2
1623 | dns.have_additionals << 3;
1624 if (dns.rr_bits && dns.rr_bits != 0xf) {
1625 dns.have_rr_bits = 1;
1626 }
1627
1628 dns_rr_build_offset(dns.question, dns.questions, &offset[0], sizeof(offset), &n_offset, payload);
1629 dns_rr_build_offset(dns.answer, dns.answers, &offset[0], sizeof(offset), &n_offset, payload);
1630 dns_rr_build_offset(dns.authority, dns.authorities, &offset[0], sizeof(offset), &n_offset, payload);
1631 dns_rr_build_offset(dns.additional, dns.additionals, &offset[0], sizeof(offset), &n_offset, payload);
1632
1633 /* for (n = 0; n < n_offset; n++) {*/
1634 /* printf("%lu: %u\n", n, offset[n]);*/
1635 /* }*/
1636
1637 dns_rr_set_offset(dns.question, dns.questions, &offset[0], n_offset);
1638 dns_rr_set_offset(dns.answer, dns.answers, &offset[0], n_offset);
1639 dns_rr_set_offset(dns.authority, dns.authorities, &offset[0], n_offset);
1640 dns_rr_set_offset(dns.additional, dns.additionals, &offset[0], n_offset);
1641
1642 dns_rr_build_rlabel(dns.question, dns.questions);
1643 dns_rr_build_rlabel(dns.answer, dns.answers);
1644 dns_rr_build_rlabel(dns.authority, dns.authorities);
1645 dns_rr_build_rlabel(dns.additional, dns.additionals);
1646 }
1647
1648 /*
1649 * CBOR
1650 */
1651
1652 cbor_encoder_init(&cbor, message_buf, message_size, 0);
1653 cbor_err = cbor_encoder_create_array(&cbor, &message,
1654 /* timestamp */
1655 1
1656 /* message bits */
1657 + 1
1658 /* ip header */
1659 + 1 + ip.have_src_addr + ip.have_dest_addr + (ip.have_src_port | ip.have_dest_port)
1660 /* dns message */
1661 + dns.have_id + dns.have_raw
1662 + dns.have_cnt_bits + dns.have_qdcount + dns.have_ancount + dns.have_nscount + dns.have_arcount
1663 + dns.have_rr_bits + dns.have_questions + dns.have_answers + dns.have_authorities + dns.have_additionals
1664 + (malformed ? 1 : 0));
1665
1666 /*
1667 * Encode timestamp
1668 */
1669
1670 {
1671 CborEncoder timestamp;
1672
1673 if (cbor_err == CborNoError)
1674 cbor_err = cbor_encoder_create_array(&message, ×tamp, 2);
1675 if (last.ts.tv_sec && last.ts.tv_sec <= ts.tv_sec) {
1676 if (cbor_err == CborNoError)
1677 cbor_err = cbor_encode_negative_int(×tamp, ts.tv_sec - last.ts.tv_sec);
1678 if (cbor_err == CborNoError)
1679 cbor_err = cbor_encode_int(×tamp, ts.tv_usec - last.ts.tv_usec);
1680 } else {
1681 if (cbor_err == CborNoError)
1682 cbor_err = cbor_encode_uint(×tamp, ts.tv_sec);
1683 if (cbor_err == CborNoError)
1684 cbor_err = cbor_encode_uint(×tamp, ts.tv_usec);
1685 }
1686 if (cbor_err == CborNoError)
1687 cbor_err = cbor_encoder_close_container_checked(&message, ×tamp);
1688
1689 last.ts = ts;
1690 }
1691
1692 /*
1693 * Encode message bits
1694 */
1695
1696 if (cbor_err == CborNoError)
1697 cbor_err = cbor_encode_uint(&message,
1698 (flags & DNSCAP_OUTPUT_ISDNS ? 1 : 0)
1699 + (flags & DNSCAP_OUTPUT_ISDNS ? proto == IPPROTO_TCP ? 1 << 1 : 0
1700 : 0)
1701 + (flags & DNSCAP_OUTPUT_ISFRAG ? 1 << 2 : 0)
1702 + (malformed ? 1 << 3 : 0));
1703
1704 /*
1705 * Encode IP Header
1706 */
1707
1708 if (ip.is_reverse) {
1709 if (cbor_err == CborNoError)
1710 cbor_err = cbor_encode_negative_int(&message, ip.bits);
1711 } else {
1712 if (cbor_err == CborNoError)
1713 cbor_err = cbor_encode_uint(&message, ip.bits);
1714 }
1715
1716 if (ip.is_v6) {
1717 if (ip.have_src_addr && cbor_err == CborNoError)
1718 cbor_err = cbor_encode_byte_string(&message, (uint8_t*)&(ip.src_addr6), sizeof(struct in6_addr));
1719 if (ip.have_dest_addr && cbor_err == CborNoError)
1720 cbor_err = cbor_encode_byte_string(&message, (uint8_t*)&(ip.dest_addr6), sizeof(struct in6_addr));
1721 if (ip.have_src_port && ip.have_dest_port) {
1722 if (cbor_err == CborNoError)
1723 cbor_err = cbor_encode_uint(&message, (ip.dest_port6 << 16) | ip.src_port6);
1724 } else if (ip.have_src_port) {
1725 if (cbor_err == CborNoError)
1726 cbor_err = cbor_encode_uint(&message, ip.src_port6);
1727 } else if (ip.have_dest_port) {
1728 if (cbor_err == CborNoError)
1729 cbor_err = cbor_encode_negative_int(&message, ip.dest_port6);
1730 }
1731 } else {
1732 if (ip.have_src_addr && cbor_err == CborNoError)
1733 cbor_err = cbor_encode_byte_string(&message, (uint8_t*)&(ip.src_addr4), sizeof(struct in_addr));
1734 if (ip.have_dest_addr && cbor_err == CborNoError)
1735 cbor_err = cbor_encode_byte_string(&message, (uint8_t*)&(ip.dest_addr4), sizeof(struct in_addr));
1736 if (ip.have_src_port && ip.have_dest_port) {
1737 if (cbor_err == CborNoError)
1738 cbor_err = cbor_encode_uint(&message, (ip.dest_port4 << 16) | ip.src_port4);
1739 } else if (ip.have_src_port) {
1740 if (cbor_err == CborNoError)
1741 cbor_err = cbor_encode_uint(&message, ip.src_port4);
1742 } else if (ip.have_dest_port) {
1743 if (cbor_err == CborNoError)
1744 cbor_err = cbor_encode_negative_int(&message, ip.dest_port4);
1745 }
1746 }
1747
1748 /*
1749 * Encode DNS Message
1750 */
1751 if (flags & DNSCAP_OUTPUT_ISDNS && !dns.header_is_complete) {
1752 if (cbor_err == CborNoError)
1753 cbor_err = cbor_encode_boolean(&message, false);
1754 }
1755 if (dns.have_id && cbor_err == CborNoError)
1756 cbor_err = cbor_encode_uint(&message, dns.id);
1757 if (dns.have_raw && cbor_err == CborNoError)
1758 cbor_err = cbor_encode_uint(&message, dns.raw);
1759 if (dns.have_cnt_bits && cbor_err == CborNoError)
1760 cbor_err = cbor_encode_negative_int(&message, dns.cnt_bits);
1761 if (dns.have_qdcount && cbor_err == CborNoError)
1762 cbor_err = cbor_encode_uint(&message, dns.qdcount);
1763 if (dns.have_ancount && cbor_err == CborNoError)
1764 cbor_err = cbor_encode_uint(&message, dns.ancount);
1765 if (dns.have_nscount && cbor_err == CborNoError)
1766 cbor_err = cbor_encode_uint(&message, dns.nscount);
1767 if (dns.have_arcount && cbor_err == CborNoError)
1768 cbor_err = cbor_encode_uint(&message, dns.arcount);
1769 if (dns.have_rr_bits && cbor_err == CborNoError)
1770 cbor_err = cbor_encode_simple_value(&message, dns.rr_bits);
1771 if (dns.have_questions) {
1772 CborEncoder rrs;
1773 dns_rr_t* rr = dns.question;
1774 size_t n = dns.questions;
1775
1776 if (cbor_err == CborNoError)
1777 cbor_err = cbor_encoder_create_array(&message, &rrs, n);
1778 while (n--) {
1779 CborEncoder item;
1780
1781 if (rr->have_type && rr->type == last.dns_type) {
1782 rr->have_type = 0;
1783 }
1784 if (rr->have_class && rr->class == last.dns_class) {
1785 rr->have_class = 0;
1786 }
1787
1788 if (cbor_err == CborNoError)
1789 cbor_err = cbor_encoder_create_array(&rrs, &item,
1790 (rr->is_complete ? 0 : 1) + rr->have_labels + rr->have_type + rr->have_class);
1791 if (!rr->is_complete) {
1792 if (cbor_err == CborNoError)
1793 cbor_err = cbor_encode_boolean(&item, false);
1794 }
1795 if (rr->have_labels) {
1796 if (rr->have_rlabel_idx) {
1797 if (cbor_err == CborNoError)
1798 cbor_err = cbor_encode_negative_int(&item, rr->rlabel_idx);
1799 } else {
1800 if (cbor_err == CborNoError)
1801 cbor_err = encode_label(&item, rr->label, rr->labels);
1802 }
1803 }
1804 if (rr->have_type && cbor_err == CborNoError)
1805 cbor_err = cbor_encode_uint(&item, rr->type);
1806 if (rr->have_class && cbor_err == CborNoError)
1807 cbor_err = cbor_encode_negative_int(&item, rr->class);
1808 if (cbor_err == CborNoError)
1809 cbor_err = cbor_encoder_close_container_checked(&rrs, &item);
1810
1811 if (rr->have_type) {
1812 last.dns_type = rr->type;
1813 }
1814 if (rr->have_class) {
1815 last.dns_class = rr->class;
1816 }
1817
1818 rr++;
1819 }
1820 if (cbor_err == CborNoError)
1821 cbor_err = cbor_encoder_close_container_checked(&message, &rrs);
1822 }
1823 if (dns.have_answers && cbor_err == CborNoError)
1824 cbor_err = dns_build_rrs(&message, dns.answer, dns.answers);
1825 if (dns.have_authorities && cbor_err == CborNoError)
1826 cbor_err = dns_build_rrs(&message, dns.authority, dns.authorities);
1827 if (dns.have_additionals && cbor_err == CborNoError)
1828 cbor_err = dns_build_rrs(&message, dns.additional, dns.additionals);
1829
1830 /*
1831 * Encode malformed
1832 */
1833
1834 if (malformed && cbor_err == CborNoError)
1835 cbor_err = cbor_encode_byte_string(&message, (uint8_t*)malformed, malformed_size);
1836
1837 /*
1838 * Close
1839 */
1840
1841 free_dns(&dns);
1842
1843 if (cbor_err == CborNoError)
1844 cbor_err = cbor_encoder_close_container_checked(&cbor, &message);
1845 if (cbor_err != CborNoError) {
1846 fprintf(stderr, "cbor error[%d]: %s\n", cbor_err, cbor_error_string(cbor_err));
1847 return DUMP_CDS_ECBOR;
1848 }
1849
1850 /* if (print_cbor>1)*/
1851 /* {*/
1852 /* uint8_t* p = message_buf;*/
1853 /* size_t s = cbor_encoder_get_buffer_size(&cbor, message_buf);*/
1854
1855 /* while (s--) {*/
1856 /* printf("%02x", *p++);*/
1857 /* }*/
1858 /* printf("\n");*/
1859 /* }*/
1860
1861 if (((cbor_size + message_size) - (cbor_buf_p - cbor_buf)) < cbor_encoder_get_buffer_size(&cbor, message_buf)) {
1862 return DUMP_CDS_EBUF;
1863 }
1864 memcpy(cbor_buf_p, message_buf, cbor_encoder_get_buffer_size(&cbor, message_buf));
1865 cbor_buf_p += cbor_encoder_get_buffer_size(&cbor, message_buf);
1866
1867 if (cbor_buf_p < (cbor_buf + cbor_size)) {
1868 return DUMP_CDS_OK;
1869 }
1870
1871 cbor_flushed = 1;
1872 return DUMP_CDS_FLUSH;
1873 }
1874
dump_cds(FILE * fp)1875 int dump_cds(FILE* fp)
1876 {
1877 CborError cbor_err;
1878
1879 if (!fp) {
1880 return DUMP_CDS_EINVAL;
1881 }
1882
1883 /* *cbor_buf_p = 0xff;*/
1884 /* cbor_buf_p++;*/
1885
1886 /* fprintf(stderr, "cds output: %lu bytes\n", cbor_buf_p - cbor_buf);*/
1887
1888 if (fwrite(cbor_buf, cbor_buf_p - cbor_buf, 1, fp) != 1) {
1889 return DUMP_CDS_EWRITE;
1890 }
1891
1892 return DUMP_CDS_OK;
1893 }
1894
have_cds_support()1895 int have_cds_support()
1896 {
1897 return 1;
1898 }
1899
1900 #else /* HAVE_LIBTINYCBOR */
1901
cds_set_cbor_size(size_t size)1902 int cds_set_cbor_size(size_t size)
1903 {
1904 return DUMP_CDS_ENOSUP;
1905 }
1906
cds_set_message_size(size_t size)1907 int cds_set_message_size(size_t size)
1908 {
1909 return DUMP_CDS_ENOSUP;
1910 }
1911
cds_set_max_rlabels(size_t size)1912 int cds_set_max_rlabels(size_t size)
1913 {
1914 return DUMP_CDS_ENOSUP;
1915 }
1916
cds_set_min_rlabel_size(size_t size)1917 int cds_set_min_rlabel_size(size_t size)
1918 {
1919 return DUMP_CDS_ENOSUP;
1920 }
1921
cds_set_use_rdata_index(int use)1922 int cds_set_use_rdata_index(int use)
1923 {
1924 return DUMP_CDS_ENOSUP;
1925 }
1926
cds_set_use_rdata_rindex(int use)1927 int cds_set_use_rdata_rindex(int use)
1928 {
1929 return DUMP_CDS_ENOSUP;
1930 }
1931
cds_set_rdata_index_min_size(size_t size)1932 int cds_set_rdata_index_min_size(size_t size)
1933 {
1934 return DUMP_CDS_ENOSUP;
1935 }
1936
cds_set_rdata_rindex_min_size(size_t size)1937 int cds_set_rdata_rindex_min_size(size_t size)
1938 {
1939 return DUMP_CDS_ENOSUP;
1940 }
1941
cds_set_rdata_rindex_size(size_t size)1942 int cds_set_rdata_rindex_size(size_t size)
1943 {
1944 return DUMP_CDS_ENOSUP;
1945 }
1946
output_cds(iaddr from,iaddr to,uint8_t proto,unsigned flags,unsigned sport,unsigned dport,my_bpftimeval ts,const u_char * pkt_copy,size_t olen,const u_char * payload,size_t payloadlen)1947 int output_cds(iaddr from, iaddr to, uint8_t proto, unsigned flags, unsigned sport, unsigned dport, my_bpftimeval ts, const u_char* pkt_copy, size_t olen, const u_char* payload, size_t payloadlen)
1948 {
1949 return DUMP_CDS_ENOSUP;
1950 }
1951
dump_cds(FILE * fp)1952 int dump_cds(FILE* fp)
1953 {
1954 return DUMP_CDS_ENOSUP;
1955 }
1956
have_cds_support()1957 int have_cds_support()
1958 {
1959 return 0;
1960 }
1961
1962 #endif
1963