赞
踩
本人内核小菜,最近工作需要在内核模块做udp的recv checksum 校验,整理了相关资料并把关键的函数列出来。
参考4.9内核及相关博客
http://blog.csdn.net/one_clouder/article/details/53177992
http://wenx05124561.blog.163.com/blog/static/124000805201242032041268/
//recv udp packet check
static bool checksumError(struct sk_buff* skb, struct udphdr* uh)
{
unsigned int psum = 0;
//needn't check if below:
//1. ip_summed is CHECKSUM_UNNECESSARY hardware check
if(skb->ip_summed == CHECKSUM_UNNECESSARY)
{
return false;
}
//2. udp header check is 0,mean needn't check
if(uh->check == 0)
{
incCounter64(&recvChecksumStat_g.checkZero);
return false;
}
//otherwise, we must calculate csum
//skb->data must move to udphr
if(skb_pull(skb, ip_hdrlen (skb)) == NULL) //注意:勾包是L3 skb->data 指向ip头
{
return true;
}
//calculate pseudo header csum
psum = csum_tcpudp_nofold(ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, skb->len, ip_hdr(skb)->protocol, 0);
if(skb->ip_summed == CHECKSUM_COMPLETE)
{
//payload csum has calculated by hardware, and set it to skb->csum
if(!csum_fold(csum_add(psum, skb->csum)))
{
skb->ip_summed = CHECKSUM_UNNECESSARY;//避免处理不了时,返回协议栈处理还要再算一次
return false;
}
}
//calculate payload csum and fold pseudo header csum
skb->csum = skb_checksum(skb, 0, skb->len, 0);
if(!csum_fold(csum_add(psum, skb->csum)))
{
skb->ip_summed = CHECKSUM_UNNECESSARY;
return false;
}
return true;
}
//call
if(checksumError(skb, udph)) //check csum
{
if (net_ratelimit())
{
log(Error, "handlePacket: checksum error!src %u:%u dst %u:%u\n", iph->saddr, ntohs(udph->source), iph->daddr, ntohs(udph->dest));
}
//discard packet if csum error
return NF_DROP; //直接返回 不需要 kfree_skb(skb); nf_hook_slow函数中free掉,否则crash
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。