2
* Copyright (C) 2006 Justin Karneges
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the
6
* "Software"), to deal in the Software without restriction, including
7
* without limitation the rights to use, copy, modify, merge, publish,
8
* distribute, sublicense, and/or sell copies of the Software, and to
9
* permit persons to whom the Software is furnished to do so, subject to
10
* the following conditions:
12
* The above copyright notice and this permission notice shall be included
13
* in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
#include "jdns_packet.h"
28
// maximum length of a sublabel
29
#define MAX_SUBLABEL_LENGTH 63
31
// maximum length of a label, including final terminating zero (root sublabel)
32
// according to RFC 2181, the maximum length is 255, not counting the root
33
// sublabel. so, with the root sublabel, that means a max length of 256.
34
#define MAX_LABEL_LENGTH 256
36
// jer's endian functions
37
static unsigned short int net2short(const unsigned char **bufp)
47
static unsigned long int net2long(const unsigned char **bufp)
61
static void short2net(unsigned short int i, unsigned char **bufp)
63
*(*bufp + 1) = (unsigned char)i;
65
**bufp = (unsigned char)i;
69
static void long2net(unsigned long int l, unsigned char **bufp)
71
*(*bufp + 3) = (unsigned char)l;
73
*(*bufp + 2) = (unsigned char)l;
75
*(*bufp + 1) = (unsigned char)l;
77
**bufp = (unsigned char)l;
82
typedef struct jdns_packet_label
87
} jdns_packet_label_t;
89
static void jdns_packet_label_delete(jdns_packet_label_t *a);
90
static jdns_packet_label_t *jdns_packet_label_copy(const jdns_packet_label_t *a);
92
static jdns_packet_label_t *jdns_packet_label_new()
94
jdns_packet_label_t *a = JDNS_OBJECT_NEW(jdns_packet_label);
100
jdns_packet_label_t *jdns_packet_label_copy(const jdns_packet_label_t *a)
102
jdns_packet_label_t *c = jdns_packet_label_new();
103
c->offset = a->offset;
105
c->value = jdns_string_copy(a->value);
109
void jdns_packet_label_delete(jdns_packet_label_t *a)
113
jdns_string_delete(a->value);
117
// gets an offset for decompression. does range and hop count checking also
118
static int getoffset(const unsigned char *str, int refsize, int *hopsleft)
120
unsigned short int x;
133
static int readlabel(const unsigned char *in, int insize, const unsigned char *ref, int refsize, int *_at, jdns_string_t **name)
136
// string format is one character smaller than dns format. e.g.:
137
// dns: [7] affinix [3] com [0] = 13 bytes
138
// string: "affinix.com." = 12 bytes
139
// only exception is '.' itself, but that won't influence the max.
140
unsigned char out[MAX_LABEL_LENGTH - 1];
142
const unsigned char *label, *last;
150
if(at < 0 || at >= insize)
163
// we make this a while loop instead of an 'if', in case
164
// there's a pointer to a pointer. as a precaution,
165
// we will hop no more than 8 times
171
// need the next byte, too
175
offset = getoffset(label, refsize, &hopsleft);
179
label = ref + offset;
184
last = ref + refsize;
192
label_size = *label & 0x3f;
194
// null label? then we're done
202
// enough source bytes? (length byte + length)
203
if(label + label_size + 1 > last)
206
// enough dest bytes? (length + dot)
207
if(out_size + label_size + 1 > MAX_LABEL_LENGTH - 1)
210
memcpy(out + out_size, label + 1, label_size);
211
out_size += label_size;
216
at += label_size + 1;
218
label += label_size + 1;
222
*name = jdns_string_new();
223
jdns_string_set(*name, out, out_size);
230
// this function compares labels in label format:
231
// [length] [value ...] [length] [value ...] [0]
232
static int matchlabel(const unsigned char *a, int asize, const unsigned char *b, int bsize, const unsigned char *ref, int refsize, int ahopsleft, int bhopsleft)
234
int n, alen, blen, offset;
240
if(asize < 1 || bsize < 1)
243
// always ensure we get called without a pointer
248
offset = getoffset(a, refsize, &ahopsleft);
251
return matchlabel(ref + offset, refsize - offset, b, bsize, ref, refsize, ahopsleft, bhopsleft);
257
offset = getoffset(b, refsize, &bhopsleft);
260
return matchlabel(a, asize, ref + offset, refsize - offset, ref, refsize, ahopsleft, bhopsleft);
266
// must be same length
274
// length byte + length + first byte of next label
281
for(n = 1; n < alen + 1; ++n)
289
return matchlabel(a + n, asize - n, b + n, bsize - n, ref, refsize, ahopsleft, bhopsleft);
292
int jdns_packet_name_isvalid(const unsigned char *name, int size)
296
// at least one byte, no larger than MAX_LABEL_LENGTH - 1 (one byte is
297
// gained when converting to a label)
298
if(size < 1 || size > (MAX_LABEL_LENGTH - 1))
301
// last byte must be a dot
302
if(name[size - 1] != '.')
305
// first byte can't be a dot if there are characters after
306
if(size > 1 && name[0] == '.')
309
// each sublabel must be between 1 and MAX_SUBLABEL_LENGTH in length
313
// search for dot or end
314
for(n = at; n < size; ++n)
319
// length of last one is always zero
324
if(len < 1 || len > MAX_SUBLABEL_LENGTH)
326
at = n + 1; // skip over the dot
332
// this function assumes label is pointing to a MAX_LABEL_LENGTH byte buffer
333
static int name_to_label(const jdns_string_t *name, unsigned char *label)
337
if(!jdns_packet_name_isvalid(name->data, name->size))
350
// search for dot or end
351
for(n = at; n < name->size; ++n)
353
if(name->data[n] == '.')
357
if(i + (len + 1) > MAX_LABEL_LENGTH) // length byte + length
361
memcpy(label + i, name->data + at, len);
364
if(n >= name->size) // end?
366
at = n + 1; // skip over the dot
372
// lookup list is made of jdns_packet_labels
373
static int writelabel(const jdns_string_t *name, int at, int left, unsigned char **bufp, jdns_list_t *lookup)
375
unsigned char label[MAX_LABEL_LENGTH];
381
len = name_to_label(name, label);
387
for(n = 0; label[n]; n += label[n] + 1)
389
for(i = 0; i < lookup->count; ++i)
391
jdns_packet_label_t *pl = (jdns_packet_label_t *)lookup->item[i];
393
if(matchlabel(label + n, len - n, pl->value->data, pl->value->size, ref, refsize, 8, 8))
395
// set up a pointer right here, overwriting
396
// the length byte and the first content
397
// byte of this section within 'label'.
398
// this is safe, because the length value
399
// will always be greater than zero,
400
// ensuring we have two bytes available to
403
short2net((unsigned short int)pl->offset, &l);
405
len = n + 2; // cut things short
409
if(label[n] & 0xc0) // double loop, so break again
416
// copy into buffer, point there now
417
memcpy(*bufp, label, len);
421
// for each new label, store its location for future compression
422
for(n = 0; l[n]; n += l[n] + 1)
425
jdns_packet_label_t *pl;
429
pl = jdns_packet_label_new();
430
str = jdns_string_new();
431
jdns_string_set(str, l + n, len - n);
432
pl->offset = l + n - ref;
434
jdns_list_insert(lookup, pl, -1);
440
//----------------------------------------------------------------------------
442
//----------------------------------------------------------------------------
443
#define JDNS_PACKET_WRITE_RAW 0
444
#define JDNS_PACKET_WRITE_NAME 1
446
struct jdns_packet_write
450
jdns_string_t *value;
453
void jdns_packet_write_delete(jdns_packet_write_t *a);
454
jdns_packet_write_t *jdns_packet_write_copy(const jdns_packet_write_t *a);
456
jdns_packet_write_t *jdns_packet_write_new()
458
jdns_packet_write_t *a = JDNS_OBJECT_NEW(jdns_packet_write);
464
jdns_packet_write_t *jdns_packet_write_copy(const jdns_packet_write_t *a)
466
jdns_packet_write_t *c = jdns_packet_write_new();
469
c->value = jdns_string_copy(a->value);
473
void jdns_packet_write_delete(jdns_packet_write_t *a)
477
jdns_string_delete(a->value);
481
//----------------------------------------------------------------------------
482
// jdns_packet_question
483
//----------------------------------------------------------------------------
484
jdns_packet_question_t *jdns_packet_question_new()
486
jdns_packet_question_t *a = JDNS_OBJECT_NEW(jdns_packet_question);
493
jdns_packet_question_t *jdns_packet_question_copy(const jdns_packet_question_t *a)
495
jdns_packet_question_t *c = jdns_packet_question_new();
497
c->qname = jdns_string_copy(a->qname);
499
c->qclass = a->qclass;
503
void jdns_packet_question_delete(jdns_packet_question_t *a)
507
jdns_string_delete(a->qname);
511
//----------------------------------------------------------------------------
512
// jdns_packet_resource
513
//----------------------------------------------------------------------------
514
jdns_packet_resource_t *jdns_packet_resource_new()
516
jdns_packet_resource_t *a = JDNS_OBJECT_NEW(jdns_packet_resource);
524
a->writelog = jdns_list_new();
525
a->writelog->valueList = 1;
529
jdns_packet_resource_t *jdns_packet_resource_copy(const jdns_packet_resource_t *a)
531
jdns_packet_resource_t *c = jdns_packet_resource_new();
533
c->qname = jdns_string_copy(a->qname);
535
c->qclass = a->qclass;
537
c->rdlength = a->rdlength;
538
c->rdata = jdns_copy_array(a->rdata, a->rdlength);
540
jdns_list_delete(c->writelog);
541
c->writelog = jdns_list_copy(a->writelog);
545
void jdns_packet_resource_delete(jdns_packet_resource_t *a)
549
jdns_string_delete(a->qname);
552
jdns_list_delete(a->writelog);
556
void jdns_packet_resource_add_bytes(jdns_packet_resource_t *a, const unsigned char *data, int size)
558
jdns_packet_write_t *write = jdns_packet_write_new();
559
write->type = JDNS_PACKET_WRITE_RAW;
560
write->value = jdns_string_new();
561
jdns_string_set(write->value, data, size);
562
jdns_list_insert_value(a->writelog, write, -1);
563
jdns_packet_write_delete(write);
566
void jdns_packet_resource_add_name(jdns_packet_resource_t *a, const jdns_string_t *name)
568
jdns_packet_write_t *write = jdns_packet_write_new();
569
write->type = JDNS_PACKET_WRITE_NAME;
570
write->value = jdns_string_copy(name);
571
jdns_list_insert_value(a->writelog, write, -1);
572
jdns_packet_write_delete(write);
575
int jdns_packet_resource_read_name(const jdns_packet_resource_t *a, const jdns_packet_t *p, int *at, jdns_string_t **name)
577
return readlabel(a->rdata, a->rdlength, p->raw_data, p->raw_size, at, name);
580
//----------------------------------------------------------------------------
582
//----------------------------------------------------------------------------
584
// note: both process_qsection and process_rrsection modify the 'dest' list,
585
// even if later items cause an error. this turns out to be convenient
586
// for handling truncated dns packets
588
static int process_qsection(jdns_list_t *dest, int count, const unsigned char *data, int size, const unsigned char **bufp)
592
jdns_string_t *name = 0;
593
const unsigned char *buf;
596
for(n = 0; n < count; ++n)
598
jdns_packet_question_t *q;
603
if(!readlabel(data + offset, size - offset, data, size, &at, &name))
609
if(size - offset < 4)
614
q = jdns_packet_question_new();
617
q->qtype = net2short(&buf);
618
q->qclass = net2short(&buf);
620
jdns_list_insert_value(dest, q, -1);
621
jdns_packet_question_delete(q);
628
jdns_string_delete(name);
632
static int process_rrsection(jdns_list_t *dest, int count, const unsigned char *data, int size, const unsigned char **bufp)
636
jdns_string_t *name = 0;
637
const unsigned char *buf;
640
for(n = 0; n < count; ++n)
642
jdns_packet_resource_t *r;
647
if(!readlabel(data + offset, size - offset, data, size, &at, &name))
652
// need 10 more bytes
653
if(offset + 10 > size)
658
r = jdns_packet_resource_new();
661
r->qtype = net2short(&buf);
662
r->qclass = net2short(&buf);
663
r->ttl = net2long(&buf);
665
// per RFC 2181, ttl is supposed to be a 31 bit number. if
666
// the top bit of the 32 bit field is 1, then entire ttl is
667
// to be considered 0.
668
if(r->ttl & 0x80000000)
671
r->rdlength = net2short(&buf);
675
// make sure we have enough for the rdata
676
if(size - offset < r->rdlength)
678
jdns_packet_resource_delete(r);
682
r->rdata = jdns_copy_array(buf, r->rdlength);
685
jdns_list_insert_value(dest, r, -1);
686
jdns_packet_resource_delete(r);
693
jdns_string_delete(name);
697
static int append_qsection(const jdns_list_t *src, int at, int left, unsigned char **bufp, jdns_list_t *lookup)
699
unsigned char *buf, *start, *last;
705
for(n = 0; n < src->count; ++n)
707
jdns_packet_question_t *q = (jdns_packet_question_t *)src->item[n];
709
if(!writelabel(q->qname, buf - start, last - buf, &buf, lookup))
715
short2net(q->qtype, &buf);
716
short2net(q->qclass, &buf);
726
static int append_rrsection(const jdns_list_t *src, int at, int left, unsigned char **bufp, jdns_list_t *lookup)
728
unsigned char *buf, *start, *last, *rdlengthp;
734
for(n = 0; n < src->count; ++n)
736
jdns_packet_resource_t *r = (jdns_packet_resource_t *)src->item[n];
738
if(!writelabel(r->qname, buf - start, last - buf, &buf, lookup))
744
short2net(r->qtype, &buf);
745
short2net(r->qclass, &buf);
746
long2net(r->ttl, &buf);
748
// skip over rdlength
754
for(i = 0; i < r->writelog->count; ++i)
756
jdns_packet_write_t *write = (jdns_packet_write_t *)r->writelog->item[i];
757
if(write->type == JDNS_PACKET_WRITE_RAW)
759
if(buf + write->value->size > last)
762
memcpy(buf, write->value->data, write->value->size);
763
buf += write->value->size;
765
else // JDNS_PACKET_WRITE_NAME
767
if(!writelabel(write->value, buf - start, last - buf, &buf, lookup))
772
i = buf - rdlengthp; // should be rdata size + 2
773
short2net((unsigned short int)(i - 2), &rdlengthp);
783
jdns_packet_t *jdns_packet_new()
785
jdns_packet_t *a = JDNS_OBJECT_NEW(jdns_packet);
796
a->questions = jdns_list_new();
797
a->answerRecords = jdns_list_new();
798
a->authorityRecords = jdns_list_new();
799
a->additionalRecords = jdns_list_new();
801
a->questions->valueList = 1;
802
a->answerRecords->valueList = 1;
803
a->authorityRecords->valueList = 1;
804
a->additionalRecords->valueList = 1;
813
jdns_packet_t *jdns_packet_copy(const jdns_packet_t *a)
815
jdns_packet_t *c = jdns_packet_new();
817
c->opts.qr = a->opts.qr;
818
c->opts.opcode = a->opts.opcode;
819
c->opts.aa = a->opts.aa;
820
c->opts.tc = a->opts.tc;
821
c->opts.rd = a->opts.rd;
822
c->opts.ra = a->opts.ra;
823
c->opts.z = a->opts.z;
824
c->opts.rcode = a->opts.rcode;
826
jdns_list_delete(c->questions);
827
jdns_list_delete(c->answerRecords);
828
jdns_list_delete(c->authorityRecords);
829
jdns_list_delete(c->additionalRecords);
830
c->questions = jdns_list_copy(a->questions);
831
c->answerRecords = jdns_list_copy(a->answerRecords);
832
c->authorityRecords = jdns_list_copy(a->authorityRecords);
833
c->additionalRecords = jdns_list_copy(a->additionalRecords);
835
c->fully_parsed = a->fully_parsed;
837
c->raw_size = a->raw_size;
838
c->raw_data = jdns_copy_array(a->raw_data, a->raw_size);
843
void jdns_packet_delete(jdns_packet_t *a)
847
jdns_list_delete(a->questions);
848
jdns_list_delete(a->answerRecords);
849
jdns_list_delete(a->authorityRecords);
850
jdns_list_delete(a->additionalRecords);
852
jdns_free(a->raw_data);
856
int jdns_packet_import(jdns_packet_t **a, const unsigned char *data, int size)
858
jdns_packet_t *tmp = 0;
859
const unsigned char *buf;
861
// need at least some data
862
if(!data || size == 0)
865
// header (id + options + item counts) is 12 bytes
869
tmp = jdns_packet_new();
873
tmp->id = net2short(&buf);
876
if(buf[0] & 0x80) // qr is bit 7
878
tmp->opts.opcode = (buf[0] & 0x78) >> 3; // opcode is bits 6,5,4,3
879
if(buf[0] & 0x04) // aa is bit 2
881
if(buf[0] & 0x02) // tc is bit 1
883
if(buf[0] & 0x01) // rd is bit 0
885
if(buf[1] & 0x80) // ra is bit 7 (second byte)
887
tmp->opts.z = (buf[1] & 0x70) >> 4; // z is bits 6,5,4
888
tmp->opts.rcode = buf[1] & 0x0f; // rcode is bits 3,2,1,0
892
tmp->qdcount = net2short(&buf);
893
tmp->ancount = net2short(&buf);
894
tmp->nscount = net2short(&buf);
895
tmp->arcount = net2short(&buf);
897
// if these fail, we don't count them as errors, since the packet
898
// might have been truncated
899
if(!process_qsection(tmp->questions, tmp->qdcount, data, size, &buf))
901
if(!process_rrsection(tmp->answerRecords, tmp->ancount, data, size, &buf))
903
if(!process_rrsection(tmp->authorityRecords, tmp->nscount, data, size, &buf))
905
if(!process_rrsection(tmp->additionalRecords, tmp->arcount, data, size, &buf))
908
tmp->fully_parsed = 1;
911
// keep the raw data for reference during rdata parsing
912
tmp->raw_size = size;
913
tmp->raw_data = jdns_copy_array(data, size);
919
jdns_packet_delete(tmp);
923
int jdns_packet_export(jdns_packet_t *a, int maxsize)
925
unsigned char *block = 0;
926
unsigned char *buf, *last;
929
jdns_list_t *lookup = 0; // to hold jdns_packet_label_t
931
// clear out any existing raw data before we begin
934
jdns_free(a->raw_data);
941
block = (unsigned char *)jdns_alloc(size);
942
memset(block, 0, size);
950
short2net(a->id, &buf);
953
c = (unsigned char)a->opts.opcode;
963
c = (unsigned char)a->opts.z;
965
c = (unsigned char)a->opts.rcode;
968
short2net((unsigned short int)a->questions->count, &buf);
969
short2net((unsigned short int)a->answerRecords->count, &buf);
970
short2net((unsigned short int)a->authorityRecords->count, &buf);
971
short2net((unsigned short int)a->additionalRecords->count, &buf);
974
lookup = jdns_list_new();
975
lookup->autoDelete = 1;
977
if(!append_qsection(a->questions, buf - block, last - buf, &buf, lookup))
979
if(!append_rrsection(a->answerRecords, buf - block, last - buf, &buf, lookup))
981
if(!append_rrsection(a->authorityRecords, buf - block, last - buf, &buf, lookup))
983
if(!append_rrsection(a->additionalRecords, buf - block, last - buf, &buf, lookup))
986
// done with all sections
987
jdns_list_delete(lookup);
991
block = (unsigned char *)jdns_realloc(block, size);
994
a->qdcount = a->questions->count;
995
a->ancount = a->answerRecords->count;
996
a->nscount = a->authorityRecords->count;
997
a->arcount = a->additionalRecords->count;
1004
jdns_list_delete(lookup);