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