Linux内核数据包格式

LInux kernel中MAC头,IP头,TCP头结构体定义,内核打印方式。

 

MAC头:

//内核中MAC头结构体
#defein ETH_ALEN 6
struct ethhdr {
        unsigned char   h_dest[ETH_ALEN];  //48位目的MAC地址   
        unsigned char   h_source[ETH_ALEN];    //48位源MAC地址
        __be16          h_proto;             //16位协议类型
} __attribute__((packed));

 

//有这样两个宏可以方便地打印mac地址:
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]

//使用样例如下:
const struct ethhdr* eh = eth_hdr(skb);
printk(KERN_INFO "source mac:" MAC_FMT "\n", MAC_ARG(eh->h_source));
printk(KERN_INFO "dest mac:" MAC_FMT "\n", MAC_ARG(eh->h_dest));

IP头:

//linux kernel中ip地址结构体
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u8    ihl:4,    
                version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
        __u8    version:4,  //4位版本号
                ihl:4;    //4位首部长度
#else
#error  "Please fix <asm/byteorder.h>"
#endif
        __u8    tos;    //8位服务类型
        __be16  tot_len;    //16位总长度
        __be16  id;    //16位标识
        __be16  frag_off;    //3位标志,13位片偏移
        __u8    ttl;    //8位生存时间
        __u8    protocol;    //8位协议
        __sum16 check;    //16位首部校验和
        __be32  saddr;    //32位源地址
        __be32  daddr;    //32位目的地址
        /*The options start here. */
};
//打印IP地址
#define NIPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
 
struct iphdr *nh;
struct sk_buff *skb;
nh = ip_hdr(skb);
printk(KERN_INFO "src: %u.%u.%u.%u, dst: %u.%u.%u.%u\n", 
NIPQUAD(nh->saddr), NIPQUAD(nh->daddr));

 

TCP头定义:

 

//linux kernel 中tcp结构体
struct tcphdr {
        __be16  source;    //16位源端口号
        __be16  dest;    //16位目的端口号
        __be32  seq;    //32位序号
        __be32  ack_seq;    //32位确认序号
#if defined(__LITTLE_ENDIAN_BITFIELD)
        __u16   res1:4,
                doff:4,
                fin:1,
                syn:1,
                rst:1,
                psh:1,
                ack:1,
                urg:1,
                ece:1,
                cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
        __u16   doff:4,
                res1:4,
                cwr:1,
                ece:1,
                urg:1,
                ack:1,
                psh:1,
                rst:1,
                syn:1,
                fin:1;
#else
#error  "Adjust your <asm/byteorder.h> defines"
#endif
        __be16  window;
        __sum16 check;
        __be16  urg_ptr;
        };
//打印tcp端口号
const struct tcphdr* th = tcp_hdr(skb);
printk(KERN_INFO "src_port: %d, dst_port: %d\n", 
 ntohs(th->source), ntohs(th->dest));
uint32_t htonl(uint32_t hostlong);//32位的主机字节序转换到网络字节序 
uint16_t htons(uint16_t hostshort);//16位的主机字节序转换到网络字节序 
uint32_t ntohl(uint32_t netlong);//32位的网络字节序转换到主机字节序 
uint16_t ntohs(uint16_t netshort);//16位的网络字节序转换到主机字节序 

 

おすすめ

転載: blog.csdn.net/xiadeliang1111/article/details/103421779