IP地址系列标识

时间:2014-05-24 08:35:04

标签: c linux ip ip-address kernel-module

我需要识别数据包IP(即IPv4或IPv6)的IP地址族。已成功使用libnetfilter捕获数据包并获取源和目标IP地址。但现在我需要从我正在实施的kernel module中识别所获得的IP地址族。

IP地址存储如下,

struct iphdr *ip_header = (struct iphdr *)skb_network_header(skb);  

unsigned int src_ip = (unsigned int)ip_header->saddr;   
unsigned int dest_ip = (unsigned int)ip_header->daddr;  

在我的研究过程中,我空洞地介绍了如何执行此功能,我只找到了如何格式化并使用%pI4%pI6将其显示为字符串。但不是如何以编程方式识别IP地址族。 (可能类似于函数IPAddress.AddressFamily

的Linux内核模块

如果专家能帮助我解决这个问题,我会非常感激,因为我被困了好几天。

提前致谢:)

修改

根据@alk的建议,如果专家建议我改变上面提到的unsigned int变量声明以支持IPv6,我将非常感激。 :)

1 个答案:

答案 0 :(得分:2)

skb_network_header返回的指针指向的前4位为您提供了ip标头的版本以及此版本的数据包。

根据这一点,你需要采用不同的方式踩头。

void * p = (void *) skb_network_header(skb);
unsigned int protocol_version = (*((unsigned char *) p) & 0xf0) >> 4;

switch (protocol_version)
{
case 4:
  struct ip_hdr * pip4_hdr = p; 

  printk("src=%pI4\n", &pip4_hdr->saddr);
  printk("dst=%pI4\n", &pip4_hdr->daddr);

  break;

case 6;
  struct ip6_hdr * pip6_hdr = p;

  printk("src=%pI6\n", &pip6_hdr->ip6_src);
  printk("dst=%pI6\n", &pip6_hdr->ip6_dst);

  break;

default:
  printk("<unhandled protocol version: %u>\n", protocol_version);

  break;
}

(未测试的)

供参考:IPv6IPv4标题的结构。