首页 > 代码库 > 【Atheros】pktgen的ipv6地址处理函数参考及ipv6基本知识

【Atheros】pktgen的ipv6地址处理函数参考及ipv6基本知识

pktgen有很多函数可以作为很好的网络相关的工具函数,这里列出ipv6中1:0:0:0:0:0:0:1和1::1这两种地址形式相互转化的工具函数。

第一个函数,用于把一个1:0:0:0:0:0:0:1形式的地址转化为1::1

/* * scan_ip6, fmt_ip taken from dietlibc-0.21 * Author Felix von Leitner <felix-dietlibc@fefe.de> * * Slightly modified for kernel. * Should be candidate for net/ipv4/utils.c * --ro */static unsigned int scan_ip6(const char *s, char ip[16]){    unsigned int i;    unsigned int len = 0;    unsigned long u;    char suffix[16];    unsigned int prefixlen = 0;    unsigned int suffixlen = 0;    __be32 tmp;    char *pos;    for (i = 0; i < 16; i++)        ip[i] = 0;    for (;;) {        if (*s == :) {            len++;            if (s[1] == :) {    /* Found "::", skip to part 2 */                s += 2;                len++;                break;            }            s++;        }        u = simple_strtoul(s, &pos, 16);        i = pos - s;        if (!i)            return 0;        if (prefixlen == 12 && s[i] == .) {            /* the last 4 bytes may be written as IPv4 address */            tmp = in_aton(s);            memcpy((struct in_addr *)(ip + 12), &tmp, sizeof(tmp));            return i + len;        }        ip[prefixlen++] = (u >> 8);        ip[prefixlen++] = (u & 255);        s += i;        len += i;        if (prefixlen == 16)            return len;    }/* part 2, after "::" */    for (;;) {        if (*s == :) {            if (suffixlen == 0)                break;            s++;            len++;        } else if (suffixlen != 0)            break;        u = simple_strtol(s, &pos, 16);        i = pos - s;        if (!i) {            if (*s)                len--;            break;        }        if (suffixlen + prefixlen <= 12 && s[i] == .) {            tmp = in_aton(s);            memcpy((struct in_addr *)(suffix + suffixlen), &tmp,                   sizeof(tmp));            suffixlen += 4;            len += strlen(s);            break;        }        suffix[suffixlen++] = (u >> 8);        suffix[suffixlen++] = (u & 255);        s += i;        len += i;        if (prefixlen + suffixlen == 16)            break;    }    for (i = 0; i < suffixlen; i++)        ip[16 - suffixlen + i] = suffix[i];    return len;}

第二个函数完成反向的转换,把1::1恢复成完成的地址:

static unsigned int fmt_ip6(char *s, const char ip[16]){    unsigned int len;    unsigned int i;    unsigned int temp;    unsigned int compressing;    int j;    len = 0;    compressing = 0;    for (j = 0; j < 16; j += 2) {#ifdef V4MAPPEDPREFIX        if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) {            inet_ntoa_r(*(struct in_addr *)(ip + 12), s);            temp = strlen(s);            return len + temp;        }#endif        temp = ((unsigned long)(unsigned char)ip[j] << 8) +            (unsigned long)(unsigned char)ip[j + 1];        if (temp == 0) {            if (!compressing) {                compressing = 1;                if (j == 0) {                    *s++ = :;                    ++len;                }            }        } else {            if (compressing) {                compressing = 0;                *s++ = :;                ++len;            }            i = fmt_xlong(s, temp);            len += i;            s += i;            if (j < 14) {                *s++ = :;                ++len;            }        }    }    if (compressing) {        *s++ = :;        ++len;    }    *s = 0;    return len;}

 

下面附上ipv6的一些相关的基础知识,看懂这些也更有助于理解上面的两个函数,ps:这好像是我之前在一些网站上截的,我当时也记了源地址,但是源网站已经挂掉了:

IPv4地址是类似 A.B.C.D 的格式,它是32位,用.分成四段,用10进制表示;而IPv6地址类似X:X:X:X:X:X:X:X的格式,它是128位的,用:分 成8段,用16进制表示,每一段的值从8位扩充到16位。

RFC2373 中定义了完整的IPv6地址表示:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx

例如: 2001:0000: 1F 1F :0000:0000:0100: 11A 0:ADDF

为简化表示, rfc2373提出每段中前面的0可以省略,连续的0可省略为::,但只能出现一次。例如:

1080:0:0:0:8:800: 200C : 417A 可简写为 1080::8:800: 200C : 417A

FF01:0:0:0:0:0:0:101 可简写为 FF01::101

0:0:0:0:0:0:0:1 可简写为 ::1

0:0:0:0:0:0:0:0 可简写为 ::

这里给出一个表格,以比较IPv4和IPv6地址对应关系和区别。

IPv4

IPv6

组播地址(224.0.0.0/4)

IPv6组播地址(FF00::/8)

有广播地址

无广播,只有任播(anycast)

未指定地址为 0.0.0 .0

未指定地址为 ::

回路地址为 127.0.0.1

回路地址为 ::1

私有地址( 10.0.0 .0/8、172.16.0.0/12和192.168.0.0/16)

本地站点地址( FEC0::/48)

Microsoft自动专用IP寻址自动配置的地址(169.254.0.0/16)

本地链路地址( FE80::/64)

表达方式:点分十进制

表达方式:冒号十六进制式

子网掩码表示:以点阵十进制表示法或前缀长度表示法( CIDR)

子网掩码表示:仅使用前缀长度表示法( CIDR)

常见的IPv6地址及其前缀:

::/128  即0:0:0:0:0:0:0:0,只能作为尚未获得正式地址的主机的源地址,不能作为目的地址,不能分配给真实的网络接口。

::1/128 即0:0:0:0:0:0:0:1,回环地址,相当于IPv4中的localhost(127.0.0.1),ping locahost可得到此地址。

2001::/16  全球可聚合地址,由 IANA 按地域和ISP进行分配,是最常用的IPv6地址,属于单播地址。

2002::/16  6 to 4 地址,用于6to4自动构造隧道技术的地址,属于单播地址。

3ffe::/16   早期开始的IPv6 6bone试验网 地址,属于单播地址。

fe80::/10   本地链路地址,用于单一链路,适用于自动配置、邻机发现等,路由器不转发以fe80开头的地址。

ff00::/8  组播地址。

::A.B.C.D  兼容IPv4的IPv6地址,其中<A.B.C.D>代表IPv4地址。自动将IPv6包以隧道方式在IPv4网络中传送的IPv4/IPv6节点将使用这些地址。

::FFFF:A.B.C.D   是IPv4映射过来的IPv6地址,其中<A.B.C.D>代表IPv4地址,例如 ::ffff:202.120.2.30 ,它是在不支持IPv6的网上用于表示IPv4节点。

【Atheros】pktgen的ipv6地址处理函数参考及ipv6基本知识