Я пытаюсь написать функцию, которая берет поток байтов (включая заголовок 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
, и это кажется немного бессмысленным, поскольку оно уже есть, готовое к работе. Должен быть лучший способ? Инкапсулировать, инкапсулировать, повторно инкапсулировать, отправлять, похоже, слишком много ненужных шагов. Я пишу базовый интерфейс для некоторого ранее существующего кода, поэтому я не могу адаптировать вход, чтобы не включать в себя заголовки уровня канала передачи данных.
Посмотрите здесь , http://austinmarton.wordpress.com/2011/09/14/sending-raw-ethernet-packets-from-a-specific-interface-in-c-on-linux/ –
Я думаю, что это близко, но что мне делать введите для MAC-адреса назначения в sll_addr? Если возможно, я хочу избежать необходимости извлекать это из своих исходных данных (так как пакет уже сконструирован, поэтому я не понимаю, почему я должен разорвать его на части). Наверное, я понимаю, если это невозможно? – Froskoy
Ahem. http://stackoverflow.com/questions/1519585/how-to-get-mac-address-for-an-interface-in-linux-using-ac-program –