libnavajo
web server for static and dynamic pages developement in C++
IpAddress.hh
Go to the documentation of this file.
1 //********************************************************
12 //********************************************************
13 
14 #ifndef IPADDRESS_HH_
15 #define IPADDRESS_HH_
16 
17 #include <stdexcept>
18 #include <errno.h>
19 #include <vector>
20 #include <string>
21 #include <sstream>
22 #include <string.h>
23 
24 
25 #ifdef WIN32
26 
27 #include "pthread.h"
28 #include <winsock2.h>
29 #include <Windows.h>
30 #include <in6addr.h>
31 #include <ws2tcpip.h>
32 #define u_int32_t uint32_t
33 #define u_int8_t uint8_t
34 #define u_int16_t uint16_t
35 #include "stdint.h"
36 
37 #define in_addr_t DWORD
38 #define index(s, c) strchr((char*)s, c)
39 #define rindex(s, c) strrchr((char*)s, c)
40 
41 #define inet_ntop(f,b,l,o) inet_ntop(f,(PVOID)(b),l,o)
42 
43 #else
44 
45 #include <netdb.h>
46 #include <arpa/inet.h>
47 
48 #endif
49 
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 
55 #define INET6_ADDRLEN 16
56 
57 
58 /***********************************************************************
59  * IpAdress struct definition
60  * for IPv4 and IPv6 address
61  */
62 
63 
64 class IpAddress
65 {
66  public:
67 
68  typedef union
69  {
70  in_addr_t v4;
71  in6_addr v6;
72  } IP;
73 
74  IP ip;
75  u_int8_t ipversion;
76 
77  inline void init() { ipversion=0; memset (ip.v6.s6_addr, 0, INET6_ADDRLEN); };
78 
79  IpAddress() { init(); };
80 
81  IpAddress(const in_addr_t &addrIPv4) :
82  ipversion(4) { ip.v4=addrIPv4; };
83 
84  IpAddress(const in6_addr &addrIPv6) :
85  ipversion(6) { memcpy ((void*)&(ip.v6), (void*)(&addrIPv6), INET6_ADDRLEN); };
86 
87  IpAddress(const std::string& value)
88  {
89  init();
90  if ( index(value.c_str(), ':') != NULL ) // IPv6
91  {
92  struct sockaddr_in6 tmp;
93  if ( inet_pton(AF_INET6, value.c_str(), &(tmp.sin6_addr)) == 0 )
94  return ;
95  *this = tmp.sin6_addr;
96  }
97  else // IPv4
98  {
99  struct in_addr tmp;
100  if ( inet_pton(AF_INET, value.c_str(), &tmp) == 0 )
101  return ;
102 
103  *this = tmp.s_addr;
104  }
105  }
106 
107  inline bool isNull() const { return ipversion == 0; };
108 
109  inline IpAddress& operator= (const in_addr_t &addrIPv4) { this->ipversion=4; this->ip.v4=addrIPv4; return *this; };
110  inline IpAddress& operator= (const in6_addr &addrIPv6) { this->ipversion=6; memcpy ((void*)&(ip.v6), (void*)(&addrIPv6), INET6_ADDRLEN); return *this; };
111  inline IpAddress& operator= (const IpAddress& i) { if (i.ipversion == 4) *this=i.ip.v4; else *this=i.ip.v6; return *this;};
112 
113  inline bool operator== (IpAddress const &ipA) const
114  {
115  if (ipA.ipversion != this->ipversion) return false;
116 
117  if (this->ipversion == 4) return this->ip.v4 == ipA.ip.v4;
118 
119  // IPv6
120  int i=INET6_ADDRLEN-1; bool res=true;
121  for (; i>=0 && res; i--) res=ipA.ip.v6.s6_addr[i] == this->ip.v6.s6_addr[i];
122  return (i == -1) && res;
123  };
124 
125  bool operator<(const IpAddress& A) const
126  {
127  bool res=true;
128  if (ipversion == 4)
129  res = ip.v4 < A.ip.v4;
130  else //IPv6
131  {
132  int i=0;
133  for (; i<INET6_ADDRLEN-1 && ( ip.v6.s6_addr[i] == A.ip.v6.s6_addr[i] ); i++);
134 
135  res = ip.v6.s6_addr[i] < A.ip.v6.s6_addr[i];
136  }
137 
138  return res;
139  };
140 
141  inline bool isUndef() const { return ipversion == 0; };
142 
143  inline std::string str() const
144  {
145  std::string res="";
146  if (ipversion == 4)
147  {
148  struct in_addr iplocal;
149  iplocal.s_addr=ip.v4;
150  res+=inet_ntoa(iplocal);
151  }
152  else
153  { // IPv6
154  char ipStr[INET6_ADDRSTRLEN];
155  if (inet_ntop(AF_INET6, &(ip.v6), ipStr, INET6_ADDRSTRLEN ) == NULL)
156  res+="ERROR !";
157  else
158  res+=ipStr;
159  }
160 
161  return res;
162  };
163 
164  static pthread_mutex_t resolvIP_mutex;
165 
166  inline bool snresolve( char *hname, const size_t maxlength) const
167  {
168  int error = 0;
169  struct sockaddr_in sin;
170  struct sockaddr_in6 sin6;
171 
172  pthread_mutex_lock( &resolvIP_mutex );
173 
174  if (ipversion == 4)
175  {
176  sin.sin_family=AF_INET;
177  struct in_addr addr; addr.s_addr=ip.v4;
178  sin.sin_addr=addr;
179  error = getnameinfo((sockaddr*)&sin, sizeof sin, hname, maxlength, NULL, 0, NI_NAMEREQD);
180  }
181  else
182  { // IPv6
183  sin6.sin6_family=AF_INET6;
184  sin6.sin6_addr=ip.v6;
185  error = getnameinfo((sockaddr*)&sin6, sizeof sin6, hname, maxlength, NULL, 0, NI_NAMEREQD);
186  }
187 
188  pthread_mutex_unlock( &resolvIP_mutex );
189 
190  return (!error);
191  };
192 
193  inline static IpAddress* fromString(const std::string& value)
194  {
195  IpAddress* newIp = new IpAddress(value);
196 
197  if (newIp != NULL && !newIp->isNull() )
198  return newIp;
199 
200  if (newIp != NULL) delete newIp;
201 
202  return NULL;
203  }
204 
205 };
206 
207 /***********************************************************************
208  * IpNetwork struct definition
209  */
210 
212 {
213  public:
214 
215  IpAddress addr;
216  u_int8_t mask;
217 
218  IpNetwork() { };
219  IpNetwork(const IpAddress &A): addr(A)
220  { if (A.ipversion == 4) mask=32; else mask=128; };
221  IpNetwork(const IpAddress &a,const u_int8_t &m)
222  { addr = a; mask=m; };
223 
224 
225  // TODO: IpNetwork(const std::string& value)
226 
227 
228  inline bool operator<(const IpNetwork& A) const
229  {
230  if (A.addr.ipversion == 4)
231  {
232  if (addr.ipversion != 4) return false; // IpV6 > IpV4
233 
234  u_int32_t netmask=0, Anetmask=0;
235  for (u_int8_t i=0; i < A.mask ; i++)
236  Anetmask |= 1 << (31-i);
237  Anetmask=htonl(Anetmask);
238 
239  for (u_int8_t i=0; i < mask ; i++)
240  netmask |= 1 << (31-i);
241  netmask=htonl(netmask);
242  return (addr.ip.v4 & netmask) < (A.addr.ip.v4 & Anetmask);
243  }
244 
245  if (A.addr.ipversion == 6)
246  {
247  if (addr.ipversion != 6) return true; // IpV6 > IpV4
248 
249  bool res=true;
250  int i=0;
251  u_int8_t netmask=0, Anetmask=0;
252 
253  for (; i<INET6_ADDRLEN-1 && res; i++)
254  ;
255 
256  {
257  for (u_int8_t j=i*8; j<(i+1)*8 ; j++)
258  {
259  if (j < A.mask) Anetmask |= 1 << (8-(j-i*8));
260  if (j < mask) netmask |= 1 << (8-(j-i*8));
261  }
262 
263  res = ( addr.ip.v6.s6_addr[i] & netmask ) == ( A.addr.ip.v6.s6_addr[i] & Anetmask );
264  }
265  return ( addr.ip.v6.s6_addr[i] & netmask ) < ( A.addr.ip.v6.s6_addr[i] & Anetmask );
266  }
267 
268  return false;
269  };
270 
271  inline std::string strCIDR() const
272  {
273  std::string netCIDR=addr.str()+"/";
274  std::stringstream masklengthSs; masklengthSs << (int)mask;
275  netCIDR+=masklengthSs.str();
276  return netCIDR;
277  };
278 
286  inline bool isInside(const IpAddress& ip) const
287  {
288  bool res = false;
289 
290  if (ip.ipversion == 4)
291  {
292  if (addr.ipversion == 4)
293  {
294  u_int32_t netmask=0;
295  for (u_int8_t j=0; j < mask ; j++)
296  netmask |= 1 << (31-j);
297  netmask=htonl(netmask);
298  res = ( addr.ip.v4 & netmask ) == ( ip.ip.v4 & netmask ) ;
299  }
300  }
301 
302  if (ip.ipversion == 6)
303  {
304  if (addr.ipversion == 6)
305  {
306  res=true;
307  int i=0;
308 
309  for (; i<INET6_ADDRLEN && res; i++)
310  {
311  u_int8_t netmask=0;
312  for (u_int8_t j=i*8; j<(i+1)*8 ; j++)
313  if (j < mask) netmask |= 1 << (8-(j-i*8));
314 
315  res = ( ( addr.ip.v6.s6_addr[i] & netmask ) == (ip.ip.v6.s6_addr[i] & netmask) );
316  }
317  }
318  }
319 
320  return res;
321  };
322 
323  inline static IpNetwork* fromString(const std::string& value)
324  {
325  IpNetwork *ipNet=NULL;
326  std::string ipstr;
327  size_t found=value.find_first_of('/');
328  if (found == std::string::npos)
329  {
330  IpAddress *addr=IpAddress::fromString(value);
331  if (addr==NULL) return NULL;
332  ipNet=new IpNetwork(*addr);
333  delete addr;
334  }
335  else
336  {
337  ipstr=value.substr(0, found);
338 
339  IpAddress *addr=IpAddress::fromString(ipstr);
340 
341  if (addr==NULL) return NULL;
342 
343  u_int8_t maskDec=0;
344  std::string maskStr=value.substr(found+1);
345 
346  // Mask
347  if ( maskStr.find_first_of('.') != std::string::npos ) // mask is formating like "w.x.y.z"
348  {
349  if (addr->ipversion == 6)
350  {
351  delete addr;
352  return NULL;
353  }
354 
355  struct in_addr tmp;
356  if ( inet_pton(AF_INET, maskStr.c_str(), &tmp) == 0 )
357  // if (inet_aton(maskStr.c_str(), &tmp) == 0)
358  {
359  delete addr;
360  return NULL;
361  }
362  else
363  {
364  u_int32_t netmask=ntohl(tmp.s_addr);
365  bool thisistheend=false;
366  maskDec=0;
367  for (u_int8_t j=0; j < 32 ; j++)
368  if ((netmask >> (31-j)) & 1)
369  {
370  if (!thisistheend)
371  maskDec++;
372  else
373  {
374  delete addr;
375  return NULL;
376  }
377  }
378  else
379  thisistheend=true;
380  }
381  }
382  else
383  {
384  size_t s=0, e=0, j=0;
385 
386  while (( maskStr[s] == ' ' || maskStr[s] == '\t' ) && s < maskStr.length())
387  s++;
388  e=s;
389 
390  if (e < maskStr.length())
391 
392  while ( e < maskStr.length() && maskStr[e] >= '0' && maskStr[e] <= '9' )
393  e++;
394 
395  j=e;
396 
397  while (j < maskStr.length() && ( maskStr[j] == ' ' || maskStr[j] == '\t' || maskStr[j] == '\n' || maskStr[j] == '\r') )
398  j++;
399 
400  if (e==s || j!=maskStr.length()) return NULL;
401 
402  maskDec=atoi(maskStr.substr(s,e-s+1).c_str());
403  }
404 
405  if ((maskDec > 32 && addr->ipversion == 4) || (maskDec > 128 && addr->ipversion == 6))
406  {
407  delete addr;
408  return NULL;
409  }
410 
411  ipNet=new IpNetwork(*addr, maskDec);
412  delete addr;
413  }
414  return ipNet;
415  }
416 } ;
417 
418 
426 inline static bool isIpBelongToIpNetwork(const IpAddress& ip, const std::vector<IpNetwork>& net)
427 {
428  bool res = false;
429 
430  for( std::vector<IpNetwork>::const_iterator i=net.begin(); i!=net.end() && !res; i++)
431  res = i->isInside(ip);
432 
433  return res;
434 };
435 
436 /***********************************************************************/
437 
438 #endif
Definition: IpAddress.hh:68
Definition: IpAddress.hh:64
bool isInside(const IpAddress &ip) const
Definition: IpAddress.hh:286
Definition: IpAddress.hh:211