Skip to content

Instantly share code, notes, and snippets.

@pps83
Last active June 20, 2018 21:30
Show Gist options
  • Save pps83/96bbffef32fb73a538fc0faacff149d9 to your computer and use it in GitHub Desktop.
Save pps83/96bbffef32fb73a538fc0faacff149d9 to your computer and use it in GitHub Desktop.
#ifdef _WIN32 // inet_pton is available from Vista only (based on inet_pton.c from wireshark)
#define NS_INADDRSZ_ 4
#define NS_IN6ADDRSZ_ 16
#define NS_INT16SZ_ 2
static int inet_pton4(const char *src, unsigned char *dst)
{
char saw_digit = 0, octets = 0, ch;
unsigned char tmp[NS_INADDRSZ_], *tp = tmp;
*tp = 0;
while ((ch = *src++) != '\0')
{
if (ch >= '0' && ch <= '9')
{
unsigned n = *tp * 10 + (ch - '0');
if (n > 255)
return 0;
*tp = (unsigned char)n;
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, NS_INADDRSZ_);
return 1;
}
static bool nextHex(unsigned int& val, char c)
{
if (c <= '9')
{
int ret = c - '0';
if (ret >= 0)
{
val = val * 16 + ret;
return true;
}
}
else if ((c | ' ') <= 'f')
{
int ret = ((c | ' ') - 'a');
if (ret >= 0)
{
val = val * 16 + 10 + ret;
return true;
}
}
return false;
}
static int inet_pton6(const char* src, unsigned char* dst)
{
unsigned char tmp[NS_IN6ADDRSZ_] = { 0 }, *tp = tmp, *endp = tp + NS_IN6ADDRSZ_, *colonp = NULL;
const char* curtok;
char ch, saw_xdigit;
unsigned int val;
// Leading :: requires some special handling.
if (*src == ':')
{
if (*++src != ':')
return 0;
}
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = *src++) != '\0')
{
if (nextHex(val, ch))
{
if (val > 0xffff)
return 0;
saw_xdigit = 1;
continue;
}
if (ch == ':')
{
curtok = src;
if (!saw_xdigit)
{
if (colonp)
return 0;
colonp = tp;
continue;
}
else if (*src == '\0')
return 0;
if (tp + NS_INT16SZ_ > endp)
return 0;
*tp++ = (unsigned char)(val >> 8) & 0xff;
*tp++ = (unsigned char)val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && (tp + NS_INADDRSZ_) <= endp && inet_pton4(curtok, tp) > 0)
{
tp += NS_INADDRSZ_;
saw_xdigit = 0;
break; // '\0' was seen by inet_pton4()
}
return 0;
}
if (saw_xdigit)
{
if (tp + NS_INT16SZ_ > endp)
return 0;
*tp++ = (unsigned char)(val >> 8) & 0xff;
*tp++ = (unsigned char)val & 0xff;
}
if (colonp != NULL)
{
const int n = (int)(tp - colonp);
if (tp == endp)
return (0);
for (int i = 1; i <= n; i++)
{
endp[-i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return 0;
memcpy(dst, tmp, NS_IN6ADDRSZ_);
return 1;
}
#define inet_pton inet_pton_
int inet_pton_(int af, const char *src, void *dst)
{
if (AF_INET == af)
return inet_pton4(src, (unsigned char*)dst);
else if (AF_INET6 == af)
return inet_pton6(src, (unsigned char*)dst);
else
{
WSASetLastError(EAFNOSUPPORT);
return -1;
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment