b9d4650f1dc1cef660809a98d992d241ec64db19
[exim.git] / src / src / drtables.c
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) The Exim Maintainers 2020 - 2024 */
6 /* Copyright (c) University of Cambridge 1995 - 2018 */
7 /* See the file NOTICE for conditions of use and distribution. */
8 /* SPDX-License-Identifier: GPL-2.0-or-later */
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 tree_node * lookups_tree = NULL;
23 unsigned lookup_list_count = 0;
24
25 /* Lists of information about which drivers are included in the exim binary. */
26
27 auth_info * auths_available= NULL;
28 router_info * routers_available = NULL;
29 transport_info * transports_available = NULL;
30
31
32
33 #ifndef MACRO_PREDEF
34
35 gstring *
36 auth_show_supported(gstring * g)
37 {
38 uschar * b = US""               /* static-build authenticatornames */
39 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
40   " cram_md5"
41 #endif
42 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
43   " cyrus_sasl"
44 #endif
45 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
46   " dovecot"
47 #endif
48 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
49   " external"
50 #endif
51 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
52   " gsasl"
53 #endif
54 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
55   " heimdal_gssapi"
56 #endif
57 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
58   " plaintext"
59 #endif
60 #if defined(AUTH_SPA) && AUTH_SPA!=2
61   " spa"
62 #endif
63 #if defined(AUTH_TLS) && AUTH_TLS!=2
64   " tls"
65 #endif
66   ;
67
68 uschar * d = US""               /* dynamic-module authenticator names */
69 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
70   " cram_md5"
71 #endif
72 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
73   " cyrus_sasl"
74 #endif
75 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
76   " dovecot"
77 #endif
78 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
79   " external"
80 #endif
81 #if defined(AUTH_GSASL) && AUTH_GSASL==2
82   " gsasl"
83 #endif
84 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
85   " heimdal_gssapi"
86 #endif
87 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
88   " plaintext"
89 #endif
90 #if defined(AUTH_SPA) && AUTH_SPA==2
91   " spa"
92 #endif
93 #if defined(AUTH_TLS) && AUTH_TLS==2
94   " tls"
95 #endif
96   ;
97
98 if (*b) g = string_fmt_append(g, "Authenticators (built-in):%s\n", b);
99 if (*d) g = string_fmt_append(g, "Authenticators (dynamic): %s\n", d);
100 return g;
101 }
102
103 gstring *
104 route_show_supported(gstring * g)
105 {
106 uschar * b = US""               /* static-build router names */
107 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
108   " accept"
109 #endif
110 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
111   " dnslookup"
112 #endif
113 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
114   " ipliteral"
115 #endif
116 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
117   " iplookup"
118 #endif
119 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
120   " manualroute"
121 #endif
122 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
123   " redirect"
124 #endif
125 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
126   " queryprogram"
127 #endif
128   ;
129
130 uschar * d = US""               /* dynamic-module router names */
131 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
132   " accept"
133 #endif
134 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
135   " dnslookup"
136 #endif
137 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
138   " ipliteral"
139 #endif
140 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
141   " iplookup"
142 #endif
143 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
144   " manualroute"
145 #endif
146 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
147   " redirect"
148 #endif
149 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
150   " queryprogram"
151 #endif
152   ;
153
154 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
155 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
156 return g;
157 }
158
159 gstring *
160 transport_show_supported(gstring * g)
161 {
162 uschar * b = US""               /* static-build transportnames */
163 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
164   " appendfile"
165 # ifdef SUPPORT_MAILDIR
166     "/maildir"
167 # endif
168 # ifdef SUPPORT_MAILSTORE
169     "/mailstore"
170 # endif
171 # ifdef SUPPORT_MBX
172     "/mbx"
173 # endif
174 #endif
175 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
176   " autoreply"
177 #endif
178 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
179   " lmtp"
180 #endif
181 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
182   " pipe"
183 #endif
184 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
185   " queuefile"
186 #endif
187 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
188   " smtp"
189 #endif
190   ;
191
192 uschar * d = US""               /* dynamic-module transportnames */
193 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
194   " appendfile"
195 # ifdef SUPPORT_MAILDIR
196     "/maildir"
197 # endif
198 # ifdef SUPPORT_MAILSTORE
199     "/mailstore"
200 # endif
201 # ifdef SUPPORT_MBX
202     "/mbx"
203 # endif
204 #endif
205 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
206   " autoreply"
207 #endif
208 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
209   " lmtp"
210 #endif
211 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
212   " pipe"
213 #endif
214 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
215   " queuefile"
216 #endif
217 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
218   " smtp"
219 #endif
220   ;
221
222 if (*b) g = string_fmt_append(g, "Transports (built-in):%s\n", b);
223 if (*d) g = string_fmt_append(g, "Transports (dynamic): %s\n", d);
224 return g;
225 }
226
227
228
229 static void
230 add_lookup_to_tree(lookup_info * li)
231 {
232 tree_node * new = store_get_perm(sizeof(tree_node) + Ustrlen(li->name),
233                                                         GET_UNTAINTED);
234 new->data.ptr = (void *)li;
235 Ustrcpy(new->name, li->name);
236 if (tree_insertnode(&lookups_tree, new))
237   li->acq_num = lookup_list_count++;
238 else
239   log_write(0, LOG_MAIN|LOG_PANIC, "Duplicate lookup name '%s'", li->name);
240 }
241
242
243 /* Add all the lookup types provided by the module */
244 static void
245 addlookupmodule(const struct lookup_module_info * lmi)
246 {
247 for (int j = 0; j < lmi->lookupcount; j++)
248   add_lookup_to_tree(lmi->lookups[j]);
249 }
250
251
252
253 /* Hunt for the lookup with the given acquisition number */
254
255 static unsigned hunt_acq;
256
257 static void
258 acq_cb(uschar * name, uschar * ptr, void * ctx)
259 {
260 lookup_info * li = (lookup_info *)ptr;
261 if (li->acq_num == hunt_acq) *(lookup_info **)ctx = li;
262 }
263
264 const lookup_info *
265 lookup_with_acq_num(unsigned k)
266 {
267 const lookup_info * li = NULL;
268 hunt_acq = k;
269 tree_walk(lookups_tree, acq_cb, &li);
270 return li;
271 }
272
273
274
275 /* These need to be at file level for old versions of gcc (2.95.2 reported),
276 which give parse errors on an extern in function scope.  Each entry needs
277 to also be invoked in init_lookup_list() below  */
278
279 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
280 extern lookup_module_info cdb_lookup_module_info;
281 #endif
282 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
283 extern lookup_module_info dbmdb_lookup_module_info;
284 #endif
285 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
286 extern lookup_module_info dnsdb_lookup_module_info;
287 #endif
288 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
289 extern lookup_module_info dsearch_lookup_module_info;
290 #endif
291 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
292 extern lookup_module_info ibase_lookup_module_info;
293 #endif
294 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
295 extern lookup_module_info json_lookup_module_info;
296 #endif
297 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
298 extern lookup_module_info ldap_lookup_module_info;
299 #endif
300 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
301 extern lookup_module_info lsearch_lookup_module_info;
302 #endif
303 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
304 extern lookup_module_info mysql_lookup_module_info;
305 #endif
306 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
307 extern lookup_module_info nis_lookup_module_info;
308 #endif
309 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
310 extern lookup_module_info nisplus_lookup_module_info;
311 #endif
312 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
313 extern lookup_module_info oracle_lookup_module_info;
314 #endif
315 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
316 extern lookup_module_info passwd_lookup_module_info;
317 #endif
318 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
319 extern lookup_module_info pgsql_lookup_module_info;
320 #endif
321 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
322 extern lookup_module_info redis_lookup_module_info;
323 #endif
324 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
325 extern lookup_module_info lmdb_lookup_module_info;
326 #endif
327 #if defined(SUPPORT_SPF)
328 extern lookup_module_info spf_lookup_module_info;       /* see below */
329 #endif
330 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
331 extern lookup_module_info sqlite_lookup_module_info;
332 #endif
333 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
334 extern lookup_module_info testdb_lookup_module_info;
335 #endif
336 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
337 extern lookup_module_info whoson_lookup_module_info;
338 #endif
339
340 extern lookup_module_info readsock_lookup_module_info;
341
342
343 #ifdef LOOKUP_MODULE_DIR
344 static void *
345 mod_open(const uschar * name, const uschar * class, uschar ** errstr)
346 {
347 const uschar * path = string_sprintf(
348   LOOKUP_MODULE_DIR "/%s_%s." DYNLIB_FN_EXT, name, class);
349 void * dl;
350 if (!(dl = dlopen(CS path, RTLD_NOW)))
351   {
352   if (errstr)
353     *errstr = string_sprintf("Error loading %s: %s", name, dlerror());
354   else
355     (void) dlerror();           /* clear out error state */
356   return NULL;
357   }
358
359 /* FreeBSD nsdispatch() can trigger dlerror() errors about
360 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
361 state before calling dlsym(), so that any error afterwards only comes
362 from dlsym().  */
363
364 (void) dlerror();
365 return dl;
366 }
367
368
369 /* Try to load a lookup module with the given name.
370
371 Arguments:
372     name                name of the lookup
373     errstr              if not NULL, place "open fail" error message here
374
375 Return: boolean success
376 */
377
378 static BOOL
379 lookup_mod_load(const uschar * name, uschar ** errstr)
380 {
381 void * dl;
382 struct lookup_module_info * info;
383 const char * errormsg;
384
385 if (!(dl = mod_open(name, US"lookup", errstr)))
386   return FALSE;
387
388 info = (struct lookup_module_info *) dlsym(dl, "_lookup_module_info");
389 if ((errormsg = dlerror()))
390   {
391   fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
392   log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)", name, errormsg);
393   dlclose(dl);
394   return FALSE;
395   }
396 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
397   {
398   fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
399   log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim", name);
400   dlclose(dl);
401   return FALSE;
402   }
403
404 addlookupmodule(info);
405 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\" (%d lookup type%s)\n",
406                                     name, info->lookupcount,
407                                     info->lookupcount > 1 ? "s" : "");
408 return TRUE;
409 }
410
411
412 /* Try to load a lookup module, assuming the module name is the same
413 as the lookup type name.  This will only work for single-method modules.
414 Other have to be always-load (see the RE in init_lookup_list() below).
415 */
416
417 BOOL
418 lookup_one_mod_load(const uschar * name, uschar ** errstr)
419 {
420 if (!lookup_mod_load(name, errstr)) return FALSE;
421 /*XXX notify daemon? */
422 return TRUE;
423 }
424
425 #endif  /*LOOKUP_MODULE_DIR*/
426
427
428
429 misc_module_info * misc_module_list = NULL;
430
431 static void
432 misc_mod_add(misc_module_info * mi)
433 {
434 if (mi->init && mi->init(mi))
435   {
436   DEBUG(D_any) if (mi->lib_vers_report)
437     debug_printf_indent("%Y", mi->lib_vers_report(NULL));
438
439   mi->next = misc_module_list;
440   misc_module_list = mi;
441   }
442 else DEBUG(D_any)
443   debug_printf_indent("module init call failed for %s\n", mi->name);
444 /* fprintf(stderr,"misc_mod_add: added %s\n", mi->name); */
445 }
446
447
448 #ifdef LOOKUP_MODULE_DIR
449
450 /* Load a "misc" module, and add to list */
451
452 static misc_module_info *
453 misc_mod_load(const uschar * name, uschar ** errstr)
454 {
455 void * dl;
456 struct misc_module_info * mi;
457 const char * errormsg;
458
459 DEBUG(D_any) debug_printf_indent("loading module '%s'\n", name);
460 if (!(dl = mod_open(name, US"miscmod", errstr)))
461   {
462   DEBUG(D_any) debug_printf_indent(" mod_open: %s\n", *errstr);
463   return NULL;
464   }
465
466 mi = (struct misc_module_info *) dlsym(dl,
467                                     CS string_sprintf("%s_module_info", name));
468 if ((errormsg = dlerror()))
469   {
470   fprintf(stderr, "%s does not appear to be a '%s' module (%s)\n",
471           name, name, errormsg);
472   log_write(0, LOG_MAIN|LOG_PANIC,
473     "%s does not contain the expected module info symbol (%s)", name, errormsg);
474   dlclose(dl);
475   return NULL;
476   }
477 if (mi->dyn_magic != MISC_MODULE_MAGIC)
478   {
479   fprintf(stderr, "Module %s is not compatible with this version of Exim\n", name);
480   log_write(0, LOG_MAIN|LOG_PANIC, "Module %s is not compatible with this version of Exim", name);
481   dlclose(dl);
482   return FALSE;
483   }
484
485 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\"\n", name);
486 misc_mod_add(mi);
487 return mi;
488 }
489
490 #endif  /*LOOKUP_MODULE_DIR*/
491
492
493 /* Find a "misc" module by name, if loaded.
494 For now use a linear search down a linked list.  If the number of
495 modules gets large, we might consider a tree.
496 */
497
498 misc_module_info *
499 misc_mod_findonly(const uschar * name)
500 {
501 for (misc_module_info * mi = misc_module_list; mi; mi = mi->next)
502   if (Ustrcmp(name, mi->name) == 0)
503     return mi;
504 return NULL;
505 }
506
507 /* Find a "misc" module, possibly already loaded, by name. */
508
509 misc_module_info *
510 misc_mod_find(const uschar * name, uschar ** errstr)
511 {
512 misc_module_info * mi;
513 if ((mi = misc_mod_findonly(name))) return mi;
514 #ifdef LOOKUP_MODULE_DIR
515 return misc_mod_load(name, errstr);
516 #else
517 return NULL;
518 #endif  /*LOOKUP_MODULE_DIR*/
519 }
520
521
522 /* For any "misc" module having a connection-init routine, call it. */
523
524 int
525 misc_mod_conn_init(const uschar * sender_helo_name,
526   const uschar * sender_host_address)
527 {
528 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
529   if (mi->conn_init)
530     if ((mi->conn_init) (sender_helo_name, sender_host_address) != OK)
531       return FAIL;
532 return OK;
533 }
534
535 /* Ditto, smtp-reset */
536
537 void
538 misc_mod_smtp_reset(void)
539 {
540 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
541   if (mi->smtp_reset)
542     (mi->smtp_reset)();
543 }
544
545 /* Ditto, msg-init */
546
547 int
548 misc_mod_msg_init(void)
549 {
550 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
551   if (mi->msg_init)
552     if ((mi->msg_init)() != OK)
553       return FAIL;
554 return OK;
555 }
556
557 /* Ditto, authres.  Having to sort the responses (mainly for the testsuite)
558 is pretty painful - maybe we should sort the modules on insertion to
559 the list? */
560
561 gstring *
562 misc_mod_authres(gstring * g)
563 {
564 typedef struct {
565   const uschar * name;
566   gstring *      res;
567 } pref;
568 pref prefs[] = {
569   {US"spf", NULL}, {US"dkim", NULL}, {US"dmarc", NULL}, {US"arc", NULL}
570 };
571 gstring * others = NULL;
572
573 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
574   if (mi->authres)
575     {
576     pref * p;
577     for (p = prefs; p < prefs + nelem(prefs); p++)
578       if (Ustrcmp(p->name, mi->name) == 0) break;
579
580     if (p) p->res = (mi->authres)(NULL);
581     else   others = (mi->authres)(others);
582     }
583
584 for (pref * p = prefs; p < prefs + nelem(prefs); p++)
585   g = gstring_append(g, p->res);
586 return gstring_append(g, others);
587 }
588
589
590
591
592
593
594 void
595 init_lookup_list(void)
596 {
597 #ifdef LOOKUP_MODULE_DIR
598 DIR * dd;
599 int countmodules = 0;
600 #endif
601 static BOOL lookup_list_init_done = FALSE;
602
603 if (lookup_list_init_done)
604   return;
605 lookup_list_init_done = TRUE;
606
607 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
608 addlookupmodule(&cdb_lookup_module_info);
609 #endif
610
611 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
612 addlookupmodule(&dbmdb_lookup_module_info);
613 #endif
614
615 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
616 addlookupmodule(&dnsdb_lookup_module_info);
617 #endif
618
619 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
620 addlookupmodule(&dsearch_lookup_module_info);
621 #endif
622
623 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
624 addlookupmodule(&ibase_lookup_module_info);
625 #endif
626
627 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
628 addlookupmodule(&ldap_lookup_module_info);
629 #endif
630
631 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
632 addlookupmodule(&json_lookup_module_info);
633 #endif
634
635 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
636 addlookupmodule(&lsearch_lookup_module_info);
637 #endif
638
639 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
640 addlookupmodule(&mysql_lookup_module_info);
641 #endif
642
643 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
644 addlookupmodule(&nis_lookup_module_info);
645 #endif
646
647 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
648 addlookupmodule(&nisplus_lookup_module_info);
649 #endif
650
651 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
652 addlookupmodule(&oracle_lookup_module_info);
653 #endif
654
655 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
656 addlookupmodule(&passwd_lookup_module_info);
657 #endif
658
659 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
660 addlookupmodule(&pgsql_lookup_module_info);
661 #endif
662
663 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
664 addlookupmodule(&redis_lookup_module_info);
665 #endif
666
667 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
668 addlookupmodule(&lmdb_lookup_module_info);
669 #endif
670
671 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
672 addlookupmodule(&sqlite_lookup_module_info);
673 #endif
674
675 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
676 addlookupmodule(&testdb_lookup_module_info);
677 #endif
678
679 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
680 addlookupmodule(&whoson_lookup_module_info);
681 #endif
682
683 /* This is provided by the spf "misc" module, and the lookup aspect is always
684 linked statically whether or not the "misc" module (and hence libspf2) is
685 dynamic-load. */
686
687 #if defined(SUPPORT_SPF)
688 addlookupmodule(&spf_lookup_module_info);
689 #endif
690
691 /* This is a custom expansion, and not available as either
692 a list-syntax lookup or a lookup expansion. However, it is
693 implemented by a lookup module. */
694
695 addlookupmodule(&readsock_lookup_module_info);
696
697 DEBUG(D_lookup) debug_printf("Total %d built-in lookups\n", lookup_list_count);
698
699
700 #ifdef LOOKUP_MODULE_DIR
701 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
702   {
703   DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
704   log_write(0, LOG_MAIN|LOG_PANIC,
705           "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
706   }
707 else
708   {
709   /* Look specifically for modules we know offer several lookup types and
710   load them now, since we cannot load-on-first-use. */
711
712   struct dirent * ent;
713   const pcre2_code * regex_islookupmod = regex_must_compile(
714     US"(lsearch|ldap|nis)_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
715
716   DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
717   while ((ent = readdir(dd)))
718     {
719     char * name = ent->d_name;
720     int len = (int)strlen(name);
721     if (regex_match_and_setup(regex_islookupmod, US name, 0, 0))
722       {
723       uschar * errstr;
724       if (lookup_mod_load(expand_nstring[1], &errstr))
725         countmodules++;
726       else
727         {
728         fprintf(stderr, "%s\n", errstr);
729         log_write(0, LOG_MAIN|LOG_PANIC, "%s", errstr);
730         }
731       }
732     }
733   closedir(dd);
734   }
735
736 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
737 #endif
738 }
739
740
741 /* Add module info struct to the modules list for those that are
742 built as static */
743
744 #if !defined(DISABLE_DKIM) && (!defined(SUPPORT_DKIM) || SUPPORT_DKIM!=2)
745 extern misc_module_info dkim_module_info;
746 #endif
747 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
748 extern misc_module_info dmarc_module_info;
749 #endif
750 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
751 extern misc_module_info spf_module_info;
752 #endif
753 #if defined(EXPERIMENTAL_ARC) && (!defined(SUPPORT_ARC) || SUPPORT_ARC!=2)
754 extern misc_module_info arc_module_info;
755 #endif
756 #if defined(RADIUS_CONFIG_FILE) && (!defined(SUPPORT_RADIUS) || SUPPORT_RADUIS!=2)
757 extern misc_module_info radius_module_info;
758 #endif
759 #if defined(SUPPORT_PAM) && SUPPORT_PAM!=2
760 extern misc_module_info pam_module_info;
761 #endif
762
763 void
764 init_misc_mod_list(void)
765 {
766 static BOOL onetime = FALSE;
767 if (onetime) return;
768 onetime = TRUE;
769
770 #if !defined(DISABLE_DKIM) && (!defined(SUPPORT_DKIM) || SUPPORT_DKIM!=2)
771   misc_mod_add(&dkim_module_info);
772 #endif
773 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
774   misc_mod_add(&spf_module_info);
775 #endif
776 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
777 /* dmarc depends on spf so this add must go after, for the both-static case */
778   misc_mod_add(&dmarc_module_info);
779 #endif
780 #if defined(EXPERIMENTAL_ARC) && (!defined(SUPPORT_ARC) || SUPPORT_ARC!=2)
781   misc_mod_add(&arc_module_info);
782 #endif
783 #if defined(RADIUS_CONFIG_FILE) && (!defined(SUPPORT_RADIUS) || SUPPORT_RADUIS!=2)
784   misc_mod_add(&radius_module_info);
785 #endif
786 #if defined(SUPPORT_PAM) && SUPPORT_PAM!=2
787   misc_mod_add(&pam_module_info);
788 #endif
789 }
790
791
792 #endif  /*!MACRO_PREDEF*/
793 /* End of drtables.c */