]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/iputils.hh
Standardize license text in all PDNS files
[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
73d98e5a 62// for illumos
b0228347
AT
63#ifdef BE_64
64
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)
69
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)
74
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)
79
80#endif
81
e95bd1ae
RK
82#ifdef __FreeBSD__
83#include <sys/endian.h>
84#endif
85
37d3f960
BH
86union ComboAddress {
87 struct sockaddr_in sin4;
88 struct sockaddr_in6 sin6;
89
fd4ed0ab
BH
90 bool operator==(const ComboAddress& rhs) const
91 {
92 if(boost::tie(sin4.sin_family, sin4.sin_port) != boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
93 return false;
94 if(sin4.sin_family == AF_INET)
95 return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
96 else
a683e8bd 97 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0;
fd4ed0ab
BH
98 }
99
bb6f86bd
PL
100 bool operator!=(const ComboAddress& rhs) const
101 {
102 return(!operator==(rhs));
103 }
104
37d3f960
BH
105 bool operator<(const ComboAddress& rhs) const
106 {
f563fff4 107 if(sin4.sin_family == 0) {
108 return false;
109 }
fd4ed0ab 110 if(boost::tie(sin4.sin_family, sin4.sin_port) < boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960 111 return true;
fd4ed0ab 112 if(boost::tie(sin4.sin_family, sin4.sin_port) > boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960
BH
113 return false;
114
115 if(sin4.sin_family == AF_INET)
116 return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
117 else
a683e8bd 118 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0;
37d3f960
BH
119 }
120
fd4ed0ab
BH
121 bool operator>(const ComboAddress& rhs) const
122 {
5f15ee47 123 return rhs.operator<(*this);
fd4ed0ab
BH
124 }
125
545725f2 126 struct addressOnlyHash
127 {
128 uint32_t operator()(const ComboAddress& ca) const
129 {
130 const unsigned char* start;
131 int len;
132 if(ca.sin4.sin_family == AF_INET) {
133 start =(const unsigned char*)&ca.sin4.sin_addr.s_addr;
134 len=4;
135 }
136 else {
137 start =(const unsigned char*)&ca.sin6.sin6_addr.s6_addr;
138 len=16;
139 }
140 return burtle(start, len, 0);
141 }
142 };
143
662d5441 144 struct addressOnlyLessThan: public std::binary_function<ComboAddress, ComboAddress, bool>
11a7242f
BH
145 {
146 bool operator()(const ComboAddress& a, const ComboAddress& b) const
147 {
148 if(a.sin4.sin_family < b.sin4.sin_family)
4957a608 149 return true;
11a7242f 150 if(a.sin4.sin_family > b.sin4.sin_family)
4957a608 151 return false;
11a7242f 152 if(a.sin4.sin_family == AF_INET)
4957a608 153 return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
11a7242f 154 else
a683e8bd 155 return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
11a7242f
BH
156 }
157 };
fd4ed0ab 158
0940e4eb 159 struct addressOnlyEqual: public std::binary_function<ComboAddress, ComboAddress, bool>
160 {
161 bool operator()(const ComboAddress& a, const ComboAddress& b) const
162 {
163 if(a.sin4.sin_family != b.sin4.sin_family)
164 return false;
165 if(a.sin4.sin_family == AF_INET)
166 return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
167 else
a683e8bd 168 return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr));
0940e4eb 169 }
170 };
171
172
fd4ed0ab 173 socklen_t getSocklen() const
a9af3782
BH
174 {
175 if(sin4.sin_family == AF_INET)
176 return sizeof(sin4);
177 else
178 return sizeof(sin6);
179 }
fd4ed0ab
BH
180
181 ComboAddress()
182 {
183 sin4.sin_family=AF_INET;
184 sin4.sin_addr.s_addr=0;
185 sin4.sin_port=0;
186 }
187
a7360cd9
AT
188 ComboAddress(const struct sockaddr *sa, socklen_t salen) {
189 setSockaddr(sa, salen);
190 };
191
192 ComboAddress(const struct sockaddr_in6 *sa) {
193 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6));
194 };
195
196 ComboAddress(const struct sockaddr_in *sa) {
197 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in));
198 };
199
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);
203 }
204
85db02c5 205 // 'port' sets a default value in case 'str' does not set a port
fd4ed0ab
BH
206 explicit ComboAddress(const string& str, uint16_t port=0)
207 {
208 memset(&sin6, 0, sizeof(sin6));
209 sin4.sin_family = AF_INET;
85db02c5
BH
210 sin4.sin_port = 0;
211 if(makeIPv4sockaddr(str, &sin4)) {
fd4ed0ab 212 sin6.sin6_family = AF_INET6;
f71bc087 213 if(makeIPv6sockaddr(str, &sin6) < 0)
3f81d239 214 throw PDNSException("Unable to convert presentation address '"+ str +"'");
b03c5a46 215
fd4ed0ab 216 }
85db02c5
BH
217 if(!sin4.sin_port) // 'str' overrides port!
218 sin4.sin_port=htons(port);
fd4ed0ab 219 }
a9af3782 220
eb5bae86 221 bool isMappedIPv4() const
2914b022
BH
222 {
223 if(sin4.sin_family!=AF_INET6)
224 return false;
225
226 int n=0;
227 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
228 for(n=0; n < 10; ++n)
229 if(ptr[n])
4957a608 230 return false;
2914b022
BH
231
232 for(; n < 12; ++n)
233 if(ptr[n]!=0xff)
4957a608 234 return false;
2914b022
BH
235
236 return true;
237 }
238
eb5bae86 239 ComboAddress mapToIPv4() const
2914b022
BH
240 {
241 if(!isMappedIPv4())
3f81d239 242 throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
2914b022
BH
243 ComboAddress ret;
244 ret.sin4.sin_family=AF_INET;
11a7242f 245 ret.sin4.sin_port=sin4.sin_port;
2914b022
BH
246
247 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
a683e8bd
RG
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));
2914b022
BH
250 return ret;
251 }
252
37d3f960
BH
253 string toString() const
254 {
506a9050 255 char host[1024];
c44d3917 256 if(sin4.sin_family && !getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST))
257 return host;
258 else
259 return "invalid";
37d3f960 260 }
b8c3ea84
BH
261
262 string toStringWithPort() const
263 {
264 if(sin4.sin_family==AF_INET)
335da0ba 265 return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 266 else
335da0ba 267 return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 268 }
22779196 269
270 void truncate(unsigned int bits);
37d3f960
BH
271};
272
12c86877 273/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
3f81d239 274class NetmaskException: public PDNSException
12c86877
BH
275{
276public:
3f81d239 277 NetmaskException(const string &a) : PDNSException(a) {}
12c86877
BH
278};
279
37d3f960
BH
280inline ComboAddress makeComboAddress(const string& str)
281{
282 ComboAddress address;
283 address.sin4.sin_family=AF_INET;
1e77c17c 284 if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
37d3f960 285 address.sin4.sin_family=AF_INET6;
f71bc087 286 if(makeIPv6sockaddr(str, &address.sin6) < 0)
4957a608 287 throw NetmaskException("Unable to convert '"+str+"' to a netmask");
37d3f960
BH
288 }
289 return address;
290}
291
12c86877
BH
292/** This class represents a netmask and can be queried to see if a certain
293 IP address is matched by this mask */
12c86877
BH
294class Netmask
295{
296public:
6f97329b
BH
297 Netmask()
298 {
299 d_network.sin4.sin_family=0; // disable this doing anything useful
f563fff4 300 d_network.sin4.sin_port = 0; // this guarantees d_network compares identical
2fd2d93c
AT
301 d_mask=0;
302 d_bits=0;
6f97329b
BH
303 }
304
a4c8835f 305 Netmask(const ComboAddress& network, uint8_t bits=0xff)
6f97329b
BH
306 {
307 d_network = network;
a4c8835f 308
e1c8a4bb 309 if(bits > 128)
a4c8835f
BH
310 bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
311
6f97329b
BH
312 d_bits = bits;
313 if(d_bits<32)
314 d_mask=~(0xFFFFFFFF>>d_bits);
315 else
316 d_mask=0xFFFFFFFF; // not actually used for IPv6
317 }
318
12c86877
BH
319 //! Constructor supplies the mask, which cannot be changed
320 Netmask(const string &mask)
321 {
37d3f960
BH
322 pair<string,string> split=splitField(mask,'/');
323 d_network=makeComboAddress(split.first);
324
325 if(!split.second.empty()) {
a683e8bd 326 d_bits = (uint8_t)pdns_stou(split.second);
37d3f960 327 if(d_bits<32)
4957a608 328 d_mask=~(0xFFFFFFFF>>d_bits);
8519b8a2 329 else
4957a608 330 d_mask=0xFFFFFFFF;
37d3f960
BH
331 }
332 else if(d_network.sin4.sin_family==AF_INET) {
333 d_bits = 32;
334 d_mask = 0xFFFFFFFF;
335 }
5c1def57 336 else {
37d3f960 337 d_bits=128;
5c1def57
BH
338 d_mask=0; // silence silly warning - d_mask is unused for IPv6
339 }
12c86877
BH
340 }
341
2914b022
BH
342 bool match(const ComboAddress& ip) const
343 {
344 return match(&ip);
345 }
346
12c86877 347 //! If this IP address in socket address matches
37d3f960 348 bool match(const ComboAddress *ip) const
12c86877 349 {
37d3f960
BH
350 if(d_network.sin4.sin_family != ip->sin4.sin_family) {
351 return false;
352 }
353 if(d_network.sin4.sin_family == AF_INET) {
354 return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr));
355 }
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;
360
361 for(n=0; n < bytes; ++n) {
4957a608
BH
362 if(us[n]!=them[n]) {
363 return false;
364 }
37d3f960
BH
365 }
366 // still here, now match remaining bits
f0739fb6 367 uint8_t bits= d_bits % 8;
a683e8bd 368 uint8_t mask= (uint8_t) ~(0xFF>>bits);
f0739fb6 369
37d3f960
BH
370 return((us[n] & mask) == (them[n] & mask));
371 }
372 return false;
12c86877
BH
373 }
374
375 //! If this ASCII IP address matches
376 bool match(const string &ip) const
377 {
37d3f960
BH
378 ComboAddress address=makeComboAddress(ip);
379 return match(&address);
12c86877
BH
380 }
381
382 //! If this IP address in native format matches
37d3f960 383 bool match4(uint32_t ip) const
12c86877 384 {
37d3f960 385 return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
12c86877
BH
386 }
387
2c95fc65
BH
388 string toString() const
389 {
335da0ba 390 return d_network.toString()+"/"+std::to_string((unsigned int)d_bits);
2c95fc65
BH
391 }
392
a4c8835f
BH
393 string toStringNoMask() const
394 {
395 return d_network.toString();
396 }
9f84a557 397 const ComboAddress& getNetwork() const
a4c8835f
BH
398 {
399 return d_network;
400 }
e1c8a4bb
RG
401 const ComboAddress getMaskedNetwork() const
402 {
403 ComboAddress result(d_network);
404 if(isIpv4()) {
405 result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask);
406 }
407 else if(isIpv6()) {
408 size_t idx;
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);
413
414 if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) {
415 us[bytes] &= mask;
416 }
417
418 for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) {
419 us[idx] = 0;
420 }
421 }
422 return result;
423 }
a4c8835f
BH
424 int getBits() const
425 {
426 return d_bits;
427 }
709ca59f
AT
428 bool isIpv6() const
429 {
430 return d_network.sin6.sin6_family == AF_INET6;
431 }
432 bool isIpv4() const
433 {
434 return d_network.sin4.sin_family == AF_INET;
435 }
644dd1da 436
437 bool operator<(const Netmask& rhs) const
438 {
439 return tie(d_network, d_bits) < tie(rhs.d_network, rhs.d_bits);
440 }
39ec5d29 441
442 bool operator==(const Netmask& rhs) const
443 {
444 return tie(d_network, d_bits) == tie(rhs.d_network, rhs.d_bits);
445 }
446
87e665b1 447 bool empty() const
448 {
449 return d_network.sin4.sin_family==0;
450 }
451
12c86877 452private:
37d3f960 453 ComboAddress d_network;
092f210a 454 uint32_t d_mask;
37d3f960 455 uint8_t d_bits;
12c86877
BH
456};
457
44845aab
AT
458/** Per-bit binary tree map implementation with <Netmask,T> pair.
459 *
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.
463 *
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.
466 *
467 * You can store IPv4 and IPv6 addresses to same tree, separate payload storage is kept per AFI.
468 *
469 * To erase something copy values to new tree sans the value you want to erase.
470 *
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.
474 *
475 * Please see NetmaskGroup for example of simple use case. Other usecases can be found
476 * from GeoIPBackend and Sortlist, and from dnsdist.
477 */
478template <typename T>
479class NetmaskTree {
480public:
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;
485
486private:
487 /** Single node in tree, internal use only.
488 */
489 class TreeNode : boost::noncopyable {
490 public:
491 explicit TreeNode(int bits) noexcept : parent(NULL),d_bits(bits) {
492 }
493
494 //<! Makes a left node with one more bit than parent
495 TreeNode* make_left() {
496 if (!left) {
497 left = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
498 left->parent = this;
499 }
500 return left.get();
501 }
502
503 //<! Makes a right node with one more bit than parent
504 TreeNode* make_right() {
505 if (!right) {
506 right = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
507 right->parent = this;
508 }
509 return right.get();
510 }
511
512 unique_ptr<TreeNode> left;
513 unique_ptr<TreeNode> right;
514 TreeNode* parent;
515
516 unique_ptr<node_type> node4; //<! IPv4 value-pair
517 unique_ptr<node_type> node6; //<! IPv6 value-pair
518
519 int d_bits; //<! How many bits have been used so far
520 };
521
522public:
523 NetmaskTree() noexcept {
524 }
525
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;
531 }
532
533 NetmaskTree& operator=(const NetmaskTree& rhs) {
534 clear();
535 // see above.
536 for(auto const& node: rhs._nodes)
537 insert(node->first).second = node->second;
538 return *this;
539 }
540
44845aab
AT
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(); }
543
544 typename std::vector<node_type*>::iterator begin() { return _nodes.begin(); }
545 typename std::vector<node_type*>::iterator end() { return _nodes.end(); }
546
547 node_type& insert(const string &mask) {
548 return insert(key_type(mask));
549 }
550
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;
557
558 if (key.getNetwork().sin4.sin_family == AF_INET) {
559 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
560 int bits = 0;
561 // we turn left on 0 and right on 1
562 while(bits < key.getBits()) {
563 uint8_t val = addr[31-bits];
564 if (val)
565 node = node->make_right();
566 else
567 node = node->make_left();
568 bits++;
569 }
570 // only create node if not yet assigned
571 if (!node->node4) {
572 node->node4 = unique_ptr<node_type>(new node_type());
573 _nodes.push_back(node->node4.get());
574 }
575 value = node->node4.get();
576 } else {
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]));
580 int bits = 0;
581 while(bits < key.getBits()) {
582 uint8_t val;
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];
587
588 // we turn left on 0 and right on 1
589 if (val)
590 node = node->make_right();
591 else
592 node = node->make_left();
593 bits++;
594 }
595 // only create node if not yet assigned
596 if (!node->node6) {
597 node->node6 = unique_ptr<node_type>(new node_type());
598 _nodes.push_back(node->node6.get());
599 }
600 value = node->node6.get();
601 }
602 // assign key
603 value->first = key;
604 return *value;
605 }
606
2dfbbc41 607 //<! Creates or updates value
44845aab
AT
608 void insert_or_assign(const key_type& mask, const value_type& value) {
609 insert(mask).second = value;
610 }
611
e6419866
AT
612 void insert_or_assign(const string& mask, const value_type& value) {
613 insert(key_type(mask)).second = value;
44845aab
AT
614 }
615
41d0adb7
AT
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;
620 }
621
2dfbbc41 622 //<! Returns "best match" for key_type, which might not be value
44845aab
AT
623 const node_type* lookup(const key_type& value) const {
624 return lookup(value.getNetwork(), value.getBits());
625 }
626
2dfbbc41 627 //<! Perform best match lookup for value, using at most max_bits
44845aab
AT
628 const node_type* lookup(const ComboAddress& value, int max_bits = 128) const {
629 if (!root) return nullptr;
630
631 TreeNode *node = root.get();
632 node_type *ret = nullptr;
633
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));
638 int bits = 0;
639
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
645 if (val) {
646 if (node->right) node = node->right.get();
647 // ..and we break when road ends
648 else break;
649 } else {
650 if (node->left) node = node->left.get();
651 else break;
652 }
653 bits++;
654 }
655 // needed if we did not find one in loop
656 if (node->node4) ret = node->node4.get();
657 } else {
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]));
662 int bits = 0;
663 while(bits < max_bits) {
664 if (node->node6) ret = node->node6.get();
665 uint8_t val;
666 if (bits < 64) val = addr_high[63-bits];
667 else val = addr_low[127-bits];
668 if (val) {
669 if (node->right) node = node->right.get();
670 else break;
671 } else {
672 if (node->left) node = node->left.get();
673 else break;
674 }
675 bits++;
676 }
677 if (node->node6) ret = node->node6.get();
678 }
679
680 // this can be nullptr.
681 return ret;
682 }
683
2dfbbc41 684 //<! Removes key from TreeMap. This does not clean up the tree.
44845aab
AT
685 void erase(const key_type& key) {
686 TreeNode *node = root.get();
687
688 // no tree, no value
689 if ( node == nullptr ) return;
690
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));
694 int bits = 0;
695 while(node && bits < key.getBits()) {
696 uint8_t val = addr[31-bits];
697 if (val) {
698 node = node->right.get();
699 } else {
700 node = node->left.get();
701 }
702 bits++;
703 }
704 if (node) {
705 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
706 if (node->node4.get() == *it) _nodes.erase(it);
707 node->node4.reset();
708 }
709 } else {
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]));
713 int bits = 0;
714 while(node && bits < key.getBits()) {
715 uint8_t val;
716 if (bits < 64) val = addr_high[63-bits];
717 else val = addr_low[127-bits];
718 if (val) {
719 node = node->right.get();
720 } else {
721 node = node->left.get();
722 }
723 bits++;
724 }
725 if (node) {
726 for(auto it = _nodes.begin(); it != _nodes.end(); it++)
b841314c 727 if (node->node6.get() == *it) _nodes.erase(it);
44845aab
AT
728 node->node6.reset();
729 }
730 }
731 }
732
733 void erase(const string& key) {
734 erase(key_type(key));
735 }
736
737 //<! checks whether the container is empty.
738 bool empty() const {
739 return _nodes.empty();
740 }
741
742 //<! returns the number of elements
743 size_type size() const {
744 return _nodes.size();
745 }
746
747 //<! See if given ComboAddress matches any prefix
748 bool match(const ComboAddress& value) const {
749 return (lookup(value) != nullptr);
750 }
751
752 bool match(const std::string& value) const {
753 return match(ComboAddress(value));
754 }
755
756 //<! Clean out the tree
757 void clear() {
758 _nodes.clear();
759 root.reset(nullptr);
760 }
761
762 //<! swaps the contents, rhs is left with nullptr.
763 void swap(NetmaskTree& rhs) {
764 root.swap(rhs.root);
765 _nodes.swap(rhs._nodes);
766 }
767
768private:
769 unique_ptr<TreeNode> root; //<! Root of our tree
770 std::vector<node_type*> _nodes; //<! Container for actual values
771};
772
12c86877
BH
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.
775*/
776class NetmaskGroup
777{
778public:
779 //! If this IP address is matched by any of the classes within
60af67b8 780
1e77c17c 781 bool match(const ComboAddress *ip) const
12c86877 782 {
5ac553e1 783 return tree.match(*ip);
12c86877 784 }
60af67b8 785
1e77c17c 786 bool match(const ComboAddress& ip) const
60af67b8 787 {
788 return match(&ip);
789 }
790
376effcf 791 //! Add this string to the list of possible matches
12c86877
BH
792 void addMask(const string &ip)
793 {
5ac553e1 794 addMask(Netmask(ip));
12c86877 795 }
68b011bd 796
376effcf 797 //! Add this Netmask to the list of possible matches
798 void addMask(const Netmask& nm)
799 {
5ac553e1 800 tree.insert(nm);
376effcf 801 }
802
68b011bd
KM
803 void clear()
804 {
5ac553e1 805 tree.clear();
68b011bd
KM
806 }
807
5ac553e1 808 bool empty() const
12c86877 809 {
5ac553e1 810 return tree.empty();
12c86877
BH
811 }
812
5ac553e1 813 size_t size() const
2c95fc65 814 {
5ac553e1 815 return tree.size();
2c95fc65
BH
816 }
817
818 string toString() const
819 {
820 ostringstream str;
5ac553e1
AT
821 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
822 if(iter != tree.begin())
4957a608 823 str <<", ";
5ac553e1 824 str<<(*iter)->first.toString();
2c95fc65
BH
825 }
826 return str.str();
827 }
828
41942bb3
CH
829 void toStringVector(vector<string>* vec) const
830 {
5ac553e1
AT
831 for(auto iter = tree.begin(); iter != tree.end(); ++iter)
832 vec->push_back((*iter)->first.toString());
41942bb3
CH
833 }
834
68b011bd
KM
835 void toMasks(const string &ips)
836 {
837 vector<string> parts;
838 stringtok(parts, ips, ", \t");
839
840 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter)
841 addMask(*iter);
842 }
843
12c86877 844private:
5ac553e1 845 NetmaskTree<bool> tree;
12c86877
BH
846};
847
002c970a 848
60c8afa8 849struct SComboAddress
850{
851 SComboAddress(const ComboAddress& orig) : ca(orig) {}
852 ComboAddress ca;
853 bool operator<(const SComboAddress& rhs) const
854 {
855 return ComboAddress::addressOnlyLessThan()(ca, rhs.ca);
856 }
857 operator const ComboAddress&()
858 {
859 return ca;
860 }
861};
862
863
002c970a 864int SSocket(int family, int type, int flags);
865int SConnect(int sockfd, const ComboAddress& remote);
866int SBind(int sockfd, const ComboAddress& local);
867int SAccept(int sockfd, ComboAddress& remote);
868int SListen(int sockfd, int limit);
869int SSetsockopt(int sockfd, int level, int opname, int value);
870
3e3f0358 871#if defined(IP_PKTINFO)
872 #define GEN_IP_PKTINFO IP_PKTINFO
873#elif defined(IP_RECVDSTADDR)
874 #define GEN_IP_PKTINFO IP_RECVDSTADDR
875#endif
876bool IsAnyAddress(const ComboAddress& addr);
877bool HarvestDestinationAddress(struct msghdr* msgh, ComboAddress* destination);
878bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv);
b71b60ee 879void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, char* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr);
a683e8bd 880ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to);
fbe2a2e0
RG
881ssize_t sendMsgWithTimeout(int fd, const char* buffer, size_t len, int timeout, ComboAddress& dest, const ComboAddress& local, unsigned int localItf);
882
12c86877 883#endif
f9f9592e
AT
884
885extern template class NetmaskTree<bool>;