необработанные сокеты Ethernet, заполняющие sockaddr_ll

Я создаю программное обеспечение сервера/клиента, используя PF_PACKET и SOCK_RAW, а также собственный протокол при вызове socket().

Когда в клиентском программном обеспечении я создаю сокет таким же образом и просто делаю rcvfrom этого сокета, и я получаю данные

Мой вопрос заключается в том, должен ли я заполнять структуру sockaddr_ll так же, как и для сервера, поскольку, когда я отвечаю от клиента, исходный MAC-адрес, который я получил, является странным, например, 11:11:00:00:00:00 и конечно это не MAC моего клиента

Кто-нибудь знает, что это происходит? Откройте сокет

if ( (sckfd=socket(PF_PACKET, SOCK_RAW, htons(proto)))<0)
{
    myError("socket");

}

вот как я получаю данные

n = recvfrom(sckfd, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);

Так вот как я в основном получаю данные в клиенте без заполнения структуры sockaddr_ll

Для серверной программы мне нужно заполнить структуру

struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;   
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);

Мой вопрос: я получаю, как показано, и отправляю, как показано, и когда я отвечаю на сервер, вызываю ту же функцию, которая используется на сервере для отправки, то что я получаю 11:11:00:00:00:00 при получении ответов клиента


person user2948982    schedule 06.11.2013    source источник
comment
Было бы лучше показать некоторый соответствующий код и описать эту проблему. (и лучше, чем или)   -  person ryyker    schedule 06.11.2013
comment
Код показан знаю ryyker3   -  person user2948982    schedule 06.11.2013


Ответы (1)


Вероятно, вам следует использовать

socket(AF_PACKET, SOCK_DGRAM, htons(proto)))

вместо сокета SOCK_RAW. С помощью SOCK_RAW вы отправляете/принимаете весь кадр Ethernet, включая исходный и целевой MAC-адреса. с SOCK_DGRAM ядро ​​заполнит заголовок Ethernet.

Вы, вероятно, хотите отправить ответ на тот же адрес, с которого пришел запрос, recvfrom() может заполнить исходный адрес;

struct sockaddr_ll src_addr;
socklen_t addr_len = sizeof src_addr;
n = recvfrom(sckfd, buffer, 2048, 0, 
            (struct sockaddr*)&src_addr, &addr_len);

Теперь вы узнали адрес источника, поэтому отправьте пакет обратно на него:

...
sendto(sckfd, data, data_len, src_addr, addr_len);

И если вам нужно использовать SOCK_RAW, вы также получите заголовок Ethernet, поэтому просто скопируйте MAC-адреса из полученных данных и поменяйте их местами при создании кадра ответа.

Для сокета SOCK_RAW вы создаете весь кадр Ethernet, вам не нужно заполнять адрес Ethernet, поэтому следующее не требуется;

 memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
person nos    schedule 06.11.2013
comment
Спасибо, мне нужно использовать SOCK_RAW. Но это был действительно хороший ответ. - person user2948982; 07.11.2013
comment
@nos Извините, если мой вопрос глупый, но как вы понимаете, что AF_PACKET + SOCK_RAW использует struct sockaddr_pkt? Вы имеете в виду AF_INET+SOCK_RAW? - person thuovila; 07.11.2013
comment
Глядя в исходники ядра. Нет, я не имею в виду AF_INET+SOCK_RAW. - person nos; 07.11.2013
comment
@nos Кажется, я понимаю, что ты имеешь в виду. Я не знал этого раньше. Хотя я думаю, что с точки зрения API системных вызовов пользователь также может использовать пользовательскую область struct msghdr с sendmsg() в сокете SOCK_RAW, или я все еще что-то не понимаю? - person thuovila; 07.11.2013
comment
вы можете использовать sendmsg() или sendto() - person nos; 07.11.2013
comment
Привет, @thuovila. Я думаю, вам стоит взглянуть на эту ссылку hacked10bits.blogspot.com/2011/12/ говорит об отправке и получении кадров Ethernet - person user2948982; 08.11.2013
comment
Я удалил пару вещей. Как оказалось, struct sockadd_pkt используется для 3. типа необработанного сокета Ethernet, типа AF_PACKET/SOCK_PACKET. Хотя и AF_PACKET/SOCK_RAW, и AF_PACKET/SOCK_DGRAM используют структуру sockaddr_ll. Также кажется, что для AF_PACKET/SOCK_RAW вам не нужно заполнять адрес Ethernet назначения в структуре sockaddr_ll (в конце концов, вы уже установили его в отправляемом фрейме) - person nos; 08.11.2013