Copyright updates:
[exim.git] / src / src / drtables.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
f9ba5e22 5/* Copyright (c) University of Cambridge 1995 - 2018 */
1e1ddfac 6/* Copyright (c) The Exim Maintainers 2020 */
059ec3d9
PH
7/* See the file NOTICE for conditions of use and distribution. */
8
9
10#include "exim.h"
11
e6d225ae 12#include <string.h>
059ec3d9
PH
13
14/* This module contains tables that define the lookup methods and drivers
15that are actually included in the binary. Its contents are controlled by
16various macros in config.h that ultimately come from Local/Makefile. They are
17all described in src/EDITME. */
18
19
e6d225ae
DW
20lookup_info **lookup_list;
21int lookup_list_count = 0;
059ec3d9 22
4c04137d 23/* Table of information about all possible authentication mechanisms. All
059ec3d9
PH
24entries are always present if any mechanism is declared, but the functions are
25set to NULL for those that are not compiled into the binary. */
26
27#ifdef AUTH_CRAM_MD5
28#include "auths/cram_md5.h"
29#endif
30
31#ifdef AUTH_CYRUS_SASL
32#include "auths/cyrus_sasl.h"
33#endif
34
14aa5a05
PH
35#ifdef AUTH_DOVECOT
36#include "auths/dovecot.h"
37#endif
38
b53c265b
JH
39#ifdef AUTH_EXTERNAL
40#include "auths/external.h"
41#endif
42
44bbabb5
PP
43#ifdef AUTH_GSASL
44#include "auths/gsasl_exim.h"
45#endif
46
dde3daac
PP
47#ifdef AUTH_HEIMDAL_GSSAPI
48#include "auths/heimdal_gssapi.h"
49#endif
50
059ec3d9
PH
51#ifdef AUTH_PLAINTEXT
52#include "auths/plaintext.h"
53#endif
54
55#ifdef AUTH_SPA
56#include "auths/spa.h"
57#endif
58
b3ef41c9
JH
59#ifdef AUTH_TLS
60#include "auths/tls.h"
61#endif
62
059ec3d9
PH
63auth_info auths_available[] = {
64
65/* Checking by an expansion condition on plain text */
66
67#ifdef AUTH_CRAM_MD5
68 {
f2ed27cf
JH
69 .driver_name = US"cram_md5", /* lookup name */
70 .options = auth_cram_md5_options,
71 .options_count = &auth_cram_md5_options_count,
72 .options_block = &auth_cram_md5_option_defaults,
73 .options_len = sizeof(auth_cram_md5_options_block),
74 .init = auth_cram_md5_init,
75 .servercode = auth_cram_md5_server,
76 .clientcode = auth_cram_md5_client,
25bd12fd
JH
77 .version_report = NULL,
78 .macros_create = NULL,
059ec3d9
PH
79 },
80#endif
81
82#ifdef AUTH_CYRUS_SASL
83 {
f2ed27cf
JH
84 .driver_name = US"cyrus_sasl",
85 .options = auth_cyrus_sasl_options,
86 .options_count = &auth_cyrus_sasl_options_count,
87 .options_block = &auth_cyrus_sasl_option_defaults,
88 .options_len = sizeof(auth_cyrus_sasl_options_block),
89 .init = auth_cyrus_sasl_init,
90 .servercode = auth_cyrus_sasl_server,
91 .clientcode = NULL,
25bd12fd
JH
92 .version_report = auth_cyrus_sasl_version_report,
93 .macros_create = NULL,
059ec3d9
PH
94 },
95#endif
96
14aa5a05
PH
97#ifdef AUTH_DOVECOT
98 {
f2ed27cf
JH
99 .driver_name = US"dovecot",
100 .options = auth_dovecot_options,
101 .options_count = &auth_dovecot_options_count,
102 .options_block = &auth_dovecot_option_defaults,
103 .options_len = sizeof(auth_dovecot_options_block),
104 .init = auth_dovecot_init,
105 .servercode = auth_dovecot_server,
106 .clientcode = NULL,
25bd12fd
JH
107 .version_report = NULL,
108 .macros_create = NULL,
44bbabb5
PP
109 },
110#endif
111
b53c265b
JH
112#ifdef AUTH_EXTERNAL
113 {
114 .driver_name = US"external",
115 .options = auth_external_options,
116 .options_count = &auth_external_options_count,
117 .options_block = &auth_external_option_defaults,
118 .options_len = sizeof(auth_external_options_block),
119 .init = auth_external_init,
120 .servercode = auth_external_server,
121 .clientcode = auth_external_client,
25bd12fd
JH
122 .version_report = NULL,
123 .macros_create = NULL,
b53c265b
JH
124 },
125#endif
126
44bbabb5
PP
127#ifdef AUTH_GSASL
128 {
f2ed27cf
JH
129 .driver_name = US"gsasl",
130 .options = auth_gsasl_options,
131 .options_count = &auth_gsasl_options_count,
132 .options_block = &auth_gsasl_option_defaults,
133 .options_len = sizeof(auth_gsasl_options_block),
134 .init = auth_gsasl_init,
135 .servercode = auth_gsasl_server,
14a806d6 136 .clientcode = auth_gsasl_client,
25bd12fd
JH
137 .version_report = auth_gsasl_version_report,
138 .macros_create = auth_gsasl_macros,
14aa5a05
PH
139 },
140#endif
141
dde3daac
PP
142#ifdef AUTH_HEIMDAL_GSSAPI
143 {
f2ed27cf
JH
144 .driver_name = US"heimdal_gssapi",
145 .options = auth_heimdal_gssapi_options,
7be14582 146 .options_count = &auth_heimdal_gssapi_options_count,
f2ed27cf
JH
147 .options_block = &auth_heimdal_gssapi_option_defaults,
148 .options_len = sizeof(auth_heimdal_gssapi_options_block),
149 .init = auth_heimdal_gssapi_init,
150 .servercode = auth_heimdal_gssapi_server,
151 .clientcode = NULL,
25bd12fd
JH
152 .version_report = auth_heimdal_gssapi_version_report,
153 .macros_create = NULL,
dde3daac
PP
154 },
155#endif
156
059ec3d9
PH
157#ifdef AUTH_PLAINTEXT
158 {
f2ed27cf
JH
159 .driver_name = US"plaintext",
160 .options = auth_plaintext_options,
161 .options_count = &auth_plaintext_options_count,
162 .options_block = &auth_plaintext_option_defaults,
163 .options_len = sizeof(auth_plaintext_options_block),
164 .init = auth_plaintext_init,
165 .servercode = auth_plaintext_server,
166 .clientcode = auth_plaintext_client,
25bd12fd
JH
167 .version_report = NULL,
168 .macros_create = NULL,
059ec3d9
PH
169 },
170#endif
171
172#ifdef AUTH_SPA
173 {
f2ed27cf
JH
174 .driver_name = US"spa",
175 .options = auth_spa_options,
176 .options_count = &auth_spa_options_count,
177 .options_block = &auth_spa_option_defaults,
178 .options_len = sizeof(auth_spa_options_block),
179 .init = auth_spa_init,
180 .servercode = auth_spa_server,
181 .clientcode = auth_spa_client,
25bd12fd
JH
182 .version_report = NULL,
183 .macros_create = NULL,
059ec3d9
PH
184 },
185#endif
186
b3ef41c9
JH
187#ifdef AUTH_TLS
188 {
f2ed27cf
JH
189 .driver_name = US"tls",
190 .options = auth_tls_options,
191 .options_count = &auth_tls_options_count,
192 .options_block = &auth_tls_option_defaults,
193 .options_len = sizeof(auth_tls_options_block),
194 .init = auth_tls_init,
195 .servercode = auth_tls_server,
196 .clientcode = NULL,
25bd12fd
JH
197 .version_report = NULL,
198 .macros_create = NULL,
b3ef41c9
JH
199 },
200#endif
201
adf73d37 202 { .driver_name = US"" } /* end marker */
059ec3d9
PH
203};
204
205
206/* Tables of information about which routers and transports are included in the
207exim binary. */
208
209/* Pull in the necessary header files */
210
211#include "routers/rf_functions.h"
212
213#ifdef ROUTER_ACCEPT
214#include "routers/accept.h"
215#endif
216
217#ifdef ROUTER_DNSLOOKUP
218#include "routers/dnslookup.h"
219#endif
220
221#ifdef ROUTER_MANUALROUTE
222#include "routers/manualroute.h"
223#endif
224
225#ifdef ROUTER_IPLITERAL
226#include "routers/ipliteral.h"
227#endif
228
229#ifdef ROUTER_IPLOOKUP
230#include "routers/iplookup.h"
231#endif
232
233#ifdef ROUTER_QUERYPROGRAM
234#include "routers/queryprogram.h"
235#endif
236
237#ifdef ROUTER_REDIRECT
238#include "routers/redirect.h"
239#endif
240
241#ifdef TRANSPORT_APPENDFILE
242#include "transports/appendfile.h"
243#endif
244
245#ifdef TRANSPORT_AUTOREPLY
246#include "transports/autoreply.h"
247#endif
248
249#ifdef TRANSPORT_LMTP
250#include "transports/lmtp.h"
251#endif
252
253#ifdef TRANSPORT_PIPE
254#include "transports/pipe.h"
255#endif
256
3369a853
ACK
257#ifdef EXPERIMENTAL_QUEUEFILE
258#include "transports/queuefile.h"
259#endif
260
059ec3d9
PH
261#ifdef TRANSPORT_SMTP
262#include "transports/smtp.h"
263#endif
264
265
266/* Now set up the structures, terminated by an entry with a null name. */
267
268router_info routers_available[] = {
269#ifdef ROUTER_ACCEPT
270 {
f2ed27cf
JH
271 .driver_name = US"accept",
272 .options = accept_router_options,
273 .options_count = &accept_router_options_count,
274 .options_block = &accept_router_option_defaults,
275 .options_len = sizeof(accept_router_options_block),
276 .init = accept_router_init,
277 .code = accept_router_entry,
278 .tidyup = NULL, /* no tidyup entry */
279 .ri_flags = ri_yestransport
059ec3d9
PH
280 },
281#endif
282#ifdef ROUTER_DNSLOOKUP
283 {
f2ed27cf
JH
284 .driver_name = US"dnslookup",
285 .options = dnslookup_router_options,
286 .options_count = &dnslookup_router_options_count,
287 .options_block = &dnslookup_router_option_defaults,
288 .options_len = sizeof(dnslookup_router_options_block),
289 .init = dnslookup_router_init,
290 .code = dnslookup_router_entry,
291 .tidyup = NULL, /* no tidyup entry */
292 .ri_flags = ri_yestransport
059ec3d9
PH
293 },
294#endif
295#ifdef ROUTER_IPLITERAL
296 {
f2ed27cf
JH
297 .driver_name = US"ipliteral",
298 .options = ipliteral_router_options,
299 .options_count = &ipliteral_router_options_count,
300 .options_block = &ipliteral_router_option_defaults,
301 .options_len = sizeof(ipliteral_router_options_block),
302 .init = ipliteral_router_init,
303 .code = ipliteral_router_entry,
304 .tidyup = NULL, /* no tidyup entry */
305 .ri_flags = ri_yestransport
059ec3d9
PH
306 },
307#endif
308#ifdef ROUTER_IPLOOKUP
309 {
f2ed27cf
JH
310 .driver_name = US"iplookup",
311 .options = iplookup_router_options,
312 .options_count = &iplookup_router_options_count,
313 .options_block = &iplookup_router_option_defaults,
314 .options_len = sizeof(iplookup_router_options_block),
315 .init = iplookup_router_init,
316 .code = iplookup_router_entry,
317 .tidyup = NULL, /* no tidyup entry */
318 .ri_flags = ri_notransport
059ec3d9
PH
319 },
320#endif
321#ifdef ROUTER_MANUALROUTE
322 {
f2ed27cf
JH
323 .driver_name = US"manualroute",
324 .options = manualroute_router_options,
325 .options_count = &manualroute_router_options_count,
326 .options_block = &manualroute_router_option_defaults,
327 .options_len = sizeof(manualroute_router_options_block),
328 .init = manualroute_router_init,
329 .code = manualroute_router_entry,
330 .tidyup = NULL, /* no tidyup entry */
331 .ri_flags = 0
059ec3d9
PH
332 },
333#endif
334#ifdef ROUTER_QUERYPROGRAM
335 {
f2ed27cf
JH
336 .driver_name = US"queryprogram",
337 .options = queryprogram_router_options,
338 .options_count = &queryprogram_router_options_count,
339 .options_block = &queryprogram_router_option_defaults,
340 .options_len = sizeof(queryprogram_router_options_block),
341 .init = queryprogram_router_init,
342 .code = queryprogram_router_entry,
343 .tidyup = NULL, /* no tidyup entry */
344 .ri_flags = 0
059ec3d9
PH
345 },
346#endif
347#ifdef ROUTER_REDIRECT
348 {
f2ed27cf
JH
349 .driver_name = US"redirect",
350 .options = redirect_router_options,
351 .options_count = &redirect_router_options_count,
352 .options_block = &redirect_router_option_defaults,
353 .options_len = sizeof(redirect_router_options_block),
354 .init = redirect_router_init,
355 .code = redirect_router_entry,
356 .tidyup = NULL, /* no tidyup entry */
357 .ri_flags = ri_notransport
059ec3d9
PH
358 },
359#endif
adf73d37 360 { US"" }
059ec3d9
PH
361};
362
363
364
365transport_info transports_available[] = {
366#ifdef TRANSPORT_APPENDFILE
367 {
f2ed27cf
JH
368 .driver_name = US"appendfile",
369 .options = appendfile_transport_options,
370 .options_count = &appendfile_transport_options_count,
371 .options_block = &appendfile_transport_option_defaults, /* private options defaults */
372 .options_len = sizeof(appendfile_transport_options_block),
373 .init = appendfile_transport_init,
374 .code = appendfile_transport_entry,
375 .tidyup = NULL,
376 .closedown = NULL,
377 .local = TRUE
059ec3d9
PH
378 },
379#endif
380#ifdef TRANSPORT_AUTOREPLY
381 {
f2ed27cf
JH
382 .driver_name = US"autoreply",
383 .options = autoreply_transport_options,
384 .options_count = &autoreply_transport_options_count,
385 .options_block = &autoreply_transport_option_defaults,
386 .options_len = sizeof(autoreply_transport_options_block),
387 .init = autoreply_transport_init,
388 .code = autoreply_transport_entry,
389 .tidyup = NULL,
390 .closedown = NULL,
391 .local = TRUE
059ec3d9
PH
392 },
393#endif
394#ifdef TRANSPORT_LMTP
395 {
f2ed27cf
JH
396 .driver_name = US"lmtp",
397 .options = lmtp_transport_options,
398 .options_count = &lmtp_transport_options_count,
399 .options_block = &lmtp_transport_option_defaults,
400 .options_len = sizeof(lmtp_transport_options_block),
401 .init = lmtp_transport_init,
402 .code = lmtp_transport_entry,
403 .tidyup = NULL,
404 .closedown = NULL,
405 .local = TRUE
059ec3d9
PH
406 },
407#endif
408#ifdef TRANSPORT_PIPE
409 {
f2ed27cf
JH
410 .driver_name = US"pipe",
411 .options = pipe_transport_options,
412 .options_count = &pipe_transport_options_count,
413 .options_block = &pipe_transport_option_defaults,
414 .options_len = sizeof(pipe_transport_options_block),
415 .init = pipe_transport_init,
416 .code = pipe_transport_entry,
417 .tidyup = NULL,
418 .closedown = NULL,
419 .local = TRUE
059ec3d9
PH
420 },
421#endif
3369a853
ACK
422#ifdef EXPERIMENTAL_QUEUEFILE
423 {
f2ed27cf
JH
424 .driver_name = US"queuefile",
425 .options = queuefile_transport_options,
426 .options_count = &queuefile_transport_options_count,
427 .options_block = &queuefile_transport_option_defaults,
428 .options_len = sizeof(queuefile_transport_options_block),
429 .init = queuefile_transport_init,
430 .code = queuefile_transport_entry,
431 .tidyup = NULL,
432 .closedown = NULL,
433 .local = TRUE
3369a853
ACK
434 },
435#endif
059ec3d9
PH
436#ifdef TRANSPORT_SMTP
437 {
f2ed27cf
JH
438 .driver_name = US"smtp",
439 .options = smtp_transport_options,
440 .options_count = &smtp_transport_options_count,
441 .options_block = &smtp_transport_option_defaults,
442 .options_len = sizeof(smtp_transport_options_block),
443 .init = smtp_transport_init,
444 .code = smtp_transport_entry,
445 .tidyup = NULL,
446 .closedown = smtp_transport_closedown,
447 .local = FALSE
059ec3d9
PH
448 },
449#endif
adf73d37 450 { US"" }
059ec3d9
PH
451};
452
ab1604ea
JH
453#ifndef MACRO_PREDEF
454
455gstring *
456auth_show_supported(gstring * g)
457{
458g = string_cat(g, US"Authenticators:");
459for (auth_info * ai = auths_available; ai->driver_name[0]; ai++)
460 g = string_fmt_append(g, " %s", ai->driver_name);
461return string_cat(g, US"\n");
462}
463
464gstring *
465route_show_supported(gstring * g)
adf73d37 466{
ab1604ea
JH
467g = string_cat(g, US"Routers:");
468for (router_info * rr = routers_available; rr->driver_name[0]; rr++)
469 g = string_fmt_append(g, " %s", rr->driver_name);
470return string_cat(g, US"\n");
471}
472
473gstring *
474transport_show_supported(gstring * g)
475{
476g = string_cat(g, US"Transports:");
adf73d37 477#ifdef TRANSPORT_APPENDFILE
ab1604ea 478 g = string_cat(g, US" appendfile");
adf73d37 479 #ifdef SUPPORT_MAILDIR
ab1604ea 480 g = string_cat(g, US"/maildir"); /* damn these subclasses */
adf73d37
JH
481 #endif
482 #ifdef SUPPORT_MAILSTORE
ab1604ea 483 g = string_cat(g, US"/mailstore");
adf73d37
JH
484 #endif
485 #ifdef SUPPORT_MBX
ab1604ea 486 g = string_cat(g, US"/mbx");
adf73d37
JH
487 #endif
488#endif
489#ifdef TRANSPORT_AUTOREPLY
ab1604ea 490 g = string_cat(g, US" autoreply");
adf73d37
JH
491#endif
492#ifdef TRANSPORT_LMTP
ab1604ea 493 g = string_cat(g, US" lmtp");
adf73d37
JH
494#endif
495#ifdef TRANSPORT_PIPE
ab1604ea 496 g = string_cat(g, US" pipe");
adf73d37
JH
497#endif
498#ifdef EXPERIMENTAL_QUEUEFILE
ab1604ea 499 g = string_cat(g, US" queuefile");
adf73d37
JH
500#endif
501#ifdef TRANSPORT_SMTP
ab1604ea 502 g = string_cat(g, US" smtp");
adf73d37 503#endif
ab1604ea 504return string_cat(g, US"\n");
adf73d37
JH
505}
506
d185889f 507
d185889f 508
e6d225ae
DW
509struct lookupmodulestr
510{
511 void *dl;
512 struct lookup_module_info *info;
513 struct lookupmodulestr *next;
514};
515
516static struct lookupmodulestr *lookupmodules = NULL;
517
96f5fe4c
JH
518static void
519addlookupmodule(void *dl, struct lookup_module_info *info)
e6d225ae 520{
f3ebb786 521struct lookupmodulestr *p = store_get(sizeof(struct lookupmodulestr), FALSE);
96f5fe4c
JH
522
523p->dl = dl;
524p->info = info;
525p->next = lookupmodules;
526lookupmodules = p;
527lookup_list_count += info->lookupcount;
e6d225ae
DW
528}
529
530/* only valid after lookup_list and lookup_list_count are assigned */
96f5fe4c
JH
531static void
532add_lookup_to_list(lookup_info *info)
e6d225ae 533{
96f5fe4c
JH
534/* need to add the lookup to lookup_list, sorted */
535int pos = 0;
536
537/* strategy is to go through the list until we find
538either an empty spot or a name that is higher.
539this can't fail because we have enough space. */
540
541while (lookup_list[pos] && (Ustrcmp(lookup_list[pos]->name, info->name) <= 0))
542 pos++;
543
544if (lookup_list[pos])
545 {
546 /* need to insert it, so move all the other items up
547 (last slot is still empty, of course) */
548
d447dbd1 549 memmove(&lookup_list[pos+1], &lookup_list[pos],
96f5fe4c 550 sizeof(lookup_info *) * (lookup_list_count-pos-1));
e6d225ae 551 }
96f5fe4c 552lookup_list[pos] = info;
e6d225ae
DW
553}
554
4d805ee9
PP
555
556/* These need to be at file level for old versions of gcc (2.95.2 reported),
557 * which give parse errors on an extern in function scope. Each entry needs
558 * to also be invoked in init_lookup_list() below */
559
78f72498
JH
560#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
561extern lookup_module_info cdb_lookup_module_info;
4d805ee9 562#endif
78f72498
JH
563#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
564extern lookup_module_info dbmdb_lookup_module_info;
4d805ee9 565#endif
78f72498
JH
566#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
567extern lookup_module_info dnsdb_lookup_module_info;
4d805ee9 568#endif
78f72498
JH
569#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
570extern lookup_module_info dsearch_lookup_module_info;
4d805ee9 571#endif
78f72498
JH
572#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
573extern lookup_module_info ibase_lookup_module_info;
4d805ee9 574#endif
ffc92d69
JH
575#if defined(LOOKUP_JSON)
576extern lookup_module_info json_lookup_module_info;
577#endif
78f72498
JH
578#if defined(LOOKUP_LDAP)
579extern lookup_module_info ldap_lookup_module_info;
de78e2d5 580#endif
78f72498
JH
581#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
582extern lookup_module_info lsearch_lookup_module_info;
4d805ee9 583#endif
78f72498
JH
584#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
585extern lookup_module_info mysql_lookup_module_info;
4d805ee9
PP
586#endif
587#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
588extern lookup_module_info nis_lookup_module_info;
589#endif
78f72498
JH
590#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
591extern lookup_module_info nisplus_lookup_module_info;
4d805ee9 592#endif
78f72498
JH
593#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
594extern lookup_module_info oracle_lookup_module_info;
4d805ee9 595#endif
78f72498
JH
596#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
597extern lookup_module_info passwd_lookup_module_info;
4d805ee9 598#endif
78f72498
JH
599#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
600extern lookup_module_info pgsql_lookup_module_info;
4d805ee9 601#endif
78f72498
JH
602#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
603extern lookup_module_info redis_lookup_module_info;
4d805ee9 604#endif
5bde3efa
ACK
605#if defined(EXPERIMENTAL_LMDB)
606extern lookup_module_info lmdb_lookup_module_info;
607#endif
7952eef9 608#if defined(SUPPORT_SPF)
78f72498 609extern lookup_module_info spf_lookup_module_info;
4d805ee9 610#endif
78f72498
JH
611#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
612extern lookup_module_info sqlite_lookup_module_info;
4d805ee9 613#endif
78f72498
JH
614#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
615extern lookup_module_info testdb_lookup_module_info;
616#endif
617#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
618extern lookup_module_info whoson_lookup_module_info;
4d805ee9
PP
619#endif
620
1950cf85
JH
621extern lookup_module_info readsock_lookup_module_info;
622
96f5fe4c
JH
623
624void
625init_lookup_list(void)
e6d225ae 626{
fb2bba55 627#ifdef LOOKUP_MODULE_DIR
2fa25efc
JH
628DIR *dd;
629struct dirent *ent;
630int countmodules = 0;
631int moduleerrors = 0;
fb2bba55 632#endif
2fa25efc
JH
633static BOOL lookup_list_init_done = FALSE;
634rmark reset_point;
e6d225ae 635
2fa25efc
JH
636if (lookup_list_init_done)
637 return;
638reset_point = store_mark();
639lookup_list_init_done = TRUE;
6545de78 640
e6d225ae 641#if defined(LOOKUP_CDB) && LOOKUP_CDB!=2
2fa25efc 642addlookupmodule(NULL, &cdb_lookup_module_info);
e6d225ae
DW
643#endif
644
645#if defined(LOOKUP_DBM) && LOOKUP_DBM!=2
2fa25efc 646addlookupmodule(NULL, &dbmdb_lookup_module_info);
e6d225ae
DW
647#endif
648
649#if defined(LOOKUP_DNSDB) && LOOKUP_DNSDB!=2
2fa25efc 650addlookupmodule(NULL, &dnsdb_lookup_module_info);
e6d225ae
DW
651#endif
652
653#if defined(LOOKUP_DSEARCH) && LOOKUP_DSEARCH!=2
2fa25efc 654addlookupmodule(NULL, &dsearch_lookup_module_info);
e6d225ae
DW
655#endif
656
657#if defined(LOOKUP_IBASE) && LOOKUP_IBASE!=2
2fa25efc 658addlookupmodule(NULL, &ibase_lookup_module_info);
e6d225ae
DW
659#endif
660
661#ifdef LOOKUP_LDAP
2fa25efc 662addlookupmodule(NULL, &ldap_lookup_module_info);
e6d225ae
DW
663#endif
664
ffc92d69 665#ifdef LOOKUP_JSON
2fa25efc 666addlookupmodule(NULL, &json_lookup_module_info);
ffc92d69
JH
667#endif
668
e6d225ae 669#if defined(LOOKUP_LSEARCH) && LOOKUP_LSEARCH!=2
2fa25efc 670addlookupmodule(NULL, &lsearch_lookup_module_info);
e6d225ae
DW
671#endif
672
673#if defined(LOOKUP_MYSQL) && LOOKUP_MYSQL!=2
2fa25efc 674addlookupmodule(NULL, &mysql_lookup_module_info);
e6d225ae
DW
675#endif
676
677#if defined(LOOKUP_NIS) && LOOKUP_NIS!=2
2fa25efc 678addlookupmodule(NULL, &nis_lookup_module_info);
e6d225ae
DW
679#endif
680
681#if defined(LOOKUP_NISPLUS) && LOOKUP_NISPLUS!=2
2fa25efc 682addlookupmodule(NULL, &nisplus_lookup_module_info);
e6d225ae
DW
683#endif
684
685#if defined(LOOKUP_ORACLE) && LOOKUP_ORACLE!=2
2fa25efc 686addlookupmodule(NULL, &oracle_lookup_module_info);
e6d225ae
DW
687#endif
688
689#if defined(LOOKUP_PASSWD) && LOOKUP_PASSWD!=2
2fa25efc 690addlookupmodule(NULL, &passwd_lookup_module_info);
e6d225ae
DW
691#endif
692
693#if defined(LOOKUP_PGSQL) && LOOKUP_PGSQL!=2
2fa25efc 694addlookupmodule(NULL, &pgsql_lookup_module_info);
e6d225ae
DW
695#endif
696
de78e2d5 697#if defined(LOOKUP_REDIS) && LOOKUP_REDIS!=2
2fa25efc 698addlookupmodule(NULL, &redis_lookup_module_info);
9bdd29ad
TL
699#endif
700
5bde3efa 701#ifdef EXPERIMENTAL_LMDB
2fa25efc 702addlookupmodule(NULL, &lmdb_lookup_module_info);
5bde3efa
ACK
703#endif
704
7952eef9 705#ifdef SUPPORT_SPF
2fa25efc 706addlookupmodule(NULL, &spf_lookup_module_info);
e6d225ae
DW
707#endif
708
709#if defined(LOOKUP_SQLITE) && LOOKUP_SQLITE!=2
2fa25efc 710addlookupmodule(NULL, &sqlite_lookup_module_info);
e6d225ae
DW
711#endif
712
713#if defined(LOOKUP_TESTDB) && LOOKUP_TESTDB!=2
2fa25efc 714addlookupmodule(NULL, &testdb_lookup_module_info);
e6d225ae
DW
715#endif
716
717#if defined(LOOKUP_WHOSON) && LOOKUP_WHOSON!=2
2fa25efc 718addlookupmodule(NULL, &whoson_lookup_module_info);
e6d225ae
DW
719#endif
720
1950cf85
JH
721addlookupmodule(NULL, &readsock_lookup_module_info);
722
e6d225ae 723#ifdef LOOKUP_MODULE_DIR
54a2a2a9 724if (!(dd = exim_opendir(LOOKUP_MODULE_DIR)))
2fa25efc
JH
725 {
726 DEBUG(D_lookup) debug_printf("Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
727 log_write(0, LOG_MAIN, "Couldn't open %s: not loading lookup modules\n", LOOKUP_MODULE_DIR);
e6d225ae 728 }
2fa25efc
JH
729else
730 {
731 const pcre *regex_islookupmod = regex_must_compile(
732 US"\\." DYNLIB_FN_EXT "$", FALSE, TRUE);
733
734 DEBUG(D_lookup) debug_printf("Loading lookup modules from %s\n", LOOKUP_MODULE_DIR);
735 while ((ent = readdir(dd)))
736 {
737 char *name = ent->d_name;
738 int len = (int)strlen(name);
739 if (pcre_exec(regex_islookupmod, NULL, name, len, 0, PCRE_EOPT, NULL, 0) >= 0)
740 {
741 int pathnamelen = len + (int)strlen(LOOKUP_MODULE_DIR) + 2;
742 void *dl;
743 struct lookup_module_info *info;
744 const char *errormsg;
745
746 /* SRH: am I being paranoid here or what? */
747 if (pathnamelen > big_buffer_size)
748 {
749 fprintf(stderr, "Loading lookup modules: %s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
750 log_write(0, LOG_MAIN|LOG_PANIC, "%s/%s: name too long\n", LOOKUP_MODULE_DIR, name);
751 continue;
752 }
753
754 /* SRH: snprintf here? */
755 sprintf(CS big_buffer, "%s/%s", LOOKUP_MODULE_DIR, name);
756
757 if (!(dl = dlopen(CS big_buffer, RTLD_NOW)))
758 {
3fc07bd5
AM
759 errormsg = dlerror();
760 fprintf(stderr, "Error loading %s: %s\n", name, errormsg);
761 log_write(0, LOG_MAIN|LOG_PANIC, "Error loading lookup module %s: %s\n", name, errormsg);
2fa25efc 762 moduleerrors++;
2fa25efc
JH
763 continue;
764 }
765
766 /* FreeBSD nsdispatch() can trigger dlerror() errors about
767 * _nss_cache_cycle_prevention_function; we need to clear the dlerror()
768 * state before calling dlsym(), so that any error afterwards only
769 * comes from dlsym().
770 */
771 errormsg = dlerror();
772
773 info = (struct lookup_module_info*) dlsym(dl, "_lookup_module_info");
774 if ((errormsg = dlerror()))
775 {
776 fprintf(stderr, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
3fc07bd5 777 log_write(0, LOG_MAIN|LOG_PANIC, "%s does not appear to be a lookup module (%s)\n", name, errormsg);
2fa25efc
JH
778 dlclose(dl);
779 moduleerrors++;
2fa25efc
JH
780 continue;
781 }
782 if (info->magic != LOOKUP_MODULE_INFO_MAGIC)
783 {
784 fprintf(stderr, "Lookup module %s is not compatible with this version of Exim\n", name);
3fc07bd5 785 log_write(0, LOG_MAIN|LOG_PANIC, "Lookup module %s is not compatible with this version of Exim\n", name);
2fa25efc
JH
786 dlclose(dl);
787 moduleerrors++;
2fa25efc
JH
788 continue;
789 }
790
791 addlookupmodule(dl, info);
792 DEBUG(D_lookup) debug_printf("Loaded \"%s\" (%d lookup types)\n", name, info->lookupcount);
793 countmodules++;
e6d225ae
DW
794 }
795 }
2fa25efc
JH
796 store_free((void*)regex_islookupmod);
797 closedir(dd);
e6d225ae
DW
798 }
799
2fa25efc 800DEBUG(D_lookup) debug_printf("Loaded %d lookup modules\n", countmodules);
e6d225ae
DW
801#endif
802
2fa25efc 803DEBUG(D_lookup) debug_printf("Total %d lookups\n", lookup_list_count);
e6d225ae 804
2fa25efc
JH
805lookup_list = store_malloc(sizeof(lookup_info *) * lookup_list_count);
806memset(lookup_list, 0, sizeof(lookup_info *) * lookup_list_count);
e6d225ae 807
2fa25efc
JH
808/* now add all lookups to the real list */
809for (struct lookupmodulestr * p = lookupmodules; p; p = p->next)
810 for (int j = 0; j < p->info->lookupcount; j++)
811 add_lookup_to_list(p->info->lookups[j]);
812store_reset(reset_point);
813/* just to be sure */
814lookupmodules = NULL;
e6d225ae
DW
815}
816
d185889f 817#endif /*!MACRO_PREDEF*/
059ec3d9 818/* End of drtables.c */