summaryrefslogtreecommitdiffstats
path: root/ip6t_MAP66.c
diff options
context:
space:
mode:
Diffstat (limited to 'ip6t_MAP66.c')
-rw-r--r--ip6t_MAP66.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/ip6t_MAP66.c b/ip6t_MAP66.c
index ca0e559..b00c818 100644
--- a/ip6t_MAP66.c
+++ b/ip6t_MAP66.c
@@ -126,10 +126,22 @@ static unsigned int MAP66_tg6(
&hdr->saddr, &hdr->daddr);
#endif
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
+ if (skb_cloned(skb) && !skb->sk) {
+ struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC);
+ if (!nskb) {
+ pr_devel("MAP66: cannot copy, dropped\n");
+ return NF_DROP;
+ }
+ kfree_skb(skb);
+ skb = nskb;
+ }
+#else
if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) {
pr_devel("MAP66: unwriteable, dropped\n");
return NF_DROP;
}
+#endif
hdr = ipv6_hdr(skb);
if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags)) {
@@ -148,7 +160,12 @@ static unsigned int MAP66_tg6(
if (0 != (IP6T_MAP66_OPT_SRC_TO & info->mapflags)) {
pr_devel("MAP66 SRC, nocheck=%d, ip_summed=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags), skb->ip_summed);
- map16(&hdr->saddr, &info->pfix_src_to, info->pfix_src_len, info->pfix_src_csum);
+ if (0 != (IP6T_MAP66_OPT_UNBALANCED & info->mapflags)) {
+ memcpy(&hdr->saddr, &info->pfix_src_to, sizeof(u_int16_t) * info->pfix_src_len);
+ }
+ else {
+ map16(&hdr->saddr, &info->pfix_src_to, info->pfix_src_len, info->pfix_src_csum);
+ }
if (0 == (IP6T_MAP66_OPT_NOCHECK & info->mapflags) &&
is_my_ipv6_addr(par->out, &hdr->saddr))
{