Rapid spam filtering system https://rspamd.com/
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.

467 lines
12 KiB

  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_SOA = 6,
  46. RDNS_REQUEST_PTR = 12,
  47. RDNS_REQUEST_MX = 15,
  48. RDNS_REQUEST_TXT = 16,
  49. RDNS_REQUEST_SRV = 33,
  50. RDNS_REQUEST_SPF = 99,
  51. RDNS_REQUEST_AAAA = 28,
  52. RDNS_REQUEST_TLSA = 52,
  53. RDNS_REQUEST_ANY = 255
  54. };
  55. union rdns_reply_element_un {
  56. struct {
  57. struct in_addr addr;
  58. } a;
  59. struct {
  60. struct in6_addr addr;
  61. } aaa;
  62. struct {
  63. char *name;
  64. } ptr;
  65. struct {
  66. char *name;
  67. } ns;
  68. struct {
  69. char *name;
  70. uint16_t priority;
  71. } mx;
  72. struct {
  73. char *data;
  74. } txt;
  75. struct {
  76. uint16_t priority;
  77. uint16_t weight;
  78. uint16_t port;
  79. char *target;
  80. } srv;
  81. struct {
  82. char *mname;
  83. char *admin;
  84. uint32_t serial;
  85. int32_t refresh;
  86. int32_t retry;
  87. int32_t expire;
  88. uint32_t minimum;
  89. } soa;
  90. struct {
  91. uint8_t usage;
  92. uint8_t selector;
  93. uint8_t match_type;
  94. uint16_t datalen;
  95. uint8_t *data;
  96. } tlsa;
  97. };
  98. struct rdns_reply_entry {
  99. union rdns_reply_element_un content;
  100. enum rdns_request_type type;
  101. int32_t ttl;
  102. struct rdns_reply_entry *prev, *next;
  103. };
  104. enum dns_rcode {
  105. RDNS_RC_INVALID = -1,
  106. RDNS_RC_NOERROR = 0,
  107. RDNS_RC_FORMERR = 1,
  108. RDNS_RC_SERVFAIL = 2,
  109. RDNS_RC_NXDOMAIN = 3,
  110. RDNS_RC_NOTIMP = 4,
  111. RDNS_RC_REFUSED = 5,
  112. RDNS_RC_YXDOMAIN = 6,
  113. RDNS_RC_YXRRSET = 7,
  114. RDNS_RC_NXRRSET = 8,
  115. RDNS_RC_NOTAUTH = 9,
  116. RDNS_RC_NOTZONE = 10,
  117. RDNS_RC_TIMEOUT = 11,
  118. RDNS_RC_NETERR = 12,
  119. RDNS_RC_NOREC = 13
  120. };
  121. struct rdns_reply {
  122. struct rdns_request *request;
  123. struct rdns_resolver *resolver;
  124. struct rdns_reply_entry *entries;
  125. const char *requested_name;
  126. enum dns_rcode code;
  127. bool authenticated;
  128. };
  129. typedef void (*rdns_periodic_callback)(void *user_data);
  130. struct rdns_async_context {
  131. void *data;
  132. void* (*add_read)(void *priv_data, int fd, void *user_data);
  133. void (*del_read)(void *priv_data, void *ev_data);
  134. void* (*add_write)(void *priv_data, int fd, void *user_data);
  135. void (*del_write)(void *priv_data, void *ev_data);
  136. void* (*add_timer)(void *priv_data, double after, void *user_data);
  137. void (*repeat_timer)(void *priv_data, void *ev_data);
  138. void (*del_timer)(void *priv_data, void *ev_data);
  139. void* (*add_periodic)(void *priv_data, double after,
  140. rdns_periodic_callback cb, void *user_data);
  141. void (*del_periodic)(void *priv_data, void *ev_data);
  142. void (*cleanup)(void *priv_data);
  143. };
  144. struct rdns_upstream_elt {
  145. void *server;
  146. void *lib_data;
  147. };
  148. struct rdns_upstream_context {
  149. void *data;
  150. struct rdns_upstream_elt* (*select)(const char *name,
  151. size_t len, void *ups_data);
  152. struct rdns_upstream_elt* (*select_retransmit)(const char *name,
  153. size_t len, void *ups_data);
  154. unsigned int (*count)(void *ups_data);
  155. void (*ok)(struct rdns_upstream_elt *elt, void *ups_data);
  156. void (*fail)(struct rdns_upstream_elt *elt, void *ups_data);
  157. };
  158. /**
  159. * Type of rdns plugin
  160. */
  161. enum rdns_plugin_type {
  162. RDNS_PLUGIN_CURVE = 0
  163. };
  164. typedef ssize_t (*rdns_network_send_callback) (struct rdns_request *req, void *plugin_data);
  165. typedef ssize_t (*rdns_network_recv_callback) (struct rdns_io_channel *ioc, void *buf,
  166. size_t len, void *plugin_data, struct rdns_request **req_out);
  167. typedef void (*rdns_network_finish_callback) (struct rdns_request *req, void *plugin_data);
  168. typedef void (*rdns_plugin_dtor_callback) (struct rdns_resolver *resolver, void *plugin_data);
  169. struct rdns_plugin {
  170. enum rdns_plugin_type type;
  171. union {
  172. struct {
  173. rdns_network_send_callback send_cb;
  174. rdns_network_recv_callback recv_cb;
  175. rdns_network_finish_callback finish_cb;
  176. } curve_plugin;
  177. } cb;
  178. rdns_plugin_dtor_callback dtor;
  179. void *data;
  180. };
  181. /*
  182. * RDNS logger types
  183. */
  184. /*
  185. * These types are somehow compatible with glib
  186. */
  187. enum rdns_log_level {
  188. RDNS_LOG_ERROR = 1 << 3,
  189. RDNS_LOG_WARNING = 1 << 4,
  190. RDNS_LOG_INFO = 1 << 6,
  191. RDNS_LOG_DEBUG = 1 << 7
  192. };
  193. typedef void (*rdns_log_function) (
  194. void *log_data, //!< opaque data pointer
  195. enum rdns_log_level level, //!< level of message
  196. const char *function, //!< calling function
  197. const char *format, //!< format
  198. va_list args //!< set of arguments
  199. );
  200. struct rdns_request_name {
  201. char *name;
  202. enum rdns_request_type type;
  203. unsigned int len;
  204. };
  205. #define MAX_FAKE_NAME 1000
  206. /*
  207. * RDNS API
  208. */
  209. /**
  210. * Create DNS resolver structure
  211. */
  212. struct rdns_resolver *rdns_resolver_new (void);
  213. /**
  214. * Bind resolver to specified async context
  215. * @param ctx
  216. */
  217. void rdns_resolver_async_bind (struct rdns_resolver *resolver,
  218. struct rdns_async_context *ctx);
  219. /**
  220. * Enable stub dnssec resolver
  221. * @param resolver
  222. */
  223. void rdns_resolver_set_dnssec (struct rdns_resolver *resolver, bool enabled);
  224. /**
  225. * Add new DNS server definition to the resolver
  226. * @param resolver resolver object
  227. * @param name name of DNS server (should be ipv4 or ipv6 address)
  228. * @param priority priority (can be 0 for fair round-robin)
  229. * @param io_cnt a number of sockets that are simultaneously opened to this server
  230. * @return opaque pointer that could be used to select upstream
  231. */
  232. void* rdns_resolver_add_server (struct rdns_resolver *resolver,
  233. const char *name, unsigned int port,
  234. int priority, unsigned int io_cnt);
  235. /**
  236. * Load nameservers definition from resolv.conf file
  237. * @param resolver resolver object
  238. * @param path path to resolv.conf file (/etc/resolv.conf typically)
  239. * @return true if resolv.conf has been parsed
  240. */
  241. bool rdns_resolver_parse_resolv_conf (struct rdns_resolver *resolver,
  242. const char *path);
  243. typedef bool (*rdns_resolv_conf_cb) (struct rdns_resolver *resolver,
  244. const char *name, unsigned int port,
  245. int priority, unsigned int io_cnt, void *ud);
  246. /**
  247. * Parse nameservers calling the specified callback for each nameserver
  248. * @param resolve resolver object
  249. * @param path path to resolv.conf file (/etc/resolv.conf typically)
  250. * @param cb callback to call
  251. * @param ud userdata for callback
  252. * @return true if resolv.conf has been parsed
  253. */
  254. bool rdns_resolver_parse_resolv_conf_cb (struct rdns_resolver *resolver,
  255. const char *path, rdns_resolv_conf_cb cb, void *ud);
  256. /**
  257. * Set an external logger function to log messages from the resolver
  258. * @param resolver resolver object
  259. * @param logger logger callback
  260. * @param log_data opaque data
  261. */
  262. void rdns_resolver_set_logger (struct rdns_resolver *resolver,
  263. rdns_log_function logger, void *log_data);
  264. /**
  265. * Set log level for an internal logger (stderr one)
  266. * @param resolver resolver object
  267. * @param level desired log level
  268. */
  269. void rdns_resolver_set_log_level (struct rdns_resolver *resolver,
  270. enum rdns_log_level level);
  271. /**
  272. * Set upstream library for selecting DNS upstreams
  273. * @param resolver resolver object
  274. * @param ups_ctx upstream functions
  275. * @param ups_data opaque data
  276. */
  277. void rdns_resolver_set_upstream_lib (struct rdns_resolver *resolver,
  278. struct rdns_upstream_context *ups_ctx,
  279. void *ups_data);
  280. /**
  281. * Set maximum number of dns requests to be sent to a socket to be refreshed
  282. * @param resolver resolver object
  283. * @param max_ioc_uses unsigned count of socket usage limit
  284. * @param check_time specifies how often to check for sockets and refresh them
  285. */
  286. void rdns_resolver_set_max_io_uses (struct rdns_resolver *resolver,
  287. uint64_t max_ioc_uses, double check_time);
  288. /**
  289. * Register new plugin for rdns resolver
  290. * @param resolver
  291. * @param plugin
  292. */
  293. void rdns_resolver_register_plugin (struct rdns_resolver *resolver,
  294. struct rdns_plugin *plugin);
  295. /**
  296. * Add a fake reply for a specified name
  297. * @param resolver
  298. * @param type
  299. * @param name (must not be larger than MAX_FAKE_NAME)
  300. * @param reply
  301. */
  302. void rdns_resolver_set_fake_reply (struct rdns_resolver *resolver,
  303. const char *name,
  304. enum rdns_request_type type,
  305. enum dns_rcode rcode,
  306. struct rdns_reply_entry *reply);
  307. /**
  308. * Init DNS resolver
  309. * @param resolver
  310. * @return
  311. */
  312. bool rdns_resolver_init (struct rdns_resolver *resolver);
  313. /**
  314. * Decrease refcount for a resolver and free it if refcount is 0
  315. * @param resolver
  316. */
  317. void rdns_resolver_release (struct rdns_resolver *resolver);
  318. /**
  319. * Make a DNS request
  320. * @param resolver resolver object
  321. * @param cb callback to call on resolve completing
  322. * @param ud user data for callback
  323. * @param timeout timeout in seconds
  324. * @param repeats how much time to retransmit query
  325. * @param queries how much RR queries to send
  326. * @param ... -> queries in format: <query_type>[,type_argument[,type_argument...]]
  327. * @return opaque request object or NULL
  328. */
  329. struct rdns_request* rdns_make_request_full (
  330. struct rdns_resolver *resolver,
  331. dns_callback_type cb,
  332. void *cbdata,
  333. double timeout,
  334. unsigned int repeats,
  335. unsigned int queries,
  336. ...
  337. );
  338. /**
  339. * Get textual presentation of DNS error code
  340. */
  341. const char *rdns_strerror (enum dns_rcode rcode);
  342. /**
  343. * Get textual presentation of DNS request type
  344. */
  345. const char *rdns_strtype (enum rdns_request_type type);
  346. /**
  347. * Parse string and return request type
  348. * @param str
  349. * @return
  350. */
  351. enum rdns_request_type rdns_type_fromstr (const char *str);
  352. /**
  353. * Returns string representing request type
  354. * @param rcode
  355. * @return
  356. */
  357. const char *
  358. rdns_str_from_type (enum rdns_request_type rcode);
  359. /**
  360. * Parse string and return error code
  361. * @param str
  362. * @return
  363. */
  364. enum dns_rcode rdns_rcode_fromstr (const char *str);
  365. /**
  366. * Increase refcount for a request
  367. * @param req
  368. * @return
  369. */
  370. struct rdns_request* rdns_request_retain (struct rdns_request *req);
  371. /**
  372. * Decrease refcount for a request and free it if refcount is 0
  373. * @param req
  374. */
  375. void rdns_request_release (struct rdns_request *req);
  376. /**
  377. * Check whether a request contains `type` request
  378. * @param req request object
  379. * @param type check for a specified type
  380. * @return true if `type` has been requested
  381. */
  382. bool rdns_request_has_type (struct rdns_request *req, enum rdns_request_type type);
  383. /**
  384. * Return requested name for a request
  385. * @param req request object
  386. * @return requested name as it was passed to `rdns_make_request`
  387. */
  388. const struct rdns_request_name* rdns_request_get_name (struct rdns_request *req,
  389. unsigned int *count);
  390. /**
  391. * Return PTR string for a request (ipv4 or ipv6) addresses
  392. * @param str string representation of IP address
  393. * @return name to resolve or NULL if `str` is not an IP address; caller must free result when it is unused
  394. */
  395. char * rdns_generate_ptr_from_str (const char *str);
  396. /**
  397. * Format DNS name of the packet punycoding if needed
  398. * @param req request
  399. * @param name name string
  400. * @param namelen length of name
  401. */
  402. bool rdns_format_dns_name (struct rdns_resolver *resolver,
  403. const char *name, size_t namelen,
  404. char **out, size_t *outlen);
  405. /*
  406. * Private functions used by async libraries as callbacks
  407. */
  408. void rdns_process_read (int fd, void *arg);
  409. void rdns_process_timer (void *arg);
  410. void rdns_process_retransmit (int fd, void *arg);
  411. #ifdef __cplusplus
  412. }
  413. #endif
  414. #endif