Я пытаюсь отправить и получить пакеты типа SOCK_RAW
поверх PF_SOCKET
, используя свой собственный идентификатор протокола на том же компьютере. Вот мой пример кода отправителя и получателя -
sender.c
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<linux/if_arp.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CUSTOM_PROTO 0xB588
int main ()
{
int sockfd = -1;
struct sockaddr_ll dest_addr = {0}, src_addr={0};
char *buffer = NULL;
struct ethhdr *eh;
sockfd = socket(PF_PACKET, SOCK_RAW, htons(CUSTOM_PROTO) );
if ( sockfd == -1 )
{
perror("socket");
return -1;
}
buffer = malloc(1518);
eh = (struct ethhdr *)buffer;
dest_addr.sll_ifindex = if_nametoindex("eth0");
dest_addr.sll_addr[0] = 0x0;
dest_addr.sll_addr[1] = 0xc;
dest_addr.sll_addr[2] = 0x29;
dest_addr.sll_addr[3] = 0x49;
dest_addr.sll_addr[4] = 0x3f;
dest_addr.sll_addr[5] = 0x5b;
dest_addr.sll_addr[6] = 0x0;
dest_addr.sll_addr[7] = 0x0;
//other host MAC address
unsigned char dest_mac[6] = {0x0, 0xc, 0x29, 0x49, 0x3f, 0x5b};
/*set the frame header*/
memcpy((void*)buffer, (void*)dest_mac, ETH_ALEN);
memcpy((void*)(buffer+ETH_ALEN), (void*)dest_mac, ETH_ALEN);
eh->h_proto = htons(PAVAN_PROTO);
memcpy((void*)(buffer+ETH_ALEN+ETH_ALEN + 2), "Pavan", 6 );
int send = sendto(sockfd, buffer, 1514, 0, (struct sockaddr*)&dest_addr,
sizeof(dest_addr) );
if ( send == -1 )
{
perror("sendto");
return -1;
}
return 0;
}
receiver.c
#include<sys/socket.h>
#include<linux/if_packet.h>
#include<linux/if_ether.h>
#include<linux/if_arp.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define CUSTOM_PROTO 0xB588
int main ()
{
int sockfd = -1;
struct sockaddr_ll dest_addr = {0}, src_addr={0};
char *recvbuf = malloc(1514);
sockfd = socket(PF_PACKET, SOCK_RAW, htons(CUSTOM_PROTO) );
if ( sockfd == -1 )
{
perror("socket");
return -1;
}
int len = recvfrom(sockfd, recvbuf, 1514, 0, NULL, NULL);
printf("I received: \n");
return 0;
}
Оба отправителя и получателя работают в Ubuntu Virtualbox. Проблема заключается в том, что приемник находится в recvfrom
. Но в receiver.c
, если я изменяю htons(CUSTOM_PROTO)
на htons(ETH_P_ALL)
, приемник работает отлично.
Почему ядро не доставляет пакет с моим собственным идентификатором протокола в свой собственный идентификатор протокола ID?
Я проверил в GDB, что заголовок Ethernet сформирован правильно, когда я получаю пакет с htons(ETH_P_ALL)
Обновление: Вместо интерфейса eth0
и его соответствующего MAC, если я выбираю локальный loopback lo
и MAC-адрес 00:00:00:00:00:00
, CUSTOM_PROTO
работает просто отлично!
Обновление 2 CUSTOM_PROTO
отлично работает, если отправитель и получатель находятся на разных машинах. Это открытие и предварительное обновление заставили меня подозревать, что пакеты, отправленные на eth0
, не принимаются одним и тем же компьютером. Но тот факт, что ETH_P_ALL
работает на одной машине, опровергает мои подозрения.