diff options
-rw-r--r-- | README.dbk | 4 | ||||
-rw-r--r-- | ip6t_MAP66.c | 39 | ||||
-rw-r--r-- | ip6t_MAP66.h | 5 | ||||
-rw-r--r-- | libip6t_MAP66.c | 46 |
4 files changed, 50 insertions, 44 deletions
@@ -308,8 +308,8 @@ ip6tables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp- OLSR-based mesh network, any interface uses an fdca:ffee:babe::/64 prefix. The following internal mapping is configured for this: </para> - <programlisting>ip6tables -t mangle -I PREROUTING -i br0 -s 2002:c0a8:4141::/64 -j MAP66 --src-to fdca:ffee:babe::/64 -ip6tables -t mangle -I POSTROUTING -o br0 -d fdca:ffee:babe::/64 -j MAP66 --dst-to 2002:c0a8:4141::/64</programlisting> + <programlisting>ip6tables -t mangle -I PREROUTING -i br0 -s 2002:c0a8:4141::/64 -j MAP66 --src-to fdca:ffee:babe::/64 --newcsum +ip6tables -t mangle -I POSTROUTING -o br0 -d fdca:ffee:babe::/64 -j MAP66 --dst-to 2002:c0a8:4141::/64 -newcsum</programlisting> </section> </section> diff --git a/ip6t_MAP66.c b/ip6t_MAP66.c index 6446927..ca0e559 100644 --- a/ip6t_MAP66.c +++ b/ip6t_MAP66.c @@ -126,17 +126,28 @@ static unsigned int MAP66_tg6( &hdr->saddr, &hdr->daddr); #endif + if (!skb_make_writable(skb, sizeof(struct ipv6hdr))) { + pr_devel("MAP66: unwriteable, dropped\n"); + return NF_DROP; + } + hdr = ipv6_hdr(skb); + if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags)) { - pr_devel("MAP66 DST, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags)); + pr_devel("MAP66 DST, nocheck=%d, ip_summed=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags), skb->ip_summed); if (0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags) || !is_my_ipv6_addr(par->in, &hdr->daddr)) { - map16(&hdr->daddr, &info->pfix_dst_to, info->pfix_dst_len, info->pfix_dst_csum); + if (0 != (IP6T_MAP66_OPT_UNBALANCED & info->mapflags)) { + memcpy(&hdr->daddr, &info->pfix_dst_to, sizeof(u_int16_t) * info->pfix_dst_len); + } + else { + map16(&hdr->daddr, &info->pfix_dst_to, info->pfix_dst_len, info->pfix_dst_csum); + } } } if (0 != (IP6T_MAP66_OPT_SRC_TO & info->mapflags)) { - pr_devel("MAP66 SRC, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & 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_NOCHECK & info->mapflags) && is_my_ipv6_addr(par->out, &hdr->saddr)) @@ -170,17 +181,27 @@ static bool MAP66_tg6_check( return false; } - if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags) && - (0 >= info->pfix_dst_len || 8 <= info->pfix_dst_len)) + if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags) && (0 >= info->pfix_dst_len || + 0 != (IP6T_MAP66_OPT_UNBALANCED & info->mapflags) ? 8 : 7 < info->pfix_dst_len)) { - printk("MAP66: Unsupported --" IP6T_MAP66_DST_TO " prefix length /%d\n", 16 * info->pfix_dst_len); + if (8 == info->pfix_dst_len) { + printk("MAP66: --" IP6T_MAP66_DST_TO " prefix length /%d only possible with --unbalanced\n", 16 * info->pfix_dst_len); + } + else { + printk("MAP66: Unsupported --" IP6T_MAP66_DST_TO " prefix length /%d\n", 16 * info->pfix_dst_len); + } return false; } - if (0 != (IP6T_MAP66_OPT_SRC_TO & info->mapflags) && - (0 >= info->pfix_src_len || 8 <= info->pfix_src_len)) + if (0 != (IP6T_MAP66_OPT_SRC_TO & info->mapflags) && (0 >= info->pfix_src_len || + 0 != (IP6T_MAP66_OPT_UNBALANCED & info->mapflags) ? 8 : 7 < info->pfix_src_len)) { - printk("MAP66: Unsupported --" IP6T_MAP66_SRC_TO " prefix length /%d\n", 16 * info->pfix_src_len); + if (8 == info->pfix_src_len) { + printk("MAP66: --" IP6T_MAP66_SRC_TO " prefix length /%d only possible with --unbalanced\n", 16 * info->pfix_src_len); + } + else { + printk("MAP66: Unsupported --" IP6T_MAP66_SRC_TO " prefix length /%d\n", 16 * info->pfix_src_len); + } return false; } return true; diff --git a/ip6t_MAP66.h b/ip6t_MAP66.h index c3e124f..482ac8c 100644 --- a/ip6t_MAP66.h +++ b/ip6t_MAP66.h @@ -12,8 +12,8 @@ #define IP6T_MAP66_OPT_DST_TO 0x01 #define IP6T_MAP66_OPT_SRC_TO 0x02 -#define IP6T_MAP66_OPT_OFFSET 0x04 -#define IP6T_MAP66_OPT_NOCHECK 0x08 +#define IP6T_MAP66_OPT_NOCHECK 0x04 +#define IP6T_MAP66_OPT_UNBALANCED 0x08 struct ip6t_MAP66_info { struct in6_addr pfix_dst_to; /* The prefix to map destination addrs to */ @@ -22,7 +22,6 @@ struct ip6t_MAP66_info { struct in6_addr pfix_src_to; /* The prefix to map source addrs from */ u_int16_t pfix_src_len; /* Source addrs prefix length DIV 16 */ u_int16_t pfix_src_csum; /* Pre-calculated csum for source addrs */ - u_int16_t mapoffset; /* Offset in addrs for balanced csum change */ u_int16_t mapflags; /* Some flags */ }; diff --git a/libip6t_MAP66.c b/libip6t_MAP66.c index 9fab6a6..c710a69 100644 --- a/libip6t_MAP66.c +++ b/libip6t_MAP66.c @@ -61,8 +61,8 @@ static void MAP66_help(void) "MAP66 target options\n" " --" IP6T_MAP66_DST_TO " ipv6addr/prefixlength (Prefix to map IPv6 destination address to)\n" " --" IP6T_MAP66_SRC_TO " ipv6addr/prefixlength (Prefix to map IPv6 source address to)\n" -" --offset number (Use another part of addrs to balance csum)\n" " --nocheck (Disables the do-not-map-to-my-addr check)\n" +" --unbalanced (Don't balance address for csum neutrality)\n" "\n" "Note: you need two ip6tables rules to map an internal network\n" "using ULAs to/from external network with official IPv6 address.\n" @@ -141,36 +141,14 @@ static int MAP66_parse( xtables_error(PARAMETER_PROBLEM, "Invalid IPv6 address in --" IP6T_MAP66_SRC_TO ": \"%s\"", optarg); } i = atoi(p + 1); - if (0 > i || 128 <= i || 0 != i % 16) { - xtables_error(PARAMETER_PROBLEM, "Invalid prefix length in --" IP6T_MAP66_SRC_TO ": \"%s\" (use /112, /96 .. /0)", p + 1); + if (0 >= i || 128 < i || 0 != i % 16) { + xtables_error(PARAMETER_PROBLEM, "Invalid prefix length in --" IP6T_MAP66_SRC_TO ": \"%s\" (use /128, /112, /96 .. /16)", p + 1); } info->pfix_src_len = i / 16; info->pfix_src_csum = ~csum16((const u_int16_t *)&info->pfix_src_to, info->pfix_src_len); return 1; break; case '3': - if (!optarg) { - xtables_error(PARAMETER_PROBLEM, "--offset: You must specify a value"); - } - if (xtables_check_inverse(optarg, &invert, NULL, 0 -#if IPTABLES_VERSION_CODE >= IPTABLES_VERSION_CMP(1,4,6) - ,argv -#endif - )) { - xtables_error(PARAMETER_PROBLEM, "Unexpected `!' after --offset"); - } - if (0 != (IP6T_MAP66_OPT_OFFSET & *flags)) { - xtables_error(PARAMETER_PROBLEM, "Multiple --offset not supported"); - } - *flags |= IP6T_MAP66_OPT_OFFSET; - i = atoi(p + 1); - if (0 > i || 14 <= i) { - xtables_error(PARAMETER_PROBLEM, "Invalid value in --offset: \"%s\" (use 0-14)", p + 1); - } - info->mapoffset = i; - return 0; - break; - case '4': if (0 != (IP6T_MAP66_OPT_NOCHECK & *flags)) { xtables_error(PARAMETER_PROBLEM, "Multiple --nocheck not supported"); } @@ -178,6 +156,14 @@ static int MAP66_parse( *flags |= IP6T_MAP66_OPT_NOCHECK; return 1; break; + case '4': + if (0 != (IP6T_MAP66_OPT_UNBALANCED & *flags)) { + xtables_error(PARAMETER_PROBLEM, "Multiple --unbalanced not supported"); + } + info->mapflags |= IP6T_MAP66_OPT_UNBALANCED; + *flags |= IP6T_MAP66_OPT_UNBALANCED; + return 1; + break; } return 0; } @@ -201,19 +187,19 @@ static void MAP66_save( if (0 != (IP6T_MAP66_OPT_SRC_TO & info->mapflags)) { printf("--" IP6T_MAP66_SRC_TO " %s/%d ", inet_ntop(AF_INET6, &info->pfix_src_to, s, sizeof(s)), 16 * info->pfix_src_len); } - if (0 != info->mapoffset)) { - printf("--offset %d ", info->mapoffset); - } if (0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags)) { printf("--nocheck "); } + if (0 != (IP6T_MAP66_OPT_UNBALANCED & info->mapflags)) { + printf("--unbalanced "); + } } static struct option MAP66_opts[] = { { .name = IP6T_MAP66_DST_TO, .has_arg = 1, .flag = NULL, .val = '1' }, { .name = IP6T_MAP66_SRC_TO, .has_arg = 1, .flag = NULL, .val = '2' }, - { .name = "offset", .has_arg = 1, .flag = NULL, .val = '3' }, - { .name = "nocheck", .has_arg = 0, .flag = NULL, .val = '4' }, + { .name = "nocheck", .has_arg = 0, .flag = NULL, .val = '3' }, + { .name = "unbalanced", .has_arg = 0, .flag = NULL, .val = '4' }, { .name = NULL } }; |