summaryrefslogtreecommitdiffstats
path: root/ip6t_MAP66.c
diff options
context:
space:
mode:
Diffstat (limited to 'ip6t_MAP66.c')
-rw-r--r--ip6t_MAP66.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/ip6t_MAP66.c b/ip6t_MAP66.c
index 239378e..ffe4afa 100644
--- a/ip6t_MAP66.c
+++ b/ip6t_MAP66.c
@@ -35,17 +35,17 @@ static inline u_int16_t csum16(const u_int16_t *buf, int len)
/* Perform checksum neutral mapping */
static void map16(
struct in6_addr* addr,
- unsigned char mask,
const struct in6_addr* to,
+ int len,
u_int16_t csum)
{
csum = add16(
- *((u_int16_t*)addr + mask),
- add16(csum16((const u_int16_t *)addr, mask), csum)
+ *((u_int16_t*)addr + len),
+ add16(csum16((const u_int16_t *)addr, len), csum)
);
if (csum == 0xffff) csum = 0x0000;
- *((u_int16_t *)addr + mask) = csum;
- memcpy(addr, to, sizeof(u_int16_t) * mask);
+ *((u_int16_t *)addr + len) = csum;
+ memcpy(addr, to, sizeof(u_int16_t) * len);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
@@ -126,27 +126,23 @@ static unsigned int MAP66_tg6(
&hdr->saddr, &hdr->daddr);
#endif
- switch(par->hooknum) {
- case NF_INET_PRE_ROUTING:
- pr_devel("MAP66 PRE, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags));
- if (0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags) ||
- !is_my_ipv6_addr(par->in, &hdr->daddr))
- {
- map16(&hdr->daddr, info->prefixlength, &info->prefix, info->prefixcsum);
- }
- break;
- case NF_INET_POST_ROUTING:
- pr_devel("MAP66 POST, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags));
- map16(&hdr->saddr, info->prefixlength, &info->prefix, info->prefixcsum);
- if (0 == (IP6T_MAP66_OPT_NOCHECK & info->mapflags) &&
- is_my_ipv6_addr(par->out, &hdr->saddr))
- {
- return NF_DROP;
- }
- break;
- default:
- pr_devel("MAP66: unsupported hook: %d\n", par->hooknum);
- break;
+ if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags)) {
+ pr_devel("MAP66 DST, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags));
+ 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_SRC_TO & info->mapflags)) {
+ pr_devel("MAP66 SRC, check=%d\n", 0 != (IP6T_MAP66_OPT_NOCHECK & info->mapflags));
+ 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))
+ {
+ return NF_DROP;
+ }
}
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,28)
@@ -169,8 +165,23 @@ static bool MAP66_tg6_check(
{
const struct ip6t_MAP66_info *info = par->targinfo;
- if (0 >= info->prefixlength || 8 <= info->prefixlength) {
- printk("MAP66: Unsupported prefix length /%d\n", 16 * info->prefixlength);
+
+ if (0 == ((IP6T_MAP66_OPT_DST_TO | IP6T_MAP66_OPT_SRC_TO) & info->mapflags)) {
+ printk("MAP66: No " IP6T_MAP66_DST_TO " nor " IP6T_MAP66_SRC_TO "\n");
+ return false;
+ }
+
+ if (0 != (IP6T_MAP66_OPT_DST_TO & info->mapflags) &&
+ (0 >= info->pfix_dst_len || 8 <= info->pfix_dst_len))
+ {
+ printk("MAP66: Unsupported 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))
+ {
+ printk("MAP66: Unsupported src-to prefix length /%d\n", 16 * info->pfix_src_len);
return false;
}
return true;