Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / ibm-public / postfix / dist / src / global / anvil_clnt.c
blobf8822eea67d1bcd908cbb74c43782a810439f966
1 /* $NetBSD$ */
3 /*++
4 /* NAME
5 /* anvil_clnt 3
6 /* SUMMARY
7 /* connection count and rate management client interface
8 /* SYNOPSIS
9 /* #include <anvil_clnt.h>
11 /* ANVIL_CLNT *anvil_clnt_create(void)
13 /* void anvil_clnt_free(anvil_clnt)
14 /* ANVIL_CLNT *anvil_clnt;
16 /* int anvil_clnt_connect(anvil_clnt, service, addr,
17 /* count, rate)
18 /* ANVIL_CLNT *anvil_clnt;
19 /* const char *service;
20 /* const char *addr;
21 /* int *count;
22 /* int *rate;
24 /* int anvil_clnt_mail(anvil_clnt, service, addr, msgs)
25 /* ANVIL_CLNT *anvil_clnt;
26 /* const char *service;
27 /* const char *addr;
28 /* int *msgs;
30 /* int anvil_clnt_rcpt(anvil_clnt, service, addr, rcpts)
31 /* ANVIL_CLNT *anvil_clnt;
32 /* const char *service;
33 /* const char *addr;
34 /* int *rcpts;
36 /* int anvil_clnt_newtls(anvil_clnt, service, addr, newtls)
37 /* ANVIL_CLNT *anvil_clnt;
38 /* const char *service;
39 /* const char *addr;
40 /* int *newtls;
42 /* int anvil_clnt_newtls_stat(anvil_clnt, service, addr, newtls)
43 /* ANVIL_CLNT *anvil_clnt;
44 /* const char *service;
45 /* const char *addr;
46 /* int *newtls;
48 /* int anvil_clnt_disconnect(anvil_clnt, service, addr)
49 /* ANVIL_CLNT *anvil_clnt;
50 /* const char *service;
51 /* const char *addr;
53 /* int anvil_clnt_lookup(anvil_clnt, service, addr,
54 /* count, rate, msgs, rcpts)
55 /* ANVIL_CLNT *anvil_clnt;
56 /* const char *service;
57 /* const char *addr;
58 /* int *count;
59 /* int *rate;
60 /* int *msgs;
61 /* int *rcpts;
62 /* DESCRIPTION
63 /* anvil_clnt_create() instantiates a local anvil service
64 /* client endpoint.
66 /* anvil_clnt_connect() informs the anvil server that a
67 /* remote client has connected, and returns the current
68 /* connection count and connection rate for that remote client.
70 /* anvil_clnt_mail() registers a MAIL FROM event and
71 /* returns the current MAIL FROM rate for the specified remote
72 /* client.
74 /* anvil_clnt_rcpt() registers a RCPT TO event and
75 /* returns the current RCPT TO rate for the specified remote
76 /* client.
78 /* anvil_clnt_newtls() registers a remote client request
79 /* to negotiate a new (uncached) TLS session and returns the
80 /* current newtls request rate for the specified remote client.
82 /* anvil_clnt_newtls_stat() returns the current newtls request
83 /* rate for the specified remote client.
85 /* anvil_clnt_disconnect() informs the anvil server that a remote
86 /* client has disconnected.
88 /* anvil_clnt_lookup() returns the current count and rate
89 /* information for the specified client.
91 /* anvil_clnt_free() destroys a local anvil service client
92 /* endpoint.
94 /* Arguments:
95 /* .IP anvil_clnt
96 /* Client rate control service handle.
97 /* .IP service
98 /* The service that the remote client is connected to.
99 /* .IP addr
100 /* Null terminated string that identifies the remote client.
101 /* .IP count
102 /* Pointer to storage for the current number of connections from
103 /* this remote client.
104 /* .IP rate
105 /* Pointer to storage for the current connection rate for this
106 /* remote client.
107 /* .IP msgs
108 /* Pointer to storage for the current message rate for this
109 /* remote client.
110 /* .IP rcpts
111 /* Pointer to storage for the current recipient rate for this
112 /* remote client.
113 /* .IP newtls
114 /* Pointer to storage for the current "new TLS session" rate
115 /* for this remote client.
116 /* DIAGNOSTICS
117 /* The update and status query routines return
118 /* ANVIL_STAT_OK in case of success, ANVIL_STAT_FAIL otherwise
119 /* (either the communication with the server is broken or the
120 /* server experienced a problem).
121 /* SEE ALSO
122 /* anvil(8), connection/rate limiting
123 /* LICENSE
124 /* .ad
125 /* .fi
126 /* The Secure Mailer license must be distributed with this software.
127 /* AUTHOR(S)
128 /* Wietse Venema
129 /* IBM T.J. Watson Research
130 /* P.O. Box 704
131 /* Yorktown Heights, NY 10598, USA
132 /*--*/
134 /* System library. */
136 #include <sys_defs.h>
138 /* Utility library. */
140 #include <mymalloc.h>
141 #include <msg.h>
142 #include <attr_clnt.h>
143 #include <stringops.h>
145 /* Global library. */
147 #include <mail_proto.h>
148 #include <mail_params.h>
149 #include <anvil_clnt.h>
151 /* Application specific. */
153 #define ANVIL_IDENT(service, addr) \
154 printable(concatenate(service, ":", addr, (char *) 0), '?')
156 /* anvil_clnt_create - instantiate connection rate service client */
158 ANVIL_CLNT *anvil_clnt_create(void)
160 ATTR_CLNT *anvil_clnt;
163 * Use whatever IPC is preferred for internal use: UNIX-domain sockets or
164 * Solaris streams.
166 #ifndef VAR_ANVIL_SERVICE
167 anvil_clnt = attr_clnt_create("local:" ANVIL_CLASS "/" ANVIL_SERVICE,
168 var_ipc_timeout, 0, 0);
169 #else
170 anvil_clnt = attr_clnt_create(var_anvil_service, var_ipc_timeout, 0, 0);
171 #endif
172 return ((ANVIL_CLNT *) anvil_clnt);
175 /* anvil_clnt_free - destroy connection rate service client */
177 void anvil_clnt_free(ANVIL_CLNT *anvil_clnt)
179 attr_clnt_free((ATTR_CLNT *) anvil_clnt);
182 /* anvil_clnt_lookup - status query */
184 int anvil_clnt_lookup(ANVIL_CLNT *anvil_clnt, const char *service,
185 const char *addr, int *count, int *rate,
186 int *msgs, int *rcpts, int *newtls)
188 char *ident = ANVIL_IDENT(service, addr);
189 int status;
191 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
192 ATTR_FLAG_NONE, /* Query attributes. */
193 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_LOOKUP,
194 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
195 ATTR_TYPE_END,
196 ATTR_FLAG_MISSING, /* Reply attributes. */
197 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
198 ATTR_TYPE_INT, ANVIL_ATTR_COUNT, count,
199 ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate,
200 ATTR_TYPE_INT, ANVIL_ATTR_MAIL, msgs,
201 ATTR_TYPE_INT, ANVIL_ATTR_RCPT, rcpts,
202 ATTR_TYPE_INT, ANVIL_ATTR_NTLS, newtls,
203 ATTR_TYPE_END) != 6)
204 status = ANVIL_STAT_FAIL;
205 else if (status != ANVIL_STAT_OK)
206 status = ANVIL_STAT_FAIL;
207 myfree(ident);
208 return (status);
211 /* anvil_clnt_connect - heads-up and status query */
213 int anvil_clnt_connect(ANVIL_CLNT *anvil_clnt, const char *service,
214 const char *addr, int *count, int *rate)
216 char *ident = ANVIL_IDENT(service, addr);
217 int status;
219 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
220 ATTR_FLAG_NONE, /* Query attributes. */
221 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_CONN,
222 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
223 ATTR_TYPE_END,
224 ATTR_FLAG_MISSING, /* Reply attributes. */
225 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
226 ATTR_TYPE_INT, ANVIL_ATTR_COUNT, count,
227 ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate,
228 ATTR_TYPE_END) != 3)
229 status = ANVIL_STAT_FAIL;
230 else if (status != ANVIL_STAT_OK)
231 status = ANVIL_STAT_FAIL;
232 myfree(ident);
233 return (status);
236 /* anvil_clnt_mail - heads-up and status query */
238 int anvil_clnt_mail(ANVIL_CLNT *anvil_clnt, const char *service,
239 const char *addr, int *msgs)
241 char *ident = ANVIL_IDENT(service, addr);
242 int status;
244 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
245 ATTR_FLAG_NONE, /* Query attributes. */
246 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_MAIL,
247 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
248 ATTR_TYPE_END,
249 ATTR_FLAG_MISSING, /* Reply attributes. */
250 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
251 ATTR_TYPE_INT, ANVIL_ATTR_RATE, msgs,
252 ATTR_TYPE_END) != 2)
253 status = ANVIL_STAT_FAIL;
254 else if (status != ANVIL_STAT_OK)
255 status = ANVIL_STAT_FAIL;
256 myfree(ident);
257 return (status);
260 /* anvil_clnt_rcpt - heads-up and status query */
262 int anvil_clnt_rcpt(ANVIL_CLNT *anvil_clnt, const char *service,
263 const char *addr, int *rcpts)
265 char *ident = ANVIL_IDENT(service, addr);
266 int status;
268 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
269 ATTR_FLAG_NONE, /* Query attributes. */
270 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_RCPT,
271 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
272 ATTR_TYPE_END,
273 ATTR_FLAG_MISSING, /* Reply attributes. */
274 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
275 ATTR_TYPE_INT, ANVIL_ATTR_RATE, rcpts,
276 ATTR_TYPE_END) != 2)
277 status = ANVIL_STAT_FAIL;
278 else if (status != ANVIL_STAT_OK)
279 status = ANVIL_STAT_FAIL;
280 myfree(ident);
281 return (status);
284 /* anvil_clnt_newtls - heads-up and status query */
286 int anvil_clnt_newtls(ANVIL_CLNT *anvil_clnt, const char *service,
287 const char *addr, int *newtls)
289 char *ident = ANVIL_IDENT(service, addr);
290 int status;
292 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
293 ATTR_FLAG_NONE, /* Query attributes. */
294 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS,
295 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
296 ATTR_TYPE_END,
297 ATTR_FLAG_MISSING, /* Reply attributes. */
298 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
299 ATTR_TYPE_INT, ANVIL_ATTR_RATE, newtls,
300 ATTR_TYPE_END) != 2)
301 status = ANVIL_STAT_FAIL;
302 else if (status != ANVIL_STAT_OK)
303 status = ANVIL_STAT_FAIL;
304 myfree(ident);
305 return (status);
308 /* anvil_clnt_newtls_stat - status query */
310 int anvil_clnt_newtls_stat(ANVIL_CLNT *anvil_clnt, const char *service,
311 const char *addr, int *newtls)
313 char *ident = ANVIL_IDENT(service, addr);
314 int status;
316 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
317 ATTR_FLAG_NONE, /* Query attributes. */
318 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_NTLS_STAT,
319 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
320 ATTR_TYPE_END,
321 ATTR_FLAG_MISSING, /* Reply attributes. */
322 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
323 ATTR_TYPE_INT, ANVIL_ATTR_RATE, newtls,
324 ATTR_TYPE_END) != 2)
325 status = ANVIL_STAT_FAIL;
326 else if (status != ANVIL_STAT_OK)
327 status = ANVIL_STAT_FAIL;
328 myfree(ident);
329 return (status);
332 /* anvil_clnt_disconnect - heads-up only */
334 int anvil_clnt_disconnect(ANVIL_CLNT *anvil_clnt, const char *service,
335 const char *addr)
337 char *ident = ANVIL_IDENT(service, addr);
338 int status;
340 if (attr_clnt_request((ATTR_CLNT *) anvil_clnt,
341 ATTR_FLAG_NONE, /* Query attributes. */
342 ATTR_TYPE_STR, ANVIL_ATTR_REQ, ANVIL_REQ_DISC,
343 ATTR_TYPE_STR, ANVIL_ATTR_IDENT, ident,
344 ATTR_TYPE_END,
345 ATTR_FLAG_MISSING, /* Reply attributes. */
346 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, &status,
347 ATTR_TYPE_END) != 1)
348 status = ANVIL_STAT_FAIL;
349 else if (status != ANVIL_STAT_OK)
350 status = ANVIL_STAT_FAIL;
351 myfree(ident);
352 return (status);
355 #ifdef TEST
358 * Stand-alone client for testing.
360 #include <unistd.h>
361 #include <string.h>
362 #include <msg_vstream.h>
363 #include <mail_conf.h>
364 #include <mail_params.h>
365 #include <vstring_vstream.h>
367 static void usage(void)
369 vstream_printf("usage: "
370 ANVIL_REQ_CONN " service addr | "
371 ANVIL_REQ_DISC " service addr | "
372 ANVIL_REQ_MAIL " service addr | "
373 ANVIL_REQ_RCPT " service addr | "
374 ANVIL_REQ_NTLS " service addr | "
375 ANVIL_REQ_NTLS_STAT " service addr | "
376 ANVIL_REQ_LOOKUP " service addr\n");
379 int main(int unused_argc, char **argv)
381 VSTRING *inbuf = vstring_alloc(1);
382 char *bufp;
383 char *cmd;
384 ssize_t cmd_len;
385 char *service;
386 char *addr;
387 int count;
388 int rate;
389 int msgs;
390 int rcpts;
391 int newtls;
392 ANVIL_CLNT *anvil;
394 msg_vstream_init(argv[0], VSTREAM_ERR);
396 mail_conf_read();
397 msg_info("using config files in %s", var_config_dir);
398 if (chdir(var_queue_dir) < 0)
399 msg_fatal("chdir %s: %m", var_queue_dir);
401 msg_verbose++;
403 anvil = anvil_clnt_create();
405 while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) {
406 bufp = vstring_str(inbuf);
407 if ((cmd = mystrtok(&bufp, " ")) == 0 || *bufp == 0
408 || (service = mystrtok(&bufp, " ")) == 0 || *service == 0
409 || (addr = mystrtok(&bufp, " ")) == 0 || *addr == 0
410 || mystrtok(&bufp, " ") != 0) {
411 vstream_printf("bad command syntax\n");
412 usage();
413 vstream_fflush(VSTREAM_OUT);
414 continue;
416 cmd_len = strlen(cmd);
417 if (strncmp(cmd, ANVIL_REQ_CONN, cmd_len) == 0) {
418 if (anvil_clnt_connect(anvil, service, addr, &count, &rate) != ANVIL_STAT_OK)
419 msg_warn("error!");
420 else
421 vstream_printf("count=%d, rate=%d\n", count, rate);
422 } else if (strncmp(cmd, ANVIL_REQ_MAIL, cmd_len) == 0) {
423 if (anvil_clnt_mail(anvil, service, addr, &msgs) != ANVIL_STAT_OK)
424 msg_warn("error!");
425 else
426 vstream_printf("rate=%d\n", msgs);
427 } else if (strncmp(cmd, ANVIL_REQ_RCPT, cmd_len) == 0) {
428 if (anvil_clnt_rcpt(anvil, service, addr, &rcpts) != ANVIL_STAT_OK)
429 msg_warn("error!");
430 else
431 vstream_printf("rate=%d\n", rcpts);
432 } else if (strncmp(cmd, ANVIL_REQ_NTLS, cmd_len) == 0) {
433 if (anvil_clnt_newtls(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
434 msg_warn("error!");
435 else
436 vstream_printf("rate=%d\n", newtls);
437 } else if (strncmp(cmd, ANVIL_REQ_NTLS_STAT, cmd_len) == 0) {
438 if (anvil_clnt_newtls_stat(anvil, service, addr, &newtls) != ANVIL_STAT_OK)
439 msg_warn("error!");
440 else
441 vstream_printf("rate=%d\n", newtls);
442 } else if (strncmp(cmd, ANVIL_REQ_DISC, cmd_len) == 0) {
443 if (anvil_clnt_disconnect(anvil, service, addr) != ANVIL_STAT_OK)
444 msg_warn("error!");
445 else
446 vstream_printf("OK\n");
447 } else if (strncmp(cmd, ANVIL_REQ_LOOKUP, cmd_len) == 0) {
448 if (anvil_clnt_lookup(anvil, service, addr, &count, &rate,
449 &msgs, &rcpts, &newtls) != ANVIL_STAT_OK)
450 msg_warn("error!");
451 else
452 vstream_printf("count=%d, rate=%d msgs=%d rcpts=%d newtls=%d\n",
453 count, rate, msgs, rcpts, newtls);
454 } else {
455 vstream_printf("bad command: \"%s\"\n", cmd);
456 usage();
458 vstream_fflush(VSTREAM_OUT);
460 vstring_free(inbuf);
461 anvil_clnt_free(anvil);
462 return (0);
465 #endif