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