36ea2f565d47c8c2dc6330c1d4232c600e1fa39c
[public/netxms.git] / src / libnetxms / inetaddr.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Utility Library
4 ** Copyright (C) 2003-2015 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: inetaddr.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include <nxcpapi.h>
26
27 /**
28 * Invalid address
29 */
30 const InetAddress InetAddress::INVALID = InetAddress();
31
32 /**
33 * Loopback address (IPv4)
34 */
35 const InetAddress InetAddress::LOOPBACK = InetAddress(0x7F000001);
36
37 /**
38 * IPv4 link local subnet
39 */
40 static const InetAddress IPV4_LINK_LOCAL = InetAddress(0xA9FE0000, 0xFFFF0000);
41
42 /**
43 * IPv6 link local subnet
44 */
45 static const InetAddress IPV6_LINK_LOCAL = InetAddress((const BYTE *)"\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10);
46
47 /**
48 * Create IPv4 address object
49 */
50 InetAddress::InetAddress(UINT32 addr)
51 {
52 m_family = AF_INET;
53 m_addr.v4 = addr;
54 m_maskBits = 32;
55 }
56
57 /**
58 * Create IPv4 address object
59 */
60 InetAddress::InetAddress(UINT32 addr, UINT32 mask)
61 {
62 m_family = AF_INET;
63 m_addr.v4 = addr;
64 m_maskBits = BitsInMask(mask);
65 }
66
67 /**
68 * Create IPv6 address object
69 */
70 InetAddress::InetAddress(const BYTE *addr, int maskBits)
71 {
72 m_family = AF_INET6;
73 memcpy(m_addr.v6, addr, 16);
74 m_maskBits = maskBits;
75 }
76
77 /**
78 * Create invalid address object
79 */
80 InetAddress::InetAddress()
81 {
82 m_family = AF_UNSPEC;
83 m_maskBits = 0;
84 }
85
86 /**
87 * Returns true if address is a wildcard address
88 */
89 bool InetAddress::isAnyLocal() const
90 {
91 return (m_family == AF_INET) ? (m_addr.v4 == 0) : !memcmp(m_addr.v6, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16);
92 }
93
94 /**
95 * Returns true if address is a loopback address
96 */
97 bool InetAddress::isLoopback() const
98 {
99 return (m_family == AF_INET) ? ((m_addr.v4 & 0xFF000000) == 0x7F000000) : !memcmp(m_addr.v6, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 16);
100 }
101
102 /**
103 * Returns true if address is a multicast address
104 */
105 bool InetAddress::isMulticast() const
106 {
107 return (m_family == AF_INET) ? ((m_addr.v4 >= 0xE0000000) && (m_addr.v4 != 0xFFFFFFFF)) : (m_addr.v6[0] == 0xFF);
108 }
109
110 /**
111 * Returns true if address is a broadcast address
112 */
113 bool InetAddress::isBroadcast() const
114 {
115 return (m_family == AF_INET) ? (m_addr.v4 == 0xFFFFFFFF) : false;
116 }
117
118 /**
119 * Returns true if address is a link local address
120 */
121 bool InetAddress::isLinkLocal() const
122 {
123 return (m_family == AF_INET) ? IPV4_LINK_LOCAL.contain(*this) : IPV6_LINK_LOCAL.contain(*this);
124 }
125
126 /**
127 * Convert to string
128 */
129 String InetAddress::toString() const
130 {
131 TCHAR buffer[64];
132 String s = (m_family == AF_UNSPEC) ? _T("UNSPEC") : ((m_family == AF_INET) ? IpToStr(m_addr.v4, buffer) : Ip6ToStr(m_addr.v6, buffer));
133 return s;
134 }
135
136 /**
137 * Convert to string
138 */
139 TCHAR *InetAddress::toString(TCHAR *buffer) const
140 {
141 if (m_family == AF_UNSPEC)
142 {
143 _tcscpy(buffer, _T("UNSPEC"));
144 return buffer;
145 }
146 return (m_family == AF_INET) ? IpToStr(m_addr.v4, buffer) : Ip6ToStr(m_addr.v6, buffer);
147 }
148
149 #ifdef UNICODE
150
151 /**
152 * Convert to string (single byte version)
153 */
154 char *InetAddress::toStringA(char *buffer) const
155 {
156 if (m_family == AF_UNSPEC)
157 {
158 strcpy(buffer, "UNSPEC");
159 return buffer;
160 }
161 return (m_family == AF_INET) ? IpToStrA(m_addr.v4, buffer) : Ip6ToStrA(m_addr.v6, buffer);
162 }
163
164 #endif
165
166 /**
167 * Build hash key. Supplied array must be at least 18 bytes long.
168 */
169 BYTE *InetAddress::buildHashKey(BYTE *key) const
170 {
171 if (m_family == AF_INET)
172 {
173 key[0] = 6;
174 key[1] = AF_INET;
175 memcpy(&key[2], &m_addr.v4, 4);
176 memset(&key[6], 0, 12);
177 }
178 else
179 {
180 key[0] = 18;
181 key[1] = AF_INET6;
182 memcpy(&key[2], &m_addr.v6, 16);
183 }
184 return key;
185 }
186
187 /**
188 * Get corresponding subnet address for this InetAddress
189 */
190 InetAddress InetAddress::getSubnetAddress() const
191 {
192 InetAddress addr(*this);
193 if ((m_family == AF_INET) && (m_maskBits < 32))
194 {
195 addr.m_addr.v4 = (m_maskBits == 0) ? 0 : (m_addr.v4 & (0xFFFFFFFF << (32 - m_maskBits)));
196 }
197 else if ((m_family == AF_INET6) && (m_maskBits < 128))
198 {
199 int b = m_maskBits / 8;
200 int shift = m_maskBits % 8;
201 BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
202 addr.m_addr.v6[b] &= mask;
203 for(int i = b + 1; i < 16; i++)
204 addr.m_addr.v6[i] = 0;
205 }
206 return addr;
207 }
208
209 /**
210 * Get corresponding subnet broadcast address for this InetAddress
211 */
212 InetAddress InetAddress::getSubnetBroadcast() const
213 {
214 InetAddress addr(*this);
215 if ((m_family == AF_INET) && (m_maskBits < 32))
216 {
217 addr.m_addr.v4 = m_addr.v4 | (0xFFFFFFFF >> m_maskBits);
218 }
219 return addr;
220 }
221
222 /**
223 * Check if this address is a subnet broadcast for given subnet mask length
224 */
225 bool InetAddress::isSubnetBroadcast(int maskBits) const
226 {
227 if (m_family == AF_INET)
228 {
229 UINT32 mask = 0xFFFFFFFF << (32 - maskBits);
230 return (m_addr.v4 & (~mask)) == (~mask);
231 }
232 return false;
233 }
234
235 /**
236 * Check if this InetAddress contain given InetAddress using current network mask
237 */
238 bool InetAddress::contain(const InetAddress &a) const
239 {
240 if (a.m_family != m_family)
241 return false;
242
243 if (m_family == AF_INET)
244 {
245 UINT32 mask = (m_maskBits > 0) ? (0xFFFFFFFF << (32 - m_maskBits)) : 0;
246 return (a.m_addr.v4 & mask) == m_addr.v4;
247 }
248 else
249 {
250 BYTE addr[16];
251 memcpy(addr, a.m_addr.v6, 16);
252 if (m_maskBits < 128)
253 {
254 int b = m_maskBits / 8;
255 int shift = m_maskBits % 8;
256 BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
257 addr[b] &= mask;
258 for(int i = b + 1; i < 16; i++)
259 addr[i] = 0;
260 }
261 return !memcmp(addr, m_addr.v6, 16);
262 }
263 }
264
265 /**
266 * Check if this InetAddress are in same subnet with given InetAddress
267 * (using mask bits from this InetAddress)
268 */
269 bool InetAddress::sameSubnet(const InetAddress &a) const
270 {
271 if (a.m_family != m_family)
272 return false;
273
274 if (m_family == AF_INET)
275 {
276 UINT32 mask = (m_maskBits > 0) ? (0xFFFFFFFF << (32 - m_maskBits)) : 0;
277 return (a.m_addr.v4 & mask) == (m_addr.v4 & mask);
278 }
279 else
280 {
281 BYTE addr1[16], addr2[16];
282 memcpy(addr1, a.m_addr.v6, 16);
283 memcpy(addr2, m_addr.v6, 16);
284 if (m_maskBits < 128)
285 {
286 int b = m_maskBits / 8;
287 int shift = m_maskBits % 8;
288 BYTE mask = (shift > 0) ? (BYTE)(0xFF << (8 - shift)) : 0;
289 addr1[b] &= mask;
290 addr2[b] &= mask;
291 for(int i = b + 1; i < 16; i++)
292 {
293 addr1[i] = 0;
294 addr2[i] = 0;
295 }
296 }
297 return !memcmp(addr1, addr2, 16);
298 }
299 }
300
301 /**
302 * Check if two inet addresses are equal
303 * This method ignores mask bits and only compares addresses.
304 * To compare two address/mask pairs use InetAddress::compareTo.
305 */
306 bool InetAddress::equals(const InetAddress &a) const
307 {
308 if (a.m_family != m_family)
309 return false;
310 return ((m_family == AF_INET) ? (a.m_addr.v4 == m_addr.v4) : !memcmp(a.m_addr.v6, m_addr.v6, 16));
311 }
312
313 /**
314 * Compare two inet addresses
315 */
316 int InetAddress::compareTo(const InetAddress &a) const
317 {
318 int r = a.m_family - m_family;
319 if (r != 0)
320 return r;
321
322 if (m_family == AF_INET)
323 {
324 return (m_addr.v4 == a.m_addr.v4) ? (m_maskBits - a.m_maskBits) : ((m_addr.v4 < a.m_addr.v4) ? -1 : 1);
325 }
326 else
327 {
328 r = memcmp(a.m_addr.v6, m_addr.v6, 16);
329 return (r == 0) ? (m_maskBits - a.m_maskBits) : r;
330 }
331 }
332
333 /**
334 * Fill sockaddr structure
335 */
336 struct sockaddr *InetAddress::fillSockAddr(SockAddrBuffer *buffer, UINT16 port) const
337 {
338 if (!isValid())
339 return NULL;
340
341 memset(buffer, 0, sizeof(SockAddrBuffer));
342 ((struct sockaddr *)buffer)->sa_family = m_family;
343 if (m_family == AF_INET)
344 {
345 buffer->sa4.sin_addr.s_addr = htonl(m_addr.v4);
346 buffer->sa4.sin_port = htons(port);
347 }
348 else
349 {
350 #ifdef WITH_IPV6
351 memcpy(buffer->sa6.sin6_addr.s6_addr, m_addr.v6, 16);
352 buffer->sa6.sin6_port = htons(port);
353 #else
354 return NULL;
355 #endif
356 }
357 return (struct sockaddr *)buffer;
358 }
359
360 /**
361 * Get host name by IP address
362 *
363 * @param buffer buffer to place host name to
364 * @param buflen buffer length in characters
365 * @return buffer on success, NULL on failure
366 */
367 TCHAR *InetAddress::getHostByAddr(TCHAR *buffer, size_t buflen) const
368 {
369 if (!isValid())
370 return NULL;
371
372 struct hostent *hs = NULL;
373 if (m_family == AF_INET)
374 {
375 UINT32 addr = htonl(m_addr.v4);
376 hs = gethostbyaddr((const char *)&addr, 4, AF_INET);
377 }
378 else
379 {
380 hs = gethostbyaddr((const char *)m_addr.v6, 16, AF_INET6);
381 }
382
383 if (hs == NULL)
384 return NULL;
385
386 #ifdef UNICODE
387 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, hs->h_name, -1, buffer, (int)buflen);
388 buffer[buflen - 1] = 0;
389 #else
390 nx_strncpy(buffer, hs->h_name, buflen);
391 #endif
392
393 return buffer;
394 }
395
396 /**
397 * Resolve hostname
398 */
399 InetAddress InetAddress::resolveHostName(const WCHAR *hostname, int af)
400 {
401 char mbName[256];
402 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, hostname, -1, mbName, 256, NULL, NULL);
403 return resolveHostName(mbName, af);
404 }
405
406 /**
407 * Resolve hostname
408 */
409 InetAddress InetAddress::resolveHostName(const char *hostname, int af)
410 {
411 InetAddress addr = parse(hostname);
412 if (addr.isValid())
413 return addr;
414
415 // Not a valid IP address, resolve hostname
416 #if HAVE_GETADDRINFO
417 struct addrinfo *ai;
418 if (getaddrinfo(hostname, NULL, NULL, &ai) == 0)
419 {
420 addr = InetAddress::createFromSockaddr(ai->ai_addr);
421 freeaddrinfo(ai);
422 return addr;
423 }
424 #else
425 #if HAVE_GETHOSTBYNAME2_R
426 struct hostent h, *hs = NULL;
427 char buffer[1024];
428 int err;
429 gethostbyname2_r(hostname, af, &h, buffer, 1024, &hs, &err);
430 #else
431 struct hostent *hs = gethostbyname(hostname);
432 #endif
433 if (hs != NULL)
434 {
435 if (hs->h_addrtype == AF_INET)
436 {
437 return InetAddress(ntohl(*((UINT32 *)hs->h_addr)));
438 }
439 else if (hs->h_addrtype == AF_INET6)
440 {
441 return InetAddress((BYTE *)hs->h_addr);
442 }
443 }
444 #endif /* HAVE_GETADDRINFO */
445 return InetAddress();
446 }
447
448 /**
449 * Parse string as IP address
450 */
451 InetAddress InetAddress::parse(const WCHAR *str)
452 {
453 char mb[256];
454 WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR, str, -1, mb, 256, NULL, NULL);
455 return parse(mb);
456 }
457
458 /**
459 * Parse string as IP address
460 */
461 InetAddress InetAddress::parse(const char *str)
462 {
463 // Check for IPv4 address
464 #ifdef _WIN32
465 char strCopy[256];
466 strncpy(strCopy, str, 255);
467
468 struct sockaddr_in addr4;
469 addr4.sin_family = AF_INET;
470 INT addrLen = sizeof(addr4);
471 if (WSAStringToAddressA(strCopy, AF_INET, NULL, (struct sockaddr *)&addr4, &addrLen) == 0)
472 {
473 return InetAddress(ntohl(addr4.sin_addr.s_addr));
474 }
475 #else
476 struct in_addr addr4;
477 if (inet_aton(str, &addr4))
478 {
479 return InetAddress(ntohl(addr4.s_addr));
480 }
481 #endif
482
483 // Check for IPv6 address
484 #if defined(_WIN32)
485 struct sockaddr_in6 addr6;
486 addr6.sin6_family = AF_INET6;
487 addrLen = sizeof(addr6);
488 if (WSAStringToAddressA(strCopy, AF_INET6, NULL, (struct sockaddr *)&addr6, &addrLen) == 0)
489 {
490 return InetAddress(addr6.sin6_addr.u.Byte);
491 }
492 #elif defined(WITH_IPV6)
493 struct in6_addr addr6;
494 if (inet_pton(AF_INET6, str, &addr6))
495 {
496 return InetAddress(addr6.s6_addr);
497 }
498 #endif
499 return InetAddress();
500 }
501
502 /**
503 * Create IndetAddress from struct sockaddr
504 */
505 InetAddress InetAddress::createFromSockaddr(struct sockaddr *s)
506 {
507 if (s->sa_family == AF_INET)
508 return InetAddress(ntohl(((struct sockaddr_in *)s)->sin_addr.s_addr));
509 #ifdef WITH_IPV6
510 if (s->sa_family == AF_INET6)
511 return InetAddress(((struct sockaddr_in6 *)s)->sin6_addr.s6_addr);
512 #endif
513 return InetAddress();
514 }
515
516 /**
517 * Address list constructor
518 */
519 InetAddressList::InetAddressList()
520 {
521 m_list = new ObjectArray<InetAddress>(8, 8, true);
522 }
523
524 /**
525 * Address list destructor
526 */
527 InetAddressList::~InetAddressList()
528 {
529 delete m_list;
530 }
531
532 /**
533 * Add address to list
534 */
535 void InetAddressList::add(const InetAddress &addr)
536 {
537 if (!hasAddress(addr))
538 m_list->add(new InetAddress(addr));
539 }
540
541 /**
542 * Add multiple addresses to list
543 */
544 void InetAddressList::add(const InetAddressList &addrList)
545 {
546 for(int i = 0; i < addrList.m_list->size(); i++)
547 add(*(addrList.m_list->get(i)));
548 }
549
550 /**
551 * Remove address from list
552 */
553 void InetAddressList::remove(const InetAddress &addr)
554 {
555 int index = indexOf(addr);
556 if (index != -1)
557 m_list->remove(index);
558 }
559
560 /**
561 * Replace IP address (update it's properties - currently only network mask)
562 */
563 void InetAddressList::replace(const InetAddress& addr)
564 {
565 int index = indexOf(addr);
566 if (index != -1)
567 {
568 m_list->get(index)->setMaskBits(addr.getMaskBits());
569 }
570 }
571
572 /**
573 * Get index in list of given address
574 */
575 int InetAddressList::indexOf(const InetAddress &addr) const
576 {
577 for(int i = 0; i < m_list->size(); i++)
578 if (m_list->get(i)->equals(addr))
579 return i;
580 return -1;
581 }
582
583 /**
584 * Get first valid unicast address from the list
585 */
586 const InetAddress& InetAddressList::getFirstUnicastAddress() const
587 {
588 for(int i = 0; i < m_list->size(); i++)
589 {
590 InetAddress *a = m_list->get(i);
591 if (a->isValidUnicast())
592 return *a;
593 }
594 return InetAddress::INVALID;
595 }
596
597 /**
598 * Get first valid IPv4 unicast address from the list
599 */
600 const InetAddress& InetAddressList::getFirstUnicastAddressV4() const
601 {
602 for(int i = 0; i < m_list->size(); i++)
603 {
604 InetAddress *a = m_list->get(i);
605 if ((a->getFamily() == AF_INET) && a->isValidUnicast())
606 return *a;
607 }
608 return InetAddress::INVALID;
609 }
610
611 /**
612 * Check if given address is within same subnet as one of addresses on this list
613 */
614 const InetAddress& InetAddressList::findSameSubnetAddress(const InetAddress& addr) const
615 {
616 for(int i = 0; i < m_list->size(); i++)
617 {
618 InetAddress *a = m_list->get(i);
619 if (a->sameSubnet(addr))
620 return *a;
621 }
622 return InetAddress::INVALID;
623 }
624
625 /**
626 * Check if all addresses in list are loopback
627 */
628 bool InetAddressList::isLoopbackOnly() const
629 {
630 if (m_list->size() == 0)
631 return false;
632 for(int i = 0; i < m_list->size(); i++)
633 {
634 if (!m_list->get(i)->isLoopback())
635 return false;
636 }
637 return true;
638 }
639
640 /**
641 * Fill NXCP message
642 */
643 void InetAddressList::fillMessage(NXCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId) const
644 {
645 msg->setField(sizeFieldId, m_list->size());
646 UINT32 fieldId = baseFieldId;
647 for(int i = 0; i < m_list->size(); i++)
648 {
649 msg->setField(fieldId++, *m_list->get(i));
650 }
651 }