17c478bd9Sstevel@tonic-gate /*
2*24472db6Sjbeck * Copyright (c) 1999-2007 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate * All rights reserved.
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set
67c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of
77c478bd9Sstevel@tonic-gate * the sendmail distribution.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate */
107c478bd9Sstevel@tonic-gate
117c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
127c478bd9Sstevel@tonic-gate
137c478bd9Sstevel@tonic-gate #include <sm/gen.h>
14*24472db6Sjbeck SM_RCSID("@(#)$Id: smfi.c,v 8.83 2007/04/23 16:44:39 ca Exp $")
157c478bd9Sstevel@tonic-gate #include <sm/varargs.h>
167c478bd9Sstevel@tonic-gate #include "libmilter.h"
177c478bd9Sstevel@tonic-gate
187c478bd9Sstevel@tonic-gate static int smfi_header __P((SMFICTX *, int, int, char *, char *));
197c478bd9Sstevel@tonic-gate static int myisenhsc __P((const char *, int));
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate /* for smfi_set{ml}reply, let's be generous. 256/16 should be sufficient */
227c478bd9Sstevel@tonic-gate #define MAXREPLYLEN 980 /* max. length of a reply string */
237c478bd9Sstevel@tonic-gate #define MAXREPLIES 32 /* max. number of reply strings */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate ** SMFI_HEADER -- send a header to the MTA
277c478bd9Sstevel@tonic-gate **
287c478bd9Sstevel@tonic-gate ** Parameters:
297c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
307c478bd9Sstevel@tonic-gate ** cmd -- Header modification command
317c478bd9Sstevel@tonic-gate ** hdridx -- Header index
327c478bd9Sstevel@tonic-gate ** headerf -- Header field name
337c478bd9Sstevel@tonic-gate ** headerv -- Header field value
347c478bd9Sstevel@tonic-gate **
357c478bd9Sstevel@tonic-gate ** Returns:
367c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate static int
smfi_header(ctx,cmd,hdridx,headerf,headerv)407c478bd9Sstevel@tonic-gate smfi_header(ctx, cmd, hdridx, headerf, headerv)
417c478bd9Sstevel@tonic-gate SMFICTX *ctx;
427c478bd9Sstevel@tonic-gate int cmd;
437c478bd9Sstevel@tonic-gate int hdridx;
447c478bd9Sstevel@tonic-gate char *headerf;
457c478bd9Sstevel@tonic-gate char *headerv;
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate size_t len, l1, l2, offset;
487c478bd9Sstevel@tonic-gate int r;
497c478bd9Sstevel@tonic-gate mi_int32 v;
507c478bd9Sstevel@tonic-gate char *buf;
517c478bd9Sstevel@tonic-gate struct timeval timeout;
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate if (headerf == NULL || *headerf == '\0' || headerv == NULL)
547c478bd9Sstevel@tonic-gate return MI_FAILURE;
557c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
567c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
577c478bd9Sstevel@tonic-gate l1 = strlen(headerf) + 1;
587c478bd9Sstevel@tonic-gate l2 = strlen(headerv) + 1;
597c478bd9Sstevel@tonic-gate len = l1 + l2;
607c478bd9Sstevel@tonic-gate if (hdridx >= 0)
617c478bd9Sstevel@tonic-gate len += MILTER_LEN_BYTES;
627c478bd9Sstevel@tonic-gate buf = malloc(len);
637c478bd9Sstevel@tonic-gate if (buf == NULL)
647c478bd9Sstevel@tonic-gate return MI_FAILURE;
657c478bd9Sstevel@tonic-gate offset = 0;
667c478bd9Sstevel@tonic-gate if (hdridx >= 0)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate v = htonl(hdridx);
697c478bd9Sstevel@tonic-gate (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES);
707c478bd9Sstevel@tonic-gate offset += MILTER_LEN_BYTES;
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate (void) memcpy(buf + offset, headerf, l1);
737c478bd9Sstevel@tonic-gate (void) memcpy(buf + offset + l1, headerv, l2);
747c478bd9Sstevel@tonic-gate r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
757c478bd9Sstevel@tonic-gate free(buf);
767c478bd9Sstevel@tonic-gate return r;
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate ** SMFI_ADDHEADER -- send a new header to the MTA
817c478bd9Sstevel@tonic-gate **
827c478bd9Sstevel@tonic-gate ** Parameters:
837c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
847c478bd9Sstevel@tonic-gate ** headerf -- Header field name
857c478bd9Sstevel@tonic-gate ** headerv -- Header field value
867c478bd9Sstevel@tonic-gate **
877c478bd9Sstevel@tonic-gate ** Returns:
887c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
897c478bd9Sstevel@tonic-gate */
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate int
smfi_addheader(ctx,headerf,headerv)927c478bd9Sstevel@tonic-gate smfi_addheader(ctx, headerf, headerv)
937c478bd9Sstevel@tonic-gate SMFICTX *ctx;
947c478bd9Sstevel@tonic-gate char *headerf;
957c478bd9Sstevel@tonic-gate char *headerv;
967c478bd9Sstevel@tonic-gate {
977c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_ADDHDRS))
987c478bd9Sstevel@tonic-gate return MI_FAILURE;
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate return smfi_header(ctx, SMFIR_ADDHEADER, -1, headerf, headerv);
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate /*
1047c478bd9Sstevel@tonic-gate ** SMFI_INSHEADER -- send a new header to the MTA (to be inserted)
1057c478bd9Sstevel@tonic-gate **
1067c478bd9Sstevel@tonic-gate ** Parameters:
1077c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
1087c478bd9Sstevel@tonic-gate ** hdridx -- index into header list where insertion should occur
1097c478bd9Sstevel@tonic-gate ** headerf -- Header field name
1107c478bd9Sstevel@tonic-gate ** headerv -- Header field value
1117c478bd9Sstevel@tonic-gate **
1127c478bd9Sstevel@tonic-gate ** Returns:
1137c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
1147c478bd9Sstevel@tonic-gate */
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate int
smfi_insheader(ctx,hdridx,headerf,headerv)1177c478bd9Sstevel@tonic-gate smfi_insheader(ctx, hdridx, headerf, headerv)
1187c478bd9Sstevel@tonic-gate SMFICTX *ctx;
1197c478bd9Sstevel@tonic-gate int hdridx;
1207c478bd9Sstevel@tonic-gate char *headerf;
1217c478bd9Sstevel@tonic-gate char *headerv;
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_ADDHDRS) || hdridx < 0)
1247c478bd9Sstevel@tonic-gate return MI_FAILURE;
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate return smfi_header(ctx, SMFIR_INSHEADER, hdridx, headerf, headerv);
1277c478bd9Sstevel@tonic-gate }
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate ** SMFI_CHGHEADER -- send a changed header to the MTA
1317c478bd9Sstevel@tonic-gate **
1327c478bd9Sstevel@tonic-gate ** Parameters:
1337c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
1347c478bd9Sstevel@tonic-gate ** headerf -- Header field name
1357c478bd9Sstevel@tonic-gate ** hdridx -- Header index value
1367c478bd9Sstevel@tonic-gate ** headerv -- Header field value
1377c478bd9Sstevel@tonic-gate **
1387c478bd9Sstevel@tonic-gate ** Returns:
1397c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
1407c478bd9Sstevel@tonic-gate */
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate int
smfi_chgheader(ctx,headerf,hdridx,headerv)1437c478bd9Sstevel@tonic-gate smfi_chgheader(ctx, headerf, hdridx, headerv)
1447c478bd9Sstevel@tonic-gate SMFICTX *ctx;
1457c478bd9Sstevel@tonic-gate char *headerf;
1467c478bd9Sstevel@tonic-gate mi_int32 hdridx;
1477c478bd9Sstevel@tonic-gate char *headerv;
1487c478bd9Sstevel@tonic-gate {
1497c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_CHGHDRS) || hdridx < 0)
1507c478bd9Sstevel@tonic-gate return MI_FAILURE;
1517c478bd9Sstevel@tonic-gate if (headerv == NULL)
1527c478bd9Sstevel@tonic-gate headerv = "";
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate return smfi_header(ctx, SMFIR_CHGHEADER, hdridx, headerf, headerv);
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate
157058561cbSjbeck #if 0
158058561cbSjbeck /*
159058561cbSjbeck ** BUF_CRT_SEND -- construct buffer to send from arguments
160058561cbSjbeck **
161058561cbSjbeck ** Parameters:
162058561cbSjbeck ** ctx -- Opaque context structure
163058561cbSjbeck ** cmd -- command
164058561cbSjbeck ** arg0 -- first argument
165058561cbSjbeck ** argv -- list of arguments (NULL terminated)
166058561cbSjbeck **
167058561cbSjbeck ** Returns:
168058561cbSjbeck ** MI_SUCCESS/MI_FAILURE
169058561cbSjbeck */
170058561cbSjbeck
171058561cbSjbeck static int
172058561cbSjbeck buf_crt_send __P((SMFICTX *, int cmd, char *, char **));
173058561cbSjbeck
174058561cbSjbeck static int
175058561cbSjbeck buf_crt_send(ctx, cmd, arg0, argv)
176058561cbSjbeck SMFICTX *ctx;
177058561cbSjbeck int cmd;
178058561cbSjbeck char *arg0;
179058561cbSjbeck char **argv;
180058561cbSjbeck {
181058561cbSjbeck size_t len, l0, l1, offset;
182058561cbSjbeck int r;
183058561cbSjbeck char *buf, *arg, **argvl;
184058561cbSjbeck struct timeval timeout;
185058561cbSjbeck
186058561cbSjbeck if (arg0 == NULL || *arg0 == '\0')
187058561cbSjbeck return MI_FAILURE;
188058561cbSjbeck timeout.tv_sec = ctx->ctx_timeout;
189058561cbSjbeck timeout.tv_usec = 0;
190058561cbSjbeck l0 = strlen(arg0) + 1;
191058561cbSjbeck len = l0;
192058561cbSjbeck argvl = argv;
193058561cbSjbeck while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
194058561cbSjbeck {
195058561cbSjbeck l1 = strlen(arg) + 1;
196058561cbSjbeck len += l1;
197058561cbSjbeck SM_ASSERT(len > l1);
198058561cbSjbeck }
199058561cbSjbeck
200058561cbSjbeck buf = malloc(len);
201058561cbSjbeck if (buf == NULL)
202058561cbSjbeck return MI_FAILURE;
203058561cbSjbeck (void) memcpy(buf, arg0, l0);
204058561cbSjbeck offset = l0;
205058561cbSjbeck
206058561cbSjbeck argvl = argv;
207058561cbSjbeck while (argvl != NULL && (arg = *argv) != NULL && *arg != '\0')
208058561cbSjbeck {
209058561cbSjbeck l1 = strlen(arg) + 1;
210058561cbSjbeck SM_ASSERT(offset < len);
211058561cbSjbeck SM_ASSERT(offset + l1 <= len);
212058561cbSjbeck (void) memcpy(buf + offset, arg, l1);
213058561cbSjbeck offset += l1;
214058561cbSjbeck SM_ASSERT(offset > l1);
215058561cbSjbeck }
216058561cbSjbeck
217058561cbSjbeck r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
218058561cbSjbeck free(buf);
219058561cbSjbeck return r;
220058561cbSjbeck }
221058561cbSjbeck #endif /* 0 */
222058561cbSjbeck
223058561cbSjbeck /*
224058561cbSjbeck ** SEND2 -- construct buffer to send from arguments
225058561cbSjbeck **
226058561cbSjbeck ** Parameters:
227058561cbSjbeck ** ctx -- Opaque context structure
228058561cbSjbeck ** cmd -- command
229058561cbSjbeck ** arg0 -- first argument
230058561cbSjbeck ** argv -- list of arguments (NULL terminated)
231058561cbSjbeck **
232058561cbSjbeck ** Returns:
233058561cbSjbeck ** MI_SUCCESS/MI_FAILURE
234058561cbSjbeck */
235058561cbSjbeck
236058561cbSjbeck static int
237058561cbSjbeck send2 __P((SMFICTX *, int cmd, char *, char *));
238058561cbSjbeck
239058561cbSjbeck static int
send2(ctx,cmd,arg0,arg1)240058561cbSjbeck send2(ctx, cmd, arg0, arg1)
241058561cbSjbeck SMFICTX *ctx;
242058561cbSjbeck int cmd;
243058561cbSjbeck char *arg0;
244058561cbSjbeck char *arg1;
245058561cbSjbeck {
246058561cbSjbeck size_t len, l0, l1, offset;
247058561cbSjbeck int r;
248058561cbSjbeck char *buf;
249058561cbSjbeck struct timeval timeout;
250058561cbSjbeck
251058561cbSjbeck if (arg0 == NULL || *arg0 == '\0')
252058561cbSjbeck return MI_FAILURE;
253058561cbSjbeck timeout.tv_sec = ctx->ctx_timeout;
254058561cbSjbeck timeout.tv_usec = 0;
255058561cbSjbeck l0 = strlen(arg0) + 1;
256058561cbSjbeck len = l0;
257058561cbSjbeck if (arg1 != NULL)
258058561cbSjbeck {
259058561cbSjbeck l1 = strlen(arg1) + 1;
260058561cbSjbeck len += l1;
261058561cbSjbeck SM_ASSERT(len > l1);
262058561cbSjbeck }
263058561cbSjbeck
264058561cbSjbeck buf = malloc(len);
265058561cbSjbeck if (buf == NULL)
266058561cbSjbeck return MI_FAILURE;
267058561cbSjbeck (void) memcpy(buf, arg0, l0);
268058561cbSjbeck offset = l0;
269058561cbSjbeck
270058561cbSjbeck if (arg1 != NULL)
271058561cbSjbeck {
272058561cbSjbeck l1 = strlen(arg1) + 1;
273058561cbSjbeck SM_ASSERT(offset < len);
274058561cbSjbeck SM_ASSERT(offset + l1 <= len);
275058561cbSjbeck (void) memcpy(buf + offset, arg1, l1);
276058561cbSjbeck offset += l1;
277058561cbSjbeck SM_ASSERT(offset > l1);
278058561cbSjbeck }
279058561cbSjbeck
280058561cbSjbeck r = mi_wr_cmd(ctx->ctx_sd, &timeout, cmd, buf, len);
281058561cbSjbeck free(buf);
282058561cbSjbeck return r;
283058561cbSjbeck }
284058561cbSjbeck
285058561cbSjbeck /*
286058561cbSjbeck ** SMFI_CHGFROM -- change enveloper sender ("from") address
287058561cbSjbeck **
288058561cbSjbeck ** Parameters:
289058561cbSjbeck ** ctx -- Opaque context structure
290058561cbSjbeck ** from -- new envelope sender address ("MAIL From")
291058561cbSjbeck ** args -- ESMTP arguments
292058561cbSjbeck **
293058561cbSjbeck ** Returns:
294058561cbSjbeck ** MI_SUCCESS/MI_FAILURE
295058561cbSjbeck */
296058561cbSjbeck
297058561cbSjbeck int
smfi_chgfrom(ctx,from,args)298058561cbSjbeck smfi_chgfrom(ctx, from, args)
299058561cbSjbeck SMFICTX *ctx;
300058561cbSjbeck char *from;
301058561cbSjbeck char *args;
302058561cbSjbeck {
303058561cbSjbeck if (from == NULL || *from == '\0')
304058561cbSjbeck return MI_FAILURE;
305058561cbSjbeck if (!mi_sendok(ctx, SMFIF_CHGFROM))
306058561cbSjbeck return MI_FAILURE;
307058561cbSjbeck return send2(ctx, SMFIR_CHGFROM, from, args);
308058561cbSjbeck }
309058561cbSjbeck
310058561cbSjbeck /*
311058561cbSjbeck ** SMFI_SETSYMLIST -- set list of macros that the MTA should send.
312058561cbSjbeck **
313058561cbSjbeck ** Parameters:
314058561cbSjbeck ** ctx -- Opaque context structure
315058561cbSjbeck ** where -- SMTP stage
316058561cbSjbeck ** macros -- list of macros
317058561cbSjbeck **
318058561cbSjbeck ** Returns:
319058561cbSjbeck ** MI_SUCCESS/MI_FAILURE
320058561cbSjbeck */
321058561cbSjbeck
322058561cbSjbeck int
smfi_setsymlist(ctx,where,macros)323058561cbSjbeck smfi_setsymlist(ctx, where, macros)
324058561cbSjbeck SMFICTX *ctx;
325058561cbSjbeck int where;
326058561cbSjbeck char *macros;
327058561cbSjbeck {
328058561cbSjbeck SM_ASSERT(ctx != NULL);
329058561cbSjbeck
330058561cbSjbeck if (macros == NULL || *macros == '\0')
331058561cbSjbeck return MI_FAILURE;
332058561cbSjbeck if (where < SMFIM_FIRST || where > SMFIM_LAST)
333058561cbSjbeck return MI_FAILURE;
334058561cbSjbeck if (where < 0 || where >= MAX_MACROS_ENTRIES)
335058561cbSjbeck return MI_FAILURE;
336058561cbSjbeck
337058561cbSjbeck if (ctx->ctx_mac_list[where] != NULL)
338058561cbSjbeck return MI_FAILURE;
339058561cbSjbeck
340058561cbSjbeck ctx->ctx_mac_list[where] = strdup(macros);
341058561cbSjbeck if (ctx->ctx_mac_list[where] == NULL)
342058561cbSjbeck return MI_FAILURE;
343058561cbSjbeck
344058561cbSjbeck return MI_SUCCESS;
345058561cbSjbeck }
346058561cbSjbeck
347058561cbSjbeck /*
348058561cbSjbeck ** SMFI_ADDRCPT_PAR -- send an additional recipient to the MTA
349058561cbSjbeck **
350058561cbSjbeck ** Parameters:
351058561cbSjbeck ** ctx -- Opaque context structure
352058561cbSjbeck ** rcpt -- recipient address
353058561cbSjbeck ** args -- ESMTP arguments
354058561cbSjbeck **
355058561cbSjbeck ** Returns:
356058561cbSjbeck ** MI_SUCCESS/MI_FAILURE
357058561cbSjbeck */
358058561cbSjbeck
359058561cbSjbeck int
smfi_addrcpt_par(ctx,rcpt,args)360058561cbSjbeck smfi_addrcpt_par(ctx, rcpt, args)
361058561cbSjbeck SMFICTX *ctx;
362058561cbSjbeck char *rcpt;
363058561cbSjbeck char *args;
364058561cbSjbeck {
365058561cbSjbeck if (rcpt == NULL || *rcpt == '\0')
366058561cbSjbeck return MI_FAILURE;
367058561cbSjbeck if (!mi_sendok(ctx, SMFIF_ADDRCPT_PAR))
368058561cbSjbeck return MI_FAILURE;
369058561cbSjbeck return send2(ctx, SMFIR_ADDRCPT_PAR, rcpt, args);
370058561cbSjbeck }
371058561cbSjbeck
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate ** SMFI_ADDRCPT -- send an additional recipient to the MTA
3747c478bd9Sstevel@tonic-gate **
3757c478bd9Sstevel@tonic-gate ** Parameters:
3767c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
3777c478bd9Sstevel@tonic-gate ** rcpt -- recipient address
3787c478bd9Sstevel@tonic-gate **
3797c478bd9Sstevel@tonic-gate ** Returns:
3807c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
3817c478bd9Sstevel@tonic-gate */
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate int
smfi_addrcpt(ctx,rcpt)3847c478bd9Sstevel@tonic-gate smfi_addrcpt(ctx, rcpt)
3857c478bd9Sstevel@tonic-gate SMFICTX *ctx;
3867c478bd9Sstevel@tonic-gate char *rcpt;
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate size_t len;
3897c478bd9Sstevel@tonic-gate struct timeval timeout;
3907c478bd9Sstevel@tonic-gate
3917c478bd9Sstevel@tonic-gate if (rcpt == NULL || *rcpt == '\0')
3927c478bd9Sstevel@tonic-gate return MI_FAILURE;
3937c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_ADDRCPT))
3947c478bd9Sstevel@tonic-gate return MI_FAILURE;
3957c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
3967c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
3977c478bd9Sstevel@tonic-gate len = strlen(rcpt) + 1;
3987c478bd9Sstevel@tonic-gate return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDRCPT, rcpt, len);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate /*
4027c478bd9Sstevel@tonic-gate ** SMFI_DELRCPT -- send a recipient to be removed to the MTA
4037c478bd9Sstevel@tonic-gate **
4047c478bd9Sstevel@tonic-gate ** Parameters:
4057c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
4067c478bd9Sstevel@tonic-gate ** rcpt -- recipient address
4077c478bd9Sstevel@tonic-gate **
4087c478bd9Sstevel@tonic-gate ** Returns:
4097c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
4107c478bd9Sstevel@tonic-gate */
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate int
smfi_delrcpt(ctx,rcpt)4137c478bd9Sstevel@tonic-gate smfi_delrcpt(ctx, rcpt)
4147c478bd9Sstevel@tonic-gate SMFICTX *ctx;
4157c478bd9Sstevel@tonic-gate char *rcpt;
4167c478bd9Sstevel@tonic-gate {
4177c478bd9Sstevel@tonic-gate size_t len;
4187c478bd9Sstevel@tonic-gate struct timeval timeout;
4197c478bd9Sstevel@tonic-gate
4207c478bd9Sstevel@tonic-gate if (rcpt == NULL || *rcpt == '\0')
4217c478bd9Sstevel@tonic-gate return MI_FAILURE;
4227c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_DELRCPT))
4237c478bd9Sstevel@tonic-gate return MI_FAILURE;
4247c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
4257c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
4267c478bd9Sstevel@tonic-gate len = strlen(rcpt) + 1;
4277c478bd9Sstevel@tonic-gate return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_DELRCPT, rcpt, len);
4287c478bd9Sstevel@tonic-gate }
4297c478bd9Sstevel@tonic-gate
4307c478bd9Sstevel@tonic-gate /*
4317c478bd9Sstevel@tonic-gate ** SMFI_REPLACEBODY -- send a body chunk to the MTA
4327c478bd9Sstevel@tonic-gate **
4337c478bd9Sstevel@tonic-gate ** Parameters:
4347c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
4357c478bd9Sstevel@tonic-gate ** bodyp -- body chunk
4367c478bd9Sstevel@tonic-gate ** bodylen -- length of body chunk
4377c478bd9Sstevel@tonic-gate **
4387c478bd9Sstevel@tonic-gate ** Returns:
4397c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
4407c478bd9Sstevel@tonic-gate */
4417c478bd9Sstevel@tonic-gate
4427c478bd9Sstevel@tonic-gate int
smfi_replacebody(ctx,bodyp,bodylen)4437c478bd9Sstevel@tonic-gate smfi_replacebody(ctx, bodyp, bodylen)
4447c478bd9Sstevel@tonic-gate SMFICTX *ctx;
4457c478bd9Sstevel@tonic-gate unsigned char *bodyp;
4467c478bd9Sstevel@tonic-gate int bodylen;
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate int len, off, r;
4497c478bd9Sstevel@tonic-gate struct timeval timeout;
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate if (bodylen < 0 ||
4527c478bd9Sstevel@tonic-gate (bodyp == NULL && bodylen > 0))
4537c478bd9Sstevel@tonic-gate return MI_FAILURE;
4547c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_CHGBODY))
4557c478bd9Sstevel@tonic-gate return MI_FAILURE;
4567c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
4577c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
4587c478bd9Sstevel@tonic-gate
4597c478bd9Sstevel@tonic-gate /* split body chunk if necessary */
4607c478bd9Sstevel@tonic-gate off = 0;
46149218d4fSjbeck do
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate len = (bodylen >= MILTER_CHUNK_SIZE) ? MILTER_CHUNK_SIZE :
4647c478bd9Sstevel@tonic-gate bodylen;
4657c478bd9Sstevel@tonic-gate if ((r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_REPLBODY,
4667c478bd9Sstevel@tonic-gate (char *) (bodyp + off), len)) != MI_SUCCESS)
4677c478bd9Sstevel@tonic-gate return r;
4687c478bd9Sstevel@tonic-gate off += len;
4697c478bd9Sstevel@tonic-gate bodylen -= len;
47049218d4fSjbeck } while (bodylen > 0);
4717c478bd9Sstevel@tonic-gate return MI_SUCCESS;
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate /*
4757c478bd9Sstevel@tonic-gate ** SMFI_QUARANTINE -- quarantine an envelope
4767c478bd9Sstevel@tonic-gate **
4777c478bd9Sstevel@tonic-gate ** Parameters:
4787c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
4797c478bd9Sstevel@tonic-gate ** reason -- why?
4807c478bd9Sstevel@tonic-gate **
4817c478bd9Sstevel@tonic-gate ** Returns:
4827c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
4837c478bd9Sstevel@tonic-gate */
4847c478bd9Sstevel@tonic-gate
4857c478bd9Sstevel@tonic-gate int
smfi_quarantine(ctx,reason)4867c478bd9Sstevel@tonic-gate smfi_quarantine(ctx, reason)
4877c478bd9Sstevel@tonic-gate SMFICTX *ctx;
4887c478bd9Sstevel@tonic-gate char *reason;
4897c478bd9Sstevel@tonic-gate {
4907c478bd9Sstevel@tonic-gate size_t len;
4917c478bd9Sstevel@tonic-gate int r;
4927c478bd9Sstevel@tonic-gate char *buf;
4937c478bd9Sstevel@tonic-gate struct timeval timeout;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate if (reason == NULL || *reason == '\0')
4967c478bd9Sstevel@tonic-gate return MI_FAILURE;
4977c478bd9Sstevel@tonic-gate if (!mi_sendok(ctx, SMFIF_QUARANTINE))
4987c478bd9Sstevel@tonic-gate return MI_FAILURE;
4997c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
5007c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
5017c478bd9Sstevel@tonic-gate len = strlen(reason) + 1;
5027c478bd9Sstevel@tonic-gate buf = malloc(len);
5037c478bd9Sstevel@tonic-gate if (buf == NULL)
5047c478bd9Sstevel@tonic-gate return MI_FAILURE;
5057c478bd9Sstevel@tonic-gate (void) memcpy(buf, reason, len);
5067c478bd9Sstevel@tonic-gate r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_QUARANTINE, buf, len);
5077c478bd9Sstevel@tonic-gate free(buf);
5087c478bd9Sstevel@tonic-gate return r;
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate /*
5127c478bd9Sstevel@tonic-gate ** MYISENHSC -- check whether a string contains an enhanced status code
5137c478bd9Sstevel@tonic-gate **
5147c478bd9Sstevel@tonic-gate ** Parameters:
5157c478bd9Sstevel@tonic-gate ** s -- string with possible enhanced status code.
5167c478bd9Sstevel@tonic-gate ** delim -- delim for enhanced status code.
5177c478bd9Sstevel@tonic-gate **
5187c478bd9Sstevel@tonic-gate ** Returns:
5197c478bd9Sstevel@tonic-gate ** 0 -- no enhanced status code.
5207c478bd9Sstevel@tonic-gate ** >4 -- length of enhanced status code.
5217c478bd9Sstevel@tonic-gate **
5227c478bd9Sstevel@tonic-gate ** Side Effects:
5237c478bd9Sstevel@tonic-gate ** none.
5247c478bd9Sstevel@tonic-gate */
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate static int
myisenhsc(s,delim)5277c478bd9Sstevel@tonic-gate myisenhsc(s, delim)
5287c478bd9Sstevel@tonic-gate const char *s;
5297c478bd9Sstevel@tonic-gate int delim;
5307c478bd9Sstevel@tonic-gate {
5317c478bd9Sstevel@tonic-gate int l, h;
5327c478bd9Sstevel@tonic-gate
5337c478bd9Sstevel@tonic-gate if (s == NULL)
5347c478bd9Sstevel@tonic-gate return 0;
5357c478bd9Sstevel@tonic-gate if (!((*s == '2' || *s == '4' || *s == '5') && s[1] == '.'))
5367c478bd9Sstevel@tonic-gate return 0;
5377c478bd9Sstevel@tonic-gate h = 0;
5387c478bd9Sstevel@tonic-gate l = 2;
5397c478bd9Sstevel@tonic-gate while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
5407c478bd9Sstevel@tonic-gate ++h;
5417c478bd9Sstevel@tonic-gate if (h == 0 || s[l + h] != '.')
5427c478bd9Sstevel@tonic-gate return 0;
5437c478bd9Sstevel@tonic-gate l += h + 1;
5447c478bd9Sstevel@tonic-gate h = 0;
5457c478bd9Sstevel@tonic-gate while (h < 3 && isascii(s[l + h]) && isdigit(s[l + h]))
5467c478bd9Sstevel@tonic-gate ++h;
5477c478bd9Sstevel@tonic-gate if (h == 0 || s[l + h] != delim)
5487c478bd9Sstevel@tonic-gate return 0;
5497c478bd9Sstevel@tonic-gate return l + h;
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate ** SMFI_SETREPLY -- set the reply code for the next reply to the MTA
5547c478bd9Sstevel@tonic-gate **
5557c478bd9Sstevel@tonic-gate ** Parameters:
5567c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
5577c478bd9Sstevel@tonic-gate ** rcode -- The three-digit (RFC 821) SMTP reply code.
5587c478bd9Sstevel@tonic-gate ** xcode -- The extended (RFC 2034) reply code.
5597c478bd9Sstevel@tonic-gate ** message -- The text part of the SMTP reply.
5607c478bd9Sstevel@tonic-gate **
5617c478bd9Sstevel@tonic-gate ** Returns:
5627c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
5637c478bd9Sstevel@tonic-gate */
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate int
smfi_setreply(ctx,rcode,xcode,message)5667c478bd9Sstevel@tonic-gate smfi_setreply(ctx, rcode, xcode, message)
5677c478bd9Sstevel@tonic-gate SMFICTX *ctx;
5687c478bd9Sstevel@tonic-gate char *rcode;
5697c478bd9Sstevel@tonic-gate char *xcode;
5707c478bd9Sstevel@tonic-gate char *message;
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate size_t len;
5737c478bd9Sstevel@tonic-gate char *buf;
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate if (rcode == NULL || ctx == NULL)
5767c478bd9Sstevel@tonic-gate return MI_FAILURE;
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate /* ### <sp> \0 */
5797c478bd9Sstevel@tonic-gate len = strlen(rcode) + 2;
5807c478bd9Sstevel@tonic-gate if (len != 5)
5817c478bd9Sstevel@tonic-gate return MI_FAILURE;
5827c478bd9Sstevel@tonic-gate if ((rcode[0] != '4' && rcode[0] != '5') ||
5837c478bd9Sstevel@tonic-gate !isascii(rcode[1]) || !isdigit(rcode[1]) ||
5847c478bd9Sstevel@tonic-gate !isascii(rcode[2]) || !isdigit(rcode[2]))
5857c478bd9Sstevel@tonic-gate return MI_FAILURE;
5867c478bd9Sstevel@tonic-gate if (xcode != NULL)
5877c478bd9Sstevel@tonic-gate {
5887c478bd9Sstevel@tonic-gate if (!myisenhsc(xcode, '\0'))
5897c478bd9Sstevel@tonic-gate return MI_FAILURE;
5907c478bd9Sstevel@tonic-gate len += strlen(xcode) + 1;
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate if (message != NULL)
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate size_t ml;
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /* XXX check also for unprintable chars? */
5977c478bd9Sstevel@tonic-gate if (strpbrk(message, "\r\n") != NULL)
5987c478bd9Sstevel@tonic-gate return MI_FAILURE;
5997c478bd9Sstevel@tonic-gate ml = strlen(message);
6007c478bd9Sstevel@tonic-gate if (ml > MAXREPLYLEN)
6017c478bd9Sstevel@tonic-gate return MI_FAILURE;
6027c478bd9Sstevel@tonic-gate len += ml + 1;
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate buf = malloc(len);
6057c478bd9Sstevel@tonic-gate if (buf == NULL)
6067c478bd9Sstevel@tonic-gate return MI_FAILURE; /* oops */
6077c478bd9Sstevel@tonic-gate (void) sm_strlcpy(buf, rcode, len);
6087c478bd9Sstevel@tonic-gate (void) sm_strlcat(buf, " ", len);
6097c478bd9Sstevel@tonic-gate if (xcode != NULL)
6107c478bd9Sstevel@tonic-gate (void) sm_strlcat(buf, xcode, len);
6117c478bd9Sstevel@tonic-gate if (message != NULL)
6127c478bd9Sstevel@tonic-gate {
6137c478bd9Sstevel@tonic-gate if (xcode != NULL)
6147c478bd9Sstevel@tonic-gate (void) sm_strlcat(buf, " ", len);
6157c478bd9Sstevel@tonic-gate (void) sm_strlcat(buf, message, len);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate if (ctx->ctx_reply != NULL)
6187c478bd9Sstevel@tonic-gate free(ctx->ctx_reply);
6197c478bd9Sstevel@tonic-gate ctx->ctx_reply = buf;
6207c478bd9Sstevel@tonic-gate return MI_SUCCESS;
6217c478bd9Sstevel@tonic-gate }
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate /*
6247c478bd9Sstevel@tonic-gate ** SMFI_SETMLREPLY -- set multiline reply code for the next reply to the MTA
6257c478bd9Sstevel@tonic-gate **
6267c478bd9Sstevel@tonic-gate ** Parameters:
6277c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
6287c478bd9Sstevel@tonic-gate ** rcode -- The three-digit (RFC 821) SMTP reply code.
6297c478bd9Sstevel@tonic-gate ** xcode -- The extended (RFC 2034) reply code.
6307c478bd9Sstevel@tonic-gate ** txt, ... -- The text part of the SMTP reply,
6317c478bd9Sstevel@tonic-gate ** MUST be terminated with NULL.
6327c478bd9Sstevel@tonic-gate **
6337c478bd9Sstevel@tonic-gate ** Returns:
6347c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
6357c478bd9Sstevel@tonic-gate */
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate int
6387c478bd9Sstevel@tonic-gate #if SM_VA_STD
smfi_setmlreply(SMFICTX * ctx,const char * rcode,const char * xcode,...)6397c478bd9Sstevel@tonic-gate smfi_setmlreply(SMFICTX *ctx, const char *rcode, const char *xcode, ...)
6407c478bd9Sstevel@tonic-gate #else /* SM_VA_STD */
6417c478bd9Sstevel@tonic-gate smfi_setmlreply(ctx, rcode, xcode, va_alist)
6427c478bd9Sstevel@tonic-gate SMFICTX *ctx;
6437c478bd9Sstevel@tonic-gate const char *rcode;
6447c478bd9Sstevel@tonic-gate const char *xcode;
6457c478bd9Sstevel@tonic-gate va_dcl
6467c478bd9Sstevel@tonic-gate #endif /* SM_VA_STD */
6477c478bd9Sstevel@tonic-gate {
6487c478bd9Sstevel@tonic-gate size_t len;
6497c478bd9Sstevel@tonic-gate size_t rlen;
6507c478bd9Sstevel@tonic-gate int args;
6517c478bd9Sstevel@tonic-gate char *buf, *txt;
6527c478bd9Sstevel@tonic-gate const char *xc;
6537c478bd9Sstevel@tonic-gate char repl[16];
6547c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate if (rcode == NULL || ctx == NULL)
6577c478bd9Sstevel@tonic-gate return MI_FAILURE;
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate /* ### <sp> */
6607c478bd9Sstevel@tonic-gate len = strlen(rcode) + 1;
6617c478bd9Sstevel@tonic-gate if (len != 4)
6627c478bd9Sstevel@tonic-gate return MI_FAILURE;
6637c478bd9Sstevel@tonic-gate if ((rcode[0] != '4' && rcode[0] != '5') ||
6647c478bd9Sstevel@tonic-gate !isascii(rcode[1]) || !isdigit(rcode[1]) ||
6657c478bd9Sstevel@tonic-gate !isascii(rcode[2]) || !isdigit(rcode[2]))
6667c478bd9Sstevel@tonic-gate return MI_FAILURE;
6677c478bd9Sstevel@tonic-gate if (xcode != NULL)
6687c478bd9Sstevel@tonic-gate {
6697c478bd9Sstevel@tonic-gate if (!myisenhsc(xcode, '\0'))
6707c478bd9Sstevel@tonic-gate return MI_FAILURE;
6717c478bd9Sstevel@tonic-gate xc = xcode;
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate else
6747c478bd9Sstevel@tonic-gate {
6757c478bd9Sstevel@tonic-gate if (rcode[0] == '4')
6767c478bd9Sstevel@tonic-gate xc = "4.0.0";
6777c478bd9Sstevel@tonic-gate else
6787c478bd9Sstevel@tonic-gate xc = "5.0.0";
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate /* add trailing space */
6827c478bd9Sstevel@tonic-gate len += strlen(xc) + 1;
6837c478bd9Sstevel@tonic-gate rlen = len;
6847c478bd9Sstevel@tonic-gate args = 0;
6857c478bd9Sstevel@tonic-gate SM_VA_START(ap, xcode);
6867c478bd9Sstevel@tonic-gate while ((txt = SM_VA_ARG(ap, char *)) != NULL)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate size_t tl;
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate tl = strlen(txt);
6917c478bd9Sstevel@tonic-gate if (tl > MAXREPLYLEN)
6927c478bd9Sstevel@tonic-gate break;
6937c478bd9Sstevel@tonic-gate
6947c478bd9Sstevel@tonic-gate /* this text, reply codes, \r\n */
6957c478bd9Sstevel@tonic-gate len += tl + 2 + rlen;
6967c478bd9Sstevel@tonic-gate if (++args > MAXREPLIES)
6977c478bd9Sstevel@tonic-gate break;
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate /* XXX check also for unprintable chars? */
7007c478bd9Sstevel@tonic-gate if (strpbrk(txt, "\r\n") != NULL)
7017c478bd9Sstevel@tonic-gate break;
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate SM_VA_END(ap);
7047c478bd9Sstevel@tonic-gate if (txt != NULL)
7057c478bd9Sstevel@tonic-gate return MI_FAILURE;
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate /* trailing '\0' */
7087c478bd9Sstevel@tonic-gate ++len;
7097c478bd9Sstevel@tonic-gate buf = malloc(len);
7107c478bd9Sstevel@tonic-gate if (buf == NULL)
7117c478bd9Sstevel@tonic-gate return MI_FAILURE; /* oops */
7127c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(buf, len, 3, rcode, args == 1 ? " " : "-", xc);
7137c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(repl, sizeof repl, 4, rcode, args == 1 ? " " : "-",
7147c478bd9Sstevel@tonic-gate xc, " ");
7157c478bd9Sstevel@tonic-gate SM_VA_START(ap, xcode);
7167c478bd9Sstevel@tonic-gate txt = SM_VA_ARG(ap, char *);
7177c478bd9Sstevel@tonic-gate if (txt != NULL)
7187c478bd9Sstevel@tonic-gate {
7197c478bd9Sstevel@tonic-gate (void) sm_strlcat2(buf, " ", txt, len);
7207c478bd9Sstevel@tonic-gate while ((txt = SM_VA_ARG(ap, char *)) != NULL)
7217c478bd9Sstevel@tonic-gate {
7227c478bd9Sstevel@tonic-gate if (--args <= 1)
7237c478bd9Sstevel@tonic-gate repl[3] = ' ';
7247c478bd9Sstevel@tonic-gate (void) sm_strlcat2(buf, "\r\n", repl, len);
7257c478bd9Sstevel@tonic-gate (void) sm_strlcat(buf, txt, len);
7267c478bd9Sstevel@tonic-gate }
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate if (ctx->ctx_reply != NULL)
7297c478bd9Sstevel@tonic-gate free(ctx->ctx_reply);
7307c478bd9Sstevel@tonic-gate ctx->ctx_reply = buf;
7317c478bd9Sstevel@tonic-gate SM_VA_END(ap);
7327c478bd9Sstevel@tonic-gate return MI_SUCCESS;
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate
7357c478bd9Sstevel@tonic-gate /*
7367c478bd9Sstevel@tonic-gate ** SMFI_SETPRIV -- set private data
7377c478bd9Sstevel@tonic-gate **
7387c478bd9Sstevel@tonic-gate ** Parameters:
7397c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
7407c478bd9Sstevel@tonic-gate ** privatedata -- pointer to private data
7417c478bd9Sstevel@tonic-gate **
7427c478bd9Sstevel@tonic-gate ** Returns:
7437c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
7447c478bd9Sstevel@tonic-gate */
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate int
smfi_setpriv(ctx,privatedata)7477c478bd9Sstevel@tonic-gate smfi_setpriv(ctx, privatedata)
7487c478bd9Sstevel@tonic-gate SMFICTX *ctx;
7497c478bd9Sstevel@tonic-gate void *privatedata;
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate if (ctx == NULL)
7527c478bd9Sstevel@tonic-gate return MI_FAILURE;
7537c478bd9Sstevel@tonic-gate ctx->ctx_privdata = privatedata;
7547c478bd9Sstevel@tonic-gate return MI_SUCCESS;
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate /*
7587c478bd9Sstevel@tonic-gate ** SMFI_GETPRIV -- get private data
7597c478bd9Sstevel@tonic-gate **
7607c478bd9Sstevel@tonic-gate ** Parameters:
7617c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
7627c478bd9Sstevel@tonic-gate **
7637c478bd9Sstevel@tonic-gate ** Returns:
7647c478bd9Sstevel@tonic-gate ** pointer to private data
7657c478bd9Sstevel@tonic-gate */
7667c478bd9Sstevel@tonic-gate
7677c478bd9Sstevel@tonic-gate void *
smfi_getpriv(ctx)7687c478bd9Sstevel@tonic-gate smfi_getpriv(ctx)
7697c478bd9Sstevel@tonic-gate SMFICTX *ctx;
7707c478bd9Sstevel@tonic-gate {
7717c478bd9Sstevel@tonic-gate if (ctx == NULL)
7727c478bd9Sstevel@tonic-gate return NULL;
7737c478bd9Sstevel@tonic-gate return ctx->ctx_privdata;
7747c478bd9Sstevel@tonic-gate }
7757c478bd9Sstevel@tonic-gate
7767c478bd9Sstevel@tonic-gate /*
7777c478bd9Sstevel@tonic-gate ** SMFI_GETSYMVAL -- get the value of a macro
7787c478bd9Sstevel@tonic-gate **
7797c478bd9Sstevel@tonic-gate ** See explanation in mfapi.h about layout of the structures.
7807c478bd9Sstevel@tonic-gate **
7817c478bd9Sstevel@tonic-gate ** Parameters:
7827c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
7837c478bd9Sstevel@tonic-gate ** symname -- name of macro
7847c478bd9Sstevel@tonic-gate **
7857c478bd9Sstevel@tonic-gate ** Returns:
7867c478bd9Sstevel@tonic-gate ** value of macro (NULL in case of failure)
7877c478bd9Sstevel@tonic-gate */
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate char *
smfi_getsymval(ctx,symname)7907c478bd9Sstevel@tonic-gate smfi_getsymval(ctx, symname)
7917c478bd9Sstevel@tonic-gate SMFICTX *ctx;
7927c478bd9Sstevel@tonic-gate char *symname;
7937c478bd9Sstevel@tonic-gate {
7947c478bd9Sstevel@tonic-gate int i;
7957c478bd9Sstevel@tonic-gate char **s;
7967c478bd9Sstevel@tonic-gate char one[2];
7977c478bd9Sstevel@tonic-gate char braces[4];
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate if (ctx == NULL || symname == NULL || *symname == '\0')
8007c478bd9Sstevel@tonic-gate return NULL;
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate if (strlen(symname) == 3 && symname[0] == '{' && symname[2] == '}')
8037c478bd9Sstevel@tonic-gate {
8047c478bd9Sstevel@tonic-gate one[0] = symname[1];
8057c478bd9Sstevel@tonic-gate one[1] = '\0';
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate else
8087c478bd9Sstevel@tonic-gate one[0] = '\0';
8097c478bd9Sstevel@tonic-gate if (strlen(symname) == 1)
8107c478bd9Sstevel@tonic-gate {
8117c478bd9Sstevel@tonic-gate braces[0] = '{';
8127c478bd9Sstevel@tonic-gate braces[1] = *symname;
8137c478bd9Sstevel@tonic-gate braces[2] = '}';
8147c478bd9Sstevel@tonic-gate braces[3] = '\0';
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate else
8177c478bd9Sstevel@tonic-gate braces[0] = '\0';
8187c478bd9Sstevel@tonic-gate
8197c478bd9Sstevel@tonic-gate /* search backwards through the macro array */
8207c478bd9Sstevel@tonic-gate for (i = MAX_MACROS_ENTRIES - 1 ; i >= 0; --i)
8217c478bd9Sstevel@tonic-gate {
8227c478bd9Sstevel@tonic-gate if ((s = ctx->ctx_mac_ptr[i]) == NULL ||
8237c478bd9Sstevel@tonic-gate ctx->ctx_mac_buf[i] == NULL)
8247c478bd9Sstevel@tonic-gate continue;
8257c478bd9Sstevel@tonic-gate while (s != NULL && *s != NULL)
8267c478bd9Sstevel@tonic-gate {
8277c478bd9Sstevel@tonic-gate if (strcmp(*s, symname) == 0)
8287c478bd9Sstevel@tonic-gate return *++s;
8297c478bd9Sstevel@tonic-gate if (one[0] != '\0' && strcmp(*s, one) == 0)
8307c478bd9Sstevel@tonic-gate return *++s;
8317c478bd9Sstevel@tonic-gate if (braces[0] != '\0' && strcmp(*s, braces) == 0)
8327c478bd9Sstevel@tonic-gate return *++s;
8337c478bd9Sstevel@tonic-gate ++s; /* skip over macro value */
8347c478bd9Sstevel@tonic-gate ++s; /* points to next macro name */
8357c478bd9Sstevel@tonic-gate }
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate return NULL;
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate /*
8417c478bd9Sstevel@tonic-gate ** SMFI_PROGRESS -- send "progress" message to the MTA to prevent premature
8427c478bd9Sstevel@tonic-gate ** timeouts during long milter-side operations
8437c478bd9Sstevel@tonic-gate **
8447c478bd9Sstevel@tonic-gate ** Parameters:
8457c478bd9Sstevel@tonic-gate ** ctx -- Opaque context structure
8467c478bd9Sstevel@tonic-gate **
8477c478bd9Sstevel@tonic-gate ** Return value:
8487c478bd9Sstevel@tonic-gate ** MI_SUCCESS/MI_FAILURE
8497c478bd9Sstevel@tonic-gate */
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate int
smfi_progress(ctx)8527c478bd9Sstevel@tonic-gate smfi_progress(ctx)
8537c478bd9Sstevel@tonic-gate SMFICTX *ctx;
8547c478bd9Sstevel@tonic-gate {
8557c478bd9Sstevel@tonic-gate struct timeval timeout;
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate if (ctx == NULL)
8587c478bd9Sstevel@tonic-gate return MI_FAILURE;
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate timeout.tv_sec = ctx->ctx_timeout;
8617c478bd9Sstevel@tonic-gate timeout.tv_usec = 0;
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_PROGRESS, NULL, 0);
8647c478bd9Sstevel@tonic-gate }
865058561cbSjbeck
866058561cbSjbeck /*
867058561cbSjbeck ** SMFI_VERSION -- return (runtime) version of libmilter
868058561cbSjbeck **
869058561cbSjbeck ** Parameters:
870058561cbSjbeck ** major -- (pointer to) major version
871058561cbSjbeck ** minor -- (pointer to) minor version
872058561cbSjbeck ** patchlevel -- (pointer to) patchlevel version
873058561cbSjbeck **
874058561cbSjbeck ** Return value:
875058561cbSjbeck ** MI_SUCCESS
876058561cbSjbeck */
877058561cbSjbeck
878058561cbSjbeck int
smfi_version(major,minor,patchlevel)879058561cbSjbeck smfi_version(major, minor, patchlevel)
880058561cbSjbeck unsigned int *major;
881058561cbSjbeck unsigned int *minor;
882058561cbSjbeck unsigned int *patchlevel;
883058561cbSjbeck {
884058561cbSjbeck if (major != NULL)
885058561cbSjbeck *major = SM_LM_VRS_MAJOR(SMFI_VERSION);
886058561cbSjbeck if (minor != NULL)
887058561cbSjbeck *minor = SM_LM_VRS_MINOR(SMFI_VERSION);
888058561cbSjbeck if (patchlevel != NULL)
889*24472db6Sjbeck *patchlevel = SM_LM_VRS_PLVL(SMFI_VERSION);
890058561cbSjbeck return MI_SUCCESS;
891058561cbSjbeck }
892