I even have tried setsockopt IPV6_CHECKSUM, but it still doesn't work.
So how to solve this problem? Microsoft has api to calculate IPv6 Checksum
or not? I need a ping6 whith flood options in MS windows platform.
> I'm trying to implement a ping6 in MS WindowsXP sp2. Basically, it's a raw
> socket network program. But problem is base on RFC3542 ("Advanced Sockets
> Application Program Interface (API) for IPv6"), if I create a raw ipv6
> socket with protocol set to IPPROTO_ICMPV6, it's the kernel not me to set
> the icmpv6 checksum byte, but in fact it doesn't work.
The kernel is not supposed to set the checksum unless you enable the
IPV6_CHECKSUM option.
> I refer to one of the working ping.c program in MS platform.
> It seems in Microsoft platform, the programmer have to calculate the
> checksum for ICMP. But in ICMPV6 case, the checksum calculated by source
> address too, which cann't obtain before it comes to the IP stack and
> routes to figure out which interface to use.
Yeah, the checksum depends on the source, destination, payload length and
next header. The last 3 fields are known. The first one could be
guessed/forced while binding to a specific local address via bind().
One very portable way to achieve this properly consists of allocating a
standard UDP socket, and connect()ing it to the wanted destination (this is
non-blocking, contrary to TCP connect()). Then you can get a suitable
source address via getsockname() upon the UDP socket, and you can bind the
ICMPv6 raw socket to the same socket address (don't forget to clear the
sin6_port field). That should work fine and in a very portable fashion,
unless the IPv6 routing setup changed in between the connect() and bind()
calls, which is very unlikely.
> I even have tried setsockopt IPV6_CHECKSUM, but it still doesn't work.
How did you check that it doesn't work? Running a packet sniffer on the
emitting host might show incorrect checksums even if they are actually
correct on the wire. Which value did you pass to IPV6_CHECKSUM (it should
be 2 for ICMPv6)?
I'm not saying you did it wrong - I've never actually tried.
--
Rémi Denis-Courmont
http://www.simphalempin.com/home/
> Yeah, the checksum depends on the source, destination, payload length and
> next header. The last 3 fields are known. The first one could be
> guessed/forced while binding to a specific local address via bind().
If you don't intend to received any packet that does not come from the host
you're pinging, you can simply connect() the ICMPv6 socket first, and then
call getsockname() on it to find out your source IPv6 address. That's
cleaner and more straight-forward than the UDP thing I suggested earlier.
> Le Mardi 25 Avril 2006 06:06, IPv6 and Windows APIs a écrit :
>
> > I'm trying to implement a ping6 in MS WindowsXP sp2. Basically, it's a raw
> > socket network program. But problem is base on RFC3542 ("Advanced Sockets
> > Application Program Interface (API) for IPv6"), if I create a raw ipv6
> > socket with protocol set to IPPROTO_ICMPV6, it's the kernel not me to set
> > the icmpv6 checksum byte, but in fact it doesn't work.
>
> The kernel is not supposed to set the checksum unless you enable the
> IPV6_CHECKSUM option.
No, in section 3.1 of RFC3542, it says
" The kernel will calculate and insert the ICMPv6 checksum for ICMPv6
raw sockets, since this checksum is mandatory."
Actually I have already tried that in Linux and NetBSD, it works fine and
also I found ICMPv6 checksum addition codes in Linux kernel.
>
> > I refer to one of the working ping.c program in MS platform.
> > It seems in Microsoft platform, the programmer have to calculate the
> > checksum for ICMP. But in ICMPV6 case, the checksum calculated by source
> > address too, which cann't obtain before it comes to the IP stack and
> > routes to figure out which interface to use.
>
> Yeah, the checksum depends on the source, destination, payload length and
> next header. The last 3 fields are known. The first one could be
> guessed/forced while binding to a specific local address via bind().
I don't want to do any modification to the ping6 command line. I want to get
that source address automatically.
>
> One very portable way to achieve this properly consists of allocating a
> standard UDP socket, and connect()ing it to the wanted destination (this is
> non-blocking, contrary to TCP connect()). Then you can get a suitable
> source address via getsockname() upon the UDP socket, and you can bind the
> ICMPv6 raw socket to the same socket address (don't forget to clear the
> sin6_port field). That should work fine and in a very portable fashion,
> unless the IPv6 routing setup changed in between the connect() and bind()
> calls, which is very unlikely.
>
> > I even have tried setsockopt IPV6_CHECKSUM, but it still doesn't work.
>
> How did you check that it doesn't work? Running a packet sniffer on the
> emitting host might show incorrect checksums even if they are actually
> correct on the wire. Which value did you pass to IPV6_CHECKSUM (it should
> be 2 for ICMPv6)?
int offset = 2;
if (setsockopt(s, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) <
0) {
perror("ping6, checksum");
}
the output is
"ping6, checksum: Protocol not available"
It seems like IPPROTO_IPV6 setsockopt is not supported.
"IPv6 and Windows APIs" wrote: