Kamal
Kamal

Reputation: 65

Invalid argument when trying to bind python socket to IPv6 address

I'm trying from my virtual machine to bind my socket in python to the address of my other virtual machine so that I could sniff the frames that are exchanged by the two. So here's my code

    import socket

UDP_IP = "fe80:849b:21f4:624c:d70b"
UDP_PORT = 61627

sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
sock.bind((UDP_IP, UDP_PORT))

while True:
    data, addr = sock.recvfrom(1024)
    print(data)

When I try to execute my python, I get an error message :

sock.bind((UDP_IP, UDP_PORT))
socket.error: [Error 22] Invalid argument

What am I doing wrong, thanks in advance !

Upvotes: 3

Views: 2156

Answers (1)

Mikhail Zakharov
Mikhail Zakharov

Reputation: 1099

I bet, you had found the answer already, but nevertheless on the first glance I see two issues with your code:

  1. In IPv6 fe80::/10 address block is reserved for Link-local addresses. These addresses are valid for local subnet only, therefore they are used with scope suffixes like %eth0 to specify proper scope. Where eth0 is a name of the network interface for which the IPv6 address is valid.

So for my MacOS laptop UDP_IP address could look like:

UDP_IP = "fe80:849b:21f4:624c:d70b%en0"
  1. Next, specifying (UDP_IP, UDP_PORT) tuple is absolutely valid for IPv4 but for IPv6 this tuple should also contain flow_info and scope_id fields. Sometimes, flow_info and scope_id could be omitted or missed: (UDP_IP, UDP_PORT, 0, 0). It may work sometimes, but it's not the right way to use in the code.

So, these fields can be fetched via socket.getaddrinfo(IP, PORT) which returns a list of tuples for each address family and socket_kind. Filter them with something like that:

for ainfo in socket.getaddrinfo(UDP_IP, UDP_PORT):
    if ainfo[0].name == 'AF_INET6' and ainfo[1].name == 'SOCK_DGRAM':
        target_address = ainfo[4]
        break

sock.bind(target_address)

I'm not sure, if I wrote the sample code right, as I didn't test it, check it before usage.

Upvotes: 7

Related Questions