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.

lmtp.c 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. /*
  2. * Copyright (c) 2009-2012, Vsevolod Stakhov
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
  14. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  17. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. */
  24. #include "config.h"
  25. #include "buffer.h"
  26. #include "main.h"
  27. #include "lmtp.h"
  28. #include "lmtp_proto.h"
  29. #include "cfg_file.h"
  30. #include "util.h"
  31. #include "url.h"
  32. #include "message.h"
  33. static gchar greetingbuf[1024];
  34. static struct timeval io_tv;
  35. static gboolean lmtp_write_socket (void *arg);
  36. void start_lmtp (struct rspamd_worker *worker);
  37. worker_t lmtp_worker = {
  38. "controller", /* Name */
  39. NULL, /* Init function */
  40. start_lmtp, /* Start function */
  41. TRUE, /* Has socket */
  42. FALSE, /* Non unique */
  43. FALSE, /* Non threaded */
  44. TRUE /* Killable */
  45. };
  46. #ifndef HAVE_SA_SIGINFO
  47. static void
  48. sig_handler (gint signo)
  49. #else
  50. static void
  51. sig_handler (gint signo, siginfo_t *info, void *unused)
  52. #endif
  53. {
  54. switch (signo) {
  55. case SIGINT:
  56. case SIGTERM:
  57. _exit (1);
  58. break;
  59. }
  60. }
  61. /*
  62. * Config reload is designed by sending sigusr to active workers and pending shutdown of them
  63. */
  64. static void
  65. sigusr2_handler (gint fd, short what, void *arg)
  66. {
  67. struct rspamd_worker *worker = (struct rspamd_worker *)arg;
  68. /* Do not accept new connections, preparing to end worker's process */
  69. struct timeval tv;
  70. tv.tv_sec = SOFT_SHUTDOWN_TIME;
  71. tv.tv_usec = 0;
  72. event_del (&worker->sig_ev_usr1);
  73. event_del (&worker->sig_ev_usr2);
  74. event_del (&worker->bind_ev);
  75. msg_info ("lmtp worker's shutdown is pending in %d sec",
  76. SOFT_SHUTDOWN_TIME);
  77. event_loopexit (&tv);
  78. return;
  79. }
  80. /*
  81. * Reopen log is designed by sending sigusr1 to active workers and pending shutdown of them
  82. */
  83. static void
  84. sigusr1_handler (gint fd, short what, void *arg)
  85. {
  86. struct rspamd_worker *worker = (struct rspamd_worker *) arg;
  87. rspamd_log_reopen (worker->srv->logger);
  88. return;
  89. }
  90. /*
  91. * Destructor for recipients list
  92. */
  93. static void
  94. rcpt_destruct (void *pointer)
  95. {
  96. struct rspamd_task *task = (struct rspamd_task *)pointer;
  97. if (task->rcpt) {
  98. g_list_free (task->rcpt);
  99. }
  100. }
  101. /*
  102. * Free all structures of lmtp proto
  103. */
  104. static void
  105. free_lmtp_task (struct rspamd_lmtp_proto *lmtp, gboolean is_soft)
  106. {
  107. GList *part;
  108. struct mime_part *p;
  109. struct rspamd_task *task = lmtp->task;
  110. if (lmtp) {
  111. debug_task ("free pointer %p", lmtp->task);
  112. while ((part = g_list_first (lmtp->task->parts))) {
  113. lmtp->task->parts = g_list_remove_link (lmtp->task->parts, part);
  114. p = (struct mime_part *)part->data;
  115. g_byte_array_free (p->content, FALSE);
  116. g_list_free_1 (part);
  117. }
  118. rspamd_mempool_delete (lmtp->task->task_pool);
  119. if (is_soft) {
  120. /* Plan dispatcher shutdown */
  121. lmtp->task->dispatcher->wanna_die = 1;
  122. }
  123. else {
  124. rspamd_remove_dispatcher (lmtp->task->dispatcher);
  125. }
  126. close (lmtp->task->sock);
  127. g_free (lmtp->task);
  128. g_free (lmtp);
  129. }
  130. }
  131. /*
  132. * Callback that is called when there is data to read in buffer
  133. */
  134. static gboolean
  135. lmtp_read_socket (rspamd_fstring_t * in, void *arg)
  136. {
  137. struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
  138. struct rspamd_task *task = lmtp->task;
  139. ssize_t r;
  140. switch (task->state) {
  141. case READ_COMMAND:
  142. case READ_HEADER:
  143. if (read_lmtp_input_line (lmtp, in) != 0) {
  144. msg_info ("closing lmtp connection due to protocol error");
  145. lmtp->task->state = CLOSING_CONNECTION;
  146. }
  147. /* Task was read, recall read handler once more with new state to process message and write reply */
  148. if (task->state == READ_MESSAGE) {
  149. lmtp_read_socket (in, arg);
  150. }
  151. break;
  152. case READ_MESSAGE:
  153. r = process_message (lmtp->task);
  154. r = rspamd_process_filters (lmtp->task);
  155. if (r == -1) {
  156. return FALSE;
  157. }
  158. else if (r == 0) {
  159. task->state = WAIT_FILTER;
  160. rspamd_dispatcher_pause (lmtp->task->dispatcher);
  161. }
  162. else {
  163. rspamd_process_statistics (lmtp->task);
  164. task->state = WRITE_REPLY;
  165. lmtp_write_socket (lmtp);
  166. }
  167. break;
  168. default:
  169. debug_task ("invalid state while reading from socket %d",
  170. lmtp->task->state);
  171. break;
  172. }
  173. return TRUE;
  174. }
  175. /*
  176. * Callback for socket writing
  177. */
  178. static gboolean
  179. lmtp_write_socket (void *arg)
  180. {
  181. struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
  182. struct rspamd_task *task = lmtp->task;
  183. switch (lmtp->task->state) {
  184. case WRITE_REPLY:
  185. if (write_lmtp_reply (lmtp) == 1) {
  186. lmtp->task->state = WAIT_FILTER;
  187. }
  188. else {
  189. lmtp->task->state = CLOSING_CONNECTION;
  190. }
  191. break;
  192. case WRITE_ERROR:
  193. write_lmtp_reply (lmtp);
  194. lmtp->task->state = CLOSING_CONNECTION;
  195. break;
  196. case CLOSING_CONNECTION:
  197. debug_task ("normally closing connection");
  198. free_lmtp_task (lmtp, TRUE);
  199. return FALSE;
  200. break;
  201. default:
  202. debug_task ("invalid state while writing to socket %d",
  203. lmtp->task->state);
  204. break;
  205. }
  206. return TRUE;
  207. }
  208. /*
  209. * Called if something goes wrong
  210. */
  211. static void
  212. lmtp_err_socket (GError * err, void *arg)
  213. {
  214. struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
  215. msg_info ("abnormally closing connection, error: %s", err->message);
  216. /* Free buffers */
  217. free_lmtp_task (lmtp, FALSE);
  218. }
  219. /*
  220. * Accept new connection and construct task
  221. */
  222. static void
  223. accept_socket (gint fd, short what, void *arg)
  224. {
  225. struct rspamd_worker *worker = (struct rspamd_worker *)arg;
  226. union sa_union su;
  227. struct rspamd_task *new_task;
  228. struct rspamd_lmtp_proto *lmtp;
  229. socklen_t addrlen = sizeof (su.ss);
  230. gint nfd;
  231. if ((nfd =
  232. accept_from_socket (fd, (struct sockaddr *)&su.ss, &addrlen)) == -1) {
  233. msg_warn ("accept failed: %s", strerror (errno));
  234. return;
  235. }
  236. lmtp = g_malloc (sizeof (struct rspamd_lmtp_proto));
  237. new_task = rspamd_task_new (worker);
  238. if (su.ss.ss_family == AF_UNIX) {
  239. msg_info ("accepted connection from unix socket");
  240. new_task->client_addr.s_addr = INADDR_NONE;
  241. }
  242. else if (su.ss.ss_family == AF_INET) {
  243. msg_info ("accepted connection from %s port %d",
  244. inet_ntoa (su.s4.sin_addr), ntohs (su.s4.sin_port));
  245. memcpy (&new_task->client_addr, &su.s4.sin_addr,
  246. sizeof (struct in_addr));
  247. }
  248. new_task->sock = nfd;
  249. new_task->cfg = worker->srv->cfg;
  250. new_task->task_pool = rspamd_mempool_new (rspamd_mempool_suggest_size ());
  251. /* Add destructor for recipients list (it would be better to use anonymous function here */
  252. rspamd_mempool_add_destructor (new_task->task_pool,
  253. (rspamd_mempool_destruct_t) rcpt_destruct, new_task);
  254. new_task->results = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
  255. new_task->ev_base = worker->ctx;
  256. rspamd_mempool_add_destructor (new_task->task_pool,
  257. (rspamd_mempool_destruct_t) g_hash_table_destroy, new_task->results);
  258. worker->srv->stat->connections_count++;
  259. lmtp->task = new_task;
  260. lmtp->state = LMTP_READ_LHLO;
  261. /* Set up dispatcher */
  262. new_task->dispatcher = rspamd_create_dispatcher (new_task->ev_base,
  263. nfd,
  264. BUFFER_LINE,
  265. lmtp_read_socket,
  266. lmtp_write_socket,
  267. lmtp_err_socket,
  268. &io_tv,
  269. (void *)lmtp);
  270. new_task->dispatcher->peer_addr = new_task->client_addr.s_addr;
  271. if (!rspamd_dispatcher_write (lmtp->task->dispatcher, greetingbuf,
  272. strlen (greetingbuf), FALSE, FALSE)) {
  273. msg_warn ("cannot write greeting");
  274. }
  275. }
  276. /*
  277. * Start lmtp worker process
  278. */
  279. void
  280. start_lmtp (struct rspamd_worker *worker)
  281. {
  282. struct sigaction signals;
  283. gchar *hostbuf;
  284. gsize hostmax;
  285. module_t **mod;
  286. worker->srv->pid = getpid ();
  287. worker->ctx = event_init ();
  288. rspamd_signals_init (&signals, sig_handler);
  289. sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
  290. /* SIGUSR2 handler */
  291. signal_set (&worker->sig_ev_usr2, SIGUSR2, sigusr2_handler,
  292. (void *) worker);
  293. event_base_set (worker->ctx, &worker->sig_ev_usr2);
  294. signal_add (&worker->sig_ev_usr2, NULL);
  295. /* SIGUSR1 handler */
  296. signal_set (&worker->sig_ev_usr1, SIGUSR1, sigusr1_handler,
  297. (void *) worker);
  298. event_base_set (worker->ctx, &worker->sig_ev_usr1);
  299. signal_add (&worker->sig_ev_usr1, NULL);
  300. /* Accept event */
  301. event_set (&worker->bind_ev,
  302. worker->cf->listen_sock,
  303. EV_READ | EV_PERSIST,
  304. accept_socket,
  305. (void *)worker);
  306. event_base_set (worker->ctx, &worker->bind_ev);
  307. event_add (&worker->bind_ev, NULL);
  308. /* Perform modules configuring */
  309. mod = &modules[0];
  310. while (*mod) {
  311. (*mod)->module_config_func (worker->srv->cfg);
  312. mod++;
  313. }
  314. /* Fill hostname buf */
  315. hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
  316. hostbuf = alloca (hostmax);
  317. gethostname (hostbuf, hostmax);
  318. hostbuf[hostmax - 1] = '\0';
  319. rspamd_snprintf (greetingbuf,
  320. sizeof (greetingbuf),
  321. "%d rspamd version %s LMTP on %s Ready\r\n",
  322. LMTP_OK,
  323. RVERSION,
  324. hostbuf);
  325. io_tv.tv_sec = 60000;
  326. io_tv.tv_usec = 0;
  327. gperf_profiler_init (worker->srv->cfg, "lmtp");
  328. event_base_loop (worker->ctx, 0);
  329. exit (EXIT_SUCCESS);
  330. }
  331. /*
  332. * vi:ts=4
  333. */