2
* Copyright (C) 2005,2006 Justin Karneges
4
* Permission is hereby granted, free of charge, to any person obtaining a
5
* copy of this software and associated documentation files (the
6
* "Software"), to deal in the Software without restriction, including
7
* without limitation the rights to use, copy, modify, merge, publish,
8
* distribute, sublicense, and/or sell copies of the Software, and to
9
* permit persons to whom the Software is furnished to do so, subject to
10
* the following conditions:
12
* The above copyright notice and this permission notice shall be included
13
* in all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
#include "jdns_packet.h"
29
#include "jdns_mdnsd.h"
31
#define JDNS_UDP_UNI_OUT_MAX 512
32
#define JDNS_UDP_UNI_IN_MAX 16384
33
#define JDNS_UDP_MUL_OUT_MAX 9000
34
#define JDNS_UDP_MUL_IN_MAX 16384
36
// cache no more than 7 days
37
#define JDNS_TTL_MAX (86400 * 7)
39
//----------------------------------------------------------------------------
41
//----------------------------------------------------------------------------
43
// declare this here, but implement it later after we define jdns_session_t
44
static void _debug_line(jdns_session_t *s, const char *format, ...);
46
static unsigned char _hex_nibble(unsigned char c)
51
return 'a' + (c - 10);
56
static void _hex_byte(unsigned char c, unsigned char *dest)
58
dest[0] = _hex_nibble((unsigned char)(c >> 4));
59
dest[1] = _hex_nibble((unsigned char)(c & 0x0f));
62
static jdns_string_t *_make_printable(const unsigned char *str, int size)
70
out = jdns_string_new();
71
jdns_string_set_cstr(out, "");
75
// make room for the largest possible result
76
buf = (unsigned char *)malloc(size * 4);
78
for(n = 0; n < size; ++n)
80
unsigned char c = str[n];
86
else if(c >= 0x20 && c < 0x7f)
94
_hex_byte(c, buf + i);
99
out = jdns_string_new();
100
jdns_string_set(out, buf, i);
105
static jdns_string_t *_make_printable_str(const jdns_string_t *str)
107
return _make_printable(str->data, str->size);
110
static jdns_string_t *_make_printable_cstr(const char *str)
112
return _make_printable((const unsigned char *)str, strlen(str));
115
static unsigned char *_fix_input(const unsigned char *in)
125
// add a dot to the end if needed
126
if(in[len - 1] != '.' && len < 254)
128
out = (unsigned char *)malloc(len + 2); // a dot and a zero
129
memcpy(out, in, len);
136
out = (unsigned char *)malloc(len + 1); // a zero
137
memcpy(out, in, len);
144
static const char *_qtype2str(int qtype)
149
case JDNS_RTYPE_A: str = "A"; break;
150
case JDNS_RTYPE_AAAA: str = "AAAA"; break;
151
case JDNS_RTYPE_MX: str = "MX"; break;
152
case JDNS_RTYPE_SRV: str = "SRV"; break;
153
case JDNS_RTYPE_CNAME: str = "CNAME"; break;
154
case JDNS_RTYPE_PTR: str = "PTR"; break;
155
case JDNS_RTYPE_TXT: str = "TXT"; break;
156
case JDNS_RTYPE_HINFO: str = "HINFO"; break;
157
case JDNS_RTYPE_NS: str = "NS"; break;
158
case JDNS_RTYPE_ANY: str = "ANY"; break;
159
default: str = ""; break;
164
static jdns_response_t *_packet2response(const jdns_packet_t *packet, const unsigned char *qname, int qtype, int classmask)
169
r = jdns_response_new();
170
for(n = 0; n < packet->answerRecords->count; ++n)
172
jdns_packet_resource_t *res = (jdns_packet_resource_t *)packet->answerRecords->item[n];
175
if((res->qclass & classmask) != 0x0001)
177
rr = jdns_rr_from_resource(res, packet);
180
// if qname is set, restrict answers to those that match
185
// name must match, type can match or be CNAME
186
if((res->qtype != qtype && res->qtype != JDNS_RTYPE_CNAME) || !jdns_domain_cmp(res->qname->data, qname))
188
// put unusable records in additional section
193
jdns_response_append_answer(r, rr);
195
jdns_response_append_additional(r, rr);
198
for(n = 0; n < packet->authorityRecords->count; ++n)
200
jdns_packet_resource_t *res = (jdns_packet_resource_t *)packet->authorityRecords->item[n];
202
if((res->qclass & classmask) != 0x0001)
204
rr = jdns_rr_from_resource(res, packet);
207
jdns_response_append_authority(r, rr);
210
for(n = 0; n < packet->additionalRecords->count; ++n)
212
jdns_packet_resource_t *res = (jdns_packet_resource_t *)packet->additionalRecords->item[n];
214
if((res->qclass & classmask) != 0x0001)
216
rr = jdns_rr_from_resource(res, packet);
219
jdns_response_append_additional(r, rr);
225
// size must be 1 to 16
226
static void _print_hexdump_line(jdns_session_t *s, const unsigned char *buf, int size)
228
char line[67]; // 3 * 16 + 2 + 16 + zero byte
231
memset(line, ' ', 66);
235
for(n = 0; n < size; ++n)
237
unsigned char c = buf[n];
238
_hex_byte(c, ((unsigned char *)line) + n * 3);
239
line[n * 3 + 2] = ' ';
240
if(c >= 0x20 && c < 0x7f)
245
_debug_line(s, " %s", line);
248
static void _print_hexdump(jdns_session_t *s, const unsigned char *buf, int size)
257
for(n = 0; n < lines; ++n)
264
_print_hexdump_line(s, buf + at, len);
268
static void _print_packet_resources(jdns_session_t *s, const jdns_list_t *reslist)
271
for(n = 0; n < reslist->count; ++n)
273
jdns_packet_resource_t *r;
275
r = (jdns_packet_resource_t *)reslist->item[n];
276
str = _make_printable_str(r->qname);
277
_debug_line(s, " %04x/%04x [%s] ttl=%ld size=%d", r->qclass, r->qtype, str->data, r->ttl, r->rdlength);
278
jdns_string_delete(str);
282
static void _print_packet(jdns_session_t *s, const jdns_packet_t *packet)
285
_debug_line(s, "Packet:");
286
_debug_line(s, " id: %d", packet->id);
287
_debug_line(s, " opts: qr:%d, opcode:%d, aa:%d, tc:%d, rd:%d, ra:%d, z:%d, rcode:%d",
288
packet->opts.qr, packet->opts.opcode, packet->opts.aa, packet->opts.tc,
289
packet->opts.rd, packet->opts.ra, packet->opts.z, packet->opts.rcode);
290
_debug_line(s, " qdcount=%d, ancount=%d, nscount=%d, arcount=%d",
291
packet->qdcount, packet->ancount, packet->nscount, packet->arcount);
292
if(packet->questions->count > 0)
294
_debug_line(s, " questions: (class/type name)");
295
for(n = 0; n < packet->questions->count; ++n)
297
jdns_packet_question_t *q;
299
q = (jdns_packet_question_t *)packet->questions->item[n];
300
str = _make_printable_str(q->qname);
301
_debug_line(s, " %04x/%04x [%s]", q->qclass, q->qtype, str->data);
302
jdns_string_delete(str);
305
if(packet->answerRecords->count > 0)
307
_debug_line(s, " answerRecords: (class/type owner ttl size)");
308
_print_packet_resources(s, packet->answerRecords);
310
if(packet->authorityRecords->count > 0)
312
_debug_line(s, " authorityRecords: (class/type owner ttl size)");
313
_print_packet_resources(s, packet->authorityRecords);
315
if(packet->additionalRecords->count > 0)
317
_debug_line(s, " additionalRecords: (class/type owner ttl size)");
318
_print_packet_resources(s, packet->additionalRecords);
322
static void _print_rr(jdns_session_t *s, const jdns_rr_t *rr, const unsigned char *owner)
325
jdns_string_t *ownerstr;
327
ownerstr = jdns_string_new();
329
// not the expected owner?
330
if(!owner || !jdns_domain_cmp(owner, rr->owner))
333
jdns_string_t *str = _make_printable_cstr((const char *)rr->owner);
334
buf = (unsigned char *)malloc(str->size + 3); // " [%s]"
337
memcpy(buf + 2, str->data, str->size);
338
buf[str->size + 2] = ']';
339
jdns_string_set(ownerstr, buf, str->size + 3);
340
jdns_string_delete(str);
344
jdns_string_set_cstr(ownerstr, "");
350
_debug_line(s, " A: [%s] (ttl=%d)%s", rr->data.address->c_str, rr->ttl, ownerstr->data);
353
case JDNS_RTYPE_AAAA:
355
_debug_line(s, " AAAA: [%s] (ttl=%d)%s", rr->data.address->c_str, rr->ttl, ownerstr->data);
360
jdns_string_t *str = _make_printable_cstr((const char *)rr->data.server->name);
361
_debug_line(s, " MX: [%s] priority=%d (ttl=%d)%s", str->data, rr->data.server->priority, rr->ttl, ownerstr->data);
362
jdns_string_delete(str);
367
jdns_string_t *str = _make_printable_cstr((const char *)rr->data.server->name);
368
_debug_line(s, " SRV: [%s] port=%d priority=%d weight=%d (ttl=%d)%s", str->data, rr->data.server->port, rr->data.server->priority, rr->data.server->weight, rr->ttl, ownerstr->data);
369
jdns_string_delete(str);
372
case JDNS_RTYPE_CNAME:
374
jdns_string_t *str = _make_printable_cstr((const char *)rr->data.name);
375
_debug_line(s, " CNAME: [%s] (ttl=%d)%s", str->data, rr->ttl, ownerstr->data);
376
jdns_string_delete(str);
381
jdns_string_t *str = _make_printable_cstr((const char *)rr->data.name);
382
_debug_line(s, " PTR: [%s] (ttl=%d)%s", str->data, rr->ttl, ownerstr->data);
383
jdns_string_delete(str);
388
_debug_line(s, " TXT: count=%d (ttl=%d)%s", rr->data.texts->count, rr->ttl, ownerstr->data);
389
for(n = 0; n < rr->data.texts->count; ++n)
391
jdns_string_t *str, *pstr;
392
str = rr->data.texts->item[n];
393
pstr = _make_printable_str(str);
394
_debug_line(s, " len=%d [%s]", str->size, pstr->data);
395
jdns_string_delete(pstr);
399
case JDNS_RTYPE_HINFO:
401
jdns_string_t *cpu, *os;
402
cpu = _make_printable_str(rr->data.hinfo.cpu);
403
os = _make_printable_str(rr->data.hinfo.os);
404
_debug_line(s, " HINFO: [%s] [%s] (ttl=%d)%s", cpu->data, os->data, rr->ttl, ownerstr->data);
405
jdns_string_delete(cpu);
406
jdns_string_delete(os);
411
jdns_string_t *str = _make_printable_cstr((const char *)rr->data.name);
412
_debug_line(s, " NS: [%s] (ttl=%d)%s", str->data, rr->ttl, ownerstr->data);
413
jdns_string_delete(str);
418
_debug_line(s, " Unknown (%d): %d bytes (ttl=%d)%s", rr->type, rr->rdlength, rr->ttl, ownerstr->data);
422
jdns_string_delete(ownerstr);
425
static void _print_records(jdns_session_t *s, const jdns_response_t *r, const unsigned char *owner)
428
_debug_line(s, "Records:");
429
_debug_line(s, " Answer Records: %d", r->answerCount);
430
for(n = 0; n < r->answerCount; ++n)
431
_print_rr(s, r->answerRecords[n], owner);
432
_debug_line(s, " Authority Records: %d", r->authorityCount);
433
for(n = 0; n < r->authorityCount; ++n)
434
_print_rr(s, r->authorityRecords[n], owner);
435
_debug_line(s, " Additional Records: %d", r->additionalCount);
436
for(n = 0; n < r->additionalCount; ++n)
437
_print_rr(s, r->additionalRecords[n], owner);
440
static int _min(int a, int b)
442
return (a < b) ? a : b;
445
//----------------------------------------------------------------------------
447
//----------------------------------------------------------------------------
448
jdns_event_t *jdns_event_new()
450
jdns_event_t *e = alloc_type(jdns_event_t);
455
void jdns_event_delete(jdns_event_t *e)
459
jdns_response_delete(e->response);
463
//----------------------------------------------------------------------------
464
// jdns - internal types
465
//----------------------------------------------------------------------------
466
typedef struct list_item
468
void (*dtor)(void *);
479
list_t *l = alloc_type(list_t);
485
void list_delete(list_t *l)
490
for(n = 0; n < l->count; ++n)
491
l->item[n]->dtor(l->item[n]);
497
void list_insert(list_t *l, void *item, int pos)
499
list_item_t *i = (list_item_t *)item;
501
l->item = (list_item_t **)malloc(sizeof(list_item_t *));
503
l->item = (list_item_t **)realloc(l->item, sizeof(list_item_t *) * (l->count + 1));
505
memmove(l->item + pos + 1, l->item + pos, (l->count - pos) * sizeof(list_item_t *));
512
void list_remove(list_t *l, void *item)
515
list_item_t *i = (list_item_t *)item;
517
for(n = 0; n < l->count; ++n)
531
memmove(l->item + pos, l->item + pos + 1, (l->count - pos - 1) * sizeof(list_item_t *));
542
typedef struct name_server
544
void (*dtor)(struct name_server *);
546
jdns_address_t *address;
550
void name_server_delete(name_server_t *ns);
552
name_server_t *name_server_new()
554
name_server_t *ns = alloc_type(name_server_t);
555
ns->dtor = name_server_delete;
560
void name_server_delete(name_server_t *ns)
564
jdns_address_delete(ns->address);
568
int _intarray_indexOf(int *array, int count, int val)
571
for(n = 0; n < count; ++n)
579
int _intarray_add(int **array, int *count, int val)
583
p = (int *)malloc(sizeof(int));
585
p = (int *)realloc(*array, sizeof(int) * (*count + 1));
589
(*array)[*count] = val;
594
void _intarray_remove(int **array, int *count, int pos)
599
memmove(*array + pos, *array + pos + 1, (*count - pos - 1) * sizeof(int));
601
p = (int *)realloc(*array, sizeof(int) * (*count));
615
void (*dtor)(struct query *);
626
// what we are looking up
627
unsigned char *qname;
630
// how many transmission attempts we have done. note this
631
// is not actually how many packets have been sent, since
632
// it is possible for the first transmission to send many
633
// at once. this variable lets us decide when to give up.
634
// (idea taken from qdns).
635
// set to -1 to deactivate (stop sending packets)
638
// which nameservers we've tried (stored as a list of ids)
639
int servers_tried_count;
642
// which servers we shouldn't try again
643
int servers_failed_count;
646
// flag to indicate whether or not we've tried all available
647
// nameservers already. this means that all future
648
// transmissions are likely repeats, and should be slowed
652
// holds a timeout for the next step (time_start == -1 means no timer)
656
// whether or not to look in the cache for this query
659
// cname subquerying. only cname_parent or cname_child may be set,
661
int cname_chain_count;
662
struct query *cname_parent;
663
struct query *cname_child;
665
// accumulates known multicast records to prevent duplicates
666
jdns_response_t *mul_known;
669
void query_delete(query_t *q);
673
query_t *q = alloc_type(query_t);
674
q->dtor = query_delete;
675
q->req_ids_count = 0;
678
q->servers_tried_count = 0;
679
q->servers_tried = 0;
680
q->servers_failed_count = 0;
681
q->servers_failed = 0;
682
q->cname_chain_count = 0;
689
void query_delete(query_t *q)
698
free(q->servers_tried);
699
if(q->servers_failed)
700
free(q->servers_failed);
701
jdns_response_delete(q->mul_known);
705
int query_have_req_id(const query_t *q, int req_id)
707
if(_intarray_indexOf(q->req_ids, q->req_ids_count, req_id) != -1)
712
void query_add_req_id(query_t *q, int req_id)
714
_intarray_add(&q->req_ids, &q->req_ids_count, req_id);
717
void query_remove_req_id(query_t *q, int req_id)
721
pos = _intarray_indexOf(q->req_ids, q->req_ids_count, req_id);
723
_intarray_remove(&q->req_ids, &q->req_ids_count, pos);
726
int query_server_tried(const query_t *q, int ns_id)
728
if(_intarray_indexOf(q->servers_tried, q->servers_tried_count, ns_id) != -1)
733
void query_add_server_tried(query_t *q, int ns_id)
735
_intarray_add(&q->servers_tried, &q->servers_tried_count, ns_id);
738
void query_clear_servers_tried(query_t *q)
741
free(q->servers_tried);
742
q->servers_tried_count = 0;
743
q->servers_tried = 0;
746
int query_server_failed(const query_t *q, int ns_id)
748
if(_intarray_indexOf(q->servers_failed, q->servers_failed_count, ns_id) != -1)
753
void query_add_server_failed(query_t *q, int ns_id)
755
_intarray_add(&q->servers_failed, &q->servers_failed_count, ns_id);
758
void query_name_server_gone(query_t *q, int ns_id)
762
pos = _intarray_indexOf(q->servers_tried, q->servers_tried_count, ns_id);
764
_intarray_remove(&q->servers_tried, &q->servers_tried_count, pos);
766
pos = _intarray_indexOf(q->servers_failed, q->servers_failed_count, ns_id);
768
_intarray_remove(&q->servers_failed, &q->servers_failed_count, pos);
771
typedef struct datagram
773
void (*dtor)(struct datagram *);
775
jdns_address_t *dest_address;
782
int query_send_type; // 0 == normal, 1 == first step send-all
784
// name server association
788
void datagram_delete(datagram_t *a);
790
datagram_t *datagram_new()
792
datagram_t *a = alloc_type(datagram_t);
793
a->dtor = datagram_delete;
801
void datagram_delete(datagram_t *a)
805
jdns_address_delete(a->dest_address);
811
typedef struct cache_item
813
void (*dtor)(struct cache_item *);
814
unsigned char *qname;
818
jdns_rr_t *record; // if zero, nxdomain is assumed
821
void cache_item_delete(cache_item_t *e);
823
cache_item_t *cache_item_new()
825
cache_item_t *a = alloc_type(cache_item_t);
826
a->dtor = cache_item_delete;
832
void cache_item_delete(cache_item_t *a)
838
jdns_rr_delete(a->record);
844
void (*dtor)(struct event *);
848
void event_delete(event_t *e);
852
event_t *e = alloc_type(event_t);
853
e->dtor = event_delete;
858
void event_delete(event_t *e)
862
jdns_event_delete(e->event);
866
typedef struct published_item
868
void (*dtor)(struct published_item *);
871
unsigned char *qname;
877
void published_item_delete(published_item_t *a);
879
published_item_t *published_item_new()
881
published_item_t *a = alloc_type(published_item_t);
882
a->dtor = published_item_delete;
889
void published_item_delete(published_item_t *a)
895
jdns_rr_delete(a->rr);
899
//----------------------------------------------------------------------------
901
//----------------------------------------------------------------------------
912
int next_name_server_id;
914
int handle_readable, handle_writable;
916
list_t *name_servers;
925
jdns_address_t *maddr;
928
jdns_session_t *jdns_session_new(jdns_callbacks_t *callbacks)
930
jdns_session_t *s = alloc_type(jdns_session_t);
931
memcpy(&s->cb, callbacks, sizeof(jdns_callbacks_t));
935
s->next_dns_id = s->cb.rand_int(s, s->cb.app);
938
s->next_name_server_id = 0;
940
s->handle_readable = 0;
941
s->handle_writable = 1;
943
s->name_servers = list_new();
944
s->queries = list_new();
945
s->outgoing = list_new();
946
s->events = list_new();
947
s->cache = list_new();
950
s->published = list_new();
956
void jdns_session_delete(jdns_session_t *s)
961
s->cb.udp_unbind(s, s->cb.app, s->handle);
962
list_delete(s->name_servers);
963
list_delete(s->queries);
964
list_delete(s->outgoing);
965
list_delete(s->events);
966
list_delete(s->cache);
971
list_delete(s->published);
972
jdns_address_delete(s->maddr);
977
// declare some internal functions
978
static int _callback_time_now(mdnsd d, void *arg);
979
static int _callback_rand_int(mdnsd d, void *arg);
981
static void _append_event(jdns_session_t *s, jdns_event_t *event);
982
static void _remove_name_server_datagrams(jdns_session_t *s, int ns_id);
983
static void _remove_query_datagrams(jdns_session_t *s, const query_t *q);
985
static int _unicast_query(jdns_session_t *s, const unsigned char *name, int qtype);
986
static void _unicast_cancel(jdns_session_t *s, query_t *q);
987
static int _multicast_query(jdns_session_t *s, const unsigned char *name, int qtype);
988
static void _multicast_cancel(jdns_session_t *s, int req_id);
989
static int _multicast_publish(jdns_session_t *s, int mode, const jdns_rr_t *rr);
990
static void _multicast_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rr);
991
static void _multicast_cancel_publish(jdns_session_t *s, int id);
992
static void _multicast_flush(jdns_session_t *s);
994
static int jdns_step_unicast(jdns_session_t *s, int now);
995
static int jdns_step_multicast(jdns_session_t *s, int now);
997
static int _int_wrap(int *src, int start)
1007
static int get_next_qid(jdns_session_t *s)
1013
id = _int_wrap(&s->next_qid, 0);
1014
for(n = 0; n < s->queries->count; ++n)
1016
if(((query_t *)s->queries->item[n])->id == id)
1027
static int get_next_req_id(jdns_session_t *s)
1033
id = _int_wrap(&s->next_req_id, 1);
1035
// no query using this?
1036
for(n = 0; n < s->queries->count; ++n)
1038
query_t *q = (query_t *)s->queries->item[n];
1039
for(k = 0; k < q->req_ids_count; ++k)
1041
if(q->req_ids[k] == id)
1051
// no publish using this?
1052
for(n = 0; n < s->published->count; ++n)
1054
if(((published_item_t *)s->published->item[n])->id == id)
1064
// starts at random, must fit in 16 bits
1065
static int get_next_dns_id(jdns_session_t *s)
1067
return (s->next_dns_id++ & 0xffff);
1071
static int get_next_name_server_id(jdns_session_t *s)
1077
id = _int_wrap(&s->next_name_server_id, 0);
1078
for(n = 0; n < s->name_servers->count; ++n)
1080
if(((name_server_t *)s->name_servers->item[n])->id == id)
1090
int jdns_init_unicast(jdns_session_t *s, const jdns_address_t *addr, int port)
1094
ret = s->cb.udp_bind(s, s->cb.app, addr, port, 0);
1102
int jdns_init_multicast(jdns_session_t *s, const jdns_address_t *addr, int port, const jdns_address_t *maddr)
1106
ret = s->cb.udp_bind(s, s->cb.app, addr, port, maddr);
1111
s->maddr = jdns_address_copy(maddr);
1113
// class 1. note: frame size is ignored by the jdns version of mdnsd
1114
s->mdns = mdnsd_new(0x0001, 1000, s->port, _callback_time_now, _callback_rand_int, s);
1118
void jdns_shutdown(jdns_session_t *s)
1120
if(s->shutdown == 0)
1121
s->shutdown = 1; // request shutdown
1124
void jdns_set_nameservers(jdns_session_t *s, const jdns_nameserverlist_t *nslist)
1129
for(k = 0; k < s->name_servers->count; ++k)
1131
name_server_t *ns = (name_server_t *)(s->name_servers->item[k]);
1133
for(n = 0; n < nslist->count; ++n)
1135
jdns_nameserver_t *i = (jdns_nameserver_t *)nslist->item[n];
1136
if(jdns_address_cmp(ns->address, i->address) && ns->port == i->port)
1147
// remove any pending packets to this nameserver
1148
_remove_name_server_datagrams(s, ns->id);
1150
_debug_line(s, "ns [%s:%d] (id=%d) removed", ns->address->c_str, ns->port, ns->id);
1152
list_remove(s->name_servers, ns);
1153
--k; // adjust position
1154
for(i = 0; i < s->queries->count; ++i)
1155
query_name_server_gone((query_t *)s->queries->item[i], ns_id);
1160
for(n = 0; n < nslist->count; ++n)
1163
jdns_nameserver_t *i;
1166
i = (jdns_nameserver_t *)nslist->item[n];
1168
for(k = 0; k < s->name_servers->count; ++k)
1170
ns = (name_server_t *)(s->name_servers->item[k]);
1171
if(jdns_address_cmp(ns->address, i->address) && ns->port == i->port)
1179
_debug_line(s, "ns [%s:%d] (id=%d) still present", ns->address->c_str, ns->port, ns->id);
1183
ns = name_server_new();
1184
ns->id = get_next_name_server_id(s);
1185
ns->address = jdns_address_copy(i->address);
1187
list_insert(s->name_servers, ns, -1);
1188
_debug_line(s, "ns [%s:%d] (id=%d) added", ns->address->c_str, ns->port, ns->id);
1193
if(nslist->count == 0)
1195
_debug_line(s, "nameserver count is zero, invalidating any queries");
1197
// invalidate all of the queries!
1198
for(n = 0; n < s->queries->count; ++n)
1200
query_t *q = (query_t *)s->queries->item[n];
1202
// report event to any requests listening
1203
for(k = 0; k < q->req_ids_count; ++k)
1205
jdns_event_t *event = jdns_event_new();
1206
event->type = JDNS_EVENT_RESPONSE;
1207
event->id = q->req_ids[k];
1208
event->status = JDNS_STATUS_TIMEOUT;
1209
_append_event(s, event);
1212
// this line is probably redundant, but just for
1213
// consistency we'll do it...
1214
_remove_query_datagrams(s, q);
1216
list_remove(s->queries, q);
1217
--n; // adjust position
1222
void jdns_probe(jdns_session_t *s)
1227
_multicast_flush(s);
1230
int jdns_query(jdns_session_t *s, const unsigned char *name, int rtype)
1233
return _unicast_query(s, name, rtype);
1235
return _multicast_query(s, name, rtype);
1238
void jdns_cancel_query(jdns_session_t *s, int id)
1245
_multicast_cancel(s, id);
1250
for(n = 0; n < s->queries->count; ++n)
1252
query_t *q = (query_t *)s->queries->item[n];
1253
if(query_have_req_id(q, id))
1255
query_remove_req_id(q, id);
1257
// note: calling _cancel_query might remove an item
1258
// from s->queries, thereby screwing up our iterator
1259
// position, but that's ok because we just break
1262
// if no one else is depending on this request, then take action
1263
if(q->req_ids_count == 0 && !q->cname_parent)
1265
// remove a possible cname child
1266
if(q->cname_child && q->cname_child->req_ids_count == 0)
1268
q->cname_child->cname_parent = 0;
1269
_unicast_cancel(s, q->cname_child);
1273
_unicast_cancel(s, q);
1280
int jdns_publish(jdns_session_t *s, int mode, const jdns_rr_t *rr)
1282
return _multicast_publish(s, mode, rr);
1285
void jdns_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rr)
1287
_multicast_update_publish(s, id, rr);
1290
void jdns_cancel_publish(jdns_session_t *s, int id)
1292
_multicast_cancel_publish(s, id);
1295
int jdns_step(jdns_session_t *s)
1300
// session is shut down
1301
if(s->shutdown == 2)
1304
now = s->cb.time_now(s, s->cb.app);
1305
passed = now - s->last_time;
1307
_debug_line(s, "passed: %d", passed);
1310
ret = jdns_step_unicast(s, now);
1312
ret = jdns_step_multicast(s, now);
1318
int jdns_next_timer(jdns_session_t *s)
1320
return s->next_timer;
1323
void jdns_set_handle_readable(jdns_session_t *s, int handle)
1326
s->handle_readable = 1;
1329
void jdns_set_handle_writable(jdns_session_t *s, int handle)
1332
s->handle_writable = 1;
1335
jdns_event_t *jdns_next_event(jdns_session_t *s)
1337
jdns_event_t *event = 0;
1338
if(s->events->count > 0)
1340
event_t *e = (event_t *)s->events->item[0];
1343
list_remove(s->events, e);
1348
//----------------------------------------------------------------------------
1349
// jdns - internal functions
1350
//----------------------------------------------------------------------------
1352
// we don't have vsnprintf on windows, so don't pass anything enormous to
1353
// this function. the plan is that no line should exceed 1000 bytes,
1354
// although _print_rr() might get close. a 2048 byte buffer should be
1356
void _debug_line(jdns_session_t *s, const char *format, ...)
1358
char *buf = (char *)malloc(2048);
1360
va_start(ap, format);
1361
vsprintf(buf, format, ap);
1363
s->cb.debug_line(s, s->cb.app, buf);
1367
int _callback_time_now(mdnsd d, void *arg)
1369
jdns_session_t *s = (jdns_session_t *)arg;
1371
// offset the time, mdnsd doesn't like starting at 0
1372
return s->cb.time_now(s, s->cb.app) + 120 * 1000;
1375
int _callback_rand_int(mdnsd d, void *arg)
1377
jdns_session_t *s = (jdns_session_t *)arg;
1379
return s->cb.rand_int(s, s->cb.app);
1382
void _append_event(jdns_session_t *s, jdns_event_t *event)
1384
event_t *e = event_new();
1386
list_insert(s->events, e, -1);
1389
void _remove_name_server_datagrams(jdns_session_t *s, int ns_id)
1392
for(n = 0; n < s->outgoing->count; ++n)
1394
datagram_t *a = (datagram_t *)s->outgoing->item[n];
1395
if(a->ns_id == ns_id)
1397
list_remove(s->outgoing, a);
1398
--n; // adjust position
1403
void _remove_query_datagrams(jdns_session_t *s, const query_t *q)
1406
for(n = 0; n < s->outgoing->count; ++n)
1408
datagram_t *a = (datagram_t *)s->outgoing->item[n];
1411
list_remove(s->outgoing, a);
1412
--n; // adjust position
1417
void _process_message(jdns_session_t *s, jdns_packet_t *p, int now, query_t *q, name_server_t *ns);
1419
// return 1 if 'q' should be deleted, 0 if not
1420
int _process_response(jdns_session_t *s, jdns_response_t *r, int nxdomain, query_t *q);
1422
jdns_response_t *_cache_get_response(jdns_session_t *s, const unsigned char *qname, int qtype, int *_lowest_timeleft)
1425
int lowest_timeleft = -1;
1426
int now = s->cb.time_now(s, s->cb.app);
1427
jdns_response_t *r = 0;
1428
for(n = 0; n < s->cache->count; ++n)
1430
cache_item_t *i = (cache_item_t *)s->cache->item[n];
1431
if(jdns_domain_cmp(i->qname, qname) && i->qtype == qtype)
1433
int passed, timeleft;
1436
r = jdns_response_new();
1439
jdns_response_append_answer(r, jdns_rr_copy(i->record));
1441
passed = now - i->time_start;
1442
timeleft = (i->ttl * 1000) - passed;
1443
if(lowest_timeleft == -1 || timeleft < lowest_timeleft)
1444
lowest_timeleft = timeleft;
1447
if(_lowest_timeleft)
1448
*_lowest_timeleft = lowest_timeleft;
1452
query_t *_get_query(jdns_session_t *s, const unsigned char *qname, int qtype, int unique)
1460
// check for existing queries
1461
for(n = 0; n < s->queries->count; ++n)
1463
q = (query_t *)s->queries->item[n];
1464
if(jdns_domain_cmp(q->qname, qname) && q->qtype == qtype)
1466
// if it is inactive, just nuke it
1469
_remove_query_datagrams(s, q);
1470
list_remove(s->queries, q);
1471
--n; // adjust position
1473
// otherwise, latch onto the first one we find
1476
str = _make_printable_cstr((const char *)q->qname);
1477
_debug_line(s, "[%d] reusing query for: [%s] [%s]", q->id, _qtype2str(qtype), str->data);
1478
jdns_string_delete(str);
1486
q->id = get_next_qid(s);
1487
q->qname = _ustrdup(qname);
1495
list_insert(s->queries, q, -1);
1497
str = _make_printable_cstr((const char *)q->qname);
1498
_debug_line(s, "[%d] querying: [%s] [%s]", q->id, _qtype2str(qtype), str->data);
1499
jdns_string_delete(str);
1503
int _unicast_query(jdns_session_t *s, const unsigned char *name, int qtype)
1505
unsigned char *qname;
1510
str = _make_printable_cstr((const char *)name);
1511
_debug_line(s, "query input: [%s]", str->data);
1512
jdns_string_delete(str);
1514
qname = _fix_input(name);
1516
q = _get_query(s, qname, qtype, 0);
1517
req_id = get_next_req_id(s);
1518
query_add_req_id(q, req_id);
1523
void _unicast_cancel(jdns_session_t *s, query_t *q)
1525
// didn't even do a step yet? just remove it
1528
_remove_query_datagrams(s, q);
1529
list_remove(s->queries, q);
1531
// otherwise, just deactivate
1534
// deactivate and remain in the background for
1535
// 1 minute. this will allow us to cache a
1536
// reply, even if the user is not currently
1539
q->time_start = s->cb.time_now(s, s->cb.app);
1540
q->time_next = 60000;
1544
void _queue_packet(jdns_session_t *s, query_t *q, const name_server_t *ns, int recurse, int query_send_type)
1546
jdns_packet_t *packet;
1549
packet = jdns_packet_new();
1550
packet->id = q->dns_id;
1551
packet->opts.rd = recurse; // recursion desired
1553
jdns_packet_question_t *question = jdns_packet_question_new();
1554
question->qname = jdns_string_new();
1555
jdns_string_set_cstr(question->qname, (const char *)q->qname);
1556
question->qtype = q->qtype;
1557
question->qclass = 0x0001;
1558
jdns_list_insert(packet->questions, question, -1);
1559
jdns_packet_question_delete(question);
1561
if(!jdns_packet_export(packet, JDNS_UDP_UNI_OUT_MAX))
1563
_debug_line(s, "outgoing packet export error, not sending");
1564
jdns_packet_delete(packet);
1569
a->handle = s->handle;
1570
a->dest_address = jdns_address_copy(ns->address);
1571
a->dest_port = ns->port;
1572
a->data = jdns_copy_array(packet->raw_data, packet->raw_size);
1573
a->size = packet->raw_size;
1575
a->query_send_type = query_send_type;
1578
jdns_packet_delete(packet);
1580
list_insert(s->outgoing, a, -1);
1583
// return 1 if packets still need to be written
1584
int _unicast_do_writes(jdns_session_t *s, int now);
1586
// return 1 if packets still need to be read
1587
int _unicast_do_reads(jdns_session_t *s, int now);
1589
int jdns_step_unicast(jdns_session_t *s, int now)
1594
int smallest_time = -1;
1597
if(s->shutdown == 1)
1599
jdns_event_t *event = jdns_event_new();
1600
event->type = JDNS_EVENT_SHUTDOWN;
1601
_append_event(s, event);
1606
// expire cached items
1607
for(n = 0; n < s->cache->count; ++n)
1609
cache_item_t *i = (cache_item_t *)s->cache->item[n];
1610
if(now >= i->time_start + (i->ttl * 1000))
1612
jdns_string_t *str = _make_printable_cstr((const char *)i->qname);
1613
_debug_line(s, "cache exp [%s]", str->data);
1614
jdns_string_delete(str);
1615
list_remove(s->cache, i);
1616
--n; // adjust position
1620
need_write = _unicast_do_writes(s, now);
1621
need_read = _unicast_do_reads(s, now);
1623
// calculate next timer (based on queries and cache)
1624
for(n = 0; n < s->queries->count; ++n)
1626
query_t *q = (query_t *)(s->queries->item[n]);
1627
if(q->time_start != -1)
1629
int qpassed = now - q->time_start;
1630
int timeleft = q->time_next - qpassed;
1634
if(smallest_time == -1 || timeleft < smallest_time)
1635
smallest_time = timeleft;
1638
for(n = 0; n < s->cache->count; ++n)
1640
cache_item_t *i = (cache_item_t *)(s->cache->item[n]);
1641
int passed = now - i->time_start;
1642
int timeleft = (i->ttl * 1000) - passed;
1646
if(smallest_time == -1 || timeleft < smallest_time)
1647
smallest_time = timeleft;
1651
if(smallest_time != -1)
1653
flags |= JDNS_STEP_TIMER;
1654
s->next_timer = smallest_time;
1656
// offset it a little bit, so that the user doesn't call
1657
// us too early, resulting in a no-op and another timer
1658
// of 1 millisecond.
1661
if(need_read || need_write)
1662
flags |= JDNS_STEP_HANDLE;
1666
int _unicast_do_writes(jdns_session_t *s, int now)
1671
for(n = 0; n < s->queries->count; ++n)
1674
int qpassed, timeleft;
1677
int already_sending;
1679
q = (query_t *)s->queries->item[n];
1682
if(q->time_start == -1)
1685
qpassed = now - q->time_start;
1686
timeleft = q->time_next - qpassed;
1689
_debug_line(s, "[%d] time_start/next=%d/%d (left=%d)", q->id, q->time_start, q->time_next, timeleft);
1696
int lowest_timeleft;
1697
int qtype = q->qtype;
1700
r = _cache_get_response(s, q->qname, qtype, &lowest_timeleft);
1702
// not found? try cname
1705
qtype = JDNS_RTYPE_CNAME;
1706
r = _cache_get_response(s, q->qname, qtype, &lowest_timeleft);
1713
_debug_line(s, "[%d] using cached answer", q->id);
1715
// are any of the records about to expire in 3 minutes?
1716
// assume the client is interested in this record and
1717
// query it again "in the background"
1718
if(lowest_timeleft < (3 * 60 * 1000))
1722
_debug_line(s, "requerying for cached item about to expire");
1724
new_q = _get_query(s, q->qname, q->qtype, 1);
1725
new_q->retrying = 1; // slow it down
1726
new_q->trycache = 0; // don't use the cache for this
1729
nxdomain = r->answerCount == 0 ? 1 : 0;
1730
if(_process_response(s, r, nxdomain, q))
1732
_remove_query_datagrams(s, q);
1733
list_remove(s->queries, q);
1734
--n; // adjust position
1743
// time up on an inactive query? remove it
1744
_debug_line(s, "removing inactive query");
1745
_remove_query_datagrams(s, q);
1746
list_remove(s->queries, q);
1747
--n; // adjust position
1753
// too many tries, give up
1757
// no nameservers, give up
1758
// (this would happen if someone removed all nameservers
1760
if(s->name_servers->count == 0)
1765
// report event to any requests listening
1766
for(k = 0; k < q->req_ids_count; ++k)
1768
jdns_event_t *event = jdns_event_new();
1769
event->type = JDNS_EVENT_RESPONSE;
1770
event->id = q->req_ids[k];
1771
event->status = JDNS_STATUS_TIMEOUT;
1772
_append_event(s, event);
1775
_remove_query_datagrams(s, q);
1776
list_remove(s->queries, q);
1777
--n; // adjust position
1781
// assign a packet id if we don't have one yet
1783
q->dns_id = get_next_dns_id(s);
1785
// out of name servers?
1786
if(q->servers_tried_count == s->name_servers->count)
1788
// clear the 'tried' list, and start over in retry mode
1789
query_clear_servers_tried(q);
1793
// find a nameserver that has not been tried or failed
1795
for(k = 0; k < s->name_servers->count; ++k)
1797
name_server_t *i = (name_server_t *)s->name_servers->item[k];
1798
if(!query_server_tried(q, i->id) && !query_server_failed(q, i->id))
1805
// in theory, it is not possible for 'ns' to be null here
1807
// don't send the packet if there is already one in the queue
1808
already_sending = 0;
1809
for(k = 0; k < s->outgoing->count; ++k)
1811
datagram_t *a = (datagram_t *)s->outgoing->item[k];
1812
if(a->query == q && a->query_send_type == 0)
1814
already_sending = 1;
1819
// send the query, with recursion desired, normal query_send_type
1820
if(!already_sending)
1821
_queue_packet(s, q, ns, 1, 0);
1823
query_add_server_tried(q, ns->id);
1825
// if there is one query, then do a trick on the first step
1826
/*if(s->queries->count == 1 && q->step == 0 && !q->retrying)
1828
// query all other servers non-recursively
1829
// note: if sending fails, there is no retry
1830
for(k = 0; k < s->name_servers->count; ++k)
1832
name_server_t *i = (name_server_t *)s->name_servers->item[k];
1833
if(!query_server_tried(q, i->id))
1835
// last arg sets first-step query_send_type
1836
_queue_packet(s, q, i, 0, 1);
1841
// out of name servers?
1842
if(q->servers_tried_count == s->name_servers->count)
1844
// clear the 'tried' list, and start over in retry mode
1845
query_clear_servers_tried(q);
1849
q->time_start = now;
1850
q->time_next = q->retrying ? 1500 : 800;
1854
// try to send queued outgoing packets
1855
for(n = 0; n < s->outgoing->count; ++n)
1857
datagram_t *a = (datagram_t *)s->outgoing->item[n];
1860
if(!s->handle_writable)
1866
_debug_line(s, "SEND %s:%d (size=%d)", a->dest_address->c_str, a->dest_port, a->size);
1867
_print_hexdump(s, a->data, a->size);
1869
ret = s->cb.udp_write(s, s->cb.app, a->handle, a->dest_address, a->dest_port, a->data, a->size);
1872
s->handle_writable = 0;
1877
list_remove(s->outgoing, a);
1878
--n; // adjust position
1884
void _cache_add(jdns_session_t *s, const unsigned char *qname, int qtype, int time_start, int ttl, const jdns_rr_t *record)
1890
i = cache_item_new();
1891
i->qname = _ustrdup(qname);
1893
i->time_start = time_start;
1896
i->record = jdns_rr_copy(record);
1897
list_insert(s->cache, i, -1);
1899
str = _make_printable_cstr((const char *)i->qname);
1900
_debug_line(s, "cache add [%s] for %d seconds", str->data, i->ttl);
1901
jdns_string_delete(str);
1904
void _cache_remove_all_of_kind(jdns_session_t *s, const unsigned char *qname, int qtype)
1907
for(n = 0; n < s->cache->count; ++n)
1909
cache_item_t *i = (cache_item_t *)s->cache->item[n];
1910
if(jdns_domain_cmp(i->qname, qname) && i->qtype == qtype)
1912
jdns_string_t *str = _make_printable_cstr((const char *)i->qname);
1913
_debug_line(s, "cache del [%s]", str->data);
1914
jdns_string_delete(str);
1915
list_remove(s->cache, i);
1916
--n; // adjust position
1921
int _unicast_do_reads(jdns_session_t *s, int now)
1926
// let's always ask for reads, just so the user doesn't have to
1927
// worry about what should happen to incoming packets otherwise
1930
if(!s->handle_readable)
1935
unsigned char buf[JDNS_UDP_UNI_IN_MAX];
1936
int bufsize = JDNS_UDP_UNI_IN_MAX;
1938
jdns_packet_t *packet;
1939
jdns_address_t *addr;
1944
addr = jdns_address_new();
1945
ret = s->cb.udp_read(s, s->cb.app, s->handle, addr, &port, buf, &bufsize);
1950
s->handle_readable = 0;
1951
jdns_address_delete(addr);
1955
_debug_line(s, "RECV %s:%d (size=%d)", addr->c_str, port, bufsize);
1956
_print_hexdump(s, buf, bufsize);
1958
if(!jdns_packet_import(&packet, buf, bufsize))
1960
_debug_line(s, "error parsing packet / too large");
1962
jdns_address_delete(addr);
1966
_print_packet(s, packet);
1968
if(s->queries->count == 0)
1970
_debug_line(s, "we have no queries");
1972
jdns_address_delete(addr);
1976
// who does it belong to?
1979
for(n = 0; n < s->queries->count; ++n)
1981
query_t *i = (query_t *)s->queries->item[n];
1985
if(i->dns_id == packet->id)
1994
// what name server did it come from?
1995
for(k = 0; k < s->name_servers->count; ++k)
1997
name_server_t *i = (name_server_t *)s->name_servers->item[k];
1998
if(jdns_address_cmp(i->address, addr) && i->port == port)
2005
// none? maybe that's because we're using unicast
2006
// over multicast, where responses always come
2007
// from an unexpected address
2008
if(!ns && s->name_servers->count > 0)
2011
jdns_address_t *m4, *m6;
2013
i = (name_server_t *)s->name_servers->item[0];
2014
m4 = jdns_address_multicast4_new();
2015
m6 = jdns_address_multicast6_new();
2016
if(jdns_address_cmp(i->address, m4) || jdns_address_cmp(i->address, m6))
2018
jdns_address_delete(m4);
2019
jdns_address_delete(m6);
2022
// if there is no suitable name server, don't accept
2028
jdns_address_delete(addr);
2030
// no queries? eat the packet
2033
_debug_line(s, "no such query for packet");
2034
jdns_packet_delete(packet);
2038
_process_message(s, packet, now, q, ns);
2039
jdns_packet_delete(packet);
2045
void _process_message(jdns_session_t *s, jdns_packet_t *packet, int now, query_t *q, name_server_t *ns)
2050
int recursion_desired;
2051
int answer_section_ok;
2055
if(packet->opts.opcode != 0)
2057
_debug_line(s, "opcode != 0, discarding");
2061
// we don't test RA (recursion available)
2062
// we don't test the extra Z fields
2064
authoritative = packet->opts.aa;
2065
truncated = packet->opts.tc;
2066
recursion_desired = packet->opts.rd;
2067
answer_section_ok = 0;
2068
if(packet->qdcount == packet->questions->count && packet->ancount == packet->answerRecords->count)
2069
answer_section_ok = 1;
2075
if(packet->opts.rcode == 3)
2077
r = jdns_response_new();
2081
else if(packet->opts.rcode == 0)
2083
int at_least_something;
2086
r = _packet2response(packet, q->qname, q->qtype, 0xffff);
2087
at_least_something = 0;
2088
if(r->answerCount > 0)
2089
at_least_something = 1;
2090
_print_records(s, r, q->qname);
2093
if(at_least_something)
2099
// note: why does qdns care about recursion_desired here?
2100
if(authoritative && recursion_desired)
2106
jdns_response_delete(r);
2116
// cache nxdomain for 1 minute
2117
if(q->qtype != JDNS_RTYPE_ANY)
2119
_cache_remove_all_of_kind(s, q->qname, q->qtype);
2120
_cache_add(s, q->qname, q->qtype, now, 60, 0);
2126
int cache_additional;
2129
_cache_remove_all_of_kind(s, q->qname, q->qtype);
2132
cache_additional = 1;
2134
// if truncated, we may not want to cache
2137
cache_additional = 0;
2138
if(!answer_section_ok)
2144
for(n = 0; n < r->answerCount; ++n)
2146
jdns_rr_t *record = r->answerRecords[n];
2147
_cache_add(s, q->qname, record->type, now, _min(record->ttl, JDNS_TTL_MAX), record);
2151
if(cache_additional)
2153
for(n = 0; n < r->additionalCount; ++n)
2155
jdns_rr_t *record = r->additionalRecords[n];
2156
_cache_add(s, record->owner, record->type, now, _min(record->ttl, JDNS_TTL_MAX), record);
2162
// don't pass authority/additional records upwards
2164
jdns_response_remove_extra(r);
2166
// this server returned an error?
2168
query_add_server_failed(q, ns->id);
2170
if(_process_response(s, r, nxdomain, q))
2172
_remove_query_datagrams(s, q);
2173
list_remove(s->queries, q);
2176
jdns_response_delete(r);
2179
int _process_response(jdns_session_t *s, jdns_response_t *r, int nxdomain, query_t *q)
2188
// if not all servers have errored, ignore error
2190
for(k = 0; k < s->name_servers->count; ++k)
2192
name_server_t *ns = (name_server_t *)s->name_servers->item[k];
2193
if(!query_server_failed(q, ns->id))
2202
// report event to any requests listening
2203
for(k = 0; k < q->req_ids_count; ++k)
2205
jdns_event_t *event = jdns_event_new();
2206
event->type = JDNS_EVENT_RESPONSE;
2207
event->id = q->req_ids[k];
2208
event->status = JDNS_STATUS_ERROR;
2209
_append_event(s, event);
2212
// report error to parent
2215
// report event to any requests listening
2216
query_t *cq = q->cname_parent;
2217
for(k = 0; k < cq->req_ids_count; ++k)
2219
jdns_event_t *event = jdns_event_new();
2220
event->type = JDNS_EVENT_RESPONSE;
2221
event->id = cq->req_ids[k];
2222
event->status = JDNS_STATUS_ERROR;
2223
_append_event(s, event);
2225
list_remove(s->queries, cq);
2233
// report event to any requests listening
2234
for(k = 0; k < q->req_ids_count; ++k)
2236
jdns_event_t *event = jdns_event_new();
2237
event->type = JDNS_EVENT_RESPONSE;
2238
event->id = q->req_ids[k];
2239
event->status = JDNS_STATUS_NXDOMAIN;
2240
_append_event(s, event);
2243
// report error to parent
2246
// report event to any requests listening
2247
query_t *cq = q->cname_parent;
2248
for(k = 0; k < cq->req_ids_count; ++k)
2250
jdns_event_t *event = jdns_event_new();
2251
event->type = JDNS_EVENT_RESPONSE;
2252
event->id = cq->req_ids[k];
2253
event->status = JDNS_STATUS_ERROR;
2254
_append_event(s, event);
2256
list_remove(s->queries, cq);
2262
// all we got was a cname that we didn't ask for?
2263
if(r->answerCount == 1 && r->answerRecords[0]->type == JDNS_RTYPE_CNAME && q->qtype != JDNS_RTYPE_CNAME)
2267
_debug_line(s, "all we got was a cname, following the chain ...");
2269
// max chain count, bail
2270
if(q->cname_chain_count >= 16)
2272
// report event to any requests listening
2273
for(k = 0; k < q->req_ids_count; ++k)
2275
jdns_event_t *event = jdns_event_new();
2276
event->type = JDNS_EVENT_RESPONSE;
2277
event->id = q->req_ids[k];
2278
event->status = JDNS_STATUS_ERROR;
2279
_append_event(s, event);
2282
// report error to parent
2285
// report event to any requests listening
2286
query_t *cq = q->cname_parent;
2287
for(k = 0; k < cq->req_ids_count; ++k)
2289
jdns_event_t *event = jdns_event_new();
2290
event->type = JDNS_EVENT_RESPONSE;
2291
event->id = cq->req_ids[k];
2292
event->status = JDNS_STATUS_ERROR;
2293
_append_event(s, event);
2295
list_remove(s->queries, cq);
2301
new_q = _get_query(s, r->answerRecords[0]->data.name, q->qtype, 1);
2304
new_q->cname_chain_count = q->cname_chain_count + 1;
2305
new_q->cname_parent = q->cname_parent;
2306
new_q->cname_parent->cname_child = new_q;
2310
new_q->cname_chain_count = q->cname_chain_count + 1;
2311
new_q->cname_parent = q;
2312
q->cname_child = new_q;
2314
q->dns_id = -1; // don't handle responses
2318
// if this query now has a child, then don't report events or delete
2322
// report event to any requests listening
2323
for(k = 0; k < q->req_ids_count; ++k)
2325
jdns_event_t *event = jdns_event_new();
2326
event->type = JDNS_EVENT_RESPONSE;
2327
event->id = q->req_ids[k];
2328
event->status = JDNS_STATUS_SUCCESS;
2329
event->response = jdns_response_copy(r);
2330
_append_event(s, event);
2336
// report event to any requests listening
2337
query_t *cq = q->cname_parent;
2338
for(k = 0; k < cq->req_ids_count; ++k)
2340
jdns_event_t *event = jdns_event_new();
2341
event->type = JDNS_EVENT_RESPONSE;
2342
event->id = cq->req_ids[k];
2343
event->status = JDNS_STATUS_SUCCESS;
2344
event->response = jdns_response_copy(r);
2345
_append_event(s, event);
2347
list_remove(s->queries, cq);
2353
//----------------------------------------------------------------------------
2355
//----------------------------------------------------------------------------
2356
static jdns_rr_t *_mdnsda2rr(mdnsda a)
2360
if(a->type == JDNS_RTYPE_ANY)
2363
// for AAAA, TXT and HINFO, run the raw rdata through jdns_rr's parser
2364
if(a->type == JDNS_RTYPE_AAAA || a->type == JDNS_RTYPE_TXT || a->type == JDNS_RTYPE_HINFO)
2366
jdns_packet_resource_t *pr = jdns_packet_resource_new();
2367
pr->qname = jdns_string_new();
2368
jdns_string_set_cstr(pr->qname, (const char *)a->name);
2369
pr->qtype = a->type;
2370
pr->qclass = 0x0001; // class is always 1 for us
2374
pr->ttl = a->real_ttl;
2375
pr->rdata = jdns_copy_array(a->rdata, a->rdlen);
2376
pr->rdlength = a->rdlen;
2378
// we don't need a reference for these types
2379
rr = jdns_rr_from_resource(pr, 0);
2381
// else, pull the values out of 'a' directly
2385
rr->owner = _ustrdup(a->name);
2386
rr->qclass = 0x0001; // class is always 1 for us
2390
rr->ttl = a->real_ttl;
2396
jdns_address_t *addr = jdns_address_new();
2397
jdns_address_set_ipv4(addr, a->ip);
2398
jdns_rr_set_A(rr, addr);
2399
jdns_address_delete(addr);
2402
case JDNS_RTYPE_AAAA:
2409
// don't care about MX
2414
case JDNS_RTYPE_SRV:
2416
jdns_rr_set_SRV(rr, a->rdname, a->srv.port, a->srv.priority, a->srv.weight);
2419
case JDNS_RTYPE_CNAME:
2421
jdns_rr_set_CNAME(rr, a->rdname);
2424
case JDNS_RTYPE_PTR:
2426
jdns_rr_set_PTR(rr, a->rdname);
2429
case JDNS_RTYPE_TXT:
2434
case JDNS_RTYPE_HINFO:
2441
// don't care about NS
2448
jdns_rr_set_record(rr, a->type, a->rdata, a->rdlen);
2457
static int _cmp_rdata(const jdns_rr_t *a, const jdns_rr_t *b)
2459
if(a->rdlength != b->rdlength)
2461
if(memcmp(a->rdata, b->rdata, a->rdlength) != 0)
2466
static int _cmp_rr(const jdns_rr_t *a, const jdns_rr_t *b)
2468
if(a->type != b->type)
2470
if(!jdns_domain_cmp(a->owner, b->owner))
2475
if(!jdns_address_cmp(a->data.address, b->data.address))
2478
case JDNS_RTYPE_AAAA:
2479
if(!_cmp_rdata(a, b))
2485
case JDNS_RTYPE_SRV:
2486
if(a->data.server->port != b->data.server->port
2487
|| a->data.server->priority != b->data.server->priority
2488
|| a->data.server->weight != b->data.server->weight
2489
|| !jdns_domain_cmp(a->data.server->name, b->data.server->name)
2493
case JDNS_RTYPE_CNAME:
2494
if(!jdns_domain_cmp(a->data.name, b->data.name))
2497
case JDNS_RTYPE_PTR:
2498
if(!jdns_domain_cmp(a->data.name, b->data.name))
2501
case JDNS_RTYPE_TXT:
2502
if(!_cmp_rdata(a, b))
2505
case JDNS_RTYPE_HINFO:
2506
if(!_cmp_rdata(a, b))
2513
if(!_cmp_rdata(a, b))
2520
int _multicast_query_ans(mdnsda a, void *arg)
2527
jdns_event_t *event;
2529
s = (jdns_session_t *)arg;
2531
// what query is this for?
2533
for(n = 0; n < s->queries->count; ++n)
2535
query_t *i = (query_t *)s->queries->item[n];
2536
if((i->qtype == JDNS_RTYPE_ANY || i->qtype == a->type) && jdns_domain_cmp(i->qname, a->name))
2543
// note: this can't happen, but we'll check anyway
2546
_debug_line(s, "no such multicast query");
2554
// add/remove as a known
2557
for(n = 0; n < q->mul_known->answerCount; ++n)
2559
jdns_rr_t *k = q->mul_known->answerRecords[n];
2562
jdns_response_remove_answer(q->mul_known, n);
2568
jdns_response_append_answer(q->mul_known, rr);
2570
r = jdns_response_new();
2571
jdns_response_append_answer(r, rr);
2574
// report event to any requests listening
2575
for(n = 0; n < q->req_ids_count; ++n)
2577
event = jdns_event_new();
2578
event->type = JDNS_EVENT_RESPONSE;
2579
event->id = q->req_ids[n];
2580
event->status = JDNS_STATUS_SUCCESS;
2581
event->response = jdns_response_copy(r);
2582
_append_event(s, event);
2585
jdns_response_delete(r);
2589
query_t *_get_multicast_query(jdns_session_t *s, const unsigned char *qname, int qtype)
2595
// check for existing queries
2596
for(n = 0; n < s->queries->count; ++n)
2598
q = (query_t *)s->queries->item[n];
2599
if(jdns_domain_cmp(q->qname, qname) && q->qtype == qtype)
2601
str = _make_printable_cstr((const char *)q->qname);
2602
_debug_line(s, "[%d] reusing query for: [%s] [%s]", q->id, _qtype2str(qtype), str->data);
2603
jdns_string_delete(str);
2609
q->id = get_next_qid(s);
2610
q->qname = _ustrdup(qname);
2613
q->mul_known = jdns_response_new();
2614
list_insert(s->queries, q, -1);
2616
str = _make_printable_cstr((const char *)q->qname);
2617
_debug_line(s, "[%d] querying: [%s] [%s]", q->id, _qtype2str(qtype), str->data);
2618
jdns_string_delete(str);
2622
int _multicast_query(jdns_session_t *s, const unsigned char *name, int qtype)
2624
unsigned char *qname;
2629
str = _make_printable_cstr((const char *)name);
2630
_debug_line(s, "query input: [%s]", str->data);
2631
jdns_string_delete(str);
2633
// add a dot to the end if needed
2634
qname = _fix_input(name);
2636
q = _get_multicast_query(s, qname, qtype);
2637
req_id = get_next_req_id(s);
2638
query_add_req_id(q, req_id);
2641
// start the mdnsd_query if necessary
2645
mdnsd_query(s->mdns, (char *)q->qname, q->qtype, _multicast_query_ans, s);
2651
// report the knowns
2652
for(n = 0; n < q->mul_known->answerCount; ++n)
2654
const jdns_rr_t *rr;
2656
jdns_event_t *event;
2658
rr = q->mul_known->answerRecords[n];
2659
r = jdns_response_new();
2660
jdns_response_append_answer(r, rr);
2662
event = jdns_event_new();
2663
event->type = JDNS_EVENT_RESPONSE;
2665
event->status = JDNS_STATUS_SUCCESS;
2666
event->response = r;
2667
_append_event(s, event);
2673
void _multicast_cancel(jdns_session_t *s, int req_id)
2676
for(n = 0; n < s->queries->count; ++n)
2678
query_t *q = (query_t *)s->queries->item[n];
2679
if(query_have_req_id(q, req_id))
2681
query_remove_req_id(q, req_id);
2683
// if no one else is depending on this request, then take action
2684
if(q->req_ids_count == 0)
2686
mdnsd_query(s->mdns, (char *)q->qname, q->qtype, NULL, 0);
2687
list_remove(s->queries, q);
2694
void _multicast_pubresult(int result, char *name, int type, void *arg)
2697
published_item_t *pub;
2698
jdns_event_t *event;
2701
s = (jdns_session_t *)arg;
2703
// find the associated pub item
2705
for(n = 0; n < s->published->count; ++n)
2707
published_item_t *i = (published_item_t *)s->published->item[n];
2708
if(strcmp((char *)i->qname, name) == 0 && i->qtype == type)
2715
// note: this can't happen, but we'll check anyway
2718
_debug_line(s, "no such multicast published item");
2724
jdns_string_t *str = _make_printable_cstr(name);
2725
_debug_line(s, "published name %s for type %d", str->data, type);
2726
jdns_string_delete(str);
2728
event = jdns_event_new();
2729
event->type = JDNS_EVENT_PUBLISH;
2730
event->id = pub->id;
2731
event->status = JDNS_STATUS_SUCCESS;
2732
_append_event(s, event);
2736
jdns_string_t *str = _make_printable_cstr(name);
2737
_debug_line(s, "conflicting name detected %s for type %d", str->data, type);
2738
jdns_string_delete(str);
2740
event = jdns_event_new();
2741
event->type = JDNS_EVENT_PUBLISH;
2742
event->id = pub->id;
2743
event->status = JDNS_STATUS_CONFLICT;
2744
_append_event(s, event);
2747
list_remove(s->published, pub);
2751
static jdns_string_t *_create_text(const jdns_stringlist_t *texts)
2760
for(n = 0; n < texts->count; ++n)
2761
total += texts->item[n]->size + 1;
2765
buf = (unsigned char *)malloc(total);
2766
for(n = 0; n < texts->count; ++n)
2768
unsigned int len = texts->item[n]->size;
2770
memcpy(buf + at, texts->item[n]->data, len);
2775
out = jdns_string_new();
2782
jdns_string_set_cstr(out, "");
2786
static void _publish_applyrr_unknown(jdns_session_t *s, mdnsdr r, const jdns_rr_t *rr)
2788
// for unsupported/unknown, just take the rdata
2789
// note: for this to work, the app must explicitly set the rdata.
2790
// if the record is MX or some other known but unsupported record
2791
// type, setting the known fields is not enough
2792
mdnsd_set_raw(s->mdns, r, (char *)rr->rdata, rr->rdlength);
2795
static int _publish_applyrr(jdns_session_t *s, mdnsdr r, const jdns_rr_t *rr)
2799
_publish_applyrr_unknown(s, r, rr);
2803
// jdns_mdnsd supports: A, AAAA, SRV, CNAME, PTR, TXT, and HINFO
2808
unsigned long int ip_net = htonl(rr->data.address->addr.v4);
2809
mdnsd_set_raw(s->mdns, r, (char *)&ip_net, 4);
2812
case JDNS_RTYPE_AAAA:
2814
mdnsd_set_raw(s->mdns, r, (char *)rr->data.address->addr.v6, 16);
2817
case JDNS_RTYPE_SRV:
2819
mdnsd_set_srv(s->mdns, r, rr->data.server->priority, rr->data.server->weight, rr->data.server->port, (char *)rr->data.server->name);
2822
case JDNS_RTYPE_CNAME:
2824
mdnsd_set_host(s->mdns, r, (char *)rr->data.name);
2827
case JDNS_RTYPE_PTR:
2829
mdnsd_set_host(s->mdns, r, (char *)rr->data.name);
2832
case JDNS_RTYPE_TXT:
2834
jdns_string_t *out = _create_text(rr->data.texts);
2835
mdnsd_set_raw(s->mdns, r, (char *)out->data, out->size);
2836
jdns_string_delete(out);
2839
case JDNS_RTYPE_HINFO:
2842
jdns_stringlist_t *list;
2844
list = jdns_stringlist_new();
2845
jdns_stringlist_append(list, rr->data.hinfo.cpu);
2846
jdns_stringlist_append(list, rr->data.hinfo.os);
2847
out = _create_text(list);
2848
jdns_stringlist_delete(list);
2850
mdnsd_set_raw(s->mdns, r, (char *)out->data, out->size);
2851
jdns_string_delete(out);
2856
_publish_applyrr_unknown(s, r, rr);
2864
static void report_published(jdns_session_t *s, published_item_t *pub)
2866
jdns_event_t *event;
2869
str = _make_printable_cstr((char *)pub->qname);
2870
_debug_line(s, "published name %s for type %d", str->data, pub->qtype);
2871
jdns_string_delete(str);
2873
event = jdns_event_new();
2874
event->type = JDNS_EVENT_PUBLISH;
2875
event->id = pub->id;
2876
event->status = JDNS_STATUS_SUCCESS;
2877
_append_event(s, event);
2880
int _multicast_publish(jdns_session_t *s, int mode, const jdns_rr_t *rr)
2883
published_item_t *pub;
2885
jdns_event_t *event;
2889
next_id = get_next_req_id(s);
2891
// see if we have an item with this name+type combination already
2893
for(n = 0; n < s->published->count; ++n)
2895
published_item_t *i = (published_item_t *)s->published->item[n];
2896
if(i->qtype == rr->type && jdns_domain_cmp(i->qname, rr->owner))
2905
if(!jdns_rr_verify(rr))
2908
if(mode == JDNS_PUBLISH_UNIQUE)
2909
r = mdnsd_unique(s->mdns, (char *)rr->owner, rr->type, rr->ttl, _multicast_pubresult, s);
2911
r = mdnsd_shared(s->mdns, (char *)rr->owner, rr->type, rr->ttl);
2913
if(!_publish_applyrr(s, r, rr))
2916
pub = published_item_new();
2919
pub->qname = _ustrdup(rr->owner);
2920
pub->qtype = rr->type;
2922
pub->rr = jdns_rr_copy(rr);
2923
list_insert(s->published, pub, -1);
2925
// mdnsd doesn't report publish events for shared, so do that here
2926
if(mode == JDNS_PUBLISH_SHARED)
2927
report_published(s, pub);
2932
_debug_line(s, "attempt to publish record, malformed, unsupported, or duplicate type");
2937
mdnsd_done(s->mdns, r);
2940
// send an error to the app
2941
event = jdns_event_new();
2942
event->type = JDNS_EVENT_PUBLISH;
2943
event->id = next_id;
2944
event->status = JDNS_STATUS_ERROR;
2945
_append_event(s, event);
2950
void _multicast_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rr)
2953
published_item_t *pub;
2958
for(n = 0; n < s->published->count; ++n)
2960
published_item_t *i = (published_item_t *)s->published->item[n];
2973
if(!_publish_applyrr(s, r, rr))
2975
_debug_line(s, "attempt to update_publish an unsupported type");
2980
void _multicast_cancel_publish(jdns_session_t *s, int id)
2983
for(n = 0; n < s->published->count; ++n)
2985
published_item_t *i = (published_item_t *)s->published->item[n];
2988
mdnsd_done(s->mdns, i->rec);
2989
list_remove(s->published, i);
2995
void _multicast_flush(jdns_session_t *s)
2999
// to flush, we make like our queries and published items are all new.
3000
// we'll do this by destroying/creating the mdnsd object again (so it
3001
// is fresh) and then reapply all queries and published items to it.
3003
// start over with mdnsd
3004
mdnsd_free(s->mdns);
3005
s->mdns = mdnsd_new(0x0001, 1000, s->port, _callback_time_now, _callback_rand_int, s);
3007
// attempt to publish again
3008
for(n = 0; n < s->published->count; ++n)
3010
published_item_t *i;
3013
i = (published_item_t *)s->published->item[n];
3014
if(i->mode == JDNS_PUBLISH_UNIQUE)
3015
r = mdnsd_unique(s->mdns, (char *)i->rr->owner, i->rr->type, i->rr->ttl, _multicast_pubresult, s);
3017
r = mdnsd_shared(s->mdns, (char *)i->rr->owner, i->rr->type, i->rr->ttl);
3018
_publish_applyrr(s, r, i->rr);
3022
// restore the queries
3023
for(n = 0; n < s->queries->count; ++n)
3025
query_t *q = (query_t *)s->queries->item[n];
3028
mdnsd_query(s->mdns, (char *)q->qname, q->qtype, _multicast_query_ans, s);
3032
int jdns_step_multicast(jdns_session_t *s, int now)
3034
int need_read, need_write, smallest_time;
3035
struct mytimeval *tv;
3036
jdns_packet_t *packet;
3045
if(s->shutdown == 1)
3046
mdnsd_shutdown(s->mdns);
3050
jdns_address_t *addr;
3051
unsigned short int port;
3056
if(!mdnsd_out(s->mdns, &packet, &addr, &port))
3059
if(!s->handle_writable)
3062
jdns_address_delete(addr);
3066
if(!jdns_packet_export(packet, JDNS_UDP_MUL_OUT_MAX))
3068
_debug_line(s, "outgoing packet export error, not sending");
3069
jdns_packet_delete(packet);
3073
buf = packet->raw_data;
3074
buf_len = packet->raw_size;
3079
addr = jdns_address_copy(s->maddr);
3083
_debug_line(s, "SEND %s:%d (size=%d)", addr->c_str, port, buf_len);
3084
_print_hexdump(s, buf, buf_len);
3086
ret = s->cb.udp_write(s, s->cb.app, s->handle, addr, port, buf, buf_len);
3088
jdns_address_delete(addr);
3089
jdns_packet_delete(packet);
3091
// if we can't write the packet, oh well
3094
s->handle_writable = 0;
3100
if(s->shutdown == 1)
3102
jdns_event_t *event = jdns_event_new();
3103
event->type = JDNS_EVENT_SHUTDOWN;
3104
_append_event(s, event);
3109
// let's always ask for reads, just so the user doesn't have to
3110
// worry about what should happen to incoming packets otherwise
3113
if(s->handle_readable)
3117
unsigned char buf[JDNS_UDP_MUL_IN_MAX];
3118
int bufsize = JDNS_UDP_MUL_IN_MAX;
3120
jdns_address_t *addr;
3124
addr = jdns_address_new();
3125
ret = s->cb.udp_read(s, s->cb.app, s->handle, addr, &port, buf, &bufsize);
3130
s->handle_readable = 0;
3131
jdns_address_delete(addr);
3135
_debug_line(s, "RECV %s:%d (size=%d)", addr->c_str, port, bufsize);
3136
_print_hexdump(s, buf, bufsize);
3138
if(!jdns_packet_import(&packet, buf, bufsize))
3140
_debug_line(s, "error parsing packet / too large");
3142
jdns_address_delete(addr);
3146
_print_packet(s, packet);
3148
r = _packet2response(packet, 0, 0, 0x7fff);
3149
_print_records(s, r, 0);
3151
mdnsd_in(s->mdns, packet, r, addr, (unsigned short)port);
3153
jdns_address_delete(addr);
3154
jdns_packet_delete(packet);
3155
jdns_response_delete(r);
3159
tv = mdnsd_sleep(s->mdns);
3160
smallest_time = tv->tv_sec * 1000 + tv->tv_usec / 1000;
3163
if(smallest_time != -1)
3165
flags |= JDNS_STEP_TIMER;
3166
s->next_timer = smallest_time;
3168
// offset it a little bit, so that the user doesn't call
3169
// us too early, resulting in a no-op and another timer
3170
// of 1 millisecond.
3173
if(need_read || need_write)
3174
flags |= JDNS_STEP_HANDLE;