那么你如何正确地做到这一点?
我知道怎么做,通过创build套接字,然后使用ioctl设置IFF_PROMISC标志(如“ 如何检查C中的networking设备状态? ”等),但至less在理论上这看起来有缺陷。
1)通过ioctl读取标志2)更新标志3)其他人修改标志4)通过ioctl设置更新标志
有没有更好的方法,或者我只是担心太多?
后来我发现应该通过setsockopt(也没有竞争)添加接口到PACKET_MR_PROMISC,像这样:
void set_promisc(const char *ifname, bool enable) { struct packet_mreq mreq = {0}; int sfd; int action; if ((sfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { perror("unable to open socket"); return; } mreq.mr_ifindex = if_nametoindex(ifname); mreq.mr_type = PACKET_MR_PROMISC; if (mreq.mr_ifindex == 0) { perror("unable to get interface index"); return; } if (enable) action = PACKET_ADD_MEMBERSHIP; else action = PACKET_DROP_MEMBERSHIP; if (setsockopt(sfd, SOL_PACKET, action, &mreq, sizeof(mreq)) != 0) { perror("unable to enter promiscouous mode"); return; } close(sfd); }
不幸的是,这对接口没有任何影响,但是,如果我正确地取消了这个文档的话,它应该是这样。 可能从2001年(tm)破碎 ? 在pcap源的评论也抱怨这一点。
PACKET_MR_PROMISC
打开设备的混杂模式。 这不会反映在ifconfig
显示的状态中,因为它不会修改设备上的全局IFF_PROMISC
标志的状态。 这并不意味着它还没有完成。 这就是pcap库现在的工作原理,以及wireshark(和其他一些实用程序)可以打开设备并查看未发送到本地系统的数据包的事实表明它可以工作。
每个设备上有一个内部计数器,每当进程使用PACKET_MR_PROMISC
时PACKET_MR_PROMISC
,当该进程消失时递减。 这解决了你最初描述的种族。
从你提供的最后一个链接:
> IFF_PROMISC is not set, It's not supposed to be set. The correct way to put into promiscuous mode the device to which a PF_PACKET socket is to do a SOL_PACKET/PACKET_ADD_MEMBERSHIP "setsockopt()" call with PACKET_MR_PROMISC as the argument (see the "packet(7)" man page), and that's what libpcap is doing. The old way of directly setting IFF_PROMISC had problems - to quote the comment at the front of "pcap-linux.c": [snipped]