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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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