summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2009-11-21 21:13:13 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2009-11-21 21:13:13 (GMT)
commit7f4dfb88f23a14f0b9603e648d4a1a459a6f26a3 (patch) (unidiff)
tree2beb9dee6a3a93130bd7f783a62afa20ed14e853
parentd20b648b02aa1f8caf9975a116c54e05d67d1c39 (diff)
downloadmailfromd-7f4dfb88f23a14f0b9603e648d4a1a459a6f26a3.tar.gz
mailfromd-7f4dfb88f23a14f0b9603e648d4a1a459a6f26a3.tar.bz2
Use callout resolver to handle timed-out callouts.mtax-cleanup
* mfd/savclt.c: New file. * mfd/Makefile.am (mailfromd_SOURCES): Add savclt.c * mfd/callout.c (transcript): Get ID as 1st arg. Remove static qualifier. All callers updated. * mfd/engine.c (method_strict) (method_standard): If callout returned mf_temp_failure, try to pass the task to the callout server, if one is defined. * mfd/mailfromd.h (transcript) (schedule_callout): New protos. (callout_server_sa, callout_server_sa_len): New externs. * mfd/main.c (force_remove): Initialize to 0 (see srvman.c) (server_config_stmt): New statements single-process and reuseaddr. (add_legacy_milter_port, server_section_parser): Pass flags to mfd_server_new. (mf_cfg_param): New statement `callout-url'. * mfd/savsrv.c (MF_SOURCE_NAME): Fixed. (verify, callout_session_server): Set proctitle. (callout_session_server): Fix memory leak. * mfd/srvman.c (struct mfd_server): New member `flags'. (mfd_server_new): Take flags as 4th argument. (server_run): Use flags to set single-user and reuseaddr modes. * mfd/srvman.h (SRV_SINGLE_PROCESS) (SRV_KEEP_EXISTING): New defines. (mfd_server_new): Change signature. (srvman_url_to_sockaddr): New proto.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--mfd/Makefile.am1
-rw-r--r--mfd/callout.c10
-rw-r--r--mfd/engine.c6
-rw-r--r--mfd/mailfromd.h15
-rw-r--r--mfd/main.c55
-rw-r--r--mfd/savclt.c275
-rw-r--r--mfd/savsrv.c14
-rw-r--r--mfd/srvman.c11
-rw-r--r--mfd/srvman.h7
9 files changed, 364 insertions, 30 deletions
diff --git a/mfd/Makefile.am b/mfd/Makefile.am
index 962c22a..c68afcf 100644
--- a/mfd/Makefile.am
+++ b/mfd/Makefile.am
@@ -72,6 +72,7 @@ mailfromd_SOURCES = \
72 pragma.c\ 72 pragma.c\
73 prog.c\ 73 prog.c\
74 prog.h\ 74 prog.h\
75 savclt.c\
75 savsrv.c\ 76 savsrv.c\
76 srvman.c\ 77 srvman.c\
77 srvman.h\ 78 srvman.h\
diff --git a/mfd/callout.c b/mfd/callout.c
index c028838..acecb26 100644
--- a/mfd/callout.c
+++ b/mfd/callout.c
@@ -129,8 +129,8 @@ smtp_io_free(struct smtp_io_data *iop)
129 free(iop); 129 free(iop);
130} 130}
131 131
132static void 132void
133transcript(struct smtp_io_data *io, char *prefix, const char *msg) 133transcript(const char *id, char *prefix, const char *msg)
134{ 134{
135 if (do_transcript) { 135 if (do_transcript) {
136 int len = strlen(msg); 136 int len = strlen(msg);
@@ -141,7 +141,7 @@ transcript(struct smtp_io_data *io, char *prefix, const char *msg)
141 } 141 }
142 if (len) 142 if (len)
143 logmsg(LOG_INFO, "%s: %s %*.*s", 143 logmsg(LOG_INFO, "%s: %s %*.*s",
144 io->id, 144 id,
145 prefix, len, len, msg); 145 prefix, len, len, msg);
146 } 146 }
147} 147}
@@ -216,7 +216,7 @@ smtp_send(struct smtp_io_data *iop, const char *command)
216 init_timeout_ctl (&tctl, io_timeout); 216 init_timeout_ctl (&tctl, io_timeout);
217 217
218 iop->reply = NULL; /* Clear reply for logging purposes */ 218 iop->reply = NULL; /* Clear reply for logging purposes */
219 transcript(iop, "SEND:", command); 219 transcript(iop->id, "SEND:", command);
220 do { 220 do {
221 size_t nb; 221 size_t nb;
222 int rc; 222 int rc;
@@ -343,7 +343,7 @@ smtp_recv(struct smtp_io_data *iop, enum smtp_timeout to)
343 int rc = smtp_recvline(iop, to); 343 int rc = smtp_recvline(iop, to);
344 if (rc) 344 if (rc)
345 return -1; 345 return -1;
346 transcript(iop, "RECV:", iop->reply); 346 transcript(iop->id, "RECV:", iop->reply);
347 code = strtoul(iop->reply, &p, 0); 347 code = strtoul(iop->reply, &p, 0);
348 if (p - iop->reply != 3 || (*p != '-' && *p != ' ')) { 348 if (p - iop->reply != 3 || (*p != '-' && *p != ' ')) {
349 mu_error(_("unexpected reply from server: %s"), 349 mu_error(_("unexpected reply from server: %s"),
diff --git a/mfd/engine.c b/mfd/engine.c
index e1f2de0..c9741c1 100644
--- a/mfd/engine.c
+++ b/mfd/engine.c
@@ -271,6 +271,7 @@ mfl_smtp_io_callback(void *data, const char *key, const char *value)
271 set_last_poll_recv(env, value); 271 set_last_poll_recv(env, value);
272} 272}
273 273
274
274/* Method "strict". Verifies whether EMAIL is understood either by 275/* Method "strict". Verifies whether EMAIL is understood either by
275 host CLIENT_ADDR or one of MX servers of its domain */ 276 host CLIENT_ADDR or one of MX servers of its domain */
276mf_status 277mf_status
@@ -299,6 +300,8 @@ method_strict(eval_environ_t env, char *email, char *client_addr,
299 300
300 if (mf_resolved(rc)) 301 if (mf_resolved(rc))
301 cache_insert2(email, client_addr, rc); 302 cache_insert2(email, client_addr, rc);
303 else if (rc == mf_temp_failure)
304 schedule_callout(email, ehlo, mailfrom, client_addr);
302 } else { 305 } else {
303 set_last_poll_helo(env, ""); 306 set_last_poll_helo(env, "");
304 set_last_poll_greeting(env, ""); 307 set_last_poll_greeting(env, "");
@@ -330,10 +333,13 @@ method_standard(eval_environ_t env, char *email, char *ehlo, char *mailfrom)
330 smtp_timeout_soft, 333 smtp_timeout_soft,
331 mfl_smtp_io_callback, 334 mfl_smtp_io_callback,
332 env); 335 env);
336 smtp_io_setup_callout(io, email, ehlo, mailfrom);
333 rc = callout_standard(io); 337 rc = callout_standard(io);
334 smtp_io_free(io); 338 smtp_io_free(io);
335 if (mf_resolved(rc)) 339 if (mf_resolved(rc))
336 cache_insert(email, rc); 340 cache_insert(email, rc);
341 else if (rc == mf_temp_failure)
342 schedule_callout(email, ehlo, mailfrom, NULL);
337 } else { 343 } else {
338 set_last_poll_helo(env, ""); 344 set_last_poll_helo(env, "");
339 set_last_poll_greeting(env, ""); 345 set_last_poll_greeting(env, "");
diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h
index 5df5463..74cf107 100644
--- a/mfd/mailfromd.h
+++ b/mfd/mailfromd.h
@@ -986,10 +986,6 @@ void milter_settimeout(time_t t);
986int xeval(eval_environ_t env, enum smtp_state tag); 986int xeval(eval_environ_t env, enum smtp_state tag);
987 987
988mf_status listens_on (const char *client_addr, int port, time_t timeout); 988mf_status listens_on (const char *client_addr, int port, time_t timeout);
989mf_status check_on_host(eval_environ_t env, char *email, char *client_addr,
990 char *ehlo, char *mailfrom);
991mf_status check_mx_records(eval_environ_t env, char *email, char *client_addr,
992 char *ehlo, char *mailfrom, int *pcount);
993mf_status method_strict(eval_environ_t env, char *email, char *client_addr, 989mf_status method_strict(eval_environ_t env, char *email, char *client_addr,
994 char *ehlo, char *mailfrom); 990 char *ehlo, char *mailfrom);
995mf_status method_standard(eval_environ_t env, char *email, char *ehlo, 991mf_status method_standard(eval_environ_t env, char *email, char *ehlo,
@@ -1147,9 +1143,18 @@ mf_status callout_host(struct smtp_io_data *, const char *);
1147mf_status callout_mx(struct smtp_io_data *, const char *, int *); 1143mf_status callout_mx(struct smtp_io_data *, const char *, int *);
1148mf_status callout_strict(struct smtp_io_data *, const char *); 1144mf_status callout_strict(struct smtp_io_data *, const char *);
1149mf_status callout_standard(struct smtp_io_data *); 1145mf_status callout_standard(struct smtp_io_data *);
1150 1146
1147void transcript(const char *id, char *prefix, const char *msg);
1148
1151/* savsrv.c */ 1149/* savsrv.c */
1152int callout_session_server(const char *id, int fd, 1150int callout_session_server(const char *id, int fd,
1153 struct sockaddr const *sa, socklen_t len, 1151 struct sockaddr const *sa, socklen_t len,
1154 void *server_data, void *srvman_data); 1152 void *server_data, void *srvman_data);
1155 1153
1154/* savclt.c */
1155void schedule_callout(const char *email, const char *ehlo,
1156 const char *mailfrom,
1157 const char *client_addr);
1158extern struct sockaddr *callout_server_sa;
1159extern socklen_t callout_server_sa_len;
1160
diff --git a/mfd/main.c b/mfd/main.c
index 8ffff46..a69d7c0 100644
--- a/mfd/main.c
+++ b/mfd/main.c
@@ -70,9 +70,9 @@ int do_trace; /* Enable tracing configuration */
70int mtasim_option; /* mtasim compatibility mode */ 70int mtasim_option; /* mtasim compatibility mode */
71unsigned optimization_level = 1; /* Optimization level */ 71unsigned optimization_level = 1; /* Optimization level */
72int log_to_stderr; /* Use stderr for logging */ 72int log_to_stderr; /* Use stderr for logging */
73int force_remove = 1; /* Remove local communication socket if it already
74 exists */
75int foreground; /* Stay in foreground */ 73int foreground; /* Stay in foreground */
74int force_remove; /* Remove local communication socket if it already
75 exists */
76int single_process_option; /* Run in single process mode. */ 76int single_process_option; /* Run in single process mode. */
77unsigned long source_address = INADDR_ANY; /* Source address for TCP 77unsigned long source_address = INADDR_ANY; /* Source address for TCP
78 connections */ 78 connections */
@@ -622,7 +622,8 @@ add_legacy_milter_port(const char *str, mu_debug_t dbg)
622 url = parse_milter_url(dbg, str); 622 url = parse_milter_url(dbg, str);
623 if (url) { 623 if (url) {
624 mfd_server_t srv = mfd_server_new(id, url, 624 mfd_server_t srv = mfd_server_new(id, url,
625 milter_session_server); 625 milter_session_server,
626 0);
626 if (srv) 627 if (srv)
627 mfd_srvman_attach_server(srv); 628 mfd_srvman_attach_server(srv);
628 else 629 else
@@ -1381,7 +1382,6 @@ parse_opt(int key, char *arg, struct argp_state *state)
1381 break; 1382 break;
1382 1383
1383 case 'r': 1384 case 'r':
1384 /*FIXME*/
1385 force_remove = 1; 1385 force_remove = 1;
1386 break; 1386 break;
1387 1387
@@ -2099,6 +2099,8 @@ struct server_config_stmt {
2099 mu_acl_t acl; 2099 mu_acl_t acl;
2100 size_t max_children; 2100 size_t max_children;
2101 mfd_server_func_t server; 2101 mfd_server_func_t server;
2102 int single_process;
2103 int reuseaddr;
2102}; 2104};
2103 2105
2104static struct server_config_stmt server_config_stmt; 2106static struct server_config_stmt server_config_stmt;
@@ -2126,6 +2128,12 @@ struct mu_cfg_param server_section_param[] = {
2126 &server_config_stmt.max_children, 0, 2128 &server_config_stmt.max_children, 0,
2127 NULL, 2129 NULL,
2128 N_("Maximum number of instances allowed for this server.") }, 2130 N_("Maximum number of instances allowed for this server.") },
2131 { "single-process", mu_cfg_bool,
2132 &server_config_stmt.single_process, 0, NULL,
2133 N_("Single-process mode.") },
2134 { "reuseaddr", mu_cfg_bool,
2135 &server_config_stmt.reuseaddr, 0, NULL,
2136 N_("Reuse existing socket (default).") },
2129 { "acl", mu_cfg_section, 2137 { "acl", mu_cfg_section,
2130 &server_config_stmt.acl }, 2138 &server_config_stmt.acl },
2131 { NULL } 2139 { NULL }
@@ -2141,6 +2149,7 @@ server_section_parser(enum mu_cfg_section_stage stage,
2141 switch (stage) { 2149 switch (stage) {
2142 case mu_cfg_section_start: 2150 case mu_cfg_section_start:
2143 memset(&server_config_stmt, 0, sizeof(server_config_stmt)); 2151 memset(&server_config_stmt, 0, sizeof(server_config_stmt));
2152 server_config_stmt.reuseaddr = 1;
2144 if (mu_cfg_assert_value_type (node->label, MU_CFG_STRING, 2153 if (mu_cfg_assert_value_type (node->label, MU_CFG_STRING,
2145 tree->debug)) 2154 tree->debug))
2146 return 1; 2155 return 1;
@@ -2160,10 +2169,17 @@ server_section_parser(enum mu_cfg_section_stage stage,
2160 if (!server_config_stmt.id) 2169 if (!server_config_stmt.id)
2161 server_config_stmt.id = next_server_id(); 2170 server_config_stmt.id = next_server_id();
2162 if (server_config_stmt.url && server_config_stmt.server) { 2171 if (server_config_stmt.url && server_config_stmt.server) {
2163 mfd_server_t srv = 2172 int flags = 0;
2164 mfd_server_new(server_config_stmt.id, 2173 mfd_server_t srv;
2165 server_config_stmt.url, 2174
2166 server_config_stmt.server); 2175 if (server_config_stmt.single_process)
2176 flags |= SRV_SINGLE_PROCESS;
2177 if (!server_config_stmt.reuseaddr)
2178 flags |= SRV_KEEP_EXISTING;
2179 srv = mfd_server_new(server_config_stmt.id,
2180 server_config_stmt.url,
2181 server_config_stmt.server,
2182 flags);
2167 if (srv) { 2183 if (srv) {
2168 mfd_server_set_max_children(srv, 2184 mfd_server_set_max_children(srv,
2169 server_config_stmt.max_children); 2185 server_config_stmt.max_children);
@@ -2202,6 +2218,22 @@ cb_milter_listen(mu_debug_t err, void *data, mu_config_value_t *arg)
2202} 2218}
2203 2219
2204 2220
2221static int
2222cb_callout_url(mu_debug_t err, void *data, mu_config_value_t *arg)
2223{
2224 mu_url_t url;
2225 if (mu_cfg_assert_value_type(arg, MU_CFG_STRING, err))
2226 return 1;
2227 url = parse_milter_url(err, arg->v.string);
2228 if (url) {
2229 callout_server_sa = srvman_url_to_sockaddr(url,
2230 &callout_server_sa_len);
2231 mu_url_destroy(&url);
2232 }
2233 return 0;
2234}
2235
2236
2205struct mu_cfg_param mf_cfg_param[] = { 2237struct mu_cfg_param mf_cfg_param[] = {
2206 { "debug", mu_cfg_callback, NULL, 0, cb_debug, 2238 { "debug", mu_cfg_callback, NULL, 0, cb_debug,
2207 N_("Set Mailfromd debug verbosity level. Argument is a comma-" 2239 N_("Set Mailfromd debug verbosity level. Argument is a comma-"
@@ -2292,6 +2324,13 @@ struct mu_cfg_param mf_cfg_param[] = {
2292 N_("file: string") }, 2324 N_("file: string") },
2293 2325
2294 { "database", mu_cfg_section, NULL }, 2326 { "database", mu_cfg_section, NULL },
2327
2328 { "callout-url", mu_cfg_callback,
2329 NULL, 0,
2330 cb_callout_url,
2331 N_("URL of the callout server"),
2332 N_("url") },
2333
2295 2334
2296 { NULL } 2335 { NULL }
2297}; 2336};
diff --git a/mfd/savclt.c b/mfd/savclt.c
new file mode 100644
index 0000000..447f685
--- a/dev/null
+++ b/mfd/savclt.c
@@ -0,0 +1,275 @@
1/* This file is part of Mailfromd.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#define MF_SOURCE_NAME MF_SOURCE_SAVCLT
18#ifdef HAVE_CONFIG_H
19# include <config.h>
20#endif
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29#include <netdb.h>
30
31#include "mailfromd.h"
32
33struct sockaddr *callout_server_sa;
34socklen_t callout_server_sa_len;
35time_t savclt_timeout = 3;
36
37/* Ideally, I'd want to use smtp_io functions here. But they are
38 based on Mailutils' TCP streams, which so far do not support
39 UNIX sockets. So, for the time being, I use the straightforward
40 I/O approach. */
41int
42savclt_getline(int fd, char **pbuf, size_t *pbufsize)
43{
44 char *buf = *pbuf;
45 size_t bufsize = *pbufsize;
46 int off = 0;
47#define DELTA 128
48 time_t start = time(NULL);
49
50 if (buf == NULL) {
51 bufsize = DELTA;
52 buf = xmalloc(bufsize);
53 }
54
55 do {
56 struct timeval tv;
57 int rc, flags;
58 time_t diff = time(NULL) - start;
59
60 if (diff > savclt_timeout) {
61 errno = ETIMEDOUT;
62 return -1;
63 }
64
65 tv.tv_sec = savclt_timeout - diff;
66 tv.tv_usec = 0;
67 flags = MU_STREAM_READY_RD;
68 rc = mu_fd_wait(fd, &flags, &tv);
69 if (rc) {
70 debug1(1, "mu_fd_wait: %s", mu_strerror(rc));
71 errno = rc;
72 return -1;
73 }
74 if (!(flags & MU_STREAM_READY_RD)) {
75 errno = ETIMEDOUT;
76 return -1;
77 }
78
79 if (off + 1 == bufsize) {
80 bufsize += DELTA;
81 buf = xrealloc(buf, bufsize);
82 }
83
84 rc = read(fd, buf + off, 1);
85 if (rc == -1)
86 return -1;
87 if (rc == 0)
88 break;
89 off++;
90 } while (buf[off - 1] != '\n');
91
92 if (off + 1 == bufsize) {
93 bufsize++;
94 buf = xrealloc(buf, bufsize);
95 }
96 buf[off] = 0;
97 *pbuf = buf;
98 *pbufsize = bufsize;
99 transcript("savclt", "RECV:", buf);
100 return off;
101}
102
103static int
104send_line(int fd, const char *txt, size_t len)
105{
106 time_t start = time(NULL);
107
108 while (len) {
109 struct timeval tv;
110 int rc, flags;
111 time_t diff = time(NULL) - start;
112
113 if (diff > savclt_timeout) {
114 errno = ETIMEDOUT;
115 return -1;
116 }
117
118 tv.tv_sec = savclt_timeout - diff;
119 tv.tv_usec = 0;
120 flags = MU_STREAM_READY_WR;
121 rc = mu_fd_wait(fd, &flags, &tv);
122 if (rc) {
123 debug1(1, "mu_fd_wait: %s", mu_strerror(rc));
124 errno = rc;
125 return -1;
126 }
127 if (!(flags & MU_STREAM_READY_WR)) {
128 errno = ETIMEDOUT;
129 return -1;
130 }
131
132 rc = write(fd, txt, len);
133 if (rc <= 0) {
134 if (errno == EAGAIN)
135 continue;
136 return -1;
137 }
138 txt += rc;
139 len -= rc;
140 }
141 return 0;
142 }
143
144int
145savclt_wrtline(int fd, char **pbuf, size_t *pbufsize,
146 const char *fmt, ...)
147{
148 int rc;
149 va_list ap;
150
151 va_start(ap, fmt);
152 rc = mu_vasnprintf(pbuf, pbufsize, fmt, ap);
153 va_end(ap);
154 if (rc == 0) {
155 transcript("savclt", "SEND:", *pbuf);
156 rc = send_line(fd, *pbuf, strlen(*pbuf));
157 }
158 return rc;
159}
160
161
162static int
163connect_callout_server()
164{
165 int fd;
166 int flags;
167 int rc;
168
169 if (!callout_server_sa)
170 return -1;
171 fd = socket(callout_server_sa->sa_family, SOCK_STREAM, 0);
172 if (fd == -1) {
173 mu_error("schedule_callout: socket: %s",
174 mu_strerror(errno));
175 return -1;
176 }
177
178 flags = fcntl(fd, F_GETFL);
179 flags |= O_NONBLOCK;
180 fcntl(fd, F_SETFL, flags);
181
182 rc = connect(fd, callout_server_sa, callout_server_sa_len);
183 if (rc == -1) {
184 if (errno == EINPROGRESS) {
185 struct timeval tv;
186
187 tv.tv_sec = savclt_timeout;
188 tv.tv_usec = 0;
189 flags = MU_STREAM_READY_WR;
190 rc = mu_fd_wait(fd, &flags, &tv);
191 if (rc) {
192 debug1(1, "mu_fd_wait: %s", mu_strerror(rc));
193 close(fd);
194 return -1;
195 }
196
197 if (flags & MU_STREAM_READY_WR) {
198 socklen_t len = sizeof(flags);
199 rc = getsockopt(fd, SOL_SOCKET, SO_ERROR,
200 &flags, &len);
201 if (rc) {
202 mu_error("getsockopt: %s",
203 mu_strerror(rc));
204 close(fd);
205 return -1;
206 }
207 } else
208 flags = ETIMEDOUT;
209 } else
210 flags = errno;
211
212 if (flags) {
213 mu_error("connect: %s", mu_strerror(flags));
214 close(fd);
215 return -1;
216 }
217 }
218
219 if (rc) {
220 close(fd);
221 return -1;
222 }
223
224 return fd;
225}
226
227enum callout_server_state {
228 css_init,
229 css_send,
230 css_quit,
231};
232
233void
234schedule_callout(const char *email, const char *ehlo, const char *mailfrom,
235 const char *client_addr)
236{
237 size_t size = 0;
238 char *buf = NULL;
239 int fd = connect_callout_server();
240 enum callout_server_state state = css_init;
241 int rc;
242
243 while (state != css_quit) {
244 if (savclt_getline(fd, &buf, &size) < 0)
245 break;
246 trimcrlf(buf);
247 if (!(strlen(buf) > 2 && memcmp(buf, "OK", 2) == 0
248 && isspace(buf[2])))
249 break;
250
251 switch (state) {
252 case css_init:
253 if (client_addr)
254 rc = savclt_wrtline(fd, &buf, &size,
255 "SVRFY \"%s\" \"%s\" \"%s\" \"%s\"\r\n",
256 email, ehlo, mailfrom, client_addr);
257 else
258 rc = savclt_wrtline(fd, &buf, &size,
259 "VRFY \"%s\" \"%s\" \"%s\"\r\n",
260 email, ehlo, mailfrom);
261 state = (rc < 0) ? css_quit : css_send;
262 break;
263
264 case css_send:
265 savclt_wrtline(fd, &buf, &size, "QUIT\r\n");
266 break;
267
268 case css_quit:
269 break;
270 }
271 }
272 close(fd);
273 free(buf);
274}
275
diff --git a/mfd/savsrv.c b/mfd/savsrv.c
index 4e90d36..34f95b4 100644
--- a/mfd/savsrv.c
+++ b/mfd/savsrv.c
@@ -14,7 +14,7 @@
14 You should have received a copy of the GNU General Public License 14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16 16
17#define MF_SOURCE_NAME MF_SOURCE_CALLOUT 17#define MF_SOURCE_NAME MF_SOURCE_SAVSRV
18#ifdef HAVE_CONFIG_H 18#ifdef HAVE_CONFIG_H
19# include <config.h> 19# include <config.h>
20#endif 20#endif
@@ -23,11 +23,6 @@
23#include <unistd.h> 23#include <unistd.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <stdio.h> 25#include <stdio.h>
26#include <stdarg.h>
27#include <syslog.h>
28#include <signal.h>
29#include <pwd.h>
30#include <grp.h>
31#include <sys/socket.h> 26#include <sys/socket.h>
32#include <netinet/in.h> 27#include <netinet/in.h>
33#include <arpa/inet.h> 28#include <arpa/inet.h>
@@ -57,6 +52,7 @@ verify(struct vrfy_queue *qp, FILE *fp)
57{ 52{
58 mf_status rc; 53 mf_status rc;
59 54
55 mf_proctitle_format("callout server: %s", smtp_io_email(qp->io));
60 if (qp->hostname) { 56 if (qp->hostname) {
61 rc = callout_strict(qp->io, qp->hostname); 57 rc = callout_strict(qp->io, qp->hostname);
62 if (mf_resolved(rc)) 58 if (mf_resolved(rc))
@@ -192,6 +188,7 @@ callout_session_server(const char *id, int fd,
192 char *buf = NULL; 188 char *buf = NULL;
193 size_t size = 0; 189 size_t size = 0;
194 190
191 mf_proctitle_format("callout server");
195 setvbuf(fp, NULL, _IOLBF, 0); 192 setvbuf(fp, NULL, _IOLBF, 0);
196 fprintf(fp, "OK mailfromd callout server ready\r\n"); 193 fprintf(fp, "OK mailfromd callout server ready\r\n");
197 while (getline(&buf, &size, fp) >= 0) { 194 while (getline(&buf, &size, fp) >= 0) {
@@ -201,6 +198,8 @@ callout_session_server(const char *id, int fd,
201 int rc = 0; 198 int rc = 0;
202 199
203 trimcrlf(buf); 200 trimcrlf(buf);
201 debug1(2,"C: %s", buf);
202
204 if (mu_argcv_get(buf, "", NULL, &argc, &argv)) { 203 if (mu_argcv_get(buf, "", NULL, &argc, &argv)) {
205 fprintf(fp, "NO cannot parse line\r\n"); 204 fprintf(fp, "NO cannot parse line\r\n");
206 continue; 205 continue;
@@ -218,7 +217,8 @@ callout_session_server(const char *id, int fd,
218 break; 217 break;
219 } 218 }
220 fclose(fp); 219 fclose(fp);
221 220 free(buf);
221
222 /* Run queued verifications */ 222 /* Run queued verifications */
223 run_queue(NULL); 223 run_queue(NULL);
224 return 0; 224 return 0;
diff --git a/mfd/srvman.c b/mfd/srvman.c
index 47a5b54..6743385 100644
--- a/mfd/srvman.c
+++ b/mfd/srvman.c
@@ -45,6 +45,7 @@ struct mfd_server {
45 socklen_t salen; /* Length of the sa */ 45 socklen_t salen; /* Length of the sa */
46 int backlog; /* Backlog value for listen(2) */ 46 int backlog; /* Backlog value for listen(2) */
47 int fd; /* Socket descriptor */ 47 int fd; /* Socket descriptor */
48 int flags; /* SRV_* flags */
48 mfd_server_prefork_hook_t prefork_hook; /* Pre-fork function */ 49 mfd_server_prefork_hook_t prefork_hook; /* Pre-fork function */
49 mfd_server_func_t conn; /* Connection handler */ 50 mfd_server_func_t conn; /* Connection handler */
50 mfd_srvman_hook_t free_hook; 51 mfd_srvman_hook_t free_hook;
@@ -378,7 +379,7 @@ mfd_server_shutdown(struct mfd_server *srv)
378} 379}
379 380
380struct mfd_server * 381struct mfd_server *
381mfd_server_new(const char *id, mu_url_t url, mfd_server_func_t conn) 382mfd_server_new(const char *id, mu_url_t url, mfd_server_func_t conn, int flags)
382{ 383{
383 struct mfd_server *srv; 384 struct mfd_server *srv;
384 struct sockaddr *sa; 385 struct sockaddr *sa;
@@ -394,6 +395,7 @@ mfd_server_new(const char *id, mu_url_t url, mfd_server_func_t conn)
394 srv->salen = salen; 395 srv->salen = salen;
395 srv->backlog = 8; 396 srv->backlog = 8;
396 srv->conn = conn; 397 srv->conn = conn;
398 srv->flags = flags;
397 return srv; 399 return srv;
398} 400}
399 401
@@ -496,7 +498,7 @@ server_run(int connfd, struct mfd_server *srv,
496 if (srv->acl && check_acl(srv->id, srv->acl, sa, salen)) 498 if (srv->acl && check_acl(srv->id, srv->acl, sa, salen))
497 return; 499 return;
498 500
499 if (single_process_option) { 501 if (single_process_option || (srv->flags & SRV_SINGLE_PROCESS)) {
500 if ((!srvman_param.prefork_hook 502 if ((!srvman_param.prefork_hook
501 || srvman_param.prefork_hook(sa, salen, 503 || srvman_param.prefork_hook(sa, salen,
502 srvman_param.data) == 0) 504 srvman_param.data) == 0)
@@ -707,7 +709,8 @@ server_prep(struct mfd_server *srv, int fd)
707 mu_error(_("%s: file %s is not a socket"), 709 mu_error(_("%s: file %s is not a socket"),
708 srv->id, s_un->sun_path); 710 srv->id, s_un->sun_path);
709 return 1; 711 return 1;
710 } else if (force_remove) { 712 } else if (force_remove
713 || !(srv->flags & SRV_KEEP_EXISTING)) {
711 if (unlink(s_un->sun_path)) { 714 if (unlink(s_un->sun_path)) {
712 mu_error(_("%s: cannot unlink file %s: %s"), 715 mu_error(_("%s: cannot unlink file %s: %s"),
713 srv->id, s_un->sun_path, 716 srv->id, s_un->sun_path,
@@ -722,7 +725,7 @@ server_prep(struct mfd_server *srv, int fd)
722 break; 725 break;
723 726
724 case AF_INET: 727 case AF_INET:
725 if (force_remove) { 728 if (force_remove || !(srv->flags & SRV_KEEP_EXISTING)) {
726 t = 1; 729 t = 1;
727 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 730 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
728 &t, sizeof(t)); 731 &t, sizeof(t));
diff --git a/mfd/srvman.h b/mfd/srvman.h
index e2e63fa..dffce48 100644
--- a/mfd/srvman.h
+++ b/mfd/srvman.h
@@ -33,6 +33,9 @@ typedef int (*mfd_srvman_prefork_hook_t) (struct sockaddr const *sa,
33#define DEFAULT_PIDTAB_SIZE 64 33#define DEFAULT_PIDTAB_SIZE 64
34#define DEFAULT_SHUTDOWN_TIMEOUT 5 34#define DEFAULT_SHUTDOWN_TIMEOUT 5
35 35
36#define SRV_SINGLE_PROCESS 0x01
37#define SRV_KEEP_EXISTING 0x02
38
36struct srvman_param { 39struct srvman_param {
37 void *data; /* Server manager data */ 40 void *data; /* Server manager data */
38 mu_acl_t acl; /* Global Access Control List */ 41 mu_acl_t acl; /* Global Access Control List */
@@ -48,7 +51,7 @@ extern struct srvman_param srvman_param;
48 51
49void mfd_server_shutdown(mfd_server_t srv); 52void mfd_server_shutdown(mfd_server_t srv);
50mfd_server_t mfd_server_new(const char *id, mu_url_t url, 53mfd_server_t mfd_server_new(const char *id, mu_url_t url,
51 mfd_server_func_t conn); 54 mfd_server_func_t conn, int flags);
52void mfd_server_free(mfd_server_t srv); 55void mfd_server_free(mfd_server_t srv);
53void mfd_server_set_prefork_hook(mfd_server_t srv, 56void mfd_server_set_prefork_hook(mfd_server_t srv,
54 mfd_server_prefork_hook_t hook); 57 mfd_server_prefork_hook_t hook);
@@ -66,3 +69,5 @@ void mfd_srvman_shutdown(void);
66void mfd_srvman_free(void); 69void mfd_srvman_free(void);
67size_t mfd_srvman_count_servers(void); 70size_t mfd_srvman_count_servers(void);
68void mfd_srvman_stop(void); 71void mfd_srvman_stop(void);
72
73struct sockaddr *srvman_url_to_sockaddr(mu_url_t url, size_t *psalen);

Return to:

Send suggestions and report system problems to the System administrator.