558359032170e8a28dc96285a505dea757dc1b0e
[users/jgh/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 void
205 auth_show_supported(FILE * f)
206 {
207 fprintf(f, "Authenticators:");
208 for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
209         fprintf(f, " %s", ai->driver_name);
210 fprintf(f, "\n");
211 }
212
213
214 /* Tables of information about which routers and transports are included in the
215 exim binary. */
216
217 /* Pull in the necessary header files */
218
219 #include "routers/rf_functions.h"
220
221 #ifdef ROUTER_ACCEPT
222 #include "routers/accept.h"
223 #endif
224
225 #ifdef ROUTER_DNSLOOKUP
226 #include "routers/dnslookup.h"
227 #endif
228
229 #ifdef ROUTER_MANUALROUTE
230 #include "routers/manualroute.h"
231 #endif
232
233 #ifdef ROUTER_IPLITERAL
234 #include "routers/ipliteral.h"
235 #endif
236
237 #ifdef ROUTER_IPLOOKUP
238 #include "routers/iplookup.h"
239 #endif
240
241 #ifdef ROUTER_QUERYPROGRAM
242 #include "routers/queryprogram.h"
243 #endif
244
245 #ifdef ROUTER_REDIRECT
246 #include "routers/redirect.h"
247 #endif
248
249 #ifdef TRANSPORT_APPENDFILE
250 #include "transports/appendfile.h"
251 #endif
252
253 #ifdef TRANSPORT_AUTOREPLY
254 #include "transports/autoreply.h"
255 #endif
256
257 #ifdef TRANSPORT_LMTP
258 #include "transports/lmtp.h"
259 #endif
260
261 #ifdef TRANSPORT_PIPE
262 #include "transports/pipe.h"
263 #endif
264
265 #ifdef EXPERIMENTAL_QUEUEFILE
266 #include "transports/queuefile.h"
267 #endif
268
269 #ifdef TRANSPORT_SMTP
270 #include "transports/smtp.h"
271 #endif
272
273
274 /* Now set up the structures, terminated by an entry with a null name. */
275
276 router_info routers_available[] = {
277 #ifdef ROUTER_ACCEPT
278   {
279   .driver_name =        US"accept",
280   .options =            accept_router_options,
281   .options_count =      &accept_router_options_count,
282   .options_block =      &accept_router_option_defaults,
283   .options_len =        sizeof(accept_router_options_block),
284   .init =               accept_router_init,
285   .code =               accept_router_entry,
286   .tidyup =             NULL,     /* no tidyup entry */
287   .ri_flags =           ri_yestransport
288   },
289 #endif
290 #ifdef ROUTER_DNSLOOKUP
291   {
292   .driver_name =        US"dnslookup",
293   .options =            dnslookup_router_options,
294   .options_count =      &dnslookup_router_options_count,
295   .options_block =      &dnslookup_router_option_defaults,
296   .options_len =        sizeof(dnslookup_router_options_block),
297   .init =               dnslookup_router_init,
298   .code =               dnslookup_router_entry,
299   .tidyup =             NULL,     /* no tidyup entry */
300   .ri_flags =           ri_yestransport
301   },
302 #endif
303 #ifdef ROUTER_IPLITERAL
304   {
305   .driver_name =        US"ipliteral",
306   .options =            ipliteral_router_options,
307   .options_count =      &ipliteral_router_options_count,
308   .options_block =      &ipliteral_router_option_defaults,
309   .options_len =        sizeof(ipliteral_router_options_block),
310   .init =               ipliteral_router_init,
311   .code =               ipliteral_router_entry,
312   .tidyup =             NULL,     /* no tidyup entry */
313   .ri_flags =           ri_yestransport
314   },
315 #endif
316 #ifdef ROUTER_IPLOOKUP
317   {
318   .driver_name =        US"iplookup",
319   .options =            iplookup_router_options,
320   .options_count =      &iplookup_router_options_count,
321   .options_block =      &iplookup_router_option_defaults,
322   .options_len =        sizeof(iplookup_router_options_block),
323   .init =               iplookup_router_init,
324   .code =               iplookup_router_entry,
325   .tidyup =             NULL,     /* no tidyup entry */
326   .ri_flags =           ri_notransport
327   },
328 #endif
329 #ifdef ROUTER_MANUALROUTE
330   {
331   .driver_name =        US"manualroute",
332   .options =            manualroute_router_options,
333   .options_count =      &manualroute_router_options_count,
334   .options_block =      &manualroute_router_option_defaults,
335   .options_len =        sizeof(manualroute_router_options_block),
336   .init =               manualroute_router_init,
337   .code =               manualroute_router_entry,
338   .tidyup =             NULL,     /* no tidyup entry */
339   .ri_flags =           0
340   },
341 #endif
342 #ifdef ROUTER_QUERYPROGRAM
343   {
344   .driver_name =        US"queryprogram",
345   .options =            queryprogram_router_options,
346   .options_count =      &queryprogram_router_options_count,
347   .options_block =      &queryprogram_router_option_defaults,
348   .options_len =        sizeof(queryprogram_router_options_block),
349   .init =               queryprogram_router_init,
350   .code =               queryprogram_router_entry,
351   .tidyup =             NULL,     /* no tidyup entry */
352   .ri_flags =           0
353   },
354 #endif
355 #ifdef ROUTER_REDIRECT
356   {
357   .driver_name =        US"redirect",
358   .options =            redirect_router_options,
359   .options_count =      &redirect_router_options_count,
360   .options_block =      &redirect_router_option_defaults,
361   .options_len =        sizeof(redirect_router_options_block),
362   .init =               redirect_router_init,
363   .code =               redirect_router_entry,
364   .tidyup =             NULL,     /* no tidyup entry */
365   .ri_flags =           ri_notransport
366   },
367 #endif
368   { US"" }
369 };
370
371
372 void
373 route_show_supported(FILE * f)
374 {
375 fprintf(f, "Routers:");
376 for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
377         fprintf(f, " %s", rr->driver_name);
378 fprintf(f, "\n");
379 }
380
381
382
383
384 transport_info transports_available[] = {
385 #ifdef TRANSPORT_APPENDFILE
386   {
387   .driver_name =        US"appendfile",
388   .options =            appendfile_transport_options,
389   .options_count =      &appendfile_transport_options_count,
390   .options_block =      &appendfile_transport_option_defaults,       /* private options defaults */
391   .options_len =        sizeof(appendfile_transport_options_block),
392   .init =               appendfile_transport_init,
393   .code =               appendfile_transport_entry,
394   .tidyup =             NULL,
395   .closedown =          NULL,
396   .local =              TRUE
397   },
398 #endif
399 #ifdef TRANSPORT_AUTOREPLY
400   {
401   .driver_name =        US"autoreply",
402   .options =            autoreply_transport_options,
403   .options_count =      &autoreply_transport_options_count,
404   .options_block =      &autoreply_transport_option_defaults,
405   .options_len =        sizeof(autoreply_transport_options_block),
406   .init =               autoreply_transport_init,
407   .code =               autoreply_transport_entry,
408   .tidyup =             NULL,
409   .closedown =          NULL,
410   .local =              TRUE
411   },
412 #endif
413 #ifdef TRANSPORT_LMTP
414   {
415   .driver_name =        US"lmtp",
416   .options =            lmtp_transport_options,
417   .options_count =      &lmtp_transport_options_count,
418   .options_block =      &lmtp_transport_option_defaults,
419   .options_len =        sizeof(lmtp_transport_options_block),
420   .init =               lmtp_transport_init,
421   .code =               lmtp_transport_entry,
422   .tidyup =             NULL,
423   .closedown =          NULL,
424   .local =              TRUE
425   },
426 #endif
427 #ifdef TRANSPORT_PIPE
428   {
429   .driver_name =        US"pipe",
430   .options =            pipe_transport_options,
431   .options_count =      &pipe_transport_options_count,
432   .options_block =      &pipe_transport_option_defaults,
433   .options_len =        sizeof(pipe_transport_options_block),
434   .init =               pipe_transport_init,
435   .code =               pipe_transport_entry,
436   .tidyup =             NULL,
437   .closedown =          NULL,
438   .local =              TRUE
439   },
440 #endif
441 #ifdef EXPERIMENTAL_QUEUEFILE
442   {
443   .driver_name =        US"queuefile",
444   .options =            queuefile_transport_options,
445   .options_count =      &queuefile_transport_options_count,
446   .options_block =      &queuefile_transport_option_defaults,
447   .options_len =        sizeof(queuefile_transport_options_block),
448   .init =               queuefile_transport_init,
449   .code =               queuefile_transport_entry,
450   .tidyup =             NULL,
451   .closedown =          NULL,
452   .local =              TRUE
453   },
454 #endif
455 #ifdef TRANSPORT_SMTP
456   {
457   .driver_name =        US"smtp",
458   .options =            smtp_transport_options,
459   .options_count =      &smtp_transport_options_count,
460   .options_block =      &smtp_transport_option_defaults,
461   .options_len =        sizeof(smtp_transport_options_block),
462   .init =               smtp_transport_init,
463   .code =               smtp_transport_entry,
464   .tidyup =             NULL,
465   .closedown =          smtp_transport_closedown,
466   .local =              FALSE
467   },
468 #endif
469   { US"" }
470 };
471
472 void
473 transport_show_supported(FILE * f)
474 {
475 fprintf(f, "Transports:");
476 #ifdef TRANSPORT_APPENDFILE
477   fprintf(f, " appendfile");
478   #ifdef SUPPORT_MAILDIR
479     fprintf(f, "/maildir");     /* damn these subclasses */
480   #endif
481   #ifdef SUPPORT_MAILSTORE
482     fprintf(f, "/mailstore");
483   #endif
484   #ifdef SUPPORT_MBX
485     fprintf(f, "/mbx");
486   #endif
487 #endif
488 #ifdef TRANSPORT_AUTOREPLY
489   fprintf(f, " autoreply");
490 #endif
491 #ifdef TRANSPORT_LMTP
492   fprintf(f, " lmtp");
493 #endif
494 #ifdef TRANSPORT_PIPE
495   fprintf(f, " pipe");
496 #endif
497 #ifdef EXPERIMENTAL_QUEUEFILE
498   fprintf(f, " queuefile");
499 #endif
500 #ifdef TRANSPORT_SMTP
501   fprintf(f, " smtp");
502 #endif
503 fprintf(f, "\n");
504 }
505
506
507 #ifndef MACRO_PREDEF
508
509 struct lookupmodulestr
510 {
511   void *dl;
512   struct lookup_module_info *info;
513   struct lookupmodulestr *next;
514 };
515
516 static struct lookupmodulestr *lookupmodules = NULL;
517
518 static void
519 addlookupmodule(void *dl, struct lookup_module_info *info)
520 {
521 struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
522
523 p->dl = dl;
524 p->info = info;
525 p->next = lookupmodules;
526 lookupmodules = p;
527 lookup_list_count += info->lookupcount;
528 }
529
530 /* only valid after lookup_list and lookup_list_count are assigned */
531 static void
532 add_lookup_to_list(lookup_info *info)
533 {
534 /* need to add the lookup to lookup_list, sorted */
535 int pos = 0;
536
537 /* strategy is to go through the list until we find
538 either an empty spot or a name that is higher.
539 this can't fail because we have enough space. */
540
541 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
542   pos++;
543
544 if (lookup_list[pos])
545   {
546   /* need to insert it, so move all the other items up
547   (last slot is still empty, of course) */
548
549   memmove(&lookup_list[pos+1],
550           &lookup_list[pos],
551           sizeof(lookup_info *) * (lookup_list_count-pos-1));
552   }
553 lookup_list[pos] = info;
554 }
555
556
557 /* These need to be at file level for old versions of gcc (2.95.2 reported),
558  * which give parse errors on an extern in function scope.  Each entry needs
559  * to also be invoked in init_lookup_list() below  */
560
561 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
562 extern lookup_module_info cdb_lookup_module_info;
563 #endif
564 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
565 extern lookup_module_info dbmdb_lookup_module_info;
566 #endif
567 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
568 extern lookup_module_info dnsdb_lookup_module_info;
569 #endif
570 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
571 extern lookup_module_info dsearch_lookup_module_info;
572 #endif
573 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
574 extern lookup_module_info ibase_lookup_module_info;
575 #endif
576 #if defined(LOOKUP_JSON)
577 extern lookup_module_info json_lookup_module_info;
578 #endif
579 #if defined(LOOKUP_LDAP)
580 extern lookup_module_info ldap_lookup_module_info;
581 #endif
582 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
583 extern lookup_module_info lsearch_lookup_module_info;
584 #endif
585 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
586 extern lookup_module_info mysql_lookup_module_info;
587 #endif
588 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
589 extern lookup_module_info nis_lookup_module_info;
590 #endif
591 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
592 extern lookup_module_info nisplus_lookup_module_info;
593 #endif
594 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
595 extern lookup_module_info oracle_lookup_module_info;
596 #endif
597 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
598 extern lookup_module_info passwd_lookup_module_info;
599 #endif
600 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
601 extern lookup_module_info pgsql_lookup_module_info;
602 #endif
603 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
604 extern lookup_module_info redis_lookup_module_info;
605 #endif
606 #if defined(EXPERIMENTAL_LMDB)
607 extern lookup_module_info lmdb_lookup_module_info;
608 #endif
609 #if defined(SUPPORT_SPF)
610 extern lookup_module_info spf_lookup_module_info;
611 #endif
612 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
613 extern lookup_module_info sqlite_lookup_module_info;
614 #endif
615 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
616 extern lookup_module_info testdb_lookup_module_info;
617 #endif
618 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
619 extern lookup_module_info whoson_lookup_module_info;
620 #endif
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 #ifdef LOOKUP_MODULE_DIR
721 if (!(dd = opendir(LOOKUP_MODULE_DIR)))
722   {
723   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
724   log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
725   }
726 else
727   {
728   const pcre *regex_islookupmod = regex_must_compile(
729     US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
730
731   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
732   while ((ent = readdir(dd)))
733     {
734     char *name = ent->d_name;
735     int len = (int)strlen(name);
736     if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0)
737       {
738       int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
739       void *dl;
740       struct lookup_module_info *info;
741       const char *errormsg;
742
743       /* SRH: am I being paranoid here or what? */
744       if (pathnamelen > big_buffer_size)
745         {
746         fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
747         log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
748         continue;
749         }
750
751       /* SRH: snprintf here? */
752       sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
753
754       if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
755         {
756         errormessage = dlerror();
757         fprintf(stderr, "Error loading %s: %s\n", name, errormessage);
758         moduleerrors++;
759         log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormessage);
760         continue;
761         }
762
763       /* FreeBSD nsdispatch() can trigger dlerror() errors about
764        * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
765        * state before calling dlsym(), so that any error afterwards only
766        * comes from dlsym().
767        */
768       errormsg = dlerror();
769
770       info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
771       if ((errormsg = dlerror()))
772         {
773         fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
774         dlclose(dl);
775         moduleerrors++;
776         log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
777         continue;
778         }
779       if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
780         {
781         fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
782         dlclose(dl);
783         moduleerrors++;
784         log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
785         continue;
786         }
787
788       addlookupmodule(dl, info);
789       DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
790       countmodules++;
791       }
792     }
793   store_free((void*)regex_islookupmod);
794   closedir(dd);
795   }
796
797 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
798 #endif
799
800 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
801
802 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
803 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
804
805 /* now add all lookups to the real list */
806 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
807   for (int j = 0; j < p->info->lookupcount; j++)
808     add_lookup_to_list(p->info->lookups[j]);
809 store_reset(reset_point);
810 /* just to be sure */
811 lookupmodules = NULL;
812 }
813
814 #endif  /*!MACRO_PREDEF*/
815 /* End of drtables.c */