1 karl 1.37 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.6 //
|
3 karl 1.23 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.19 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.23 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.25 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.37 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.6 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
15 kumpf 1.11 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
18 mike 1.6 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.23 //
|
21 kumpf 1.11 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
22 mike 1.6 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
24 kumpf 1.11 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
27 mike 1.6 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
|
33 mike 1.8
|
34 sage 1.12 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
|
35 r.kieninger 1.21 #include <Pegasus/Common/Config.h>
36 #endif
|
37 sage 1.12
|
38 mike 1.8 #include <fstream>
|
39 kumpf 1.13 #include <cctype> // for tolower()
|
40 kumpf 1.14 #include <cstring>
|
41 mike 1.6 #include "System.h"
|
42 r.kieninger 1.21 #include "Socket.h"
|
43 mike 1.39 #include "Network.h"
|
44 kumpf 1.10 #include <Pegasus/Common/PegasusVersion.h>
|
45 mateus.baur 1.50 #include <Pegasus/Common/FileSystem.h>
|
46 dave.sudlik 1.52 #include <Pegasus/Common/HostAddress.h>
47 #include <Pegasus/Common/Array.h>
|
48 kumpf 1.10
|
49 mike 1.6 #if defined(PEGASUS_OS_TYPE_WINDOWS)
50 # include "SystemWindows.cpp"
|
51 kumpf 1.41 #elif defined(PEGASUS_OS_TYPE_UNIX) || defined(PEGASUS_OS_VMS)
|
52 mike 1.40 # include "SystemPOSIX.cpp"
|
53 mike 1.6 #else
54 # error "Unsupported platform"
55 #endif
|
56 mike 1.8
57 PEGASUS_USING_STD;
58
59 PEGASUS_NAMESPACE_BEGIN
60
|
61 kumpf 1.20 Boolean System::bindVerbose = false;
62
|
63 mike 1.8 Boolean System::copyFile(const char* fromPath, const char* toPath)
64 {
|
65 ramnath 1.9 ifstream is(fromPath PEGASUS_IOS_BINARY);
|
66 mateus.baur 1.50 fstream os(toPath, ios::out PEGASUS_OR_IOS_BINARY);
|
67 mike 1.8
68 char c;
69
70 while (is.get(c))
71 {
|
72 kumpf 1.44 if (!os.put(c))
73 return false;
|
74 mike 1.8 }
75
|
76 mateus.baur 1.50 FileSystem::syncWithDirectoryUpdates(os);
|
77 kumpf 1.42 return is.eof();
|
78 kumpf 1.13 }
79
|
80 kumpf 1.44 static const Uint8 _toLowerTable[256] =
|
81 mike 1.32 {
82 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
83 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
84 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
85 0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
86 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
87 0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
88 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
89 0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
90 0x40,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
91 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
92 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
93 0x78,0x79,0x7A,0x5B,0x5C,0x5D,0x5E,0x5F,
94 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
95 0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
96 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,
97 0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
98 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
99 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
100 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
101 0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
102 mike 1.32 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,
103 0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
104 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,
105 0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
106 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
107 0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
108 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,
109 0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
110 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,
111 0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
112 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,
113 0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
114 };
115
|
116 kumpf 1.13 Sint32 System::strcasecmp(const char* s1, const char* s2)
117 {
|
118 mike 1.32 // Note: this is faster than glibc strcasecmp().
119
120 Uint8* p = (Uint8*)s1;
121 Uint8* q = (Uint8*)s2;
122 int r;
123
124 for (;;)
|
125 kumpf 1.13 {
|
126 kumpf 1.44 if ((r = _toLowerTable[p[0]] - _toLowerTable[q[0]]) || !p[0] ||
127 (r = _toLowerTable[p[1]] - _toLowerTable[q[1]]) || !p[1] ||
128 (r = _toLowerTable[p[2]] - _toLowerTable[q[2]]) || !p[2] ||
129 (r = _toLowerTable[p[3]] - _toLowerTable[q[3]]) || !p[3])
130 break;
|
131 kumpf 1.13
|
132 kumpf 1.44 p += 4;
133 q += 4;
|
134 kumpf 1.13 }
135
|
136 mike 1.32 return r;
|
137 mike 1.8 }
138
|
139 tony 1.15 // Return the just the file name from the path into basename
140 char *System::extract_file_name(const char *fullpath, char *basename)
141 {
|
142 kumpf 1.44 if (fullpath == NULL)
143 {
144 basename[0] = '\0';
145 return basename;
146 }
|
147 kumpf 1.31
|
148 kumpf 1.44 for (const char* p = fullpath + strlen(fullpath) - 1; p >= fullpath; p--)
149 {
150 if (*p == '\\' || *p == '/')
151 {
152 strcpy(basename, p+1);
153 return basename;
154 }
155 }
156
157 strcpy(basename, fullpath);
158 return basename;
|
159 tony 1.15 }
160
161 // Return the just the path to the file name into dirname
162 char *System::extract_file_path(const char *fullpath, char *dirname)
163 {
|
164 kumpf 1.44 char *p;
165 char buff[4096];
166 if (fullpath == NULL)
167 {
168 dirname[0] = '\0';
169 return dirname;
170 }
171 strncpy(buff, fullpath, sizeof(buff)-1);
172 buff[sizeof(buff)-1] = '\0';
173 for (p = buff + strlen(buff); p >= buff; p--)
|
174 tony 1.15 {
|
175 kumpf 1.44 if (*p == '\\' || *p == '/')
|
176 tony 1.15 {
177 strncpy(dirname, buff, p+1 - buff);
178 dirname[p+1 - buff] = '\0';
179 return dirname;
180 }
181 }
|
182 kumpf 1.44 strcpy(dirname, fullpath);
183 return dirname;
|
184 tony 1.15 }
185
|
186 kumpf 1.66 String System::getHostName()
187 {
188 static String _hostname;
189 static MutexType _mutex = PEGASUS_MUTEX_INITIALIZER;
190
191 // Use double-checked locking pattern to avoid overhead of
192 // mutex on subsequent calls.
193
194 if (0 == _hostname.size())
195 {
196 mutex_lock(&_mutex);
197
198 if (0 == _hostname.size())
199 {
200 char hostname[PEGASUS_MAXHOSTNAMELEN + 1];
201 // If gethostname() fails, an empty or truncated value is used.
202 hostname[0] = 0;
203 gethostname(hostname, sizeof(hostname));
204 hostname[sizeof(hostname)-1] = 0;
205 _hostname.assign(hostname);
206 }
207 kumpf 1.66
208 mutex_unlock(&_mutex);
209 }
210
211 return _hostname;
212 }
213
214 static String _getFullyQualifiedHostName()
215 {
216 char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
217
218 // Get the short name of the local host.
219 // If gethostname() fails, an empty or truncated value is used.
220 hostName[0] = 0;
221 gethostname(hostName, sizeof(hostName));
222 hostName[sizeof(hostName)-1] = 0;
223
224 #if defined(PEGASUS_OS_ZOS)|| \
225 defined(PEGASUS_OS_VMS)
226
227 String fqName;
228 kumpf 1.66 struct addrinfo *resolv;
229 struct addrinfo hint;
230 struct hostent *he;
231
232 memset (&hint, 0, sizeof(struct addrinfo));
233 hint.ai_flags = AI_CANONNAME;
234 hint.ai_family = AF_UNSPEC; // any family
235 hint.ai_socktype = 0; // any socket type
236 hint.ai_protocol = 0; // any protocol
|
237 carson.hovey 1.68 int success = System::getAddrInfo(hostName, NULL, &hint, &resolv);
|
238 kumpf 1.66 if (success==0)
239 {
240 // assign fully qualified hostname
241 fqName.assign(resolv->ai_canonname);
242 }
243 else
244 {
|
245 carson.hovey 1.68 if ((he = System::getHostByName(hostName)))
|
246 kumpf 1.66 {
247 strncpy(hostName, he->h_name, sizeof(hostName) - 1);
248 }
249 // assign hostName
250 // if gethostbyname was successful assign that result
251 // else assign unqualified hostname
252 fqName.assign(hostName);
253 }
254 if (resolv)
255 {
256 freeaddrinfo(resolv);
257 }
258
259 return fqName;
260
261 #else /* !PEGASUS_OS_ZOS && !PEGASUS_OS_VMS */
262
263 char hostEntryBuffer[8192];
264 struct hostent hostEntryStruct;
265 struct hostent* hostEntry = System::getHostByName(
266 hostName, &hostEntryStruct, hostEntryBuffer, sizeof (hostEntryBuffer));
267 kumpf 1.66
268 if (hostEntry)
269 {
270 strncpy(hostName, hostEntry->h_name, sizeof(hostName) - 1);
271 }
272 return String(hostName);
273
274 #endif
275 }
276
277 String System::getFullyQualifiedHostName()
278 {
279 static String _hostname;
280 static MutexType _mutex = PEGASUS_MUTEX_INITIALIZER;
281
282 // Use double-checked locking pattern to avoid overhead of
283 // mutex on subsequent calls.
284
285 if (0 == _hostname.size())
286 {
287 mutex_lock(&_mutex);
288 kumpf 1.66
289 if (0 == _hostname.size())
290 {
291 try
292 {
293 _hostname = _getFullyQualifiedHostName();
294 }
295 catch (...)
296 {
297 mutex_unlock(&_mutex);
298 throw;
299 }
300 }
301
302 mutex_unlock(&_mutex);
303 }
304
305 return _hostname;
306 }
307
|
308 dave.sudlik 1.52 Boolean System::getHostIP(const String &hostName, int *af, String &hostIP)
|
309 marek 1.24 {
|
310 dave.sudlik 1.52 #ifdef PEGASUS_ENABLE_IPV6
311 struct addrinfo *info, hints;
312 memset (&hints, 0, sizeof(struct addrinfo));
313
314 // Check for valid IPV4 address, if found return ipv4 address
315 *af = AF_INET;
316 hints.ai_family = *af;
317 hints.ai_protocol = IPPROTO_TCP;
318 hints.ai_socktype = SOCK_STREAM;
|
319 dmitry.mikulin 1.59 if (!getAddrInfo(hostName.getCString(), 0, &hints, &info))
|
320 dave.sudlik 1.52 {
321 char ipAddress[PEGASUS_INET_ADDRSTR_LEN];
322 HostAddress::convertBinaryToText(info->ai_family,
|
323 kumpf 1.54 &(reinterpret_cast<struct sockaddr_in*>(info->ai_addr))->sin_addr,
324 ipAddress,
|
325 dave.sudlik 1.52 PEGASUS_INET_ADDRSTR_LEN);
326 hostIP = ipAddress;
327 freeaddrinfo(info);
328 return true;
329 }
330
331 // Check for valid IPV6 Address.
332 *af = AF_INET6;
333 hints.ai_family = *af;
334 hints.ai_protocol = IPPROTO_TCP;
335 hints.ai_socktype = SOCK_STREAM;
|
336 dmitry.mikulin 1.59 if (!getAddrInfo(hostName.getCString(), 0, &hints, &info))
|
337 dave.sudlik 1.52 {
338 char ipAddress[PEGASUS_INET6_ADDRSTR_LEN];
339 HostAddress::convertBinaryToText(info->ai_family,
|
340 kumpf 1.54 &(reinterpret_cast<struct sockaddr_in6*>(info->ai_addr))->sin6_addr,
341 ipAddress,
|
342 dave.sudlik 1.52 PEGASUS_INET6_ADDRSTR_LEN);
343 hostIP = ipAddress;
344 freeaddrinfo(info);
345 return true;
346 }
347
348 return false;
349 #else
350 *af = AF_INET;
|
351 kumpf 1.36 struct hostent* hostEntry;
352 struct in_addr inaddr;
353 String ipAddress;
354 CString hostNameCString = hostName.getCString();
355 const char* hostNamePtr = hostNameCString;
356
357 char hostEntryBuffer[8192];
358 struct hostent hostEntryStruct;
|
359 dmitry.mikulin 1.59 hostEntry = getHostByName(hostNamePtr, &hostEntryStruct,
360 hostEntryBuffer, sizeof (hostEntryBuffer));
|
361 kumpf 1.36
362 if (hostEntry)
|
363 marek 1.24 {
|
364 kumpf 1.36 ::memcpy( &inaddr, hostEntry->h_addr,4);
|
365 marek 1.24 ipAddress = ::inet_ntoa( inaddr );
|
366 dmitry.mikulin 1.59 hostIP = ipAddress;
367 return true;
|
368 marek 1.24 }
|
369 dmitry.mikulin 1.59 return false;
|
370 dave.sudlik 1.52 #endif
|
371 marek 1.24 }
|
372 r.kieninger 1.21
|
373 venkat.puvvada 1.56
374 #ifdef PEGASUS_ENABLE_IPV6
375 Boolean System::isIPv6StackActive()
376 {
377 SocketHandle ip6Socket;
378 if ((ip6Socket = Socket::createSocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP))
379 == PEGASUS_INVALID_SOCKET)
380 {
381 if (getSocketError() == PEGASUS_INVALID_ADDRESS_FAMILY)
382 {
383 return false;
384 }
385 }
386 else
387 {
|
388 carson.hovey 1.64 #if defined(PEGASUS_OS_VMS)
389 // vms has tcpipv6 support in the kernel so socket
390 // will always work so a call to "bind" is needed
391 // to complete this test.
392
393 struct sockaddr_storage listenAddress;
394 memset(&listenAddress, 0, sizeof (listenAddress));
395 SocketLength addressLength;
396
397 HostAddress::convertTextToBinary(
398 HostAddress::AT_IPV6,
399 "::1",
400 &reinterpret_cast<struct sockaddr_in6*>(&listenAddress)->sin6_addr);
401 listenAddress.ss_family = AF_INET6;
402 reinterpret_cast<struct sockaddr_in6*>(&listenAddress)->sin6_port = 0;
403
404 addressLength = sizeof(struct sockaddr_in6);
405
406 if (::bind(
407 ip6Socket,
408 reinterpret_cast<struct sockaddr*>(&listenAddress),
409 carson.hovey 1.64 addressLength) < 0)
410 {
411 Socket::close(ip6Socket);
412 return false;
413 }
414 #endif // PEGASUS_OS_VMS
415
|
416 venkat.puvvada 1.56 Socket::close(ip6Socket);
417 }
418
419 return true;
420 }
421 #endif
422
|
423 r.kieninger 1.21 // ------------------------------------------------------------------------
424 // Convert a hostname into a a single host unique integer representation
425 // ------------------------------------------------------------------------
|
426 marek 1.63 Boolean System::acquireIP(const char* hostname, int *af, void *dst)
|
427 dave.sudlik 1.52 {
428 #ifdef PEGASUS_ENABLE_IPV6
429 String ipAddress;
430 if(getHostIP(hostname, af, ipAddress))
|
431 dmitry.mikulin 1.59 {
|
432 dave.sudlik 1.52 HostAddress::convertTextToBinary(*af, ipAddress.getCString(), dst);
433 return true;
434 }
435 return false;
436 #else
437 *af = AF_INET;
|
438 kumpf 1.44 Uint32 ip = 0xFFFFFFFF;
|
439 marek 1.65 if (!hostname)
440 {
441 *af = 0xFFFFFFFF;
442 return false;
443 }
|
444 r.kieninger 1.21
|
445 dave.sudlik 1.22 ////////////////////////////////////////////////////////////////////////////////
446 // This code used to check if the first character of "hostname" was alphabetic
|
447 kumpf 1.44 // to indicate hostname instead of IP address. But RFC 1123, section 2.1,
448 // relaxed this requirement to alphabetic character *or* digit. So bug 1462
449 // changed the flow here to call inet_addr first to check for a valid IP
450 // address in dotted decimal notation. If it's not a valid IP address, then
451 // try to validate it as a hostname.
452 // RFC 1123 states: The host SHOULD check the string syntactically for a
453 // dotted-decimal number before looking it up in the Domain Name System.
|
454 dave.sudlik 1.22 // Hence the call to inet_addr() first.
455 ////////////////////////////////////////////////////////////////////////////////
456
|
457 kumpf 1.44 Uint32 tmp_addr = inet_addr((char *) hostname);
|
458 kumpf 1.36 struct hostent* hostEntry;
|
459 r.kieninger 1.21
|
460 dave.sudlik 1.22 // Note: 0xFFFFFFFF is actually a valid IP address (255.255.255.255).
461 // A better solution would be to use inet_aton() or equivalent, as
462 // inet_addr() is now considered "obsolete".
463
464 if (tmp_addr == 0xFFFFFFFF) // if hostname is not an IP address
|
465 kumpf 1.36 {
466 char hostEntryBuffer[8192];
467 struct hostent hostEntryStruct;
|
468 dmitry.mikulin 1.59 hostEntry = getHostByName(hostname, &hostEntryStruct,
469 hostEntryBuffer, sizeof (hostEntryBuffer));
|
470 kumpf 1.36
471 if (!hostEntry)
|
472 kumpf 1.44 {
|
473 dave.sudlik 1.52 // error, couldn't resolve the ip
474 memcpy(dst, &ip, sizeof (Uint32));
475 return false;
|
476 kumpf 1.44 }
477 unsigned char ip_part1,ip_part2,ip_part3,ip_part4;
478
479 ip_part1 = hostEntry->h_addr[0];
480 ip_part2 = hostEntry->h_addr[1];
481 ip_part3 = hostEntry->h_addr[2];
482 ip_part4 = hostEntry->h_addr[3];
483 ip = ip_part1;
484 ip = (ip << 8) + ip_part2;
485 ip = (ip << 8) + ip_part3;
486 ip = (ip << 8) + ip_part4;
487 }
|
488 dave.sudlik 1.22 else // else hostname *is* a dotted-decimal IP address
|
489 kumpf 1.44 {
490 // resolve hostaddr to a real host entry
491 // casting to (const char *) as (char *) will work as (void *) too,
492 // those it fits all platforms
|
493 ms.aruran 1.45 char hostEntryBuffer[8192];
494 struct hostent hostEntryStruct;
|
495 dmitry.mikulin 1.59 hostEntry =
496 getHostByAddr((const char*) &tmp_addr, sizeof(tmp_addr), AF_INET,
497 &hostEntryStruct, hostEntryBuffer, sizeof (hostEntryBuffer));
|
498 ms.aruran 1.45
|
499 kumpf 1.44 if (hostEntry == 0)
500 {
501 // error, couldn't resolve the ip
|
502 dave.sudlik 1.52 memcpy(dst, &ip, sizeof (Uint32));
503 return false;
|
504 kumpf 1.44 }
505 else
506 {
507 unsigned char ip_part1,ip_part2,ip_part3,ip_part4;
|
508 r.kieninger 1.21
|
509 kumpf 1.44 ip_part1 = hostEntry->h_addr[0];
510 ip_part2 = hostEntry->h_addr[1];
511 ip_part3 = hostEntry->h_addr[2];
512 ip_part4 = hostEntry->h_addr[3];
513 ip = ip_part1;
514 ip = (ip << 8) + ip_part2;
515 ip = (ip << 8) + ip_part3;
516 ip = (ip << 8) + ip_part4;
517 }
518 }
|
519 dave.sudlik 1.52 memcpy(dst, &ip, sizeof (Uint32));
|
520 carolann.graves 1.29
521 return true;
|
522 dave.sudlik 1.52 #endif
|
523 carolann.graves 1.29 }
524
|
525 kumpf 1.44 Boolean System::resolveHostNameAtDNS(
526 const char* hostname,
527 Uint32* resolvedNameIP)
|
528 marek 1.43 {
|
529 dmitry.mikulin 1.59 struct hostent* hostEntry;
530
|
531 marek 1.43 // ask the DNS for hostname resolution to IP address
532 // this can mean a time delay for as long as the DNS
|
533 kumpf 1.44 // takes to answer
534 char hostEntryBuffer[8192];
535 struct hostent hostEntryStruct;
|
536 dmitry.mikulin 1.59 hostEntry = getHostByName(hostname, &hostEntryStruct,
537 hostEntryBuffer, sizeof (hostEntryBuffer));
|
538 marek 1.43
539 if (hostEntry == 0)
540 {
541 // error, couldn't resolve the hostname to an ip address
542 return false;
|
543 kumpf 1.44 }
544 else
|
545 marek 1.43 {
546 unsigned char ip_part1,ip_part2,ip_part3,ip_part4;
547 ip_part1 = hostEntry->h_addr[0];
548 ip_part2 = hostEntry->h_addr[1];
549 ip_part3 = hostEntry->h_addr[2];
550 ip_part4 = hostEntry->h_addr[3];
551 *resolvedNameIP = ip_part1;
552 *resolvedNameIP = (*resolvedNameIP << 8) + ip_part2;
553 *resolvedNameIP = (*resolvedNameIP << 8) + ip_part3;
554 *resolvedNameIP = (*resolvedNameIP << 8) + ip_part4;
555 }
556 return true;
557 }
558
559 Boolean System::resolveIPAtDNS(Uint32 ip_addr, Uint32 * resolvedIP)
560 {
|
561 kumpf 1.44 struct hostent *entry;
|
562 marek 1.43
|
563 dmitry.mikulin 1.59 entry = getHostByAddr((const char *) &ip_addr, sizeof(ip_addr), AF_INET);
|
564 ouyang.jian 1.51
|
565 kumpf 1.44 if (entry == 0)
566 {
567 // error, couldn't resolve the ip
568 return false;
569 }
570 else
571 {
572 unsigned char ip_part1,ip_part2,ip_part3,ip_part4;
573 ip_part1 = entry->h_addr[0];
574 ip_part2 = entry->h_addr[1];
575 ip_part3 = entry->h_addr[2];
576 ip_part4 = entry->h_addr[3];
577 *resolvedIP = ip_part1;
578 *resolvedIP = (*resolvedIP << 8) + ip_part2;
579 *resolvedIP = (*resolvedIP << 8) + ip_part3;
580 *resolvedIP = (*resolvedIP << 8) + ip_part4;
581 }
582 return true;
|
583 marek 1.43 }
584
585
|
586 dave.sudlik 1.52 Boolean System::isLoopBack(int af, void *binIPAddress)
587 {
588 #ifdef PEGASUS_ENABLE_IPV6
589 struct in6_addr ip6 = PEGASUS_IPV6_LOOPBACK_INIT;
590 #endif
591 Uint32 ip4 = PEGASUS_IPV4_LOOPBACK_INIT;
592 switch (af)
593 {
594 #ifdef PEGASUS_ENABLE_IPV6
595 case AF_INET6:
596 return !memcmp(&ip6, binIPAddress, sizeof (ip6));
597 #endif
598 case AF_INET:
599 Uint32 n = ntohl( *(Uint32*)binIPAddress);
600 return !memcmp(&ip4, &n, sizeof (ip4));
601 }
602
603 return false;
604 }
605
|
606 marek 1.43 Boolean System::isLocalHost(const String &hostName)
607 {
|
608 dave.sudlik 1.52 // Get all ip addresses on the node and compare them with the given hostname.
609 #ifdef PEGASUS_ENABLE_IPV6
610 CString csName = hostName.getCString();
|
611 dave.sudlik 1.53 struct addrinfo hints, *res1, *res2, *res1root, *res2root;
|
612 dave.sudlik 1.52 char localHostName[PEGASUS_MAXHOSTNAMELEN];
613 gethostname(localHostName, PEGASUS_MAXHOSTNAMELEN);
614 Boolean isLocal = false;
615
616 memset(&hints, 0, sizeof(hints));
617 hints.ai_family = AF_INET;
618 hints.ai_socktype = SOCK_STREAM;
619 hints.ai_protocol = IPPROTO_TCP;
|
620 dave.sudlik 1.53 res1root = res2root = 0;
|
621 dmitry.mikulin 1.59 getAddrInfo(csName, 0, &hints, &res1root);
622 getAddrInfo(localHostName, 0, &hints, &res2root);
|
623 dave.sudlik 1.52
|
624 dave.sudlik 1.53 res1 = res1root;
|
625 dave.sudlik 1.52 while (res1 && !isLocal)
626 {
627 if (isLoopBack(AF_INET,
|
628 kumpf 1.54 &(reinterpret_cast<struct sockaddr_in*>(res1->ai_addr))->sin_addr))
|
629 dave.sudlik 1.52 {
630 isLocal = true;
631 break;
632 }
633
|
634 dave.sudlik 1.53 res2 = res2root;
635 while (res2)
|
636 dave.sudlik 1.52 {
|
637 kumpf 1.54 if (!memcmp(
638 &(reinterpret_cast<struct sockaddr_in*>(res1->ai_addr))->
639 sin_addr,
640 &(reinterpret_cast<struct sockaddr_in*>(res2->ai_addr))->
641 sin_addr,
642 sizeof (struct in_addr)))
|
643 dave.sudlik 1.52 {
644 isLocal = true;
645 break;
646 }
|
647 dave.sudlik 1.53 res2 = res2->ai_next;
|
648 dave.sudlik 1.52 }
649 res1 = res1->ai_next;
650 }
|
651 kumpf 1.62 if (res1root)
652 {
653 freeaddrinfo(res1root);
654 }
655 if (res2root)
656 {
657 freeaddrinfo(res2root);
658 }
|
659 dave.sudlik 1.52 if (isLocal)
660 {
661 return true;
662 }
663
664 hints.ai_family = AF_INET6;
|
665 dave.sudlik 1.53 res1root = res2root = 0;
|
666 dmitry.mikulin 1.59 getAddrInfo(csName, 0, &hints, &res1root);
667 getAddrInfo(localHostName, 0, &hints, &res2root);
|
668 dave.sudlik 1.53
669 res1 = res1root;
|
670 dave.sudlik 1.52 while (res1 && !isLocal)
671 {
|
672 kumpf 1.54 if (isLoopBack(
673 AF_INET6,
674 &(reinterpret_cast<struct sockaddr_in6*>(res1->ai_addr))->
675 sin6_addr))
|
676 dave.sudlik 1.52 {
677 isLocal = true;
678 break;
679 }
680
|
681 dave.sudlik 1.53 res2 = res2root;
682 while (res2)
|
683 dave.sudlik 1.52 {
|
684 kumpf 1.54 if (!memcmp(
685 &(reinterpret_cast<struct sockaddr_in6*>(res1->ai_addr))->
686 sin6_addr,
687 &(reinterpret_cast<struct sockaddr_in6*>(res2->ai_addr))->
688 sin6_addr,
689 sizeof (struct in6_addr)))
|
690 dave.sudlik 1.52 {
691 isLocal = true;
692 break;
693 }
|
694 dave.sudlik 1.53 res2 = res2->ai_next;
|
695 dave.sudlik 1.52 }
696 res1 = res1->ai_next;
697 }
|
698 kumpf 1.62 if (res1root)
699 {
700 freeaddrinfo(res1root);
701 }
702 if (res2root)
703 {
704 freeaddrinfo(res2root);
705 }
|
706 dave.sudlik 1.52 return isLocal;
707 #else
708
|
709 marek 1.43 // differentiate between a dotted IP address given
710 // and a real hostname given
711 CString csName = hostName.getCString();
|
712 marek 1.46 char cc_hostname[PEGASUS_MAXHOSTNAMELEN];
713 strcpy(cc_hostname, (const char*) csName);
|
714 marek 1.43 Uint32 tmp_addr = 0xFFFFFFFF;
715 Boolean hostNameIsIPNotation;
716
717 // Note: Platforms already supporting the inet_aton()
718 // should define their platform here,
719 // as this is the superior way to work
|
720 kumpf 1.54 #if defined(PEGASUS_OS_LINUX) || \
721 defined(PEGASUS_OS_AIX) || \
|
722 ouyang.jian 1.55 defined(PEGASUS_OS_HPUX) || \
|
723 carson.hovey 1.60 defined(PEGASUS_OS_PASE) || \
724 defined(PEGASUS_OS_VMS)
|
725 kumpf 1.44
|
726 marek 1.43 struct in_addr inaddr;
727 // if inet_aton failed(return=0),
728 // we do not have a valip IP address (x.x.x.x)
729 int atonSuccess = inet_aton(cc_hostname, &inaddr);
730 if (atonSuccess == 0) hostNameIsIPNotation = false;
731 else
732 {
733 hostNameIsIPNotation = true;
734 tmp_addr = inaddr.s_addr;
735 }
736 #else
737 // Note: 0xFFFFFFFF is actually a valid IP address (255.255.255.255).
738 // A better solution would be to use inet_aton() or equivalent, as
739 // inet_addr() is now considered "obsolete".
740 // Note: inet_aton() not yet supported on all Pegasus platforms
|
741 kumpf 1.44 tmp_addr = inet_addr((char *) cc_hostname);
|
742 marek 1.43 if (tmp_addr == 0xFFFFFFFF) hostNameIsIPNotation = false;
743 else hostNameIsIPNotation = true;
744 #endif
|
745 kumpf 1.44
|
746 marek 1.43 if (!hostNameIsIPNotation) // if hostname is not an IP address
|
747 kumpf 1.44 {
|
748 marek 1.43 // localhost ?
749 if (String::equalNoCase(hostName,String("localhost"))) return true;
|
750 marek 1.46 char localHostName[PEGASUS_MAXHOSTNAMELEN];
|
751 marek 1.47 CString cstringLocalHostName = System::getHostName().getCString();
|
752 marek 1.46 strcpy(localHostName, (const char*) cstringLocalHostName);
|
753 marek 1.43 // given hostname equals what system returns as local hostname ?
754 if (String::equalNoCase(hostName,localHostName)) return true;
755 Uint32 hostIP;
756 // bail out if hostname unresolveable
757 if (!System::resolveHostNameAtDNS(cc_hostname, &hostIP)) return false;
758 // lets see if the IP is defined on one of the network interfaces
759 // this can help us avoid another call to DNS
760 if (System::isIpOnNetworkInterface(hostIP)) return true;
761 // need to check if the local hosts name is possibly
762 // registered at the DNS with the IP address equal resolvedNameIP
763 Uint32 localHostIP;
|
764 kumpf 1.44 if (!System::resolveHostNameAtDNS(localHostName, &localHostIP))
765 return false;
|
766 marek 1.43 if (localHostIP == hostIP) return true;
|
767 kumpf 1.44 }
768 else
|
769 marek 1.43 { // hostname is an IP address
770 // 127.0.0.1 is always the loopback
771 // inet_addr returns network byte order
772 if (tmp_addr == htonl(0x7F000001)) return true;
773 // IP defined on a local AF_INET network interface
774 if (System::isIpOnNetworkInterface(tmp_addr)) return true;
775 // out of luck so far, lets ask the DNS what our IP is
776 // and check against what we got
777 Uint32 localHostIP;
|
778 kumpf 1.44 if (!System::resolveHostNameAtDNS(
779 (const char*) System::getHostName().getCString(), &localHostIP))
780 return false;
|
781 marek 1.43 if (localHostIP == tmp_addr) return true;
782 // not yet, sometimes resolving the IP address we got against the DNS
783 // can solve the problem
|
784 kumpf 1.44 // casting to (const char *) as (char *) will work as (void *) too,
785 // those it fits all platforms
|
786 marek 1.43 Uint32 hostIP;
787 if (!System::resolveIPAtDNS(tmp_addr, &hostIP)) return false;
788 if (hostIP == localHostIP) return true;
789 }
790 return false;
|
791 dave.sudlik 1.52 #endif
|
792 marek 1.43 }
793
|
794 dmitry.mikulin 1.59 struct hostent* System::getHostByName(
795 const char* name,
796 struct hostent* he,
797 char* buf,
798 size_t len)
799 {
800 int hostEntryErrno = 0;
801 struct hostent* hostEntry = 0;
802 unsigned int maxTries = 5;
803
804 do
805 {
806 #if defined(PEGASUS_OS_LINUX)
807 gethostbyname_r(name,
808 he,
809 buf,
810 len,
811 &hostEntry,
812 &hostEntryErrno);
813 #elif defined(PEGASUS_OS_SOLARIS)
814 hostEntry = gethostbyname_r((char *)name,
815 dmitry.mikulin 1.59 he,
816 buf,
817 len,
818 &hostEntryErrno);
819 #elif defined(PEGASUS_OS_ZOS)
820 char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
821 if (String::equalNoCase("localhost", String(name)))
822 {
823 gethostname(hostName, PEGASUS_MAXHOSTNAMELEN);
824 hostName[sizeof(hostName) - 1] = 0;
825 hostEntry = gethostbyname(hostName);
826 }
827 else
828 {
829 hostEntry = gethostbyname((char *)name);
830 }
831 hostEntryErrno = h_errno;
832 #else
833 hostEntry = gethostbyname((char *)name);
834 hostEntryErrno = h_errno;
835 #endif
836 dmitry.mikulin 1.59 } while (hostEntry == 0 && hostEntryErrno == TRY_AGAIN &&
837 maxTries-- > 0);
838
839 return hostEntry;
840 }
841
842 struct hostent* System::getHostByAddr(
843 const char *addr,
844 int len,
845 int type,
846 struct hostent* he,
847 char* buf,
848 size_t buflen)
849 {
850 int hostEntryErrno = 0;
851 struct hostent* hostEntry = 0;
852 unsigned int maxTries = 5;
853
854 do
855 {
856 #if defined(PEGASUS_OS_LINUX)
857 dmitry.mikulin 1.59 gethostbyaddr_r(addr,
858 len,
859 type,
860 he,
861 buf,
862 buflen,
863 &hostEntry,
864 &hostEntryErrno);
865 #elif defined(PEGASUS_OS_SOLARIS)
866 char hostEntryBuffer[8192];
867 struct hostent hostEntryStruct;
868
869 hostEntry = gethostbyaddr_r(addr,
870 len,
871 type,
872 he,
873 buf,
874 buflen,
875 &hostEntryErrno);
876 #else
877 hostEntry = gethostbyaddr(addr,
878 dmitry.mikulin 1.59 len,
879 type);
880 hostEntryErrno = h_errno;
881 #endif
882 } while (hostEntry == 0 && hostEntryErrno == TRY_AGAIN &&
883 maxTries-- > 0);
884
885 return hostEntry;
886 }
887
|
888 dmitry.mikulin 1.61 #if defined(PEGASUS_OS_ZOS) || \
889 defined(PEGASUS_OS_VMS) || \
890 defined(PEGASUS_ENABLE_IPV6)
891
|
892 dmitry.mikulin 1.59 int System::getAddrInfo(
893 const char *hostname,
894 const char *servname,
895 const struct addrinfo *hints,
896 struct addrinfo **res)
897 {
898 int rc = 0;
899 unsigned int maxTries = 5;
900
|
901 ouyang.jian 1.67 #ifdef PEGASUS_OS_PASE
902 CString hostNameCString;
903 if (String::equalNoCase(hostname, "localhost"))
904 {
905 hostNameCString = getHostName().getCString();
906 hostname = (const char*)hostNameCString;
907 }
908 #endif
909
|
910 dmitry.mikulin 1.59 while ((rc = getaddrinfo(hostname,
911 servname,
912 hints,
913 res)) == EAI_AGAIN &&
914 maxTries-- > 0)
915 ;
916 return rc;
917 }
918
919 int System::getNameInfo(
920 const struct sockaddr *sa,
921 size_t salen,
922 char *host,
923 size_t hostlen,
924 char *serv,
925 size_t servlen,
926 int flags)
927 {
928 int rc = 0;
929 unsigned int maxTries = 5;
930
931 dmitry.mikulin 1.59 while ((rc = getnameinfo(sa,
932 salen,
933 host,
934 hostlen,
935 serv,
936 servlen,
937 flags)) == EAI_AGAIN &&
938 maxTries-- > 0)
939 ;
940 return rc;
941 }
942
|
943 dmitry.mikulin 1.61 #endif
|
944 dmitry.mikulin 1.59
|
945 tony 1.17 // System ID constants for Logger::put and Logger::trace
946 const String System::CIMLISTENER = "cimlistener"; // Listener systme ID
947
|
948 mike 1.8 PEGASUS_NAMESPACE_END
|