2013-04-26 6 views
6

Sto provando a inviare un frame Ethernet OAM utilizzando socket raw. Ho avuto successo nel farlo.La funzione sendto non utilizza l'indirizzo MAC fornito in struct sockaddr_ll quando si inviano pacchetti grezzi

La funzione di invio che ho scritto è:

int send_frame(sock_info *info,char *buf,int length) 
    { 
     struct sockaddr_ll dest_addr; 
     memset(&dest_addr,0,sizeof(struct sockaddr_ll)); 
     dest_addr.sll_family = PF_PACKET; 
     dest_addr.sll_protocol = htons(8902); 
     dest_addr.sll_ifindex = info->if_index; 
     dest_addr.sll_halen = ETH_MAC_ADDR_LEN; 
     dest_addr.sll_pkttype = PACKET_OTHERHOST; 
     dest_addr.sll_hatype = ARPHRD_ETHER; 
     memset(dest_addr.sll_addr,0,8); 

     dest_addr.sll_addr[0] = 0x00; 
     dest_addr.sll_addr[1] = 0xE0; 
     dest_addr.sll_addr[2] = 0x0C; 
     dest_addr.sll_addr[3] = 0x00; 
     dest_addr.sll_addr[4] = 0x95; 
     dest_addr.sll_addr[5] = 0x02; 

     return sendto(info->sock_fd, buf, length, 0, (struct sockaddr*) &dest_addr, sizeof(struct sockaddr_ll)); 
    } 

ero in grado di catturare il pacchetto con Wireshark. Dopo aver provato troppe cose, ho scoperto che il buffer utilizzato per l'invio dovrebbe avere tutti i campi frame ethernet (a partire dall'indirizzo di destinazione). Quando ho aggiunto la destinazione e l'indirizzo di origine e altri campi Ethernet nel buffer, sono riuscito a catturare il pacchetto utilizzando wireshark. Pertanto, la funzione di invio non utilizza l'indirizzo MAC memorizzato in dest_addr.sll_addr.

La mia domanda è, allora qual è la necessità del campo sll_addr nello struct sockaddr_ll? I manuali dicono che è l'indirizzo MAC di destinazione.

risposta

3

A me suona come esso funziona come la pagina di manuale descrive (man 7 pacchetto):

pacchetti SOCK_RAW sono passati da e per il driver di periferica senza variazioni dei dati a pacchetto. Quando si riceve un pacchetto, l'indirizzo è ancora analizzato e passato in una struttura di indirizzo standard sockaddr_ll. Durante la trasmissione di un pacchetto, il buffer fornito dall'utente deve contenere l'intestazione livello fisico. Tale pacchetto è quindi in coda non modificato per il driver di rete dell'interfaccia definita dall'indirizzo di destinazione. Alcuni driver di dispositivo aggiungono sempre altre intestazioni. SOCK_RAW è simile a ma non è compatibile con l'obsoleto PF_INET/SOCK_PACKET di Linux 2.0.

Il buffer qui si riferisce al 2o parametro di sendto(). Quindi, lo stock sockaddr_ll viene utilizzato solo per restituire i dati al chiamante, non per formattare il pacchetto RAW RAW. Forse vuoi utilizzare l'utente SOCK_DGRAM o libpcap?