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

ipv4.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_IPV4_HH
00028 # define QOLYESTER_IPV4_HH 1
00029 
00030 # include <netinet/in.h>
00031 # include <netdb.h>
00032 # include <arpa/inet.h>
00033 # include <cassert>
00034 # include <cstring>
00035 # include <ostream>
00036 # include <stdexcept>
00037 # include <cerrno>
00038 
00039 namespace olsr {
00040 
00041   namespace net {
00042 
00043     // The definition of IPv4 addresses.
00044 
00049     class IPv4Address {
00050       typedef IPv4Address       This;
00051     public:
00052 
00057       typedef sockaddr_in               sockaddr_t;
00062       typedef in_addr                   addr_t;
00063 
00064       enum {
00065         address_size  = sizeof (addr_t), 
00066         proto         = PF_INET,         
00067         family        = AF_INET,         
00068         header_length = 28               
00069       };
00070 
00074       IPv4Address() {
00075         _addr.s_addr = 0;
00076       }
00077 
00082       IPv4Address(const sockaddr_t& s) {
00083         _addr = s.sin_addr;
00084       }
00085 
00090       IPv4Address(const addr_t& a) {
00091         _addr = a;
00092       }
00093 
00099       IPv4Address(const u_int8_t* bytes, unsigned len) {
00100         assert(len == address_size);
00101         _addr.s_addr = *(unsigned*) bytes;
00102       }
00103 
00108       IPv4Address(const std::string& s) {
00109         *this = resolve(s);
00110       }
00111 
00116       static This       netmask(unsigned prefix) {
00117         assert(prefix <= 32);
00118         addr_t          addr;
00119         u_int8_t*       raw = reinterpret_cast<u_int8_t*>(&addr);
00120 
00121         unsigned        i;
00122 
00123         for (i = 0; i + 8 < address_size * 8 && i + 8 < prefix; i += 8, ++raw)
00124           *raw = 0xff;
00125 
00126         *raw = 0xff << (8 - (prefix - i));
00127         return addr;
00128       }
00129 
00134       const unsigned char*      bytes() const {
00135         return reinterpret_cast<const unsigned char*>(&_addr.s_addr);
00136       }
00137 
00142       const std::string to_string() const {
00143         return std::string(::inet_ntoa(_addr));
00144       }
00145 
00151       const sockaddr_t make_sockaddr(u_int16_t port) const {
00152         sockaddr_t      sin;
00153 
00154         memset(&sin, 0, sizeof sin);
00155         sin.sin_family = AF_INET;
00156         sin.sin_addr   = _addr;
00157         sin.sin_port   = htons(port);
00158 
00159         return sin;
00160       }
00161 
00166       void      dump(u_int8_t* p) const {
00167         *(addr_t*)p = _addr;
00168       }
00169 
00174       bool      is_linklocal() const {
00175         return false;
00176       }
00177 
00178       static const This addr_any; 
00179 
00183       static void set_scope_index(sockaddr_t&, unsigned) {}
00184 
00190       static unsigned   netmask_to_prefix(const This& nm) {
00191         unsigned        prefix = 0;
00192 
00193         if (nm._addr.s_addr == 0xffffffff)
00194           return 32;
00195         else if (nm._addr.s_addr == 0)
00196           return 0;
00197 
00198         if ((nm._addr.s_addr & htonl(0xffff0000)) == htonl(0xffff0000))
00199           prefix += 16;
00200 
00201         if ((nm._addr.s_addr & htonl(0xffffff00)) == htonl(0xffffff00))
00202           prefix += 8;
00203 
00204         while (prefix < 31)
00205           if ((nm._addr.s_addr & htonl((0xffffffff << (31 - prefix)))) ==
00206               htonl(((0xffffffff << (31 - prefix)))))
00207             ++prefix;
00208           else
00209             break;
00210 
00211         return prefix;
00212       }
00213 
00220       static const This network(const This& a, unsigned prefix) {
00221         assert(prefix <= 32);
00222         This            ret(a);
00223         unsigned int    addr = ntohl(ret._addr.s_addr);
00224         unsigned        cprefix = 32 - prefix;
00225         unsigned        i;
00226 
00227         for (i = 0; i + 8 <= cprefix; i += 8)
00228           addr &= ~(0xffU << i);
00229 
00230         for (; i < cprefix; ++i)
00231           addr &= ~(1 << i);
00232 
00233         ret._addr.s_addr = htonl(addr);
00234 
00235         return ret;
00236       }
00237 
00243       static const This resolve(const std::string& s) {
00244         ::size_t        hstbuflen = 1024;
00245         ::hostent       hostbuf;
00246         ::hostent*      hp;
00247         int             herr;
00248         int             ret;
00249 
00250         char*   tmphstbuf = new char[hstbuflen];
00251 
00252         while ((ret = gethostbyname2_r(s.c_str(),
00253                                            AF_INET,
00254                                            &hostbuf,
00255                                            tmphstbuf,
00256                                            hstbuflen,
00257                                            &hp,
00258                                            &herr)) == ERANGE) {
00259           hstbuflen *= 2;
00260           delete[] tmphstbuf;
00261           tmphstbuf = new char[hstbuflen];
00262         }
00263 
00264         if (ret || hp == NULL) {
00265           throw std::runtime_error(std::string("Resolving ") +
00266                                    s +
00267                                    std::string(": ") +
00268                                    std::string(::hstrerror(herr)));
00269         }
00270 
00271         return IPv4Address(*((::in_addr*)hp->h_addr));
00272       }
00273 
00279       bool      operator<(const This& rhs) const {
00280         return ntohl(_addr.s_addr) < ntohl(rhs._addr.s_addr);
00281       }
00282 
00288       bool      operator==(const This& rhs) const {
00289         return _addr.s_addr == rhs._addr.s_addr;
00290       }
00291 
00297       bool      operator!=(const This& rhs) const {
00298         return !operator==(rhs);
00299       }
00300 
00305       unsigned long     hash() const {
00306         return (unsigned long) _addr.s_addr;
00307       }
00308 
00309     private:
00310       ::in_addr _addr; 
00311     };
00312 
00313     const IPv4Address   IPv4Address::addr_any((::in_addr) { INADDR_ANY });
00314 
00315     std::ostream&
00316     operator << (std::ostream& o, const IPv4Address& a)
00317     {
00318       return o << a.to_string();
00319     }
00320 
00321   } // namespace net
00322 
00323 } // namespace olsr
00324 
00325 #endif // ! QOLYESTER_IPV4_HH

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