]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/iputils.hh
spelling: arise
[thirdparty/pdns.git] / pdns / iputils.hh
CommitLineData
12c86877 1/*
12471842
PL
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
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.
17 *
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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
12c86877
BH
22#ifndef PDNS_IPUTILSHH
23#define PDNS_IPUTILSHH
24
25#include <string>
092f210a
BH
26#include <sys/socket.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
12c86877
BH
29#include <iostream>
30#include <stdio.h>
31#include <functional>
44845aab 32#include <bitset>
5c409fa2 33#include "pdnsexception.hh"
809fe23f 34#include "misc.hh"
506a9050
BH
35#include <sys/socket.h>
36#include <netdb.h>
335da0ba 37#include <sstream>
fd4ed0ab
BH
38#include <boost/tuple/tuple.hpp>
39#include <boost/tuple/tuple_comparison.hpp>
40
10f4eea8 41#include "namespaces.hh"
12c86877 42
323c477a
PD
43#ifdef __APPLE__
44#include <libkern/OSByteOrder.h>
45
46#define htobe16(x) OSSwapHostToBigInt16(x)
47#define htole16(x) OSSwapHostToLittleInt16(x)
48#define be16toh(x) OSSwapBigToHostInt16(x)
49#define le16toh(x) OSSwapLittleToHostInt16(x)
50
51#define htobe32(x) OSSwapHostToBigInt32(x)
52#define htole32(x) OSSwapHostToLittleInt32(x)
53#define be32toh(x) OSSwapBigToHostInt32(x)
54#define le32toh(x) OSSwapLittleToHostInt32(x)
55
56#define htobe64(x) OSSwapHostToBigInt64(x)
57#define htole64(x) OSSwapHostToLittleInt64(x)
58#define be64toh(x) OSSwapBigToHostInt64(x)
59#define le64toh(x) OSSwapLittleToHostInt64(x)
60#endif
61
28fe507d 62#ifdef __sun
b0228347
AT
63
64#define htobe16(x) BE_16(x)
65#define htole16(x) LE_16(x)
28fe507d
RD
66#define be16toh(x) BE_IN16(&(x))
67#define le16toh(x) LE_IN16(&(x))
b0228347
AT
68
69#define htobe32(x) BE_32(x)
70#define htole32(x) LE_32(x)
28fe507d
RD
71#define be32toh(x) BE_IN32(&(x))
72#define le32toh(x) LE_IN32(&(x))
b0228347
AT
73
74#define htobe64(x) BE_64(x)
75#define htole64(x) LE_64(x)
28fe507d
RD
76#define be64toh(x) BE_IN64(&(x))
77#define le64toh(x) LE_IN64(&(x))
b0228347
AT
78
79#endif
80
e95bd1ae
RK
81#ifdef __FreeBSD__
82#include <sys/endian.h>
83#endif
84
37d3f960
BH
85union ComboAddress {
86 struct sockaddr_in sin4;
87 struct sockaddr_in6 sin6;
88
fd4ed0ab
BH
89 bool operator==(const ComboAddress& rhs) const
90 {
91 if(boost::tie(sin4.sin_family, sin4.sin_port) != boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
92 return false;
93 if(sin4.sin_family == AF_INET)
94 return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
95 else
a683e8bd 96 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0;
fd4ed0ab
BH
97 }
98
bb6f86bd
PL
99 bool operator!=(const ComboAddress& rhs) const
100 {
101 return(!operator==(rhs));
102 }
103
37d3f960
BH
104 bool operator<(const ComboAddress& rhs) const
105 {
f563fff4 106 if(sin4.sin_family == 0) {
107 return false;
108 }
fd4ed0ab 109 if(boost::tie(sin4.sin_family, sin4.sin_port) < boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960 110 return true;
fd4ed0ab 111 if(boost::tie(sin4.sin_family, sin4.sin_port) > boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960
BH
112 return false;
113
114 if(sin4.sin_family == AF_INET)
115 return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
116 else
a683e8bd 117 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0;
37d3f960
BH
118 }
119
fd4ed0ab
BH
120 bool operator>(const ComboAddress& rhs) const
121 {
5f15ee47 122 return rhs.operator<(*this);
fd4ed0ab
BH
123 }
124
545725f2 125 struct addressOnlyHash
126 {
127 uint32_t operator()(const ComboAddress& ca) const
128 {
129 const unsigned char* start;
130 int len;
131 if(ca.sin4.sin_family == AF_INET) {
132 start =(const unsigned char*)&ca.sin4.sin_addr.s_addr;
133 len=4;
134 }
135 else {
136 start =(const unsigned char*)&ca.sin6.sin6_addr.s6_addr;
137 len=16;
138 }
139 return burtle(start, len, 0);
140 }
141 };
142
662d5441 143 struct addressOnlyLessThan: public std::binary_function<ComboAddress, ComboAddress, bool>
11a7242f
BH
144 {
145 bool operator()(const ComboAddress& a, const ComboAddress& b) const
146 {
147 if(a.sin4.sin_family < b.sin4.sin_family)
4957a608 148 return true;
11a7242f 149 if(a.sin4.sin_family > b.sin4.sin_family)
4957a608 150 return false;
11a7242f 151 if(a.sin4.sin_family == AF_INET)
4957a608 152 return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
11a7242f 153 else
a683e8bd 154 return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
11a7242f
BH
155 }
156 };
fd4ed0ab 157
0940e4eb 158 struct addressOnlyEqual: public std::binary_function<ComboAddress, ComboAddress, bool>
159 {
160 bool operator()(const ComboAddress& a, const ComboAddress& b) const
161 {
162 if(a.sin4.sin_family != b.sin4.sin_family)
163 return false;
164 if(a.sin4.sin_family == AF_INET)
165 return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
166 else
a683e8bd 167 return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr));
0940e4eb 168 }
169 };
170
171
fd4ed0ab 172 socklen_t getSocklen() const
a9af3782
BH
173 {
174 if(sin4.sin_family == AF_INET)
175 return sizeof(sin4);
176 else
177 return sizeof(sin6);
178 }
fd4ed0ab
BH
179
180 ComboAddress()
181 {
182 sin4.sin_family=AF_INET;
183 sin4.sin_addr.s_addr=0;
184 sin4.sin_port=0;
185 }
186
a7360cd9
AT
187 ComboAddress(const struct sockaddr *sa, socklen_t salen) {
188 setSockaddr(sa, salen);
189 };
190
191 ComboAddress(const struct sockaddr_in6 *sa) {
192 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6));
193 };
194
195 ComboAddress(const struct sockaddr_in *sa) {
196 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in));
197 };
198
199 void setSockaddr(const struct sockaddr *sa, socklen_t salen) {
200 if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
201 memcpy(this, sa, salen);
202 }
203
85db02c5 204 // 'port' sets a default value in case 'str' does not set a port
fd4ed0ab
BH
205 explicit ComboAddress(const string& str, uint16_t port=0)
206 {
207 memset(&sin6, 0, sizeof(sin6));
208 sin4.sin_family = AF_INET;
85db02c5
BH
209 sin4.sin_port = 0;
210 if(makeIPv4sockaddr(str, &sin4)) {
fd4ed0ab 211 sin6.sin6_family = AF_INET6;
f71bc087 212 if(makeIPv6sockaddr(str, &sin6) < 0)
3f81d239 213 throw PDNSException("Unable to convert presentation address '"+ str +"'");
b03c5a46 214
fd4ed0ab 215 }
85db02c5
BH
216 if(!sin4.sin_port) // 'str' overrides port!
217 sin4.sin_port=htons(port);
fd4ed0ab 218 }
a9af3782 219
a94673ea
RG
220 bool isIPv6() const
221 {
222 return sin4.sin_family == AF_INET6;
223 }
224 bool isIPv4() const
225 {
226 return sin4.sin_family == AF_INET;
227 }
228
eb5bae86 229 bool isMappedIPv4() const
2914b022
BH
230 {
231 if(sin4.sin_family!=AF_INET6)
232 return false;
233
234 int n=0;
235 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
236 for(n=0; n < 10; ++n)
237 if(ptr[n])
4957a608 238 return false;
2914b022
BH
239
240 for(; n < 12; ++n)
241 if(ptr[n]!=0xff)
4957a608 242 return false;
2914b022
BH
243
244 return true;
245 }
246
eb5bae86 247 ComboAddress mapToIPv4() const
2914b022
BH
248 {
249 if(!isMappedIPv4())
3f81d239 250 throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
2914b022
BH
251 ComboAddress ret;
252 ret.sin4.sin_family=AF_INET;
11a7242f 253 ret.sin4.sin_port=sin4.sin_port;
2914b022
BH
254
255 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
a683e8bd
RG
256 ptr+=(sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr));
257 memcpy(&ret.sin4.sin_addr.s_addr, ptr, sizeof(ret.sin4.sin_addr.s_addr));
2914b022
BH
258 return ret;
259 }
260
37d3f960
BH
261 string toString() const
262 {
506a9050 263 char host[1024];
c44d3917 264 if(sin4.sin_family && !getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST))
265 return host;
266 else
267 return "invalid";
37d3f960 268 }
b8c3ea84
BH
269
270 string toStringWithPort() const
271 {
272 if(sin4.sin_family==AF_INET)
335da0ba 273 return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 274 else
335da0ba 275 return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 276 }
22779196 277
5b6099b2 278 void truncate(unsigned int bits) noexcept;
37d3f960
BH
279};
280
12c86877 281/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
3f81d239 282class NetmaskException: public PDNSException
12c86877
BH
283{
284public:
3f81d239 285 NetmaskException(const string &a) : PDNSException(a) {}
12c86877
BH
286};
287
37d3f960
BH
288inline ComboAddress makeComboAddress(const string& str)
289{
290 ComboAddress address;
291 address.sin4.sin_family=AF_INET;
1e77c17c 292 if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
37d3f960 293 address.sin4.sin_family=AF_INET6;
f71bc087 294 if(makeIPv6sockaddr(str, &address.sin6) < 0)
4957a608 295 throw NetmaskException("Unable to convert '"+str+"' to a netmask");
37d3f960
BH
296 }
297 return address;
298}
299
12c86877
BH
300/** This class represents a netmask and can be queried to see if a certain
301 IP address is matched by this mask */
12c86877
BH
302class Netmask
303{
304public:
6f97329b
BH
305 Netmask()
306 {
307 d_network.sin4.sin_family=0; // disable this doing anything useful
f563fff4 308 d_network.sin4.sin_port = 0; // this guarantees d_network compares identical
2fd2d93c
AT
309 d_mask=0;
310 d_bits=0;
6f97329b
BH
311 }
312
a4c8835f 313 Netmask(const ComboAddress& network, uint8_t bits=0xff)
6f97329b
BH
314 {
315 d_network = network;
a4c8835f 316
e1c8a4bb 317 if(bits > 128)
a4c8835f
BH
318 bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
319
6f97329b
BH
320 d_bits = bits;
321 if(d_bits<32)
322 d_mask=~(0xFFFFFFFF>>d_bits);
323 else
324 d_mask=0xFFFFFFFF; // not actually used for IPv6
325 }
326
12c86877
BH
327 //! Constructor supplies the mask, which cannot be changed
328 Netmask(const string &mask)
329 {
37d3f960
BH
330 pair<string,string> split=splitField(mask,'/');
331 d_network=makeComboAddress(split.first);
332
333 if(!split.second.empty()) {
a683e8bd 334 d_bits = (uint8_t)pdns_stou(split.second);
37d3f960 335 if(d_bits<32)
4957a608 336 d_mask=~(0xFFFFFFFF>>d_bits);
8519b8a2 337 else
4957a608 338 d_mask=0xFFFFFFFF;
37d3f960
BH
339 }
340 else if(d_network.sin4.sin_family==AF_INET) {
341 d_bits = 32;
342 d_mask = 0xFFFFFFFF;
343 }
5c1def57 344 else {
37d3f960 345 d_bits=128;
5c1def57
BH
346 d_mask=0; // silence silly warning - d_mask is unused for IPv6
347 }
12c86877
BH
348 }
349
2914b022
BH
350 bool match(const ComboAddress& ip) const
351 {
352 return match(&ip);
353 }
354
12c86877 355 //! If this IP address in socket address matches
37d3f960 356 bool match(const ComboAddress *ip) const
12c86877 357 {
37d3f960
BH
358 if(d_network.sin4.sin_family != ip->sin4.sin_family) {
359 return false;
360 }
361 if(d_network.sin4.sin_family == AF_INET) {
362 return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr));
363 }
364 if(d_network.sin6.sin6_family == AF_INET6) {
365 uint8_t bytes=d_bits/8, n;
366 const uint8_t *us=(const uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
367 const uint8_t *them=(const uint8_t*) &ip->sin6.sin6_addr.s6_addr;
368
369 for(n=0; n < bytes; ++n) {
4957a608
BH
370 if(us[n]!=them[n]) {
371 return false;
372 }
37d3f960
BH
373 }
374 // still here, now match remaining bits
f0739fb6 375 uint8_t bits= d_bits % 8;
a683e8bd 376 uint8_t mask= (uint8_t) ~(0xFF>>bits);
f0739fb6 377
37d3f960
BH
378 return((us[n] & mask) == (them[n] & mask));
379 }
380 return false;
12c86877
BH
381 }
382
383 //! If this ASCII IP address matches
384 bool match(const string &ip) const
385 {
37d3f960
BH
386 ComboAddress address=makeComboAddress(ip);
387 return match(&address);
12c86877
BH
388 }
389
390 //! If this IP address in native format matches
37d3f960 391 bool match4(uint32_t ip) const
12c86877 392 {
37d3f960 393 return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
12c86877
BH
394 }
395
2c95fc65
BH
396 string toString() const
397 {
335da0ba 398 return d_network.toString()+"/"+std::to_string((unsigned int)d_bits);
2c95fc65
BH
399 }
400
a4c8835f
BH
401 string toStringNoMask() const
402 {
403 return d_network.toString();
404 }
9f84a557 405 const ComboAddress& getNetwork() const
a4c8835f
BH
406 {
407 return d_network;
408 }
e1c8a4bb
RG
409 const ComboAddress getMaskedNetwork() const
410 {
411 ComboAddress result(d_network);
412 if(isIpv4()) {
413 result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask);
414 }
415 else if(isIpv6()) {
416 size_t idx;
417 uint8_t bytes=d_bits/8;
418 uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr;
419 uint8_t bits= d_bits % 8;
420 uint8_t mask= (uint8_t) ~(0xFF>>bits);
421
422 if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) {
423 us[bytes] &= mask;
424 }
425
426 for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) {
427 us[idx] = 0;
428 }
429 }
430 return result;
431 }
a4c8835f
BH
432 int getBits() const
433 {
434 return d_bits;
435 }
709ca59f
AT
436 bool isIpv6() const
437 {
438 return d_network.sin6.sin6_family == AF_INET6;
439 }
440 bool isIpv4() const
441 {
442 return d_network.sin4.sin_family == AF_INET;
443 }
644dd1da 444
445 bool operator<(const Netmask& rhs) const
446 {
447 return tie(d_network, d_bits) < tie(rhs.d_network, rhs.d_bits);
448 }
39ec5d29 449
450 bool operator==(const Netmask& rhs) const
451 {
452 return tie(d_network, d_bits) == tie(rhs.d_network, rhs.d_bits);
453 }
454
87e665b1 455 bool empty() const
456 {
457 return d_network.sin4.sin_family==0;
458 }
459
12c86877 460private:
37d3f960 461 ComboAddress d_network;
092f210a 462 uint32_t d_mask;
37d3f960 463 uint8_t d_bits;
12c86877
BH
464};
465
44845aab
AT
466/** Per-bit binary tree map implementation with <Netmask,T> pair.
467 *
468 * This is an binary tree implementation for storing attributes for IPv4 and IPv6 prefixes.
469 * The most simple use case is simple NetmaskTree<bool> used by NetmaskGroup, which only
470 * wants to know if given IP address is matched in the prefixes stored.
471 *
472 * This element is useful for anything that needs to *STORE* prefixes, and *MATCH* IP addresses
473 * to a *LIST* of *PREFIXES*. Not the other way round.
474 *
475 * You can store IPv4 and IPv6 addresses to same tree, separate payload storage is kept per AFI.
476 *
477 * To erase something copy values to new tree sans the value you want to erase.
478 *
479 * Use swap if you need to move the tree to another NetmaskTree instance, it is WAY faster
480 * than using copy ctor or assigment operator, since it moves the nodes and tree root to
481 * new home instead of actually recreating the tree.
482 *
483 * Please see NetmaskGroup for example of simple use case. Other usecases can be found
484 * from GeoIPBackend and Sortlist, and from dnsdist.
485 */
486template <typename T>
487class NetmaskTree {
488public:
489 typedef Netmask key_type;
490 typedef T value_type;
491 typedef std::pair<key_type,value_type> node_type;
492 typedef size_t size_type;
493
494private:
495 /** Single node in tree, internal use only.
496 */
497 class TreeNode : boost::noncopyable {
498 public:
499 explicit TreeNode(int bits) noexcept : parent(NULL),d_bits(bits) {
500 }
501
502 //<! Makes a left node with one more bit than parent
503 TreeNode* make_left() {
504 if (!left) {
505 left = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
506 left->parent = this;
507 }
508 return left.get();
509 }
510
511 //<! Makes a right node with one more bit than parent
512 TreeNode* make_right() {
513 if (!right) {
514 right = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
515 right->parent = this;
516 }
517 return right.get();
518 }
519
520 unique_ptr<TreeNode> left;
521 unique_ptr<TreeNode> right;
522 TreeNode* parent;
523
524 unique_ptr<node_type> node4; //<! IPv4 value-pair
525 unique_ptr<node_type> node6; //<! IPv6 value-pair
526
527 int d_bits; //<! How many bits have been used so far
528 };
529
530public:
531 NetmaskTree() noexcept {
532 }
533
534 NetmaskTree(const NetmaskTree& rhs) {
535 // it is easier to copy the nodes than tree.
536 // also acts as handy compactor
537 for(auto const& node: rhs._nodes)
538 insert(node->first).second = node->second;
539 }
540
541 NetmaskTree& operator=(const NetmaskTree& rhs) {
542 clear();
543 // see above.
544 for(auto const& node: rhs._nodes)
545 insert(node->first).second = node->second;
546 return *this;
547 }
548
44845aab
AT
549 const typename std::vector<node_type*>::const_iterator begin() const { return _nodes.begin(); }
550 const typename std::vector<node_type*>::const_iterator end() const { return _nodes.end(); }
551
552 typename std::vector<node_type*>::iterator begin() { return _nodes.begin(); }
553 typename std::vector<node_type*>::iterator end() { return _nodes.end(); }
554
555 node_type& insert(const string &mask) {
556 return insert(key_type(mask));
557 }
558
559 //<! Creates new value-pair in tree and returns it.
560 node_type& insert(const key_type& key) {
561 // lazily initialize tree on first insert.
562 if (!root) root = unique_ptr<TreeNode>(new TreeNode(0));
563 TreeNode* node = root.get();
564 node_type* value = nullptr;
565
566 if (key.getNetwork().sin4.sin_family == AF_INET) {
567 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
568 int bits = 0;
569 // we turn left on 0 and right on 1
570 while(bits < key.getBits()) {
571 uint8_t val = addr[31-bits];
572 if (val)
573 node = node->make_right();
574 else
575 node = node->make_left();
576 bits++;
577 }
578 // only create node if not yet assigned
579 if (!node->node4) {
580 node->node4 = unique_ptr<node_type>(new node_type());
581 _nodes.push_back(node->node4.get());
582 }
583 value = node->node4.get();
584 } else {
585 uint64_t* addr = (uint64_t*)key.getNetwork().sin6.sin6_addr.s6_addr;
586 std::bitset<64> addr_low(be64toh(addr[1]));
587 std::bitset<64> addr_high(be64toh(addr[0]));
588 int bits = 0;
589 while(bits < key.getBits()) {
590 uint8_t val;
591 // we use high address until we are
592 if (bits < 64) val = addr_high[63-bits];
593 // past 64 bits, and start using low address
594 else val = addr_low[127-bits];
595
596 // we turn left on 0 and right on 1
597 if (val)
598 node = node->make_right();
599 else
600 node = node->make_left();
601 bits++;
602 }
603 // only create node if not yet assigned
604 if (!node->node6) {
605 node->node6 = unique_ptr<node_type>(new node_type());
606 _nodes.push_back(node->node6.get());
607 }
608 value = node->node6.get();
609 }
610 // assign key
611 value->first = key;
612 return *value;
613 }
614
2dfbbc41 615 //<! Creates or updates value
44845aab
AT
616 void insert_or_assign(const key_type& mask, const value_type& value) {
617 insert(mask).second = value;
618 }
619
e6419866
AT
620 void insert_or_assign(const string& mask, const value_type& value) {
621 insert(key_type(mask)).second = value;
44845aab
AT
622 }
623
41d0adb7
AT
624 //<! check if given key is present in TreeMap
625 bool has_key(const key_type& key) const {
626 const node_type *ptr = lookup(key);
627 return ptr && ptr->first == key;
628 }
629
2dfbbc41 630 //<! Returns "best match" for key_type, which might not be value
44845aab
AT
631 const node_type* lookup(const key_type& value) const {
632 return lookup(value.getNetwork(), value.getBits());
633 }
634
2dfbbc41 635 //<! Perform best match lookup for value, using at most max_bits
44845aab
AT
636 const node_type* lookup(const ComboAddress& value, int max_bits = 128) const {
637 if (!root) return nullptr;
638
639 TreeNode *node = root.get();
640 node_type *ret = nullptr;
641
642 // exact same thing as above, except
643 if (value.sin4.sin_family == AF_INET) {
644 max_bits = std::max(0,std::min(max_bits,32));
645 std::bitset<32> addr(be32toh(value.sin4.sin_addr.s_addr));
646 int bits = 0;
647
648 while(bits < max_bits) {
649 // ...we keep track of last non-empty node
650 if (node->node4) ret = node->node4.get();
651 uint8_t val = addr[31-bits];
652 // ...and we don't create left/right hand
653 if (val) {
654 if (node->right) node = node->right.get();
655 // ..and we break when road ends
656 else break;
657 } else {
658 if (node->left) node = node->left.get();
659 else break;
660 }
661 bits++;
662 }
663 // needed if we did not find one in loop
664 if (node->node4) ret = node->node4.get();
665 } else {
666 uint64_t* addr = (uint64_t*)value.sin6.sin6_addr.s6_addr;
667 max_bits = std::max(0,std::min(max_bits,128));
668 std::bitset<64> addr_low(be64toh(addr[1]));
669 std::bitset<64> addr_high(be64toh(addr[0]));
670 int bits = 0;
671 while(bits < max_bits) {
672 if (node->node6) ret = node->node6.get();
673 uint8_t val;
674 if (bits < 64) val = addr_high[63-bits];
675 else val = addr_low[127-bits];
676 if (val) {
677 if (node->right) node = node->right.get();
678 else break;
679 } else {
680 if (node->left) node = node->left.get();
681 else break;
682 }
683 bits++;
684 }
685 if (node->node6) ret = node->node6.get();
686 }
687
688 // this can be nullptr.
689 return ret;
690 }
691
2dfbbc41 692 //<! Removes key from TreeMap. This does not clean up the tree.
44845aab
AT
693 void erase(const key_type& key) {
694 TreeNode *node = root.get();
695
696 // no tree, no value
697 if ( node == nullptr ) return;
698
699 // exact same thing as above, except
700 if (key.getNetwork().sin4.sin_family == AF_INET) {
701 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
702 int bits = 0;
703 while(node && bits < key.getBits()) {
704 uint8_t val = addr[31-bits];
705 if (val) {
706 node = node->right.get();
707 } else {
708 node = node->left.get();
709 }
710 bits++;
711 }
712 if (node) {
713 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
714 if (node->node4.get() == *it) _nodes.erase(it);
715 node->node4.reset();
716 }
717 } else {
718 uint64_t* addr = (uint64_t*)key.getNetwork().sin6.sin6_addr.s6_addr;
719 std::bitset<64> addr_low(be64toh(addr[1]));
720 std::bitset<64> addr_high(be64toh(addr[0]));
721 int bits = 0;
722 while(node && bits < key.getBits()) {
723 uint8_t val;
724 if (bits < 64) val = addr_high[63-bits];
725 else val = addr_low[127-bits];
726 if (val) {
727 node = node->right.get();
728 } else {
729 node = node->left.get();
730 }
731 bits++;
732 }
733 if (node) {
734 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
b841314c 735 if (node->node6.get() == *it) _nodes.erase(it);
44845aab
AT
736 node->node6.reset();
737 }
738 }
739 }
740
741 void erase(const string& key) {
742 erase(key_type(key));
743 }
744
745 //<! checks whether the container is empty.
746 bool empty() const {
747 return _nodes.empty();
748 }
749
750 //<! returns the number of elements
751 size_type size() const {
752 return _nodes.size();
753 }
754
755 //<! See if given ComboAddress matches any prefix
756 bool match(const ComboAddress& value) const {
757 return (lookup(value) != nullptr);
758 }
759
760 bool match(const std::string& value) const {
761 return match(ComboAddress(value));
762 }
763
764 //<! Clean out the tree
765 void clear() {
766 _nodes.clear();
767 root.reset(nullptr);
768 }
769
770 //<! swaps the contents, rhs is left with nullptr.
771 void swap(NetmaskTree& rhs) {
772 root.swap(rhs.root);
773 _nodes.swap(rhs._nodes);
774 }
775
776private:
777 unique_ptr<TreeNode> root; //<! Root of our tree
778 std::vector<node_type*> _nodes; //<! Container for actual values
779};
780
12c86877
BH
781/** This class represents a group of supplemental Netmask classes. An IP address matchs
782 if it is matched by zero or more of the Netmask classes within.
783*/
784class NetmaskGroup
785{
786public:
787 //! If this IP address is matched by any of the classes within
60af67b8 788
1e77c17c 789 bool match(const ComboAddress *ip) const
12c86877 790 {
ee15a1e1
PD
791 const auto &ret = tree.lookup(*ip);
792 if(ret) return ret->second;
793 return false;
12c86877 794 }
60af67b8 795
1e77c17c 796 bool match(const ComboAddress& ip) const
60af67b8 797 {
798 return match(&ip);
799 }
800
376effcf 801 //! Add this string to the list of possible matches
ee15a1e1 802 void addMask(const string &ip, bool positive=true)
12c86877 803 {
ee15a1e1
PD
804 if(!ip.empty() && ip[0] == '!') {
805 addMask(Netmask(ip.substr(1)), false);
806 } else {
807 addMask(Netmask(ip), positive);
808 }
12c86877 809 }
68b011bd 810
376effcf 811 //! Add this Netmask to the list of possible matches
ee15a1e1 812 void addMask(const Netmask& nm, bool positive=true)
376effcf 813 {
ee15a1e1 814 tree.insert(nm).second=positive;
376effcf 815 }
816
68b011bd
KM
817 void clear()
818 {
5ac553e1 819 tree.clear();
68b011bd
KM
820 }
821
5ac553e1 822 bool empty() const
12c86877 823 {
5ac553e1 824 return tree.empty();
12c86877
BH
825 }
826
5ac553e1 827 size_t size() const
2c95fc65 828 {
5ac553e1 829 return tree.size();
2c95fc65
BH
830 }
831
832 string toString() const
833 {
834 ostringstream str;
5ac553e1
AT
835 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
836 if(iter != tree.begin())
4957a608 837 str <<", ";
ee15a1e1
PD
838 if(!((*iter)->second))
839 str<<"!";
5ac553e1 840 str<<(*iter)->first.toString();
2c95fc65
BH
841 }
842 return str.str();
843 }
844
41942bb3
CH
845 void toStringVector(vector<string>* vec) const
846 {
ee15a1e1
PD
847 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
848 vec->push_back(((*iter)->second ? "" : "!") + (*iter)->first.toString());
849 }
41942bb3
CH
850 }
851
68b011bd
KM
852 void toMasks(const string &ips)
853 {
854 vector<string> parts;
855 stringtok(parts, ips, ", \t");
856
857 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter)
858 addMask(*iter);
859 }
860
12c86877 861private:
5ac553e1 862 NetmaskTree<bool> tree;
12c86877
BH
863};
864
002c970a 865
60c8afa8 866struct SComboAddress
867{
868 SComboAddress(const ComboAddress& orig) : ca(orig) {}
869 ComboAddress ca;
870 bool operator<(const SComboAddress& rhs) const
871 {
872 return ComboAddress::addressOnlyLessThan()(ca, rhs.ca);
873 }
874 operator const ComboAddress&()
875 {
876 return ca;
877 }
878};
879
880
002c970a 881int SSocket(int family, int type, int flags);
882int SConnect(int sockfd, const ComboAddress& remote);
51959320
RG
883/* tries to connect to remote for a maximum of timeout seconds.
884 sockfd should be set to non-blocking beforehand.
885 returns 0 on success (the socket is writable), throw a
886 runtime_error otherwise */
887int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout);
002c970a 888int SBind(int sockfd, const ComboAddress& local);
889int SAccept(int sockfd, ComboAddress& remote);
890int SListen(int sockfd, int limit);
891int SSetsockopt(int sockfd, int level, int opname, int value);
892
3e3f0358 893#if defined(IP_PKTINFO)
894 #define GEN_IP_PKTINFO IP_PKTINFO
895#elif defined(IP_RECVDSTADDR)
896 #define GEN_IP_PKTINFO IP_RECVDSTADDR
897#endif
898bool IsAnyAddress(const ComboAddress& addr);
899bool HarvestDestinationAddress(struct msghdr* msgh, ComboAddress* destination);
900bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv);
b71b60ee 901void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr);
a683e8bd 902ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to);
fbe2a2e0
RG
903ssize_t sendMsgWithTimeout(int fd, const char* buffer, size_t len, int timeout, ComboAddress& dest, const ComboAddress& local, unsigned int localItf);
904
12c86877 905#endif
f9f9592e
AT
906
907extern template class NetmaskTree<bool>;