2010-07-26 21 views
8

Nous essayons de communiquer avec le serveur qui écoute sur l'interface loopback Linux via une socket raw et il semble que le serveur ne reçoive pas un seul paquet de notre part. Les paquets que nous envoyons sont visibles dans Wireshark.L'interface raw loop on loopback est-elle possible?

Est-ce que le socket brut sur le loopback est possible? (S'il vous plaît, ne demandez pas pourquoi nous en avons besoin: il est trop compliqué à expliquer ici)

EDIT: voilà comment nous ouvrons

_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)) 

Le serveur est lighttpd et il est accessible via la prise normale sur localhost . netstat --raw imprime la table vide mais je suis absolument sûr que nous avons deux sockets raw fonctionnels sur les périphériques eth normaux.

+0

S'il vous plaît après: a) exactement quel type de socket que vous utilisez, est-il un AF_PACKET? b) Comment liez-vous, utilisez-vous bind ou SO_BINDTODEVICE? c) Qu'est-ce que le serveur et qu'est-ce qu'il essaie de faire? Pouvez-vous parler avec une socket IP (en supposant IP ici)? Pouvez-vous envoyer la sortie de netstat --raw? – MarkR

+0

@MarkR: Étant donné qu'il utilise des sockets raw, je devine SOCK_RAW. SOCK_PACKET est obsolète, de toute façon. –

+0

Je trouve la page "man 7 packet" assez utile, veuillez la lire et voir si ce qu'elle décrit correspond à ce que vous faites. – MarkR

Répondre

3

Les sockets raw se comportent particulièrement bien avec bind() et connect(), mais je ne peux pas confirmer que votre problème réside avec eux. Je vous suggère de suivre une approche plus directe:

Auteur

#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); 
} 

Récepteur

#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); 
} 

J'espère que ces se comportent exactement comme vous voulez qu'ils. Lire man 7 raw pour les détails sanglants de pourquoi cela fonctionne et plus important encoreman 7 packet si vous voulez l'étendre. Notez également que IPPROTO_RAW implique l'option de socket IP_HDRINCL, c'est pourquoi nous construisons l'en-tête ip nous-mêmes - bien que la somme de contrôle IP et la longueur totale soient calculées et remplies par le noyau, encore.

modifier: En outre, si vous vouliez une socket raw avec laquelle envoyer des données valides à une application comme lighttpd, vous auriez à correspondre l'argument à socket() ainsi que de fournir des valeurs valides pour les champs d'en-tête IP. Un en-tête Ethernet correct n'est pas obligatoire - le seul champ important sera rempli pour vous par la pile du noyau.

+0

Merci. Je vais l'essayer. – jackhab

0

S'il vous plaît faire se lier à vous if_index

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));