2012-07-10 21 views
7

Sto scrivendo un modulo del kernel che utilizza gli hook di Netfilter per modificare alcune informazioni dell'intestazione TCP e ovviamente, prima dell'invio, voglio ricalcolare il checksum.
Inoltre, modifica l'intestazione dal lato ricevente, quindi devo ricalcolarlo anche lì.Come calcolare il checksum TCP

Ricerca in linea, ho trovato alcune persone che dicono che posso semplicemente impostarlo su 0 e verrà calcolato per me, a quanto pare non ha funzionato.
ho trovato anche questa funzione

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

Anche se nessuno ha spiegato come questo viene utilizzato, e se mi può effettivamente usarlo al di ricezione/invio allo stesso modo.
Il mio tentativo era di impostare il checksum a 0, quindi chiamare questa funzione passando lo skb che ho e il skb-> sk che ho, ancora nulla.

Quindi, per favore, qual è un modo semplice per calcolare il checksum dei datagrammi TCP?

+0

Che cosa hai impostato a 0 e dove ti aspettavi di trovare la somma di controllo? Guardando il codice, dovresti impostare tcp_hdr (skb) -> check a 0, quindi chiamare la funzione e successivamente il nuovo checksum dovrebbe essere lì. – BjoernD

+0

e questo è esattamente quello che ho fatto, ma tutte le connessioni TCP semplicemente non ha funzionato quando ho caricato il modulo. – Fingolfin

+0

Probabilmente dovresti aggiungere il tag 'C' alla domanda. Btw, date un'occhiata a http://www.winpcap.org/pipermail/winpcap-users/2007-July/001984.html – Jite

risposta

3

Per ricalcolare il checksum, è meglio calcolare un checksum incrementale: è sufficiente modificare il checksum esistente in base ai campi che sono stati modificati, anziché leggere l'intero pacchetto.

Questo deve essere fatto mentre si sta modificando il pacchetto, quando si conoscono sia i vecchi valori che i nuovi valori memorizzati.

L'idea di base è tcp->check += (new_val - old_val).
È un po 'più complicato di questo, perché:
1. old_val e new_val devono essere valori a 16 bit, che sono allineati su 2 byte (ad esempio cambiando un numero di porta).
2. Il checksum utilizza l'aritmetica del complemento, quindi è necessario eseguire "carry feedback". Ciò significa fondamentalmente che se tcp->check + new_val - old_val è negativo, è necessario sottrarre 1 dal risultato.

+1

Questo è il modo giusto di farlo. È più veloce e ha meno rischi di corruzione dei dati. Recuperare il checksum da zero avrebbe corso il rischio di mascherare qualsiasi corruzione che era già accaduta ai dati. – kasperd

1

Ecco un esempio che si combinano netfilter API + checksum per il protocollo TCP (non IP):

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

guardare nel file denominato 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; 

(notarlo è stato assegnato a zero prima, checksum calcolato, quindi checksum IP indicato come non necessario).

dipende dal modulo netfilter u caricare (ci sono molti !!!) lavoreranno in diversi strati, ad esempio, iptable lavoro a livello IP è mostrato di seguito (immagine):

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

1

@ la risposta di ugoren non è precisa. Secondo RFC1624 https://tools.ietf.org/html/rfc1624, a volte questo produce -0 (0xFFFF), che non è consentito.

Il modo corretto per calcolare checksum dovrebbe essere: new_tcp_check = ~(~old_tcp_check + ~old_val + new_val)

Problemi correlati