Host-unreachable replies
blueoak opened this issue · comments
Looks like replies to ICMP Echo-request messages (ping) which are not Echo-reply are not being handled properly in the receive method and can be interpreted as a positive reply. Specifically, pings to some addresses can return an ICMP host-unreachable message, which, for my specific purpose, should be interpreted as a non-reply. As a quick fix, I added an
else: pass
clause after the
if pkt[_ICMPV6_HDR_OFFSET] == _ICMPV6_ECHO_REPLY:
...
elif pkt[_ICMP_HDR_OFFSET] == _ICMP_ECHO_REPLY:
...
clauses, but I would also suggest a better check for IP4 vs. IP6 packets instead of looking at a byte at a particular location.
Agreed! treating "host unreachable" reply packets as a non-reply is essential. Based on the above, this is my version which also does a better check to distinguish IPv4 from IPv6 packets:
# Some offsets we use when extracting data from the header
_ICMP_VER_OFFSET = 0
try:
pkt_id = None
pkt_ident = None
pkt_ver = pkt[_ICMP_VER_OFFSET] >> 4
if pkt_ver == 6 and \
pkt[_ICMPV6_HDR_OFFSET] == _ICMPV6_ECHO_REPLY:
pkt_id = (pkt[_ICMPV6_ID_OFFSET] << 8) + \
pkt[_ICMPV6_ID_OFFSET + 1]
pkt_ident = (pkt[_ICMPV6_IDENT_OFFSET] << 8) + \
pkt[_ICMPV6_IDENT_OFFSET + 1]
payload = pkt[_ICMPV6_PAYLOAD_OFFSET:]
elif pkt_ver == 4 and \
pkt[_ICMP_HDR_OFFSET] == _ICMP_ECHO_REPLY:
pkt_id = (pkt[_ICMP_ID_OFFSET] << 8) + \
pkt[_ICMP_ID_OFFSET + 1]
pkt_ident = (pkt[_ICMP_IDENT_OFFSET] << 8) + \
pkt[_ICMP_IDENT_OFFSET + 1]
payload = pkt[_ICMP_PAYLOAD_OFFSET:]
else:
# Silently ignore other ICMP packet types (not _ECHO_REPLY)
pass
Possibly could be improved further by extracting the pkt_id/pkt_ident
for other ICMP packet types, and removing those from self._remaining_ids
without setting the results
dict? That would allow the function to return sooner in the event of non-ECHO_REPLY packets, instead of waiting for timeout.