1 /*
2 * Copyright (c) 2000 Charles Ying. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the same terms as sendmail itself.
6 *
7 */
8
9 #include "EXTERN.h"
10 #include "perl.h"
11 #include "XSUB.h"
12
13 #include "intpools.h"
14
15 #include "libmilter/mfapi.h"
16 #include "callbacks.h"
17
18
19 /* Conversion for an easier interface to the milter API. */
20 #define MI_BOOL_CVT(mi_bool) (((mi_bool) == MI_SUCCESS) ? TRUE : FALSE)
21
22 typedef SMFICTX *Sendmail_Milter_Context;
23
24
25 /* Wrapper functions to do some real work. */
26
milter_register(pTHX_ char * name,SV * milter_desc_ref,int flags)27 int milter_register(pTHX_ char *name, SV *milter_desc_ref, int flags)
28 {
29 HV *milter_desc = (HV *)NULL;
30 struct smfiDesc filter_desc;
31
32 if (!SvROK(milter_desc_ref) &&
33 (SvTYPE(SvRV(milter_desc_ref)) != SVt_PVHV))
34 croak("expected reference to hash for milter descriptor.");
35
36 milter_desc = (HV *)SvRV(milter_desc_ref);
37
38 register_callbacks(&filter_desc, name, milter_desc, flags);
39
40 return smfi_register(filter_desc);
41 }
42
milter_main(int max_interpreters,int max_requests)43 int milter_main(int max_interpreters, int max_requests)
44 {
45 init_callbacks(max_interpreters, max_requests);
46
47 return smfi_main();
48 }
49
50
51 /* Constants from libmilter/mfapi.h */
52
53 static int
not_here(char * s)54 not_here(char *s)
55 {
56 croak("%s not implemented on this architecture", s);
57 return -1;
58 }
59
60 static double
constant_SMFIF_A(char * name,int len,int arg)61 constant_SMFIF_A(char *name, int len, int arg)
62 {
63 if (7 + 2 >= len ) {
64 errno = EINVAL;
65 return 0;
66 }
67 switch (name[7 + 2]) {
68 case 'H':
69 if (strEQ(name + 7, "DDHDRS")) { /* SMFIF_A removed */
70 #ifdef SMFIF_ADDHDRS
71 return SMFIF_ADDHDRS;
72 #else
73 goto not_there;
74 #endif
75 }
76 case 'R':
77 if (strEQ(name + 7, "DDRCPT")) { /* SMFIF_A removed */
78 #ifdef SMFIF_ADDRCPT
79 return SMFIF_ADDRCPT;
80 #else
81 goto not_there;
82 #endif
83 }
84 }
85 errno = EINVAL;
86 return 0;
87
88 not_there:
89 errno = ENOENT;
90 return 0;
91 }
92
93 static double
constant_SMFIF_C(char * name,int len,int arg)94 constant_SMFIF_C(char *name, int len, int arg)
95 {
96 if (7 + 2 >= len ) {
97 errno = EINVAL;
98 return 0;
99 }
100 switch (name[7 + 2]) {
101 case 'B':
102 if (strEQ(name + 7, "HGBODY")) { /* SMFIF_C removed */
103 #ifdef SMFIF_CHGBODY
104 return SMFIF_CHGBODY;
105 #else
106 goto not_there;
107 #endif
108 }
109 case 'H':
110 if (strEQ(name + 7, "HGHDRS")) { /* SMFIF_C removed */
111 #ifdef SMFIF_CHGHDRS
112 return SMFIF_CHGHDRS;
113 #else
114 goto not_there;
115 #endif
116 }
117 }
118 errno = EINVAL;
119 return 0;
120
121 not_there:
122 errno = ENOENT;
123 return 0;
124 }
125
126 static double
constant_SMFIF(char * name,int len,int arg)127 constant_SMFIF(char *name, int len, int arg)
128 {
129 if (5 + 1 >= len ) {
130 errno = EINVAL;
131 return 0;
132 }
133 switch (name[5 + 1]) {
134 case 'A':
135 if (!strnEQ(name + 5,"_", 1))
136 break;
137 return constant_SMFIF_A(name, len, arg);
138 case 'C':
139 if (!strnEQ(name + 5,"_", 1))
140 break;
141 return constant_SMFIF_C(name, len, arg);
142 case 'D':
143 if (strEQ(name + 5, "_DELRCPT")) { /* SMFIF removed */
144 #ifdef SMFIF_DELRCPT
145 return SMFIF_DELRCPT;
146 #else
147 goto not_there;
148 #endif
149 }
150 case 'M':
151 if (strEQ(name + 5, "_MODBODY")) { /* SMFIF removed */
152 #ifdef SMFIF_MODBODY
153 return SMFIF_MODBODY;
154 #else
155 goto not_there;
156 #endif
157 }
158 }
159 errno = EINVAL;
160 return 0;
161
162 not_there:
163 errno = ENOENT;
164 return 0;
165 }
166
167 static double
constant_SMFI_V(char * name,int len,int arg)168 constant_SMFI_V(char *name, int len, int arg)
169 {
170 switch (name[6 + 0]) {
171 case '1':
172 if (strEQ(name + 6, "1_ACTS")) { /* SMFI_V removed */
173 #ifdef SMFI_V1_ACTS
174 return SMFI_V1_ACTS;
175 #else
176 goto not_there;
177 #endif
178 }
179 case '2':
180 if (strEQ(name + 6, "2_ACTS")) { /* SMFI_V removed */
181 #ifdef SMFI_V2_ACTS
182 return SMFI_V2_ACTS;
183 #else
184 goto not_there;
185 #endif
186 }
187 }
188 errno = EINVAL;
189 return 0;
190
191 not_there:
192 errno = ENOENT;
193 return 0;
194 }
195
196 static double
constant_SMFI_(char * name,int len,int arg)197 constant_SMFI_(char *name, int len, int arg)
198 {
199 switch (name[5 + 0]) {
200 case 'C':
201 if (strEQ(name + 5, "CURR_ACTS")) { /* SMFI_ removed */
202 #ifdef SMFI_CURR_ACTS
203 return SMFI_CURR_ACTS;
204 #else
205 goto not_there;
206 #endif
207 }
208 case 'V':
209 return constant_SMFI_V(name, len, arg);
210 }
211 errno = EINVAL;
212 return 0;
213
214 not_there:
215 errno = ENOENT;
216 return 0;
217 }
218
219 static double
constant_SMFIS(char * name,int len,int arg)220 constant_SMFIS(char *name, int len, int arg)
221 {
222 if (5 + 1 >= len ) {
223 errno = EINVAL;
224 return 0;
225 }
226 switch (name[5 + 1]) {
227 case 'A':
228 if (strEQ(name + 5, "_ACCEPT")) { /* SMFIS removed */
229 #ifdef SMFIS_ACCEPT
230 return SMFIS_ACCEPT;
231 #else
232 goto not_there;
233 #endif
234 }
235 case 'C':
236 if (strEQ(name + 5, "_CONTINUE")) { /* SMFIS removed */
237 #ifdef SMFIS_CONTINUE
238 return SMFIS_CONTINUE;
239 #else
240 goto not_there;
241 #endif
242 }
243 case 'D':
244 if (strEQ(name + 5, "_DISCARD")) { /* SMFIS removed */
245 #ifdef SMFIS_DISCARD
246 return SMFIS_DISCARD;
247 #else
248 goto not_there;
249 #endif
250 }
251 case 'R':
252 if (strEQ(name + 5, "_REJECT")) { /* SMFIS removed */
253 #ifdef SMFIS_REJECT
254 return SMFIS_REJECT;
255 #else
256 goto not_there;
257 #endif
258 }
259 case 'T':
260 if (strEQ(name + 5, "_TEMPFAIL")) { /* SMFIS removed */
261 #ifdef SMFIS_TEMPFAIL
262 return SMFIS_TEMPFAIL;
263 #else
264 goto not_there;
265 #endif
266 }
267 }
268 errno = EINVAL;
269 return 0;
270
271 not_there:
272 errno = ENOENT;
273 return 0;
274 }
275
276 static double
constant(char * name,int len,int arg)277 constant(char *name, int len, int arg)
278 {
279 errno = 0;
280 if (0 + 4 >= len ) {
281 errno = EINVAL;
282 return 0;
283 }
284 switch (name[0 + 4]) {
285 case 'F':
286 if (!strnEQ(name + 0,"SMFI", 4))
287 break;
288 return constant_SMFIF(name, len, arg);
289 case 'S':
290 if (!strnEQ(name + 0,"SMFI", 4))
291 break;
292 return constant_SMFIS(name, len, arg);
293 case '_':
294 if (!strnEQ(name + 0,"SMFI", 4))
295 break;
296 return constant_SMFI_(name, len, arg);
297 }
298 errno = EINVAL;
299 return 0;
300
301 not_there:
302 errno = ENOENT;
303 return 0;
304 }
305
306
307 MODULE = Sendmail::Milter PACKAGE = Sendmail::Milter PREFIX = smfi_
308
309 PROTOTYPES: DISABLE
310
311 double
312 constant(sv,arg)
313 PREINIT:
314 STRLEN len;
315 INPUT:
316 SV * sv
317 char * s = SvPV(sv, len);
318 int arg
319 CODE:
320 RETVAL = constant(s,len,arg);
321 OUTPUT:
322 RETVAL
323
324 bool
325 smfi_register(name, milter_desc_ref, flags=0)
326 char* name;
327 SV* milter_desc_ref;
328 int flags;
329 CODE:
330 RETVAL = MI_BOOL_CVT(milter_register(aTHX_ name, milter_desc_ref,
331 flags));
332 OUTPUT:
333 RETVAL
334
335 bool
336 smfi_main(max_interpreters=0, max_requests=0)
337 int max_interpreters;
338 int max_requests;
339 CODE:
340 RETVAL = MI_BOOL_CVT(milter_main(max_interpreters, max_requests));
341 OUTPUT:
342 RETVAL
343
344 bool
345 smfi_setdbg(dbg)
346 int dbg;
347 CODE:
348 RETVAL = MI_BOOL_CVT(smfi_setdbg(dbg));
349 OUTPUT:
350 RETVAL
351
352 bool
353 smfi_setconn(conn)
354 char* conn;
355 CODE:
356 RETVAL = MI_BOOL_CVT(smfi_setconn(conn));
357 OUTPUT:
358 RETVAL
359
360 bool
361 smfi_settimeout(timeout)
362 int timeout;
363 CODE:
364 RETVAL = MI_BOOL_CVT(smfi_settimeout(timeout));
365 OUTPUT:
366 RETVAL
367
368 int
369 test_intpools(max_interp, max_requests, i_max, j_max, callback)
370 int max_interp;
371 int max_requests;
372 int i_max;
373 int j_max;
374 SV* callback;
375 CODE:
376 RETVAL = test_intpools(aTHX_ max_interp, max_requests, i_max, j_max,
377 callback);
378 OUTPUT:
379 RETVAL
380
381
382 MODULE = Sendmail::Milter PACKAGE = Sendmail::Milter::Context PREFIX = smfi_
383
384 char *
385 smfi_getsymval(Sendmail_Milter_Context ctx, char* symname)
386
387 bool
388 smfi_setreply(ctx, rcode, xcode, message)
389 Sendmail_Milter_Context ctx;
390 char* rcode;
391 char* xcode;
392 char* message;
393 CODE:
394 RETVAL = MI_BOOL_CVT(smfi_setreply(ctx, rcode, xcode, message));
395 OUTPUT:
396 RETVAL
397
398 bool
399 smfi_addheader(ctx, headerf, headerv)
400 Sendmail_Milter_Context ctx;
401 char* headerf;
402 char* headerv;
403 CODE:
404 RETVAL = MI_BOOL_CVT(smfi_addheader(ctx, headerf, headerv));
405 OUTPUT:
406 RETVAL
407
408 bool
409 smfi_chgheader(ctx, headerf, index, headerv)
410 Sendmail_Milter_Context ctx;
411 char* headerf;
412 int index;
413 char* headerv;
414 CODE:
415 RETVAL = MI_BOOL_CVT(smfi_chgheader(ctx, headerf, index, headerv));
416 OUTPUT:
417 RETVAL
418
419 bool
420 smfi_addrcpt(ctx, rcpt)
421 Sendmail_Milter_Context ctx;
422 char* rcpt;
423 CODE:
424 RETVAL = MI_BOOL_CVT(smfi_addrcpt(ctx, rcpt));
425 OUTPUT:
426 RETVAL
427
428 bool
429 smfi_delrcpt(ctx, rcpt)
430 Sendmail_Milter_Context ctx;
431 char* rcpt;
432 CODE:
433 RETVAL = MI_BOOL_CVT(smfi_delrcpt(ctx, rcpt));
434 OUTPUT:
435 RETVAL
436
437 bool
438 smfi_replacebody(ctx, body_data)
439 Sendmail_Milter_Context ctx;
440 SV* body_data;
441 PREINIT:
442 u_char *bodyp;
443 int len;
444 CODE:
445 bodyp = SvPV(body_data, len);
446 RETVAL = MI_BOOL_CVT(smfi_replacebody(ctx, bodyp, len));;
447 OUTPUT:
448 RETVAL
449
450 bool
451 smfi_setpriv(ctx, data)
452 Sendmail_Milter_Context ctx;
453 SV* data;
454 CODE:
455 if (SvTRUE(data))
456 RETVAL = MI_BOOL_CVT(smfi_setpriv(ctx, (void *)newSVsv(data)));
457 else
458 RETVAL = MI_BOOL_CVT(smfi_setpriv(ctx, NULL));
459 OUTPUT:
460 RETVAL
461
462 SV *
463 smfi_getpriv(ctx)
464 Sendmail_Milter_Context ctx;
465 CODE:
466 RETVAL = (SV *) smfi_getpriv(ctx);
467 OUTPUT:
468 RETVAL
469