linux raw ethernet socket привязывается к определенному протоколу

Я пишу код для отправки сырых кадров Ethernet между двумя Linux-системами. Чтобы проверить это, я просто хочу получить простой клиент-отправитель и сервер-прием.

У меня есть клиент, который правильно делает пакеты (я вижу их с помощью анализатора пакетов).

На стороне сервера я инициализирую сокет так:

fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL));

где MY_ETH_PROTOCOL - 2-байтовая константа, которую я использую как ethertype, поэтому я не слышу посторонний сетевой трафик.

когда я привязываю этот сокет к своему интерфейсу, я должен снова передать ему протокол в структуре socket_addr: socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
Если я компилирую и запускаю такой код, он терпит неудачу. Мой сервер не видит пакет. Однако, если я изменю код следующим образом:
socket_address.sll_protocol = htons(ETH_P_ALL);
Затем сервер может видеть пакет, отправленный от клиента (а также многие другие пакеты), поэтому мне нужно выполнить некоторую проверку пакета, чтобы убедиться, что он соответствует MY_ETH_PROTOCOL.

Но я не хочу, чтобы мой сервер слышал трафик, который не отправляется по указанному протоколу, поэтому это не решение. Как мне это сделать?


person dschatz    schedule 29.07.2010    source источник
comment
Можете ли вы вставить код в то место, где вы настроили свой socket_address?   -  person bstpierre    schedule 30.07.2010


Ответы (2)


Я решил проблему.

Согласно http://linuxreviews.org/dictionary/Ethernet/ со ссылкой на 2-байтовое поле, следующее за MAC-адреса:

"значения этого поля от 64 до 1522 указывают на использование нового формата 802.3 Ethernet с полем длины, а значения 1536 в десятичной системе счисления (0600 в шестнадцатеричной системе) и выше указывают на использование исходного формата кадра DIX или Ethernet II с подпрограммой EtherType. -идентификатор протокола ".

поэтому я должен убедиться, что мой ethertype> = 0x0600.

Согласно http://standards.ieee.org/regauth/ethertype/eth.txt использование 0x88b5 и 0x88b6 «доступно для публичного использования для разработки протоколов для прототипов и конкретных поставщиков». Это то, что я собираюсь использовать в качестве эфирного типа. Мне не нужна дополнительная фильтрация, так как ядро ​​должно следить за тем, чтобы собирать кадры Ethernet только с правильным MAC-адресом назначения и с использованием этого протокола.

person dschatz    schedule 30.07.2010
comment
Я сделал, как ты сказал. Но мой клиент не может получить пакет указанного протокола. Вы можете вставить свой код? благодарю вас! электронная почта: [email protected] - person jianxi sun; 20.08.2014

Раньше я обходил эту проблему, используя фильтр пакетов.

Размахивание руками (непроверенный псевдокод)

struct bpf_insn my_filter[] = {
    ...
}

s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol));
struct sock_fprog pf;
pf.filter = my_filter;
pf.len = my_filter_len;
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));

sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(protocol);
sll.sll_ifindex = if_nametoindex("eth0");

bind(s, &sll, sizeof(sll));

Проверка ошибок и правильная установка фильтра пакетов оставлены в качестве упражнения для читателя ...

В зависимости от вашего приложения альтернативой, с которой может быть проще начать работу, является libpcap.

person bstpierre    schedule 29.07.2010