~ubuntu-branches/ubuntu/utopic/psi/utopic

« back to all changes in this revision

Viewing changes to iris/src/jdns/jdns_util.c

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2005-2008  Justin Karneges
 
3
 *
 
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:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included
 
13
 * in all copies or substantial portions of the Software.
 
14
 *
 
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.
 
22
 */
 
23
 
 
24
#include "jdns_p.h"
 
25
 
 
26
#include "jdns_packet.h"
 
27
 
 
28
//----------------------------------------------------------------------------
 
29
// misc
 
30
//----------------------------------------------------------------------------
 
31
void *jdns_alloc(int size)
 
32
{
 
33
        return malloc(size);
 
34
}
 
35
 
 
36
void *jdns_realloc(void *p, int size)
 
37
{
 
38
        return realloc(p, size);
 
39
}
 
40
 
 
41
void jdns_free(void *p)
 
42
{
 
43
        free(p);
 
44
}
 
45
 
 
46
char *jdns_strdup(const char *s)
 
47
{
 
48
        char *p;
 
49
        int len;
 
50
 
 
51
        len = strlen(s) + 1; // the zero
 
52
        p = (char *)jdns_alloc(len);
 
53
        memcpy(p, s, len);
 
54
        return p;
 
55
}
 
56
 
 
57
unsigned char *jdns_copy_array(const unsigned char *src, int size)
 
58
{
 
59
        unsigned char *out;
 
60
        if(size <= 0)
 
61
                return 0;
 
62
        out = (unsigned char *)jdns_alloc(size);
 
63
        memcpy(out, src, size);
 
64
        return out;
 
65
}
 
66
 
 
67
int jdns_domain_cmp(const unsigned char *a, const unsigned char *b)
 
68
{
 
69
        int n;
 
70
        int len_a;
 
71
 
 
72
        // case-insensitive compare
 
73
        len_a = _ustrlen(a);
 
74
        if(len_a != (int)_ustrlen(b))
 
75
                return 0;
 
76
 
 
77
        for(n = 0; n < len_a; ++n)
 
78
        {
 
79
                if(tolower(a[n]) != tolower(b[n]))
 
80
                        return 0;
 
81
        }
 
82
        return 1;
 
83
}
 
84
 
 
85
int jdns_sprintf_s(char *str, int n, const char *format, ...)
 
86
{
 
87
        int ret;
 
88
        va_list ap;
 
89
        va_start(ap, format);
 
90
        ret = jdns_vsprintf_s(str, n, format, ap);
 
91
        va_end(ap);
 
92
        return ret;
 
93
}
 
94
 
 
95
int jdns_vsprintf_s(char *str, int n, const char *format, va_list ap)
 
96
{
 
97
#if defined(_MSC_VER) && _MSC_VER >= 1400
 
98
        return vsprintf_s(str, n, format, ap);
 
99
#else
 
100
        (void)n;
 
101
        return vsprintf(str, format, ap);
 
102
#endif
 
103
}
 
104
 
 
105
FILE *jdns_fopen(const char *path, const char *mode)
 
106
{
 
107
#if defined(_MSC_VER) && _MSC_VER >= 1400
 
108
        FILE *fp;
 
109
        if(fopen_s(&fp, path, mode) != 0)
 
110
                return 0;
 
111
        return fp;
 
112
#else
 
113
        return fopen(path, mode);
 
114
#endif
 
115
}
 
116
 
 
117
jdns_string_t *jdns_getenv(const char *name)
 
118
{
 
119
#if defined(_MSC_VER) && _MSC_VER >= 1400
 
120
        jdns_string_t *out;
 
121
        char *dest;
 
122
        size_t size;
 
123
        int sizei;
 
124
        errno_t ret;
 
125
        ret = getenv_s(&size, 0, 0, name);
 
126
        if(ret != 0 || size == 0)
 
127
                return 0;
 
128
        sizei = (int)size;
 
129
        dest = (char *)jdns_alloc(sizei);
 
130
        ret = getenv_s(&size, dest, size, name);
 
131
        if(ret != 0)
 
132
        {
 
133
                free(dest);
 
134
                return 0;
 
135
        }
 
136
        out = jdns_string_new();
 
137
        out->size = sizei - 1;
 
138
        out->data = dest; // must be zero-terminated, which it is
 
139
        return out;
 
140
#else
 
141
        jdns_string_t *out;
 
142
        char *val;
 
143
        val = getenv(name);
 
144
        if(!val)
 
145
                return 0;
 
146
        out = jdns_string_new();
 
147
        jdns_string_set_cstr(out, val);
 
148
        return out;
 
149
#endif
 
150
}
 
151
 
 
152
char *jdns_strcpy(char *dst, const char *src)
 
153
{
 
154
#if defined(_MSC_VER) && _MSC_VER >= 1400
 
155
        int len;
 
156
        // deliberately unsafe
 
157
        len = strlen(src);
 
158
        if(strcpy_s(dst, len + 1, src) != 0)
 
159
                return 0;
 
160
        return dst;
 
161
#else
 
162
        return strcpy(dst, src);
 
163
#endif
 
164
}
 
165
 
 
166
//----------------------------------------------------------------------------
 
167
// jdns_object
 
168
//----------------------------------------------------------------------------
 
169
void *jdns_object_new(int size, void (*dtor)(void *), void *(*cctor)(const void *))
 
170
{
 
171
        jdns_object_t *a = (jdns_object_t *)jdns_alloc(size);
 
172
        memset(a, 0, size);
 
173
        a->dtor = dtor;
 
174
        a->cctor = cctor;
 
175
        return a;
 
176
}
 
177
 
 
178
void *jdns_object_copy(const void *a)
 
179
{
 
180
        return ((const jdns_object_t *)a)->cctor(a);
 
181
}
 
182
 
 
183
void jdns_object_delete(void *a)
 
184
{
 
185
        ((jdns_object_t *)a)->dtor(a);
 
186
}
 
187
 
 
188
void jdns_object_free(void *a)
 
189
{
 
190
        jdns_free(a);
 
191
}
 
192
 
 
193
//----------------------------------------------------------------------------
 
194
// jdns_list
 
195
//----------------------------------------------------------------------------
 
196
jdns_list_t *jdns_list_new()
 
197
{
 
198
        jdns_list_t *a = JDNS_OBJECT_NEW(jdns_list);
 
199
        a->count = 0;
 
200
        a->item = 0;
 
201
        a->valueList = 0;
 
202
        a->autoDelete = 0;
 
203
        return a;
 
204
}
 
205
 
 
206
jdns_list_t *jdns_list_copy(const jdns_list_t *a)
 
207
{
 
208
        jdns_list_t *c = jdns_list_new();
 
209
 
 
210
        // note: copying a list with autoDelete should not ever be done.
 
211
        //   heck, let's not even allow it.  return an empty list.
 
212
        if(a->autoDelete)
 
213
                return c;
 
214
 
 
215
        c->valueList = a->valueList;
 
216
 
 
217
        // copy the items
 
218
        if(a->item)
 
219
        {
 
220
                int n;
 
221
                c->count = a->count;
 
222
                c->item = (void **)jdns_alloc(sizeof(void *) * c->count);
 
223
                if(a->valueList)
 
224
                {
 
225
                        // deep copy
 
226
                        for(n = 0; n < c->count; ++n)
 
227
                                c->item[n] = jdns_object_copy(a->item[n]);
 
228
                }
 
229
                else
 
230
                {
 
231
                        // just the pointer
 
232
                        for(n = 0; n < c->count; ++n)
 
233
                                c->item[n] = a->item[n];
 
234
                }
 
235
        }
 
236
        return c;
 
237
}
 
238
 
 
239
void jdns_list_delete(jdns_list_t *a)
 
240
{
 
241
        if(!a)
 
242
                return;
 
243
        jdns_list_clear(a);
 
244
        jdns_object_free(a);
 
245
}
 
246
 
 
247
void jdns_list_clear(jdns_list_t *a)
 
248
{
 
249
        if(a->item)
 
250
        {
 
251
                // delete the items if necessary
 
252
                if(a->valueList || a->autoDelete)
 
253
                {
 
254
                        int n;
 
255
                        for(n = 0; n < a->count; ++n)
 
256
                                jdns_object_delete(a->item[n]);
 
257
                }
 
258
                jdns_free(a->item);
 
259
                a->item = 0;
 
260
                a->count = 0;
 
261
        }
 
262
}
 
263
 
 
264
void jdns_list_insert(jdns_list_t *a, void *item, int pos)
 
265
{
 
266
        // make memory
 
267
        if(!a->item)
 
268
                a->item = (void **)jdns_alloc(sizeof(void *));
 
269
        else
 
270
                a->item = (void **)jdns_realloc(a->item, sizeof(void *) * (a->count + 1));
 
271
 
 
272
        // prepare position
 
273
        if(pos != -1)
 
274
                memmove(a->item + pos + 1, a->item + pos, (a->count - pos) * sizeof(void *));
 
275
        else
 
276
                pos = a->count;
 
277
 
 
278
        // insert it
 
279
        if(a->valueList)
 
280
                a->item[pos] = jdns_object_copy(item);
 
281
        else
 
282
                a->item[pos] = item;
 
283
        ++a->count;
 
284
}
 
285
 
 
286
void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos)
 
287
{
 
288
        jdns_list_insert(a, (void *)item, pos);
 
289
}
 
290
 
 
291
void jdns_list_remove(jdns_list_t *a, void *item)
 
292
{
 
293
        int n;
 
294
        int pos = -1;
 
295
        for(n = 0; n < a->count; ++n)
 
296
        {
 
297
                if(a->item[n] == item)
 
298
                {
 
299
                        pos = n;
 
300
                        break;
 
301
                }
 
302
        }
 
303
        if(pos == -1)
 
304
                return;
 
305
 
 
306
        jdns_list_remove_at(a, pos);
 
307
}
 
308
 
 
309
void jdns_list_remove_at(jdns_list_t *a, int pos)
 
310
{
 
311
        if(pos < 0 || pos >= a->count)
 
312
                return;
 
313
 
 
314
        // delete the item if necessary
 
315
        if(a->valueList || a->autoDelete)
 
316
                jdns_object_delete(a->item[pos]);
 
317
 
 
318
        // free the position
 
319
        if(a->count > 1)
 
320
        {
 
321
                memmove(a->item + pos, a->item + pos + 1, (a->count - pos - 1) * sizeof(void *));
 
322
                --a->count;
 
323
        }
 
324
        else
 
325
        {
 
326
                jdns_free(a->item);
 
327
                a->item = 0;
 
328
                a->count = 0;
 
329
        }
 
330
}
 
331
 
 
332
//----------------------------------------------------------------------------
 
333
// jdns_string
 
334
//----------------------------------------------------------------------------
 
335
jdns_string_t *jdns_string_new()
 
336
{
 
337
        jdns_string_t *s = JDNS_OBJECT_NEW(jdns_string);
 
338
        s->data = 0;
 
339
        s->size = 0;
 
340
        return s;
 
341
}
 
342
 
 
343
jdns_string_t *jdns_string_copy(const jdns_string_t *s)
 
344
{
 
345
        jdns_string_t *c = jdns_string_new();
 
346
        if(s->data)
 
347
                jdns_string_set(c, s->data, s->size);
 
348
        return c;
 
349
}
 
350
 
 
351
void jdns_string_delete(jdns_string_t *s)
 
352
{
 
353
        if(!s)
 
354
                return;
 
355
        if(s->data)
 
356
                jdns_free(s->data);
 
357
        jdns_object_free(s);
 
358
}
 
359
 
 
360
void jdns_string_set(jdns_string_t *s, const unsigned char *str, int str_len)
 
361
{
 
362
        if(s->data)
 
363
                jdns_free(s->data);
 
364
        s->data = (unsigned char *)jdns_alloc(str_len + 1);
 
365
        memcpy(s->data, str, str_len);
 
366
        s->data[str_len] = 0;
 
367
        s->size = str_len;
 
368
}
 
369
 
 
370
void jdns_string_set_cstr(jdns_string_t *s, const char *str)
 
371
{
 
372
        jdns_string_set(s, (const unsigned char *)str, strlen(str));
 
373
}
 
374
 
 
375
int jdns_string_indexOf(const jdns_string_t *s, unsigned char c, int pos)
 
376
{
 
377
        int n;
 
378
        for(n = pos; n < s->size; ++n)
 
379
        {
 
380
                if(s->data[n] == c)
 
381
                        return n;
 
382
        }
 
383
        return -1;
 
384
}
 
385
 
 
386
jdns_stringlist_t *jdns_string_split(const jdns_string_t *s, unsigned char sep)
 
387
{
 
388
        int at, n, len;
 
389
        jdns_string_t *str;
 
390
        jdns_stringlist_t *out;
 
391
 
 
392
        at = 0;
 
393
        out = jdns_stringlist_new();
 
394
        while(at < s->size)
 
395
        {
 
396
                n = jdns_string_indexOf(s, sep, at);
 
397
                if(n == -1)
 
398
                        n = s->size;
 
399
                len = n - at;
 
400
                // FIXME: should we allow empty items?
 
401
                //if(len == 0)
 
402
                //      break;
 
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
 
408
        }
 
409
        return out;
 
410
}
 
411
 
 
412
//----------------------------------------------------------------------------
 
413
// jdns_stringlist
 
414
//----------------------------------------------------------------------------
 
415
jdns_stringlist_t *jdns_stringlist_new()
 
416
{
 
417
        jdns_list_t *a = jdns_list_new();
 
418
        a->valueList = 1;
 
419
        return (jdns_stringlist_t *)a;
 
420
}
 
421
 
 
422
jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a)
 
423
{
 
424
        return (jdns_stringlist_t *)jdns_list_copy((const jdns_list_t *)a);
 
425
}
 
426
 
 
427
void jdns_stringlist_delete(jdns_stringlist_t *a)
 
428
{
 
429
        jdns_list_delete((jdns_list_t *)a);
 
430
        // note: no need to call jdns_object_free() here
 
431
}
 
432
 
 
433
void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str)
 
434
{
 
435
        jdns_list_insert_value((jdns_list_t *)a, str, -1);
 
436
}
 
437
 
 
438
//----------------------------------------------------------------------------
 
439
// jdns_address
 
440
//----------------------------------------------------------------------------
 
441
jdns_address_t *jdns_address_new()
 
442
{
 
443
        jdns_address_t *a = alloc_type(jdns_address_t);
 
444
        a->isIpv6 = 0;
 
445
        a->addr.v4 = 0;
 
446
        a->c_str = jdns_strdup("");
 
447
        return a;
 
448
}
 
449
 
 
450
jdns_address_t *jdns_address_copy(const jdns_address_t *a)
 
451
{
 
452
        jdns_address_t *c = jdns_address_new();
 
453
        if(a->isIpv6)
 
454
                jdns_address_set_ipv6(c, a->addr.v6);
 
455
        else
 
456
                jdns_address_set_ipv4(c, a->addr.v4);
 
457
        return c;
 
458
}
 
459
 
 
460
void jdns_address_delete(jdns_address_t *a)
 
461
{
 
462
        if(!a)
 
463
                return;
 
464
        if(a->isIpv6)
 
465
                jdns_free(a->addr.v6);
 
466
        jdns_free(a->c_str);
 
467
        jdns_free(a);
 
468
}
 
469
 
 
470
void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4)
 
471
{
 
472
        if(a->isIpv6)
 
473
                jdns_free(a->addr.v6);
 
474
        jdns_free(a->c_str);
 
475
        a->isIpv6 = 0;
 
476
        a->addr.v4 = ipv4;
 
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));
 
483
}
 
484
 
 
485
void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6)
 
486
{
 
487
        int n;
 
488
        unsigned char *p;
 
489
        unsigned short word[8];
 
490
        if(a->isIpv6)
 
491
                jdns_free(a->addr.v6);
 
492
        jdns_free(a->c_str);
 
493
        a->isIpv6 = 1;
 
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]);
 
502
}
 
503
 
 
504
int jdns_address_set_cstr(jdns_address_t *a, const char *str)
 
505
{
 
506
        int slen = strlen(str);
 
507
 
 
508
        // ipv6
 
509
        if(strchr(str, ':'))
 
510
        {
 
511
                jdns_string_t *in;
 
512
                jdns_stringlist_t *list;
 
513
                unsigned char ipv6[16];
 
514
                int n, at, count, fill;
 
515
 
 
516
                in = jdns_string_new();
 
517
                jdns_string_set_cstr(in, str);
 
518
                list = jdns_string_split(in, ':');
 
519
                jdns_string_delete(in);
 
520
 
 
521
                // a confusing outputting-backwards parser adapted from qt
 
522
 
 
523
                count = list->count;
 
524
 
 
525
                if(count < 3 || count > 8)
 
526
                        goto error;
 
527
 
 
528
                at = 16;
 
529
                fill = 9 - count;
 
530
                for(n = count - 1; n >= 0; --n)
 
531
                {
 
532
                        if(at <= 0)
 
533
                                goto error;
 
534
 
 
535
                        if(list->item[n]->size == 0)
 
536
                        {
 
537
                                if(n == count - 1)
 
538
                                {
 
539
                                        if(list->item[n - 1]->size != 0)
 
540
                                                goto error;
 
541
                                        ipv6[--at] = 0;
 
542
                                        ipv6[--at] = 0;
 
543
                                }
 
544
                                else if(n == 0)
 
545
                                {
 
546
                                        if(list->item[n + 1]->size != 0)
 
547
                                                goto error;
 
548
                                        ipv6[--at] = 0;
 
549
                                        ipv6[--at] = 0;
 
550
                                }
 
551
                                else
 
552
                                {
 
553
                                        int i;
 
554
                                        for(i = 0; i < fill; ++i)
 
555
                                        {
 
556
                                                if(at <= 0)
 
557
                                                        goto error;
 
558
                                                ipv6[--at] = 0;
 
559
                                                ipv6[--at] = 0;
 
560
                                        }
 
561
                                }
 
562
                        }
 
563
                        else
 
564
                        {
 
565
                                if(jdns_string_indexOf(list->item[n], '.', 0) == -1)
 
566
                                {
 
567
                                        int x;
 
568
                                        x = strtol((const char *)list->item[n]->data, NULL, 16);
 
569
                                        if(x < 0 || x > 0xffff)
 
570
                                                goto error;
 
571
                                        ipv6[--at] = x & 0xff;
 
572
                                        ipv6[--at] = (x >> 8) & 0xff;
 
573
                                }
 
574
                                else
 
575
                                {
 
576
                                        jdns_address_t *v4;
 
577
 
 
578
                                        if(n != count - 1)
 
579
                                                goto error;
 
580
 
 
581
                                        v4 = jdns_address_new();
 
582
                                        if(!jdns_address_set_cstr(v4, (char *)list->item[n]->data))
 
583
                                        {
 
584
                                                jdns_address_delete(v4);
 
585
                                                goto error;
 
586
                                        }
 
587
 
 
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);
 
593
                                        --fill;
 
594
                                }
 
595
                        }
 
596
                }
 
597
                jdns_stringlist_delete(list);
 
598
 
 
599
                jdns_address_set_ipv6(a, ipv6);
 
600
                return 1;
 
601
 
 
602
error:
 
603
                jdns_stringlist_delete(list);
 
604
                return 0;
 
605
        }
 
606
        else if(strchr(str, '.'))
 
607
        {
 
608
                unsigned char b[4];
 
609
                int x;
 
610
                unsigned long int ipv4;
 
611
                int at;
 
612
                char *part;
 
613
                int len;
 
614
                const char *p, *p2;
 
615
 
 
616
                p = str;
 
617
                at = 0;
 
618
                while(1)
 
619
                {
 
620
                        p2 = strchr(p, '.');
 
621
                        if(!p2)
 
622
                                p2 = str + slen;
 
623
                        len = p2 - p;
 
624
 
 
625
                        // convert the section into a byte
 
626
                        part = (char *)jdns_alloc(len + 1);
 
627
                        memcpy(part, p, len);
 
628
                        part[len] = 0;
 
629
                        x = strtol(part, NULL, 10);
 
630
                        jdns_free(part);
 
631
                        if(x < 0 || x > 0xff)
 
632
                                break;
 
633
                        b[at++] = (unsigned char)x;
 
634
 
 
635
                        // done?
 
636
                        if(p2 >= str + slen)
 
637
                                break;
 
638
 
 
639
                        // skip over the separator
 
640
                        p = p2 + 1;
 
641
                }
 
642
                if(at != 4)
 
643
                        return 0;
 
644
 
 
645
                ipv4 = 0;
 
646
                ipv4 += b[0];
 
647
                ipv4 <<= 8;
 
648
                ipv4 += b[1];
 
649
                ipv4 <<= 8;
 
650
                ipv4 += b[2];
 
651
                ipv4 <<= 8;
 
652
                ipv4 += b[3];
 
653
 
 
654
                jdns_address_set_ipv4(a, ipv4);
 
655
                return 1;
 
656
        }
 
657
        else
 
658
                return 0;
 
659
}
 
660
 
 
661
int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b)
 
662
{
 
663
        // same protocol?
 
664
        if(a->isIpv6 != b->isIpv6)
 
665
                return 0;
 
666
        if(a->isIpv6)
 
667
        {
 
668
                int n;
 
669
                for(n = 0; n < 16; ++n)
 
670
                {
 
671
                        if(a->addr.v6[n] != b->addr.v6[n])
 
672
                                break;
 
673
                }
 
674
                if(n == 16)
 
675
                        return 1;
 
676
        }
 
677
        else
 
678
        {
 
679
                if(a->addr.v4 == b->addr.v4)
 
680
                        return 1;
 
681
        }
 
682
        return 0;
 
683
}
 
684
 
 
685
// FF02::FB
 
686
unsigned char jdns_multicast_addr6_value_v6[] =
 
687
{
 
688
        0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 
689
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb
 
690
};
 
691
 
 
692
jdns_address_t *jdns_address_multicast4_new()
 
693
{
 
694
        jdns_address_t *a = jdns_address_new();
 
695
        jdns_address_set_ipv4(a, 0xe00000fb);
 
696
        return a;
 
697
}
 
698
 
 
699
jdns_address_t *jdns_address_multicast6_new()
 
700
{
 
701
        jdns_address_t *a = jdns_address_new();
 
702
        jdns_address_set_ipv6(a, jdns_multicast_addr6_value_v6);
 
703
        return a;
 
704
}
 
705
 
 
706
//----------------------------------------------------------------------------
 
707
// jdns_server
 
708
//----------------------------------------------------------------------------
 
709
jdns_server_t *jdns_server_new()
 
710
{
 
711
        jdns_server_t *s = alloc_type(jdns_server_t);
 
712
        s->name = 0;
 
713
        s->port = 0;
 
714
        s->priority = 0;
 
715
        s->weight = 0;
 
716
        return s;
 
717
}
 
718
 
 
719
jdns_server_t *jdns_server_copy(const jdns_server_t *s)
 
720
{
 
721
        jdns_server_t *c = jdns_server_new();
 
722
        if(s->name)
 
723
                c->name = _ustrdup(s->name);
 
724
        c->port = s->port;
 
725
        c->priority = s->priority;
 
726
        c->weight = s->weight;
 
727
        return c;
 
728
}
 
729
 
 
730
void jdns_server_delete(jdns_server_t *s)
 
731
{
 
732
        if(!s)
 
733
                return;
 
734
        if(s->name)
 
735
                jdns_free(s->name);
 
736
        jdns_object_free(s);
 
737
}
 
738
 
 
739
void jdns_server_set_name(jdns_server_t *s, const unsigned char *name)
 
740
{
 
741
        if(s->name)
 
742
                jdns_free(s->name);
 
743
        s->name = _ustrdup(name);
 
744
}
 
745
 
 
746
//----------------------------------------------------------------------------
 
747
// jdns_nameserver
 
748
//----------------------------------------------------------------------------
 
749
jdns_nameserver_t *jdns_nameserver_new()
 
750
{
 
751
        jdns_nameserver_t *a = alloc_type(jdns_nameserver_t);
 
752
        a->address = 0;
 
753
        a->port = -1;
 
754
        return a;
 
755
}
 
756
 
 
757
jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a)
 
758
{
 
759
        jdns_nameserver_t *c = jdns_nameserver_new();
 
760
        if(a->address)
 
761
                c->address = jdns_address_copy(a->address);
 
762
        c->port = a->port;
 
763
        return c;
 
764
}
 
765
 
 
766
void jdns_nameserver_delete(jdns_nameserver_t *a)
 
767
{
 
768
        if(!a)
 
769
                return;
 
770
        jdns_address_delete(a->address);
 
771
        jdns_free(a);
 
772
}
 
773
 
 
774
void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr, int port)
 
775
{
 
776
        if(a->address)
 
777
                jdns_address_delete(a->address);
 
778
        a->address = jdns_address_copy(addr);
 
779
        a->port = port;
 
780
}
 
781
 
 
782
//----------------------------------------------------------------------------
 
783
// jdns_nameserverlist
 
784
//----------------------------------------------------------------------------
 
785
jdns_nameserverlist_t *jdns_nameserverlist_new()
 
786
{
 
787
        jdns_nameserverlist_t *a = alloc_type(jdns_nameserverlist_t);
 
788
        a->count = 0;
 
789
        a->item = 0;
 
790
        return a;
 
791
}
 
792
 
 
793
jdns_nameserverlist_t *jdns_nameserverlist_copy(const jdns_nameserverlist_t *a)
 
794
{
 
795
        int n;
 
796
        jdns_nameserverlist_t *c = jdns_nameserverlist_new();
 
797
        if(a->item)
 
798
        {
 
799
                c->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *) * a->count);
 
800
                c->count = a->count;
 
801
                for(n = 0; n < c->count; ++n)
 
802
                        c->item[n] = jdns_nameserver_copy(a->item[n]);
 
803
        }
 
804
        return c;
 
805
}
 
806
 
 
807
void jdns_nameserverlist_delete(jdns_nameserverlist_t *a)
 
808
{
 
809
        int n;
 
810
        if(!a)
 
811
                return;
 
812
        if(a->item)
 
813
        {
 
814
                for(n = 0; n < a->count; ++n)
 
815
                        jdns_nameserver_delete(a->item[n]);
 
816
                jdns_free(a->item);
 
817
        }
 
818
        jdns_free(a);
 
819
}
 
820
 
 
821
void jdns_nameserverlist_append(jdns_nameserverlist_t *a, const jdns_address_t *addr, int port)
 
822
{
 
823
        if(!a->item)
 
824
                a->item = (jdns_nameserver_t **)jdns_alloc(sizeof(jdns_nameserver_t *));
 
825
        else
 
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);
 
829
        ++a->count;
 
830
}
 
831
 
 
832
//----------------------------------------------------------------------------
 
833
// jdns_dnshost
 
834
//----------------------------------------------------------------------------
 
835
jdns_dnshost_t *jdns_dnshost_new()
 
836
{
 
837
        jdns_dnshost_t *a = alloc_type(jdns_dnshost_t);
 
838
        a->name = 0;
 
839
        a->address = 0;
 
840
        return a;
 
841
}
 
842
 
 
843
jdns_dnshost_t *jdns_dnshost_copy(const jdns_dnshost_t *a)
 
844
{
 
845
        jdns_dnshost_t *c = jdns_dnshost_new();
 
846
        if(a->name)
 
847
                c->name = jdns_string_copy(a->name);
 
848
        if(a->address)
 
849
                c->address = jdns_address_copy(a->address);
 
850
        return c;
 
851
}
 
852
 
 
853
void jdns_dnshost_delete(jdns_dnshost_t *a)
 
854
{
 
855
        if(!a)
 
856
                return;
 
857
        jdns_string_delete(a->name);
 
858
        jdns_address_delete(a->address);
 
859
        jdns_free(a);
 
860
}
 
861
 
 
862
//----------------------------------------------------------------------------
 
863
// jdns_dnshostlist
 
864
//----------------------------------------------------------------------------
 
865
jdns_dnshostlist_t *jdns_dnshostlist_new()
 
866
{
 
867
        jdns_dnshostlist_t *a = alloc_type(jdns_dnshostlist_t);
 
868
        a->count = 0;
 
869
        a->item = 0;
 
870
        return a;
 
871
}
 
872
 
 
873
jdns_dnshostlist_t *jdns_dnshostlist_copy(const jdns_dnshostlist_t *a)
 
874
{
 
875
        int n;
 
876
        jdns_dnshostlist_t *c = jdns_dnshostlist_new();
 
877
        if(a->item)
 
878
        {
 
879
                c->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *) * a->count);
 
880
                c->count = a->count;
 
881
                for(n = 0; n < c->count; ++n)
 
882
                        c->item[n] = jdns_dnshost_copy(a->item[n]);
 
883
        }
 
884
        return c;
 
885
}
 
886
 
 
887
void jdns_dnshostlist_delete(jdns_dnshostlist_t *a)
 
888
{
 
889
        int n;
 
890
        if(!a)
 
891
                return;
 
892
        if(a->item)
 
893
        {
 
894
                for(n = 0; n < a->count; ++n)
 
895
                        jdns_dnshost_delete(a->item[n]);
 
896
                jdns_free(a->item);
 
897
        }
 
898
        jdns_free(a);
 
899
}
 
900
 
 
901
void jdns_dnshostlist_append(jdns_dnshostlist_t *a, const jdns_dnshost_t *host)
 
902
{
 
903
        if(!a->item)
 
904
                a->item = (jdns_dnshost_t **)jdns_alloc(sizeof(jdns_dnshost_t *));
 
905
        else
 
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);
 
908
        ++a->count;
 
909
}
 
910
 
 
911
//----------------------------------------------------------------------------
 
912
// jdns_dnsparams
 
913
//----------------------------------------------------------------------------
 
914
jdns_dnsparams_t *jdns_dnsparams_new()
 
915
{
 
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();
 
920
        return a;
 
921
}
 
922
 
 
923
jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a)
 
924
{
 
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);
 
929
        return c;
 
930
}
 
931
 
 
932
void jdns_dnsparams_delete(jdns_dnsparams_t *a)
 
933
{
 
934
        if(!a)
 
935
                return;
 
936
        jdns_nameserverlist_delete(a->nameservers);
 
937
        jdns_stringlist_delete(a->domains);
 
938
        jdns_dnshostlist_delete(a->hosts);
 
939
        jdns_free(a);
 
940
}
 
941
 
 
942
void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a, const jdns_address_t *addr, int port)
 
943
{
 
944
        jdns_nameserverlist_append(a->nameservers, addr, port);
 
945
}
 
946
 
 
947
void jdns_dnsparams_append_domain(jdns_dnsparams_t *a, const jdns_string_t *domain)
 
948
{
 
949
        jdns_stringlist_append(a->domains, domain);
 
950
}
 
951
 
 
952
void jdns_dnsparams_append_host(jdns_dnsparams_t *a, const jdns_string_t *name, const jdns_address_t *address)
 
953
{
 
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);
 
959
}
 
960
 
 
961
//----------------------------------------------------------------------------
 
962
// jdns_rr
 
963
//----------------------------------------------------------------------------
 
964
void _jdns_rr_data_reset(jdns_rr_t *r)
 
965
{
 
966
        if(r->rdata)
 
967
        {
 
968
                jdns_free(r->rdata);
 
969
                r->rdata = 0;
 
970
        }
 
971
        r->rdlength = 0;
 
972
 
 
973
        if(r->haveKnown)
 
974
        {
 
975
                switch(r->type)
 
976
                {
 
977
                        case JDNS_RTYPE_A:
 
978
                        case JDNS_RTYPE_AAAA:
 
979
                                jdns_address_delete(r->data.address);
 
980
                                break;
 
981
                        case JDNS_RTYPE_MX:
 
982
                        case JDNS_RTYPE_SRV:
 
983
                                jdns_server_delete(r->data.server);
 
984
                                break;
 
985
                        case JDNS_RTYPE_CNAME:
 
986
                        case JDNS_RTYPE_PTR:
 
987
                        case JDNS_RTYPE_NS:
 
988
                                jdns_free(r->data.name);
 
989
                                break;
 
990
                        case JDNS_RTYPE_TXT:
 
991
                                jdns_stringlist_delete(r->data.texts);
 
992
                                break;
 
993
                        case JDNS_RTYPE_HINFO:
 
994
                                jdns_string_delete(r->data.hinfo.cpu);
 
995
                                jdns_string_delete(r->data.hinfo.os);
 
996
                                break;
 
997
                        default:
 
998
                                break;
 
999
                };
 
1000
                r->haveKnown = 0;
 
1001
        }
 
1002
        r->type = -1;
 
1003
}
 
1004
 
 
1005
void _jdns_rr_data_copy(const jdns_rr_t *r, jdns_rr_t *c)
 
1006
{
 
1007
        c->type = r->type;
 
1008
        c->qclass = r->qclass;
 
1009
        c->rdlength = r->rdlength;
 
1010
        c->rdata = jdns_copy_array(r->rdata, r->rdlength);
 
1011
 
 
1012
        if(r->haveKnown)
 
1013
        {
 
1014
                switch(r->type)
 
1015
                {
 
1016
                        case JDNS_RTYPE_A:
 
1017
                        case JDNS_RTYPE_AAAA:
 
1018
                                c->data.address = jdns_address_copy(r->data.address);
 
1019
                                break;
 
1020
                        case JDNS_RTYPE_MX:
 
1021
                        case JDNS_RTYPE_SRV:
 
1022
                                c->data.server = jdns_server_copy(r->data.server);
 
1023
                                break;
 
1024
                        case JDNS_RTYPE_CNAME:
 
1025
                        case JDNS_RTYPE_PTR:
 
1026
                        case JDNS_RTYPE_NS:
 
1027
                                c->data.name = _ustrdup(r->data.name);
 
1028
                                break;
 
1029
                        case JDNS_RTYPE_TXT:
 
1030
                                c->data.texts = jdns_stringlist_copy(r->data.texts);
 
1031
                                break;
 
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);
 
1035
                                break;
 
1036
                        default:
 
1037
                                break;
 
1038
                };
 
1039
                c->haveKnown = 1;
 
1040
        }
 
1041
}
 
1042
 
 
1043
jdns_rr_t *jdns_rr_new()
 
1044
{
 
1045
        jdns_rr_t *r = alloc_type(jdns_rr_t);
 
1046
        r->owner = 0;
 
1047
        r->ttl = 0;
 
1048
        r->type = -1;
 
1049
        r->qclass = 0;
 
1050
        r->rdata = 0;
 
1051
        r->rdlength = 0;
 
1052
        r->haveKnown = 0;
 
1053
        return r;
 
1054
}
 
1055
 
 
1056
jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r)
 
1057
{
 
1058
        jdns_rr_t *c = jdns_rr_new();
 
1059
        if(r->owner)
 
1060
                c->owner = _ustrdup(r->owner);
 
1061
        c->ttl = r->ttl;
 
1062
        _jdns_rr_data_copy(r, c);
 
1063
        return c;
 
1064
}
 
1065
 
 
1066
void jdns_rr_delete(jdns_rr_t *r)
 
1067
{
 
1068
        if(!r)
 
1069
                return;
 
1070
        if(r->owner)
 
1071
                jdns_free(r->owner);
 
1072
        _jdns_rr_data_reset(r);
 
1073
        jdns_free(r);
 
1074
}
 
1075
 
 
1076
void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name)
 
1077
{
 
1078
        if(r->owner)
 
1079
                jdns_free(r->owner);
 
1080
        r->owner = _ustrdup(name);
 
1081
}
 
1082
 
 
1083
void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata, int rdlength)
 
1084
{
 
1085
        _jdns_rr_data_reset(r);
 
1086
        r->type = type;
 
1087
        r->rdlength = rdlength;
 
1088
        r->rdata = jdns_copy_array(rdata, rdlength);
 
1089
}
 
1090
 
 
1091
void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address)
 
1092
{
 
1093
        _jdns_rr_data_reset(r);
 
1094
        r->type = JDNS_RTYPE_A;
 
1095
        r->haveKnown = 1;
 
1096
        r->data.address = jdns_address_copy(address);
 
1097
}
 
1098
 
 
1099
void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address)
 
1100
{
 
1101
        _jdns_rr_data_reset(r);
 
1102
        r->type = JDNS_RTYPE_AAAA;
 
1103
        r->haveKnown = 1;
 
1104
        r->data.address = jdns_address_copy(address);
 
1105
}
 
1106
 
 
1107
void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority)
 
1108
{
 
1109
        jdns_server_t *s = jdns_server_new();
 
1110
        jdns_server_set_name(s, name);
 
1111
        s->priority = priority;
 
1112
 
 
1113
        _jdns_rr_data_reset(r);
 
1114
        r->type = JDNS_RTYPE_MX;
 
1115
        r->haveKnown = 1;
 
1116
        r->data.server = s;
 
1117
}
 
1118
 
 
1119
void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port, int priority, int weight)
 
1120
{
 
1121
        jdns_server_t *s = jdns_server_new();
 
1122
        jdns_server_set_name(s, name);
 
1123
        s->port = port;
 
1124
        s->priority = priority;
 
1125
        s->weight = weight;
 
1126
 
 
1127
        _jdns_rr_data_reset(r);
 
1128
        r->type = JDNS_RTYPE_SRV;
 
1129
        r->haveKnown = 1;
 
1130
        r->data.server = s;
 
1131
}
 
1132
 
 
1133
void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name)
 
1134
{
 
1135
        _jdns_rr_data_reset(r);
 
1136
        r->type = JDNS_RTYPE_CNAME;
 
1137
        r->haveKnown = 1;
 
1138
        r->data.name = _ustrdup(name);
 
1139
}
 
1140
 
 
1141
void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name)
 
1142
{
 
1143
        _jdns_rr_data_reset(r);
 
1144
        r->type = JDNS_RTYPE_PTR;
 
1145
        r->haveKnown = 1;
 
1146
        r->data.name = _ustrdup(name);
 
1147
}
 
1148
 
 
1149
void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts)
 
1150
{
 
1151
        _jdns_rr_data_reset(r);
 
1152
        r->type = JDNS_RTYPE_TXT;
 
1153
        r->haveKnown = 1;
 
1154
        r->data.texts = jdns_stringlist_copy(texts);
 
1155
}
 
1156
 
 
1157
void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu, const jdns_string_t *os)
 
1158
{
 
1159
        _jdns_rr_data_reset(r);
 
1160
        r->type = JDNS_RTYPE_HINFO;
 
1161
        r->haveKnown = 1;
 
1162
        r->data.hinfo.cpu = jdns_string_copy(cpu);
 
1163
        r->data.hinfo.os = jdns_string_copy(os);
 
1164
}
 
1165
 
 
1166
void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name)
 
1167
{
 
1168
        _jdns_rr_data_reset(r);
 
1169
        r->type = JDNS_RTYPE_NS;
 
1170
        r->haveKnown = 1;
 
1171
        r->data.name = _ustrdup(name);
 
1172
}
 
1173
 
 
1174
int jdns_rr_verify(const jdns_rr_t *r)
 
1175
{
 
1176
        if(r->type == -1)
 
1177
                return 0;
 
1178
 
 
1179
        if(!jdns_packet_name_isvalid(r->owner, _ustrlen(r->owner)))
 
1180
                return 0;
 
1181
 
 
1182
        switch(r->type)
 
1183
        {
 
1184
                case JDNS_RTYPE_MX:
 
1185
                case JDNS_RTYPE_SRV:
 
1186
                {
 
1187
                        // consider it valid if we don't have a known to check
 
1188
                        if(!r->haveKnown)
 
1189
                                return 1;
 
1190
                        if(!jdns_packet_name_isvalid(r->data.server->name, _ustrlen(r->data.server->name)))
 
1191
                                return 0;
 
1192
                        break;
 
1193
                }
 
1194
                case JDNS_RTYPE_CNAME:
 
1195
                case JDNS_RTYPE_PTR:
 
1196
                case JDNS_RTYPE_NS:
 
1197
                {
 
1198
                        if(!r->haveKnown)
 
1199
                                return 1;
 
1200
                        if(!jdns_packet_name_isvalid(r->data.name, _ustrlen(r->data.name)))
 
1201
                                return 0;
 
1202
                        break;
 
1203
                }
 
1204
                case JDNS_RTYPE_TXT:
 
1205
                {
 
1206
                        int n;
 
1207
                        if(!r->haveKnown)
 
1208
                                return 1;
 
1209
                        for(n = 0; n < r->data.texts->count; ++n)
 
1210
                        {
 
1211
                                if(r->data.texts->item[n]->size > 255)
 
1212
                                        return 0;
 
1213
                        }
 
1214
                        break;
 
1215
                }
 
1216
                case JDNS_RTYPE_HINFO:
 
1217
                {
 
1218
                        if(!r->haveKnown)
 
1219
                                return 1;
 
1220
                        if(r->data.hinfo.cpu->size > 255)
 
1221
                                return 0;
 
1222
                        if(r->data.hinfo.os->size > 255)
 
1223
                                return 0;
 
1224
                        break;
 
1225
                }
 
1226
        }
 
1227
 
 
1228
        return 1;
 
1229
}
 
1230
 
 
1231
static jdns_string_t *read_name_at_end(const jdns_packet_resource_t *pr, const jdns_packet_t *ref, int _at)
 
1232
{
 
1233
        jdns_string_t *name;
 
1234
        int at;
 
1235
        at = _at;
 
1236
        if(!jdns_packet_resource_read_name(pr, ref, &at, &name))
 
1237
                return 0;
 
1238
        if(at != pr->rdlength)
 
1239
        {
 
1240
                jdns_string_delete(name);
 
1241
                return 0;
 
1242
        }
 
1243
        return name;
 
1244
}
 
1245
 
 
1246
static jdns_string_t *read_text_string(const jdns_packet_resource_t *pr, int *_at)
 
1247
{
 
1248
        jdns_string_t *out;
 
1249
        int at, len;
 
1250
        at = *_at;
 
1251
        if(at + 1 > pr->rdlength)
 
1252
                return 0;
 
1253
        len = pr->rdata[at++];
 
1254
        if(at + len > pr->rdlength)
 
1255
                return 0;
 
1256
        out = jdns_string_new();
 
1257
        jdns_string_set(out, pr->rdata + at, len);
 
1258
        at += len;
 
1259
        *_at = at;
 
1260
        return out;
 
1261
}
 
1262
 
 
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)
 
1267
{
 
1268
        jdns_rr_t *rr = 0;
 
1269
 
 
1270
        if(pr->qtype == JDNS_RTYPE_ANY)
 
1271
                return 0;
 
1272
 
 
1273
        switch(pr->qtype)
 
1274
        {
 
1275
                case JDNS_RTYPE_A:
 
1276
                {
 
1277
                        jdns_address_t *addr;
 
1278
                        unsigned long int ip;
 
1279
                        if(pr->rdlength != 4)
 
1280
                                break;
 
1281
                        memcpy(&ip, pr->rdata, 4);
 
1282
                        ip = ntohl(ip);
 
1283
                        addr = jdns_address_new();
 
1284
                        jdns_address_set_ipv4(addr, ip);
 
1285
                        rr = jdns_rr_new();
 
1286
                        jdns_rr_set_A(rr, addr);
 
1287
                        jdns_address_delete(addr);
 
1288
                        break;
 
1289
                }
 
1290
                case JDNS_RTYPE_AAAA:
 
1291
                {
 
1292
                        jdns_address_t *addr;
 
1293
                        if(pr->rdlength != 16)
 
1294
                                break;
 
1295
                        addr = jdns_address_new();
 
1296
                        jdns_address_set_ipv6(addr, pr->rdata);
 
1297
                        rr = jdns_rr_new();
 
1298
                        jdns_rr_set_AAAA(rr, addr);
 
1299
                        jdns_address_delete(addr);
 
1300
                        break;
 
1301
                }
 
1302
                case JDNS_RTYPE_MX:
 
1303
                {
 
1304
                        unsigned short priority;
 
1305
                        jdns_string_t *name;
 
1306
                        if(pr->rdlength < 2)
 
1307
                                break;
 
1308
                        memcpy(&priority, pr->rdata, 2);
 
1309
                        priority = ntohs(priority);
 
1310
                        name = read_name_at_end(pr, ref, 2);
 
1311
                        if(!name)
 
1312
                                break;
 
1313
                        rr = jdns_rr_new();
 
1314
                        jdns_rr_set_MX(rr, name->data, priority);
 
1315
                        jdns_string_delete(name);
 
1316
                        break;
 
1317
                }
 
1318
                case JDNS_RTYPE_SRV:
 
1319
                {
 
1320
                        unsigned short priority, weight, port;
 
1321
                        jdns_string_t *name;
 
1322
                        if(pr->rdlength < 6)
 
1323
                                break;
 
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);
 
1329
                        port = ntohs(port);
 
1330
                        name = read_name_at_end(pr, ref, 6);
 
1331
                        if(!name)
 
1332
                                break;
 
1333
                        rr = jdns_rr_new();
 
1334
                        jdns_rr_set_SRV(rr, name->data, port, priority, weight);
 
1335
                        jdns_string_delete(name);
 
1336
                        break;
 
1337
                }
 
1338
                case JDNS_RTYPE_CNAME:
 
1339
                {
 
1340
                        jdns_string_t *name;
 
1341
                        name = read_name_at_end(pr, ref, 0);
 
1342
                        if(!name)
 
1343
                                break;
 
1344
                        rr = jdns_rr_new();
 
1345
                        jdns_rr_set_CNAME(rr, name->data);
 
1346
                        jdns_string_delete(name);
 
1347
                        break;
 
1348
                }
 
1349
                case JDNS_RTYPE_PTR:
 
1350
                {
 
1351
                        jdns_string_t *name;
 
1352
                        name = read_name_at_end(pr, ref, 0);
 
1353
                        if(!name)
 
1354
                                break;
 
1355
                        rr = jdns_rr_new();
 
1356
                        jdns_rr_set_PTR(rr, name->data);
 
1357
                        jdns_string_delete(name);
 
1358
                        break;
 
1359
                }
 
1360
                case JDNS_RTYPE_TXT:
 
1361
                {
 
1362
                        jdns_stringlist_t *texts;
 
1363
                        jdns_string_t *str;
 
1364
                        int at, error;
 
1365
                        texts = jdns_stringlist_new();
 
1366
                        at = 0;
 
1367
                        error = 0;
 
1368
                        while(at < pr->rdlength)
 
1369
                        {
 
1370
                                str = read_text_string(pr, &at);
 
1371
                                if(!str)
 
1372
                                {
 
1373
                                        error = 1;
 
1374
                                        break;
 
1375
                                }
 
1376
                                jdns_stringlist_append(texts, str);
 
1377
                                jdns_string_delete(str);
 
1378
                        }
 
1379
                        if(error)
 
1380
                        {
 
1381
                                jdns_stringlist_delete(texts);
 
1382
                                break;
 
1383
                        }
 
1384
                        rr = jdns_rr_new();
 
1385
                        jdns_rr_set_TXT(rr, texts);
 
1386
                        jdns_stringlist_delete(texts);
 
1387
                        break;
 
1388
                }
 
1389
                case JDNS_RTYPE_HINFO:
 
1390
                {
 
1391
                        jdns_string_t *cpu, *os;
 
1392
                        int at;
 
1393
                        at = 0;
 
1394
                        cpu = read_text_string(pr, &at);
 
1395
                        if(!cpu)
 
1396
                                break;
 
1397
                        os = read_text_string(pr, &at);
 
1398
                        if(!os)
 
1399
                        {
 
1400
                                jdns_string_delete(cpu);
 
1401
                                break;
 
1402
                        }
 
1403
                        if(at != pr->rdlength)
 
1404
                        {
 
1405
                                jdns_string_delete(cpu);
 
1406
                                jdns_string_delete(os);
 
1407
                                break;
 
1408
                        }
 
1409
                        rr = jdns_rr_new();
 
1410
                        jdns_rr_set_HINFO(rr, cpu, os);
 
1411
                        jdns_string_delete(cpu);
 
1412
                        jdns_string_delete(os);
 
1413
                        break;
 
1414
                }
 
1415
                case JDNS_RTYPE_NS:
 
1416
                {
 
1417
                        jdns_string_t *name;
 
1418
                        name = read_name_at_end(pr, ref, 0);
 
1419
                        if(!name)
 
1420
                                break;
 
1421
                        rr = jdns_rr_new();
 
1422
                        jdns_rr_set_NS(rr, name->data);
 
1423
                        jdns_string_delete(name);
 
1424
                        break;
 
1425
                }
 
1426
                default:
 
1427
                {
 
1428
                        rr = jdns_rr_new();
 
1429
                        rr->type = pr->qtype;
 
1430
                        break;
 
1431
                }
 
1432
        }
 
1433
 
 
1434
        if(rr)
 
1435
        {
 
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);
 
1441
        }
 
1442
 
 
1443
        return rr;
 
1444
}
 
1445
 
 
1446
//----------------------------------------------------------------------------
 
1447
// jdns_response
 
1448
//----------------------------------------------------------------------------
 
1449
#define ARRAY_DELETE(array, count, dtor) \
 
1450
        { \
 
1451
                if(count > 0) \
 
1452
                { \
 
1453
                        int n; \
 
1454
                        for(n = 0; n < count; ++n) \
 
1455
                                dtor(array[n]); \
 
1456
                } \
 
1457
                jdns_free(array); \
 
1458
                array = 0; \
 
1459
                count = 0; \
 
1460
        }
 
1461
 
 
1462
#define ARRAY_COPY(type, array_src, count_src, array_dest, count_dest, cctor) \
 
1463
        { \
 
1464
                if(count_src > 0) \
 
1465
                { \
 
1466
                        int n; \
 
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]); \
 
1471
                } \
 
1472
        }
 
1473
 
 
1474
#define ARRAY_APPEND(type, array, count, item) \
 
1475
        { \
 
1476
                if(!array) \
 
1477
                        array = (type **)jdns_alloc(sizeof(type *)); \
 
1478
                else \
 
1479
                        array = (type **)jdns_realloc(array, sizeof(type *) * (count + 1)); \
 
1480
                array[count] = item; \
 
1481
                ++count; \
 
1482
        }
 
1483
 
 
1484
jdns_response_t *jdns_response_new()
 
1485
{
 
1486
        jdns_response_t *r = alloc_type(jdns_response_t);
 
1487
        r->answerCount = 0;
 
1488
        r->answerRecords = 0;
 
1489
        r->authorityCount = 0;
 
1490
        r->authorityRecords = 0;
 
1491
        r->additionalCount = 0;
 
1492
        r->additionalRecords = 0;
 
1493
        return r;
 
1494
}
 
1495
 
 
1496
jdns_response_t *jdns_response_copy(const jdns_response_t *r)
 
1497
{
 
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);
 
1502
        return c;
 
1503
}
 
1504
 
 
1505
void jdns_response_delete(jdns_response_t *r)
 
1506
{
 
1507
        if(!r)
 
1508
                return;
 
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);
 
1512
        jdns_free(r);
 
1513
}
 
1514
 
 
1515
void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr)
 
1516
{
 
1517
        ARRAY_APPEND(jdns_rr_t, r->answerRecords, r->answerCount, jdns_rr_copy(rr));
 
1518
}
 
1519
 
 
1520
void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr)
 
1521
{
 
1522
        ARRAY_APPEND(jdns_rr_t, r->authorityRecords, r->authorityCount, jdns_rr_copy(rr));
 
1523
}
 
1524
 
 
1525
void jdns_response_append_additional(jdns_response_t *r, const jdns_rr_t *rr)
 
1526
{
 
1527
        ARRAY_APPEND(jdns_rr_t, r->additionalRecords, r->additionalCount, jdns_rr_copy(rr));
 
1528
}
 
1529
 
 
1530
void jdns_response_remove_extra(jdns_response_t *r)
 
1531
{
 
1532
        ARRAY_DELETE(r->authorityRecords, r->authorityCount, jdns_rr_delete);
 
1533
        ARRAY_DELETE(r->additionalRecords, r->additionalCount, jdns_rr_delete);
 
1534
}
 
1535
 
 
1536
void jdns_response_remove_answer(jdns_response_t *r, int pos)
 
1537
{
 
1538
        jdns_rr_t *rr = r->answerRecords[pos];
 
1539
        jdns_rr_delete(rr);
 
1540
 
 
1541
        // free the position
 
1542
        if(r->answerCount > 1)
 
1543
        {
 
1544
                memmove(r->answerRecords + pos, r->answerRecords + pos + 1, (r->answerCount - pos - 1) * sizeof(void *));
 
1545
                --r->answerCount;
 
1546
        }
 
1547
        else
 
1548
        {
 
1549
                jdns_free(r->answerRecords);
 
1550
                r->answerRecords = 0;
 
1551
                r->answerCount = 0;
 
1552
        }
 
1553
}