Kea 2.2.0
io_address.cc
Go to the documentation of this file.
1// Copyright (C) 2010-2020 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
10#include <asiolink/io_error.h>
12
13#include <boost/static_assert.hpp>
14// moved to container_hash on recent boost versions (backward compatible)
15#include <boost/functional/hash.hpp>
16
17#include <unistd.h> // for some IPC/network system calls
18#include <stdint.h>
19#include <sys/socket.h>
20#include <netinet/in.h>
21
22using namespace boost::asio;
23using boost::asio::ip::udp;
24using boost::asio::ip::tcp;
25
26using namespace std;
27
28namespace isc {
29namespace asiolink {
30
31// XXX: we cannot simply construct the address in the initialization list,
32// because we'd like to throw our own exception on failure.
33IOAddress::IOAddress(const std::string& address_str) {
34 boost::system::error_code err;
35 asio_address_ = ip::address::from_string(address_str, err);
36 if (err) {
37 isc_throw(IOError, "Failed to convert string to address '"
38 << address_str << "': " << err.message());
39 }
40}
41
42IOAddress::IOAddress(const boost::asio::ip::address& asio_address) :
43 asio_address_(asio_address)
44{}
45
46IOAddress::IOAddress(uint32_t v4address):
47 asio_address_(boost::asio::ip::address_v4(v4address)) {
48
49}
50
51string
53 return (asio_address_.to_string());
54}
55
57IOAddress::fromBytes(short family, const uint8_t* data) {
58 if (data == NULL) {
59 isc_throw(BadValue, "NULL pointer received.");
60 } else
61 if ( (family != AF_INET) && (family != AF_INET6) ) {
62 isc_throw(BadValue, "Invalid family type. Only AF_INET and AF_INET6"
63 << "are supported");
64 }
65
66 BOOST_STATIC_ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
67 char addr_str[INET6_ADDRSTRLEN];
68 inet_ntop(family, data, addr_str, INET6_ADDRSTRLEN);
69 return IOAddress(string(addr_str));
70}
71
72std::vector<uint8_t>
74 if (asio_address_.is_v4()) {
75 const boost::asio::ip::address_v4::bytes_type bytes4 =
76 asio_address_.to_v4().to_bytes();
77 return (std::vector<uint8_t>(bytes4.begin(), bytes4.end()));
78 }
79
80 // Not V4 address, so must be a V6 address (else we could never construct
81 // this object).
82 const boost::asio::ip::address_v6::bytes_type bytes6 =
83 asio_address_.to_v6().to_bytes();
84 return (std::vector<uint8_t>(bytes6.begin(), bytes6.end()));
85}
86
87short
89 if (asio_address_.is_v4()) {
90 return (AF_INET);
91 } else {
92 return (AF_INET6);
93 }
94}
95
96bool
98 if (!asio_address_.is_v6()) {
99 return (false);
100 }
101 return (asio_address_.to_v6().is_link_local());
102}
103
104bool
106 if (!asio_address_.is_v6()) {
107 return (false);
108 }
109 return (asio_address_.to_v6().is_multicast());
110}
111
112uint32_t
114 if (asio_address_.is_v4()) {
115 return (asio_address_.to_v4().to_ulong());
116 } else {
117 isc_throw(BadValue, "Can't convert " << toText()
118 << " address to IPv4.");
119 }
120}
121
122std::ostream&
123operator<<(std::ostream& os, const IOAddress& address) {
124 os << address.toText();
125 return (os);
126}
127
128IOAddress
130 if (a.getFamily() != b.getFamily()) {
131 isc_throw(BadValue, "Both addresses have to be the same family");
132 }
133 if (a.isV4()) {
134 // Subtracting v4 is easy. We have a conversion function to uint32_t.
135 return (IOAddress(a.toUint32() - b.toUint32()));
136 } else {
137 // v6 is more involved.
138
139 // Let's extract the raw data first.
140 vector<uint8_t> a_vec = a.toBytes();
141 vector<uint8_t> b_vec = b.toBytes();
142
143 // ... and prepare the result
144 vector<uint8_t> result(V6ADDRESS_LEN,0);
145
146 // Carry is a boolean, but to avoid its frequent casting, let's
147 // use uint8_t. Also, some would prefer to call it borrow, but I prefer
148 // carry. Somewhat relevant discussion here:
149 // http://en.wikipedia.org/wiki/Carry_flag#Carry_flag_vs._Borrow_flag
150 uint8_t carry = 0;
151
152 // Now perform subtraction with borrow.
153 for (int i = a_vec.size() - 1; i >= 0; --i) {
154 result[i] = a_vec[i] - b_vec[i] - carry;
155 carry = (a_vec[i] < b_vec[i] + carry);
156 }
157
158 return (fromBytes(AF_INET6, &result[0]));
159 }
160}
161
164 std::vector<uint8_t> packed(addr.toBytes());
165
166 // Start increasing the least significant byte
167 for (int i = packed.size() - 1; i >= 0; --i) {
168 // if we haven't overflowed (0xff -> 0x0), than we are done
169 if (++packed[i] != 0) {
170 break;
171 }
172 }
173
174 return (IOAddress::fromBytes(addr.getFamily(), &packed[0]));
175}
176
177size_t
178hash_value(const IOAddress& address) {
179 if (address.isV4()) {
180 boost::hash<uint32_t> hasher;
181 return (hasher(address.toUint32()));
182 } else {
183 boost::hash<std::vector<uint8_t> > hasher;
184 return (hasher(address.toBytes()));
185 }
186}
187
188} // namespace asiolink
189} // namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.