2
* Copyright (C) 2005-2008 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.
26
#include "jdns_packet.h"
28
//----------------------------------------------------------------------------
30
//----------------------------------------------------------------------------
31
void *jdns_alloc(int size)
36
void *jdns_realloc(void *p, int size)
38
return realloc(p, size);
41
void jdns_free(void *p)
46
char *jdns_strdup(const char *s)
51
len = strlen(s) + 1; // the zero
52
p = (char *)jdns_alloc(len);
57
unsigned char *jdns_copy_array(const unsigned char *src, int size)
62
out = (unsigned char *)jdns_alloc(size);
63
memcpy(out, src, size);
67
int jdns_domain_cmp(const unsigned char *a, const unsigned char *b)
72
// case-insensitive compare
74
if(len_a != (int)_ustrlen(b))
77
for(n = 0; n < len_a; ++n)
79
if(tolower(a[n]) != tolower(b[n]))
85
int jdns_sprintf_s(char *str, int n, const char *format, ...)
90
ret = jdns_vsprintf_s(str, n, format, ap);
95
int jdns_vsprintf_s(char *str, int n, const char *format, va_list ap)
97
#if defined(_MSC_VER) && _MSC_VER >= 1400
98
return vsprintf_s(str, n, format, ap);
101
return vsprintf(str, format, ap);
105
FILE *jdns_fopen(const char *path, const char *mode)
107
#if defined(_MSC_VER) && _MSC_VER >= 1400
109
if(fopen_s(&fp, path, mode) != 0)
113
return fopen(path, mode);
117
jdns_string_t *jdns_getenv(const char *name)
119
#if defined(_MSC_VER) && _MSC_VER >= 1400
125
ret = getenv_s(&size, 0, 0, name);
126
if(ret != 0 || size == 0)
129
dest = (char *)jdns_alloc(sizei);
130
ret = getenv_s(&size, dest, size, name);
136
out = jdns_string_new();
137
out->size = sizei - 1;
138
out->data = dest; // must be zero-terminated, which it is
146
out = jdns_string_new();
147
jdns_string_set_cstr(out, val);
152
char *jdns_strcpy(char *dst, const char *src)
154
#if defined(_MSC_VER) && _MSC_VER >= 1400
156
// deliberately unsafe
158
if(strcpy_s(dst, len + 1, src) != 0)
162
return strcpy(dst, src);
166
//----------------------------------------------------------------------------
168
//----------------------------------------------------------------------------
169
void *jdns_object_new(int size, void (*dtor)(void *), void *(*cctor)(const void *))
171
jdns_object_t *a = (jdns_object_t *)jdns_alloc(size);
178
void *jdns_object_copy(const void *a)
180
return ((const jdns_object_t *)a)->cctor(a);
183
void jdns_object_delete(void *a)
185
((jdns_object_t *)a)->dtor(a);
188
void jdns_object_free(void *a)
193
//----------------------------------------------------------------------------
195
//----------------------------------------------------------------------------
196
jdns_list_t *jdns_list_new()
198
jdns_list_t *a = JDNS_OBJECT_NEW(jdns_list);
206
jdns_list_t *jdns_list_copy(const jdns_list_t *a)
208
jdns_list_t *c = jdns_list_new();
210
// note: copying a list with autoDelete should not ever be done.
211
// heck, let's not even allow it. return an empty list.
215
c->valueList = a->valueList;
222
c->item = (void **)jdns_alloc(sizeof(void *) * c->count);
226
for(n = 0; n < c->count; ++n)
227
c->item[n] = jdns_object_copy(a->item[n]);
232
for(n = 0; n < c->count; ++n)
233
c->item[n] = a->item[n];
239
void jdns_list_delete(jdns_list_t *a)
247
void jdns_list_clear(jdns_list_t *a)
251
// delete the items if necessary
252
if(a->valueList || a->autoDelete)
255
for(n = 0; n < a->count; ++n)
256
jdns_object_delete(a->item[n]);
264
void jdns_list_insert(jdns_list_t *a, void *item, int pos)
268
a->item = (void **)jdns_alloc(sizeof(void *));
270
a->item = (void **)jdns_realloc(a->item, sizeof(void *) * (a->count + 1));
274
memmove(a->item + pos + 1, a->item + pos, (a->count - pos) * sizeof(void *));
280
a->item[pos] = jdns_object_copy(item);
286
void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos)
288
jdns_list_insert(a, (void *)item, pos);
291
void jdns_list_remove(jdns_list_t *a, void *item)
295
for(n = 0; n < a->count; ++n)
297
if(a->item[n] == item)
306
jdns_list_remove_at(a, pos);
309
void jdns_list_remove_at(jdns_list_t *a, int pos)
311
if(pos < 0 || pos >= a->count)
314
// delete the item if necessary
315
if(a->valueList || a->autoDelete)
316
jdns_object_delete(a->item[pos]);
321
memmove(a->item + pos, a->item + pos + 1, (a->count - pos - 1) * sizeof(void *));
332
//----------------------------------------------------------------------------
334
//----------------------------------------------------------------------------
335
jdns_string_t *jdns_string_new()
337
jdns_string_t *s = JDNS_OBJECT_NEW(jdns_string);
343
jdns_string_t *jdns_string_copy(const jdns_string_t *s)
345
jdns_string_t *c = jdns_string_new();
347
jdns_string_set(c, s->data, s->size);
351
void jdns_string_delete(jdns_string_t *s)
360
void jdns_string_set(jdns_string_t *s, const unsigned char *str, int str_len)
364
s->data = (unsigned char *)jdns_alloc(str_len + 1);
365
memcpy(s->data, str, str_len);
366
s->data[str_len] = 0;
370
void jdns_string_set_cstr(jdns_string_t *s, const char *str)
372
jdns_string_set(s, (const unsigned char *)str, strlen(str));
375
int jdns_string_indexOf(const jdns_string_t *s, unsigned char c, int pos)
378
for(n = pos; n < s->size; ++n)
386
jdns_stringlist_t *jdns_string_split(const jdns_string_t *s, unsigned char sep)
390
jdns_stringlist_t *out;
393
out = jdns_stringlist_new();
396
n = jdns_string_indexOf(s, sep, at);
400
// FIXME: should we allow empty items?
403
str = jdns_string_new();
404
jdns_string_set(str, s->data + at, len);
405
jdns_stringlist_append(out, str);
406
jdns_string_delete(str);
407
at = n + 1; // skip over separator
412
//----------------------------------------------------------------------------
414
//----------------------------------------------------------------------------
415
jdns_stringlist_t *jdns_stringlist_new()
417
jdns_list_t *a = jdns_list_new();
419
return (jdns_stringlist_t *)a;
422
jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a)
424
return (jdns_stringlist_t *)jdns_list_copy((const jdns_list_t *)a);
427
void jdns_stringlist_delete(jdns_stringlist_t *a)
429
jdns_list_delete((jdns_list_t *)a);
430
// note: no need to call jdns_object_free() here
433
void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str)
435
jdns_list_insert_value((jdns_list_t *)a, str, -1);
438
//----------------------------------------------------------------------------
440
//----------------------------------------------------------------------------
441
jdns_address_t *jdns_address_new()
443
jdns_address_t *a = alloc_type(jdns_address_t);
446
a->c_str = jdns_strdup("");
450
jdns_address_t *jdns_address_copy(const jdns_address_t *a)
452
jdns_address_t *c = jdns_address_new();
454
jdns_address_set_ipv6(c, a->addr.v6);
456
jdns_address_set_ipv4(c, a->addr.v4);
460
void jdns_address_delete(jdns_address_t *a)
465
jdns_free(a->addr.v6);
470
void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4)
473
jdns_free(a->addr.v6);
477
a->c_str = (char *)jdns_alloc(16); // max size (3 * 4 + 3 + 1)
478
jdns_sprintf_s(a->c_str, 16, "%d.%d.%d.%d",
479
(unsigned char)((ipv4 >> 24) & 0xff),
480
(unsigned char)((ipv4 >> 16) & 0xff),
481
(unsigned char)((ipv4 >> 8) & 0xff),
482
(unsigned char)((ipv4) & 0xff));
485
void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6)
489
unsigned short word[8];
491
jdns_free(a->addr.v6);
494
a->addr.v6 = (unsigned char *)jdns_alloc(16);
495
memcpy(a->addr.v6, ipv6, 16);
496
p = (unsigned char *)a->addr.v6;
497
a->c_str = (char *)jdns_alloc(40); // max size (8 * 4 + 7 + 1)
498
// each word in a 16-byte ipv6 address is network byte order
499
for(n = 0; n < 8; ++n)
500
word[n] = ((unsigned short)(p[n * 2]) << 8) + (unsigned short)(p[n * 2 + 1]);
501
jdns_sprintf_s(a->c_str, 40, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X", word[0], word[1], word[2], word[3], word[4], word[5], word[6], word[7]);
504
int jdns_address_set_cstr(jdns_address_t *a, const char *str)
506
int slen = strlen(str);
512
jdns_stringlist_t *list;
513
unsigned char ipv6[16];
514
int n, at, count, fill;
516
in = jdns_string_new();
517
jdns_string_set_cstr(in, str);
518
list = jdns_string_split(in, ':');
519
jdns_string_delete(in);
521
// a confusing outputting-backwards parser adapted from qt
525
if(count < 3 || count > 8)
530
for(n = count - 1; n >= 0; --n)
535
if(list->item[n]->size == 0)
539
if(list->item[n - 1]->size != 0)
546
if(list->item[n + 1]->size != 0)
554
for(i = 0; i < fill; ++i)
565
if(jdns_string_indexOf(list->item[n], '.', 0) == -1)
568
x = strtol((const char *)list->item[n]->data, NULL, 16);
569
if(x < 0 || x > 0xffff)
571
ipv6[--at] = x & 0xff;
572
ipv6[--at] = (x >> 8) & 0xff;
581
v4 = jdns_address_new();
582
if(!jdns_address_set_cstr(v4, (char *)list->item[n]->data))
584
jdns_address_delete(v4);
588
ipv6[--at] = (unsigned char)(v4->addr.v4 & 0xff);
589
ipv6[--at] = (unsigned char)((v4->addr.v4 >> 8) & 0xff);
590
ipv6[--at] = (unsigned char)((v4->addr.v4 >> 16) & 0xff);
591
ipv6[--at] = (unsigned char)((v4->addr.v4 >> 24) & 0xff);
592
jdns_address_delete(v4);
597
jdns_stringlist_delete(list);
599
jdns_address_set_ipv6(a, ipv6);
603
jdns_stringlist_delete(list);
606
else if(strchr(str, '.'))
610
unsigned long int ipv4;
625
// convert the section into a byte
626
part = (char *)jdns_alloc(len + 1);
627
memcpy(part, p, len);
629
x = strtol(part, NULL, 10);
631
if(x < 0 || x > 0xff)
633
b[at++] = (unsigned char)x;
639
// skip over the separator
654
jdns_address_set_ipv4(a, ipv4);
661
int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b)
664
if(a->isIpv6 != b->isIpv6)
669
for(n = 0; n < 16; ++n)
671
if(a->addr.v6[n] != b->addr.v6[n])
679
if(a->addr.v4 == b->addr.v4)
686
unsigned char jdns_multicast_addr6_value_v6[] =
688
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb
692
jdns_address_t *jdns_address_multicast4_new()
694
jdns_address_t *a = jdns_address_new();
695
jdns_address_set_ipv4(a, 0xe00000fb);
699
jdns_address_t *jdns_address_multicast6_new()
701
jdns_address_t *a = jdns_address_new();
702
jdns_address_set_ipv6(a, jdns_multicast_addr6_value_v6);
706
//----------------------------------------------------------------------------
708
//----------------------------------------------------------------------------
709
jdns_server_t *jdns_server_new()
711
jdns_server_t *s = alloc_type(jdns_server_t);
719
jdns_server_t *jdns_server_copy(const jdns_server_t *s)
721
jdns_server_t *c = jdns_server_new();
723
c->name = _ustrdup(s->name);
725
c->priority = s->priority;
726
c->weight = s->weight;
730
void jdns_server_delete(jdns_server_t *s)
739
void jdns_server_set_name(jdns_server_t *s, const unsigned char *name)
743
s->name = _ustrdup(name);
746
//----------------------------------------------------------------------------
748
//----------------------------------------------------------------------------
749
jdns_nameserver_t *jdns_nameserver_new()
751
jdns_nameserver_t *a = alloc_type(jdns_nameserver_t);
757
jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a)
759
jdns_nameserver_t *c = jdns_nameserver_new();
761
c->address = jdns_address_copy(a->address);
766
void jdns_nameserver_delete(jdns_nameserver_t *a)
770
jdns_address_delete(a->address);
774
void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr, int port)
777
jdns_address_delete(a->address);
778
a->address = jdns_address_copy(addr);
782
//----------------------------------------------------------------------------
783
// jdns_nameserverlist
784
//----------------------------------------------------------------------------
785
jdns_nameserverlist_t *jdns_nameserverlist_new()
787
jdns_nameserverlist_t *a = alloc_type(jdns_nameserverlist_t);
793
jdns_nameserverlist_t *jdns_nameserverlist_copy(const jdns_nameserverlist_t *a)
796
jdns_nameserverlist_t *c = jdns_nameserverlist_new();
799
c->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *) * a->count);
801
for(n = 0; n < c->count; ++n)
802
c->item[n] = jdns_nameserver_copy(a->item[n]);
807
void jdns_nameserverlist_delete(jdns_nameserverlist_t *a)
814
for(n = 0; n < a->count; ++n)
815
jdns_nameserver_delete(a->item[n]);
821
void jdns_nameserverlist_append(jdns_nameserverlist_t *a, const jdns_address_t *addr, int port)
824
a->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *));
826
a->item = (jdns_nameserver_t **)jdns_realloc(a->item, sizeof(jdns_nameserver_t *) * (a->count + 1));
827
a->item[a->count] = jdns_nameserver_new();
828
jdns_nameserver_set(a->item[a->count], addr, port);
832
//----------------------------------------------------------------------------
834
//----------------------------------------------------------------------------
835
jdns_dnshost_t *jdns_dnshost_new()
837
jdns_dnshost_t *a = alloc_type(jdns_dnshost_t);
843
jdns_dnshost_t *jdns_dnshost_copy(const jdns_dnshost_t *a)
845
jdns_dnshost_t *c = jdns_dnshost_new();
847
c->name = jdns_string_copy(a->name);
849
c->address = jdns_address_copy(a->address);
853
void jdns_dnshost_delete(jdns_dnshost_t *a)
857
jdns_string_delete(a->name);
858
jdns_address_delete(a->address);
862
//----------------------------------------------------------------------------
864
//----------------------------------------------------------------------------
865
jdns_dnshostlist_t *jdns_dnshostlist_new()
867
jdns_dnshostlist_t *a = alloc_type(jdns_dnshostlist_t);
873
jdns_dnshostlist_t *jdns_dnshostlist_copy(const jdns_dnshostlist_t *a)
876
jdns_dnshostlist_t *c = jdns_dnshostlist_new();
879
c->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *) * a->count);
881
for(n = 0; n < c->count; ++n)
882
c->item[n] = jdns_dnshost_copy(a->item[n]);
887
void jdns_dnshostlist_delete(jdns_dnshostlist_t *a)
894
for(n = 0; n < a->count; ++n)
895
jdns_dnshost_delete(a->item[n]);
901
void jdns_dnshostlist_append(jdns_dnshostlist_t *a, const jdns_dnshost_t *host)
904
a->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *));
906
a->item = (jdns_dnshost_t **)jdns_realloc(a->item, sizeof(jdns_dnshost_t *) * (a->count + 1));
907
a->item[a->count] = jdns_dnshost_copy(host);
911
//----------------------------------------------------------------------------
913
//----------------------------------------------------------------------------
914
jdns_dnsparams_t *jdns_dnsparams_new()
916
jdns_dnsparams_t *a = alloc_type(jdns_dnsparams_t);
917
a->nameservers = jdns_nameserverlist_new();
918
a->domains = jdns_stringlist_new();
919
a->hosts = jdns_dnshostlist_new();
923
jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a)
925
jdns_dnsparams_t *c = jdns_dnsparams_new();
926
c->nameservers = jdns_nameserverlist_copy(a->nameservers);
927
c->domains = jdns_stringlist_copy(a->domains);
928
c->hosts = jdns_dnshostlist_copy(a->hosts);
932
void jdns_dnsparams_delete(jdns_dnsparams_t *a)
936
jdns_nameserverlist_delete(a->nameservers);
937
jdns_stringlist_delete(a->domains);
938
jdns_dnshostlist_delete(a->hosts);
942
void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a, const jdns_address_t *addr, int port)
944
jdns_nameserverlist_append(a->nameservers, addr, port);
947
void jdns_dnsparams_append_domain(jdns_dnsparams_t *a, const jdns_string_t *domain)
949
jdns_stringlist_append(a->domains, domain);
952
void jdns_dnsparams_append_host(jdns_dnsparams_t *a, const jdns_string_t *name, const jdns_address_t *address)
954
jdns_dnshost_t *h = jdns_dnshost_new();
955
h->name = jdns_string_copy(name);
956
h->address = jdns_address_copy(address);
957
jdns_dnshostlist_append(a->hosts, h);
958
jdns_dnshost_delete(h);
961
//----------------------------------------------------------------------------
963
//----------------------------------------------------------------------------
964
void _jdns_rr_data_reset(jdns_rr_t *r)
978
case JDNS_RTYPE_AAAA:
979
jdns_address_delete(r->data.address);
983
jdns_server_delete(r->data.server);
985
case JDNS_RTYPE_CNAME:
988
jdns_free(r->data.name);
991
jdns_stringlist_delete(r->data.texts);
993
case JDNS_RTYPE_HINFO:
994
jdns_string_delete(r->data.hinfo.cpu);
995
jdns_string_delete(r->data.hinfo.os);
1005
void _jdns_rr_data_copy(const jdns_rr_t *r, jdns_rr_t *c)
1008
c->qclass = r->qclass;
1009
c->rdlength = r->rdlength;
1010
c->rdata = jdns_copy_array(r->rdata, r->rdlength);
1017
case JDNS_RTYPE_AAAA:
1018
c->data.address = jdns_address_copy(r->data.address);
1021
case JDNS_RTYPE_SRV:
1022
c->data.server = jdns_server_copy(r->data.server);
1024
case JDNS_RTYPE_CNAME:
1025
case JDNS_RTYPE_PTR:
1027
c->data.name = _ustrdup(r->data.name);
1029
case JDNS_RTYPE_TXT:
1030
c->data.texts = jdns_stringlist_copy(r->data.texts);
1032
case JDNS_RTYPE_HINFO:
1033
c->data.hinfo.cpu = jdns_string_copy(r->data.hinfo.cpu);
1034
c->data.hinfo.os = jdns_string_copy(r->data.hinfo.os);
1043
jdns_rr_t *jdns_rr_new()
1045
jdns_rr_t *r = alloc_type(jdns_rr_t);
1056
jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r)
1058
jdns_rr_t *c = jdns_rr_new();
1060
c->owner = _ustrdup(r->owner);
1062
_jdns_rr_data_copy(r, c);
1066
void jdns_rr_delete(jdns_rr_t *r)
1071
jdns_free(r->owner);
1072
_jdns_rr_data_reset(r);
1076
void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name)
1079
jdns_free(r->owner);
1080
r->owner = _ustrdup(name);
1083
void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata, int rdlength)
1085
_jdns_rr_data_reset(r);
1087
r->rdlength = rdlength;
1088
r->rdata = jdns_copy_array(rdata, rdlength);
1091
void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address)
1093
_jdns_rr_data_reset(r);
1094
r->type = JDNS_RTYPE_A;
1096
r->data.address = jdns_address_copy(address);
1099
void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address)
1101
_jdns_rr_data_reset(r);
1102
r->type = JDNS_RTYPE_AAAA;
1104
r->data.address = jdns_address_copy(address);
1107
void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority)
1109
jdns_server_t *s = jdns_server_new();
1110
jdns_server_set_name(s, name);
1111
s->priority = priority;
1113
_jdns_rr_data_reset(r);
1114
r->type = JDNS_RTYPE_MX;
1119
void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port, int priority, int weight)
1121
jdns_server_t *s = jdns_server_new();
1122
jdns_server_set_name(s, name);
1124
s->priority = priority;
1127
_jdns_rr_data_reset(r);
1128
r->type = JDNS_RTYPE_SRV;
1133
void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name)
1135
_jdns_rr_data_reset(r);
1136
r->type = JDNS_RTYPE_CNAME;
1138
r->data.name = _ustrdup(name);
1141
void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name)
1143
_jdns_rr_data_reset(r);
1144
r->type = JDNS_RTYPE_PTR;
1146
r->data.name = _ustrdup(name);
1149
void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts)
1151
_jdns_rr_data_reset(r);
1152
r->type = JDNS_RTYPE_TXT;
1154
r->data.texts = jdns_stringlist_copy(texts);
1157
void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu, const jdns_string_t *os)
1159
_jdns_rr_data_reset(r);
1160
r->type = JDNS_RTYPE_HINFO;
1162
r->data.hinfo.cpu = jdns_string_copy(cpu);
1163
r->data.hinfo.os = jdns_string_copy(os);
1166
void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name)
1168
_jdns_rr_data_reset(r);
1169
r->type = JDNS_RTYPE_NS;
1171
r->data.name = _ustrdup(name);
1174
int jdns_rr_verify(const jdns_rr_t *r)
1179
if(!jdns_packet_name_isvalid(r->owner, _ustrlen(r->owner)))
1185
case JDNS_RTYPE_SRV:
1187
// consider it valid if we don't have a known to check
1190
if(!jdns_packet_name_isvalid(r->data.server->name, _ustrlen(r->data.server->name)))
1194
case JDNS_RTYPE_CNAME:
1195
case JDNS_RTYPE_PTR:
1200
if(!jdns_packet_name_isvalid(r->data.name, _ustrlen(r->data.name)))
1204
case JDNS_RTYPE_TXT:
1209
for(n = 0; n < r->data.texts->count; ++n)
1211
if(r->data.texts->item[n]->size > 255)
1216
case JDNS_RTYPE_HINFO:
1220
if(r->data.hinfo.cpu->size > 255)
1222
if(r->data.hinfo.os->size > 255)
1231
static jdns_string_t *read_name_at_end(const jdns_packet_resource_t *pr, const jdns_packet_t *ref, int _at)
1233
jdns_string_t *name;
1236
if(!jdns_packet_resource_read_name(pr, ref, &at, &name))
1238
if(at != pr->rdlength)
1240
jdns_string_delete(name);
1246
static jdns_string_t *read_text_string(const jdns_packet_resource_t *pr, int *_at)
1251
if(at + 1 > pr->rdlength)
1253
len = pr->rdata[at++];
1254
if(at + len > pr->rdlength)
1256
out = jdns_string_new();
1257
jdns_string_set(out, pr->rdata + at, len);
1263
// if the type is known, then it must be parsed properly
1264
// if the type is unknown, then that's ok
1265
// rdata is always copied, known or not
1266
jdns_rr_t *jdns_rr_from_resource(const jdns_packet_resource_t *pr, const jdns_packet_t *ref)
1270
if(pr->qtype == JDNS_RTYPE_ANY)
1277
jdns_address_t *addr;
1278
unsigned long int ip;
1279
if(pr->rdlength != 4)
1281
memcpy(&ip, pr->rdata, 4);
1283
addr = jdns_address_new();
1284
jdns_address_set_ipv4(addr, ip);
1286
jdns_rr_set_A(rr, addr);
1287
jdns_address_delete(addr);
1290
case JDNS_RTYPE_AAAA:
1292
jdns_address_t *addr;
1293
if(pr->rdlength != 16)
1295
addr = jdns_address_new();
1296
jdns_address_set_ipv6(addr, pr->rdata);
1298
jdns_rr_set_AAAA(rr, addr);
1299
jdns_address_delete(addr);
1304
unsigned short priority;
1305
jdns_string_t *name;
1306
if(pr->rdlength < 2)
1308
memcpy(&priority, pr->rdata, 2);
1309
priority = ntohs(priority);
1310
name = read_name_at_end(pr, ref, 2);
1314
jdns_rr_set_MX(rr, name->data, priority);
1315
jdns_string_delete(name);
1318
case JDNS_RTYPE_SRV:
1320
unsigned short priority, weight, port;
1321
jdns_string_t *name;
1322
if(pr->rdlength < 6)
1324
memcpy(&priority, pr->rdata, 2);
1325
priority = ntohs(priority);
1326
memcpy(&weight, pr->rdata + 2, 2);
1327
weight = ntohs(weight);
1328
memcpy(&port, pr->rdata + 4, 2);
1330
name = read_name_at_end(pr, ref, 6);
1334
jdns_rr_set_SRV(rr, name->data, port, priority, weight);
1335
jdns_string_delete(name);
1338
case JDNS_RTYPE_CNAME:
1340
jdns_string_t *name;
1341
name = read_name_at_end(pr, ref, 0);
1345
jdns_rr_set_CNAME(rr, name->data);
1346
jdns_string_delete(name);
1349
case JDNS_RTYPE_PTR:
1351
jdns_string_t *name;
1352
name = read_name_at_end(pr, ref, 0);
1356
jdns_rr_set_PTR(rr, name->data);
1357
jdns_string_delete(name);
1360
case JDNS_RTYPE_TXT:
1362
jdns_stringlist_t *texts;
1365
texts = jdns_stringlist_new();
1368
while(at < pr->rdlength)
1370
str = read_text_string(pr, &at);
1376
jdns_stringlist_append(texts, str);
1377
jdns_string_delete(str);
1381
jdns_stringlist_delete(texts);
1385
jdns_rr_set_TXT(rr, texts);
1386
jdns_stringlist_delete(texts);
1389
case JDNS_RTYPE_HINFO:
1391
jdns_string_t *cpu, *os;
1394
cpu = read_text_string(pr, &at);
1397
os = read_text_string(pr, &at);
1400
jdns_string_delete(cpu);
1403
if(at != pr->rdlength)
1405
jdns_string_delete(cpu);
1406
jdns_string_delete(os);
1410
jdns_rr_set_HINFO(rr, cpu, os);
1411
jdns_string_delete(cpu);
1412
jdns_string_delete(os);
1417
jdns_string_t *name;
1418
name = read_name_at_end(pr, ref, 0);
1422
jdns_rr_set_NS(rr, name->data);
1423
jdns_string_delete(name);
1429
rr->type = pr->qtype;
1436
rr->qclass = pr->qclass;
1437
rr->owner = _ustrdup(pr->qname->data);
1438
rr->ttl = (int)pr->ttl; // pr->ttl is 31-bits, cast is safe
1439
rr->rdlength = pr->rdlength;
1440
rr->rdata = jdns_copy_array(pr->rdata, pr->rdlength);
1446
//----------------------------------------------------------------------------
1448
//----------------------------------------------------------------------------
1449
#define ARRAY_DELETE(array, count, dtor) \
1454
for(n = 0; n < count; ++n) \
1462
#define ARRAY_COPY(type, array_src, count_src, array_dest, count_dest, cctor) \
1467
count_dest = count_src; \
1468
array_dest = (type **)jdns_alloc(sizeof(type *) * count_dest); \
1469
for(n = 0; n < count_dest; ++n) \
1470
array_dest[n] = cctor(array_src[n]); \
1474
#define ARRAY_APPEND(type, array, count, item) \
1477
array = (type **)jdns_alloc(sizeof(type *)); \
1479
array = (type **)jdns_realloc(array, sizeof(type *) * (count + 1)); \
1480
array[count] = item; \
1484
jdns_response_t *jdns_response_new()
1486
jdns_response_t *r = alloc_type(jdns_response_t);
1488
r->answerRecords = 0;
1489
r->authorityCount = 0;
1490
r->authorityRecords = 0;
1491
r->additionalCount = 0;
1492
r->additionalRecords = 0;
1496
jdns_response_t *jdns_response_copy(const jdns_response_t *r)
1498
jdns_response_t *c = jdns_response_new();
1499
ARRAY_COPY(jdns_rr_t, r->answerRecords, r->answerCount, c->answerRecords, c->answerCount, jdns_rr_copy);
1500
ARRAY_COPY(jdns_rr_t, r->authorityRecords, r->authorityCount, c->authorityRecords, c->authorityCount, jdns_rr_copy);
1501
ARRAY_COPY(jdns_rr_t, r->additionalRecords, r->additionalCount, c->additionalRecords, c->additionalCount, jdns_rr_copy);
1505
void jdns_response_delete(jdns_response_t *r)
1509
ARRAY_DELETE(r->answerRecords, r->answerCount, jdns_rr_delete);
1510
ARRAY_DELETE(r->authorityRecords, r->authorityCount, jdns_rr_delete);
1511
ARRAY_DELETE(r->additionalRecords, r->additionalCount, jdns_rr_delete);
1515
void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr)
1517
ARRAY_APPEND(jdns_rr_t, r->answerRecords, r->answerCount, jdns_rr_copy(rr));
1520
void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr)
1522
ARRAY_APPEND(jdns_rr_t, r->authorityRecords, r->authorityCount, jdns_rr_copy(rr));
1525
void jdns_response_append_additional(jdns_response_t *r, const jdns_rr_t *rr)
1527
ARRAY_APPEND(jdns_rr_t, r->additionalRecords, r->additionalCount, jdns_rr_copy(rr));
1530
void jdns_response_remove_extra(jdns_response_t *r)
1532
ARRAY_DELETE(r->authorityRecords, r->authorityCount, jdns_rr_delete);
1533
ARRAY_DELETE(r->additionalRecords, r->additionalCount, jdns_rr_delete);
1536
void jdns_response_remove_answer(jdns_response_t *r, int pos)
1538
jdns_rr_t *rr = r->answerRecords[pos];
1541
// free the position
1542
if(r->answerCount > 1)
1544
memmove(r->answerRecords + pos, r->answerRecords + pos + 1, (r->answerCount - pos - 1) * sizeof(void *));
1549
jdns_free(r->answerRecords);
1550
r->answerRecords = 0;