如何在Linux

时间:2017-01-16 14:06:08

标签: c linux network-programming

那么你如何正确地做到这一点?

我知道如何通过创建套接字,然后使用ioctl设置IFF_PROMISC标志(如“howto check a network devices status in C?”及其他地方所述),但这至少在理论上看起来有缺陷。

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);
}

不幸的是,这对接口没有任何影响,尽管如果我正确地使用the doc,它应该是。可能broken since 2001 (tm)? pcap source中的评论也抱怨这一点。

1 个答案:

答案 0 :(得分:3)

PACKET_MR_PROMISC打开设备的混杂模式。这不会反映在ifconfig显示的状态中,因为它不会修改设备上全局IFF_PROMISC标志的状态。这并不意味着它还没有完成。这就是pcap库现在的工作方式以及wireshark(以及其他十几个实用程序)可以打开设备并查看未发送到本地系统的数据包这一事实表明它可以正常工作。

每个设备上都有一个内部计数器,每次进程使用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]