IPv6 bug in 2.3.4??
Hey there, I've noticed a potential bug and wanted to see if anyone else can replicate it, or has also seen it. When creating a socket with getaddrinfo, with the address family set to AF_UNSPEC and the host set to localhost, the socket binds to IPv4 instead of IPv6. When using the FQD of the machine it binds to IPv6. I've tested the same code on two different machines, and the one running python 2.3.3 works as it should, but the python 2.3.4 doesn't. Anyone seen this? Can you replicate the error? Any help would be appreciated. Oh yeah, I'm running on FC2 on the 2.3.4 machine and redhat 8 on the 2.3.3 machine. Cheers, David.
David G Mills wrote:
I've noticed a potential bug and wanted to see if anyone else can replicate it, or has also seen it. When creating a socket with getaddrinfo, with the address family set to AF_UNSPEC and the host set to localhost, the socket binds to IPv4 instead of IPv6. When using the FQD of the machine it binds to IPv6. I've tested the same code on two different machines, and the one running python 2.3.3 works as it should, but the python 2.3.4 doesn't.
Can you show the code fragment that you use? socket.getaddrinfo does never ever create sockets; only socket.socket does. So you apparently somehow use the results of getaddrinfo to create the socket. As getaddrinfo may return multiple results, you somehow need to select one of the results to create the socket, but you don't explain which result you use. A code snippet would answer the question.
Anyone seen this? Can you replicate the error? Any help would be appreciated. Oh yeah, I'm running on FC2 on the 2.3.4 machine and redhat 8 on the 2.3.3 machine.
I can imagine a code fragment where this happens, but I hardly can see an error here. Regards, Martin
Welcome to the fun land of IPv6: Dealing with buggy and changing implementations. As far as I am aware, Python's socket module is basically just a wrapper around the operating system. The operating system behaviour changed, not Python's. On Wed, 2004-10-27 at 09:53, David G Mills wrote:
I've noticed a potential bug and wanted to see if anyone else can replicate it, or has also seen it. When creating a socket with getaddrinfo, with the address family set to AF_UNSPEC and the host set to localhost, the socket binds to IPv4 instead of IPv6. When using the FQD of the machine it binds to IPv6. I've tested the same code on two different machines, and the one running python 2.3.3 works as it should, but the python 2.3.4 doesn't.
What do you expect getaddrinfo to do? Return the IPv6 address first? That is very much up to the implementation. The man page states:
PF_UNSPEC in ai_family specifies any protocol family (either IPv4 or IPv6, for example)
This would imply that returning either an IPv4 or an IPv6 address would be correct. On my system, the following code returns a list of ipv6 addresses: import socket stuff = socket.getaddrinfo( "evanjones.ca", "http", socket.AF_UNSPEC ) print stuff [(10, 1, 6, '', ('2002:42a0:8738:1::1', 80, 0, 0)), (10, 1, 6, '', ('2001:470:1f01:ffff::151', 80, 0, 0)), (2, 1, 6, '', ('66.160.135.56', 80)) It does return the IPv6 addresses first, but I'm not sure that is intentional, or if it is pure chance. In your case, if you are looking up the name "localhost," it could be that /etc/hosts on one machine does not map "::1" to the name "localhost." Compare the contents of these files on both machines. My new Debian machine has "ip6-localhost" as "::1." If I change it so "::1" is also localhost, Python returns both addresses. The one thing that *is* a Python bug is that it does not include "IN6ADDR_LOOPBACK_INIT" or "in6addr_loopback" as constants in the socket module. Hmm... Maybe I should fix this...
Anyone seen this? Can you replicate the error? Any help would be appreciated. Oh yeah, I'm running on FC2 on the 2.3.4 machine and redhat 8 on the 2.3.3 machine.
These machines have different versions of glibc, which could also explain the behaviour change. In fact, there are very recent bug fixes to glibc. For example, this mailing list thread is a fix on top of glibc-2.3.3. My Debian Unstable machine is only running 2.3.2: http://sources.redhat.com/ml/libc-hacker/2004-09/msg00060.html On my system, /usr/share/doc/libc6/BUGS states:
[ *] Some of the functions which also handled IPv6 are currently broken. IPv6 and IPv4 lookups occasionally happen when not needed. This happens in getaddrinfo() and getnameinfo(). IPv4 handling of these functions is OK though and there are patches available to fix the IPv6 code as well.
So basically, IPv6 is still very much a "work in progress." I suggest not relying on specific system behaviour. Hope this helps, Evan Jones
okay, here's my code: HOST = 'localhost' PORT = 55555 s = None for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE): af, socktype, proto, canonname, sa = res try: s = socket.socket(af, socktype, proto) except socket.error, msg: s = None continue try: s.bind(sa) s.listen(5) except socket.error, msg: s.close() s = None continue break First off I'd like to point out that when host is set to a fully qualified domain name, comp.foo.org for example, the correct behaviour is seen, getaddrinfo returns an IPv4 and IPv6 address, and when the socket is created, it binds to the IPv6 address. Only when localhost is used does it fail to find an IPv6 address. Now there's nothing wrong with the /etc/hosts file, as I tested with the one from the working machine. Also when using AF_INET6 and host=localhost it works fine, which is why I am puzzled. Thanks for the glibc information, I shall investigate down that path and see what I can discover, but if you can think of anything else that might be causing this I'd like to hear it. =) Regards, David. On Wed, 27 Oct 2004, Evan Jones wrote:
Welcome to the fun land of IPv6: Dealing with buggy and changing implementations. As far as I am aware, Python's socket module is basically just a wrapper around the operating system. The operating system behaviour changed, not Python's.
On Wed, 2004-10-27 at 09:53, David G Mills wrote:
I've noticed a potential bug and wanted to see if anyone else can replicate it, or has also seen it. When creating a socket with getaddrinfo, with the address family set to AF_UNSPEC and the host set to localhost, the socket binds to IPv4 instead of IPv6. When using the FQD of the machine it binds to IPv6. I've tested the same code on two different machines, and the one running python 2.3.3 works as it should, but the python 2.3.4 doesn't.
What do you expect getaddrinfo to do? Return the IPv6 address first? That is very much up to the implementation. The man page states:
PF_UNSPEC in ai_family specifies any protocol family (either IPv4 or IPv6, for example)
This would imply that returning either an IPv4 or an IPv6 address would be correct. On my system, the following code returns a list of ipv6 addresses:
import socket stuff = socket.getaddrinfo( "evanjones.ca", "http", socket.AF_UNSPEC ) print stuff
[(10, 1, 6, '', ('2002:42a0:8738:1::1', 80, 0, 0)), (10, 1, 6, '', ('2001:470:1f01:ffff::151', 80, 0, 0)), (2, 1, 6, '', ('66.160.135.56', 80))
It does return the IPv6 addresses first, but I'm not sure that is intentional, or if it is pure chance. In your case, if you are looking up the name "localhost," it could be that /etc/hosts on one machine does not map "::1" to the name "localhost." Compare the contents of these files on both machines. My new Debian machine has "ip6-localhost" as "::1." If I change it so "::1" is also localhost, Python returns both addresses.
The one thing that *is* a Python bug is that it does not include "IN6ADDR_LOOPBACK_INIT" or "in6addr_loopback" as constants in the socket module. Hmm... Maybe I should fix this...
Anyone seen this? Can you replicate the error? Any help would be appreciated. Oh yeah, I'm running on FC2 on the 2.3.4 machine and redhat 8 on the 2.3.3 machine.
These machines have different versions of glibc, which could also explain the behaviour change. In fact, there are very recent bug fixes to glibc. For example, this mailing list thread is a fix on top of glibc-2.3.3. My Debian Unstable machine is only running 2.3.2:
http://sources.redhat.com/ml/libc-hacker/2004-09/msg00060.html
On my system, /usr/share/doc/libc6/BUGS states:
[ *] Some of the functions which also handled IPv6 are currently broken. IPv6 and IPv4 lookups occasionally happen when not needed. This happens in getaddrinfo() and getnameinfo(). IPv4 handling of these functions is OK though and there are patches available to fix the IPv6 code as well.
So basically, IPv6 is still very much a "work in progress." I suggest not relying on specific system behaviour.
Hope this helps,
Evan Jones
As you suggested I investigated glibc bugs and found that when getaddrinfo uses AF_UNSPEC and looks up an address, it first looks in /etc/hosts and if it finds an IPv4 address it will just return that and never return the IPv6 address. The stop gap fix, before patching glbic, is to just remove any IPv4 entries in /etc/hosts forcing it to do a DNS lookup. Thanks for your help in this matter. Regards, David. On Wed, 27 Oct 2004, Evan Jones wrote:
Welcome to the fun land of IPv6: Dealing with buggy and changing implementations. As far as I am aware, Python's socket module is basically just a wrapper around the operating system. The operating system behaviour changed, not Python's.
On Wed, 2004-10-27 at 09:53, David G Mills wrote:
I've noticed a potential bug and wanted to see if anyone else can replicate it, or has also seen it. When creating a socket with getaddrinfo, with the address family set to AF_UNSPEC and the host set to localhost, the socket binds to IPv4 instead of IPv6. When using the FQD of the machine it binds to IPv6. I've tested the same code on two different machines, and the one running python 2.3.3 works as it should, but the python 2.3.4 doesn't.
What do you expect getaddrinfo to do? Return the IPv6 address first? That is very much up to the implementation. The man page states:
PF_UNSPEC in ai_family specifies any protocol family (either IPv4 or IPv6, for example)
This would imply that returning either an IPv4 or an IPv6 address would be correct. On my system, the following code returns a list of ipv6 addresses:
import socket stuff = socket.getaddrinfo( "evanjones.ca", "http", socket.AF_UNSPEC ) print stuff
[(10, 1, 6, '', ('2002:42a0:8738:1::1', 80, 0, 0)), (10, 1, 6, '', ('2001:470:1f01:ffff::151', 80, 0, 0)), (2, 1, 6, '', ('66.160.135.56', 80))
It does return the IPv6 addresses first, but I'm not sure that is intentional, or if it is pure chance. In your case, if you are looking up the name "localhost," it could be that /etc/hosts on one machine does not map "::1" to the name "localhost." Compare the contents of these files on both machines. My new Debian machine has "ip6-localhost" as "::1." If I change it so "::1" is also localhost, Python returns both addresses.
The one thing that *is* a Python bug is that it does not include "IN6ADDR_LOOPBACK_INIT" or "in6addr_loopback" as constants in the socket module. Hmm... Maybe I should fix this...
Anyone seen this? Can you replicate the error? Any help would be appreciated. Oh yeah, I'm running on FC2 on the 2.3.4 machine and redhat 8 on the 2.3.3 machine.
These machines have different versions of glibc, which could also explain the behaviour change. In fact, there are very recent bug fixes to glibc. For example, this mailing list thread is a fix on top of glibc-2.3.3. My Debian Unstable machine is only running 2.3.2:
http://sources.redhat.com/ml/libc-hacker/2004-09/msg00060.html
On my system, /usr/share/doc/libc6/BUGS states:
[ *] Some of the functions which also handled IPv6 are currently broken. IPv6 and IPv4 lookups occasionally happen when not needed. This happens in getaddrinfo() and getnameinfo(). IPv4 handling of these functions is OK though and there are patches available to fix the IPv6 code as well.
So basically, IPv6 is still very much a "work in progress." I suggest not relying on specific system behaviour.
Hope this helps,
Evan Jones
David G Mills wrote:
First off I'd like to point out that when host is set to a fully qualified domain name, comp.foo.org for example, the correct behaviour is seen, getaddrinfo returns an IPv4 and IPv6 address, and when the socket is created, it binds to the IPv6 address. Only when localhost is used does it fail to find an IPv6 address. Now there's nothing wrong with the /etc/hosts file, as I tested with the one from the working machine. Also when using AF_INET6 and host=localhost it works fine, which is why I am puzzled.
Ah, ok. It wasn't quite clear to me what specifically you consider an error. As Evan Jones says, Python returns the data in the very same way in which the C library returns them
Thanks for the glibc information, I shall investigate down that path and see what I can discover, but if you can think of anything else that might be causing this I'd like to hear it. =)
On my system, it would be /etc/hosts, which reads 127.0.0.1 localhost mira ::1 ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters ff02::3 ip6-allhosts So I find it perfectly ok that "localhost" only resolves to IPv4. Regards, Martin
participants (3)
-
"Martin v. Löwis"
-
David G Mills
-
Evan Jones