summaryrefslogtreecommitdiffstats
path: root/ip6t_NPTV6_common.h
diff options
context:
space:
mode:
Diffstat (limited to 'ip6t_NPTV6_common.h')
-rw-r--r--ip6t_NPTV6_common.h38
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;