Kea 1.5.0
io_address.cc
Go to the documentation of this file.
1// Copyright (C) 2010-2016 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
15#include <unistd.h> // for some IPC/network system calls
16#include <stdint.h>
17#include <sys/socket.h>
18#include <netinet/in.h>
19
20using namespace boost::asio;
21using boost::asio::ip::udp;
22using boost::asio::ip::tcp;
23
24using namespace std;
25
26namespace isc {
27namespace asiolink {
28
29// XXX: we cannot simply construct the address in the initialization list,
30// because we'd like to throw our own exception on failure.
31IOAddress::IOAddress(const std::string& address_str) {
32 boost::system::error_code err;
33 asio_address_ = ip::address::from_string(address_str, err);
34 if (err) {
35 isc_throw(IOError, "Failed to convert string to address '"
36 << address_str << "': " << err.message());
37 }
38}
39
40IOAddress::IOAddress(const boost::asio::ip::address& asio_address) :
41 asio_address_(asio_address)
42{}
43
44IOAddress::IOAddress(uint32_t v4address):
45 asio_address_(boost::asio::ip::address_v4(v4address)) {
46
47}
48
49string
51 return (asio_address_.to_string());
52}
53
55IOAddress::fromBytes(short family, const uint8_t* data) {
56 if (data == NULL) {
57 isc_throw(BadValue, "NULL pointer received.");
58 } else
59 if ( (family != AF_INET) && (family != AF_INET6) ) {
60 isc_throw(BadValue, "Invalid family type. Only AF_INET and AF_INET6"
61 << "are supported");
62 }
63
64 BOOST_STATIC_ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
65 char addr_str[INET6_ADDRSTRLEN];
66 inet_ntop(family, data, addr_str, INET6_ADDRSTRLEN);
67 return IOAddress(string(addr_str));
68}
69
70std::vector<uint8_t>
72 if (asio_address_.is_v4()) {
73 const boost::asio::ip::address_v4::bytes_type bytes4 =
74 asio_address_.to_v4().to_bytes();
75 return (std::vector<uint8_t>(bytes4.begin(), bytes4.end()));
76 }
77
78 // Not V4 address, so must be a V6 address (else we could never construct
79 // this object).
80 const boost::asio::ip::address_v6::bytes_type bytes6 =
81 asio_address_.to_v6().to_bytes();
82 return (std::vector<uint8_t>(bytes6.begin(), bytes6.end()));
83}
84
85short
87 if (asio_address_.is_v4()) {
88 return (AF_INET);
89 } else {
90 return (AF_INET6);
91 }
92}
93
94bool
96 if (!asio_address_.is_v6()) {
97 return (false);
98 }
99 return (asio_address_.to_v6().is_link_local());
100}
101
102bool
104 if (!asio_address_.is_v6()) {
105 return (false);
106 }
107 return (asio_address_.to_v6().is_multicast());
108}
109
110uint32_t
112 if (asio_address_.is_v4()) {
113 return (asio_address_.to_v4().to_ulong());
114 } else {
115 isc_throw(BadValue, "Can't convert " << toText()
116 << " address to IPv4.");
117 }
118}
119
120std::ostream&
121operator<<(std::ostream& os, const IOAddress& address) {
122 os << address.toText();
123 return (os);
124}
125
126IOAddress
128 if (a.getFamily() != b.getFamily()) {
129 isc_throw(BadValue, "Both addresses have to be the same family");
130 }
131 if (a.isV4()) {
132 // Subtracting v4 is easy. We have a conversion function to uint32_t.
133 return (IOAddress(a.toUint32() - b.toUint32()));
134 } else {
135 // v6 is more involved.
136
137 // Let's extract the raw data first.
138 vector<uint8_t> a_vec = a.toBytes();
139 vector<uint8_t> b_vec = b.toBytes();
140
141 // ... and prepare the result
142 vector<uint8_t> result(V6ADDRESS_LEN,0);
143
144 // Carry is a boolean, but to avoid its frequent casting, let's
145 // use uint8_t. Also, some would prefer to call it borrow, but I prefer
146 // carry. Somewhat relevant discussion here:
147 // http://en.wikipedia.org/wiki/Carry_flag#Carry_flag_vs._Borrow_flag
148 uint8_t carry = 0;
149
150 // Now perform subtraction with borrow.
151 for (int i = a_vec.size() - 1; i >= 0; --i) {
152 result[i] = a_vec[i] - b_vec[i] - carry;
153 carry = (a_vec[i] < b_vec[i] + carry);
154 }
155
156 return (fromBytes(AF_INET6, &result[0]));
157 }
158}
159
162 std::vector<uint8_t> packed(addr.toBytes());
163
164 // Start increasing the least significant byte
165 for (int i = packed.size() - 1; i >= 0; --i) {
166 // if we haven't overflowed (0xff -> 0x0), than we are done
167 if (++packed[i] != 0) {
168 break;
169 }
170 }
171
172 return (IOAddress::fromBytes(addr.getFamily(), &packed[0]));
173}
174
175
176} // namespace asiolink
177} // 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-dhcp-ddns.