ошибка исходного сокета с sendto: нет кода ошибки [было: ошибка raw сокета с sendto: такого устройства нет]

я застрял с отправкой сырого кадра Ethernet.

[редактировать] Я нашел несколько ошибок.
1. Это должен быть AF_PACKET в вызове сокета.
2. AF_PACKET не имеет опции SOCK_PACKET, но SOCK_DGRAM и SOCK_RAW

С SOCK_DGRAM wireshark перехватывает искаженный LLC-пакет.
Но с SOCK_RAW нет сообщения об ошибке и нет захваченного пакета.

я не нахожу, что на самом деле идет не так.
[/редактировать]

код:

if ((ethernet_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1)
cout << "Ethernet Socket: "<< strerror(errno) << endl;

struct sockaddr_ll socket_address;
socket_address.sll_family   = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex=if_nametoindex("eth0");
socket_address.sll_hatype   = 1; // ARPHRD_ETHER
socket_address.sll_pkttype  = PACKET_OTHERHOST;
socket_address.sll_halen    = ETH_ALEN;
memcpy(socket_address.sll_addr,dest_mac_addr,ETH_ALEN);

int send_result = 0;

char *opt=(char*)malloc(4*sizeof(char));
strcpy(opt,"eth0");

if(setsockopt(ethernet_socket, SOL_SOCKET, SO_BINDTODEVICE, opt, 4)==-1)
cout << "Could not bind socket to device: " << strerror(errno) << endl;

if ((send_result
= sendto(ethernet_socket, &buffer, sizeof(buffer), 0,
(struct sockaddr*)&socket_address, sizeof(socket_address)))==-1){
cout << "sendto error: "<< strerror(errno) << endl;
return send_result;
}

С уважением
Ck

2

Решение

Я нашел решение, как это работает.
я взглянул на исходный код программы Linux PackEth.

следующий код работает для меня.

if ((ethernet_socket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1)
cout << "Ethernet Socket: "<< strerror(errno) << endl;  //errorhandling

memset(&ifr, 0, sizeof(ifr));
strncpy (ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1);
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';if (ioctl(ethernet_socket, SIOCGIFINDEX, &ifr) == -1) {
cout << "No such interface:"<< strerror(errno) << endl;
close(ethernet_socket);
}

ioctl(ethernet_socket, SIOCGIFFLAGS, &ifr);
if ( (ifr.ifr_flags & 0x1) == 0) {
cout << "Interface is down: "<< strerror(errno) << endl;
close(ethernet_socket);
}

ioctl(ethernet_socket, SIOCGIFINDEX, &ifr);memset(&socket_address, 0, sizeof (socket_address));
socket_address.sll_family    = AF_PACKET;
socket_address.sll_ifindex   = ifr.ifr_ifindex;
socket_address.sll_protocol  = htons(ETH_P_ALL);

if ((raw_send = sendto(ethernet_socket, buffer, size_payload+14,0,(struct     sockaddr*)
&socket_address, sizeof(socket_address)))==-1){
cout << "sendto error: "<< strerror(errno) << endl;
return raw_send;
}
2

Другие решения

$ man 7 packet

«Пакеты SOCK_RAW передаются и из драйвера устройства без каких-либо изменений в пакетных данных. При получении пакета адрес все еще анализируется и передается в стандартной структуре адреса sockaddr_ll. При передаче пакета предоставленный пользователем буфер должен содержать заголовок физического уровня. Этот пакет затем помещается в очередь без изменений в сетевой драйвер интерфейса, определенного адресом назначения. Некоторые драйверы устройств всегда добавляют другие заголовки.

SOCK_DGRAM работает на несколько более высоком уровне. Физический заголовок удаляется до того, как пакет будет передан пользователю. Пакеты, отправленные через сокет пакета SOCK_DGRAM, получают подходящий заголовок физического уровня на основе информации в адресе назначения sockaddr_ll, прежде чем они помещаются в очередь

0

По вопросам рекламы [email protected]