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