Fix unaligned access (more cleanly) in DNS regative-caching
[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   },
78 #endif
79
80 #ifdef AUTH_CYRUS_SASL
81   {
82   .driver_name =        US"cyrus_sasl",
83   .options =            auth_cyrus_sasl_options,
84   .options_count =      &auth_cyrus_sasl_options_count,
85   .options_block =      &auth_cyrus_sasl_option_defaults,
86   .options_len =        sizeof(auth_cyrus_sasl_options_block),
87   .init =               auth_cyrus_sasl_init,
88   .servercode =         auth_cyrus_sasl_server,
89   .clientcode =         NULL,
90   .version_report =     auth_cyrus_sasl_version_report
91   },
92 #endif
93
94 #ifdef AUTH_DOVECOT
95   {
96   .driver_name =        US"dovecot",
97   .options =            auth_dovecot_options,
98   .options_count =      &auth_dovecot_options_count,
99   .options_block =      &auth_dovecot_option_defaults,
100   .options_len =        sizeof(auth_dovecot_options_block),
101   .init =               auth_dovecot_init,
102   .servercode =         auth_dovecot_server,
103   .clientcode =         NULL,
104   .version_report =     NULL
105   },
106 #endif
107
108 #ifdef AUTH_EXTERNAL
109   {
110   .driver_name =        US"external",
111   .options =            auth_external_options,
112   .options_count =      &auth_external_options_count,
113   .options_block =      &auth_external_option_defaults,
114   .options_len =        sizeof(auth_external_options_block),
115   .init =               auth_external_init,
116   .servercode =         auth_external_server,
117   .clientcode =         auth_external_client,
118   .version_report =     NULL
119   },
120 #endif
121
122 #ifdef AUTH_GSASL
123   {
124   .driver_name =        US"gsasl",
125   .options =            auth_gsasl_options,
126   .options_count =      &auth_gsasl_options_count,
127   .options_block =      &auth_gsasl_option_defaults,
128   .options_len =        sizeof(auth_gsasl_options_block),
129   .init =               auth_gsasl_init,
130   .servercode =         auth_gsasl_server,
131   .clientcode =         NULL,
132   .version_report =     auth_gsasl_version_report
133   },
134 #endif
135
136 #ifdef AUTH_HEIMDAL_GSSAPI
137   {
138   .driver_name =        US"heimdal_gssapi",
139   .options =            auth_heimdal_gssapi_options,
140   .options_count =      &auth_heimdal_gssapi_options_count,
141   .options_block =      &auth_heimdal_gssapi_option_defaults,
142   .options_len =        sizeof(auth_heimdal_gssapi_options_block),
143   .init =               auth_heimdal_gssapi_init,
144   .servercode =         auth_heimdal_gssapi_server,
145   .clientcode =         NULL,
146   .version_report =     auth_heimdal_gssapi_version_report
147   },
148 #endif
149
150 #ifdef AUTH_PLAINTEXT
151   {
152   .driver_name =        US"plaintext",
153   .options =            auth_plaintext_options,
154   .options_count =      &auth_plaintext_options_count,
155   .options_block =      &auth_plaintext_option_defaults,
156   .options_len =        sizeof(auth_plaintext_options_block),
157   .init =               auth_plaintext_init,
158   .servercode =         auth_plaintext_server,
159   .clientcode =         auth_plaintext_client,
160   .version_report =     NULL
161   },
162 #endif
163
164 #ifdef AUTH_SPA
165   {
166   .driver_name =        US"spa",
167   .options =            auth_spa_options,
168   .options_count =      &auth_spa_options_count,
169   .options_block =      &auth_spa_option_defaults,
170   .options_len =        sizeof(auth_spa_options_block),
171   .init =               auth_spa_init,
172   .servercode =         auth_spa_server,
173   .clientcode =         auth_spa_client,
174   .version_report =     NULL
175   },
176 #endif
177
178 #ifdef AUTH_TLS
179   {
180   .driver_name =        US"tls",
181   .options =            auth_tls_options,
182   .options_count =      &auth_tls_options_count,
183   .options_block =      &auth_tls_option_defaults,
184   .options_len =        sizeof(auth_tls_options_block),
185   .init =               auth_tls_init,
186   .servercode =         auth_tls_server,
187   .clientcode =         NULL,
188   .version_report =     NULL
189   },
190 #endif
191
192   { .driver_name = US"" }               /* end marker */
193 };
194
195 void
196 auth_show_supported(FILE * f)
197 {
198 fprintf(f, "Authenticators:");
199 for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
200         fprintf(f, " %s", ai->driver_name);
201 fprintf(f, "\n");
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 void
364 route_show_supported(FILE * f)
365 {
366 fprintf(f, "Routers:");
367 for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
368         fprintf(f, " %s", rr->driver_name);
369 fprintf(f, "\n");
370 }
371
372
373
374
375 transport_info transports_available[] = {
376 #ifdef TRANSPORT_APPENDFILE
377   {
378   .driver_name =        US"appendfile",
379   .options =            appendfile_transport_options,
380   .options_count =      &appendfile_transport_options_count,
381   .options_block =      &appendfile_transport_option_defaults,       /* private options defaults */
382   .options_len =        sizeof(appendfile_transport_options_block),
383   .init =               appendfile_transport_init,
384   .code =               appendfile_transport_entry,
385   .tidyup =             NULL,
386   .closedown =          NULL,
387   .local =              TRUE
388   },
389 #endif
390 #ifdef TRANSPORT_AUTOREPLY
391   {
392   .driver_name =        US"autoreply",
393   .options =            autoreply_transport_options,
394   .options_count =      &autoreply_transport_options_count,
395   .options_block =      &autoreply_transport_option_defaults,
396   .options_len =        sizeof(autoreply_transport_options_block),
397   .init =               autoreply_transport_init,
398   .code =               autoreply_transport_entry,
399   .tidyup =             NULL,
400   .closedown =          NULL,
401   .local =              TRUE
402   },
403 #endif
404 #ifdef TRANSPORT_LMTP
405   {
406   .driver_name =        US"lmtp",
407   .options =            lmtp_transport_options,
408   .options_count =      &lmtp_transport_options_count,
409   .options_block =      &lmtp_transport_option_defaults,
410   .options_len =        sizeof(lmtp_transport_options_block),
411   .init =               lmtp_transport_init,
412   .code =               lmtp_transport_entry,
413   .tidyup =             NULL,
414   .closedown =          NULL,
415   .local =              TRUE
416   },
417 #endif
418 #ifdef TRANSPORT_PIPE
419   {
420   .driver_name =        US"pipe",
421   .options =            pipe_transport_options,
422   .options_count =      &pipe_transport_options_count,
423   .options_block =      &pipe_transport_option_defaults,
424   .options_len =        sizeof(pipe_transport_options_block),
425   .init =               pipe_transport_init,
426   .code =               pipe_transport_entry,
427   .tidyup =             NULL,
428   .closedown =          NULL,
429   .local =              TRUE
430   },
431 #endif
432 #ifdef EXPERIMENTAL_QUEUEFILE
433   {
434   .driver_name =        US"queuefile",
435   .options =            queuefile_transport_options,
436   .options_count =      &queuefile_transport_options_count,
437   .options_block =      &queuefile_transport_option_defaults,
438   .options_len =        sizeof(queuefile_transport_options_block),
439   .init =               queuefile_transport_init,
440   .code =               queuefile_transport_entry,
441   .tidyup =             NULL,
442   .closedown =          NULL,
443   .local =              TRUE
444   },
445 #endif
446 #ifdef TRANSPORT_SMTP
447   {
448   .driver_name =        US"smtp",
449   .options =            smtp_transport_options,
450   .options_count =      &smtp_transport_options_count,
451   .options_block =      &smtp_transport_option_defaults,
452   .options_len =        sizeof(smtp_transport_options_block),
453   .init =               smtp_transport_init,
454   .code =               smtp_transport_entry,
455   .tidyup =             NULL,
456   .closedown =          smtp_transport_closedown,
457   .local =              FALSE
458   },
459 #endif
460   { US"" }
461 };
462
463 void
464 transport_show_supported(FILE * f)
465 {
466 fprintf(f, "Transports:");
467 #ifdef TRANSPORT_APPENDFILE
468   fprintf(f, " appendfile");
469   #ifdef SUPPORT_MAILDIR
470     fprintf(f, "/maildir");     /* damn these subclasses */
471   #endif
472   #ifdef SUPPORT_MAILSTORE
473     fprintf(f, "/mailstore");
474   #endif
475   #ifdef SUPPORT_MBX
476     fprintf(f, "/mbx");
477   #endif
478 #endif
479 #ifdef TRANSPORT_AUTOREPLY
480   fprintf(f, " autoreply");
481 #endif
482 #ifdef TRANSPORT_LMTP
483   fprintf(f, " lmtp");
484 #endif
485 #ifdef TRANSPORT_PIPE
486   fprintf(f, " pipe");
487 #endif
488 #ifdef EXPERIMENTAL_QUEUEFILE
489   fprintf(f, " queuefile");
490 #endif
491 #ifdef TRANSPORT_SMTP
492   fprintf(f, " smtp");
493 #endif
494 fprintf(f, "\n");
495 }
496
497
498 #ifndef MACRO_PREDEF
499
500 struct lookupmodulestr
501 {
502   void *dl;
503   struct lookup_module_info *info;
504   struct lookupmodulestr *next;
505 };
506
507 static struct lookupmodulestr *lookupmodules = NULL;
508
509 static void
510 addlookupmodule(void *dl, struct lookup_module_info *info)
511 {
512 struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
513
514 p->dl = dl;
515 p->info = info;
516 p->next = lookupmodules;
517 lookupmodules = p;
518 lookup_list_count += info->lookupcount;
519 }
520
521 /* only valid after lookup_list and lookup_list_count are assigned */
522 static void
523 add_lookup_to_list(lookup_info *info)
524 {
525 /* need to add the lookup to lookup_list, sorted */
526 int pos = 0;
527
528 /* strategy is to go through the list until we find
529 either an empty spot or a name that is higher.
530 this can't fail because we have enough space. */
531
532 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
533   pos++;
534
535 if (lookup_list[pos])
536   {
537   /* need to insert it, so move all the other items up
538   (last slot is still empty, of course) */
539
540   memmove(&lookup_list[pos+1],
541           &lookup_list[pos],
542           sizeof(lookup_info *) * (lookup_list_count-pos-1));
543   }
544 lookup_list[pos] = info;
545 }
546
547
548 /* These need to be at file level for old versions of gcc (2.95.2 reported),
549  * which give parse errors on an extern in function scope.  Each entry needs
550  * to also be invoked in init_lookup_list() below  */
551
552 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
553 extern lookup_module_info cdb_lookup_module_info;
554 #endif
555 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
556 extern lookup_module_info dbmdb_lookup_module_info;
557 #endif
558 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
559 extern lookup_module_info dnsdb_lookup_module_info;
560 #endif
561 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
562 extern lookup_module_info dsearch_lookup_module_info;
563 #endif
564 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
565 extern lookup_module_info ibase_lookup_module_info;
566 #endif
567 #if defined(LOOKUP_JSON)
568 extern lookup_module_info json_lookup_module_info;
569 #endif
570 #if defined(LOOKUP_LDAP)
571 extern lookup_module_info ldap_lookup_module_info;
572 #endif
573 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
574 extern lookup_module_info lsearch_lookup_module_info;
575 #endif
576 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
577 extern lookup_module_info mysql_lookup_module_info;
578 #endif
579 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
580 extern lookup_module_info nis_lookup_module_info;
581 #endif
582 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
583 extern lookup_module_info nisplus_lookup_module_info;
584 #endif
585 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
586 extern lookup_module_info oracle_lookup_module_info;
587 #endif
588 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
589 extern lookup_module_info passwd_lookup_module_info;
590 #endif
591 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
592 extern lookup_module_info pgsql_lookup_module_info;
593 #endif
594 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
595 extern lookup_module_info redis_lookup_module_info;
596 #endif
597 #if defined(EXPERIMENTAL_LMDB)
598 extern lookup_module_info lmdb_lookup_module_info;
599 #endif
600 #if defined(SUPPORT_SPF)
601 extern lookup_module_info spf_lookup_module_info;
602 #endif
603 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
604 extern lookup_module_info sqlite_lookup_module_info;
605 #endif
606 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
607 extern lookup_module_info testdb_lookup_module_info;
608 #endif
609 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
610 extern lookup_module_info whoson_lookup_module_info;
611 #endif
612
613
614 void
615 init_lookup_list(void)
616 {
617 #ifdef LOOKUP_MODULE_DIR
618   DIR *dd;
619   struct dirent *ent;
620   int countmodules = 0;
621   int moduleerrors = 0;
622 #endif
623   static BOOL lookup_list_init_done = FALSE;
624   rmark reset_point;
625
626   if (lookup_list_init_done)
627     return;
628   reset_point = store_mark();
629   lookup_list_init_done = TRUE;
630
631 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
632   addlookupmodule(NULL, &cdb_lookup_module_info);
633 #endif
634
635 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
636   addlookupmodule(NULL, &dbmdb_lookup_module_info);
637 #endif
638
639 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
640   addlookupmodule(NULL, &dnsdb_lookup_module_info);
641 #endif
642
643 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
644   addlookupmodule(NULL, &dsearch_lookup_module_info);
645 #endif
646
647 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
648   addlookupmodule(NULL, &ibase_lookup_module_info);
649 #endif
650
651 #ifdef LOOKUP_LDAP
652   addlookupmodule(NULL, &ldap_lookup_module_info);
653 #endif
654
655 #ifdef LOOKUP_JSON
656   addlookupmodule(NULL, &json_lookup_module_info);
657 #endif
658
659 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
660   addlookupmodule(NULL, &lsearch_lookup_module_info);
661 #endif
662
663 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
664   addlookupmodule(NULL, &mysql_lookup_module_info);
665 #endif
666
667 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
668   addlookupmodule(NULL, &nis_lookup_module_info);
669 #endif
670
671 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
672   addlookupmodule(NULL, &nisplus_lookup_module_info);
673 #endif
674
675 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
676   addlookupmodule(NULL, &oracle_lookup_module_info);
677 #endif
678
679 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
680   addlookupmodule(NULL, &passwd_lookup_module_info);
681 #endif
682
683 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
684   addlookupmodule(NULL, &pgsql_lookup_module_info);
685 #endif
686
687 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
688   addlookupmodule(NULL, &redis_lookup_module_info);
689 #endif
690
691 #ifdef EXPERIMENTAL_LMDB
692   addlookupmodule(NULL, &lmdb_lookup_module_info);
693 #endif
694
695 #ifdef SUPPORT_SPF
696   addlookupmodule(NULL, &spf_lookup_module_info);
697 #endif
698
699 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
700   addlookupmodule(NULL, &sqlite_lookup_module_info);
701 #endif
702
703 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
704   addlookupmodule(NULL, &testdb_lookup_module_info);
705 #endif
706
707 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
708   addlookupmodule(NULL, &whoson_lookup_module_info);
709 #endif
710
711 #ifdef LOOKUP_MODULE_DIR
712   dd = opendir(LOOKUP_MODULE_DIR);
713   if (dd == NULL) {
714     DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
715     log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
716   }
717   else {
718     const pcre *regex_islookupmod = regex_must_compile(
719       US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
720
721     DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
722     while ((ent = readdir(dd)) != NULL) {
723       char *name = ent->d_name;
724       int len = (int)strlen(name);
725       if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0) {
726         int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
727         void *dl;
728         struct lookup_module_info *info;
729         const char *errormsg;
730
731         /* SRH: am I being paranoid here or what? */
732         if (pathnamelen > big_buffer_size) {
733           fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
734           log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
735           continue;
736         }
737
738         /* SRH: snprintf here? */
739         sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
740
741         dl = dlopen(CS big_buffer, RTLD_NOW);// TJ was LAZY
742         if (dl == NULL) {
743           fprintf(stderr, "Error loading %s: %s\n", name, dlerror());
744           moduleerrors++;
745           log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, dlerror());
746           continue;
747         }
748
749         /* FreeBSD nsdispatch() can trigger dlerror() errors about
750          * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
751          * state before calling dlsym(), so that any error afterwards only
752          * comes from dlsym().
753          */
754         errormsg = dlerror();
755
756         info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
757         if ((errormsg = dlerror()) != NULL) {
758           fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
759           dlclose(dl);
760           moduleerrors++;
761           log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
762           continue;
763         }
764         if (info->magic != LOOKUP_MODULE_INFO_MAGIC) {
765           fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
766           dlclose(dl);
767           moduleerrors++;
768           log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
769           continue;
770         }
771
772         addlookupmodule(dl, info);
773         DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
774         countmodules++;
775       }
776     }
777     store_free((void*)regex_islookupmod);
778     closedir(dd);
779   }
780
781   DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
782 #endif
783
784   DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
785
786   lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
787   memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
788
789   /* now add all lookups to the real list */
790   for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
791     for (int j = 0; j < p->info->lookupcount; j++)
792       add_lookup_to_list(p->info->lookups[j]);
793   store_reset(reset_point);
794   /* just to be sure */
795   lookupmodules = NULL;
796 }
797
798 #endif  /*!MACRO_PREDEF*/
799 /* End of drtables.c */