00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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 void* bytes, unsigned len) {
00100 assert(len == address_size);
00101 _addr.s_addr = *static_cast<const u_int32_t*>(bytes);
00102 }
00103
00108 IPv4Address(const std::string& s)
00109 : _addr(resolve(s)._addr)
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 addr.s_addr = 0;
00122
00123 unsigned i;
00124
00125 for (i = 0; i + 8 < address_size * 8 && i + 8 < prefix; i += 8, ++raw)
00126 *raw = 0xff;
00127
00128 *raw = 0xff << (8 - (prefix - i));
00129 return addr;
00130 }
00131
00136 const unsigned char* bytes() const {
00137 return reinterpret_cast<const unsigned char*>(&_addr.s_addr);
00138 }
00139
00144 const std::string to_string() const {
00145 return std::string(::inet_ntoa(_addr));
00146 }
00147
00153 const sockaddr_t make_sockaddr(u_int16_t port) const {
00154 sockaddr_t sin;
00155
00156 memset(&sin, 0, sizeof sin);
00157 sin.sin_family = AF_INET;
00158 sin.sin_addr = _addr;
00159 sin.sin_port = htons(port);
00160
00161 return sin;
00162 }
00163
00168 void dump(void* p) const {
00169 *static_cast<addr_t*>(p) = _addr;
00170 }
00171
00176 bool is_linklocal() const {
00177 return false;
00178 }
00179
00180 static const This addr_any;
00181
00185 static void set_scope_index(sockaddr_t&, unsigned) {}
00186
00192 static unsigned netmask_to_prefix(const This& nm) {
00193 unsigned prefix = 0;
00194
00195 if (ntohl(nm._addr.s_addr) == 0xffffffff)
00196 return 32;
00197 else if (ntohl(nm._addr.s_addr) == 0)
00198 return 0;
00199
00200 if ((ntohl(nm._addr.s_addr) & 0xffff0000) == 0xffff0000)
00201 prefix += 16;
00202
00203 if ((ntohl(nm._addr.s_addr) & 0xffffff00) == 0xffffff00)
00204 prefix += 8;
00205
00206 while (prefix < 31)
00207 if ((ntohl(nm._addr.s_addr) & (0xffffffff << (31 - prefix))) ==
00208 (0xffffffff << (31 - prefix)))
00209 ++prefix;
00210 else
00211 break;
00212
00213 return prefix;
00214 }
00215
00222 static const This network(const This& a, unsigned prefix) {
00223 assert(prefix <= 32);
00224 This ret(a);
00225 unsigned int addr = ntohl(ret._addr.s_addr);
00226 unsigned cprefix = 32 - prefix;
00227 unsigned i;
00228
00229 for (i = 0; i + 8 <= cprefix; i += 8)
00230 addr &= ~(0xffU << i);
00231
00232 for (; i < cprefix; ++i)
00233 addr &= ~(1 << i);
00234
00235 ret._addr.s_addr = htonl(addr);
00236
00237 return ret;
00238 }
00239
00245 static const This resolve(const std::string& s) {
00246 ::size_t hstbuflen = 1024;
00247 ::hostent hostbuf;
00248 ::hostent* hp;
00249 int herr;
00250 int ret;
00251
00252 char* tmphstbuf = new char[hstbuflen];
00253
00254 while ((ret = gethostbyname2_r(s.c_str(),
00255 AF_INET,
00256 &hostbuf,
00257 tmphstbuf,
00258 hstbuflen,
00259 &hp,
00260 &herr)) == ERANGE) {
00261 hstbuflen *= 2;
00262 delete[] tmphstbuf;
00263 tmphstbuf = new char[hstbuflen];
00264 }
00265
00266 if (ret || hp == NULL) {
00267 throw std::runtime_error(std::string("Resolving ") +
00268 s +
00269 std::string(": ") +
00270 std::string(::hstrerror(herr)));
00271 }
00272
00273 return IPv4Address(*((::in_addr*)hp->h_addr));
00274 }
00275
00281 bool operator<(const This& rhs) const {
00282 return ntohl(_addr.s_addr) < ntohl(rhs._addr.s_addr);
00283 }
00284
00290 bool operator==(const This& rhs) const {
00291 return _addr.s_addr == rhs._addr.s_addr;
00292 }
00293
00299 bool operator!=(const This& rhs) const {
00300 return !operator==(rhs);
00301 }
00302
00307 unsigned long hash() const {
00308 return (unsigned long) _addr.s_addr;
00309 }
00310
00311 private:
00312 ::in_addr _addr;
00313 };
00314
00315 const IPv4Address IPv4Address::addr_any((::in_addr) { INADDR_ANY });
00316
00317 std::ostream&
00318 operator << (std::ostream& o, const IPv4Address& a)
00319 {
00320 return o << a.to_string();
00321 }
00322
00323 }
00324
00325 }
00326
00327 #endif // ! QOLYESTER_IPV4_HH