Thanks for the pointers, am still having problems sadly. Does it matter where I intercept the packets? As a dev system, I have been using a rule like: iptables -t filter -I OUTPUT -s ipaddress -j QUEUE This rule certainly picks up the packets, interestingly enough the checksum is equal to zero, which according to the rfc is correct, this I think is where my problem is coming from. Should I be queuing direct from the wire? am wondering if the linux tcp/ip stack is playing games with me ^_^ On Thu, Aug 27, 2009 at 5:34 PM, Kuzin Andrey<kuzinandrey@xxxxxxxxx> wrote: > MLm> Hi, > MLm> I am attempting to adjust contents of tcp packets using the nf queue > MLm> system, the queue part is working as I expected, however I am running > MLm> into problems recalculating the tcp checksum. At the moment, the > MLm> packet isnt being changed, and I am simply reading the checksum, then > MLm> trying to regenerate it, these values arent matching and I am at a > MLm> loss as to where I am going wrong. > MLm> Any help or suggestions please? I am at a loss > > Try this code stolen from tcpdump and other cool stuff. > > /* > * IP header checksum. > * don't modifiy the packet. > */ > u_short > in_cksum(const u_short *addr, register u_int len, int csum) > { > int nleft = len; > const u_short *w = addr; > u_short answer; > int sum = csum; > > /* > * Our algorithm is simple, using a 32 bit accumulator (sum), > * we add sequential 16 bit words to it, and at the end, fold > * back all the carry bits from the top 16 bits into the lower > * 16 bits. > */ > while (nleft > 1) { > sum += *w++; > nleft -= 2; > } > if (nleft == 1) > sum += htons(*(u_char *)w<<8); > > /* > * add back carry outs from top 16 bits to low 16 bits > */ > sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ > sum += (sum >> 16); /* add carry */ > answer = ~sum; /* truncate to 16 bits */ > return (answer); > } > > static int tcp_cksum(register const struct ip *ip, > register const struct tcphdr *tp, > register u_int len) > { > union phu { > struct phdr { > u_int32_t src; > u_int32_t dst; > u_char mbz; > u_char proto; > u_int16_t len; > } ph; > u_int16_t pa[6]; > } phu; > const u_int16_t *sp; > > /* pseudo-header.. */ > phu.ph.len = htons((u_int16_t)len); > phu.ph.mbz = 0; > phu.ph.proto = IPPROTO_TCP; > memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t)); > if ( (ip->ip_hl & 0x0f) == 5) > memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t)); > else > phu.ph.dst = ip_finddst(ip); > > sp = &phu.pa[0]; > return in_cksum((u_short *)tp, len, > sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]); > } > > > void recalculate_tcp_checksum(unsigned char *packet) > { > struct ip *ip_packet = NULL; > struct tcphdr *tcp_packet = NULL; > u_int16_t word16, padd = 0, i, sum = 0, tcp_len; > unsigned char *buff; > if (!packet) return; > > ip_packet = (struct ip *)packet; > tcp_packet = (struct tcphdr *)(packet + (ip_packet->ip_hl << 2)); > tcp_len = ntohs(ip_packet->ip_len) - (ip_packet->ip_hl << 2); > > sum = tcp_cksum(ip_packet,tcp_packet,tcp_len); > tcp_packet->check = sum; //ntohs(sum); > } > > > Use recalculate_tcp_checksum() on your modified payload in this way: > > > void *packet; > struct ip *ip_packet = NULL; > struct tcphdr *tcp_packet = NULL; > unsigned char *tcp_packet_content = NULL; > > ....... > ip_packet = ((struct ip *)packet); > > if (ip_packet->ip_p == IPPROTO_TCP) { > tcp_packet = (struct tcphdr *)(packet + sizeof(struct ip)); > tcp_packet_content = (unsigned char *)(packet + sizeof(struct ip) + sizeof(struct tcphdr)); > tcp_packet_content_size = htons(ip_packet->ip_len) - sizeof(struct ip) - sizeof(struct tcphdr); > ....... > // modify payload... > ....... > // calculate > tcp_packet->check = 0; > recalculate_tcp_checksum(packet); > } > > You also can move some of this code to recalculate_tcp_checksum() and > simply call recalculate_tcp_checksum() without any payload preparations. > > =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= > Kuzin Andrey - kuzinandrey@xxxxxxxxx > =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= > > > > -- Michael Lawson (mshindo) -- Michael Lawson (mshindo) -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html