ph10 2005/06/22 11:17:23 BST
Modified files:
exim-doc/doc-misc WishList
exim-doc/doc-txt ChangeLog NewStuff
exim-src/src expand.c functions.h match.c verify.c
exim-test-orig/AutoTest/confs 082
exim-test-orig/AutoTest/scripts 082
exim-test-orig/AutoTest/stdout 082
Log:
Added the long-awaited ${if match_ip condition.
Revision Changes Path
1.41 +0 -18 exim/exim-doc/doc-misc/WishList
1.167 +2 -0 exim/exim-doc/doc-txt/ChangeLog
1.52 +35 -0 exim/exim-doc/doc-txt/NewStuff
1.34 +39 -0 exim/exim-src/src/expand.c
1.17 +1 -0 exim/exim-src/src/functions.h
1.6 +3 -2 exim/exim-src/src/match.c
1.20 +105 -68 exim/exim-src/src/verify.c
1.2 +1 -0 exim/exim-test-orig/AutoTest/confs/082
1.14 +14 -0 exim/exim-test-orig/AutoTest/scripts/082
1.15 +14 -0 exim/exim-test-orig/AutoTest/stdout/082
Index: WishList
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-misc/WishList,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -r1.40 -r1.41
--- WishList 21 Jun 2005 14:14:55 -0000 1.40
+++ WishList 22 Jun 2005 10:17:22 -0000 1.41
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-misc/WishList,v 1.40 2005/06/21 14:14:55 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-misc/WishList,v 1.41 2005/06/22 10:17:22 ph10 Exp $
EXIM 4 WISH LIST
----------------
@@ -862,24 +862,6 @@
So as to avoid duplication problems when sending multiple addresses in multiple
copies to the same address.
-------------------------------------------------------------------------------
-
-(73) 17-Jul-02 M Match a list from within a condition
-
-e.g. ${if matchdomain {$domain}{+domainlist} ...
- ${if matchhost {$sender_host_address}{1.2.3.4/10:2.3.4.5/16}...
-
-Thought needed about how to handle host names. This may be too messy to specify
-cleanly.
-
-22-Apr-04: Implemented for domains, addresses, and local parts. Hosts are
-too messy!
-
-The only sensible approach seems to be to allow IP address arguments only.
-Anything else should be diagnosed as an error. However, if a name appears in
-the list, a PTR lookup should be done. This may require a lot of refactoring
-in the code, because of the current assumption that were are (almost) always
-dealing with THE sending host.
------------------------------------------------------------------------------
(74) 22-Jul-02 M Extend -bV to do more semantic checking
Index: ChangeLog
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/ChangeLog,v
retrieving revision 1.166
retrieving revision 1.167
diff -u -r1.166 -r1.167
--- ChangeLog 21 Jun 2005 14:14:55 -0000 1.166
+++ ChangeLog 22 Jun 2005 10:17:22 -0000 1.167
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.166 2005/06/21 14:14:55 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-txt/ChangeLog,v 1.167 2005/06/22 10:17:22 ph10 Exp $
Change log file for Exim from version 4.21
-------------------------------------------
@@ -173,6 +173,8 @@
These problems did NOT occur unless DomainKeys support was compiled.
PH/23 Added daemon_startup_retries and daemon_startup_sleep.
+
+PH/24 Added ${if match_ip condition.
Exim version 4.51
Index: NewStuff
===================================================================
RCS file: /home/cvs/exim/exim-doc/doc-txt/NewStuff,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -r1.51 -r1.52
--- NewStuff 21 Jun 2005 14:14:55 -0000 1.51
+++ NewStuff 22 Jun 2005 10:17:22 -0000 1.52
@@ -1,4 +1,4 @@
-$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.51 2005/06/21 14:14:55 ph10 Exp $
+$Cambridge: exim/exim-doc/doc-txt/NewStuff,v 1.52 2005/06/22 10:17:22 ph10 Exp $
New Features in Exim
--------------------
@@ -348,6 +348,41 @@
built-in constants previously: daemon_startup_retries defines the number
of retries after the first failure (default 9); daemon_startup_sleep
defines the length of time to wait between retries (default 30s).
+
+PH/05 There is now a new ${if condition called "match_ip". It is similar to
+ match_domain, etc. It must be followed by two argument strings. The first
+ (after expansion) must be an IP address or an empty string. The second
+ (after expansion) is a restricted host list that can match only an IP
+ address, not a host name. For example:
+
+ ${if match_ip{$sender_host_address}{1.2.3.4:5.6.7.8}{...}{...}}
+
+ The specific types of host list item that are permitted in the list are
+ shown below. Consult the manual section on host lists for further
+ details.
+
+ . An IP address, optionally with a CIDR mask.
+
+ . A single asterisk matches any IP address.
+
+ . An empty item matches only if the IP address is empty. This could be
+ useful for testing for a locally submitted message or one from specific
+ hosts in a single test such as
+
+ ${if match_ip{$sender_host_address}{:4.3.2.1:...}{...}{...}}
+
+ where the first item in the list is the empty string.
+
+ . The item @[] matches any of the local host's interface addresses.
+
+ . Lookups are assumed to be "net-" style lookups, even if "net-" is not
+ specified. Thus, the following are equivalent:
+
+ ${if match_ip{$sender_host_address}{lsearch;/some/file}...
+ ${if match_ip{$sender_host_address}{net-lsearch;/some/file}...
+
+ You do need to specify the "net-" prefix if you want to specify a
+ specific address mask, for example, by using "net24-".
Version 4.51
Index: expand.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/expand.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- expand.c 20 Jun 2005 13:58:22 -0000 1.33
+++ expand.c 22 Jun 2005 10:17:23 -0000 1.34
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/expand.c,v 1.33 2005/06/20 13:58:22 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/expand.c,v 1.34 2005/06/22 10:17:23 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -195,6 +195,7 @@
US"match",
US"match_address",
US"match_domain",
+ US"match_ip",
US"match_local_part",
US"or",
US"pam",
@@ -233,6 +234,7 @@
ECOND_MATCH,
ECOND_MATCH_ADDRESS,
ECOND_MATCH_DOMAIN,
+ ECOND_MATCH_IP,
ECOND_MATCH_LOCAL_PART,
ECOND_OR,
ECOND_PAM,
@@ -1801,6 +1803,7 @@
variables if it succeeds
match_address: matches in an address list
match_domain: matches in a domain list
+ match_ip: matches a host list that is restricted to IP addresses
match_local_part: matches in a local part list
crypteq: encrypts plaintext and compares against an encrypted text,
using crypt(), crypt16(), MD5 or SHA-1
@@ -1809,6 +1812,7 @@
case ECOND_MATCH:
case ECOND_MATCH_ADDRESS:
case ECOND_MATCH_DOMAIN:
+ case ECOND_MATCH_IP:
case ECOND_MATCH_LOCAL_PART:
case ECOND_CRYPTEQ:
@@ -1960,6 +1964,41 @@
case ECOND_MATCH_DOMAIN: /* Match in a domain list */
rc = match_isinlist(sub[0], &(sub[1]), 0, &domainlist_anchor, NULL,
MCL_DOMAIN + MCL_NOEXPAND, TRUE, NULL);
+ goto MATCHED_SOMETHING;
+
+ case ECOND_MATCH_IP: /* Match IP address in a host list */
+ if (sub[0][0] != 0 && string_is_ip_address(sub[0], NULL) <= 0)
+ {
+ expand_string_message = string_sprintf("\"%s\" is not an IP address",
+ sub[0]);
+ return NULL;
+ }
+ else
+ {
+ unsigned int *nullcache = NULL;
+ check_host_block cb;
+
+ cb.host_name = US"";
+ cb.host_address = sub[0];
+
+ /* If the host address starts off ::ffff: it is an IPv6 address in
+ IPv4-compatible mode. Find the IPv4 part for checking against IPv4
+ addresses. */
+
+ cb.host_ipv4 = (Ustrncmp(cb.host_address, "::ffff:", 7) == 0)?
+ cb.host_address + 7 : cb.host_address;
+
+ rc = match_check_list(
+ &sub[1], /* the list */
+ 0, /* separator character */
+ &hostlist_anchor, /* anchor pointer */
+ &nullcache, /* cache pointer */
+ check_host, /* function for testing */
+ &cb, /* argument for function */
+ MCL_HOST, /* type of check */
+ sub[0], /* text for debugging */
+ NULL); /* where to pass back data */
+ }
goto MATCHED_SOMETHING;
case ECOND_MATCH_LOCAL_PART:
Index: functions.h
===================================================================
RCS file: /home/cvs/exim/exim-src/src/functions.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- functions.h 20 Jun 2005 10:04:55 -0000 1.16
+++ functions.h 22 Jun 2005 10:17:23 -0000 1.17
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/functions.h,v 1.16 2005/06/20 10:04:55 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/functions.h,v 1.17 2005/06/22 10:17:23 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -52,6 +52,7 @@
extern uschar *auth_xtextencode(uschar *, int);
extern int auth_xtextdecode(uschar *, uschar **);
+extern int check_host(void *, uschar *, uschar **, uschar **);
extern uschar **child_exec_exim(int, BOOL, int *, BOOL, int, ...);
extern pid_t child_open_uid(uschar **, uschar **, int, uid_t *, gid_t *,
int *, int *, uschar *, BOOL);
Index: match.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/match.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- match.c 17 Feb 2005 11:58:26 -0000 1.5
+++ match.c 22 Jun 2005 10:17:23 -0000 1.6
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/match.c,v 1.5 2005/02/17 11:58:26 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/match.c,v 1.6 2005/06/22 10:17:23 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -697,8 +697,9 @@
case DEFER:
goto DEFER_RETURN;
- /* The ERROR return occurs only when checking hosts, when either a
- forward or reverse lookup has failed. The error string gives details of
+ /* The ERROR return occurs when checking hosts, when either a forward
+ or reverse lookup has failed. It can also occur in a match_ip list if a
+ non-IP address item is encountered. The error string gives details of
which it was. */
case ERROR:
Index: verify.c
===================================================================
RCS file: /home/cvs/exim/exim-src/src/verify.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- verify.c 17 Jun 2005 10:20:30 -0000 1.19
+++ verify.c 22 Jun 2005 10:17:23 -0000 1.20
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/exim-src/src/verify.c,v 1.19 2005/06/17 10:20:30 ph10 Exp $ */
+/* $Cambridge: exim/exim-src/src/verify.c,v 1.20 2005/06/22 10:17:23 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -1816,25 +1816,34 @@
error for error message when returning ERROR
The block contains:
- host_name the host name or NULL, implying use sender_host_name and
- sender_host_aliases, looking them up if required
+ host_name (a) the host name, or
+ (b) NULL, implying use sender_host_name and
+ sender_host_aliases, looking them up if required, or
+ (c) the empty string, meaning that only IP address matches
+ are permitted
host_address the host address
host_ipv4 the IPv4 address taken from an IPv6 one
Returns: OK matched
FAIL did not match
DEFER lookup deferred
- ERROR failed to find the host name or IP address
- unknown lookup type specified
+ ERROR (a) failed to find the host name or IP address, or
+ (b) unknown lookup type specified, or
+ (c) host name encountered when only IP addresses are
+ being matched
*/
-static int
+int
check_host(void *arg, uschar *ss, uschar **valueptr, uschar **error)
{
check_host_block *cb = (check_host_block *)arg;
+int mlen = -1;
int maskoffset;
+BOOL iplookup = FALSE;
BOOL isquery = FALSE;
-uschar *semicolon, *t;
+BOOL isiponly = cb->host_name != NULL && cb->host_name[0] == 0;
+uschar *t = ss;
+uschar *semicolon;
uschar **aliases;
/* Optimize for the special case when the pattern is "*". */
@@ -1848,12 +1857,17 @@
if (cb->host_address[0] == 0) return (*ss == 0)? OK : FAIL;
if (*ss == 0) return FAIL;
-/* If the pattern is precisely "@" then match against the primary host name;
-if it's "@[]" match against the local host's IP addresses. */
+/* If the pattern is precisely "@" then match against the primary host name,
+provided that host name matching is permitted; if it's "@[]" match against the
+local host's IP addresses. */
if (*ss == '@')
{
- if (ss[1] == 0) ss = primary_hostname;
+ if (ss[1] == 0)
+ {
+ if (isiponly) return ERROR;
+ ss = primary_hostname;
+ }
else if (Ustrcmp(ss, "@[]") == 0)
{
ip_address_item *ip;
@@ -1869,73 +1883,96 @@
if (string_is_ip_address(ss, &maskoffset) > 0)
return (host_is_in_net(cb->host_address, ss, maskoffset)? OK : FAIL);
-/* If the item is of the form net[n]-lookup;<file|query> then it is a lookup on
-a masked IP network, in textual form. The net- stuff really only applies to
-single-key lookups where the key is implicit. For query-style lookups the key
-is specified in the query. From release 4.30, the use of net- for query style
-is no longer needed, but we retain it for backward compatibility. */
+/* See if there is a semicolon in the pattern */
+
+semicolon = Ustrchr(ss, ';');
+
+/* If we are doing an IP address only match, then all lookups must be IP
+address lookups. */
-if (Ustrncmp(ss, "net", 3) == 0 && (semicolon = Ustrchr(ss, ';')) != NULL)
+if (isiponly)
{
- int mlen = 0;
+ iplookup = semicolon != NULL;
+ }
+
+/* Otherwise, if the item is of the form net[n]-lookup;<file|query> then it is
+a lookup on a masked IP network, in textual form. The net- stuff really only
+applies to single-key lookups where the key is implicit. For query-style
+lookups the key is specified in the query. From release 4.30, the use of net-
+for query style is no longer needed, but we retain it for backward
+compatibility. */
+
+else if (Ustrncmp(ss, "net", 3) == 0 && semicolon != NULL)
+ {
+ mlen = 0;
for (t = ss + 3; isdigit(*t); t++) mlen = mlen * 10 + *t - '0';
- if (*t++ == '-')
- {
- int insize;
- int search_type;
- int incoming[4];
- void *handle;
- uschar *filename, *key, *result;
- uschar buffer[64];
+ if (mlen == 0 && t == ss+3) mlen = -1; /* No mask supplied */
+ iplookup = (*t++ == '-');
+ }
- /* If no mask was supplied, set a negative value */
+/* Do the IP address lookup if that is indeed what we have */
- if (mlen == 0 && t == ss+4) mlen = -1;
+if (iplookup)
+ {
+ int insize;
+ int search_type;
+ int incoming[4];
+ void *handle;
+ uschar *filename, *key, *result;
+ uschar buffer[64];
- /* Find the search type */
+ /* Find the search type */
- search_type = search_findtype(t, semicolon - t);
+ search_type = search_findtype(t, semicolon - t);
- if (search_type < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
- search_error_message);
+ if (search_type < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
+ search_error_message);
- /* Adjust parameters for the type of lookup. For a query-style
- lookup, there is no file name, and the "key" is just the query. For
- a single-key lookup, the key is the current IP address, masked
- appropriately, and reconverted to text form, with the mask appended.
- For IPv6 addresses, specify dot separators instead of colons. */
+ /* Adjust parameters for the type of lookup. For a query-style
+ lookup, there is no file name, and the "key" is just the query. For
+ a single-key lookup, the key is the current IP address, masked
+ appropriately, and reconverted to text form, with the mask appended.
+ For IPv6 addresses, specify dot separators instead of colons. */
- if (mac_islookup(search_type, lookup_querystyle))
- {
- filename = NULL;
- key = semicolon + 1;
- }
- else
- {
- insize = host_aton(cb->host_address, incoming);
- host_mask(insize, incoming, mlen);
- (void)host_nmtoa(insize, incoming, mlen, buffer, '.');
- key = buffer;
- filename = semicolon + 1;
- }
-
- /* Now do the actual lookup; note that there is no search_close() because
- of the caching arrangements. */
-
- handle = search_open(filename, search_type, 0, NULL, NULL);
- if (handle == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
- search_error_message);
- result = search_find(handle, filename, key, -1, NULL, 0, 0, NULL);
- if (valueptr != NULL) *valueptr = result;
- return (result != NULL)? OK : search_find_defer? DEFER: FAIL;
+ if (mac_islookup(search_type, lookup_querystyle))
+ {
+ filename = NULL;
+ key = semicolon + 1;
}
+ else
+ {
+ insize = host_aton(cb->host_address, incoming);
+ host_mask(insize, incoming, mlen);
+ (void)host_nmtoa(insize, incoming, mlen, buffer, '.');
+ key = buffer;
+ filename = semicolon + 1;
+ }
+
+ /* Now do the actual lookup; note that there is no search_close() because
+ of the caching arrangements. */
+
+ handle = search_open(filename, search_type, 0, NULL, NULL);
+ if (handle == NULL) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "%s",
+ search_error_message);
+ result = search_find(handle, filename, key, -1, NULL, 0, 0, NULL);
+ if (valueptr != NULL) *valueptr = result;
+ return (result != NULL)? OK : search_find_defer? DEFER: FAIL;
}
/* The pattern is not an IP address or network reference of any kind. That is,
-it is a host name pattern. Check the characters of the pattern to see if they
-comprise only letters, digits, full stops, and hyphens (the constituents of
-domain names). Allow underscores, as they are all too commonly found. Sigh.
-Also, if allow_utf8_domains is set, allow top-bit characters. */
+it is a host name pattern. If this is an IP only match, there's an error in the
+host list. */
+
+if (isiponly)
+ {
+ *error = US"cannot match host name in match_ip list";
+ return ERROR;
+ }
+
+/* Check the characters of the pattern to see if they comprise only letters,
+digits, full stops, and hyphens (the constituents of domain names). Allow
+underscores, as they are all too commonly found. Sigh. Also, if
+allow_utf8_domains is set, allow top-bit characters. */
for (t = ss; *t != 0; t++)
if (!isalnum(*t) && *t != '.' && *t != '-' && *t != '_' &&
Index: 082
===================================================================
RCS file: /home/cvs/exim/exim-test-orig/AutoTest/confs/082,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- 082 8 Oct 2004 14:49:15 -0000 1.1
+++ 082 22 Jun 2005 10:17:23 -0000 1.2
@@ -11,6 +11,7 @@
# ----- Main settings -----
domainlist dlist = *.aa.bb : ^\Nxxx
+hostlist hlist = 10.11.12.13 : iplsearch;DIR/aux/082.iplsearch
headers_charset = iso-8859-8
# End of Exim 4 configuration
Index: 082
===================================================================
RCS file: /home/cvs/exim/exim-test-orig/AutoTest/scripts/082,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- 082 7 Jun 2005 10:41:27 -0000 1.13
+++ 082 22 Jun 2005 10:17:23 -0000 1.14
@@ -252,6 +252,20 @@
match_local_part:${if match_local_part{jo}{jack:jill:jo:john}{yes}{no}}
match_local_part:${if match_local_part{jo}{\N^\w\N}{yes}{no}}
+match_ip: 01 ${if match_ip{1.2.3.4}{4.5.6.7:1.2.3.4}}
+match_ip: 02 ${if match_ip{1.2.3.4}{4.5.6.7:1.2.3.6}}
+match_ip: 03 ${if match_ip{1.2.3.4}{4.5.6.7:1.2.3.6/24}}
+match_ip: 04 ${if match_ip{1.2.3.4}{4.5.6.7:1.2.3.6:*}}
+match_ip: 05 ${if match_ip{1.2.3.4}{4.5.6.7:1.2.3.6:name}}
+match_ip: 06 ${if match_ip{1.2.3.4}{:4.5.6.7}}
+match_ip: 07 ${if match_ip{}{:4.5.6.7}}
+match_ip: 08 ${if match_ip{10.11.12.13}{+hlist}}
+match_ip: 09 ${if match_ip{10.11.12.14}{+hlist}}
+match_ip: 10 ${if match_ip{192.168.3.4}{+hlist}}
+match_ip: 11 ${if match_ip{somename}{+hlist}}
+match_ip: 12 ${if match_ip{10.11.12.13}{testdb;something}}
+match_ip: 13 ${if match_ip{10.11.12.13}{testdb;fail}}
+
queue_running: ${if queue_running{y}{n}}
first_delivery: ${if first_delivery{y}{n}}
Index: 082
===================================================================
RCS file: /home/cvs/exim/exim-test-orig/AutoTest/stdout/082,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- 082 14 Jun 2005 09:36:12 -0000 1.14
+++ 082 22 Jun 2005 10:17:23 -0000 1.15
@@ -248,6 +248,20 @@
> match_local_part:yes
> match_local_part:yes
>
+> match_ip: 01 true
+> match_ip: 02
+> match_ip: 03 true
+> match_ip: 04 true
+> match_ip: 05
+> match_ip: 06
+> match_ip: 07 true
+> match_ip: 08 true
+> match_ip: 09
+> match_ip: 10 true
+> Failed: "somename" is not an IP address
+> match_ip: 12 true
+> match_ip: 13
+>
> queue_running: n
> first_delivery: n
>