【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 <[email protected]>

 *

 * 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节点。

你可能感兴趣的:(OS)