
Pascal.Andre at hp
Jun 5, 2009, 2:34 AM
Post #1 of 1
(512 views)
Permalink
|
|
Checksum not computed in ICMPv6 neighbor advertisement
|
|
Hi, On an Active/Standby platform (using Linux-HA 2.1.4 RHEL5, in my case), when a fail-over/switch-over is initiated and standby machine takes over the virtual IP (IPv6), IPv6addr broadcasts an ICMPv6 neighbor advertisement message. Unfortunately, this ICMPv6 message has its checksum field set to 0 (i.e. not computed). The message is thus discarded by recipients. Maybe this computation should be done by libnet itself. Unfortunately, without much time to investigate libnet, I've added code in resources/OCF/IPv6addr.c in order to compute the checksum and provide the result to libnet (as a parameter). Regards, Pascal ANDRE --- IPv6addr.c.old 2009-04-30 10:15:16.000000000 +0200 +++ IPv6addr.c 2009-04-30 11:45:43.000000000 +0200 @@ -381,6 +381,58 @@ return OCF_NOT_RUNNING; } +/* compute ICMPv6 checksum */ +static uint32_t +cksum_sum(uint16_t *addr, int len, int ntoh) +{ + uint16_t * w = addr; + uint16_t ret = 0; + uint32_t sum = 0; + + while (len > 1) { + ret = *w++; + if (ntoh) ret = ntohs(ret); + sum += ret; + len -= 2; + } + + if (len == 1) { + *(unsigned char *) (&ret) = *(unsigned char *) w; + sum += ret; + } + + return sum; +} + +static uint16_t +icmpv6_cksum(struct in6_addr* src_ip, struct libnet_in6_addr* dst_ip, char* payload, int payload_len) +{ + uint32_t sum = 0; + uint16_t val = 0; + + /* IPv6 pseudo header */ + sum += cksum_sum( src_ip->s6_addr16, 16, 1 ); + sum += cksum_sum( (uint16_t *)dst_ip, 16, 1 ); + val = payload_len + (2 * sizeof(uint32_t)); + sum += cksum_sum( &val, 2, 0 ); + val = 58; + sum += cksum_sum( &val, 2, 0 ); + + /* ICMPv6 packet */ + val = 0x8800; + sum += cksum_sum( &val, 2, 0 ); + val = 0x2000; + sum += cksum_sum( &val, 2, 0 ); + sum += cksum_sum( (uint16_t *)payload, payload_len, 1 ); + + /* perform 16-bit one's complement of sum */ + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + val = ~sum; + + return val; +} + /* Send an unsolicited advertisement packet * Please refer to rfc2461 */ @@ -416,7 +468,7 @@ libnet_seed_prand(l); /* 0x2000: RSO */ - libnet_build_icmpv4_echo(136,0,0,0x2000,0,(u_int8_t *)payload + libnet_build_icmpv4_echo(136,0,icmpv6_cksum(src_ip,&dst_ip,payload,sizeof(payload)),0x2000,0,(u_int8_t *)payload ,sizeof(payload), l, LIBNET_PTAG_INITIALIZER); libnet_build_ipv6(0,0,LIBNET_ICMPV6_H + sizeof(payload),IPPROTO_ICMP6, 255,*(struct libnet_in6_addr*)src_ip,
|