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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2