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

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