xref: /netbsd-src/external/ibm-public/postfix/dist/src/oqmgr/qmgr_message.c (revision 122b5006ee1bd67145794b4cde92f4fe4781a5ec)
1 /*	$NetBSD: qmgr_message.c,v 1.3 2020/03/18 19:05:17 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	qmgr_message 3
6 /* SUMMARY
7 /*	in-core message structures
8 /* SYNOPSIS
9 /*	#include "qmgr.h"
10 /*
11 /*	int	qmgr_message_count;
12 /*	int	qmgr_recipient_count;
13 /*	int	qmgr_vrfy_pend_count;
14 /*
15 /*	QMGR_MESSAGE *qmgr_message_alloc(class, name, qflags, mode)
16 /*	const char *class;
17 /*	const char *name;
18 /*	int	qflags;
19 /*	mode_t	mode;
20 /*
21 /*	QMGR_MESSAGE *qmgr_message_realloc(message)
22 /*	QMGR_MESSAGE *message;
23 /*
24 /*	void	qmgr_message_free(message)
25 /*	QMGR_MESSAGE *message;
26 /*
27 /*	void	qmgr_message_update_warn(message)
28 /*	QMGR_MESSAGE *message;
29 /*
30 /*	void	qmgr_message_kill_record(message, offset)
31 /*	QMGR_MESSAGE *message;
32 /*	long	offset;
33 /* DESCRIPTION
34 /*	This module performs en-gross operations on queue messages.
35 /*
36 /*	qmgr_message_count is a global counter for the total number
37 /*	of in-core message structures (i.e. the total size of the
38 /*	`active' message queue).
39 /*
40 /*	qmgr_recipient_count is a global counter for the total number
41 /*	of in-core recipient structures (i.e. the sum of all recipients
42 /*	in all in-core message structures).
43 /*
44 /*	qmgr_vrfy_pend_count is a global counter for the total
45 /*	number of in-core message structures that are associated
46 /*	with an address verification request. Requests that exceed
47 /*	the address_verify_pending_limit are deferred immediately.
48 /*	This is a backup mechanism for a more refined enforcement
49 /*	mechanism in the verify(8) daemon.
50 /*
51 /*	qmgr_message_alloc() creates an in-core message structure
52 /*	with sender and recipient information taken from the named queue
53 /*	file. A null result means the queue file could not be read or
54 /*	that the queue file contained incorrect information. A result
55 /*	QMGR_MESSAGE_LOCKED means delivery must be deferred. The number
56 /*	of recipients read from a queue file is limited by the global
57 /*	var_qmgr_rcpt_limit configuration parameter. When the limit
58 /*	is reached, the \fIrcpt_offset\fR structure member is set to
59 /*	the position where the read was terminated. Recipients are
60 /*	run through the resolver, and are assigned to destination
61 /*	queues. Recipients that cannot be assigned are deferred or
62 /*	bounced. Mail that has bounced twice is silently absorbed.
63 /*	A non-zero mode means change the queue file permissions.
64 /*
65 /*	qmgr_message_realloc() resumes reading recipients from the queue
66 /*	file, and updates the recipient list and \fIrcpt_offset\fR message
67 /*	structure members. A null result means that the file could not be
68 /*	read or that the file contained incorrect information.
69 /*
70 /*	qmgr_message_free() destroys an in-core message structure and makes
71 /*	the resources available for reuse. It is an error to destroy
72 /*	a message structure that is still referenced by queue entry structures.
73 /*
74 /*	qmgr_message_update_warn() takes a closed message, opens it, updates
75 /*	the warning field, and closes it again.
76 /*
77 /*	qmgr_message_kill_record() takes a closed message, opens it, updates
78 /*	the record type at the given offset to "killed", and closes the file.
79 /*	A killed envelope record is ignored. Killed records are not allowed
80 /*	inside the message content.
81 /* DIAGNOSTICS
82 /*	Warnings: malformed message file. Fatal errors: out of memory.
83 /* SEE ALSO
84 /*	envelope(3) message envelope parser
85 /* LICENSE
86 /* .ad
87 /* .fi
88 /*	The Secure Mailer license must be distributed with this software.
89 /* AUTHOR(S)
90 /*	Wietse Venema
91 /*	IBM T.J. Watson Research
92 /*	P.O. Box 704
93 /*	Yorktown Heights, NY 10598, USA
94 /*
95 /*	Wietse Venema
96 /*	Google, Inc.
97 /*	111 8th Avenue
98 /*	New York, NY 10011, USA
99 /*--*/
100 
101 /* System library. */
102 
103 #include <sys_defs.h>
104 #include <sys/stat.h>
105 #include <stdlib.h>
106 #include <stdio.h>			/* sscanf() */
107 #include <fcntl.h>
108 #include <errno.h>
109 #include <unistd.h>
110 #include <string.h>
111 #include <ctype.h>
112 
113 /* Utility library. */
114 
115 #include <msg.h>
116 #include <mymalloc.h>
117 #include <vstring.h>
118 #include <vstream.h>
119 #include <split_at.h>
120 #include <valid_hostname.h>
121 #include <argv.h>
122 #include <stringops.h>
123 #include <myflock.h>
124 
125 /* Global library. */
126 
127 #include <dict.h>
128 #include <mail_queue.h>
129 #include <mail_params.h>
130 #include <canon_addr.h>
131 #include <record.h>
132 #include <rec_type.h>
133 #include <sent.h>
134 #include <deliver_completed.h>
135 #include <opened.h>
136 #include <verp_sender.h>
137 #include <mail_proto.h>
138 #include <qmgr_user.h>
139 #include <split_addr.h>
140 #include <dsn_mask.h>
141 #include <rec_attr_map.h>
142 
143 /* Client stubs. */
144 
145 #include <rewrite_clnt.h>
146 #include <resolve_clnt.h>
147 
148 /* Application-specific. */
149 
150 #include "qmgr.h"
151 
152 int     qmgr_message_count;
153 int     qmgr_recipient_count;
154 int     qmgr_vrfy_pend_count;
155 
156 /* qmgr_message_create - create in-core message structure */
157 
158 static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
159 				           const char *queue_id, int qflags)
160 {
161     QMGR_MESSAGE *message;
162 
163     message = (QMGR_MESSAGE *) mymalloc(sizeof(QMGR_MESSAGE));
164     qmgr_message_count++;
165     message->flags = 0;
166     message->qflags = qflags;
167     message->tflags = 0;
168     message->tflags_offset = 0;
169     message->rflags = QMGR_READ_FLAG_DEFAULT;
170     message->fp = 0;
171     message->refcount = 0;
172     message->single_rcpt = 0;
173     message->arrival_time.tv_sec = message->arrival_time.tv_usec = 0;
174     message->create_time = 0;
175     GETTIMEOFDAY(&message->active_time);
176     message->data_offset = 0;
177     message->queue_id = mystrdup(queue_id);
178     message->queue_name = mystrdup(queue_name);
179     message->encoding = 0;
180     message->sender = 0;
181     message->dsn_envid = 0;
182     message->dsn_ret = 0;
183     message->smtputf8 = 0;
184     message->filter_xport = 0;
185     message->inspect_xport = 0;
186     message->redirect_addr = 0;
187     message->data_size = 0;
188     message->cont_length = 0;
189     message->warn_offset = 0;
190     message->warn_time = 0;
191     message->rcpt_offset = 0;
192     message->verp_delims = 0;
193     message->client_name = 0;
194     message->client_addr = 0;
195     message->client_port = 0;
196     message->client_proto = 0;
197     message->client_helo = 0;
198     message->sasl_method = 0;
199     message->sasl_username = 0;
200     message->sasl_sender = 0;
201     message->log_ident = 0;
202     message->rewrite_context = 0;
203     recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
204     return (message);
205 }
206 
207 /* qmgr_message_close - close queue file */
208 
209 static void qmgr_message_close(QMGR_MESSAGE *message)
210 {
211     vstream_fclose(message->fp);
212     message->fp = 0;
213 }
214 
215 /* qmgr_message_open - open queue file */
216 
217 static int qmgr_message_open(QMGR_MESSAGE *message)
218 {
219 
220     /*
221      * Sanity check.
222      */
223     if (message->fp)
224 	msg_panic("%s: queue file is open", message->queue_id);
225 
226     /*
227      * Open this queue file. Skip files that we cannot open. Back off when
228      * the system appears to be running out of resources.
229      */
230     if ((message->fp = mail_queue_open(message->queue_name,
231 				       message->queue_id,
232 				       O_RDWR, 0)) == 0) {
233 	if (errno != ENOENT)
234 	    msg_fatal("open %s %s: %m", message->queue_name, message->queue_id);
235 	msg_warn("open %s %s: %m", message->queue_name, message->queue_id);
236 	return (-1);
237     }
238     return (0);
239 }
240 
241 /* qmgr_message_oldstyle_scan - support for Postfix < 1.0 queue files */
242 
243 static void qmgr_message_oldstyle_scan(QMGR_MESSAGE *message)
244 {
245     VSTRING *buf;
246     long    orig_offset, extra_offset;
247     int     rec_type;
248     char   *start;
249 
250     /*
251      * Initialize. No early returns or we have a memory leak.
252      */
253     buf = vstring_alloc(100);
254     if ((orig_offset = vstream_ftell(message->fp)) < 0)
255 	msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
256 
257     /*
258      * Rewind to the very beginning to make sure we see all records.
259      */
260     if (vstream_fseek(message->fp, 0, SEEK_SET) < 0)
261 	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
262 
263     /*
264      * Scan through the old style queue file. Count the total number of
265      * recipients and find the data/extra sections offsets. Note that the new
266      * queue files require that data_size equals extra_offset - data_offset,
267      * so we set data_size to this as well and ignore the size record itself
268      * completely.
269      */
270     for (;;) {
271 	rec_type = rec_get(message->fp, buf, 0);
272 	if (rec_type <= 0)
273 	    /* Report missing end record later. */
274 	    break;
275 	start = vstring_str(buf);
276 	if (msg_verbose > 1)
277 	    msg_info("old-style scan record %c %s", rec_type, start);
278 	if (rec_type == REC_TYPE_END)
279 	    break;
280 	if (rec_type == REC_TYPE_MESG) {
281 	    if (message->data_offset == 0) {
282 		if ((message->data_offset = vstream_ftell(message->fp)) < 0)
283 		    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
284 		if ((extra_offset = atol(start)) <= message->data_offset)
285 		    msg_fatal("bad extra offset %s file %s",
286 			      start, VSTREAM_PATH(message->fp));
287 		if (vstream_fseek(message->fp, extra_offset, SEEK_SET) < 0)
288 		    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
289 		message->data_size = extra_offset - message->data_offset;
290 	    }
291 	    continue;
292 	}
293     }
294 
295     /*
296      * Clean up.
297      */
298     if (vstream_fseek(message->fp, orig_offset, SEEK_SET) < 0)
299 	msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
300     vstring_free(buf);
301 
302     /*
303      * Sanity checks. Verify that all required information was found,
304      * including the queue file end marker.
305      */
306     if (message->data_offset == 0 || rec_type != REC_TYPE_END)
307 	msg_fatal("%s: envelope records out of order", message->queue_id);
308 }
309 
310 /* qmgr_message_read - read envelope records */
311 
312 static int qmgr_message_read(QMGR_MESSAGE *message)
313 {
314     VSTRING *buf;
315     int     rec_type;
316     long    curr_offset;
317     long    save_offset = message->rcpt_offset;	/* save a flag */
318     char   *start;
319     int     nrcpt = 0;
320     const char *error_text;
321     char   *name;
322     char   *value;
323     char   *orig_rcpt = 0;
324     int     count;
325     int     dsn_notify = 0;
326     char   *dsn_orcpt = 0;
327     int     n;
328     int     have_log_client_attr = 0;
329 
330     /*
331      * Initialize. No early returns or we have a memory leak.
332      */
333     buf = vstring_alloc(100);
334 
335     /*
336      * If we re-open this file, skip over on-file recipient records that we
337      * already looked at, and refill the in-core recipient address list.
338      */
339     if (message->rcpt_offset) {
340 	if (message->rcpt_list.len)
341 	    msg_panic("%s: recipient list not empty on recipient reload",
342 		      message->queue_id);
343 	if (vstream_fseek(message->fp, message->rcpt_offset, SEEK_SET) < 0)
344 	    msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
345 	message->rcpt_offset = 0;
346     }
347 
348     /*
349      * Read envelope records. XXX Rely on the front-end programs to enforce
350      * record size limits. Read up to var_qmgr_rcpt_limit recipients from the
351      * queue file, to protect against memory exhaustion. Recipient records
352      * may appear before or after the message content, so we keep reading
353      * from the queue file until we have enough recipients (rcpt_offset != 0)
354      * and until we know all the non-recipient information.
355      *
356      * When reading recipients from queue file, stop reading when we reach a
357      * per-message in-core recipient limit rather than a global in-core
358      * recipient limit. Use the global recipient limit only in order to stop
359      * opening queue files. The purpose is to achieve equal delay for
360      * messages with recipient counts up to var_qmgr_rcpt_limit recipients.
361      *
362      * If we would read recipients up to a global recipient limit, the average
363      * number of in-core recipients per message would asymptotically approach
364      * (global recipient limit)/(active queue size limit), which gives equal
365      * delay per recipient rather than equal delay per message.
366      *
367      * On the first open, we must examine all non-recipient records.
368      *
369      * Optimization: when we know that recipient records are not mixed with
370      * non-recipient records, as is typical with mailing list mail, then we
371      * can avoid having to examine all the queue file records before we can
372      * start deliveries. This avoids some file system thrashing with huge
373      * mailing lists.
374      */
375     for (;;) {
376 	if ((curr_offset = vstream_ftell(message->fp)) < 0)
377 	    msg_fatal("vstream_ftell %s: %m", VSTREAM_PATH(message->fp));
378 	if (curr_offset == message->data_offset && curr_offset > 0) {
379 	    if (vstream_fseek(message->fp, message->data_size, SEEK_CUR) < 0)
380 		msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
381 	    curr_offset += message->data_size;
382 	}
383 	rec_type = rec_get_raw(message->fp, buf, 0, REC_FLAG_NONE);
384 	start = vstring_str(buf);
385 	if (msg_verbose > 1)
386 	    msg_info("record %c %s", rec_type, start);
387 	if (rec_type == REC_TYPE_PTR) {
388 	    if ((rec_type = rec_goto(message->fp, start)) == REC_TYPE_ERROR)
389 		break;
390 	    /* Need to update curr_offset after pointer jump. */
391 	    continue;
392 	}
393 	if (rec_type <= 0) {
394 	    msg_warn("%s: message rejected: missing end record",
395 		     message->queue_id);
396 	    break;
397 	}
398 	if (rec_type == REC_TYPE_END) {
399 	    message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
400 	    break;
401 	}
402 
403 	/*
404 	 * Map named attributes to pseudo record types, so that we don't have
405 	 * to pollute the queue file with records that are incompatible with
406 	 * past Postfix versions. Preferably, people should be able to back
407 	 * out from an upgrade without losing mail.
408 	 */
409 	if (rec_type == REC_TYPE_ATTR) {
410 	    if ((error_text = split_nameval(start, &name, &value)) != 0) {
411 		msg_warn("%s: ignoring bad attribute: %s: %.200s",
412 			 message->queue_id, error_text, start);
413 		rec_type = REC_TYPE_ERROR;
414 		break;
415 	    }
416 	    if ((n = rec_attr_map(name)) != 0) {
417 		start = value;
418 		rec_type = n;
419 	    }
420 	}
421 
422 	/*
423 	 * Process recipient records.
424 	 */
425 	if (rec_type == REC_TYPE_RCPT) {
426 	    /* See also below for code setting orig_rcpt etc. */
427 #define FUDGE(x)	((x) * (var_qmgr_fudge / 100.0))
428 	    if (message->rcpt_offset == 0) {
429 		recipient_list_add(&message->rcpt_list, curr_offset,
430 				   dsn_orcpt ? dsn_orcpt : "",
431 				   dsn_notify ? dsn_notify : 0,
432 				   orig_rcpt ? orig_rcpt : "", start);
433 		if (dsn_orcpt) {
434 		    myfree(dsn_orcpt);
435 		    dsn_orcpt = 0;
436 		}
437 		if (orig_rcpt) {
438 		    myfree(orig_rcpt);
439 		    orig_rcpt = 0;
440 		}
441 		if (dsn_notify)
442 		    dsn_notify = 0;
443 		if (message->rcpt_list.len >= FUDGE(var_qmgr_rcpt_limit)) {
444 		    if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0)
445 			msg_fatal("vstream_ftell %s: %m",
446 				  VSTREAM_PATH(message->fp));
447 		    if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
448 			/* We already examined all non-recipient records. */
449 			break;
450 		    if (message->rflags & QMGR_READ_FLAG_MIXED_RCPT_OTHER)
451 			/* Examine all remaining non-recipient records. */
452 			continue;
453 		    /* Optimizations for "pure recipient" record sections. */
454 		    if (curr_offset > message->data_offset) {
455 			/* We already examined all non-recipient records. */
456 			message->rflags |= QMGR_READ_FLAG_SEEN_ALL_NON_RCPT;
457 			break;
458 		    }
459 		    /* Examine non-recipient records in extracted segment. */
460 		    if (vstream_fseek(message->fp, message->data_offset
461 				      + message->data_size, SEEK_SET) < 0)
462 			msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp));
463 		    continue;
464 		}
465 	    }
466 	    continue;
467 	}
468 	if (rec_type == REC_TYPE_DONE || rec_type == REC_TYPE_DRCP) {
469 	    if (message->rcpt_offset == 0) {
470 		if (dsn_orcpt) {
471 		    myfree(dsn_orcpt);
472 		    dsn_orcpt = 0;
473 		}
474 		if (orig_rcpt) {
475 		    myfree(orig_rcpt);
476 		    orig_rcpt = 0;
477 		}
478 		if (dsn_notify)
479 		    dsn_notify = 0;
480 	    }
481 	    continue;
482 	}
483 	if (rec_type == REC_TYPE_DSN_ORCPT) {
484 	    /* See also above for code clearing dsn_orcpt. */
485 	    if (dsn_orcpt != 0) {
486 		msg_warn("%s: ignoring out-of-order DSN original recipient address <%.200s>",
487 			 message->queue_id, dsn_orcpt);
488 		myfree(dsn_orcpt);
489 		dsn_orcpt = 0;
490 	    }
491 	    if (message->rcpt_offset == 0)
492 		dsn_orcpt = mystrdup(start);
493 	    continue;
494 	}
495 	if (rec_type == REC_TYPE_DSN_NOTIFY) {
496 	    /* See also above for code clearing dsn_notify. */
497 	    if (dsn_notify != 0) {
498 		msg_warn("%s: ignoring out-of-order DSN notify flags <%d>",
499 			 message->queue_id, dsn_notify);
500 		dsn_notify = 0;
501 	    }
502 	    if (message->rcpt_offset == 0) {
503 		if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_NOTIFY_OK(n))
504 		    msg_warn("%s: ignoring malformed DSN notify flags <%.200s>",
505 			     message->queue_id, start);
506 		else
507 		    dsn_notify = n;
508 		continue;
509 	    }
510 	}
511 	if (rec_type == REC_TYPE_ORCP) {
512 	    /* See also above for code clearing orig_rcpt. */
513 	    if (orig_rcpt != 0) {
514 		msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
515 			 message->queue_id, orig_rcpt);
516 		myfree(orig_rcpt);
517 		orig_rcpt = 0;
518 	    }
519 	    if (message->rcpt_offset == 0)
520 		orig_rcpt = mystrdup(start);
521 	    continue;
522 	}
523 
524 	/*
525 	 * Process non-recipient records.
526 	 */
527 	if (message->rflags & QMGR_READ_FLAG_SEEN_ALL_NON_RCPT)
528 	    /* We already examined all non-recipient records. */
529 	    continue;
530 	if (rec_type == REC_TYPE_SIZE) {
531 	    if (message->data_offset == 0) {
532 		if ((count = sscanf(start, "%ld %ld %d %d %ld %d",
533 				 &message->data_size, &message->data_offset,
534 				    &nrcpt, &message->rflags,
535 				    &message->cont_length,
536 				    &message->smtputf8)) >= 3) {
537 		    /* Postfix >= 1.0 (a.k.a. 20010228). */
538 		    if (message->data_offset <= 0 || message->data_size <= 0) {
539 			msg_warn("%s: invalid size record: %.100s",
540 				 message->queue_id, start);
541 			rec_type = REC_TYPE_ERROR;
542 			break;
543 		    }
544 		    if (message->rflags & ~QMGR_READ_FLAG_USER) {
545 			msg_warn("%s: invalid flags in size record: %.100s",
546 				 message->queue_id, start);
547 			rec_type = REC_TYPE_ERROR;
548 			break;
549 		    }
550 		} else if (count == 1) {
551 		    /* Postfix < 1.0 (a.k.a. 20010228). */
552 		    qmgr_message_oldstyle_scan(message);
553 		} else {
554 		    /* Can't happen. */
555 		    msg_warn("%s: message rejected: weird size record",
556 			     message->queue_id);
557 		    rec_type = REC_TYPE_ERROR;
558 		    break;
559 		}
560 	    }
561 	    /* Postfix < 2.4 compatibility. */
562 	    if (message->cont_length == 0) {
563 		message->cont_length = message->data_size;
564 	    } else if (message->cont_length < 0) {
565 		msg_warn("%s: invalid size record: %.100s",
566 			 message->queue_id, start);
567 		rec_type = REC_TYPE_ERROR;
568 		break;
569 	    }
570 	    continue;
571 	}
572 	if (rec_type == REC_TYPE_TIME) {
573 	    if (message->arrival_time.tv_sec == 0)
574 		REC_TYPE_TIME_SCAN(start, message->arrival_time);
575 	    continue;
576 	}
577 	if (rec_type == REC_TYPE_CTIME) {
578 	    if (message->create_time == 0)
579 		message->create_time = atol(start);
580 	    continue;
581 	}
582 	if (rec_type == REC_TYPE_FILT) {
583 	    if (message->filter_xport != 0)
584 		myfree(message->filter_xport);
585 	    message->filter_xport = mystrdup(start);
586 	    continue;
587 	}
588 	if (rec_type == REC_TYPE_INSP) {
589 	    if (message->inspect_xport != 0)
590 		myfree(message->inspect_xport);
591 	    message->inspect_xport = mystrdup(start);
592 	    continue;
593 	}
594 	if (rec_type == REC_TYPE_RDR) {
595 	    if (message->redirect_addr != 0)
596 		myfree(message->redirect_addr);
597 	    message->redirect_addr = mystrdup(start);
598 	    continue;
599 	}
600 	if (rec_type == REC_TYPE_FROM) {
601 	    if (message->sender == 0) {
602 		message->sender = mystrdup(start);
603 		opened(message->queue_id, message->sender,
604 		       message->cont_length, nrcpt,
605 		       "queue %s", message->queue_name);
606 	    }
607 	    continue;
608 	}
609 	if (rec_type == REC_TYPE_DSN_ENVID) {
610 	    /* Allow Milter override. */
611 	    if (message->dsn_envid != 0)
612 		myfree(message->dsn_envid);
613 	    message->dsn_envid = mystrdup(start);
614 	}
615 	if (rec_type == REC_TYPE_DSN_RET) {
616 	    /* Allow Milter override. */
617 	    if (!alldig(start) || (n = atoi(start)) == 0 || !DSN_RET_OK(n))
618 		msg_warn("%s: ignoring malformed DSN RET flags in queue file record:%.100s",
619 			 message->queue_id, start);
620 	    else
621 		message->dsn_ret = n;
622 	}
623 	if (rec_type == REC_TYPE_ATTR) {
624 	    /* Allow extra segment to override envelope segment info. */
625 	    if (strcmp(name, MAIL_ATTR_ENCODING) == 0) {
626 		if (message->encoding != 0)
627 		    myfree(message->encoding);
628 		message->encoding = mystrdup(value);
629 	    }
630 
631 	    /*
632 	     * Backwards compatibility. Before Postfix 2.3, the logging
633 	     * attributes were called client_name, etc. Now they are called
634 	     * log_client_name. etc., and client_name is used for the actual
635 	     * client information. To support old queue files, we accept both
636 	     * names for the purpose of logging; the new name overrides the
637 	     * old one.
638 	     *
639 	     * XXX Do not use the "legacy" client_name etc. attribute values for
640 	     * initializing the logging attributes, when this file already
641 	     * contains the "modern" log_client_name etc. logging attributes.
642 	     * Otherwise, logging attributes that are not present in the
643 	     * queue file would be set with information from the real client.
644 	     */
645 	    else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_NAME) == 0) {
646 		if (have_log_client_attr == 0 && message->client_name == 0)
647 		    message->client_name = mystrdup(value);
648 	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_ADDR) == 0) {
649 		if (have_log_client_attr == 0 && message->client_addr == 0)
650 		    message->client_addr = mystrdup(value);
651 	    } else if (strcmp(name, MAIL_ATTR_ACT_CLIENT_PORT) == 0) {
652 		if (have_log_client_attr == 0 && message->client_port == 0)
653 		    message->client_port = mystrdup(value);
654 	    } else if (strcmp(name, MAIL_ATTR_ACT_PROTO_NAME) == 0) {
655 		if (have_log_client_attr == 0 && message->client_proto == 0)
656 		    message->client_proto = mystrdup(value);
657 	    } else if (strcmp(name, MAIL_ATTR_ACT_HELO_NAME) == 0) {
658 		if (have_log_client_attr == 0 && message->client_helo == 0)
659 		    message->client_helo = mystrdup(value);
660 	    }
661 	    /* Original client attributes. */
662 	    else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_NAME) == 0) {
663 		if (message->client_name != 0)
664 		    myfree(message->client_name);
665 		message->client_name = mystrdup(value);
666 		have_log_client_attr = 1;
667 	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_ADDR) == 0) {
668 		if (message->client_addr != 0)
669 		    myfree(message->client_addr);
670 		message->client_addr = mystrdup(value);
671 		have_log_client_attr = 1;
672 	    } else if (strcmp(name, MAIL_ATTR_LOG_CLIENT_PORT) == 0) {
673 		if (message->client_port != 0)
674 		    myfree(message->client_port);
675 		message->client_port = mystrdup(value);
676 		have_log_client_attr = 1;
677 	    } else if (strcmp(name, MAIL_ATTR_LOG_PROTO_NAME) == 0) {
678 		if (message->client_proto != 0)
679 		    myfree(message->client_proto);
680 		message->client_proto = mystrdup(value);
681 		have_log_client_attr = 1;
682 	    } else if (strcmp(name, MAIL_ATTR_LOG_HELO_NAME) == 0) {
683 		if (message->client_helo != 0)
684 		    myfree(message->client_helo);
685 		message->client_helo = mystrdup(value);
686 		have_log_client_attr = 1;
687 	    } else if (strcmp(name, MAIL_ATTR_SASL_METHOD) == 0) {
688 		if (message->sasl_method == 0)
689 		    message->sasl_method = mystrdup(value);
690 		else
691 		    msg_warn("%s: ignoring multiple %s attribute: %s",
692 			   message->queue_id, MAIL_ATTR_SASL_METHOD, value);
693 	    } else if (strcmp(name, MAIL_ATTR_SASL_USERNAME) == 0) {
694 		if (message->sasl_username == 0)
695 		    message->sasl_username = mystrdup(value);
696 		else
697 		    msg_warn("%s: ignoring multiple %s attribute: %s",
698 			 message->queue_id, MAIL_ATTR_SASL_USERNAME, value);
699 	    } else if (strcmp(name, MAIL_ATTR_SASL_SENDER) == 0) {
700 		if (message->sasl_sender == 0)
701 		    message->sasl_sender = mystrdup(value);
702 		else
703 		    msg_warn("%s: ignoring multiple %s attribute: %s",
704 			   message->queue_id, MAIL_ATTR_SASL_SENDER, value);
705 	    } else if (strcmp(name, MAIL_ATTR_LOG_IDENT) == 0) {
706 		if (message->log_ident == 0)
707 		    message->log_ident = mystrdup(value);
708 		else
709 		    msg_warn("%s: ignoring multiple %s attribute: %s",
710 			     message->queue_id, MAIL_ATTR_LOG_IDENT, value);
711 	    } else if (strcmp(name, MAIL_ATTR_RWR_CONTEXT) == 0) {
712 		if (message->rewrite_context == 0)
713 		    message->rewrite_context = mystrdup(value);
714 		else
715 		    msg_warn("%s: ignoring multiple %s attribute: %s",
716 			   message->queue_id, MAIL_ATTR_RWR_CONTEXT, value);
717 	    }
718 
719 	    /*
720 	     * Optional tracing flags (verify, sendmail -v, sendmail -bv).
721 	     * This record is killed after a trace logfile report is sent and
722 	     * after the logfile is deleted.
723 	     */
724 	    else if (strcmp(name, MAIL_ATTR_TRACE_FLAGS) == 0) {
725 		if (message->tflags == 0) {
726 		    message->tflags = DEL_REQ_TRACE_FLAGS(atoi(value));
727 		    if (message->tflags == DEL_REQ_FLAG_RECORD)
728 			message->tflags_offset = curr_offset;
729 		    else
730 			message->tflags_offset = 0;
731 		    if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
732 			qmgr_vrfy_pend_count++;
733 		}
734 	    }
735 	    continue;
736 	}
737 	if (rec_type == REC_TYPE_WARN) {
738 	    if (message->warn_offset == 0) {
739 		message->warn_offset = curr_offset;
740 		REC_TYPE_WARN_SCAN(start, message->warn_time);
741 	    }
742 	    continue;
743 	}
744 	if (rec_type == REC_TYPE_VERP) {
745 	    if (message->verp_delims == 0) {
746 		if (message->sender == 0 || message->sender[0] == 0) {
747 		    msg_warn("%s: ignoring VERP request for null sender",
748 			     message->queue_id);
749 		} else if (verp_delims_verify(start) != 0) {
750 		    msg_warn("%s: ignoring bad VERP request: \"%.100s\"",
751 			     message->queue_id, start);
752 		} else {
753 		    if (msg_verbose)
754 			msg_info("%s: enabling VERP for sender \"%.100s\"",
755 				 message->queue_id, message->sender);
756 		    message->single_rcpt = 1;
757 		    message->verp_delims = mystrdup(start);
758 		}
759 	    }
760 	    continue;
761 	}
762     }
763 
764     /*
765      * Grr.
766      */
767     if (dsn_orcpt != 0) {
768 	if (rec_type > 0)
769 	    msg_warn("%s: ignoring out-of-order DSN original recipient <%.200s>",
770 		     message->queue_id, dsn_orcpt);
771 	myfree(dsn_orcpt);
772     }
773     if (orig_rcpt != 0) {
774 	if (rec_type > 0)
775 	    msg_warn("%s: ignoring out-of-order original recipient <%.200s>",
776 		     message->queue_id, orig_rcpt);
777 	myfree(orig_rcpt);
778     }
779 
780     /*
781      * After sending a "delayed" warning, request sender notification when
782      * message delivery is completed. While "mail delayed" notifications are
783      * bad enough because they multiply the amount of email traffic, "delay
784      * cleared" notifications are even worse because they come in a sudden
785      * burst when the queue drains after a network outage.
786      */
787     if (var_dsn_delay_cleared && message->warn_time < 0)
788 	message->tflags |= DEL_REQ_FLAG_REC_DLY_SENT;
789 
790     /*
791      * Avoid clumsiness elsewhere in the program. When sending data across an
792      * IPC channel, sending an empty string is more convenient than sending a
793      * null pointer.
794      */
795     if (message->dsn_envid == 0)
796 	message->dsn_envid = mystrdup("");
797     if (message->encoding == 0)
798 	message->encoding = mystrdup(MAIL_ATTR_ENC_NONE);
799     if (message->client_name == 0)
800 	message->client_name = mystrdup("");
801     if (message->client_addr == 0)
802 	message->client_addr = mystrdup("");
803     if (message->client_port == 0)
804 	message->client_port = mystrdup("");
805     if (message->client_proto == 0)
806 	message->client_proto = mystrdup("");
807     if (message->client_helo == 0)
808 	message->client_helo = mystrdup("");
809     if (message->sasl_method == 0)
810 	message->sasl_method = mystrdup("");
811     if (message->sasl_username == 0)
812 	message->sasl_username = mystrdup("");
813     if (message->sasl_sender == 0)
814 	message->sasl_sender = mystrdup("");
815     if (message->log_ident == 0)
816 	message->log_ident = mystrdup("");
817     if (message->rewrite_context == 0)
818 	message->rewrite_context = mystrdup(MAIL_ATTR_RWR_LOCAL);
819     /* Postfix < 2.3 compatibility. */
820     if (message->create_time == 0)
821 	message->create_time = message->arrival_time.tv_sec;
822 
823     /*
824      * Clean up.
825      */
826     vstring_free(buf);
827 
828     /*
829      * Sanity checks. Verify that all required information was found,
830      * including the queue file end marker.
831      */
832     if (rec_type <= 0) {
833 	/* Already logged warning. */
834     } else if (message->arrival_time.tv_sec == 0) {
835 	msg_warn("%s: message rejected: missing arrival time record",
836 		 message->queue_id);
837     } else if (message->sender == 0) {
838 	msg_warn("%s: message rejected: missing sender record",
839 		 message->queue_id);
840     } else if (message->data_offset == 0) {
841 	msg_warn("%s: message rejected: missing size record",
842 		 message->queue_id);
843     } else {
844 	return (0);
845     }
846     message->rcpt_offset = save_offset;		/* restore flag */
847     return (-1);
848 }
849 
850 /* qmgr_message_update_warn - update the time of next delay warning */
851 
852 void    qmgr_message_update_warn(QMGR_MESSAGE *message)
853 {
854 
855     /*
856      * After the "mail delayed" warning, optionally send a "delay cleared"
857      * notification.
858      */
859     if (qmgr_message_open(message)
860 	|| vstream_fseek(message->fp, message->warn_offset, SEEK_SET) < 0
861 	|| rec_fprintf(message->fp, REC_TYPE_WARN, REC_TYPE_WARN_FORMAT,
862 		       REC_TYPE_WARN_ARG(-1)) < 0
863 	|| vstream_fflush(message->fp))
864 	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
865     qmgr_message_close(message);
866 }
867 
868 /* qmgr_message_kill_record - mark one message record as killed */
869 
870 void    qmgr_message_kill_record(QMGR_MESSAGE *message, long offset)
871 {
872     if (offset <= 0)
873 	msg_panic("qmgr_message_kill_record: bad offset 0x%lx", offset);
874     if (qmgr_message_open(message)
875 	|| rec_put_type(message->fp, REC_TYPE_KILL, offset) < 0
876 	|| vstream_fflush(message->fp))
877 	msg_fatal("update queue file %s: %m", VSTREAM_PATH(message->fp));
878     qmgr_message_close(message);
879 }
880 
881 /* qmgr_message_sort_compare - compare recipient information */
882 
883 static int qmgr_message_sort_compare(const void *p1, const void *p2)
884 {
885     RECIPIENT *rcpt1 = (RECIPIENT *) p1;
886     RECIPIENT *rcpt2 = (RECIPIENT *) p2;
887     QMGR_QUEUE *queue1;
888     QMGR_QUEUE *queue2;
889     char   *at1;
890     char   *at2;
891     int     result;
892 
893     /*
894      * Compare most significant to least significant recipient attributes.
895      * The comparison function must be transitive, so NULL values need to be
896      * assigned an ordinal (we set NULL last).
897      */
898 
899     queue1 = rcpt1->u.queue;
900     queue2 = rcpt2->u.queue;
901     if (queue1 != 0 && queue2 == 0)
902 	return (-1);
903     if (queue1 == 0 && queue2 != 0)
904 	return (1);
905     if (queue1 != 0 && queue2 != 0) {
906 
907 	/*
908 	 * Compare message transport.
909 	 */
910 	if ((result = strcmp(queue1->transport->name,
911 			     queue2->transport->name)) != 0)
912 	    return (result);
913 
914 	/*
915 	 * Compare queue name (nexthop or recipient@nexthop).
916 	 */
917 	if ((result = strcmp(queue1->name, queue2->name)) != 0)
918 	    return (result);
919     }
920 
921     /*
922      * Compare recipient domain.
923      */
924     at1 = strrchr(rcpt1->address, '@');
925     at2 = strrchr(rcpt2->address, '@');
926     if (at1 == 0 && at2 != 0)
927 	return (1);
928     if (at1 != 0 && at2 == 0)
929 	return (-1);
930     if (at1 != 0 && at2 != 0
931 	&& (result = strcasecmp_utf8(at1, at2)) != 0)
932 	return (result);
933 
934     /*
935      * Compare recipient address.
936      */
937     return (strcasecmp_utf8(rcpt1->address, rcpt2->address));
938 }
939 
940 /* qmgr_message_sort - sort message recipient addresses by domain */
941 
942 static void qmgr_message_sort(QMGR_MESSAGE *message)
943 {
944     qsort((void *) message->rcpt_list.info, message->rcpt_list.len,
945 	  sizeof(message->rcpt_list.info[0]), qmgr_message_sort_compare);
946     if (msg_verbose) {
947 	RECIPIENT_LIST list = message->rcpt_list;
948 	RECIPIENT *rcpt;
949 
950 	msg_info("start sorted recipient list");
951 	for (rcpt = list.info; rcpt < list.info + list.len; rcpt++)
952 	    msg_info("qmgr_message_sort: %s", rcpt->address);
953 	msg_info("end sorted recipient list");
954     }
955 }
956 
957 /* qmgr_resolve_one - resolve or skip one recipient */
958 
959 static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
960 			            const char *addr, RESOLVE_REPLY *reply)
961 {
962 #define QMGR_REDIRECT(rp, tp, np) do { \
963 	(rp)->flags = 0; \
964 	vstring_strcpy((rp)->transport, (tp)); \
965 	vstring_strcpy((rp)->nexthop, (np)); \
966     } while (0)
967 
968     if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) == 0)
969 	resolve_clnt_query_from(message->sender, addr, reply);
970     else
971 	resolve_clnt_verify_from(message->sender, addr, reply);
972     if (reply->flags & RESOLVE_FLAG_FAIL) {
973 	QMGR_REDIRECT(reply, MAIL_SERVICE_RETRY,
974 		      "4.3.0 address resolver failure");
975 	return (0);
976     } else if (reply->flags & RESOLVE_FLAG_ERROR) {
977 	QMGR_REDIRECT(reply, MAIL_SERVICE_ERROR,
978 		      "5.1.3 bad address syntax");
979 	return (0);
980     } else {
981 	return (0);
982     }
983 }
984 
985 /* qmgr_message_resolve - resolve recipients */
986 
987 static void qmgr_message_resolve(QMGR_MESSAGE *message)
988 {
989     static ARGV *defer_xport_argv;
990     RECIPIENT_LIST list = message->rcpt_list;
991     RECIPIENT *recipient;
992     QMGR_TRANSPORT *transport = 0;
993     QMGR_QUEUE *queue = 0;
994     RESOLVE_REPLY reply;
995     VSTRING *queue_name;
996     char   *at;
997     char  **cpp;
998     char   *nexthop;
999     ssize_t len;
1000     int     status;
1001     DSN     dsn;
1002     MSG_STATS stats;
1003     DSN    *saved_dsn;
1004 
1005 #define STREQ(x,y)	(strcmp(x,y) == 0)
1006 #define STR		vstring_str
1007 #define LEN		VSTRING_LEN
1008 
1009     resolve_clnt_init(&reply);
1010     queue_name = vstring_alloc(1);
1011     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1012 
1013 	/*
1014 	 * Redirect overrides all else. But only once (per entire message).
1015 	 * For consistency with the remainder of Postfix, rewrite the address
1016 	 * to canonical form before resolving it.
1017 	 */
1018 	if (message->redirect_addr) {
1019 	    if (recipient > list.info) {
1020 		recipient->u.queue = 0;
1021 		continue;
1022 	    }
1023 	    message->rcpt_offset = 0;
1024 	    rewrite_clnt_internal(REWRITE_CANON, message->redirect_addr,
1025 				  reply.recipient);
1026 	    RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1027 	    if (qmgr_resolve_one(message, recipient,
1028 				 recipient->address, &reply) < 0)
1029 		continue;
1030 	    if (!STREQ(recipient->address, STR(reply.recipient)))
1031 		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1032 	}
1033 
1034 	/*
1035 	 * Content filtering overrides the address resolver.
1036 	 *
1037 	 * XXX Bypass content_filter inspection for user-generated probes
1038 	 * (sendmail -bv). MTA-generated probes never have the "please filter
1039 	 * me" bits turned on, but we handle them here anyway for the sake of
1040 	 * future proofing.
1041 	 */
1042 #define FILTER_WITHOUT_NEXTHOP(filter, next) \
1043 	(((next) = split_at((filter), ':')) == 0 || *(next) == 0)
1044 
1045 #define RCPT_WITHOUT_DOMAIN(rcpt, next) \
1046 	((next = strrchr(rcpt, '@')) == 0 || *++(next) == 0)
1047 
1048 	else if (message->filter_xport
1049 		 && (message->tflags & DEL_REQ_TRACE_ONLY_MASK) == 0) {
1050 	    reply.flags = 0;
1051 	    vstring_strcpy(reply.transport, message->filter_xport);
1052 	    if (FILTER_WITHOUT_NEXTHOP(STR(reply.transport), nexthop)
1053 		&& *(nexthop = var_def_filter_nexthop) == 0
1054 		&& RCPT_WITHOUT_DOMAIN(recipient->address, nexthop))
1055 		nexthop = var_myhostname;
1056 	    vstring_strcpy(reply.nexthop, nexthop);
1057 	    vstring_strcpy(reply.recipient, recipient->address);
1058 	}
1059 
1060 	/*
1061 	 * Resolve the destination to (transport, nexthop, address). The
1062 	 * result address may differ from the one specified by the sender.
1063 	 */
1064 	else {
1065 	    if (qmgr_resolve_one(message, recipient,
1066 				 recipient->address, &reply) < 0)
1067 		continue;
1068 	    if (!STREQ(recipient->address, STR(reply.recipient)))
1069 		RECIPIENT_UPDATE(recipient->address, STR(reply.recipient));
1070 	}
1071 
1072 	/*
1073 	 * Bounce null recipients. This should never happen, but is most
1074 	 * likely the result of a fault in a different program, so aborting
1075 	 * the queue manager process does not help.
1076 	 */
1077 	if (recipient->address[0] == 0) {
1078 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_ERROR,
1079 			  "5.1.3 null recipient address");
1080 	}
1081 
1082 	/*
1083 	 * Redirect a forced-to-expire message without defer log to the retry
1084 	 * service, so that its defer log will contain an appropriate reason.
1085 	 * Do not redirect such a message to the error service, because if
1086 	 * that request fails, a defer log would be created with reason
1087 	 * "bounce or trace service failure" which would make no sense. Note
1088 	 * that if the bounce service fails to create a defer log, the
1089 	 * message will be returned as undeliverable anyway, because it is
1090 	 * expired.
1091 	 */
1092 	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0) {
1093 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1094 			  "4.7.0 message is administratively expired");
1095 	}
1096 
1097 	/*
1098 	 * Discard mail to the local double bounce address here, so this
1099 	 * system can run without a local delivery agent. They'd still have
1100 	 * to configure something for mail directed to the local postmaster,
1101 	 * though, but that is an RFC requirement anyway.
1102 	 *
1103 	 * XXX This lookup should be done in the resolver, and the mail should
1104 	 * be directed to a general-purpose null delivery agent.
1105 	 */
1106 	if (reply.flags & RESOLVE_CLASS_LOCAL) {
1107 	    at = strrchr(STR(reply.recipient), '@');
1108 	    len = (at ? (at - STR(reply.recipient))
1109 		   : strlen(STR(reply.recipient)));
1110 	    if (strncasecmp_utf8(STR(reply.recipient),
1111 				 var_double_bounce_sender, len) == 0
1112 		&& !var_double_bounce_sender[len]) {
1113 		status = sent(message->tflags, message->queue_id,
1114 			      QMGR_MSG_STATS(&stats, message), recipient,
1115 			      "none", DSN_SIMPLE(&dsn, "2.0.0",
1116 			"undeliverable postmaster notification discarded"));
1117 		if (status == 0) {
1118 		    deliver_completed(message->fp, recipient->offset);
1119 #if 0
1120 		    /* It's the default verification probe sender address. */
1121 		    msg_warn("%s: undeliverable postmaster notification discarded",
1122 			     message->queue_id);
1123 #endif
1124 		} else
1125 		    message->flags |= status;
1126 		continue;
1127 	    }
1128 	}
1129 
1130 	/*
1131 	 * Optionally defer deliveries over specific transports, unless the
1132 	 * restriction is lifted temporarily.
1133 	 */
1134 	if (*var_defer_xports && (message->qflags & QMGR_FLUSH_DFXP) == 0) {
1135 	    if (defer_xport_argv == 0)
1136 		defer_xport_argv = argv_split(var_defer_xports, CHARS_COMMA_SP);
1137 	    for (cpp = defer_xport_argv->argv; *cpp; cpp++)
1138 		if (strcmp(*cpp, STR(reply.transport)) == 0)
1139 		    break;
1140 	    if (*cpp) {
1141 		QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1142 			      "4.3.2 deferred transport");
1143 	    }
1144 	}
1145 
1146 	/*
1147 	 * Safety: defer excess address verification requests.
1148 	 */
1149 	if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0
1150 	    && qmgr_vrfy_pend_count > var_vrfy_pend_limit)
1151 	    QMGR_REDIRECT(&reply, MAIL_SERVICE_RETRY,
1152 			  "4.3.2 Too many address verification requests");
1153 
1154 	/*
1155 	 * Look up or instantiate the proper transport.
1156 	 */
1157 	if (transport == 0 || !STREQ(transport->name, STR(reply.transport))) {
1158 	    if ((transport = qmgr_transport_find(STR(reply.transport))) == 0)
1159 		transport = qmgr_transport_create(STR(reply.transport));
1160 	    queue = 0;
1161 	}
1162 
1163 	/*
1164 	 * This message is being flushed. If need-be unthrottle the
1165 	 * transport.
1166 	 */
1167 	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1168 	    && QMGR_TRANSPORT_THROTTLED(transport))
1169 	    qmgr_transport_unthrottle(transport);
1170 
1171 	/*
1172 	 * This transport is dead. Defer delivery to this recipient.
1173 	 */
1174 	if (QMGR_TRANSPORT_THROTTLED(transport)) {
1175 	    saved_dsn = transport->dsn;
1176 	    if ((transport = qmgr_error_transport(MAIL_SERVICE_RETRY)) != 0) {
1177 		nexthop = qmgr_error_nexthop(saved_dsn);
1178 		vstring_strcpy(reply.nexthop, nexthop);
1179 		myfree(nexthop);
1180 		queue = 0;
1181 	    } else {
1182 		qmgr_defer_recipient(message, recipient, saved_dsn);
1183 		continue;
1184 	    }
1185 	}
1186 
1187 	/*
1188 	 * The nexthop destination provides the default name for the
1189 	 * per-destination queue. When the delivery agent accepts only one
1190 	 * recipient per delivery, give each recipient its own queue, so that
1191 	 * deliveries to different recipients of the same message can happen
1192 	 * in parallel, and so that we can enforce per-recipient concurrency
1193 	 * limits and prevent one recipient from tying up all the delivery
1194 	 * agent resources. We use recipient@nexthop as queue name rather
1195 	 * than the actual recipient domain name, so that one recipient in
1196 	 * multiple equivalent domains cannot evade the per-recipient
1197 	 * concurrency limit. Split the address on the recipient delimiter if
1198 	 * one is defined, so that extended addresses don't get extra
1199 	 * delivery slots.
1200 	 *
1201 	 * Fold the result to lower case so that we don't have multiple queues
1202 	 * for the same name.
1203 	 *
1204 	 * Important! All recipients in a queue must have the same nexthop
1205 	 * value. It is OK to have multiple queues with the same nexthop
1206 	 * value, but only when those queues are named after recipients.
1207 	 *
1208 	 * The single-recipient code below was written for local(8) like
1209 	 * delivery agents, and assumes that all domains that deliver to the
1210 	 * same (transport + nexthop) are aliases for $nexthop. Delivery
1211 	 * concurrency is changed from per-domain into per-recipient, by
1212 	 * changing the queue name from nexthop into localpart@nexthop.
1213 	 *
1214 	 * XXX This assumption is incorrect when different destinations share
1215 	 * the same (transport + nexthop). In reality, such transports are
1216 	 * rarely configured to use single-recipient deliveries. The fix is
1217 	 * to decouple the per-destination recipient limit from the
1218 	 * per-destination concurrency.
1219 	 */
1220 	vstring_strcpy(queue_name, STR(reply.nexthop));
1221 	if (strcmp(transport->name, MAIL_SERVICE_ERROR) != 0
1222 	    && strcmp(transport->name, MAIL_SERVICE_RETRY) != 0
1223 	    && transport->recipient_limit == 1) {
1224 	    /* Copy the recipient localpart. */
1225 	    at = strrchr(STR(reply.recipient), '@');
1226 	    len = (at ? (at - STR(reply.recipient))
1227 		   : strlen(STR(reply.recipient)));
1228 	    vstring_strncpy(queue_name, STR(reply.recipient), len);
1229 	    /* Remove the address extension from the recipient localpart. */
1230 	    if (*var_rcpt_delim && split_addr(STR(queue_name), var_rcpt_delim))
1231 		vstring_truncate(queue_name, strlen(STR(queue_name)));
1232 	    /* Assume the recipient domain is equivalent to nexthop. */
1233 	    vstring_sprintf_append(queue_name, "@%s", STR(reply.nexthop));
1234 	}
1235 	lowercase(STR(queue_name));
1236 
1237 	/*
1238 	 * This transport is alive. Find or instantiate a queue for this
1239 	 * recipient.
1240 	 */
1241 	if (queue == 0 || !STREQ(queue->name, STR(queue_name))) {
1242 	    if ((queue = qmgr_queue_find(transport, STR(queue_name))) == 0)
1243 		queue = qmgr_queue_create(transport, STR(queue_name),
1244 					  STR(reply.nexthop));
1245 	}
1246 
1247 	/*
1248 	 * This message is being flushed. If need-be unthrottle the queue.
1249 	 */
1250 	if ((message->qflags & QMGR_FLUSH_EACH) != 0
1251 	    && QMGR_QUEUE_THROTTLED(queue))
1252 	    qmgr_queue_unthrottle(queue);
1253 
1254 	/*
1255 	 * This queue is dead. Defer delivery to this recipient.
1256 	 */
1257 	if (QMGR_QUEUE_THROTTLED(queue)) {
1258 	    saved_dsn = queue->dsn;
1259 	    if ((queue = qmgr_error_queue(MAIL_SERVICE_RETRY, saved_dsn)) == 0) {
1260 		qmgr_defer_recipient(message, recipient, saved_dsn);
1261 		continue;
1262 	    }
1263 	}
1264 
1265 	/*
1266 	 * This queue is alive. Bind this recipient to this queue instance.
1267 	 */
1268 	recipient->u.queue = queue;
1269     }
1270     resolve_clnt_free(&reply);
1271     vstring_free(queue_name);
1272 }
1273 
1274 /* qmgr_message_assign - assign recipients to specific delivery requests */
1275 
1276 static void qmgr_message_assign(QMGR_MESSAGE *message)
1277 {
1278     RECIPIENT_LIST list = message->rcpt_list;
1279     RECIPIENT *recipient;
1280     QMGR_ENTRY *entry = 0;
1281     QMGR_QUEUE *queue;
1282 
1283     /*
1284      * Try to bundle as many recipients in a delivery request as we can. When
1285      * the recipient resolves to the same site and transport as the previous
1286      * recipient, do not create a new queue entry, just move that recipient
1287      * to the recipient list of the existing queue entry. All this provided
1288      * that we do not exceed the transport-specific limit on the number of
1289      * recipients per transaction. Skip recipients with a dead transport or
1290      * destination.
1291      */
1292 #define LIMIT_OK(limit, count) ((limit) == 0 || ((count) < (limit)))
1293 
1294     for (recipient = list.info; recipient < list.info + list.len; recipient++) {
1295 	if ((queue = recipient->u.queue) != 0) {
1296 	    if (message->single_rcpt || entry == 0 || entry->queue != queue
1297 		|| !LIMIT_OK(entry->queue->transport->recipient_limit,
1298 			     entry->rcpt_list.len)) {
1299 		entry = qmgr_entry_create(queue, message);
1300 	    }
1301 	    recipient_list_add(&entry->rcpt_list, recipient->offset,
1302 			       recipient->dsn_orcpt, recipient->dsn_notify,
1303 			       recipient->orig_addr, recipient->address);
1304 	    qmgr_recipient_count++;
1305 	}
1306     }
1307     recipient_list_free(&message->rcpt_list);
1308     recipient_list_init(&message->rcpt_list, RCPT_LIST_INIT_QUEUE);
1309 }
1310 
1311 /* qmgr_message_free - release memory for in-core message structure */
1312 
1313 void    qmgr_message_free(QMGR_MESSAGE *message)
1314 {
1315     if (message->refcount != 0)
1316 	msg_panic("qmgr_message_free: reference len: %d", message->refcount);
1317     if (message->fp)
1318 	msg_panic("qmgr_message_free: queue file is open");
1319     myfree(message->queue_id);
1320     myfree(message->queue_name);
1321     if (message->dsn_envid)
1322 	myfree(message->dsn_envid);
1323     if (message->encoding)
1324 	myfree(message->encoding);
1325     if (message->sender)
1326 	myfree(message->sender);
1327     if (message->verp_delims)
1328 	myfree(message->verp_delims);
1329     if (message->filter_xport)
1330 	myfree(message->filter_xport);
1331     if (message->inspect_xport)
1332 	myfree(message->inspect_xport);
1333     if (message->redirect_addr)
1334 	myfree(message->redirect_addr);
1335     if (message->client_name)
1336 	myfree(message->client_name);
1337     if (message->client_addr)
1338 	myfree(message->client_addr);
1339     if (message->client_port)
1340 	myfree(message->client_port);
1341     if (message->client_proto)
1342 	myfree(message->client_proto);
1343     if (message->client_helo)
1344 	myfree(message->client_helo);
1345     if (message->sasl_method)
1346 	myfree(message->sasl_method);
1347     if (message->sasl_username)
1348 	myfree(message->sasl_username);
1349     if (message->sasl_sender)
1350 	myfree(message->sasl_sender);
1351     if (message->log_ident)
1352 	myfree(message->log_ident);
1353     if (message->rewrite_context)
1354 	myfree(message->rewrite_context);
1355     recipient_list_free(&message->rcpt_list);
1356     qmgr_message_count--;
1357     if ((message->tflags & DEL_REQ_FLAG_MTA_VRFY) != 0)
1358 	qmgr_vrfy_pend_count--;
1359     myfree((void *) message);
1360 }
1361 
1362 /* qmgr_message_alloc - create in-core message structure */
1363 
1364 QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id,
1365 				         int qflags, mode_t mode)
1366 {
1367     const char *myname = "qmgr_message_alloc";
1368     QMGR_MESSAGE *message;
1369     struct stat st;
1370 
1371     if (msg_verbose)
1372 	msg_info("%s: %s %s", myname, queue_name, queue_id);
1373 
1374     /*
1375      * Create an in-core message structure.
1376      */
1377     message = qmgr_message_create(queue_name, queue_id, qflags);
1378 
1379     /*
1380      * Extract message envelope information: time of arrival, sender address,
1381      * recipient addresses. Skip files with malformed envelope information.
1382      */
1383 #define QMGR_LOCK_MODE (MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT)
1384 
1385     if (qmgr_message_open(message) < 0) {
1386 	qmgr_message_free(message);
1387 	return (0);
1388     }
1389     if (myflock(vstream_fileno(message->fp), INTERNAL_LOCK, QMGR_LOCK_MODE) < 0) {
1390 	msg_info("%s: skipped, still being delivered", queue_id);
1391 	qmgr_message_close(message);
1392 	qmgr_message_free(message);
1393 	return (QMGR_MESSAGE_LOCKED);
1394     }
1395     if (qmgr_message_read(message) < 0) {
1396 	qmgr_message_close(message);
1397 	qmgr_message_free(message);
1398 	return (0);
1399     } else {
1400 
1401 	/*
1402 	 * We have validated the queue file content, so it is safe to modify
1403 	 * the file properties now.
1404 	 */
1405 	if (mode != 0 && fchmod(vstream_fileno(message->fp), mode) < 0)
1406 	    msg_fatal("fchmod %s: %m", VSTREAM_PATH(message->fp));
1407 
1408 	/*
1409 	 * If this message is forced to expire, use the existing defer
1410 	 * logfile records and do not assign any deliveries, leaving the
1411 	 * refcount at zero. If this message is forced to expire, but no
1412 	 * defer logfile records are available, assign deliveries to the
1413 	 * retry transport so that the sender will still find out what
1414 	 * recipients are affected and why. Either way, do not assign normal
1415 	 * deliveries because that would be undesirable especially with mail
1416 	 * that was expired in the 'hold' queue.
1417 	 */
1418 	if ((message->qflags & QMGR_FORCE_EXPIRE) != 0
1419 	    && stat(mail_queue_path((VSTRING *) 0, MAIL_QUEUE_DEFER,
1420 				    queue_id), &st) == 0 && st.st_size > 0) {
1421 	    /* Use this defer log; don't assign deliveries (refcount == 0). */
1422 	    message->flags = 1;			/* simplify downstream code */
1423 	    qmgr_message_close(message);
1424 	    return (message);
1425 	}
1426 
1427 	/*
1428 	 * Reset the defer log. This code should not be here, but we must
1429 	 * reset the defer log *after* acquiring the exclusive lock on the
1430 	 * queue file and *before* resolving new recipients. Since all those
1431 	 * operations are encapsulated so nicely by this routine, the defer
1432 	 * log reset has to be done here as well.
1433 	 *
1434 	 * Note: it is safe to remove the defer logfile from a previous queue
1435 	 * run of this queue file, because the defer log contains information
1436 	 * about recipients that still exist in this queue file.
1437 	 */
1438 	if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT)
1439 	    msg_fatal("%s: %s: remove %s %s: %m", myname,
1440 		      queue_id, MAIL_QUEUE_DEFER, queue_id);
1441 	qmgr_message_sort(message);
1442 	qmgr_message_resolve(message);
1443 	qmgr_message_sort(message);
1444 	qmgr_message_assign(message);
1445 	qmgr_message_close(message);
1446 	return (message);
1447     }
1448 }
1449 
1450 /* qmgr_message_realloc - refresh in-core message structure */
1451 
1452 QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *message)
1453 {
1454     const char *myname = "qmgr_message_realloc";
1455 
1456     /*
1457      * Sanity checks.
1458      */
1459     if (message->rcpt_offset <= 0)
1460 	msg_panic("%s: invalid offset: %ld", myname, message->rcpt_offset);
1461     if (msg_verbose)
1462 	msg_info("%s: %s %s offset %ld", myname, message->queue_name,
1463 		 message->queue_id, message->rcpt_offset);
1464 
1465     /*
1466      * Extract recipient addresses. Skip files with malformed envelope
1467      * information.
1468      */
1469     if (qmgr_message_open(message) < 0)
1470 	return (0);
1471     if (qmgr_message_read(message) < 0) {
1472 	qmgr_message_close(message);
1473 	return (0);
1474     } else {
1475 	qmgr_message_sort(message);
1476 	qmgr_message_resolve(message);
1477 	qmgr_message_sort(message);
1478 	qmgr_message_assign(message);
1479 	qmgr_message_close(message);
1480 	return (message);
1481     }
1482 }
1483