通信人家园

 找回密码
 注册

只需一步,快速开始

短信验证,便捷登录

搜索
查看: 8395|回复: 0
打印

UDP校验和计算 [复制链接]

军衔等级:

  新兵

注册:2013-8-4
跳转到指定楼层
1#
发表于 2016-6-16 17:49:12 |只看该作者 |倒序浏览
UDP的校验和需要计算UDP首部加数据荷载部分,但也需要加上UDP伪首部。
这个伪首部指,源地址、目的地址、UDP数据长度、协议类型(0x11),协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。
伪首部+UDP首部+数据 一起计算校验和。
在抓包实验中,也发现过在Linux系统下UDP检验和仅计算在UDP首部的情况,没具体分析是否包含了伪首部,但是肯定没计算数据。在windows系统的接收端上用wireshark抓包,发现校验和是对的。

UDP检验和的计算方法是:
1.按每16位求和得出一个32位的数;
2.如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数;
3.重复第2步直到高16位为0,将低16位取反,得到校验和。

较难和的计算,帖个代码。自己组了个码流,同时也从抓包中把UDP的码流和伪首部直接写到数组里了,两个相互比较,只是为了做个验证。代码也就没有写得那么通用。
当然,要注意的是,算出来的这个校验和是主机序的,如果要跟抓包中的校验和相比较,转成网络序再对比。


  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include

  4. typedef struct {
  5.     int srcIp;
  6.     int dstIp;
  7.     short udp_len;
  8.     char rsv;
  9.     char protocol;
  10.     unsigned short src_port;
  11.     unsigned short dst_port;
  12.     unsigned short len;
  13.     unsigned short check_sum;
  14.     char data[2];
  15. } UDPHDR;

  16. char arr[100] = {0xc0, 0xa8, 0xd1, 0x80, 0xc0, 0xa8, 0xd1, 0x01, 0x00, 0x0a, 0x00, 0x11, 0x13, 0x88, 0x13, 0x88, 0x00, 0x0a, 0x00, 0x00, 0x61, 0x66};

  17. unsigned short check_sum(unsigned short *a, int len);

  18. int main()
  19. {
  20.     short b = 0;
  21.     UDPHDR udphdr = {0};

  22.     udphdr.srcIp = inet_addr("192.168.209.128");
  23.     udphdr.dstIp = inet_addr("192.168.209.1");
  24.     udphdr.udp_len = htons(10);
  25.     udphdr.protocol = 0x11;
  26.     udphdr.rsv = 0;
  27.     udphdr.src_port = htons(5000);
  28.     udphdr.dst_port = htons(5000);
  29.     udphdr.len = htons(10);
  30.     udphdr.check_sum = 0;
  31.     udphdr.data[0] = 0x61;
  32.     udphdr.data[1] = 0x66;

  33.     b = check_sum((short *)&udphdr, 22);
  34.     printf("[test ...] b = %04x\n", b & 0xffff);

  35.     b = check_sum((short *)arr, 22);
  36.     printf("[test arr] b = %04x\n", b & 0xffff);

  37.     return 0;
  38. }

  39. unsigned short check_sum(unsigned short *a, int len)
  40. {
  41.     unsigned int sum = 0;

  42.     while (len > 1) {
  43.         sum += *a++;
  44.         len -= 2;
  45.     }

  46.     if (len) {
  47.         sum += *(unsigned char *)a;
  48.     }

  49.     while (sum >> 16) {
  50.         sum = (sum >> 16) + (sum & 0xffff);
  51.     }

  52.     return (unsigned short)(~sum);
  53. }
复制代码


举报本楼

您需要登录后才可以回帖 登录 | 注册 |

手机版|C114 ( 沪ICP备12002291号-1 )|联系我们 |网站地图  

GMT+8, 2024-11-19 17:40 , Processed in 0.160420 second(s), 15 queries , Gzip On.

Copyright © 1999-2023 C114 All Rights Reserved

Discuz Licensed

回顶部