1 martin 1.71 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.72 //
|
3 martin 1.71 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.72 //
|
10 martin 1.71 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.72 //
|
17 martin 1.71 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.72 //
|
20 martin 1.71 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.72 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.71 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.72 //
|
28 martin 1.71 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.6 //
30 //%/////////////////////////////////////////////////////////////////////////////
|
31 mike 1.8
|
32 r.kieninger 1.21 #include <Pegasus/Common/Config.h>
|
33 sage 1.12
|
34 mike 1.8 #include <fstream>
|
35 kumpf 1.13 #include <cctype> // for tolower()
|
36 kumpf 1.14 #include <cstring>
|
37 mike 1.6 #include "System.h"
|
38 r.kieninger 1.21 #include "Socket.h"
|
39 mike 1.39 #include "Network.h"
|
40 kumpf 1.10 #include <Pegasus/Common/PegasusVersion.h>
|
41 mateus.baur 1.50 #include <Pegasus/Common/FileSystem.h>
|
42 dave.sudlik 1.52 #include <Pegasus/Common/HostAddress.h>
43 #include <Pegasus/Common/Array.h>
|
44 kumpf 1.10
|
45 mike 1.6 #if defined(PEGASUS_OS_TYPE_WINDOWS)
46 # include "SystemWindows.cpp"
|
47 john.eisenbraun 1.74 #elif defined(PEGASUS_OS_TYPE_UNIX)
|
48 mike 1.40 # include "SystemPOSIX.cpp"
|
49 john.eisenbraun 1.74 # include "SystemUnix.cpp"
50 #elif defined(PEGASUS_OS_VMS)
51 # include "SystemPOSIX.cpp"
52 # include "SystemVms.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 kumpf 1.73 hints.ai_protocol = IPPROTO_TCP;
|
318 dave.sudlik 1.52 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 kumpf 1.73 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 kumpf 1.73 // Check for valid IPV6 Address.
|
332 dave.sudlik 1.52 *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 kumpf 1.73 hostEntry = getHostByName(hostNamePtr, &hostEntryStruct,
|
360 dmitry.mikulin 1.59 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 kumpf 1.73 {
|
441 marek 1.65 *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 kumpf 1.73 hostEntry = getHostByName(hostname, &hostEntryStruct,
|
469 dmitry.mikulin 1.59 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 kumpf 1.73 hostEntry =
496 getHostByAddr((const char*) &tmp_addr, sizeof(tmp_addr), AF_INET,
|
497 dmitry.mikulin 1.59 &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 kumpf 1.73 hostEntry = getHostByName(hostname, &hostEntryStruct,
|
537 dmitry.mikulin 1.59 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 kumpf 1.73
|
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 switch (af)
592 {
593 #ifdef PEGASUS_ENABLE_IPV6
594 case AF_INET6:
595 return !memcmp(&ip6, binIPAddress, sizeof (ip6));
596 #endif
597 case AF_INET:
|
598 karl 1.69 {
599 Uint32 tmp;
600 memcpy(&tmp, binIPAddress, sizeof(Uint32));
601 Uint32 n = ntohl(tmp);
|
602 venkat.puvvada 1.75 return n >= PEGASUS_IPV4_LOOPBACK_RANGE_START &&
603 n <= PEGASUS_IPV4_LOOPBACK_RANGE_END;
|
604 karl 1.69 }
|
605 dave.sudlik 1.52 }
606
607 return false;
608 }
609
|
610 marek 1.43 Boolean System::isLocalHost(const String &hostName)
611 {
|
612 dave.sudlik 1.52 // Get all ip addresses on the node and compare them with the given hostname.
613 #ifdef PEGASUS_ENABLE_IPV6
614 CString csName = hostName.getCString();
|
615 dave.sudlik 1.53 struct addrinfo hints, *res1, *res2, *res1root, *res2root;
|
616 dave.sudlik 1.52 char localHostName[PEGASUS_MAXHOSTNAMELEN];
617 gethostname(localHostName, PEGASUS_MAXHOSTNAMELEN);
618 Boolean isLocal = false;
619
620 memset(&hints, 0, sizeof(hints));
621 hints.ai_family = AF_INET;
622 hints.ai_socktype = SOCK_STREAM;
623 hints.ai_protocol = IPPROTO_TCP;
|
624 dave.sudlik 1.53 res1root = res2root = 0;
|
625 dmitry.mikulin 1.59 getAddrInfo(csName, 0, &hints, &res1root);
626 getAddrInfo(localHostName, 0, &hints, &res2root);
|
627 dave.sudlik 1.52
|
628 dave.sudlik 1.53 res1 = res1root;
|
629 dave.sudlik 1.52 while (res1 && !isLocal)
630 {
631 if (isLoopBack(AF_INET,
|
632 kumpf 1.54 &(reinterpret_cast<struct sockaddr_in*>(res1->ai_addr))->sin_addr))
|
633 dave.sudlik 1.52 {
634 isLocal = true;
635 break;
636 }
637
|
638 dave.sudlik 1.53 res2 = res2root;
|
639 kumpf 1.73 while (res2)
|
640 dave.sudlik 1.52 {
|
641 kumpf 1.54 if (!memcmp(
642 &(reinterpret_cast<struct sockaddr_in*>(res1->ai_addr))->
643 sin_addr,
644 &(reinterpret_cast<struct sockaddr_in*>(res2->ai_addr))->
645 sin_addr,
646 sizeof (struct in_addr)))
|
647 dave.sudlik 1.52 {
648 isLocal = true;
649 break;
650 }
|
651 dave.sudlik 1.53 res2 = res2->ai_next;
|
652 dave.sudlik 1.52 }
653 res1 = res1->ai_next;
|
654 kumpf 1.73 }
|
655 kumpf 1.62 if (res1root)
656 {
657 freeaddrinfo(res1root);
658 }
659 if (res2root)
660 {
661 freeaddrinfo(res2root);
662 }
|
663 dave.sudlik 1.52 if (isLocal)
664 {
665 return true;
|
666 kumpf 1.73 }
|
667 dave.sudlik 1.52
668 hints.ai_family = AF_INET6;
|
669 dave.sudlik 1.53 res1root = res2root = 0;
|
670 dmitry.mikulin 1.59 getAddrInfo(csName, 0, &hints, &res1root);
671 getAddrInfo(localHostName, 0, &hints, &res2root);
|
672 dave.sudlik 1.53
673 res1 = res1root;
|
674 dave.sudlik 1.52 while (res1 && !isLocal)
675 {
|
676 kumpf 1.54 if (isLoopBack(
677 AF_INET6,
678 &(reinterpret_cast<struct sockaddr_in6*>(res1->ai_addr))->
679 sin6_addr))
|
680 dave.sudlik 1.52 {
681 isLocal = true;
682 break;
683 }
684
|
685 dave.sudlik 1.53 res2 = res2root;
686 while (res2)
|
687 dave.sudlik 1.52 {
|
688 kumpf 1.54 if (!memcmp(
689 &(reinterpret_cast<struct sockaddr_in6*>(res1->ai_addr))->
690 sin6_addr,
691 &(reinterpret_cast<struct sockaddr_in6*>(res2->ai_addr))->
692 sin6_addr,
693 sizeof (struct in6_addr)))
|
694 dave.sudlik 1.52 {
695 isLocal = true;
696 break;
697 }
|
698 dave.sudlik 1.53 res2 = res2->ai_next;
|
699 dave.sudlik 1.52 }
700 res1 = res1->ai_next;
701 }
|
702 kumpf 1.62 if (res1root)
703 {
704 freeaddrinfo(res1root);
705 }
706 if (res2root)
707 {
708 freeaddrinfo(res2root);
709 }
|
710 dave.sudlik 1.52 return isLocal;
711 #else
712
|
713 marek 1.43 // differentiate between a dotted IP address given
714 // and a real hostname given
715 CString csName = hostName.getCString();
|
716 marek 1.46 char cc_hostname[PEGASUS_MAXHOSTNAMELEN];
717 strcpy(cc_hostname, (const char*) csName);
|
718 marek 1.43 Uint32 tmp_addr = 0xFFFFFFFF;
719 Boolean hostNameIsIPNotation;
720
721 // Note: Platforms already supporting the inet_aton()
722 // should define their platform here,
723 // as this is the superior way to work
|
724 kumpf 1.54 #if defined(PEGASUS_OS_LINUX) || \
725 defined(PEGASUS_OS_AIX) || \
|
726 ouyang.jian 1.55 defined(PEGASUS_OS_HPUX) || \
|
727 carson.hovey 1.60 defined(PEGASUS_OS_PASE) || \
728 defined(PEGASUS_OS_VMS)
|
729 kumpf 1.44
|
730 marek 1.43 struct in_addr inaddr;
731 // if inet_aton failed(return=0),
732 // we do not have a valip IP address (x.x.x.x)
733 int atonSuccess = inet_aton(cc_hostname, &inaddr);
734 if (atonSuccess == 0) hostNameIsIPNotation = false;
735 else
736 {
737 hostNameIsIPNotation = true;
738 tmp_addr = inaddr.s_addr;
739 }
740 #else
741 // Note: 0xFFFFFFFF is actually a valid IP address (255.255.255.255).
742 // A better solution would be to use inet_aton() or equivalent, as
743 // inet_addr() is now considered "obsolete".
744 // Note: inet_aton() not yet supported on all Pegasus platforms
|
745 kumpf 1.44 tmp_addr = inet_addr((char *) cc_hostname);
|
746 marek 1.43 if (tmp_addr == 0xFFFFFFFF) hostNameIsIPNotation = false;
747 else hostNameIsIPNotation = true;
748 #endif
|
749 kumpf 1.44
|
750 marek 1.43 if (!hostNameIsIPNotation) // if hostname is not an IP address
|
751 kumpf 1.44 {
|
752 marek 1.43 // localhost ?
753 if (String::equalNoCase(hostName,String("localhost"))) return true;
|
754 marek 1.46 char localHostName[PEGASUS_MAXHOSTNAMELEN];
|
755 marek 1.47 CString cstringLocalHostName = System::getHostName().getCString();
|
756 kumpf 1.73 strcpy(localHostName, (const char*) cstringLocalHostName);
|
757 marek 1.43 // given hostname equals what system returns as local hostname ?
758 if (String::equalNoCase(hostName,localHostName)) return true;
759 Uint32 hostIP;
760 // bail out if hostname unresolveable
761 if (!System::resolveHostNameAtDNS(cc_hostname, &hostIP)) return false;
762 // lets see if the IP is defined on one of the network interfaces
763 // this can help us avoid another call to DNS
764 if (System::isIpOnNetworkInterface(hostIP)) return true;
765 // need to check if the local hosts name is possibly
766 // registered at the DNS with the IP address equal resolvedNameIP
767 Uint32 localHostIP;
|
768 kumpf 1.44 if (!System::resolveHostNameAtDNS(localHostName, &localHostIP))
769 return false;
|
770 marek 1.43 if (localHostIP == hostIP) return true;
|
771 kumpf 1.44 }
772 else
|
773 marek 1.43 { // hostname is an IP address
774 // 127.0.0.1 is always the loopback
775 // inet_addr returns network byte order
776 if (tmp_addr == htonl(0x7F000001)) return true;
777 // IP defined on a local AF_INET network interface
778 if (System::isIpOnNetworkInterface(tmp_addr)) return true;
779 // out of luck so far, lets ask the DNS what our IP is
780 // and check against what we got
781 Uint32 localHostIP;
|
782 kumpf 1.44 if (!System::resolveHostNameAtDNS(
783 (const char*) System::getHostName().getCString(), &localHostIP))
784 return false;
|
785 marek 1.43 if (localHostIP == tmp_addr) return true;
786 // not yet, sometimes resolving the IP address we got against the DNS
787 // can solve the problem
|
788 kumpf 1.44 // casting to (const char *) as (char *) will work as (void *) too,
789 // those it fits all platforms
|
790 marek 1.43 Uint32 hostIP;
791 if (!System::resolveIPAtDNS(tmp_addr, &hostIP)) return false;
792 if (hostIP == localHostIP) return true;
793 }
794 return false;
|
795 dave.sudlik 1.52 #endif
|
796 marek 1.43 }
797
|
798 dmitry.mikulin 1.59 struct hostent* System::getHostByName(
|
799 kumpf 1.73 const char* name,
800 struct hostent* he,
801 char* buf,
|
802 dmitry.mikulin 1.59 size_t len)
803 {
804 int hostEntryErrno = 0;
805 struct hostent* hostEntry = 0;
806 unsigned int maxTries = 5;
807
808 do
809 {
810 #if defined(PEGASUS_OS_LINUX)
|
811 kumpf 1.73 gethostbyname_r(name,
812 he,
813 buf,
814 len,
815 &hostEntry,
|
816 dmitry.mikulin 1.59 &hostEntryErrno);
817 #elif defined(PEGASUS_OS_SOLARIS)
|
818 kumpf 1.73 hostEntry = gethostbyname_r((char *)name,
819 he,
820 buf,
821 len,
|
822 dmitry.mikulin 1.59 &hostEntryErrno);
823 #elif defined(PEGASUS_OS_ZOS)
824 char hostName[PEGASUS_MAXHOSTNAMELEN + 1];
825 if (String::equalNoCase("localhost", String(name)))
826 {
827 gethostname(hostName, PEGASUS_MAXHOSTNAMELEN);
828 hostName[sizeof(hostName) - 1] = 0;
829 hostEntry = gethostbyname(hostName);
830 }
831 else
832 {
833 hostEntry = gethostbyname((char *)name);
834 }
835 hostEntryErrno = h_errno;
836 #else
837 hostEntry = gethostbyname((char *)name);
838 hostEntryErrno = h_errno;
839 #endif
840 } while (hostEntry == 0 && hostEntryErrno == TRY_AGAIN &&
841 maxTries-- > 0);
842
843 dmitry.mikulin 1.59 return hostEntry;
844 }
845
846 struct hostent* System::getHostByAddr(
|
847 kumpf 1.73 const char *addr,
848 int len,
|
849 dmitry.mikulin 1.59 int type,
|
850 kumpf 1.73 struct hostent* he,
851 char* buf,
|
852 dmitry.mikulin 1.59 size_t buflen)
853 {
854 int hostEntryErrno = 0;
855 struct hostent* hostEntry = 0;
856 unsigned int maxTries = 5;
857
858 do
859 {
860 #if defined(PEGASUS_OS_LINUX)
|
861 kumpf 1.73 gethostbyaddr_r(addr,
862 len,
863 type,
864 he,
865 buf,
866 buflen,
867 &hostEntry,
|
868 dmitry.mikulin 1.59 &hostEntryErrno);
869 #elif defined(PEGASUS_OS_SOLARIS)
870 char hostEntryBuffer[8192];
871 struct hostent hostEntryStruct;
872
|
873 kumpf 1.73 hostEntry = gethostbyaddr_r(addr,
874 len,
875 type,
876 he,
877 buf,
878 buflen,
|
879 dmitry.mikulin 1.59 &hostEntryErrno);
880 #else
|
881 kumpf 1.73 hostEntry = gethostbyaddr(addr,
882 len,
|
883 dmitry.mikulin 1.59 type);
884 hostEntryErrno = h_errno;
885 #endif
886 } while (hostEntry == 0 && hostEntryErrno == TRY_AGAIN &&
887 maxTries-- > 0);
888
889 return hostEntry;
890 }
891
|
892 dmitry.mikulin 1.61 #if defined(PEGASUS_OS_ZOS) || \
893 defined(PEGASUS_OS_VMS) || \
894 defined(PEGASUS_ENABLE_IPV6)
895
|
896 dmitry.mikulin 1.59 int System::getAddrInfo(
|
897 kumpf 1.73 const char *hostname,
|
898 dmitry.mikulin 1.59 const char *servname,
|
899 kumpf 1.73 const struct addrinfo *hints,
|
900 dmitry.mikulin 1.59 struct addrinfo **res)
901 {
902 int rc = 0;
|
903 kumpf 1.73 unsigned int maxTries = 5;
|
904 dmitry.mikulin 1.59
|
905 ouyang.jian 1.67 #ifdef PEGASUS_OS_PASE
906 CString hostNameCString;
907 if (String::equalNoCase(hostname, "localhost"))
908 {
909 hostNameCString = getHostName().getCString();
910 hostname = (const char*)hostNameCString;
911 }
912 #endif
913
|
914 kumpf 1.73 while ((rc = getaddrinfo(hostname,
915 servname,
916 hints,
|
917 dmitry.mikulin 1.59 res)) == EAI_AGAIN &&
918 maxTries-- > 0)
919 ;
920 return rc;
921 }
922
923 int System::getNameInfo(
|
924 kumpf 1.73 const struct sockaddr *sa,
|
925 dmitry.mikulin 1.59 size_t salen,
|
926 kumpf 1.73 char *host,
927 size_t hostlen,
928 char *serv,
929 size_t servlen,
|
930 dmitry.mikulin 1.59 int flags)
931 {
932 int rc = 0;
|
933 kumpf 1.73 unsigned int maxTries = 5;
|
934 dmitry.mikulin 1.59
|
935 kumpf 1.73 while ((rc = getnameinfo(sa,
936 salen,
937 host,
938 hostlen,
939 serv,
940 servlen,
|
941 dmitry.mikulin 1.59 flags)) == EAI_AGAIN &&
942 maxTries-- > 0)
943 ;
944 return rc;
945 }
946
|
947 dmitry.mikulin 1.61 #endif
|
948 dmitry.mikulin 1.59
|
949 tony 1.17 // System ID constants for Logger::put and Logger::trace
950 const String System::CIMLISTENER = "cimlistener"; // Listener systme ID
951
|
952 mike 1.8 PEGASUS_NAMESPACE_END
|