赞
踩
ip头和tcp头checksum计算方法
ip头和tcp头checksum计算方法
最近需要用到ip头和tcp头重新校验,已生成对应的pcap包。网上搜索了下,貌似没有细化的实现。
只有根据各种片段,实现了。 主要填充代码,从sendip开源软件的tcpv4_csum修改而来。
#include
#include
#include
#include
#include
#include
#include
#include
#include //sockaddr_ll struct
#include //ifreq struct
#include
#include
#include
#include //htons
#include //ether_header struct
//计算IP校验和
unsigned short checksum(unsigned short *buffer,int size)
{
unsigned long cksum=0;
while(size>1)
{
cksum+=*buffer++;
size-=sizeof(unsigned short);
}
if(size)
{
cksum+=*(unsigned char *)buffer;
}
//将32位数转换成16
while (cksum>>16)
cksum=(cksum>>16)+(cksum & 0xffff);
return (unsigned short) (~cksum);
}
void tcpv4_check_addr( __u16 * ppkgdata )
{
const int MaxEthFrame=1514;
char * indata;
__u16 ippktlen, udppktlen,tcppktlen,wd;
__u32 ipheadlen;
struct iphdr * ipd;
struct tcphdr * tcpd;
struct udphdr * udpd;
__u16 * databegin;
indata = (char *)ppkgdata; //从MAC开始的整个帧
ipheadlen = 14 + (indata[14]&0x0f)*4 ; //MAC和ip头的长度和
databegin = (__u16 *)(indata + ipheadlen); //ip数据
ipd = (struct iphdr *)(indata + 14); //MAC数据
tcpd = (struct tcphdr *)(indata + ipheadlen); //ip数据
ippktlen = htons(ipd->tot_len); //ip头和ip数据的总长度
if(ipd->protocol == 0x6){
tcppktlen = ippktlen +14 - ipheadlen; //tcp头和tcp数据的总长度
printf("ip checksum:%x,sport:%x
",ipd->check,ipd->saddr);
ipd->check = 0;
ipd->check = checksum((unsigned short *)ipd,ipheadlen-14);
printf("end ip checksum:%x,sport:%x
",ipd->check,ipd->saddr);
printf("tcp checksum:%x
",tcpd->check);
if (tcppktlen > MaxEthFrame) {
fprintf(stderr,"Tcplen greater than MaxEthFrame(%d) ,real:%d.
",MaxEthFrame,tcppktlen);
return;
}
u_int16_t * buf = (__u16 *)malloc(MaxEthFrame);
u_int8_t *tempbuf = (u_int8_t *)buf;
tcpd->check=0;
if(tempbuf == NULL) {
fprintf(stderr,"Out of memory: TCP checksum not computed
");
return;
}
/* Set up the pseudo header */
memcpy(tempbuf,&(ipd->saddr),sizeof(u_int32_t));
memcpy(&(tempbuf[4]),&(ipd->daddr),sizeof(u_int32_t));
tempbuf[8]=0;
tempbuf[9]=(u_int16_t)ipd->protocol;
//tempbuf[10]=(u_int16_t)((indata[14]&0x0f)*4);//ip头长度
//tempbuf[11]=(u_int16_t)(tcppktlen);//tcp 头 + data
tempbuf[10]=(u_int16_t)( tcppktlen &0xFF00)>>8;
tempbuf[11]=(u_int16_t)( tcppktlen &0x00FF);
/* Copy the TCP header and data */
memcpy(tempbuf+12,tcpd,tcppktlen);
//memcpy(tempbuf+12+tcp_hdr->alloc_len,data->data,data->alloc_len);
/* printf("tcppktlen:%d,iphlen:%d,content:
",tcppktlen,(indata[14]&0x0f)*4);
for(int i=0;i
printf("%02x ",tempbuf[i]);
if((i+1) % 16 ==0) printf("
");
}
printf("
");
*/
/* CheckSum it */
tcpd->check = checksum((__u16 *)buf,12+tcppktlen);
free(buf);
printf("end tcp checksum:%x
",tcpd->check);
}//end tcp
}
int main(int argc,char ** argv){
const int MaxEthFrame=1514;
FILE * fp = fopen(argv[1],"rb");
FILE * fp_save = fopen(argv[2],"wb");
u_char * frameBuffer=NULL;
if(fp && fp_save){
printf("Read File %s ok.",argv[1]);
frameBuffer = (u_char *)malloc(MaxEthFrame);
if(frameBuffer == NULL){
printf("Alloc parket mem failed.
");
}
int size = fread(frameBuffer,sizeof(u_char),MaxEthFrame, fp);
printf("sizeof(u_char):%d,Read %d,content:
",sizeof(u_char),size);
for(int i=0;i
printf("%02x ",frameBuffer[i]);
if((i+1) % 16 ==0) printf("
");
}
printf("
");
tcpv4_check_addr(( __u16 * )frameBuffer );
printf("Change content:
",size);
for(int i=0;i
printf("%02x ",frameBuffer[i]);
if((i+1) % 16 ==0) printf("
");
}
printf("
");
fwrite(frameBuffer,sizeof(u_char),size,fp_save);
free(frameBuffer);
frameBuffer = NULL;
fclose(fp);
fclose(fp_save);
}else{
printf("open failed.");
}
return 0;
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。