Radius 协议中的ipv6 处理算法思路
如果我们想要模拟一个协议或者多个协议进行相关的操作,那么首先我们要了解这个协议中的数据发送传输,如何定义包的类型和格式。通常情况下,很少有人用C#来做这些东西。因为如此底层的东西,C#做不了,我也不打算用C#做底层协议UDP或者Radius中的通信,但是如果你用来测试某个协议,从底层到上层两个终端之间的通信的话,我想C#还是可以做的。
引入:如果做协议包的收发测试,对于一般包的定义格式,通常情况下,会用byte[]数组对一个ip地址进行存储和发送。有的时候,例如一个ipv4地址,的话,简单的函数调用Split('.") 192.168.1.1就可以按着'.'进行了分割。那么对于radius协议中,如果使用ipv6进行通信地址格式的话,我们应该如何处理地址到一些字符数组中呢。下面看一下 RFC中的地址格式定义:
A summary of the NAS-IPv6-Address Attribute format is shown below.
The fields are transmitted from left to right.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length | Address
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Address
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Address
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Address
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Address |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
我们姑且不管如何到byte[]数组,毕竟他的存储范围是有限的,暂且在这篇文章中使用string数组进行存储。分割好的IPv6地址。说到IPV6的地址格式,对于不是很清楚的童鞋们,我简单的进行阐述。
算法输出结果预估,先写出来大家对算法目的看的更清楚
Input : n:n:n:n:n:n:n:n。
OutPut:new string[8] {"n",....."n"} 直接输出
Input:3FFE:FFFF::8:800:20C4:0 ::1
OutPut:{"3FFE","FFFF","0","0",...."20C4","0"} 补零输出 {"0","0",......"1"}
Input:n:n:n:n:n:n:d.d.d.d
OutPut: {"n","n"....."d.d->16位16进制","d.d->16位16进制"}
Input: n:n::d.d.d.d
Output: {"n","n","0","0",...."d.d->16位16进制"}
算法部分:对于此种的ipv6地址,就算是当他最标准的吧,从头到尾都是:分割,那么,直接使用split函数以:分割即可,得到一个长度为8的数组。
对于有(::)在地址里面的,我们首先使用::将IP地址分成前后两个部分,之后计算前后两部分的长度,填充中间的省略的0的个数,返回冒号十六进制的形式IPV6标准数组。
对于混合式的IPv6地址比较复杂,因为如果单纯的是前96位:表示的IPv6地址加上后面的32位IPv4地址,也好处理,将后面的部分以'.'分割之后,变换成连个16位的ipv6即可。但是考虑到前面会有省略的一部分0的,也就是存在::形式的IPv6地址,那么就要参考压缩式的处理方式先对::进行分割后,在对存在'.'的ipv4混合地址进行处理。
附上代码,没来得及优化,测试几个还行。比较乱,有几个罗嗦的地方还需要改进。
public static string[] IPAddressToArray(string address)
{
string[] result = new string[8];
//address = string.Empty;
string[] ip = null;
string[] iptemp = null;
string[] iptempv4 = null;
string[] ipresult = new string[8];
//address = "5::2:10:20";
string[] a = { "::" };
if (address.Contains(':')) // ipv6 must contain ':'
{
if (address.Contains("::")) // for the ipv6 omit some zero (0) in the address
{
ip = address.Split(a, StringSplitOptions.None);
iptemp = ip[0].Split(':');
iptempv4 = ip[1].Split(':');
int iptempLength = 0;
if (iptemp[0] != string.Empty)
{
iptempLength = iptemp.Length;
}
int iptempv4Length = iptempv4.Length;
int j = 0;
int n = 0;
int k = 8 - iptempLength - iptempv4Length;
bool containsPoint = false;
foreach (string ipa in iptempv4)
{
if (ipa.Contains('.'))
{
containsPoint = true;
}
}
if (!containsPoint) // ipv6 type not contain extended ipv4 (e.g. fec0:0:0:1::1234)
{
for (int i = 0; i < 8; i++)
{
while (iptempLength != 0 && j < iptempLength)
{
ipresult[i] = iptemp[j];
i++;
j++;
}
while (k != 0)
{
ipresult[i] = "0";
i++;
k--;
}
int m = 0;
while ((8 - i) != 0)
{
ipresult[i] = iptempv4[m];
i++;
m++;
}
}
}
else // incluede extended ipv4 in the address (e.g. 0:0:0:0:0:0:10.1.2.3 ===== ::10.1.2.3)
{
int i =0;
while(i<8)
{
while (iptempLength != 0 && j < iptempLength)
{
ipresult[i] = iptemp[j];
i++;
j++;
}
while (k - 1 != 0)
{
ipresult[i] = "0";
i++;
k--;
}
while (iptempv4Length != 0 && !iptempv4[n].Contains ('.'))
{
iptempv4Length--;
ipresult[i] = iptempv4[n];
n++;
}
ipresult[i] = MergeIpv4ToV6Type(iptempv4[iptempv4.Length - 1])[0];
ipresult[++i] = MergeIpv4ToV6Type(iptempv4[iptemp.Length - 1])[1];
i++;
}
result = ipresult;
}
}
else
{
//no contains ipv6 means it do not ignore some zero in address (x:x:x:x:x:x:x:x or x:x:x:x:x:x:1.2.3.4)
iptemp = address.Split(':');
int iptempLength = iptemp.Length;
int m = 0;
for (int i = 0; i < iptemp.Length; i++)
{
while (iptempLength != 0 && !iptemp[i].Contains('.'))
{
ipresult[m] = iptemp[i];
m++;
i++;
iptempLength--;
}
if (iptemp[i].Contains('.') && iptempLength !=0)
{
ipresult[6] = MergeIpv4ToV6Type(iptemp[iptemp.Length - 1])[0];
ipresult[7] = MergeIpv4ToV6Type(iptemp[iptemp.Length - 1])[1];
}
}
result = ipresult;
}
}
else // ipv4 split it directly
{
result = address.Split('.');
}
return result;
}
public static string[] MergeIpv4ToV6Type(string ipv4)
{
string[] ipresult = new string[2];
string[] ipv4Array = ipv4.Split('.');
ipresult[0] = Convert.ToString((Convert.ToInt32(ipv4Array[0]) + Convert.ToInt32(ipv4Array[1])), 16);
ipresult[1] = Convert.ToString((Convert.ToInt32(ipv4Array[2] )+ Convert.ToInt32(ipv4Array[3])), 16);
return ipresult;
}
写的不好大家多拍砖。算法也可能有没覆盖的地方,多多包含。我也不多废话,直接引入百科内容,附上IPV6部分内容。
==============
在 Internet 协议版本 6 (IPv6) 中,地址的长度是 128 位。地址空间如此大的一个原因是将可用地址细分为反映 Internet 的拓扑的路由域的层次结构。另一个原因是映射将设备连接到网络的网络适配器(或接口)的地址。IPv6 提供了内在的功能,可以在其最低层(在网络接口层)解析地址,并且还具有自动配置功能。
文本表示形式
以下是用来将 IPv6 地址表示为文本字符串的三种常规形式:
(一)冒号十六进制形式。
这是首选形式 n:n:n:n:n:n:n:n。每个 n 都表示八个 16 位地址元素之一的十六进制值。例如:
3FFE:FFFF:7654:FEDA:1245:BA98:3210:4562.
(二)压缩形式。
由于地址长度要求,地址包含由零组成的长字符串的情况十分常见。为了简化对这些地址的写入,可以使用压缩形式,在这一压缩形式中,多个 0 块的单个连续序列由双冒号符号 (::) 表示。此符号只能在地址中出现一次。例如,多路广播地址 FFED:0:0:0:0:BA98:3210:4562 的压缩形式为 FFED::BA98:3210:4562。单播地址 3FFE:FFFF:0:0:8:800:20C4:0 的压缩形式为 3FFE:FFFF::8:800:20C4:0。环回地址 0:0:0:0:0:0:0:1 的压缩形式为 ::1。未指定的地址 0:0:0:0:0:0:0:0 的压缩形式为 ::。
(三)混合形式。
此形式组合 IPv4 和 IPv6 地址。在此情况下,地址格式为 n:n:n:n:n:n:d.d.d.d,其中每个 n 都表示六个 IPv6 高序位 16 位地址元素之一的十六进制值,每个 d 都表示 IPv4 地址的十进制值。
=====================
作者:Alexliu(alex dotNet Learning)
出处:http://alexliu.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,转载请注明。并且保留文章链接。否则保留追究法律责任的权利。