сырые данные Linux сокет Ethernet связывают с определенным протоколом

Я - написание кода для отправки необработанных кадров 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.

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

7
задан dschatz 29 July 2010 в 20:49
поделиться

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-адресом назначения и с использованием этого протокола.

5
ответ дан 7 December 2019 в 12:13
поделиться

В прошлом я обходил эту проблему с помощью пакетного фильтра.

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

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.

0
ответ дан 7 December 2019 в 12:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: