zoukankan      html  css  js  c++  java
  • IP数据包的校验和算法

    1、算法思路:

           IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:

      在发送数据时,为了计算IP数据包的校验和。应该按如下步骤: 

      (1)把IP数据包的校验和字段置为0; 

      (2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和;

      (3)把得到的结果存入校验和字段中。

      在接收数据时,计算数据包的校验和相对简单,按如下步骤:

      (1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

      (2)检查计算出的校验和的结果是否等于零(反码应为16个0);

      (3)如果等于零,说明被整除,校验是和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

      所谓的二进制反码求和,即为先进行二进制求和,然后对和取反。

           计算对IP首部检验和的算法如下:

      (1)把IP数据包的校验和字段置为0;

      (2)把首部看成以16位为单位的数字组成,依次进行二进制求和(注意:求和时应将最高位的进位保存,所以加法应采用32位加法);

      (3)将上述加法过程中产生的进位(最高位的进位)加到低16位(采用32位加法时,即为将高16位与低16位相加,之后还要把该次加法最高位产生的进位加到低16位)

      (4)将上述的和取反,即得到校验和。

    2、实现范例:

           汇编:这个可以在linux内核代码里找到,下面就是 arch/x86/include/asm/checksum_32.h里面的内容:

    /*
     *    This is a version of ip_compute_csum() optimized for IP headers,
     *    which always checksum on 4 octet boundaries.
     *
     *    By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
     *    Arnt Gulbrandsen.
     */
    static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
    {
        unsigned int sum;
    
        asm volatile("movl (%1), %0    ;
    "
                 "subl $4, %2    ;
    "
                 "jbe 2f        ;
    "
                 "addl 4(%1), %0    ;
    "
                 "adcl 8(%1), %0    ;
    "
                 "adcl 12(%1), %0;
    "
                 "1:    adcl 16(%1), %0    ;
    "
                 "lea 4(%1), %1    ;
    "
                 "decl %2    ;
    "
                 "jne 1b        ;
    "
                 "adcl $0, %0    ;
    "
                 "movl %0, %2    ;
    "
                 "shrl $16, %0    ;
    "
                 "addw %w2, %w0    ;
    "
                 "adcl $0, %0    ;
    "
                 "notl %0    ;
    "
                 "2:        ;
    "
        /* Since the input registers which are loaded with iph and ihl
           are modified, we must also specify them as outputs, or gcc
           will assume they contain their original values. */
                 : "=r" (sum), "=r" (iph), "=r" (ihl)
                 : "1" (iph), "2" (ihl)
                 : "memory");
        return (__force __sum16)sum;
    }

             

        C语言:很多网络协议都用如下代码实现校验和算法:

    /*求校验和函数*/
    USHORT CheckSum(USHORT *buffer, int size)
    {
        unsigned long cksum=0;
        while (size > 1) 
        {
            cksum += *buffer++;
            size -= sizeof(USHORT);
        }
        if (size) 
        {
            cksum += *(UCHAR*)buffer;
        }
        /*对每个16bit进行二进制反码求和*/
        cksum = (cksum >> 16) + (cksum & 0xffff);
        cksum += (cksum >>16);
        return (USHORT)(~cksum);
    }
     
  • 相关阅读:
    仿msn风格的选项卡_网页代码站(www.webdm.cn)
    拍拍网头部导航菜单_网页代码站(www.webdm.cn)
    横向滑动特效的菜单(js+css)_网页代码站(www.webdm.cn)
    QuickMenu 超强悍菜单_网页代码站(www.webdm.cn)
    紫罗兰风格的导航条_网页代码站(www.webdm.cn)
    兼容性超强的六级网站导航主菜单_网页代码站(www.webdm.cn)
    用JavaScript实现横向滑出的多级竖向菜单_网页代码站(www.webdm.cn)
    一款溢出式侧边栏导航菜单_网页代码站(www.webdm.cn)
    css打造的又一款清新的横排下拉菜单_网页代码站(www.webdm.cn)
    [ZZ]byte[]到short、int、long的相互转换
  • 原文地址:https://www.cnblogs.com/RodYang/p/3231674.html
Copyright © 2011-2022 走看看