7 /* address rewrite service client
9 /* #include <vstring.h>
10 /* #include <rewrite_clnt.h>
12 /* VSTRING *rewrite_clnt(ruleset, address, result)
13 /* const char *ruleset;
14 /* const char *address;
16 /* VSTRING *rewrite_clnt_internal(ruleset, address, result)
17 /* const char *ruleset;
18 /* const char *address;
21 /* This module implements a mail address rewriting client.
23 /* rewrite_clnt() sends a rule set name and external-form address to the
24 /* rewriting service and returns the resulting external-form address.
25 /* In case of communication failure the program keeps trying until the
26 /* mail system shuts down.
28 /* rewrite_clnt_internal() performs the same functionality but takes
29 /* input in internal (unquoted) form, and produces output in internal
32 /* Warnings: communication failure. Fatal error: mail system is down.
34 /* mail_proto(3h) low-level mail component glue.
38 /* The Secure Mailer license must be distributed with this software.
41 /* IBM T.J. Watson Research
43 /* Yorktown Heights, NY 10598, USA
53 /* Utility library. */
58 #include <vstring_vstream.h>
61 #include <quote_822_local.h>
65 #include "mail_proto.h"
66 #include "mail_params.h"
67 #include "clnt_stream.h"
68 #include "rewrite_clnt.h"
70 /* Application-specific. */
73 * XXX this is shared with the resolver client to save a file descriptor.
75 CLNT_STREAM
*rewrite_clnt_stream
= 0;
77 static time_t last_expire
;
78 static VSTRING
*last_rule
;
79 static VSTRING
*last_addr
;
80 static VSTRING
*last_result
;
82 /* rewrite_clnt - rewrite address to (transport, next hop, recipient) */
84 VSTRING
*rewrite_clnt(const char *rule
, const char *addr
, VSTRING
*result
)
94 last_rule
= vstring_alloc(10);
95 last_addr
= vstring_alloc(100);
96 last_result
= vstring_alloc(100);
100 * Sanity check. An address must be in externalized form. The result must
101 * not clobber the input, because we may have to retransmit the query.
103 #define STR vstring_str
107 if (addr
== STR(result
))
108 msg_panic("rewrite_clnt: result clobbers input");
113 if (time((time_t *) 0) < last_expire
114 && strcmp(addr
, STR(last_addr
)) == 0
115 && strcmp(rule
, STR(last_rule
)) == 0) {
116 vstring_strcpy(result
, STR(last_result
));
118 msg_info("rewrite_clnt: cached: %s: %s -> %s",
119 rule
, addr
, vstring_str(result
));
124 * Keep trying until we get a complete response. The rewrite service is
125 * CPU bound and making the client asynchronous would just complicate the
128 if (rewrite_clnt_stream
== 0)
129 rewrite_clnt_stream
= clnt_stream_create(MAIL_CLASS_PRIVATE
,
135 stream
= clnt_stream_access(rewrite_clnt_stream
);
138 if (attr_print(stream
, ATTR_FLAG_NONE
,
139 ATTR_TYPE_STR
, MAIL_ATTR_REQ
, REWRITE_ADDR
,
140 ATTR_TYPE_STR
, MAIL_ATTR_RULE
, rule
,
141 ATTR_TYPE_STR
, MAIL_ATTR_ADDR
, addr
,
143 || vstream_fflush(stream
)
144 || attr_scan(stream
, ATTR_FLAG_STRICT
,
145 ATTR_TYPE_INT
, MAIL_ATTR_FLAGS
, &server_flags
,
146 ATTR_TYPE_STR
, MAIL_ATTR_ADDR
, result
,
147 ATTR_TYPE_END
) != 2) {
148 if (msg_verbose
|| count
> 1 || (errno
&& errno
!= EPIPE
&& errno
!= ENOENT
))
149 msg_warn("problem talking to service %s: %m",
150 var_rewrite_service
);
153 msg_info("rewrite_clnt: %s: %s -> %s",
154 rule
, addr
, vstring_str(result
));
155 /* Server-requested disconnect. */
156 if (server_flags
!= 0)
157 clnt_stream_recover(rewrite_clnt_stream
);
160 sleep(1); /* XXX make configurable */
161 clnt_stream_recover(rewrite_clnt_stream
);
167 vstring_strcpy(last_rule
, rule
);
168 vstring_strcpy(last_addr
, addr
);
169 vstring_strcpy(last_result
, STR(result
));
170 last_expire
= time((time_t *) 0) + 30; /* XXX make configurable */
175 /* rewrite_clnt_internal - rewrite from/to internal form */
177 VSTRING
*rewrite_clnt_internal(const char *ruleset
, const char *addr
, VSTRING
*result
)
179 VSTRING
*src
= vstring_alloc(100);
180 VSTRING
*dst
= vstring_alloc(100);
183 * Convert the address from internal address form to external RFC822
184 * form, then rewrite it. After rewriting, convert to internal form.
186 quote_822_local(src
, addr
);
187 rewrite_clnt(ruleset
, STR(src
), dst
);
188 unquote_822_local(result
, STR(dst
));
198 #include <msg_vstream.h>
199 #include <split_at.h>
200 #include <vstring_vstream.h>
201 #include <mail_conf.h>
202 #include <mail_params.h>
204 static NORETURN
usage(char *myname
)
206 msg_fatal("usage: %s [-v] [rule address...]", myname
);
209 static void rewrite(char *rule
, char *addr
, VSTRING
*reply
)
211 rewrite_clnt(rule
, addr
, reply
);
212 vstream_printf("%-10s %s\n", "rule", rule
);
213 vstream_printf("%-10s %s\n", "address", addr
);
214 vstream_printf("%-10s %s\n\n", "result", STR(reply
));
215 vstream_fflush(VSTREAM_OUT
);
218 int main(int argc
, char **argv
)
225 msg_vstream_init(argv
[0], VSTREAM_ERR
);
228 msg_info("using config files in %s", var_config_dir
);
229 if (chdir(var_queue_dir
) < 0)
230 msg_fatal("chdir %s: %m", var_queue_dir
);
232 while ((ch
= GETOPT(argc
, argv
, "v")) > 0) {
241 reply
= vstring_alloc(1);
245 if ((rule
= argv
[optind
++]) == 0)
247 if ((addr
= argv
[optind
++]) == 0)
249 rewrite(rule
, addr
, reply
);
252 VSTRING
*buffer
= vstring_alloc(1);
254 while (vstring_fgets_nonl(buffer
, VSTREAM_IN
)) {
255 if ((addr
= split_at(STR(buffer
), ' ')) == 0
256 || *(rule
= STR(buffer
)) == 0)
258 rewrite(rule
, addr
, reply
);
260 vstring_free(buffer
);