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_lookup) if (mi->lib_vers_report)
436 debug_printf_indent("%Y\n", 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 an spf module (%s)\n", name, errormsg);
463 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be an spf module (%s)", name, errormsg);
467 if (mi->dyn_magic != MISC_MODULE_MAGIC)
469 fprintf(stderr, "Module %s is not compatible with this version of Exim\n", name);
470 log_write(0, LOG_MAIN|LOG_PANIC, "Module %s is not compatible with this version of Exim", name);
475 DEBUG(D_lookup) debug_printf_indent("Loaded \"%s\"\n", name);
480 #endif /*LOOKUP_MODULE_DIR*/
483 /* Find a "misc" module by name, if loaded.
484 For now use a linear search down a linked list. If the number of
485 modules gets large, we might consider a tree.
489 misc_mod_findonly(const uschar * name)
491 for (misc_module_info * mi = misc_module_list; mi; mi = mi->next)
492 if (Ustrcmp(name, mi->name) == 0)
496 /* Find a "misc" module, possibly already loaded, by name. */
499 misc_mod_find(const uschar * name, uschar ** errstr)
501 misc_module_info * mi;
502 if ((mi = misc_mod_findonly(name))) return mi;
503 #ifdef LOOKUP_MODULE_DIR
504 return misc_mod_load(name, errstr);
507 #endif /*LOOKUP_MODULE_DIR*/
515 init_lookup_list(void)
517 #ifdef LOOKUP_MODULE_DIR
519 int countmodules = 0;
521 static BOOL lookup_list_init_done = FALSE;
523 if (lookup_list_init_done)
525 lookup_list_init_done = TRUE;
527 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
528 addlookupmodule(&cdb_lookup_module_info);
531 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
532 addlookupmodule(&dbmdb_lookup_module_info);
535 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
536 addlookupmodule(&dnsdb_lookup_module_info);
539 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
540 addlookupmodule(&dsearch_lookup_module_info);
543 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
544 addlookupmodule(&ibase_lookup_module_info);
547 #if defined(LOOKUP_LDAP) && LOOKUP_LDAP!=2
548 addlookupmodule(&ldap_lookup_module_info);
551 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
552 addlookupmodule(&json_lookup_module_info);
555 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
556 addlookupmodule(&lsearch_lookup_module_info);
559 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
560 addlookupmodule(&mysql_lookup_module_info);
563 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
564 addlookupmodule(&nis_lookup_module_info);
567 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
568 addlookupmodule(&nisplus_lookup_module_info);
571 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
572 addlookupmodule(&oracle_lookup_module_info);
575 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
576 addlookupmodule(&passwd_lookup_module_info);
579 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
580 addlookupmodule(&pgsql_lookup_module_info);
583 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
584 addlookupmodule(&redis_lookup_module_info);
587 #if defined(LOOKUP_LMDB) && LOOKUP_LMDB!=2
588 addlookupmodule(&lmdb_lookup_module_info);
591 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
592 addlookupmodule(&sqlite_lookup_module_info);
595 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
596 addlookupmodule(&testdb_lookup_module_info);
599 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
600 addlookupmodule(&whoson_lookup_module_info);
603 /* This is provided by the spf "misc" module, and the lookup aspect is always
604 linked statically whether or not the "misc" module (and hence libspf2) is
607 #if defined(SUPPORT_SPF)
608 addlookupmodule(&spf_lookup_module_info);
611 /* This is a custom expansion, and not available as either
612 a list-syntax lookup or a lookup expansion. However, it is
613 implemented by a lookup module. */
615 addlookupmodule(&readsock_lookup_module_info);
617 DEBUG(D_lookup) debug_printf("Total %d built-in lookups\n", lookup_list_count);
620 #ifdef LOOKUP_MODULE_DIR
621 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
623 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
624 log_write(0, LOG_MAIN|LOG_PANIC,
625 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
629 /* Look specifically for modules we know offer several lookup types and
630 load them now, since we cannot load-on-first-use. */
633 const pcre2_code * regex_islookupmod = regex_must_compile(
634 US"(lsearch|ldap|nis)_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
636 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
637 while ((ent = readdir(dd)))
639 char * name = ent->d_name;
640 int len = (int)strlen(name);
641 if (regex_match_and_setup(regex_islookupmod, US name, 0, 0))
644 if (lookup_mod_load(expand_nstring[1], &errstr))
648 fprintf(stderr, "%s\n", errstr);
649 log_write(0, LOG_MAIN|LOG_PANIC, "%s", errstr);
656 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
661 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
662 extern misc_module_info spf_module_info;
666 init_misc_mod_list(void)
668 static BOOL onetime = FALSE;
670 #if defined(SUPPORT_SPF) && SUPPORT_SPF!=2
671 misc_mod_add(&spf_module_info);
677 #endif /*!MACRO_PREDEF*/
678 /* End of drtables.c */