ipv6地址转换

来源:互联网 发布:snapseed软件下载 编辑:程序博客网 时间:2024/05/17 02:44
ipv6地址解析
/* ipv6 无符号整型数组转化为字符串 */void ipv6_to_str(char *addr_str, unsigned int ipv6_addr[]){/* ipv6地址128位,数组ip维数默认为4 *//* 输出格式为: A:B:C:D:E:F:G:H. */int i;unsigned short msw, lsw;char *addr_str_end_ptr;addr_str[0] = '\0';addr_str_end_ptr = addr_str;for (i = 0; i < 4; i++){msw = ipv6_addr[i] >> 16;lsw = ipv6_addr[i] & 0x0000ffff;addr_str_end_ptr += sprintf(addr_str_end_ptr, "%X:%X:", msw, lsw); }*(addr_str_end_ptr - 1) = '\0';}char * string_white_space_trim(char *str){/* 移除字符串中空格 */int index;int new_index;int str_length;str_length = strlen(str);for (index = 0, new_index = 0; index < str_length; index++){if (!isspace((unsigned char)str[index])){str[new_index] = str[index];new_index++;}}str[new_index] = '\0';return str;}int string_char_count(const char *string, char character){/* 计算字符串中,给定字符的数量 */int i;int str_length;int count = 0;str_length = strlen(string);for (i = 0; i < str_length; i++){if (string[i] == character){count++;}}return count;}int ipv6_address_field_type_get(const char * field_str){/* 判断ipv6地址域类型                           */int i = 0;int length;int type;unsigned int ipv4_addr;/* 通过长度判断          *//* 16进制数字域: 1-4    *//* "::"域:0             *//* ipv4地址域: 7-15     */length = strlen(field_str);if (0 == length){type = 1;}else if (length <= 4){// 确保每个数字为16进制for (i = 0; i < length; i++){if (!isxdigit((unsigned char)field_str[i])){return -1;}}type = 0;}else if((length >= 7) && (length <= 15)){//确保是有效的ipv4地址if (ipv4_to_i(field_str, &ipv4_addr)){type = 2;}else{type = -1;}}else{type = -1;}return type;}int ipv6_to_i(const char *addr_str, int length, unsigned int ipv6_addr_ptr[]){/***************************************************************************//* 功能:解析ipv6地址字符串,转换为无符号整形,存入4个无符号整形的一维数组  *//* ipv6地址 128位,prefix length:                   *//*                         - 64 for EUI-64 addresses                       *//*                         - 128 for non-EUI-64 addresses                  *//* 输入:ipv6地址字符串,地址位数,默认为128位                             *//* 输出:返回解析成功或失败;指向4个无符号整形的一维数组的指针              *//****************************************************************************/char addr_str_copy[256];int i, num_fields;//unsigned int *ret_addr_ptr;unsigned short int addr_field_arr[8];int addr_index;char *ith_field; // 指向地址当前域int  ith_field_type; // 地址域类型char *next_field;int  double_colon_field_index = -1; // 字符串地址中"::"的位置unsigned int ipv4_address; // ipv6地址中的ipv4部分unsigned int msw, lsw;int error = 0;//复制一份,以便操作strcpy(addr_str_copy, addr_str);// 移除字符串中的空格字符string_white_space_trim(addr_str_copy);/* IPv6地址可能几种格式:                                          *//* 1) 2006:DB8:2A0:2F3B:34:E35:45:1   用16进制表示每个域的值(16位) *//* 2) 2006:DB8::E34:1 , "::" 代表0,且只能出现一次       *//* 3) 2002:9D36:1:2:0:5EFE:192.168.12.9 带有ipv4地址     */// 计算字符串中冒号,字符串中地址域数比冒号多一个num_fields = string_char_count(addr_str_copy, ':') + 1;// 域最大数量为length/16 + 2// 如  ::0:0:0:0:0:0:0:0.if (num_fields > ((length >> 4) + 2)){ipv6_addr_ptr = NULL;return 0;}// 初始化ith_field = addr_str_copy;for (i = 0, addr_index = 0; i < num_fields; i++){// 获得下一个域的指针next_field = strchr(ith_field, ':');/* 若当前是最后一个域, next_field 是 NULL                       *//* 否则,替换':'为'\0', 字符串可以结束,从而ith_field指向当前域   *//* next_field指向下一个域头部                                    */if (NULL != next_field){*next_field = '\0';++next_field;}// 发现这个域的类型ith_field_type = ipv6_address_field_type_get(ith_field);switch (ith_field_type){case 0:// 域类型为16进制表示if (addr_index >= (length >> 4)){error = 1;break;}// 字符串转换为16进制addr_field_arr[addr_index] = (unsigned short)strtoul(ith_field, NULL, 16);++addr_index;break;case 1:// 域类型为 "::"// 若出现在字符串的开头或结尾,忽略if ((0 == i) || (i == num_fields - 1)){break;}// 若出现大于一次,错误if (double_colon_field_index != -1){error = 1;break;}// 记下位置double_colon_field_index = addr_index;break;case 2:// 域类型为ipv4地址// 确保在地址中还有两个未设置的域if (addr_index >= 7){error = 1;break;}// ipv4地址解析ipv4_to_i(ith_field, &ipv4_address);// 存储高16位addr_field_arr[addr_index] = (unsigned short)(ipv4_address >> 16);// 存储低16位addr_field_arr[addr_index + 1] = (unsigned short)(ipv4_address & 0x0000ffff);addr_index += 2;break;default:error = 1;break;}if (error){ipv6_addr_ptr = NULL;return 0;}ith_field = next_field;}// 计算的域不是8,并且没有"::",错误if ((addr_index != (length >> 4)) && (-1 == double_colon_field_index)){ipv6_addr_ptr = NULL;return 0;}if ((addr_index != (length >> 4)) && (-1 != double_colon_field_index)){// 设置相应"::"对应addr_field_arr中位置为0memmove(addr_field_arr + (double_colon_field_index + (length >> 4) - addr_index),addr_field_arr + double_colon_field_index, (addr_index - double_colon_field_index) * 2);memset(addr_field_arr + double_colon_field_index, 0, ((length >> 4) - addr_index) * 2);}for (i = 0; i < 4; i++){msw = addr_field_arr[2 * i];lsw = addr_field_arr[2 * i + 1];(ipv6_addr_ptr)[i] = (msw << 16 | lsw);}return 1;}int main(){char addr[256];unsigned int ip_v4 = 3356567252;unsigned int ipv6[4] = {3356567252, 3356567253, 3356567254, 3356567255};unsigned int ipv61[4] = {65538, 196612, 327686, 458760};char *ipv6_str1 = "1:2:3:4:5:6:7:8";char *ipv6_str2 = "1:2:3:4:5:6:7:8::";char *ipv6_str3 = "::1:2:3:4:5:6:7:8";char *ipv6_str4 = "1:2:3:4:5:6:192.168.1.100";char *ipv6_str5 = "1:2::5:6:7:8";char *ipv6_str6 = "1::3:4:5:6:7:8";char *ipv6_str7 = "1::4:5:6:7:8";char *ipv6_str8 = "1::8";unsigned int ipv6_addr[4];unsigned int ipv4_addr;int flag;int i;    // 192.168.1.100-----3232235876//ipv4_to_str(addr, ip_v4);//printf("ipv4: %s\n", addr);ipv6_to_str(addr, ipv61);printf("ipv6: %s\n", addr);flag = ipv4_to_i("192.168.1.100", &ipv4_addr);if (flag){printf("ipv4_addr: %u\n", ipv4_addr);}flag = ipv6_to_i(ipv6_str8, 128, ipv6_addr);if (flag){for (i = 0; i < 4; i++){printf("ipv6_addr: %u\n", ipv6_addr[i]);}}return 0;}


原创粉丝点击