1 /* $NetBSD: bounce.c,v 1.2 2017/02/14 01:16:44 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* bounce 8 6 /* SUMMARY 7 /* Postfix delivery status reports 8 /* SYNOPSIS 9 /* \fBbounce\fR [generic Postfix daemon options] 10 /* DESCRIPTION 11 /* The \fBbounce\fR(8) daemon maintains per-message log files with 12 /* delivery status information. Each log file is named after the 13 /* queue file that it corresponds to, and is kept in a queue subdirectory 14 /* named after the service name in the \fBmaster.cf\fR file (either 15 /* \fBbounce\fR, \fBdefer\fR or \fBtrace\fR). 16 /* This program expects to be run from the \fBmaster\fR(8) process 17 /* manager. 18 /* 19 /* The \fBbounce\fR(8) daemon processes two types of service requests: 20 /* .IP \(bu 21 /* Append a recipient (non-)delivery status record to a per-message 22 /* log file. 23 /* .IP \(bu 24 /* Enqueue a delivery status notification message, with a copy 25 /* of a per-message log file and of the corresponding message. 26 /* When the delivery status notification message is 27 /* enqueued successfully, the per-message log file is deleted. 28 /* .PP 29 /* The software does a best notification effort. A non-delivery 30 /* notification is sent even when the log file or the original 31 /* message cannot be read. 32 /* 33 /* Optionally, a bounce (defer, trace) client can request that the 34 /* per-message log file be deleted when the requested operation fails. 35 /* This is used by clients that cannot retry transactions by 36 /* themselves, and that depend on retry logic in their own client. 37 /* STANDARDS 38 /* RFC 822 (ARPA Internet Text Messages) 39 /* RFC 2045 (Format of Internet Message Bodies) 40 /* RFC 2822 (Internet Message Format) 41 /* RFC 3462 (Delivery Status Notifications) 42 /* RFC 3464 (Delivery Status Notifications) 43 /* RFC 3834 (Auto-Submitted: message header) 44 /* RFC 5322 (Internet Message Format) 45 /* RFC 6531 (Internationalized SMTP) 46 /* RFC 6532 (Internationalized Message Format) 47 /* RFC 6533 (Internationalized Delivery Status Notifications) 48 /* DIAGNOSTICS 49 /* Problems and transactions are logged to \fBsyslogd\fR(8). 50 /* CONFIGURATION PARAMETERS 51 /* .ad 52 /* .fi 53 /* Changes to \fBmain.cf\fR are picked up automatically, as \fBbounce\fR(8) 54 /* processes run for only a limited amount of time. Use the command 55 /* "\fBpostfix reload\fR" to speed up a change. 56 /* 57 /* The text below provides only a parameter summary. See 58 /* \fBpostconf\fR(5) for more details including examples. 59 /* .IP "\fB2bounce_notice_recipient (postmaster)\fR" 60 /* The recipient of undeliverable mail that cannot be returned to 61 /* the sender. 62 /* .IP "\fBbackwards_bounce_logfile_compatibility (yes)\fR" 63 /* Produce additional \fBbounce\fR(8) logfile records that can be read by 64 /* Postfix versions before 2.0. 65 /* .IP "\fBbounce_notice_recipient (postmaster)\fR" 66 /* The recipient of postmaster notifications with the message headers 67 /* of mail that Postfix did not deliver and of SMTP conversation 68 /* transcripts of mail that Postfix did not receive. 69 /* .IP "\fBbounce_size_limit (50000)\fR" 70 /* The maximal amount of original message text that is sent in a 71 /* non-delivery notification. 72 /* .IP "\fBbounce_template_file (empty)\fR" 73 /* Pathname of a configuration file with bounce message templates. 74 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR" 75 /* The default location of the Postfix main.cf and master.cf 76 /* configuration files. 77 /* .IP "\fBdaemon_timeout (18000s)\fR" 78 /* How much time a Postfix daemon process may take to handle a 79 /* request before it is terminated by a built-in watchdog timer. 80 /* .IP "\fBdelay_notice_recipient (postmaster)\fR" 81 /* The recipient of postmaster notifications with the message headers 82 /* of mail that cannot be delivered within $delay_warning_time time 83 /* units. 84 /* .IP "\fBdeliver_lock_attempts (20)\fR" 85 /* The maximal number of attempts to acquire an exclusive lock on a 86 /* mailbox file or \fBbounce\fR(8) logfile. 87 /* .IP "\fBdeliver_lock_delay (1s)\fR" 88 /* The time between attempts to acquire an exclusive lock on a mailbox 89 /* file or \fBbounce\fR(8) logfile. 90 /* .IP "\fBipc_timeout (3600s)\fR" 91 /* The time limit for sending or receiving information over an internal 92 /* communication channel. 93 /* .IP "\fBinternal_mail_filter_classes (empty)\fR" 94 /* What categories of Postfix-generated mail are subject to 95 /* before-queue content inspection by non_smtpd_milters, header_checks 96 /* and body_checks. 97 /* .IP "\fBmail_name (Postfix)\fR" 98 /* The mail system name that is displayed in Received: headers, in 99 /* the SMTP greeting banner, and in bounced mail. 100 /* .IP "\fBmax_idle (100s)\fR" 101 /* The maximum amount of time that an idle Postfix daemon process waits 102 /* for an incoming connection before terminating voluntarily. 103 /* .IP "\fBmax_use (100)\fR" 104 /* The maximal number of incoming connections that a Postfix daemon 105 /* process will service before terminating voluntarily. 106 /* .IP "\fBnotify_classes (resource, software)\fR" 107 /* The list of error classes that are reported to the postmaster. 108 /* .IP "\fBprocess_id (read-only)\fR" 109 /* The process ID of a Postfix command or daemon process. 110 /* .IP "\fBprocess_name (read-only)\fR" 111 /* The process name of a Postfix command or daemon process. 112 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR" 113 /* The location of the Postfix top-level queue directory. 114 /* .IP "\fBsyslog_facility (mail)\fR" 115 /* The syslog facility of Postfix logging. 116 /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" 117 /* The mail system name that is prepended to the process name in syslog 118 /* records, so that "smtpd" becomes, for example, "postfix/smtpd". 119 /* .PP 120 /* Available in Postfix 3.0 and later: 121 /* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" 122 /* Detect that a message requires SMTPUTF8 support for the specified 123 /* mail origin classes. 124 /* FILES 125 /* /var/spool/postfix/bounce/* non-delivery records 126 /* /var/spool/postfix/defer/* non-delivery records 127 /* /var/spool/postfix/trace/* delivery status records 128 /* SEE ALSO 129 /* bounce(5), bounce message template format 130 /* qmgr(8), queue manager 131 /* postconf(5), configuration parameters 132 /* master(5), generic daemon options 133 /* master(8), process manager 134 /* syslogd(8), system logging 135 /* LICENSE 136 /* .ad 137 /* .fi 138 /* The Secure Mailer license must be distributed with this software. 139 /* AUTHOR(S) 140 /* Wietse Venema 141 /* IBM T.J. Watson Research 142 /* P.O. Box 704 143 /* Yorktown Heights, NY 10598, USA 144 /* 145 /* Wietse Venema 146 /* Google, Inc. 147 /* 111 8th Avenue 148 /* New York, NY 10011, USA 149 /*--*/ 150 151 /* System library. */ 152 153 #include <sys_defs.h> 154 #include <string.h> 155 #include <stdlib.h> 156 157 /* Utility library. */ 158 159 #include <msg.h> 160 #include <vstring.h> 161 #include <vstream.h> 162 #include <stringops.h> 163 #include <load_file.h> 164 165 /* Global library. */ 166 167 #include <mail_proto.h> 168 #include <mail_queue.h> 169 #include <mail_params.h> 170 #include <mail_version.h> 171 #include <mail_conf.h> 172 #include <bounce.h> 173 #include <mail_addr.h> 174 #include <rcpt_buf.h> 175 #include <dsb_scan.h> 176 177 /* Single-threaded server skeleton. */ 178 179 #include <mail_server.h> 180 181 /* Application-specific. */ 182 183 #include <bounce_service.h> 184 185 /* 186 * Tunables. 187 */ 188 int var_bounce_limit; 189 int var_max_queue_time; 190 int var_delay_warn_time; 191 char *var_notify_classes; 192 char *var_bounce_rcpt; 193 char *var_2bounce_rcpt; 194 char *var_delay_rcpt; 195 char *var_bounce_tmpl; 196 197 /* 198 * We're single threaded, so we can avoid some memory allocation overhead. 199 */ 200 static VSTRING *queue_id; 201 static VSTRING *queue_name; 202 static RCPT_BUF *rcpt_buf; 203 static VSTRING *encoding; 204 static VSTRING *sender; 205 static VSTRING *dsn_envid; 206 static VSTRING *verp_delims; 207 static DSN_BUF *dsn_buf; 208 209 /* 210 * Templates. 211 */ 212 BOUNCE_TEMPLATES *bounce_templates; 213 214 #define STR vstring_str 215 216 #define VS_NEUTER(s) printable(vstring_str(s), '?') 217 218 /* bounce_append_proto - bounce_append server protocol */ 219 220 static int bounce_append_proto(char *service_name, VSTREAM *client) 221 { 222 const char *myname = "bounce_append_proto"; 223 int flags; 224 225 /* 226 * Read and validate the client request. 227 */ 228 if (mail_command_server(client, 229 RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), 230 RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), 231 RECV_ATTR_FUNC(rcpb_scan, (void *) rcpt_buf), 232 RECV_ATTR_FUNC(dsb_scan, (void *) dsn_buf), 233 ATTR_TYPE_END) != 4) { 234 msg_warn("malformed request"); 235 return (-1); 236 } 237 238 /* 239 * Sanitize input. 240 */ 241 if (mail_queue_id_ok(STR(queue_id)) == 0) { 242 msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); 243 return (-1); 244 } 245 VS_NEUTER(rcpt_buf->address); 246 VS_NEUTER(rcpt_buf->orig_addr); 247 VS_NEUTER(rcpt_buf->dsn_orcpt); 248 VS_NEUTER(dsn_buf->status); 249 VS_NEUTER(dsn_buf->action); 250 VS_NEUTER(dsn_buf->reason); 251 VS_NEUTER(dsn_buf->dtype); 252 VS_NEUTER(dsn_buf->dtext); 253 VS_NEUTER(dsn_buf->mtype); 254 VS_NEUTER(dsn_buf->mname); 255 (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf); 256 (void) DSN_FROM_DSN_BUF(dsn_buf); 257 258 /* 259 * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and 260 * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and 261 * RECIPIENT_FROM_RCPT_BUF(). 262 */ 263 if (msg_verbose) 264 msg_info("%s: flags=0x%x service=%s id=%s org_to=%s to=%s off=%ld dsn_org=%s, notif=0x%x stat=%s act=%s why=%s", 265 myname, flags, service_name, STR(queue_id), 266 STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), 267 rcpt_buf->offset, STR(rcpt_buf->dsn_orcpt), 268 rcpt_buf->dsn_notify, STR(dsn_buf->status), 269 STR(dsn_buf->action), STR(dsn_buf->reason)); 270 271 /* 272 * On request by the client, set up a trap to delete the log file in case 273 * of errors. 274 */ 275 if (flags & BOUNCE_FLAG_CLEAN) 276 bounce_cleanup_register(service_name, STR(queue_id)); 277 278 /* 279 * Execute the request. 280 */ 281 return (bounce_append_service(flags, service_name, STR(queue_id), 282 &rcpt_buf->rcpt, &dsn_buf->dsn)); 283 } 284 285 /* bounce_notify_proto - bounce_notify server protocol */ 286 287 static int bounce_notify_proto(char *service_name, VSTREAM *client, 288 int (*service) (int, char *, char *, char *, 289 char *, int, char *, char *, int, 290 BOUNCE_TEMPLATES *)) 291 { 292 const char *myname = "bounce_notify_proto"; 293 int flags; 294 int smtputf8; 295 int dsn_ret; 296 297 /* 298 * Read and validate the client request. 299 */ 300 if (mail_command_server(client, 301 RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), 302 RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), 303 RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), 304 RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), 305 RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), 306 RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), 307 RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), 308 RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), 309 ATTR_TYPE_END) != 8) { 310 msg_warn("malformed request"); 311 return (-1); 312 } 313 314 /* 315 * Sanitize input. 316 */ 317 if (mail_queue_name_ok(STR(queue_name)) == 0) { 318 msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); 319 return (-1); 320 } 321 if (mail_queue_id_ok(STR(queue_id)) == 0) { 322 msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); 323 return (-1); 324 } 325 VS_NEUTER(encoding); 326 VS_NEUTER(sender); 327 VS_NEUTER(dsn_envid); 328 if (msg_verbose) 329 msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x", 330 myname, flags, service_name, STR(queue_name), STR(queue_id), 331 STR(encoding), smtputf8, STR(sender), STR(dsn_envid), 332 dsn_ret); 333 334 /* 335 * On request by the client, set up a trap to delete the log file in case 336 * of errors. 337 */ 338 if (flags & BOUNCE_FLAG_CLEAN) 339 bounce_cleanup_register(service_name, STR(queue_id)); 340 341 /* 342 * Execute the request. 343 */ 344 return (service(flags, service_name, STR(queue_name), 345 STR(queue_id), STR(encoding), smtputf8, 346 STR(sender), STR(dsn_envid), dsn_ret, 347 bounce_templates)); 348 } 349 350 /* bounce_verp_proto - bounce_notify server protocol, VERP style */ 351 352 static int bounce_verp_proto(char *service_name, VSTREAM *client) 353 { 354 const char *myname = "bounce_verp_proto"; 355 int flags; 356 int smtputf8; 357 int dsn_ret; 358 359 /* 360 * Read and validate the client request. 361 */ 362 if (mail_command_server(client, 363 RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), 364 RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), 365 RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), 366 RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), 367 RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), 368 RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), 369 RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), 370 RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), 371 RECV_ATTR_STR(MAIL_ATTR_VERPDL, verp_delims), 372 ATTR_TYPE_END) != 9) { 373 msg_warn("malformed request"); 374 return (-1); 375 } 376 377 /* 378 * Sanitize input. 379 */ 380 if (mail_queue_name_ok(STR(queue_name)) == 0) { 381 msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); 382 return (-1); 383 } 384 if (mail_queue_id_ok(STR(queue_id)) == 0) { 385 msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); 386 return (-1); 387 } 388 VS_NEUTER(encoding); 389 VS_NEUTER(sender); 390 VS_NEUTER(dsn_envid); 391 VS_NEUTER(verp_delims); 392 if (strlen(STR(verp_delims)) != 2) { 393 msg_warn("malformed verp delimiter string: %s", STR(verp_delims)); 394 return (-1); 395 } 396 if (msg_verbose) 397 msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x delim=%s", 398 myname, flags, service_name, STR(queue_name), 399 STR(queue_id), STR(encoding), smtputf8, STR(sender), 400 STR(dsn_envid), dsn_ret, STR(verp_delims)); 401 402 /* 403 * On request by the client, set up a trap to delete the log file in case 404 * of errors. 405 */ 406 if (flags & BOUNCE_FLAG_CLEAN) 407 bounce_cleanup_register(service_name, STR(queue_id)); 408 409 /* 410 * Execute the request. Fall back to traditional notification if a bounce 411 * was returned as undeliverable, because we don't want to VERPify those. 412 */ 413 if (!*STR(sender) || !strcasecmp_utf8(STR(sender), 414 mail_addr_double_bounce())) { 415 msg_warn("request to send VERP-style notification of bounced mail"); 416 return (bounce_notify_service(flags, service_name, STR(queue_name), 417 STR(queue_id), STR(encoding), smtputf8, 418 STR(sender), STR(dsn_envid), dsn_ret, 419 bounce_templates)); 420 } else 421 return (bounce_notify_verp(flags, service_name, STR(queue_name), 422 STR(queue_id), STR(encoding), smtputf8, 423 STR(sender), STR(dsn_envid), dsn_ret, 424 STR(verp_delims), bounce_templates)); 425 } 426 427 /* bounce_one_proto - bounce_one server protocol */ 428 429 static int bounce_one_proto(char *service_name, VSTREAM *client) 430 { 431 const char *myname = "bounce_one_proto"; 432 int flags; 433 int smtputf8; 434 int dsn_ret; 435 436 /* 437 * Read and validate the client request. 438 */ 439 if (mail_command_server(client, 440 RECV_ATTR_INT(MAIL_ATTR_FLAGS, &flags), 441 RECV_ATTR_STR(MAIL_ATTR_QUEUE, queue_name), 442 RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id), 443 RECV_ATTR_STR(MAIL_ATTR_ENCODING, encoding), 444 RECV_ATTR_INT(MAIL_ATTR_SMTPUTF8, &smtputf8), 445 RECV_ATTR_STR(MAIL_ATTR_SENDER, sender), 446 RECV_ATTR_STR(MAIL_ATTR_DSN_ENVID, dsn_envid), 447 RECV_ATTR_INT(MAIL_ATTR_DSN_RET, &dsn_ret), 448 RECV_ATTR_FUNC(rcpb_scan, (void *) rcpt_buf), 449 RECV_ATTR_FUNC(dsb_scan, (void *) dsn_buf), 450 ATTR_TYPE_END) != 10) { 451 msg_warn("malformed request"); 452 return (-1); 453 } 454 455 /* 456 * Sanitize input. 457 */ 458 if (strcmp(service_name, MAIL_SERVICE_BOUNCE) != 0) { 459 msg_warn("wrong service name \"%s\" for one-recipient bouncing", 460 service_name); 461 return (-1); 462 } 463 if (mail_queue_name_ok(STR(queue_name)) == 0) { 464 msg_warn("malformed queue name: %s", printable(STR(queue_name), '?')); 465 return (-1); 466 } 467 if (mail_queue_id_ok(STR(queue_id)) == 0) { 468 msg_warn("malformed queue id: %s", printable(STR(queue_id), '?')); 469 return (-1); 470 } 471 VS_NEUTER(encoding); 472 VS_NEUTER(sender); 473 VS_NEUTER(dsn_envid); 474 VS_NEUTER(rcpt_buf->address); 475 VS_NEUTER(rcpt_buf->orig_addr); 476 VS_NEUTER(rcpt_buf->dsn_orcpt); 477 VS_NEUTER(dsn_buf->status); 478 VS_NEUTER(dsn_buf->action); 479 VS_NEUTER(dsn_buf->reason); 480 VS_NEUTER(dsn_buf->dtype); 481 VS_NEUTER(dsn_buf->dtext); 482 VS_NEUTER(dsn_buf->mtype); 483 VS_NEUTER(dsn_buf->mname); 484 (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf); 485 (void) DSN_FROM_DSN_BUF(dsn_buf); 486 487 /* 488 * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and 489 * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and 490 * RECIPIENT_FROM_RCPT_BUF(). 491 */ 492 if (msg_verbose) 493 msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s dsn_ret=0x%x orig_to=%s to=%s off=%ld dsn_orig=%s notif=0x%x stat=%s act=%s why=%s", 494 myname, flags, STR(queue_name), STR(queue_id), 495 STR(encoding), smtputf8, STR(sender), STR(dsn_envid), 496 dsn_ret, STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), 497 rcpt_buf->offset, STR(rcpt_buf->dsn_orcpt), 498 rcpt_buf->dsn_notify, STR(dsn_buf->status), 499 STR(dsn_buf->action), STR(dsn_buf->reason)); 500 501 /* 502 * Execute the request. 503 */ 504 return (bounce_one_service(flags, STR(queue_name), STR(queue_id), 505 STR(encoding), smtputf8, STR(sender), 506 STR(dsn_envid), dsn_ret, rcpt_buf, 507 dsn_buf, bounce_templates)); 508 } 509 510 /* bounce_service - parse bounce command type and delegate */ 511 512 static void bounce_service(VSTREAM *client, char *service_name, char **argv) 513 { 514 int command; 515 int status; 516 517 /* 518 * Sanity check. This service takes no command-line arguments. The 519 * service name should be usable as a subdirectory name. 520 */ 521 if (argv[0]) 522 msg_fatal("unexpected command-line argument: %s", argv[0]); 523 if (mail_queue_name_ok(service_name) == 0) 524 msg_fatal("malformed service name: %s", service_name); 525 526 /* 527 * Read and validate the first parameter of the client request. Let the 528 * request-specific protocol routines take care of the remainder. 529 */ 530 if (attr_scan(client, ATTR_FLAG_STRICT | ATTR_FLAG_MORE, 531 RECV_ATTR_INT(MAIL_ATTR_NREQ, &command), 0) != 1) { 532 msg_warn("malformed request"); 533 status = -1; 534 } else if (command == BOUNCE_CMD_VERP) { 535 status = bounce_verp_proto(service_name, client); 536 } else if (command == BOUNCE_CMD_FLUSH) { 537 status = bounce_notify_proto(service_name, client, 538 bounce_notify_service); 539 } else if (command == BOUNCE_CMD_WARN) { 540 status = bounce_notify_proto(service_name, client, 541 bounce_warn_service); 542 } else if (command == BOUNCE_CMD_TRACE) { 543 status = bounce_notify_proto(service_name, client, 544 bounce_trace_service); 545 } else if (command == BOUNCE_CMD_APPEND) { 546 status = bounce_append_proto(service_name, client); 547 } else if (command == BOUNCE_CMD_ONE) { 548 status = bounce_one_proto(service_name, client); 549 } else { 550 msg_warn("unknown command: %d", command); 551 status = -1; 552 } 553 554 /* 555 * When the request has completed, send the completion status to the 556 * client. 557 */ 558 attr_print(client, ATTR_FLAG_NONE, 559 SEND_ATTR_INT(MAIL_ATTR_STATUS, status), 560 ATTR_TYPE_END); 561 vstream_fflush(client); 562 563 /* 564 * When a cleanup trap was set, delete the log file in case of error. 565 * This includes errors while sending the completion status to the 566 * client. 567 */ 568 if (bounce_cleanup_path) { 569 if (status || vstream_ferror(client)) 570 bounce_cleanup_log(); 571 bounce_cleanup_unregister(); 572 } 573 } 574 575 static void load_helper(VSTREAM *stream, void *context) 576 { 577 BOUNCE_TEMPLATES *templates = (BOUNCE_TEMPLATES *) context; 578 579 bounce_templates_load(stream, templates); 580 } 581 582 /* pre_jail_init - pre-jail initialization */ 583 584 static void pre_jail_init(char *unused_name, char **unused_argv) 585 { 586 587 /* 588 * Bundle up a bunch of bounce template information. 589 */ 590 bounce_templates = bounce_templates_create(); 591 592 /* 593 * Load the alternate message files (if specified) before entering the 594 * chroot jail. 595 */ 596 if (*var_bounce_tmpl) 597 load_file(var_bounce_tmpl, load_helper, (void *) bounce_templates); 598 } 599 600 /* post_jail_init - initialize after entering chroot jail */ 601 602 static void post_jail_init(char *service_name, char **unused_argv) 603 { 604 605 /* 606 * Special case: dump bounce templates. This is not part of the master(5) 607 * public interface. This internal interface is used by the postconf 608 * command. It was implemented before bounce templates were isolated into 609 * modules that could have been called directly. 610 */ 611 if (strcmp(service_name, "dump_templates") == 0) { 612 bounce_templates_dump(VSTREAM_OUT, bounce_templates); 613 vstream_fflush(VSTREAM_OUT); 614 exit(0); 615 } 616 if (strcmp(service_name, "expand_templates") == 0) { 617 bounce_templates_expand(VSTREAM_OUT, bounce_templates); 618 vstream_fflush(VSTREAM_OUT); 619 exit(0); 620 } 621 622 /* 623 * Initialize. We're single threaded so we can reuse some memory upon 624 * successive requests. 625 */ 626 queue_id = vstring_alloc(10); 627 queue_name = vstring_alloc(10); 628 rcpt_buf = rcpb_create(); 629 encoding = vstring_alloc(10); 630 sender = vstring_alloc(10); 631 dsn_envid = vstring_alloc(10); 632 verp_delims = vstring_alloc(10); 633 dsn_buf = dsb_create(); 634 } 635 636 MAIL_VERSION_STAMP_DECLARE; 637 638 /* main - the main program */ 639 640 int main(int argc, char **argv) 641 { 642 static const CONFIG_INT_TABLE int_table[] = { 643 VAR_BOUNCE_LIMIT, DEF_BOUNCE_LIMIT, &var_bounce_limit, 1, 0, 644 0, 645 }; 646 static const CONFIG_TIME_TABLE time_table[] = { 647 VAR_MAX_QUEUE_TIME, DEF_MAX_QUEUE_TIME, &var_max_queue_time, 0, 8640000, 648 VAR_DELAY_WARN_TIME, DEF_DELAY_WARN_TIME, &var_delay_warn_time, 0, 0, 649 0, 650 }; 651 static const CONFIG_STR_TABLE str_table[] = { 652 VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0, 653 VAR_BOUNCE_RCPT, DEF_BOUNCE_RCPT, &var_bounce_rcpt, 1, 0, 654 VAR_2BOUNCE_RCPT, DEF_2BOUNCE_RCPT, &var_2bounce_rcpt, 1, 0, 655 VAR_DELAY_RCPT, DEF_DELAY_RCPT, &var_delay_rcpt, 1, 0, 656 VAR_BOUNCE_TMPL, DEF_BOUNCE_TMPL, &var_bounce_tmpl, 0, 0, 657 0, 658 }; 659 660 /* 661 * Fingerprint executables and core dumps. 662 */ 663 MAIL_VERSION_STAMP_ALLOCATE; 664 665 /* 666 * Pass control to the single-threaded service skeleton. 667 */ 668 single_server_main(argc, argv, bounce_service, 669 CA_MAIL_SERVER_INT_TABLE(int_table), 670 CA_MAIL_SERVER_STR_TABLE(str_table), 671 CA_MAIL_SERVER_TIME_TABLE(time_table), 672 CA_MAIL_SERVER_PRE_INIT(pre_jail_init), 673 CA_MAIL_SERVER_POST_INIT(post_jail_init), 674 CA_MAIL_SERVER_UNLIMITED, 675 0); 676 } 677