2010-07-26 12 views
8

Estamos tratando de comunicarnos con el servidor que escucha en la interfaz de bucle invertido de Linux a través de un socket sin formato y parece que el servidor no obtiene un solo paquete de nosotros. Los paquetes que enviamos son visibles en Wireshark.¿Es posible la conexión sin formato en la interfaz loopback?

¿Es posible el socket sin formato en loopback? (Por favor, no pregunte por qué la necesitamos: es demasiado complicado de explicar aquí)

EDIT: así es como lo abrimos

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

El servidor es lighttpd y es accesible a través de socket normales en localhost . netstat --raw imprime la tabla vacía, pero estoy absolutamente seguro de que tenemos dos sockets brutos funcionales en dispositivos eth normales.

+0

favor mensaje: a) Exactamente qué tipo de enchufe que está utilizando, es un AF_PACKET? b) Cómo lo vincula, ¿está utilizando bind o SO_BINDTODEVICE? c) ¿Qué es el servidor y qué intenta hacer? ¿Puedes hablar con un conector de IP (asumiendo IP aquí)? ¿Puedes enviar la salida de netstat --raw? – MarkR

+0

@MarkR: Dado que va por enchufes sin procesar, supongo que SOCK_RAW. SOCK_PACKET está obsoleto, de todos modos. –

+0

La página "man 7 packet" me parece bastante útil, léala y vea si lo que describe es coherente con lo que está haciendo. – MarkR

Respuesta

3

Los sockets crudos se comportan particularmente gaseosos con bind() y connect(), pero no puedo confirmar que su problema resida en ellos. Le sugiero que siga un enfoque más directo:

remitente

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

receptor

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

Espero que estos se comportan exactamente como usted quiere que ellos. Lea man 7 raw para conocer los detalles sangrientos de por qué esto funciona y más importante aúnman 7 packet si desea extenderlo. Además, tenga en cuenta que IPPROTO_RAW implica la opción de socket IP_HDRINCL, por lo que estamos construyendo el encabezado ip nosotros mismos, aunque la suma de comprobación IP y la longitud total se calculan y completan por el núcleo, aún.

edición: Además, si se desea un conector directo con el que enviar datos válidos para una aplicación como lighttpd, que tendría que coincidir con el argumento a socket(), así como proporcionar valores válidos para los campos de la cabecera IP. Un encabezado de ethernet apropiado no es obligatorio; el único campo importante será llenado por la pila kernel.

+0

Gracias. Lo intentaré. – jackhab

0

Por favor asegúrese de que se unen a 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)); 
Cuestiones relacionadas