git://git.exim.org
/
exim.git
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
b003ce3
)
Expansions: mask_n operator
author
Jeremy Harris
<jgh146exb@wizmail.org>
Sun, 8 Aug 2021 16:34:49 +0000
(17:34 +0100)
committer
Jeremy Harris
<jgh146exb@wizmail.org>
Sun, 8 Aug 2021 16:34:49 +0000
(17:34 +0100)
doc/doc-docbook/spec.xfpt
patch
|
blob
|
history
doc/doc-txt/NewStuff
patch
|
blob
|
history
src/src/expand.c
patch
|
blob
|
history
test/scripts/0000-Basic/0002
patch
|
blob
|
history
test/stdout/0002
patch
|
blob
|
history
diff --git
a/doc/doc-docbook/spec.xfpt
b/doc/doc-docbook/spec.xfpt
index 0385de6dbc5b96b8c907f366ce99c3b5c27604e9..e766b69e2d1e193a87f4d1b0bcc09c43e7210098 100644
(file)
--- a/
doc/doc-docbook/spec.xfpt
+++ b/
doc/doc-docbook/spec.xfpt
@@
-11228,7
+11228,8
@@
empty.
The parsing correctly handles SMTPUTF8 Unicode in the string.
The parsing correctly handles SMTPUTF8 Unicode in the string.
-.vitem &*${mask:*&<&'IP&~address'&>&*/*&<&'bit&~count'&>&*}*&
+.vitem &*${mask:*&<&'IP&~address'&>&*/*&<&'bit&~count'&>&*}*& &&&
+ &*${mask_n:*&<&'IP&~address'&>&*/*&<&'bit&~count'&>&*}*&
.cindex "masked IP address"
.cindex "IP address" "masking"
.cindex "CIDR notation"
.cindex "masked IP address"
.cindex "IP address" "masking"
.cindex "CIDR notation"
@@
-11242,8
+11243,14
@@
the result back to text, with mask appended. For example,
.code
${mask:10.111.131.206/28}
.endd
.code
${mask:10.111.131.206/28}
.endd
-returns the string &"10.111.131.192/28"&. Since this operation is expected to
-be mostly used for looking up masked addresses in files, the result for an IPv6
+returns the string &"10.111.131.192/28"&.
+
+Since this operation is expected to
+be mostly used for looking up masked addresses in files, the
+.new
+normal
+.wen
+result for an IPv6
address uses dots to separate components instead of colons, because colon
terminates a key string in lsearch files. So, for example,
.code
address uses dots to separate components instead of colons, because colon
terminates a key string in lsearch files. So, for example,
.code
@@
-11253,6
+11260,10
@@
returns the string
.code
3ffe.ffff.836f.0a00.000a.0800.2000.0000/99
.endd
.code
3ffe.ffff.836f.0a00.000a.0800.2000.0000/99
.endd
+.new
+If the optional form &*mask_n*& is used, IPv6 address result are instead
+returned in normailsed form, using colons and with zero-compression.
+.wen
Letters in IPv6 addresses are always output in lower case.
Letters in IPv6 addresses are always output in lower case.
diff --git
a/doc/doc-txt/NewStuff
b/doc/doc-txt/NewStuff
index 478446b41f1c0ee859cf65af717ca6def5afb8c6..1d6190b294e512a516f05d3d1236c598d77fe9c8 100644
(file)
--- a/
doc/doc-txt/NewStuff
+++ b/
doc/doc-txt/NewStuff
@@
-11,6
+11,8
@@
Version 4.96
1. A new ACL condition: seen. Records/tests a timestamp against a key.
1. A new ACL condition: seen. Records/tests a timestamp against a key.
+ 2. A variant of the "mask" expansion operator to give normalised IPv6.
+
Version 4.95
------------
Version 4.95
------------
diff --git
a/src/src/expand.c
b/src/src/expand.c
index 4fb935528e49b1c6fe9ab3a959d0aa113bbc8336..83c0ad051f4daef1ea36e08d8db500922ed91bf7 100644
(file)
--- a/
src/src/expand.c
+++ b/
src/src/expand.c
@@
-7333,11
+7333,11
@@
while (*s)
int count;
uschar *endptr;
int binary[4];
int count;
uschar *endptr;
int binary[4];
- int mask, maskoffset;
-
int type = string_is_ip_address(sub, &maskoffset)
;
+ int
type,
mask, maskoffset;
+
BOOL normalised
;
uschar buffer[64];
uschar buffer[64];
- if (
type
== 0)
+ if (
(type = string_is_ip_address(sub, &maskoffset))
== 0)
{
expand_string_message = string_sprintf("\"%s\" is not an IP address",
sub);
{
expand_string_message = string_sprintf("\"%s\" is not an IP address",
sub);
@@
-7353,13
+7353,18
@@
while (*s)
mask = Ustrtol(sub + maskoffset + 1, &endptr, 10);
mask = Ustrtol(sub + maskoffset + 1, &endptr, 10);
- if (*endptr
!= 0 || mask < 0 || mask > ((type == 4)
? 32 : 128))
+ if (*endptr
|| mask < 0 || mask > (type == 4
? 32 : 128))
{
expand_string_message = string_sprintf("mask value too big in \"%s\"",
sub);
goto EXPAND_FAILED;
}
{
expand_string_message = string_sprintf("mask value too big in \"%s\"",
sub);
goto EXPAND_FAILED;
}
+ /* If an optional 'n' was given, ipv6 gets normalised output:
+ colons rather than dots, and zero-compressed. */
+
+ normalised = arg && *arg == 'n';
+
/* Convert the address to binary integer(s) and apply the mask */
sub[maskoffset] = 0;
/* Convert the address to binary integer(s) and apply the mask */
sub[maskoffset] = 0;
@@
-7368,8
+7373,14
@@
while (*s)
/* Convert to masked textual format and add to output. */
/* Convert to masked textual format and add to output. */
- yield = string_catn(yield, buffer,
- host_nmtoa(count, binary, mask, buffer, '.'));
+ if (type == 4 || !normalised)
+ yield = string_catn(yield, buffer,
+ host_nmtoa(count, binary, mask, buffer, '.'));
+ else
+ {
+ ipv6_nmtoa(binary, buffer);
+ yield = string_fmt_append(yield, "%s/%d", buffer, mask);
+ }
continue;
}
continue;
}
diff --git
a/test/scripts/0000-Basic/0002
b/test/scripts/0000-Basic/0002
index cc289e04eeb9618b960cbb84bf97cec9f9899e5c..db3eae6be4f80dc967f81a2bf50ef0fdfb03cacc 100644
(file)
--- a/
test/scripts/0000-Basic/0002
+++ b/
test/scripts/0000-Basic/0002
@@
-248,6
+248,8
@@
mask: ${mask:192.168.10.206/33}
mask: ${mask:192.168.10.206/0}
mask: ${mask:192.168.10.206}
mask: ${mask:a.b.c.d}
mask: ${mask:192.168.10.206/0}
mask: ${mask:192.168.10.206}
mask: ${mask:a.b.c.d}
+mask: ${mask:2a00:2:3:4:5:6:7:8/79}
+mask_n: ${mask_n:2a00:2:3:4:5:6:7:8/79}
ipv6denorm: ${ipv6denorm:::1}
ipv6denorm: ${ipv6denorm:fe00::1}
ipv6denorm: ${ipv6denorm:192.168.0.1}
ipv6denorm: ${ipv6denorm:::1}
ipv6denorm: ${ipv6denorm:fe00::1}
ipv6denorm: ${ipv6denorm:192.168.0.1}
diff --git
a/test/stdout/0002
b/test/stdout/0002
index 0b9a95cd5fa566b4a6982a2d83449efb68a20175..5c8c2520c3f4eb298df4fa2b13756e400fd31733 100644
(file)
--- a/
test/stdout/0002
+++ b/
test/stdout/0002
@@
-230,6
+230,8
@@
newline tab\134backslash ~tilde\177DEL\200\201.
> mask: 0.0.0.0/0
> Failed: missing mask value in "192.168.10.206"
> Failed: "a.b.c.d" is not an IP address
> mask: 0.0.0.0/0
> Failed: missing mask value in "192.168.10.206"
> Failed: "a.b.c.d" is not an IP address
+> mask: 2a00.0002.0003.0004.0004.0000.0000.0000/79
+> mask_n: 2a00:2:3:4:4::/79
> ipv6denorm: 0000:0000:0000:0000:0000:0000:0000:0001
> ipv6denorm: fe00:0000:0000:0000:0000:0000:0000:0001
> ipv6denorm: 0000:0000:0000:0000:0000:ffff:c0a8:0001
> ipv6denorm: 0000:0000:0000:0000:0000:0000:0000:0001
> ipv6denorm: fe00:0000:0000:0000:0000:0000:0000:0001
> ipv6denorm: 0000:0000:0000:0000:0000:ffff:c0a8:0001