Линукс сырой Ethernet сокет привязки к конкретному протоколу - PullRequest
7 голосов
/ 30 июля 2010

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

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

Ответы [ 2 ]

5 голосов
/ 30 июля 2010

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

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

0 голосов
/ 30 июля 2010

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

Hand Waving (непроверенный псевдокод)

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 .

...