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.

dns.c 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "dns.h"
  18. #include "rspamd.h"
  19. #include "utlist.h"
  20. #include "contrib/librdns/rdns.h"
  21. #include "contrib/librdns/dns_private.h"
  22. #include "contrib/librdns/rdns_ev.h"
  23. #include "unix-std.h"
  24. static const gchar *M = "rspamd dns";
  25. static struct rdns_upstream_elt* rspamd_dns_select_upstream (const char *name,
  26. size_t len, void *ups_data);
  27. static struct rdns_upstream_elt* rspamd_dns_select_upstream_retransmit (
  28. const char *name,
  29. size_t len,
  30. struct rdns_upstream_elt *prev_elt,
  31. void *ups_data);
  32. static void rspamd_dns_upstream_ok (struct rdns_upstream_elt *elt,
  33. void *ups_data);
  34. static void rspamd_dns_upstream_fail (struct rdns_upstream_elt *elt,
  35. void *ups_data, const gchar *reason);
  36. static unsigned int rspamd_dns_upstream_count (void *ups_data);
  37. static struct rdns_upstream_context rspamd_ups_ctx = {
  38. .select = rspamd_dns_select_upstream,
  39. .select_retransmit = rspamd_dns_select_upstream_retransmit,
  40. .ok = rspamd_dns_upstream_ok,
  41. .fail = rspamd_dns_upstream_fail,
  42. .count = rspamd_dns_upstream_count,
  43. .data = NULL
  44. };
  45. struct rspamd_dns_request_ud {
  46. struct rspamd_async_session *session;
  47. dns_callback_type cb;
  48. gpointer ud;
  49. rspamd_mempool_t *pool;
  50. struct rspamd_task *task;
  51. struct rspamd_symcache_item *item;
  52. struct rdns_request *req;
  53. struct rdns_reply *reply;
  54. };
  55. struct rspamd_dns_fail_cache_entry {
  56. const char *name;
  57. gint32 namelen;
  58. enum rdns_request_type type;
  59. };
  60. static guint
  61. rspamd_dns_fail_hash (gconstpointer ptr)
  62. {
  63. struct rspamd_dns_fail_cache_entry *elt =
  64. (struct rspamd_dns_fail_cache_entry *)ptr;
  65. /* We don't care about type when doing hashing */
  66. return rspamd_cryptobox_fast_hash (elt->name, elt->namelen,
  67. rspamd_hash_seed ());
  68. }
  69. static gboolean
  70. rspamd_dns_fail_equal (gconstpointer p1, gconstpointer p2)
  71. {
  72. struct rspamd_dns_fail_cache_entry *e1 = (struct rspamd_dns_fail_cache_entry *)p1,
  73. *e2 = (struct rspamd_dns_fail_cache_entry *)p2;
  74. if (e1->type == e2->type && e1->namelen == e2->namelen) {
  75. return memcmp (e1->name, e2->name, e1->namelen) == 0;
  76. }
  77. return FALSE;
  78. }
  79. static void
  80. rspamd_dns_fin_cb (gpointer arg)
  81. {
  82. struct rspamd_dns_request_ud *reqdata = (struct rspamd_dns_request_ud *)arg;
  83. if (reqdata->item) {
  84. rspamd_symcache_set_cur_item (reqdata->task, reqdata->item);
  85. }
  86. if (reqdata->reply) {
  87. reqdata->cb (reqdata->reply, reqdata->ud);
  88. }
  89. else {
  90. struct rdns_reply fake_reply;
  91. memset (&fake_reply, 0, sizeof (fake_reply));
  92. fake_reply.code = RDNS_RC_TIMEOUT;
  93. fake_reply.request = reqdata->req;
  94. fake_reply.resolver = reqdata->req->resolver;
  95. fake_reply.requested_name = reqdata->req->requested_names[0].name;
  96. reqdata->cb (&fake_reply, reqdata->ud);
  97. }
  98. rdns_request_release (reqdata->req);
  99. if (reqdata->item) {
  100. rspamd_symcache_item_async_dec_check (reqdata->task,
  101. reqdata->item, M);
  102. }
  103. if (reqdata->pool == NULL) {
  104. g_free (reqdata);
  105. }
  106. }
  107. static void
  108. rspamd_dns_callback (struct rdns_reply *reply, gpointer ud)
  109. {
  110. struct rspamd_dns_request_ud *reqdata = ud;
  111. reqdata->reply = reply;
  112. if (reqdata->session) {
  113. if (reply->code == RDNS_RC_SERVFAIL &&
  114. reqdata->task &&
  115. reqdata->task->resolver->fails_cache) {
  116. /* Add to cache... */
  117. const gchar *name = reqdata->req->requested_names[0].name;
  118. gchar *target;
  119. gsize namelen;
  120. struct rspamd_dns_fail_cache_entry *nentry;
  121. /* Allocate in a single entry to allow further free in a single call */
  122. namelen = strlen (name);
  123. nentry = g_malloc (sizeof (nentry) + namelen + 1);
  124. target = ((gchar *)nentry) + sizeof (nentry);
  125. rspamd_strlcpy (target, name, namelen + 1);
  126. nentry->type = reqdata->req->requested_names[0].type;
  127. nentry->name = target;
  128. nentry->namelen = namelen;
  129. /* Rdns request is retained there */
  130. rspamd_lru_hash_insert (reqdata->task->resolver->fails_cache,
  131. nentry, rdns_request_retain (reply->request),
  132. reqdata->task->task_timestamp,
  133. reqdata->task->resolver->fails_cache_time);
  134. }
  135. /*
  136. * Ref event to avoid double unref by
  137. * event removing
  138. */
  139. rdns_request_retain (reply->request);
  140. rspamd_session_remove_event (reqdata->session,
  141. rspamd_dns_fin_cb, reqdata);
  142. }
  143. else {
  144. reqdata->cb (reply, reqdata->ud);
  145. if (reqdata->pool == NULL) {
  146. g_free (reqdata);
  147. }
  148. }
  149. }
  150. struct rspamd_dns_request_ud *
  151. rspamd_dns_resolver_request (struct rspamd_dns_resolver *resolver,
  152. struct rspamd_async_session *session,
  153. rspamd_mempool_t *pool,
  154. dns_callback_type cb,
  155. gpointer ud,
  156. enum rdns_request_type type,
  157. const char *name)
  158. {
  159. struct rdns_request *req;
  160. struct rspamd_dns_request_ud *reqdata = NULL;
  161. g_assert (resolver != NULL);
  162. if (resolver->r == NULL) {
  163. return NULL;
  164. }
  165. if (session && rspamd_session_blocked (session)) {
  166. return NULL;
  167. }
  168. if (pool != NULL) {
  169. reqdata =
  170. rspamd_mempool_alloc0 (pool, sizeof (struct rspamd_dns_request_ud));
  171. }
  172. else {
  173. reqdata = g_malloc0 (sizeof (struct rspamd_dns_request_ud));
  174. }
  175. reqdata->pool = pool;
  176. reqdata->session = session;
  177. reqdata->cb = cb;
  178. reqdata->ud = ud;
  179. req = rdns_make_request_full (resolver->r, rspamd_dns_callback, reqdata,
  180. resolver->request_timeout, resolver->max_retransmits, 1, name,
  181. type);
  182. reqdata->req = req;
  183. if (session) {
  184. if (req != NULL) {
  185. rspamd_session_add_event (session,
  186. (event_finalizer_t) rspamd_dns_fin_cb,
  187. reqdata,
  188. M);
  189. }
  190. }
  191. if (req == NULL) {
  192. if (pool == NULL) {
  193. g_free (reqdata);
  194. }
  195. return NULL;
  196. }
  197. return reqdata;
  198. }
  199. struct rspamd_dns_cached_delayed_cbdata {
  200. struct rspamd_task *task;
  201. dns_callback_type cb;
  202. gpointer ud;
  203. ev_timer tm;
  204. struct rdns_request *req;
  205. };
  206. static void
  207. rspamd_fail_cache_cb (EV_P_ ev_timer *w, int revents)
  208. {
  209. struct rspamd_dns_cached_delayed_cbdata *cbd =
  210. (struct rspamd_dns_cached_delayed_cbdata *)w->data;
  211. struct rdns_reply fake_reply;
  212. ev_timer_stop (EV_A_ w);
  213. memset (&fake_reply, 0, sizeof (fake_reply));
  214. fake_reply.code = RDNS_RC_SERVFAIL;
  215. fake_reply.request = cbd->req;
  216. fake_reply.resolver = cbd->req->resolver;
  217. fake_reply.requested_name = cbd->req->requested_names[0].name;
  218. cbd->cb (&fake_reply, cbd->ud);
  219. rdns_request_release (cbd->req);
  220. }
  221. static gboolean
  222. make_dns_request_task_common (struct rspamd_task *task,
  223. dns_callback_type cb,
  224. gpointer ud,
  225. enum rdns_request_type type,
  226. const char *name,
  227. gboolean forced)
  228. {
  229. struct rspamd_dns_request_ud *reqdata;
  230. if (!forced && task->dns_requests >= task->cfg->dns_max_requests) {
  231. return FALSE;
  232. }
  233. if (task->resolver->fails_cache) {
  234. /* Search in failures cache */
  235. struct rspamd_dns_fail_cache_entry search;
  236. struct rdns_request *req;
  237. search.name = name;
  238. search.namelen = strlen (name);
  239. search.type = type;
  240. if ((req = rspamd_lru_hash_lookup (task->resolver->fails_cache,
  241. &search, task->task_timestamp)) != NULL) {
  242. /*
  243. * We need to reply with SERVFAIL again to the API, so add a special
  244. * timer, uh-oh, and fire it
  245. */
  246. struct rspamd_dns_cached_delayed_cbdata *cbd =
  247. rspamd_mempool_alloc0 (task->task_pool, sizeof (*cbd));
  248. ev_timer_init (&cbd->tm, rspamd_fail_cache_cb, 0.0, 0.0);
  249. cbd->task = task;
  250. cbd->cb = cb;
  251. cbd->ud = ud;
  252. cbd->req = rdns_request_retain (req);
  253. cbd->tm.data = cbd;
  254. return TRUE;
  255. }
  256. }
  257. reqdata = rspamd_dns_resolver_request (
  258. task->resolver, task->s, task->task_pool, cb, ud,
  259. type, name);
  260. if (reqdata) {
  261. task->dns_requests ++;
  262. reqdata->task = task;
  263. reqdata->item = rspamd_symcache_get_cur_item (task);
  264. if (reqdata->item) {
  265. /* We are inside some session */
  266. rspamd_symcache_item_async_inc (task, reqdata->item, M);
  267. }
  268. if (!forced && task->dns_requests >= task->cfg->dns_max_requests) {
  269. msg_info_task ("stop resolving on reaching %ud requests",
  270. task->dns_requests);
  271. }
  272. return TRUE;
  273. }
  274. return FALSE;
  275. }
  276. gboolean
  277. rspamd_dns_resolver_request_task (struct rspamd_task *task,
  278. dns_callback_type cb,
  279. gpointer ud,
  280. enum rdns_request_type type,
  281. const char *name)
  282. {
  283. return make_dns_request_task_common (task, cb, ud, type, name, FALSE);
  284. }
  285. gboolean
  286. rspamd_dns_resolver_request_task_forced (struct rspamd_task *task,
  287. dns_callback_type cb,
  288. gpointer ud,
  289. enum rdns_request_type type,
  290. const char *name)
  291. {
  292. return make_dns_request_task_common (task, cb, ud, type, name, TRUE);
  293. }
  294. static void rspamd_rnds_log_bridge (
  295. void *log_data,
  296. enum rdns_log_level level,
  297. const char *function,
  298. const char *format,
  299. va_list args)
  300. {
  301. rspamd_logger_t *logger = log_data;
  302. rspamd_common_logv (logger, (GLogLevelFlags)level, "rdns", NULL,
  303. function, format, args);
  304. }
  305. static void
  306. rspamd_dns_server_init (struct upstream *up, guint idx, gpointer ud)
  307. {
  308. struct rspamd_dns_resolver *r = ud;
  309. rspamd_inet_addr_t *addr;
  310. void *serv;
  311. struct rdns_upstream_elt *elt;
  312. addr = rspamd_upstream_addr_next (up);
  313. if (r->cfg) {
  314. serv = rdns_resolver_add_server (r->r, rspamd_inet_address_to_string (addr),
  315. rspamd_inet_address_get_port (addr), 0, r->cfg->dns_io_per_server);
  316. }
  317. else {
  318. serv = rdns_resolver_add_server (r->r, rspamd_inet_address_to_string (addr),
  319. rspamd_inet_address_get_port (addr), 0, 8);
  320. }
  321. g_assert (serv != NULL);
  322. elt = rspamd_mempool_alloc0 (r->cfg->cfg_pool, sizeof (*elt));
  323. elt->server = serv;
  324. elt->lib_data = up;
  325. rspamd_upstream_set_data (up, elt);
  326. }
  327. static void
  328. rspamd_dns_server_reorder (struct upstream *up, guint idx, gpointer ud)
  329. {
  330. struct rspamd_dns_resolver *r = ud;
  331. rspamd_upstream_set_weight (up, rspamd_upstreams_count (r->ups) - idx + 1);
  332. }
  333. static bool
  334. rspamd_dns_resolv_conf_on_server (struct rdns_resolver *resolver,
  335. const char *name, unsigned int port,
  336. int priority, unsigned int io_cnt, void *ud)
  337. {
  338. struct rspamd_dns_resolver *dns_resolver = ud;
  339. struct rspamd_config *cfg;
  340. rspamd_inet_addr_t *addr;
  341. gint test_fd;
  342. cfg = dns_resolver->cfg;
  343. msg_info_config ("parsed nameserver %s from resolv.conf", name);
  344. /* Try to open a connection */
  345. if (!rspamd_parse_inet_address (&addr, name, strlen (name),
  346. RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
  347. msg_warn_config ("cannot parse nameserver address %s", name);
  348. return FALSE;
  349. }
  350. rspamd_inet_address_set_port (addr, port);
  351. test_fd = rspamd_inet_address_connect (addr, SOCK_DGRAM, TRUE);
  352. if (test_fd == -1 && (errno != EINTR || errno != ECONNREFUSED || errno != ECONNRESET)) {
  353. msg_info_config ("cannot open connection to nameserver at address %s: %s",
  354. name, strerror (errno));
  355. rspamd_inet_address_free (addr);
  356. return FALSE;
  357. }
  358. rspamd_inet_address_free (addr);
  359. close (test_fd);
  360. return rspamd_upstreams_add_upstream (dns_resolver->ups, name, port,
  361. RSPAMD_UPSTREAM_PARSE_NAMESERVER,
  362. NULL);
  363. }
  364. static void
  365. rspamd_process_fake_reply (struct rspamd_config *cfg,
  366. struct rspamd_dns_resolver *dns_resolver,
  367. const ucl_object_t *cur_arr)
  368. {
  369. const ucl_object_t *cur;
  370. ucl_object_iter_t it;
  371. it = ucl_object_iterate_new (cur_arr);
  372. while ((cur = ucl_object_iterate_safe (it, true))) {
  373. const ucl_object_t *type_obj, *name_obj, *code_obj, *replies_obj;
  374. enum rdns_request_type rtype = RDNS_REQUEST_A;
  375. enum dns_rcode rcode = RDNS_RC_NOERROR;
  376. struct rdns_reply_entry *replies = NULL;
  377. const gchar *name = NULL;
  378. if (ucl_object_type (cur) != UCL_OBJECT) {
  379. continue;
  380. }
  381. name_obj = ucl_object_lookup (cur, "name");
  382. if (name_obj == NULL ||
  383. (name = ucl_object_tostring (name_obj)) == NULL) {
  384. msg_err_config ("no name for fake dns reply");
  385. continue;
  386. }
  387. type_obj = ucl_object_lookup (cur, "type");
  388. if (type_obj) {
  389. rtype = rdns_type_fromstr (ucl_object_tostring (type_obj));
  390. if (rtype == RDNS_REQUEST_INVALID) {
  391. msg_err_config ("invalid type for %s: %s", name,
  392. ucl_object_tostring (type_obj));
  393. continue;
  394. }
  395. }
  396. code_obj = ucl_object_lookup_any (cur, "code", "rcode", NULL);
  397. if (code_obj) {
  398. rcode = rdns_rcode_fromstr (ucl_object_tostring (code_obj));
  399. if (rcode == RDNS_RC_INVALID) {
  400. msg_err_config ("invalid rcode for %s: %s", name,
  401. ucl_object_tostring (code_obj));
  402. continue;
  403. }
  404. }
  405. if (rcode == RDNS_RC_NOERROR) {
  406. /* We want replies to be set for this rcode */
  407. replies_obj = ucl_object_lookup (cur, "replies");
  408. if (replies_obj == NULL || ucl_object_type (replies_obj) != UCL_ARRAY) {
  409. msg_err_config ("invalid replies for fake DNS record %s", name);
  410. continue;
  411. }
  412. ucl_object_iter_t rep_it;
  413. const ucl_object_t *rep_obj;
  414. rep_it = ucl_object_iterate_new (replies_obj);
  415. while ((rep_obj = ucl_object_iterate_safe (rep_it, true))) {
  416. const gchar *str_rep = ucl_object_tostring (rep_obj);
  417. struct rdns_reply_entry *rep;
  418. gchar **svec;
  419. if (str_rep == NULL) {
  420. msg_err_config ("invalid reply element for fake DNS record %s",
  421. name);
  422. continue;
  423. }
  424. rep = calloc (1, sizeof (*rep));
  425. g_assert (rep != NULL);
  426. rep->type = rtype;
  427. rep->ttl = 0;
  428. switch (rtype) {
  429. case RDNS_REQUEST_A:
  430. if (inet_pton (AF_INET, str_rep, &rep->content.a.addr) != 1) {
  431. msg_err_config ("invalid A reply element for fake "
  432. "DNS record %s: %s",
  433. name, str_rep);
  434. free (rep);
  435. }
  436. else {
  437. DL_APPEND (replies, rep);
  438. }
  439. break;
  440. case RDNS_REQUEST_NS:
  441. rep->content.ns.name = strdup (str_rep);
  442. DL_APPEND (replies, rep);
  443. break;
  444. case RDNS_REQUEST_PTR:
  445. rep->content.ptr.name = strdup (str_rep);
  446. DL_APPEND (replies, rep);
  447. break;
  448. case RDNS_REQUEST_MX:
  449. svec = g_strsplit_set (str_rep, " :", -1);
  450. if (svec && svec[0] && svec[1]) {
  451. rep->content.mx.priority = strtoul (svec[0], NULL, 10);
  452. rep->content.mx.name = strdup (svec[1]);
  453. DL_APPEND (replies, rep);
  454. }
  455. else {
  456. msg_err_config ("invalid MX reply element for fake "
  457. "DNS record %s: %s",
  458. name, str_rep);
  459. free (rep);
  460. }
  461. g_strfreev (svec);
  462. break;
  463. case RDNS_REQUEST_TXT:
  464. rep->content.txt.data = strdup (str_rep);
  465. DL_APPEND (replies, rep);
  466. break;
  467. case RDNS_REQUEST_SOA:
  468. svec = g_strsplit_set (str_rep, " :", -1);
  469. /* 7 elements */
  470. if (svec && svec[0] && svec[1] && svec[2] &&
  471. svec[3] && svec[4] && svec[5] && svec[6]) {
  472. rep->content.soa.mname = strdup (svec[0]);
  473. rep->content.soa.admin = strdup (svec[1]);
  474. rep->content.soa.serial = strtoul (svec[2], NULL, 10);
  475. rep->content.soa.refresh = strtol (svec[3], NULL, 10);
  476. rep->content.soa.retry = strtol (svec[4], NULL, 10);
  477. rep->content.soa.expire = strtol (svec[5], NULL, 10);
  478. rep->content.soa.minimum = strtoul (svec[6], NULL, 10);
  479. DL_APPEND (replies, rep);
  480. }
  481. else {
  482. msg_err_config ("invalid MX reply element for fake "
  483. "DNS record %s: %s",
  484. name, str_rep);
  485. free (rep);
  486. }
  487. g_strfreev (svec);
  488. break;
  489. case RDNS_REQUEST_AAAA:
  490. if (inet_pton (AF_INET6, str_rep, &rep->content.aaa.addr) != 1) {
  491. msg_err_config ("invalid AAAA reply element for fake "
  492. "DNS record %s: %s",
  493. name, str_rep);
  494. free (rep);
  495. }
  496. else {
  497. DL_APPEND (replies, rep);
  498. }
  499. case RDNS_REQUEST_SRV:
  500. default:
  501. msg_err_config ("invalid or unsupported reply element "
  502. "for fake DNS record %s(%s): %s",
  503. name, rdns_str_from_type (rtype), str_rep);
  504. free (rep);
  505. break;
  506. }
  507. }
  508. ucl_object_iterate_free (rep_it);
  509. if (replies) {
  510. struct rdns_reply_entry *tmp_entry;
  511. guint i = 0;
  512. DL_COUNT (replies, tmp_entry, i);
  513. msg_info_config ("added fake record: %s(%s); %d replies", name,
  514. rdns_str_from_type (rtype), i);
  515. rdns_resolver_set_fake_reply (dns_resolver->r,
  516. name, rtype, rcode, replies);
  517. }
  518. else {
  519. msg_warn_config ("record %s has no replies, not adding",
  520. name);
  521. }
  522. }
  523. else {
  524. /* This entry returns some non valid code, no replies are possible */
  525. replies_obj = ucl_object_lookup (cur, "replies");
  526. if (replies_obj) {
  527. msg_warn_config ("replies are set for non-successful return "
  528. "code for %s(%s), they will be ignored", name, rdns_str_from_type (rtype));
  529. }
  530. rdns_resolver_set_fake_reply (dns_resolver->r,
  531. name, rtype, rcode, NULL);
  532. }
  533. }
  534. ucl_object_iterate_free (it);
  535. }
  536. static void
  537. rspamd_dns_resolver_config_ucl (struct rspamd_config *cfg,
  538. struct rspamd_dns_resolver *dns_resolver,
  539. const ucl_object_t *dns_section)
  540. {
  541. const ucl_object_t *fake_replies, *fails_cache_size, *fails_cache_time;
  542. static const ev_tstamp default_fails_cache_time = 10.0;
  543. /* Process fake replies */
  544. fake_replies = ucl_object_lookup_any (dns_section, "fake_records",
  545. "fake_replies", NULL);
  546. if (fake_replies && ucl_object_type (fake_replies) == UCL_ARRAY) {
  547. const ucl_object_t *cur_arr;
  548. DL_FOREACH (fake_replies, cur_arr) {
  549. rspamd_process_fake_reply (cfg, dns_resolver, cur_arr);
  550. }
  551. }
  552. fails_cache_size = ucl_object_lookup (dns_section, "fails_cache_size");
  553. if (fails_cache_size && ucl_object_type (fails_cache_size) == UCL_INT) {
  554. dns_resolver->fails_cache_time = default_fails_cache_time;
  555. fails_cache_time = ucl_object_lookup (dns_section, "fails_cache_time");
  556. if (fails_cache_time) {
  557. dns_resolver->fails_cache_time = ucl_object_todouble (fails_cache_time);
  558. }
  559. dns_resolver->fails_cache = rspamd_lru_hash_new_full (
  560. ucl_object_toint (fails_cache_size),
  561. g_free, (GDestroyNotify)rdns_request_release,
  562. rspamd_dns_fail_hash, rspamd_dns_fail_equal);
  563. }
  564. }
  565. struct rspamd_dns_resolver *
  566. rspamd_dns_resolver_init (rspamd_logger_t *logger,
  567. struct ev_loop *ev_base,
  568. struct rspamd_config *cfg)
  569. {
  570. struct rspamd_dns_resolver *dns_resolver;
  571. dns_resolver = g_malloc0 (sizeof (struct rspamd_dns_resolver));
  572. dns_resolver->event_loop = ev_base;
  573. if (cfg != NULL) {
  574. dns_resolver->request_timeout = cfg->dns_timeout;
  575. dns_resolver->max_retransmits = cfg->dns_retransmits;
  576. }
  577. else {
  578. dns_resolver->request_timeout = 1;
  579. dns_resolver->max_retransmits = 2;
  580. }
  581. dns_resolver->r = rdns_resolver_new ();
  582. rdns_bind_libev (dns_resolver->r, dns_resolver->event_loop);
  583. if (cfg != NULL) {
  584. rdns_resolver_set_log_level (dns_resolver->r, cfg->log_level);
  585. dns_resolver->cfg = cfg;
  586. rdns_resolver_set_dnssec (dns_resolver->r, cfg->enable_dnssec);
  587. if (cfg->nameservers == NULL) {
  588. /* Parse resolv.conf */
  589. dns_resolver->ups = rspamd_upstreams_create (cfg->ups_ctx);
  590. rspamd_upstreams_set_flags (dns_resolver->ups,
  591. RSPAMD_UPSTREAM_FLAG_NORESOLVE);
  592. rspamd_upstreams_set_rotation (dns_resolver->ups,
  593. RSPAMD_UPSTREAM_MASTER_SLAVE);
  594. if (!rdns_resolver_parse_resolv_conf_cb (dns_resolver->r,
  595. "/etc/resolv.conf",
  596. rspamd_dns_resolv_conf_on_server,
  597. dns_resolver)) {
  598. msg_err ("cannot parse resolv.conf and no nameservers defined, "
  599. "so no ways to resolve addresses");
  600. rdns_resolver_release (dns_resolver->r);
  601. dns_resolver->r = NULL;
  602. return dns_resolver;
  603. }
  604. /* Use normal resolv.conf rules */
  605. rspamd_upstreams_foreach (dns_resolver->ups, rspamd_dns_server_reorder,
  606. dns_resolver);
  607. }
  608. else {
  609. dns_resolver->ups = rspamd_upstreams_create (cfg->ups_ctx);
  610. rspamd_upstreams_set_flags (dns_resolver->ups,
  611. RSPAMD_UPSTREAM_FLAG_NORESOLVE);
  612. if (!rspamd_upstreams_from_ucl (dns_resolver->ups, cfg->nameservers,
  613. 53, dns_resolver)) {
  614. msg_err_config ("cannot parse DNS nameservers definitions");
  615. rdns_resolver_release (dns_resolver->r);
  616. dns_resolver->r = NULL;
  617. return dns_resolver;
  618. }
  619. }
  620. rspamd_upstreams_foreach (dns_resolver->ups, rspamd_dns_server_init,
  621. dns_resolver);
  622. rdns_resolver_set_upstream_lib (dns_resolver->r, &rspamd_ups_ctx,
  623. dns_resolver->ups);
  624. cfg->dns_resolver = dns_resolver;
  625. if (cfg->rcl_obj) {
  626. /* Configure additional options */
  627. const ucl_object_t *opts_section, *dns_section, *tmp;
  628. opts_section = ucl_object_lookup (cfg->rcl_obj, "options");
  629. if (opts_section) {
  630. /* TODO: implement a more simple merge logic */
  631. DL_FOREACH (opts_section, tmp) {
  632. dns_section = ucl_object_lookup (opts_section, "dns");
  633. if (dns_section) {
  634. rspamd_dns_resolver_config_ucl (cfg, dns_resolver,
  635. dns_section);
  636. }
  637. }
  638. }
  639. }
  640. }
  641. rdns_resolver_set_logger (dns_resolver->r, rspamd_rnds_log_bridge, logger);
  642. rdns_resolver_init (dns_resolver->r);
  643. return dns_resolver;
  644. }
  645. void
  646. rspamd_dns_resolver_deinit (struct rspamd_dns_resolver *resolver)
  647. {
  648. if (resolver) {
  649. if (resolver->r) {
  650. rdns_resolver_release (resolver->r);
  651. }
  652. if (resolver->ups) {
  653. rspamd_upstreams_destroy (resolver->ups);
  654. }
  655. if (resolver->fails_cache) {
  656. rspamd_lru_hash_destroy (resolver->fails_cache);
  657. }
  658. g_free (resolver);
  659. }
  660. }
  661. static struct rdns_upstream_elt*
  662. rspamd_dns_select_upstream (const char *name,
  663. size_t len, void *ups_data)
  664. {
  665. struct upstream_list *ups = ups_data;
  666. struct upstream *up;
  667. up = rspamd_upstream_get (ups, RSPAMD_UPSTREAM_ROUND_ROBIN, name, len);
  668. if (up) {
  669. msg_debug ("select %s", rspamd_upstream_name (up));
  670. return rspamd_upstream_get_data (up);
  671. }
  672. return NULL;
  673. }
  674. static struct rdns_upstream_elt*
  675. rspamd_dns_select_upstream_retransmit (
  676. const char *name,
  677. size_t len,
  678. struct rdns_upstream_elt *prev_elt,
  679. void *ups_data)
  680. {
  681. struct upstream_list *ups = ups_data;
  682. struct upstream *up;
  683. if (prev_elt) {
  684. up = rspamd_upstream_get_except (ups, (struct upstream *)prev_elt->lib_data,
  685. RSPAMD_UPSTREAM_MASTER_SLAVE, name, len);
  686. }
  687. else {
  688. up = rspamd_upstream_get_forced (ups, RSPAMD_UPSTREAM_RANDOM, name, len);
  689. }
  690. if (up) {
  691. msg_debug ("select forced %s", rspamd_upstream_name (up));
  692. return rspamd_upstream_get_data (up);
  693. }
  694. return NULL;
  695. }
  696. static void
  697. rspamd_dns_upstream_ok (struct rdns_upstream_elt *elt,
  698. void *ups_data)
  699. {
  700. struct upstream *up = elt->lib_data;
  701. rspamd_upstream_ok (up);
  702. }
  703. static void
  704. rspamd_dns_upstream_fail (struct rdns_upstream_elt *elt,
  705. void *ups_data, const gchar *reason)
  706. {
  707. struct upstream *up = elt->lib_data;
  708. rspamd_upstream_fail (up, FALSE, reason);
  709. }
  710. static unsigned int
  711. rspamd_dns_upstream_count (void *ups_data)
  712. {
  713. struct upstream_list *ups = ups_data;
  714. return rspamd_upstreams_alive (ups);
  715. }