Reputation: 47
I'm trying to create a function that will track IP assignments for unique mac addresses. I plan on doing this by creating a dictionary that uses the MAC + Location as the key, and the value will be a set() as a way of tracking unique IP assignments per mac address.
I can't seem to append new IP addresses to the set() dictionary value though using the below:
Function:
def trackmac(ip, location, mac):
if ip_tracker.get(f'{mac} {location}') == None:
ip_tracker[f'{mac} {location}'] = set((ip,))
print(f'[!] First ip entry: {ip}')
elif ip_tracker.get(f'{mac} {location}') != None:
print('[!] not first ip entry')
update_iplist = ip_tracker.get(f'{mac} {location}')
ip_tracker[f'{mac} {location}'] = update_iplist.add(ip)
Output:
Once I test the function the first time the key (MAC + Location) has been seen it creates a set and adds the IP address.
>>> trackmac('192.168.1.10', 'home', 'AA:AA:AA:AA:AA:AA')
[!] First ip entry: 192.168.1.10
>>> print(ip_tracker)
{'AA:AA:AA:AA:AA:AA home': {'192.168.1.10'}}
>>> trackmac('192.168.1.11', 'home', 'BB:BB:BB:BB:BB:BB')
[!] First ip entry: 192.168.1.11
>>> print(ip_tracker)
{'AA:AA:AA:AA:AA:AA home': {'192.168.1.10'}, 'BB:BB:BB:BB:BB:BB home': {'192.168.1.11'}}
Error:
The second time it returns the value of that key as None rather than adding the new IP address to the set() value.
>>> trackmac('192.168.1.12', 'home', 'BB:BB:BB:BB:BB:BB')
[!] not first ip entry
>>> print(ip_tracker)
{'AA:AA:AA:AA:AA:AA home': {'192.168.1.10'}, 'BB:BB:BB:BB:BB:BB home': None}
Upvotes: 1
Views: 108
Reputation: 17322
How do you update a dictionary value that is a set in Python?
my_dict[key_with_set].add(my_value)
your issue is the fact that set.add
returns None
, this line ip_tracker[f'{mac} {location}'] = update_iplist.add(ip)
will make ip_tracker[f'{mac} {location}']
to be equal with None
since update_iplist.add(ip)
returns None
you can use:
def trackmac(ip, location, mac):
ip_tracker.setdefault(f'{mac} {location}', set()).add(ip)
Upvotes: 1
Reputation: 1537
The culprits are these lines:
update_iplist = ip_tracker.get(f'{mac} {location}')
ip_tracker[f'{mac} {location}'] = update_iplist.add(ip)
When you call update_iplist.add(ip)
on the set of IP addresses, the return value of the function add()
is None
, because it only has a side effect of adding your new IP address to the set. The assignment then overwrites the value stored in the dictionary with None
.
The wrong assumption here is that the add()
function actually returns the set, when in truth it doesn't.
You can easily fix it by replacing those two lines as follows:
ip_tracker[f'{mac} {location}'].add(ip)
This is safe to do because you already checked that the key exists in the dictionary.
Hope this helps
Upvotes: 1
Reputation: 106465
The set.add
method modifies the set in-place and returns None
, so your:
ip_tracker[f'{mac} {location}'] = update_iplist.add(ip)
would override the value of that key with None
.
You can instead use the dict.setdefault
method to initialize each new key with an empty set, and then call the set.add
method to add an IP to it:
def trackmac(ip, location, mac):
ip_tracker.setdefault(f'{mac} {location}', set()).add(ip)
Upvotes: 1