aboutsummaryrefslogtreecommitdiff
path: root/src/IpAddress.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/IpAddress.cpp')
-rw-r--r--src/IpAddress.cpp172
1 files changed, 170 insertions, 2 deletions
diff --git a/src/IpAddress.cpp b/src/IpAddress.cpp
index 58ed661..75e4348 100644
--- a/src/IpAddress.cpp
+++ b/src/IpAddress.cpp
@@ -1,6 +1,171 @@
#include "../include/sibs/IpAddress.hpp"
#include <cstring>
+#if OS_FAMILY == OS_FAMILY_WINDOWS
+// Source: https://stackoverflow.com/questions/15370033/how-to-use-inet-pton-with-the-mingw-compiler
+#define NS_INADDRSZ 4
+#define NS_IN6ADDRSZ 16
+#define NS_INT16SZ 2
+
+int inet_pton(int af, const char *src, void *dst)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return inet_pton4(src, dst);
+ case AF_INET6:
+ return inet_pton6(src, dst);
+ default:
+ return -1;
+ }
+}
+
+int inet_pton4(const char *src, void *_dst)
+{
+ char *dst = (char*)_dst;
+ uint8_t tmp[NS_INADDRSZ], *tp;
+
+ int saw_digit = 0;
+ int octets = 0;
+ *(tp = tmp) = 0;
+
+ int ch;
+ while ((ch = *src++) != '\0')
+ {
+ if (ch >= '0' && ch <= '9')
+ {
+ uint32_t n = *tp * 10 + (ch - '0');
+
+ if (saw_digit && *tp == 0)
+ return 0;
+
+ if (n > 255)
+ return 0;
+
+ *tp = 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;
+}
+
+int inet_pton6(const char *src, void *_dst)
+{
+ char *dst = (char*)_dst;
+ static const char xdigits[] = "0123456789abcdef";
+ uint8_t tmp[NS_IN6ADDRSZ];
+
+ uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ);
+ uint8_t *endp = tp + NS_IN6ADDRSZ;
+ uint8_t *colonp = NULL;
+
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ {
+ if (*++src != ':')
+ return 0;
+ }
+
+ const char *curtok = src;
+ int saw_xdigit = 0;
+ uint32_t val = 0;
+ int ch;
+ while ((ch = tolower(*src++)) != '\0')
+ {
+ const char *pch = strchr(xdigits, ch);
+ if (pch != NULL)
+ {
+ val <<= 4;
+ val |= (pch - xdigits);
+ 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++ = (uint8_t) (val >> 8) & 0xff;
+ *tp++ = (uint8_t) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, (char*) 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++ = (uint8_t) (val >> 8) & 0xff;
+ *tp++ = (uint8_t) val & 0xff;
+ }
+ if (colonp != NULL)
+ {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = 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;
+}
+#endif
+
namespace sibs
{
Ipv4::Ipv4() : Ipv4(nullptr, 0)
@@ -44,8 +209,11 @@ namespace sibs
std::string Ipv4::getAddress() const
{
std::string result;
- result.resize(INET_ADDRSTRLEN);
- inet_ntop(AF_INET, &address.sin_addr, &result[0], INET_ADDRSTRLEN);
+ const int addrLen = sizeof(address);
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ getnameinfo((sockaddr *)&address, addrLen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST | NI_NUMERICSERV);
+ result += host;
return result;
}