reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
DnsUtil.cxx
Go to the documentation of this file.
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#if !defined(WIN32)
6#if defined(__SUNPRO_CC) || defined (__sun__)
7#define BSD_COMP /* !rk! needed to enable SIOCGIFCONF */
8#endif
9#include <sys/types.h>
10#include <sys/socket.h>
11#include <netinet/in.h>
12#include <arpa/inet.h>
13#include <sys/ioctl.h>
14#include <net/if.h>
15#include <errno.h>
16#include <netdb.h>
17#endif
18
19#include <stdio.h>
20#include <ctype.h>
21#include <memory>
22
23#include "rutil/compat.hxx"
24#include "rutil/Socket.hxx"
25#include "rutil/DnsUtil.hxx"
26#include "rutil/Logger.hxx"
27#include "rutil/Inserter.hxx"
28#include "rutil/WinCompat.hxx"
30
31#define RESIPROCATE_SUBSYSTEM resip::Subsystem::DNS
32
33#ifndef MAXHOSTNAMELEN
34#define MAXHOSTNAMELEN 256
35#endif
36
37using namespace resip;
38using namespace std;
39
40
41list<Data>
43{
44 list<Data> names;
45
46 if (DnsUtil::isIpV4Address(host))
47 {
48 names.push_back(host);
49 return names;
50 }
51
52 struct hostent* result=0;
53 int ret=0;
54 int herrno=0;
55
56#if defined(__linux__)
57 struct hostent hostbuf;
58 char buffer[8192];
59 ret = gethostbyname_r( host.c_str(), &hostbuf, buffer, sizeof(buffer), &result, &herrno);
60 resip_assert (ret != ERANGE);
61#elif defined(__QNX__) || defined(__SUNPRO_CC)
62 struct hostent hostbuf;
63 char buffer[8192];
64 result = gethostbyname_r( host.c_str(), &hostbuf, buffer, sizeof(buffer), &herrno );
65#elif defined(__APPLE__)
66 // gethostbyname in os/x is thread-safe...
67 // http://developer.apple.com/technotes/tn2002/pdf/tn2053.pdf
68 result = gethostbyname( host.c_str() );
69 ret = (result == 0);
70#else
71 resip_assert(0);
72 return names;
73#endif
74
75 if (ret != 0 || result == 0)
76 {
77 Data msg;
78 switch (herrno)
79 {
80 case HOST_NOT_FOUND:
81 msg = "host not found: ";
82 break;
83 case NO_DATA:
84 msg = "no data found for: ";
85 break;
86 case NO_RECOVERY:
87 msg = "no recovery lookup up: ";
88 break;
89 case TRY_AGAIN:
90 msg = "try again: ";
91 break;
92 }
93 msg += host;
94
95 DebugLog (<< "DNS lookup of " << host << " resulted in " << msg);
96 throw Exception("no dns resolution:" + msg, __FILE__, __LINE__);
97 }
98 else
99 {
100 resip_assert(result);
101 resip_assert(result->h_length == 4);
102 char str[256];
103 for (char** pptr = result->h_addr_list; *pptr != 0; pptr++)
104 {
105 inet_ntop(result->h_addrtype, (u_int32_t*)(*pptr), str, sizeof(str));
106 names.push_back(str);
107 }
108
109 StackLog (<< "DNS lookup of " << host << ": canonical name: " << result->h_name
110 << " "
111 << Inserter(names));
112
113 return names;
114 }
115}
116
117const Data&
119{
120 // The function-local static ensures we can initialize the static storage of
121 // localHostName at runtime, instead of at global static initialization time.
122 // Under windows, when building a DLL you cannot call initNetwork and
123 // other socket API's reliably from DLLMain, so we need to delay this call.
124 // We rely on C++11 thread-safe initialization guarantees for local statics
125 // to ensure that the localHostName is initialized in a thread-safe
126 // manner exactly once before use, even if the initial getLocalHostName() is
127 // invoked by multiple threads. Since localHostName is immutable, the returned
128 // variable reference can be safely read by multiple threads.
129 static const Data localHostName = lookupLocalHostName();
130 return localHostName;
131}
132
133Data
134DnsUtil::lookupLocalHostName()
135{
136 char buffer[MAXHOSTNAMELEN + 1];
137 initNetwork();
138 // can't assume the name is NUL terminated when truncation occurs,
139 // so insert trailing NUL here
140 buffer[0] = buffer[MAXHOSTNAMELEN] = '\0';
141 if (gethostname(buffer,sizeof(buffer)-1) == -1)
142 {
143 int err = getErrno();
144 switch (err)
145 {
146 // !RjS! This makes no sense for non-windows. The
147 // current hack (see the #define in .hxx) needs
148 // to be reworked.
150 CritLog( << "could not find local hostname because network not initialized:" << strError(err) );
151 break;
152 default:
153 CritLog( << "could not find local hostname:" << strError(err) );
154 break;
155 }
156 throw Exception("could not find local hostname",__FILE__,__LINE__);
157 }
158
159 struct addrinfo* result=0;
160 struct addrinfo hints;
161 memset(&hints, 0, sizeof(hints));
162 hints.ai_flags |= AI_CANONNAME;
163 hints.ai_family |= AF_UNSPEC;
164 int res = getaddrinfo(buffer, 0, &hints, &result);
165 if (!res)
166 {
167 // !jf! this should really use the Data class
168 if (strchr(result->ai_canonname, '.') != 0)
169 {
170 snprintf(buffer, sizeof(buffer), "%s", result->ai_canonname);
171 }
172 else
173 {
174 InfoLog( << "local hostname does not contain a domain part " << buffer);
175 }
176 freeaddrinfo(result);
177 }
178 else
179 {
180 InfoLog (<< "Couldn't determine local hostname. Error was: " << gai_strerror(res) << ". Returning empty string");
181 }
182
183 return buffer;
184}
185
186Data
188{
189 Data lhn(getLocalHostName());
190 Data::size_type dpos = lhn.find(".");
191 if (dpos != Data::npos)
192 {
193 return lhn.substr(dpos+1);
194 }
195 else
196 {
197#if defined( __APPLE__ ) || defined( WIN32 ) || defined(__SUNPRO_CC) || defined(__sun__) || defined( __ANDROID__ )
198 throw Exception("Could not find domainname in local hostname",__FILE__,__LINE__);
199#else
200 DebugLog( << "No domain portion in hostname <" << lhn << ">, so using getdomainname");
201 char buffer[MAXHOSTNAMELEN + 1];
202 // can't assume the name is NUL terminated when truncation occurs,
203 // so insert trailing NUL here
204 buffer[0] = buffer[MAXHOSTNAMELEN] = '\0';
205 if (int e = getdomainname(buffer,sizeof(buffer)-1) == -1)
206 {
207 if ( e != 0 )
208 {
209 int err = getErrno();
210 CritLog(<< "Couldn't find domainname: " << strerror(err));
211 throw Exception(strError(err), __FILE__,__LINE__);
212 }
213 }
214 DebugLog (<< "Found local domain name " << buffer);
215
216 return Data(buffer);
217#endif
218 }
219}
220
221Data
223{
224 Data result;
225 std::list<std::pair<Data,Data> > ifs = DnsUtil::getInterfaces(myInterface);
226
227 if (ifs.empty())
228 {
229 WarningLog( << "No interfaces matching " << myInterface << " were found" );
230 throw Exception("No interfaces matching", __FILE__, __LINE__);
231 }
232 else
233 {
234 InfoLog (<< "Local IP address for " << myInterface << " is " << ifs.begin()->second);
235 return ifs.begin()->second;
236 }
237}
238
239Data
240DnsUtil::inet_ntop(const struct in_addr& addr)
241{
242 char str[256];
243 inet_ntop(AF_INET, &addr, str, sizeof(str));
244 return Data(str);
245}
246
247#ifdef USE_IPV6
248Data
249DnsUtil::inet_ntop(const struct in6_addr& addr)
250{
251 char str[256];
252 inet_ntop(AF_INET6, &addr, str, sizeof(str));
253 return Data(str);
254}
255#endif
256
257Data
258DnsUtil::inet_ntop(const struct sockaddr& addr)
259{
260#ifdef USE_IPV6
261 if (addr.sa_family == AF_INET6)
262 {
263 const struct sockaddr_in6* addr6 = reinterpret_cast<const sockaddr_in6*>(&addr);
264 return DnsUtil::inet_ntop(addr6->sin6_addr);
265 }
266 else
267#endif
268 {
269 const struct sockaddr_in* addr4 = reinterpret_cast<const sockaddr_in*>(&addr);
270 return DnsUtil::inet_ntop(addr4->sin_addr);
271 }
272}
273
274int
275DnsUtil::inet_pton(const Data& printableIp, struct in_addr& dst)
276{
277 return DnsUtil::inet_pton(AF_INET, printableIp.c_str(), &dst);
278}
279
280#ifdef USE_IPV6
281int
282DnsUtil::inet_pton(const Data& printableIp, struct in6_addr& dst)
283{
284 return DnsUtil::inet_pton(AF_INET6, printableIp.c_str(), &dst);
285}
286#endif
287
288
289bool
291{
292 // ok, this is fairly monstrous but it works. It is also more than 10 times
293 // faster than the commented-out code below, in the worst case scenario.
294
295 const char* first = ipAddress.data();
296 const char* end = first + ipAddress.size();
297 int octets = 0;
298 while(octets++ < 4)
299 {
300 const char* last=first;
301
302 // .bwc. I have tried using std::bitset instead of the 0 <= *last <= 9
303 // check, but it is slower.
304 while(last != end && *last >= '0' && *last <= '9' && last - first <= 3)
305 {
306 // Skip at most 3 decimals, without going past the end of the buffer.
307 ++last;
308 }
309
310 // last should now point to either a '.', or the end of the buffer.
311
312 switch(last-first) // number of decimals in this octet
313 {
314 case 2:
315 if(*first == '0')
316 {
317 // Two-decimal octet can't begin with 0...
318 // ?bwc? Maybe let this slide?
319 return false;
320 }
321 case 1:
322 // ... but a one-decimal octet can begin with a 0.
323 break; // x. or xx.
324 case 3:
325 // xxx. (could be too large)
326 // .bwc. I have tried implementing this with a reinterpret_cast
327 // and a UInt32 comparison (accounting for endianness), and memcmp,
328 // but both appear to be slower, even when using
329 // "255.255.255.255" (which maximizes the number of comparisons).
330 if(*first != '1')
331 {
332 if(*first == '2')
333 {
334 // Might have overflow if first digit is 2
335 if(*(first+1)>'5' || (*(first+1)=='5' && *(first+2)>'5'))
336 {
337 return false;
338 }
339 }
340 else
341 {
342 // First digit greater than 2 means overflow, 0 not allowed.
343 return false;
344 }
345 }
346 break;
347 default:
348 return false;
349 }
350
351 if(octets < 4)
352 {
353 if(last != end && *last == '.')
354 {
355 // Skip over the '.'
356 ++last;
357 }
358 else
359 {
360 return false;
361 }
362 }
363 first = last; // is now pointing at either the first digit in the next
364 // octet, or the end of the buffer.
365 }
366
367 return first==end;
368// unsigned int p1,p2,p3,p4;
369// int count=0;
370// int result = sscanf( ipAddress.c_str(),
371// "%u.%u.%u.%u%n",
372// &p1, &p2, &p3, &p4, &count );
373//
374// if ( (result == 4) && (p1 <= 255) && (p2 <= 255) && (p3 <= 255) && (p4 <= 255) && (count == int(ipAddress.size())) )
375// {
376// return true;
377// }
378// else
379// {
380// return false;
381// }
382}
383
384// RFC 1884
385bool
387{
388 if (ipAddress.empty())
389 {
390 return false;
391 }
392
393 // first character must be a hex digit or colon
394 if (!isxdigit(static_cast< unsigned char >(*ipAddress.data())) &&
395 *ipAddress.data() != ':')
396 {
397 return false;
398 }
399
400 switch (ipAddress.size())
401 {
402 case 1:
403 return false;
404 case 2:
405 return (*(ipAddress.data()+1) == ':' ||
406 *(ipAddress.data()+0) == ':');
407 case 3:
408 return (*(ipAddress.data()+2) == ':' ||
409 *(ipAddress.data()+1) == ':' ||
410 *(ipAddress.data()+0) == ':');
411 case 4:
412 return (*(ipAddress.data()+3) == ':' ||
413 *(ipAddress.data()+2) == ':' ||
414 *(ipAddress.data()+1) == ':' ||
415 *(ipAddress.data()+0) == ':');
416 default:
417
418 return (*(ipAddress.data()+4) == ':' ||
419 *(ipAddress.data()+3) == ':' ||
420 *(ipAddress.data()+2) == ':' ||
421 *(ipAddress.data()+1) == ':' ||
422 *(ipAddress.data()+0) == ':');
423 }
424}
425
426Data
428{
429#ifdef USE_IPV6
430 struct in6_addr dst;
431 int res = DnsUtil::inet_pton(ipV6Address, dst);
432 if (res <= 0)
433 {
434 // .bwc. Until we supply an isIpV6Address that works, this is not an
435 // error on anyone's part but our own. Don't log as a warning/error.
436 InfoLog(<< ipV6Address << " is not a well formed IPV6 address");
437 // .bwc. We should not assert in this function, because
438 // DnsUtil::isIpV6Address does not do a full validity check. If we have no
439 // way of determining whether a V6 addr is valid before making this call,
440 // this call _needs_ to be safe.
441 // assert(0);
442 return Data::Empty;
443 }
444 return DnsUtil::inet_ntop(dst);
445#else
446 // assert(0);
447
448 return ipV6Address;
449#endif
450}
451
452bool
453DnsUtil::isIpAddress(const Data& ipAddress)
454{
455 return isIpV4Address(ipAddress) || isIpV6Address(ipAddress);
456}
457
458
459std::list<std::pair<Data,Data> >
461{
462 std::list<std::pair<Data,Data> > results;
463
464#if !defined(WIN32)
465
466 struct ifconf ifc;
467
468 int s = socket( AF_INET, SOCK_DGRAM, 0 );
469 resip_assert( s != INVALID_SOCKET ); // can run out of file descs
470 const int len = 100 * sizeof(struct ifreq);
471 int maxRet = 40;
472
473 char buf[ len ];
474 ifc.ifc_len = len;
475 ifc.ifc_buf = buf;
476
477 int e = ioctl(s,SIOCGIFCONF,&ifc);
478 char *ptr = buf;
479 int tl = ifc.ifc_len;
480 int count=0;
481
482 while ( (tl > 0) && ( count < maxRet) )
483 {
484 struct ifreq* ifr = (struct ifreq *)ptr;
485
486 count++;
487
488#if defined(__NetBSD__) || defined(__APPLE__)
489 int si = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len;
490#else
491 int si = sizeof(ifr->ifr_name) + sizeof(ifr->ifr_ifru);
492#endif
493
494 tl -= si;
495 ptr += si;
496
497 char* name = ifr->ifr_name;
498
499 struct ifreq ifr2;
500 ifr2 = *ifr;
501
502 e = ioctl(s,SIOCGIFADDR,&ifr2);
503 if ( e == -1 )
504 {
505 // no valid address for this interface, skip it
506 DebugLog (<< "Ignoring interface " << name << " as there is no valid address" );
507 continue;
508 }
509 struct sockaddr a = ifr2.ifr_addr;
510 Data ip = DnsUtil::inet_ntop(a);
511
512 e = ioctl(s,SIOCGIFFLAGS,&ifr2);
513 if ( e == -1 )
514 {
515 // no valid flags for this interface, skip it
516 DebugLog (<< "Ignoring interface " << name << " as there is no valid flags" );
517 continue;
518 }
519 short flags = ifr2.ifr_flags;
520
521#if 0
522 // if this does not work on your OS, it is not used yet,
523 // comment it out and put a note of what OS it does not work for
524 struct ifmediareq media;
525 e = ioctl(s,SIOCGIFMEDIA,&media);
526 int status = media.ifm_status;
527 int active = media.ifm_active;
528 DebugLog (<< "Media status=" << hex << status
529 << " active=" << hex << active << dec );
530#endif
531
532#if 0
533 // if this does not work on your OS, it is not used yet,
534 // comment it out and put a note of what OS it does not work for
535 e = ioctl(s,SIOCGIFPHYS,&ifr2);
536 int phys= ifr2.ifr_phys;
537 DebugLog (<< "Phys=" << hex << phys << dec );
538#endif
539
540 DebugLog (<< "Considering: " << name << " -> " << ip
541 << " flags=0x" << hex << flags << dec );
542
543 if ( (flags & IFF_UP) == 0 )
544 {
545 DebugLog (<< " ignore because: interface is not up");
546 continue;
547 }
548
549 if ( (flags & IFF_LOOPBACK) != 0 )
550 {
551 DebugLog (<< " ignore because: interface is loopback");
552 continue;
553 }
554
555 if ( (flags & IFF_RUNNING) == 0 )
556 {
557 DebugLog (<< " ignore because: interface is not running");
558 continue;
559 }
560
561 if ( ( (name[0]<'A') || (name[0]>'z') )
562#if defined(__MACH__) && defined(__GNU__) // for GNU HURD
563 && (name[0] != '/')
564#endif
565 ) // should never happen
566 {
567 DebugLog (<< " ignore because: name looks bogus");
568 resip_assert(0);
569 continue;
570 }
571
572 if (matching == Data::Empty || matching == name)
573 {
574 DebugLog (<< " using this");
575 results.push_back(std::make_pair(Data(name), ip));
576 }
577 }
578
579 close(s);
580#else
581#if defined(WIN32)
582 try
583 {
584 return WinCompat::getInterfaces(matching);
585 }
586 catch(WinCompat::Exception& e)
587 {
588 DebugLog (<< " WinCompat::getInterfaces throws " << e.getMessage());
589 return results;
590 }
591#else
592 resip_assert(0);
593#endif
594#endif
595
596 return results;
597}
598
599#ifdef __APPLE__
600const Data DnsUtil::UInt8ToStr[]={
601 "0.", "1.", "2.", "3.", "4.", "5.", "6.", "7.",
602 "8.", "9.", "10.", "11.", "12.", "13.", "14.", "15.",
603 "16.", "17.", "18.", "19.", "20.", "21.", "22.", "23.",
604 "24.", "25.", "26.", "27.", "28.", "29.", "30.", "31.",
605 "32.", "33.", "34.", "35.", "36.", "37.", "38.", "39.",
606 "40.", "41.", "42.", "43.", "44.", "45.", "46.", "47.",
607 "48.", "49.", "50.", "51.", "52.", "53.", "54.", "55.",
608 "56.", "57.", "58.", "59.", "60.", "61.", "62.", "63.",
609 "64.", "65.", "66.", "67.", "68.", "69.", "70.", "71.",
610 "72.", "73.", "74.", "75.", "76.", "77.", "78.", "79.",
611 "80.", "81.", "82.", "83.", "84.", "85.", "86.", "87.",
612 "88.", "89.", "90.", "91.", "92.", "93.", "94.", "95.",
613 "96.", "97.", "98.", "99.","100.","101.","102.","103.",
614"104.","105.","106.","107.","108.","109.","110.","111.",
615"112.","113.","114.","115.","116.","117.","118.","119.",
616"120.","121.","122.","123.","124.","125.","126.","127.",
617"128.","129.","130.","131.","132.","133.","134.","135.",
618"136.","137.","138.","139.","140.","141.","142.","143.",
619"144.","145.","146.","147.","148.","149.","150.","151.",
620"152.","153.","154.","155.","156.","157.","158.","159.",
621"160.","161.","162.","163.","164.","165.","166.","167.",
622"168.","169.","170.","171.","172.","173.","174.","175.",
623"176.","177.","178.","179.","180.","181.","182.","183.",
624"184.","185.","186.","187.","188.","189.","190.","191.",
625"192.","193.","194.","195.","196.","197.","198.","199.",
626"200.","201.","202.","203.","204.","205.","206.","207.",
627"208.","209.","210.","211.","212.","213.","214.","215.",
628"216.","217.","218.","219.","220.","221.","222.","223.",
629"224.","225.","226.","227.","228.","229.","230.","231.",
630"232.","233.","234.","235.","236.","237.","238.","239.",
631"240.","241.","242.","243.","244.","245.","246.","247.",
632"248.","249.","250.","251.","252.","253.","254.","255."
633};
634#endif // __APPLE__
635
636#if !(defined(WIN32) || defined(__CYGWIN__))
637const char *DnsUtil::inet_ntop(int af, const void* src, char* dst,
638 size_t size)
639{
640
641#ifdef __APPLE__
642 if(af==AF_INET)
643 {
644 // .bwc. inet_ntop4 seems to be implemented with sprintf on OS X.
645 // This code is about 5-6 times faster. Linux has a well-optimized
646 // inet_ntop, however.
647 const uint8_t* bytes=(const uint8_t*)src;
648 Data dest(Data::Borrow, dst, sizeof("xxx.xxx.xxx.xxx."));
649 dest.clear();
650 dest.append(UInt8ToStr[bytes[0]].data(), UInt8ToStr[bytes[0]].size());
651 dest.append(UInt8ToStr[bytes[1]].data(), UInt8ToStr[bytes[1]].size());
652 dest.append(UInt8ToStr[bytes[2]].data(), UInt8ToStr[bytes[2]].size());
653 dest.append(UInt8ToStr[bytes[3]].data(), UInt8ToStr[bytes[3]].size()-1);
654 return dst;
655 }
656 else
657#endif // __APPLE__
658 {
659 return ::inet_ntop(af, src, dst, size);
660 }
661}
662
663int DnsUtil::inet_pton(int af, const char* src, void* dst)
664{
665 return ::inet_pton(af, src, dst);
666}
667#else
668#define __restrict
669
670#define NS_INT16SZ 2
671#define NS_INADDRSZ 4
672#define NS_IN6ADDRSZ 16
673
674const char* inet_ntop4(const u_char *src, char *dst, size_t size);
675#ifdef USE_IPV6
676const char * inet_ntop6(const u_char *src, char *dst, size_t size);
677#endif
678//adapted from freebsd inet_ntop.c(1.12) and inet_pton.c(1.5) for windows(non-compliant snprinf workaround)
679/* const char *
680 * inet_ntop4(src, dst, size)
681 * format an IPv4 address, more or less like inet_ntoa()
682 * return:
683 * `dst' (as a const)
684 * notes:
685 * (1) uses no statics
686 * (2) takes a u_char* not an in_addr as input
687 * author:
688 * Paul Vixie, 1996.
689 */
690const char *
691DnsUtil::inet_ntop(int af, const void * __restrict src, char * __restrict dst,
692 size_t size)
693{
694 switch (af)
695 {
696 case AF_INET:
697 return (inet_ntop4((const u_char *)src, dst, size));
698#ifdef USE_IPV6
699 case AF_INET6:
700 return (inet_ntop6((const u_char *)src, dst, size));
701#endif
702 default:
703 errno = EAFNOSUPPORT;
704 return (NULL);
705 }
706 /* NOTREACHED */
707}
708
709
710static const char fmt[] = "%u.%u.%u.%u";
711const char*
712inet_ntop4(const u_char *src, char *dst, size_t size)
713{
714 if (snprintf(dst, size, fmt, src[0], src[1], src[2], src[3]) < 0)
715 {
716 errno = ENOSPC;
717 dst[size-1] = 0;
718 return NULL;
719 }
720 return (dst);
721}
722
723
724#ifdef USE_IPV6
725/* const char *
726 * inet_ntop6(src, dst, size)
727 * convert IPv6 binary address into presentation (printable) format
728 * author:
729 * Paul Vixie, 1996.
730 */
731
732const char *
733inet_ntop6(const u_char *src, char *dst, size_t size)
734{
735 /*
736 * Note that int32_t and int16_t need only be "at least" large enough
737 * to contain a value of the specified size. On some systems, like
738 * Crays, there is no such thing as an integer variable with 16 bits.
739 * Keep this in mind if you think this function should have been coded
740 * to use pointer overlays. All the world's not a VAX.
741 */
742 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
743 struct { int base, len; } best, cur;
744 u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
745 int i;
746
747 /*
748 * Preprocess:
749 * Copy the input (bytewise) array into a wordwise array.
750 * Find the longest run of 0x00's in src[] for :: shorthanding.
751 */
752 memset(words, '\0', sizeof words);
753 for (i = 0; i < NS_IN6ADDRSZ; i++)
754 words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
755 best.base = -1;
756 cur.base = -1;
757 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
758 if (words[i] == 0) {
759 if (cur.base == -1)
760 cur.base = i, cur.len = 1;
761 else
762 cur.len++;
763 } else {
764 if (cur.base != -1) {
765 if (best.base == -1 || cur.len > best.len)
766 best = cur;
767 cur.base = -1;
768 }
769 }
770 }
771 if (cur.base != -1) {
772 if (best.base == -1 || cur.len > best.len)
773 best = cur;
774 }
775 if (best.base != -1 && best.len < 2)
776 best.base = -1;
777
778 /*
779 * Format the result.
780 */
781 tp = tmp;
782 for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
783 /* Are we inside the best run of 0x00's? */
784 if (best.base != -1 && i >= best.base &&
785 i < (best.base + best.len)) {
786 if (i == best.base)
787 *tp++ = ':';
788 continue;
789 }
790 /* Are we following an initial run of 0x00s or any real hex? */
791 if (i != 0)
792 *tp++ = ':';
793 /* Is this address an encapsulated IPv4? */
794 if (i == 6 && best.base == 0 &&
795 (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
796 if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
797 return (NULL);
798 tp += strlen(tp);
799 break;
800 }
801 tp += snprintf(tp, sizeof(tmp) - (tp - tmp), "%x", words[i]);
802 }
803 /* Was it a trailing run of 0x00's? */
804 if (best.base != -1 && (best.base + best.len) ==
806 *tp++ = ':';
807 *tp++ = '\0';
808
809 /*
810 * Check for overflow, copy, and we're done.
811 */
812 if ((size_t)(tp - tmp) > size) {
813 errno = ENOSPC;
814 return (NULL);
815 }
816 memcpy(dst, tmp, (size_t)(tp - tmp));
817 return (dst);
818}
819
820static int inet_pton6(const char *src, u_char *dst);
821#endif //USE_IPV6
822
823static int inet_pton4(const char *src, u_char *dst);
824
825/* int
826 * inet_pton(af, src, dst)
827 * convert from presentation format (which usually means ASCII printable)
828 * to network format (which is usually some kind of binary format).
829 * return:
830 * 1 if the address was valid for the specified address family
831 * 0 if the address wasn't valid (`dst' is untouched in this case)
832 * -1 if some other error occurred (`dst' is untouched in this case, too)
833 * author:
834 * Paul Vixie, 1996.
835 */
836int
837DnsUtil::inet_pton(int af, const char* src, void* dst)
838{
839 switch (af) {
840 case AF_INET:
841 return (inet_pton4(src, (u_char*) dst));
842#ifdef USE_IPV6
843 case AF_INET6:
844 return (inet_pton6(src, (u_char*) dst));
845#endif
846 default:
847 errno = EAFNOSUPPORT;
848 return (-1);
849 }
850 /* NOTREACHED */
851}
852
853/* int
854 * inet_pton4(src, dst)
855 * like inet_aton() but without all the hexadecimal and shorthand.
856 * return:
857 * 1 if `src' is a valid dotted quad, else 0.
858 * notice:
859 * does not touch `dst' unless it's returning 1.
860 * author:
861 * Paul Vixie, 1996.
862 */
863static const char digits[] = "0123456789";
864static int
865inet_pton4(const char *src, u_char *dst)
866{
867 int saw_digit, octets, ch;
868 u_char tmp[NS_INADDRSZ], *tp;
869
870 saw_digit = 0;
871 octets = 0;
872 *(tp = tmp) = 0;
873 while ((ch = *src++) != '\0') {
874 const char *pch;
875
876 if ((pch = strchr(digits, ch)) != NULL) {
877 u_int newVal = u_int(*tp * 10 + (pch - digits));
878
879 if (newVal > 255)
880 return (0);
881 *tp = newVal;
882 if (! saw_digit) {
883 if (++octets > 4)
884 return (0);
885 saw_digit = 1;
886 }
887 } else if (ch == '.' && saw_digit) {
888 if (octets == 4)
889 return (0);
890 *++tp = 0;
891 saw_digit = 0;
892 } else
893 return (0);
894 }
895 if (octets < 4)
896 return (0);
897
898 memcpy(dst, tmp, NS_INADDRSZ);
899 return (1);
900}
901
902#ifdef USE_IPV6
903
904/* int
905 * inet_pton6(src, dst)
906 * convert presentation level address to network order binary form.
907 * return:
908 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
909 * notice:
910 * (1) does not touch `dst' unless it's returning 1.
911 * (2) :: in a full address is silently ignored.
912 * credit:
913 * inspired by Mark Andrews.
914 * author:
915 * Paul Vixie, 1996.
916 */
917static const char xdigits_l[] = "0123456789abcdef",
918 xdigits_u[] = "0123456789ABCDEF";
919static int
920inet_pton6(const char *src, u_char *dst)
921{
922 u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
923 const char *xdigits, *curtok;
924 int ch, saw_xdigit;
925 u_int val;
926
927 memset((tp = tmp), '\0', NS_IN6ADDRSZ);
928 endp = tp + NS_IN6ADDRSZ;
929 colonp = NULL;
930 /* Leading :: requires some special handling. */
931 if (*src == ':')
932 if (*++src != ':')
933 return (0);
934 curtok = src;
935 saw_xdigit = 0;
936 val = 0;
937 while ((ch = *src++) != '\0') {
938 const char *pch;
939
940 if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
941 pch = strchr((xdigits = xdigits_u), ch);
942 if (pch != NULL) {
943 val <<= 4;
944 val |= (pch - xdigits);
945 if (val > 0xffff)
946 return (0);
947 saw_xdigit = 1;
948 continue;
949 }
950 if (ch == ':') {
951 curtok = src;
952 if (!saw_xdigit) {
953 if (colonp)
954 return (0);
955 colonp = tp;
956 continue;
957 }
958 if (tp + NS_INT16SZ > endp)
959 return (0);
960 *tp++ = (u_char) (val >> 8) & 0xff;
961 *tp++ = (u_char) val & 0xff;
962 saw_xdigit = 0;
963 val = 0;
964 continue;
965 }
966 if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
967 inet_pton4(curtok, tp) > 0) {
968 tp += NS_INADDRSZ;
969 saw_xdigit = 0;
970 break; /* '\0' was seen by inet_pton4(). */
971 }
972 return (0);
973 }
974 if (saw_xdigit) {
975 if (tp + NS_INT16SZ > endp)
976 return (0);
977 *tp++ = (u_char) (val >> 8) & 0xff;
978 *tp++ = (u_char) val & 0xff;
979 }
980 if (colonp != NULL) {
981 /*
982 * Since some memmove()'s erroneously fail to handle
983 * overlapping regions, we'll do the shift by hand.
984 */
985 const int n = int(tp - colonp);
986 int i;
987
988 for (i = 1; i <= n; i++) {
989 endp[- i] = colonp[n - i];
990 colonp[n - i] = 0;
991 }
992 tp = endp;
993 }
994 if (tp != endp)
995 return (0);
996 memcpy(dst, tmp, NS_IN6ADDRSZ);
997 return (1);
998}
999
1000
1001#endif
1002#endif
1003
1004/* ====================================================================
1005 * The Vovida Software License, Version 1.0
1006 *
1007 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
1008 *
1009 * Redistribution and use in source and binary forms, with or without
1010 * modification, are permitted provided that the following conditions
1011 * are met:
1012 *
1013 * 1. Redistributions of source code must retain the above copyright
1014 * notice, this list of conditions and the following disclaimer.
1015 *
1016 * 2. Redistributions in binary form must reproduce the above copyright
1017 * notice, this list of conditions and the following disclaimer in
1018 * the documentation and/or other materials provided with the
1019 * distribution.
1020 *
1021 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
1022 * and "Vovida Open Communication Application Library (VOCAL)" must
1023 * not be used to endorse or promote products derived from this
1024 * software without prior written permission. For written
1025 * permission, please contact vocal@vovida.org.
1026 *
1027 * 4. Products derived from this software may not be called "VOCAL", nor
1028 * may "VOCAL" appear in their name, without prior written
1029 * permission of Vovida Networks, Inc.
1030 *
1031 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
1032 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1033 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
1034 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
1035 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
1036 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
1037 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1038 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
1039 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
1040 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1041 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
1042 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1043 * DAMAGE.
1044 *
1045 * ====================================================================
1046 *
1047 * This software consists of voluntary contributions made by Vovida
1048 * Networks, Inc. and many individuals on behalf of Vovida Networks,
1049 * Inc. For more information on Vovida Networks, Inc., please see
1050 * <http://www.vovida.org/>.
1051 *
1052 */
1053
1054/* Copyright (c) 1996 by Internet Software Consortium.
1055 *
1056 * Permission to use, copy, modify, and distribute this software for any
1057 * purpose with or without fee is hereby granted, provided that the above
1058 * copyright notice and this permission notice appear in all copies.
1059 *
1060 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1061 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1062 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1063 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1064 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1065 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1066 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1067 * SOFTWARE.
1068 */
1069
#define MAXHOSTNAMELEN
Definition DnsUtil.cxx:34
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define InfoLog(args_)
Definition Logger.hxx:131
#define CritLog(args_)
Definition Logger.hxx:140
#define WarningLog(args_)
Definition Logger.hxx:134
#define resip_assert(x)
This file needs to work for both C and C++ code.
Handles cross-platform sockets compatibility.
#define WSANOTINITIALISED
Definition Socket.hxx:82
#define INVALID_SOCKET
Definition Socket.hxx:95
static const struct nv flags[]
Definition adig.c:62
static int inet_pton6(const char *src, u_char *dst)
Definition ares_init.c:1278
#define NS_IN6ADDRSZ
Definition ares_init.c:1261
#define NS_INT16SZ
Definition ares_init.c:1259
static int inet_pton4(const char *src, u_char *dst)
Definition ares_init.c:1373
#define NS_INADDRSZ
Definition ares_init.c:1260
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
static const Data Empty
Constant that represents a zero-length data.
Definition Data.hxx:882
const char * c_str() const
Returns a null-terminated string representing.
Definition Data.cxx:1097
@ Borrow
The Data instance is borrowing the memory from the passed in buffer.
Definition Data.hxx:260
Data & append(const char *str, size_type len)
Appends the specified number of bytes to the end of this Data.
Definition Data.cxx:1058
Data substr(size_type first, size_type count=Data::npos) const
Copies a portion of this Data into a new Data.
Definition Data.cxx:1932
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
size_t size_type
Definition Data.hxx:94
size_type size() const noexcept
Returns the number of bytes in this Data.
Definition Data.hxx:599
size_type find(const Data &match, size_type start=0) const
Finds a specified sequence of bytes in this Data.
Definition Data.cxx:1947
static const size_type npos
Represents an impossible position; returned to indicate failure to find.
Definition Data.hxx:887
const char * begin() const noexcept
Returns a pointer to the beginning of the buffer used by the Data.
Definition Data.hxx:642
Data & clear()
Clears the contents of this Data.
Definition Data.hxx:800
const char * data() const noexcept
Returns a pointer to the contents of this Data.
Definition Data.hxx:608
static bool isIpV6Address(const Data &ipAddress)
Definition DnsUtil.cxx:386
static Data canonicalizeIpV6Address(const Data &ipV6Address)
Converts the printable form of an IPv6 address into consistent format so that string comparisons will...
Definition DnsUtil.cxx:427
static Data getLocalDomainName()
Definition DnsUtil.cxx:187
static std::list< std::pair< Data, Data > > getInterfaces(const Data &matchingInterface=Data::Empty)
Definition DnsUtil.cxx:460
static bool isIpAddress(const Data &ipAddress)
Definition DnsUtil.cxx:453
static const Data & getLocalHostName()
Definition DnsUtil.cxx:118
static int inet_pton(const Data &printableIp, struct in_addr &dst)
Convert from the presentation format of the IPv4 address to struct in_addr.
Definition DnsUtil.cxx:275
static Data inet_ntop(const struct in_addr &addr)
Converts from the network format to presentation format.
Definition DnsUtil.cxx:240
static bool isIpV4Address(const Data &ipAddress)
Definition DnsUtil.cxx:290
static std::list< Data > lookupARecords(const Data &host)
Used to synchronously query A records - only for test code usage.
Definition DnsUtil.cxx:42
static Data getLocalIpAddress(const Data &defaultInterface=Data::Empty)
Gets the IP address of "the" local interface.
Definition DnsUtil.cxx:222
This file is used to handle compatibility fixes/tweaks so reSIProcate can function on multiple platfo...
dcm! – add UnusedChecking(_enum) below;
InserterClass< T > Inserter(const T &t)
Templatized function to construct an instance of InserterClass for a container to be inserted.
Definition Inserter.hxx:312
void initNetwork()
set up network - does nothing in unix but needed for windows
Definition Socket.cxx:83
int getErrno()
Definition Socket.hxx:97
std::string strError(int err)
Definition compat.hxx:274
unsigned char uint8_t
Definition Stun.hxx:29