diff -uarNbB 2.6.25/xt_TCPOPTSTRIP.c 2.6.18/xt_TCPOPTSTRIP.c --- 2.6.25/xt_TCPOPTSTRIP.c 2008-11-02 17:11:02.000000000 +0100 +++ 2.6.18/xt_TCPOPTSTRIP.c 2008-11-02 17:11:57.000000000 +0100 @@ -29,8 +29,16 @@ return opt[offset+1]; } +static u_int16_t +cheat_check(u_int32_t oldvalinv, u_int32_t newval, u_int16_t oldcheck) +{ + u_int32_t diffs[] = { oldvalinv, newval }; + return csum_fold(csum_partial((char *)diffs, sizeof(diffs), + oldcheck^0xFFFF)); +} + static unsigned int -tcpoptstrip_mangle_packet(struct sk_buff *skb, +tcpoptstrip_mangle_packet(struct sk_buff **pskb, const struct xt_tcpoptstrip_target_info *info, unsigned int tcphoff, unsigned int minlen) { @@ -39,20 +47,20 @@ u_int16_t n, o; u_int8_t *opt; - if (!skb_make_writable(skb, skb->len)) + if (!skb_make_writable(pskb, (*pskb)->len)) return NF_DROP; - tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); + tcph = (struct tcphdr *)(skb_network_header(*pskb) + tcphoff); opt = (u_int8_t *)tcph; /* * Walk through all TCP options - if we find some option to remove, * set all octets to %TCPOPT_NOP and adjust checksum. */ - for (i = sizeof(struct tcphdr); i < tcp_hdrlen(skb); i += optl) { + for (i = sizeof(struct tcphdr); i < tcp_hdrlen(*pskb); i += optl) { optl = optlen(opt, i); - if (i + optl > tcp_hdrlen(skb)) + if (i + optl > tcp_hdrlen(*pskb)) break; if (!tcpoptstrip_test_bit(info->strip_bmap, opt[i])) @@ -65,8 +73,9 @@ o <<= 8; n <<= 8; } - inet_proto_csum_replace2(&tcph->check, skb, htons(o), - htons(n), 0); + tcph->check = cheat_check(htons(o)^0xFFFF, + htons(n), + tcph->check); } memset(opt + i, TCPOPT_NOP, optl); } @@ -75,36 +84,35 @@ } static unsigned int -tcpoptstrip_tg4(struct sk_buff *skb, const struct net_device *in, +tcpoptstrip_tg4(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) + const struct xt_target *target, const void *targinfo, void *userinfo) { - return tcpoptstrip_mangle_packet(skb, targinfo, ip_hdrlen(skb), + return tcpoptstrip_mangle_packet(pskb, targinfo, ip_hdrlen(*pskb), sizeof(struct iphdr) + sizeof(struct tcphdr)); } #if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) static unsigned int -tcpoptstrip_tg6(struct sk_buff *skb, const struct net_device *in, +tcpoptstrip_tg6(struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, unsigned int hooknum, - const struct xt_target *target, const void *targinfo) + const struct xt_target *target, const void *targinfo, void *userinfo) { - struct ipv6hdr *ipv6h = ipv6_hdr(skb); + struct ipv6hdr *ipv6h = ipv6_hdr(*pskb); unsigned int tcphoff; u_int8_t nexthdr; nexthdr = ipv6h->nexthdr; - tcphoff = ipv6_skip_exthdr(skb, sizeof(*ipv6h), &nexthdr); + tcphoff = ipv6_skip_exthdr(*pskb, sizeof(*ipv6h), &nexthdr); if (tcphoff < 0) return NF_DROP; - return tcpoptstrip_mangle_packet(skb, targinfo, tcphoff, + return tcpoptstrip_mangle_packet(pskb, targinfo, tcphoff, sizeof(*ipv6h) + sizeof(struct tcphdr)); } #endif -static struct xt_target tcpoptstrip_tg_reg[] __read_mostly = { - { +static struct xt_target tcpoptstrip_tg4_reg = { .name = "TCPOPTSTRIP", .family = AF_INET, .table = "mangle", @@ -112,9 +120,9 @@ .target = tcpoptstrip_tg4, .targetsize = sizeof(struct xt_tcpoptstrip_target_info), .me = THIS_MODULE, - }, + }; #if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) - { +static struct xt_target tcpoptstrip_tg6_reg = { .name = "TCPOPTSTRIP", .family = AF_INET6, .table = "mangle", @@ -122,20 +130,29 @@ .target = tcpoptstrip_tg6, .targetsize = sizeof(struct xt_tcpoptstrip_target_info), .me = THIS_MODULE, - }, + }; #endif -}; static int __init tcpoptstrip_tg_init(void) { - return xt_register_targets(tcpoptstrip_tg_reg, - ARRAY_SIZE(tcpoptstrip_tg_reg)); + int ret; + ret = xt_register_target(&tcpoptstrip_tg4_reg); +#if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) + if (ret) { + xt_unregister_target(&tcpoptstrip_tg4_reg); + return ret; + } + ret = xt_register_target(&tcpoptstrip_tg6_reg); +#endif + return ret; } static void __exit tcpoptstrip_tg_exit(void) { - xt_unregister_targets(tcpoptstrip_tg_reg, - ARRAY_SIZE(tcpoptstrip_tg_reg)); + xt_unregister_target(&tcpoptstrip_tg4_reg); +#if defined(CONFIG_IP6_NF_MANGLE) || defined(CONFIG_IP6_NF_MANGLE_MODULE) + xt_unregister_target(&tcpoptstrip_tg6_reg); +#endif } module_init(tcpoptstrip_tg_init);