LINUX.ORG.RU

write пишет write: No such device or address

 , ,


1

3

При попытке запустить так sudo ./run пишет ошибку write: No such device or address.

Вот код

#include <stdio.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/if_ether.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

unsigned char ipsrc[4] = { 0xc0, 0xa8, 0x01, 0x05 };
unsigned char ipdst[4] = { 0xc0, 0xa8, 0x01, 0x02 };
unsigned char srchw[6] = { 0x74, 0x2f, 0x68, 0xa2, 0x87, 0xc6 };
unsigned char broadcast[6]= { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
unsigned char unknown[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

int main ( int argc, char *argv[] )
{
	int sock;

	if ( ( sock = socket ( AF_PACKET, SOCK_RAW, htons ( ETH_P_ALL ) ) ) == -1 ) // ETH_P_ARP
	{
		perror ( "socket" );
		exit ( EXIT_FAILURE );
	}

	int length = sizeof ( struct ether_header ) + sizeof ( struct ether_arp );

	char buffer[length+1]; // length == 42

	struct ether_header *eh = (struct ether_header *)&buffer[0];
	struct ether_arp *ea = (struct ether_arp *) ( sizeof ( struct ether_header ) + &buffer[0] );

	strncpy ( eh->ether_shost, srchw, ETH_ALEN );
	strncpy ( eh->ether_dhost, broadcast, ETH_ALEN );
	eh->ether_type = ETHERTYPE_ARP;

	ea->ea_hdr.ar_hrd = ARPHRD_ETHER;
	ea->ea_hdr.ar_pro = 0x800;
	ea->ea_hdr.ar_hln = 6;
	ea->ea_hdr.ar_pln = 4;
	ea->ea_hdr.ar_op = ARPOP_REQUEST;

	strncpy ( ea->arp_sha, srchw, ETH_ALEN );
	strncpy ( ea->arp_tha, unknown, ETH_ALEN );
	strncpy ( ea->arp_spa, ipsrc, 4 );
	strncpy ( ea->arp_tpa, ipdst, 4 );


	if ( write ( sock, buffer, length ) == -1 )
	{
		perror ( "write" );
	}
	close ( sock );
}

Ответ на: комментарий от anonymous

И, сдается мне, ты где-то не используешь htons/htonl.

anonymous
()

Нашёл решение. Нужно заполнить структуру sockaddr_ll, указав там index, а потом сделать bind.

u0atgKIRznY5
() автор топика
unsigned char ipsrc[4] = { 0xc0, 0xa8, 0x01, 0x05 };
unsigned char ipdst[4] = { 0xc0, 0xa8, 0x01, 0x02 };

И не лень каждый раз возиться с этими байтами? Для такого придумали in_addr_t inet_addr(const char*)

Или можешь навелосипедить что-то свое, это не так уж и трудно.

Вот мой хеллоуворлд (для маленьких индейцев only):

int createIpFromString(const char *ipString) {
    
    int ip = 0;
    char currentSymbol = 0;
    
    for(int partNumber = 0, currentNumber = 0; partNumber < 4; ++partNumber) {
        
        int numericPartDetected = 0;
        
        while((currentSymbol = *ipString++) >= '0' && currentSymbol <= '9') {
            currentNumber = currentNumber * 10 + currentSymbol - '0';
            numericPartDetected = 1;
        }
        
        if(numericPartDetected == 0 || currentNumber > 255) {
            ip = -1;
            break;
        }
        
        // \0 is allowed as delimeter only if it last part of ip address
        if(currentSymbol == '.' || (currentSymbol == '\0' && partNumber == 3)) {
               ip |= currentNumber << (partNumber * 8);
               currentNumber = 0;
        } else {
            ip = -1;
            break;
        }
    }
    
    if(currentSymbol != '\0') {
        ip = -1;
    }
    
    return ip; // -1 if error
}

unsigned short createPortFromString(const char *portString) {
    unsigned short port = 0;
    char currentSymbol;
    while((currentSymbol = *portString++)) {
        if(currentSymbol >= '0' && currentSymbol <= '9') {
            port = port * 10 + currentSymbol - '0';
        } else {
            port = 0; // error
            break;
        }
    }
    return port << 8 | port >> 8;
}

Когда-то нужно было обойтись без stdlib...

anonymous
()
Ответ на: комментарий от anonymous

хочу на лоре опцию, игнора для анонимусов тех кто игнорит анонимусов!

anonymous
()

Как уже выше заметили, strncpy нельзя использовать не для строк, иначе все поломается на первом 0x00

anonymous
()
unsigned char unknown[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

unknown находится в статической области памяти, а значит по дефолту инициализируется нулями.

char buffer[length+1]; // length == 42

Зачем здесь +1? Ты же в буфере хранишь не строку, а значит \0 символ помещать в него не нужно.

anonymous
()
int length = sizeof ( struct ether_header ) + sizeof ( struct ether_arp );
// ^^ const int, enum или #define
char buffer[length+1]; // length == 42
// ^^ int не имеет чётко определённого размера
// напрашивается assert(length == 42), чтобы хотя бы поймать ошибку сразу
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.