linux ip校验和计算,ip头和tcp头checksum计算方法

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值