使用af_packet从数据包获取接口名称

时间:2016-03-21 08:58:29

标签: c linux sockets

使用以下方法使用AF_PACKET和环形缓冲区(伪C)捕获数据包:

// Set up socket
fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))

// Set socket bind options
struct sockaddr_ll sll;
sll.sll_family = AF_PACKET
sll.sll_protocol = htons(ETH_P_ALL)
sll.sll_ifindex = 0  // Bind to all interfaces

// Bind socket to all interfaces
bind(fd, (struct sockaddr *) &sll, socklen_t(sizeof(sll)))

// Set tpacket options in tp
setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &tp, socklen_t(sizeof(tp)))

// Map the ring buffer
mmap(NULL, ring_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)

// Read from ring using offsets
...

如上所示,如果sll_ifindex设置为0,套接字将在所有接口上接收。有没有办法修改此方法,或以某种方式收集数据包到达的网络接口?

1 个答案:

答案 0 :(得分:1)

是。放入环形缓冲区的每个帧都会在其前面插入两个结构:首先是tpacket_hdr,然后是sockaddr_ll。后者描述了接收数据包的接口。结构之间有填充,因此代码看起来像这样:

struct tpacket_hdr *tp = <Next frame in ring buffer>;
<wait for packet to arrive>
struct sockaddr_ll *sll = (struct sockaddr_ll*)((char *)tp + TPACKET_ALIGN(sizeof(*tp)));
printf("Frame received on IF index %u", sll->sll_ifindex);

您可以将界面索引翻译为SIOCGIFNAME ioctl

的名称