linux内核的ip头校验和测试
测试程序:
#include "stdio.h"
#include "stdlib.h"
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
typedef __signed__ long __s64;
typedef unsigned long __u64;
typedef __s8 s8;
typedef __u8 u8;
typedef __s16 s16;
typedef __u16 u16;
typedef __s32 s32;
typedef __u32 u32;
typedef __s64 s64;
typedef __u64 u64;
#ifdef __CHECKER__
#define __bitwise__ __attribute__((bitwise))
#else
#define __bitwise__
#endif
#define __bitwise __bitwise__
typedef __u16 __bitwise __le16;
typedef __u16 __bitwise __be16;
typedef __u32 __bitwise __le32;
typedef __u32 __bitwise __be32;
typedef __u64 __bitwise __le64;
typedef __u64 __bitwise __be64;
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;
struct iphdr {
__u8 ihl:4,
version:4;
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
unsigned short check;
__be32 saddr;
__be32 daddr;
};
static inline unsigned short ip_fast_csum(const void *iph, unsigned int ihl)
{
unsigned int sum;
asm(" movl (%1), %0\n"
" subl $4, %2\n"
" jbe 2f\n"
" addl 4(%1), %0\n"
" adcl 8(%1), %0\n"
" adcl 12(%1), %0\n"
"1: adcl 16(%1), %0\n"
" lea 4(%1), %1\n"
" decl %2\n"
" jne 1b\n"
" adcl $0, %0\n"
" movl %0, %2\n"
" shrl $16, %0\n"
" addw %w2, %w0\n"
" adcl $0, %0\n"
" notl %0\n"
"2:"
: "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl)
: "memory");
return (unsigned short)sum;
}
struct iphdr iph;
/*ip 16位校验和*/
unsigned short ip4_csum(void)
{
// struct iphdr iph;
iph.check = 0;
iph.ihl = 5;
iph.version = 4;
iph.tos = 1;
iph.tot_len = 2;
iph.id = 3;
iph.frag_off = 4;
iph.ttl = 5;
iph.protocol = 6;
//iph.check = 0;
iph.saddr = 7;
iph.daddr = 8;
return ip_fast_csum((u8 *)&iph, 5);
}
void main(void)
{
iph.check = ip4_csum();
printf("校验正确:%x\n", ip_fast_csum((u8 *)&iph, 5));
iph.id = 2;
printf("校验错误:%x\n", ip_fast_csum((u8 *)&iph, 5));
iph.frag_off = 5;
printf("校验错误:%x\n", ip_fast_csum((u8 *)&iph, 5));
iph.frag_off = 6;
printf("校验错误:%x\n", ip_fast_csum((u8 *)&iph, 5));
iph.ttl = 6;
printf("校验错误:%x\n", ip_fast_csum((u8 *)&iph, 5));
}
测试结果:
校验正确:0
校验错误:1
校验错误:0
校验错误:fffe
校验错误:fffd
结果分析:
有一个校验和的错误没有检查出来,校验错误时校验和应该不为0,但第3行的校验和仍然为0。
参考: