Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

ipv6.hh

Go to the documentation of this file.
00001 // Copyright (C) 2003, 2004, 2005 Laboratoire de Recherche en Informatique
00002 
00003 // This file is part of Qolyester.
00004 
00005 // Qolyester is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 
00010 // Qolyester is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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 u_int8_t* 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(u_int8_t* p) const {
00196         *(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   } // namespace net
00369 
00370 } // namespace olsr
00371 
00372 #endif // ! QOLYESTER_IPV6_HH

Generated on Thu Jul 28 21:21:47 2005 for Qolyester daemon by  doxygen 1.4.1