ze-filter  (ze-filter-0.8.0-develop-180218)
ze-modules.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : Sat Jun 2 22:18:08 CEST 2007
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 
26 #include <ze-sys.h>
27 #include <ze-filter.h>
28 #include <ze-filter.h>
29 #include <ze-modules.h>
30 
31 
32 
33 typedef bool(*MOD_INIT_F) (int, mod_open_T *);
34 typedef bool(*MOD_CLOSE_F) ();
35 typedef bool(*MOD_INFO_F) (mod_info_T *);
36 typedef bool(*MOD_CALL_F) (int, int, mod_ctx_T *);
37 typedef bool(*MOD_SERVICE_F) (int);
38 
39 /* information about a module */
40 typedef struct {
41  bool ok;
42  char *name;
43  char *fname;
44  void *handle;
45  bool enable;
47  char *args;
48 
54 } module_T;
55 
56 #define NMOD 128
57 static module_T modules[NMOD];
58 static bool mod_ok = FALSE;
59 static uint32_t calls = 0;
60 
61 static void close_all_modules(void);
62 
63 /* ****************************************************************************
64  * *
65  * *
66  **************************************************************************** */
67 #define MOD_INFO(mod, minfo) \
68  do { \
69  ZE_MessageInfo(9, " * Register info"); \
70  ZE_MessageInfo(9, " NAME : %s\n", mod->name); \
71  ZE_MessageInfo(9, " NAME : %s\n", mod->fname); \
72  ZE_MessageInfo(9, " ARGS : %s\n", STRNULL(mod->args, "NO ARGS")); \
73  ZE_MessageInfo(9, " ENABLE : %s\n", STRBOOL(mod->enable, "YES", "NO")); \
74  ZE_MessageInfo(9, " CALLBACKS : %08X\n", mod->callbacks); \
75  ZE_MessageInfo(9, " * Module info"); \
76  ZE_MessageInfo(9, " NAME : %s\n", minfo->name); \
77  ZE_MessageInfo(9, " AUTHOR : %s\n", minfo->author); \
78  ZE_MessageInfo(9, " VERSION : %s\n", minfo->version); \
79  } while (0)
80 
81 /* ****************************************************************************
82  * *
83  * *
84  **************************************************************************** */
85 
86 static bool
87 load_module(modp, fname, modsys)
88  module_T *modp;
89  char *fname;
90  mod_open_T *modsys;
91 {
92  void *handle = NULL;
93  char *error = NULL;
94 
95  char path[1024];
96  bool res = FALSE;
97 
98  ASSERT(modp != NULL);
99  ADJUST_FILENAME(path, fname, modsys->moddir, NULL);
100 
101  handle = dlopen(path, RTLD_LAZY);
102  if (handle == NULL) {
103  ZE_LogSysError("%s", dlerror());
104  goto fin;
105  }
106 
107  {
108  void *fp = NULL;
109  char *fn = NULL;
110 
111  fn = "mod_init";
112  dlerror();
113  fp = dlsym(handle, fn);
114  if ((error = dlerror()) == NULL)
115  modp->finit = (MOD_INIT_F) fp;
116  else
117  ZE_LogSysError("%s", error);
118 
119  fn = "mod_close";
120  dlerror();
121  fp = dlsym(handle, fn);
122  if ((error = dlerror()) == NULL)
123  modp->fclose = (MOD_CLOSE_F) fp;
124  else
125  ZE_LogSysError("%s", error);
126 
127  fn = "mod_info";
128  dlerror();
129  fp = dlsym(handle, fn);
130  if ((error = dlerror()) == NULL)
131  modp->finfo = (MOD_INFO_F) fp;
132  else
133  ZE_LogSysError("%s", error);
134 
135  fn = "mod_call";
136  dlerror();
137  fp = dlsym(handle, fn);
138  if ((error = dlerror()) == NULL)
139  modp->fcall = (MOD_CALL_F) fp;
140  else
141  ZE_LogSysError("%s", error);
142 
143  fn = "mod_service";
144  dlerror();
145  fp = dlsym(handle, fn);
146  if ((error = dlerror()) == NULL)
147  modp->fservice = (MOD_SERVICE_F) fp;
148  else
149  ZE_LogSysError("%s", error);
150  }
151 
152  if (modp->finit != NULL)
153  res = (*modp->finit) (MOD_VERSION, modsys);
154 
155  modp->handle = handle;
156 
157 fin:
158  return res;
159 }
160 
161 
162 static int
163 read_mod_cf_line(line, arg)
164  char *line;
165  void *arg;
166 {
167  char *argv[8];
168  int argc;
169  int i;
170  mod_open_T *modsys = (mod_open_T *) arg;
171  char *fname = NULL;
172  char *name = NULL;
173  char *args = NULL;
174  uint32_t callbacks = 0;
175  bool enable = FALSE;
176  int res = 0;
177 
178  ASSERT(modsys != NULL);
179 
180  ZE_MessageInfo(9, " * %s", line);
181 
182  memset(argv, 0, sizeof (argv));
183  argc = zeStr2Tokens(line, 8, argv, " \t");
184  for (i = 0; i < argc; i++) {
185  switch (i) {
186  case 0:
187  ZE_MessageInfo(9, "Name : %s", argv[i]);
188  name = argv[i];
189  break;
190  case 1:
191  ZE_MessageInfo(9, "File : %s", argv[i]);
192  fname = argv[i];
193  break;
194  case 2:
195  ZE_MessageInfo(9, "Enabled : %s", argv[i]);
196  if (zeStrRegex(argv[i], "YES|ENABLE|OUI", NULL, NULL, TRUE))
197  enable = TRUE;
198  break;
199  case 3:
200  ZE_MessageInfo(9, "Callbacks : %s", argv[i]);
201  {
202  char buf[256];
203  char *cargv[32];
204  int cargc;
205  int j;
206 
207  strlcpy(buf, argv[i], sizeof (buf));
208  memset(cargv, 0, sizeof (cargv));
209  cargc = zeStr2Tokens(buf, 32, cargv, ",");
210  for (j = 0; j < cargc; j++) {
211  if (STRCASEEQUAL(cargv[j], "connect")) {
212  SET_BIT(callbacks, CALLBACK_CONNECT);
213  continue;
214  }
215  if (STRCASEEQUAL(cargv[j], "helo")) {
216  SET_BIT(callbacks, CALLBACK_EHLO);
217  continue;
218  }
219  if (STRCASEEQUAL(cargv[j], "ehlo")) {
220  SET_BIT(callbacks, CALLBACK_EHLO);
221  continue;
222  }
223  if (STRCASEEQUAL(cargv[j], "mail")) {
224  SET_BIT(callbacks, CALLBACK_MAIL);
225  continue;
226  }
227  if (STRCASEEQUAL(cargv[j], "rcpt")) {
228  SET_BIT(callbacks, CALLBACK_RCPT);
229  continue;
230  }
231  if (STRCASEEQUAL(cargv[j], "data")) {
232  SET_BIT(callbacks, CALLBACK_DATA);
233  continue;
234  }
235  if (STRCASEEQUAL(cargv[j], "header")) {
236  SET_BIT(callbacks, CALLBACK_HEADER);
237  continue;
238  }
239  if (STRCASEEQUAL(cargv[j], "eom")) {
240  SET_BIT(callbacks, CALLBACK_EOM);
241  continue;
242  }
243  if (STRCASEEQUAL(cargv[j], "abort")) {
244  SET_BIT(callbacks, CALLBACK_ABORT);
245  continue;
246  }
247  if (STRCASEEQUAL(cargv[j], "close")) {
248  SET_BIT(callbacks, CALLBACK_CLOSE);
249  continue;
250  }
251  if (STRCASEEQUAL(cargv[j], "all")) {
252  SET_BIT(callbacks, CALLBACK_CONNECT);
253  SET_BIT(callbacks, CALLBACK_EHLO);
254  SET_BIT(callbacks, CALLBACK_CLOSE);
255  SET_BIT(callbacks, CALLBACK_MAIL);
256  SET_BIT(callbacks, CALLBACK_RCPT);
257  SET_BIT(callbacks, CALLBACK_DATA);
258  SET_BIT(callbacks, CALLBACK_EOM);
259  SET_BIT(callbacks, CALLBACK_ABORT);
260  SET_BIT(callbacks, CALLBACK_CLOSE);
261  break;
262  }
263  }
264  }
265  break;
266  case 4:
267  ZE_MessageInfo(9, "Arguments : %s", argv[i]);
268  args = argv[i];
269  break;
270  default:
271  ZE_MessageInfo(9, "???? : %s", argv[i]);
272  break;
273  }
274  }
275  if (fname != NULL && name != NULL) {
276  module_T *p = NULL;
277  int i;
278 
279  for (i = 0; i < NMOD; i++) {
280  if (modules[i].fname == NULL)
281  break;
282  if (STRCASEEQUAL(modules[i].name, name))
283  break;
284  }
285  ZE_MessageInfo(9, "Opening module : %s", name);
286  if (i < NMOD && modules[i].name == NULL) {
287  modsys->calloffer = 0;
288  modsys->callrequest = callbacks;
289  modsys->args = args;
290  if (load_module(&modules[i], fname, modsys)) {
291  modules[i].ok = TRUE;
292  modules[i].name = strdup(name);
293  modules[i].fname = strdup(fname);
294  if (args != NULL)
295  modules[i].args = strdup(args);
296  /*
297  ** modules[i].callbacks = callbacks & modsys->callbacks;
298  */
299  callbacks &= modsys->calloffer;
300  modules[i].callbacks = callbacks;
301 
302  modules[i].enable = enable && (callbacks != 0);
303 
304  calls |= callbacks;
305 
306  i++;
307  res = 1;
308  }
309  }
310  } else {
311  ZE_MessageInfo(9, "Error : module filename is null !");
312  }
313 
314  return res;
315 }
316 
317 bool
318 load_all_modules(cfdir, modcf, moddir)
319  char *cfdir;
320  char *modcf;
321  char *moddir;
322 {
323  int r;
324 
325  char path[1024];
326  mod_open_T modsys;
327 
328  if (!mod_ok) {
329  ZE_MessageInfo(10, "*** Loading ze-filter modules ...");
330  memset(&modsys, 0, sizeof (modsys));
331  mod_ok = TRUE;
332 
333  atexit(close_all_modules);
334  }
335 
336  modsys.moddir = moddir;
337 
338  ADJUST_FILENAME(path, modcf, cfdir, "modules.cf");
339  r = zm_RdFile(path, NULL, (RDFILE_F) read_mod_cf_line, &modsys);
340 
341  return TRUE;
342 }
343 
344 /* ****************************************************************************
345  * *
346  * *
347  **************************************************************************** */
348 static void
349 close_all_modules(void)
350 {
351  int i;
352 
353  ZE_MessageInfo(9, "*** Module subsystem");
354  for (i = 0; i < NMOD; i++) {
355  module_T *m = (module_T *) & modules[i];
356  char *error = NULL;
357 
358  mod_info_T info;
359 
360  if (!m->ok)
361  continue;
362 
363  m->enable = FALSE;
364 
365  if (m->fclose == NULL)
366  continue;
367 
368  ZE_MessageInfo(9, "* Module %4d : %s", i, m->name);
369  if ((*m->fclose) ()) {
370  ZE_MessageInfo(9, " * Closed !!!");
371  }
372  }
373 }
374 
375 /* ****************************************************************************
376  * *
377  * *
378  **************************************************************************** */
379 bool
381 {
382  int i;
383 
384  ZE_MessageInfo(9, "*** Module subsystem");
385  for (i = 0; i < NMOD; i++) {
386  module_T *m = (module_T *) & modules[i];
387  char *error = NULL;
388 
389  mod_info_T info;
390 
391  if (!m->ok)
392  continue;
393 
394  if (m->finfo == NULL)
395  continue;
396 
397  memset(&info, 0, sizeof (info));
398 
399  ZE_MessageInfo(9, "* Module %4d", i);
400  if ((*m->finfo) (&info)) {
401  ZE_MessageInfo(9, " * Register info");
402  ZE_MessageInfo(9, " NAME : %s", m->name);
403  ZE_MessageInfo(9, " NAME : %s", m->fname);
404  ZE_MessageInfo(9, " ARGS : %s", STRNULL(m->args, "NO ARGS"));
405  ZE_MessageInfo(9, " ENABLE : %s", STRBOOL(m->enable, "YES", "NO"));
406  ZE_MessageInfo(9, " CALLBACKS : %08X", m->callbacks);
407  ZE_MessageInfo(9, " * Module info");
408  ZE_MessageInfo(9, " NAME : %s", info.name);
409  ZE_MessageInfo(9, " AUTHOR : %s", info.author);
410  ZE_MessageInfo(9, " VERSION : %s", info.version);
411  }
412  }
413  return TRUE;
414 }
415 
416 /* ****************************************************************************
417  * *
418  * *
419  **************************************************************************** */
420 bool
421 module_call(callback, step, mctx)
422  int callback;
423  int step;
424  mod_ctx_T *mctx;
425 {
426  int i;
427 
428  ASSERT(mctx != NULL);
429 
430  ZE_MessageInfo(9, "*** Calling subsystems : %s", CALLBACK_LABEL(callback));
431  for (i = 0; i < NMOD; i++) {
432  module_T *m = (module_T *) & modules[i];
433  int result = MODR_CONTINUE;
434 
435  /*
436  * was this module configured ?
437  */
438  if (!m->ok)
439  continue;
440 
441  /*
442  * is this module enabled ?
443  */
444  if (!m->enable)
445  continue;
446 
447  /*
448  * Is this module enabled for this callback ?
449  */
450  if (!GET_BIT(m->callbacks, callback))
451  continue;
452 
453  if (m->fcall == NULL)
454  continue;
455 
456  ZE_MessageInfo(9, "* Module %4d : %s", i, m->name);
457  if ((*m->fcall) (callback, step, mctx)) {
458  strlcpy(mctx->modname, m->name, sizeof (mctx->modname));
459 
460  ZE_MessageInfo(11, " * Call result");
461  ZE_MessageInfo(11, " REPLY : %s %s %s", mctx->code, mctx->xcode,
462  mctx->reply);
463 #if 0
464  ZE_MessageInfo(10, " NAME : %s", m->name);
465  ZE_MessageInfo(10, " NAME : %s", m->fname);
466  ZE_MessageInfo(10, " ARGS : %s", STRNULL(m->args, "NO ARGS"));
467  ZE_MessageInfo(10, " ENABLE : %s", STRBOOL(m->enable, "YES", "NO"));
468  ZE_MessageInfo(10, " CALLBACKS : %08X", m->callbacks);
469  ZE_MessageInfo(10, " * Module info");
470  ZE_MessageInfo(10, " NAME : %s", info.name);
471  ZE_MessageInfo(10, " AUTHOR : %s", info.author);
472  ZE_MessageInfo(10, " VERSION : %s", info.version);
473 #endif
474  }
475 
476  if (mctx->result != MODR_CONTINUE
477  || ((mctx->flags & MODF_STOP_CHECKS) != 0))
478  break;
479  }
480  return TRUE;
481 }
482 
483 /* ****************************************************************************
484  * *
485  * *
486  **************************************************************************** */
487 bool
489  int why;
490 {
491  int i;
492 
493  ZE_MessageInfo(9, "*** Calling subsystems : service");
494  for (i = 0; i < NMOD; i++) {
495  module_T *m = (module_T *) & modules[i];
496 
497  /*
498  * was this module configured ?
499  */
500  if (!m->ok)
501  continue;
502 
503  /*
504  * is this module enabled ?
505  */
506  if (!m->enable)
507  continue;
508 
509  if (m->fservice == NULL)
510  continue;
511 
512  ZE_MessageInfo(9, "* Module %4d : %s", i, m->name);
513  if ((*m->fservice) (why)) {
514  ZE_MessageInfo(9, " * Service result");
515  }
516  }
517  return TRUE;
518 }
#define CALLBACK_HEADER
Definition: ze-callback.h:33
char * args
Definition: ze-modules.h:81
bool(* MOD_SERVICE_F)(int)
Definition: ze-modules.c:37
#define NMOD
Definition: ze-modules.c:56
#define STRBOOL(x, t, f)
Definition: macros.h:87
int zm_RdFile(char *fname, char *tag, RDFILE_F f, void *arg)
Definition: zeRdFile.c:185
#define MOD_VERSION
Definition: ze-modules.h:31
char * name
Definition: ze-modules.h:48
bool(* MOD_INFO_F)(mod_info_T *)
Definition: ze-modules.c:35
#define MODF_STOP_CHECKS
Definition: ze-modules.h:40
#define CALLBACK_CONNECT
Definition: ze-callback.h:28
#define ASSERT(a)
Definition: macros.h:27
bool module_service(int why)
Definition: ze-modules.c:488
bool enable
Definition: ze-modules.c:45
bool load_all_modules(char *cfdir, char *modcf, char *moddir)
Definition: ze-modules.c:318
#define CALLBACK_EHLO
Definition: ze-callback.h:29
#define STRNULL(x, r)
Definition: macros.h:81
#define CALLBACK_RCPT
Definition: ze-callback.h:31
MOD_SERVICE_F fservice
Definition: ze-modules.c:53
bool module_call(int callback, int step, mod_ctx_T *mctx)
Definition: ze-modules.c:421
char * name
Definition: ze-modules.c:42
#define FALSE
Definition: macros.h:160
bool ok
Definition: ze-modules.c:41
#define strlcpy
Definition: zeString.h:32
#define ADJUST_FILENAME(path, fname, cfdir, defval)
Definition: macros.h:236
bool zeStrRegex(char *, char *, long *, long *, bool)
Definition: zeStrings.c:544
MOD_CLOSE_F fclose
Definition: ze-modules.c:50
char * fname
Definition: ze-modules.c:43
#define GET_BIT(p, i)
Definition: macros.h:168
#define SET_BIT(p, i)
Definition: macros.h:166
int zeStr2Tokens(char *, int, char **, char *)
Definition: zeStrings.c:610
uint32_t calloffer
Definition: ze-modules.h:83
uint32_t callbacks
Definition: ze-modules.c:46
char * version
Definition: ze-modules.h:50
int(* RDFILE_F)(void *, void *)
Definition: ze-rdfile.h:35
Error dont have limits h nor values h typedef int bool
Definition: ze-sys.h:261
uint32_t callrequest
Definition: ze-modules.h:82
#define CALLBACK_DATA
Definition: ze-callback.h:32
char * author
Definition: ze-modules.h:49
#define CALLBACK_MAIL
Definition: ze-callback.h:30
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define TRUE
Definition: macros.h:157
#define MODR_CONTINUE
Definition: ze-modules.h:35
MOD_INFO_F finfo
Definition: ze-modules.c:51
char code[8]
Definition: ze-modules.h:71
MOD_CALL_F fcall
Definition: ze-modules.c:52
#define CALLBACK_CLOSE
Definition: ze-callback.h:38
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
#define CALLBACK_ABORT
Definition: ze-callback.h:37
char * args
Definition: ze-modules.c:47
bool module_info()
Definition: ze-modules.c:380
int result
Definition: ze-modules.h:69
#define CALLBACK_LABEL(i)
Definition: ze-callback.h:42
char * moddir
Definition: ze-modules.h:79
char modname[32]
Definition: ze-modules.h:74
#define STRCASEEQUAL(a, b)
Definition: macros.h:72
bool(* MOD_CLOSE_F)()
Definition: ze-modules.c:34
bool(* MOD_INIT_F)(int, mod_open_T *)
Definition: ze-modules.c:33
char xcode[8]
Definition: ze-modules.h:72
#define CALLBACK_EOM
Definition: ze-callback.h:36
int flags
Definition: ze-modules.h:70
long uint32_t
Definition: ze-sys.h:489
bool(* MOD_CALL_F)(int, int, mod_ctx_T *)
Definition: ze-modules.c:36
void * handle
Definition: ze-modules.c:44
MOD_INIT_F finit
Definition: ze-modules.c:49
char reply[64]
Definition: ze-modules.h:73