我在尝试从一个指定的以太网接口捕获所有数据包时遇到了一个问题。我打开一个AF_PACKET套接字,并将指定的接口设置为promise模式。它从指定的接口捕获数据包。但是,它也从其他以太网接口(例如eth0)接收数据包。
我还尝试通过调用带有PACKET_DROP_MEMBERSHIP的setsockopt来过滤eth0接口,但它不起作用。它仍然捕获来自eth0的数据包。
// The following code opens socket and set the specified intf to PACKET_MR_PROMISC
// However, it also picks up packets from all other interfaces, for example, eth0
int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
int interface_number = if_nametoindex(interface_name.c_str());
if (interface_number == -1) {
syslog(LOG_ERR, "Can't get interface number for %s.n", interface_name.c_str());
return -1;
}
per_socket_data->ifindex = interface_number;
syslog(LOG_INFO, "intf %s, ifindex %d. n", interface_name.c_str(), interface_number);
// Switch to PROMISC mode
struct packet_mreq sock_params;
memset(&sock_params, 0, sizeof(sock_params));
sock_params.mr_type = PACKET_MR_PROMISC;
sock_params.mr_ifindex = interface_number;
int set_promisc = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&sock_params, sizeof(sock_params));
// The following code tries to prevent capturing packets from eth0. However, this does not work.
int eth0_interface_number = if_nametoindex(eth0.c_str());
if (eth0_interface_number == -1) {
syslog(LOG_ERR, "Can't get interface number for %s.n", eth0.c_str());
return -1;
}
syslog(LOG_INFO, "intf %s, ifindex %d. n", eth0.c_str(), eth0_interface_number);
memset(&sock_params, 0, sizeof(sock_params));
sock_params.mr_ifindex = eth0_interface_number;
int exclude_eth0 = setsockopt(fd, SOL_PACKET, PACKET_DROP_MEMBERSHIP, (void *)&sock_params, sizeof(sock_params));
如何解决这个问题?
是否已尝试SO_BINDTODEVICE套接字选项?
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface_name.c_str());
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
详细信息请参见socket(7)的手册页。