]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: log: properly format IPv6 address when LOG_OPT_HEXA modifier is used.
authorRadek Zajic <radek.zajic@showmax.com>
Fri, 22 Mar 2019 10:21:54 +0000 (10:21 +0000)
committerWilly Tarreau <w@1wt.eu>
Fri, 22 Mar 2019 16:31:18 +0000 (17:31 +0100)
In lf_ip(), when LOG_OPT_HEXA modifier is used, there is a code to format the
IP address as a hexadecimal string. This code does not properly handle cases
when the IP address is IPv6. In such case, the code only prints `00000000`.

This patch adds support for IPv6. For legacy IPv4, the format remains
unchanged. If IPv6 socket is used to accept IPv6 connection, the full IPv6
address is returned. For example, IPv6 localhost, ::1, is printed as
00000000000000000000000000000001.

If IPv6 socket accepts IPv4 connection, the IPv4 address is mapped by the
kernel into the IPv4-mapped-IPv6 address space (RFC4291, section 2.5.5.2)
and is formatted as such. For example, 127.0.0.1 becomes ::ffff:127.0.0.1,
which is printed as 00000000000000000000FFFF7F000001.

This should be backported to 1.9.

src/log.c

index 9fb5c17626c8ddc9739ca733c5159982da0d67c6..f8d3414e2b5cf1d3ae09a314852940e20f54b039 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -1153,8 +1153,21 @@ char *lf_ip(char *dst, const struct sockaddr *sockaddr, size_t size, const struc
        char pn[INET6_ADDRSTRLEN];
 
        if (node->options & LOG_OPT_HEXA) {
-               const unsigned char *addr = (const unsigned char *)&((struct sockaddr_in *)sockaddr)->sin_addr.s_addr;
-               iret = snprintf(dst, size, "%02X%02X%02X%02X", addr[0], addr[1], addr[2], addr[3]);
+               unsigned char *addr = NULL;
+               switch (sockaddr->sa_family) {
+               case AF_INET:
+                       addr = (unsigned char *)&((struct sockaddr_in *)sockaddr)->sin_addr.s_addr;
+                       iret = snprintf(dst, size, "%02X%02X%02X%02X", addr[0], addr[1], addr[2], addr[3]);
+                       break;
+               case AF_INET6:
+                       addr = (unsigned char *)&((struct sockaddr_in6 *)sockaddr)->sin6_addr.s6_addr;
+                       iret = snprintf(dst, size, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+                                       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7],
+                                       addr[8], addr[9], addr[10], addr[11], addr[12], addr[13], addr[14], addr[15]);
+                       break;
+               default:
+                       return NULL;
+               }
                if (iret < 0 || iret > size)
                        return NULL;
                ret += iret;