xref: /netbsd-src/external/ibm-public/postfix/dist/src/trivial-rewrite/trivial-rewrite.c (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1 /*	$NetBSD: trivial-rewrite.c,v 1.1.1.2 2010/06/17 18:07:10 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	trivial-rewrite 8
6 /* SUMMARY
7 /*	Postfix address rewriting and resolving daemon
8 /* SYNOPSIS
9 /*	\fBtrivial-rewrite\fR [generic Postfix daemon options]
10 /* DESCRIPTION
11 /*	The \fBtrivial-rewrite\fR(8) daemon processes three types of client
12 /*	service requests:
13 /* .IP "\fBrewrite \fIcontext address\fR"
14 /*	Rewrite an address to standard form, according to the
15 /*	address rewriting context:
16 /* .RS
17 /* .IP \fBlocal\fR
18 /*	Append the domain names specified with \fB$myorigin\fR or
19 /*	\fB$mydomain\fR to incomplete addresses; do \fBswap_bangpath\fR
20 /*	and \fBallow_percent_hack\fR processing as described below, and
21 /*	strip source routed addresses (\fI@site,@site:user@domain\fR)
22 /*	to \fIuser@domain\fR form.
23 /* .IP \fBremote\fR
24 /*	Append the domain name specified with
25 /*	\fB$remote_header_rewrite_domain\fR to incomplete
26 /*	addresses. Otherwise the result is identical to that of
27 /*	the \fBlocal\fR address rewriting context. This prevents
28 /*      Postfix from appending the local domain to spam from poorly
29 /*	written remote clients.
30 /* .RE
31 /* .IP "\fBresolve \fIsender\fR \fIaddress\fR"
32 /*	Resolve the address to a (\fItransport\fR, \fInexthop\fR,
33 /*      \fIrecipient\fR, \fIflags\fR) quadruple. The meaning of
34 /*	the results is as follows:
35 /* .RS
36 /* .IP \fItransport\fR
37 /*	The delivery agent to use. This is the first field of an entry
38 /*	in the \fBmaster.cf\fR file.
39 /* .IP \fInexthop\fR
40 /*	The host to send to and optional delivery method information.
41 /* .IP \fIrecipient\fR
42 /*	The envelope recipient address that is passed on to \fInexthop\fR.
43 /* .IP \fIflags\fR
44 /*	The address class, whether the address requires relaying,
45 /*	whether the address has problems, and whether the request failed.
46 /* .RE
47 /* .IP "\fBverify \fIsender\fR \fIaddress\fR"
48 /*	Resolve the address for address verification purposes.
49 /* SERVER PROCESS MANAGEMENT
50 /* .ad
51 /* .fi
52 /*	The \fBtrivial-rewrite\fR(8) servers run under control by
53 /*	the Postfix master
54 /*	server.  Each server can handle multiple simultaneous connections.
55 /*	When all servers are busy while a client connects, the master
56 /*	creates a new server process, provided that the trivial-rewrite
57 /*	server process limit is not exceeded.
58 /*	Each trivial-rewrite server terminates after
59 /*	serving at least \fB$max_use\fR clients of after \fB$max_idle\fR
60 /*	seconds of idle time.
61 /* STANDARDS
62 /* .ad
63 /* .fi
64 /*	None. The command does not interact with the outside world.
65 /* SECURITY
66 /* .ad
67 /* .fi
68 /*	The \fBtrivial-rewrite\fR(8) daemon is not security sensitive.
69 /*	By default, this daemon does not talk to remote or local users.
70 /*	It can run at a fixed low privilege in a chrooted environment.
71 /* DIAGNOSTICS
72 /*	Problems and transactions are logged to \fBsyslogd\fR(8).
73 /* CONFIGURATION PARAMETERS
74 /* .ad
75 /* .fi
76 /*	On busy mail systems a long time may pass before a \fBmain.cf\fR
77 /*	change affecting \fBtrivial-rewrite\fR(8) is picked up. Use the command
78 /*	"\fBpostfix reload\fR" to speed up a change.
79 /*
80 /*	The text below provides only a parameter summary. See
81 /*	\fBpostconf\fR(5) for more details including examples.
82 /* COMPATIBILITY CONTROLS
83 /* .ad
84 /* .fi
85 /* .IP "\fBresolve_dequoted_address (yes)\fR"
86 /*	Resolve a recipient address safely instead of correctly, by
87 /*	looking inside quotes.
88 /* .IP "\fBresolve_null_domain (no)\fR"
89 /*	Resolve an address that ends in the "@" null domain as if the
90 /*	local hostname were specified, instead of rejecting the address as
91 /*	invalid.
92 /* .IP "\fBresolve_numeric_domain (no)\fR"
93 /*	Resolve "user@ipaddress" as "user@[ipaddress]", instead of
94 /*	rejecting the address as invalid.
95 /* .PP
96 /*	Available with Postfix version 2.5 and later:
97 /* .IP "\fBallow_min_user (no)\fR"
98 /*	Allow a sender or recipient address to have `-' as the first
99 /*	character.
100 /* ADDRESS REWRITING CONTROLS
101 /* .ad
102 /* .fi
103 /* .IP "\fBmyorigin ($myhostname)\fR"
104 /*	The domain name that locally-posted mail appears to come
105 /*	from, and that locally posted mail is delivered to.
106 /* .IP "\fBallow_percent_hack (yes)\fR"
107 /*	Enable the rewriting of the form "user%domain" to "user@domain".
108 /* .IP "\fBappend_at_myorigin (yes)\fR"
109 /*	With locally submitted mail, append the string "@$myorigin" to mail
110 /*	addresses without domain information.
111 /* .IP "\fBappend_dot_mydomain (yes)\fR"
112 /*	With locally submitted mail, append the string ".$mydomain" to
113 /*	addresses that have no ".domain" information.
114 /* .IP "\fBrecipient_delimiter (empty)\fR"
115 /*	The separator between user names and address extensions (user+foo).
116 /* .IP "\fBswap_bangpath (yes)\fR"
117 /*	Enable the rewriting of "site!user" into "user@site".
118 /* .PP
119 /*	Available in Postfix 2.2 and later:
120 /* .IP "\fBremote_header_rewrite_domain (empty)\fR"
121 /*	Don't rewrite message headers from remote clients at all when
122 /*	this parameter is empty; otherwise, rewrite message headers and
123 /*	append the specified domain name to incomplete addresses.
124 /* ROUTING CONTROLS
125 /* .ad
126 /* .fi
127 /*	The following is applicable to Postfix version 2.0 and later.
128 /*	Earlier versions do not have support for: virtual_transport,
129 /*	relay_transport, virtual_alias_domains, virtual_mailbox_domains
130 /*	or proxy_interfaces.
131 /* .IP "\fBlocal_transport (local:$myhostname)\fR"
132 /*	The default mail delivery transport and next-hop destination
133 /*	for final delivery to domains listed with mydestination, and for
134 /*	[ipaddress] destinations that match $inet_interfaces or $proxy_interfaces.
135 /* .IP "\fBvirtual_transport (virtual)\fR"
136 /*	The default mail delivery transport and next-hop destination for
137 /*	final delivery to domains listed with $virtual_mailbox_domains.
138 /* .IP "\fBrelay_transport (relay)\fR"
139 /*	The default mail delivery transport and next-hop destination for
140 /*	remote delivery to domains listed with $relay_domains.
141 /* .IP "\fBdefault_transport (smtp)\fR"
142 /*	The default mail delivery transport and next-hop destination for
143 /*	destinations that do not match $mydestination, $inet_interfaces,
144 /*	$proxy_interfaces, $virtual_alias_domains, $virtual_mailbox_domains,
145 /*	or $relay_domains.
146 /* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR"
147 /*	What Postfix features match subdomains of "domain.tld" automatically,
148 /*	instead of requiring an explicit ".domain.tld" pattern.
149 /* .IP "\fBrelayhost (empty)\fR"
150 /*	The next-hop destination of non-local mail; overrides non-local
151 /*	domains in recipient addresses.
152 /* .IP "\fBtransport_maps (empty)\fR"
153 /*	Optional lookup tables with mappings from recipient address to
154 /*	(message delivery transport, next-hop destination).
155 /* .PP
156 /*	Available in Postfix version 2.3 and later:
157 /* .IP "\fBsender_dependent_relayhost_maps (empty)\fR"
158 /*	A sender-dependent override for the global relayhost parameter
159 /*	setting.
160 /* .PP
161 /*	Available in Postfix version 2.5 and later:
162 /* .IP "\fBempty_address_relayhost_maps_lookup_key (<>)\fR"
163 /*	The sender_dependent_relayhost_maps search string that will be
164 /*	used instead of the null sender address.
165 /* .PP
166 /*	Available in Postfix version 2.7 and later:
167 /* .IP "\fBempty_address_default_transport_maps_lookup_key (<>)\fR"
168 /*	The sender_dependent_default_transport_maps search string that
169 /*	will be used instead of the null sender address.
170 /* .IP "\fBsender_dependent_default_transport_maps (empty)\fR"
171 /*	A sender-dependent override for the global default_transport
172 /*	parameter setting.
173 /* ADDRESS VERIFICATION CONTROLS
174 /* .ad
175 /* .fi
176 /*	Postfix version 2.1 introduces sender and recipient address verification.
177 /*	This feature is implemented by sending probe email messages that
178 /*	are not actually delivered.
179 /*	By default, address verification probes use the same route
180 /*	as regular mail. To override specific aspects of message
181 /*	routing for address verification probes, specify one or more
182 /*	of the following:
183 /* .IP "\fBaddress_verify_local_transport ($local_transport)\fR"
184 /*	Overrides the local_transport parameter setting for address
185 /*	verification probes.
186 /* .IP "\fBaddress_verify_virtual_transport ($virtual_transport)\fR"
187 /*	Overrides the virtual_transport parameter setting for address
188 /*	verification probes.
189 /* .IP "\fBaddress_verify_relay_transport ($relay_transport)\fR"
190 /*	Overrides the relay_transport parameter setting for address
191 /*	verification probes.
192 /* .IP "\fBaddress_verify_default_transport ($default_transport)\fR"
193 /*	Overrides the default_transport parameter setting for address
194 /*	verification probes.
195 /* .IP "\fBaddress_verify_relayhost ($relayhost)\fR"
196 /*	Overrides the relayhost parameter setting for address verification
197 /*	probes.
198 /* .IP "\fBaddress_verify_transport_maps ($transport_maps)\fR"
199 /*	Overrides the transport_maps parameter setting for address verification
200 /*	probes.
201 /* .PP
202 /*	Available in Postfix version 2.3 and later:
203 /* .IP "\fBaddress_verify_sender_dependent_relayhost_maps ($sender_dependent_relayhost_maps)\fR"
204 /*	Overrides the sender_dependent_relayhost_maps parameter setting for address
205 /*	verification probes.
206 /* .PP
207 /*	Available in Postfix version 2.7 and later:
208 /* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR"
209 /*	Overrides the sender_dependent_default_transport_maps parameter
210 /*	setting for address verification probes.
211 /* MISCELLANEOUS CONTROLS
212 /* .ad
213 /* .fi
214 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
215 /*	The default location of the Postfix main.cf and master.cf
216 /*	configuration files.
217 /* .IP "\fBdaemon_timeout (18000s)\fR"
218 /*	How much time a Postfix daemon process may take to handle a
219 /*	request before it is terminated by a built-in watchdog timer.
220 /* .IP "\fBempty_address_recipient (MAILER-DAEMON)\fR"
221 /*	The recipient of mail addressed to the null address.
222 /* .IP "\fBipc_timeout (3600s)\fR"
223 /*	The time limit for sending or receiving information over an internal
224 /*	communication channel.
225 /* .IP "\fBmax_idle (100s)\fR"
226 /*	The maximum amount of time that an idle Postfix daemon process waits
227 /*	for an incoming connection before terminating voluntarily.
228 /* .IP "\fBmax_use (100)\fR"
229 /*	The maximal number of incoming connections that a Postfix daemon
230 /*	process will service before terminating voluntarily.
231 /* .IP "\fBrelocated_maps (empty)\fR"
232 /*	Optional lookup tables with new contact information for users or
233 /*	domains that no longer exist.
234 /* .IP "\fBprocess_id (read-only)\fR"
235 /*	The process ID of a Postfix command or daemon process.
236 /* .IP "\fBprocess_name (read-only)\fR"
237 /*	The process name of a Postfix command or daemon process.
238 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
239 /*	The location of the Postfix top-level queue directory.
240 /* .IP "\fBshow_user_unknown_table_name (yes)\fR"
241 /*	Display the name of the recipient table in the "User unknown"
242 /*	responses.
243 /* .IP "\fBsyslog_facility (mail)\fR"
244 /*	The syslog facility of Postfix logging.
245 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
246 /*	The mail system name that is prepended to the process name in syslog
247 /*	records, so that "smtpd" becomes, for example, "postfix/smtpd".
248 /* .PP
249 /*	Available in Postfix version 2.0 and later:
250 /* .IP "\fBhelpful_warnings (yes)\fR"
251 /*	Log warnings about problematic configuration settings, and provide
252 /*	helpful suggestions.
253 /* SEE ALSO
254 /*	postconf(5), configuration parameters
255 /*	transport(5), transport table format
256 /*	relocated(5), format of the "user has moved" table
257 /*	master(8), process manager
258 /*	syslogd(8), system logging
259 /* README FILES
260 /* .ad
261 /* .fi
262 /*	Use "\fBpostconf readme_directory\fR" or
263 /*	"\fBpostconf html_directory\fR" to locate this information.
264 /* .na
265 /* .nf
266 /*	ADDRESS_CLASS_README, Postfix address classes howto
267 /*	ADDRESS_VERIFICATION_README, Postfix address verification
268 /* LICENSE
269 /* .ad
270 /* .fi
271 /*	The Secure Mailer license must be distributed with this software.
272 /* AUTHOR(S)
273 /*	Wietse Venema
274 /*	IBM T.J. Watson Research
275 /*	P.O. Box 704
276 /*	Yorktown Heights, NY 10598, USA
277 /*--*/
278 
279 /* System library. */
280 
281 #include <sys_defs.h>
282 #include <unistd.h>
283 #include <stdlib.h>
284 #include <string.h>
285 
286 /* Utility library. */
287 
288 #include <msg.h>
289 #include <vstring.h>
290 #include <vstream.h>
291 #include <vstring_vstream.h>
292 #include <split_at.h>
293 #include <stringops.h>
294 #include <dict.h>
295 #include <events.h>
296 
297 /* Global library. */
298 
299 #include <mail_params.h>
300 #include <mail_version.h>
301 #include <mail_proto.h>
302 #include <resolve_local.h>
303 #include <mail_conf.h>
304 #include <resolve_clnt.h>
305 #include <rewrite_clnt.h>
306 #include <tok822.h>
307 #include <mail_addr.h>
308 
309 /* Multi server skeleton. */
310 
311 #include <mail_server.h>
312 
313 /* Application-specific. */
314 
315 #include <trivial-rewrite.h>
316 #include <transport.h>
317 
318 static VSTRING *command;
319 
320  /*
321   * Tunable parameters.
322   */
323 char   *var_transport_maps;
324 bool    var_swap_bangpath;
325 bool    var_append_dot_mydomain;
326 bool    var_append_at_myorigin;
327 bool    var_percent_hack;
328 char   *var_local_transport;
329 char   *var_virt_transport;
330 char   *var_relay_transport;
331 int     var_resolve_dequoted;
332 char   *var_virt_alias_maps;		/* XXX virtual_alias_domains */
333 char   *var_virt_mailbox_maps;		/* XXX virtual_mailbox_domains */
334 char   *var_virt_alias_doms;
335 char   *var_virt_mailbox_doms;
336 char   *var_relocated_maps;
337 char   *var_def_transport;
338 char   *var_snd_def_xport_maps;
339 char   *var_empty_addr;
340 int     var_show_unk_rcpt_table;
341 int     var_resolve_nulldom;
342 char   *var_remote_rwr_domain;
343 char   *var_snd_relay_maps;
344 char   *var_null_relay_maps_key;
345 char   *var_null_def_xport_maps_key;
346 int     var_resolve_num_dom;
347 bool    var_allow_min_user;
348 
349  /*
350   * Shadow personality for address verification.
351   */
352 char   *var_vrfy_xport_maps;
353 char   *var_vrfy_local_xport;
354 char   *var_vrfy_virt_xport;
355 char   *var_vrfy_relay_xport;
356 char   *var_vrfy_def_xport;
357 char   *var_vrfy_snd_def_xport_maps;
358 char   *var_vrfy_relayhost;
359 char   *var_vrfy_relay_maps;
360 
361  /*
362   * Different resolver personalities depending on the kind of request.
363   */
364 RES_CONTEXT resolve_regular = {
365     VAR_LOCAL_TRANSPORT, &var_local_transport,
366     VAR_VIRT_TRANSPORT, &var_virt_transport,
367     VAR_RELAY_TRANSPORT, &var_relay_transport,
368     VAR_DEF_TRANSPORT, &var_def_transport,
369     VAR_SND_DEF_XPORT_MAPS, &var_snd_def_xport_maps, 0,
370     VAR_RELAYHOST, &var_relayhost,
371     VAR_SND_RELAY_MAPS, &var_snd_relay_maps, 0,
372     VAR_TRANSPORT_MAPS, &var_transport_maps, 0
373 };
374 
375 RES_CONTEXT resolve_verify = {
376     VAR_VRFY_LOCAL_XPORT, &var_vrfy_local_xport,
377     VAR_VRFY_VIRT_XPORT, &var_vrfy_virt_xport,
378     VAR_VRFY_RELAY_XPORT, &var_vrfy_relay_xport,
379     VAR_VRFY_DEF_XPORT, &var_vrfy_def_xport,
380     VAR_VRFY_SND_DEF_XPORT_MAPS, &var_vrfy_snd_def_xport_maps, 0,
381     VAR_VRFY_RELAYHOST, &var_vrfy_relayhost,
382     VAR_VRFY_RELAY_MAPS, &var_vrfy_relay_maps, 0,
383     VAR_VRFY_XPORT_MAPS, &var_vrfy_xport_maps, 0
384 };
385 
386  /*
387   * Connection management. When file-based lookup tables change we should
388   * restart at our convenience, but avoid client read errors. We restart
389   * rather than reopen, because the process may be chrooted (and if it isn't
390   * we still need code that handles the chrooted case anyway).
391   *
392   * Three variants are implemented. Only one should be used.
393   *
394   * ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
395   *
396   * This code detaches the trivial-rewrite process from the master, stops
397   * accepting new clients, and handles established clients in the background,
398   * asking them to reconnect the next time they send a request. The master
399   * creates a new process that accepts connections. This is reasonably safe
400   * because the number of trivial-rewrite server processes is small compared
401   * to the number of trivial-rewrite client processes. The few extra
402   * background processes should not make a difference in Postfix's footprint.
403   * However, once a daemon detaches from the master, its exit status will be
404   * lost, and abnormal termination may remain undetected. Timely restart is
405   * achieved by checking the table changed status every 10 seconds or so
406   * before responding to a client request.
407   *
408   * ifdef CHECK_TABLE_STATS_PERIODICALLY
409   *
410   * This code runs every 10 seconds and terminates the process when lookup
411   * tables have changed. This is subject to race conditions when established
412   * clients send a request while the server exits; those clients may read EOF
413   * instead of a server reply. If the experience with the oldest option
414   * (below) is anything to go by, however, then this is unlikely to be a
415   * problem during real deployment.
416   *
417   * ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
418   *
419   * This is the old code. It checks the table changed status when a new client
420   * connects (i.e. before the server calls accept()), and terminates
421   * immediately. This is invisible for the connecting client, but is subject
422   * to race conditions when established clients send a request while the
423   * server exits; those clients may read EOF instead of a server reply. This
424   * has, however, not been a problem in real deployment. With the old code,
425   * timely restart is achieved by setting the ipc_ttl parameter to 60
426   * seconds, so that the table change status is checked several times a
427   * minute.
428   */
429 int     server_flags;
430 
431  /*
432   * Define exactly one of these.
433   */
434 /* #define DETACH_AND_ASK_CLIENTS_TO_RECONNECT	/* correct and complex */
435 #define CHECK_TABLE_STATS_PERIODICALLY	/* quick */
436 /* #define CHECK_TABLE_STATS_BEFORE_ACCEPT	/* slow */
437 
438 /* rewrite_service - read request and send reply */
439 
440 static void rewrite_service(VSTREAM *stream, char *unused_service, char **argv)
441 {
442     int     status = -1;
443 
444 #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
445     static time_t last;
446     time_t  now;
447     const char *table;
448 
449 #endif
450 
451     /*
452      * Sanity check. This service takes no command-line arguments.
453      */
454     if (argv[0])
455 	msg_fatal("unexpected command-line argument: %s", argv[0]);
456 
457     /*
458      * Client connections are long-lived. Be sure to refesh timely.
459      */
460 #ifdef DETACH_AND_ASK_CLIENTS_TO_RECONNECT
461     if (server_flags == 0 && (now = event_time()) - last > 10) {
462 	if ((table = dict_changed_name()) != 0) {
463 	    msg_info("table %s has changed -- restarting", table);
464 	    if (multi_server_drain() == 0)
465 		server_flags = 1;
466 	}
467 	last = now;
468     }
469 #endif
470 
471     /*
472      * This routine runs whenever a client connects to the UNIX-domain socket
473      * dedicated to address rewriting. All connection-management stuff is
474      * handled by the common code in multi_server.c.
475      */
476     if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
477 		  ATTR_TYPE_STR, MAIL_ATTR_REQ, command,
478 		  ATTR_TYPE_END) == 1) {
479 	if (strcmp(vstring_str(command), REWRITE_ADDR) == 0) {
480 	    status = rewrite_proto(stream);
481 	} else if (strcmp(vstring_str(command), RESOLVE_REGULAR) == 0) {
482 	    status = resolve_proto(&resolve_regular, stream);
483 	} else if (strcmp(vstring_str(command), RESOLVE_VERIFY) == 0) {
484 	    status = resolve_proto(&resolve_verify, stream);
485 	} else {
486 	    msg_warn("bad command %.30s", printable(vstring_str(command), '?'));
487 	}
488     }
489     if (status < 0)
490 	multi_server_disconnect(stream);
491 }
492 
493 /* pre_accept - see if tables have changed */
494 
495 #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
496 
497 static void pre_accept(char *unused_name, char **unused_argv)
498 {
499     const char *table;
500 
501     if ((table = dict_changed_name()) != 0) {
502 	msg_info("table %s has changed -- restarting", table);
503 	exit(0);
504     }
505 }
506 
507 #endif
508 
509 static void check_table_stats(int unused_event, char *unused_context)
510 {
511     const char *table;
512 
513     if ((table = dict_changed_name()) != 0) {
514 	msg_info("table %s has changed -- restarting", table);
515 	exit(0);
516     }
517     event_request_timer(check_table_stats, (char *) 0, 10);
518 }
519 
520 /* pre_jail_init - initialize before entering chroot jail */
521 
522 static void pre_jail_init(char *unused_name, char **unused_argv)
523 {
524     command = vstring_alloc(100);
525     rewrite_init();
526     resolve_init();
527     if (*RES_PARAM_VALUE(resolve_regular.transport_maps))
528 	resolve_regular.transport_info =
529 	    transport_pre_init(resolve_regular.transport_maps_name,
530 			   RES_PARAM_VALUE(resolve_regular.transport_maps));
531     if (*RES_PARAM_VALUE(resolve_verify.transport_maps))
532 	resolve_verify.transport_info =
533 	    transport_pre_init(resolve_verify.transport_maps_name,
534 			    RES_PARAM_VALUE(resolve_verify.transport_maps));
535     if (*RES_PARAM_VALUE(resolve_regular.snd_relay_maps))
536 	resolve_regular.snd_relay_info =
537 	    maps_create(resolve_regular.snd_relay_maps_name,
538 			RES_PARAM_VALUE(resolve_regular.snd_relay_maps),
539 			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
540 			| DICT_FLAG_NO_REGSUB);
541     if (*RES_PARAM_VALUE(resolve_verify.snd_relay_maps))
542 	resolve_verify.snd_relay_info =
543 	    maps_create(resolve_verify.snd_relay_maps_name,
544 			RES_PARAM_VALUE(resolve_verify.snd_relay_maps),
545 			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
546 			| DICT_FLAG_NO_REGSUB);
547     if (*RES_PARAM_VALUE(resolve_regular.snd_def_xp_maps))
548 	resolve_regular.snd_def_xp_info =
549 	    maps_create(resolve_regular.snd_def_xp_maps_name,
550 			RES_PARAM_VALUE(resolve_regular.snd_def_xp_maps),
551 			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
552 			| DICT_FLAG_NO_REGSUB);
553     if (*RES_PARAM_VALUE(resolve_verify.snd_def_xp_maps))
554 	resolve_verify.snd_def_xp_info =
555 	    maps_create(resolve_verify.snd_def_xp_maps_name,
556 			RES_PARAM_VALUE(resolve_verify.snd_def_xp_maps),
557 			DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
558 			| DICT_FLAG_NO_REGSUB);
559 }
560 
561 /* post_jail_init - initialize after entering chroot jail */
562 
563 static void post_jail_init(char *unused_name, char **unused_argv)
564 {
565     if (resolve_regular.transport_info)
566 	transport_post_init(resolve_regular.transport_info);
567     if (resolve_verify.transport_info)
568 	transport_post_init(resolve_verify.transport_info);
569     check_table_stats(0, (char *) 0);
570 }
571 
572 MAIL_VERSION_STAMP_DECLARE;
573 
574 /* main - pass control to the multi-threaded skeleton code */
575 
576 int     main(int argc, char **argv)
577 {
578     static const CONFIG_STR_TABLE str_table[] = {
579 	VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
580 	VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 1, 0,
581 	VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport, 1, 0,
582 	VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport, 1, 0,
583 	VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 1, 0,
584 	VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0,
585 	VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 0, 0,
586 	VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,
587 	VAR_VIRT_MAILBOX_DOMS, DEF_VIRT_MAILBOX_DOMS, &var_virt_mailbox_doms, 0, 0,
588 	VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocated_maps, 0, 0,
589 	VAR_EMPTY_ADDR, DEF_EMPTY_ADDR, &var_empty_addr, 1, 0,
590 	VAR_VRFY_XPORT_MAPS, DEF_VRFY_XPORT_MAPS, &var_vrfy_xport_maps, 0, 0,
591 	VAR_VRFY_LOCAL_XPORT, DEF_VRFY_LOCAL_XPORT, &var_vrfy_local_xport, 1, 0,
592 	VAR_VRFY_VIRT_XPORT, DEF_VRFY_VIRT_XPORT, &var_vrfy_virt_xport, 1, 0,
593 	VAR_VRFY_RELAY_XPORT, DEF_VRFY_RELAY_XPORT, &var_vrfy_relay_xport, 1, 0,
594 	VAR_VRFY_DEF_XPORT, DEF_VRFY_DEF_XPORT, &var_vrfy_def_xport, 1, 0,
595 	VAR_VRFY_RELAYHOST, DEF_VRFY_RELAYHOST, &var_vrfy_relayhost, 0, 0,
596 	VAR_REM_RWR_DOMAIN, DEF_REM_RWR_DOMAIN, &var_remote_rwr_domain, 0, 0,
597 	VAR_SND_RELAY_MAPS, DEF_SND_RELAY_MAPS, &var_snd_relay_maps, 0, 0,
598 	VAR_NULL_RELAY_MAPS_KEY, DEF_NULL_RELAY_MAPS_KEY, &var_null_relay_maps_key, 1, 0,
599 	VAR_VRFY_RELAY_MAPS, DEF_VRFY_RELAY_MAPS, &var_vrfy_relay_maps, 0, 0,
600 	VAR_SND_DEF_XPORT_MAPS, DEF_SND_DEF_XPORT_MAPS, &var_snd_def_xport_maps, 0, 0,
601 	VAR_NULL_DEF_XPORT_MAPS_KEY, DEF_NULL_DEF_XPORT_MAPS_KEY, &var_null_def_xport_maps_key, 1, 0,
602 	VAR_VRFY_SND_DEF_XPORT_MAPS, DEF_VRFY_SND_DEF_XPORT_MAPS, &var_vrfy_snd_def_xport_maps, 0, 0,
603 	0,
604     };
605     static const CONFIG_BOOL_TABLE bool_table[] = {
606 	VAR_SWAP_BANGPATH, DEF_SWAP_BANGPATH, &var_swap_bangpath,
607 	VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
608 	VAR_APP_AT_MYORIGIN, DEF_APP_AT_MYORIGIN, &var_append_at_myorigin,
609 	VAR_PERCENT_HACK, DEF_PERCENT_HACK, &var_percent_hack,
610 	VAR_RESOLVE_DEQUOTED, DEF_RESOLVE_DEQUOTED, &var_resolve_dequoted,
611 	VAR_SHOW_UNK_RCPT_TABLE, DEF_SHOW_UNK_RCPT_TABLE, &var_show_unk_rcpt_table,
612 	VAR_RESOLVE_NULLDOM, DEF_RESOLVE_NULLDOM, &var_resolve_nulldom,
613 	VAR_RESOLVE_NUM_DOM, DEF_RESOLVE_NUM_DOM, &var_resolve_num_dom,
614 	VAR_ALLOW_MIN_USER, DEF_ALLOW_MIN_USER, &var_allow_min_user,
615 	0,
616     };
617 
618     /*
619      * Fingerprint executables and core dumps.
620      */
621     MAIL_VERSION_STAMP_ALLOCATE;
622 
623     multi_server_main(argc, argv, rewrite_service,
624 		      MAIL_SERVER_STR_TABLE, str_table,
625 		      MAIL_SERVER_BOOL_TABLE, bool_table,
626 		      MAIL_SERVER_PRE_INIT, pre_jail_init,
627 		      MAIL_SERVER_POST_INIT, post_jail_init,
628 #ifdef CHECK_TABLE_STATS_BEFORE_ACCEPT
629 		      MAIL_SERVER_PRE_ACCEPT, pre_accept,
630 #endif
631 		      0);
632 }
633