2017-01-16 2 views
2

Итак, как вы это делаете правильно?Как правильно поместить сетевой интерфейс в беспорядочный режим на Linux

Я знаю, как это сделать, создав сокет, а затем установив флаг IFF_PROMISC с помощью ioctl (как описано в «howto check a network devices status in C?» и в другом месте), но это выглядит ошибочным, по крайней мере, теоретически.

1) вы читаете флаги через IOCTL 2) обновить флаги 3) кто-то еще измененные флаги 4) вы установили обновленные флаги через IOCTL

Есть ли лучший способ или я просто слишком беспокоиться?

Позже я обнаружил, что один должен добавить интерфейс PACKET_MR_PROMISC через setsockopt (который также не имеет расы), как это:

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 также жалуются на это.

+0

И ** ** почему вы думаете, 'ioctl' не так? И что было бы «более простым способом»? – Olaf

+0

Операция чтения/изменения/записи должна быть атомарной. – dbrank0

ответ

2

PACKET_MR_PROMISC включает в себя беспорядочный режим для устройства. Это не будет отражено в состоянии, указанном ifconfig, поскольку оно не изменяет состояние глобального флага IFF_PROMISC на устройстве. Это не значит, что это еще не сделано. Вот как сейчас работает библиотека pcap, и тот факт, что wirehark (и еще дюжина других утилит) может открыть устройство и видеть пакеты, не адресованные локальной системе, показывает, что он работает.

Внутренний счетчик на каждом устройстве, который увеличивается каждый раз, когда процесс использует 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] 
+0

Спасибо, что правильно прочитал это для меня. O :-) («ip link» также не отображает флаг P ...). Быстрое продвижение и принятие этого, если тестирование показывает, что оно действительно работает, хотя можно сказать, что это по другим причинам (люди ожидают увидеть режим, настроенный с ifconfig и так далее). – dbrank0

+0

Хорошо. Да, это работает. Для справки: беспорядочный режим сохраняется только до закрытия гнезда. После этого восстанавливается ранее эффективный режим. Поэтому, если я правильно понимаю, нельзя установить беспорядочный режим и выйти (режим сохранения) с использованием этого интерфейса. Это нормально для моего использования. – dbrank0