Hi,
I was very suprised when I found out that it is possible to create a
socket for AF_INET, build a sockaddr struct for a v6 address (take
getaddrinfo for example) and give all that to bind.
<code>
...
n = getaddrinfo("2::2", "4321", &hints, &res);
socketfd = socket(PF_INET, SOCK_STREAM, 6);
if(bind(socketfd, res->ai_addr, res->ai_addrlen)) {
exit(1);
}
....
</code>
What I expected was that the kernel returns with an error but what I got
was an IPv4 socket listening on 0.0.0.0:4321. The problem is that the
sockaddr_in and sockaddr_in6 structures first differ in sin_addr(v4) and
flowinfo (v6). As flowinfo is exactly 32bit and set to zero the kernel
doesn't care and takes the v6 struct as a v4 struct. I think bind should
exactly check if the length of the given parameter is correct. This little
patch would go for a more precise check:
/usr/src/linux/net/ipv4/af_inet.c
486c486
< if (addr_len != sizeof(struct sockaddr_in))
---
> if (addr_len < sizeof(struct sockaddr_in))
I don't know why there is a '<' comparison? Maybe someone of you can give me
a hint.
Thanks
Mischa
--
"Mit seinem Geld begnuegt sich keiner, mit seinem Verstand jeder."
(Quelle: Unbekannt)
|