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