(file) Return to HostAddress.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 dave.sudlik 1.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 // 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 
 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         {
 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         // 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     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         {
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             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                 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         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    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 
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             {
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                 ++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             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 {
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     {
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     _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     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 marek       1.3     if (_hostAddrStr.size() == 0)
393                         return;
394                 
395                     if (isValidIPV4Address(_hostAddrStr))
396 dave.sudlik 1.2     {
397 marek       1.3         _isValid = true;
398                         _addrType = AT_IPV4;
399                     } 
400                     else if (isValidIPV6Address(_hostAddrStr))
401 dave.sudlik 1.2     {
402 marek       1.3         _isValid = true;
403 dave.sudlik 1.2         _addrType = AT_IPV6;
404                     } 
405 marek       1.3     else if (isValidHostName(_hostAddrStr))
406 dave.sudlik 1.2     {
407 marek       1.3         _isValid = true;
408 dave.sudlik 1.2         _addrType = AT_HOSTNAME;
409                     }
410                 }
411                 
412                 Boolean HostAddress::isValidIPV6Address (const String &ipv6Address)
413                 {
414 marek       1.3     const Uint16* p = (const Uint16*)ipv6Address.getChar16Data();
415                     int numColons = 0;
416                 
417                     while (*p)
418 dave.sudlik 1.2     {
419 marek       1.3         if (*p > 127)
420 dave.sudlik 1.2             return false;
421 marek       1.3 
422                         if (*p == ':')
423                             numColons++;
424                 
425                         p++;
426 dave.sudlik 1.2     }
427                 
428 marek       1.3     // No need to check whether IPV6 if no colons found.
429                 
430                     if (numColons == 0)
431                         return false;
432                 
433 dave.sudlik 1.2     CString addr = ipv6Address.getCString();
434                 #ifdef PEGASUS_ENABLE_IPV6
435                     struct in6_addr iaddr;
436                 #else
437                     char iaddr[PEGASUS_IN6_ADDR_SIZE];
438                 #endif
439 marek       1.3     return  convertTextToBinary(AT_IPV6, (const char*)addr, (void*)&iaddr) == 1;
440 dave.sudlik 1.2 }
441                 
442                 Boolean HostAddress::isValidIPV4Address (const String &ipv4Address)
443                 {
444 marek       1.3     const Uint16* src = (const Uint16*)ipv4Address.getChar16Data();
445                     Uint16 octetValue[4] = {0};
446                 
447                     for (Uint32 octet = 1, i = 0; octet <= 4; octet++)
448 dave.sudlik 1.2     {
449 marek       1.3         int j = 0;
450                 
451                         if (!(isascii(src[i]) && isdigit(src[i])))
452                             return false;
453                 
454                         while (isascii(src[i]) && isdigit(src[i]))
455 dave.sudlik 1.2         {
456 marek       1.3             if (j == 3)
457                                 return false;
458                 
459                             octetValue[octet-1] = octetValue[octet-1] * 10 + (src[i] - '0');
460                             i++;
461                             j++;
462                         }
463                 
464                         if (octetValue[octet-1] > 255)
465                             return false;
466                 
467                         if ((octet != 4) && (src[i++] != '.'))
468                             return false;
469                 
470                         if ((octet == 4) && (src[i] != ':') && src[i] != char(0))
471 dave.sudlik 1.2             return false;
472                     }
473                 
474 marek       1.3     return true;
475 dave.sudlik 1.2 }
476                 
477 marek       1.3 Boolean HostAddress::isValidHostName (const String &hostName_)
478 dave.sudlik 1.2 {
479 marek       1.3     const Uint16* hostName = (const Uint16*)hostName_.getChar16Data();
480                 
481 dave.sudlik 1.2     Uint32 i = 0;
482                     Boolean expectHostSegment = true;
483                     Boolean hostSegmentIsNumeric;
484                     while (expectHostSegment)
485                     {
486                         expectHostSegment = false;
487                         hostSegmentIsNumeric = true; // assume all-numeric host segment
488                         if (!(isascii(hostName[i]) &&
489                             (isalnum(hostName[i]) || (hostName[i] == '_'))))
490                         {
491                             return false;
492                         }
493                         while (isascii(hostName[i]) &&
494                             (isalnum(hostName[i]) || (hostName[i] == '-') ||
495                                 (hostName[i] == '_')))
496                         {
497                             // If a non-digit is encountered, set "all-numeric"
498                             // flag to false
499                             if (isalpha(hostName[i]) || (hostName[i] == '-') ||
500                                 (hostName[i] == '_'))
501                             {
502 dave.sudlik 1.2                 hostSegmentIsNumeric = false;
503                             }
504                             i++;
505                         }
506                         if (hostName[i] == '.')
507                         {
508                             i++;
509                             expectHostSegment = true;
510                         }
511                     }
512                     // If the last Host Segment is all numeric, then return false.
513                     // RFC 1123 says "highest-level component label will be alphabetic".
514                     if (hostSegmentIsNumeric || hostName[i] != char(0))
515                     {
516                         return false;
517                     }
518                 
519                     return true;
520                 }
521                 
522                 
523 dave.sudlik 1.2 int HostAddress::convertTextToBinary(int af, const char *src, void *dst)
524                 {
525                 #if defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
526                     if (af == AT_IPV4)
527                     {
528                         return _inet_ptonv4(src, dst);
529                     }
530                     else if(af == AT_IPV6)
531                     {
532                         return _inet_ptonv6(src, dst);
533                     }
534                     return -1; // Unsupported address family.
535                 #else
536                     return ::inet_pton(af, src, dst);
537                 #endif 
538                 }
539                 
540                 const char * HostAddress::convertBinaryToText(int af, const void *src,
541                     char *dst, Uint32 size)
542                 {
543                 #if defined (PEGASUS_OS_TYPE_WINDOWS) || !defined (PEGASUS_ENABLE_IPV6)
544 dave.sudlik 1.2     if (af == AT_IPV6)
545                     {
546                         return _inet_ntopv6(src, dst, size);
547                     }
548                     else if (af == AT_IPV4)
549                     {
550                         return _inet_ntopv4(src, dst, size);
551                     }
552                     return 0; // Unsupported address family.
553                 #else
554                     return ::inet_ntop(af, src, dst, size);
555                 #endif 
556                 }
557                 
558                 PEGASUS_NAMESPACE_END

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2