xref: /netbsd-src/external/ibm-public/postfix/dist/src/scache/scache.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: scache.c,v 1.2 2017/02/14 01:16:47 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	scache 8
6 /* SUMMARY
7 /*	Postfix shared connection cache server
8 /* SYNOPSIS
9 /*	\fBscache\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /*	The \fBscache\fR(8) server maintains a shared multi-connection
12 /*	cache. This information can be used by, for example, Postfix
13 /*	SMTP clients or other Postfix delivery agents.
14 /*
15 /*	The connection cache is organized into logical destination
16 /*	names, physical endpoint names, and connections.
17 /*
18 /*	As a specific example, logical SMTP destinations specify
19 /*	(transport, domain, port), and physical SMTP endpoints
20 /*	specify (transport, IP address, port).  An SMTP connection
21 /*	may be saved after a successful mail transaction.
22 /*
23 /*	In the general case, one logical destination may refer to
24 /*	zero or more physical endpoints, one physical endpoint may
25 /*	be referenced by zero or more logical destinations, and
26 /*	one endpoint may refer to zero or more connections.
27 /*
28 /*	The exact syntax of a logical destination or endpoint name
29 /*	is application dependent; the \fBscache\fR(8) server does
30 /*	not care.  A connection is stored as a file descriptor together
31 /*	with application-dependent information that is needed to
32 /*	re-activate a connection object. Again, the \fBscache\fR(8)
33 /*	server is completely unaware of the details of that
34 /*	information.
35 /*
36 /*	All information is stored with a finite time to live (ttl).
37 /*	The connection cache daemon terminates when no client is
38 /*	connected for \fBmax_idle\fR time units.
39 /*
40 /*	This server implements the following requests:
41 /* .IP "\fBsave_endp\fI ttl endpoint endpoint_properties file_descriptor\fR"
42 /*	Save the specified file descriptor and connection property data
43 /*	under the specified endpoint name. The endpoint properties
44 /*	are used by the client to re-activate a passivated connection
45 /*	object.
46 /* .IP "\fBfind_endp\fI endpoint\fR"
47 /*	Look up cached properties and a cached file descriptor for the
48 /*	specified endpoint.
49 /* .IP "\fBsave_dest\fI ttl destination destination_properties endpoint\fR"
50 /*	Save the binding between a logical destination and an
51 /*	endpoint under the destination name, together with destination
52 /*	specific connection properties. The destination properties
53 /*	are used by the client to re-activate a passivated connection
54 /*	object.
55 /* .IP "\fBfind_dest\fI destination\fR"
56 /*	Look up cached destination properties, cached endpoint properties,
57 /*	and a cached file descriptor for the specified logical destination.
58 /* SECURITY
59 /* .ad
60 /* .fi
61 /*	The \fBscache\fR(8) server is not security-sensitive. It does not
62 /*	talk to the network, and it does not talk to local users.
63 /*	The \fBscache\fR(8) server can run chrooted at fixed low privilege.
64 /*
65 /*	The \fBscache\fR(8) server is not a trusted process. It must
66 /*	not be used to store information that is security sensitive.
67 /* DIAGNOSTICS
68 /*	Problems and transactions are logged to \fBsyslogd\fR(8).
69 /* BUGS
70 /*	The session cache cannot be shared among multiple machines.
71 /*
72 /*	When a connection expires from the cache, it is closed without
73 /*	the appropriate protocol specific handshake.
74 /* CONFIGURATION PARAMETERS
75 /* .ad
76 /* .fi
77 /*	Changes to \fBmain.cf\fR are picked up automatically as \fBscache\fR(8)
78 /*	processes run for only a limited amount of time. Use the command
79 /*	"\fBpostfix reload\fR" to speed up a change.
80 /*
81 /*	The text below provides only a parameter summary. See
82 /*	\fBpostconf\fR(5) for more details including examples.
83 /* RESOURCE CONTROLS
84 /* .ad
85 /* .fi
86 /* .IP "\fBconnection_cache_ttl_limit (2s)\fR"
87 /*	The maximal time-to-live value that the \fBscache\fR(8) connection
88 /*	cache server
89 /*	allows.
90 /* .IP "\fBconnection_cache_status_update_time (600s)\fR"
91 /*	How frequently the \fBscache\fR(8) server logs usage statistics with
92 /*	connection cache hit and miss rates for logical destinations and for
93 /*	physical endpoints.
94 /* MISCELLANEOUS CONTROLS
95 /* .ad
96 /* .fi
97 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
98 /*	The default location of the Postfix main.cf and master.cf
99 /*	configuration files.
100 /* .IP "\fBdaemon_timeout (18000s)\fR"
101 /*	How much time a Postfix daemon process may take to handle a
102 /*	request before it is terminated by a built-in watchdog timer.
103 /* .IP "\fBipc_timeout (3600s)\fR"
104 /*	The time limit for sending or receiving information over an internal
105 /*	communication channel.
106 /* .IP "\fBmax_idle (100s)\fR"
107 /*	The maximum amount of time that an idle Postfix daemon process waits
108 /*	for an incoming connection before terminating voluntarily.
109 /* .IP "\fBprocess_id (read-only)\fR"
110 /*	The process ID of a Postfix command or daemon process.
111 /* .IP "\fBprocess_name (read-only)\fR"
112 /*	The process name of a Postfix command or daemon process.
113 /* .IP "\fBsyslog_facility (mail)\fR"
114 /*	The syslog facility of Postfix logging.
115 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
116 /*	The mail system name that is prepended to the process name in syslog
117 /*	records, so that "smtpd" becomes, for example, "postfix/smtpd".
118 /* SEE ALSO
119 /*	smtp(8), SMTP client
120 /*	postconf(5), configuration parameters
121 /*	master(8), process manager
122 /*	syslogd(8), system logging
123 /* README FILES
124 /* .ad
125 /* .fi
126 /*	Use "\fBpostconf readme_directory\fR" or
127 /*	"\fBpostconf html_directory\fR" to locate this information.
128 /* .na
129 /* .nf
130 /*	CONNECTION_CACHE_README, Postfix connection cache
131 /* LICENSE
132 /* .ad
133 /* .fi
134 /*	The Secure Mailer license must be distributed with this software.
135 /* HISTORY
136 /*	This service was introduced with Postfix version 2.2.
137 /* AUTHOR(S)
138 /*	Wietse Venema
139 /*	IBM T.J. Watson Research
140 /*	P.O. Box 704
141 /*	Yorktown Heights, NY 10598, USA
142 /*
143 /*	Wietse Venema
144 /*	Google, Inc.
145 /*	111 8th Avenue
146 /*	New York, NY 10011, USA
147 /*--*/
148 
149 /* System library. */
150 
151 #include <sys_defs.h>
152 #include <time.h>
153 
154 /* Utility library. */
155 
156 #include <msg.h>
157 #include <iostuff.h>
158 #include <htable.h>
159 #include <ring.h>
160 #include <events.h>
161 
162 /* Global library. */
163 
164 #include <mail_params.h>
165 #include <mail_version.h>
166 #include <mail_proto.h>
167 #include <scache.h>
168 
169 /* Single server skeleton. */
170 
171 #include <mail_server.h>
172 #include <mail_conf.h>
173 
174 /* Application-specific. */
175 
176  /*
177   * Tunable parameters.
178   */
179 int     var_scache_ttl_lim;
180 int     var_scache_stat_time;
181 
182  /*
183   * Request parameters.
184   */
185 static VSTRING *scache_request;
186 static VSTRING *scache_dest_label;
187 static VSTRING *scache_dest_prop;
188 static VSTRING *scache_endp_label;
189 static VSTRING *scache_endp_prop;
190 
191 #ifdef CANT_WRITE_BEFORE_SENDING_FD
192 static VSTRING *scache_dummy;
193 
194 #endif
195 
196  /*
197   * Session cache instance.
198   */
199 static SCACHE *scache;
200 
201  /*
202   * Statistics.
203   */
204 static int scache_dest_hits;
205 static int scache_dest_miss;
206 static int scache_dest_count;
207 static int scache_endp_hits;
208 static int scache_endp_miss;
209 static int scache_endp_count;
210 static int scache_sess_count;
211 time_t  scache_start_time;
212 
213  /*
214   * Silly little macros.
215   */
216 #define STR(x)			vstring_str(x)
217 #define VSTREQ(x,y)		(strcmp(STR(x),y) == 0)
218 
219 /* scache_save_endp_service - protocol to save endpoint->stream binding */
220 
221 static void scache_save_endp_service(VSTREAM *client_stream)
222 {
223     const char *myname = "scache_save_endp_service";
224     int     ttl;
225     int     fd;
226     SCACHE_SIZE size;
227 
228     if (attr_scan(client_stream,
229 		  ATTR_FLAG_STRICT,
230 		  RECV_ATTR_INT(MAIL_ATTR_TTL, &ttl),
231 		  RECV_ATTR_STR(MAIL_ATTR_LABEL, scache_endp_label),
232 		  RECV_ATTR_STR(MAIL_ATTR_PROP, scache_endp_prop),
233 		  ATTR_TYPE_END) != 3
234 	|| ttl <= 0) {
235 	msg_warn("%s: bad or missing request parameter", myname);
236 	attr_print(client_stream, ATTR_FLAG_NONE,
237 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_BAD),
238 		   ATTR_TYPE_END);
239 	return;
240     } else if (
241 #ifdef CANT_WRITE_BEFORE_SENDING_FD
242 	       attr_print(client_stream, ATTR_FLAG_NONE,
243 			  SEND_ATTR_STR(MAIL_ATTR_DUMMY, ""),
244 			  ATTR_TYPE_END) != 0
245 	       || vstream_fflush(client_stream) != 0
246 	       || read_wait(vstream_fileno(client_stream),
247 			    client_stream->timeout) < 0	/* XXX */
248 	       ||
249 #endif
250 	       (fd = LOCAL_RECV_FD(vstream_fileno(client_stream))) < 0) {
251 	msg_warn("%s: unable to receive file descriptor: %m", myname);
252 	(void) attr_print(client_stream, ATTR_FLAG_NONE,
253 			  SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_FAIL),
254 			  ATTR_TYPE_END);
255 	return;
256     } else {
257 	scache_save_endp(scache,
258 			 ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl,
259 			 STR(scache_endp_label), STR(scache_endp_prop), fd);
260 	(void) attr_print(client_stream, ATTR_FLAG_NONE,
261 			  SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_OK),
262 			  ATTR_TYPE_END);
263 	scache_size(scache, &size);
264 	if (size.endp_count > scache_endp_count)
265 	    scache_endp_count = size.endp_count;
266 	if (size.sess_count > scache_sess_count)
267 	    scache_sess_count = size.sess_count;
268 	return;
269     }
270 }
271 
272 /* scache_find_endp_service - protocol to find connection for endpoint */
273 
274 static void scache_find_endp_service(VSTREAM *client_stream)
275 {
276     const char *myname = "scache_find_endp_service";
277     int     fd;
278 
279     if (attr_scan(client_stream,
280 		  ATTR_FLAG_STRICT,
281 		  RECV_ATTR_STR(MAIL_ATTR_LABEL, scache_endp_label),
282 		  ATTR_TYPE_END) != 1) {
283 	msg_warn("%s: bad or missing request parameter", myname);
284 	attr_print(client_stream, ATTR_FLAG_NONE,
285 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_BAD),
286 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
287 		   ATTR_TYPE_END);
288 	return;
289     } else if ((fd = scache_find_endp(scache, STR(scache_endp_label),
290 				      scache_endp_prop)) < 0) {
291 	attr_print(client_stream, ATTR_FLAG_NONE,
292 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_FAIL),
293 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
294 		   ATTR_TYPE_END);
295 	scache_endp_miss++;
296 	return;
297     } else {
298 	attr_print(client_stream, ATTR_FLAG_NONE,
299 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_OK),
300 		   SEND_ATTR_STR(MAIL_ATTR_PROP, STR(scache_endp_prop)),
301 		   ATTR_TYPE_END);
302 	if (vstream_fflush(client_stream) != 0
303 #ifdef CANT_WRITE_BEFORE_SENDING_FD
304 	    || attr_scan(client_stream, ATTR_FLAG_STRICT,
305 			 RECV_ATTR_STR(MAIL_ATTR_DUMMY, scache_dummy),
306 			 ATTR_TYPE_END) != 1
307 #endif
308 	    || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
309 #ifdef MUST_READ_AFTER_SENDING_FD
310 	    || attr_scan(client_stream, ATTR_FLAG_STRICT,
311 			 RECV_ATTR_STR(MAIL_ATTR_DUMMY, scache_dummy),
312 			 ATTR_TYPE_END) != 1
313 #endif
314 	    )
315 	    msg_warn("%s: cannot send file descriptor: %m", myname);
316 	if (close(fd) < 0)
317 	    msg_warn("close(%d): %m", fd);
318 	scache_endp_hits++;
319 	return;
320     }
321 }
322 
323 /* scache_save_dest_service - protocol to save destination->endpoint binding */
324 
325 static void scache_save_dest_service(VSTREAM *client_stream)
326 {
327     const char *myname = "scache_save_dest_service";
328     int     ttl;
329     SCACHE_SIZE size;
330 
331     if (attr_scan(client_stream,
332 		  ATTR_FLAG_STRICT,
333 		  RECV_ATTR_INT(MAIL_ATTR_TTL, &ttl),
334 		  RECV_ATTR_STR(MAIL_ATTR_LABEL, scache_dest_label),
335 		  RECV_ATTR_STR(MAIL_ATTR_PROP, scache_dest_prop),
336 		  RECV_ATTR_STR(MAIL_ATTR_LABEL, scache_endp_label),
337 		  ATTR_TYPE_END) != 4
338 	|| ttl <= 0) {
339 	msg_warn("%s: bad or missing request parameter", myname);
340 	attr_print(client_stream, ATTR_FLAG_NONE,
341 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_BAD),
342 		   ATTR_TYPE_END);
343 	return;
344     } else {
345 	scache_save_dest(scache,
346 			 ttl > var_scache_ttl_lim ? var_scache_ttl_lim : ttl,
347 			 STR(scache_dest_label), STR(scache_dest_prop),
348 			 STR(scache_endp_label));
349 	attr_print(client_stream, ATTR_FLAG_NONE,
350 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_OK),
351 		   ATTR_TYPE_END);
352 	scache_size(scache, &size);
353 	if (size.dest_count > scache_dest_count)
354 	    scache_dest_count = size.dest_count;
355 	if (size.endp_count > scache_endp_count)
356 	    scache_endp_count = size.endp_count;
357 	return;
358     }
359 }
360 
361 /* scache_find_dest_service - protocol to find connection for destination */
362 
363 static void scache_find_dest_service(VSTREAM *client_stream)
364 {
365     const char *myname = "scache_find_dest_service";
366     int     fd;
367 
368     if (attr_scan(client_stream,
369 		  ATTR_FLAG_STRICT,
370 		  RECV_ATTR_STR(MAIL_ATTR_LABEL, scache_dest_label),
371 		  ATTR_TYPE_END) != 1) {
372 	msg_warn("%s: bad or missing request parameter", myname);
373 	attr_print(client_stream, ATTR_FLAG_NONE,
374 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_BAD),
375 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
376 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
377 		   ATTR_TYPE_END);
378 	return;
379     } else if ((fd = scache_find_dest(scache, STR(scache_dest_label),
380 				      scache_dest_prop,
381 				      scache_endp_prop)) < 0) {
382 	attr_print(client_stream, ATTR_FLAG_NONE,
383 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_FAIL),
384 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
385 		   SEND_ATTR_STR(MAIL_ATTR_PROP, ""),
386 		   ATTR_TYPE_END);
387 	scache_dest_miss++;
388 	return;
389     } else {
390 	attr_print(client_stream, ATTR_FLAG_NONE,
391 		   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_OK),
392 		   SEND_ATTR_STR(MAIL_ATTR_PROP, STR(scache_dest_prop)),
393 		   SEND_ATTR_STR(MAIL_ATTR_PROP, STR(scache_endp_prop)),
394 		   ATTR_TYPE_END);
395 	if (vstream_fflush(client_stream) != 0
396 #ifdef CANT_WRITE_BEFORE_SENDING_FD
397 	    || attr_scan(client_stream, ATTR_FLAG_STRICT,
398 			 RECV_ATTR_STR(MAIL_ATTR_DUMMY, scache_dummy),
399 			 ATTR_TYPE_END) != 1
400 #endif
401 	    || LOCAL_SEND_FD(vstream_fileno(client_stream), fd) < 0
402 #ifdef MUST_READ_AFTER_SENDING_FD
403 	    || attr_scan(client_stream, ATTR_FLAG_STRICT,
404 			 RECV_ATTR_STR(MAIL_ATTR_DUMMY, scache_dummy),
405 			 ATTR_TYPE_END) != 1
406 #endif
407 	    )
408 	    msg_warn("%s: cannot send file descriptor: %m", myname);
409 	if (close(fd) < 0)
410 	    msg_warn("close(%d): %m", fd);
411 	scache_dest_hits++;
412 	return;
413     }
414 }
415 
416 /* scache_service - perform service for client */
417 
418 static void scache_service(VSTREAM *client_stream, char *unused_service,
419 			           char **argv)
420 {
421 
422     /*
423      * Sanity check. This service takes no command-line arguments.
424      */
425     if (argv[0])
426 	msg_fatal("unexpected command-line argument: %s", argv[0]);
427 
428     /*
429      * This routine runs whenever a client connects to the UNIX-domain socket
430      * dedicated to the scache service. All connection-management stuff is
431      * handled by the common code in multi_server.c.
432      *
433      * XXX Workaround: with some requests, the client sends a dummy message
434      * after the server replies (yes that's a botch). When the scache server
435      * is slow, this dummy message may become concatenated with the next
436      * request from the same client. The do-while loop below will repeat
437      * instead of discarding the client request. We must process it now
438      * because there will be no select() notification.
439      */
440     do {
441 	if (attr_scan(client_stream,
442 		      ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
443 		      RECV_ATTR_STR(MAIL_ATTR_REQ, scache_request),
444 		      ATTR_TYPE_END) == 1) {
445 	    if (VSTREQ(scache_request, SCACHE_REQ_SAVE_DEST)) {
446 		scache_save_dest_service(client_stream);
447 	    } else if (VSTREQ(scache_request, SCACHE_REQ_FIND_DEST)) {
448 		scache_find_dest_service(client_stream);
449 	    } else if (VSTREQ(scache_request, SCACHE_REQ_SAVE_ENDP)) {
450 		scache_save_endp_service(client_stream);
451 	    } else if (VSTREQ(scache_request, SCACHE_REQ_FIND_ENDP)) {
452 		scache_find_endp_service(client_stream);
453 	    } else {
454 		msg_warn("unrecognized request: \"%s\", ignored",
455 			 STR(scache_request));
456 		attr_print(client_stream, ATTR_FLAG_NONE,
457 			   SEND_ATTR_INT(MAIL_ATTR_STATUS, SCACHE_STAT_BAD),
458 			   ATTR_TYPE_END);
459 	    }
460 	}
461     } while (vstream_peek(client_stream) > 0);
462     vstream_fflush(client_stream);
463 }
464 
465 /* scache_status_dump - log and reset cache statistics */
466 
467 static void scache_status_dump(char *unused_name, char **unused_argv)
468 {
469     if (scache_dest_hits || scache_dest_miss
470 	|| scache_endp_hits || scache_endp_miss
471 	|| scache_dest_count || scache_endp_count
472 	|| scache_sess_count)
473 	msg_info("statistics: start interval %.15s",
474 		 ctime(&scache_start_time) + 4);
475 
476     if (scache_dest_hits || scache_dest_miss) {
477 	msg_info("statistics: domain lookup hits=%d miss=%d success=%d%%",
478 		 scache_dest_hits, scache_dest_miss,
479 		 scache_dest_hits * 100
480 		 / (scache_dest_hits + scache_dest_miss));
481 	scache_dest_hits = scache_dest_miss = 0;
482     }
483     if (scache_endp_hits || scache_endp_miss) {
484 	msg_info("statistics: address lookup hits=%d miss=%d success=%d%%",
485 		 scache_endp_hits, scache_endp_miss,
486 		 scache_endp_hits * 100
487 		 / (scache_endp_hits + scache_endp_miss));
488 	scache_endp_hits = scache_endp_miss = 0;
489     }
490     if (scache_dest_count || scache_endp_count || scache_sess_count) {
491 	msg_info("statistics: max simultaneous domains=%d addresses=%d connection=%d",
492 		 scache_dest_count, scache_endp_count, scache_sess_count);
493 	scache_dest_count = 0;
494 	scache_endp_count = 0;
495 	scache_sess_count = 0;
496     }
497     scache_start_time = event_time();
498 }
499 
500 /* scache_status_update - log and reset cache statistics periodically */
501 
502 static void scache_status_update(int unused_event, void *context)
503 {
504     scache_status_dump((char *) 0, (char **) 0);
505     event_request_timer(scache_status_update, context, var_scache_stat_time);
506 }
507 
508 /* post_jail_init - initialization after privilege drop */
509 
510 static void post_jail_init(char *unused_name, char **unused_argv)
511 {
512 
513     /*
514      * Pre-allocate the cache instance.
515      */
516     scache = scache_multi_create();
517 
518     /*
519      * Pre-allocate buffers.
520      */
521     scache_request = vstring_alloc(10);
522     scache_dest_label = vstring_alloc(10);
523     scache_dest_prop = vstring_alloc(10);
524     scache_endp_label = vstring_alloc(10);
525     scache_endp_prop = vstring_alloc(10);
526 #ifdef CANT_WRITE_BEFORE_SENDING_FD
527     scache_dummy = vstring_alloc(10);
528 #endif
529 
530     /*
531      * Disable the max_use limit. We still terminate when no client is
532      * connected for $idle_limit time units.
533      */
534     var_use_limit = 0;
535 
536     /*
537      * Dump and reset cache statistics every so often.
538      */
539     event_request_timer(scache_status_update, (void *) 0, var_scache_stat_time);
540     scache_start_time = event_time();
541 }
542 
543 MAIL_VERSION_STAMP_DECLARE;
544 
545 /* main - pass control to the multi-threaded skeleton */
546 
547 int     main(int argc, char **argv)
548 {
549     static const CONFIG_TIME_TABLE time_table[] = {
550 	VAR_SCACHE_TTL_LIM, DEF_SCACHE_TTL_LIM, &var_scache_ttl_lim, 1, 0,
551 	VAR_SCACHE_STAT_TIME, DEF_SCACHE_STAT_TIME, &var_scache_stat_time, 1, 0,
552 	0,
553     };
554 
555     /*
556      * Fingerprint executables and core dumps.
557      */
558     MAIL_VERSION_STAMP_ALLOCATE;
559 
560     multi_server_main(argc, argv, scache_service,
561 		      CA_MAIL_SERVER_TIME_TABLE(time_table),
562 		      CA_MAIL_SERVER_POST_INIT(post_jail_init),
563 		      CA_MAIL_SERVER_EXIT(scache_status_dump),
564 		      CA_MAIL_SERVER_SOLITARY,
565 		      0);
566 }
567