Postfix3.3.1
deliver_pass.c
[詳解]
1 /*++
2 /* NAME
3 /* deliver_pass 3
4 /* SUMMARY
5 /* deliver request pass_through
6 /* SYNOPSIS
7 /* #include <deliver_request.h>
8 /*
9 /* int deliver_pass(class, service, request, recipient)
10 /* const char *class;
11 /* const char *service;
12 /* DELIVER_REQUEST *request;
13 /* RECIPIENT *recipient;
14 /*
15 /* int deliver_pass_all(class, service, request)
16 /* const char *class;
17 /* const char *service;
18 /* DELIVER_REQUEST *request;
19 /* DESCRIPTION
20 /* This module implements the client side of the `queue manager
21 /* to delivery agent' protocol, passing one recipient on from
22 /* one delivery agent to another.
23 /*
24 /* deliver_pass() delegates delivery of the named recipient.
25 /*
26 /* deliver_pass_all() delegates an entire delivery request.
27 /*
28 /* Arguments:
29 /* .IP class
30 /* Destination delivery agent service class
31 /* .IP service
32 /* String of the form \fItransport\fR:\fInexthop\fR. Either transport
33 /* or nexthop are optional. For details see the transport map manual page.
34 /* .IP request
35 /* Delivery request with queue file information.
36 /* .IP recipient
37 /* Recipient information. See recipient_list(3).
38 /* DIAGNOSTICS
39 /* LICENSE
40 /* .ad
41 /* .fi
42 /* The Secure Mailer license must be distributed with this software.
43 /* BUGS
44 /* One recipient at a time; this is OK for mailbox deliveries.
45 /*
46 /* Hop status information cannot be passed back.
47 /* AUTHOR(S)
48 /* Wietse Venema
49 /* IBM T.J. Watson Research
50 /* P.O. Box 704
51 /* Yorktown Heights, NY 10598, USA
52 /*--*/
53 
54 /* System library. */
55 
56 #include <sys_defs.h>
57 
58 /* Utility library. */
59 
60 #include <msg.h>
61 #include <vstring.h>
62 #include <vstream.h>
63 #include <split_at.h>
64 #include <mymalloc.h>
65 
66 /* Global library. */
67 
68 #include <mail_params.h>
69 #include <deliver_pass.h>
70 #include <dsb_scan.h>
71 #include <defer.h>
72 #include <rcpt_print.h>
73 
74 #define DELIVER_PASS_DEFER 1
75 #define DELIVER_PASS_UNKNOWN 2
76 
77 /* deliver_pass_initial_reply - retrieve initial delivery process response */
78 
79 static int deliver_pass_initial_reply(VSTREAM *stream)
80 {
81  int stat;
82 
83  if (attr_scan(stream, ATTR_FLAG_STRICT,
85  ATTR_TYPE_END) != 1) {
86  msg_warn("%s: malformed response", VSTREAM_PATH(stream));
87  stat = -1;
88  }
89  return (stat);
90 }
91 
92 /* deliver_pass_send_request - send delivery request to delivery process */
93 
94 static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
95  const char *nexthop,
96  RECIPIENT *rcpt)
97 {
98  int stat;
99 
100  attr_print(stream, ATTR_FLAG_NONE,
112  SEND_ATTR_FUNC(msg_stats_print, (void *) &request->msg_stats),
113  /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
119  /* XXX Should be encapsulated with ATTR_TYPE_FUNC. */
123  /* XXX Ditto if we want to pass TLS certificate info. */
127  ATTR_TYPE_END);
128  attr_print(stream, ATTR_FLAG_NONE,
129  SEND_ATTR_FUNC(rcpt_print, (void *) rcpt),
130  ATTR_TYPE_END);
131 
132  if (vstream_fflush(stream)) {
133  msg_warn("%s: bad write: %m", VSTREAM_PATH(stream));
134  stat = -1;
135  } else {
136  stat = 0;
137  }
138  return (stat);
139 }
140 
141 /* deliver_pass_final_reply - retrieve final delivery status response */
142 
143 static int deliver_pass_final_reply(VSTREAM *stream, DSN_BUF *dsb)
144 {
145  int stat;
146 
147  if (attr_scan(stream, ATTR_FLAG_STRICT,
148  RECV_ATTR_FUNC(dsb_scan, (void *) dsb),
150  ATTR_TYPE_END) != 2) {
151  msg_warn("%s: malformed response", VSTREAM_PATH(stream));
152  return (DELIVER_PASS_UNKNOWN);
153  } else {
154  return (stat ? DELIVER_PASS_DEFER : 0);
155  }
156 }
157 
158 /* deliver_pass - deliver one per-site queue entry */
159 
160 int deliver_pass(const char *class, const char *service,
161  DELIVER_REQUEST *request,
162  RECIPIENT *rcpt)
163 {
164  VSTREAM *stream;
165  DSN_BUF *dsb;
166  DSN dsn;
167  int status;
168  char *saved_service;
169  char *transport;
170  char *nexthop;
171 
172  /*
173  * Parse service into transport:nexthop form, and allow for omission of
174  * optional fields
175  */
176  transport = saved_service = mystrdup(service);
177  if ((nexthop = split_at(saved_service, ':')) == 0 || *nexthop == 0)
178  nexthop = request->nexthop;
179  if (*transport == 0)
180  msg_fatal("missing transport name in \"%s\"", service);
181 
182  /*
183  * Initialize.
184  */
185  stream = mail_connect_wait(class, transport);
186  dsb = dsb_create();
187 
188  /*
189  * Get the delivery process initial response. Send the queue file info
190  * and recipient info to the delivery process. Retrieve the delivery
191  * agent status report. The numerical status code indicates if delivery
192  * should be tried again. The reason text is sent only when a destination
193  * should be avoided for a while, so that the queue manager can log why
194  * it does not even try to schedule delivery to the affected recipients.
195  * XXX Can't pass back hop status info because the problem is with a
196  * different transport.
197  */
198  if (deliver_pass_initial_reply(stream) != 0
199  || deliver_pass_send_request(stream, request, nexthop, rcpt) != 0) {
200  (void) DSN_SIMPLE(&dsn, "4.3.0", "mail transport unavailable");
201  status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
202  request->queue_id, &request->msg_stats,
203  rcpt, "none", &dsn);
204  } else if ((status = deliver_pass_final_reply(stream, dsb))
206  (void) DSN_SIMPLE(&dsn, "4.3.0", "unknown mail transport error");
207  status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
208  request->queue_id, &request->msg_stats,
209  rcpt, "none", &dsn);
210  }
211 
212  /*
213  * Clean up.
214  */
215  vstream_fclose(stream);
216  dsb_free(dsb);
217  myfree(saved_service);
218 
219  return (status);
220 }
221 
222 /* deliver_pass_all - pass entire delivery request */
223 
224 int deliver_pass_all(const char *class, const char *service,
225  DELIVER_REQUEST *request)
226 {
227  RECIPIENT_LIST *list;
228  RECIPIENT *rcpt;
229  int status = 0;
230 
231  /*
232  * XXX We should find out if the target transport can handle
233  * multi-recipient requests. Unfortunately such code is hard to test,
234  * rarely used, and therefore will be buggy.
235  */
236  list = &request->rcpt_list;
237  for (rcpt = list->info; rcpt < list->info + list->len; rcpt++)
238  status |= deliver_pass(class, service, request, rcpt);
239  return (status);
240 }
#define ATTR_FLAG_NONE
Definition: attr.h:98
void myfree(void *ptr)
Definition: mymalloc.c:207
VSTREAM * mail_connect_wait(const char *class, const char *name)
Definition: mail_connect.c:108
RECIPIENT_LIST rcpt_list
DSN_BUF * dsb_create(void)
Definition: dsn_buf.c:169
char * mystrdup(const char *str)
Definition: mymalloc.c:225
#define MAIL_ATTR_ENCODING
Definition: mail_proto.h:202
int msg_stats_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *)
#define DSN_SIMPLE(dsn, _status, _reason)
Definition: dsn.h:41
#define stat(p, s)
Definition: warn_stat.h:18
#define DELIVER_PASS_DEFER
Definition: deliver_pass.c:74
#define MAIL_ATTR_SIZE
Definition: mail_proto.h:139
#define MAIL_ATTR_RWR_CONTEXT
Definition: mail_proto.h:163
void dsb_free(DSN_BUF *dsb)
Definition: dsn_buf.c:190
#define RECV_ATTR_INT(name, val)
Definition: attr.h:71
#define ATTR_TYPE_END
Definition: attr.h:39
#define VSTREAM_PATH(vp)
Definition: vstream.h:126
#define MAIL_ATTR_SASL_METHOD
Definition: mail_proto.h:156
int dsb_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp, int flags, void *ptr)
Definition: dsb_scan.c:48
#define MAIL_ATTR_LOG_HELO_NAME
Definition: mail_proto.h:210
#define MAIL_ATTR_LOG_PROTO_NAME
Definition: mail_proto.h:211
#define DEL_REQ_TRACE_FLAGS(f)
MSG_STATS msg_stats
#define MAIL_ATTR_QUEUE
Definition: mail_proto.h:129
#define attr_print
Definition: attr.h:109
int vstream_fclose(VSTREAM *stream)
Definition: vstream.c:1268
#define MAIL_ATTR_SMTPUTF8
Definition: mail_proto.h:277
#define MAIL_ATTR_SASL_SENDER
Definition: mail_proto.h:158
void msg_warn(const char *fmt,...)
Definition: msg.c:215
#define MAIL_ATTR_DSN_RET
Definition: mail_proto.h:274
int deliver_pass(const char *class, const char *service, DELIVER_REQUEST *request, RECIPIENT *rcpt)
Definition: deliver_pass.c:160
#define MAIL_ATTR_LOG_IDENT
Definition: mail_proto.h:162
#define MAIL_ATTR_DSN_ENVID
Definition: mail_proto.h:273
#define MAIL_ATTR_LOG_CLIENT_ADDR
Definition: mail_proto.h:208
#define MAIL_ATTR_STATUS
Definition: mail_proto.h:126
#define SEND_ATTR_INT(name, val)
Definition: attr.h:63
int deliver_pass_all(const char *class, const char *service, DELIVER_REQUEST *request)
Definition: deliver_pass.c:224
#define SEND_ATTR_LONG(name, val)
Definition: attr.h:67
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define MAIL_ATTR_NEXTHOP
Definition: mail_proto.h:148
int vstream_fflush(VSTREAM *stream)
Definition: vstream.c:1257
#define MAIL_ATTR_SASL_USERNAME
Definition: mail_proto.h:157
#define MAIL_ATTR_RCPT_COUNT
Definition: mail_proto.h:132
#define SEND_ATTR_FUNC(func, val)
Definition: attr.h:69
#define DELIVER_PASS_UNKNOWN
Definition: deliver_pass.c:75
Definition: dsn.h:17
#define MAIL_ATTR_LOG_CLIENT_NAME
Definition: mail_proto.h:207
RECIPIENT * info
#define MAIL_ATTR_SENDER
Definition: mail_proto.h:131
char * split_at(char *string, int delimiter)
Definition: split_at.c:53
#define RECV_ATTR_FUNC(func, val)
Definition: attr.h:77
int defer_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
Definition: defer.c:187
int rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp, int flags, void *ptr)
Definition: rcpt_print.c:51
#define MAIL_ATTR_QUEUEID
Definition: mail_proto.h:130
#define attr_scan
Definition: attr.h:111
#define SEND_ATTR_STR(name, val)
Definition: attr.h:64
#define MAIL_ATTR_FLAGS
Definition: mail_proto.h:128
#define MAIL_ATTR_LOG_CLIENT_PORT
Definition: mail_proto.h:209
#define MAIL_ATTR_OFFSET
Definition: mail_proto.h:138
#define ATTR_FLAG_STRICT
Definition: attr.h:103