Add inet_pton for Windows XP support

This commit is contained in:
Benau 2020-04-14 11:00:59 +08:00
parent c1a28c6459
commit 8e64433c3a

View File

@ -24,13 +24,6 @@
# include <winsock2.h>
# include <ws2tcpip.h>
extern "C"
{
#ifndef InetPtopN
WINSOCK_API_LINKAGE INT WSAAPI inet_pton(INT Family, PCSTR pszAddrString, PVOID pAddrBuf);
#endif
}
#else
# include <winsock2.h>
# include <in6addr.h>
@ -52,6 +45,157 @@ extern "C"
#include <array>
#include <string>
// ============================================================================
// For Windows XP support
#define IN6ADDRSZ 16
#define INADDRSZ 4
#define INT16SZ 2
static int
stk_inet_pton4(const char *src, unsigned char *dst)
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
unsigned char tmp[INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
tp = tmp;
*tp = 0;
while((ch = *src++) != '\0')
{
const char *pch;
pch = strchr(digits, ch);
if(pch)
{
unsigned int val = *tp * 10 + (unsigned int)(pch - digits);
if(saw_digit && *tp == 0)
return (0);
if(val > 255)
return (0);
*tp = (unsigned char)val;
if(! saw_digit)
{
if(++octets > 4)
return (0);
saw_digit = 1;
}
}
else if(ch == '.' && saw_digit)
{
if(octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
}
else
return (0);
}
if(octets < 4)
return (0);
memcpy(dst, tmp, INADDRSZ);
return (1);
}
static int
stk_inet_pton6(const char *src, void *dest)
{
unsigned char *dst = (unsigned char*)dest;
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *curtok;
int ch, saw_xdigit;
size_t val;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if(*src == ':')
{
if(*++src != ':')
return (0);
}
curtok = src;
saw_xdigit = 0;
val = 0;
while((ch = *src++) != '\0')
{
const char *xdigits;
const char *pch;
pch = strchr((xdigits = xdigits_l), ch);
if(!pch)
pch = strchr((xdigits = xdigits_u), ch);
if(pch != NULL)
{
val <<= 4;
val |= (pch - xdigits);
if(++saw_xdigit > 4)
return (0);
continue;
}
if(ch == ':')
{
curtok = src;
if(!saw_xdigit)
{
if(colonp)
return (0);
colonp = tp;
continue;
}
if(tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) ((val >> 8) & 0xff);
*tp++ = (unsigned char) (val & 0xff);
saw_xdigit = 0;
val = 0;
continue;
}
if(ch == '.' && ((tp + INADDRSZ) <= endp) &&
stk_inet_pton4(curtok, tp) > 0)
{
tp += INADDRSZ;
saw_xdigit = 0;
break; /* '\0' was seen by stk_inet_pton4(). */
}
return (0);
}
if(saw_xdigit)
{
if(tp + INT16SZ > endp)
return (0);
*tp++ = (unsigned char) ((val >> 8) & 0xff);
*tp++ = (unsigned char) (val & 0xff);
}
if(colonp != NULL)
{
/*
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const ssize_t n = tp - colonp;
ssize_t i;
if(tp == endp)
return (0);
for(i = 1; i <= n; i++)
{
*(endp - i) = *(colonp + n - i);
*(colonp + n - i) = 0;
}
tp = endp;
}
if(tp != endp)
return (0);
memcpy(dst, tmp, IN6ADDRSZ);
return (1);
}
// ============================================================================
// Android STK seems to crash when using inet_ntop so we copy it from linux
static const char *
@ -283,7 +427,7 @@ void andIPv6(struct in6_addr* ipv6, const struct in6_addr* mask)
extern "C" int64_t upperIPv6(const char* ipv6)
{
struct in6_addr v6_in;
if (inet_pton(AF_INET6, ipv6, &v6_in) != 1)
if (stk_inet_pton6(ipv6, &v6_in) != 1)
return 0;
uint64_t result = 0;
unsigned shift = 56;
@ -303,13 +447,13 @@ extern "C" int insideIPv6CIDR(const char* ipv6_cidr, const char* ipv6_in)
if (mask_location == NULL)
return 0;
struct in6_addr v6_in;
if (inet_pton(AF_INET6, ipv6_in, &v6_in) != 1)
if (stk_inet_pton6(ipv6_in, &v6_in) != 1)
return 0;
char ipv6[INET6_ADDRSTRLEN] = {};
memcpy(ipv6, ipv6_cidr, mask_location - ipv6_cidr);
struct in6_addr cidr;
if (inet_pton(AF_INET6, ipv6, &cidr) != 1)
if (stk_inet_pton6(ipv6, &cidr) != 1)
return 0;
int mask_length = atoi(mask_location + 1);