From 4d12daceb37ee7d0636f3bed0c8709a2bbdee653 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Sat, 31 Aug 2024 22:07:17 +0100 Subject: [PATCH] Macros for module func call numbers --- src/OS/Makefile-Base | 4 ++ src/scripts/MakeLinks | 2 +- src/src/acl.c | 17 +++----- src/src/exim.h | 2 + src/src/expand.c | 4 +- src/src/lookups/spf.c | 7 +-- src/src/miscmods/README | 84 ++++++++++++++++++++++++++++++++++++ src/src/miscmods/dmarc.c | 11 ++--- src/src/miscmods/dmarc_api.h | 17 ++++++++ src/src/miscmods/spf.c | 12 +++--- src/src/miscmods/spf_api.h | 19 ++++++++ src/src/receive.c | 2 +- 12 files changed, 153 insertions(+), 28 deletions(-) create mode 100644 src/src/miscmods/README create mode 100644 src/src/miscmods/dmarc_api.h create mode 100644 src/src/miscmods/spf_api.h diff --git a/src/OS/Makefile-Base b/src/OS/Makefile-Base index 43cec361c..591b4261c 100644 --- a/src/OS/Makefile-Base +++ b/src/OS/Makefile-Base @@ -685,6 +685,8 @@ HDRS = blob.h \ hintsdb/hints_tdb.h \ local_scan.h \ macros.h \ + miscmods/dmarc_api.h \ + miscmods/spf_api.h \ mytypes.h \ path_max.h \ sha_ver.h \ @@ -704,6 +706,8 @@ PHDRS = ../config.h \ ../hintsdb/hints_tdb.h \ ../local_scan.h \ ../macros.h \ + ../miscmods/dmarc_api.h \ + ../miscmods/spf_api.h \ ../mytypes.h \ ../path_max.h \ ../structs.h \ diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks index e45097243..0be066352 100755 --- a/src/scripts/MakeLinks +++ b/src/scripts/MakeLinks @@ -94,7 +94,7 @@ d="miscmods" mkdir $d cd $d # Makefile is generated -for f in dmarc.c dmarc.h spf.c spf.h +for f in dmarc.c dmarc.h dmarc_api.h spf.c spf.h spf_api.h do ln -s ../../src/$d/$f $f done diff --git a/src/src/acl.c b/src/src/acl.c index 30fc09174..023ac2ff6 100644 --- a/src/src/acl.c +++ b/src/src/acl.c @@ -3961,29 +3961,24 @@ for (; cb; cb = cb->next) typedef uschar * (*efn_t)(int); uschar * expanded_query; -debug_printf("%s %d\n", __FUNCTION__, __LINE__); if (!mi) { rc = DEFER; break; } /* shouldn't happen */ -debug_printf("%s %d: mi %p\n", __FUNCTION__, __LINE__, mi); if (!f.dmarc_has_been_checked) { typedef int (*pfn_t)(void); - (void) (((pfn_t *) mi->functions)[0]) (); /* dmarc_process */ + (void) (((pfn_t *) mi->functions)[DMARC_PROCESS]) (); f.dmarc_has_been_checked = TRUE; } -debug_printf("%s %d\n", __FUNCTION__, __LINE__); /* used long way of dmarc_exim_expand_query() in case we need more view into the process in the future. */ /*XXX is this call used with any other arg? */ - expanded_query = (((efn_t *) mi->functions)[1]) (DMARC_VERIFY_STATUS); - -debug_printf("%s %d\n", __FUNCTION__, __LINE__); + expanded_query = (((efn_t *) mi->functions)[DMARC_EXPAND_QUERY]) + (DMARC_VERIFY_STATUS); rc = match_isinlist(expanded_query, &arg, 0, NULL, NULL, MCL_STRING, TRUE, NULL); -debug_printf("%s %d\n", __FUNCTION__, __LINE__); } break; #endif @@ -4223,7 +4218,9 @@ debug_printf("%s %d\n", __FUNCTION__, __LINE__); /* We have hardwired function-call numbers, and also prototypes for the functions. We could do a function name table search for the number but I can't see how to deal with prototypes. Is a K&R non-prototyped - function still usable with today's compilers? */ + function still usable with today's compilers (but we would lose on + type-checking)? We could macroize the typedef, and even the function + table access - but it obscures how it works rather. */ { misc_module_info * mi = misc_mod_find(US"spf", &log_message); typedef int (*fn_t)(const uschar **, const uschar *, int); @@ -4232,7 +4229,7 @@ debug_printf("%s %d\n", __FUNCTION__, __LINE__); if (!mi) { rc = DEFER; break; } /* shouldn't happen */ - fn = ((fn_t *) mi->functions)[0]; /* spf_process() */ + fn = ((fn_t *) mi->functions)[SPF_PROCESS]; rc = fn(&arg, sender_address, cb->type == ACLC_SPF ? SPF_PROCESS_NORMAL : SPF_PROCESS_GUESS); diff --git a/src/src/exim.h b/src/src/exim.h index 284748c5d..c996a2f8c 100644 --- a/src/src/exim.h +++ b/src/src/exim.h @@ -544,12 +544,14 @@ config.h, mytypes.h, and store.h, so we don't need to mention them explicitly. #endif #ifdef SUPPORT_SPF # include "miscmods/spf.h" +# include "miscmods/spf_api.h" #endif #ifndef DISABLE_DKIM # include "dkim.h" #endif #ifdef SUPPORT_DMARC # include "miscmods/dmarc.h" +# include "miscmods/dmarc_api.h" # include #endif diff --git a/src/src/expand.c b/src/src/expand.c index a6b05bd87..af3816051 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -4888,7 +4888,7 @@ while (*s) if (mi) { typedef gstring * (*fn_t)(gstring *); - fn_t fn = ((fn_t *) mi->functions)[1]; /* authres_spf */ + fn_t fn = ((fn_t *) mi->functions)[SPF_AUTHRES]; yield = fn(yield); } } @@ -4903,7 +4903,7 @@ while (*s) { /*XXX is authres common enough to be generic? */ typedef gstring * (*fn_t)(gstring *); - fn_t fn = ((fn_t *) mi->functions)[2]; /* authres_dmarc*/ + fn_t fn = ((fn_t *) mi->functions)[DMARC_AUTHRES]; yield = fn(yield); } } diff --git a/src/src/lookups/spf.c b/src/src/lookups/spf.c index a06f9117d..996bae294 100644 --- a/src/src/lookups/spf.c +++ b/src/src/lookups/spf.c @@ -39,7 +39,7 @@ misc_module_info * mi = misc_mod_find(US"spf", errmsg); if (mi) { typedef void * (*fn_t)(const uschar *, uschar **); - return (((fn_t *) mi->functions)[3]) (filename, errmsg); + return (((fn_t *) mi->functions)[SPF_OPEN]) (filename, errmsg); } return NULL; } @@ -52,7 +52,7 @@ misc_module_info * mi = misc_mod_find(US"spf", NULL); if (mi) { typedef void (*fn_t)(void *); - return (((fn_t *) mi->functions)[4]) (handle); + return (((fn_t *) mi->functions)[SPF_CLOSE]) (handle); } } @@ -67,7 +67,8 @@ if (mi) { typedef int (*fn_t) (void *, const uschar *, const uschar *, int, uschar **, uschar **, uint *, const uschar *); - return (((fn_t *) mi->functions)[5]) (handle, filename, keystring, key_len, + return (((fn_t *) mi->functions)[SPF_FIND]) + (handle, filename, keystring, key_len, result, errmsg, do_cache, opts); } return FAIL; diff --git a/src/src/miscmods/README b/src/src/miscmods/README new file mode 100644 index 000000000..e534a4eed --- /dev/null +++ b/src/src/miscmods/README @@ -0,0 +1,84 @@ +/************************************************* +* Exim - an Internet mail transport agent * +*************************************************/ + +Copyright (c) The Exim Maintainers 2024 + +This directory contains source for modules that can be built as part +of Exim, either static-linked or as dynamic-load modules. Doing the +latter keeps the runtime binary smaller when a feature is not used +by the configuration, especially when a library is involved. + +Which modules are built, and the choice of static vs. dynamic, is +under the control of the Local/Makefile at build time. +Any combination of static/dynamic is valid. + +Moudules built for dynamic load must be installed in a directory +which is defined in Local/Makefile. + +The API starts with a struct with a known name _module_info. +For dynamic builds this includes a magic number permitting versioning +of the highlevel interface. +The structure has elements for some commonly-needed call types +(init, version-report etc.). Any my be left as null pointers; +those present will be called at appropriate times. + +The current list is + init + lib_vers_report + smtp_reset + msg_init + +Then there are three pair of elements, each being a table pointer +and table length, for options, functions, and variable that the +module provides. + +The options table defines main-section configuration options, using +the same definition entry struct as the main table in readconf.c; +entries here should have their proper opt_ and +should be duplicated in the main table, but with opt_module and the +module name (this supports both getting the module loaded, if dynamic, +and writing the value from the config). Entries must be in order by +the option name. + +The functions table defines service functions additional to the "common" +ones noted above. Each offset in the table should have a #define in an +include-file brought in to the general set by exim.h. + +The variables table defins $variables for expansion, using the same +definition entry struct as the main var_table in expand.c; +entries here should have their proper vtype_ and should be duplicated +in the main table but with vtype_module and the module name. + +There are service functions to locate and to locate-or-load modules +by name; these hide the static/dynamic aspect of a module. Most +new coding will only need these for calls to the "additiona" custom +functions a module provides. The example code is: + + { + /* You need to know the function's prototype */ + typedef int (*fn_t)(const uschar **, const uschar *, int); + fn_t fn; + misc_module_info * mi = misc_mod_find(US"spf", &log_message); + + if (mi) + { + fn = ((fn_t *) mi->functions)[SPF_PROCESS]; + rc = fn(args...); + } + } + + + +Adding new modules +------------------ + +Put the code in this directory. Use filenames starting with the module name. +Write an include file with anything callers need to know, in particular +#defines for the function call numbers. Include that file from exim.h +and add it to HDRS and PHDRS in OS/Makefile-Base. +Add a SUPPORT_ line to Local/Makefile, and (if dynamic) any +SUPPORT__INCLUDE or SUPPORT__LIBS required. +Add the capitalised module name to the "miscmods" like in +scripts/Configure-Makefile. +Add all the filenames to the "miscmods" list in scripts/Makelinks diff --git a/src/src/miscmods/dmarc.c b/src/src/miscmods/dmarc.c index 0a97bf6b7..37648d045 100644 --- a/src/src/miscmods/dmarc.c +++ b/src/src/miscmods/dmarc.c @@ -461,7 +461,8 @@ if (!dmarc_abort && !sender_host_authenticated) { typedef SPF_response_t * (*fn_t)(void); if (spf_mod_info) - spf_response_p = ((fn_t *) spf_mod_info->functions)[2](); /* spf_get_response */ + /*XXX ugly use of a pointer */ + spf_response_p = ((fn_t *) spf_mod_info->functions)[SPF_GET_RESPONSE](); } if (!spf_response_p) @@ -746,10 +747,10 @@ static optionlist dmarc_options[] = { }; static void * dmarc_functions[] = { - dmarc_process, - dmarc_exim_expand_query, - authres_dmarc, - dmarc_store_data, + [DMARC_PROCESS] = dmarc_process, + [DMARC_EXPAND_QUERY] = dmarc_exim_expand_query, + [DMARC_AUTHRES] = authres_dmarc, + [DMARC_STORE_DATA] = dmarc_store_data, }; /* dmarc_forensic_sender is provided for visibility of the the option setting diff --git a/src/src/miscmods/dmarc_api.h b/src/src/miscmods/dmarc_api.h new file mode 100644 index 000000000..6ba8a5060 --- /dev/null +++ b/src/src/miscmods/dmarc_api.h @@ -0,0 +1,17 @@ +/************************************************* +* Exim - an Internet mail transport agent * +*************************************************/ + +/* Copyright (c) The Exim Maintainers 2024 */ +/* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* API definitions for the dmarc module */ + + +/* Function table entry numbers */ + +#define DMARC_PROCESS 0 +#define DMARC_EXPAND_QUERY 1 +#define DMARC_AUTHRES 2 +#define DMARC_STORE_DATA 3 diff --git a/src/src/miscmods/spf.c b/src/src/miscmods/spf.c index f28fd0cbf..ea23c1c65 100644 --- a/src/src/miscmods/spf.c +++ b/src/src/miscmods/spf.c @@ -565,13 +565,13 @@ static optionlist spf_options[] = { }; static void * spf_functions[] = { - spf_process, - authres_spf, - spf_get_response, /* ugly; for dmarc */ + [SPF_PROCESS] = spf_process, + [SPF_AUTHRES] = authres_spf, + [SPF_GET_RESPONSE] = spf_get_response, /* ugly; for dmarc */ - spf_lookup_open, - spf_lookup_close, - spf_lookup_find, + [SPF_OPEN] = spf_lookup_open, + [SPF_CLOSE] = spf_lookup_close, + [SPF_FIND] = spf_lookup_find, }; static var_entry spf_variables[] = { diff --git a/src/src/miscmods/spf_api.h b/src/src/miscmods/spf_api.h new file mode 100644 index 000000000..3801e3e3f --- /dev/null +++ b/src/src/miscmods/spf_api.h @@ -0,0 +1,19 @@ +/************************************************* +* Exim - an Internet mail transport agent * +*************************************************/ + +/* Copyright (c) The Exim Maintainers 2024 */ +/* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* API definitions for the spfmodule */ + + +/* Function table entry numbers */ + +#define SPF_PROCESS 0 +#define SPF_AUTHRES 1 +#define SPF_GET_RESPONSE 2 +#define SPF_OPEN 3 +#define SPF_CLOSE 4 +#define SPF_FIND 5 diff --git a/src/src/receive.c b/src/src/receive.c index 37b152f48..a6b7722bf 100644 --- a/src/src/receive.c +++ b/src/src/receive.c @@ -3631,7 +3631,7 @@ else if (mi) { typedef int (*fn_t)(header_line *); - (((fn_t *) mi->functions)[3]) (dmarc_from_header); + (((fn_t *) mi->functions)[DMARC_STORE_DATA]) (dmarc_from_header); } } #endif -- 2.30.2