2 PowerDNS Versatile Database Driven Nameserver
3 Copyright (C) 2002 - 2016 PowerDNS.COM BV
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2
7 as published by the Free Software Foundation
9 Additionally, the license of this program contains a special
10 exception which allows to distribute the program in binary form when
11 it is linked against OpenSSL.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #ifndef PDNS_IPUTILSHH
23 #define PDNS_IPUTILSHH
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
33 #include "pdnsexception.hh"
35 #include <sys/socket.h>
38 #include <boost/tuple/tuple.hpp>
39 #include <boost/tuple/tuple_comparison.hpp>
41 #include "namespaces.hh"
44 #include <libkern/OSByteOrder.h>
46 #define htobe16(x) OSSwapHostToBigInt16(x)
47 #define htole16(x) OSSwapHostToLittleInt16(x)
48 #define be16toh(x) OSSwapBigToHostInt16(x)
49 #define le16toh(x) OSSwapLittleToHostInt16(x)
51 #define htobe32(x) OSSwapHostToBigInt32(x)
52 #define htole32(x) OSSwapHostToLittleInt32(x)
53 #define be32toh(x) OSSwapBigToHostInt32(x)
54 #define le32toh(x) OSSwapLittleToHostInt32(x)
56 #define htobe64(x) OSSwapHostToBigInt64(x)
57 #define htole64(x) OSSwapHostToLittleInt64(x)
58 #define be64toh(x) OSSwapBigToHostInt64(x)
59 #define le64toh(x) OSSwapLittleToHostInt64(x)
65 #define htobe16(x) BE_16(x)
66 #define htole16(x) LE_16(x)
67 #define be16toh(x) BE_IN16(x)
68 #define le16toh(x) LE_IN16(x)
70 #define htobe32(x) BE_32(x)
71 #define htole32(x) LE_32(x)
72 #define be32toh(x) BE_IN32(x)
73 #define le32toh(x) LE_IN32(x)
75 #define htobe64(x) BE_64(x)
76 #define htole64(x) LE_64(x)
77 #define be64toh(x) BE_IN64(x)
78 #define le64toh(x) LE_IN64(x)
83 #include <sys/endian.h>
87 struct sockaddr_in sin4;
88 struct sockaddr_in6 sin6;
90 bool operator==(const ComboAddress& rhs) const
92 if(boost::tie(sin4.sin_family, sin4.sin_port) != boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
94 if(sin4.sin_family == AF_INET)
95 return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
97 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0;
100 bool operator!=(const ComboAddress& rhs) const
102 return(!operator==(rhs));
105 bool operator<(const ComboAddress& rhs) const
107 if(sin4.sin_family == 0) {
110 if(boost::tie(sin4.sin_family, sin4.sin_port) < boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
112 if(boost::tie(sin4.sin_family, sin4.sin_port) > boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
115 if(sin4.sin_family == AF_INET)
116 return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
118 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0;
121 bool operator>(const ComboAddress& rhs) const
123 return rhs.operator<(*this);
126 struct addressOnlyHash
128 uint32_t operator()(const ComboAddress& ca) const
130 const unsigned char* start;
132 if(ca.sin4.sin_family == AF_INET) {
133 start =(const unsigned char*)&ca.sin4.sin_addr.s_addr;
137 start =(const unsigned char*)&ca.sin6.sin6_addr.s6_addr;
140 return burtle(start, len, 0);
144 struct addressOnlyLessThan: public std::binary_function<ComboAddress, ComboAddress, bool>
146 bool operator()(const ComboAddress& a, const ComboAddress& b) const
148 if(a.sin4.sin_family < b.sin4.sin_family)
150 if(a.sin4.sin_family > b.sin4.sin_family)
152 if(a.sin4.sin_family == AF_INET)
153 return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
155 return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
159 struct addressOnlyEqual: public std::binary_function<ComboAddress, ComboAddress, bool>
161 bool operator()(const ComboAddress& a, const ComboAddress& b) const
163 if(a.sin4.sin_family != b.sin4.sin_family)
165 if(a.sin4.sin_family == AF_INET)
166 return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
168 return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr));
173 socklen_t getSocklen() const
175 if(sin4.sin_family == AF_INET)
183 sin4.sin_family=AF_INET;
184 sin4.sin_addr.s_addr=0;
188 ComboAddress(const struct sockaddr *sa, socklen_t salen) {
189 setSockaddr(sa, salen);
192 ComboAddress(const struct sockaddr_in6 *sa) {
193 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6));
196 ComboAddress(const struct sockaddr_in *sa) {
197 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in));
200 void setSockaddr(const struct sockaddr *sa, socklen_t salen) {
201 if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
202 memcpy(this, sa, salen);
205 // 'port' sets a default value in case 'str' does not set a port
206 explicit ComboAddress(const string& str, uint16_t port=0)
208 memset(&sin6, 0, sizeof(sin6));
209 sin4.sin_family = AF_INET;
211 if(makeIPv4sockaddr(str, &sin4)) {
212 sin6.sin6_family = AF_INET6;
213 if(makeIPv6sockaddr(str, &sin6) < 0)
214 throw PDNSException("Unable to convert presentation address '"+ str +"'");
217 if(!sin4.sin_port) // 'str' overrides port!
218 sin4.sin_port=htons(port);
221 bool isMappedIPv4() const
223 if(sin4.sin_family!=AF_INET6)
227 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
228 for(n=0; n < 10; ++n)
239 ComboAddress mapToIPv4() const
242 throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
244 ret.sin4.sin_family=AF_INET;
245 ret.sin4.sin_port=sin4.sin_port;
247 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
248 ptr+=(sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr));
249 memcpy(&ret.sin4.sin_addr.s_addr, ptr, sizeof(ret.sin4.sin_addr.s_addr));
253 string toString() const
256 if(sin4.sin_family && !getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST))
262 string toStringWithPort() const
264 if(sin4.sin_family==AF_INET)
265 return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
267 return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
270 void truncate(unsigned int bits);
273 /** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
274 class NetmaskException: public PDNSException
277 NetmaskException(const string &a) : PDNSException(a) {}
280 inline ComboAddress makeComboAddress(const string& str)
282 ComboAddress address;
283 address.sin4.sin_family=AF_INET;
284 if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
285 address.sin4.sin_family=AF_INET6;
286 if(makeIPv6sockaddr(str, &address.sin6) < 0)
287 throw NetmaskException("Unable to convert '"+str+"' to a netmask");
292 /** This class represents a netmask and can be queried to see if a certain
293 IP address is matched by this mask */
299 d_network.sin4.sin_family=0; // disable this doing anything useful
300 d_network.sin4.sin_port = 0; // this guarantees d_network compares identical
305 Netmask(const ComboAddress& network, uint8_t bits=0xff)
310 bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
314 d_mask=~(0xFFFFFFFF>>d_bits);
316 d_mask=0xFFFFFFFF; // not actually used for IPv6
319 //! Constructor supplies the mask, which cannot be changed
320 Netmask(const string &mask)
322 pair<string,string> split=splitField(mask,'/');
323 d_network=makeComboAddress(split.first);
325 if(!split.second.empty()) {
326 d_bits = (uint8_t)pdns_stou(split.second);
328 d_mask=~(0xFFFFFFFF>>d_bits);
332 else if(d_network.sin4.sin_family==AF_INET) {
338 d_mask=0; // silence silly warning - d_mask is unused for IPv6
342 bool match(const ComboAddress& ip) const
347 //! If this IP address in socket address matches
348 bool match(const ComboAddress *ip) const
350 if(d_network.sin4.sin_family != ip->sin4.sin_family) {
353 if(d_network.sin4.sin_family == AF_INET) {
354 return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr));
356 if(d_network.sin6.sin6_family == AF_INET6) {
357 uint8_t bytes=d_bits/8, n;
358 const uint8_t *us=(const uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
359 const uint8_t *them=(const uint8_t*) &ip->sin6.sin6_addr.s6_addr;
361 for(n=0; n < bytes; ++n) {
366 // still here, now match remaining bits
367 uint8_t bits= d_bits % 8;
368 uint8_t mask= (uint8_t) ~(0xFF>>bits);
370 return((us[n] & mask) == (them[n] & mask));
375 //! If this ASCII IP address matches
376 bool match(const string &ip) const
378 ComboAddress address=makeComboAddress(ip);
379 return match(&address);
382 //! If this IP address in native format matches
383 bool match4(uint32_t ip) const
385 return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
388 string toString() const
390 return d_network.toString()+"/"+std::to_string((unsigned int)d_bits);
393 string toStringNoMask() const
395 return d_network.toString();
397 const ComboAddress& getNetwork() const
401 const ComboAddress getMaskedNetwork() const
403 ComboAddress result(d_network);
405 result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask);
409 uint8_t bytes=d_bits/8;
410 uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr;
411 uint8_t bits= d_bits % 8;
412 uint8_t mask= (uint8_t) ~(0xFF>>bits);
414 if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) {
418 for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) {
430 return d_network.sin6.sin6_family == AF_INET6;
434 return d_network.sin4.sin_family == AF_INET;
437 bool operator<(const Netmask& rhs) const
439 return tie(d_network, d_bits) < tie(rhs.d_network, rhs.d_bits);
442 bool operator==(const Netmask& rhs) const
444 return tie(d_network, d_bits) == tie(rhs.d_network, rhs.d_bits);
449 return d_network.sin4.sin_family==0;
453 ComboAddress d_network;
458 /** Per-bit binary tree map implementation with <Netmask,T> pair.
460 * This is an binary tree implementation for storing attributes for IPv4 and IPv6 prefixes.
461 * The most simple use case is simple NetmaskTree<bool> used by NetmaskGroup, which only
462 * wants to know if given IP address is matched in the prefixes stored.
464 * This element is useful for anything that needs to *STORE* prefixes, and *MATCH* IP addresses
465 * to a *LIST* of *PREFIXES*. Not the other way round.
467 * You can store IPv4 and IPv6 addresses to same tree, separate payload storage is kept per AFI.
469 * To erase something copy values to new tree sans the value you want to erase.
471 * Use swap if you need to move the tree to another NetmaskTree instance, it is WAY faster
472 * than using copy ctor or assigment operator, since it moves the nodes and tree root to
473 * new home instead of actually recreating the tree.
475 * Please see NetmaskGroup for example of simple use case. Other usecases can be found
476 * from GeoIPBackend and Sortlist, and from dnsdist.
478 template <typename T>
481 typedef Netmask key_type;
482 typedef T value_type;
483 typedef std::pair<key_type,value_type> node_type;
484 typedef size_t size_type;
487 /** Single node in tree, internal use only.
489 class TreeNode : boost::noncopyable {
491 explicit TreeNode(int bits) noexcept : parent(NULL),d_bits(bits) {
494 //<! Makes a left node with one more bit than parent
495 TreeNode* make_left() {
497 left = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
503 //<! Makes a right node with one more bit than parent
504 TreeNode* make_right() {
506 right = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
507 right->parent = this;
512 unique_ptr<TreeNode> left;
513 unique_ptr<TreeNode> right;
516 unique_ptr<node_type> node4; //<! IPv4 value-pair
517 unique_ptr<node_type> node6; //<! IPv6 value-pair
519 int d_bits; //<! How many bits have been used so far
523 NetmaskTree() noexcept {
526 NetmaskTree(const NetmaskTree& rhs) {
527 // it is easier to copy the nodes than tree.
528 // also acts as handy compactor
529 for(auto const& node: rhs._nodes)
530 insert(node->first).second = node->second;
533 NetmaskTree& operator=(const NetmaskTree& rhs) {
536 for(auto const& node: rhs._nodes)
537 insert(node->first).second = node->second;
541 const typename std::vector<node_type*>::const_iterator begin() const { return _nodes.begin(); }
542 const typename std::vector<node_type*>::const_iterator end() const { return _nodes.end(); }
544 typename std::vector<node_type*>::iterator begin() { return _nodes.begin(); }
545 typename std::vector<node_type*>::iterator end() { return _nodes.end(); }
547 node_type& insert(const string &mask) {
548 return insert(key_type(mask));
551 //<! Creates new value-pair in tree and returns it.
552 node_type& insert(const key_type& key) {
553 // lazily initialize tree on first insert.
554 if (!root) root = unique_ptr<TreeNode>(new TreeNode(0));
555 TreeNode* node = root.get();
556 node_type* value = nullptr;
558 if (key.getNetwork().sin4.sin_family == AF_INET) {
559 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
561 // we turn left on 0 and right on 1
562 while(bits < key.getBits()) {
563 uint8_t val = addr[31-bits];
565 node = node->make_right();
567 node = node->make_left();
570 // only create node if not yet assigned
572 node->node4 = unique_ptr<node_type>(new node_type());
573 _nodes.push_back(node->node4.get());
575 value = node->node4.get();
577 uint64_t* addr = (uint64_t*)key.getNetwork().sin6.sin6_addr.s6_addr;
578 std::bitset<64> addr_low(be64toh(addr[1]));
579 std::bitset<64> addr_high(be64toh(addr[0]));
581 while(bits < key.getBits()) {
583 // we use high address until we are
584 if (bits < 64) val = addr_high[63-bits];
585 // past 64 bits, and start using low address
586 else val = addr_low[127-bits];
588 // we turn left on 0 and right on 1
590 node = node->make_right();
592 node = node->make_left();
595 // only create node if not yet assigned
597 node->node6 = unique_ptr<node_type>(new node_type());
598 _nodes.push_back(node->node6.get());
600 value = node->node6.get();
607 //<! Creates or updates value
608 void insert_or_assign(const key_type& mask, const value_type& value) {
609 insert(mask).second = value;
612 void insert_or_assign(const string& mask, const value_type& value) {
613 insert(key_type(mask)).second = value;
616 //<! check if given key is present in TreeMap
617 bool has_key(const key_type& key) const {
618 const node_type *ptr = lookup(key);
619 return ptr && ptr->first == key;
622 //<! Returns "best match" for key_type, which might not be value
623 const node_type* lookup(const key_type& value) const {
624 return lookup(value.getNetwork(), value.getBits());
627 //<! Perform best match lookup for value, using at most max_bits
628 const node_type* lookup(const ComboAddress& value, int max_bits = 128) const {
629 if (!root) return nullptr;
631 TreeNode *node = root.get();
632 node_type *ret = nullptr;
634 // exact same thing as above, except
635 if (value.sin4.sin_family == AF_INET) {
636 max_bits = std::max(0,std::min(max_bits,32));
637 std::bitset<32> addr(be32toh(value.sin4.sin_addr.s_addr));
640 while(bits < max_bits) {
641 // ...we keep track of last non-empty node
642 if (node->node4) ret = node->node4.get();
643 uint8_t val = addr[31-bits];
644 // ...and we don't create left/right hand
646 if (node->right) node = node->right.get();
647 // ..and we break when road ends
650 if (node->left) node = node->left.get();
655 // needed if we did not find one in loop
656 if (node->node4) ret = node->node4.get();
658 uint64_t* addr = (uint64_t*)value.sin6.sin6_addr.s6_addr;
659 max_bits = std::max(0,std::min(max_bits,128));
660 std::bitset<64> addr_low(be64toh(addr[1]));
661 std::bitset<64> addr_high(be64toh(addr[0]));
663 while(bits < max_bits) {
664 if (node->node6) ret = node->node6.get();
666 if (bits < 64) val = addr_high[63-bits];
667 else val = addr_low[127-bits];
669 if (node->right) node = node->right.get();
672 if (node->left) node = node->left.get();
677 if (node->node6) ret = node->node6.get();
680 // this can be nullptr.
684 //<! Removes key from TreeMap. This does not clean up the tree.
685 void erase(const key_type& key) {
686 TreeNode *node = root.get();
689 if ( node == nullptr ) return;
691 // exact same thing as above, except
692 if (key.getNetwork().sin4.sin_family == AF_INET) {
693 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
695 while(node && bits < key.getBits()) {
696 uint8_t val = addr[31-bits];
698 node = node->right.get();
700 node = node->left.get();
705 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
706 if (node->node4.get() == *it) _nodes.erase(it);
710 uint64_t* addr = (uint64_t*)key.getNetwork().sin6.sin6_addr.s6_addr;
711 std::bitset<64> addr_low(be64toh(addr[1]));
712 std::bitset<64> addr_high(be64toh(addr[0]));
714 while(node && bits < key.getBits()) {
716 if (bits < 64) val = addr_high[63-bits];
717 else val = addr_low[127-bits];
719 node = node->right.get();
721 node = node->left.get();
726 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
727 if (node->node6.get() == *it) _nodes.erase(it);
733 void erase(const string& key) {
734 erase(key_type(key));
737 //<! checks whether the container is empty.
739 return _nodes.empty();
742 //<! returns the number of elements
743 size_type size() const {
744 return _nodes.size();
747 //<! See if given ComboAddress matches any prefix
748 bool match(const ComboAddress& value) const {
749 return (lookup(value) != nullptr);
752 bool match(const std::string& value) const {
753 return match(ComboAddress(value));
756 //<! Clean out the tree
762 //<! swaps the contents, rhs is left with nullptr.
763 void swap(NetmaskTree& rhs) {
765 _nodes.swap(rhs._nodes);
769 unique_ptr<TreeNode> root; //<! Root of our tree
770 std::vector<node_type*> _nodes; //<! Container for actual values
773 /** This class represents a group of supplemental Netmask classes. An IP address matchs
774 if it is matched by zero or more of the Netmask classes within.
779 //! If this IP address is matched by any of the classes within
781 bool match(const ComboAddress *ip) const
783 return tree.match(*ip);
786 bool match(const ComboAddress& ip) const
791 //! Add this string to the list of possible matches
792 void addMask(const string &ip)
794 addMask(Netmask(ip));
797 //! Add this Netmask to the list of possible matches
798 void addMask(const Netmask& nm)
818 string toString() const
821 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
822 if(iter != tree.begin())
824 str<<(*iter)->first.toString();
829 void toStringVector(vector<string>* vec) const
831 for(auto iter = tree.begin(); iter != tree.end(); ++iter)
832 vec->push_back((*iter)->first.toString());
835 void toMasks(const string &ips)
837 vector<string> parts;
838 stringtok(parts, ips, ", \t");
840 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter)
845 NetmaskTree<bool> tree;
851 SComboAddress(const ComboAddress& orig) : ca(orig) {}
853 bool operator<(const SComboAddress& rhs) const
855 return ComboAddress::addressOnlyLessThan()(ca, rhs.ca);
857 operator const ComboAddress&()
864 int SSocket(int family, int type, int flags);
865 int SConnect(int sockfd, const ComboAddress& remote);
866 int SBind(int sockfd, const ComboAddress& local);
867 int SAccept(int sockfd, ComboAddress& remote);
868 int SListen(int sockfd, int limit);
869 int SSetsockopt(int sockfd, int level, int opname, int value);
871 #if defined(IP_PKTINFO)
872 #define GEN_IP_PKTINFO IP_PKTINFO
873 #elif defined(IP_RECVDSTADDR)
874 #define GEN_IP_PKTINFO IP_RECVDSTADDR
876 bool IsAnyAddress(const ComboAddress& addr);
877 bool HarvestDestinationAddress(struct msghdr* msgh, ComboAddress* destination);
878 bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv);
879 void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr);
880 ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to);
881 ssize_t sendMsgWithTimeout(int fd, const char* buffer, size_t len, int timeout, ComboAddress& dest, const ComboAddress& local, unsigned int localItf);
885 extern template class NetmaskTree<bool>;