我需要仅在特定接口上设置传入数据包的原始套接字(仅包含eth0和eth1,eth1)。换句话说,我只需要在一个特定接口上输入传入数据包。
与其他嗅探器比较
在ifconfig中,每个接口都有一个RX Packets字段。虽然这保持不变,但这个嗅探器仍将注册为接收数据包。也许RX Packets仅限于某些协议?我还将它与python嗅探器进行了比较 - 存在同样的问题。 python嗅探器不会返回与此c嗅探器一样多的数据包。我无法将其与wireshark进行比较,因为我无法在系统上安装它,它是嵌入式的。
绑定
我想也许我错误地绑定了这个,但这似乎有效。运行其中两个,一个在eth0上,另一个在eth1上,给出不同的结果/
疑似问题
在我看来,问题在于recvfrom命令不仅仅过滤到传入的数据包,而是从缓冲区读取,无论是传入还是传出。也许有一种方法可以查看地址以查看数据包是传入还是传出,如python中,或者recvfrom可能已经在执行此操作。
注意
接近结束时,程序会打印嗅探的数据包大小以及已收到大小数据包的时间。这是修剪过的代码。提前谢谢。
#include<errno.h> //error codes
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<time.h>
#include<unistd.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<string.h>
#include<netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<net/if.h>
const int TIME_INTERVAL = 2;
const int BUF_LENGTH = 65534;
int main()
{
int sock_errno(void), data_size=0, raw_sock;
long recv_count = 0, last_count = 0, rate = 0;
time_t start;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;
char buffer[BUF_LENGTH];
int hist[BUF_LENGTH];
int i;
for (i = 0; i < BUF_LENGTH; i++)
hist[i] = 0;
int table[BUF_LENGTH];
int index = 0;
//Create a raw socket that shall sniff
raw_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
//bind to interface
clilen = sizeof(struct sockaddr_in);
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "eth1");
setsockopt(raw_sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr));
start = time(NULL);
while (1)
{
data_size = recvfrom(raw_sock, buffer, BUF_LENGTH, 0, (struct sockaddr*)&cliaddr, &clilen);
recv_count = recv_count + data_size;
hist[data_size] = hist[data_size] + 1;
if (time(NULL) - start > TIME_INTERVAL) // display data every time interval
{
start = time(NULL);
rate = (float)(recv_count - last_count) / TIME_INTERVAL;
printf("(I) Bytes received: %d\n", recv_count);
for (i=0; i<BUF_LENGTH; i++) {
if (hist[i] > 0) //only print received packet sizes
{
printf("%d - ", i); //print packet size
printf("%d\n", hist[i]); //print received counter
}
}
printf("\n\n");
}
}
close(raw_sock);
return 0;
}
答案 0 :(得分:0)
查看Raw Socket promiscuous mode not sniffing what I write
的答案查看http://man7.org/linux/man-pages/man7/packet.7.html将cliaddr的类型更改为struct sockaddr_ll然后您可以查看cliaddr.sll_pkttype以确定传入或传出
struct sockaddr_ll {
unsigned short sll_family; /* Always AF_PACKET */
unsigned short sll_protocol; /* Physical layer protocol */
int sll_ifindex; /* Interface number */
unsigned short sll_hatype; /* ARP hardware type */
unsigned char sll_pkttype; /* Packet type */
unsigned char sll_halen; /* Length of address */
unsigned char sll_addr[8]; /* Physical layer address */
};
sll_pkttype包含数据包类型。 对于发往本地主机的数据包,有效类型为PACKET_HOST, PACKET_BROADCAST用于物理层广播包, PACKET_MULTICAST用于发送到物理层组播的数据包 地址,PACKET_OTHERHOST,用于将数据包发送到其他主机 在混杂模式下被设备驱动程序捕获,并且 PACKET_OUTGOING来自本地主机的数据包 环回到数据包套接字。