Reputation: 17881
I formerly used the code below to bind IPv4 address to Python socket as source ip address.
import socket
true_socket = socket.socket
def bound_socket(*a, **k):
sock = true_socket(*a, **k)
sock.bind((sourceIP, 0))
return sock
socket.socket = bound_socket
Does above code work for IPv6 address? If not, how can I bind an IPv6 address?
Thanks in advance!
Upvotes: 8
Views: 13097
Reputation: 91017
If you really want an extensive solution, you could extend your solution to use getaddrinfo()
:
import socket
l = socket.getaddrinfo(None, "", 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
for i in l: print i
This gives
(2, 1, 6, '', ('0.0.0.0', 0))
(10, 1, 6, '', ('::', 0, 0, 0))
These are the parameters you should create a socket with:
s = socket.socket(i[0], i[1], i[2])
if i[0] == AF_INET6: s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
s.bind(i[4])
Now you have as many sockets as you have protocols and you can use them. (Alas, the IPV6_V6ONLY
doesn't work under older Windows versions...)
If you have a given host name/IP to bind to, do
l = socket.getaddrinfo("mylocalIP", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
and it will choose the correct address/protocol family for you:
>>> socket.getaddrinfo("::1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(10, 1, 6, '', ('::1', 0, 0, 0))]
>>> socket.getaddrinfo("127.0.0.1", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(2, 1, 6, '', ('127.0.0.1', 0))]
>>> socket.getaddrinfo("localhost", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(10, 1, 6, '', ('::1', 0, 0, 0)), (2, 1, 6, '', ('127.0.0.1', 0))]
>>> socket.getaddrinfo("192.168.1.32", None, 0, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
[(2, 1, 6, '', ('192.168.1.32', 0))]
etc.
2
vs 10
are AF_INET
vs. AF_INET6
; socket.AI_PASSIVE
means that you need this address for bind()
ing.
Upvotes: 4
Reputation: 11100
you can try this, to get an IPV6 address, it is recommend that you use socket.getaddrinfo
it will return all the different address both IPV4 and IPV6, you can bind them all or just which ever one you want/need.
import socket
def bound_socket(*a, **k):
sock = socket.socket(*a, **k)
if socket.AF_INET6 in a:
if not socket.has_ipv6:
raise ValueError("There's no support for IPV6!")
else:
address = [addr for addr in socket.getaddrinfo(source_ip, None)
if socket.AF_INET6 == addr[0]] # You ussually want the first one.
if not address:
raise ValueError("Couldn't find ipv6 address for source %s" % source_ip)
sock.bind(address[0][-1])
else:
sock.bind((source_ip, 0))
return sock
Upvotes: 6
Reputation: 87054
This should do the trick... set the address family.
import socket
s = socket.socket(family=socket.AF_INET6)
s.bind(('::1', 1234))
Upvotes: 3