94db7f7fda92693f557bf685d2e795fd7e79389a
[exim.git] / src / src / dbstuff.h
1 /*************************************************
2 *     Exim - an Internet mail transport agent    *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2018 */
6 /* Copyright (c) The Exim Maintainers 2020 */
7 /* See the file NOTICE for conditions of use and distribution. */
8
9 /* This header file contains macro definitions so that a variety of DBM
10 libraries can be used by Exim. Nigel Metheringham provided the original set for
11 Berkeley DB 1.x in native mode and ndbm. Subsequently, versions for Berkeley DB
12 2.x and 3.x were added. Later still, support for tdb was added, courtesy of
13 James Antill. Most recently, support for native mode gdbm was added, with code
14 from Pierre A. Humblet, so Exim could be made to work with Cygwin.
15
16 For convenience, the definitions of the structures used in the various hints
17 databases are also kept in this file, which is used by the maintenance
18 utilities as well as the main Exim binary. */
19
20
21 # ifdef USE_TDB
22
23 /* ************************* tdb interface ************************ */
24
25 #include <tdb.h>
26
27 /* Basic DB type */
28 #define EXIM_DB TDB_CONTEXT
29
30 /* Cursor type: tdb uses the previous "key" in _nextkey() (really it wants
31 tdb_traverse to be called) */
32 #define EXIM_CURSOR TDB_DATA
33
34 /* The datum type used for queries */
35 #define EXIM_DATUM TDB_DATA
36
37 /* Some text for messages */
38 #define EXIM_DBTYPE "tdb"
39
40 /* Access functions */
41
42 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
43 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
44        *(dbpp) = tdb_open(CS name, 0, TDB_DEFAULT, flags, mode)
45
46 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
47 #define EXIM_DBGET(db, key, data)      \
48        (data = tdb_fetch(db, key), data.dptr != NULL)
49
50 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
51 #define EXIM_DBPUT(db, key, data)      \
52        tdb_store(db, key, data, TDB_REPLACE)
53
54 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
55 #define EXIM_DBPUTB(db, key, data)      \
56        tdb_store(db, key, data, TDB_INSERT)
57
58 /* Returns from EXIM_DBPUTB */
59
60 #define EXIM_DBPUTB_OK  0
61 #define EXIM_DBPUTB_DUP (-1)
62
63 /* EXIM_DBDEL */
64 #define EXIM_DBDEL(db, key) tdb_delete(db, key)
65
66 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
67 #define EXIM_DBCREATE_CURSOR(db, cursor) { \
68    *(cursor) = store_malloc(sizeof(TDB_DATA)); (*(cursor))->dptr = NULL; }
69
70 /* EXIM_DBSCAN - This is complicated because we have to free the last datum
71 free() must not die when passed NULL */
72 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
73        (key = (first ? tdb_firstkey(db) : tdb_nextkey(db, *(cursor))), \
74         free((cursor)->dptr), *(cursor) = key, \
75         key.dptr != NULL)
76
77 /* EXIM_DBDELETE_CURSOR - terminate scanning operation. */
78 #define EXIM_DBDELETE_CURSOR(cursor) store_free(cursor)
79
80 /* EXIM_DBCLOSE */
81 #define EXIM_DBCLOSE__(db)        tdb_close(db)
82
83 /* Datum access types - these are intended to be assignable */
84
85 #define EXIM_DATUM_SIZE(datum)  (datum).dsize
86 #define EXIM_DATUM_DATA(datum)  (datum).dptr
87
88 /* Free the stuff inside the datum. */
89
90 #define EXIM_DATUM_FREE(datum)  (free((datum).dptr), (datum).dptr = NULL)
91
92 /* No initialization is needed. */
93
94 #define EXIM_DATUM_INIT(datum)
95
96
97
98 /********************* Berkeley db native definitions **********************/
99
100 #elif defined USE_DB
101
102 #include <db.h>
103
104
105 /* We can distinguish between versions 1.x and 2.x/3.x by looking for a
106 definition of DB_VERSION_STRING, which is present in versions 2.x onwards. */
107
108 #ifdef DB_VERSION_STRING
109
110 # if DB_VERSION_MAJOR >= 6
111 #  error Version 6 and later BDB API is not supported
112 # endif
113
114 /* The API changed (again!) between the 2.x and 3.x versions */
115
116 #if DB_VERSION_MAJOR >= 3
117
118 /***************** Berkeley db 3.x/4.x native definitions ******************/
119
120 /* Basic DB type */
121 # if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1)
122 #  define EXIM_DB       DB_ENV
123 /* Cursor type, for scanning */
124 #  define EXIM_CURSOR   DBC
125
126 /* The datum type used for queries */
127 #  define EXIM_DATUM    DBT
128
129 /* Some text for messages */
130 #  define EXIM_DBTYPE   "db (v4.1+)"
131
132 /* Only more-recent versions.  5+ ? */
133 #  ifndef DB_FORCESYNC
134 #   define DB_FORCESYNC 0
135 #  endif
136
137
138 /* Access functions */
139
140 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. The
141 API changed for DB 4.1. - and we also starting using the "env" with a
142 specified working dir, to avoid the DBCONFIG file trap. */
143
144 #  define ENV_TO_DB(env) ((DB *)((env)->app_private))
145
146 #  define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
147   if (  db_env_create(dbpp, 0) != 0                                             \
148      || ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), 0)               \
149      || (*dbpp)->open(*dbpp, CS dirname, DB_CREATE|DB_INIT_MPOOL|DB_PRIVATE, 0) != 0\
150      )                                                                          \
151     *dbpp = NULL;                                       \
152   else if (db_create((DB **) &((*dbpp)->app_private), *dbpp, 0) != 0)           \
153     {                                                   \
154     ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0);   \
155     *dbpp = NULL;                                       \
156     }                                                   \
157   else if (ENV_TO_DB(*dbpp)->open(ENV_TO_DB(*dbpp), NULL, CS name, NULL,        \
158               (flags) == O_RDONLY ? DB_UNKNOWN : DB_HASH,                       \
159               (flags) == O_RDONLY ? DB_RDONLY : DB_CREATE,                      \
160               mode) != 0                                                        \
161           )                                                                     \
162     {                                                   \
163     ENV_TO_DB(*dbpp)->close(ENV_TO_DB(*dbpp), 0);       \
164     ((DB_ENV *)(*dbpp))->close((DB_ENV *)(*dbpp), 0);   \
165     *dbpp = NULL;                                       \
166     }
167
168 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
169 #  define EXIM_DBGET(db, key, data)      \
170        (ENV_TO_DB(db)->get(ENV_TO_DB(db), NULL, &key, &data, 0) == 0)
171
172 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
173 #  define EXIM_DBPUT(db, key, data)      \
174        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, 0)
175
176 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
177 #  define EXIM_DBPUTB(db, key, data)      \
178        ENV_TO_DB(db)->put(ENV_TO_DB(db), NULL, &key, &data, DB_NOOVERWRITE)
179
180 /* Return values from EXIM_DBPUTB */
181
182 #  define EXIM_DBPUTB_OK  0
183 #  define EXIM_DBPUTB_DUP DB_KEYEXIST
184
185 /* EXIM_DBDEL */
186 #  define EXIM_DBDEL(db, key)     ENV_TO_DB(db)->del(ENV_TO_DB(db), NULL, &key, 0)
187
188 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
189
190 #  define EXIM_DBCREATE_CURSOR(db, cursor) \
191        ENV_TO_DB(db)->cursor(ENV_TO_DB(db), NULL, cursor, 0)
192
193 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
194 #  define EXIM_DBSCAN(db, key, data, first, cursor)      \
195        ((cursor)->c_get(cursor, &key, &data,         \
196          (first? DB_FIRST : DB_NEXT)) == 0)
197
198 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
199 #  define EXIM_DBDELETE_CURSOR(cursor) \
200        (cursor)->c_close(cursor)
201
202 /* EXIM_DBCLOSE */
203 #  define EXIM_DBCLOSE__(db) \
204         (ENV_TO_DB(db)->close(ENV_TO_DB(db), 0) , ((DB_ENV *)(db))->close((DB_ENV *)(db), DB_FORCESYNC))
205
206 /* Datum access types - these are intended to be assignable. */
207
208 #  define EXIM_DATUM_SIZE(datum)  (datum).size
209 #  define EXIM_DATUM_DATA(datum)  (datum).data
210
211 /* The whole datum structure contains other fields that must be cleared
212 before use, but we don't have to free anything after reading data. */
213
214 #  define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
215 #  define EXIM_DATUM_FREE(datum)
216
217 # else  /* pre- 4.1 */
218
219 #  define EXIM_DB       DB
220
221 /* Cursor type, for scanning */
222 #  define EXIM_CURSOR   DBC
223
224 /* The datum type used for queries */
225 #  define EXIM_DATUM    DBT
226
227 /* Some text for messages */
228 #  define EXIM_DBTYPE   "db (v3/4)"
229
230 /* Access functions */
231
232 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed. */
233
234 #  define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
235        if (db_create(dbpp, NULL, 0) != 0 || \
236          ((*dbpp)->set_errcall(*dbpp, dbfn_bdb_error_callback), \
237          ((*dbpp)->open)(*dbpp, CS name, NULL, \
238          ((flags) == O_RDONLY)? DB_UNKNOWN : DB_HASH, \
239          ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
240          mode)) != 0) *(dbpp) = NULL
241
242 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
243 #  define EXIM_DBGET(db, key, data)      \
244        ((db)->get(db, NULL, &key, &data, 0) == 0)
245
246 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
247 #  define EXIM_DBPUT(db, key, data)      \
248        (db)->put(db, NULL, &key, &data, 0)
249
250 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
251 #  define EXIM_DBPUTB(db, key, data)      \
252        (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
253
254 /* Return values from EXIM_DBPUTB */
255
256 #  define EXIM_DBPUTB_OK  0
257 #  define EXIM_DBPUTB_DUP DB_KEYEXIST
258
259 /* EXIM_DBDEL */
260 #  define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
261
262 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
263
264 #  define EXIM_DBCREATE_CURSOR(db, cursor) \
265        (db)->cursor(db, NULL, cursor, 0)
266
267 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
268 #  define EXIM_DBSCAN(db, key, data, first, cursor)      \
269        ((cursor)->c_get(cursor, &key, &data,         \
270          (first? DB_FIRST : DB_NEXT)) == 0)
271
272 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
273 #  define EXIM_DBDELETE_CURSOR(cursor) \
274        (cursor)->c_close(cursor)
275
276 /* EXIM_DBCLOSE */
277 #  define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
278
279 /* Datum access types - these are intended to be assignable. */
280
281 #  define EXIM_DATUM_SIZE(datum)  (datum).size
282 #  define EXIM_DATUM_DATA(datum)  (datum).data
283
284 /* The whole datum structure contains other fields that must be cleared
285 before use, but we don't have to free anything after reading data. */
286
287 #  define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
288 #  define EXIM_DATUM_FREE(datum)
289
290 # endif
291
292
293 #else /* DB_VERSION_MAJOR >= 3 */
294
295 /******************* Berkeley db 2.x native definitions ********************/
296
297 /* Basic DB type */
298 #define EXIM_DB       DB
299
300 /* Cursor type, for scanning */
301 #define EXIM_CURSOR   DBC
302
303 /* The datum type used for queries */
304 #define EXIM_DATUM    DBT
305
306 /* Some text for messages */
307 #define EXIM_DBTYPE   "db (v2)"
308
309 /* Access functions */
310
311 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
312 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp)         \
313        if ((errno = db_open(CS name, DB_HASH,           \
314          ((flags) == O_RDONLY)? DB_RDONLY : DB_CREATE, \
315          mode, NULL, NULL, dbpp)) != 0) *(dbpp) = NULL
316
317 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
318 #define EXIM_DBGET(db, key, data)      \
319        ((db)->get(db, NULL, &key, &data, 0) == 0)
320
321 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
322 #define EXIM_DBPUT(db, key, data)      \
323        (db)->put(db, NULL, &key, &data, 0)
324
325 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
326 #define EXIM_DBPUTB(db, key, data)      \
327        (db)->put(db, NULL, &key, &data, DB_NOOVERWRITE)
328
329 /* Return values from EXIM_DBPUTB */
330
331 #define EXIM_DBPUTB_OK  0
332 #define EXIM_DBPUTB_DUP DB_KEYEXIST
333
334 /* EXIM_DBDEL */
335 #define EXIM_DBDEL(db, key)     (db)->del(db, NULL, &key, 0)
336
337 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation */
338
339 /* The API of this function was changed between releases 2.4.14 and 2.7.3. I do
340 not know exactly where the change happened, but the Change Log for 2.5.9 lists
341 the new option that is available, so I guess that it happened at 2.5.x. */
342
343 #if DB_VERSION_MINOR >= 5
344 #define EXIM_DBCREATE_CURSOR(db, cursor) \
345        (db)->cursor(db, NULL, cursor, 0)
346 #else
347 #define EXIM_DBCREATE_CURSOR(db, cursor) \
348        (db)->cursor(db, NULL, cursor)
349 #endif
350
351 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
352 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
353        ((cursor)->c_get(cursor, &key, &data,         \
354          (first? DB_FIRST : DB_NEXT)) == 0)
355
356 /* EXIM_DBDELETE_CURSOR - terminate scanning operation */
357 #define EXIM_DBDELETE_CURSOR(cursor) \
358        (cursor)->c_close(cursor)
359
360 /* EXIM_DBCLOSE */
361 #define EXIM_DBCLOSE__(db)        (db)->close(db, 0)
362
363 /* Datum access types - these are intended to be assignable. */
364
365 #define EXIM_DATUM_SIZE(datum)  (datum).size
366 #define EXIM_DATUM_DATA(datum)  (datum).data
367
368 /* The whole datum structure contains other fields that must be cleared
369 before use, but we don't have to free anything after reading data. */
370
371 #define EXIM_DATUM_INIT(datum)   memset(&datum, 0, sizeof(datum))
372 #define EXIM_DATUM_FREE(datum)
373
374 #endif /* DB_VERSION_MAJOR >= 3 */
375
376
377 /* If DB_VERSION_TYPE is not defined, we have version 1.x */
378
379 #else  /* DB_VERSION_TYPE */
380
381 /******************* Berkeley db 1.x native definitions ********************/
382
383 /* Basic DB type */
384 #define EXIM_DB       DB
385
386 /* Cursor type, not used with DB 1.x: just set up a dummy */
387 #define EXIM_CURSOR   int
388
389 /* The datum type used for queries */
390 #define EXIM_DATUM    DBT
391
392 /* Some text for messages */
393 #define EXIM_DBTYPE   "db (v1)"
394
395 /* When scanning, for the non-first case we historically just passed 0
396 as the flags field and it worked.  On FreeBSD 8 it no longer works and
397 instead leads to memory exhaustion.  The man-page on FreeBSD says to use
398 R_NEXT, but this 1.x is a historical fallback and I've no idea how portable
399 the use of that flag is; so the solution is to define R_NEXT here if it's not
400 already defined, with a default value of 0 because that's what we've always
401 before been able to pass successfully. */
402 #ifndef R_NEXT
403 #define R_NEXT 0
404 #endif
405
406 /* Access functions */
407
408 /* EXIM_DBOPEN - sets *dbpp to point to an EXIM_DB, NULL if failed */
409 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
410        *(dbpp) = dbopen(CS name, flags, mode, DB_HASH, NULL)
411
412 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
413 #define EXIM_DBGET(db, key, data)      \
414        ((db)->get(db, &key, &data, 0) == 0)
415
416 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
417 #define EXIM_DBPUT(db, key, data)      \
418        (db)->put(db, &key, &data, 0)
419
420 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
421 #define EXIM_DBPUTB(db, key, data)      \
422        (db)->put(db, &key, &data, R_NOOVERWRITE)
423
424 /* Returns from EXIM_DBPUTB */
425
426 #define EXIM_DBPUTB_OK  0
427 #define EXIM_DBPUTB_DUP 1
428
429 /* EXIM_DBDEL */
430 #define EXIM_DBDEL(db, key)     (db)->del(db, &key, 0)
431
432 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
433 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
434
435 /* EXIM_DBSCAN - returns TRUE if data is returned, FALSE at end */
436 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
437        ((db)->seq(db, &key, &data, (first? R_FIRST : R_NEXT)) == 0)
438
439 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
440 #define EXIM_DBDELETE_CURSOR(cursor) { }
441
442 /* EXIM_DBCLOSE */
443 #define EXIM_DBCLOSE__(db)        (db)->close(db)
444
445 /* Datum access types - these are intended to be assignable */
446
447 #define EXIM_DATUM_SIZE(datum)  (datum).size
448 #define EXIM_DATUM_DATA(datum)  (datum).data
449
450 /* There's no clearing required before use, and we don't have to free anything
451 after reading data. */
452
453 #define EXIM_DATUM_INIT(datum)
454 #define EXIM_DATUM_FREE(datum)
455
456 #endif /* DB_VERSION_STRING */
457
458
459
460 /********************* gdbm interface definitions **********************/
461
462 #elif defined USE_GDBM
463
464 #include <gdbm.h>
465
466 /* Basic DB type */
467 typedef struct {
468        GDBM_FILE gdbm;  /* Database */
469        datum lkey;      /* Last key, for scans */
470 } EXIM_DB;
471
472 /* Cursor type, not used with gdbm: just set up a dummy */
473 #define EXIM_CURSOR int
474
475 /* The datum type used for queries */
476 #define EXIM_DATUM datum
477
478 /* Some text for messages */
479
480 #define EXIM_DBTYPE "gdbm"
481
482 /* Access functions */
483
484 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
485 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
486      { (*(dbpp)) = (EXIM_DB *) malloc(sizeof(EXIM_DB));\
487        if (*(dbpp) != NULL) { \
488          (*(dbpp))->lkey.dptr = NULL;\
489          (*(dbpp))->gdbm = gdbm_open(CS name, 0, (((flags) & O_CREAT))?GDBM_WRCREAT:(((flags) & (O_RDWR|O_WRONLY))?GDBM_WRITER:GDBM_READER), mode, 0);\
490           if ((*(dbpp))->gdbm == NULL) {\
491               free(*(dbpp));\
492               *(dbpp) = NULL;\
493           }\
494        }\
495      }
496
497 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
498 #define EXIM_DBGET(db, key, data)      \
499        (data = gdbm_fetch(db->gdbm, key), data.dptr != NULL)
500
501 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
502 #define EXIM_DBPUT(db, key, data)      \
503        gdbm_store(db->gdbm, key, data, GDBM_REPLACE)
504
505 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
506 #define EXIM_DBPUTB(db, key, data)      \
507        gdbm_store(db->gdbm, key, data, GDBM_INSERT)
508
509 /* Returns from EXIM_DBPUTB */
510
511 #define EXIM_DBPUTB_OK  0
512 #define EXIM_DBPUTB_DUP 1
513
514 /* EXIM_DBDEL */
515 #define EXIM_DBDEL(db, key) gdbm_delete(db->gdbm, key)
516
517 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
518 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
519
520 /* EXIM_DBSCAN */
521 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
522   ( key = ((first)? gdbm_firstkey(db->gdbm) : gdbm_nextkey(db->gdbm, db->lkey)), \
523     (((db)->lkey.dptr != NULL)? (free((db)->lkey.dptr),1) : 1),\
524     db->lkey = key, key.dptr != NULL)
525
526 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
527 #define EXIM_DBDELETE_CURSOR(cursor) { }
528
529 /* EXIM_DBCLOSE */
530 #define EXIM_DBCLOSE__(db) \
531 { gdbm_close((db)->gdbm);\
532   if ((db)->lkey.dptr != NULL) free((db)->lkey.dptr);\
533   free(db); }
534
535 /* Datum access types - these are intended to be assignable */
536
537 #define EXIM_DATUM_SIZE(datum) (datum).dsize
538 #define EXIM_DATUM_DATA(datum) (datum).dptr
539
540 /* There's no clearing required before use, but we have to free the dptr
541 after reading data. */
542
543 #define EXIM_DATUM_INIT(datum)
544 #define EXIM_DATUM_FREE(datum) free(datum.dptr)
545
546 #else  /* USE_GDBM */
547
548
549 /* If none of USE_DB, USG_GDBM, or USE_TDB are set, the default is the NDBM
550 interface */
551
552
553 /********************* ndbm interface definitions **********************/
554
555 #include <ndbm.h>
556
557 /* Basic DB type */
558 #define EXIM_DB DBM
559
560 /* Cursor type, not used with ndbm: just set up a dummy */
561 #define EXIM_CURSOR int
562
563 /* The datum type used for queries */
564 #define EXIM_DATUM datum
565
566 /* Some text for messages */
567
568 #define EXIM_DBTYPE "ndbm"
569
570 /* Access functions */
571
572 /* EXIM_DBOPEN - returns a EXIM_DB *, NULL if failed */
573 #define EXIM_DBOPEN__(name, dirname, flags, mode, dbpp) \
574        *(dbpp) = dbm_open(CS name, flags, mode)
575
576 /* EXIM_DBGET - returns TRUE if successful, FALSE otherwise */
577 #define EXIM_DBGET(db, key, data)      \
578        (data = dbm_fetch(db, key), data.dptr != NULL)
579
580 /* EXIM_DBPUT - returns nothing useful, assumes replace mode */
581 #define EXIM_DBPUT(db, key, data)      \
582        dbm_store(db, key, data, DBM_REPLACE)
583
584 /* EXIM_DBPUTB - non-overwriting for use by dbmbuild */
585 #define EXIM_DBPUTB(db, key, data)      \
586        dbm_store(db, key, data, DBM_INSERT)
587
588 /* Returns from EXIM_DBPUTB */
589
590 #define EXIM_DBPUTB_OK  0
591 #define EXIM_DBPUTB_DUP 1
592
593 /* EXIM_DBDEL */
594 #define EXIM_DBDEL(db, key) dbm_delete(db, key)
595
596 /* EXIM_DBCREATE_CURSOR - initialize for scanning operation (null) */
597 #define EXIM_DBCREATE_CURSOR(db, cursor) {}
598
599 /* EXIM_DBSCAN */
600 #define EXIM_DBSCAN(db, key, data, first, cursor)      \
601        (key = (first? dbm_firstkey(db) : dbm_nextkey(db)), key.dptr != NULL)
602
603 /* EXIM_DBDELETE_CURSOR - terminate scanning operation (null). */
604 #define EXIM_DBDELETE_CURSOR(cursor) { }
605
606 /* EXIM_DBCLOSE */
607 #define EXIM_DBCLOSE__(db) dbm_close(db)
608
609 /* Datum access types - these are intended to be assignable */
610
611 #define EXIM_DATUM_SIZE(datum) (datum).dsize
612 #define EXIM_DATUM_DATA(datum) (datum).dptr
613
614 /* There's no clearing required before use, and we don't have to free anything
615 after reading data. */
616
617 #define EXIM_DATUM_INIT(datum)
618 #define EXIM_DATUM_FREE(datum)
619
620 #endif /* USE_GDBM */
621
622
623
624
625
626 # ifdef COMPILE_UTILITY
627
628 #  define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
629   EXIM_DBOPEN__(name, dirname, flags, mode, dbpp)
630 #  define EXIM_DBCLOSE(db) EXIM_DBCLOSE__(db)
631
632 # else
633
634 #  define EXIM_DBOPEN(name, dirname, flags, mode, dbpp) \
635   do { \
636   DEBUG(D_hints_lookup) \
637     debug_printf_indent("EXIM_DBOPEN: file <%s> dir <%s> flags=%s\n", \
638       (name), (dirname),                \
639       (flags) == O_RDONLY ? "O_RDONLY"  \
640       : (flags) == O_RDWR ? "O_RDWR"    \
641       : (flags) == (O_RDWR|O_CREAT) ? "O_RDWR|O_CREAT"  \
642       : "??");  \
643   if (is_tainted2(name, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB file not permitted", name) \
644       || is_tainted2(dirname, LOG_MAIN|LOG_PANIC, "Tainted name '%s' for DB directory not permitted", dirname)) \
645     *dbpp = NULL; \
646   else \
647     { EXIM_DBOPEN__(name, dirname, flags, mode, dbpp); } \
648   DEBUG(D_hints_lookup) debug_printf_indent("returned from EXIM_DBOPEN: %p\n", *dbpp); \
649   } while(0)
650 #  define EXIM_DBCLOSE(db) \
651   do { \
652   DEBUG(D_hints_lookup) debug_printf_indent("EXIM_DBCLOSE(%p)\n", db); \
653   EXIM_DBCLOSE__(db); \
654   } while(0)
655
656 #  endif
657
658 /********************* End of dbm library definitions **********************/
659
660
661 /* Structure for carrying around an open DBM file, and an open locking file
662 that relates to it. */
663
664 typedef struct {
665   EXIM_DB *dbptr;
666   int lockfd;
667 } open_db;
668
669
670 /* Structures for records stored in exim database dbm files. They all
671 start with the same fields, described in the generic type. */
672
673
674 typedef struct {
675   time_t time_stamp;      /* Timestamp of writing */
676 } dbdata_generic;
677
678
679 /* This structure keeps track of retry information for a host or a local
680 address. */
681
682 typedef struct {
683   time_t time_stamp;
684   /*************/
685   time_t first_failed;    /* Time of first failure */
686   time_t last_try;        /* Time of last try */
687   time_t next_try;        /* Time of next try */
688   BOOL   expired;         /* Retry time has expired */
689   int    basic_errno;     /* Errno of last failure */
690   int    more_errno;      /* Additional information */
691   uschar text[1];         /* Text message for last failure */
692 } dbdata_retry;
693
694 /* These structures keep track of addresses that have had callout verification
695 performed on them. There are two groups of records:
696
697 1. keyed by localpart@domain -
698      Full address was tested and record holds result
699
700 2. keyed by domain -
701      Domain response upto MAIL FROM:<>, postmaster, random local part;
702
703 If a record exists, the result field is either ccache_accept or ccache_reject,
704 or, for a domain record only, ccache_reject_mfnull when MAIL FROM:<> was
705 rejected. The other fields, however, (which are only relevant to domain
706 records) may also contain ccache_unknown if that particular test has not been
707 done.
708
709 Originally, there was only one structure, used for both types. However, it got
710 expanded for domain records, so it got split. To make it possible for Exim to
711 handle the old type of record, we retain the old definition. The different
712 kinds of record can be distinguished by their different lengths. */
713
714 typedef struct {
715   time_t time_stamp;
716   /*************/
717   int   result;
718   int   postmaster_result; /* Postmaster is accepted */
719   int   random_result;     /* Random local part was accepted */
720 } dbdata_callout_cache_obs;
721
722 typedef struct {
723   time_t time_stamp;       /* Timestamp of last address check */
724   /*************/
725   int   result;            /* accept or reject */
726 } dbdata_callout_cache_address;
727
728 /* For this new layout, we put the additional fields (the timestamps)
729 last so that if somebody reverts to an older Exim, the new records will
730 still make sense because they match the old layout. */
731
732 typedef struct {
733   time_t time_stamp;       /* Time stamp of last connection */
734   /*************/
735   int   result;            /* Domain reject or accept */
736   int   postmaster_result; /* Postmaster result */
737   int   random_result;     /* Random result */
738   time_t postmaster_stamp; /* Timestamp of postmaster check */
739   time_t random_stamp;     /* Timestamp of random check */
740 } dbdata_callout_cache;
741
742 /* This structure keeps track of messages that are waiting for a particular
743 host for a particular transport. */
744
745 typedef struct {
746   time_t time_stamp;
747   /*************/
748   int    count;           /* Count of message ids */
749   int    sequence;        /* Sequence for continued records */
750   uschar text[1];         /* One long character string */
751 } dbdata_wait;
752
753
754 /* The contents of the "misc" database are a mixture of different kinds of
755 record, as defined below. The keys used for a specific type all start with a
756 given string such as "etrn-" or "host-serialize-". */
757
758
759 /* This structure records a connection to a particular host, for the
760 purpose of serializing access to certain hosts. For possible future extension,
761 a field is defined for holding the count of connections, but it is not
762 at present in use. The same structure is used for recording a running ETRN
763 process. */
764
765 typedef struct {
766   time_t time_stamp;
767   /*************/
768   int    count;           /* Reserved for possible connection count */
769 } dbdata_serialize;
770
771
772 /* This structure records the information required for the ratelimit
773 ACL condition. */
774
775 typedef struct {
776   time_t time_stamp;
777   /*************/
778   int    time_usec;       /* Fractional part of time, from gettimeofday() */
779   double rate;            /* Smoothed sending rate at that time */
780 } dbdata_ratelimit;
781
782 /* Same as above, plus a Bloom filter for uniquifying events. */
783
784 typedef struct {
785   dbdata_ratelimit dbd;
786   time_t   bloom_epoch;   /* When the Bloom filter was last reset */
787   unsigned bloom_size;    /* Number of bytes in the Bloom filter */
788   uschar   bloom[40];     /* Bloom filter which may be larger than this */
789 } dbdata_ratelimit_unique;
790
791
792 /* For "seen" ACL condition */
793 typedef struct {
794   time_t time_stamp;
795 } dbdata_seen;
796
797 #ifndef DISABLE_PIPE_CONNECT
798 /* This structure records the EHLO responses, cleartext and crypted,
799 for an IP, as bitmasks (cf. OPTION_TLS).  For LIMITS, also values
800 advertised for MAILMAX, RCPTMAX and RCPTDOMAINMAX; zero meaning no
801 value advertised. */
802
803 typedef struct {
804   unsigned short cleartext_features;
805   unsigned short crypted_features;
806   unsigned short cleartext_auths;
807   unsigned short crypted_auths;
808
809 # ifdef EXPERIMENTAL_ESMTP_LIMITS
810   unsigned int limit_mail;
811   unsigned int limit_rcpt;
812   unsigned int limit_rcptdom;
813 # endif
814 } ehlo_resp_precis;
815
816 typedef struct {
817   time_t time_stamp;
818   /*************/
819   ehlo_resp_precis data;
820 } dbdata_ehlo_resp;
821 #endif
822
823 typedef struct {
824   time_t time_stamp;
825   /*************/
826   uschar verify_override:1;
827   uschar ocsp:3;
828   uschar session[1];
829 } dbdata_tls_session;
830
831
832 /* End of dbstuff.h */