2011-04-16 13 views
5

Estoy estudiando tomas sin procesar. Usé la opción IP_HDRINCL para construir mis propios encabezados de IP. Después del encabezado IP, estoy construyendo un encabezado UDP. Luego envío el paquete a la dirección de bucle invertido de mi sistema. Tengo otro programa en ejecución que capturará los paquetes UDP tal como vienen. Para comprobar si los paquetes se están formando y recibiendo correctamente, tengo otro proceso en ejecución que es la lectura de datagramas de IP sin procesar. Mi problema es que aunque el segundo proceso (leer datagramas sin procesar) está funcionando bien (todos los campos IP y UDP parecen estar bien), pero el primer proceso (recibir UDP) no recibe ninguno de los paquetes que creé. El campo de protocolo en el encabezado IP está bien y el puerto también coincide ... Estoy usando Linux 2.6.35-22. Quiero saber si esto es normal en los nuevos kernels? Por favor, compruebe el código a continuación para detectar cualquier error. El proceso de UDP que debe recibir los paquetes se escucha en un socket enlazado al puerto 50000 en la misma máquina ...Ayuda de socket sin procesar: ¿Por qué los paquetes UDP creados por sockets sin procesar no están siendo recibidos por kernel UDP?

unsigned short in_cksum(unsigned short *addr, int len) 
{ 
    int nleft = len; 
    int sum = 0; 
    unsigned short *w = addr; 
    unsigned short answer = 0; 

    while (nleft > 1) { 
     sum += *w++; 
     nleft -= 2; 
    } 

    if (nleft == 1) { 
     *(unsigned char *) (&answer) = *(unsigned char *) w; 
     sum += answer; 
    } 

    sum = (sum >> 16) + (sum & 0xFFFF); 
    sum += (sum >> 16); 
    answer = ~sum; 
    return (answer); 
} 


main() 
{ 
    int fd=socket(AF_INET,SOCK_RAW,IPPROTO_UDP); 

    int val=1; 

    int ret=setsockopt(fd,IPPROTO_IP,IP_HDRINCL,&val,sizeof(val)); 

    char buf[8192]; 

    /* create a IP header */ 

    struct iphdr* ip=(struct iphdr*)buf;//(struct iphdr*) malloc(sizeof(struct iphdr)); 

    ip->version=4; 
    ip->ihl=5; 
    ip->tos=0; 
    ip->id=0; 
    ip->frag_off=0; 
    ip->ttl=255; 
    ip->protocol=IPPROTO_UDP; 
    ip->check=0; 
    ip->saddr=inet_addr("1.2.3.4"); 
    ip->daddr=inet_addr("127.0.0.1"); 


    struct udphdr* udp=(struct udphdr*)(buf+sizeof(struct iphdr));//(struct udphdr*) malloc(sizeof(struct udphdr)); 
    udp->source=htons(40000); 
    udp->dest=htons(50000); 
    udp->check=0; 
    char* data=(char*)buf+sizeof(struct iphdr)+sizeof(struct udphdr);strcpy(data,"Harry Potter and the Philosopher's Stone"); 
    udp->len=htons(sizeof(struct udphdr)+strlen(data)); 
    udp->check=in_cksum((unsigned short*) udp,8+strlen(data)); 

    ip->tot_len=htons(sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data)); 

    struct sockaddr_in d; 
    bzero(&d,sizeof(d)); 
    d.sin_family=AF_INET; 
    d.sin_port=htons(50000); 
    inet_pton(AF_INET,"localhost",&d.sin_addr.s_addr); 
    while(1) 
    sendto(fd,buf,sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data),0,(struct sockaddr*) &d,sizeof(d)); 
} 
+1

fuego Wireshark. ¿Están incluso golpeando el cable? – rook

+0

Sí lo son ... y está mostrando correctamente el protocolo como UDP, el puerto de destino como 50000. Pero, el puerto de origen se etiqueta como "saftynetp". Tiene el valor correcto de 40000 pero no sé lo que esto significa – pflz

+2

capturar un paquete UDP real transmitido por socat o algo así y luego intentar forjar un paquete idéntico. Asegúrese de verificar todo, incluida la suma de comprobación. Ejecutar un programa diff como Meld en los volcados de paquetes funciona bien. – rook

Respuesta

0

He intentado algo muy similar. El problema es que la API de socket y, por extensión, cualquier programa que los use, no devuelven datos que la interfaz está ESCRIBIENDO a diferencia de los sockets sin formato utilizados por sniffers como wiresharks/tcpdump que sí lo hacen. Entonces, aunque sus paquetes estén formados correctamente, la aplicación UDP no los está leyendo. Si tiene otra computadora en la red, use una para generar el tráfico y la otra para leerla. Alternativamente, si tiene dos interfaces, podría abrir un socket sin formato en cada ... uno para escribir y el otro para leer.

3

Parece que hay un problema con el cálculo de la suma de comprobación UDP.

udp->check=in_cksum((unsigned short*) udp,8+strlen(data)); 

UDP comprobación de suma debe incluir algo que se llama la "pseudo-cabecera" antes de la cabecera UDP. El código calcula la suma de comprobación solo sobre el encabezado UDP y la carga útil. El proceso de recepción de UDP podría no estar recibiendo los paquetes debido a las sumas de verificación incorrectas.

Habilite la validación de suma de comprobación en Wireshark y compruebe si los campos de suma de comprobación de los paquetes UDP son correctos o no.

ver lo siguiente:

Cuestiones relacionadas