From 06ab4fd01a24734c2269a982f0fca847304785f5 Mon Sep 17 00:00:00 2001 From: Jeremy Harris Date: Thu, 14 Nov 2024 23:57:49 +0000 Subject: [PATCH] Explicit IPv6 addresses for mysql and pgsql --- doc/doc-docbook/spec.xfpt | 17 ++++++++++-- doc/doc-txt/NewStuff | 2 ++ src/src/lookups/mysql.c | 17 ++++++++---- src/src/lookups/pgsql.c | 23 +++++++++++----- test/scripts/2610-MySQL/2610 | 2 ++ test/scripts/2620-Postgresql/2620 | 5 +++- test/stderr/2610 | 32 +++++++++++++++++++-- test/stderr/2620 | 46 ++++++++++++++++++++++++++++++- test/stdout/2610 | 2 ++ test/stdout/2620 | 5 +++- 10 files changed, 132 insertions(+), 19 deletions(-) diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt index 6aa1604a6..8674cfa43 100644 --- a/doc/doc-docbook/spec.xfpt +++ b/doc/doc-docbook/spec.xfpt @@ -8261,12 +8261,21 @@ An option group name for MySQL option files can be specified in square brackets; the default value is &"exim"&. The full syntax of each item in &%mysql_servers%& is: .display -<&'hostname'&>::<&'port'&>(<&'socket name'&>)[<&'option group'&>]/&&& - <&'database'&>/<&'user'&>/<&'password'&> +<&'hostspec'&><&'portspec'&>(<&'socket name'&>)[<&'option group'&>]/&&& + <&'database'&>/<&'user'&>/<&'password'&> .endd Any of the four sub-parts of the first field can be omitted. For normal use on the local host it can be left blank or set to just &"localhost"&. +.new +A &'hostspec'& can be a hostname, an IPv4 address or an IPv6 address. +For the latter, a &'portspec'& is a dot followed by a port number; +for the other two a &'portspec'& is a colon followed by a port number. +.wen + +Note that the default list-separator for the list of servers is a colon so +(unless that is changed) all colons in list items must be doubled. + No database need be supplied &-- but if it is absent here, it must be given in the queries. @@ -8282,6 +8291,10 @@ parameters for the connection. .subsection "Special PostgreSQL features" SECID74 +.new +The &'hostspec'& for PostgreSQL follows the same rules as for MySQL above. +.wen + PostgreSQL lookups can also use Unix domain socket connections to the database. This is usually faster and costs less CPU time than a TCP/IP connection. However it can be used only if the mail server runs on the same machine as the diff --git a/doc/doc-txt/NewStuff b/doc/doc-txt/NewStuff index cdcb11bb8..2cce3f533 100644 --- a/doc/doc-txt/NewStuff +++ b/doc/doc-txt/NewStuff @@ -28,6 +28,8 @@ Version 4.98 8. ATRN provider support + 9. IPv6 address support for mysql and pgsql lookups + Version 4.98 ------------ 1. The dkim_status ACL condition may now be used in data ACLs diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c index 6b4638f70..ff19f5c80 100644 --- a/src/src/lookups/mysql.c +++ b/src/src/lookups/mysql.c @@ -207,11 +207,18 @@ if (!cn) *p = 0; } - if ((p = Ustrchr(sdata[0], ':'))) - { - *p++ = 0; - port = Uatoi(p); - } + /* If there is a colon (":") it could be a port number after an ipv4 or + hostname, or could be an ipv6. The latter must have at least two colons, + and we look instead for a period ("."). */ + + if ((p = Ustrrchr(sdata[0], ':'))) + if ( Ustrchr(sdata[0], ':') == p /* only one colon */ + || (p = Ustrrchr(sdata[0], '.')) /* >1 colon, and a period */ + ) + { + *p++ = 0; + port = Uatoi(p); + } if (Ustrchr(sdata[0], '/')) { diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c index 9d97afca9..c0e2ada51 100644 --- a/src/src/lookups/pgsql.c +++ b/src/src/lookups/pgsql.c @@ -146,7 +146,7 @@ for (int i = 2; i >= 0; i--) if (!pp) { *errmsg = string_sprintf("incomplete pgSQL server data: %s", - (i == 2)? server : server_copy); + i == 2 ? server : server_copy); *defer_break = TRUE; return DEFER; } @@ -210,12 +210,21 @@ if (!cn) else { - uschar *p; - if ((p = Ustrchr(server, ':'))) - { - *p++ = 0; - port = p; - } + uschar * p; + + /* If there is a colon (":") it could be a port number after an ipv4 or + hostname, or could be an ipv6. The latter must have at least two colons, + and we look instead for a period ("."). We assume a hostname never + contains a colon. */ + + if ((p = Ustrrchr(server, ':'))) + if ( Ustrchr(server, ':') == p /* only one colon */ + || (p = Ustrrchr(server, '.')) /* >1 colon, and a period */ + ) + { + *p++ = 0; + port = p; + } if (Ustrchr(server, '/')) { diff --git a/test/scripts/2610-MySQL/2610 b/test/scripts/2610-MySQL/2610 index 597504a59..edefd38b9 100644 --- a/test/scripts/2610-MySQL/2610 +++ b/test/scripts/2610-MySQL/2610 @@ -74,6 +74,8 @@ ${lookup mysql {select * from them where id='nlonly';}} ${lookup mysql {servers=x:127.0.0.1::PORT_N; select name from them where id='ph10';}} ${lookup mysql {servers=127.0.0.1::PORT_N:x; select name from them where id='ph10';}} ${lookup mysql {servers=127.0.0.1::PORT_N/test/root/:x; select name from them where id='ph10';}} +oldsyntax ipv6: ${lookup mysql {servers=>>>>>>>>>>>>>>> Exim pid=p1234 (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>> 01:01:01 p1235 Exim version x.yz uid=CALLER_UID gid=CALLER_GID pid=p1235 D=fff9ffff diff --git a/test/stderr/2620 b/test/stderr/2620 index fc3e76f2e..fe7459356 100644 --- a/test/stderr/2620 +++ b/test/stderr/2620 @@ -168,6 +168,48 @@ LOG: MAIN PGSQL using cached connection for localhost:PORT_N/test/CALLER creating new cache entry lookup yielded: Philip░Hazel + search_open: pgsql "NULL" + cached open + search_find: file="NULL" + key="servers=127.0.0.1::PORT_N/test/CALLER/:x; select name from them where id='ph10';" partial=-1 affix=NULL starflags=0 opts=NULL + LRU list: + internal_search_find: file="NULL" + type=pgsql key="servers=127.0.0.1::PORT_N/test/CALLER/:x; select name from them where id='ph10';" opts=NULL + database lookup required for servers=127.0.0.1::PORT_N/test/CALLER/:x; select name from them where id='ph10'; + PostgreSQL query: "servers=127.0.0.1::PORT_N/test/CALLER/:x; select name from them where id='ph10';" opts 'NULL' +LOG: MAIN + Exim configuration error in line 14 of -be stdin: + WARNING: obsolete syntax used for lookup + PGSQL new connection: host=127.0.0.1 port=PORT_N database=test user=CALLER + creating new cache entry + lookup yielded: Philip░Hazel + search_open: pgsql "NULL" + cached open + search_find: file="NULL" + key="servers=>>>>>>>>>>>>>>> Exim pid=p1235 (fresh-exec) terminating with rc=0 >>>>>>>>>>>>>>>> Exim version x.yz .... diff --git a/test/stdout/2610 b/test/stdout/2610 index 961928b8e..aeacedf4c 100644 --- a/test/stdout/2610 +++ b/test/stdout/2610 @@ -14,6 +14,8 @@ > Failed: lookup of "servers=x:127.0.0.1::1223; select name from them where id='ph10';" gave DEFER: MySQL server "x" not found in mysql_servers > Philip Hazel > Philip Hazel +> oldsyntax ipv6: Philip Hazel +> newsyntax ipv6: Philip Hazel > Philip Hazel > Philip Hazel > x diff --git a/test/stdout/2620 b/test/stdout/2620 index f0796ae6f..c8fe17cce 100644 --- a/test/stdout/2620 +++ b/test/stdout/2620 @@ -46,7 +46,10 @@ after" id=newline > name='stquot id=quote1 > Failed: lookup of "servers=x:localhost; select name from them where id='ph10';" gave DEFER: PostgreSQL server "x" not found in pgsql_servers > Philip Hazel -> Philip Hazel +> name: Philip Hazel +> ipv4: Philip Hazel +> oldsyntax ipv6: Philip Hazel +> newsyntax ipv6: Philip Hazel > Philip Hazel > x > Philip Hazel -- 2.30.2