summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.dbk4
-rw-r--r--ip6t_MAP66.c39
-rw-r--r--ip6t_MAP66.h5
-rw-r--r--libip6t_MAP66.c46
4 files changed, 50 insertions, 44 deletions
diff --git a/README.dbk b/README.dbk
index a0f122b..2437a31 100644
--- a/README.dbk
+++ b/README.dbk
@@ -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 }
};