1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) The Exim Maintainers 2020 - 2023 */
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 int lookup_list_count = 0;
24 /* Table of information about all possible authentication mechanisms. All
25 entries are always present if any mechanism is declared, but the functions are
26 set to NULL for those that are not compiled into the binary. */
29 #include "auths/cram_md5.h"
32 #ifdef AUTH_CYRUS_SASL
33 #include "auths/cyrus_sasl.h"
37 #include "auths/dovecot.h"
41 #include "auths/external.h"
45 #include "auths/gsasl_exim.h"
48 #ifdef AUTH_HEIMDAL_GSSAPI
49 #include "auths/heimdal_gssapi.h"
53 #include "auths/plaintext.h"
57 #include "auths/spa.h"
61 #include "auths/tls.h"
64 auth_info * auths_available_newlist = NULL;
65 auth_info auths_available_oldarray[] = {
67 /* Checking by an expansion condition on plain text */
72 .driver_name = US"cram_md5", /* lookup name */
73 .options = auth_cram_md5_options,
74 .options_count = &auth_cram_md5_options_count,
75 .options_block = &auth_cram_md5_option_defaults,
76 .options_len = sizeof(auth_cram_md5_options_block),
77 .init = auth_cram_md5_init,
79 .servercode = auth_cram_md5_server,
80 .clientcode = auth_cram_md5_client,
81 .version_report = NULL,
82 .macros_create = NULL,
86 #ifdef AUTH_CYRUS_SASL
89 .driver_name = US"cyrus_sasl",
90 .options = auth_cyrus_sasl_options,
91 .options_count = &auth_cyrus_sasl_options_count,
92 .options_block = &auth_cyrus_sasl_option_defaults,
93 .options_len = sizeof(auth_cyrus_sasl_options_block),
94 .init = auth_cyrus_sasl_init,
96 .servercode = auth_cyrus_sasl_server,
98 .version_report = auth_cyrus_sasl_version_report,
99 .macros_create = NULL,
106 .driver_name = US"dovecot",
107 .options = auth_dovecot_options,
108 .options_count = &auth_dovecot_options_count,
109 .options_block = &auth_dovecot_option_defaults,
110 .options_len = sizeof(auth_dovecot_options_block),
111 .init = auth_dovecot_init,
113 .servercode = auth_dovecot_server,
115 .version_report = NULL,
116 .macros_create = NULL,
123 .driver_name = US"external",
124 .options = auth_external_options,
125 .options_count = &auth_external_options_count,
126 .options_block = &auth_external_option_defaults,
127 .options_len = sizeof(auth_external_options_block),
128 .init = auth_external_init,
130 .servercode = auth_external_server,
131 .clientcode = auth_external_client,
132 .version_report = NULL,
133 .macros_create = NULL,
140 .driver_name = US"gsasl",
141 .options = auth_gsasl_options,
142 .options_count = &auth_gsasl_options_count,
143 .options_block = &auth_gsasl_option_defaults,
144 .options_len = sizeof(auth_gsasl_options_block),
145 .init = auth_gsasl_init,
147 .servercode = auth_gsasl_server,
148 .clientcode = auth_gsasl_client,
149 .version_report = auth_gsasl_version_report,
150 .macros_create = auth_gsasl_macros,
154 #ifdef AUTH_HEIMDAL_GSSAPI
157 .driver_name = US"heimdal_gssapi",
158 .options = auth_heimdal_gssapi_options,
159 .options_count = &auth_heimdal_gssapi_options_count,
160 .options_block = &auth_heimdal_gssapi_option_defaults,
161 .options_len = sizeof(auth_heimdal_gssapi_options_block),
162 .init = auth_heimdal_gssapi_init,
164 .servercode = auth_heimdal_gssapi_server,
166 .version_report = auth_heimdal_gssapi_version_report,
167 .macros_create = NULL,
171 #ifdef AUTH_PLAINTEXT
174 .driver_name = US"plaintext",
175 .options = auth_plaintext_options,
176 .options_count = &auth_plaintext_options_count,
177 .options_block = &auth_plaintext_option_defaults,
178 .options_len = sizeof(auth_plaintext_options_block),
179 .init = auth_plaintext_init,
181 .servercode = auth_plaintext_server,
182 .clientcode = auth_plaintext_client,
183 .version_report = NULL,
184 .macros_create = NULL,
191 .driver_name = US"spa",
192 .options = auth_spa_options,
193 .options_count = &auth_spa_options_count,
194 .options_block = &auth_spa_option_defaults,
195 .options_len = sizeof(auth_spa_options_block),
196 .init = auth_spa_init,
198 .servercode = auth_spa_server,
199 .clientcode = auth_spa_client,
200 .version_report = NULL,
201 .macros_create = NULL,
208 .driver_name = US"tls",
209 .options = auth_tls_options,
210 .options_count = &auth_tls_options_count,
211 .options_block = &auth_tls_option_defaults,
212 .options_len = sizeof(auth_tls_options_block),
213 .init = auth_tls_init,
215 .servercode = auth_tls_server,
217 .version_report = NULL,
218 .macros_create = NULL,
222 { .drinfo = { .driver_name = US"" }} /* end marker */
226 /* Tables of information about which routers and transports are included in the
229 /* Pull in the necessary header files */
231 #include "routers/rf_functions.h"
234 # include "routers/accept.h"
237 #ifdef ROUTER_DNSLOOKUP
238 # include "routers/dnslookup.h"
241 #ifdef ROUTER_MANUALROUTE
242 # include "routers/manualroute.h"
245 #ifdef ROUTER_IPLITERAL
246 # include "routers/ipliteral.h"
249 #ifdef ROUTER_IPLOOKUP
250 # include "routers/iplookup.h"
253 #ifdef ROUTER_QUERYPROGRAM
254 # include "routers/queryprogram.h"
257 #ifdef ROUTER_REDIRECT
258 # include "routers/redirect.h"
261 #ifdef TRANSPORT_APPENDFILE
262 # include "transports/appendfile.h"
265 #ifdef TRANSPORT_AUTOREPLY
266 # include "transports/autoreply.h"
269 #ifdef TRANSPORT_LMTP
270 # include "transports/lmtp.h"
273 #ifdef TRANSPORT_PIPE
274 # include "transports/pipe.h"
277 #ifdef EXPERIMENTAL_QUEUEFILE
278 # include "transports/queuefile.h"
281 #ifdef TRANSPORT_SMTP
282 # include "transports/smtp.h"
286 router_info * routers_available_newlist = NULL;
288 /* Now set up the structures, terminated by an entry with a null name. */
290 router_info routers_available_oldarray[] = {
294 .driver_name = US"accept",
295 .options = accept_router_options,
296 .options_count = &accept_router_options_count,
297 .options_block = &accept_router_option_defaults,
298 .options_len = sizeof(accept_router_options_block),
299 .init = accept_router_init,
301 .code = accept_router_entry,
302 .tidyup = NULL, /* no tidyup entry */
303 .ri_flags = ri_yestransport
306 #ifdef ROUTER_DNSLOOKUP
309 .driver_name = US"dnslookup",
310 .options = dnslookup_router_options,
311 .options_count = &dnslookup_router_options_count,
312 .options_block = &dnslookup_router_option_defaults,
313 .options_len = sizeof(dnslookup_router_options_block),
314 .init = dnslookup_router_init,
316 .code = dnslookup_router_entry,
317 .tidyup = NULL, /* no tidyup entry */
318 .ri_flags = ri_yestransport
321 #ifdef ROUTER_IPLITERAL
324 .driver_name = US"ipliteral",
325 .options = ipliteral_router_options,
326 .options_count = &ipliteral_router_options_count,
327 .options_block = &ipliteral_router_option_defaults,
328 .options_len = sizeof(ipliteral_router_options_block),
329 .init = ipliteral_router_init,
331 .code = ipliteral_router_entry,
332 .tidyup = NULL, /* no tidyup entry */
333 .ri_flags = ri_yestransport
336 #ifdef ROUTER_IPLOOKUP
339 .driver_name = US"iplookup",
340 .options = iplookup_router_options,
341 .options_count = &iplookup_router_options_count,
342 .options_block = &iplookup_router_option_defaults,
343 .options_len = sizeof(iplookup_router_options_block),
344 .init = iplookup_router_init,
346 .code = iplookup_router_entry,
347 .tidyup = NULL, /* no tidyup entry */
348 .ri_flags = ri_notransport
351 #ifdef ROUTER_MANUALROUTE
354 .driver_name = US"manualroute",
355 .options = manualroute_router_options,
356 .options_count = &manualroute_router_options_count,
357 .options_block = &manualroute_router_option_defaults,
358 .options_len = sizeof(manualroute_router_options_block),
359 .init = manualroute_router_init,
361 .code = manualroute_router_entry,
362 .tidyup = NULL, /* no tidyup entry */
366 #ifdef ROUTER_REDIRECT
369 .driver_name = US"redirect",
370 .options = redirect_router_options,
371 .options_count = &redirect_router_options_count,
372 .options_block = &redirect_router_option_defaults,
373 .options_len = sizeof(redirect_router_options_block),
374 .init = redirect_router_init,
376 .code = redirect_router_entry,
377 .tidyup = NULL, /* no tidyup entry */
378 .ri_flags = ri_notransport
381 { .drinfo = { .driver_name = US"" }}
386 transport_info * transports_available_newlist = NULL;
387 transport_info transports_available_oldarray[] = {
388 #ifdef TRANSPORT_APPENDFILE
391 .driver_name = US"appendfile",
392 .options = appendfile_transport_options,
393 .options_count = &appendfile_transport_options_count,
394 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
395 .options_len = sizeof(appendfile_transport_options_block),
396 .init = appendfile_transport_init,
398 .code = appendfile_transport_entry,
404 #ifdef TRANSPORT_AUTOREPLY
407 .driver_name = US"autoreply",
408 .options = autoreply_transport_options,
409 .options_count = &autoreply_transport_options_count,
410 .options_block = &autoreply_transport_option_defaults,
411 .options_len = sizeof(autoreply_transport_options_block),
412 .init = autoreply_transport_init,
414 .code = autoreply_transport_entry,
420 #ifdef TRANSPORT_LMTP
423 .driver_name = US"lmtp",
424 .options = lmtp_transport_options,
425 .options_count = &lmtp_transport_options_count,
426 .options_block = &lmtp_transport_option_defaults,
427 .options_len = sizeof(lmtp_transport_options_block),
428 .init = lmtp_transport_init,
430 .code = lmtp_transport_entry,
436 #ifdef TRANSPORT_PIPE
439 .driver_name = US"pipe",
440 .options = pipe_transport_options,
441 .options_count = &pipe_transport_options_count,
442 .options_block = &pipe_transport_option_defaults,
443 .options_len = sizeof(pipe_transport_options_block),
444 .init = pipe_transport_init,
446 .code = pipe_transport_entry,
452 #ifdef EXPERIMENTAL_QUEUEFILE
455 .driver_name = US"queuefile",
456 .options = queuefile_transport_options,
457 .options_count = &queuefile_transport_options_count,
458 .options_block = &queuefile_transport_option_defaults,
459 .options_len = sizeof(queuefile_transport_options_block),
460 .init = queuefile_transport_init,
462 .code = queuefile_transport_entry,
468 #ifdef TRANSPORT_SMTP
471 .driver_name = US"smtp",
472 .options = smtp_transport_options,
473 .options_count = &smtp_transport_options_count,
474 .options_block = &smtp_transport_option_defaults,
475 .options_len = sizeof(smtp_transport_options_block),
476 .init = smtp_transport_init,
478 .code = smtp_transport_entry,
480 .closedown = smtp_transport_closedown,
484 { .drinfo = { .driver_name = US"" }}
490 auth_show_supported(gstring * g)
492 g = string_cat(g, US"Authenticators:");
493 /*XXX these run off the static list as we want them before the conf is read */
494 /*XXX Could possibly check for dyn flag + file presence */
495 for (auth_info * ai = auths_available_oldarray; ai->drinfo.driver_name[0]; ai++)
496 g = string_fmt_append(g, " %s", ai->drinfo.driver_name);
497 return string_cat(g, US"\n");
501 route_show_supported(gstring * g)
504 g = string_cat(g, US"Routers:");
505 /*XXX these run off the static list as we want them before the conf is read */
506 /*XXX lookup_show_supported is in exim.c and just works off the #defines, with hardoded strings */
507 for (router_info * rr = routers_available_oldarray; rr->drinfo.driver_name[0]; rr++)
508 g = string_fmt_append(g, " %s", rr->drinfo.driver_name);
509 return string_cat(g, US"\n");
512 uschar * b = US"" /* static-build router names */
513 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT!=2
516 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP!=2
519 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL!=2
522 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP!=2
525 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE!=2
528 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT!=2
531 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM!=2
536 uschar * d = US"" /* dynamic-module router names */
537 #if defined(ROUTER_ACCEPT) && ROUTER_ACCEPT==2
540 #if defined(ROUTER_DNSLOOKUP) && ROUTER_DNSLOOKUP==2
543 # if defined(ROUTER_IPLITERAL) && ROUTER_IPLITERAL==2
546 #if defined(ROUTER_IPLOOKUP) && ROUTER_IPLOOKUP==2
549 #if defined(ROUTER_MANUALROUTE) && ROUTER_MANUALROUTE==2
552 #if defined(ROUTER_REDIRECT) && ROUTER_REDIRECT==2
555 #if defined(ROUTER_QUERYPROGRAM) && ROUTER_QUERYPROGRAM==2
560 if (*b) g = string_fmt_append(g, "Routers (built-in):%s\n", b);
561 if (*d) g = string_fmt_append(g, "Routers (dynamic): %s\n", d);
567 transport_show_supported(gstring * g)
569 g = string_cat(g, US"Transports:");
570 #ifdef TRANSPORT_APPENDFILE
571 g = string_cat(g, US" appendfile");
572 #ifdef SUPPORT_MAILDIR
573 g = string_cat(g, US"/maildir"); /* damn these subclasses */
575 #ifdef SUPPORT_MAILSTORE
576 g = string_cat(g, US"/mailstore");
579 g = string_cat(g, US"/mbx");
582 #ifdef TRANSPORT_AUTOREPLY
583 g = string_cat(g, US" autoreply");
585 #ifdef TRANSPORT_LMTP
586 g = string_cat(g, US" lmtp");
588 #ifdef TRANSPORT_PIPE
589 g = string_cat(g, US" pipe");
591 #ifdef EXPERIMENTAL_QUEUEFILE
592 g = string_cat(g, US" queuefile");
594 #ifdef TRANSPORT_SMTP
595 g = string_cat(g, US" smtp");
597 return string_cat(g, US"\n");
602 struct lookupmodulestr
605 struct lookup_module_info *info;
606 struct lookupmodulestr *next;
609 static struct lookupmodulestr *lookupmodules = NULL;
612 addlookupmodule(void *dl, struct lookup_module_info *info)
614 struct lookupmodulestr * p =
615 store_get(sizeof(struct lookupmodulestr), GET_UNTAINTED);
619 p->next = lookupmodules;
621 lookup_list_count += info->lookupcount;
624 /* only valid after lookup_list and lookup_list_count are assigned */
626 add_lookup_to_list(lookup_info *info)
628 /* need to add the lookup to lookup_list, sorted */
631 /* strategy is to go through the list until we find
632 either an empty spot or a name that is higher.
633 this can't fail because we have enough space. */
635 while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
638 if (lookup_list[pos])
640 /* need to insert it, so move all the other items up
641 (last slot is still empty, of course) */
643 memmove(&lookup_list[pos+1], &lookup_list[pos],
644 sizeof(lookup_info *) * (lookup_list_count-pos-1));
646 lookup_list[pos] = info;
650 /* These need to be at file level for old versions of gcc (2.95.2 reported),
651 which give parse errors on an extern in function scope. Each entry needs
652 to also be invoked in init_lookup_list() below */
654 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
655 extern lookup_module_info cdb_lookup_module_info;
657 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
658 extern lookup_module_info dbmdb_lookup_module_info;
660 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
661 extern lookup_module_info dnsdb_lookup_module_info;
663 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
664 extern lookup_module_info dsearch_lookup_module_info;
666 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
667 extern lookup_module_info ibase_lookup_module_info;
669 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
670 extern lookup_module_info json_lookup_module_info;
672 #if defined(LOOKUP_LDAP)
673 extern lookup_module_info ldap_lookup_module_info;
675 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
676 extern lookup_module_info lsearch_lookup_module_info;
678 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
679 extern lookup_module_info mysql_lookup_module_info;
681 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
682 extern lookup_module_info nis_lookup_module_info;
684 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
685 extern lookup_module_info nisplus_lookup_module_info;
687 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
688 extern lookup_module_info oracle_lookup_module_info;
690 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
691 extern lookup_module_info passwd_lookup_module_info;
693 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
694 extern lookup_module_info pgsql_lookup_module_info;
696 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
697 extern lookup_module_info redis_lookup_module_info;
699 #if defined(LOOKUP_LMDB)
700 extern lookup_module_info lmdb_lookup_module_info;
702 #if defined(SUPPORT_SPF)
703 extern lookup_module_info spf_lookup_module_info;
705 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
706 extern lookup_module_info sqlite_lookup_module_info;
708 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
709 extern lookup_module_info testdb_lookup_module_info;
711 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
712 extern lookup_module_info whoson_lookup_module_info;
715 extern lookup_module_info readsock_lookup_module_info;
719 init_lookup_list(void)
721 #ifdef LOOKUP_MODULE_DIR
724 int countmodules = 0;
725 int moduleerrors = 0;
727 static BOOL lookup_list_init_done = FALSE;
730 if (lookup_list_init_done)
732 reset_point = store_mark();
733 lookup_list_init_done = TRUE;
735 #if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
736 addlookupmodule(NULL, &cdb_lookup_module_info);
739 #if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
740 addlookupmodule(NULL, &dbmdb_lookup_module_info);
743 #if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
744 addlookupmodule(NULL, &dnsdb_lookup_module_info);
747 #if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
748 addlookupmodule(NULL, &dsearch_lookup_module_info);
751 #if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
752 addlookupmodule(NULL, &ibase_lookup_module_info);
756 addlookupmodule(NULL, &ldap_lookup_module_info);
759 #if defined(LOOKUP_JSON) && LOOKUP_JSON!=2
760 addlookupmodule(NULL, &json_lookup_module_info);
763 #if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
764 addlookupmodule(NULL, &lsearch_lookup_module_info);
767 #if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
768 addlookupmodule(NULL, &mysql_lookup_module_info);
771 #if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
772 addlookupmodule(NULL, &nis_lookup_module_info);
775 #if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
776 addlookupmodule(NULL, &nisplus_lookup_module_info);
779 #if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
780 addlookupmodule(NULL, &oracle_lookup_module_info);
783 #if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
784 addlookupmodule(NULL, &passwd_lookup_module_info);
787 #if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
788 addlookupmodule(NULL, &pgsql_lookup_module_info);
791 #if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
792 addlookupmodule(NULL, &redis_lookup_module_info);
796 addlookupmodule(NULL, &lmdb_lookup_module_info);
800 addlookupmodule(NULL, &spf_lookup_module_info);
803 #if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
804 addlookupmodule(NULL, &sqlite_lookup_module_info);
807 #if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
808 addlookupmodule(NULL, &testdb_lookup_module_info);
811 #if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
812 addlookupmodule(NULL, &whoson_lookup_module_info);
815 /* This is a custom expansion, and not available as either
816 a list-syntax lookup or a lookup expansion. However, it is
817 implemented by a lookup module. */
819 addlookupmodule(NULL, &readsock_lookup_module_info);
821 #ifdef LOOKUP_MODULE_DIR
822 if (!(dd = exim_opendir(CUS LOOKUP_MODULE_DIR)))
824 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
825 log_write(0, LOG_MAIN|LOG_PANIC,
826 "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
830 const pcre2_code * regex_islookupmod = regex_must_compile(
831 US"_lookup\\." DYNLIB_FN_EXT "$", MCS_NOFLAGS, TRUE);
833 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
834 while ((ent = readdir(dd)))
836 char * name = ent->d_name;
837 int len = (int)strlen(name);
838 if (regex_match(regex_islookupmod, US name, len, NULL))
840 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
842 struct lookup_module_info *info;
843 const char *errormsg;
845 /* SRH: am I being paranoid here or what? */
846 if (pathnamelen > big_buffer_size)
848 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
849 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
853 /* SRH: snprintf here? */
854 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
856 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
858 errormsg = dlerror();
859 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
860 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
865 /* FreeBSD nsdispatch() can trigger dlerror() errors about
866 _nss_cache_cycle_prevention_function; we need to clear the dlerror()
867 state before calling dlsym(), so that any error afterwards only comes
870 errormsg = dlerror();
872 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
873 if ((errormsg = dlerror()))
875 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
876 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
881 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
883 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
884 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
890 addlookupmodule(dl, info);
891 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
895 store_free((void*)regex_islookupmod);
899 DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
902 DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
904 lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
905 memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
907 /* now add all lookups to the real list */
908 for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
909 for (int j = 0; j < p->info->lookupcount; j++)
910 add_lookup_to_list(p->info->lookups[j]);
911 store_reset(reset_point);
912 /* just to be sure */
913 lookupmodules = NULL;
916 #endif /*!MACRO_PREDEF*/
917 /* End of drtables.c */