7ecca505629bfba639dd18cd5eb191260e52f00e
[exim.git] / src / src / drtables.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* See the file NOTICE for conditions of use and distribution. */
7
8
9 #include "exim.h"
10
11 #include <string.h>
12
13 /* This module contains tables that define the lookup methods and drivers
14 that are actually included in the binary. Its contents are controlled by
15 various macros in config.h that ultimately come from Local/Makefile. They are
16 all described in src/EDITME. */
17
18
19 lookup_info **lookup_list;
20 int lookup_list_count = 0;
21
22 /* Table of information about all possible authentication mechanisms. All
23 entries are always present if any mechanism is declared, but the functions are
24 set to NULL for those that are not compiled into the binary. */
25
26 #ifdef AUTH_CRAM_MD5
27 #include "auths/cram_md5.h"
28 #endif
29
30 #ifdef AUTH_CYRUS_SASL
31 #include "auths/cyrus_sasl.h"
32 #endif
33
34 #ifdef AUTH_DOVECOT
35 #include "auths/dovecot.h"
36 #endif
37
38 #ifdef AUTH_EXTERNAL
39 #include "auths/external.h"
40 #endif
41
42 #ifdef AUTH_GSASL
43 #include "auths/gsasl_exim.h"
44 #endif
45
46 #ifdef AUTH_HEIMDAL_GSSAPI
47 #include "auths/heimdal_gssapi.h"
48 #endif
49
50 #ifdef AUTH_PLAINTEXT
51 #include "auths/plaintext.h"
52 #endif
53
54 #ifdef AUTH_SPA
55 #include "auths/spa.h"
56 #endif
57
58 #ifdef AUTH_TLS
59 #include "auths/tls.h"
60 #endif
61
62 auth_info auths_available[] = {
63
64 /* Checking by an expansion condition on plain text */
65
66 #ifdef AUTH_CRAM_MD5
67   {
68   .driver_name =        US"cram_md5",                              /* lookup name */
69   .options =            auth_cram_md5_options,
70   .options_count =      &auth_cram_md5_options_count,
71   .options_block =      &auth_cram_md5_option_defaults,
72   .options_len =        sizeof(auth_cram_md5_options_block),
73   .init =               auth_cram_md5_init,
74   .servercode =         auth_cram_md5_server,
75   .clientcode =         auth_cram_md5_client,
76   .version_report =     NULL,
77   .macros_create =      NULL,
78   },
79 #endif
80
81 #ifdef AUTH_CYRUS_SASL
82   {
83   .driver_name =        US"cyrus_sasl",
84   .options =            auth_cyrus_sasl_options,
85   .options_count =      &auth_cyrus_sasl_options_count,
86   .options_block =      &auth_cyrus_sasl_option_defaults,
87   .options_len =        sizeof(auth_cyrus_sasl_options_block),
88   .init =               auth_cyrus_sasl_init,
89   .servercode =         auth_cyrus_sasl_server,
90   .clientcode =         NULL,
91   .version_report =     auth_cyrus_sasl_version_report,
92   .macros_create =      NULL,
93   },
94 #endif
95
96 #ifdef AUTH_DOVECOT
97   {
98   .driver_name =        US"dovecot",
99   .options =            auth_dovecot_options,
100   .options_count =      &auth_dovecot_options_count,
101   .options_block =      &auth_dovecot_option_defaults,
102   .options_len =        sizeof(auth_dovecot_options_block),
103   .init =               auth_dovecot_init,
104   .servercode =         auth_dovecot_server,
105   .clientcode =         NULL,
106   .version_report =     NULL,
107   .macros_create =      NULL,
108   },
109 #endif
110
111 #ifdef AUTH_EXTERNAL
112   {
113   .driver_name =        US"external",
114   .options =            auth_external_options,
115   .options_count =      &auth_external_options_count,
116   .options_block =      &auth_external_option_defaults,
117   .options_len =        sizeof(auth_external_options_block),
118   .init =               auth_external_init,
119   .servercode =         auth_external_server,
120   .clientcode =         auth_external_client,
121   .version_report =     NULL,
122   .macros_create =      NULL,
123   },
124 #endif
125
126 #ifdef AUTH_GSASL
127   {
128   .driver_name =        US"gsasl",
129   .options =            auth_gsasl_options,
130   .options_count =      &auth_gsasl_options_count,
131   .options_block =      &auth_gsasl_option_defaults,
132   .options_len =        sizeof(auth_gsasl_options_block),
133   .init =               auth_gsasl_init,
134   .servercode =         auth_gsasl_server,
135   .clientcode =         auth_gsasl_client,
136   .version_report =     auth_gsasl_version_report,
137   .macros_create =      auth_gsasl_macros,
138   },
139 #endif
140
141 #ifdef AUTH_HEIMDAL_GSSAPI
142   {
143   .driver_name =        US"heimdal_gssapi",
144   .options =            auth_heimdal_gssapi_options,
145   .options_count =      &auth_heimdal_gssapi_options_count,
146   .options_block =      &auth_heimdal_gssapi_option_defaults,
147   .options_len =        sizeof(auth_heimdal_gssapi_options_block),
148   .init =               auth_heimdal_gssapi_init,
149   .servercode =         auth_heimdal_gssapi_server,
150   .clientcode =         NULL,
151   .version_report =     auth_heimdal_gssapi_version_report,
152   .macros_create =      NULL,
153   },
154 #endif
155
156 #ifdef AUTH_PLAINTEXT
157   {
158   .driver_name =        US"plaintext",
159   .options =            auth_plaintext_options,
160   .options_count =      &auth_plaintext_options_count,
161   .options_block =      &auth_plaintext_option_defaults,
162   .options_len =        sizeof(auth_plaintext_options_block),
163   .init =               auth_plaintext_init,
164   .servercode =         auth_plaintext_server,
165   .clientcode =         auth_plaintext_client,
166   .version_report =     NULL,
167   .macros_create =      NULL,
168   },
169 #endif
170
171 #ifdef AUTH_SPA
172   {
173   .driver_name =        US"spa",
174   .options =            auth_spa_options,
175   .options_count =      &auth_spa_options_count,
176   .options_block =      &auth_spa_option_defaults,
177   .options_len =        sizeof(auth_spa_options_block),
178   .init =               auth_spa_init,
179   .servercode =         auth_spa_server,
180   .clientcode =         auth_spa_client,
181   .version_report =     NULL,
182   .macros_create =      NULL,
183   },
184 #endif
185
186 #ifdef AUTH_TLS
187   {
188   .driver_name =        US"tls",
189   .options =            auth_tls_options,
190   .options_count =      &auth_tls_options_count,
191   .options_block =      &auth_tls_option_defaults,
192   .options_len =        sizeof(auth_tls_options_block),
193   .init =               auth_tls_init,
194   .servercode =         auth_tls_server,
195   .clientcode =         NULL,
196   .version_report =     NULL,
197   .macros_create =      NULL,
198   },
199 #endif
200
201   { .driver_name = US"" }               /* end marker */
202 };
203
204
205 /* Tables of information about which routers and transports are included in the
206 exim binary. */
207
208 /* Pull in the necessary header files */
209
210 #include "routers/rf_functions.h"
211
212 #ifdef ROUTER_ACCEPT
213 #include "routers/accept.h"
214 #endif
215
216 #ifdef ROUTER_DNSLOOKUP
217 #include "routers/dnslookup.h"
218 #endif
219
220 #ifdef ROUTER_MANUALROUTE
221 #include "routers/manualroute.h"
222 #endif
223
224 #ifdef ROUTER_IPLITERAL
225 #include "routers/ipliteral.h"
226 #endif
227
228 #ifdef ROUTER_IPLOOKUP
229 #include "routers/iplookup.h"
230 #endif
231
232 #ifdef ROUTER_QUERYPROGRAM
233 #include "routers/queryprogram.h"
234 #endif
235
236 #ifdef ROUTER_REDIRECT
237 #include "routers/redirect.h"
238 #endif
239
240 #ifdef TRANSPORT_APPENDFILE
241 #include "transports/appendfile.h"
242 #endif
243
244 #ifdef TRANSPORT_AUTOREPLY
245 #include "transports/autoreply.h"
246 #endif
247
248 #ifdef TRANSPORT_LMTP
249 #include "transports/lmtp.h"
250 #endif
251
252 #ifdef TRANSPORT_PIPE
253 #include "transports/pipe.h"
254 #endif
255
256 #ifdef EXPERIMENTAL_QUEUEFILE
257 #include "transports/queuefile.h"
258 #endif
259
260 #ifdef TRANSPORT_SMTP
261 #include "transports/smtp.h"
262 #endif
263
264
265 /* Now set up the structures, terminated by an entry with a null name. */
266
267 router_info routers_available[] = {
268 #ifdef ROUTER_ACCEPT
269   {
270   .driver_name =        US"accept",
271   .options =            accept_router_options,
272   .options_count =      &accept_router_options_count,
273   .options_block =      &accept_router_option_defaults,
274   .options_len =        sizeof(accept_router_options_block),
275   .init =               accept_router_init,
276   .code =               accept_router_entry,
277   .tidyup =             NULL,     /* no tidyup entry */
278   .ri_flags =           ri_yestransport
279   },
280 #endif
281 #ifdef ROUTER_DNSLOOKUP
282   {
283   .driver_name =        US"dnslookup",
284   .options =            dnslookup_router_options,
285   .options_count =      &dnslookup_router_options_count,
286   .options_block =      &dnslookup_router_option_defaults,
287   .options_len =        sizeof(dnslookup_router_options_block),
288   .init =               dnslookup_router_init,
289   .code =               dnslookup_router_entry,
290   .tidyup =             NULL,     /* no tidyup entry */
291   .ri_flags =           ri_yestransport
292   },
293 #endif
294 #ifdef ROUTER_IPLITERAL
295   {
296   .driver_name =        US"ipliteral",
297   .options =            ipliteral_router_options,
298   .options_count =      &ipliteral_router_options_count,
299   .options_block =      &ipliteral_router_option_defaults,
300   .options_len =        sizeof(ipliteral_router_options_block),
301   .init =               ipliteral_router_init,
302   .code =               ipliteral_router_entry,
303   .tidyup =             NULL,     /* no tidyup entry */
304   .ri_flags =           ri_yestransport
305   },
306 #endif
307 #ifdef ROUTER_IPLOOKUP
308   {
309   .driver_name =        US"iplookup",
310   .options =            iplookup_router_options,
311   .options_count =      &iplookup_router_options_count,
312   .options_block =      &iplookup_router_option_defaults,
313   .options_len =        sizeof(iplookup_router_options_block),
314   .init =               iplookup_router_init,
315   .code =               iplookup_router_entry,
316   .tidyup =             NULL,     /* no tidyup entry */
317   .ri_flags =           ri_notransport
318   },
319 #endif
320 #ifdef ROUTER_MANUALROUTE
321   {
322   .driver_name =        US"manualroute",
323   .options =            manualroute_router_options,
324   .options_count =      &manualroute_router_options_count,
325   .options_block =      &manualroute_router_option_defaults,
326   .options_len =        sizeof(manualroute_router_options_block),
327   .init =               manualroute_router_init,
328   .code =               manualroute_router_entry,
329   .tidyup =             NULL,     /* no tidyup entry */
330   .ri_flags =           0
331   },
332 #endif
333 #ifdef ROUTER_QUERYPROGRAM
334   {
335   .driver_name =        US"queryprogram",
336   .options =            queryprogram_router_options,
337   .options_count =      &queryprogram_router_options_count,
338   .options_block =      &queryprogram_router_option_defaults,
339   .options_len =        sizeof(queryprogram_router_options_block),
340   .init =               queryprogram_router_init,
341   .code =               queryprogram_router_entry,
342   .tidyup =             NULL,     /* no tidyup entry */
343   .ri_flags =           0
344   },
345 #endif
346 #ifdef ROUTER_REDIRECT
347   {
348   .driver_name =        US"redirect",
349   .options =            redirect_router_options,
350   .options_count =      &redirect_router_options_count,
351   .options_block =      &redirect_router_option_defaults,
352   .options_len =        sizeof(redirect_router_options_block),
353   .init =               redirect_router_init,
354   .code =               redirect_router_entry,
355   .tidyup =             NULL,     /* no tidyup entry */
356   .ri_flags =           ri_notransport
357   },
358 #endif
359   { US"" }
360 };
361
362
363
364 transport_info transports_available[] = {
365 #ifdef TRANSPORT_APPENDFILE
366   {
367   .driver_name =        US"appendfile",
368   .options =            appendfile_transport_options,
369   .options_count =      &appendfile_transport_options_count,
370   .options_block =      &appendfile_transport_option_defaults,       /* private options defaults */
371   .options_len =        sizeof(appendfile_transport_options_block),
372   .init =               appendfile_transport_init,
373   .code =               appendfile_transport_entry,
374   .tidyup =             NULL,
375   .closedown =          NULL,
376   .local =              TRUE
377   },
378 #endif
379 #ifdef TRANSPORT_AUTOREPLY
380   {
381   .driver_name =        US"autoreply",
382   .options =            autoreply_transport_options,
383   .options_count =      &autoreply_transport_options_count,
384   .options_block =      &autoreply_transport_option_defaults,
385   .options_len =        sizeof(autoreply_transport_options_block),
386   .init =               autoreply_transport_init,
387   .code =               autoreply_transport_entry,
388   .tidyup =             NULL,
389   .closedown =          NULL,
390   .local =              TRUE
391   },
392 #endif
393 #ifdef TRANSPORT_LMTP
394   {
395   .driver_name =        US"lmtp",
396   .options =            lmtp_transport_options,
397   .options_count =      &lmtp_transport_options_count,
398   .options_block =      &lmtp_transport_option_defaults,
399   .options_len =        sizeof(lmtp_transport_options_block),
400   .init =               lmtp_transport_init,
401   .code =               lmtp_transport_entry,
402   .tidyup =             NULL,
403   .closedown =          NULL,
404   .local =              TRUE
405   },
406 #endif
407 #ifdef TRANSPORT_PIPE
408   {
409   .driver_name =        US"pipe",
410   .options =            pipe_transport_options,
411   .options_count =      &pipe_transport_options_count,
412   .options_block =      &pipe_transport_option_defaults,
413   .options_len =        sizeof(pipe_transport_options_block),
414   .init =               pipe_transport_init,
415   .code =               pipe_transport_entry,
416   .tidyup =             NULL,
417   .closedown =          NULL,
418   .local =              TRUE
419   },
420 #endif
421 #ifdef EXPERIMENTAL_QUEUEFILE
422   {
423   .driver_name =        US"queuefile",
424   .options =            queuefile_transport_options,
425   .options_count =      &queuefile_transport_options_count,
426   .options_block =      &queuefile_transport_option_defaults,
427   .options_len =        sizeof(queuefile_transport_options_block),
428   .init =               queuefile_transport_init,
429   .code =               queuefile_transport_entry,
430   .tidyup =             NULL,
431   .closedown =          NULL,
432   .local =              TRUE
433   },
434 #endif
435 #ifdef TRANSPORT_SMTP
436   {
437   .driver_name =        US"smtp",
438   .options =            smtp_transport_options,
439   .options_count =      &smtp_transport_options_count,
440   .options_block =      &smtp_transport_option_defaults,
441   .options_len =        sizeof(smtp_transport_options_block),
442   .init =               smtp_transport_init,
443   .code =               smtp_transport_entry,
444   .tidyup =             NULL,
445   .closedown =          smtp_transport_closedown,
446   .local =              FALSE
447   },
448 #endif
449   { US"" }
450 };
451
452 #ifndef MACRO_PREDEF
453
454 gstring *
455 auth_show_supported(gstring * g)
456 {
457 g = string_cat(g, US"Authenticators:");
458 for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
459         g = string_fmt_append(g, " %s", ai->driver_name);
460 return string_cat(g, US"\n");
461 }
462
463 gstring *
464 route_show_supported(gstring * g)
465 {
466 g = string_cat(g, US"Routers:");
467 for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
468         g = string_fmt_append(g, " %s", rr->driver_name);
469 return string_cat(g, US"\n");
470 }
471
472 gstring *
473 transport_show_supported(gstring * g)
474 {
475 g = string_cat(g, US"Transports:");
476 #ifdef TRANSPORT_APPENDFILE
477   g = string_cat(g, US" appendfile");
478   #ifdef SUPPORT_MAILDIR
479     g = string_cat(g, US"/maildir");    /* damn these subclasses */
480   #endif
481   #ifdef SUPPORT_MAILSTORE
482     g = string_cat(g, US"/mailstore");
483   #endif
484   #ifdef SUPPORT_MBX
485     g = string_cat(g, US"/mbx");
486   #endif
487 #endif
488 #ifdef TRANSPORT_AUTOREPLY
489   g = string_cat(g, US" autoreply");
490 #endif
491 #ifdef TRANSPORT_LMTP
492   g = string_cat(g, US" lmtp");
493 #endif
494 #ifdef TRANSPORT_PIPE
495   g = string_cat(g, US" pipe");
496 #endif
497 #ifdef EXPERIMENTAL_QUEUEFILE
498   g = string_cat(g, US" queuefile");
499 #endif
500 #ifdef TRANSPORT_SMTP
501   g = string_cat(g, US" smtp");
502 #endif
503 return string_cat(g, US"\n");
504 }
505
506
507
508 struct lookupmodulestr
509 {
510   void *dl;
511   struct lookup_module_info *info;
512   struct lookupmodulestr *next;
513 };
514
515 static struct lookupmodulestr *lookupmodules = NULL;
516
517 static void
518 addlookupmodule(void *dl, struct lookup_module_info *info)
519 {
520 struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
521
522 p->dl = dl;
523 p->info = info;
524 p->next = lookupmodules;
525 lookupmodules = p;
526 lookup_list_count += info->lookupcount;
527 }
528
529 /* only valid after lookup_list and lookup_list_count are assigned */
530 static void
531 add_lookup_to_list(lookup_info *info)
532 {
533 /* need to add the lookup to lookup_list, sorted */
534 int pos = 0;
535
536 /* strategy is to go through the list until we find
537 either an empty spot or a name that is higher.
538 this can't fail because we have enough space. */
539
540 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
541   pos++;
542
543 if (lookup_list[pos])
544   {
545   /* need to insert it, so move all the other items up
546   (last slot is still empty, of course) */
547
548   memmove(&lookup_list[pos+1], &lookup_list[pos],
549           sizeof(lookup_info *) * (lookup_list_count-pos-1));
550   }
551 lookup_list[pos] = info;
552 }
553
554
555 /* These need to be at file level for old versions of gcc (2.95.2 reported),
556  * which give parse errors on an extern in function scope.  Each entry needs
557  * to also be invoked in init_lookup_list() below  */
558
559 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
560 extern lookup_module_info cdb_lookup_module_info;
561 #endif
562 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
563 extern lookup_module_info dbmdb_lookup_module_info;
564 #endif
565 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
566 extern lookup_module_info dnsdb_lookup_module_info;
567 #endif
568 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
569 extern lookup_module_info dsearch_lookup_module_info;
570 #endif
571 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
572 extern lookup_module_info ibase_lookup_module_info;
573 #endif
574 #if defined(LOOKUP_JSON)
575 extern lookup_module_info json_lookup_module_info;
576 #endif
577 #if defined(LOOKUP_LDAP)
578 extern lookup_module_info ldap_lookup_module_info;
579 #endif
580 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
581 extern lookup_module_info lsearch_lookup_module_info;
582 #endif
583 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
584 extern lookup_module_info mysql_lookup_module_info;
585 #endif
586 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
587 extern lookup_module_info nis_lookup_module_info;
588 #endif
589 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
590 extern lookup_module_info nisplus_lookup_module_info;
591 #endif
592 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
593 extern lookup_module_info oracle_lookup_module_info;
594 #endif
595 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
596 extern lookup_module_info passwd_lookup_module_info;
597 #endif
598 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
599 extern lookup_module_info pgsql_lookup_module_info;
600 #endif
601 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
602 extern lookup_module_info redis_lookup_module_info;
603 #endif
604 #if defined(EXPERIMENTAL_LMDB)
605 extern lookup_module_info lmdb_lookup_module_info;
606 #endif
607 #if defined(SUPPORT_SPF)
608 extern lookup_module_info spf_lookup_module_info;
609 #endif
610 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
611 extern lookup_module_info sqlite_lookup_module_info;
612 #endif
613 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
614 extern lookup_module_info testdb_lookup_module_info;
615 #endif
616 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
617 extern lookup_module_info whoson_lookup_module_info;
618 #endif
619
620 extern lookup_module_info readsock_lookup_module_info;
621
622
623 void
624 init_lookup_list(void)
625 {
626 #ifdef LOOKUP_MODULE_DIR
627 DIR *dd;
628 struct dirent *ent;
629 int countmodules = 0;
630 int moduleerrors = 0;
631 #endif
632 static BOOL lookup_list_init_done = FALSE;
633 rmark reset_point;
634
635 if (lookup_list_init_done)
636   return;
637 reset_point = store_mark();
638 lookup_list_init_done = TRUE;
639
640 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
641 addlookupmodule(NULL, &cdb_lookup_module_info);
642 #endif
643
644 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
645 addlookupmodule(NULL, &dbmdb_lookup_module_info);
646 #endif
647
648 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
649 addlookupmodule(NULL, &dnsdb_lookup_module_info);
650 #endif
651
652 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
653 addlookupmodule(NULL, &dsearch_lookup_module_info);
654 #endif
655
656 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
657 addlookupmodule(NULL, &ibase_lookup_module_info);
658 #endif
659
660 #ifdef LOOKUP_LDAP
661 addlookupmodule(NULL, &ldap_lookup_module_info);
662 #endif
663
664 #ifdef LOOKUP_JSON
665 addlookupmodule(NULL, &json_lookup_module_info);
666 #endif
667
668 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
669 addlookupmodule(NULL, &lsearch_lookup_module_info);
670 #endif
671
672 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
673 addlookupmodule(NULL, &mysql_lookup_module_info);
674 #endif
675
676 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
677 addlookupmodule(NULL, &nis_lookup_module_info);
678 #endif
679
680 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
681 addlookupmodule(NULL, &nisplus_lookup_module_info);
682 #endif
683
684 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
685 addlookupmodule(NULL, &oracle_lookup_module_info);
686 #endif
687
688 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
689 addlookupmodule(NULL, &passwd_lookup_module_info);
690 #endif
691
692 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
693 addlookupmodule(NULL, &pgsql_lookup_module_info);
694 #endif
695
696 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
697 addlookupmodule(NULL, &redis_lookup_module_info);
698 #endif
699
700 #ifdef EXPERIMENTAL_LMDB
701 addlookupmodule(NULL, &lmdb_lookup_module_info);
702 #endif
703
704 #ifdef SUPPORT_SPF
705 addlookupmodule(NULL, &spf_lookup_module_info);
706 #endif
707
708 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
709 addlookupmodule(NULL, &sqlite_lookup_module_info);
710 #endif
711
712 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
713 addlookupmodule(NULL, &testdb_lookup_module_info);
714 #endif
715
716 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
717 addlookupmodule(NULL, &whoson_lookup_module_info);
718 #endif
719
720 addlookupmodule(NULL, &readsock_lookup_module_info);
721
722 #ifdef LOOKUP_MODULE_DIR
723 if (!(dd = exim_opendir(LOOKUP_MODULE_DIR)))
724   {
725   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
726   log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
727   }
728 else
729   {
730   const pcre *regex_islookupmod = regex_must_compile(
731     US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
732
733   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
734   while ((ent = readdir(dd)))
735     {
736     char *name = ent->d_name;
737     int len = (int)strlen(name);
738     if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0)
739       {
740       int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
741       void *dl;
742       struct lookup_module_info *info;
743       const char *errormsg;
744
745       /* SRH: am I being paranoid here or what? */
746       if (pathnamelen > big_buffer_size)
747         {
748         fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
749         log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
750         continue;
751         }
752
753       /* SRH: snprintf here? */
754       sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
755
756       if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
757         {
758         errormsg = dlerror();
759         fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
760         log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
761         moduleerrors++;
762         continue;
763         }
764
765       /* FreeBSD nsdispatch() can trigger dlerror() errors about
766        * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
767        * state before calling dlsym(), so that any error afterwards only
768        * comes from dlsym().
769        */
770       errormsg = dlerror();
771
772       info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
773       if ((errormsg = dlerror()))
774         {
775         fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
776         log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
777         dlclose(dl);
778         moduleerrors++;
779         continue;
780         }
781       if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
782         {
783         fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
784         log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
785         dlclose(dl);
786         moduleerrors++;
787         continue;
788         }
789
790       addlookupmodule(dl, info);
791       DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
792       countmodules++;
793       }
794     }
795   store_free((void*)regex_islookupmod);
796   closedir(dd);
797   }
798
799 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
800 #endif
801
802 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
803
804 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
805 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
806
807 /* now add all lookups to the real list */
808 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
809   for (int j = 0; j < p->info->lookupcount; j++)
810     add_lookup_to_list(p->info->lookups[j]);
811 store_reset(reset_point);
812 /* just to be sure */
813 lookupmodules = NULL;
814 }
815
816 #endif  /*!MACRO_PREDEF*/
817 /* End of drtables.c */