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.c 4.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /*-
  2. * Licensed under the Apache License, Version 2.0 (the "License");
  3. * you may not use this file except in compliance with the License.
  4. * You may obtain a copy of the License at
  5. *
  6. * http://www.apache.org/licenses/LICENSE-2.0
  7. *
  8. * Unless required by applicable law or agreed to in writing, software
  9. * distributed under the License is distributed on an "AS IS" BASIS,
  10. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. * See the License for the specific language governing permissions and
  12. * limitations under the License.
  13. */
  14. #include "lua_common.h"
  15. #include "lua_dns_resolver.h"
  16. #include "lua_thread_pool.h"
  17. LUA_FUNCTION_DEF(dns, request);
  18. static const struct luaL_reg dns_f[] = {
  19. LUA_INTERFACE_DEF(dns, request),
  20. {"__tostring", rspamd_lua_class_tostring},
  21. {NULL, NULL}};
  22. static const char *M = "rspamd lua dns";
  23. void lua_dns_callback(struct rdns_reply *reply, void *arg);
  24. struct lua_rspamd_dns_cbdata {
  25. struct thread_entry *thread;
  26. struct rspamd_task *task;
  27. struct rspamd_dns_resolver *resolver;
  28. struct rspamd_symcache_dynamic_item *item;
  29. struct rspamd_async_session *s;
  30. };
  31. static int
  32. lua_dns_request(lua_State *L)
  33. {
  34. GError *err = NULL;
  35. struct rspamd_async_session *session = NULL;
  36. struct rspamd_config *cfg = NULL;
  37. struct lua_rspamd_dns_cbdata *cbdata = NULL;
  38. const char *to_resolve = NULL;
  39. const char *type_str = NULL;
  40. struct rspamd_task *task = NULL;
  41. rspamd_mempool_t *pool = NULL;
  42. int ret = 0;
  43. gboolean forced = FALSE;
  44. /* Check arguments */
  45. if (!rspamd_lua_parse_table_arguments(L, 1, &err,
  46. RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
  47. "*name=S;task=U{task};*type=S;forced=B;session=U{session};config=U{config}",
  48. &to_resolve,
  49. &task,
  50. &type_str,
  51. &forced,
  52. &session,
  53. &cfg)) {
  54. if (err) {
  55. ret = luaL_error(L, "invalid arguments: %s", err->message);
  56. g_error_free(err);
  57. return ret;
  58. }
  59. return luaL_error(L, "invalid arguments");
  60. }
  61. if (task) {
  62. session = task->s;
  63. pool = task->task_pool;
  64. cfg = task->cfg;
  65. }
  66. else if (session && cfg) {
  67. pool = cfg->cfg_pool;
  68. }
  69. else {
  70. return luaL_error(L, "invalid arguments: either task or session/config should be set");
  71. }
  72. enum rdns_request_type type = rdns_type_fromstr(type_str);
  73. if (type == RDNS_REQUEST_INVALID) {
  74. return luaL_error(L, "invalid arguments: this record type is not supported");
  75. }
  76. cbdata = rspamd_mempool_alloc0(pool, sizeof(*cbdata));
  77. cbdata->task = task;
  78. if (type == RDNS_REQUEST_PTR) {
  79. char *ptr_str;
  80. ptr_str = rdns_generate_ptr_from_str(to_resolve);
  81. if (ptr_str == NULL) {
  82. msg_err_task_check("wrong resolve string to PTR request: %s",
  83. to_resolve);
  84. lua_pushnil(L);
  85. return 1;
  86. }
  87. to_resolve = rspamd_mempool_strdup(pool, ptr_str);
  88. free(ptr_str);
  89. }
  90. if (task == NULL) {
  91. ret = (rspamd_dns_resolver_request(cfg->dns_resolver,
  92. session,
  93. pool,
  94. lua_dns_callback,
  95. cbdata,
  96. type,
  97. to_resolve) != NULL);
  98. }
  99. else {
  100. if (forced) {
  101. ret = rspamd_dns_resolver_request_task_forced(task,
  102. lua_dns_callback,
  103. cbdata,
  104. type,
  105. to_resolve);
  106. }
  107. else {
  108. ret = rspamd_dns_resolver_request_task(task,
  109. lua_dns_callback,
  110. cbdata,
  111. type,
  112. to_resolve);
  113. }
  114. }
  115. if (ret) {
  116. cbdata->thread = lua_thread_pool_get_running_entry(cfg->lua_thread_pool);
  117. cbdata->s = session;
  118. if (task) {
  119. cbdata->item = rspamd_symcache_get_cur_item(task);
  120. rspamd_symcache_item_async_inc(task, cbdata->item, M);
  121. }
  122. return lua_thread_yield(cbdata->thread, 0);
  123. }
  124. else {
  125. lua_pushnil(L);
  126. return 1;
  127. }
  128. }
  129. void lua_dns_callback(struct rdns_reply *reply, void *arg)
  130. {
  131. struct lua_rspamd_dns_cbdata *cbdata = arg;
  132. lua_State *L = cbdata->thread->lua_state;
  133. if (reply->code != RDNS_RC_NOERROR) {
  134. lua_pushboolean(L, false);
  135. lua_pushstring(L, rdns_strerror(reply->code));
  136. }
  137. else {
  138. lua_push_dns_reply(L, reply);
  139. lua_pushboolean(L, reply->flags & RDNS_AUTH);
  140. lua_setfield(L, -3, "authenticated");
  141. lua_pushboolean(L, reply->flags & RDNS_TRUNCATED);
  142. lua_setfield(L, -3, "truncated");
  143. /* result 1 - not and error */
  144. lua_pushboolean(L, true);
  145. /* push table into stack, result 2 - results itself */
  146. lua_pushvalue(L, -3);
  147. }
  148. lua_thread_resume(cbdata->thread, 2);
  149. if (cbdata->item) {
  150. rspamd_symcache_item_async_dec_check(cbdata->task, cbdata->item, M);
  151. }
  152. }
  153. static int
  154. lua_load_dns(lua_State *L)
  155. {
  156. lua_newtable(L);
  157. luaL_register(L, NULL, dns_f);
  158. return 1;
  159. }
  160. void luaopen_dns(lua_State *L)
  161. {
  162. rspamd_lua_add_preload(L, "rspamd_dns", lua_load_dns);
  163. }