How can you set the IPv6 Hop Limit in a Python socket? For IPv4 TTL, the following code works:
import socket
import binascii
ttl=70
target_ip='8.8.8.8'
target_port=53
hexstream='a2d2012000010000000000010377777706676f6f676c6503636f6d00000100010000291000000000000000'
message=binascii.unhexlify(hexstream)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_IP, socket.IP_TTL, ttl)
s.sendto(message, (target_ip, target_port))
data, address = s.recvfrom(4096)
print(f"Received response from {address}")
s.close()
But when I try to modify that for IPv6 Hop Limit, I get a "Protocol not available" error.
import socket
import binascii
hop_limit=61
target_ip="2001:4860:4860::8888"
target_port=53
hexstream='a2d2012000010000000000010377777706676f6f676c6503636f6d00000100010000291000000000000000'
message=binascii.unhexlify(hexstream)
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_IP, socket.IPV6_HOPLIMIT, hop_limit)
s.sendto(message, (target_ip, target_port))
data, address = s.recvfrom(4096)
print(f"Received response from {address}")
s.close()
Output:
>>> s.setsockopt(socket.SOL_IP, socket.IPV6_HOPLIMIT, hop_limit)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 92] Protocol not available
The API for IPv6 is in many cases different to the IPv4 API. With IPv6 it is not possible to set the hoplimit once using setsockopt
. Instead it needs to be sent for each individual datagram using sendmsg
.
import socket
import struct
hop_limit = 11
msg = b"test"
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.sendmsg([msg],
[(socket.IPPROTO_IPV6, socket.IPV6_HOPLIMIT, struct.pack("i",hop_limit))],
0, ('::1',1234))
To verify with tcpdump:
$ sudo tcpdump -i lo -v port 1234
... IP6 (flowlabel 0xfc1e4, hlim 11, ...) ::1.51437 > ::1.1234: ... UDP, length 4
^^^^^^^