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