Drizzled Public API Documentation

ipv6.h
00001 /*
00002   Original copyright header listed below. This comes via rsync.
00003   Any additional changes are provided via the same license as the original.
00004 
00005   Copyright (C) 2011 Muhammad Umair
00006 
00007 */
00008 /*
00009  * Copyright (C) 1996-2001  Internet Software Consortium.
00010  *
00011  * Permission to use, copy, modify, and distribute this software for any
00012  * purpose with or without fee is hereby granted, provided that the above
00013  * copyright notice and this permission notice appear in all copies.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
00016  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
00018  * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
00019  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
00020  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
00021  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
00022  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00023  */
00024 
00025 #pragma once
00026 
00027 #include <cstdio>
00028 #include <cstring>
00029 #include <iostream>
00030 
00031 namespace drizzled
00032 {
00033 namespace type
00034 {
00035 
00036 class IPv6 {
00037 
00038     struct ipv6_ds
00039     {
00040       unsigned short ip6[8];
00041     } str;
00042 
00043     //Function to store the IPv4 address in IPv6 Data Structure
00044     int ipv4_inet_pton(const char *src)
00045     {
00046   char *ptr_src ;
00047   char ipv4_map_ipv6[20], ipv4[16], octet_1[5], octet_2[5], concat_octets[20];
00048   int octet[4], octet_index = 0 , dot_count = 0;
00049 
00050   static const char hex[] = "0123456789";
00051   const char * char_ptr_src;
00052 
00053   memset(ipv4_map_ipv6, 0, sizeof(ipv4_map_ipv6));
00054   strcpy(ipv4_map_ipv6, src);
00055 
00056   memset(octet, 0, sizeof(octet));
00057   memset(ipv4, 0, sizeof(ipv4));
00058   memset(octet_1, 0, sizeof(octet_1));
00059   memset(octet_2, 0, sizeof(octet_2));
00060   memset(concat_octets, 0, sizeof(concat_octets));
00061 
00062         ptr_src = ipv4_map_ipv6;
00063 
00064         if (*ptr_src == ':' && *++ptr_src != ':')
00065             return 0; // Invalid IP Address
00066 
00067         if (*ptr_src == ':' && *++ptr_src == ':')
00068             ++ptr_src;
00069 
00070   strcpy(ipv4,ptr_src);
00071 
00072   ptr_src = ipv4;
00073 
00074         while(*ptr_src != '\0')
00075         {
00076             dot_count++;
00077 
00078             if (*ptr_src == '.' && *++ptr_src != '.')
00079             {
00080                 if (dot_count == 1)
00081                     return 0; // Invalid IP Address
00082             }
00083 
00084             char_ptr_src = strchr (hex, *ptr_src);
00085 
00086             if(char_ptr_src == NULL)
00087             {
00088                 return 0; // Invalid IP Address
00089             }
00090             ++ptr_src;
00091         }
00092 
00093         ptr_src = ipv4;
00094 
00095   while(*ptr_src != '\0')
00096         {
00097             if ( *ptr_src == ':' && *++ptr_src == '\0')
00098             {
00099                     return 0; // Invalid IP Address
00100             }
00101 
00102             if ( *ptr_src == '.' && *++ptr_src == '\0')
00103             {
00104                     return 0; // Invalid IP Address
00105             }
00106           ++ptr_src;
00107         }
00108 
00109   ptr_src = strtok(ipv4,".");
00110 
00111   while (ptr_src != '\0')
00112   {
00113     sscanf(ptr_src, "%d", &octet[octet_index]);
00114 
00115     if(octet[octet_index++] > 255)
00116     {
00117       return 0; // Invalid IP Address
00118     }
00119 
00120     ptr_src = strtok (NULL, ".");
00121   }// end of main while loop
00122 
00123         if(octet[3] == 0)
00124         {
00125             octet[3] = octet[2];
00126             octet[2] = octet[1];
00127             octet[1] = octet[0];
00128             octet[0] = 0;
00129         }
00130 
00131   if(octet_index < 3 || octet_index > 4)
00132   {
00133     return 0; // Invalid IP Address
00134   }
00135 
00136   octet_index = 0;
00137 
00138         str.ip6[0] = str.ip6[1] = str.ip6[2] = str.ip6[3] = str.ip6[4] = str.ip6[5] = 0;
00139 
00140   for (int i=6 ; i <= 7; i++)
00141   {
00142     if (i == 7)
00143     {
00144       ++octet_index;
00145     }
00146 
00147     sprintf(octet_1, "%02x", octet[octet_index]);
00148 
00149     sprintf(octet_2, "%02x", octet[++octet_index]);
00150 
00151     strcpy(concat_octets,octet_1);
00152 
00153     strcat(concat_octets,octet_2);
00154 
00155     sscanf(concat_octets,"%x",(unsigned int *)&str.ip6[i]);
00156 
00157     memset(octet_1, 0, sizeof(octet_1));
00158 
00159     memset(octet_2, 0, sizeof(octet_2));
00160 
00161     memset(concat_octets, 0, sizeof(concat_octets));
00162       }
00163 
00164   return 1;
00165     }//end of ipv4_inet_pton() function
00166 
00167     //Function to retain the IPv4 address from IPv6 Data Structure
00168     char * ipv4_inet_ntop(char *destination)
00169     {
00170   memset(destination, 0, sizeof(destination));
00171 
00172   snprintf(destination, IPV6_BUFFER_LENGTH, "%03x:%03x:%03x:%03x:%03x:%03x:%03d.%03d.%03d.%03d" ,
00173   str.ip6[0],str.ip6[1],str.ip6[2],str.ip6[3],str.ip6[4],str.ip6[5],
00174   (((unsigned int )str.ip6[6]>>8) & 0xFF),
00175   ((unsigned int )str.ip6[6] & 0xFF),
00176   (((unsigned int )str.ip6[7]>>8) & 0xFF),
00177   ((unsigned int )str.ip6[7] & 0xFF));
00178 
00179   return destination;
00180 
00181     }// end of ipv4_inet_ntop function
00182 
00183 
00184     //Function to store the IPv6 address in IPv6 Data Structure
00185     int ipv6_inet_pton(const char *src)
00186     {
00187         if (strlen(src)> IPV6_DISPLAY_LENGTH)
00188         {
00189           return 0;   //Invalid IPaddress
00190         }
00191 
00192         //Local variables
00193         char ipv6[IPV6_BUFFER_LENGTH];
00194 
00195         memset(ipv6, 0, IPV6_BUFFER_LENGTH);
00196 
00197         strcpy(ipv6,src);
00198 
00199         char ipv6_temp[IPV6_BUFFER_LENGTH], ipv6_temp1[IPV6_BUFFER_LENGTH], ipv6_temp2[IPV6_BUFFER_LENGTH];
00200 
00201         memset(ipv6_temp, 0, IPV6_BUFFER_LENGTH);
00202 
00203         strcpy(ipv6_temp, ipv6);
00204 
00205         memset(ipv6_temp1, 0, IPV6_BUFFER_LENGTH);
00206 
00207         strcpy(ipv6_temp1, ipv6);
00208 
00209         memset(ipv6_temp2, 0, IPV6_BUFFER_LENGTH);
00210 
00211         strcpy(ipv6_temp2,ipv6);
00212 
00213 
00214         static const char hex[] = "0123456789abcdef";
00215         char temp[IPV6_BUFFER_LENGTH];
00216         char *ptr_src ,*ptr_char, *ptr_src1;
00217         const char *char_ptr_src;  // get the src char
00218         int char_int = 0, index_ip6 = 0, octet_count = 0, not_colon = 0, colon = 0, count_colon = 0;
00219         char temp_first[IPV6_BUFFER_LENGTH],temp_end[IPV6_BUFFER_LENGTH];
00220 
00221         memset(temp_first, 0, IPV6_BUFFER_LENGTH);
00222 
00223         memset(temp_end, 0, IPV6_BUFFER_LENGTH);
00224 
00225         ptr_src = ipv6;
00226         //while loop check three consective colons
00227          while (*ptr_src != '\0')
00228          {
00229 
00230             if (*ptr_src == ':' && *++ptr_src == ':' && *++ptr_src == ':')
00231             {
00232                 return 0; // Invalid IP Address
00233             }
00234 
00235           ++ptr_src;
00236           }
00237 
00238         ptr_src = ipv6;
00239 
00240         //Check first colon position
00241         while (*ptr_src != '\0')
00242         {
00243             count_colon++;
00244 
00245             if (*ptr_src == ':' && *++ptr_src != ':')
00246             {
00247                 if (count_colon == 1)
00248                     return 0; // Invalid IP Address
00249             }
00250 
00251           ++ptr_src;
00252         }
00253 
00254         ptr_src = ipv6;
00255 
00256         //Check last colon position
00257         while (*ptr_src != '\0')
00258         {
00259             if ( *ptr_src == ':' && *++ptr_src == '\0')
00260             {
00261                     return 0; // Invalid IP Address
00262             }
00263 
00264             ++ptr_src;
00265         }
00266 
00267         count_colon = 0;
00268 
00269         //while loop count the total number of octets
00270         ptr_src = strtok (ipv6_temp2,":");
00271 
00272 
00273         while (ptr_src != NULL)
00274         {
00275             octet_count++;
00276 
00277             ptr_src = strtok (NULL, ":");
00278         }
00279         //Retrun zero if total number of octets are greater than 8
00280         if(octet_count > 8)
00281         {
00282             return 0 ; // Invalid IP Address
00283         }
00284 
00285        bool colon_flag = true;
00286        ptr_src = ipv6;
00287 
00288   //Check the existance of consective two colons
00289         while (*ptr_src != '\0')
00290         {
00291             if (*ptr_src == ':' && *++ptr_src == ':')
00292             {
00293                 colon_flag = false;
00294             }
00295             ++ptr_src;
00296         }
00297 
00298         if (colon_flag ==  true && octet_count < 8)
00299         {
00300             return 0;
00301         }
00302 
00303         int num_miss_octet =0;
00304 
00305   num_miss_octet = 8 - octet_count;
00306 #if 0
00307         size = 2*num_miss_octet +1;
00308 #endif
00309 
00310         std::string zero_append;
00311 
00312         ptr_src = ipv6_temp;
00313 
00314         //while loop locate the "::" position (start,middle or end)
00315         while(*ptr_src != '\0')
00316         {
00317             if(*ptr_src == ':' && *++ptr_src == ':')
00318             {
00319                 if (*++ptr_src=='\0')
00320                 {
00321                     colon =2;
00322                 }
00323                 else if (not_colon == 0)
00324                 {
00325                     colon=1;
00326                 }
00327                 else
00328                 {
00329                     colon=3;
00330                 }
00331 
00332                 count_colon++;
00333 
00334                 if(count_colon == 2)
00335                 {
00336                     return 0; // Invalid IP Address. Ther must be single time double  colon '::'
00337                 }
00338             }
00339 
00340             ptr_src++;
00341             not_colon++;
00342         }// end of while loop
00343 
00344         // if colon = 0 means the IPv6 Address string is in presffered form otherwise first it covert it into prefeered form
00345         if(colon>0)
00346         {
00347             //zero padding format according to the '::' position
00348             zero_append+= "";
00349 
00350             for (int i= 0; i < num_miss_octet; i++)
00351             {
00352                 if(colon==1) // start
00353                 {
00354                     zero_append+= "0:";
00355                 }
00356 
00357                 if(colon==2 || colon==3)  //middle or end colon =2 shows at end
00358                 {
00359                     zero_append+= ":0";
00360                 }
00361             }
00362 
00363             if(colon==3)
00364             {
00365                 zero_append+= ":";
00366             }
00367 
00368             ptr_src = temp_end;
00369 
00370             if(colon==1 || colon==3)
00371             {  //only for start and middle
00372 
00373               ptr_src1 = strstr (ipv6_temp,"::");
00374 
00375               ptr_src1 = ptr_src1+2;
00376 
00377               while(*ptr_src1 != '\0')
00378               {
00379                 *ptr_src++ = *ptr_src1++;
00380 
00381                 if(*ptr_src1 == '\0')
00382                 {
00383                     *ptr_src ='\0';
00384                 }
00385               }
00386             }
00387 
00388             //copy the input IPv6 string before and after '::'
00389             ptr_src1 = strstr (ipv6_temp1,"::");
00390 
00391             *ptr_src1 ='\0';
00392 
00393             strcpy(temp_first,ipv6_temp1);
00394 
00395             if(colon==2) // end
00396             {
00397                 strcat(temp_first, zero_append.c_str());
00398             }
00399             else
00400             {
00401                 strcat(temp_first, zero_append.c_str());
00402 
00403                 strcat(temp_first,temp_end);
00404             }
00405 
00406             memset(ipv6, 0, IPV6_BUFFER_LENGTH);
00407 
00408             strcpy(ipv6,temp_first);
00409         }// end of main if statement
00410 
00411 
00412 
00413         //while loop store each octet on ipv6 struture in decimal value of hexadecimal digits
00414         ptr_char = temp;
00415 
00416         ptr_src = strtok (ipv6,":");
00417 
00418 
00419         while (ptr_src != NULL)
00420         {
00421                 strcpy(temp, ptr_src);
00422 
00423                 ptr_char = temp;
00424 
00425                 int octet_length = strlen(ptr_char);
00426 
00427                 *(ptr_char + octet_length) = '\0';
00428 
00429 
00430                 while(*ptr_char != '\0')
00431                 {
00432                     char_int = tolower(*ptr_char);
00433 
00434                     char_ptr_src = strchr (hex, char_int);
00435 
00436                     if(char_ptr_src == NULL)
00437                     {
00438                         return 0; // Invalid IP Address
00439 
00440                     }
00441 
00442                         *ptr_char = *char_ptr_src;
00443                         ptr_char++;
00444                 }//end of inner while loop
00445 
00446                 ptr_char -= octet_length;
00447 
00448                 unsigned int ptr_char_val = 0;
00449 
00450                 sscanf(ptr_char, "%x", (unsigned int *)&ptr_char_val);
00451 
00452                 //check if "xxxx" value greater than "ffff=65535"
00453                 if (ptr_char_val > 65535)
00454                 {
00455                     str.ip6[0] = str.ip6[1] = str.ip6[2] = str.ip6[3] = str.ip6[4] = str.ip6[5] = str.ip6[6] = str.ip6[7] = 0;
00456                     return 0;
00457                 }
00458 
00459                 unsigned int *ptr = (unsigned int *)&(str.ip6[index_ip6++]);
00460 
00461                 sscanf(ptr_char, "%x", ptr);
00462 
00463                 memset(temp, 0, IPV6_BUFFER_LENGTH);
00464 
00465                 ptr_src = strtok (NULL, ":");
00466         }// end of main while loop
00467 
00468         return 1;
00469     }// end of Ipv6_Inet_pton function
00470 
00471     //Function to retain the IPv6 address from IPv6 Data Structure
00472     char* ipv6_inet_ntop(char *destination)
00473     {
00474         char temp[10];
00475 
00476         memset(temp, 0, sizeof(temp));
00477 
00478         memset(destination, 0, IPV6_BUFFER_LENGTH);
00479 
00480 
00481         for (int i= 0; i <= 7; i++)
00482         {
00483             if(i==7)
00484             {
00485                 sprintf(temp,"%04x",str.ip6[i]);
00486 
00487                 strcat(destination,temp);
00488             }
00489             else
00490             {
00491                 sprintf(temp,"%04x:",str.ip6[i]);
00492 
00493                 strcat(destination,temp);
00494             }
00495 
00496             memset(temp, 0, sizeof(temp));
00497         }
00498 
00499 
00500         return destination;
00501     }// end of Ipv6_Inet_ntop function
00502 
00503 
00504     public:
00505 
00506     IPv6()
00507     {
00508         str.ip6[0] = str.ip6[1] = str.ip6[2] = str.ip6[3] = str.ip6[4] = str.ip6[5] = str.ip6[6] = str.ip6[7] = 0;
00509     }
00510 
00511 
00512     void store_object(unsigned char *out)
00513     {
00514         memcpy(out, (unsigned char *)&str, sizeof(str));
00515     }
00516 
00517     void restore_object(const unsigned char * in)
00518     {
00519       memcpy(&str, (struct ipv6_ds *)in,  sizeof(str));
00520     }
00521 
00522     int inet_pton(const char *ip)
00523     {
00524          char * pch;
00525 
00526          pch=strchr((char *)ip,'.');
00527 
00528          if(pch == NULL)
00529          {
00530             return ipv6_inet_pton(ip);
00531          }
00532          else
00533          {
00534             return ipv4_inet_pton(ip);
00535          }
00536     }
00537 
00538     char * inet_ntop(char *dest)
00539     {
00540         if (str.ip6[0]==0 && str.ip6[1]==0 && str.ip6[2]==0 && str.ip6[3]==0 && str.ip6[4]==0 && str.ip6[5]==0 && str.ip6[6]!=0)
00541         {
00542             return ipv4_inet_ntop(dest);
00543         }
00544        else
00545         {
00546             return ipv6_inet_ntop(dest);
00547         }
00548     }
00549 
00550     static const size_t LENGTH= 16;
00551     static const size_t IPV6_DISPLAY_LENGTH= 39;
00552     static const size_t IPV6_BUFFER_LENGTH= IPV6_DISPLAY_LENGTH+1;
00553 
00554 };  // endof class
00555 
00556 } /* namespace type */
00557 } /* namespace drizzled */
00558