File indexing completed on 2024-05-19 04:06:38
0001 /* 0002 * Copyright (C) 2005-2008 Justin Karneges 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a 0005 * copy of this software and associated documentation files (the 0006 * "Software"), to deal in the Software without restriction, including 0007 * without limitation the rights to use, copy, modify, merge, publish, 0008 * distribute, sublicense, and/or sell copies of the Software, and to 0009 * permit persons to whom the Software is furnished to do so, subject to 0010 * the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included 0013 * in all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 0016 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 0017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 0018 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 0019 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 0020 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 0021 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0022 */ 0023 0024 #include "jdns_p.h" 0025 0026 #include "jdns_packet.h" 0027 0028 #ifdef WIN32 0029 # include <winsock2.h> 0030 #endif 0031 0032 /*---------------------------------------------------------------------------- */ 0033 /* misc */ 0034 /*---------------------------------------------------------------------------- */ 0035 void *jdns_alloc(int size) 0036 { 0037 return malloc(size); 0038 } 0039 0040 void *jdns_realloc(void *p, int size) 0041 { 0042 return realloc(p, size); 0043 } 0044 0045 void jdns_free(void *p) 0046 { 0047 free(p); 0048 } 0049 0050 char *jdns_strdup(const char *s) 0051 { 0052 char *p; 0053 int len; 0054 0055 len = strlen(s) + 1; /* the zero */ 0056 p = (char *)jdns_alloc(len); 0057 memcpy(p, s, len); 0058 return p; 0059 } 0060 0061 unsigned char *jdns_copy_array(const unsigned char *src, int size) 0062 { 0063 unsigned char *out; 0064 if(size <= 0) 0065 return 0; 0066 out = (unsigned char *)jdns_alloc(size); 0067 memcpy(out, src, size); 0068 return out; 0069 } 0070 0071 int jdns_domain_cmp(const unsigned char *a, const unsigned char *b) 0072 { 0073 int n; 0074 int len_a; 0075 0076 /* case-insensitive compare */ 0077 len_a = _ustrlen(a); 0078 if(len_a != (int)_ustrlen(b)) 0079 return 0; 0080 0081 for(n = 0; n < len_a; ++n) 0082 { 0083 if(tolower(a[n]) != tolower(b[n])) 0084 return 0; 0085 } 0086 return 1; 0087 } 0088 0089 int jdns_sprintf_s(char *str, int n, const char *format, ...) 0090 { 0091 int ret; 0092 va_list ap; 0093 va_start(ap, format); 0094 ret = jdns_vsprintf_s(str, n, format, ap); 0095 va_end(ap); 0096 return ret; 0097 } 0098 0099 int jdns_vsprintf_s(char *str, int n, const char *format, va_list ap) 0100 { 0101 #if defined(_MSC_VER) && _MSC_VER >= 1400 0102 return vsprintf_s(str, n, format, ap); 0103 #else 0104 (void)n; 0105 return vsprintf(str, format, ap); 0106 #endif 0107 } 0108 0109 FILE *jdns_fopen(const char *path, const char *mode) 0110 { 0111 #if defined(_MSC_VER) && _MSC_VER >= 1400 0112 FILE *fp; 0113 if(fopen_s(&fp, path, mode) != 0) 0114 return 0; 0115 return fp; 0116 #else 0117 return fopen(path, mode); 0118 #endif 0119 } 0120 0121 jdns_string_t *jdns_getenv(const char *name) 0122 { 0123 #if defined(_MSC_VER) && _MSC_VER >= 1400 0124 jdns_string_t *out; 0125 char *dest; 0126 size_t size; 0127 int sizei; 0128 errno_t ret; 0129 ret = getenv_s(&size, 0, 0, name); 0130 if(ret != 0 || size == 0) 0131 return 0; 0132 sizei = (int)size; 0133 dest = (char *)jdns_alloc(sizei); 0134 ret = getenv_s(&size, dest, size, name); 0135 if(ret != 0) 0136 { 0137 free(dest); 0138 return 0; 0139 } 0140 out = jdns_string_new(); 0141 out->size = sizei - 1; 0142 out->data = dest; /* must be zero-terminated, which it is */ 0143 return out; 0144 #else 0145 jdns_string_t *out; 0146 char *val; 0147 val = getenv(name); 0148 if(!val) 0149 return 0; 0150 out = jdns_string_new(); 0151 jdns_string_set_cstr(out, val); 0152 return out; 0153 #endif 0154 } 0155 0156 char *jdns_strcpy(char *dst, const char *src) 0157 { 0158 #if defined(_MSC_VER) && _MSC_VER >= 1400 0159 int len; 0160 /* deliberately unsafe */ 0161 len = strlen(src); 0162 if(strcpy_s(dst, len + 1, src) != 0) 0163 return 0; 0164 return dst; 0165 #else 0166 return strcpy(dst, src); 0167 #endif 0168 } 0169 0170 /*---------------------------------------------------------------------------- */ 0171 /* jdns_object */ 0172 /*---------------------------------------------------------------------------- */ 0173 void *jdns_object_new(int size, void (*dtor)(void *), void *(*cctor)(const void *)) 0174 { 0175 jdns_object_t *a = (jdns_object_t *)jdns_alloc(size); 0176 memset(a, 0, size); 0177 a->dtor = dtor; 0178 a->cctor = cctor; 0179 return a; 0180 } 0181 0182 void *jdns_object_copy(const void *a) 0183 { 0184 return ((const jdns_object_t *)a)->cctor(a); 0185 } 0186 0187 void jdns_object_delete(void *a) 0188 { 0189 ((jdns_object_t *)a)->dtor(a); 0190 } 0191 0192 void jdns_object_free(void *a) 0193 { 0194 jdns_free(a); 0195 } 0196 0197 /*---------------------------------------------------------------------------- */ 0198 /* jdns_list */ 0199 /*---------------------------------------------------------------------------- */ 0200 jdns_list_t *jdns_list_new() 0201 { 0202 jdns_list_t *a = JDNS_OBJECT_NEW(jdns_list); 0203 a->count = 0; 0204 a->item = 0; 0205 a->valueList = 0; 0206 a->autoDelete = 0; 0207 return a; 0208 } 0209 0210 jdns_list_t *jdns_list_copy(const jdns_list_t *a) 0211 { 0212 jdns_list_t *c = jdns_list_new(); 0213 0214 /* note: copying a list with autoDelete should not ever be done. */ 0215 /* heck, let's not even allow it. return an empty list. */ 0216 if(a->autoDelete) 0217 return c; 0218 0219 c->valueList = a->valueList; 0220 0221 /* copy the items */ 0222 if(a->item) 0223 { 0224 int n; 0225 c->count = a->count; 0226 c->item = (void **)jdns_alloc(sizeof(void *) * c->count); 0227 if(a->valueList) 0228 { 0229 /* deep copy */ 0230 for(n = 0; n < c->count; ++n) 0231 c->item[n] = jdns_object_copy(a->item[n]); 0232 } 0233 else 0234 { 0235 /* just the pointer */ 0236 for(n = 0; n < c->count; ++n) 0237 c->item[n] = a->item[n]; 0238 } 0239 } 0240 return c; 0241 } 0242 0243 void jdns_list_delete(jdns_list_t *a) 0244 { 0245 if(!a) 0246 return; 0247 jdns_list_clear(a); 0248 jdns_object_free(a); 0249 } 0250 0251 void jdns_list_clear(jdns_list_t *a) 0252 { 0253 if(a->item) 0254 { 0255 /* delete the items if necessary */ 0256 if(a->valueList || a->autoDelete) 0257 { 0258 int n; 0259 for(n = 0; n < a->count; ++n) 0260 jdns_object_delete(a->item[n]); 0261 } 0262 jdns_free(a->item); 0263 a->item = 0; 0264 a->count = 0; 0265 } 0266 } 0267 0268 void jdns_list_insert(jdns_list_t *a, void *item, int pos) 0269 { 0270 /* make memory */ 0271 if(!a->item) 0272 a->item = (void **)jdns_alloc(sizeof(void *)); 0273 else 0274 a->item = (void **)jdns_realloc(a->item, sizeof(void *) * (a->count + 1)); 0275 0276 /* prepare position */ 0277 if(pos != -1) 0278 memmove(a->item + pos + 1, a->item + pos, (a->count - pos) * sizeof(void *)); 0279 else 0280 pos = a->count; 0281 0282 /* insert it */ 0283 if(a->valueList) 0284 a->item[pos] = jdns_object_copy(item); 0285 else 0286 a->item[pos] = item; 0287 ++a->count; 0288 } 0289 0290 void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos) 0291 { 0292 jdns_list_insert(a, (void *)item, pos); 0293 } 0294 0295 void jdns_list_remove(jdns_list_t *a, void *item) 0296 { 0297 int n; 0298 int pos = -1; 0299 for(n = 0; n < a->count; ++n) 0300 { 0301 if(a->item[n] == item) 0302 { 0303 pos = n; 0304 break; 0305 } 0306 } 0307 if(pos == -1) 0308 return; 0309 0310 jdns_list_remove_at(a, pos); 0311 } 0312 0313 void jdns_list_remove_at(jdns_list_t *a, int pos) 0314 { 0315 if(pos < 0 || pos >= a->count) 0316 return; 0317 0318 /* delete the item if necessary */ 0319 if(a->valueList || a->autoDelete) 0320 jdns_object_delete(a->item[pos]); 0321 0322 /* free the position */ 0323 if(a->count > 1) 0324 { 0325 memmove(a->item + pos, a->item + pos + 1, (a->count - pos - 1) * sizeof(void *)); 0326 --a->count; 0327 } 0328 else 0329 { 0330 jdns_free(a->item); 0331 a->item = 0; 0332 a->count = 0; 0333 } 0334 } 0335 0336 /*---------------------------------------------------------------------------- */ 0337 /* jdns_string */ 0338 /*---------------------------------------------------------------------------- */ 0339 jdns_string_t *jdns_string_new() 0340 { 0341 jdns_string_t *s = JDNS_OBJECT_NEW(jdns_string); 0342 s->data = 0; 0343 s->size = 0; 0344 return s; 0345 } 0346 0347 jdns_string_t *jdns_string_copy(const jdns_string_t *s) 0348 { 0349 jdns_string_t *c = jdns_string_new(); 0350 if(s->data) 0351 jdns_string_set(c, s->data, s->size); 0352 return c; 0353 } 0354 0355 void jdns_string_delete(jdns_string_t *s) 0356 { 0357 if(!s) 0358 return; 0359 if(s->data) 0360 jdns_free(s->data); 0361 jdns_object_free(s); 0362 } 0363 0364 void jdns_string_set(jdns_string_t *s, const unsigned char *str, int str_len) 0365 { 0366 if(s->data) 0367 jdns_free(s->data); 0368 s->data = (unsigned char *)jdns_alloc(str_len + 1); 0369 memcpy(s->data, str, str_len); 0370 s->data[str_len] = 0; 0371 s->size = str_len; 0372 } 0373 0374 void jdns_string_set_cstr(jdns_string_t *s, const char *str) 0375 { 0376 jdns_string_set(s, (const unsigned char *)str, strlen(str)); 0377 } 0378 0379 int jdns_string_indexOf(const jdns_string_t *s, unsigned char c, int pos) 0380 { 0381 int n; 0382 for(n = pos; n < s->size; ++n) 0383 { 0384 if(s->data[n] == c) 0385 return n; 0386 } 0387 return -1; 0388 } 0389 0390 jdns_stringlist_t *jdns_string_split(const jdns_string_t *s, unsigned char sep) 0391 { 0392 int at, n, len; 0393 jdns_string_t *str; 0394 jdns_stringlist_t *out; 0395 0396 at = 0; 0397 out = jdns_stringlist_new(); 0398 while(at < s->size) 0399 { 0400 n = jdns_string_indexOf(s, sep, at); 0401 if(n == -1) 0402 n = s->size; 0403 len = n - at; 0404 /* FIXME: should we allow empty items? */ 0405 /*if(len == 0) */ 0406 /* break; */ 0407 str = jdns_string_new(); 0408 jdns_string_set(str, s->data + at, len); 0409 jdns_stringlist_append(out, str); 0410 jdns_string_delete(str); 0411 at = n + 1; /* skip over separator */ 0412 } 0413 return out; 0414 } 0415 0416 /*---------------------------------------------------------------------------- */ 0417 /* jdns_stringlist */ 0418 /*---------------------------------------------------------------------------- */ 0419 jdns_stringlist_t *jdns_stringlist_new() 0420 { 0421 jdns_list_t *a = jdns_list_new(); 0422 a->valueList = 1; 0423 return (jdns_stringlist_t *)a; 0424 } 0425 0426 jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a) 0427 { 0428 return (jdns_stringlist_t *)jdns_list_copy((const jdns_list_t *)a); 0429 } 0430 0431 void jdns_stringlist_delete(jdns_stringlist_t *a) 0432 { 0433 jdns_list_delete((jdns_list_t *)a); 0434 /* note: no need to call jdns_object_free() here */ 0435 } 0436 0437 void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str) 0438 { 0439 jdns_list_insert_value((jdns_list_t *)a, str, -1); 0440 } 0441 0442 /*---------------------------------------------------------------------------- */ 0443 /* jdns_address */ 0444 /*---------------------------------------------------------------------------- */ 0445 jdns_address_t *jdns_address_new() 0446 { 0447 jdns_address_t *a = alloc_type(jdns_address_t); 0448 a->isIpv6 = 0; 0449 a->addr.v4 = 0; 0450 a->c_str = jdns_strdup(""); 0451 return a; 0452 } 0453 0454 jdns_address_t *jdns_address_copy(const jdns_address_t *a) 0455 { 0456 jdns_address_t *c = jdns_address_new(); 0457 if(a->isIpv6) 0458 jdns_address_set_ipv6(c, a->addr.v6); 0459 else 0460 jdns_address_set_ipv4(c, a->addr.v4); 0461 return c; 0462 } 0463 0464 void jdns_address_delete(jdns_address_t *a) 0465 { 0466 if(!a) 0467 return; 0468 if(a->isIpv6) 0469 jdns_free(a->addr.v6); 0470 jdns_free(a->c_str); 0471 jdns_free(a); 0472 } 0473 0474 void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4) 0475 { 0476 if(a->isIpv6) 0477 jdns_free(a->addr.v6); 0478 jdns_free(a->c_str); 0479 a->isIpv6 = 0; 0480 a->addr.v4 = ipv4; 0481 a->c_str = (char *)jdns_alloc(16); /* max size (3 * 4 + 3 + 1) */ 0482 jdns_sprintf_s(a->c_str, 16, "%d.%d.%d.%d", 0483 (unsigned char)((ipv4 >> 24) & 0xff), 0484 (unsigned char)((ipv4 >> 16) & 0xff), 0485 (unsigned char)((ipv4 >> 8) & 0xff), 0486 (unsigned char)((ipv4) & 0xff)); 0487 } 0488 0489 void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6) 0490 { 0491 int n; 0492 unsigned char *p; 0493 unsigned short word[8]; 0494 if(a->isIpv6) 0495 jdns_free(a->addr.v6); 0496 jdns_free(a->c_str); 0497 a->isIpv6 = 1; 0498 a->addr.v6 = (unsigned char *)jdns_alloc(16); 0499 memcpy(a->addr.v6, ipv6, 16); 0500 p = (unsigned char *)a->addr.v6; 0501 a->c_str = (char *)jdns_alloc(40); /* max size (8 * 4 + 7 + 1) */ 0502 /* each word in a 16-byte ipv6 address is network byte order */ 0503 for(n = 0; n < 8; ++n) 0504 word[n] = ((unsigned short)(p[n * 2]) << 8) + (unsigned short)(p[n * 2 + 1]); 0505 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]); 0506 } 0507 0508 int jdns_address_set_cstr(jdns_address_t *a, const char *str) 0509 { 0510 int slen = strlen(str); 0511 0512 /* ipv6 */ 0513 if(strchr(str, ':')) 0514 { 0515 jdns_string_t *in; 0516 jdns_stringlist_t *list; 0517 unsigned char ipv6[16]; 0518 int n, at, count, fill; 0519 0520 in = jdns_string_new(); 0521 jdns_string_set_cstr(in, str); 0522 list = jdns_string_split(in, ':'); 0523 jdns_string_delete(in); 0524 0525 /* a confusing outputting-backwards parser adapted from qt */ 0526 0527 count = list->count; 0528 0529 if(count < 3 || count > 8) 0530 goto error; 0531 0532 at = 16; 0533 fill = 9 - count; 0534 for(n = count - 1; n >= 0; --n) 0535 { 0536 if(at <= 0) 0537 goto error; 0538 0539 if(list->item[n]->size == 0) 0540 { 0541 if(n == count - 1) 0542 { 0543 if(list->item[n - 1]->size != 0) 0544 goto error; 0545 ipv6[--at] = 0; 0546 ipv6[--at] = 0; 0547 } 0548 else if(n == 0) 0549 { 0550 if(list->item[n + 1]->size != 0) 0551 goto error; 0552 ipv6[--at] = 0; 0553 ipv6[--at] = 0; 0554 } 0555 else 0556 { 0557 int i; 0558 for(i = 0; i < fill; ++i) 0559 { 0560 if(at <= 0) 0561 goto error; 0562 ipv6[--at] = 0; 0563 ipv6[--at] = 0; 0564 } 0565 } 0566 } 0567 else 0568 { 0569 if(jdns_string_indexOf(list->item[n], '.', 0) == -1) 0570 { 0571 int x; 0572 x = strtol((const char *)list->item[n]->data, NULL, 16); 0573 if(x < 0 || x > 0xffff) 0574 goto error; 0575 ipv6[--at] = x & 0xff; 0576 ipv6[--at] = (x >> 8) & 0xff; 0577 } 0578 else 0579 { 0580 jdns_address_t *v4; 0581 0582 if(n != count - 1) 0583 goto error; 0584 0585 v4 = jdns_address_new(); 0586 if(!jdns_address_set_cstr(v4, (char *)list->item[n]->data)) 0587 { 0588 jdns_address_delete(v4); 0589 goto error; 0590 } 0591 0592 ipv6[--at] = (unsigned char)(v4->addr.v4 & 0xff); 0593 ipv6[--at] = (unsigned char)((v4->addr.v4 >> 8) & 0xff); 0594 ipv6[--at] = (unsigned char)((v4->addr.v4 >> 16) & 0xff); 0595 ipv6[--at] = (unsigned char)((v4->addr.v4 >> 24) & 0xff); 0596 jdns_address_delete(v4); 0597 --fill; 0598 } 0599 } 0600 } 0601 jdns_stringlist_delete(list); 0602 0603 jdns_address_set_ipv6(a, ipv6); 0604 return 1; 0605 0606 error: 0607 jdns_stringlist_delete(list); 0608 return 0; 0609 } 0610 else if(strchr(str, '.')) 0611 { 0612 unsigned char b[4]; 0613 int x; 0614 unsigned long int ipv4; 0615 int at; 0616 char *part; 0617 int len; 0618 const char *p, *p2; 0619 0620 p = str; 0621 at = 0; 0622 while(1) 0623 { 0624 p2 = strchr(p, '.'); 0625 if(!p2) 0626 p2 = str + slen; 0627 len = p2 - p; 0628 0629 /* convert the section into a byte */ 0630 part = (char *)jdns_alloc(len + 1); 0631 memcpy(part, p, len); 0632 part[len] = 0; 0633 x = strtol(part, NULL, 10); 0634 jdns_free(part); 0635 if(x < 0 || x > 0xff) 0636 break; 0637 b[at++] = (unsigned char)x; 0638 0639 /* done? */ 0640 if(p2 >= str + slen) 0641 break; 0642 0643 /* skip over the separator */ 0644 p = p2 + 1; 0645 } 0646 if(at != 4) 0647 return 0; 0648 0649 ipv4 = 0; 0650 ipv4 += b[0]; 0651 ipv4 <<= 8; 0652 ipv4 += b[1]; 0653 ipv4 <<= 8; 0654 ipv4 += b[2]; 0655 ipv4 <<= 8; 0656 ipv4 += b[3]; 0657 0658 jdns_address_set_ipv4(a, ipv4); 0659 return 1; 0660 } 0661 else 0662 return 0; 0663 } 0664 0665 int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b) 0666 { 0667 /* same protocol? */ 0668 if(a->isIpv6 != b->isIpv6) 0669 return 0; 0670 if(a->isIpv6) 0671 { 0672 int n; 0673 for(n = 0; n < 16; ++n) 0674 { 0675 if(a->addr.v6[n] != b->addr.v6[n]) 0676 break; 0677 } 0678 if(n == 16) 0679 return 1; 0680 } 0681 else 0682 { 0683 if(a->addr.v4 == b->addr.v4) 0684 return 1; 0685 } 0686 return 0; 0687 } 0688 0689 /* FF02::FB */ 0690 unsigned char jdns_multicast_addr6_value_v6[] = 0691 { 0692 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb 0694 }; 0695 0696 jdns_address_t *jdns_address_multicast4_new() 0697 { 0698 jdns_address_t *a = jdns_address_new(); 0699 jdns_address_set_ipv4(a, 0xe00000fb); 0700 return a; 0701 } 0702 0703 jdns_address_t *jdns_address_multicast6_new() 0704 { 0705 jdns_address_t *a = jdns_address_new(); 0706 jdns_address_set_ipv6(a, jdns_multicast_addr6_value_v6); 0707 return a; 0708 } 0709 0710 /*---------------------------------------------------------------------------- */ 0711 /* jdns_server */ 0712 /*---------------------------------------------------------------------------- */ 0713 jdns_server_t *jdns_server_new() 0714 { 0715 jdns_server_t *s = alloc_type(jdns_server_t); 0716 s->name = 0; 0717 s->port = 0; 0718 s->priority = 0; 0719 s->weight = 0; 0720 return s; 0721 } 0722 0723 jdns_server_t *jdns_server_copy(const jdns_server_t *s) 0724 { 0725 jdns_server_t *c = jdns_server_new(); 0726 if(s->name) 0727 c->name = _ustrdup(s->name); 0728 c->port = s->port; 0729 c->priority = s->priority; 0730 c->weight = s->weight; 0731 return c; 0732 } 0733 0734 void jdns_server_delete(jdns_server_t *s) 0735 { 0736 if(!s) 0737 return; 0738 if(s->name) 0739 jdns_free(s->name); 0740 jdns_object_free(s); 0741 } 0742 0743 void jdns_server_set_name(jdns_server_t *s, const unsigned char *name) 0744 { 0745 if(s->name) 0746 jdns_free(s->name); 0747 s->name = _ustrdup(name); 0748 } 0749 0750 /*---------------------------------------------------------------------------- */ 0751 /* jdns_nameserver */ 0752 /*---------------------------------------------------------------------------- */ 0753 jdns_nameserver_t *jdns_nameserver_new() 0754 { 0755 jdns_nameserver_t *a = alloc_type(jdns_nameserver_t); 0756 a->address = 0; 0757 a->port = -1; 0758 return a; 0759 } 0760 0761 jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a) 0762 { 0763 jdns_nameserver_t *c = jdns_nameserver_new(); 0764 if(a->address) 0765 c->address = jdns_address_copy(a->address); 0766 c->port = a->port; 0767 return c; 0768 } 0769 0770 void jdns_nameserver_delete(jdns_nameserver_t *a) 0771 { 0772 if(!a) 0773 return; 0774 jdns_address_delete(a->address); 0775 jdns_free(a); 0776 } 0777 0778 void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr, int port) 0779 { 0780 if(a->address) 0781 jdns_address_delete(a->address); 0782 a->address = jdns_address_copy(addr); 0783 a->port = port; 0784 } 0785 0786 /*---------------------------------------------------------------------------- */ 0787 /* jdns_nameserverlist */ 0788 /*---------------------------------------------------------------------------- */ 0789 jdns_nameserverlist_t *jdns_nameserverlist_new() 0790 { 0791 jdns_nameserverlist_t *a = alloc_type(jdns_nameserverlist_t); 0792 a->count = 0; 0793 a->item = 0; 0794 return a; 0795 } 0796 0797 jdns_nameserverlist_t *jdns_nameserverlist_copy(const jdns_nameserverlist_t *a) 0798 { 0799 int n; 0800 jdns_nameserverlist_t *c = jdns_nameserverlist_new(); 0801 if(a->item) 0802 { 0803 c->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *) * a->count); 0804 c->count = a->count; 0805 for(n = 0; n < c->count; ++n) 0806 c->item[n] = jdns_nameserver_copy(a->item[n]); 0807 } 0808 return c; 0809 } 0810 0811 void jdns_nameserverlist_delete(jdns_nameserverlist_t *a) 0812 { 0813 int n; 0814 if(!a) 0815 return; 0816 if(a->item) 0817 { 0818 for(n = 0; n < a->count; ++n) 0819 jdns_nameserver_delete(a->item[n]); 0820 jdns_free(a->item); 0821 } 0822 jdns_free(a); 0823 } 0824 0825 void jdns_nameserverlist_append(jdns_nameserverlist_t *a, const jdns_address_t *addr, int port) 0826 { 0827 if(!a->item) 0828 a->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *)); 0829 else 0830 a->item = (jdns_nameserver_t **)jdns_realloc(a->item, sizeof(jdns_nameserver_t *) * (a->count + 1)); 0831 a->item[a->count] = jdns_nameserver_new(); 0832 jdns_nameserver_set(a->item[a->count], addr, port); 0833 ++a->count; 0834 } 0835 0836 /*---------------------------------------------------------------------------- */ 0837 /* jdns_dnshost */ 0838 /*---------------------------------------------------------------------------- */ 0839 jdns_dnshost_t *jdns_dnshost_new() 0840 { 0841 jdns_dnshost_t *a = alloc_type(jdns_dnshost_t); 0842 a->name = 0; 0843 a->address = 0; 0844 return a; 0845 } 0846 0847 jdns_dnshost_t *jdns_dnshost_copy(const jdns_dnshost_t *a) 0848 { 0849 jdns_dnshost_t *c = jdns_dnshost_new(); 0850 if(a->name) 0851 c->name = jdns_string_copy(a->name); 0852 if(a->address) 0853 c->address = jdns_address_copy(a->address); 0854 return c; 0855 } 0856 0857 void jdns_dnshost_delete(jdns_dnshost_t *a) 0858 { 0859 if(!a) 0860 return; 0861 jdns_string_delete(a->name); 0862 jdns_address_delete(a->address); 0863 jdns_free(a); 0864 } 0865 0866 /*---------------------------------------------------------------------------- */ 0867 /* jdns_dnshostlist */ 0868 /*---------------------------------------------------------------------------- */ 0869 jdns_dnshostlist_t *jdns_dnshostlist_new() 0870 { 0871 jdns_dnshostlist_t *a = alloc_type(jdns_dnshostlist_t); 0872 a->count = 0; 0873 a->item = 0; 0874 return a; 0875 } 0876 0877 jdns_dnshostlist_t *jdns_dnshostlist_copy(const jdns_dnshostlist_t *a) 0878 { 0879 int n; 0880 jdns_dnshostlist_t *c = jdns_dnshostlist_new(); 0881 if(a->item) 0882 { 0883 c->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *) * a->count); 0884 c->count = a->count; 0885 for(n = 0; n < c->count; ++n) 0886 c->item[n] = jdns_dnshost_copy(a->item[n]); 0887 } 0888 return c; 0889 } 0890 0891 void jdns_dnshostlist_delete(jdns_dnshostlist_t *a) 0892 { 0893 int n; 0894 if(!a) 0895 return; 0896 if(a->item) 0897 { 0898 for(n = 0; n < a->count; ++n) 0899 jdns_dnshost_delete(a->item[n]); 0900 jdns_free(a->item); 0901 } 0902 jdns_free(a); 0903 } 0904 0905 void jdns_dnshostlist_append(jdns_dnshostlist_t *a, const jdns_dnshost_t *host) 0906 { 0907 if(!a->item) 0908 a->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *)); 0909 else 0910 a->item = (jdns_dnshost_t **)jdns_realloc(a->item, sizeof(jdns_dnshost_t *) * (a->count + 1)); 0911 a->item[a->count] = jdns_dnshost_copy(host); 0912 ++a->count; 0913 } 0914 0915 /*---------------------------------------------------------------------------- */ 0916 /* jdns_dnsparams */ 0917 /*---------------------------------------------------------------------------- */ 0918 jdns_dnsparams_t *jdns_dnsparams_new() 0919 { 0920 jdns_dnsparams_t *a = alloc_type(jdns_dnsparams_t); 0921 a->nameservers = jdns_nameserverlist_new(); 0922 a->domains = jdns_stringlist_new(); 0923 a->hosts = jdns_dnshostlist_new(); 0924 return a; 0925 } 0926 0927 jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a) 0928 { 0929 jdns_dnsparams_t *c = jdns_dnsparams_new(); 0930 c->nameservers = jdns_nameserverlist_copy(a->nameservers); 0931 c->domains = jdns_stringlist_copy(a->domains); 0932 c->hosts = jdns_dnshostlist_copy(a->hosts); 0933 return c; 0934 } 0935 0936 void jdns_dnsparams_delete(jdns_dnsparams_t *a) 0937 { 0938 if(!a) 0939 return; 0940 jdns_nameserverlist_delete(a->nameservers); 0941 jdns_stringlist_delete(a->domains); 0942 jdns_dnshostlist_delete(a->hosts); 0943 jdns_free(a); 0944 } 0945 0946 void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a, const jdns_address_t *addr, int port) 0947 { 0948 jdns_nameserverlist_append(a->nameservers, addr, port); 0949 } 0950 0951 void jdns_dnsparams_append_domain(jdns_dnsparams_t *a, const jdns_string_t *domain) 0952 { 0953 jdns_stringlist_append(a->domains, domain); 0954 } 0955 0956 void jdns_dnsparams_append_host(jdns_dnsparams_t *a, const jdns_string_t *name, const jdns_address_t *address) 0957 { 0958 jdns_dnshost_t *h = jdns_dnshost_new(); 0959 h->name = jdns_string_copy(name); 0960 h->address = jdns_address_copy(address); 0961 jdns_dnshostlist_append(a->hosts, h); 0962 jdns_dnshost_delete(h); 0963 } 0964 0965 /*---------------------------------------------------------------------------- */ 0966 /* jdns_rr */ 0967 /*---------------------------------------------------------------------------- */ 0968 void _jdns_rr_data_reset(jdns_rr_t *r) 0969 { 0970 if(r->rdata) 0971 { 0972 jdns_free(r->rdata); 0973 r->rdata = 0; 0974 } 0975 r->rdlength = 0; 0976 0977 if(r->haveKnown) 0978 { 0979 switch(r->type) 0980 { 0981 case JDNS_RTYPE_A: 0982 case JDNS_RTYPE_AAAA: 0983 jdns_address_delete(r->data.address); 0984 break; 0985 case JDNS_RTYPE_MX: 0986 case JDNS_RTYPE_SRV: 0987 jdns_server_delete(r->data.server); 0988 break; 0989 case JDNS_RTYPE_CNAME: 0990 case JDNS_RTYPE_PTR: 0991 case JDNS_RTYPE_NS: 0992 jdns_free(r->data.name); 0993 break; 0994 case JDNS_RTYPE_TXT: 0995 jdns_stringlist_delete(r->data.texts); 0996 break; 0997 case JDNS_RTYPE_HINFO: 0998 jdns_string_delete(r->data.hinfo.cpu); 0999 jdns_string_delete(r->data.hinfo.os); 1000 break; 1001 default: 1002 break; 1003 }; 1004 r->haveKnown = 0; 1005 } 1006 r->type = -1; 1007 } 1008 1009 void _jdns_rr_data_copy(const jdns_rr_t *r, jdns_rr_t *c) 1010 { 1011 c->type = r->type; 1012 c->qclass = r->qclass; 1013 c->rdlength = r->rdlength; 1014 c->rdata = jdns_copy_array(r->rdata, r->rdlength); 1015 1016 if(r->haveKnown) 1017 { 1018 switch(r->type) 1019 { 1020 case JDNS_RTYPE_A: 1021 case JDNS_RTYPE_AAAA: 1022 c->data.address = jdns_address_copy(r->data.address); 1023 break; 1024 case JDNS_RTYPE_MX: 1025 case JDNS_RTYPE_SRV: 1026 c->data.server = jdns_server_copy(r->data.server); 1027 break; 1028 case JDNS_RTYPE_CNAME: 1029 case JDNS_RTYPE_PTR: 1030 case JDNS_RTYPE_NS: 1031 c->data.name = _ustrdup(r->data.name); 1032 break; 1033 case JDNS_RTYPE_TXT: 1034 c->data.texts = jdns_stringlist_copy(r->data.texts); 1035 break; 1036 case JDNS_RTYPE_HINFO: 1037 c->data.hinfo.cpu = jdns_string_copy(r->data.hinfo.cpu); 1038 c->data.hinfo.os = jdns_string_copy(r->data.hinfo.os); 1039 break; 1040 default: 1041 break; 1042 }; 1043 c->haveKnown = 1; 1044 } 1045 } 1046 1047 jdns_rr_t *jdns_rr_new() 1048 { 1049 jdns_rr_t *r = alloc_type(jdns_rr_t); 1050 r->owner = 0; 1051 r->ttl = 0; 1052 r->type = -1; 1053 r->qclass = 0; 1054 r->rdata = 0; 1055 r->rdlength = 0; 1056 r->haveKnown = 0; 1057 return r; 1058 } 1059 1060 jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r) 1061 { 1062 jdns_rr_t *c = jdns_rr_new(); 1063 if(r->owner) 1064 c->owner = _ustrdup(r->owner); 1065 c->ttl = r->ttl; 1066 _jdns_rr_data_copy(r, c); 1067 return c; 1068 } 1069 1070 void jdns_rr_delete(jdns_rr_t *r) 1071 { 1072 if(!r) 1073 return; 1074 if(r->owner) 1075 jdns_free(r->owner); 1076 _jdns_rr_data_reset(r); 1077 jdns_free(r); 1078 } 1079 1080 void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name) 1081 { 1082 if(r->owner) 1083 jdns_free(r->owner); 1084 r->owner = _ustrdup(name); 1085 } 1086 1087 void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata, int rdlength) 1088 { 1089 _jdns_rr_data_reset(r); 1090 r->type = type; 1091 r->rdlength = rdlength; 1092 r->rdata = jdns_copy_array(rdata, rdlength); 1093 } 1094 1095 void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address) 1096 { 1097 _jdns_rr_data_reset(r); 1098 r->type = JDNS_RTYPE_A; 1099 r->haveKnown = 1; 1100 r->data.address = jdns_address_copy(address); 1101 } 1102 1103 void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address) 1104 { 1105 _jdns_rr_data_reset(r); 1106 r->type = JDNS_RTYPE_AAAA; 1107 r->haveKnown = 1; 1108 r->data.address = jdns_address_copy(address); 1109 } 1110 1111 void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority) 1112 { 1113 jdns_server_t *s = jdns_server_new(); 1114 jdns_server_set_name(s, name); 1115 s->priority = priority; 1116 1117 _jdns_rr_data_reset(r); 1118 r->type = JDNS_RTYPE_MX; 1119 r->haveKnown = 1; 1120 r->data.server = s; 1121 } 1122 1123 void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port, int priority, int weight) 1124 { 1125 jdns_server_t *s = jdns_server_new(); 1126 jdns_server_set_name(s, name); 1127 s->port = port; 1128 s->priority = priority; 1129 s->weight = weight; 1130 1131 _jdns_rr_data_reset(r); 1132 r->type = JDNS_RTYPE_SRV; 1133 r->haveKnown = 1; 1134 r->data.server = s; 1135 } 1136 1137 void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name) 1138 { 1139 _jdns_rr_data_reset(r); 1140 r->type = JDNS_RTYPE_CNAME; 1141 r->haveKnown = 1; 1142 r->data.name = _ustrdup(name); 1143 } 1144 1145 void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name) 1146 { 1147 _jdns_rr_data_reset(r); 1148 r->type = JDNS_RTYPE_PTR; 1149 r->haveKnown = 1; 1150 r->data.name = _ustrdup(name); 1151 } 1152 1153 void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts) 1154 { 1155 _jdns_rr_data_reset(r); 1156 r->type = JDNS_RTYPE_TXT; 1157 r->haveKnown = 1; 1158 r->data.texts = jdns_stringlist_copy(texts); 1159 } 1160 1161 void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu, const jdns_string_t *os) 1162 { 1163 _jdns_rr_data_reset(r); 1164 r->type = JDNS_RTYPE_HINFO; 1165 r->haveKnown = 1; 1166 r->data.hinfo.cpu = jdns_string_copy(cpu); 1167 r->data.hinfo.os = jdns_string_copy(os); 1168 } 1169 1170 void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name) 1171 { 1172 _jdns_rr_data_reset(r); 1173 r->type = JDNS_RTYPE_NS; 1174 r->haveKnown = 1; 1175 r->data.name = _ustrdup(name); 1176 } 1177 1178 int jdns_rr_verify(const jdns_rr_t *r) 1179 { 1180 if(r->type == -1) 1181 return 0; 1182 1183 if(!jdns_packet_name_isvalid(r->owner, _ustrlen(r->owner))) 1184 return 0; 1185 1186 switch(r->type) 1187 { 1188 case JDNS_RTYPE_MX: 1189 case JDNS_RTYPE_SRV: 1190 { 1191 /* consider it valid if we don't have a known to check */ 1192 if(!r->haveKnown) 1193 return 1; 1194 if(!jdns_packet_name_isvalid(r->data.server->name, _ustrlen(r->data.server->name))) 1195 return 0; 1196 break; 1197 } 1198 case JDNS_RTYPE_CNAME: 1199 case JDNS_RTYPE_PTR: 1200 case JDNS_RTYPE_NS: 1201 { 1202 if(!r->haveKnown) 1203 return 1; 1204 if(!jdns_packet_name_isvalid(r->data.name, _ustrlen(r->data.name))) 1205 return 0; 1206 break; 1207 } 1208 case JDNS_RTYPE_TXT: 1209 { 1210 int n; 1211 if(!r->haveKnown) 1212 return 1; 1213 for(n = 0; n < r->data.texts->count; ++n) 1214 { 1215 if(r->data.texts->item[n]->size > 255) 1216 return 0; 1217 } 1218 break; 1219 } 1220 case JDNS_RTYPE_HINFO: 1221 { 1222 if(!r->haveKnown) 1223 return 1; 1224 if(r->data.hinfo.cpu->size > 255) 1225 return 0; 1226 if(r->data.hinfo.os->size > 255) 1227 return 0; 1228 break; 1229 } 1230 } 1231 1232 return 1; 1233 } 1234 1235 static jdns_string_t *read_name_at_end(const jdns_packet_resource_t *pr, const jdns_packet_t *ref, int _at) 1236 { 1237 jdns_string_t *name; 1238 int at; 1239 at = _at; 1240 if(!jdns_packet_resource_read_name(pr, ref, &at, &name)) 1241 return 0; 1242 if(at != pr->rdlength) 1243 { 1244 jdns_string_delete(name); 1245 return 0; 1246 } 1247 return name; 1248 } 1249 1250 static jdns_string_t *read_text_string(const jdns_packet_resource_t *pr, int *_at) 1251 { 1252 jdns_string_t *out; 1253 int at, len; 1254 at = *_at; 1255 if(at + 1 > pr->rdlength) 1256 return 0; 1257 len = pr->rdata[at++]; 1258 if(at + len > pr->rdlength) 1259 return 0; 1260 out = jdns_string_new(); 1261 jdns_string_set(out, pr->rdata + at, len); 1262 at += len; 1263 *_at = at; 1264 return out; 1265 } 1266 1267 /* if the type is known, then it must be parsed properly */ 1268 /* if the type is unknown, then that's ok */ 1269 /* rdata is always copied, known or not */ 1270 jdns_rr_t *jdns_rr_from_resource(const jdns_packet_resource_t *pr, const jdns_packet_t *ref) 1271 { 1272 jdns_rr_t *rr = 0; 1273 1274 if(pr->qtype == JDNS_RTYPE_ANY) 1275 return 0; 1276 1277 switch(pr->qtype) 1278 { 1279 case JDNS_RTYPE_A: 1280 { 1281 jdns_address_t *addr; 1282 unsigned long int ip; 1283 if(pr->rdlength != 4) 1284 break; 1285 memcpy(&ip, pr->rdata, 4); 1286 ip = ntohl(ip); 1287 addr = jdns_address_new(); 1288 jdns_address_set_ipv4(addr, ip); 1289 rr = jdns_rr_new(); 1290 jdns_rr_set_A(rr, addr); 1291 jdns_address_delete(addr); 1292 break; 1293 } 1294 case JDNS_RTYPE_AAAA: 1295 { 1296 jdns_address_t *addr; 1297 if(pr->rdlength != 16) 1298 break; 1299 addr = jdns_address_new(); 1300 jdns_address_set_ipv6(addr, pr->rdata); 1301 rr = jdns_rr_new(); 1302 jdns_rr_set_AAAA(rr, addr); 1303 jdns_address_delete(addr); 1304 break; 1305 } 1306 case JDNS_RTYPE_MX: 1307 { 1308 unsigned short priority; 1309 jdns_string_t *name; 1310 if(pr->rdlength < 2) 1311 break; 1312 memcpy(&priority, pr->rdata, 2); 1313 priority = ntohs(priority); 1314 name = read_name_at_end(pr, ref, 2); 1315 if(!name) 1316 break; 1317 rr = jdns_rr_new(); 1318 jdns_rr_set_MX(rr, name->data, priority); 1319 jdns_string_delete(name); 1320 break; 1321 } 1322 case JDNS_RTYPE_SRV: 1323 { 1324 unsigned short priority, weight, port; 1325 jdns_string_t *name; 1326 if(pr->rdlength < 6) 1327 break; 1328 memcpy(&priority, pr->rdata, 2); 1329 priority = ntohs(priority); 1330 memcpy(&weight, pr->rdata + 2, 2); 1331 weight = ntohs(weight); 1332 memcpy(&port, pr->rdata + 4, 2); 1333 port = ntohs(port); 1334 name = read_name_at_end(pr, ref, 6); 1335 if(!name) 1336 break; 1337 rr = jdns_rr_new(); 1338 jdns_rr_set_SRV(rr, name->data, port, priority, weight); 1339 jdns_string_delete(name); 1340 break; 1341 } 1342 case JDNS_RTYPE_CNAME: 1343 { 1344 jdns_string_t *name; 1345 name = read_name_at_end(pr, ref, 0); 1346 if(!name) 1347 break; 1348 rr = jdns_rr_new(); 1349 jdns_rr_set_CNAME(rr, name->data); 1350 jdns_string_delete(name); 1351 break; 1352 } 1353 case JDNS_RTYPE_PTR: 1354 { 1355 jdns_string_t *name; 1356 name = read_name_at_end(pr, ref, 0); 1357 if(!name) 1358 break; 1359 rr = jdns_rr_new(); 1360 jdns_rr_set_PTR(rr, name->data); 1361 jdns_string_delete(name); 1362 break; 1363 } 1364 case JDNS_RTYPE_TXT: 1365 { 1366 jdns_stringlist_t *texts; 1367 jdns_string_t *str; 1368 int at, error; 1369 texts = jdns_stringlist_new(); 1370 at = 0; 1371 error = 0; 1372 while(at < pr->rdlength) 1373 { 1374 str = read_text_string(pr, &at); 1375 if(!str) 1376 { 1377 error = 1; 1378 break; 1379 } 1380 jdns_stringlist_append(texts, str); 1381 jdns_string_delete(str); 1382 } 1383 if(error) 1384 { 1385 jdns_stringlist_delete(texts); 1386 break; 1387 } 1388 rr = jdns_rr_new(); 1389 jdns_rr_set_TXT(rr, texts); 1390 jdns_stringlist_delete(texts); 1391 break; 1392 } 1393 case JDNS_RTYPE_HINFO: 1394 { 1395 jdns_string_t *cpu, *os; 1396 int at; 1397 at = 0; 1398 cpu = read_text_string(pr, &at); 1399 if(!cpu) 1400 break; 1401 os = read_text_string(pr, &at); 1402 if(!os) 1403 { 1404 jdns_string_delete(cpu); 1405 break; 1406 } 1407 if(at != pr->rdlength) 1408 { 1409 jdns_string_delete(cpu); 1410 jdns_string_delete(os); 1411 break; 1412 } 1413 rr = jdns_rr_new(); 1414 jdns_rr_set_HINFO(rr, cpu, os); 1415 jdns_string_delete(cpu); 1416 jdns_string_delete(os); 1417 break; 1418 } 1419 case JDNS_RTYPE_NS: 1420 { 1421 jdns_string_t *name; 1422 name = read_name_at_end(pr, ref, 0); 1423 if(!name) 1424 break; 1425 rr = jdns_rr_new(); 1426 jdns_rr_set_NS(rr, name->data); 1427 jdns_string_delete(name); 1428 break; 1429 } 1430 default: 1431 { 1432 rr = jdns_rr_new(); 1433 rr->type = pr->qtype; 1434 break; 1435 } 1436 } 1437 1438 if(rr) 1439 { 1440 rr->qclass = pr->qclass; 1441 rr->owner = _ustrdup(pr->qname->data); 1442 rr->ttl = (int)pr->ttl; /* pr->ttl is 31-bits, cast is safe */ 1443 rr->rdlength = pr->rdlength; 1444 rr->rdata = jdns_copy_array(pr->rdata, pr->rdlength); 1445 } 1446 1447 return rr; 1448 } 1449 1450 /*---------------------------------------------------------------------------- */ 1451 /* jdns_response */ 1452 /*---------------------------------------------------------------------------- */ 1453 #define ARRAY_DELETE(array, count, dtor) \ 1454 { \ 1455 if(count > 0) \ 1456 { \ 1457 int n; \ 1458 for(n = 0; n < count; ++n) \ 1459 dtor(array[n]); \ 1460 } \ 1461 jdns_free(array); \ 1462 array = 0; \ 1463 count = 0; \ 1464 } 1465 1466 #define ARRAY_COPY(type, array_src, count_src, array_dest, count_dest, cctor) \ 1467 { \ 1468 if(count_src > 0) \ 1469 { \ 1470 int n; \ 1471 count_dest = count_src; \ 1472 array_dest = (type **)jdns_alloc(sizeof(type *) * count_dest); \ 1473 for(n = 0; n < count_dest; ++n) \ 1474 array_dest[n] = cctor(array_src[n]); \ 1475 } \ 1476 } 1477 1478 #define ARRAY_APPEND(type, array, count, item) \ 1479 { \ 1480 if(!array) \ 1481 array = (type **)jdns_alloc(sizeof(type *)); \ 1482 else \ 1483 array = (type **)jdns_realloc(array, sizeof(type *) * (count + 1)); \ 1484 array[count] = item; \ 1485 ++count; \ 1486 } 1487 1488 jdns_response_t *jdns_response_new() 1489 { 1490 jdns_response_t *r = alloc_type(jdns_response_t); 1491 r->answerCount = 0; 1492 r->answerRecords = 0; 1493 r->authorityCount = 0; 1494 r->authorityRecords = 0; 1495 r->additionalCount = 0; 1496 r->additionalRecords = 0; 1497 return r; 1498 } 1499 1500 jdns_response_t *jdns_response_copy(const jdns_response_t *r) 1501 { 1502 jdns_response_t *c = jdns_response_new(); 1503 ARRAY_COPY(jdns_rr_t, r->answerRecords, r->answerCount, c->answerRecords, c->answerCount, jdns_rr_copy); 1504 ARRAY_COPY(jdns_rr_t, r->authorityRecords, r->authorityCount, c->authorityRecords, c->authorityCount, jdns_rr_copy); 1505 ARRAY_COPY(jdns_rr_t, r->additionalRecords, r->additionalCount, c->additionalRecords, c->additionalCount, jdns_rr_copy); 1506 return c; 1507 } 1508 1509 void jdns_response_delete(jdns_response_t *r) 1510 { 1511 if(!r) 1512 return; 1513 ARRAY_DELETE(r->answerRecords, r->answerCount, jdns_rr_delete); 1514 ARRAY_DELETE(r->authorityRecords, r->authorityCount, jdns_rr_delete); 1515 ARRAY_DELETE(r->additionalRecords, r->additionalCount, jdns_rr_delete); 1516 jdns_free(r); 1517 } 1518 1519 void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr) 1520 { 1521 ARRAY_APPEND(jdns_rr_t, r->answerRecords, r->answerCount, jdns_rr_copy(rr)); 1522 } 1523 1524 void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr) 1525 { 1526 ARRAY_APPEND(jdns_rr_t, r->authorityRecords, r->authorityCount, jdns_rr_copy(rr)); 1527 } 1528 1529 void jdns_response_append_additional(jdns_response_t *r, const jdns_rr_t *rr) 1530 { 1531 ARRAY_APPEND(jdns_rr_t, r->additionalRecords, r->additionalCount, jdns_rr_copy(rr)); 1532 } 1533 1534 void jdns_response_remove_extra(jdns_response_t *r) 1535 { 1536 ARRAY_DELETE(r->authorityRecords, r->authorityCount, jdns_rr_delete); 1537 ARRAY_DELETE(r->additionalRecords, r->additionalCount, jdns_rr_delete); 1538 } 1539 1540 void jdns_response_remove_answer(jdns_response_t *r, int pos) 1541 { 1542 jdns_rr_t *rr = r->answerRecords[pos]; 1543 jdns_rr_delete(rr); 1544 1545 /* free the position */ 1546 if(r->answerCount > 1) 1547 { 1548 memmove(r->answerRecords + pos, r->answerRecords + pos + 1, (r->answerCount - pos - 1) * sizeof(void *)); 1549 --r->answerCount; 1550 } 1551 else 1552 { 1553 jdns_free(r->answerRecords); 1554 r->answerRecords = 0; 1555 r->answerCount = 0; 1556 } 1557 }