Как я могу получать пакеты уровня 2 в POSIXy C ++? Пакеты имеют только MAC-адрес src и dst, тип / длину и данные, отформатированные пользователем. Это не TCP, UDP или IP, или IGMP, или ARP, или что-то в этом роде - это домашний формат, данный мне парнями из аппаратного обеспечения.
Мой разъем (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
Я думаю, что способ сделать это - написать собственную сетевую службу, которая привязывается к слою MUX в сетевом стеке VxWorks. Это достаточно хорошо задокументировано в Руководстве программиста по сети VxWorks, и я делал это несколько раз.
Пользовательская сетевая служба может быть настроена для просмотра всех пакетов уровня 2, полученных на сетевом интерфейсе, с использованием типа службы MUX_PROTO_SNARF, как работает собственный протокол WDB Wind River, или пакетов с определенным типом протокола.
Также возможно добавить интерфейс сокета к вашей пользовательской сетевой службе, написав собственный серверный модуль сокета, который находится между сетевой службой и API-интерфейсом сокета. Это не требуется, если вы готовы выполнять обработку приложения в сетевой службе.
Вы не сказали, какую версию VxWorks вы используете, но я думаю, что вышеизложенное справедливо для VxWorks 5.5.x и 6.x
Пробовали ли вы установить протокол сокета на htons(ETH_P_ALL)
, как предписано в packet(7)
? То, что вы делаете, не имеет большого отношения к IP (хотя IPPROTO_RAW
может быть каким-то значением wildcard, не знаю)
Думаю, решить эту проблему будет немного сложнее, чем вы ожидаете. Учитывая, что это вообще не IP (или, очевидно, какой-либо другой протокол, который что-нибудь распознает), я не думаю, что вы сможете полностью решить свои проблемы с помощью кода пользовательского уровня. В Linux, я думаю, вам нужно написать свой собственный драйвер , независимый от устройства, интерфейс (вероятно, с использованием NAPI
). Заставить его работать под VxWorks почти наверняка будет нетривиально (больше похоже на полное переписывание с нуля, чем на то, что большинство людей считают портом).
Вы пытались подтвердить через Wireshark, что пакет действительно был отправлен с другого конца?
Кроме того, для отладки спросите своих аппаратных разработчиков, есть ли у них отладочный пин (вы можете прикрепить к логическому анализатору), что они могут утверждать, когда он получает пакет. Просто чтобы убедиться, что оборудование нормально принимает пакеты.