1 /* 2 3 Firewall Builder 4 5 Copyright (C) 2008 NetCitadel, LLC 6 7 Author: Vadim Kurland vadim@fwbuilder.org 8 9 $Id$ 10 11 12 This program is free software which we release under the GNU General Public 13 License. You may redistribute and/or modify this program under the terms 14 of that license as published by the Free Software Foundation; either 15 version 2 of the License, or (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 To get a copy of the GNU General Public License, write to the Free Software 23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 25 */ 26 27 #ifndef __INETADDR_HH_FLAG__ 28 #define __INETADDR_HH_FLAG__ 29 30 #include <string> 31 #include <vector> 32 #include <typeinfo> 33 #include <assert.h> 34 35 #ifndef _WIN32 36 # include <sys/types.h> 37 # include <sys/socket.h> 38 # include <netinet/in.h> 39 # include <arpa/inet.h> 40 #else 41 # include <winsock2.h> 42 # include <wtypes.h> 43 # include <ws2tcpip.h> 44 45 typedef unsigned int uint32_t; 46 47 #endif 48 49 #include "fwbuilder/uint128.h" 50 #include "fwbuilder/libfwbuilder-config.h" 51 #include "fwbuilder/FWException.h" 52 53 namespace libfwbuilder 54 { 55 56 /** 57 * Class InetAddr is a wrapper for struct inet_addr and in6_addr 58 * 59 * Why both address families are implemented as the same class ? Mostly 60 * because I need to have a family of two-argument operators such as 61 * operator&, operator| etc which return new object of the class that 62 * represent the same address family as the arguments. These operators 63 * should be "friends" of class InetAddr since they return new object 64 * by value rather than modify "this". But how to do it if returned 65 * type should be different depending on the types of arguments ? 66 * 67 */ 68 class InetAddr 69 { 70 protected: 71 72 friend class InetAddrMask; 73 friend class Inet6AddrMask; 74 75 int address_family; 76 // Address in network order 77 struct in_addr ipv4; 78 struct in6_addr ipv6; 79 80 // copy in6_addr from sa to da _copy_in6_addr(struct in6_addr * da,const struct in6_addr * sa)81 static inline void _copy_in6_addr(struct in6_addr* da, 82 const struct in6_addr* sa) 83 { 84 ((uint32_t*)(da))[0] = ((uint32_t*)(sa))[0]; 85 ((uint32_t*)(da))[1] = ((uint32_t*)(sa))[1]; 86 ((uint32_t*)(da))[2] = ((uint32_t*)(sa))[2]; 87 ((uint32_t*)(da))[3] = ((uint32_t*)(sa))[3]; 88 } 89 90 void init_from_string(const char* data); 91 void init_from_int(unsigned int n); 92 93 public: 94 InetAddr()95 explicit InetAddr() 96 { 97 address_family = AF_INET; 98 ipv4.s_addr = 0; 99 ((uint32_t *) (&ipv6))[0] = 0; 100 ((uint32_t *) (&ipv6))[1] = 0; 101 ((uint32_t *) (&ipv6))[2] = 0; 102 ((uint32_t *) (&ipv6))[3] = 0; 103 } 104 ~InetAddr()105 virtual ~InetAddr() {} 106 addressLengthBits()107 inline unsigned int addressLengthBits() const 108 { 109 if (address_family == AF_INET) return sizeof(ipv4) * 8; 110 return sizeof(ipv6) * 8; 111 } 112 113 bool isValidV4Netmask(); 114 115 void init_from_uint128(uint128 int128a); 116 uint128 to_uint128() const; 117 118 InetAddr(const char *data) throw(FWException); 119 InetAddr(int af, const char *data) throw(FWException); 120 InetAddr(const struct in_addr*) throw(FWException); 121 InetAddr(const struct in6_addr*) throw(FWException); 122 explicit InetAddr(const std::string&) 123 throw(FWException, FWNotSupportedException); 124 explicit InetAddr(int af, const std::string&) 125 throw(FWException, FWNotSupportedException); 126 InetAddr(const InetAddr &); 127 // creates netmask 'n' bits long 128 explicit InetAddr(int n) throw(FWException); 129 explicit InetAddr(int af, int n) throw(FWException); 130 131 InetAddr& operator=(const InetAddr &addr); 132 addressFamily()133 int addressFamily() const { return address_family; } isV4()134 bool isV4() const { return (address_family==AF_INET); } isV6()135 bool isV6() const { return (address_family==AF_INET6); } 136 getV4()137 const struct in_addr* getV4() const { return &ipv4; } getV6()138 const struct in6_addr* getV6() const { return &ipv6; } 139 getAny()140 static inline InetAddr getAny() 141 { 142 return InetAddr(); 143 } 144 145 static inline InetAddr getAllOnes(int af=AF_INET) 146 { 147 if (af==AF_INET) 148 { 149 struct in_addr allones; 150 allones.s_addr = 0xffffffff; 151 return InetAddr(&allones); 152 } else 153 { 154 struct in6_addr a; 155 ((uint32_t *) (&a))[0] = 0xffffffff; 156 ((uint32_t *) (&a))[1] = 0xffffffff; 157 ((uint32_t *) (&a))[2] = 0xffffffff; 158 ((uint32_t *) (&a))[3] = 0xffffffff; 159 return InetAddr(&a); 160 } 161 } 162 163 static inline InetAddr getLoopbackAddr(int af=AF_INET) 164 { 165 if (af==AF_INET) 166 { 167 struct in_addr loopback; 168 loopback.s_addr = htonl(INADDR_LOOPBACK); 169 return InetAddr(&loopback); 170 } else 171 { 172 struct in6_addr a; 173 ((uint32_t *) (&a))[0] = 0; 174 ((uint32_t *) (&a))[1] = 0; 175 ((uint32_t *) (&a))[2] = 0; 176 ((uint32_t *) (&a))[3] = htonl (1); 177 return InetAddr(&a); 178 } 179 } 180 181 std::string toString() const; 182 183 /** 184 * Broadcast : 255.255.255.255 185 * 186 * there are no broadcast addresses in ipv6. However some multicast 187 * addresses serve similar purpose. For example "link-scope 188 * all-hosts multicast" address ff02::1 corresponds to the ipv4 189 * broadcast 255.255.255.255 190 */ isBroadcast()191 inline bool isBroadcast() const 192 { 193 if (address_family==AF_INET) 194 return ipv4.s_addr == INADDR_BROADCAST; 195 else 196 return IN6_IS_ADDR_MC_LINKLOCAL(&ipv6); 197 } 198 199 /** 200 * Multicast : 224.0.0.0 - 239.0.0.0 201 */ isMulticast()202 inline bool isMulticast() const 203 { 204 if (address_family==AF_INET) 205 return IN_MULTICAST(ntohl(ipv4.s_addr)); 206 else 207 return IN6_IS_ADDR_MULTICAST(&ipv6); 208 } 209 210 /** 211 * INADDR_ANY: 0 212 */ isAny()213 inline bool isAny() const 214 { 215 if (address_family==AF_INET) 216 return ipv4.s_addr == INADDR_ANY; 217 else 218 return (IN6_IS_ADDR_UNSPECIFIED(&ipv6)); 219 } 220 221 /** 222 * calculate distance between _this_ address and address a2 and return 223 * it as int 224 * This method is limited, it only calculates distance that fit in 32 bit 225 * number 226 */ distance(const InetAddr & a2)227 inline unsigned int distance(const InetAddr &a2) const 228 { 229 if (address_family==AF_INET) 230 return ntohl(a2.ipv4.s_addr) - ntohl(ipv4.s_addr) + 1; 231 else 232 { 233 uint128 d1 = to_uint128(); 234 uint128 d2 = a2.to_uint128(); 235 uint128 res; 236 if (d1 < d2) 237 { 238 res = d2; 239 res -= d1; 240 } else 241 { 242 res = d1; 243 res -= d2; 244 } 245 return res.to_integer() + 1; 246 } 247 } 248 249 /** 250 * returns the "length" of the netmask, that is number of bits set to '1' 251 * counting from left to right 252 */ 253 int getLength() const; 254 255 /** 256 * for netmasks: return true if this is host mask, i.e. all '1' 257 */ isHostMask()258 inline bool isHostMask() const 259 { 260 if (address_family==AF_INET) 261 return ipv4.s_addr == INADDR_BROADCAST; 262 else 263 return (((uint32_t*)(&ipv6))[0] == 0xffffffff && 264 ((uint32_t*)(&ipv6))[1] == 0xffffffff && 265 ((uint32_t*)(&ipv6))[2] == 0xffffffff && 266 ((uint32_t*)(&ipv6))[3] == 0xffffffff); 267 } 268 269 /*****************************************************************/ 270 271 InetAddr opAnd(const InetAddr &mask) const; 272 273 InetAddr opOr(const InetAddr &mask) const; 274 275 InetAddr opPlus(int increment) const; 276 277 InetAddr opMinus(int decrement) const; 278 279 bool opLT(const InetAddr &other) const; 280 281 bool opGT(const InetAddr &other) const; 282 283 bool opEQ(const InetAddr &other) const; 284 285 bool opNEQ(const InetAddr &other) const; 286 287 InetAddr opCompl() const; 288 289 /*****************************************************************/ 290 291 inline friend InetAddr operator&(const InetAddr &addr, 292 const InetAddr &mask) 293 { 294 assert (typeid(addr) == typeid(mask)); 295 return addr.opAnd(mask); 296 } 297 298 inline friend InetAddr operator|(const InetAddr &addr, 299 const InetAddr &mask) 300 { 301 assert (typeid(addr) == typeid(mask)); 302 return addr.opOr(mask); 303 } 304 305 inline friend InetAddr operator+(const InetAddr &addr, int increment) 306 { 307 return addr.opPlus(increment); 308 } 309 310 inline friend InetAddr operator-(const InetAddr &addr, int decrement) 311 { 312 return addr.opMinus(decrement); 313 } 314 315 inline friend bool operator<(const InetAddr &a, const InetAddr &b) 316 { 317 assert (typeid(a) == typeid(b)); 318 return a.opLT(b); 319 } 320 321 inline friend bool operator>(const InetAddr &a, const InetAddr &b) 322 { 323 assert (typeid(a) == typeid(b)); 324 return a.opGT(b); 325 } 326 327 inline friend bool operator==(const InetAddr &a, const InetAddr &b) 328 { 329 assert (typeid(a) == typeid(b)); 330 return a.opEQ(b); 331 } 332 333 inline friend bool operator!=(const InetAddr &a, const InetAddr &b) 334 { 335 assert (typeid(a) == typeid(b)); 336 return a.opNEQ(b); 337 } 338 339 inline friend InetAddr operator~(const InetAddr &a) 340 { 341 return a.opCompl(); 342 } 343 344 }; 345 346 } 347 348 #endif 349