2012-07-10 375 views
7

Estoy escribiendo un módulo del kernel que utiliza ganchos netfilter para modificar algunas de la información del encabezado TCP y, obviamente, antes de enviar, quiero volver a calcular la suma de comprobación.
También edito el encabezado en el lado de recepción, así que tengo que volver a calcularlo allí también.Cómo calcular la suma de comprobación TCP

La búsqueda en línea, me encontré con algunas personas diciendo que puedo simplemente ponerlo a 0 y va a ser calculado para mí, al parecer, que no funcionó.
También he encontrado esta función

tcp_v4_send_check(struct sock *sk, struct sk_buff *skb); 

Aunque nadie ha explicado cómo se usa, y si yo en realidad se puede utilizar en la recepción/envío de la misma manera.
Mi propio intento fue establecer checksum en 0 y luego llamar a esta función pasando el skb que tengo y el skb-> sk que tengo, todavía nada.

Entonces, ¿cuál es una forma sencilla de calcular la suma de comprobación de los datagramas TCP?

+0

¿Qué es exactamente lo que pone a 0 y dónde se puede esperar encontrar la suma de comprobación? Al mirar el código, debe establecer tcp_hdr (skb) -> check en 0, luego llamar a la función y, posteriormente, la nueva suma de comprobación debe estar allí. – BjoernD

+0

y eso es exactamente lo que hice, pero todas las conexiones TCP simplemente no funcionaron cuando cargué el módulo. – Fingolfin

+0

Probablemente deberías agregar la etiqueta 'C' a la pregunta. Por cierto, eche un vistazo a http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.html – Jite

Respuesta

3

volver a calcular la suma de comprobación, se calcula una suma de comprobación mejor incrementales - basta con modificar la suma de control existente sobre la base de los campos que ha cambiado, en lugar de leer todo el paquete.

Esto se debe hacer mientras se está cambiando el paquete, cuando se sabe tanto los valores antiguos y los nuevos valores se almacenan.

La idea básica es tcp->check += (new_val - old_val).
Es un poco más complicado que esto, becuase:
1. old_val y new_val necesitan ser valores de 16 bits, que están alineadas en 2 bytes (cambiando por ejemplo, un número de puerto).
2. La suma de comprobación usa una aritmética de complemento, por lo que debe hacer "llevar comentarios". Esto significa básicamente que si tcp->check + new_val - old_val es negativo, debe restar 1 del resultado.

+1

Esta es la forma correcta de hacerlo. Es más rápido y tiene menos riesgo de corrupción de datos. Volver a calcular la suma de verificación desde cero habría corrido el riesgo de enmascarar cualquier corrupción que ya le haya sucedido a los datos. – kasperd

1

Este es un ejemplo que se combinan netfilter API + checksum de TCP (no IP):

http://www.linuxvirtualserver.org/software/tcpsp/index.html

Mira en el archivo llamado tcpsp_core.c.

th->check = 0; 
    th->check = csum_tcpudp_magic(iph->saddr, iph->daddr, 
            datalen, iph->protocol, 
            csum_partial((char *)th, datalen, 0)); 
    skb->ip_summed = CHECKSUM_UNNECESSARY; 

(observe que primero se asigna cero, se calcula la suma de comprobación y luego se indica la suma de comprobación de IP como no necesaria).

Depende de qué módulo netfilter u carga (hay muchos !!!) que van a trabajar en diferentes capas, por ejemplo, iptable de trabajo en la capa IP se muestra a continuación (imagen):

http://ars.sciencedirect.com/content/image/1-s2.0-S1389128608004040-gr3.jpg

1

@ La respuesta de Ugoren no es precisa. De acuerdo con RFC1624 https://tools.ietf.org/html/rfc1624, esto a veces producirá -0 (0xFFFF), lo que no está permitido.

La forma correcta para calcular la suma de comprobación debe ser: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

Cuestiones relacionadas