diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-04-20 09:45:27 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-04-20 09:52:18 +0300 |
commit | e8caefcc1b1a19abfca6a1e0a7dfea4af2761b53 (patch) | |
tree | d406fc23d7ccfe18fafba72ea5233834edccec4f | |
parent | 2bc017183f7c923bba31a84b394f2208745a0aeb (diff) | |
download | fileserv-e8caefcc1b1a19abfca6a1e0a7dfea4af2761b53.tar.gz fileserv-e8caefcc1b1a19abfca6a1e0a7dfea4af2761b53.tar.bz2 |
Handle IPv4 mapped addresses
-rw-r--r-- | src/remoteip.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/src/remoteip.c b/src/remoteip.c index 9515df0..61bb015 100644 --- a/src/remoteip.c +++ b/src/remoteip.c @@ -27,6 +27,18 @@ str_is_ipv4(const char *addr) return (dot_count == 3); } +#define PFXSTR_IPV4_MAPPED "::ffff:" +#define PFXLEN_IPV4_MAPPED (sizeof PFXSTR_IPV4_MAPPED - 1) + +static int +str_is_ipv4mapped(const char *addr) +{ + return strlen(addr) > PFXLEN_IPV4_MAPPED + && strncasecmp(PFXSTR_IPV4_MAPPED, addr, PFXLEN_IPV4_MAPPED) + == 0 + && str_is_ipv4(addr + PFXLEN_IPV4_MAPPED); +} + /* Returns 1 if ADDR is a valid IPv6 address */ static int str_is_ipv6(const char *addr) @@ -120,7 +132,7 @@ static int str_to_cidr(char const *str, struct cidr *cidr) { int rc; - char *ipbuf; + char *ipbuf, *ipstart; union { struct in_addr in; struct in6_addr in6; @@ -137,10 +149,14 @@ str_to_cidr(char const *str, struct cidr *cidr) ipbuf = xmalloc(len+1); memcpy(ipbuf, str, len); ipbuf[len] = 0; + ipstart = ipbuf; - if (str_is_ipv4(ipbuf)) + if (str_is_ipv4(ipstart)) + cidr->family = AF_INET; + else if (str_is_ipv4mapped(ipstart)) { cidr->family = AF_INET; - else if (str_is_ipv6(ipbuf)) + ipstart += PFXLEN_IPV4_MAPPED; + } else if (str_is_ipv6(ipbuf)) cidr->family = AF_INET6; else { free(ipbuf); @@ -148,7 +164,7 @@ str_to_cidr(char const *str, struct cidr *cidr) return -1; } - rc = inet_pton(cidr->family, ipbuf, &inaddr); + rc = inet_pton(cidr->family, ipstart, &inaddr); free(ipbuf); if (rc != 1) { |