getmac icon indicating copy to clipboard operation
getmac copied to clipboard

get_mac_address() is caching an old mac address, no longer present in local ARP

Open lucasbritosig opened this issue 2 years ago • 7 comments

Describe the bug get_mac_address() is caching an old mac address for a given IP, even when it has timeout from OS ARP table. Only an explicit delete of the ARP entry on the OS make it return '00:00:00:00:00:00' again.

To Reproduce

  • Force ARP resolution for an IP1 (a device in LAN)
  • Change IP from IP1 to IP2 on the target device.
  • Wait ARP entry timeout (or more)
  • execute get_mac_address(ip=IP1), will still get the device MAC (which is now IP2) instead of '00:00:00:00:00:00'.

OS ARP for IP1: $ arp 192.168.88.101 -v Address HWtype HWaddress Flags Mask Iface 192.168.88.101 (incomplete) wlp3s0 Entries: 20 Skipped: 19 Found: 1

Expected behavior Expects '00:00:00:00:00:00'

System info (please complete the following information):

  • OS name: Ubuntu
  • OS Version: 20.04.4 LTS focal
  • Python version: 3.8.10 x64

Additional context Running "arp -d 192.168.88.101" solves the issue.

lucasbritosig avatar Jul 14 '22 19:07 lucasbritosig

Also tested in Ubuntu 16.04.7 LTS Python 3.5.2 (o a wired NIC)

lucasbritosig avatar Jul 14 '22 20:07 lucasbritosig

Hmm, by default on Ubuntu getmac will just read the ARP entries from /proc/net/arp directly. Can you post a dump of your ARP table after IP has been changed to IP2 and a ping has been performed? Is the old entry for IP1 still in the table? I'm curious if there are two entries in the table, and if so, maybe it's a simple fix for the parser to select the correct entry.

Also, I should note that getmac avoids shelling out to arp whenever possible since that's relatively expensive (100s of ms to seconds).

GhostofGoes avatar Jul 19 '22 04:07 GhostofGoes

You are right, both entries in /proc/net/arp... Also arpreq is returning the same But getmacbyip (capy.layers.l2) works fine (192.168.0.47 is the connected one)

$ cat /proc/net/arp
IP address       HW type     Flags       HW address            Mask     Device
192.168.0.46     0x1         0x0         f2:1e:63:ac:de:24     *        wlp3s0
192.168.0.47     0x1         0x2         f2:1e:63:ac:de:24     *        wlp3s0
>>> import getmac
>>> getmac.get_mac_address(ip='192.168.0.46')
'f2:1e:63:ac:de:24'
>>> getmac.get_mac_address(ip='192.168.0.47')
'f2:1e:63:ac:de:24'
>>> from scapy.layers.l2 import getmacbyip
>>> getmacbyip('192.168.0.47')
'f2:1e:63:ac:de:24'
>>> getmacbyip('192.168.0.46')
>>> 

lucasbritosig avatar Jul 19 '22 13:07 lucasbritosig

Looks like flags need to be parsed (?)

0x0 incomplete 0x2 complete 0x6 complete and manually set

lucasbritosig avatar Jul 19 '22 13:07 lucasbritosig

https://superuser.com/questions/822054/definition-of-arp-result-flags

lucasbritosig avatar Jul 19 '22 13:07 lucasbritosig

Thanks for investigating and the additional information. It's definitely a bug, and one that should be relatively easy to fix. I'll add a check that the flag != 0x0, which should do the trick, unless there's an edge case that it misses.

Since the refactor for 0.9.0 is nearing completion, I'll just implement it in that branch and include the fix in the 0.9.0 release.

GhostofGoes avatar Jul 20 '22 04:07 GhostofGoes

Punting this to 1.0.0 release

GhostofGoes avatar Jan 23 '23 22:01 GhostofGoes