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.
31
typedef void (*jdns_object_dtor_func)(void *);
32
typedef void *(*jdns_object_cctor_func)(const void *);
35
jdns_object_dtor_func dtor; \
36
jdns_object_cctor_func cctor;
38
#define JDNS_OBJECT_NEW(name) \
39
(name##_t *)jdns_object_new(sizeof(name##_t), \
40
(jdns_object_dtor_func)name##_delete, \
41
(jdns_object_cctor_func)name##_copy);
43
typedef struct jdns_object
48
void *jdns_object_new(int size, void (*dtor)(void *),
49
void *(*cctor)(const void *));
50
void *jdns_object_copy(const void *a);
51
void jdns_object_delete(void *a);
52
void jdns_object_free(void *a);
54
#define JDNS_LIST_DECLARE(name) \
59
typedef struct jdns_list
68
jdns_list_t *jdns_list_new();
69
jdns_list_t *jdns_list_copy(const jdns_list_t *a);
70
void jdns_list_delete(jdns_list_t *a);
71
void jdns_list_clear(jdns_list_t *a);
72
void jdns_list_insert(jdns_list_t *a, void *item, int pos);
73
void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos);
74
void jdns_list_remove(jdns_list_t *a, void *item);
75
void jdns_list_remove_at(jdns_list_t *a, int pos);
77
typedef struct jdns_string
84
jdns_string_t *jdns_string_new();
85
jdns_string_t *jdns_string_copy(const jdns_string_t *s);
86
void jdns_string_delete(jdns_string_t *s);
87
void jdns_string_set(jdns_string_t *s, const unsigned char *str,
89
void jdns_string_set_cstr(jdns_string_t *s, const char *str);
92
typedef struct jdns_stringlist
99
jdns_stringlist_t *jdns_stringlist_new();
100
jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a);
101
void jdns_stringlist_delete(jdns_stringlist_t *a);
102
void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str);
104
typedef struct jdns_address
109
unsigned long int v4;
110
unsigned char *v6; // 16 bytes
115
jdns_address_t *jdns_address_new();
116
jdns_address_t *jdns_address_copy(const jdns_address_t *a);
117
void jdns_address_delete(jdns_address_t *a);
118
void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4);
119
void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6);
120
// return 1 if string was ok, else 0. Note: IPv4 addresses only!
121
int jdns_address_set_cstr(jdns_address_t *a, const char *str);
122
// return 1 if the same, else 0
123
int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b);
125
// convenient predefined addresses/ports
126
#define JDNS_UNICAST_PORT 53
127
#define JDNS_MULTICAST_PORT 5353
128
jdns_address_t *jdns_address_multicast4_new(); // 224.0.0.251
129
jdns_address_t *jdns_address_multicast6_new(); // FF02::FB
131
typedef struct jdns_server
134
int port; // SRV only
136
int weight; // SRV only
139
jdns_server_t *jdns_server_new();
140
jdns_server_t *jdns_server_copy(const jdns_server_t *s);
141
void jdns_server_delete(jdns_server_t *s);
142
void jdns_server_set_name(jdns_server_t *s, const unsigned char *name);
144
typedef struct jdns_nameserver
146
jdns_address_t *address;
150
jdns_nameserver_t *jdns_nameserver_new();
151
jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a);
152
void jdns_nameserver_delete(jdns_nameserver_t *a);
153
void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr,
156
typedef struct jdns_nameserverlist
159
jdns_nameserver_t **item;
160
} jdns_nameserverlist_t;
162
jdns_nameserverlist_t *jdns_nameserverlist_new();
163
jdns_nameserverlist_t *jdns_nameserverlist_copy(
164
const jdns_nameserverlist_t *a);
165
void jdns_nameserverlist_delete(jdns_nameserverlist_t *a);
166
void jdns_nameserverlist_append(jdns_nameserverlist_t *a,
167
const jdns_address_t *addr, int port);
169
typedef struct jdns_dnshost
172
jdns_address_t *address;
175
typedef struct jdns_dnshostlist
178
jdns_dnshost_t **item;
179
} jdns_dnshostlist_t;
181
typedef struct jdns_dnsparams
183
jdns_nameserverlist_t *nameservers;
184
jdns_stringlist_t *domains;
185
jdns_dnshostlist_t *hosts;
188
jdns_dnsparams_t *jdns_dnsparams_new();
189
jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a);
190
void jdns_dnsparams_delete(jdns_dnsparams_t *a);
191
void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a,
192
const jdns_address_t *addr, int port);
193
void jdns_dnsparams_append_domain(jdns_dnsparams_t *a,
194
const jdns_string_t *domain);
195
void jdns_dnsparams_append_host(jdns_dnsparams_t *a,
196
const jdns_string_t *name, const jdns_address_t *address);
198
#define JDNS_RTYPE_A 1
199
#define JDNS_RTYPE_AAAA 28
200
#define JDNS_RTYPE_MX 15
201
#define JDNS_RTYPE_SRV 33
202
#define JDNS_RTYPE_CNAME 5
203
#define JDNS_RTYPE_PTR 12
204
#define JDNS_RTYPE_TXT 16
205
#define JDNS_RTYPE_HINFO 13
206
#define JDNS_RTYPE_NS 2
207
#define JDNS_RTYPE_ANY 255
209
typedef struct jdns_rr
211
unsigned char *owner;
216
unsigned char *rdata;
221
jdns_address_t *address; // for A, AAAA
222
jdns_server_t *server; // for MX, SRV
223
unsigned char *name; // for CNAME, PTR, NS
224
jdns_stringlist_t *texts; // for TXT
229
} hinfo; // for HINFO
233
jdns_rr_t *jdns_rr_new();
234
jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r);
235
void jdns_rr_delete(jdns_rr_t *r);
236
void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name);
237
void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata,
239
void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address);
240
void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address);
241
void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority);
242
void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port,
243
int priority, int weight);
244
void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name);
245
void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name);
246
void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts);
247
void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu,
248
const jdns_string_t *os);
249
void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name);
250
// note: only works on known types
251
int jdns_rr_verify(const jdns_rr_t *r);
253
typedef struct jdns_response
256
jdns_rr_t **answerRecords;
258
jdns_rr_t **authorityRecords;
260
jdns_rr_t **additionalRecords;
263
jdns_response_t *jdns_response_new();
264
jdns_response_t *jdns_response_copy(const jdns_response_t *r);
265
void jdns_response_delete(jdns_response_t *r);
266
void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr);
267
void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr);
268
void jdns_response_append_additional(jdns_response_t *r,
269
const jdns_rr_t *rr);
271
#define JDNS_PUBLISH_SHARED 0x0001
272
#define JDNS_PUBLISH_UNIQUE 0x0002
274
#define JDNS_STEP_TIMER 0x0001
275
#define JDNS_STEP_HANDLE 0x0002
277
#define JDNS_EVENT_RESPONSE 0x0001
278
#define JDNS_EVENT_PUBLISH 0x0002
279
#define JDNS_EVENT_SHUTDOWN 0x0003
281
#define JDNS_STATUS_SUCCESS 0x0001
282
#define JDNS_STATUS_NXDOMAIN 0x0002
283
#define JDNS_STATUS_ERROR 0x0003
284
#define JDNS_STATUS_TIMEOUT 0x0004
285
#define JDNS_STATUS_CONFLICT 0x0005
287
typedef struct jdns_session jdns_session_t;
289
typedef struct jdns_callbacks
291
void *app; // user-supplied context
295
// app: user-supplied context
296
// return: milliseconds since session started
297
int (*time_now)(jdns_session_t *s, void *app);
301
// app: user-supplied context
302
// return: random integer between 0-65535
303
int (*rand_int)(jdns_session_t *s, void *app);
307
// app: user-supplied context
308
// str: a line of debug text
310
void (*debug_line)(jdns_session_t *s, void *app, const char *str);
314
// app: user-supplied context
315
// addr: ip address of interface to bind to. 0 for all
316
// port: port of interface to bind to. 0 for any
317
// maddr: multicast address. 0 if not using multicast
318
// return: handle (>0) of bound socket, or 0 on error
319
// note: for multicast, the following must be done:
320
// use SO_REUSEPORT to share with other mdns programs
321
// use IP_ADD_MEMBERSHIP to associate addr and maddr
322
// set IP_MULTICAST_TTL to 255
323
int (*udp_bind)(jdns_session_t *s, void *app,
324
const jdns_address_t *addr, int port,
325
const jdns_address_t *maddr);
329
// app: user-supplied context
330
// handle: handle of socket obtained with udp_bind
332
void (*udp_unbind)(jdns_session_t *s, void *app, int handle);
336
// app: user-supplied context
337
// handle: handle of socket obtained with udp_bind
338
// addr: store ip address of sender
339
// port: store port of sender
340
// buf: store packet content
341
// bufsize: value contains max size, to be changed to real size
342
// return: 1 if packet read, 0 if none available
343
int (*udp_read)(jdns_session_t *s, void *app, int handle,
344
jdns_address_t *addr, int *port, unsigned char *buf,
349
// app: user-supplied context
350
// handle: handle of socket obtained with udp_bind
351
// addr: ip address of recipient
352
// port: port of recipient
353
// buf: packet content
354
// bufsize: size of packet
355
// return: 1 if packet taken for writing, 0 if this is a bad time
356
int (*udp_write)(jdns_session_t *s, void *app, int handle,
357
const jdns_address_t *addr, int port, unsigned char *buf,
361
typedef struct jdns_event
363
int type; // JDNS_EVENT
364
int id; // query id or publish id
366
// for query, this can be SUCCESS, NXDOMAIN, ERROR, or TIMEOUT
367
// for publish, this can be SUCCESS, ERROR, or CONFLICT
371
jdns_response_t *response;
374
void jdns_event_delete(jdns_event_t *e);
377
// callbacks: the struct of callbacks
378
// return: newly allocated session
379
jdns_session_t *jdns_session_new(jdns_callbacks_t *callbacks);
381
// jdns_session_delete:
382
// s: session to free
384
void jdns_session_delete(jdns_session_t *s);
386
// jdns_init_unicast:
388
// addr: ip address of interface to bind to. NULL for all
389
// port: port of interface to bind to. 0 for any
390
// return: 1 on success, 0 on failure
391
int jdns_init_unicast(jdns_session_t *s, const jdns_address_t *addr,
394
// jdns_init_multicast:
396
// addr: ip address of interface to bind to. NULL for all
397
// port: port of interface to bind to. 0 for any
398
// addr: multicast address to associate with. cannot be NULL
399
// return: 1 on success, 0 on failure
400
int jdns_init_multicast(jdns_session_t *s, const jdns_address_t *addr,
401
int port, const jdns_address_t *maddr);
406
void jdns_shutdown(jdns_session_t *s);
408
// jdns_set_nameservers:
410
// nslist: list of nameservers
412
void jdns_set_nameservers(jdns_session_t *s,
413
const jdns_nameserverlist_t *nslist);
418
void jdns_probe(jdns_session_t *s);
422
// name: the name to look up
423
// rtype: the record type
424
// return: id of this operation
425
int jdns_query(jdns_session_t *s, const unsigned char *name, int rtype);
427
// jdns_cancel_query:
429
// id: the operation id to cancel
431
void jdns_cancel_query(jdns_session_t *s, int id);
435
// mode: JDNS_PUBLISH shared or unique
436
// rec: the record data
437
// return: id of this operation
438
// note: supported record types: A, AAAA, SRV, CNAME, PTR, TXT, and HINFO.
439
// if the published type is not one of these, raw rdata must be set.
440
int jdns_publish(jdns_session_t *s, int mode, const jdns_rr_t *rec);
442
// jdns_update_publish:
444
// id: the operation id to update
445
// rec: the record data
447
// note: update only works on successfully published records, and no event
448
// is generated for a successful update.
449
void jdns_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rec);
451
// jdns_cancel_publish:
453
// id: the operation id to cancel
455
void jdns_cancel_publish(jdns_session_t *s, int id);
459
// return: JDNS_STEP flags OR'd together
460
int jdns_step(jdns_session_t *s);
464
// return: milliseconds until timeout
465
int jdns_next_timer(jdns_session_t *s);
467
// jdns_set_handle_readable:
469
// handle: handle that is now readable
471
void jdns_set_handle_readable(jdns_session_t *s, int handle);
473
// jdns_set_handle_writable:
475
// handle: handle that is now writable
477
void jdns_set_handle_writable(jdns_session_t *s, int handle);
481
// return: newly allocated event, or zero if none are ready
482
jdns_event_t *jdns_next_event(jdns_session_t *s);
484
// jdns_system_dnsparams:
485
// return: newly allocated dnsparams from the system
486
jdns_dnsparams_t *jdns_system_dnsparams();
488
// jdns_set_hold_ids_enabled
490
// enabled: whether to enable id holding. default is 0 (disabled)
492
// normally, when a unicast query completes or any kind of query or publish
493
// operation results in an error, the operation is automatically "canceled".
494
// when id holding is enabled, the operation still stops internally, but the
495
// id value used by that operation is "held" until the application
496
// explicitly calls jdns_cancel_query() or jdns_cancel_publish() to release
497
// it. this allows the application to ensure there is no ambiguity when
498
// determining which operation a particular event belongs to. it is disabled
499
// be default so as to not introduce memory leaks in existing applications,
500
// however new applications really should use it.
501
void jdns_set_hold_ids_enabled(jdns_session_t *s, int enabled);