2010-08-19 3 views
10

Как получить пакеты уровня 2 в POSIXy C++? Пакеты имеют только src и dst MAC-адрес, тип/длину и пользовательские форматированные данные. Они не являются TCP или UDP или IP или IGMP или ARP, или что-то еще - они являются домашним форматом, предоставленным мне парнями Hardware.Как получить сырые пакеты уровня 2 в C/C++?

Мой socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) никогда не возвращается с его recvfrom().

Я могу отправить штраф, я просто не могу получить независимо от того, какие параметры я бросаю в сетевой стек.

(Платформа VxWorks, но я могу перевести POSIX или Linux или что-то ...)

получить код (текущее воплощение):

int s; 

if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
    printf("socket create error."); 
     return -1; 
} 

    struct ifreq   _ifr; 
    strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0")); 
    ioctl(s, IP_SIOCGIFINDEX, &_ifr); 

    struct sockaddr_ll _sockAttrib; 
    memset(&_sockAttrib, 0, sizeof(_sockAttrib)); 
    _sockAttrib.sll_len  = sizeof(_sockAttrib); 
    _sockAttrib.sll_family = AF_PACKET; 
    _sockAttrib.sll_protocol = IFT_ETHER; 
    _sockAttrib.sll_ifindex = _ifr.ifr_ifindex; 
    _sockAttrib.sll_hatype = 0xFFFF; 
    _sockAttrib.sll_pkttype = PACKET_HOST; 
    _sockAttrib.sll_halen = 6; 
    _sockAttrib.sll_addr[0] = 0x00; 
    _sockAttrib.sll_addr[1] = 0x02; 
    _sockAttrib.sll_addr[2] = 0x03; 
    _sockAttrib.sll_addr[3] = 0x12; 
    _sockAttrib.sll_addr[4] = 0x34; 
    _sockAttrib.sll_addr[5] = 0x56; 
    int _sockAttribLen = sizeof(_sockAttrib); 


char packet[64]; 
memset(packet, 0, sizeof(packet)); 

    if (recvfrom(s, (char *)packet, sizeof(packet), 0, 
       (struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0) 
    { 
     printf("packet receive error."); 
    } 

    // code never reaches here 
+0

Удивительный вопрос! –

+1

Я рад, что вы отметили этот POSIX, удачи, пытаясь сделать это на Windoze;) –

+0

Просто nitpick: POSIX не определяет привязки C++, только C. –

ответ

4

Я думаю, что способ сделать это - написать свою собственную сетевую службу, которая привязывается к уровню MUX в сетевом стеке VxWorks. Это достаточно хорошо документировано в Руководстве сетевого программиста VxWorks и что-то, что я сделал несколько раз.

Пользовательский сетевой сервис может быть настроен для просмотра всех пакетов уровня 2, полученных на сетевом интерфейсе, с использованием типа сервиса MUX_PROTO_SNARF, с которым работает собственный протокол WDB Wind River, или пакетов с определенным типом протокола.

Также можно добавить интерфейс сокета к вашей пользовательской службе сети, написав собственный сервер сокетов, который находится между сетевой службой и API сокета. Это не требуется, если вы с удовольствием выполняете обработку приложений в Сетевой службе.

Вы не сказали, какая версия VxWorks вы используете, но я думаю, что выше справедливо для VxWorks 5.5.x и 6.x

+0

Спасибо. Я пошел на ленивый маршрут и просто скопировал пакет из кода Xilinx, прежде чем он попал в сетевой стек. Ваш путь был бы ... не ленивым, а не по графику ... :) – spydez

3

Вы пробовали настройки протокола сокет htons(ETH_P_ALL), как предписанное в packet(7)? То, что вы делаете, не имеет большого отношения к IP (хотя IPPROTO_RAW может быть подстановочным значением, dunno)

+0

Правильный ответ - протокол, переданный в 'socket()', не должен быть 'IPPROTO_RAW', это должен быть ethernet (802.3) для вашего пользовательского протокола в сетевом порядке. – caf

+0

Спасибо. Вы правы, но это все еще не работает. – spydez

+0

может начать читать справочные страницы и проверить любые аргументы, которые вы догадались там. – mvds

1

Я думаю, что это будет немного сложнее решить проблему, чем вы ожидаете. Учитывая, что это не IP вообще (или, по-видимому, какой-либо другой протокол ничего узнает), я не думаю, что вы сможете полностью решить свои проблемы с кодом пользователя. В Linux я думаю, вам нужно написать свой собственный драйвер device agnostic interface (возможно, используя NAPI). Как заставить его работать под VxWorks почти наверняка будет нетривиальным (больше похоже на полное переписывание с нуля, чем то, что большинство людей будет рассматривать как порт).

0

Вы пытались подтвердить через Wireshark, что пакет действительно был отправлен с другого конца?

Кроме того, для отладки попросите своих аппаратных ребята, если у них есть отладочный вывод (вы можете подключиться к логическому анализатору), который они могут утверждать, когда он получает пакет. Просто чтобы убедиться, что аппаратное обеспечение получает пакеты в порядке.

+0

Это все внутри FPGA, так что его невозможно надуть. HW говорит, что это работает, поэтому я должен пойти с этим пока. – spydez

0

Прежде всего, необходимо указать протокол, как ETH_P_ALL, чтобы ваш интерфейс получает все пакет. Установите ваш сокет в беспорядочный режим. Затем привяжите свой RAW-сокет к интерфейсу, прежде чем выполнять прием.

Смежные вопросы