1 dave.sudlik 1.2.2.2 //%2007////////////////////////////////////////////////////////////////////////
2 //
3 // 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 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // 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 // 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 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 dave.sudlik 1.2.2.2 // 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 // 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 // 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
34 #include <Pegasus/Common/HostAddress.h>
35
36 PEGASUS_NAMESPACE_BEGIN
37
38 #if defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
39
40 /*
41 Address conversion utility functions.
42 */
43 dave.sudlik 1.2.2.2
44 /*
45 Converts given "src" text address (Ex: 127.0.0.1) to equivalent binary form
46 and stores in "dst" buffer (Ex 0x7f000001). Returns 1 if given ipv4 address
47 is valid or returns -1 if invalid. Returns value in network byte order.
48 */
49
50 static int _inet_ptonv4(const char *src, void *dst)
51 {
52 Boolean isValid = true;
53 Uint16 octetValue[4] = {0};
54 // Check for valid IPV4 address.
55 for (Uint32 octet = 1, i = 0; octet <= 4; octet++)
56 {
57 int j = 0;
58 if (!(isascii(src[i]) && isdigit(src[i])))
59 {
60 isValid = false;
61 break;
62 }
63 while (isascii(src[i]) && isdigit(src[i]))
64 dave.sudlik 1.2.2.2 {
65 if (j == 3)
66 {
67 isValid = false;
68 break;
69 }
70 octetValue[octet-1] = octetValue[octet-1]*10 + (src[i] - '0');
71 i++;
72 j++;
73 }
74 if (octetValue[octet-1] > 255)
75 {
76 isValid = false;
77 break;
78 }
79 // Check for invalid character in IP address
80 if ((octet != 4) && (src[i++] != '.'))
81 {
82 isValid = false;
83 break;
84 }
85 dave.sudlik 1.2.2.2 // Check for the case where it's a valid host name that happens
86 // to have 4 (or more) leading all-numeric host segments.
87 if ((octet == 4) && (src[i] != ':') &&
88 src[i] != char(0))
89 {
90 isValid = false;
91 break;
92 }
93 }
94 if (!isValid)
95 {
96 return 0;
97 }
98
99 // Return the value in network byte order.
100 Uint32 value;
101 value = octetValue[0];
102 value = (value << 8) + octetValue[1];
103 value = (value << 8) + octetValue[2];
104 value = (value << 8) + octetValue[3];
105 value = htonl(value);
106 dave.sudlik 1.2.2.2 memcpy (dst, &value, sizeof(Uint32));
107
108 return 1;
109 }
110
111 /*
112 Converts given ipv6 text address (ex. ::1) to binary form and stroes
113 in "dst" buffer (ex. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1). Returns 1
114 if src ipv6 address is valid or returns -1 if invalid. Returns value
115 in network byte order.
116 */
117 static int _inet_ptonv6(const char *src, void *dst)
118 {
119 int ccIndex = -1;
120 int sNumber = 0;
121 Uint16 sValues[8] = {0};
122 Boolean ipv4Mapped = false;
123
124 while (*src && sNumber < 8)
125 {
126 if (*src == ':')
127 dave.sudlik 1.2.2.2 {
128 if (!*++src)
129 {
130 return 0;
131 }
132 if (*src == ':')
133 {
134 if (ccIndex != -1)
135 {
136 return 0;
137 }
138 ccIndex = sNumber;
139 if (!*++src)
140 {
141 break;
142 }
143 }
144 }
145 if ((isalpha(*src) && tolower(*src) <= 'f') || isdigit(*src))
146 {
147 // Check for ipv4 compatible ipv6 or ipv4 mapped ipv6 addresses
148 dave.sudlik 1.2.2.2 if(!strchr(src, ':') && strchr(src, '.'))
149 {
150 if ( _inet_ptonv4 (src, sValues + sNumber) != 1)
151 {
152 return 0;
153 }
154 sNumber += 2;
155 ipv4Mapped = true;
156 break;
157 }
158 int chars = 0;
159 while (*src && *src != ':')
160 {
161 if (chars++ == 4)
162 {
163 return 0;
164 }
165 if (!((isalpha(*src) && tolower(*src) <= 'f') || isdigit(*src)))
166 {
167 return 0;
168 }
169 dave.sudlik 1.2.2.2 sValues[sNumber] = sValues[sNumber] * 16 +
170 (isdigit(*src) ? *src - '0' : (tolower(*src) - 'a' + 10));
171 ++src;
172 }
173 sValues[sNumber] = htons(sValues[sNumber]);
174 ++sNumber;
175 }
176 else
177 {
178 return 0;
179 }
180 }
181
182 if ((!ipv4Mapped &&*src) || (ccIndex == -1 && sNumber < 8) ||
183 (ccIndex != -1 && sNumber == 8) )
184 {
185 return 0;
186 }
187 memset(dst, 0, PEGASUS_IN6_ADDR_SIZE);
188 for (int i = 0, j = 0; i < 8 ; ++i)
189 {
190 dave.sudlik 1.2.2.2 if (ccIndex == i)
191 {
192 i += 7 - sNumber;
193 }
194 else
195 {
196 memcpy ((char*) dst + i * 2, sValues + j++ , 2);
197 }
198 }
199 return 1;
200 }
201
202 /*
203 Converts given ipv4 address in binary form to text form. Ex. 0x7f000001
204 to 127.0.0.1.
205 */
206 static const char *_inet_ntopv4(const void *src, char *dst, Uint32 size)
207 {
208
209 Uint32 n;
210
211 dave.sudlik 1.2.2.2 memset(dst, 0, size);
212 memcpy(&n, src, sizeof (Uint32));
213 n = ntohl(n);
214 sprintf(dst, "%u.%u.%u.%u", n >> 24 & 0xFF ,
215 n >> 16 & 0xFF, n >> 8 & 0xFF, n & 0xFF);
216
217 return dst;
218 }
219
220 /*
221 Converts given ipv6 address in binary form to text form. Ex.
222 0000000000000001 to ::1.
223 */
224 static const char *_inet_ntopv6(const void *src, char *dst, Uint32 size)
225 {
226
227 Uint16 n[8];
228 int ccIndex = -1;
229 int maxZeroCnt = 0;
230 int zeroCnt = 0;
231 int index = 0;
232 dave.sudlik 1.2.2.2
233 memcpy (n, src, PEGASUS_IN6_ADDR_SIZE);
234 memset(dst, 0, size);
235 for (int i = 0; i < 8 ; ++i)
236 {
237 if (n[i])
238 {
239 if (zeroCnt)
240 {
241 if (zeroCnt > maxZeroCnt)
242 {
243 ccIndex = index;
244 maxZeroCnt = zeroCnt;
245 }
246 zeroCnt = index = 0;
247 }
248 n[i] = ntohs (n[i]);
249 }
250 else
251 {
252 if(!zeroCnt++)
253 dave.sudlik 1.2.2.2 {
254 if (ccIndex == -1)
255 {
256 ccIndex = i;
257 }
258 index = i;
259 }
260 }
261 }
262 char tmp[50];
263 *dst = 0;
264 zeroCnt = 0;
265
266 for (int i = 0; i < 8 ; ++i)
267 {
268 if (i == ccIndex)
269 {
270 sprintf(tmp, "::");
271 while ( i < 8 && !n[i])
272 {
273 ++i;
274 dave.sudlik 1.2.2.2 ++zeroCnt;
275 }
276 --i;
277 }
278 else
279 {
280 Boolean mapped = false;
281 if (ccIndex == 0 && zeroCnt > 4)
282 {
283 // check for ipv4 mapped ipv6 and ipv4 compatible ipv6
284 // addresses.
285 if (zeroCnt == 5 && n[i] == 0xffff)
286 {
287 strcat(dst,"ffff:");
288 mapped = true;
289 }
290 else if (zeroCnt == 6 && n[6])
291 {
292 mapped = true;
293 }
294 }
295 dave.sudlik 1.2.2.2 if (mapped)
296 {
297 Uint32 m;
298 m = htons(n[7]);
299 m = (m << 16) + htons(n[6]);
300 HostAddress::convertBinaryToText(AF_INET, &m, tmp, 50);
301 i += 2;
302 }
303 else
304 {
305 sprintf(tmp, i < 7 && ccIndex != i + 1 ? "%x:" : "%x", n[i]);
306 }
307 }
308 strcat(dst,tmp);
309 }
310
311 return dst;
312 }
313 #endif // defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
314
315 void HostAddress::_init()
316 dave.sudlik 1.2.2.2 {
317 _hostAddrStr = String::EMPTY;
318 _isValid = false;
319 _addrType = AT_INVALID;
320 }
321
322 HostAddress::HostAddress()
323 {
324 _init();
325 }
326
327 HostAddress::HostAddress(const String &addrStr)
328 {
329 _init();
330 _hostAddrStr = addrStr;
331 _parseAddress();
332 }
333
334 HostAddress& HostAddress::operator =(const HostAddress &rhs)
335 {
336 if (this != &rhs)
337 dave.sudlik 1.2.2.2 {
338 _hostAddrStr = rhs._hostAddrStr;
339 _isValid = rhs._isValid;
340 _addrType = rhs._addrType;
341 }
342
343 return *this;
344 }
345
346 HostAddress::HostAddress(const HostAddress &rhs)
347 {
348 *this = rhs;
349 }
350
351 HostAddress::~HostAddress()
352 {
353 }
354
355 void HostAddress::setHostAddress(const String &addrStr)
356 {
357 _init();
358 dave.sudlik 1.2.2.2 _hostAddrStr = addrStr;
359 _parseAddress();
360 }
361
362 Uint32 HostAddress::getAddressType()
363 {
364 return _addrType;
365 }
366
367 Boolean HostAddress::isValid()
368 {
369 return _isValid;
370 }
371
372 String HostAddress::getHost()
373 {
374 return _hostAddrStr;
375 }
376
377 Boolean HostAddress::equal(int af, void *p1, void *p2)
378 {
379 dave.sudlik 1.2.2.2 switch (af)
380 {
381 case AT_IPV6:
382 return !memcmp(p1, p2, PEGASUS_IN6_ADDR_SIZE);
383 case AT_IPV4:
384 return !memcmp(p1, p2, sizeof(struct in_addr));
385 }
386
387 return false;
388 }
389
390 void HostAddress::_parseAddress()
391 {
392 if (_hostAddrStr == String::EMPTY)
393 {
394 return;
395 }
396 if ((_isValid = isValidIPV6Address(_hostAddrStr)))
397 {
398 _addrType = AT_IPV6;
399 }
400 dave.sudlik 1.2.2.2 else if( (_isValid = isValidIPV4Address(_hostAddrStr)))
401 {
402 _addrType = AT_IPV4;
403 }
404 else if((_isValid = isValidHostName(_hostAddrStr)))
405 {
406 _addrType = AT_HOSTNAME;
407 }
408 }
409
410 Boolean HostAddress::isValidIPV6Address (const String &ipv6Address)
411 {
412 int i = 0;
413 while (ipv6Address[i])
414 {
415 if (!isascii(ipv6Address[i++]))
416 {
417 return false;
418 }
419 }
420
421 dave.sudlik 1.2.2.2 CString addr = ipv6Address.getCString();
422 #ifdef PEGASUS_ENABLE_IPV6
423 struct in6_addr iaddr;
424 #else
425 char iaddr[PEGASUS_IN6_ADDR_SIZE];
426 #endif
427 return 1 == convertTextToBinary(AT_IPV6, (const char*) addr,
428 (void*)&iaddr);
429 }
430
431 Boolean HostAddress::isValidIPV4Address (const String &ipv4Address)
432 {
433 int i = 0;
434 while (ipv4Address[i])
435 {
436 if (!isascii(ipv4Address[i++]))
437 {
438 return false;
439 }
440 }
441
442 dave.sudlik 1.2.2.2 CString addr = ipv4Address.getCString();
443 struct in_addr iaddr;
444
445 return 1 == convertTextToBinary(AT_IPV4, (const char*) addr,
446 (void*)&iaddr);
447 }
448
449 Boolean HostAddress::isValidHostName (const String &hostName)
450 {
451 Uint32 i = 0;
452 Boolean expectHostSegment = true;
453 Boolean hostSegmentIsNumeric;
454 while (expectHostSegment)
455 {
456 expectHostSegment = false;
457 hostSegmentIsNumeric = true; // assume all-numeric host segment
458 if (!(isascii(hostName[i]) &&
459 (isalnum(hostName[i]) || (hostName[i] == '_'))))
460 {
461 return false;
462 }
463 dave.sudlik 1.2.2.2 while (isascii(hostName[i]) &&
464 (isalnum(hostName[i]) || (hostName[i] == '-') ||
465 (hostName[i] == '_')))
466 {
467 // If a non-digit is encountered, set "all-numeric"
468 // flag to false
469 if (isalpha(hostName[i]) || (hostName[i] == '-') ||
470 (hostName[i] == '_'))
471 {
472 hostSegmentIsNumeric = false;
473 }
474 i++;
475 }
476 if (hostName[i] == '.')
477 {
478 i++;
479 expectHostSegment = true;
480 }
481 }
482 // If the last Host Segment is all numeric, then return false.
483 // RFC 1123 says "highest-level component label will be alphabetic".
484 dave.sudlik 1.2.2.2 if (hostSegmentIsNumeric || hostName[i] != char(0))
485 {
486 return false;
487 }
488
489 return true;
490 }
491
492
493 int HostAddress::convertTextToBinary(int af, const char *src, void *dst)
494 {
495 #if defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
496 if (af == AT_IPV4)
497 {
498 return _inet_ptonv4(src, dst);
499 }
500 else if(af == AT_IPV6)
501 {
502 return _inet_ptonv6(src, dst);
503 }
504 return -1; // Unsupported address family.
505 dave.sudlik 1.2.2.2 #else
506 return ::inet_pton(af, src, dst);
507 #endif
508 }
509
510 const char * HostAddress::convertBinaryToText(int af, const void *src,
511 char *dst, Uint32 size)
512 {
513 #if defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
514 if (af == AT_IPV6)
515 {
516 return _inet_ntopv6(src, dst, size);
517 }
518 else if (af == AT_IPV4)
519 {
520 return _inet_ntopv4(src, dst, size);
521 }
522 return 0; // Unsupported address family.
523 #else
524 return ::inet_ntop(af, src, dst, size);
525 #endif
526 dave.sudlik 1.2.2.2 }
527
528 PEGASUS_NAMESPACE_END
|