00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00026
00027 #ifndef QOLYESTER_IPV6_HH
00028 # define QOLYESTER_IPV6_HH 1
00029
00030 # include <netinet/in.h>
00031 # include <netdb.h>
00032 # include <arpa/inet.h>
00033 # include <sys/socket.h>
00034 # include <sys/types.h>
00035 # include <cassert>
00036 # include <cstring>
00037 # include <cerrno>
00038 # include <ostream>
00039 # include <stdexcept>
00040
00041 namespace olsr {
00042
00043 namespace net {
00044
00049 class IPv6Address {
00050 typedef IPv6Address This;
00051 public:
00052
00057 typedef sockaddr_in6 sockaddr_t;
00062 typedef in6_addr addr_t;
00063
00064 enum {
00065 address_size = sizeof (addr_t),
00066 proto = PF_INET6,
00067 family = AF_INET6,
00068 header_length = 48
00069 };
00070
00074 IPv6Address() {
00075 _addr.s6_addr32[0] = _addr.s6_addr32[1] =
00076 _addr.s6_addr32[2] = _addr.s6_addr32[3] = 0;
00077 }
00078
00083 IPv6Address(const sockaddr_t& s)
00084 : _addr(s.sin6_addr)
00085 {}
00086
00091 IPv6Address(const addr_t& a)
00092 : _addr(a)
00093 {}
00094
00100 IPv6Address(const void* bytes, unsigned len) {
00101 assert(len == address_size);
00102 memcpy(_addr.s6_addr, bytes, len);
00103 }
00104
00109 IPv6Address(const std::string& s)
00110 : _addr(resolve(s)._addr)
00111 {}
00112
00117 static This netmask(unsigned prefix) {
00118 assert(prefix <= 128);
00119
00120 addr_t addr;
00121
00122 for (unsigned i = 0; i < 4; ++i)
00123 if (i < prefix / 32)
00124 addr.s6_addr32[i] = 0xffffffff;
00125 else if (i > prefix / 32)
00126 addr.s6_addr32[i] = 0;
00127 else if (prefix % 32 == 0) {
00128 addr.s6_addr32[i] = 0;
00129 return addr;
00130 }
00131
00132 unsigned index = prefix / 32 * 2;
00133 for (unsigned i = index; i < index + 2; ++i)
00134 if (i < prefix / 16)
00135 addr.s6_addr16[i] = 0xffff;
00136 else if (i > prefix / 16)
00137 addr.s6_addr16[i] = 0;
00138 else if (prefix % 16 == 0) {
00139 addr.s6_addr16[i] = 0;
00140 return addr;
00141 }
00142
00143 index = prefix / 16 * 2;
00144 for (unsigned i = index; i < index + 2; ++i)
00145 if (i < prefix / 8)
00146 addr.s6_addr[i] = 0xff;
00147 else if (i > prefix / 8)
00148 addr.s6_addr[i] = 0;
00149 else if (prefix % 8 == 0) {
00150 addr.s6_addr[i] = 0;
00151 return addr;
00152 }
00153
00154 addr.s6_addr[prefix / 8] = 0xff << (7 - (prefix % 8));
00155 return addr;
00156 }
00157
00162 const unsigned char* bytes() const {
00163 return reinterpret_cast<const unsigned char*>(&_addr.s6_addr);
00164 }
00165
00170 const std::string to_string() const {
00171 char buffer[INET6_ADDRSTRLEN];
00172 return std::string(inet_ntop(AF_INET6, &_addr, buffer, sizeof buffer));
00173 }
00174
00180 const sockaddr_t make_sockaddr(u_int16_t port) const {
00181 sockaddr_t sin6;
00182
00183 memset(&sin6, 0, sizeof sin6);
00184 sin6.sin6_family = AF_INET6;
00185 sin6.sin6_addr = _addr;
00186 sin6.sin6_port = htons(port);
00187
00188 return sin6;
00189 }
00190
00195 void dump(void* p) const {
00196 *static_cast<addr_t*>(p) = _addr;
00197 }
00198
00203 bool is_linklocal() const {
00204 return IN6_IS_ADDR_LINKLOCAL(&_addr);
00205 }
00206
00212 static void set_scope_index(sockaddr_t& sin, unsigned index) {
00213 sin.sin6_scope_id = index;
00214 }
00215
00216 static const This addr_any;
00217
00224 static const This network(const This& a, unsigned prefix) {
00225 assert(prefix <= 128);
00226 This ret(a);
00227 unsigned cprefix = 128 - prefix;
00228 unsigned i;
00229
00230 for (i = 0; i + 32 <= cprefix; i += 32)
00231 ret._addr.s6_addr32[3 - i / 32] = 0;
00232
00233 if (i < cprefix && i + 16 <= cprefix) {
00234 ret._addr.s6_addr16[7 - i / 16] = 0;
00235 i += 16;
00236 }
00237
00238 if (i < cprefix && i + 8 <= cprefix) {
00239 ret._addr.s6_addr[15 - i / 8] = 0;
00240 i += 8;
00241 }
00242
00243 for (; i < cprefix; ++i)
00244 ret._addr.s6_addr[15 - i / 8] &= ~(1 << (i % 8));
00245
00246 return ret;
00247 }
00248
00254 static unsigned netmask_to_prefix(const This& nm) {
00255 unsigned prefix = 0;
00256 for (prefix = 0; prefix < 128;)
00257 if (nm._addr.s6_addr32[prefix / 32] == 0xffffffff)
00258 prefix += 32;
00259 else
00260 break;
00261
00262 if (prefix < 128 && nm._addr.s6_addr16[prefix / 16] == 0xffff)
00263 prefix += 16;
00264
00265 if (prefix < 128 && nm._addr.s6_addr[prefix / 8] == 0xff)
00266 prefix += 8;
00267
00268 while (prefix < 128)
00269 if (nm._addr.s6_addr[prefix / 8] & (1 << (7 - (prefix % 8))))
00270 ++prefix;
00271 else
00272 break;
00273
00274 return prefix;
00275 }
00276
00282 static const This resolve(const std::string& s) {
00283 size_t hstbuflen = 1024;
00284 hostent hostbuf;
00285 hostent* hp;
00286 int herr;
00287 int ret;
00288
00289 char* tmphstbuf = new char[hstbuflen];
00290
00291 while ((ret = gethostbyname2_r(s.c_str(),
00292 AF_INET6,
00293 &hostbuf,
00294 tmphstbuf,
00295 hstbuflen,
00296 &hp,
00297 &herr)) == ERANGE) {
00298 hstbuflen *= 2;
00299 delete[] tmphstbuf;
00300 tmphstbuf = new char[hstbuflen];
00301 }
00302
00303 if (ret || hp == NULL) {
00304 throw std::runtime_error(std::string("Resolving ") +
00305 s +
00306 std::string(": ") +
00307 std::string(::hstrerror(herr)));
00308 }
00309
00310 return IPv6Address(*((addr_t*)hp->h_addr));
00311 }
00312
00318 bool operator<(const This& rhs) const {
00319 for (int i = 0; i < 4; ++i)
00320 if (ntohl(_addr.s6_addr32[i]) < ntohl(rhs._addr.s6_addr32[i]))
00321 return true;
00322 else if (ntohl(rhs._addr.s6_addr32[i]) < ntohl(_addr.s6_addr32[i]))
00323 break;
00324 return false;
00325 }
00326
00332 bool operator==(const This& rhs) const {
00333 for (int i = 0; i < 4; ++i)
00334 if (_addr.s6_addr32[i] != rhs._addr.s6_addr32[i])
00335 return false;
00336 return true;
00337 }
00338
00344 bool operator!=(const This& rhs) const {
00345 return !operator==(rhs);
00346 }
00347
00352 unsigned long hash() const {
00353 return (unsigned long) _addr.s6_addr32[3];
00354 }
00355
00356 private:
00357 in6_addr _addr;
00358 };
00359
00360 const IPv6Address IPv6Address::addr_any(in6addr_any);
00361
00362 std::ostream&
00363 operator << (std::ostream& o, const olsr::net::IPv6Address& a)
00364 {
00365 return o << a.to_string();
00366 }
00367
00368 }
00369
00370 }
00371
00372 #endif // ! QOLYESTER_IPV6_HH