2013-07-31 2 views
0

Я пытаюсь написать функцию, которая берет поток байтов (включая заголовок ethernet и, возможно, протоколы верхнего уровня, инкапсулированные в пакет Ethernet) и отправляет его в сети на конкретном интерфейсе.Внедрение необработанного пакета в сеть в C (Linux)

Вот краткое изложение моего кода:

// create socket 
int s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); 
if (s < 0) { 
    // error handling 
} 

// set up to just receive/send packets on one interface (stored in the variable iface_name e.g. eth0) 
struct ifreq ifr; 
bzero(&ifr, sizeof(struct ifreq)); 
strncpy(ifr.ifr_ifrn.ifrn_name, iface_name, IFNAMSIZ); 
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 
    // error handling 
} 

// set up socaddr for write 
struct sockaddr sa; 
sa.sa_family = PF_PACKET; 
sa.sa_data = htons(ETH_P_ALL); 

// write to wire 
// buf has type char* and len has type int 
// buf contains ethernet header, followed by payload (e.g. ARP packet or IP packet) 
if (sendto(s, buf, len, 0, &sa, sizeof(struct sockaddr)) < 0) { 
    perror("sendto"); 
    // more error handling 
} 

Я получаю ошибку

sendto: Invalid argument 

Как я могу исправить эту ошибку?

Моя первоначальная догадка заключается в том, что это почему-то вызвано аргументом sa, поскольку все остальные являются довольно стандартными, и не так много, чтобы пойти не так. Я мог бы заменить это аргументом sockaddr_ll типа, как в this example, но это означало бы извлечение информации заголовка от buf, и это кажется немного бессмысленным, поскольку оно уже есть, готовое к работе. Должен быть лучший способ? Инкапсулировать, инкапсулировать, повторно инкапсулировать, отправлять, похоже, слишком много ненужных шагов. Я пишу базовый интерфейс для некоторого ранее существующего кода, поэтому я не могу адаптировать вход, чтобы не включать в себя заголовки уровня канала передачи данных.

+0

Посмотрите здесь , http://austinmarton.wordpress.com/2011/09/14/sending-raw-ethernet-packets-from-a-specific-interface-in-c-on-linux/ –

+0

Я думаю, что это близко, но что мне делать введите для MAC-адреса назначения в sll_addr? Если возможно, я хочу избежать необходимости извлекать это из своих исходных данных (так как пакет уже сконструирован, поэтому я не понимаю, почему я должен разорвать его на части). Наверное, я понимаю, если это невозможно? – Froskoy

+0

Ahem. http://stackoverflow.com/questions/1519585/how-to-get-mac-address-for-an-interface-in-linux-using-ac-program –

ответ

0

его ваши библиотеки:

http://linux.die.net/man/7/raw посмотреть определение заголовка и смотреть на то, как он делает свой сокет он не использует htons, а: IPPROTO_RAW, расположенные в

#include <netinet/in.h>