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.
27
#include "jdns_export.h"
33
typedef void (*jdns_object_dtor_func)(void *);
34
typedef void *(*jdns_object_cctor_func)(const void *);
37
jdns_object_dtor_func dtor; \
38
jdns_object_cctor_func cctor;
40
#define JDNS_OBJECT_NEW(name) \
41
(name##_t *)jdns_object_new(sizeof(name##_t), \
42
(jdns_object_dtor_func)name##_delete, \
43
(jdns_object_cctor_func)name##_copy);
45
typedef struct jdns_object
50
JDNS_EXPORT void *jdns_object_new(int size, void (*dtor)(void *),
51
void *(*cctor)(const void *));
52
JDNS_EXPORT void *jdns_object_copy(const void *a);
53
JDNS_EXPORT void jdns_object_delete(void *a);
54
JDNS_EXPORT void jdns_object_free(void *a);
56
#define JDNS_LIST_DECLARE(name) \
61
typedef struct jdns_list
70
JDNS_EXPORT jdns_list_t *jdns_list_new();
71
JDNS_EXPORT jdns_list_t *jdns_list_copy(const jdns_list_t *a);
72
JDNS_EXPORT void jdns_list_delete(jdns_list_t *a);
73
JDNS_EXPORT void jdns_list_clear(jdns_list_t *a);
74
JDNS_EXPORT void jdns_list_insert(jdns_list_t *a, void *item, int pos);
75
JDNS_EXPORT void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos);
76
JDNS_EXPORT void jdns_list_remove(jdns_list_t *a, void *item);
77
JDNS_EXPORT void jdns_list_remove_at(jdns_list_t *a, int pos);
79
typedef struct jdns_string
86
JDNS_EXPORT jdns_string_t *jdns_string_new();
87
JDNS_EXPORT jdns_string_t *jdns_string_copy(const jdns_string_t *s);
88
JDNS_EXPORT void jdns_string_delete(jdns_string_t *s);
89
JDNS_EXPORT void jdns_string_set(jdns_string_t *s, const unsigned char *str,
91
JDNS_EXPORT void jdns_string_set_cstr(jdns_string_t *s, const char *str);
94
typedef struct jdns_stringlist
101
JDNS_EXPORT jdns_stringlist_t *jdns_stringlist_new();
102
JDNS_EXPORT jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a);
103
JDNS_EXPORT void jdns_stringlist_delete(jdns_stringlist_t *a);
104
JDNS_EXPORT void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str);
106
typedef struct jdns_address
111
unsigned long int v4;
112
unsigned char *v6; // 16 bytes
117
JDNS_EXPORT jdns_address_t *jdns_address_new();
118
JDNS_EXPORT jdns_address_t *jdns_address_copy(const jdns_address_t *a);
119
JDNS_EXPORT void jdns_address_delete(jdns_address_t *a);
120
JDNS_EXPORT void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4);
121
JDNS_EXPORT void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6);
122
// return 1 if string was ok, else 0. Note: IPv4 addresses only!
123
JDNS_EXPORT int jdns_address_set_cstr(jdns_address_t *a, const char *str);
124
// return 1 if the same, else 0
125
JDNS_EXPORT int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b);
127
// convenient predefined addresses/ports
128
#define JDNS_UNICAST_PORT 53
129
#define JDNS_MULTICAST_PORT 5353
130
JDNS_EXPORT jdns_address_t *jdns_address_multicast4_new(); // 224.0.0.251
131
JDNS_EXPORT jdns_address_t *jdns_address_multicast6_new(); // FF02::FB
133
typedef struct jdns_server
136
int port; // SRV only
138
int weight; // SRV only
141
JDNS_EXPORT jdns_server_t *jdns_server_new();
142
JDNS_EXPORT jdns_server_t *jdns_server_copy(const jdns_server_t *s);
143
JDNS_EXPORT void jdns_server_delete(jdns_server_t *s);
144
JDNS_EXPORT void jdns_server_set_name(jdns_server_t *s, const unsigned char *name);
146
typedef struct jdns_nameserver
148
jdns_address_t *address;
152
JDNS_EXPORT jdns_nameserver_t *jdns_nameserver_new();
153
JDNS_EXPORT jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a);
154
JDNS_EXPORT void jdns_nameserver_delete(jdns_nameserver_t *a);
155
JDNS_EXPORT void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr,
158
typedef struct jdns_nameserverlist
161
jdns_nameserver_t **item;
162
} jdns_nameserverlist_t;
164
JDNS_EXPORT jdns_nameserverlist_t *jdns_nameserverlist_new();
165
JDNS_EXPORT jdns_nameserverlist_t *jdns_nameserverlist_copy(const jdns_nameserverlist_t *a);
166
JDNS_EXPORT void jdns_nameserverlist_delete(jdns_nameserverlist_t *a);
167
JDNS_EXPORT void jdns_nameserverlist_append(jdns_nameserverlist_t *a,
168
const jdns_address_t *addr, int port);
170
typedef struct jdns_dnshost
173
jdns_address_t *address;
176
typedef struct jdns_dnshostlist
179
jdns_dnshost_t **item;
180
} jdns_dnshostlist_t;
182
typedef struct jdns_dnsparams
184
jdns_nameserverlist_t *nameservers;
185
jdns_stringlist_t *domains;
186
jdns_dnshostlist_t *hosts;
189
JDNS_EXPORT jdns_dnsparams_t *jdns_dnsparams_new();
190
JDNS_EXPORT jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a);
191
JDNS_EXPORT void jdns_dnsparams_delete(jdns_dnsparams_t *a);
192
JDNS_EXPORT void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a,
193
const jdns_address_t *addr, int port);
194
JDNS_EXPORT void jdns_dnsparams_append_domain(jdns_dnsparams_t *a,
195
const jdns_string_t *domain);
196
JDNS_EXPORT void jdns_dnsparams_append_host(jdns_dnsparams_t *a,
197
const jdns_string_t *name, const jdns_address_t *address);
199
#define JDNS_RTYPE_A 1
200
#define JDNS_RTYPE_AAAA 28
201
#define JDNS_RTYPE_MX 15
202
#define JDNS_RTYPE_SRV 33
203
#define JDNS_RTYPE_CNAME 5
204
#define JDNS_RTYPE_PTR 12
205
#define JDNS_RTYPE_TXT 16
206
#define JDNS_RTYPE_HINFO 13
207
#define JDNS_RTYPE_NS 2
208
#define JDNS_RTYPE_ANY 255
210
typedef struct jdns_rr
212
unsigned char *owner;
217
unsigned char *rdata;
222
jdns_address_t *address; // for A, AAAA
223
jdns_server_t *server; // for MX, SRV
224
unsigned char *name; // for CNAME, PTR, NS
225
jdns_stringlist_t *texts; // for TXT
230
} hinfo; // for HINFO
234
JDNS_EXPORT jdns_rr_t *jdns_rr_new();
235
JDNS_EXPORT jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r);
236
JDNS_EXPORT void jdns_rr_delete(jdns_rr_t *r);
237
JDNS_EXPORT void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name);
238
JDNS_EXPORT void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata,
240
JDNS_EXPORT void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address);
241
JDNS_EXPORT void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address);
242
JDNS_EXPORT void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority);
243
JDNS_EXPORT void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port,
244
int priority, int weight);
245
JDNS_EXPORT void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name);
246
JDNS_EXPORT void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name);
247
JDNS_EXPORT void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts);
248
JDNS_EXPORT void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu,
249
const jdns_string_t *os);
250
JDNS_EXPORT void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name);
251
// note: only works on known types
252
JDNS_EXPORT int jdns_rr_verify(const jdns_rr_t *r);
254
typedef struct jdns_response
257
jdns_rr_t **answerRecords;
259
jdns_rr_t **authorityRecords;
261
jdns_rr_t **additionalRecords;
264
JDNS_EXPORT jdns_response_t *jdns_response_new();
265
JDNS_EXPORT jdns_response_t *jdns_response_copy(const jdns_response_t *r);
266
JDNS_EXPORT void jdns_response_delete(jdns_response_t *r);
267
JDNS_EXPORT void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr);
268
JDNS_EXPORT void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr);
269
JDNS_EXPORT void jdns_response_append_additional(jdns_response_t *r,
270
const jdns_rr_t *rr);
272
#define JDNS_PUBLISH_SHARED 0x0001
273
#define JDNS_PUBLISH_UNIQUE 0x0002
275
#define JDNS_STEP_TIMER 0x0001
276
#define JDNS_STEP_HANDLE 0x0002
278
#define JDNS_EVENT_RESPONSE 0x0001
279
#define JDNS_EVENT_PUBLISH 0x0002
280
#define JDNS_EVENT_SHUTDOWN 0x0003
282
#define JDNS_STATUS_SUCCESS 0x0001
283
#define JDNS_STATUS_NXDOMAIN 0x0002
284
#define JDNS_STATUS_ERROR 0x0003
285
#define JDNS_STATUS_TIMEOUT 0x0004
286
#define JDNS_STATUS_CONFLICT 0x0005
288
typedef struct jdns_session jdns_session_t;
290
typedef struct jdns_callbacks
292
void *app; // user-supplied context
296
// app: user-supplied context
297
// return: milliseconds since session started
298
int (*time_now)(jdns_session_t *s, void *app);
302
// app: user-supplied context
303
// return: random integer between 0-65535
304
int (*rand_int)(jdns_session_t *s, void *app);
308
// app: user-supplied context
309
// str: a line of debug text
311
void (*debug_line)(jdns_session_t *s, void *app, const char *str);
315
// app: user-supplied context
316
// addr: ip address of interface to bind to. 0 for all
317
// port: port of interface to bind to. 0 for any
318
// maddr: multicast address. 0 if not using multicast
319
// return: handle (>0) of bound socket, or 0 on error
320
// note: for multicast, the following must be done:
321
// use SO_REUSEPORT to share with other mdns programs
322
// use IP_ADD_MEMBERSHIP to associate addr and maddr
323
// set IP_MULTICAST_TTL to 255
324
int (*udp_bind)(jdns_session_t *s, void *app,
325
const jdns_address_t *addr, int port,
326
const jdns_address_t *maddr);
330
// app: user-supplied context
331
// handle: handle of socket obtained with udp_bind
333
void (*udp_unbind)(jdns_session_t *s, void *app, int handle);
337
// app: user-supplied context
338
// handle: handle of socket obtained with udp_bind
339
// addr: store ip address of sender
340
// port: store port of sender
341
// buf: store packet content
342
// bufsize: value contains max size, to be changed to real size
343
// return: 1 if packet read, 0 if none available
344
int (*udp_read)(jdns_session_t *s, void *app, int handle,
345
jdns_address_t *addr, int *port, unsigned char *buf,
350
// app: user-supplied context
351
// handle: handle of socket obtained with udp_bind
352
// addr: ip address of recipient
353
// port: port of recipient
354
// buf: packet content
355
// bufsize: size of packet
356
// return: 1 if packet taken for writing, 0 if this is a bad time
357
int (*udp_write)(jdns_session_t *s, void *app, int handle,
358
const jdns_address_t *addr, int port, unsigned char *buf,
362
typedef struct jdns_event
364
int type; // JDNS_EVENT
365
int id; // query id or publish id
367
// for query, this can be SUCCESS, NXDOMAIN, ERROR, or TIMEOUT
368
// for publish, this can be SUCCESS, ERROR, or CONFLICT
372
jdns_response_t *response;
375
JDNS_EXPORT void jdns_event_delete(jdns_event_t *e);
378
// callbacks: the struct of callbacks
379
// return: newly allocated session
380
JDNS_EXPORT jdns_session_t *jdns_session_new(jdns_callbacks_t *callbacks);
382
// jdns_session_delete:
383
// s: session to free
385
JDNS_EXPORT void jdns_session_delete(jdns_session_t *s);
387
// jdns_init_unicast:
389
// addr: ip address of interface to bind to. NULL for all
390
// port: port of interface to bind to. 0 for any
391
// return: 1 on success, 0 on failure
392
JDNS_EXPORT int jdns_init_unicast(jdns_session_t *s, const jdns_address_t *addr,
395
// jdns_init_multicast:
397
// addr: ip address of interface to bind to. NULL for all
398
// port: port of interface to bind to. 0 for any
399
// addr: multicast address to associate with. cannot be NULL
400
// return: 1 on success, 0 on failure
401
JDNS_EXPORT int jdns_init_multicast(jdns_session_t *s, const jdns_address_t *addr,
402
int port, const jdns_address_t *maddr);
407
JDNS_EXPORT void jdns_shutdown(jdns_session_t *s);
409
// jdns_set_nameservers:
411
// nslist: list of nameservers
413
JDNS_EXPORT void jdns_set_nameservers(jdns_session_t *s,
414
const jdns_nameserverlist_t *nslist);
419
JDNS_EXPORT void jdns_probe(jdns_session_t *s);
423
// name: the name to look up
424
// rtype: the record type
425
// return: id of this operation
426
JDNS_EXPORT int jdns_query(jdns_session_t *s, const unsigned char *name, int rtype);
428
// jdns_cancel_query:
430
// id: the operation id to cancel
432
JDNS_EXPORT void jdns_cancel_query(jdns_session_t *s, int id);
436
// mode: JDNS_PUBLISH shared or unique
437
// rec: the record data
438
// return: id of this operation
439
// note: supported record types: A, AAAA, SRV, CNAME, PTR, TXT, and HINFO.
440
// if the published type is not one of these, raw rdata must be set.
441
JDNS_EXPORT int jdns_publish(jdns_session_t *s, int mode, const jdns_rr_t *rec);
443
// jdns_update_publish:
445
// id: the operation id to update
446
// rec: the record data
448
// note: update only works on successfully published records, and no event
449
// is generated for a successful update.
450
JDNS_EXPORT void jdns_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rec);
452
// jdns_cancel_publish:
454
// id: the operation id to cancel
456
JDNS_EXPORT void jdns_cancel_publish(jdns_session_t *s, int id);
460
// return: JDNS_STEP flags OR'd together
461
JDNS_EXPORT int jdns_step(jdns_session_t *s);
465
// return: milliseconds until timeout
466
JDNS_EXPORT int jdns_next_timer(jdns_session_t *s);
468
// jdns_set_handle_readable:
470
// handle: handle that is now readable
472
JDNS_EXPORT void jdns_set_handle_readable(jdns_session_t *s, int handle);
474
// jdns_set_handle_writable:
476
// handle: handle that is now writable
478
JDNS_EXPORT void jdns_set_handle_writable(jdns_session_t *s, int handle);
482
// return: newly allocated event, or zero if none are ready
483
JDNS_EXPORT jdns_event_t *jdns_next_event(jdns_session_t *s);
485
// jdns_system_dnsparams:
486
// return: newly allocated dnsparams from the system
487
JDNS_EXPORT jdns_dnsparams_t *jdns_system_dnsparams();
489
// jdns_set_hold_ids_enabled
491
// enabled: whether to enable id holding. default is 0 (disabled)
493
// normally, when a unicast query completes or any kind of query or publish
494
// operation results in an error, the operation is automatically "canceled".
495
// when id holding is enabled, the operation still stops internally, but the
496
// id value used by that operation is "held" until the application
497
// explicitly calls jdns_cancel_query() or jdns_cancel_publish() to release
498
// it. this allows the application to ensure there is no ambiguity when
499
// determining which operation a particular event belongs to. it is disabled
500
// be default so as to not introduce memory leaks in existing applications,
501
// however new applications really should use it.
502
JDNS_EXPORT void jdns_set_hold_ids_enabled(jdns_session_t *s, int enabled);