2010-08-19 13 views
10

Come si ricevono i pacchetti di livello 2 in POSIXy C++? I pacchetti hanno solo indirizzo MAC src e dst, tipo/lunghezza e dati formattati personalizzati. Non sono TCP o UDP o IP o IGMP o ARP o altro - sono un formato fatto in casa dai ragazzi dell'Hardware.Come si ricevono pacchetti raw, layer 2 in C/C++?

Il mio socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW) non torna mai dal suo recvfrom().

Posso inviare correttamente, non riesco a ricevere tutte le opzioni che scelgo nello stack di rete.

(Platform è VxWorks, ma posso tradurre POSIX o Linux o qualunque cosa ...)

codice di ricezione (attuale incarnazione):

int s; 

if ((s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
    printf("socket create error."); 
     return -1; 
} 

    struct ifreq   _ifr; 
    strncpy(_ifr.ifr_name, "lltemac0", strlen("lltemac0")); 
    ioctl(s, IP_SIOCGIFINDEX, &_ifr); 

    struct sockaddr_ll _sockAttrib; 
    memset(&_sockAttrib, 0, sizeof(_sockAttrib)); 
    _sockAttrib.sll_len  = sizeof(_sockAttrib); 
    _sockAttrib.sll_family = AF_PACKET; 
    _sockAttrib.sll_protocol = IFT_ETHER; 
    _sockAttrib.sll_ifindex = _ifr.ifr_ifindex; 
    _sockAttrib.sll_hatype = 0xFFFF; 
    _sockAttrib.sll_pkttype = PACKET_HOST; 
    _sockAttrib.sll_halen = 6; 
    _sockAttrib.sll_addr[0] = 0x00; 
    _sockAttrib.sll_addr[1] = 0x02; 
    _sockAttrib.sll_addr[2] = 0x03; 
    _sockAttrib.sll_addr[3] = 0x12; 
    _sockAttrib.sll_addr[4] = 0x34; 
    _sockAttrib.sll_addr[5] = 0x56; 
    int _sockAttribLen = sizeof(_sockAttrib); 


char packet[64]; 
memset(packet, 0, sizeof(packet)); 

    if (recvfrom(s, (char *)packet, sizeof(packet), 0, 
       (struct sockaddr *)&_sockAttrib, &_sockAttribLen) < 0) 
    { 
     printf("packet receive error."); 
    } 

    // code never reaches here 
+0

domanda Impressionante! –

+1

Sono contento che hai contrassegnato questo POSIX, buona fortuna cercando di fare questo su Windoze;) –

+0

Solo un nitpick: POSIX non definisce binding C++, solo C. –

risposta

4

Penso che il modo per farlo è quello di scrivere il proprio servizio di rete che si lega allo strato MUX nello stack di rete VxWorks. Questo è ragionevolmente ben documentato nella Guida per programmatori di rete VxWorks e qualcosa che ho fatto un certo numero di volte.

Un servizio di rete personalizzato può essere configurato per visualizzare tutti i pacchetti di livello 2 ricevuti su un'interfaccia di rete utilizzando il tipo di servizio MUX_PROTO_SNARF, ovvero il funzionamento del protocollo WDB di Wind River o pacchetti con un tipo di protocollo specifico.

E 'anche possibile aggiungere un'interfaccia socket per la vostra abitudine Servizio di rete scrivendo una presa personalizzato back-end che si trova tra il servizio di rete e l'API socket. Questo non è necessario se si è soddisfatti di eseguire l'elaborazione dell'applicazione nel servizio di rete.

Non hai detto quale versione di VxWorks che si sta utilizzando, ma penso che quanto sopra vale per VxWorks 5.5.x e 6.x

+0

Grazie. Sono andato alla strada pigra e ho appena copiato il pacchetto dal codice Xilinx prima di entrare nello stack di rete. Il tuo modo sarebbe il ... non pigro, non in ritardo ... – spydez

3

Hai provato l'impostazione del protocollo di presa a htons(ETH_P_ALL) come prescritto in packet(7)? Quello che stai facendo non ha molto a che fare con IP (anche se IPPROTO_RAW potrebbe essere un valore jolly, non so)

+0

Risposta corretta: il protocollo passato a 'socket()' non dovrebbe essere 'IPPROTO_RAW', dovrebbe essere l'ethernet (802.3) ID protocollo per il protocollo personalizzato, in ordine di byte di rete. – caf

+0

Grazie. Hai ragione ma non funziona ancora. – spydez

+0

forse inizi a leggere le pagine man e controlla gli argomenti che hai indovinato. – mvds

1

Penso che questo sarà un problema un po 'più difficile da risolvere di quanto ti aspetti. Dato che non IP a tutti (o apparentemente qualsiasi altro nulla protocollo riconoscerà), non credo che sarete in grado di risolvere il problema (s) interamente con il codice a livello utente. Su Linux, penso che avresti bisogno di scrivere il proprio autista device agnostic interface (probabilmente usando NAPI). Riuscire a farlo funzionare con VxWorks sarà quasi certamente non banale (più come una completa riscrittura da zero rispetto a ciò che la maggior parte delle persone potrebbe pensare come una porta).

0

Hai provato a verificare tramite Wireshark che un pacchetto è stato effettivamente inviato dall'altra parte?

Inoltre, per il debug, chiedi ai tuoi ragazzi di hardware se hanno un pin di debug (che puoi collegare a un analizzatore logico) che possono far valere quando riceve un pacchetto. Giusto per assicurarmi che l'hardware stia ottenendo i pacchetti bene.

+0

È tutto all'interno di un FPGA, quindi non può essere sharked. HW dice che funziona, quindi devo andare con quello per ora. – spydez

0

Prima di tutto bisogna specificare il protocollo come ETH_P_ALL in modo che l'interfaccia ottiene tutto il pacchetto. Imposta il tuo socket in modalità promiscua. Quindi collegare il socket RAW a un'interfaccia prima di eseguire una ricezione.