0

I am working on python socket program. below is a part of code, where am calling bind function with link local IPv6 address of the ethernet interface.

but the code is throwing error.

code:

import socket

localIP = "fe80::3c96:a2e2:a7ca:6323"                                      
localPort = 20001
bufferSize = 1024                                           

snd_adv = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
snd_adv.bind((localIP, localPort))                          #this is throwing error

addr2 = ("fe80::faf5:32ff:fe4f:6340", 20003)       #this is working good
msg = ['0x00', '0xf0']
snd_adv.sendto(bytes(msg), addr2)

Error:

    snd_adv.bind((localIP, localPort))
OSError: [Errno 22] Invalid argument

why the code is throwing error? And also I have tried some of the code changes, like "fe80::3c96:a2e2:a7ca:6323%en0"-scope ID and getaddrinfo(). these also didn't work.

how can I use a link local IPv6 address in bind function of above code? python version is - Python 3.10.1

Eth interface:

enp1s10   Link encap:Ethernet  HWaddr 1c:7e:e5:19:00:74
          inet addr:10.78.7.1  Bcast:10.78.7.255  Mask:255.255.255.0
          inet6 addr: 2001:2016:0:1::1/64 Scope:Global
          inet6 addr: fe80::3c96:a2e2:a7ca:6323/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8397200 errors:0 dropped:0 overruns:0 frame:0
          TX packets:7014580 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1367076016 (1.3 GB)  TX bytes:7326419371 (7.3 GB)
Mahadev
  • 63
  • 1
  • 6

1 Answers1

0

The key is link local addresses are available in all interface, if you don't tell the program which interface to use, it will throw you an OSError:invalid argument

the bind function accept two type of input, 2-tuple or 4-tuple.
2-tuple: (address, port)
4-tuple: (address, port, flowinfo, scope_id)

you need to use the 4-tuple for AF_INET6 socket binding. scope_id is very important in your case.

the simplest way to get a usable 4-tuples is to use the socket.getaddrinfo function.

import socket

ipv6 = r"fe80::3c96:a2e2:a7ca:6323%eth0"
PORT = 6058
socket_addr = socket.getaddrinfo(ipv6,PORT,socket.AF_INET6,socket.SOCK_DGRAM,socket.SOL_UDP)[0][4]

recv_socket = socket.socket(socket.AF_INET6,socket.SOCK_DGRAM)
recv_socket.bind(socket_addr)

thing that need to take care is you need to specify your interface in your ipv6 address by adding %eth0 or %wlan0 by case.

From my experience:

  1. you can use 2-tuple in windows but not in raspberry pi linux
  2. you can use ip link show to find the scope_id too