You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

rdns.h 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * Copyright (c) 2013-2014, Vsevolod Stakhov
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  16. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  18. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  19. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  21. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  23. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #ifndef RDNS_H
  26. #define RDNS_H
  27. #include <sys/types.h>
  28. #include <stddef.h>
  29. #include <stdint.h>
  30. #include <stdbool.h>
  31. #include <stdarg.h>
  32. #include <netinet/in.h>
  33. #include <arpa/inet.h>
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. struct rdns_reply;
  38. struct rdns_request;
  39. struct rdns_io_channel;
  40. typedef void (*dns_callback_type) (struct rdns_reply *reply, void *arg);
  41. enum rdns_request_type {
  42. RDNS_REQUEST_INVALID = -1,
  43. RDNS_REQUEST_A = 1,
  44. RDNS_REQUEST_NS = 2,
  45. RDNS_REQUEST_CNAME = 5,
  46. RDNS_REQUEST_SOA = 6,
  47. RDNS_REQUEST_PTR = 12,
  48. RDNS_REQUEST_MX = 15,
  49. RDNS_REQUEST_TXT = 16,
  50. RDNS_REQUEST_SRV = 33,
  51. RDNS_REQUEST_SPF = 99,
  52. RDNS_REQUEST_AAAA = 28,
  53. RDNS_REQUEST_TLSA = 52,
  54. RDNS_REQUEST_ANY = 255
  55. };
  56. union rdns_reply_element_un {
  57. struct {
  58. struct in_addr addr;
  59. } a;
  60. struct {
  61. struct in6_addr addr;
  62. } aaa;
  63. struct {
  64. char *name;
  65. } ptr;
  66. struct {
  67. char *name;
  68. } ns;
  69. struct {
  70. char *name;
  71. uint16_t priority;
  72. } mx;
  73. struct {
  74. char *data;
  75. } txt;
  76. struct {
  77. uint16_t priority;
  78. uint16_t weight;
  79. uint16_t port;
  80. char *target;
  81. } srv;
  82. struct {
  83. char *mname;
  84. char *admin;
  85. uint32_t serial;
  86. int32_t refresh;
  87. int32_t retry;
  88. int32_t expire;
  89. uint32_t minimum;
  90. } soa;
  91. struct {
  92. uint8_t usage;
  93. uint8_t selector;
  94. uint8_t match_type;
  95. uint16_t datalen;
  96. uint8_t *data;
  97. } tlsa;
  98. struct {
  99. char *name;
  100. } cname;
  101. };
  102. struct rdns_reply_entry {
  103. union rdns_reply_element_un content;
  104. enum rdns_request_type type;
  105. int32_t ttl;
  106. struct rdns_reply_entry *prev, *next;
  107. };
  108. enum dns_rcode {
  109. RDNS_RC_INVALID = -1,
  110. RDNS_RC_NOERROR = 0,
  111. RDNS_RC_FORMERR = 1,
  112. RDNS_RC_SERVFAIL = 2,
  113. RDNS_RC_NXDOMAIN = 3,
  114. RDNS_RC_NOTIMP = 4,
  115. RDNS_RC_REFUSED = 5,
  116. RDNS_RC_YXDOMAIN = 6,
  117. RDNS_RC_YXRRSET = 7,
  118. RDNS_RC_NXRRSET = 8,
  119. RDNS_RC_NOTAUTH = 9,
  120. RDNS_RC_NOTZONE = 10,
  121. RDNS_RC_TIMEOUT = 11,
  122. RDNS_RC_NETERR = 12,
  123. RDNS_RC_NOREC = 13
  124. };
  125. enum dns_reply_flags {
  126. RDNS_AUTH = (1u << 0u),
  127. RDNS_TRUNCATED = (1u << 1u)
  128. };
  129. struct rdns_reply {
  130. struct rdns_request *request;
  131. struct rdns_resolver *resolver;
  132. struct rdns_reply_entry *entries;
  133. const char *requested_name;
  134. enum dns_rcode code;
  135. uint8_t flags; /* see enum dns_reply_flags */
  136. };
  137. typedef void (*rdns_periodic_callback)(void *user_data);
  138. struct rdns_async_context {
  139. void *data;
  140. void* (*add_read)(void *priv_data, int fd, void *user_data);
  141. void (*del_read)(void *priv_data, void *ev_data);
  142. void* (*add_write)(void *priv_data, int fd, void *user_data);
  143. void (*del_write)(void *priv_data, void *ev_data);
  144. void* (*add_timer)(void *priv_data, double after, void *user_data);
  145. void (*repeat_timer)(void *priv_data, void *ev_data);
  146. void (*del_timer)(void *priv_data, void *ev_data);
  147. void* (*add_periodic)(void *priv_data, double after,
  148. rdns_periodic_callback cb, void *user_data);
  149. void (*del_periodic)(void *priv_data, void *ev_data);
  150. void (*cleanup)(void *priv_data);
  151. };
  152. struct rdns_upstream_elt {
  153. void *server;
  154. void *lib_data;
  155. };
  156. struct rdns_upstream_context {
  157. void *data;
  158. struct rdns_upstream_elt* (*select)(const char *name,
  159. size_t len, void *ups_data);
  160. struct rdns_upstream_elt* (*select_retransmit)(const char *name, size_t len,
  161. struct rdns_upstream_elt* prev_elt,
  162. void *ups_data);
  163. unsigned int (*count)(void *ups_data);
  164. void (*ok)(struct rdns_upstream_elt *elt, void *ups_data);
  165. void (*fail)(struct rdns_upstream_elt *elt, void *ups_data, const char *reason);
  166. };
  167. /**
  168. * Type of rdns plugin
  169. */
  170. enum rdns_plugin_type {
  171. RDNS_PLUGIN_CURVE = 0
  172. };
  173. typedef ssize_t (*rdns_network_send_callback) (struct rdns_request *req, void *plugin_data,
  174. struct sockaddr *saddr, socklen_t slen);
  175. typedef ssize_t (*rdns_network_recv_callback) (struct rdns_io_channel *ioc, void *buf,
  176. size_t len, void *plugin_data,
  177. struct rdns_request **req_out,
  178. struct sockaddr *saddr, socklen_t slen);
  179. typedef void (*rdns_network_finish_callback) (struct rdns_request *req, void *plugin_data);
  180. typedef void (*rdns_plugin_dtor_callback) (struct rdns_resolver *resolver, void *plugin_data);
  181. struct rdns_plugin {
  182. enum rdns_plugin_type type;
  183. union {
  184. struct {
  185. rdns_network_send_callback send_cb;
  186. rdns_network_recv_callback recv_cb;
  187. rdns_network_finish_callback finish_cb;
  188. } curve_plugin;
  189. } cb;
  190. rdns_plugin_dtor_callback dtor;
  191. void *data;
  192. };
  193. /*
  194. * RDNS logger types
  195. */
  196. /*
  197. * These types are somehow compatible with glib
  198. */
  199. enum rdns_log_level {
  200. RDNS_LOG_ERROR = 1 << 3,
  201. RDNS_LOG_WARNING = 1 << 4,
  202. RDNS_LOG_INFO = 1 << 6,
  203. RDNS_LOG_DEBUG = 1 << 7
  204. };
  205. typedef void (*rdns_log_function) (
  206. void *log_data, //!< opaque data pointer
  207. enum rdns_log_level level, //!< level of message
  208. const char *function, //!< calling function
  209. const char *format, //!< format
  210. va_list args //!< set of arguments
  211. );
  212. struct rdns_request_name {
  213. char *name;
  214. enum rdns_request_type type;
  215. unsigned int len;
  216. };
  217. #define MAX_FAKE_NAME 1000
  218. /*
  219. * RDNS API
  220. */
  221. enum rdns_resolver_flags {
  222. RDNS_RESOLVER_DEFAULT,
  223. RDNS_RESOLVER_NOIDN = (1u << 0u),
  224. };
  225. /**
  226. * Create DNS resolver structure
  227. */
  228. struct rdns_resolver *rdns_resolver_new (int flags);
  229. /**
  230. * Bind resolver to specified async context
  231. * @param ctx
  232. */
  233. void rdns_resolver_async_bind (struct rdns_resolver *resolver,
  234. struct rdns_async_context *ctx);
  235. /**
  236. * Enable stub dnssec resolver
  237. * @param resolver
  238. */
  239. void rdns_resolver_set_dnssec (struct rdns_resolver *resolver, bool enabled);
  240. /**
  241. * Add new DNS server definition to the resolver
  242. * @param resolver resolver object
  243. * @param name name of DNS server (should be ipv4 or ipv6 address)
  244. * @param priority priority (can be 0 for fair round-robin)
  245. * @param io_cnt a number of sockets that are simultaneously opened to this server
  246. * @return opaque pointer that could be used to select upstream
  247. */
  248. void* rdns_resolver_add_server (struct rdns_resolver *resolver,
  249. const char *name, unsigned int port,
  250. int priority, unsigned int io_cnt);
  251. /**
  252. * Load nameservers definition from resolv.conf file
  253. * @param resolver resolver object
  254. * @param path path to resolv.conf file (/etc/resolv.conf typically)
  255. * @return true if resolv.conf has been parsed
  256. */
  257. bool rdns_resolver_parse_resolv_conf (struct rdns_resolver *resolver,
  258. const char *path);
  259. typedef bool (*rdns_resolv_conf_cb) (struct rdns_resolver *resolver,
  260. const char *name, unsigned int port,
  261. int priority, unsigned int io_cnt, void *ud);
  262. /**
  263. * Parse nameservers calling the specified callback for each nameserver
  264. * @param resolve resolver object
  265. * @param path path to resolv.conf file (/etc/resolv.conf typically)
  266. * @param cb callback to call
  267. * @param ud userdata for callback
  268. * @return true if resolv.conf has been parsed
  269. */
  270. bool rdns_resolver_parse_resolv_conf_cb (struct rdns_resolver *resolver,
  271. const char *path, rdns_resolv_conf_cb cb, void *ud);
  272. /**
  273. * Set an external logger function to log messages from the resolver
  274. * @param resolver resolver object
  275. * @param logger logger callback
  276. * @param log_data opaque data
  277. */
  278. void rdns_resolver_set_logger (struct rdns_resolver *resolver,
  279. rdns_log_function logger, void *log_data);
  280. /**
  281. * Set log level for an internal logger (stderr one)
  282. * @param resolver resolver object
  283. * @param level desired log level
  284. */
  285. void rdns_resolver_set_log_level (struct rdns_resolver *resolver,
  286. enum rdns_log_level level);
  287. /**
  288. * Set upstream library for selecting DNS upstreams
  289. * @param resolver resolver object
  290. * @param ups_ctx upstream functions
  291. * @param ups_data opaque data
  292. */
  293. void rdns_resolver_set_upstream_lib (struct rdns_resolver *resolver,
  294. struct rdns_upstream_context *ups_ctx,
  295. void *ups_data);
  296. /**
  297. * Set maximum number of dns requests to be sent to a socket to be refreshed
  298. * @param resolver resolver object
  299. * @param max_ioc_uses unsigned count of socket usage limit
  300. * @param check_time specifies how often to check for sockets and refresh them
  301. */
  302. void rdns_resolver_set_max_io_uses (struct rdns_resolver *resolver,
  303. uint64_t max_ioc_uses, double check_time);
  304. /**
  305. * Register new plugin for rdns resolver
  306. * @param resolver
  307. * @param plugin
  308. */
  309. void rdns_resolver_register_plugin (struct rdns_resolver *resolver,
  310. struct rdns_plugin *plugin);
  311. /**
  312. * Add a fake reply for a specified name
  313. * @param resolver
  314. * @param type
  315. * @param name (must not be larger than MAX_FAKE_NAME)
  316. * @param reply
  317. */
  318. void rdns_resolver_set_fake_reply (struct rdns_resolver *resolver,
  319. const char *name,
  320. enum rdns_request_type type,
  321. enum dns_rcode rcode,
  322. struct rdns_reply_entry *reply);
  323. /**
  324. * Init DNS resolver
  325. * @param resolver
  326. * @return
  327. */
  328. bool rdns_resolver_init (struct rdns_resolver *resolver);
  329. /**
  330. * Decrease refcount for a resolver and free it if refcount is 0
  331. * @param resolver
  332. */
  333. void rdns_resolver_release (struct rdns_resolver *resolver);
  334. /**
  335. * Make a DNS request
  336. * @param resolver resolver object
  337. * @param cb callback to call on resolve completing
  338. * @param ud user data for callback
  339. * @param timeout timeout in seconds
  340. * @param repeats how much time to retransmit query
  341. * @param queries how much RR queries to send
  342. * @param ... -> queries in format: <query_type>[,type_argument[,type_argument...]]
  343. * @return opaque request object or NULL
  344. */
  345. struct rdns_request* rdns_make_request_full (
  346. struct rdns_resolver *resolver,
  347. dns_callback_type cb,
  348. void *cbdata,
  349. double timeout,
  350. unsigned int repeats,
  351. unsigned int queries,
  352. ...
  353. );
  354. /**
  355. * Get textual presentation of DNS error code
  356. */
  357. const char *rdns_strerror (enum dns_rcode rcode);
  358. /**
  359. * Get textual presentation of DNS request type
  360. */
  361. const char *rdns_strtype (enum rdns_request_type type);
  362. /**
  363. * Parse string and return request type
  364. * @param str
  365. * @return
  366. */
  367. enum rdns_request_type rdns_type_fromstr (const char *str);
  368. /**
  369. * Returns string representing request type
  370. * @param rcode
  371. * @return
  372. */
  373. const char *
  374. rdns_str_from_type (enum rdns_request_type rcode);
  375. /**
  376. * Parse string and return error code
  377. * @param str
  378. * @return
  379. */
  380. enum dns_rcode rdns_rcode_fromstr (const char *str);
  381. /**
  382. * Increase refcount for a request
  383. * @param req
  384. * @return
  385. */
  386. struct rdns_request* rdns_request_retain (struct rdns_request *req);
  387. /**
  388. * Decrease refcount for a request and free it if refcount is 0
  389. * @param req
  390. */
  391. void rdns_request_release (struct rdns_request *req);
  392. /**
  393. * Check whether a request contains `type` request
  394. * @param req request object
  395. * @param type check for a specified type
  396. * @return true if `type` has been requested
  397. */
  398. bool rdns_request_has_type (struct rdns_request *req, enum rdns_request_type type);
  399. /**
  400. * Return requested name for a request
  401. * @param req request object
  402. * @return requested name as it was passed to `rdns_make_request`
  403. */
  404. const struct rdns_request_name* rdns_request_get_name (struct rdns_request *req,
  405. unsigned int *count);
  406. /**
  407. * Return a DNS server name associated with the request
  408. * @param req request object
  409. * @return name of a DNS server
  410. */
  411. const char* rdns_request_get_server (struct rdns_request *req);
  412. /**
  413. * Return PTR string for a request (ipv4 or ipv6) addresses
  414. * @param str string representation of IP address
  415. * @return name to resolve or NULL if `str` is not an IP address; caller must free result when it is unused
  416. */
  417. char * rdns_generate_ptr_from_str (const char *str);
  418. /**
  419. * Format DNS name of the packet punycoding if needed
  420. * @param req request
  421. * @param name name string
  422. * @param namelen length of name
  423. */
  424. bool rdns_format_dns_name (struct rdns_resolver *resolver,
  425. const char *name, size_t namelen,
  426. char **out, size_t *outlen);
  427. /*
  428. * Private functions used by async libraries as callbacks
  429. */
  430. void rdns_process_read (int fd, void *arg);
  431. void rdns_process_timer (void *arg);
  432. void rdns_process_write (int fd, void *arg);
  433. #ifdef __cplusplus
  434. }
  435. #endif
  436. #endif