int SConnectWithTimeout(int sockfd, const ComboAddress& remote, const struct timeval& timeout)
{
int ret = connect(sockfd, reinterpret_cast<const struct sockaddr*>(&remote), remote.getSocklen());
- if(ret < 0) {
+ if (ret < 0) {
int savederrno = errno;
if (savederrno == EINPROGRESS) {
- if (timeout <= timeval{0,0}) {
+ if (timeout <= timeval{0, 0}) {
return savederrno;
}
if (error) {
savederrno = 0;
socklen_t errlen = sizeof(savederrno);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&savederrno, &errlen) == 0) {
+ if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)&savederrno, &errlen) == 0) {
NetworkErr("connecting to " + remote.toStringWithPort() + " failed: " + stringerror(savederrno));
}
else {
}
else if (res == 0) {
NetworkErr("timeout while connecting to " + remote.toStringWithPort());
- } else if (res < 0) {
+ }
+ else if (res < 0) {
savederrno = errno;
NetworkErr("waiting to connect to " + remote.toStringWithPort() + ": " + stringerror(savederrno));
}
if (family == AF_INET) {
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
#ifdef IP_PMTUDISC_OMIT
- /* Linux 3.15+ has IP_PMTUDISC_OMIT, which discards PMTU information to prevent
- poisoning, but still allows fragmentation if the packet size exceeds the
- outgoing interface MTU, which is good.
- */
+ /* Linux 3.15+ has IP_PMTUDISC_OMIT, which discards PMTU information to prevent
+ poisoning, but still allows fragmentation if the packet size exceeds the
+ outgoing interface MTU, which is good.
+ */
try {
SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_OMIT);
return;
}
- catch(const std::exception& e) {
+ catch (const std::exception& e) {
/* failed, let's try IP_PMTUDISC_DONT instead */
}
#endif /* IP_PMTUDISC_OMIT */
- /* IP_PMTUDISC_DONT disables Path MTU discovery */
+ /* IP_PMTUDISC_DONT disables Path MTU discovery */
SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT);
#endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) */
}
else {
- #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
+#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
#ifdef IPV6_PMTUDISC_OMIT
- /* Linux 3.15+ has IPV6_PMTUDISC_OMIT, which discards PMTU information to prevent
- poisoning, but still allows fragmentation if the packet size exceeds the
- outgoing interface MTU, which is good.
- */
+ /* Linux 3.15+ has IPV6_PMTUDISC_OMIT, which discards PMTU information to prevent
+ poisoning, but still allows fragmentation if the packet size exceeds the
+ outgoing interface MTU, which is good.
+ */
try {
SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_OMIT);
return;
}
- catch(const std::exception& e) {
+ catch (const std::exception& e) {
/* failed, let's try IP_PMTUDISC_DONT instead */
}
#endif /* IPV6_PMTUDISC_OMIT */
- /* IPV6_PMTUDISC_DONT disables Path MTU discovery */
+ /* IPV6_PMTUDISC_DONT disables Path MTU discovery */
SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_DONT);
#endif /* defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) */
}
bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv)
{
#ifdef SO_TIMESTAMP
- struct cmsghdr *cmsg;
- for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != nullptr; cmsg = CMSG_NXTHDR(msgh,cmsg)) {
- if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP || cmsg->cmsg_type == SCM_TIMESTAMP) &&
- CMSG_LEN(sizeof(*tv)) == cmsg->cmsg_len) {
+ struct cmsghdr* cmsg;
+ for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != nullptr; cmsg = CMSG_NXTHDR(msgh, cmsg)) {
+ if ((cmsg->cmsg_level == SOL_SOCKET) && (cmsg->cmsg_type == SO_TIMESTAMP || cmsg->cmsg_type == SCM_TIMESTAMP) && CMSG_LEN(sizeof(*tv)) == cmsg->cmsg_len) {
memcpy(tv, CMSG_DATA(cmsg), sizeof(*tv));
return true;
}
#endif
for (cmsg = CMSG_FIRSTHDR(msgh); cmsg != nullptr; cmsg = CMSG_NXTHDR(const_cast<struct msghdr*>(msgh), const_cast<struct cmsghdr*>(cmsg))) {
#if defined(IP_PKTINFO)
- if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
- struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
- destination->sin4.sin_addr = i->ipi_addr;
- destination->sin4.sin_family = AF_INET;
- return true;
+ if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
+ struct in_pktinfo* i = (struct in_pktinfo*)CMSG_DATA(cmsg);
+ destination->sin4.sin_addr = i->ipi_addr;
+ destination->sin4.sin_family = AF_INET;
+ return true;
}
#elif defined(IP_RECVDSTADDR)
if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
- struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
+ struct in_addr* i = (struct in_addr*)CMSG_DATA(cmsg);
destination->sin4.sin_addr = *i;
destination->sin4.sin_family = AF_INET;
return true;
#endif
if ((cmsg->cmsg_level == IPPROTO_IPV6) && (cmsg->cmsg_type == IPV6_PKTINFO)) {
- struct in6_pktinfo *i = (struct in6_pktinfo *) CMSG_DATA(cmsg);
- destination->sin6.sin6_addr = i->ipi6_addr;
- destination->sin4.sin_family = AF_INET6;
- return true;
+ struct in6_pktinfo* i = (struct in6_pktinfo*)CMSG_DATA(cmsg);
+ destination->sin6.sin6_addr = i->ipi6_addr;
+ destination->sin4.sin_family = AF_INET6;
+ return true;
}
}
return false;
bool IsAnyAddress(const ComboAddress& addr)
{
- if(addr.sin4.sin_family == AF_INET)
+ if (addr.sin4.sin_family == AF_INET)
return addr.sin4.sin_addr.s_addr == 0;
- else if(addr.sin4.sin_family == AF_INET6)
+ else if (addr.sin4.sin_family == AF_INET6)
return !memcmp(&addr.sin6.sin6_addr, &in6addr_any, sizeof(addr.sin6.sin6_addr));
return false;
}
-int sendOnNBSocket(int fd, const struct msghdr *msgh)
+int sendOnNBSocket(int fd, const struct msghdr* msgh)
{
int sendErr = 0;
#ifdef __OpenBSD__
void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, cmsgbuf_aligned* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr)
{
iov->iov_base = data;
- iov->iov_len = datalen;
+ iov->iov_len = datalen;
memset(msgh, 0, sizeof(struct msghdr));
msgh->msg_controllen = cbufsize;
msgh->msg_name = addr;
msgh->msg_namelen = addr->getSocklen();
- msgh->msg_iov = iov;
+ msgh->msg_iov = iov;
msgh->msg_iovlen = 1;
msgh->msg_flags = 0;
}
void ComboAddress::truncate(unsigned int bits) noexcept
{
uint8_t* start;
- int len=4;
- if(sin4.sin_family==AF_INET) {
- if(bits >= 32)
+ int len = 4;
+ if (sin4.sin_family == AF_INET) {
+ if (bits >= 32)
return;
start = (uint8_t*)&sin4.sin_addr.s_addr;
- len=4;
+ len = 4;
}
else {
- if(bits >= 128)
+ if (bits >= 128)
return;
start = (uint8_t*)&sin6.sin6_addr.s6_addr;
- len=16;
+ len = 16;
}
- auto tozero= len*8 - bits; // if set to 22, this will clear 1 byte, as it should
+ auto tozero = len * 8 - bits; // if set to 22, this will clear 1 byte, as it should
- memset(start + len - tozero/8, 0, tozero/8); // blot out the whole bytes on the right
+ memset(start + len - tozero / 8, 0, tozero / 8); // blot out the whole bytes on the right
- auto bitsleft=tozero % 8; // 2 bits left to clear
+ auto bitsleft = tozero % 8; // 2 bits left to clear
// a b c d, to truncate to 22 bits, we just zeroed 'd' and need to zero 2 bits from c
// so and by '11111100', which is ~((1<<2)-1) = ~3
- uint8_t* place = start + len - 1 - tozero/8;
- *place &= (~((1<<bitsleft)-1));
+ uint8_t* place = start + len - 1 - tozero / 8;
+ *place &= (~((1 << bitsleft) - 1));
}
size_t sendMsgWithOptions(int socketDesc, const void* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags)
}
/* partial write */
- #ifdef MSG_FASTOPEN
+#ifdef MSG_FASTOPEN
firstTry = false;
- #endif
+#endif
iov.iov_len -= written;
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast,cppcoreguidelines-pro-bounds-pointer-arithmetic): it's the API
iov.iov_base = reinterpret_cast<void*>(reinterpret_cast<char*>(iov.iov_base) + written);
}
unixDie("failed in sendMsgWithOptions");
}
- }
- while (true);
+ } while (true);
return 0;
}
return ComboAddress(input, port);
case 1: { // case 3
string::size_type cpos = input.rfind(':');
- pair<std::string,std::string> both;
+ pair<std::string, std::string> both;
both.first = input.substr(0, cpos);
both.second = input.substr(cpos + 1);
{
std::set<std::string> result;
#ifdef HAVE_GETIFADDRS
- struct ifaddrs *ifaddr;
+ struct ifaddrs* ifaddr;
if (getifaddrs(&ifaddr) == -1) {
return result;
}
- for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
+ for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_name == nullptr) {
continue;
}
std::vector<ComboAddress> getListOfAddressesOfNetworkInterface(const std::string& itf)
{
std::vector<ComboAddress> result;
- struct ifaddrs *ifaddr = nullptr;
+ struct ifaddrs* ifaddr = nullptr;
if (getifaddrs(&ifaddr) == -1) {
return result;
}
- for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
+ for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_name == nullptr || strcmp(ifa->ifa_name, itf.c_str()) != 0) {
continue;
}
std::vector<ComboAddress> result;
return result;
}
-#endif // HAVE_GETIFADDRS
+#endif // HAVE_GETIFADDRS
#ifdef HAVE_GETIFADDRS
static uint8_t convertNetmaskToBits(const uint8_t* mask, socklen_t len)
std::vector<Netmask> getListOfRangesOfNetworkInterface(const std::string& itf)
{
std::vector<Netmask> result;
- struct ifaddrs *ifaddr = nullptr;
+ struct ifaddrs* ifaddr = nullptr;
if (getifaddrs(&ifaddr) == -1) {
return result;
}
- for (struct ifaddrs *ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
+ for (struct ifaddrs* ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_name == nullptr || strcmp(ifa->ifa_name, itf.c_str()) != 0) {
continue;
}
std::vector<Netmask> result;
return result;
}
-#endif // HAVE_GETIFADDRS
+#endif // HAVE_GETIFADDRS
#undef IP_PKTINFO
#endif
-union ComboAddress {
+union ComboAddress
+{
struct sockaddr_in sin4;
struct sockaddr_in6 sin6;
bool operator==(const ComboAddress& rhs) const
{
- if(std::tie(sin4.sin_family, sin4.sin_port) != std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
+ if (std::tie(sin4.sin_family, sin4.sin_port) != std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
return false;
- if(sin4.sin_family == AF_INET)
+ if (sin4.sin_family == AF_INET)
return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
else
- return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0;
+ return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) == 0;
}
bool operator!=(const ComboAddress& rhs) const
{
- return(!operator==(rhs));
+ return (!operator==(rhs));
}
bool operator<(const ComboAddress& rhs) const
{
- if(sin4.sin_family == 0) {
+ if (sin4.sin_family == 0) {
return false;
}
- if(std::tie(sin4.sin_family, sin4.sin_port) < std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
+ if (std::tie(sin4.sin_family, sin4.sin_port) < std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
return true;
- if(std::tie(sin4.sin_family, sin4.sin_port) > std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
+ if (std::tie(sin4.sin_family, sin4.sin_port) > std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
return false;
- if(sin4.sin_family == AF_INET)
+ if (sin4.sin_family == AF_INET)
return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
else
return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0;
{
bool operator()(const ComboAddress& a, const ComboAddress& b) const
{
- if(a.sin4.sin_family < b.sin4.sin_family)
+ if (a.sin4.sin_family < b.sin4.sin_family)
return true;
- if(a.sin4.sin_family > b.sin4.sin_family)
+ if (a.sin4.sin_family > b.sin4.sin_family)
return false;
- if(a.sin4.sin_family == AF_INET)
+ if (a.sin4.sin_family == AF_INET)
return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
else
return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
{
bool operator()(const ComboAddress& a, const ComboAddress& b) const
{
- if(a.sin4.sin_family != b.sin4.sin_family)
+ if (a.sin4.sin_family != b.sin4.sin_family)
return false;
- if(a.sin4.sin_family == AF_INET)
+ if (a.sin4.sin_family == AF_INET)
return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
else
return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr));
}
};
-
socklen_t getSocklen() const
{
- if(sin4.sin_family == AF_INET)
+ if (sin4.sin_family == AF_INET)
return sizeof(sin4);
else
return sizeof(sin6);
ComboAddress()
{
- sin4.sin_family=AF_INET;
- sin4.sin_addr.s_addr=0;
- sin4.sin_port=0;
+ sin4.sin_family = AF_INET;
+ sin4.sin_addr.s_addr = 0;
+ sin4.sin_port = 0;
sin6.sin6_scope_id = 0;
sin6.sin6_flowinfo = 0;
}
- ComboAddress(const struct sockaddr *sa, socklen_t salen) {
+ ComboAddress(const struct sockaddr* sa, socklen_t salen)
+ {
setSockaddr(sa, salen);
};
- ComboAddress(const struct sockaddr_in6 *sa) {
+ ComboAddress(const struct sockaddr_in6* sa)
+ {
setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6));
};
- ComboAddress(const struct sockaddr_in *sa) {
+ ComboAddress(const struct sockaddr_in* sa)
+ {
setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in));
};
- void setSockaddr(const struct sockaddr *sa, socklen_t salen) {
- if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
+ void setSockaddr(const struct sockaddr* sa, socklen_t salen)
+ {
+ if (salen > sizeof(struct sockaddr_in6))
+ throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
memcpy(this, sa, salen);
}
// 'port' sets a default value in case 'str' does not set a port
- explicit ComboAddress(const string& str, uint16_t port=0)
+ explicit ComboAddress(const string& str, uint16_t port = 0)
{
memset(&sin6, 0, sizeof(sin6));
sin4.sin_family = AF_INET;
sin4.sin_port = 0;
- if(makeIPv4sockaddr(str, &sin4)) {
+ if (makeIPv4sockaddr(str, &sin4)) {
sin6.sin6_family = AF_INET6;
- if(makeIPv6sockaddr(str, &sin6) < 0) {
- throw PDNSException("Unable to convert presentation address '"+ str +"'");
+ if (makeIPv6sockaddr(str, &sin6) < 0) {
+ throw PDNSException("Unable to convert presentation address '" + str + "'");
}
-
}
- if(!sin4.sin_port) // 'str' overrides port!
- sin4.sin_port=htons(port);
+ if (!sin4.sin_port) // 'str' overrides port!
+ sin4.sin_port = htons(port);
}
bool isIPv6() const
return sin4.sin_family == AF_INET;
}
- bool isMappedIPv4() const
+ bool isMappedIPv4() const
{
- if(sin4.sin_family!=AF_INET6)
+ if (sin4.sin_family != AF_INET6)
return false;
- int n=0;
+ int n = 0;
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&sin6.sin6_addr.s6_addr);
- for(n=0; n < 10; ++n)
- if(ptr[n])
+ for (n = 0; n < 10; ++n)
+ if (ptr[n])
return false;
- for(; n < 12; ++n)
- if(ptr[n]!=0xff)
+ for (; n < 12; ++n)
+ if (ptr[n] != 0xff)
return false;
return true;
ComboAddress mapToIPv4() const
{
- if(!isMappedIPv4())
+ if (!isMappedIPv4())
throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
ComboAddress ret;
- ret.sin4.sin_family=AF_INET;
- ret.sin4.sin_port=sin4.sin_port;
+ ret.sin4.sin_family = AF_INET;
+ ret.sin4.sin_port = sin4.sin_port;
const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&sin6.sin6_addr.s6_addr);
- ptr+=(sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr));
+ ptr += (sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr));
memcpy(&ret.sin4.sin_addr.s_addr, ptr, sizeof(ret.sin4.sin_addr.s_addr));
return ret;
}
{
char host[1024];
int retval = 0;
- if(sin4.sin_family && !(retval = getnameinfo(reinterpret_cast<const struct sockaddr*>(this), getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST)))
+ if (sin4.sin_family && !(retval = getnameinfo(reinterpret_cast<const struct sockaddr*>(this), getSocklen(), host, sizeof(host), 0, 0, NI_NUMERICHOST)))
return string(host);
else
- return "invalid "+string(gai_strerror(retval));
+ return "invalid " + string(gai_strerror(retval));
}
//! Ignores any interface specifiers possibly available in the sockaddr data.
string toStringNoInterface() const
{
char host[1024];
- if(sin4.sin_family == AF_INET && (nullptr != inet_ntop(sin4.sin_family, &sin4.sin_addr, host, sizeof(host))))
+ if (sin4.sin_family == AF_INET && (nullptr != inet_ntop(sin4.sin_family, &sin4.sin_addr, host, sizeof(host))))
return string(host);
- else if(sin4.sin_family == AF_INET6 && (nullptr != inet_ntop(sin4.sin_family, &sin6.sin6_addr, host, sizeof(host))))
+ else if (sin4.sin_family == AF_INET6 && (nullptr != inet_ntop(sin4.sin_family, &sin6.sin6_addr, host, sizeof(host))))
return string(host);
else
- return "invalid "+stringerror();
+ return "invalid " + stringerror();
}
[[nodiscard]] string toStringReversed() const
string toStringWithPort() const
{
- if(sin4.sin_family==AF_INET)
+ if (sin4.sin_family == AF_INET)
return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
else
- return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
+ return "[" + toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
}
string toStringWithPortExcept(int port) const
{
- if(ntohs(sin4.sin_port) == port)
+ if (ntohs(sin4.sin_port) == port)
return toString();
- if(sin4.sin_family==AF_INET)
+ if (sin4.sin_family == AF_INET)
return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
else
- return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
+ return "[" + toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
}
string toLogString() const
*/
bool getBit(int index) const
{
- if(isIPv4()) {
+ if (isIPv4()) {
if (index >= 32)
return false;
if (index < 0) {
uint32_t ls_addr = ntohl(sin4.sin_addr.s_addr);
- return ((ls_addr & (1U<<index)) != 0x00000000);
+ return ((ls_addr & (1U << index)) != 0x00000000);
}
- if(isIPv6()) {
+ if (isIPv6()) {
if (index >= 128)
return false;
if (index < 0) {
uint8_t byte_idx = index / 8;
uint8_t bit_idx = index % 8;
- return ((ls_addr[15-byte_idx] & (1U << bit_idx)) != 0x00);
+ return ((ls_addr[15 - byte_idx] & (1U << bit_idx)) != 0x00);
}
return false;
}
* \param withPort Also print the port (default true)
* \param portExcept Print the port, except when this is the port (default 53)
*/
- template < template < class ... > class Container, class ... Args >
- static string caContainerToString(const Container<ComboAddress, Args...>& c, const bool withPort = true, const uint16_t portExcept = 53) {
- vector<string> strs;
- for (const auto& ca : c) {
- if (withPort) {
- strs.push_back(ca.toStringWithPortExcept(portExcept));
- continue;
+ template <template <class...> class Container, class... Args>
+ static string caContainerToString(const Container<ComboAddress, Args...>& c, const bool withPort = true, const uint16_t portExcept = 53)
+ {
+ vector<string> strs;
+ for (const auto& ca : c) {
+ if (withPort) {
+ strs.push_back(ca.toStringWithPortExcept(portExcept));
+ continue;
+ }
+ strs.push_back(ca.toString());
}
- strs.push_back(ca.toString());
- }
- return boost::join(strs, ",");
+ return boost::join(strs, ",");
};
};
/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
-class NetmaskException: public PDNSException
+class NetmaskException : public PDNSException
{
public:
- NetmaskException(const string &a) : PDNSException(a) {}
+ NetmaskException(const string& a) :
+ PDNSException(a) {}
};
inline ComboAddress makeComboAddress(const string& str)
{
ComboAddress address;
- address.sin4.sin_family=AF_INET;
- if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
- address.sin4.sin_family=AF_INET6;
- if(makeIPv6sockaddr(str, &address.sin6) < 0)
- throw NetmaskException("Unable to convert '"+str+"' to a netmask");
+ address.sin4.sin_family = AF_INET;
+ if (inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
+ address.sin4.sin_family = AF_INET6;
+ if (makeIPv6sockaddr(str, &address.sin6) < 0)
+ throw NetmaskException("Unable to convert '" + str + "' to a netmask");
}
return address;
}
if (version == 4) {
address.sin4.sin_family = AF_INET;
- if (len != sizeof(address.sin4.sin_addr)) throw NetmaskException("invalid raw address length");
+ if (len != sizeof(address.sin4.sin_addr))
+ throw NetmaskException("invalid raw address length");
memcpy(&address.sin4.sin_addr, raw, sizeof(address.sin4.sin_addr));
}
else if (version == 6) {
address.sin6.sin6_family = AF_INET6;
- if (len != sizeof(address.sin6.sin6_addr)) throw NetmaskException("invalid raw address length");
+ if (len != sizeof(address.sin6.sin6_addr))
+ throw NetmaskException("invalid raw address length");
memcpy(&address.sin6.sin6_addr, raw, sizeof(address.sin6.sin6_addr));
}
- else throw NetmaskException("invalid address family");
+ else
+ throw NetmaskException("invalid address family");
return address;
}
-inline ComboAddress makeComboAddressFromRaw(uint8_t version, const string &str)
+inline ComboAddress makeComboAddressFromRaw(uint8_t version, const string& str)
{
return makeComboAddressFromRaw(version, str.c_str(), str.size());
}
d_bits = 0;
}
- Netmask(const ComboAddress& network, uint8_t bits=0xff): d_network(network)
+ Netmask(const ComboAddress& network, uint8_t bits = 0xff) :
+ d_network(network)
{
d_network.sin4.sin_port = 0;
setBits(bits);
}
- Netmask(const sockaddr_in* network, uint8_t bits = 0xff): d_network(network)
+ Netmask(const sockaddr_in* network, uint8_t bits = 0xff) :
+ d_network(network)
{
d_network.sin4.sin_port = 0;
setBits(bits);
}
- Netmask(const sockaddr_in6* network, uint8_t bits = 0xff): d_network(network)
+ Netmask(const sockaddr_in6* network, uint8_t bits = 0xff) :
+ d_network(network)
{
d_network.sin4.sin_port = 0;
setBits(bits);
d_network.sin4.sin_addr.s_addr = htonl(ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
}
else if (isIPv6()) {
- uint8_t bytes = d_bits/8;
- uint8_t *us = (uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
+ uint8_t bytes = d_bits / 8;
+ uint8_t* us = (uint8_t*)&d_network.sin6.sin6_addr.s6_addr;
uint8_t bits = d_bits % 8;
- uint8_t mask = (uint8_t) ~(0xFF>>bits);
+ uint8_t mask = (uint8_t) ~(0xFF >> bits);
if (bytes < sizeof(d_network.sin6.sin6_addr.s6_addr)) {
us[bytes] &= mask;
}
- for(size_t idx = bytes + 1; idx < sizeof(d_network.sin6.sin6_addr.s6_addr); ++idx) {
+ for (size_t idx = bytes + 1; idx < sizeof(d_network.sin6.sin6_addr.s6_addr); ++idx) {
us[idx] = 0;
}
}
}
//! Constructor supplies the mask, which cannot be changed
- Netmask(const string &mask)
+ Netmask(const string& mask)
{
- pair<string,string> split = splitField(mask,'/');
+ pair<string, string> split = splitField(mask, '/');
d_network = makeComboAddress(split.first);
if (!split.second.empty()) {
}
//! If this IP address in socket address matches
- bool match(const ComboAddress *ip) const
+ bool match(const ComboAddress* ip) const
{
- if(d_network.sin4.sin_family != ip->sin4.sin_family) {
+ if (d_network.sin4.sin_family != ip->sin4.sin_family) {
return false;
}
- if(d_network.sin4.sin_family == AF_INET) {
+ if (d_network.sin4.sin_family == AF_INET) {
return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr));
}
- if(d_network.sin6.sin6_family == AF_INET6) {
- uint8_t bytes=d_bits/8, n;
- const uint8_t *us=(const uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
- const uint8_t *them=(const uint8_t*) &ip->sin6.sin6_addr.s6_addr;
+ if (d_network.sin6.sin6_family == AF_INET6) {
+ uint8_t bytes = d_bits / 8, n;
+ const uint8_t* us = (const uint8_t*)&d_network.sin6.sin6_addr.s6_addr;
+ const uint8_t* them = (const uint8_t*)&ip->sin6.sin6_addr.s6_addr;
- for(n=0; n < bytes; ++n) {
- if(us[n]!=them[n]) {
+ for (n = 0; n < bytes; ++n) {
+ if (us[n] != them[n]) {
return false;
}
}
// still here, now match remaining bits
- uint8_t bits= d_bits % 8;
- uint8_t mask= (uint8_t) ~(0xFF>>bits);
+ uint8_t bits = d_bits % 8;
+ uint8_t mask = (uint8_t) ~(0xFF >> bits);
- return((us[n]) == (them[n] & mask));
+ return ((us[n]) == (them[n] & mask));
}
return false;
}
//! If this ASCII IP address matches
- bool match(const string &ip) const
+ bool match(const string& ip) const
{
- ComboAddress address=makeComboAddress(ip);
+ ComboAddress address = makeComboAddress(ip);
return match(&address);
}
string toString() const
{
- return d_network.toStringNoInterface()+"/"+std::to_string((unsigned int)d_bits);
+ return d_network.toStringNoInterface() + "/" + std::to_string((unsigned int)d_bits);
}
string toStringNoMask() const
bool empty() const
{
- return d_network.sin4.sin_family==0;
+ return d_network.sin4.sin_family == 0;
}
//! Get normalized version of the netmask. This means that all address bits below the network bits are zero.
- Netmask getNormalized() const {
+ Netmask getNormalized() const
+ {
return Netmask(getMaskedNetwork(), d_bits);
}
//! Get Netmask for super network of this one (i.e. with fewer network bits)
- Netmask getSuper(uint8_t bits) const {
+ Netmask getSuper(uint8_t bits) const
+ {
return Netmask(d_network, std::min(d_bits, bits));
}
if (bit < -d_bits)
return false;
if (bit >= 0) {
- if(isIPv4()) {
+ if (isIPv4()) {
if (bit >= 32 || bit < (32 - d_bits))
return false;
}
- if(isIPv6()) {
+ if (isIPv6()) {
if (bit >= 128 || bit < (128 - d_bits))
return false;
}
return d_network.getBit(bit);
}
- struct Hash {
+ struct Hash
+ {
size_t operator()(const Netmask& nm) const
{
return burtle(&nm.d_bits, 1, ComboAddress::addressOnlyHash()(nm.d_network));
uint8_t d_bits;
};
-namespace std {
- template<>
- struct hash<Netmask> {
- auto operator()(const Netmask& nm) const {
- return Netmask::Hash{}(nm);
- }
- };
+namespace std
+{
+template <>
+struct hash<Netmask>
+{
+ auto operator()(const Netmask& nm) const
+ {
+ return Netmask::Hash{}(nm);
+ }
+};
}
/** Binary tree map implementation with <Netmask,T> pair.
* from GeoIPBackend and Sortlist, and from dnsdist.
*/
template <typename T, class K = Netmask>
-class NetmaskTree {
+class NetmaskTree
+{
public:
class Iterator;
typedef K key_type;
typedef T value_type;
- typedef std::pair<const key_type,value_type> node_type;
+ typedef std::pair<const key_type, value_type> node_type;
typedef size_t size_type;
typedef class Iterator iterator;
private:
/** Single node in tree, internal use only.
- */
- class TreeNode : boost::noncopyable {
+ */
+ class TreeNode : boost::noncopyable
+ {
public:
explicit TreeNode() noexcept :
- parent(nullptr), node(), assigned(false), d_bits(0) {
+ parent(nullptr), node(), assigned(false), d_bits(0)
+ {
}
explicit TreeNode(const key_type& key) :
- parent(nullptr), node({key.getNormalized(), value_type()}),
- assigned(false), d_bits(key.getFullBits()) {
+ parent(nullptr), node({key.getNormalized(), value_type()}), assigned(false), d_bits(key.getFullBits())
+ {
}
//<! Makes a left leaf node with specified key.
- TreeNode* make_left(const key_type& key) {
+ TreeNode* make_left(const key_type& key)
+ {
d_bits = node.first.getBits();
left = make_unique<TreeNode>(key);
left->parent = this;
}
//<! Makes a right leaf node with specified key.
- TreeNode* make_right(const key_type& key) {
+ TreeNode* make_right(const key_type& key)
+ {
d_bits = node.first.getBits();
right = make_unique<TreeNode>(key);
right->parent = this;
}
//<! Splits branch at indicated bit position by inserting key
- TreeNode* split(const key_type& key, int bits) {
+ TreeNode* split(const key_type& key, int bits)
+ {
if (parent == nullptr) {
// not to be called on the root node
throw std::logic_error(
}
// determine reference from parent
- unique_ptr<TreeNode>& parent_ref =
- (parent->left.get() == this ? parent->left : parent->right);
+ unique_ptr<TreeNode>& parent_ref = (parent->left.get() == this ? parent->left : parent->right);
if (parent_ref.get() != this) {
throw std::logic_error(
"NetmaskTree::TreeNode::split(): parent node reference is invalid");
// attach "this" node below the new node
// (left or right depending on bit)
new_child->parent = new_node;
- if (new_child->node.first.getBit(-1-bits)) {
+ if (new_child->node.first.getBit(-1 - bits)) {
std::swap(new_node->right, new_child);
- } else {
+ }
+ else {
std::swap(new_node->left, new_child);
}
}
//<! Forks branch for new key at indicated bit position
- TreeNode* fork(const key_type& key, int bits) {
+ TreeNode* fork(const key_type& key, int bits)
+ {
if (parent == nullptr) {
// not to be called on the root node
throw std::logic_error(
}
// determine reference from parent
- unique_ptr<TreeNode>& parent_ref =
- (parent->left.get() == this ? parent->left : parent->right);
+ unique_ptr<TreeNode>& parent_ref = (parent->left.get() == this ? parent->left : parent->right);
if (parent_ref.get() != this) {
throw std::logic_error(
"NetmaskTree::TreeNode::fork(): parent node reference is invalid");
// (left or right depending on bit)
new_child1->parent = branch_node;
new_child2->parent = branch_node;
- if (new_child1->node.first.getBit(-1-bits)) {
+ if (new_child1->node.first.getBit(-1 - bits)) {
branch_node->right = std::move(new_child1);
branch_node->left = std::move(new_child2);
- } else {
+ }
+ else {
branch_node->right = std::move(new_child2);
branch_node->left = std::move(new_child1);
}
}
//<! Traverse left branch depth-first
- TreeNode *traverse_l()
+ TreeNode* traverse_l()
{
- TreeNode *tnode = this;
+ TreeNode* tnode = this;
while (tnode->left)
tnode = tnode->left.get();
}
//<! Traverse tree depth-first and in-order (L-N-R)
- TreeNode *traverse_lnr()
+ TreeNode* traverse_lnr()
{
- TreeNode *tnode = this;
+ TreeNode* tnode = this;
// precondition: descended left as deep as possible
if (tnode->right) {
// ascend to parent
while (tnode->parent != nullptr) {
- TreeNode *prev_child = tnode;
+ TreeNode* prev_child = tnode;
tnode = tnode->parent;
// return this node, but only when we come from the left child branch
}
//<! Traverse only assigned nodes
- TreeNode *traverse_lnr_assigned()
+ TreeNode* traverse_lnr_assigned()
{
- TreeNode *tnode = traverse_lnr();
+ TreeNode* tnode = traverse_lnr();
while (tnode != nullptr && !tnode->assigned)
tnode = tnode->traverse_lnr();
void copyTree(const NetmaskTree& rhs)
{
try {
- TreeNode *node = rhs.d_root.get();
+ TreeNode* node = rhs.d_root.get();
if (node != nullptr)
node = node->traverse_l();
while (node != nullptr) {
}
public:
- class Iterator {
+ class Iterator
+ {
public:
typedef node_type value_type;
typedef node_type& reference;
const NetmaskTree* d_tree;
TreeNode* d_node;
- Iterator(const NetmaskTree* tree, TreeNode* node): d_tree(tree), d_node(node) {
+ Iterator(const NetmaskTree* tree, TreeNode* node) :
+ d_tree(tree), d_node(node)
+ {
}
public:
- Iterator(): d_tree(nullptr), d_node(nullptr) {}
+ Iterator() :
+ d_tree(nullptr), d_node(nullptr) {}
Iterator& operator++() // prefix
{
};
public:
- NetmaskTree() noexcept: d_root(new TreeNode()), d_left(nullptr), d_size(0) {
+ NetmaskTree() noexcept :
+ d_root(new TreeNode()), d_left(nullptr), d_size(0)
+ {
}
- NetmaskTree(const NetmaskTree& rhs): d_root(new TreeNode()), d_left(nullptr), d_size(0) {
+ NetmaskTree(const NetmaskTree& rhs) :
+ d_root(new TreeNode()), d_left(nullptr), d_size(0)
+ {
copyTree(rhs);
}
- NetmaskTree& operator=(const NetmaskTree& rhs) {
+ NetmaskTree& operator=(const NetmaskTree& rhs)
+ {
clear();
copyTree(rhs);
return *this;
}
- const iterator begin() const {
+ const iterator begin() const
+ {
return Iterator(this, d_left);
}
- const iterator end() const {
+ const iterator end() const
+ {
return Iterator(this, nullptr);
}
- iterator begin() {
+ iterator begin()
+ {
return Iterator(this, d_left);
}
- iterator end() {
+ iterator end()
+ {
return Iterator(this, nullptr);
}
- node_type& insert(const string &mask) {
+ node_type& insert(const string& mask)
+ {
return insert(key_type(mask));
}
//<! Creates new value-pair in tree and returns it.
- node_type& insert(const key_type& key) {
+ node_type& insert(const key_type& key)
+ {
TreeNode* node;
bool is_left = true;
d_left = node;
return node->node;
}
- } else if (key.isIPv6()) {
+ }
+ else if (key.isIPv6()) {
node = d_root->right.get();
if (node == nullptr) {
node = new TreeNode(key);
}
if (d_root->left)
is_left = false;
- } else
+ }
+ else
throw NetmaskException("invalid address family");
// we turn left on 0 and right on 1
int bits = 0;
- for(; bits < key.getBits(); bits++) {
- bool vall = key.getBit(-1-bits);
+ for (; bits < key.getBits(); bits++) {
+ bool vall = key.getBit(-1 - bits);
if (bits >= node->d_bits) {
// the end of the current node is reached; continue with the next
break;
}
node = node->right.get();
- } else {
+ }
+ else {
if (!node->left) {
// the left branch doesn't exist yet; attach our key here
node = node->make_left(key);
if (node->assigned)
is_left = false;
node = node->make_right(key);
- } else {
+ }
+ else {
node = node->make_left(key);
}
break;
}
- bool valr = node->node.first.getBit(-1-bits);
+ bool valr = node->node.first.getBit(-1 - bits);
if (vall != valr) {
if (vall)
is_left = false;
if (is_left)
d_left = node;
node->assigned = true;
- } else {
+ }
+ else {
// tree node exists for this value
if (is_left && d_left != node) {
throw std::logic_error(
}
//<! Creates or updates value
- void insert_or_assign(const key_type& mask, const value_type& value) {
+ void insert_or_assign(const key_type& mask, const value_type& value)
+ {
insert(mask).second = value;
}
- void insert_or_assign(const string& mask, const value_type& value) {
+ void insert_or_assign(const string& mask, const value_type& value)
+ {
insert(key_type(mask)).second = value;
}
//<! check if given key is present in TreeMap
- bool has_key(const key_type& key) const {
- const node_type *ptr = lookup(key);
+ bool has_key(const key_type& key) const
+ {
+ const node_type* ptr = lookup(key);
return ptr && ptr->first == key;
}
//<! Returns "best match" for key_type, which might not be value
- [[nodiscard]] node_type* lookup(const key_type& value) const {
+ [[nodiscard]] node_type* lookup(const key_type& value) const
+ {
uint8_t max_bits = value.getBits();
return lookupImpl(value, max_bits);
}
//<! Perform best match lookup for value, using at most max_bits
- [[nodiscard]] node_type* lookup(const ComboAddress& value, int max_bits = 128) const {
+ [[nodiscard]] node_type* lookup(const ComboAddress& value, int max_bits = 128) const
+ {
uint8_t addr_bits = value.getBits();
if (max_bits < 0 || max_bits > addr_bits) {
max_bits = addr_bits;
}
//<! Removes key from TreeMap.
- void erase(const key_type& key) {
- TreeNode *node = nullptr;
+ void erase(const key_type& key)
+ {
+ TreeNode* node = nullptr;
if (key.isIPv4())
node = d_root->left.get();
else
throw NetmaskException("invalid address family");
// no tree, no value
- if (node == nullptr) return;
+ if (node == nullptr)
+ return;
int bits = 0;
- for(; node && bits < key.getBits(); bits++) {
- bool vall = key.getBit(-1-bits);
+ for (; node && bits < key.getBits(); bits++) {
+ bool vall = key.getBit(-1 - bits);
if (bits >= node->d_bits) {
// the end of the current node is reached; continue with the next
if (vall) {
node = node->right.get();
- } else {
+ }
+ else {
node = node->left.get();
}
continue;
node = nullptr;
break;
}
- bool valr = node->node.first.getBit(-1-bits);
+ bool valr = node->node.first.getBit(-1 - bits);
if (vall != valr) {
// the branch matches just upto this point, yet continues in a different
// direction
}
}
- void erase(const string& key) {
+ void erase(const string& key)
+ {
erase(key_type(key));
}
//<! checks whether the container is empty.
- [[nodiscard]] bool empty() const {
+ [[nodiscard]] bool empty() const
+ {
return (d_size == 0);
}
//<! returns the number of elements
- size_type size() const {
+ size_type size() const
+ {
return d_size;
}
//<! See if given ComboAddress matches any prefix
- bool match(const ComboAddress& value) const {
+ bool match(const ComboAddress& value) const
+ {
return (lookup(value) != nullptr);
}
- bool match(const std::string& value) const {
+ bool match(const std::string& value) const
+ {
return match(ComboAddress(value));
}
//<! Clean out the tree
- void clear() {
+ void clear()
+ {
d_root.reset(new TreeNode());
d_left = nullptr;
d_size = 0;
}
private:
-
- [[nodiscard]] node_type* lookupImpl(const key_type& value, uint8_t max_bits) const {
- TreeNode *node = nullptr;
+ [[nodiscard]] node_type* lookupImpl(const key_type& value, uint8_t max_bits) const
+ {
+ TreeNode* node = nullptr;
if (value.isIPv4())
node = d_root->left.get();
node = d_root->right.get();
else
throw NetmaskException("invalid address family");
- if (node == nullptr) return nullptr;
+ if (node == nullptr)
+ return nullptr;
- node_type *ret = nullptr;
+ node_type* ret = nullptr;
int bits = 0;
- for(; bits < max_bits; bits++) {
- bool vall = value.getBit(-1-bits);
+ for (; bits < max_bits; bits++) {
+ bool vall = value.getBit(-1 - bits);
if (bits >= node->d_bits) {
// the end of the current node is reached; continue with the next
// (we keep track of last assigned node)
if (!node->right)
break;
node = node->right.get();
- } else {
+ }
+ else {
if (!node->left)
break;
node = node->left.get();
// the matching branch ends here
break;
}
- bool valr = node->node.first.getBit(-1-bits);
+ bool valr = node->node.first.getBit(-1 - bits);
if (vall != valr) {
// the branch matches just upto this point, yet continues in a different
// direction
}
unique_ptr<TreeNode> d_root; //<! Root of our tree
- TreeNode *d_left;
+ TreeNode* d_left;
size_type d_size;
};
//! If this IP address is matched by any of the classes within
- bool match(const ComboAddress *ip) const
+ bool match(const ComboAddress* ip) const
{
- const auto &ret = tree.lookup(*ip);
- if(ret) return ret->second;
+ const auto& ret = tree.lookup(*ip);
+ if (ret)
+ return ret->second;
return false;
}
bool lookup(const ComboAddress* ip, Netmask* nmp) const
{
- const auto &ret = tree.lookup(*ip);
+ const auto& ret = tree.lookup(*ip);
if (ret) {
if (nmp != nullptr)
*nmp = ret->first;
}
//! Add this string to the list of possible matches
- void addMask(const string &ip, bool positive=true)
+ void addMask(const string& ip, bool positive = true)
{
- if(!ip.empty() && ip[0] == '!') {
+ if (!ip.empty() && ip[0] == '!') {
addMask(Netmask(ip.substr(1)), false);
- } else {
+ }
+ else {
addMask(Netmask(ip), positive);
}
}
//! Add this Netmask to the list of possible matches
- void addMask(const Netmask& nm, bool positive=true)
+ void addMask(const Netmask& nm, bool positive = true)
{
- tree.insert(nm).second=positive;
+ tree.insert(nm).second = positive;
}
void addMasks(const NetmaskGroup& group, boost::optional<bool> positive)
string toString() const
{
ostringstream str;
- for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
- if(iter != tree.begin())
- str <<", ";
- if(!(iter->second))
- str<<"!";
- str<<iter->first.toString();
+ for (auto iter = tree.begin(); iter != tree.end(); ++iter) {
+ if (iter != tree.begin())
+ str << ", ";
+ if (!(iter->second))
+ str << "!";
+ str << iter->first.toString();
}
return str.str();
}
return out;
}
- void toMasks(const string &ips)
+ void toMasks(const string& ips)
{
vector<string> parts;
stringtok(parts, ips, ", \t");
struct SComboAddress
{
- SComboAddress(const ComboAddress& orig) : ca(orig) {}
+ SComboAddress(const ComboAddress& orig) :
+ ca(orig) {}
ComboAddress ca;
bool operator<(const SComboAddress& rhs) const
{
class NetworkError : public runtime_error
{
public:
- NetworkError(const string& why="Network Error") : runtime_error(why.c_str())
+ NetworkError(const string& why = "Network Error") :
+ runtime_error(why.c_str())
{}
- NetworkError(const char *why="Network Error") : runtime_error(why)
+ NetworkError(const char* why = "Network Error") :
+ runtime_error(why)
{}
};
class AddressAndPortRange
{
public:
- AddressAndPortRange(): d_addrMask(0), d_portMask(0)
+ AddressAndPortRange() :
+ d_addrMask(0), d_portMask(0)
{
d_addr.sin4.sin_family = 0; // disable this doing anything useful
d_addr.sin4.sin_port = 0; // this guarantees d_network compares identical
if (index < 16) {
/* we are into the port bits */
uint16_t port = d_addr.getPort();
- return ((port & (1U<<index)) != 0x0000);
+ return ((port & (1U << index)) != 0x0000);
}
index -= 16;
bool setReusePort(int sockfd);
#if defined(IP_PKTINFO)
- #define GEN_IP_PKTINFO IP_PKTINFO
+#define GEN_IP_PKTINFO IP_PKTINFO
#elif defined(IP_RECVDSTADDR)
- #define GEN_IP_PKTINFO IP_RECVDSTADDR
+#define GEN_IP_PKTINFO IP_RECVDSTADDR
#endif
bool IsAnyAddress(const ComboAddress& addr);