From 9553de7fecfe9926d7af9d4656b8ba68e8c28fe0 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Fri, 26 Feb 2021 09:12:50 +0100 Subject: [PATCH] MINOR: tools: Add function to compare an address to a network address ipcmp2net() function may be used to compare an addres (struct sockaddr_storage) to a network address (struct net_addr). Among other things, this function will be used to add support of IPv6 for "except" parameter of "forwardfor" and "originalto" options. --- include/haproxy/tools.h | 7 +++++++ src/tools.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/include/haproxy/tools.h b/include/haproxy/tools.h index 4e3e4af98..46fef67c5 100644 --- a/include/haproxy/tools.h +++ b/include/haproxy/tools.h @@ -740,6 +740,13 @@ extern int v6tov4(struct in_addr *sin_addr, struct in6_addr *sin6_addr); */ int ipcmp(struct sockaddr_storage *ss1, struct sockaddr_storage *ss2); +/* compare a struct sockaddr_storage to a struct net_addr and return : + * 0 (true) if is matching + * 1 (false) if is not matching + * -1 (unable) if or is not AF_INET* + */ +int ipcmp2net(const struct sockaddr_storage *addr, const struct net_addr *net); + /* copy ip from into * the caller must clear before calling. * Returns a pointer to the destination diff --git a/src/tools.c b/src/tools.c index 4db3e1898..82e106394 100644 --- a/src/tools.c +++ b/src/tools.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -3110,6 +3111,40 @@ int ipcmp(struct sockaddr_storage *ss1, struct sockaddr_storage *ss2) return 1; } +/* compare a struct sockaddr_storage to a struct net_addr and return : + * 0 (true) if is matching + * 1 (false) if is not matching + * -1 (unable) if or is not AF_INET* + */ +int ipcmp2net(const struct sockaddr_storage *addr, const struct net_addr *net) +{ + if ((addr->ss_family != AF_INET) && (addr->ss_family != AF_INET6)) + return -1; + + if ((net->family != AF_INET) && (net->family != AF_INET6)) + return -1; + + if (addr->ss_family != net->family) + return 1; + + if (addr->ss_family == AF_INET && + (((struct sockaddr_in *)addr)->sin_addr.s_addr & net->addr.v4.mask.s_addr) == net->addr.v4.ip.s_addr) + return 0; + else { + const struct in6_addr *addr6 = &(((const struct sockaddr_in6*)addr)->sin6_addr); + const struct in6_addr *nip6 = &net->addr.v6.ip; + const struct in6_addr *nmask6 = &net->addr.v6.mask; + + if ((read_u32(&addr6->s6_addr[0]) & read_u32(&nmask6->s6_addr[0])) == read_u32(&nip6->s6_addr[0]) && + (read_u32(&addr6->s6_addr[4]) & read_u32(&nmask6->s6_addr[4])) == read_u32(&nip6->s6_addr[4]) && + (read_u32(&addr6->s6_addr[8]) & read_u32(&nmask6->s6_addr[8])) == read_u32(&nip6->s6_addr[8]) && + (read_u32(&addr6->s6_addr[12]) & read_u32(&nmask6->s6_addr[12])) == read_u32(&nip6->s6_addr[12])) + return 0; + } + + return 1; +} + /* copy IP address from into * The caller must allocate and clear before calling. * The source must be in either AF_INET or AF_INET6 family, or the destination