Include <dlfcn.h> only when necessary
[exim.git] / src / src / drtables.c
1 /* $Cambridge: exim/src/src/drtables.c,v 1.11 2009/11/16 19:50:36 nm4 Exp $ */
2
3 /*************************************************
4 *     Exim - an Internet mail transport agent    *
5 *************************************************/
6
7 /* Copyright (c) University of Cambridge 1995 - 2009 */
8 /* See the file NOTICE for conditions of use and distribution. */
9
10
11 #include "exim.h"
12
13 #include <string.h>
14
15 /* This module contains tables that define the lookup methods and drivers
16 that are actually included in the binary. Its contents are controlled by
17 various macros in config.h that ultimately come from Local/Makefile. They are
18 all described in src/EDITME. */
19
20
21 lookup_info **lookup_list;
22 int lookup_list_count = 0;
23
24 /* Table of information about all possible authentication mechamisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set to NULL for those that are not compiled into the binary. */
27
28 #ifdef AUTH_CRAM_MD5
29 #include "auths/cram_md5.h"
30 #endif
31
32 #ifdef AUTH_CYRUS_SASL
33 #include "auths/cyrus_sasl.h"
34 #endif
35
36 #ifdef AUTH_DOVECOT
37 #include "auths/dovecot.h"
38 #endif
39
40 #ifdef AUTH_PLAINTEXT
41 #include "auths/plaintext.h"
42 #endif
43
44 #ifdef AUTH_SPA
45 #include "auths/spa.h"
46 #endif
47
48 auth_info auths_available[] = {
49
50 /* Checking by an expansion condition on plain text */
51
52 #ifdef AUTH_CRAM_MD5
53   {
54   US"cram_md5",                              /* lookup name */
55   auth_cram_md5_options,
56   &auth_cram_md5_options_count,
57   &auth_cram_md5_option_defaults,
58   sizeof(auth_cram_md5_options_block),
59   auth_cram_md5_init,                        /* init function */
60   auth_cram_md5_server,                      /* server function */
61   auth_cram_md5_client                       /* client function */
62   },
63 #endif
64
65 #ifdef AUTH_CYRUS_SASL
66   {
67   US"cyrus_sasl",           /* lookup name */
68   auth_cyrus_sasl_options,
69   &auth_cyrus_sasl_options_count,
70   &auth_cyrus_sasl_option_defaults,
71   sizeof(auth_cyrus_sasl_options_block),
72   auth_cyrus_sasl_init,                      /* init function */
73   auth_cyrus_sasl_server,                    /* server function */
74   NULL                                       /* client function */
75   },
76 #endif
77
78 #ifdef AUTH_DOVECOT
79   {
80   US"dovecot",                                /* lookup name */
81   auth_dovecot_options,
82   &auth_dovecot_options_count,
83   &auth_dovecot_option_defaults,
84   sizeof(auth_dovecot_options_block),
85   auth_dovecot_init,                          /* init function */
86   auth_dovecot_server,                        /* server function */
87   NULL                                        /* client function */
88   },
89 #endif
90
91 #ifdef AUTH_PLAINTEXT
92   {
93   US"plaintext",                             /* lookup name */
94   auth_plaintext_options,
95   &auth_plaintext_options_count,
96   &auth_plaintext_option_defaults,
97   sizeof(auth_plaintext_options_block),
98   auth_plaintext_init,                       /* init function */
99   auth_plaintext_server,                     /* server function */
100   auth_plaintext_client                      /* client function */
101   },
102 #endif
103
104 #ifdef AUTH_SPA
105   {
106   US"spa",                                   /* lookup name */
107   auth_spa_options,
108   &auth_spa_options_count,
109   &auth_spa_option_defaults,
110   sizeof(auth_spa_options_block),
111   auth_spa_init,                             /* init function */
112   auth_spa_server,                           /* server function */
113   auth_spa_client                            /* client function */
114   },
115 #endif
116
117 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL  }
118 };
119
120
121 /* Tables of information about which routers and transports are included in the
122 exim binary. */
123
124 /* Pull in the necessary header files */
125
126 #include "routers/rf_functions.h"
127
128 #ifdef ROUTER_ACCEPT
129 #include "routers/accept.h"
130 #endif
131
132 #ifdef ROUTER_DNSLOOKUP
133 #include "routers/dnslookup.h"
134 #endif
135
136 #ifdef ROUTER_MANUALROUTE
137 #include "routers/manualroute.h"
138 #endif
139
140 #ifdef ROUTER_IPLITERAL
141 #include "routers/ipliteral.h"
142 #endif
143
144 #ifdef ROUTER_IPLOOKUP
145 #include "routers/iplookup.h"
146 #endif
147
148 #ifdef ROUTER_QUERYPROGRAM
149 #include "routers/queryprogram.h"
150 #endif
151
152 #ifdef ROUTER_REDIRECT
153 #include "routers/redirect.h"
154 #endif
155
156 #ifdef TRANSPORT_APPENDFILE
157 #include "transports/appendfile.h"
158 #endif
159
160 #ifdef TRANSPORT_AUTOREPLY
161 #include "transports/autoreply.h"
162 #endif
163
164 #ifdef TRANSPORT_LMTP
165 #include "transports/lmtp.h"
166 #endif
167
168 #ifdef TRANSPORT_PIPE
169 #include "transports/pipe.h"
170 #endif
171
172 #ifdef TRANSPORT_SMTP
173 #include "transports/smtp.h"
174 #endif
175
176
177 /* Now set up the structures, terminated by an entry with a null name. */
178
179 router_info routers_available[] = {
180 #ifdef ROUTER_ACCEPT
181   {
182   US"accept",
183   accept_router_options,
184   &accept_router_options_count,
185   &accept_router_option_defaults,
186   sizeof(accept_router_options_block),
187   accept_router_init,
188   accept_router_entry,
189   NULL,     /* no tidyup entry */
190   ri_yestransport
191   },
192 #endif
193 #ifdef ROUTER_DNSLOOKUP
194   {
195   US"dnslookup",
196   dnslookup_router_options,
197   &dnslookup_router_options_count,
198   &dnslookup_router_option_defaults,
199   sizeof(dnslookup_router_options_block),
200   dnslookup_router_init,
201   dnslookup_router_entry,
202   NULL,     /* no tidyup entry */
203   ri_yestransport
204   },
205 #endif
206 #ifdef ROUTER_IPLITERAL
207   {
208   US"ipliteral",
209   ipliteral_router_options,
210   &ipliteral_router_options_count,
211   &ipliteral_router_option_defaults,
212   sizeof(ipliteral_router_options_block),
213   ipliteral_router_init,
214   ipliteral_router_entry,
215   NULL,     /* no tidyup entry */
216   ri_yestransport
217   },
218 #endif
219 #ifdef ROUTER_IPLOOKUP
220   {
221   US"iplookup",
222   iplookup_router_options,
223   &iplookup_router_options_count,
224   &iplookup_router_option_defaults,
225   sizeof(iplookup_router_options_block),
226   iplookup_router_init,
227   iplookup_router_entry,
228   NULL,     /* no tidyup entry */
229   ri_notransport
230   },
231 #endif
232 #ifdef ROUTER_MANUALROUTE
233   {
234   US"manualroute",
235   manualroute_router_options,
236   &manualroute_router_options_count,
237   &manualroute_router_option_defaults,
238   sizeof(manualroute_router_options_block),
239   manualroute_router_init,
240   manualroute_router_entry,
241   NULL,     /* no tidyup entry */
242   0
243   },
244 #endif
245 #ifdef ROUTER_QUERYPROGRAM
246   {
247   US"queryprogram",
248   queryprogram_router_options,
249   &queryprogram_router_options_count,
250   &queryprogram_router_option_defaults,
251   sizeof(queryprogram_router_options_block),
252   queryprogram_router_init,
253   queryprogram_router_entry,
254   NULL,     /* no tidyup entry */
255   0
256   },
257 #endif
258 #ifdef ROUTER_REDIRECT
259   {
260   US"redirect",
261   redirect_router_options,
262   &redirect_router_options_count,
263   &redirect_router_option_defaults,
264   sizeof(redirect_router_options_block),
265   redirect_router_init,
266   redirect_router_entry,
267   NULL,     /* no tidyup entry */
268   ri_notransport
269   },
270 #endif
271 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, 0 }
272 };
273
274
275
276 transport_info transports_available[] = {
277 #ifdef TRANSPORT_APPENDFILE
278   {
279   US"appendfile",                              /* driver name */
280   appendfile_transport_options,                /* local options table */
281   &appendfile_transport_options_count,         /* number of entries */
282   &appendfile_transport_option_defaults,       /* private options defaults */
283   sizeof(appendfile_transport_options_block),  /* size of private block */
284   appendfile_transport_init,                   /* init entry point */
285   appendfile_transport_entry,                  /* main entry point */
286   NULL,                                        /* no tidyup entry */
287   NULL,                                        /* no closedown entry */
288   TRUE,                                        /* local flag */
289   },
290 #endif
291 #ifdef TRANSPORT_AUTOREPLY
292   {
293   US"autoreply",                               /* driver name */
294   autoreply_transport_options,                 /* local options table */
295   &autoreply_transport_options_count,          /* number of entries */
296   &autoreply_transport_option_defaults,        /* private options defaults */
297   sizeof(autoreply_transport_options_block),   /* size of private block */
298   autoreply_transport_init,                    /* init entry point */
299   autoreply_transport_entry,                   /* main entry point */
300   NULL,                                        /* no tidyup entry */
301   NULL,                                        /* no closedown entry */
302   TRUE                                         /* local flag */
303   },
304 #endif
305 #ifdef TRANSPORT_LMTP
306   {
307   US"lmtp",                                    /* driver name */
308   lmtp_transport_options,                      /* local options table */
309   &lmtp_transport_options_count,               /* number of entries */
310   &lmtp_transport_option_defaults,             /* private options defaults */
311   sizeof(lmtp_transport_options_block),        /* size of private block */
312   lmtp_transport_init,                         /* init entry point */
313   lmtp_transport_entry,                        /* main entry point */
314   NULL,                                        /* no tidyup entry */
315   NULL,                                        /* no closedown entry */
316   TRUE                                         /* local flag */
317   },
318 #endif
319 #ifdef TRANSPORT_PIPE
320   {
321   US"pipe",                                    /* driver name */
322   pipe_transport_options,                      /* local options table */
323   &pipe_transport_options_count,               /* number of entries */
324   &pipe_transport_option_defaults,             /* private options defaults */
325   sizeof(pipe_transport_options_block),        /* size of private block */
326   pipe_transport_init,                         /* init entry point */
327   pipe_transport_entry,                        /* main entry point */
328   NULL,                                        /* no tidyup entry */
329   NULL,                                        /* no closedown entry */
330   TRUE                                         /* local flag */
331   },
332 #endif
333 #ifdef TRANSPORT_SMTP
334   {
335   US"smtp",                                    /* driver name */
336   smtp_transport_options,                      /* local options table */
337   &smtp_transport_options_count,               /* number of entries */
338   &smtp_transport_option_defaults,             /* private options defaults */
339   sizeof(smtp_transport_options_block),        /* size of private block */
340   smtp_transport_init,                         /* init entry point */
341   smtp_transport_entry,                        /* main entry point */
342   NULL,                                        /* no tidyup entry */
343   smtp_transport_closedown,                    /* close down passed channel */
344   FALSE                                        /* local flag */
345   },
346 #endif
347 { US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, FALSE }
348 };
349
350 struct lookupmodulestr
351 {
352   void *dl;
353   struct lookup_module_info *info;
354   struct lookupmodulestr *next;
355 };
356
357 static struct lookupmodulestr *lookupmodules = NULL;
358
359 static void addlookupmodule(void *dl, struct lookup_module_info *info)
360 {
361   struct lookupmodulestr *p = store_malloc(sizeof(struct lookupmodulestr));
362   p->dl = dl;
363   p->info = info;
364   p->next = lookupmodules;
365   lookupmodules = p;
366   lookup_list_count += info->lookupcount;
367 }
368
369 /* only valid after lookup_list and lookup_list_count are assigned */
370 static void add_lookup_to_list(lookup_info *info)
371 {
372   /* need to add the lookup to lookup_list, sorted */
373   int pos = 0;
374
375   /* strategy is to go through the list until we find
376    * either an empty spot or a name that is higher.
377    * this can't fail because we have enough space. */
378   while (lookup_list[pos]
379       && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0)) {
380     pos++;
381   }
382   if (lookup_list[pos]) {
383     /* need to insert it, so move all the other items up
384      * (last slot is still empty, of course) */
385     memmove(&lookup_list[pos+1],
386             &lookup_list[pos],
387             sizeof(lookup_info **) * (lookup_list_count-pos-1));
388   }
389   lookup_list[pos] = info;
390 }
391
392 void init_lookup_list(void)
393 {
394   DIR *dd;
395   struct dirent *ent;
396   const pcre *regex_islookupmod = regex_must_compile(US"\\.so$", FALSE, TRUE);
397   int countmodules = 0;
398   int moduleerrors = 0;
399   struct lookupmodulestr *p;
400
401 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
402 extern lookup_module_info cdb_lookup_module_info;
403   addlookupmodule(NULL, &cdb_lookup_module_info);
404 #endif
405
406 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
407 extern lookup_module_info dbmdb_lookup_module_info;
408   addlookupmodule(NULL, &dbmdb_lookup_module_info);
409 #endif
410
411 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
412 extern lookup_module_info dnsdb_lookup_module_info;
413   addlookupmodule(NULL, &dnsdb_lookup_module_info);
414 #endif
415
416 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
417 extern lookup_module_info dsearch_lookup_module_info;
418   addlookupmodule(NULL, &dsearch_lookup_module_info);
419 #endif
420
421 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
422 extern lookup_module_info ibase_lookup_module_info;
423   addlookupmodule(NULL, &ibase_lookup_module_info);
424 #endif
425
426 #ifdef LOOKUP_LDAP
427 extern lookup_module_info ldap_lookup_module_info;
428   addlookupmodule(NULL, &ldap_lookup_module_info);
429 #endif
430
431 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
432 extern lookup_module_info lsearch_lookup_module_info;
433   addlookupmodule(NULL, &lsearch_lookup_module_info);
434 #endif
435
436 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
437 extern lookup_module_info mysql_lookup_module_info;
438   addlookupmodule(NULL, &mysql_lookup_module_info);
439 #endif
440
441 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
442 extern lookup_module_info nis_lookup_module_info;
443   addlookupmodule(NULL, &nis_lookup_module_info);
444 #endif
445
446 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
447 extern lookup_module_info nisplus_lookup_module_info;
448   addlookupmodule(NULL, &nisplus_lookup_module_info);
449 #endif
450
451 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
452 extern lookup_module_info oracle_lookup_module_info;
453   addlookupmodule(NULL, &oracle_lookup_module_info);
454 #endif
455
456 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
457 extern lookup_module_info passwd_lookup_module_info;
458   addlookupmodule(NULL, &passwd_lookup_module_info);
459 #endif
460
461 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
462 extern lookup_module_info pgsql_lookup_module_info;
463   addlookupmodule(NULL, &pgsql_lookup_module_info);
464 #endif
465
466 #ifdef EXPERIMENTAL_SPF
467 extern lookup_module_info spf_lookup_module_info;
468   addlookupmodule(NULL, &spf_lookup_module_info);
469 #endif
470
471 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
472 extern lookup_module_info sqlite_lookup_module_info;
473   addlookupmodule(NULL, &sqlite_lookup_module_info);
474 #endif
475
476 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
477 extern lookup_module_info testdb_lookup_module_info;
478   addlookupmodule(NULL, &testdb_lookup_module_info);
479 #endif
480
481 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
482 extern lookup_module_info whoson_lookup_module_info;
483   addlookupmodule(NULL, &whoson_lookup_module_info);
484 #endif
485
486 #ifdef LOOKUP_MODULE_DIR
487   dd = opendir(LOOKUP_MODULE_DIR);
488   if (dd == NULL) {
489     DEBUG(5) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
490     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
491   }
492   else {
493     DEBUG(9) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
494     while ((ent = readdir(dd)) != NULL) {
495       char *name = ent->d_name;
496       int len = (int)strlen(name);
497       if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
498         int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
499         void *dl;
500         struct lookup_module_info *info;
501         char *errormsg;
502
503         /* SRH: am I being paranoid here or what? */
504         if (pathnamelen > big_buffer_size) {
505           fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
506           log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
507           continue;
508         }
509
510         /* SRH: snprintf here? */
511         sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
512
513         dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
514         if (dl == NULL) {
515           fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
516           moduleerrors++;
517           log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
518           continue;
519         }
520
521         info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
522         if ((errormsg = dlerror()) != NULL) {
523           fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
524           dlclose(dl);
525           moduleerrors++;
526           log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
527           continue;
528         }
529         if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
530           fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
531           dlclose(dl);
532           moduleerrors++;
533           log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
534           continue;
535         }
536
537         addlookupmodule(dl, info);
538         DEBUG(9) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
539         countmodules++;
540       }
541     }
542     closedir(dd);
543   }
544
545   DEBUG(9) debug_printf("Loaded %d lookup modules\n", countmodules);
546 #endif
547
548   store_free((void*)regex_islookupmod);
549
550   DEBUG(4) debug_printf("Total %d lookups\n", lookup_list_count);
551
552   lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
553   memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
554
555   /* now add all lookups to the real list */
556   p = lookupmodules;
557   while (p) {
558     int j;
559     struct lookupmodulestr *pnext;
560
561     for (j = 0; j < p->info->lookupcount; j++)
562       add_lookup_to_list(p->info->lookups[j]);
563
564     pnext = p->next;
565     store_free(p);
566     p = pnext;
567   }
568   /* just to be sure */
569   lookupmodules = NULL;
570 }
571
572 /* End of drtables.c */