#include std::ostream& operator<<(std::ostream& out, const llarp::inAddr& a) { char tmp[128] = {0}; if(a.isIPv6Mode()) { out << "["; } if(inet_ntop(a.isIPv4Mode() ? AF_INET : AF_INET6, (void*)&a._addr, tmp, sizeof(tmp))) { out << tmp; if(a.isIPv6Mode()) out << "]"; } return out; } namespace llarp { void inAddr::reset() { llarp::Zero(&this->_addr, sizeof(in6_addr)); } bool inAddr::from_char_array(const char* str) { this->reset(); // maybe refactor the family detection out struct addrinfo hint, *res = NULL; int ret; memset(&hint, '\0', sizeof hint); hint.ai_family = PF_UNSPEC; hint.ai_flags = AI_NUMERICHOST; ret = getaddrinfo(str, NULL, &hint, &res); if(ret) { llarp::LogError("failed to determine address family: ", str); return false; } if(res->ai_family != AF_INET && res->ai_family != AF_INET6) { llarp::LogError("Address family not supported yet", str); return false; } // convert detected-family (ipv4 or ipv6) str to in6_addr /* if (res->ai_family == AF_INET) { freeaddrinfo(res); // get IPv4 struct in_addr addr; // basically a uint32_t network order if(inet_aton(str, &addr) == 0) { llarp::LogError("failed to parse ", str); return false; } nuint32_t result; result.n = addr.s_addr; this->fromN32(result); return true; } */ ret = inet_pton(res->ai_family, str, &this->_addr); // inet_pton won't set SIIT // this->hexDebug(); freeaddrinfo(res); if(ret <= 0) { if(ret == 0) { llarp::LogWarn("Not in presentation format"); return false; } else { llarp::LogWarn("inet_pton failure"); return false; } } return true; } void inAddr::fromSIIT() { if(ipv6_is_siit(this->_addr)) { this->_addr.s6_addr[0] = this->_addr.s6_addr[12]; this->_addr.s6_addr[1] = this->_addr.s6_addr[13]; this->_addr.s6_addr[2] = this->_addr.s6_addr[14]; this->_addr.s6_addr[3] = this->_addr.s6_addr[15]; this->setIPv4Mode(); } } void inAddr::toSIIT() { if(!ipv6_is_siit(this->_addr)) { this->_addr.s6_addr[10] = 0xff; this->_addr.s6_addr[11] = 0xff; this->_addr.s6_addr[12] = this->_addr.s6_addr[0]; this->_addr.s6_addr[13] = this->_addr.s6_addr[1]; this->_addr.s6_addr[14] = this->_addr.s6_addr[2]; this->_addr.s6_addr[15] = this->_addr.s6_addr[3]; llarp::Zero(&this->_addr, sizeof(in6_addr) - 6); } } inline bool inAddr::isIPv6Mode() const { return !this->isIPv4Mode(); } bool inAddr::isIPv4Mode() const { return ipv6_is_siit(this->_addr) || (this->_addr.s6_addr[4] == 0 && this->_addr.s6_addr[5] == 0 && this->_addr.s6_addr[6] == 0 && this->_addr.s6_addr[7] == 0 && this->_addr.s6_addr[8] == 0 && this->_addr.s6_addr[9] == 0 && this->_addr.s6_addr[10] == 0 && this->_addr.s6_addr[11] == 0 && this->_addr.s6_addr[12] == 0 && this->_addr.s6_addr[13] == 0 && this->_addr.s6_addr[14] == 0 && this->_addr.s6_addr[15] == 0); } void inAddr::setIPv4Mode() { // keep first 4 // llarp::Zero(&this->_addr + 4, sizeof(in6_addr) - 4); this->_addr.s6_addr[4] = 0; this->_addr.s6_addr[5] = 0; this->_addr.s6_addr[6] = 0; this->_addr.s6_addr[7] = 0; this->_addr.s6_addr[8] = 0; this->_addr.s6_addr[9] = 0; this->_addr.s6_addr[10] = 0; this->_addr.s6_addr[11] = 0; this->_addr.s6_addr[12] = 0; this->_addr.s6_addr[13] = 0; this->_addr.s6_addr[14] = 0; this->_addr.s6_addr[15] = 0; } void inAddr::hexDebug() { char hex_buffer[16 * 3 + 1]; hex_buffer[16 * 3] = 0; for(unsigned int j = 0; j < 16; j++) sprintf(&hex_buffer[3 * j], "%02X ", this->_addr.s6_addr[j]); printf("in6_addr: [%s]\n", hex_buffer); } // // IPv4 specific functions // in_addr inAddr::toIAddr() { in_addr res; res.s_addr = toN32().n; return res; } void inAddr::from4int(const uint8_t one, const uint8_t two, const uint8_t three, const uint8_t four) { this->reset(); this->setIPv4Mode(); // Network byte order this->_addr.s6_addr[0] = one; this->_addr.s6_addr[1] = two; this->_addr.s6_addr[2] = three; this->_addr.s6_addr[3] = four; } void inAddr::fromN32(nuint32_t in) { this->reset(); this->setIPv4Mode(); memcpy(&this->_addr, &in.n, sizeof(uint32_t)); } void inAddr::fromH32(huint32_t in) { this->fromN32(xhtonl(in)); } nuint32_t inAddr::toN32() { nuint32_t result; result.n = 0; // return 0 for IPv6 if(this->isIPv4Mode()) { memcpy(&result.n, &this->_addr, sizeof(uint32_t)); } return result; } huint32_t inAddr::toH32() { return xntohl(this->toN32()); } // // IPv6 specific functions // } // namespace llarp