Postfix3.3.1
flush.c
[詳解]
1 /*++
2 /* NAME
3 /* flush 8
4 /* SUMMARY
5 /* Postfix fast flush server
6 /* SYNOPSIS
7 /* \fBflush\fR [generic Postfix daemon options]
8 /* DESCRIPTION
9 /* The \fBflush\fR(8) server maintains a record of deferred
10 /* mail by destination.
11 /* This information is used to improve the performance of the SMTP
12 /* \fBETRN\fR request, and of its command-line equivalent,
13 /* "\fBsendmail -qR\fR" or "\fBpostqueue -f\fR".
14 /* This program expects to be run from the \fBmaster\fR(8) process
15 /* manager.
16 /*
17 /* The record is implemented as a per-destination logfile with
18 /* as contents the queue IDs of deferred mail. A logfile is
19 /* append-only, and is truncated when delivery is requested
20 /* for the corresponding destination. A destination is the
21 /* part on the right-hand side of the right-most \fB@\fR in
22 /* an email address.
23 /*
24 /* Per-destination logfiles of deferred mail are maintained only for
25 /* eligible destinations. The list of eligible destinations is
26 /* specified with the \fBfast_flush_domains\fR configuration parameter,
27 /* which defaults to \fB$relay_domains\fR.
28 /*
29 /* This server implements the following requests:
30 /* .IP "\fBadd\fI sitename queueid\fR"
31 /* Inform the \fBflush\fR(8) server that the message with the specified
32 /* queue ID is queued for the specified destination.
33 /* .IP "\fBsend_site\fI sitename\fR"
34 /* Request delivery of mail that is queued for the specified
35 /* destination.
36 /* .IP "\fBsend_file\fI queueid\fR"
37 /* Request delivery of the specified deferred message.
38 /* .IP \fBrefresh\fR
39 /* Refresh non-empty per-destination logfiles that were not read in
40 /* \fB$fast_flush_refresh_time\fR hours, by simulating
41 /* send requests (see above) for the corresponding destinations.
42 /* .sp
43 /* Delete empty per-destination logfiles that were not updated in
44 /* \fB$fast_flush_purge_time\fR days.
45 /* .sp
46 /* This request completes in the background.
47 /* .IP \fBpurge\fR
48 /* Do a \fBrefresh\fR for all per-destination logfiles.
49 /* SECURITY
50 /* .ad
51 /* .fi
52 /* The \fBflush\fR(8) server is not security-sensitive. It does not
53 /* talk to the network, and it does not talk to local users.
54 /* The fast flush server can run chrooted at fixed low privilege.
55 /* DIAGNOSTICS
56 /* Problems and transactions are logged to \fBsyslogd\fR(8).
57 /* BUGS
58 /* Fast flush logfiles are truncated only after a "send"
59 /* request, not when mail is actually delivered, and therefore can
60 /* accumulate outdated or redundant data. In order to maintain sanity,
61 /* "refresh" must be executed periodically. This can
62 /* be automated with a suitable wakeup timer setting in the
63 /* \fBmaster.cf\fR configuration file.
64 /*
65 /* Upon receipt of a request to deliver mail for an eligible
66 /* destination, the \fBflush\fR(8) server requests delivery of all messages
67 /* that are listed in that destination's logfile, regardless of the
68 /* recipients of those messages. This is not an issue for mail
69 /* that is sent to a \fBrelay_domains\fR destination because
70 /* such mail typically only has recipients in one domain.
71 /* CONFIGURATION PARAMETERS
72 /* .ad
73 /* .fi
74 /* Changes to \fBmain.cf\fR are picked up automatically as \fBflush\fR(8)
75 /* processes run for only a limited amount of time. Use the command
76 /* "\fBpostfix reload\fR" to speed up a change.
77 /*
78 /* The text below provides only a parameter summary. See
79 /* \fBpostconf\fR(5) for more details including examples.
80 /* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
81 /* The default location of the Postfix main.cf and master.cf
82 /* configuration files.
83 /* .IP "\fBdaemon_timeout (18000s)\fR"
84 /* How much time a Postfix daemon process may take to handle a
85 /* request before it is terminated by a built-in watchdog timer.
86 /* .IP "\fBfast_flush_domains ($relay_domains)\fR"
87 /* Optional list of destinations that are eligible for per-destination
88 /* logfiles with mail that is queued to those destinations.
89 /* .IP "\fBfast_flush_refresh_time (12h)\fR"
90 /* The time after which a non-empty but unread per-destination "fast
91 /* flush" logfile needs to be refreshed.
92 /* .IP "\fBfast_flush_purge_time (7d)\fR"
93 /* The time after which an empty per-destination "fast flush" logfile
94 /* is deleted.
95 /* .IP "\fBipc_timeout (3600s)\fR"
96 /* The time limit for sending or receiving information over an internal
97 /* communication channel.
98 /* .IP "\fBmax_idle (100s)\fR"
99 /* The maximum amount of time that an idle Postfix daemon process waits
100 /* for an incoming connection before terminating voluntarily.
101 /* .IP "\fBmax_use (100)\fR"
102 /* The maximal number of incoming connections that a Postfix daemon
103 /* process will service before terminating voluntarily.
104 /* .IP "\fBparent_domain_matches_subdomains (see 'postconf -d' output)\fR"
105 /* A list of Postfix features where the pattern "example.com" also
106 /* matches subdomains of example.com,
107 /* instead of requiring an explicit ".example.com" pattern.
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 /* A prefix that is prepended to the process name in syslog
118 /* records, so that, for example, "smtpd" becomes "prefix/smtpd".
119 /* .PP
120 /* Available in Postfix 3.3 and later:
121 /* .IP "\fBservice_name (read-only)\fR"
122 /* The master.cf service name of a Postfix daemon process.
123 /* FILES
124 /* /var/spool/postfix/flush, "fast flush" logfiles.
125 /* SEE ALSO
126 /* smtpd(8), SMTP server
127 /* qmgr(8), queue manager
128 /* postconf(5), configuration parameters
129 /* master(5), generic daemon options
130 /* master(8), process manager
131 /* syslogd(8), system logging
132 /* README FILES
133 /* .ad
134 /* .fi
135 /* Use "\fBpostconf readme_directory\fR" or
136 /* "\fBpostconf html_directory\fR" to locate this information.
137 /* .na
138 /* .nf
139 /* ETRN_README, Postfix ETRN howto
140 /* LICENSE
141 /* .ad
142 /* .fi
143 /* The Secure Mailer license must be distributed with this software.
144 /* HISTORY
145 /* This service was introduced with Postfix version 1.0.
146 /* AUTHOR(S)
147 /* Wietse Venema
148 /* IBM T.J. Watson Research
149 /* P.O. Box 704
150 /* Yorktown Heights, NY 10598, USA
151 /*
152 /* Wietse Venema
153 /* Google, Inc.
154 /* 111 8th Avenue
155 /* New York, NY 10011, USA
156 /*--*/
157 
158 /* System library. */
159 
160 #include <sys_defs.h>
161 #include <sys/stat.h>
162 #include <sys/time.h>
163 #include <unistd.h>
164 #include <stdlib.h>
165 #include <utime.h>
166 #include <errno.h>
167 #include <ctype.h>
168 #include <string.h>
169 
170 /* Utility library. */
171 
172 #include <msg.h>
173 #include <events.h>
174 #include <vstream.h>
175 #include <vstring.h>
176 #include <vstring_vstream.h>
177 #include <myflock.h>
178 #include <htable.h>
179 #include <dict.h>
180 #include <scan_dir.h>
181 #include <stringops.h>
182 #include <safe_open.h>
183 #include <warn_stat.h>
184 #include <midna_domain.h>
185 
186 /* Global library. */
187 
188 #include <mail_params.h>
189 #include <mail_version.h>
190 #include <mail_queue.h>
191 #include <mail_proto.h>
192 #include <mail_flush.h>
193 #include <flush_clnt.h>
194 #include <mail_conf.h>
195 #include <mail_scan_dir.h>
196 #include <maps.h>
197 #include <domain_list.h>
198 #include <match_parent_style.h>
199 
200 /* Single server skeleton. */
201 
202 #include <mail_server.h>
203 
204 /* Application-specific. */
205 
206  /*
207  * Tunable parameters. The fast_flush_domains parameter is not defined here,
208  * because it is also used by the global library, and therefore is owned by
209  * the library.
210  */
213 
214  /*
215  * Flush policy stuff.
216  */
217 static DOMAIN_LIST *flush_domains;
218 
219  /*
220  * Some hard-wired policy: how many queue IDs we remember while we're
221  * flushing a logfile (duplicate elimination). Sites with 1000+ emails
222  * queued should arrange for permanent connectivity.
223  */
224 #define FLUSH_DUP_FILTER_SIZE 10000 /* graceful degradation */
225 
226  /*
227  * Silly little macros.
228  */
229 #define STR(x) vstring_str(x)
230 #define STREQ(x,y) ((x) == (y) || strcmp(x,y) == 0)
231 
232  /*
233  * Forward declarations resulting from breaking up routines according to
234  * name space: domain names versus safe-to-use pathnames.
235  */
236 static int flush_add_path(const char *, const char *);
237 static int flush_send_path(const char *, int);
238 
239  /*
240  * Do we only refresh the per-destination logfile, or do we really request
241  * mail delivery as if someone sent ETRN? If the latter, we must override
242  * information about unavailable hosts or unavailable transports.
243  *
244  * When selectively flushing deferred mail, we need to override the queue
245  * manager's "dead destination" information and unthrottle transports and
246  * queues. There are two options:
247  *
248  * - Unthrottle all transports and queues before we move mail to the incoming
249  * queue. This is less accurate, but has the advantage when flushing lots of
250  * mail, because Postfix can skip delivery of flushed messages after it
251  * discovers that a destination is (still) unavailable.
252  *
253  * - Unthrottle some transports and queues after the queue manager moves mail
254  * to the active queue. This is more accurate, but has the disadvantage when
255  * flushing lots of mail, because Postfix cannot skip delivery of flushed
256  * messages after it discovers that a destination is (still) unavailable.
257  */
258 #define REFRESH_ONLY 0
259 #define UNTHROTTLE_BEFORE (1<<0)
260 #define UNTHROTTLE_AFTER (1<<1)
261 
262 /* flush_site_to_path - convert domain or [addr] to harmless string */
263 
264 static VSTRING *flush_site_to_path(VSTRING *path, const char *site)
265 {
266  const char *ptr;
267  int ch;
268 
269  /*
270  * Convert the name to ASCII, so that we don't to end up with non-ASCII
271  * names in the file system. The IDNA library functions fold case.
272  */
273 #ifndef NO_EAI
274  if ((site = midna_domain_to_ascii(site)) == 0)
275  return (0);
276 #endif
277 
278  /*
279  * Allocate buffer on the fly; caller still needs to clean up.
280  */
281  if (path == 0)
282  path = vstring_alloc(10);
283 
284  /*
285  * Mask characters that could upset the name-to-queue-file mapping code.
286  */
287  for (ptr = site; (ch = *(unsigned const char *) ptr) != 0; ptr++)
288  if (ISALNUM(ch))
289  VSTRING_ADDCH(path, tolower(ch));
290  else
291  VSTRING_ADDCH(path, '_');
292  VSTRING_TERMINATE(path);
293 
294  if (msg_verbose)
295  msg_info("site %s to path %s", site, STR(path));
296 
297  return (path);
298 }
299 
300 /* flush_add_service - append queue ID to per-site fast flush logfile */
301 
302 static int flush_add_service(const char *site, const char *queue_id)
303 {
304  const char *myname = "flush_add_service";
305  VSTRING *site_path;
306  int status;
307 
308  if (msg_verbose)
309  msg_info("%s: site %s queue_id %s", myname, site, queue_id);
310 
311  /*
312  * If this site is not eligible for logging, deny the request.
313  */
314  if (domain_list_match(flush_domains, site) == 0)
315  return (flush_domains->error ? FLUSH_STAT_FAIL : FLUSH_STAT_DENY);
316 
317  /*
318  * Map site to path and update log.
319  */
320  if ((site_path = flush_site_to_path((VSTRING *) 0, site)) == 0)
321  return (FLUSH_STAT_DENY);
322  status = flush_add_path(STR(site_path), queue_id);
323  vstring_free(site_path);
324 
325  return (status);
326 }
327 
328 /* flush_add_path - add record to log */
329 
330 static int flush_add_path(const char *path, const char *queue_id)
331 {
332  const char *myname = "flush_add_path";
333  VSTREAM *log;
334 
335  /*
336  * Sanity check.
337  */
338  if (!mail_queue_id_ok(path))
339  return (FLUSH_STAT_BAD);
340 
341  /*
342  * Open the logfile or bust.
343  */
344  if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, path,
345  O_CREAT | O_APPEND | O_WRONLY, 0600)) == 0)
346  msg_fatal("%s: open fast flush logfile %s: %m", myname, path);
347 
348  /*
349  * We must lock the logfile, so that we don't lose information due to
350  * concurrent access. If the lock takes too long, the Postfix watchdog
351  * will eventually take care of the problem, but it will take a while.
352  */
353  if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
354  msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
355 
356  /*
357  * Append the queue ID. With 15 bits of microsecond time, a queue ID is
358  * not recycled often enough for false hits to be a problem. If it does,
359  * then we could add other signature information, such as the file size
360  * in bytes.
361  */
362  vstream_fprintf(log, "%s\n", queue_id);
363  if (vstream_fflush(log))
364  msg_warn("write fast flush logfile %s: %m", path);
365 
366  /*
367  * Clean up.
368  */
369  if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
370  msg_fatal("%s: unlock fast flush logfile %s: %m", myname, path);
371  if (vstream_fclose(log) != 0)
372  msg_warn("write fast flush logfile %s: %m", path);
373 
374  return (FLUSH_STAT_OK);
375 }
376 
377 /* flush_send_service - flush mail queued for site */
378 
379 static int flush_send_service(const char *site, int how)
380 {
381  const char *myname = "flush_send_service";
382  VSTRING *site_path;
383  int status;
384 
385  if (msg_verbose)
386  msg_info("%s: site %s", myname, site);
387 
388  /*
389  * If this site is not eligible for logging, deny the request.
390  */
391  if (domain_list_match(flush_domains, site) == 0)
392  return (flush_domains->error ? FLUSH_STAT_FAIL : FLUSH_STAT_DENY);
393 
394  /*
395  * Map site name to path name and flush the log.
396  */
397  if ((site_path = flush_site_to_path((VSTRING *) 0, site)) == 0)
398  return (FLUSH_STAT_DENY);
399  status = flush_send_path(STR(site_path), how);
400  vstring_free(site_path);
401 
402  return (status);
403 }
404 
405 /* flush_one_file - move one queue file to incoming queue */
406 
407 static int flush_one_file(const char *queue_id, VSTRING *queue_file,
408  struct utimbuf * tbuf, int how)
409 {
410  const char *myname = "flush_one_file";
411  const char *queue_name;
412  const char *path;
413 
414  /*
415  * Some other instance of this program may flush some logfile and may
416  * just have moved this queue file to the incoming queue.
417  */
418  for (queue_name = MAIL_QUEUE_DEFERRED; /* see below */ ;
419  queue_name = MAIL_QUEUE_INCOMING) {
420  path = mail_queue_path(queue_file, queue_name, queue_id);
421  if (utime(path, tbuf) == 0)
422  break;
423  if (errno != ENOENT)
424  msg_warn("%s: update %s time stamps: %m", myname, path);
425  if (STREQ(queue_name, MAIL_QUEUE_INCOMING))
426  return (0);
427  }
428 
429  /*
430  * With the UNTHROTTLE_AFTER strategy, we leave it up to the queue
431  * manager to unthrottle transports and queues as it reads recipients
432  * from a queue file. We request this unthrottle operation by setting the
433  * group read permission bit.
434  *
435  * Note: we must avoid using chmod(). It is not only slower than fchmod()
436  * but it is also less secure. With chmod(), an attacker could repeatedly
437  * send requests to the flush server and trick it into changing
438  * permissions of non-queue files, by exploiting a race condition.
439  *
440  * We use safe_open() because we don't validate the file content before
441  * modifying the file status.
442  */
443  if (how & UNTHROTTLE_AFTER) {
444  VSTRING *why;
445  struct stat st;
446  VSTREAM *fp;
447 
448  for (why = vstring_alloc(1); /* see below */ ;
449  queue_name = MAIL_QUEUE_INCOMING,
450  path = mail_queue_path(queue_file, queue_name, queue_id)) {
451  if ((fp = safe_open(path, O_RDWR, 0, &st, -1, -1, why)) != 0)
452  break;
453  if (errno != ENOENT)
454  msg_warn("%s: open %s: %s", myname, path, STR(why));
455  if (errno != ENOENT || STREQ(queue_name, MAIL_QUEUE_INCOMING)) {
456  vstring_free(why);
457  return (0);
458  }
459  }
460  vstring_free(why);
461  if ((st.st_mode & MAIL_QUEUE_STAT_READY) != MAIL_QUEUE_STAT_READY) {
462  (void) vstream_fclose(fp);
463  return (0);
464  }
465  if (fchmod(vstream_fileno(fp), st.st_mode | MAIL_QUEUE_STAT_UNTHROTTLE) < 0)
466  msg_warn("%s: fchmod %s: %m", myname, path);
467  (void) vstream_fclose(fp);
468  }
469 
470  /*
471  * Move the file to the incoming queue, if it isn't already there.
472  */
473  if (STREQ(queue_name, MAIL_QUEUE_INCOMING) == 0
474  && mail_queue_rename(queue_id, queue_name, MAIL_QUEUE_INCOMING) < 0
475  && errno != ENOENT)
476  msg_warn("%s: rename from %s to %s: %m",
477  path, queue_name, MAIL_QUEUE_INCOMING);
478 
479  /*
480  * If we got here, we achieved something, so let's claim succes.
481  */
482  return (1);
483 }
484 
485 /* flush_send_path - flush logfile file */
486 
487 static int flush_send_path(const char *path, int how)
488 {
489  const char *myname = "flush_send_path";
490  VSTRING *queue_id;
491  VSTRING *queue_file;
492  VSTREAM *log;
493  struct utimbuf tbuf;
494  static char qmgr_flush_trigger[] = {
495  QMGR_REQ_FLUSH_DEAD, /* flush dead site/transport cache */
496  };
497  static char qmgr_scan_trigger[] = {
498  QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
499  };
500  HTABLE *dup_filter;
501  int count;
502 
503  /*
504  * Sanity check.
505  */
506  if (!mail_queue_id_ok(path))
507  return (FLUSH_STAT_BAD);
508 
509  /*
510  * Open the logfile. If the file does not exist, then there is no queued
511  * mail for this destination.
512  */
513  if ((log = mail_queue_open(MAIL_QUEUE_FLUSH, path, O_RDWR, 0600)) == 0) {
514  if (errno != ENOENT)
515  msg_fatal("%s: open fast flush logfile %s: %m", myname, path);
516  return (FLUSH_STAT_OK);
517  }
518 
519  /*
520  * We must lock the logfile, so that we don't lose information when it is
521  * truncated. Unfortunately, this means that the file can be locked for a
522  * significant amount of time. If things really get stuck the Postfix
523  * watchdog will take care of it.
524  */
525  if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_EXCLUSIVE) < 0)
526  msg_fatal("%s: lock fast flush logfile %s: %m", myname, path);
527 
528  /*
529  * With the UNTHROTTLE_BEFORE strategy, we ask the queue manager to
530  * unthrottle all transports and queues before we move a deferred queue
531  * file to the incoming queue. This minimizes a race condition where the
532  * queue manager seizes a queue file before it knows that we want to
533  * flush that message.
534  *
535  * This reduces the race condition time window to a very small amount (the
536  * flush server does not really know when the queue manager reads its
537  * command fifo). But there is a worse race, where the queue manager
538  * moves a deferred queue file to the active queue before we have a
539  * chance to expedite its delivery.
540  */
541  if (how & UNTHROTTLE_BEFORE)
543  qmgr_flush_trigger, sizeof(qmgr_flush_trigger));
544 
545  /*
546  * This is the part that dominates running time: schedule the listed
547  * queue files for delivery by updating their file time stamps and by
548  * moving them from the deferred queue to the incoming queue. This should
549  * take no more than a couple seconds under normal conditions. Filter out
550  * duplicate queue file names to avoid hammering the file system, with
551  * some finite limit on the amount of memory that we are willing to
552  * sacrifice for duplicate filtering. Graceful degradation.
553  *
554  * By moving selected queue files from the deferred queue to the incoming
555  * queue we optimize for the case where most deferred mail is for other
556  * sites. If that assumption does not hold, i.e. all deferred mail is for
557  * the same site, then doing a "fast flush" will cost more disk I/O than
558  * a "slow flush" that delivers the entire deferred queue. This penalty
559  * is only temporary - it will go away after we unite the active queue
560  * and the incoming queue.
561  */
562  queue_id = vstring_alloc(10);
563  queue_file = vstring_alloc(10);
564  dup_filter = htable_create(10);
565  tbuf.actime = tbuf.modtime = event_time();
566  for (count = 0; vstring_get_nonl(queue_id, log) != VSTREAM_EOF; count++) {
567  if (!mail_queue_id_ok(STR(queue_id))) {
568  msg_warn("bad queue id \"%.30s...\" in fast flush logfile %s",
569  STR(queue_id), path);
570  continue;
571  }
572  if (dup_filter->used >= FLUSH_DUP_FILTER_SIZE
573  || htable_find(dup_filter, STR(queue_id)) == 0) {
574  if (msg_verbose)
575  msg_info("%s: logfile %s: update queue file %s time stamps",
576  myname, path, STR(queue_id));
577  if (dup_filter->used <= FLUSH_DUP_FILTER_SIZE)
578  htable_enter(dup_filter, STR(queue_id), 0);
579  count += flush_one_file(STR(queue_id), queue_file, &tbuf, how);
580  } else {
581  if (msg_verbose)
582  msg_info("%s: logfile %s: skip queue file %s as duplicate",
583  myname, path, STR(queue_file));
584  }
585  }
586  htable_free(dup_filter, (void (*) (void *)) 0);
587  vstring_free(queue_file);
588  vstring_free(queue_id);
589 
590  /*
591  * Truncate the fast flush log.
592  */
593  if (count > 0 && ftruncate(vstream_fileno(log), (off_t) 0) < 0)
594  msg_fatal("%s: truncate fast flush logfile %s: %m", myname, path);
595 
596  /*
597  * Workaround for noatime mounts. Use futimes() if available.
598  */
599  (void) utimes(VSTREAM_PATH(log), (struct timeval *) 0);
600 
601  /*
602  * Request delivery and clean up.
603  */
604  if (myflock(vstream_fileno(log), INTERNAL_LOCK, MYFLOCK_OP_NONE) < 0)
605  msg_fatal("%s: unlock fast flush logfile %s: %m", myname, path);
606  if (vstream_fclose(log) != 0)
607  msg_warn("%s: read fast flush logfile %s: %m", myname, path);
608  if (count > 0) {
609  if (msg_verbose)
610  msg_info("%s: requesting delivery for logfile %s", myname, path);
612  qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
613  }
614  return (FLUSH_STAT_OK);
615 }
616 
617 /* flush_send_file_service - flush one queue file */
618 
619 static int flush_send_file_service(const char *queue_id)
620 {
621  const char *myname = "flush_send_file_service";
622  VSTRING *queue_file;
623  struct utimbuf tbuf;
624  static char qmgr_scan_trigger[] = {
625  QMGR_REQ_SCAN_INCOMING, /* scan incoming queue */
626  };
627 
628  /*
629  * Sanity check.
630  */
631  if (!mail_queue_id_ok(queue_id))
632  return (FLUSH_STAT_BAD);
633 
634  if (msg_verbose)
635  msg_info("%s: requesting delivery for queue_id %s", myname, queue_id);
636 
637  queue_file = vstring_alloc(30);
638  tbuf.actime = tbuf.modtime = event_time();
639  if (flush_one_file(queue_id, queue_file, &tbuf, UNTHROTTLE_AFTER) > 0)
641  qmgr_scan_trigger, sizeof(qmgr_scan_trigger));
642  vstring_free(queue_file);
643 
644  return (FLUSH_STAT_OK);
645 }
646 
647 /* flush_refresh_service - refresh logfiles beyond some age */
648 
649 static int flush_refresh_service(int max_age)
650 {
651  const char *myname = "flush_refresh_service";
652  SCAN_DIR *scan;
653  char *site_path;
654  struct stat st;
655  VSTRING *path = vstring_alloc(10);
656 
658  while ((site_path = mail_scan_dir_next(scan)) != 0) {
659  if (!mail_queue_id_ok(site_path))
660  continue; /* XXX grumble. */
661  mail_queue_path(path, MAIL_QUEUE_FLUSH, site_path);
662  if (stat(STR(path), &st) < 0) {
663  if (errno != ENOENT)
664  msg_warn("%s: stat %s: %m", myname, STR(path));
665  else if (msg_verbose)
666  msg_info("%s: %s: %m", myname, STR(path));
667  continue;
668  }
669  if (st.st_size == 0) {
670  if (st.st_mtime + var_fflush_purge < event_time()) {
671  if (unlink(STR(path)) < 0)
672  msg_warn("remove logfile %s: %m", STR(path));
673  else if (msg_verbose)
674  msg_info("%s: unlink %s, empty and unchanged for %d days",
675  myname, STR(path), var_fflush_purge / 86400);
676  } else if (msg_verbose)
677  msg_info("%s: skip logfile %s - empty log", myname, site_path);
678  } else if (st.st_atime + max_age < event_time()) {
679  if (msg_verbose)
680  msg_info("%s: flush logfile %s", myname, site_path);
681  flush_send_path(site_path, REFRESH_ONLY);
682  } else {
683  if (msg_verbose)
684  msg_info("%s: skip logfile %s, unread for <%d hours(s) ",
685  myname, site_path, max_age / 3600);
686  }
687  }
688  scan_dir_close(scan);
689  vstring_free(path);
690 
691  return (FLUSH_STAT_OK);
692 }
693 
694 /* flush_request_receive - receive request */
695 
696 static int flush_request_receive(VSTREAM *client_stream, VSTRING *request)
697 {
698  int count;
699 
700  /*
701  * Kluge: choose the protocol depending on the request size.
702  */
703  if (read_wait(vstream_fileno(client_stream), var_ipc_timeout) < 0) {
704  msg_warn("timeout while waiting for data from %s",
705  VSTREAM_PATH(client_stream));
706  return (-1);
707  }
708  if ((count = peekfd(vstream_fileno(client_stream))) < 0) {
709  msg_warn("cannot examine read buffer of %s: %m",
710  VSTREAM_PATH(client_stream));
711  return (-1);
712  }
713 
714  /*
715  * Short request: master trigger. Use the string+null protocol.
716  */
717  if (count <= 2) {
718  if (vstring_get_null(request, client_stream) == VSTREAM_EOF) {
719  msg_warn("end-of-input while reading request from %s: %m",
720  VSTREAM_PATH(client_stream));
721  return (-1);
722  }
723  }
724 
725  /*
726  * Long request: real flush client. Use the attribute list protocol.
727  */
728  else {
729  if (attr_scan(client_stream,
731  RECV_ATTR_STR(MAIL_ATTR_REQ, request),
732  ATTR_TYPE_END) != 1) {
733  return (-1);
734  }
735  }
736  return (0);
737 }
738 
739 /* flush_service - perform service for client */
740 
741 static void flush_service(VSTREAM *client_stream, char *unused_service,
742  char **argv)
743 {
744  VSTRING *request = vstring_alloc(10);
745  VSTRING *site = 0;
746  VSTRING *queue_id = 0;
747  static char wakeup[] = { /* master wakeup request */
749  0,
750  };
751  int status = FLUSH_STAT_BAD;
752 
753  /*
754  * Sanity check. This service takes no command-line arguments.
755  */
756  if (argv[0])
757  msg_fatal("unexpected command-line argument: %s", argv[0]);
758 
759  /*
760  * This routine runs whenever a client connects to the UNIX-domain socket
761  * dedicated to the fast flush service. What we see below is a little
762  * protocol to (1) read a request from the client (the name of the site)
763  * and (2) acknowledge that we have received the request.
764  *
765  * All connection-management stuff is handled by the common code in
766  * single_server.c.
767  */
768  if (flush_request_receive(client_stream, request) == 0) {
769  if (STREQ(STR(request), FLUSH_REQ_ADD)) {
770  site = vstring_alloc(10);
771  queue_id = vstring_alloc(10);
772  if (attr_scan(client_stream, ATTR_FLAG_STRICT,
774  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
775  ATTR_TYPE_END) == 2
776  && mail_queue_id_ok(STR(queue_id)))
777  status = flush_add_service(STR(site), STR(queue_id));
778  attr_print(client_stream, ATTR_FLAG_NONE,
780  ATTR_TYPE_END);
781  } else if (STREQ(STR(request), FLUSH_REQ_SEND_SITE)) {
782  site = vstring_alloc(10);
783  if (attr_scan(client_stream, ATTR_FLAG_STRICT,
785  ATTR_TYPE_END) == 1)
786  status = flush_send_service(STR(site), UNTHROTTLE_BEFORE);
787  attr_print(client_stream, ATTR_FLAG_NONE,
789  ATTR_TYPE_END);
790  } else if (STREQ(STR(request), FLUSH_REQ_SEND_FILE)) {
791  queue_id = vstring_alloc(10);
792  if (attr_scan(client_stream, ATTR_FLAG_STRICT,
793  RECV_ATTR_STR(MAIL_ATTR_QUEUEID, queue_id),
794  ATTR_TYPE_END) == 1)
795  status = flush_send_file_service(STR(queue_id));
796  attr_print(client_stream, ATTR_FLAG_NONE,
798  ATTR_TYPE_END);
799  } else if (STREQ(STR(request), FLUSH_REQ_REFRESH)
800  || STREQ(STR(request), wakeup)) {
801  attr_print(client_stream, ATTR_FLAG_NONE,
803  ATTR_TYPE_END);
804  vstream_fflush(client_stream);
805  (void) flush_refresh_service(var_fflush_refresh);
806  } else if (STREQ(STR(request), FLUSH_REQ_PURGE)) {
807  attr_print(client_stream, ATTR_FLAG_NONE,
809  ATTR_TYPE_END);
810  vstream_fflush(client_stream);
811  (void) flush_refresh_service(0);
812  }
813  } else
814  attr_print(client_stream, ATTR_FLAG_NONE,
816  ATTR_TYPE_END);
817  vstring_free(request);
818  if (site)
819  vstring_free(site);
820  if (queue_id)
821  vstring_free(queue_id);
822 }
823 
824 /* pre_jail_init - pre-jail initialization */
825 
826 static void pre_jail_init(char *unused_name, char **unused_argv)
827 {
831 }
832 
834 
835 /* main - pass control to the single-threaded skeleton */
836 
837 int main(int argc, char **argv)
838 {
839  static const CONFIG_TIME_TABLE time_table[] = {
842  0,
843  };
844 
845  /*
846  * Fingerprint executables and core dumps.
847  */
849 
850  single_server_main(argc, argv, flush_service,
851  CA_MAIL_SERVER_TIME_TABLE(time_table),
852  CA_MAIL_SERVER_PRE_INIT(pre_jail_init),
854  0);
855 }
int msg_verbose
Definition: msg.c:177
void htable_free(HTABLE *table, void(*free_fn)(void *))
Definition: htable.c:287
#define VSTREAM_EOF
Definition: vstream.h:110
int var_ipc_timeout
Definition: mail_params.c:255
#define ATTR_FLAG_NONE
Definition: attr.h:98
#define CA_MAIL_SERVER_UNLIMITED
Definition: mail_server.h:70
#define MATCH_FLAG_RETURN
Definition: match_list.h:40
char * var_fflush_domains
Definition: mail_params.c:287
int match_parent_style(const char *name)
int vstring_get_null(VSTRING *vp, VSTREAM *fp)
int vstring_get_nonl(VSTRING *vp, VSTREAM *fp)
int mail_queue_id_ok(const char *queue_id)
Definition: mail_queue.c:296
#define DEF_FFLUSH_REFRESH
Definition: mail_params.h:2499
#define stat(p, s)
Definition: warn_stat.h:18
#define MAIL_ATTR_REQ
Definition: mail_proto.h:124
#define domain_list_match
Definition: domain_list.h:26
ssize_t used
Definition: htable.h:27
#define MYFLOCK_OP_EXCLUSIVE
Definition: myflock.h:30
#define MAIL_QUEUE_FLUSH
Definition: mail_queue.h:37
#define FLUSH_STAT_FAIL
Definition: flush_clnt.h:36
#define ATTR_TYPE_END
Definition: attr.h:39
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define FLUSH_STAT_BAD
Definition: flush_clnt.h:38
Definition: htable.h:25
#define DOMAIN_LIST
Definition: domain_list.h:22
#define MAIL_QUEUE_STAT_READY
Definition: mail_queue.h:48
int mail_trigger(const char *, const char *, const char *, ssize_t)
Definition: mail_trigger.c:72
#define MAIL_QUEUE_STAT_UNTHROTTLE
Definition: mail_queue.h:51
#define VSTRING_TERMINATE(vp)
Definition: vstring.h:74
#define ISALNUM(c)
Definition: sys_defs.h:1745
const char * mail_queue_path(VSTRING *buf, const char *queue_name, const char *queue_id)
Definition: mail_queue.c:204
SCAN_DIR * scan_dir_open(const char *path)
Definition: scan_dir.c:165
HTABLE * htable_create(ssize_t size)
Definition: htable.c:179
#define MAIL_CLASS_PUBLIC
Definition: mail_proto.h:95
#define VAR_FFLUSH_REFRESH
Definition: mail_params.h:2498
#define VSTRING_ADDCH(vp, ch)
Definition: vstring.h:81
#define attr_print
Definition: attr.h:109
VSTREAM * vstream_fprintf(VSTREAM *stream, const char *fmt,...)
Definition: vstream.c:1348
#define FLUSH_REQ_ADD
Definition: flush_clnt.h:27
int main(int argc, char **argv)
Definition: flush.c:837
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
SCAN_DIR * scan_dir_close(SCAN_DIR *scan)
Definition: scan_dir.c:210
VSTREAM * mail_queue_open(const char *queue_name, const char *queue_id, int flags, mode_t mode)
Definition: mail_queue.c:424
int mail_queue_rename(const char *queue_id, const char *old_queue, const char *new_queue)
Definition: mail_queue.c:247
int var_fflush_refresh
Definition: flush.c:211
#define MAIL_QUEUE_INCOMING
Definition: mail_queue.h:30
#define read_wait(fd, timeout)
Definition: iostuff.h:39
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define FLUSH_REQ_SEND_SITE
Definition: flush_clnt.h:28
#define REFRESH_ONLY
Definition: flush.c:258
VSTRING * vstring_alloc(ssize_t len)
Definition: vstring.c:353
int myflock(int fd, int lock_style, int operation)
Definition: myflock.c:87
#define VAR_FFLUSH_PURGE
Definition: mail_params.h:2494
#define FLUSH_REQ_SEND_FILE
Definition: flush_clnt.h:29
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
void * htable_find(HTABLE *table, const char *key)
Definition: htable.c:227
#define FLUSH_STAT_DENY
Definition: flush_clnt.h:39
#define CA_MAIL_SERVER_TIME_TABLE(v)
Definition: mail_server.h:59
#define MAIL_ATTR_STATUS
Definition: mail_proto.h:126
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
#define DEF_FFLUSH_PURGE
Definition: mail_params.h:2495
#define STR(x)
Definition: flush.c:229
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define MYFLOCK_OP_NONE
Definition: myflock.h:28
#define FLUSH_DUP_FILTER_SIZE
Definition: flush.c:224
ssize_t peekfd(int)
Definition: peekfd.c:60
#define domain_list_init(o, f, p)
Definition: domain_list.h:24
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define FLUSH_REQ_REFRESH
Definition: flush_clnt.h:30
#define QMGR_REQ_SCAN_INCOMING
Definition: mail_proto.h:107
#define MAIL_QUEUE_DEFERRED
Definition: mail_queue.h:32
time_t event_time(void)
Definition: events.c:647
#define UNTHROTTLE_AFTER
Definition: flush.c:260
#define STREQ(x, y)
Definition: flush.c:230
const char * midna_domain_to_ascii(const char *name)
Definition: midna_domain.c:261
VSTREAM * safe_open(const char *path, int flags, mode_t mode, struct stat *st, uid_t user, gid_t group, VSTRING *why)
Definition: safe_open.c:243
#define TRIGGER_REQ_WAKEUP
Definition: mail_proto.h:101
VSTRING * vstring_free(VSTRING *vp)
Definition: vstring.c:380
char * var_queue_service
Definition: mail_params.c:305
NORETURN single_server_main(int, char **, SINGLE_SERVER_FN,...)
#define vstream_fileno(vp)
Definition: vstream.h:115
#define FLUSH_REQ_PURGE
Definition: flush_clnt.h:31
#define FLUSH_STAT_OK
Definition: flush_clnt.h:37
#define UNTHROTTLE_BEFORE
Definition: flush.c:259
#define MAIL_ATTR_QUEUEID
Definition: mail_proto.h:130
#define MAIL_ATTR_SITE
Definition: mail_proto.h:137
#define QMGR_REQ_FLUSH_DEAD
Definition: mail_proto.h:108
int var_fflush_purge
Definition: flush.c:212
#define attr_scan
Definition: attr.h:111
MAIL_VERSION_STAMP_DECLARE
Definition: flush.c:833
#define ATTR_FLAG_MORE
Definition: attr.h:101
#define VAR_FFLUSH_DOMAINS
Definition: mail_params.h:2490
char * mail_scan_dir_next(SCAN_DIR *scan)
Definition: mail_scan_dir.c:43
#define CA_MAIL_SERVER_PRE_INIT(v)
Definition: mail_server.h:64
#define RECV_ATTR_STR(name, val)
Definition: attr.h:72
#define ATTR_FLAG_STRICT
Definition: attr.h:103
HTABLE_INFO * htable_enter(HTABLE *table, const char *key, void *value)
Definition: htable.c:212
void msg_info(const char *fmt,...)
Definition: msg.c:199