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 }
00130
00131 if (prefix % 32 == 0)
00132 return addr;
00133
00134 unsigned index = prefix / 32 * 2;
00135 for (unsigned i = index; i < index + 2; ++i)
00136 if (i < prefix / 16)
00137 addr.s6_addr16[i] = 0xffff;
00138 else if (i > prefix / 16)
00139 addr.s6_addr16[i] = 0;
00140 else if (prefix % 16 == 0) {
00141 addr.s6_addr16[i] = 0;
00142 }
00143
00144 if (prefix % 16 == 0)
00145 return addr;
00146
00147 index = prefix / 16 * 2;
00148 for (unsigned i = index; i < index + 2; ++i)
00149 if (i < prefix / 8)
00150 addr.s6_addr[i] = 0xff;
00151 else if (i > prefix / 8)
00152 addr.s6_addr[i] = 0;
00153 else if (prefix % 8 == 0) {
00154 addr.s6_addr[i] = 0;
00155 }
00156
00157 if (prefix % 8 == 0)
00158 return addr;
00159
00160 addr.s6_addr[prefix / 8] = 0xff << (8 - (prefix % 8));
00161 return addr;
00162 }
00163
00168 const unsigned char* bytes() const {
00169 return reinterpret_cast<const unsigned char*>(&_addr.s6_addr);
00170 }
00171
00176 const std::string to_string() const {
00177 char buffer[INET6_ADDRSTRLEN];
00178 return std::string(inet_ntop(AF_INET6, &_addr, buffer, sizeof buffer));
00179 }
00180
00186 const sockaddr_t make_sockaddr(u_int16_t port) const {
00187 sockaddr_t sin6;
00188
00189 memset(&sin6, 0, sizeof sin6);
00190 sin6.sin6_family = AF_INET6;
00191 sin6.sin6_addr = _addr;
00192 sin6.sin6_port = htons(port);
00193
00194 return sin6;
00195 }
00196
00201 void dump(void* p) const {
00202 *static_cast<addr_t*>(p) = _addr;
00203 }
00204
00209 bool is_linklocal() const {
00210 return IN6_IS_ADDR_LINKLOCAL(&_addr);
00211 }
00212
00218 static void set_scope_index(sockaddr_t& sin, unsigned index) {
00219 sin.sin6_scope_id = index;
00220 }
00221
00222 static const This addr_any;
00223
00230 static const This network(const This& a, unsigned prefix) {
00231 assert(prefix <= 128);
00232 This ret(a);
00233 unsigned cprefix = 128 - prefix;
00234 unsigned i;
00235
00236 for (i = 0; i + 32 <= cprefix; i += 32)
00237 ret._addr.s6_addr32[3 - i / 32] = 0;
00238
00239 if (i < cprefix && i + 16 <= cprefix) {
00240 ret._addr.s6_addr16[7 - i / 16] = 0;
00241 i += 16;
00242 }
00243
00244 if (i < cprefix && i + 8 <= cprefix) {
00245 ret._addr.s6_addr[15 - i / 8] = 0;
00246 i += 8;
00247 }
00248
00249 for (; i < cprefix; ++i)
00250 ret._addr.s6_addr[15 - i / 8] &= ~(1 << (i % 8));
00251
00252 return ret;
00253 }
00254
00260 static unsigned netmask_to_prefix(const This& nm) {
00261 unsigned prefix = 0;
00262 for (prefix = 0; prefix < 128;)
00263 if (nm._addr.s6_addr32[prefix / 32] == 0xffffffff)
00264 prefix += 32;
00265 else
00266 break;
00267
00268 if (prefix < 128 && nm._addr.s6_addr16[prefix / 16] == 0xffff)
00269 prefix += 16;
00270
00271 if (prefix < 128 && nm._addr.s6_addr[prefix / 8] == 0xff)
00272 prefix += 8;
00273
00274 while (prefix < 128)
00275 if (nm._addr.s6_addr[prefix / 8] & (1 << (7 - (prefix % 8))))
00276 ++prefix;
00277 else
00278 break;
00279
00280 return prefix;
00281 }
00282
00288 static const This resolve(const std::string& s) {
00289 size_t hstbuflen = 1024;
00290 hostent hostbuf;
00291 hostent* hp;
00292 int herr;
00293 int ret;
00294
00295 char* tmphstbuf = new char[hstbuflen];
00296
00297 while ((ret = gethostbyname2_r(s.c_str(),
00298 AF_INET6,
00299 &hostbuf,
00300 tmphstbuf,
00301 hstbuflen,
00302 &hp,
00303 &herr)) == ERANGE) {
00304 hstbuflen *= 2;
00305 delete[] tmphstbuf;
00306 tmphstbuf = new char[hstbuflen];
00307 }
00308
00309 if (ret || hp == NULL) {
00310 throw std::runtime_error(std::string("Resolving ") +
00311 s +
00312 std::string(": ") +
00313 std::string(::hstrerror(herr)));
00314 }
00315
00316 return IPv6Address(*((addr_t*)hp->h_addr));
00317 }
00318
00324 bool operator<(const This& rhs) const {
00325 for (int i = 0; i < 4; ++i)
00326 if (ntohl(_addr.s6_addr32[i]) < ntohl(rhs._addr.s6_addr32[i]))
00327 return true;
00328 else if (ntohl(rhs._addr.s6_addr32[i]) < ntohl(_addr.s6_addr32[i]))
00329 break;
00330 return false;
00331 }
00332
00338 bool operator==(const This& rhs) const {
00339 for (int i = 0; i < 4; ++i)
00340 if (_addr.s6_addr32[i] != rhs._addr.s6_addr32[i])
00341 return false;
00342 return true;
00343 }
00344
00350 bool operator!=(const This& rhs) const {
00351 return !operator==(rhs);
00352 }
00353
00358 unsigned long hash() const {
00359 return (unsigned long) _addr.s6_addr32[3];
00360 }
00361
00362 private:
00363 in6_addr _addr;
00364 };
00365
00366 const IPv6Address IPv6Address::addr_any(in6addr_any);
00367
00368 std::ostream&
00369 operator << (std::ostream& o, const olsr::net::IPv6Address& a)
00370 {
00371 return o << a.to_string();
00372 }
00373
00374 }
00375
00376 }
00377
00378 #endif // ! QOLYESTER_IPV6_HH