1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
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 */
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. */
21 //lookup_info **lookup_list;
22 tree_node * lookups_tree = NULL;
23 unsigned lookup_list_count = 0;
25 /* Lists of information about which drivers are included in the exim binary. */
27 auth_info * auths_available= NULL;
28 router_info * routers_available = NULL;
29 transport_info * transports_available = NULL;
36 auth_show_supported(gstring * g)
38 uschar * b = US"" /* static-build authenticatornames */
39 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5!=2
42 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL!=2
45 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT!=2
48 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL!=2
51 #if defined(AUTH_GSASL) && AUTH_GSASL!=2
54 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI!=2
57 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT!=2
60 #if defined(AUTH_SPA) && AUTH_SPA!=2
63 #if defined(AUTH_TLS) && AUTH_TLS!=2
68 uschar * d = US"" /* dynamic-module authenticator names */
69 #if defined(AUTH_CRAM_MD5) && AUTH_CRAM_MD5==2
72 #if defined(AUTH_CYRUS_SASL) && AUTH_CYRUS_SASL==2
75 #if defined(AUTH_DOVECOT) && AUTH_DOVECOT==2
78 #if defined(AUTH_EXTERNAL) && AUTH_EXTERNAL==2
81 #if defined(AUTH_GSASL) && AUTH_GSASL==2
84 #if defined(AUTH_HEIMDAL_GSSAPI) && AUTH_HEIMDAL_GSSAPI==2
87 #if defined(AUTH_PLAINTEXT) && AUTH_PLAINTEXT==2
90 #if defined(AUTH_SPA) && AUTH_SPA==2
93 #if defined(AUTH_TLS) && AUTH_TLS==2
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);
104 route_show_supported(gstring * g)
106 uschar * b = US"" /* static-build router names */
107 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
110 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
113 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
116 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
119 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
122 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
125 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
130 uschar * d = US"" /* dynamic-module router names */
131 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
134 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
137 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
140 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
143 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
146 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
149 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
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);
160 transport_show_supported(gstring * g)
162 uschar * b = US"" /* static-build transportnames */
163 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE!=2
165 # ifdef SUPPORT_MAILDIR
168 # ifdef SUPPORT_MAILSTORE
175 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY!=2
178 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP!=2
181 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE!=2
184 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE!=2
187 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP!=2
192 uschar * d = US"" /* dynamic-module transportnames */
193 #if defined(TRANSPORT_APPENDFILE) && TRANSPORT_APPENDFILE==2
195 # ifdef SUPPORT_MAILDIR
198 # ifdef SUPPORT_MAILSTORE
205 #if defined(TRANSPORT_AUTOREPLY) && TRANSPORT_AUTOREPLY==2
208 #if defined(TRANSPORT_LMTP) && TRANSPORT_LMTP==2
211 #if defined(TRANSPORT_PIPE) && TRANSPORT_PIPE==2
214 #if defined(EXPERIMENTAL_QUEUEFILE) && EXPERIMENTAL_QUEUEFILE==2
217 #if defined(TRANSPORT_SMTP) && TRANSPORT_SMTP==2
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);
230 add_lookup_to_tree(lookup_info * li)
232 tree_node * new = store_get_perm(sizeof(tree_node) + Ustrlen(li->name),
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++;
239 log_write(0, LOG_MAIN|LOG_PANIC, "Duplicate lookup name '%s'", li->name);
243 /* Add all the lookup types provided by the module */
245 addlookupmodule(const struct lookup_module_info * lmi)
247 for (int j = 0; j < lmi->lookupcount; j++)
248 add_lookup_to_tree(lmi->lookups[j]);
253 /* Hunt for the lookup with the given acquisition number */
255 static unsigned hunt_acq;
258 acq_cb(uschar * name, uschar * ptr, void * ctx)
260 lookup_info * li = (lookup_info *)ptr;
261 if (li->acq_num == hunt_acq) *(lookup_info **)ctx = li;
265 lookup_with_acq_num(unsigned k)
267 const lookup_info * li = NULL;
269 tree_walk(lookups_tree, acq_cb, &li);
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 */
279 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
280 extern lookup_module_info cdb_lookup_module_info;
282 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
283 extern lookup_module_info dbmdb_lookup_module_info;
285 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
286 extern lookup_module_info dnsdb_lookup_module_info;
288 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
289 extern lookup_module_info dsearch_lookup_module_info;
291 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
292 extern lookup_module_info ibase_lookup_module_info;
294 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
295 extern lookup_module_info json_lookup_module_info;
297 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
298 extern lookup_module_info ldap_lookup_module_info;
300 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
301 extern lookup_module_info lsearch_lookup_module_info;
303 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
304 extern lookup_module_info mysql_lookup_module_info;
306 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
307 extern lookup_module_info nis_lookup_module_info;
309 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
310 extern lookup_module_info nisplus_lookup_module_info;
312 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
313 extern lookup_module_info oracle_lookup_module_info;
315 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
316 extern lookup_module_info passwd_lookup_module_info;
318 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
319 extern lookup_module_info pgsql_lookup_module_info;
321 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
322 extern lookup_module_info redis_lookup_module_info;
324 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
325 extern lookup_module_info lmdb_lookup_module_info;
327 #if defined(SUPPORT_SPF)
328 extern lookup_module_info spf_lookup_module_info; /* see below */
330 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
331 extern lookup_module_info sqlite_lookup_module_info;
333 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
334 extern lookup_module_info testdb_lookup_module_info;
336 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
337 extern lookup_module_info whoson_lookup_module_info;
340 extern lookup_module_info readsock_lookup_module_info;
343 #ifdef LOOKUP_MODULE_DIR
345 mod_open(const uschar * name, const uschar * class, uschar ** errstr)
347 const uschar * path = string_sprintf(
348 LOOKUP_MODULE_DIR "/%s_%s." DYNLIB_FN_EXT, name, class);
350 if (!(dl = dlopen(CS path, RTLD_NOW)))
353 *errstr = string_sprintf("Error loading %s: %s", name, dlerror());
355 (void) dlerror(); /* clear out error state */
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
369 /* Try to load a lookup module with the given name.
372 name name of the lookup
373 errstr if not NULL, place "open fail" error message here
375 Return: boolean success
379 lookup_mod_load(const uschar * name, uschar ** errstr)
382 struct lookup_module_info * info;
383 const char * errormsg;
385 if (!(dl = mod_open(name, US"lookup", errstr)))
388 info = (struct lookup_module_info *) dlsym(dl, "_lookup_module_info");
389 if ((errormsg = dlerror()))
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);
396 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
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);
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" : "");
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).
418 lookup_one_mod_load(const uschar * name, uschar ** errstr)
420 if (!lookup_mod_load(name, errstr)) return FALSE;
421 /*XXX notify daemon? */
425 #endif /*LOOKUP_MODULE_DIR*/
429 misc_module_info * misc_module_list = NULL;
432 misc_mod_add(misc_module_info * mi)
434 if (mi->init) mi->init(mi);
435 DEBUG(D_any) if (mi->lib_vers_report)
436 debug_printf_indent("%Y", mi->lib_vers_report(NULL));
438 mi->next = misc_module_list;
439 misc_module_list = mi;
443 #ifdef LOOKUP_MODULE_DIR
445 /* Load a "misc" module, and add to list */
447 static misc_module_info *
448 misc_mod_load(const uschar * name, uschar ** errstr)
451 struct misc_module_info * mi;
452 const char * errormsg;
454 DEBUG(D_any) debug_printf_indent("loading module '%s'\n", name);
455 if (!(dl = mod_open(name, US"miscmod", errstr)))
458 mi = (struct misc_module_info *) dlsym(dl,
459 CS string_sprintf("%s_module_info", name));
460 if ((errormsg = dlerror()))
462 fprintf(stderr, "%s does not appear to be a '%s' module (%s)\n",
463 name, name, errormsg);
464 log_write(0, LOG_MAIN|LOG_PANIC,
465 "%s does not contain the expected module info symbol (%s)", name, errormsg);
469 if (mi->dyn_magic != MISC_MODULE_MAGIC)
471 fprintf(stderr, "Module %s is not compatible with this version of Exim\n", name);
472 log_write(0, LOG_MAIN|LOG_PANIC, "Module %s is not compatible with this version of Exim", name);
477 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\"\n", name);
482 #endif /*LOOKUP_MODULE_DIR*/
485 /* Find a "misc" module by name, if loaded.
486 For now use a linear search down a linked list. If the number of
487 modules gets large, we might consider a tree.
491 misc_mod_findonly(const uschar * name)
493 for (misc_module_info * mi = misc_module_list; mi; mi = mi->next)
494 if (Ustrcmp(name, mi->name) == 0)
499 /* Find a "misc" module, possibly already loaded, by name. */
502 misc_mod_find(const uschar * name, uschar ** errstr)
504 misc_module_info * mi;
505 if ((mi = misc_mod_findonly(name))) return mi;
506 #ifdef LOOKUP_MODULE_DIR
507 return misc_mod_load(name, errstr);
510 #endif /*LOOKUP_MODULE_DIR*/
514 /* For any "misc" module having a connection-init routine, call it. */
517 misc_mod_conn_init(const uschar * sender_helo_name,
518 const uschar * sender_host_address)
520 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
522 if ((mi->conn_init) (sender_helo_name, sender_host_address) != OK)
527 /* Ditto, smtp-reset */
530 misc_mod_smtp_reset(void)
532 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
537 /* Ditto, msg-init */
540 misc_mod_msg_init(void)
542 for (const misc_module_info * mi = misc_module_list; mi; mi = mi->next)
544 if ((mi->msg_init)() != OK)
554 init_lookup_list(void)
556 #ifdef LOOKUP_MODULE_DIR
558 int countmodules = 0;
560 static BOOL lookup_list_init_done = FALSE;
562 if (lookup_list_init_done)
564 lookup_list_init_done = TRUE;
566 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
567 addlookupmodule(&cdb_lookup_module_info);
570 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
571 addlookupmodule(&dbmdb_lookup_module_info);
574 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
575 addlookupmodule(&dnsdb_lookup_module_info);
578 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
579 addlookupmodule(&dsearch_lookup_module_info);
582 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
583 addlookupmodule(&ibase_lookup_module_info);
586 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
587 addlookupmodule(&ldap_lookup_module_info);
590 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
591 addlookupmodule(&json_lookup_module_info);
594 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
595 addlookupmodule(&lsearch_lookup_module_info);
598 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
599 addlookupmodule(&mysql_lookup_module_info);
602 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
603 addlookupmodule(&nis_lookup_module_info);
606 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
607 addlookupmodule(&nisplus_lookup_module_info);
610 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
611 addlookupmodule(&oracle_lookup_module_info);
614 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
615 addlookupmodule(&passwd_lookup_module_info);
618 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
619 addlookupmodule(&pgsql_lookup_module_info);
622 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
623 addlookupmodule(&redis_lookup_module_info);
626 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
627 addlookupmodule(&lmdb_lookup_module_info);
630 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
631 addlookupmodule(&sqlite_lookup_module_info);
634 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
635 addlookupmodule(&testdb_lookup_module_info);
638 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
639 addlookupmodule(&whoson_lookup_module_info);
642 /* This is provided by the spf "misc" module, and the lookup aspect is always
643 linked statically whether or not the "misc" module (and hence libspf2) is
646 #if defined(SUPPORT_SPF)
647 addlookupmodule(&spf_lookup_module_info);
650 /* This is a custom expansion, and not available as either
651 a list-syntax lookup or a lookup expansion. However, it is
652 implemented by a lookup module. */
654 addlookupmodule(&readsock_lookup_module_info);
656 DEBUG(D_lookup) debug_printf("Total %d built-in lookups\n", lookup_list_count);
659 #ifdef LOOKUP_MODULE_DIR
660 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
662 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
663 log_write(0, LOG_MAIN|LOG_PANIC,
664 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
668 /* Look specifically for modules we know offer several lookup types and
669 load them now, since we cannot load-on-first-use. */
672 const pcre2_code * regex_islookupmod = regex_must_compile(
673 US"(lsearch|ldap|nis)_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
675 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
676 while ((ent = readdir(dd)))
678 char * name = ent->d_name;
679 int len = (int)strlen(name);
680 if (regex_match_and_setup(regex_islookupmod, US name, 0, 0))
683 if (lookup_mod_load(expand_nstring[1], &errstr))
687 fprintf(stderr, "%s\n", errstr);
688 log_write(0, LOG_MAIN|LOG_PANIC, "%s", errstr);
695 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
700 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
701 extern misc_module_info dmarc_module_info;
703 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
704 extern misc_module_info spf_module_info;
708 init_misc_mod_list(void)
710 static BOOL onetime = FALSE;
713 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
714 /* dmarc depends on spf so this add must go first, for the dmarc-static case */
715 misc_mod_add(&spf_module_info);
717 #if defined(SUPPORT_DMARC) && SUPPORT_DMARC!=2
718 misc_mod_add(&dmarc_module_info);
725 #endif /*!MACRO_PREDEF*/
726 /* End of drtables.c */