diff --git a/extensions/xt_TEE.c b/extensions/xt_TEE.c index 9ef79a8..fce7adf 100644 --- a/extensions/xt_TEE.c +++ b/extensions/xt_TEE.c @@ -1,7 +1,7 @@ /* * "TEE" target extension for Xtables * Copyright © Sebastian Claßen , 2007 - * Jan Engelhardt , 2007 + * Jan Engelhardt , 2007 - 2008 * * based on ipt_ROUTE.c from Cédric de Launois * @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -209,6 +210,73 @@ tee_tg4(struct sk_buff **pskb, const struct xt_target_param *par) return XT_CONTINUE; } +static bool +tee_tg_route6(struct sk_buff *skb, const struct xt_tee_tginfo *info) +{ + struct dst_entry *dst; + struct flowi fl; + + memset(&fl, 0, sizeof(fl)); + fl.nl_u.ip6_u.daddr = info->gw.in6; + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 25) + dst = ip6_route_output(NULL, &fl); +#else + dst = ip6_route_output(dev_net(skb->dev), NULL, &fl); +#endif + if (dst == NULL) { + if (net_ratelimit()) + printk(KERN_ERR "ip6_route_output failed for tee\n"); + return false; + } + + dst_release(skb->dst); + skb->dst = dst; + skb->dev = skb->dst->dev; + skb->protocol = htons(ETH_P_IPV6); + return true; +} + +static void tee_tg_send6(struct sk_buff *skb) +{ + struct dst_entry *dst = skb->dst; + + if (dst->hh != NULL) + neigh_hh_output(dst->hh, skb); + else if (dst->neighbour != NULL) + dst->neighbour->output(skb); + else + kfree_skb(skb); + +} + +static unsigned int +tee_tg6(struct sk_buff **pskb, const struct xt_target_param *par) +{ + const struct xt_tee_tginfo *info = par->targinfo; + struct sk_buff *skb = *pskb; + + /* Try silence. */ +#ifdef WITH_CONNTRACK + if (skb->nfct == &tee_track.ct_general) + return NF_DROP; +#endif + + if ((skb = skb_copy(skb, GFP_ATOMIC)) == NULL) + return XT_CONTINUE; + +#ifdef WITH_CONNTRACK + nf_conntrack_put(skb->nfct); + skb->nfct = &tee_track.ct_general; + skb->nfctinfo = IP_CT_NEW; + nf_conntrack_get(skb->nfct); +#endif + if (tee_tg_route6(skb, info)) + tee_tg_send6(skb); + + return XT_CONTINUE; +} + static bool tee_tg_check(const struct xt_tgchk_param *par) { const struct xt_tee_tginfo *info = par->targinfo; @@ -218,15 +286,27 @@ static bool tee_tg_check(const struct xt_tgchk_param *par) sizeof(tee_zero_address)) != 0; } -static struct xt_target tee_tg_reg __read_mostly = { - .name = "TEE", - .revision = 0, - .family = NFPROTO_IPV4, - .table = "mangle", - .target = tee_tg4, - .targetsize = sizeof(struct xt_tee_tginfo), - .checkentry = tee_tg_check, - .me = THIS_MODULE, +static struct xt_target tee_tg_reg[] __read_mostly = { + { + .name = "TEE", + .revision = 0, + .family = NFPROTO_IPV4, + .table = "mangle", + .target = tee_tg4, + .targetsize = sizeof(struct xt_tee_tginfo), + .checkentry = tee_tg_check, + .me = THIS_MODULE, + }, + { + .name = "TEE", + .revision = 0, + .family = NFPROTO_IPV6, + .table = "mangle", + .target = tee_tg6, + .targetsize = sizeof(struct xt_tee_tginfo), + .checkentry = tee_tg_check, + .me = THIS_MODULE, + }, }; static int __init tee_tg_init(void) @@ -245,12 +325,12 @@ static int __init tee_tg_init(void) tee_track.status |= IPS_NAT_DONE_MASK; #endif - return xt_register_target(&tee_tg_reg); + return xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); } static void __exit tee_tg_exit(void) { - xt_unregister_target(&tee_tg_reg); + xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); /* [SC]: shoud not we cleanup tee_track here? */ } @@ -261,3 +341,4 @@ MODULE_AUTHOR("Jan Engelhardt "); MODULE_DESCRIPTION("Xtables: Reroute packet copy"); MODULE_LICENSE("GPL"); MODULE_ALIAS("ipt_TEE"); +MODULE_ALIAS("ip6t_TEE");