UDP包中的校验码是如何计算的?

ExitWindows 2005-03-01 09:40:37
UDP包中的校验码是如何计算的?

我是先组一个UDP伪头:

struct StuUdpHead{
ULONG uIpSour;
ULONG uIpTar;
BYTE bZero;
BYTE bProtocol;
short int iLen;
}UdpHead;

后接UDP头及数据,整个来计算校验码作为UDP包的校检码,但截收结果总是说校验码不正确,哪位大侠指教一下?谢谢。

...全文
2362 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
shines77 2005-03-13
  • 打赏
  • 举报
回复
mark
ExitWindows 2005-03-10
  • 打赏
  • 举报
回复
问题找到了,校验和是正确的,毛病出在其它地方。
感谢各位,特别感谢kingzai(stevenzhu)的代码。
ExitWindows 2005-03-09
  • 打赏
  • 举报
回复
找了本《TCP/IP详解 卷1:协议》,再研究一下。
ExitWindows 2005-03-02
  • 打赏
  • 举报
回复
谢谢 kingzai(stevenzhu)。
从代码上看,UDP校验是对伪UDP头、UDP头、UDP数据这样的序列做的,但我的为什么不对呢。
容我再检查一下。
kingzai 2005-03-02
  • 打赏
  • 举报
回复
/* OicqSend.c 
#pragma pack(1)

#define WIN32_LEAN_AND_MEAN

#include <winsock2.h>
#include <ws2tcpip.h>

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


#define OICQ_MAX_PACKET 1024
#define OICQ_MAX_MSG 512
#define OICQ_MSG_LEN 45
#define SRC_IP "127.0.0.1"
#define SRC_PORT 5277
#define DST_PORT 4000

typedef struct ip_hdr
{
unsigned char ip_verlen;
unsigned char ip_tos;
unsigned short ip_totallength;
unsigned short ip_id;
unsigned short ip_offset;
unsigned char ip_ttl;
unsigned char ip_protocol;
unsigned short ip_checksum;
unsigned int ip_srcaddr;
unsigned int ip_destaddr;
} IP_HDR;
typedef struct udp_hdr
{
unsigned short src_portno;
unsigned short dst_portno;
unsigned short udp_length;
unsigned short udp_checksum;
} UDP_HDR;

char strMessage[OICQ_MSG_LEN] = {
0x02,0x01,0x07,0x00,0x78,0x00,0x00,0x31,0x30,0x30,0x30,0x31,0x1f,0x30,0x1f,
0x30,0x30,0x1f,0x32,0x30,0x30,0x30,0x2d,0x30,0x31,0x2d,0x30,0x31,0x1f,0x30,
0x30,0x3a,0x30,0x30,0x3a,0x30,0x30,0x1f,0x68,0x65,0x6c,0x6c,0x6f,0x21,0x03
};

USHORT checksum(USHORT *buffer, int size)
{
unsigned long cksum=0;

while (size > 1)
{
cksum += *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum += *(UCHAR*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);

return (USHORT)(~cksum);
}

int main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
BOOL bOpt;
struct sockaddr_in remote;
IP_HDR ipHdr;
UDP_HDR udpHdr;
int ret;
DWORD i;
unsigned short iTotalSize,
iUdpSize,
iUdpChecksumSize,
iIPVersion,
iIPSize,
cksum = 0;
char buf[OICQ_MAX_PACKET],
*ptr = NULL;

printf("Spoof OICQ Msg Sender - by Janker@371.net\n\n");

if(argc!=2) {
printf("usage: OICQSEND Destination_IP_Address");
ExitProcess(1);
}

srand((unsigned)time(NULL));
strMessage[5]=rand();

if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
printf("WSAStartup() failed: %d\n", GetLastError());
return -1;
}
s = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0,0);
if (s == INVALID_SOCKET)
{
printf("WSASocket() failed: %d\n", WSAGetLastError());
return -1;
}
bOpt = TRUE;
ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL, (char *)&bOpt, sizeof(bOpt));
if (ret == SOCKET_ERROR)
{
printf("setsockopt(IP_HDRINCL) failed: %d\n", WSAGetLastError());
return -1;
}

iTotalSize = sizeof(ipHdr) + sizeof(udpHdr) + OICQ_MSG_LEN;

iIPVersion = 4;
iIPSize = sizeof(ipHdr) / sizeof(unsigned long);

ipHdr.ip_verlen = (iIPVersion << 4) ¦ iIPSize;
ipHdr.ip_tos = 0;
ipHdr.ip_totallength = htons(iTotalSize);
ipHdr.ip_id = 0;
ipHdr.ip_offset = 0;
ipHdr.ip_ttl = 128;
ipHdr.ip_protocol = 0x11;
ipHdr.ip_checksum = 0 ;
ipHdr.ip_srcaddr = inet_addr(SRC_IP);
ipHdr.ip_destaddr = inet_addr(argv[1]);

iUdpSize = sizeof(udpHdr) + OICQ_MSG_LEN;

udpHdr.src_portno = htons(SRC_PORT) ;
udpHdr.dst_portno = htons(DST_PORT) ;
udpHdr.udp_length = htons(iUdpSize) ;
udpHdr.udp_checksum = 0 ;

iUdpChecksumSize = 0;
ptr = buf;
ZeroMemory(buf, OICQ_MAX_PACKET);

memcpy(ptr, &ipHdr.ip_srcaddr, sizeof(ipHdr.ip_srcaddr));
ptr += sizeof(ipHdr.ip_srcaddr);
iUdpChecksumSize += sizeof(ipHdr.ip_srcaddr);

memcpy(ptr, &ipHdr.ip_destaddr, sizeof(ipHdr.ip_destaddr));
ptr += sizeof(ipHdr.ip_destaddr);
iUdpChecksumSize += sizeof(ipHdr.ip_destaddr);

ptr++;
iUdpChecksumSize += 1;

memcpy(ptr, &ipHdr.ip_protocol, sizeof(ipHdr.ip_protocol));
ptr += sizeof(ipHdr.ip_protocol);
iUdpChecksumSize += sizeof(ipHdr.ip_protocol);

memcpy(ptr, &udpHdr.udp_length, sizeof(udpHdr.udp_length));
ptr += sizeof(udpHdr.udp_length);
iUdpChecksumSize += sizeof(udpHdr.udp_length);

memcpy(ptr, &udpHdr, sizeof(udpHdr));
ptr += sizeof(udpHdr);
iUdpChecksumSize += sizeof(udpHdr);

for(i = 0; i <OICQ_MSG_LEN; i++, ptr++)
*ptr = strMessage[i];
iUdpChecksumSize += OICQ_MSG_LEN;

cksum = checksum((USHORT *)buf, iUdpChecksumSize);
udpHdr.udp_checksum = cksum;

ZeroMemory(buf, OICQ_MAX_PACKET);
ptr = buf;

memcpy(ptr, &ipHdr, sizeof(ipHdr)); ptr += sizeof(ipHdr);
memcpy(ptr, &udpHdr, sizeof(udpHdr)); ptr += sizeof(udpHdr);
memcpy(ptr, strMessage, OICQ_MSG_LEN);

remote.sin_family = AF_INET;
remote.sin_port = htons(DST_PORT);
remote.sin_addr.s_addr = inet_addr(argv[1]);

ret = sendto(s, buf, iTotalSize, 0, (SOCKADDR *)&remote, sizeof(remote));
if (ret == SOCKET_ERROR)
printf("sendto() failed: %d\n", WSAGetLastError());
else
printf("Send O.K.!");
closesocket(s) ;
WSACleanup() ;

return 0;
}
fisker0303 2005-03-02
  • 打赏
  • 举报
回复
详见TCP/IP详解卷一,108页。
fisker0303 2005-03-02
  • 打赏
  • 举报
回复
包括UDP的首部和UDP数据。
ExitWindows 2005-03-02
  • 打赏
  • 举报
回复
勇敢的心:
我的UDP校验就是这样做的,为什么总是错误的呢?
ExitWindows 2005-03-02
  • 打赏
  • 举报
回复
谢谢老兄。
可我想知道的是:UDP检验究竟是将哪些内容来做的校验,这些内容是什么?
oyljerry 2005-03-02
  • 打赏
  • 举报
回复
UDP校验就是伪UDP头、UDP头、UDP数据这几部分
sharkhuang 2005-03-02
  • 打赏
  • 举报
回复
老多现成的代码抄一段就ok
kingzai 2005-03-01
  • 打赏
  • 举报
回复
UDP的校验和包括UDP首部和数据,方法是计算16位的二进制和,首先将校验
和字段(16位)置0,将每个16位的反码相加,若是奇数字节即最后未到16字节,
则以0补充,结果存在校验和字段中,因接收端包含了之前的校验和,若传输
中没有任何差错,则接收端计算的校验和该为全1,否则有错,这于IP首部的
二进制反码和的计算类似,注意若计算结果为0,则存入的值为全1,若传送端的
校验和为0,发送端就没计算校验和。更多内容可以看Stevens的《TCP/IP详解》。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧