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 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 }
00322
00323 }
00324
00325 #endif // ! QOLYESTER_IPV4_HH