File indexing completed on 2024-05-19 04:06:36
0001 /* 0002 * Copyright (C) 2005,2006 Justin Karneges 0003 * 0004 * Permission is hereby granted, free of charge, to any person obtaining a 0005 * copy of this software and associated documentation files (the 0006 * "Software"), to deal in the Software without restriction, including 0007 * without limitation the rights to use, copy, modify, merge, publish, 0008 * distribute, sublicense, and/or sell copies of the Software, and to 0009 * permit persons to whom the Software is furnished to do so, subject to 0010 * the following conditions: 0011 * 0012 * The above copyright notice and this permission notice shall be included 0013 * in all copies or substantial portions of the Software. 0014 * 0015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 0016 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 0017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 0018 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 0019 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 0020 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 0021 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0022 */ 0023 0024 #ifndef JDNS_H 0025 #define JDNS_H 0026 0027 #ifdef __cplusplus 0028 extern "C" { 0029 #endif 0030 0031 typedef void (*jdns_object_dtor_func)(void *); 0032 typedef void *(*jdns_object_cctor_func)(const void *); 0033 0034 #define JDNS_OBJECT \ 0035 jdns_object_dtor_func dtor; \ 0036 jdns_object_cctor_func cctor; 0037 0038 #define JDNS_OBJECT_NEW(name) \ 0039 (name##_t *)jdns_object_new(sizeof(name##_t), \ 0040 (jdns_object_dtor_func)name##_delete, \ 0041 (jdns_object_cctor_func)name##_copy); 0042 0043 typedef struct jdns_object 0044 { 0045 JDNS_OBJECT 0046 } jdns_object_t; 0047 0048 void *jdns_object_new(int size, void (*dtor)(void *), 0049 void *(*cctor)(const void *)); 0050 void *jdns_object_copy(const void *a); 0051 void jdns_object_delete(void *a); 0052 void jdns_object_free(void *a); 0053 0054 #define JDNS_LIST_DECLARE(name) \ 0055 JDNS_OBJECT \ 0056 int count; \ 0057 name##_t **item; 0058 0059 typedef struct jdns_list 0060 { 0061 JDNS_OBJECT 0062 int count; 0063 void **item; 0064 int valueList; 0065 int autoDelete; 0066 } jdns_list_t; 0067 0068 jdns_list_t *jdns_list_new(); 0069 jdns_list_t *jdns_list_copy(const jdns_list_t *a); 0070 void jdns_list_delete(jdns_list_t *a); 0071 void jdns_list_clear(jdns_list_t *a); 0072 void jdns_list_insert(jdns_list_t *a, void *item, int pos); 0073 void jdns_list_insert_value(jdns_list_t *a, const void *item, int pos); 0074 void jdns_list_remove(jdns_list_t *a, void *item); 0075 void jdns_list_remove_at(jdns_list_t *a, int pos); 0076 0077 typedef struct jdns_string 0078 { 0079 JDNS_OBJECT 0080 unsigned char *data; 0081 int size; 0082 } jdns_string_t; 0083 0084 jdns_string_t *jdns_string_new(); 0085 jdns_string_t *jdns_string_copy(const jdns_string_t *s); 0086 void jdns_string_delete(jdns_string_t *s); 0087 void jdns_string_set(jdns_string_t *s, const unsigned char *str, 0088 int str_len); 0089 void jdns_string_set_cstr(jdns_string_t *s, const char *str); 0090 0091 /* overlays jdns_list */ 0092 typedef struct jdns_stringlist 0093 { 0094 JDNS_OBJECT 0095 int count; 0096 jdns_string_t **item; 0097 } jdns_stringlist_t; 0098 0099 jdns_stringlist_t *jdns_stringlist_new(); 0100 jdns_stringlist_t *jdns_stringlist_copy(const jdns_stringlist_t *a); 0101 void jdns_stringlist_delete(jdns_stringlist_t *a); 0102 void jdns_stringlist_append(jdns_stringlist_t *a, const jdns_string_t *str); 0103 0104 typedef struct jdns_address 0105 { 0106 int isIpv6; 0107 union 0108 { 0109 unsigned long int v4; 0110 unsigned char *v6; /* 16 bytes */ 0111 } addr; 0112 char *c_str; 0113 } jdns_address_t; 0114 0115 jdns_address_t *jdns_address_new(); 0116 jdns_address_t *jdns_address_copy(const jdns_address_t *a); 0117 void jdns_address_delete(jdns_address_t *a); 0118 void jdns_address_set_ipv4(jdns_address_t *a, unsigned long int ipv4); 0119 void jdns_address_set_ipv6(jdns_address_t *a, const unsigned char *ipv6); 0120 /* return 1 if string was ok, else 0. Note: IPv4 addresses only! */ 0121 int jdns_address_set_cstr(jdns_address_t *a, const char *str); 0122 /* return 1 if the same, else 0 */ 0123 int jdns_address_cmp(const jdns_address_t *a, const jdns_address_t *b); 0124 0125 /* convenient predefined addresses/ports */ 0126 #define JDNS_UNICAST_PORT 53 0127 #define JDNS_MULTICAST_PORT 5353 0128 jdns_address_t *jdns_address_multicast4_new(); /* 224.0.0.251 */ 0129 jdns_address_t *jdns_address_multicast6_new(); /* FF02::FB */ 0130 0131 typedef struct jdns_server 0132 { 0133 unsigned char *name; 0134 int port; /* SRV only */ 0135 int priority; 0136 int weight; /* SRV only */ 0137 } jdns_server_t; 0138 0139 jdns_server_t *jdns_server_new(); 0140 jdns_server_t *jdns_server_copy(const jdns_server_t *s); 0141 void jdns_server_delete(jdns_server_t *s); 0142 void jdns_server_set_name(jdns_server_t *s, const unsigned char *name); 0143 0144 typedef struct jdns_nameserver 0145 { 0146 jdns_address_t *address; 0147 int port; 0148 } jdns_nameserver_t; 0149 0150 jdns_nameserver_t *jdns_nameserver_new(); 0151 jdns_nameserver_t *jdns_nameserver_copy(const jdns_nameserver_t *a); 0152 void jdns_nameserver_delete(jdns_nameserver_t *a); 0153 void jdns_nameserver_set(jdns_nameserver_t *a, const jdns_address_t *addr, 0154 int port); 0155 0156 typedef struct jdns_nameserverlist 0157 { 0158 int count; 0159 jdns_nameserver_t **item; 0160 } jdns_nameserverlist_t; 0161 0162 jdns_nameserverlist_t *jdns_nameserverlist_new(); 0163 jdns_nameserverlist_t *jdns_nameserverlist_copy( 0164 const jdns_nameserverlist_t *a); 0165 void jdns_nameserverlist_delete(jdns_nameserverlist_t *a); 0166 void jdns_nameserverlist_append(jdns_nameserverlist_t *a, 0167 const jdns_address_t *addr, int port); 0168 0169 typedef struct jdns_dnshost 0170 { 0171 jdns_string_t *name; 0172 jdns_address_t *address; 0173 } jdns_dnshost_t; 0174 0175 typedef struct jdns_dnshostlist 0176 { 0177 int count; 0178 jdns_dnshost_t **item; 0179 } jdns_dnshostlist_t; 0180 0181 typedef struct jdns_dnsparams 0182 { 0183 jdns_nameserverlist_t *nameservers; 0184 jdns_stringlist_t *domains; 0185 jdns_dnshostlist_t *hosts; 0186 } jdns_dnsparams_t; 0187 0188 jdns_dnsparams_t *jdns_dnsparams_new(); 0189 jdns_dnsparams_t *jdns_dnsparams_copy(jdns_dnsparams_t *a); 0190 void jdns_dnsparams_delete(jdns_dnsparams_t *a); 0191 void jdns_dnsparams_append_nameserver(jdns_dnsparams_t *a, 0192 const jdns_address_t *addr, int port); 0193 void jdns_dnsparams_append_domain(jdns_dnsparams_t *a, 0194 const jdns_string_t *domain); 0195 void jdns_dnsparams_append_host(jdns_dnsparams_t *a, 0196 const jdns_string_t *name, const jdns_address_t *address); 0197 0198 #define JDNS_RTYPE_A 1 0199 #define JDNS_RTYPE_AAAA 28 0200 #define JDNS_RTYPE_MX 15 0201 #define JDNS_RTYPE_SRV 33 0202 #define JDNS_RTYPE_CNAME 5 0203 #define JDNS_RTYPE_PTR 12 0204 #define JDNS_RTYPE_TXT 16 0205 #define JDNS_RTYPE_HINFO 13 0206 #define JDNS_RTYPE_NS 2 0207 #define JDNS_RTYPE_ANY 255 0208 0209 typedef struct jdns_rr 0210 { 0211 unsigned char *owner; 0212 int ttl; 0213 int type; 0214 int qclass; 0215 int rdlength; 0216 unsigned char *rdata; 0217 int haveKnown; 0218 0219 union 0220 { 0221 jdns_address_t *address; /* for A, AAAA */ 0222 jdns_server_t *server; /* for MX, SRV */ 0223 unsigned char *name; /* for CNAME, PTR, NS */ 0224 jdns_stringlist_t *texts; /* for TXT */ 0225 struct 0226 { 0227 jdns_string_t *cpu; 0228 jdns_string_t *os; 0229 } hinfo; /* for HINFO */ 0230 } data; 0231 } jdns_rr_t; 0232 0233 jdns_rr_t *jdns_rr_new(); 0234 jdns_rr_t *jdns_rr_copy(const jdns_rr_t *r); 0235 void jdns_rr_delete(jdns_rr_t *r); 0236 void jdns_rr_set_owner(jdns_rr_t *r, const unsigned char *name); 0237 void jdns_rr_set_record(jdns_rr_t *r, int type, const unsigned char *rdata, 0238 int rdlength); 0239 void jdns_rr_set_A(jdns_rr_t *r, const jdns_address_t *address); 0240 void jdns_rr_set_AAAA(jdns_rr_t *r, const jdns_address_t *address); 0241 void jdns_rr_set_MX(jdns_rr_t *r, const unsigned char *name, int priority); 0242 void jdns_rr_set_SRV(jdns_rr_t *r, const unsigned char *name, int port, 0243 int priority, int weight); 0244 void jdns_rr_set_CNAME(jdns_rr_t *r, const unsigned char *name); 0245 void jdns_rr_set_PTR(jdns_rr_t *r, const unsigned char *name); 0246 void jdns_rr_set_TXT(jdns_rr_t *r, const jdns_stringlist_t *texts); 0247 void jdns_rr_set_HINFO(jdns_rr_t *r, const jdns_string_t *cpu, 0248 const jdns_string_t *os); 0249 void jdns_rr_set_NS(jdns_rr_t *r, const unsigned char *name); 0250 /* note: only works on known types */ 0251 int jdns_rr_verify(const jdns_rr_t *r); 0252 0253 typedef struct jdns_response 0254 { 0255 int answerCount; 0256 jdns_rr_t **answerRecords; 0257 int authorityCount; 0258 jdns_rr_t **authorityRecords; 0259 int additionalCount; 0260 jdns_rr_t **additionalRecords; 0261 } jdns_response_t; 0262 0263 jdns_response_t *jdns_response_new(); 0264 jdns_response_t *jdns_response_copy(const jdns_response_t *r); 0265 void jdns_response_delete(jdns_response_t *r); 0266 void jdns_response_append_answer(jdns_response_t *r, const jdns_rr_t *rr); 0267 void jdns_response_append_authority(jdns_response_t *r, const jdns_rr_t *rr); 0268 void jdns_response_append_additional(jdns_response_t *r, 0269 const jdns_rr_t *rr); 0270 0271 #define JDNS_PUBLISH_SHARED 0x0001 0272 #define JDNS_PUBLISH_UNIQUE 0x0002 0273 0274 #define JDNS_STEP_TIMER 0x0001 0275 #define JDNS_STEP_HANDLE 0x0002 0276 0277 #define JDNS_EVENT_RESPONSE 0x0001 0278 #define JDNS_EVENT_PUBLISH 0x0002 0279 #define JDNS_EVENT_SHUTDOWN 0x0003 0280 0281 #define JDNS_STATUS_SUCCESS 0x0001 0282 #define JDNS_STATUS_NXDOMAIN 0x0002 0283 #define JDNS_STATUS_ERROR 0x0003 0284 #define JDNS_STATUS_TIMEOUT 0x0004 0285 #define JDNS_STATUS_CONFLICT 0x0005 0286 0287 typedef struct jdns_session jdns_session_t; 0288 0289 typedef struct jdns_callbacks 0290 { 0291 void *app; /* user-supplied context*/ 0292 0293 /* time_now: 0294 s: session 0295 app: user-supplied context 0296 return: milliseconds since session started */ 0297 int (*time_now)(jdns_session_t *s, void *app); 0298 0299 /* rand_int: 0300 s: session 0301 app: user-supplied context 0302 return: random integer between 0-65535 */ 0303 int (*rand_int)(jdns_session_t *s, void *app); 0304 0305 /* debug_line: 0306 s: session 0307 app: user-supplied context 0308 str: a line of debug text 0309 return: nothing */ 0310 void (*debug_line)(jdns_session_t *s, void *app, const char *str); 0311 0312 /* udp_bind: 0313 s: session 0314 app: user-supplied context 0315 addr: ip address of interface to bind to. 0 for all 0316 port: port of interface to bind to. 0 for any 0317 maddr: multicast address. 0 if not using multicast 0318 return: handle (>0) of bound socket, or 0 on error 0319 note: for multicast, the following must be done: 0320 use SO_REUSEPORT to share with other mdns programs 0321 use IP_ADD_MEMBERSHIP to associate addr and maddr 0322 set IP_MULTICAST_TTL to 255 */ 0323 int (*udp_bind)(jdns_session_t *s, void *app, 0324 const jdns_address_t *addr, int port, 0325 const jdns_address_t *maddr); 0326 0327 /* udp_unbind: 0328 s: session 0329 app: user-supplied context 0330 handle: handle of socket obtained with udp_bind 0331 return: nothing */ 0332 void (*udp_unbind)(jdns_session_t *s, void *app, int handle); 0333 0334 /* udp_read: 0335 s: session 0336 app: user-supplied context 0337 handle: handle of socket obtained with udp_bind 0338 addr: store ip address of sender 0339 port: store port of sender 0340 buf: store packet content 0341 bufsize: value contains max size, to be changed to real size 0342 return: 1 if packet read, 0 if none available */ 0343 int (*udp_read)(jdns_session_t *s, void *app, int handle, 0344 jdns_address_t *addr, int *port, unsigned char *buf, 0345 int *bufsize); 0346 0347 /* udp_write: 0348 s: session 0349 app: user-supplied context 0350 handle: handle of socket obtained with udp_bind 0351 addr: ip address of recipient 0352 port: port of recipient 0353 buf: packet content 0354 bufsize: size of packet 0355 return: 1 if packet taken for writing, 0 if this is a bad time */ 0356 int (*udp_write)(jdns_session_t *s, void *app, int handle, 0357 const jdns_address_t *addr, int port, unsigned char *buf, 0358 int bufsize); 0359 } jdns_callbacks_t; 0360 0361 typedef struct jdns_event 0362 { 0363 int type; /* JDNS_EVENT */ 0364 int id; /* query id or publish id */ 0365 0366 /* for query, this can be SUCCESS, NXDOMAIN, ERROR, or TIMEOUT 0367 for publish, this can be SUCCESS, ERROR, or CONFLICT */ 0368 int status; 0369 0370 /* for query */ 0371 jdns_response_t *response; 0372 } jdns_event_t; 0373 0374 void jdns_event_delete(jdns_event_t *e); 0375 0376 /* jdns_session_new: 0377 callbacks: the struct of callbacks 0378 return: newly allocated session */ 0379 jdns_session_t *jdns_session_new(jdns_callbacks_t *callbacks); 0380 0381 /* jdns_session_delete: 0382 s: session to free 0383 return: nothing */ 0384 void jdns_session_delete(jdns_session_t *s); 0385 0386 /* jdns_init_unicast: 0387 s: session 0388 addr: ip address of interface to bind to. NULL for all 0389 port: port of interface to bind to. 0 for any 0390 return: 1 on success, 0 on failure */ 0391 int jdns_init_unicast(jdns_session_t *s, const jdns_address_t *addr, 0392 int port); 0393 0394 /* jdns_init_multicast: 0395 s: session 0396 addr: ip address of interface to bind to. NULL for all 0397 port: port of interface to bind to. 0 for any 0398 addr: multicast address to associate with. cannot be NULL 0399 return: 1 on success, 0 on failure */ 0400 int jdns_init_multicast(jdns_session_t *s, const jdns_address_t *addr, 0401 int port, const jdns_address_t *maddr); 0402 0403 /* jdns_shutdown: 0404 s: session 0405 return: nothing */ 0406 void jdns_shutdown(jdns_session_t *s); 0407 0408 /* jdns_set_nameservers: 0409 s: session 0410 nslist: list of nameservers 0411 return nothing */ 0412 void jdns_set_nameservers(jdns_session_t *s, 0413 const jdns_nameserverlist_t *nslist); 0414 0415 /* jdns_probe: 0416 s: session 0417 return: nothing */ 0418 void jdns_probe(jdns_session_t *s); 0419 0420 /* jdns_query: 0421 s: session 0422 name: the name to look up 0423 rtype: the record type 0424 return: id of this operation */ 0425 int jdns_query(jdns_session_t *s, const unsigned char *name, int rtype); 0426 0427 /* jdns_cancel_query: 0428 s: session 0429 id: the operation id to cancel 0430 return: nothing */ 0431 void jdns_cancel_query(jdns_session_t *s, int id); 0432 0433 /* jdns_publish: 0434 s: session 0435 mode: JDNS_PUBLISH shared or unique 0436 rec: the record data 0437 return: id of this operation 0438 note: supported record types: A, AAAA, SRV, CNAME, PTR, TXT, and HINFO. 0439 if the published type is not one of these, raw rdata must be set. */ 0440 int jdns_publish(jdns_session_t *s, int mode, const jdns_rr_t *rec); 0441 0442 /* jdns_update_publish: 0443 s: session 0444 id: the operation id to update 0445 rec: the record data 0446 return: nothing 0447 note: update only works on successfully published records, and no event 0448 is generated for a successful update. */ 0449 void jdns_update_publish(jdns_session_t *s, int id, const jdns_rr_t *rec); 0450 0451 /* jdns_cancel_publish: 0452 s: session 0453 id: the operation id to cancel 0454 return: nothing */ 0455 void jdns_cancel_publish(jdns_session_t *s, int id); 0456 0457 /* jdns_step: 0458 s: session 0459 return: JDNS_STEP flags OR'd together */ 0460 int jdns_step(jdns_session_t *s); 0461 0462 /* jdns_next_timer: 0463 s: session 0464 return: milliseconds until timeout */ 0465 int jdns_next_timer(jdns_session_t *s); 0466 0467 /* jdns_set_handle_readable: 0468 s: session 0469 handle: handle that is now readable 0470 return: nothing */ 0471 void jdns_set_handle_readable(jdns_session_t *s, int handle); 0472 0473 /* jdns_set_handle_writable: 0474 s: session 0475 handle: handle that is now writable 0476 return: nothing */ 0477 void jdns_set_handle_writable(jdns_session_t *s, int handle); 0478 0479 /* jdns_next_event: 0480 s: session 0481 return: newly allocated event, or zero if none are ready */ 0482 jdns_event_t *jdns_next_event(jdns_session_t *s); 0483 0484 /* jdns_system_dnsparams: 0485 return: newly allocated dnsparams from the system */ 0486 jdns_dnsparams_t *jdns_system_dnsparams(); 0487 0488 /* jdns_set_hold_ids_enabled 0489 s: session 0490 enabled: whether to enable id holding. default is 0 (disabled) 0491 return: nothing 0492 normally, when a unicast query completes or any kind of query or publish 0493 operation results in an error, the operation is automatically "canceled". 0494 when id holding is enabled, the operation still stops internally, but the 0495 id value used by that operation is "held" until the application 0496 explicitly calls jdns_cancel_query() or jdns_cancel_publish() to release 0497 it. this allows the application to ensure there is no ambiguity when 0498 determining which operation a particular event belongs to. it is disabled 0499 be default so as to not introduce memory leaks in existing applications, 0500 however new applications really should use it. */ 0501 void jdns_set_hold_ids_enabled(jdns_session_t *s, int enabled); 0502 0503 #ifdef __cplusplus 0504 } 0505 #endif 0506 0507 #endif