UDP报头只有4个字段,分别是:源端口号、目的端口号、报文长度和报头checksum,其中的报头checksum这个字段在IPv4中并不是强制的,但在IPv6中是强制的,本文介绍UDP报头中checksum的计算方法,并给出相应的源程序。
struct udphdr {
__be16 source;
__be16 dest;
__be16 len;
__sum16 check;
};
#include
#include
#include
#include
#include
#include
// udp pseudo header structure
struct pseudohdr {
uint32_t source_ip;
uint32_t destination_ip;
uint8_t zero;
uint8_t protocol;
uint16_t udp_len;
};
// udp packet structure for calculating checksum
struct udpcheckhdr {
struct pseudohdr pseudo_hdr;
struct udphdr udp_hdr;
unsigned char data[16];
};
// initial pseudo header
void init_pseudohdr(struct udpcheckhdr *p) {
p->pseudo_hdr.source_ip = inet_addr("152.1.51.27"); // 0X0198 0X1B33
p->pseudo_hdr.destination_ip = inet_addr("152.14.94.75"); // 0X0E98 0X4B5E
p->pseudo_hdr.zero = 0; // 0X00 - 0X1100
p->pseudo_hdr.protocol = 17; // 0X11
p->pseudo_hdr.udp_len = 13; // 0X000D
}
// initial udp header
void init_udphdr(struct udpcheckhdr *p) {
p->udp_hdr.source = 56020; // 0xDAD4
p->udp_hdr.dest = 8000; // 0X1F40
p->udp_hdr.len = 13; // 0X000D
p->udp_hdr.check = 0; // 0X0000
}
// initial udp data
void init_udpdata(struct udpcheckhdr *p) {
p->data[0] = 'h'; // 0X68 - 0X6568
p->data[1] = 'e'; // 0X65
p->data[2] = 'l'; // 0X6C - 0X6C6C
p->data[3] = 'l'; // 0X6C
p->data[4] = 'o'; // 0X6F - 0X006F
p->data[5] = 0;
}
uint16_t checksum1(uint16_t *p, int count) {
register long sum = 0;
unsigned short checksum;
uint16_t temp;
uint16_t i = 0;
while (count > 1) {
/* This is the inner loop */
temp = (unsigned short)*(unsigned short *)p++;
printf("Step %02d: 0X%08lX + 0X%04X
", ++i, sum, temp);
sum += temp;
count -= 2;
}
/* Add left-over byte, if any */
if (count > 0) {
temp = (unsigned short)*(unsigned short *)p;
printf("Step %02d: 0X%08lX + 0X%04X
", ++i, sum, temp);
sum += *(unsigned char *)p;
}
printf("Result before folding: 0X%08lX
", sum);
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
printf("Result after folding: 0X%08lX
", sum);
checksum = ~(unsigned short)sum;
printf("
Checksum = 0x%04X
", checksum);
return checksum;
}
uint16_t checksum2(uint16_t *p, int count) {
register long sum = 0;
unsigned short checksum;
uint16_t temp;
uint16_t i = 0;
while (count > 1) {
/* This is the inner loop */
temp = (unsigned short)*(unsigned short *)p++;
printf("Step %02d: 0X%08lX + 0X%04X(0X%04X)
", ++i, sum, (uint16_t)~temp, temp);
sum += (uint16_t)~temp;
count -= 2;
}
/* Add left-over byte, if any */
if (count > 0) {
temp = (unsigned short)*(unsigned short *)p;
printf("Step %02d: 0X%08lX + 0X%04X(0X%04X)
", ++i, sum, (uint16_t)~temp, temp);
sum += (uint16_t)~temp;
}
printf("Result before folding: 0X%08lX
", sum);
/* Fold 32-bit sum to 16 bits */
while (sum >> 16)
sum = (sum & 0xffff) + (sum >> 16);
printf("Result after folding: 0X%08lX
", sum);
checksum = (unsigned short)sum;
printf("
Checksum = 0x%04X
", checksum);
return checksum;
}
int main(int argc, char **argv) {
struct udpcheckhdr udp_packet;
init_pseudohdr(&udp_packet);
init_udphdr(&udp_packet);
init_udpdata(&udp_packet);
unsigned short *p = (unsigned short *)&udp_packet;
int count = sizeof(struct pseudohdr) + udp_packet.udp_hdr.len;
printf("
The one's complement code of 16-bit true code sum
");
checksum1(p, count);
printf("
The one's complement sum
");
checksum2(p, count);
return 0;
}
欢迎访问我的博客:https:whowin.cn
页面更新:2024-03-12
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号