2010-07-26 16 views
8

Wir versuchen, mit dem Server zu kommunizieren unter Linux Loopback-Schnittstelle über Raw-Socket zu hören und es scheint, als ob der Server nicht ein einziges Paket von uns bekommen. Die Pakete, die wir senden, sind in Wireshark sichtbar.Ist Raw-Socket auf Loopback-Schnittstelle möglich?

Ist Raw Socket on Loopback überhaupt möglich? (Bitte fragen Sie nicht, warum wir sie brauchen: es zu kompliziert ist, hier zu erklären)

EDIT: Das ist, wie wir es öffnen

_I_RawSocket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) 

memset(&ifr, 0, sizeof(ifr)); 
strcpy(ifr.ifr_ifrn.ifrn_name, _InterfaceName); 

ioctl(_I_RawSocket, SIOCGIFINDEX, &ifr) 

memset(&sll, 0, sizeof(sll)); 
sll.sll_family = AF_PACKET; 
sll.sll_ifindex = ifr.ifr_ifindex; 
sll.sll_protocol = htons(ETH_P_ALL); 

bind(_I_RawSocket, (struct sockaddr *) &sll, sizeof(sll)) 

Der Server lighttpd ist und es ist erreichbar über normale Steckdose auf localhost . netstat --raw druckt leere Tabelle, aber ich bin mir absolut sicher, dass wir zwei normale rohe Sockets auf normalen eth Geräten haben.

+0

Bitte senden Sie if_index: a) genau, welche Art von Buchse Sie verwenden, es ist ein AF_PACKET? b) Wie bindst du es, verwendest du bind oder SO_BINDTODEVICE? c) Was ist der Server und was versucht er zu tun? Kannst du mit einem IP-Socket darüber sprechen (angenommen IP hier)? Kannst du die Ausgabe von netstat --raw senden? – MarkR

+0

@MarkR: Angesichts der Tatsache, dass er für rohe Sockets geht, rate ich SOCK_RAW. SOCK_PACKET ist sowieso veraltet. –

+0

Ich finde die "man 7 packet" -Seite sehr nützlich, bitte lesen Sie es und sehen Sie, ob das, was es beschreibt, konsistent ist mit dem, was Sie tun. – MarkR

Antwort

3

Raw Sockets verhalten sich besonders gut mit bind() und connect(), aber ich kann nicht bestätigen, dass Ihr Problem bei ihnen liegt. Ich schlage vor, Sie folgen einem einfacheren Ansatz:

Sender

#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/ip.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 

#define DEST "127.0.0.1" 

int main(int argc, char **argv) 
{ 

int s; 
struct sockaddr_in dst_addr; 
char packet[50]; 

struct iphdr *ip = (struct iphdr *)packet; 

if((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
    perror("error:"); 
    exit(EXIT_FAILURE); 
} 

dst_addr.sin_family = AF_INET; 
dst_addr.sin_port = 0; /* not needed in SOCK_RAW */ 
inet_pton(AF_INET, DEST, (struct in_addr *)&dst_addr.sin_addr.s_addr); 
memset(dst_addr.sin_zero, 0, sizeof(dst_addr.sin_zero)); 

memset(packet, 'A', sizeof(packet)); /* payload will be all As */ 

ip->ihl = 5; 
ip->version = 4; 
ip->tos = 0; 
ip->tot_len = htons(40); 
ip->frag_off = 0; /* NF */ 
ip->ttl = 64; 
ip->protocol = IPPROTO_RAW; /* this has to be IPPROTO_RAW */ 
ip->check = 0; 
ip->saddr = dst_addr.sin_addr.s_addr; 
ip->daddr = dst_addr.sin_addr.s_addr; 

while(42) { 
    sleep(5); 
    if (sendto(s, packet, sizeof(packet), 0, 
    (struct sockaddr *)&dst_addr, (socklen_t)sizeof(dst_addr)) < 0) 
    perror("uh oh:"); 
} 
return(0); 
} 

Receiver

#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/ip.h> 
#include <arpa/inet.h> 
#include <string.h> 
#include <stdio.h> 
#include <stdlib.h> 


int main(int argc, char **argv) 
{ 
int s; 
struct sockaddr_in src_addr; 
char packet[50]; 

if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
    perror("error:"); 
    exit(EXIT_FAILURE); 
} 

memset(packet, 0, sizeof(packet)); 
socklen_t *len = (socklen_t *)sizeof(src_addr); 
int fromlen = sizeof(src_addr); 

while(42) { 
    if (recvfrom(s, &packet, sizeof(packet), 0, 
    (struct sockaddr *)&src_addr, &fromlen) < 0) 
    perror("uh oh:"); 

    int i = sizeof(struct iphdr); /* print the payload */ 
    for(; i < sizeof(packet); i++) { 
    printf("%c", packet[i]); 
    } 
    printf("\n"); 
} 
return(0); 
} 

Ich hoffe, diese verhalten sich genau wie Sie wollen, dass sie. Lesen Sie man 7 raw für die blutigen Details, warum das funktioniert und wichtigerman 7 packet wenn Sie es erweitern möchten. Beachten Sie auch, dass IPPROTO_RAW die Socket-Option IP_HDRINCL impliziert, weshalb wir den IP-Header selbst konstruieren - obwohl die IP-Prüfsumme und die Gesamtlänge vom Kernel immer noch berechnet und ausgefüllt werden.

edit: Wenn Sie außerdem einen Raw-Socket wünschen, mit dem gültige Daten an eine Anwendung wie lighttpd gesendet werden, müssen Sie das -Argument mit socket() vergleichen und gültige Werte für die IP-Headerfelder angeben. Ein richtiger Ethernet-Header ist nicht zwingend erforderlich - das einzige wichtige Feld wird vom Kernel-Stack für Sie gefüllt.

+0

Danke. Ich werde es versuchen. – jackhab

0

Bitte stellen Sie sicher, binden

if (ioctl(sock, SIOCGIFINDEX, &stEthReq) < 0) 
{ 
    printf("failed to get IF index!"); 
    return -1; 
} 
memset(&client_addr, 0, sizeof(client_addr)); 
client_addr.sll_family = AF_PACKET; 
client_addr.sll_ifindex = stEthReq.ifr_ifru.ifru_ivalue; 
client_addr.sll_protocol = VOS_HTONS(usEthType); 
ret = bind(sock,(struct sockaddr *)(&client_addr), sizeof(client_addr));