TCPIP_UDP


网络协议 UDP

前言

1. 帧格式

            DST_MAC     SRC_MAC     TYPE(IPV4 0x8000)
            6字节       6字节        2字节

IP_head     IPV4(版本 IP头长 DSF 0x4500)    总长度(IP_head_length(20) + UDP_length)   帧标识(相当于一个标记)    Flag    Offset  
            2字节                           2字节                                     2字节                   1字节   1字节

            TTL     Protocol               [IP头校验和]      Src_IP      Dst_IP                     
            1字节   1字节                   2字节            4字节       4字节

UDP_        Src_port    Dst_port    UDP_Length  [UDP校验和]     DATA
            2字节       2字节        2字节       2字节           ....

2. 部分参数值意义

- IP头长度为20字节
- 总长度(IP头中的长度字段):为UDP部分的长度+IP头长度(不包含MAC地址以及类型的14个字节)
- 帧标识(Identification)在经过路由之后报文不会变的字段,为了确保报文的唯一性
- UDP中的长度为UDP字段的长度和,从SRC_PROT到最后一个不为padding的字符

3. 校验和

1. IP字段的校验和

  • 每两个字节相加得到一个32bit的数,之后求到的值如果高16位有数,将高16的数辗转加到低16位得到一个16位的值,之后按位求反。代码如下,参数为完整的一个udp数据帧

      uint16_t ip_calc_ipchecksum(void *pack_info){
          int8_t* m_pack_info = (int8_t*)pack_info  ;
          //  将校验和置为0
          m_pack_info[24] = 0;
          m_pack_info[25] = 0;
    
          m_pack_info = &m_pack_info[13];
          int index = 0;
          int ip_index = 0;
    
          int32_t calc_sum = 0;
          int16_t ip_head[10] = {};
          int32_t cksum = 0;
    
          while (index != 20)
          {
              /* code */
              ip_head[ip_index] = ( ip_head[ip_index] |( m_pack_info[index] & 0xFF) ) << 8;
              ip_head[ip_index] = ( ip_head[ip_index] | (m_pack_info[index+1] & 0xFF) );
    
              calc_sum += (ip_head[ip_index] & 0xffff );
    
              index += 2;
              ip_index += 1;
          }
          if(index == 20){
              calc_sum=(calc_sum>>16)+(calc_sum&0xffff);  //把高位的进位,加到低八位,其实是32位加法
              calc_sum+=(calc_sum>>16);  //add carry
    
              cksum = 0xFFFF - calc_sum;
              return cksum;
          }
      }
    0000   28 39 26 d9 cf fb 1c bf c0 db d3 bf 08 00 45 00   (9&...........E.
    0010   00 25 ba 78 40 00 40 11 fd d6 c0 a8 00 9e c0 a8   .%.x@.@.........
    0020   00 8a da f2 30 39 00 11 77 5e 31 32 33 31 32 33   ....09..w^123123
    0030   31 32 33 00 00 00 00 00 00 00 00 00               123.........

    公式: 
        >>> 0x4500 + 0x0025 + 0xba78 + 0x4000 + 0x4011 + 0x0000(校验和置0) + 0xc0a8 + 0x009e + 0xc0a8 + 0x008a
        197158
        >>> print("0x%x" %197158)
        0x30226
        >>> print("0x%x" % (0Xffff-0x226-3))
        0xfdd6

2. UDP字段校验和

  • UDP字段校验和:SRC_IP + DST_IP + UDP协议2字节 + UDP字段中的长度 + UDP数据部分。计算方法与IP校验和相同,每2字节相加,高16位加到低16位得到一个16位数取反

      公式:
          >>> (IP)0xc0a8 + 0x008a + 0xc0a8 + 0x009e + (udp协议0x11前面补0)0x0011 + (UDP数据部分的长度)0x000e + (UDP部分的数据)0x3039 + 0xdaf2 + 0x000e + (校验和置0)0x0000 + 0x3132 + 0x3331 + 0x3233
          205926
          >>> print("0x%x" % (205926))
          0x32466
          >>> print("0x%x" % (0Xffff-0x2466-3))
          0xdb96

文章作者: bySouffle
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 bySouffle !
  目录