diff options
Diffstat (limited to 'ip6t_NPTV6_common.h')
-rw-r--r-- | ip6t_NPTV6_common.h | 38 |
1 files changed, 21 insertions, 17 deletions
diff --git a/ip6t_NPTV6_common.h b/ip6t_NPTV6_common.h index 86b297c..9b3aa6f 100644 --- a/ip6t_NPTV6_common.h +++ b/ip6t_NPTV6_common.h @@ -44,8 +44,26 @@ static inline u_int16_t add16(u_int16_t a, u_int16_t b) static bool translate_address(struct in6_addr *addr, const struct in6_addr *prefix, u_int16_t plen) { u_int16_t csum = 0; int o = plen / 16, b = plen % 16; + int fix_word; int i; + /* Fix checksum like specified in RFC 6296 */ + if (plen <= 48) { + fix_word = 3; + } + else { + for (fix_word = (plen+15)/16; fix_word < 7; fix_word++) { + if (addr->s6_addr16[fix_word] != 0xffff) + break; + } + } + + if (addr->s6_addr16[fix_word] == 0xffff) { + /* Fail before the address is translated so the ICMP error can be sent */ + return false; + } + + for (i = 0; i < o; i++) { csum = add16(csum, addr->s6_addr16[i]); csum = add16(csum, ~prefix->s6_addr16[i]); @@ -62,24 +80,10 @@ static bool translate_address(struct in6_addr *addr, const struct in6_addr *pref addr->s6_addr16[o] |= (prefix->s6_addr16[o] & bmask); } - /* Fix checksum like specified in RFC 6296 */ - if (plen <= 48) { - i = 3; - } - else { - for (i = (plen+15)/16; i < 7; i++) { - if (addr->s6_addr16[i] != 0xffff) - break; - } - } - - if (addr->s6_addr16[i] == 0xffff) { - return false; - } - addr->s6_addr16[i] = add16(addr->s6_addr16[i], csum); - if (addr->s6_addr16[i] == 0xffff) { - addr->s6_addr16[i] = 0; + addr->s6_addr16[fix_word] = add16(addr->s6_addr16[fix_word], csum); + if (addr->s6_addr16[fix_word] == 0xffff) { + addr->s6_addr16[fix_word] = 0; } return true; |