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.

lua_dns_resolver.c 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724
  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 "lua_common.h"
  17. #include "lua_thread_pool.h"
  18. #include "utlist.h"
  19. /***
  20. * @module rspamd_resolver
  21. * This module allows to resolve DNS names from LUA code. All resolving is executed
  22. * asynchronously. Here is an example of name resolution:
  23. * @example
  24. local function symbol_callback(task)
  25. local host = 'example.com'
  26. local function dns_cb(resolver, to_resolve, results, err, _, authenticated)
  27. if not results then
  28. rspamd_logger.infox('DNS resolving of %1 failed: %2', host, err)
  29. return
  30. end
  31. for _,r in ipairs(results) do
  32. -- r is of type rspamd{ip} here, but it can be converted to string
  33. rspamd_logger.infox('Resolved %1 to %2', host, tostring(r))
  34. end
  35. end
  36. task:get_resolver():resolve_a({task = task, name = host, callback = dns_cb})
  37. end
  38. */
  39. static const gchar *M = "rspamd lua dns resolver";
  40. /* Lua bindings */
  41. LUA_FUNCTION_DEF (dns_resolver, init);
  42. LUA_FUNCTION_DEF (dns_resolver, resolve_a);
  43. LUA_FUNCTION_DEF (dns_resolver, resolve_ptr);
  44. LUA_FUNCTION_DEF (dns_resolver, resolve_txt);
  45. LUA_FUNCTION_DEF (dns_resolver, resolve_mx);
  46. LUA_FUNCTION_DEF (dns_resolver, resolve_ns);
  47. LUA_FUNCTION_DEF (dns_resolver, resolve);
  48. void lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply);
  49. static const struct luaL_reg dns_resolverlib_f[] = {
  50. LUA_INTERFACE_DEF (dns_resolver, init),
  51. {NULL, NULL}
  52. };
  53. static const struct luaL_reg dns_resolverlib_m[] = {
  54. LUA_INTERFACE_DEF (dns_resolver, resolve_a),
  55. LUA_INTERFACE_DEF (dns_resolver, resolve_ptr),
  56. LUA_INTERFACE_DEF (dns_resolver, resolve_txt),
  57. LUA_INTERFACE_DEF (dns_resolver, resolve_mx),
  58. LUA_INTERFACE_DEF (dns_resolver, resolve_ns),
  59. LUA_INTERFACE_DEF (dns_resolver, resolve),
  60. {"__tostring", rspamd_lua_class_tostring},
  61. {NULL, NULL}
  62. };
  63. struct rspamd_dns_resolver *
  64. lua_check_dns_resolver (lua_State * L, gint pos)
  65. {
  66. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{resolver}");
  67. luaL_argcheck (L, ud != NULL, pos, "'resolver' expected");
  68. return ud ? *((struct rspamd_dns_resolver **)ud) : NULL;
  69. }
  70. struct lua_dns_cbdata {
  71. struct rspamd_task *task;
  72. rspamd_mempool_t *pool;
  73. struct rspamd_dns_resolver *resolver;
  74. gint cbref;
  75. gchar *to_resolve;
  76. gchar *user_str;
  77. struct rspamd_symcache_item *item;
  78. struct rspamd_async_session *s;
  79. };
  80. static int
  81. lua_dns_get_type (lua_State *L, int argno)
  82. {
  83. int type = RDNS_REQUEST_A;
  84. const gchar *strtype;
  85. if (lua_type (L, argno) != LUA_TSTRING) {
  86. lua_pushvalue (L, argno);
  87. lua_gettable (L, lua_upvalueindex (1));
  88. type = lua_tonumber (L, -1);
  89. lua_pop (L, 1);
  90. if (type == 0) {
  91. rspamd_lua_typerror (L, argno, "dns_request_type");
  92. }
  93. }
  94. else {
  95. strtype = lua_tostring (L, argno);
  96. if (g_ascii_strcasecmp (strtype, "a") == 0) {
  97. type = RDNS_REQUEST_A;
  98. }
  99. else if (g_ascii_strcasecmp (strtype, "aaaa") == 0) {
  100. type = RDNS_REQUEST_AAAA;
  101. }
  102. else if (g_ascii_strcasecmp (strtype, "mx") == 0) {
  103. type = RDNS_REQUEST_MX;
  104. }
  105. else if (g_ascii_strcasecmp (strtype, "txt") == 0) {
  106. type = RDNS_REQUEST_TXT;
  107. }
  108. else if (g_ascii_strcasecmp (strtype, "ptr") == 0) {
  109. type = RDNS_REQUEST_PTR;
  110. }
  111. else if (g_ascii_strcasecmp (strtype, "soa") == 0) {
  112. type = RDNS_REQUEST_SOA;
  113. }
  114. else {
  115. msg_err ("bad DNS type: %s", strtype);
  116. }
  117. }
  118. return type;
  119. }
  120. static void
  121. lua_dns_resolver_callback (struct rdns_reply *reply, gpointer arg)
  122. {
  123. struct lua_dns_cbdata *cd = arg;
  124. struct rspamd_dns_resolver **presolver;
  125. lua_State *L;
  126. struct lua_callback_state cbs;
  127. rspamd_mempool_t *pool;
  128. gint err_idx;
  129. GString *tb = NULL;
  130. pool = cd->pool;
  131. lua_thread_pool_prepare_callback (cd->resolver->cfg->lua_thread_pool, &cbs);
  132. L = cbs.L;
  133. lua_pushcfunction (L, &rspamd_lua_traceback);
  134. err_idx = lua_gettop (L);
  135. lua_rawgeti (L, LUA_REGISTRYINDEX, cd->cbref);
  136. presolver = lua_newuserdata (L, sizeof (gpointer));
  137. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  138. *presolver = cd->resolver;
  139. lua_pushstring (L, cd->to_resolve);
  140. lua_push_dns_reply (L, reply);
  141. /*
  142. * 1 - resolver
  143. * 2 - to_resolve
  144. * 3 - entries | nil
  145. * 4 - error | nil
  146. * 5 - user_str
  147. * 6 - reply->authenticated
  148. * 7 - server
  149. */
  150. if (reply->code != RDNS_RC_NOERROR) {
  151. lua_pushnil (L);
  152. lua_pushstring (L, rdns_strerror (reply->code));
  153. }
  154. if (cd->user_str != NULL) {
  155. lua_pushstring (L, cd->user_str);
  156. }
  157. else {
  158. lua_pushnil (L);
  159. }
  160. lua_pushboolean (L, reply->authenticated);
  161. const gchar *servname = rdns_request_get_server (reply->request);
  162. if (servname) {
  163. lua_pushstring (L, servname);
  164. }
  165. else {
  166. lua_pushnil (L);
  167. }
  168. if (cd->item) {
  169. /* We also need to restore the item in case there are some chains */
  170. rspamd_symcache_set_cur_item (cd->task, cd->item);
  171. }
  172. if (lua_pcall (L, 7, 0, err_idx) != 0) {
  173. tb = lua_touserdata (L, -1);
  174. if (tb) {
  175. msg_err_pool_check ("call to dns callback failed: %s", tb->str);
  176. g_string_free (tb, TRUE);
  177. }
  178. }
  179. lua_settop (L, err_idx - 1);
  180. /* Unref function */
  181. luaL_unref (L, LUA_REGISTRYINDEX, cd->cbref);
  182. lua_thread_pool_restore_callback (&cbs);
  183. if (cd->item) {
  184. rspamd_symcache_item_async_dec_check (cd->task, cd->item, M);
  185. }
  186. if (!cd->pool) {
  187. g_free (cd->to_resolve);
  188. g_free (cd->user_str);
  189. g_free (cd);
  190. }
  191. }
  192. void
  193. lua_push_dns_reply (lua_State *L, const struct rdns_reply *reply)
  194. {
  195. gint i = 0, naddrs = 0;
  196. struct rdns_reply_entry *elt;
  197. rspamd_inet_addr_t *addr;
  198. if (reply->code == RDNS_RC_NOERROR) {
  199. LL_FOREACH (reply->entries, elt) {
  200. naddrs ++;
  201. }
  202. lua_createtable (L, naddrs, 0);
  203. LL_FOREACH (reply->entries, elt)
  204. {
  205. switch (elt->type) {
  206. case RDNS_REQUEST_A:
  207. addr = rspamd_inet_address_new (AF_INET, &elt->content.a.addr);
  208. rspamd_lua_ip_push (L, addr);
  209. rspamd_inet_address_free (addr);
  210. lua_rawseti (L, -2, ++i);
  211. break;
  212. case RDNS_REQUEST_AAAA:
  213. addr = rspamd_inet_address_new (AF_INET6, &elt->content.aaa.addr);
  214. rspamd_lua_ip_push (L, addr);
  215. rspamd_inet_address_free (addr);
  216. lua_rawseti (L, -2, ++i);
  217. break;
  218. case RDNS_REQUEST_NS:
  219. lua_pushstring (L, elt->content.ns.name);
  220. lua_rawseti (L, -2, ++i);
  221. break;
  222. case RDNS_REQUEST_PTR:
  223. lua_pushstring (L, elt->content.ptr.name);
  224. lua_rawseti (L, -2, ++i);
  225. break;
  226. case RDNS_REQUEST_TXT:
  227. case RDNS_REQUEST_SPF:
  228. lua_pushstring (L, elt->content.txt.data);
  229. lua_rawseti (L, -2, ++i);
  230. break;
  231. case RDNS_REQUEST_MX:
  232. /* mx['name'], mx['priority'] */
  233. lua_createtable (L, 0, 2);
  234. rspamd_lua_table_set (L, "name", elt->content.mx.name);
  235. lua_pushstring (L, "priority");
  236. lua_pushinteger (L, elt->content.mx.priority);
  237. lua_settable (L, -3);
  238. lua_rawseti (L, -2, ++i);
  239. break;
  240. case RDNS_REQUEST_SOA:
  241. lua_createtable (L, 0, 7);
  242. rspamd_lua_table_set (L, "ns", elt->content.soa.mname);
  243. rspamd_lua_table_set (L, "contact", elt->content.soa.admin);
  244. lua_pushstring (L, "serial");
  245. lua_pushinteger (L, elt->content.soa.serial);
  246. lua_settable (L, -3);
  247. lua_pushstring (L, "refresh");
  248. lua_pushinteger (L, elt->content.soa.refresh);
  249. lua_settable (L, -3);
  250. lua_pushstring (L, "retry");
  251. lua_pushinteger (L, elt->content.soa.retry);
  252. lua_settable (L, -3);
  253. lua_pushstring (L, "expiry");
  254. lua_pushinteger (L, elt->content.soa.expire);
  255. lua_settable (L, -3);
  256. /* Negative TTL */
  257. lua_pushstring (L, "nx");
  258. lua_pushinteger (L, elt->content.soa.minimum);
  259. lua_settable (L, -3);
  260. lua_rawseti (L, -2, ++i);
  261. break;
  262. default:
  263. continue;
  264. }
  265. }
  266. lua_pushnil (L);
  267. }
  268. }
  269. /***
  270. * @function rspamd_resolver.init(ev_base, config)
  271. * @param {event_base} ev_base event base used for asynchronous events
  272. * @param {rspamd_config} config rspamd configuration parameters
  273. * @return {rspamd_resolver} new resolver object associated with the specified base
  274. */
  275. static int
  276. lua_dns_resolver_init (lua_State *L)
  277. {
  278. struct rspamd_dns_resolver *resolver, **presolver;
  279. struct rspamd_config *cfg, **pcfg;
  280. struct event_base *base, **pbase;
  281. /* Check args */
  282. pbase = rspamd_lua_check_udata (L, 1, "rspamd{ev_base}");
  283. luaL_argcheck (L, pbase != NULL, 1, "'ev_base' expected");
  284. base = pbase ? *(pbase) : NULL;
  285. pcfg = rspamd_lua_check_udata (L, 2, "rspamd{config}");
  286. luaL_argcheck (L, pcfg != NULL, 2, "'config' expected");
  287. cfg = pcfg ? *(pcfg) : NULL;
  288. if (base != NULL && cfg != NULL) {
  289. resolver = rspamd_dns_resolver_init (NULL, base, cfg);
  290. if (resolver) {
  291. presolver = lua_newuserdata (L, sizeof (gpointer));
  292. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  293. *presolver = resolver;
  294. }
  295. else {
  296. lua_pushnil (L);
  297. }
  298. }
  299. else {
  300. lua_pushnil (L);
  301. }
  302. return 1;
  303. }
  304. static int
  305. lua_dns_resolver_resolve_common (lua_State *L,
  306. struct rspamd_dns_resolver *resolver,
  307. enum rdns_request_type type,
  308. int first)
  309. {
  310. LUA_TRACE_POINT;
  311. struct rspamd_async_session *session = NULL;
  312. rspamd_mempool_t *pool = NULL;
  313. const gchar *to_resolve = NULL, *user_str = NULL;
  314. struct lua_dns_cbdata *cbdata;
  315. gint cbref = -1, ret;
  316. struct rspamd_task *task = NULL;
  317. GError *err = NULL;
  318. gboolean forced = FALSE;
  319. struct rspamd_symcache_item *item = NULL;
  320. /* Check arguments */
  321. if (!rspamd_lua_parse_table_arguments (L, first, &err,
  322. "session=U{session};mempool=U{mempool};*name=S;*callback=F;"
  323. "option=S;task=U{task};forced=B",
  324. &session, &pool, &to_resolve, &cbref, &user_str, &task, &forced)) {
  325. if (err) {
  326. ret = luaL_error (L, "invalid arguments: %s", err->message);
  327. g_error_free (err);
  328. return ret;
  329. }
  330. return luaL_error (L, "invalid arguments");
  331. }
  332. if (task) {
  333. pool = task->task_pool;
  334. session = task->s;
  335. item = rspamd_symcache_get_cur_item (task);
  336. }
  337. if (to_resolve != NULL) {
  338. if (pool != NULL) {
  339. cbdata = rspamd_mempool_alloc0 (pool, sizeof (struct lua_dns_cbdata));
  340. cbdata->user_str = rspamd_mempool_strdup (pool, user_str);
  341. if (type != RDNS_REQUEST_PTR) {
  342. cbdata->to_resolve = rspamd_mempool_strdup (pool, to_resolve);
  343. }
  344. else {
  345. char *ptr_str;
  346. ptr_str = rdns_generate_ptr_from_str (to_resolve);
  347. if (ptr_str == NULL) {
  348. msg_err_task_check ("wrong resolve string to PTR request: %s",
  349. to_resolve);
  350. goto err;
  351. }
  352. cbdata->to_resolve = rspamd_mempool_strdup (pool, ptr_str);
  353. to_resolve = cbdata->to_resolve;
  354. free (ptr_str);
  355. }
  356. }
  357. else {
  358. cbdata = g_malloc0 (sizeof (struct lua_dns_cbdata));
  359. cbdata->user_str = user_str ? g_strdup (user_str) : NULL;
  360. if (type != RDNS_REQUEST_PTR) {
  361. cbdata->to_resolve = g_strdup (to_resolve);
  362. }
  363. else {
  364. char *ptr_str;
  365. ptr_str = rdns_generate_ptr_from_str (to_resolve);
  366. if (ptr_str == NULL) {
  367. msg_err_task_check ("wrong resolve string to PTR request: %s",
  368. to_resolve);
  369. goto err;
  370. }
  371. cbdata->to_resolve = g_strdup (ptr_str);
  372. free (ptr_str);
  373. }
  374. }
  375. cbdata->resolver = resolver;
  376. cbdata->cbref = cbref;
  377. cbdata->task = task;
  378. cbdata->pool = pool;
  379. if (task == NULL) {
  380. if (rspamd_dns_resolver_request (resolver,
  381. session,
  382. pool,
  383. lua_dns_resolver_callback,
  384. cbdata,
  385. type,
  386. to_resolve)) {
  387. lua_pushboolean (L, TRUE);
  388. if (session) {
  389. cbdata->s = session;
  390. }
  391. }
  392. else {
  393. goto err;
  394. }
  395. }
  396. else {
  397. /* Fail-safety as this function can, in theory, call
  398. * lua_dns_resolver_callback without switching to the event loop
  399. */
  400. if (item) {
  401. rspamd_symcache_item_async_inc (task, item, M);
  402. }
  403. if (forced) {
  404. ret = rspamd_dns_resolver_request_task_forced (task,
  405. lua_dns_resolver_callback,
  406. cbdata,
  407. type,
  408. to_resolve);
  409. } else {
  410. ret = rspamd_dns_resolver_request_task (task,
  411. lua_dns_resolver_callback,
  412. cbdata,
  413. type,
  414. to_resolve);
  415. }
  416. if (ret) {
  417. cbdata->s = session;
  418. if (item) {
  419. cbdata->item = item;
  420. rspamd_symcache_item_async_inc (task, item, M);
  421. }
  422. /* callback was set up */
  423. lua_pushboolean (L, TRUE);
  424. }
  425. else {
  426. lua_pushnil (L);
  427. }
  428. if (item) {
  429. rspamd_symcache_item_async_dec_check (task, item, M);
  430. }
  431. }
  432. }
  433. else {
  434. return luaL_error (L, "invalid arguments to lua_resolve");
  435. }
  436. return 1;
  437. err:
  438. if (!pool) {
  439. /* Free resources */
  440. g_free (cbdata->to_resolve);
  441. g_free (cbdata->user_str);
  442. }
  443. lua_pushnil (L);
  444. return 1;
  445. }
  446. /***
  447. * @method resolver:resolve_a(table)
  448. * Resolve A record for a specified host.
  449. * Table elements:
  450. * * `task` - task element (preferred, required to track dependencies) -or-
  451. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  452. * * `mempool` - pool memory pool for storing intermediate data
  453. * * `name` - host name to resolve
  454. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  455. * * `forced` - true if needed to override notmal limit for DNS requests
  456. * @return {boolean} `true` if DNS request has been scheduled
  457. */
  458. static int
  459. lua_dns_resolver_resolve_a (lua_State *L)
  460. {
  461. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  462. if (dns_resolver) {
  463. return lua_dns_resolver_resolve_common (L,
  464. dns_resolver,
  465. RDNS_REQUEST_A,
  466. 2);
  467. }
  468. else {
  469. lua_pushnil (L);
  470. }
  471. return 1;
  472. }
  473. /***
  474. * @method resolver:resolve_ptr(table)
  475. * Resolve PTR record for a specified host.
  476. * Table elements:
  477. * * `task` - task element (preferred, required to track dependencies) -or-
  478. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  479. * * `mempool` - pool memory pool for storing intermediate data
  480. * * `name` - host name to resolve
  481. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  482. * * `forced` - true if needed to override notmal limit for DNS requests
  483. * @return {boolean} `true` if DNS request has been scheduled
  484. */
  485. static int
  486. lua_dns_resolver_resolve_ptr (lua_State *L)
  487. {
  488. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  489. if (dns_resolver) {
  490. return lua_dns_resolver_resolve_common (L,
  491. dns_resolver,
  492. RDNS_REQUEST_PTR,
  493. 2);
  494. }
  495. else {
  496. lua_pushnil (L);
  497. }
  498. return 1;
  499. }
  500. /***
  501. * @method resolver:resolve_txt(table)
  502. * Resolve TXT record for a specified host.
  503. * Table elements:
  504. * * `task` - task element (preferred, required to track dependencies) -or-
  505. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  506. * * `mempool` - pool memory pool for storing intermediate data
  507. * * `name` - host name to resolve
  508. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  509. * * `forced` - true if needed to override notmal limit for DNS requests
  510. * @return {boolean} `true` if DNS request has been scheduled
  511. */
  512. static int
  513. lua_dns_resolver_resolve_txt (lua_State *L)
  514. {
  515. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  516. if (dns_resolver) {
  517. return lua_dns_resolver_resolve_common (L,
  518. dns_resolver,
  519. RDNS_REQUEST_TXT,
  520. 2);
  521. }
  522. else {
  523. lua_pushnil (L);
  524. }
  525. return 1;
  526. }
  527. /***
  528. * @method resolver:resolve_mx(table)
  529. * Resolve MX record for a specified host.
  530. * Table elements:
  531. * * `task` - task element (preferred, required to track dependencies) -or-
  532. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  533. * * `mempool` - pool memory pool for storing intermediate data
  534. * * `name` - host name to resolve
  535. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  536. * * `forced` - true if needed to override notmal limit for DNS requests
  537. * @return {boolean} `true` if DNS request has been scheduled
  538. */
  539. static int
  540. lua_dns_resolver_resolve_mx (lua_State *L)
  541. {
  542. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  543. if (dns_resolver) {
  544. return lua_dns_resolver_resolve_common (L,
  545. dns_resolver,
  546. RDNS_REQUEST_MX,
  547. 2);
  548. }
  549. else {
  550. lua_pushnil (L);
  551. }
  552. return 1;
  553. }
  554. /***
  555. * @method resolver:resolve_ns(table)
  556. * Resolve NS records for a specified host.
  557. * Table elements:
  558. * * `task` - task element (preferred, required to track dependencies) -or-
  559. * * `session` - asynchronous session normally associated with rspamd task (`task:get_session()`)
  560. * * `mempool` - pool memory pool for storing intermediate data
  561. * * `name` - host name to resolve
  562. * * `callback` - callback callback function to be called upon name resolution is finished; must be of type `function (resolver, to_resolve, results, err)`
  563. * * `forced` - true if needed to override notmal limit for DNS requests
  564. * @return {boolean} `true` if DNS request has been scheduled
  565. */
  566. static int
  567. lua_dns_resolver_resolve_ns (lua_State *L)
  568. {
  569. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  570. if (dns_resolver) {
  571. return lua_dns_resolver_resolve_common (L,
  572. dns_resolver,
  573. RDNS_REQUEST_NS,
  574. 2);
  575. }
  576. else {
  577. lua_pushnil (L);
  578. }
  579. return 1;
  580. }
  581. /* XXX: broken currently */
  582. static int
  583. lua_dns_resolver_resolve (lua_State *L)
  584. {
  585. struct rspamd_dns_resolver *dns_resolver = lua_check_dns_resolver (L, 1);
  586. int type;
  587. type = lua_dns_get_type (L, 2);
  588. if (dns_resolver && type != 0) {
  589. return lua_dns_resolver_resolve_common (L, dns_resolver, type, 3);
  590. }
  591. else {
  592. lua_pushnil (L);
  593. }
  594. return 1;
  595. }
  596. static gint
  597. lua_load_dns_resolver (lua_State *L)
  598. {
  599. lua_newtable (L);
  600. luaL_register (L, NULL, dns_resolverlib_f);
  601. return 1;
  602. }
  603. void
  604. luaopen_dns_resolver (lua_State * L)
  605. {
  606. luaL_newmetatable (L, "rspamd{resolver}");
  607. lua_pushstring (L, "__index");
  608. lua_pushvalue (L, -2);
  609. lua_settable (L, -3);
  610. lua_pushstring (L, "class");
  611. lua_pushstring (L, "rspamd{resolver}");
  612. lua_rawset (L, -3);
  613. {
  614. LUA_ENUM (L, DNS_A, RDNS_REQUEST_A);
  615. LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR);
  616. LUA_ENUM (L, DNS_MX, RDNS_REQUEST_MX);
  617. LUA_ENUM (L, DNS_TXT, RDNS_REQUEST_TXT);
  618. LUA_ENUM (L, DNS_SRV, RDNS_REQUEST_SRV);
  619. LUA_ENUM (L, DNS_SPF, RDNS_REQUEST_SPF);
  620. LUA_ENUM (L, DNS_AAAA, RDNS_REQUEST_AAAA);
  621. LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA);
  622. }
  623. luaL_register (L, NULL, dns_resolverlib_m);
  624. rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
  625. lua_pop (L, 1); /* remove metatable from stack */
  626. }