]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/iputils.hh
Merge pull request #8803 from rgacogne/dnsname-centos-6
[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
4d39d7f3
TIH
85#if defined(__NetBSD__) && defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR)
86// The IP_PKTINFO option in NetBSD was incompatible with Linux until a
87// change that also introduced IP_SENDSRCADDR for FreeBSD compatibility.
88#undef IP_PKTINFO
89#endif
90
37d3f960
BH
91union ComboAddress {
92 struct sockaddr_in sin4;
93 struct sockaddr_in6 sin6;
94
fd4ed0ab
BH
95 bool operator==(const ComboAddress& rhs) const
96 {
97 if(boost::tie(sin4.sin_family, sin4.sin_port) != boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
98 return false;
99 if(sin4.sin_family == AF_INET)
100 return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
101 else
a683e8bd 102 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr))==0;
fd4ed0ab
BH
103 }
104
bb6f86bd
PL
105 bool operator!=(const ComboAddress& rhs) const
106 {
107 return(!operator==(rhs));
108 }
109
37d3f960
BH
110 bool operator<(const ComboAddress& rhs) const
111 {
f563fff4 112 if(sin4.sin_family == 0) {
113 return false;
114 }
fd4ed0ab 115 if(boost::tie(sin4.sin_family, sin4.sin_port) < boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960 116 return true;
fd4ed0ab 117 if(boost::tie(sin4.sin_family, sin4.sin_port) > boost::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
37d3f960
BH
118 return false;
119
120 if(sin4.sin_family == AF_INET)
121 return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
122 else
a683e8bd 123 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr, sizeof(sin6.sin6_addr.s6_addr)) < 0;
37d3f960
BH
124 }
125
fd4ed0ab
BH
126 bool operator>(const ComboAddress& rhs) const
127 {
5f15ee47 128 return rhs.operator<(*this);
fd4ed0ab
BH
129 }
130
545725f2 131 struct addressOnlyHash
132 {
133 uint32_t operator()(const ComboAddress& ca) const
134 {
135 const unsigned char* start;
136 int len;
137 if(ca.sin4.sin_family == AF_INET) {
138 start =(const unsigned char*)&ca.sin4.sin_addr.s_addr;
139 len=4;
140 }
141 else {
142 start =(const unsigned char*)&ca.sin6.sin6_addr.s6_addr;
143 len=16;
144 }
145 return burtle(start, len, 0);
146 }
147 };
148
662d5441 149 struct addressOnlyLessThan: public std::binary_function<ComboAddress, ComboAddress, bool>
11a7242f
BH
150 {
151 bool operator()(const ComboAddress& a, const ComboAddress& b) const
152 {
153 if(a.sin4.sin_family < b.sin4.sin_family)
4957a608 154 return true;
11a7242f 155 if(a.sin4.sin_family > b.sin4.sin_family)
4957a608 156 return false;
11a7242f 157 if(a.sin4.sin_family == AF_INET)
4957a608 158 return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
11a7242f 159 else
a683e8bd 160 return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
11a7242f
BH
161 }
162 };
fd4ed0ab 163
0940e4eb 164 struct addressOnlyEqual: public std::binary_function<ComboAddress, ComboAddress, bool>
165 {
166 bool operator()(const ComboAddress& a, const ComboAddress& b) const
167 {
168 if(a.sin4.sin_family != b.sin4.sin_family)
169 return false;
170 if(a.sin4.sin_family == AF_INET)
171 return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
172 else
a683e8bd 173 return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr, sizeof(a.sin6.sin6_addr.s6_addr));
0940e4eb 174 }
175 };
176
177
fd4ed0ab 178 socklen_t getSocklen() const
a9af3782
BH
179 {
180 if(sin4.sin_family == AF_INET)
181 return sizeof(sin4);
182 else
183 return sizeof(sin6);
184 }
fd4ed0ab
BH
185
186 ComboAddress()
187 {
188 sin4.sin_family=AF_INET;
189 sin4.sin_addr.s_addr=0;
190 sin4.sin_port=0;
5cc8371b
RG
191 sin6.sin6_scope_id = 0;
192 sin6.sin6_flowinfo = 0;
fd4ed0ab
BH
193 }
194
a7360cd9
AT
195 ComboAddress(const struct sockaddr *sa, socklen_t salen) {
196 setSockaddr(sa, salen);
197 };
198
199 ComboAddress(const struct sockaddr_in6 *sa) {
200 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in6));
201 };
202
203 ComboAddress(const struct sockaddr_in *sa) {
204 setSockaddr((const struct sockaddr*)sa, sizeof(struct sockaddr_in));
205 };
206
207 void setSockaddr(const struct sockaddr *sa, socklen_t salen) {
208 if (salen > sizeof(struct sockaddr_in6)) throw PDNSException("ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
209 memcpy(this, sa, salen);
210 }
211
85db02c5 212 // 'port' sets a default value in case 'str' does not set a port
fd4ed0ab
BH
213 explicit ComboAddress(const string& str, uint16_t port=0)
214 {
215 memset(&sin6, 0, sizeof(sin6));
216 sin4.sin_family = AF_INET;
85db02c5
BH
217 sin4.sin_port = 0;
218 if(makeIPv4sockaddr(str, &sin4)) {
fd4ed0ab 219 sin6.sin6_family = AF_INET6;
f71bc087 220 if(makeIPv6sockaddr(str, &sin6) < 0)
3f81d239 221 throw PDNSException("Unable to convert presentation address '"+ str +"'");
b03c5a46 222
fd4ed0ab 223 }
85db02c5
BH
224 if(!sin4.sin_port) // 'str' overrides port!
225 sin4.sin_port=htons(port);
fd4ed0ab 226 }
a9af3782 227
a94673ea
RG
228 bool isIPv6() const
229 {
230 return sin4.sin_family == AF_INET6;
231 }
232 bool isIPv4() const
233 {
234 return sin4.sin_family == AF_INET;
235 }
236
eb5bae86 237 bool isMappedIPv4() const
2914b022
BH
238 {
239 if(sin4.sin_family!=AF_INET6)
240 return false;
241
242 int n=0;
243 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
244 for(n=0; n < 10; ++n)
245 if(ptr[n])
4957a608 246 return false;
2914b022
BH
247
248 for(; n < 12; ++n)
249 if(ptr[n]!=0xff)
4957a608 250 return false;
2914b022
BH
251
252 return true;
253 }
254
eb5bae86 255 ComboAddress mapToIPv4() const
2914b022
BH
256 {
257 if(!isMappedIPv4())
3f81d239 258 throw PDNSException("ComboAddress can't map non-mapped IPv6 address back to IPv4");
2914b022
BH
259 ComboAddress ret;
260 ret.sin4.sin_family=AF_INET;
11a7242f 261 ret.sin4.sin_port=sin4.sin_port;
2914b022
BH
262
263 const unsigned char*ptr = (unsigned char*) &sin6.sin6_addr.s6_addr;
a683e8bd
RG
264 ptr+=(sizeof(sin6.sin6_addr.s6_addr) - sizeof(ret.sin4.sin_addr.s_addr));
265 memcpy(&ret.sin4.sin_addr.s_addr, ptr, sizeof(ret.sin4.sin_addr.s_addr));
2914b022
BH
266 return ret;
267 }
268
37d3f960
BH
269 string toString() const
270 {
506a9050 271 char host[1024];
5cc8371b 272 int retval = 0;
f4352636 273 if(sin4.sin_family && !(retval = getnameinfo((struct sockaddr*) this, getSocklen(), host, sizeof(host),0, 0, NI_NUMERICHOST)))
bfbf6814 274 return string(host);
c44d3917 275 else
f4352636 276 return "invalid "+string(gai_strerror(retval));
37d3f960 277 }
b8c3ea84
BH
278
279 string toStringWithPort() const
280 {
281 if(sin4.sin_family==AF_INET)
335da0ba 282 return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 283 else
335da0ba 284 return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
b8c3ea84 285 }
22779196 286
d622042f 287 string toStringWithPortExcept(int port) const
288 {
289 if(ntohs(sin4.sin_port) == port)
290 return toString();
291 if(sin4.sin_family==AF_INET)
292 return toString() + ":" + std::to_string(ntohs(sin4.sin_port));
293 else
294 return "["+toString() + "]:" + std::to_string(ntohs(sin4.sin_port));
295 }
296
9b0f144f
KM
297 string toLogString() const
298 {
299 return toStringWithPortExcept(53);
300 }
301
5b6099b2 302 void truncate(unsigned int bits) noexcept;
0affb140
RG
303
304 uint16_t getPort() const
305 {
306 return ntohs(sin4.sin_port);
307 }
308
79816288 309 void setPort(uint16_t port)
f43e6a40 310 {
79816288 311 sin4.sin_port = htons(port);
f43e6a40
KM
312 }
313
d38e2ba9
RG
314 void reset()
315 {
316 memset(&sin4, 0, sizeof(sin4));
317 memset(&sin6, 0, sizeof(sin6));
318 }
319
37d3f960
BH
320};
321
12c86877 322/** This exception is thrown by the Netmask class and by extension by the NetmaskGroup class */
3f81d239 323class NetmaskException: public PDNSException
12c86877
BH
324{
325public:
3f81d239 326 NetmaskException(const string &a) : PDNSException(a) {}
12c86877
BH
327};
328
37d3f960
BH
329inline ComboAddress makeComboAddress(const string& str)
330{
331 ComboAddress address;
332 address.sin4.sin_family=AF_INET;
1e77c17c 333 if(inet_pton(AF_INET, str.c_str(), &address.sin4.sin_addr) <= 0) {
37d3f960 334 address.sin4.sin_family=AF_INET6;
f71bc087 335 if(makeIPv6sockaddr(str, &address.sin6) < 0)
4957a608 336 throw NetmaskException("Unable to convert '"+str+"' to a netmask");
37d3f960
BH
337 }
338 return address;
339}
340
5cc8371b 341inline ComboAddress makeComboAddressFromRaw(uint8_t version, const char* raw, size_t len)
f4352636
PD
342{
343 ComboAddress address;
f4352636 344
45fab880 345 if (version == 4) {
5cc8371b
RG
346 address.sin4.sin_family = AF_INET;
347 if (len != sizeof(address.sin4.sin_addr)) throw NetmaskException("invalid raw address length");
348 memcpy(&address.sin4.sin_addr, raw, sizeof(address.sin4.sin_addr));
45fab880
PD
349 }
350 else if (version == 6) {
5cc8371b
RG
351 address.sin6.sin6_family = AF_INET6;
352 if (len != sizeof(address.sin6.sin6_addr)) throw NetmaskException("invalid raw address length");
353 memcpy(&address.sin6.sin6_addr, raw, sizeof(address.sin6.sin6_addr));
45fab880 354 }
f4352636 355 else throw NetmaskException("invalid address family");
f4352636
PD
356
357 return address;
358}
359
5cc8371b
RG
360inline ComboAddress makeComboAddressFromRaw(uint8_t version, const string &str)
361{
362 return makeComboAddressFromRaw(version, str.c_str(), str.size());
363}
364
12c86877
BH
365/** This class represents a netmask and can be queried to see if a certain
366 IP address is matched by this mask */
12c86877
BH
367class Netmask
368{
369public:
6f97329b
BH
370 Netmask()
371 {
372 d_network.sin4.sin_family=0; // disable this doing anything useful
f563fff4 373 d_network.sin4.sin_port = 0; // this guarantees d_network compares identical
2fd2d93c
AT
374 d_mask=0;
375 d_bits=0;
6f97329b
BH
376 }
377
5708a729 378 Netmask(const ComboAddress& network, uint8_t bits=0xff): d_network(network)
6f97329b 379 {
0bdabe94 380 d_network.sin4.sin_port=0;
e1c8a4bb 381 if(bits > 128)
a4c8835f
BH
382 bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
383
6f97329b
BH
384 d_bits = bits;
385 if(d_bits<32)
386 d_mask=~(0xFFFFFFFF>>d_bits);
387 else
388 d_mask=0xFFFFFFFF; // not actually used for IPv6
389 }
390
12c86877
BH
391 //! Constructor supplies the mask, which cannot be changed
392 Netmask(const string &mask)
393 {
37d3f960
BH
394 pair<string,string> split=splitField(mask,'/');
395 d_network=makeComboAddress(split.first);
396
397 if(!split.second.empty()) {
a683e8bd 398 d_bits = (uint8_t)pdns_stou(split.second);
37d3f960 399 if(d_bits<32)
4957a608 400 d_mask=~(0xFFFFFFFF>>d_bits);
8519b8a2 401 else
4957a608 402 d_mask=0xFFFFFFFF;
37d3f960
BH
403 }
404 else if(d_network.sin4.sin_family==AF_INET) {
405 d_bits = 32;
406 d_mask = 0xFFFFFFFF;
407 }
5c1def57 408 else {
37d3f960 409 d_bits=128;
5c1def57
BH
410 d_mask=0; // silence silly warning - d_mask is unused for IPv6
411 }
12c86877
BH
412 }
413
2914b022
BH
414 bool match(const ComboAddress& ip) const
415 {
416 return match(&ip);
417 }
418
12c86877 419 //! If this IP address in socket address matches
37d3f960 420 bool match(const ComboAddress *ip) const
12c86877 421 {
37d3f960
BH
422 if(d_network.sin4.sin_family != ip->sin4.sin_family) {
423 return false;
424 }
425 if(d_network.sin4.sin_family == AF_INET) {
426 return match4(htonl((unsigned int)ip->sin4.sin_addr.s_addr));
427 }
428 if(d_network.sin6.sin6_family == AF_INET6) {
429 uint8_t bytes=d_bits/8, n;
430 const uint8_t *us=(const uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
431 const uint8_t *them=(const uint8_t*) &ip->sin6.sin6_addr.s6_addr;
432
433 for(n=0; n < bytes; ++n) {
4957a608
BH
434 if(us[n]!=them[n]) {
435 return false;
436 }
37d3f960
BH
437 }
438 // still here, now match remaining bits
f0739fb6 439 uint8_t bits= d_bits % 8;
a683e8bd 440 uint8_t mask= (uint8_t) ~(0xFF>>bits);
f0739fb6 441
37d3f960
BH
442 return((us[n] & mask) == (them[n] & mask));
443 }
444 return false;
12c86877
BH
445 }
446
447 //! If this ASCII IP address matches
448 bool match(const string &ip) const
449 {
37d3f960
BH
450 ComboAddress address=makeComboAddress(ip);
451 return match(&address);
12c86877
BH
452 }
453
454 //! If this IP address in native format matches
37d3f960 455 bool match4(uint32_t ip) const
12c86877 456 {
37d3f960 457 return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
12c86877
BH
458 }
459
2c95fc65
BH
460 string toString() const
461 {
335da0ba 462 return d_network.toString()+"/"+std::to_string((unsigned int)d_bits);
2c95fc65
BH
463 }
464
a4c8835f
BH
465 string toStringNoMask() const
466 {
467 return d_network.toString();
468 }
9f84a557 469 const ComboAddress& getNetwork() const
a4c8835f
BH
470 {
471 return d_network;
472 }
e1c8a4bb
RG
473 const ComboAddress getMaskedNetwork() const
474 {
475 ComboAddress result(d_network);
d14121a8 476 if(isIPv4()) {
e1c8a4bb
RG
477 result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask);
478 }
37e35fbc 479 else if(isIPv6()) {
e1c8a4bb
RG
480 size_t idx;
481 uint8_t bytes=d_bits/8;
482 uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr;
483 uint8_t bits= d_bits % 8;
484 uint8_t mask= (uint8_t) ~(0xFF>>bits);
485
486 if (bytes < sizeof(result.sin6.sin6_addr.s6_addr)) {
487 us[bytes] &= mask;
488 }
489
490 for(idx = bytes + 1; idx < sizeof(result.sin6.sin6_addr.s6_addr); ++idx) {
491 us[idx] = 0;
492 }
493 }
494 return result;
495 }
8a3a3822 496 uint8_t getBits() const
a4c8835f
BH
497 {
498 return d_bits;
499 }
37e35fbc 500 bool isIPv6() const
709ca59f
AT
501 {
502 return d_network.sin6.sin6_family == AF_INET6;
503 }
d14121a8 504 bool isIPv4() const
709ca59f
AT
505 {
506 return d_network.sin4.sin_family == AF_INET;
507 }
644dd1da 508
509 bool operator<(const Netmask& rhs) const
510 {
a009559d
RG
511 if (empty() && !rhs.empty())
512 return false;
513
514 if (!empty() && rhs.empty())
515 return true;
516
517 if (d_bits > rhs.d_bits)
518 return true;
519 if (d_bits < rhs.d_bits)
520 return false;
521
522 return d_network < rhs.d_network;
523 }
524
525 bool operator>(const Netmask& rhs) const
526 {
527 return rhs.operator<(*this);
644dd1da 528 }
39ec5d29 529
530 bool operator==(const Netmask& rhs) const
531 {
532 return tie(d_network, d_bits) == tie(rhs.d_network, rhs.d_bits);
533 }
534
87e665b1 535 bool empty() const
536 {
537 return d_network.sin4.sin_family==0;
538 }
539
12c86877 540private:
37d3f960 541 ComboAddress d_network;
092f210a 542 uint32_t d_mask;
37d3f960 543 uint8_t d_bits;
12c86877
BH
544};
545
44845aab
AT
546/** Per-bit binary tree map implementation with <Netmask,T> pair.
547 *
548 * This is an binary tree implementation for storing attributes for IPv4 and IPv6 prefixes.
549 * The most simple use case is simple NetmaskTree<bool> used by NetmaskGroup, which only
550 * wants to know if given IP address is matched in the prefixes stored.
551 *
552 * This element is useful for anything that needs to *STORE* prefixes, and *MATCH* IP addresses
553 * to a *LIST* of *PREFIXES*. Not the other way round.
554 *
555 * You can store IPv4 and IPv6 addresses to same tree, separate payload storage is kept per AFI.
556 *
557 * To erase something copy values to new tree sans the value you want to erase.
558 *
559 * Use swap if you need to move the tree to another NetmaskTree instance, it is WAY faster
ba07e97e 560 * than using copy ctor or assignment operator, since it moves the nodes and tree root to
44845aab
AT
561 * new home instead of actually recreating the tree.
562 *
563 * Please see NetmaskGroup for example of simple use case. Other usecases can be found
564 * from GeoIPBackend and Sortlist, and from dnsdist.
565 */
566template <typename T>
567class NetmaskTree {
568public:
569 typedef Netmask key_type;
570 typedef T value_type;
571 typedef std::pair<key_type,value_type> node_type;
572 typedef size_t size_type;
573
574private:
575 /** Single node in tree, internal use only.
576 */
577 class TreeNode : boost::noncopyable {
578 public:
579 explicit TreeNode(int bits) noexcept : parent(NULL),d_bits(bits) {
580 }
581
582 //<! Makes a left node with one more bit than parent
583 TreeNode* make_left() {
584 if (!left) {
585 left = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
586 left->parent = this;
587 }
588 return left.get();
589 }
590
591 //<! Makes a right node with one more bit than parent
592 TreeNode* make_right() {
593 if (!right) {
594 right = unique_ptr<TreeNode>(new TreeNode(d_bits+1));
595 right->parent = this;
596 }
597 return right.get();
598 }
599
600 unique_ptr<TreeNode> left;
601 unique_ptr<TreeNode> right;
602 TreeNode* parent;
603
604 unique_ptr<node_type> node4; //<! IPv4 value-pair
605 unique_ptr<node_type> node6; //<! IPv6 value-pair
606
607 int d_bits; //<! How many bits have been used so far
608 };
609
610public:
11f4719b 611 NetmaskTree() noexcept : NetmaskTree(false) {
44845aab
AT
612 }
613
11f4719b
RG
614 NetmaskTree(bool cleanup) noexcept : d_cleanup_tree(cleanup) {
615 }
616
617 NetmaskTree(const NetmaskTree& rhs): d_cleanup_tree(rhs.d_cleanup_tree) {
44845aab
AT
618 // it is easier to copy the nodes than tree.
619 // also acts as handy compactor
620 for(auto const& node: rhs._nodes)
621 insert(node->first).second = node->second;
622 }
623
624 NetmaskTree& operator=(const NetmaskTree& rhs) {
625 clear();
626 // see above.
627 for(auto const& node: rhs._nodes)
628 insert(node->first).second = node->second;
5708a729 629 d_cleanup_tree = rhs.d_cleanup_tree;
44845aab
AT
630 return *this;
631 }
632
462dd712
RG
633 const typename std::set<node_type*>::const_iterator begin() const { return _nodes.begin(); }
634 const typename std::set<node_type*>::const_iterator end() const { return _nodes.end(); }
44845aab 635
462dd712
RG
636 typename std::set<node_type*>::iterator begin() { return _nodes.begin(); }
637 typename std::set<node_type*>::iterator end() { return _nodes.end(); }
44845aab
AT
638
639 node_type& insert(const string &mask) {
640 return insert(key_type(mask));
641 }
642
643 //<! Creates new value-pair in tree and returns it.
644 node_type& insert(const key_type& key) {
645 // lazily initialize tree on first insert.
646 if (!root) root = unique_ptr<TreeNode>(new TreeNode(0));
647 TreeNode* node = root.get();
648 node_type* value = nullptr;
649
650 if (key.getNetwork().sin4.sin_family == AF_INET) {
651 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
652 int bits = 0;
653 // we turn left on 0 and right on 1
654 while(bits < key.getBits()) {
655 uint8_t val = addr[31-bits];
656 if (val)
657 node = node->make_right();
658 else
659 node = node->make_left();
660 bits++;
661 }
662 // only create node if not yet assigned
663 if (!node->node4) {
664 node->node4 = unique_ptr<node_type>(new node_type());
462dd712 665 _nodes.insert(node->node4.get());
44845aab
AT
666 }
667 value = node->node4.get();
668 } else {
89ae2052
OM
669 uint64_t addr[2];
670 memcpy(addr, key.getNetwork().sin6.sin6_addr.s6_addr, sizeof(addr));
44845aab
AT
671 std::bitset<64> addr_low(be64toh(addr[1]));
672 std::bitset<64> addr_high(be64toh(addr[0]));
673 int bits = 0;
674 while(bits < key.getBits()) {
675 uint8_t val;
676 // we use high address until we are
677 if (bits < 64) val = addr_high[63-bits];
678 // past 64 bits, and start using low address
679 else val = addr_low[127-bits];
680
681 // we turn left on 0 and right on 1
682 if (val)
683 node = node->make_right();
684 else
685 node = node->make_left();
686 bits++;
687 }
688 // only create node if not yet assigned
689 if (!node->node6) {
690 node->node6 = unique_ptr<node_type>(new node_type());
462dd712 691 _nodes.insert(node->node6.get());
44845aab
AT
692 }
693 value = node->node6.get();
694 }
695 // assign key
696 value->first = key;
697 return *value;
698 }
699
2dfbbc41 700 //<! Creates or updates value
44845aab
AT
701 void insert_or_assign(const key_type& mask, const value_type& value) {
702 insert(mask).second = value;
703 }
704
e6419866
AT
705 void insert_or_assign(const string& mask, const value_type& value) {
706 insert(key_type(mask)).second = value;
44845aab
AT
707 }
708
41d0adb7
AT
709 //<! check if given key is present in TreeMap
710 bool has_key(const key_type& key) const {
711 const node_type *ptr = lookup(key);
712 return ptr && ptr->first == key;
713 }
714
2dfbbc41 715 //<! Returns "best match" for key_type, which might not be value
44845aab
AT
716 const node_type* lookup(const key_type& value) const {
717 return lookup(value.getNetwork(), value.getBits());
718 }
719
2dfbbc41 720 //<! Perform best match lookup for value, using at most max_bits
44845aab
AT
721 const node_type* lookup(const ComboAddress& value, int max_bits = 128) const {
722 if (!root) return nullptr;
723
724 TreeNode *node = root.get();
725 node_type *ret = nullptr;
726
727 // exact same thing as above, except
728 if (value.sin4.sin_family == AF_INET) {
729 max_bits = std::max(0,std::min(max_bits,32));
730 std::bitset<32> addr(be32toh(value.sin4.sin_addr.s_addr));
731 int bits = 0;
732
733 while(bits < max_bits) {
734 // ...we keep track of last non-empty node
735 if (node->node4) ret = node->node4.get();
736 uint8_t val = addr[31-bits];
737 // ...and we don't create left/right hand
738 if (val) {
739 if (node->right) node = node->right.get();
740 // ..and we break when road ends
741 else break;
742 } else {
743 if (node->left) node = node->left.get();
744 else break;
745 }
746 bits++;
747 }
748 // needed if we did not find one in loop
749 if (node->node4) ret = node->node4.get();
750 } else {
89ae2052
OM
751 uint64_t addr[2];
752 memcpy(addr, value.sin6.sin6_addr.s6_addr, sizeof(addr));
44845aab
AT
753 max_bits = std::max(0,std::min(max_bits,128));
754 std::bitset<64> addr_low(be64toh(addr[1]));
755 std::bitset<64> addr_high(be64toh(addr[0]));
756 int bits = 0;
757 while(bits < max_bits) {
758 if (node->node6) ret = node->node6.get();
759 uint8_t val;
760 if (bits < 64) val = addr_high[63-bits];
761 else val = addr_low[127-bits];
762 if (val) {
763 if (node->right) node = node->right.get();
764 else break;
765 } else {
766 if (node->left) node = node->left.get();
767 else break;
768 }
769 bits++;
770 }
771 if (node->node6) ret = node->node6.get();
772 }
773
774 // this can be nullptr.
775 return ret;
776 }
777
11f4719b
RG
778 void cleanup_tree(TreeNode* node)
779 {
780 // only cleanup this node if it has no children and node4 and node6 are both empty
781 if (!(node->left || node->right || node->node6 || node->node4)) {
782 // get parent node ptr
342114ca 783 TreeNode* pparent = node->parent;
11f4719b 784 // delete this node
342114ca
AT
785 if (pparent) {
786 if (pparent->left.get() == node)
787 pparent->left.reset();
11f4719b 788 else
342114ca 789 pparent->right.reset();
11f4719b 790 // now recurse up to the parent
342114ca 791 cleanup_tree(pparent);
11f4719b
RG
792 }
793 }
794 }
795
2dfbbc41 796 //<! Removes key from TreeMap. This does not clean up the tree.
44845aab
AT
797 void erase(const key_type& key) {
798 TreeNode *node = root.get();
799
800 // no tree, no value
801 if ( node == nullptr ) return;
802
803 // exact same thing as above, except
804 if (key.getNetwork().sin4.sin_family == AF_INET) {
805 std::bitset<32> addr(be32toh(key.getNetwork().sin4.sin_addr.s_addr));
806 int bits = 0;
807 while(node && bits < key.getBits()) {
808 uint8_t val = addr[31-bits];
809 if (val) {
810 node = node->right.get();
811 } else {
812 node = node->left.get();
813 }
814 bits++;
815 }
816 if (node) {
462dd712 817 _nodes.erase(node->node4.get());
44845aab 818 node->node4.reset();
11f4719b
RG
819
820 if (d_cleanup_tree)
821 cleanup_tree(node);
44845aab
AT
822 }
823 } else {
89ae2052
OM
824 uint64_t addr[2];
825 memcpy(addr, key.getNetwork().sin6.sin6_addr.s6_addr, sizeof(addr));
44845aab
AT
826 std::bitset<64> addr_low(be64toh(addr[1]));
827 std::bitset<64> addr_high(be64toh(addr[0]));
828 int bits = 0;
829 while(node && bits < key.getBits()) {
830 uint8_t val;
831 if (bits < 64) val = addr_high[63-bits];
832 else val = addr_low[127-bits];
833 if (val) {
834 node = node->right.get();
835 } else {
836 node = node->left.get();
837 }
838 bits++;
839 }
840 if (node) {
462dd712 841 _nodes.erase(node->node6.get());
44845aab 842 node->node6.reset();
11f4719b
RG
843
844 if (d_cleanup_tree)
845 cleanup_tree(node);
44845aab
AT
846 }
847 }
848 }
849
850 void erase(const string& key) {
851 erase(key_type(key));
852 }
853
854 //<! checks whether the container is empty.
855 bool empty() const {
856 return _nodes.empty();
857 }
858
859 //<! returns the number of elements
860 size_type size() const {
861 return _nodes.size();
862 }
863
864 //<! See if given ComboAddress matches any prefix
865 bool match(const ComboAddress& value) const {
866 return (lookup(value) != nullptr);
867 }
868
869 bool match(const std::string& value) const {
870 return match(ComboAddress(value));
871 }
872
873 //<! Clean out the tree
874 void clear() {
875 _nodes.clear();
876 root.reset(nullptr);
877 }
878
879 //<! swaps the contents, rhs is left with nullptr.
880 void swap(NetmaskTree& rhs) {
881 root.swap(rhs.root);
882 _nodes.swap(rhs._nodes);
883 }
884
885private:
886 unique_ptr<TreeNode> root; //<! Root of our tree
462dd712 887 std::set<node_type*> _nodes; //<! Container for actual values
11f4719b 888 bool d_cleanup_tree; //<! Whether or not to cleanup the tree on erase
44845aab
AT
889};
890
12c86877
BH
891/** This class represents a group of supplemental Netmask classes. An IP address matchs
892 if it is matched by zero or more of the Netmask classes within.
893*/
894class NetmaskGroup
895{
896public:
11f4719b
RG
897 //! By default, initialise the tree to cleanup
898 NetmaskGroup() noexcept : NetmaskGroup(true) {
899 }
900
901 //! This allows control over whether to cleanup or not
902 NetmaskGroup(bool cleanup) noexcept : tree(cleanup) {
903 }
904
12c86877 905 //! If this IP address is matched by any of the classes within
60af67b8 906
1e77c17c 907 bool match(const ComboAddress *ip) const
12c86877 908 {
ee15a1e1
PD
909 const auto &ret = tree.lookup(*ip);
910 if(ret) return ret->second;
911 return false;
12c86877 912 }
60af67b8 913
1e77c17c 914 bool match(const ComboAddress& ip) const
60af67b8 915 {
916 return match(&ip);
917 }
918
11f4719b
RG
919 bool lookup(const ComboAddress* ip, Netmask* nmp) const
920 {
921 const auto &ret = tree.lookup(*ip);
922 if (ret) {
923 if (nmp != nullptr)
924 *nmp = ret->first;
925
926 return ret->second;
927 }
928 return false;
929 }
930
931 bool lookup(const ComboAddress& ip, Netmask* nmp) const
932 {
933 return lookup(&ip, nmp);
934 }
935
376effcf 936 //! Add this string to the list of possible matches
ee15a1e1 937 void addMask(const string &ip, bool positive=true)
12c86877 938 {
ee15a1e1
PD
939 if(!ip.empty() && ip[0] == '!') {
940 addMask(Netmask(ip.substr(1)), false);
941 } else {
942 addMask(Netmask(ip), positive);
943 }
12c86877 944 }
68b011bd 945
376effcf 946 //! Add this Netmask to the list of possible matches
ee15a1e1 947 void addMask(const Netmask& nm, bool positive=true)
376effcf 948 {
ee15a1e1 949 tree.insert(nm).second=positive;
376effcf 950 }
951
11f4719b
RG
952 //! Delete this Netmask from the list of possible matches
953 void deleteMask(const Netmask& nm)
954 {
955 tree.erase(nm);
956 }
957
958 void deleteMask(const std::string& ip)
959 {
960 if (!ip.empty())
961 deleteMask(Netmask(ip));
962 }
963
68b011bd
KM
964 void clear()
965 {
5ac553e1 966 tree.clear();
68b011bd
KM
967 }
968
5ac553e1 969 bool empty() const
12c86877 970 {
5ac553e1 971 return tree.empty();
12c86877
BH
972 }
973
5ac553e1 974 size_t size() const
2c95fc65 975 {
5ac553e1 976 return tree.size();
2c95fc65
BH
977 }
978
979 string toString() const
980 {
981 ostringstream str;
5ac553e1
AT
982 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
983 if(iter != tree.begin())
4957a608 984 str <<", ";
ee15a1e1
PD
985 if(!((*iter)->second))
986 str<<"!";
5ac553e1 987 str<<(*iter)->first.toString();
2c95fc65
BH
988 }
989 return str.str();
990 }
991
41942bb3
CH
992 void toStringVector(vector<string>* vec) const
993 {
ee15a1e1
PD
994 for(auto iter = tree.begin(); iter != tree.end(); ++iter) {
995 vec->push_back(((*iter)->second ? "" : "!") + (*iter)->first.toString());
996 }
41942bb3
CH
997 }
998
68b011bd
KM
999 void toMasks(const string &ips)
1000 {
1001 vector<string> parts;
1002 stringtok(parts, ips, ", \t");
1003
1004 for (vector<string>::const_iterator iter = parts.begin(); iter != parts.end(); ++iter)
1005 addMask(*iter);
1006 }
1007
12c86877 1008private:
5ac553e1 1009 NetmaskTree<bool> tree;
12c86877
BH
1010};
1011
002c970a 1012
60c8afa8 1013struct SComboAddress
1014{
1015 SComboAddress(const ComboAddress& orig) : ca(orig) {}
1016 ComboAddress ca;
1017 bool operator<(const SComboAddress& rhs) const
1018 {
1019 return ComboAddress::addressOnlyLessThan()(ca, rhs.ca);
1020 }
1021 operator const ComboAddress&()
1022 {
1023 return ca;
1024 }
1025};
1026
73ba5999
CHB
1027class NetworkError : public runtime_error
1028{
1029public:
1030 NetworkError(const string& why="Network Error") : runtime_error(why.c_str())
1031 {}
1032 NetworkError(const char *why="Network Error") : runtime_error(why)
1033 {}
1034};
60c8afa8 1035
002c970a 1036int SSocket(int family, int type, int flags);
1037int SConnect(int sockfd, const ComboAddress& remote);
51959320
RG
1038/* tries to connect to remote for a maximum of timeout seconds.
1039 sockfd should be set to non-blocking beforehand.
1040 returns 0 on success (the socket is writable), throw a
1041 runtime_error otherwise */
1042int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout);
002c970a 1043int SBind(int sockfd, const ComboAddress& local);
1044int SAccept(int sockfd, ComboAddress& remote);
1045int SListen(int sockfd, int limit);
1046int SSetsockopt(int sockfd, int level, int opname, int value);
90f9fbc0 1047void setSocketIgnorePMTU(int sockfd);
002c970a 1048
3e3f0358 1049#if defined(IP_PKTINFO)
1050 #define GEN_IP_PKTINFO IP_PKTINFO
1051#elif defined(IP_RECVDSTADDR)
1052 #define GEN_IP_PKTINFO IP_RECVDSTADDR
1053#endif
4d39d7f3 1054
3e3f0358 1055bool IsAnyAddress(const ComboAddress& addr);
2b3eefc3 1056bool HarvestDestinationAddress(const struct msghdr* msgh, ComboAddress* destination);
3e3f0358 1057bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv);
7bec330a 1058void fillMSGHdr(struct msghdr* msgh, struct iovec* iov, cmsgbuf_aligned* cbuf, size_t cbufsize, char* data, size_t datalen, ComboAddress* addr);
a683e8bd 1059ssize_t sendfromto(int sock, const char* data, size_t len, int flags, const ComboAddress& from, const ComboAddress& to);
6714b6ac
RG
1060size_t sendMsgWithOptions(int fd, const char* buffer, size_t len, const ComboAddress* dest, const ComboAddress* local, unsigned int localItf, int flags);
1061
840ed663
RG
1062/* requires a non-blocking, connected TCP socket */
1063bool isTCPSocketUsable(int sock);
f9f9592e
AT
1064
1065extern template class NetmaskTree<bool>;
17bca36a
RG
1066
1067#endif