4 #include <sys/socket.h> 5 #include <netinet/in.h> 8 #include <sys/socket.h> 15 int makeIPv6sockaddr(
const std::string& addr,
struct sockaddr_in6* ret);
16 int makeIPv4sockaddr(
const std::string& str,
struct sockaddr_in* ret);
18 constexpr uint32_t chtonl(uint32_t s)
21 ((s & 0x000000FF) << 24) | ((s & 0x0000FF00) << 8)
22 | ((s & 0xFF000000) >> 24) | ((s & 0x00FF0000) >> 8)
26 constexpr
struct sockaddr_in operator "" _ipv4(const char* p,
size_t l)
28 struct sockaddr_in ret={};
29 ret.sin_addr.s_addr=0;
30 ret.sin_family=AF_INET;
39 ret.sin_addr.s_addr*=0x100;
40 ret.sin_addr.s_addr+=octet;
48 ret.sin_addr.s_addr*=0x100;
49 ret.sin_addr.s_addr+=octet;
51 ret.sin_addr.s_addr = chtonl(ret.sin_addr.s_addr);
54 for(++n; n < l; ++n) {
56 ret.sin_port += p[n]-
'0';
58 ret.sin_port = 0x100 * (ret.sin_port&0xff) + (ret.sin_port/0x100);
79 struct sockaddr_in sin;
80 struct sockaddr_in sin4;
81 struct sockaddr_in6 sin6;
86 if(std::tie(sin4.sin_family, sin4.sin_port) != std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
88 if(sin4.sin_family == AF_INET)
89 return sin4.sin_addr.s_addr == rhs.sin4.sin_addr.s_addr;
91 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr,
sizeof(sin6.sin6_addr.s6_addr))==0;
97 return(!
operator==(rhs));
103 if(sin4.sin_family == 0) {
106 if(std::tie(sin4.sin_family, sin4.sin_port) < std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
108 if(std::tie(sin4.sin_family, sin4.sin_port) > std::tie(rhs.sin4.sin_family, rhs.sin4.sin_port))
111 if(sin4.sin_family == AF_INET)
112 return sin4.sin_addr.s_addr < rhs.sin4.sin_addr.s_addr;
114 return memcmp(&sin6.sin6_addr.s6_addr, &rhs.sin6.sin6_addr.s6_addr,
sizeof(sin6.sin6_addr.s6_addr)) < 0;
119 return rhs.operator<(*this);
146 if(a.sin4.sin_family < b.sin4.sin_family)
148 if(a.sin4.sin_family > b.sin4.sin_family)
150 if(a.sin4.sin_family == AF_INET)
151 return a.sin4.sin_addr.s_addr < b.sin4.sin_addr.s_addr;
153 return memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr,
sizeof(a.sin6.sin6_addr.s6_addr)) < 0;
161 if(a.sin4.sin_family != b.sin4.sin_family)
163 if(a.sin4.sin_family == AF_INET)
164 return a.sin4.sin_addr.s_addr == b.sin4.sin_addr.s_addr;
166 return !memcmp(&a.sin6.sin6_addr.s6_addr, &b.sin6.sin6_addr.s6_addr,
sizeof(a.sin6.sin6_addr.s6_addr));
173 if(sin4.sin_family == AF_INET)
182 sin4.sin_family=AF_INET;
183 sin4.sin_addr.s_addr=0;
189 setSockaddr(sa, salen);
194 setSockaddr((
const struct sockaddr*)sa,
sizeof(
struct sockaddr_in6));
199 setSockaddr((
const struct sockaddr*)sa,
sizeof(
struct sockaddr_in));
203 setSockaddr((
const struct sockaddr*)&sa,
sizeof(
struct sockaddr_in));
206 void setSockaddr(
const struct sockaddr *sa, socklen_t salen) {
207 if (salen >
sizeof(
struct sockaddr_in6))
throw std::runtime_error(
"ComboAddress can't handle other than sockaddr_in or sockaddr_in6");
208 memcpy(
this, sa, salen);
224 memset(&sin6, 0,
sizeof(sin6));
225 sin4.sin_family = AF_INET;
227 if(makeIPv4sockaddr(str, &sin4)) {
228 sin6.sin6_family = AF_INET6;
229 if(makeIPv6sockaddr(str, &sin6) < 0)
230 throw std::runtime_error(
"Unable to convert presentation address '"+ str +
"'");
234 sin4.sin_port=htons(port);
239 sin4.sin_port = htons(port);
244 return sin4.sin_family == AF_INET6;
250 return sin4.sin_family == AF_INET;
256 if(sin4.sin_family!=AF_INET6)
260 const unsigned char*ptr = (
unsigned char*) &sin6.sin6_addr.s6_addr;
261 for(n=0; n < 10; ++n)
276 throw std::runtime_error(
"ComboAddress can't map non-mapped IPv6 address back to IPv4");
278 ret.sin4.sin_family=AF_INET;
279 ret.sin4.sin_port=sin4.sin_port;
281 const unsigned char*ptr = (
unsigned char*) &sin6.sin6_addr.s6_addr;
282 ptr+=(
sizeof(sin6.sin6_addr.s6_addr) -
sizeof(ret.sin4.sin_addr.s_addr));
283 memcpy(&ret.sin4.sin_addr.s_addr, ptr,
sizeof(ret.sin4.sin_addr.s_addr));
291 if(sin4.sin_family && !getnameinfo((
struct sockaddr*)
this,
getSocklen(), host,
sizeof(host),0, 0, NI_NUMERICHOST))
300 if(sin4.sin_family==AF_INET)
301 return toString() +
":" + std::to_string(ntohs(sin4.sin_port));
303 return "["+
toString() +
"]:" + std::to_string(ntohs(sin4.sin_port));
306 void truncate(
unsigned int bits);
318 d_network.sin4.sin_family=0;
319 d_network.sin4.sin_port = 0;
329 bits = (network.sin4.sin_family == AF_INET) ? 32 : 128;
333 d_mask=~(0xFFFFFFFF>>d_bits);
341 std::pair<std::string,std::string> split;
344 if(!split.second.empty()) {
345 d_bits = (uint8_t)atoi(split.second.c_str());
347 d_mask=~(0xFFFFFFFF>>d_bits);
351 else if(d_network.sin4.sin_family==AF_INET) {
369 if(d_network.sin4.sin_family != ip->sin4.sin_family) {
372 if(d_network.sin4.sin_family == AF_INET) {
373 return match4(htonl((
unsigned int)ip->sin4.sin_addr.s_addr));
375 if(d_network.sin6.sin6_family == AF_INET6) {
376 uint8_t bytes=d_bits/8, n;
377 const uint8_t *us=(
const uint8_t*) &d_network.sin6.sin6_addr.s6_addr;
378 const uint8_t *them=(
const uint8_t*) &ip->sin6.sin6_addr.s6_addr;
380 for(n=0; n < bytes; ++n) {
386 uint8_t bits= d_bits % 8;
387 uint8_t mask= (uint8_t) ~(0xFF>>bits);
389 return((us[n] & mask) == (them[n] & mask));
395 bool match(
const std::string &ip)
const 398 return match(&address);
404 return (ip & d_mask) == (ntohl(d_network.sin4.sin_addr.s_addr) & d_mask);
409 return d_network.toString()+
"/"+std::to_string((
unsigned int)d_bits);
412 std::string toStringNoMask()
const 414 return d_network.toString();
424 result.sin4.sin_addr.s_addr = htonl(ntohl(result.sin4.sin_addr.s_addr) & d_mask);
428 uint8_t bytes=d_bits/8;
429 uint8_t *us=(uint8_t*) &result.sin6.sin6_addr.s6_addr;
430 uint8_t bits= d_bits % 8;
431 uint8_t mask= (uint8_t) ~(0xFF>>bits);
433 if (bytes <
sizeof(result.sin6.sin6_addr.s6_addr)) {
437 for(idx = bytes + 1; idx <
sizeof(result.sin6.sin6_addr.s6_addr); ++idx) {
449 return d_network.sin6.sin6_family == AF_INET6;
453 return d_network.sin4.sin_family == AF_INET;
458 return std::tie(d_network, d_bits) < std::tie(rhs.d_network, rhs.d_bits);
463 return std::tie(d_network, d_bits) == std::tie(rhs.d_network, rhs.d_bits);
468 return d_network.sin4.sin_family==0;
Definition: comboaddress.hh:78
bool operator!=(const ComboAddress &rhs) const
Inequality.
Definition: comboaddress.hh:95
Netmask(const std::string &mask)
Constructor supplies the mask, which cannot be changed.
Definition: comboaddress.hh:339
std::string toString() const
Returns a string (human) represntation of the address.
Definition: comboaddress.hh:288
bool match(const ComboAddress *ip) const
If this IP address in socket address matches.
Definition: comboaddress.hh:367
ComboAddress(const std::string &str, uint16_t port=0)
Definition: comboaddress.hh:222
ComboAddress mapToIPv4() const
Extract the IPv4 address from a mapped IPv6 address.
Definition: comboaddress.hh:273
bool isIPv4() const
Is this an IPv4 address?
Definition: comboaddress.hh:248
Convenience comparator that compares regardless of port.
Definition: comboaddress.hh:142
bool isMappedIPv4() const
Is this an ffff:: style IPv6 address?
Definition: comboaddress.hh:254
ComboAddress(const struct sockaddr_in *sa)
Make a ComboAddress from a traditional sockaddr_in.
Definition: comboaddress.hh:198
Definition: comboaddress.hh:313
ComboAddress(const struct sockaddr *sa, socklen_t salen)
Make a ComboAddress from a traditional sockaddr.
Definition: comboaddress.hh:188
bool match4(uint32_t ip) const
If this IP address in native format matches.
Definition: comboaddress.hh:402
bool operator<(const ComboAddress &rhs) const
This ordering is intended to be fast and strict, but not necessarily human friendly.
Definition: comboaddress.hh:101
socklen_t getSocklen() const
it is vital to pass the correct socklen to the kernel
Definition: comboaddress.hh:171
bool operator==(const ComboAddress &rhs) const
Tests for equality, including port number. IPv4 and IPv6 are never equal.
Definition: comboaddress.hh:84
void setPort(uint16_t port)
Sets port, deals with htons for you.
Definition: comboaddress.hh:237
ComboAddress(const struct sockaddr_in &sa)
Make a ComboAddress from a traditional sockaddr.
Definition: comboaddress.hh:202
ComboAddress(const struct sockaddr_in6 *sa)
Make a ComboAddress from a traditional sockaddr_in6.
Definition: comboaddress.hh:193
bool match(const std::string &ip) const
If this ASCII IP address matches.
Definition: comboaddress.hh:395
bool isIPv6() const
Is this an IPv6 address?
Definition: comboaddress.hh:242
Convenience comparator that compares regardless of port.
Definition: comboaddress.hh:157
std::string toStringWithPort() const
Returns a string (human) represntation of the address, including port.
Definition: comboaddress.hh:298
ComboAddress()
Initializes an 'empty', impossible, ComboAddress.
Definition: comboaddress.hh:180