From 3f8a7643ce190a5aaf3cbba69d8a66baa028e2f8 Mon Sep 17 00:00:00 2001 From: Miguel Date: Fri, 4 Apr 2025 21:27:13 +0200 Subject: [PATCH] Added MAC vendor lookup functionality and updated UI to display vendor information in scan results; modified IP configuration and ping targets. --- ip_config.json | 2 +- menu-ip-change.py | 85 ++++++++++++++++++++++++++++++++++++++++++----- ping_targets.json | 2 +- requirements.txt | 8 +++++ 4 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 requirements.txt diff --git a/ip_config.json b/ip_config.json index d64ed28..e27fcc8 100644 --- a/ip_config.json +++ b/ip_config.json @@ -1 +1 @@ -{"last_interface": "Ethernet", "last_ip_prefix": "10.1.20", "previous_config": {"name": "Ethernet", "ip_address": "10.1.20.249", "subnet_mask": "255.255.255.0", "gateway": "10.1.20.1", "dhcp_enabled": false}} \ No newline at end of file +{"last_interface": "Ethernet", "last_ip_prefix": "10.1.20", "previous_config": {"name": "Ethernet", "ip_address": "10.1.20.249", "subnet_mask": "255.240.0.0", "gateway": "10.1.20.1", "dhcp_enabled": false}} \ No newline at end of file diff --git a/menu-ip-change.py b/menu-ip-change.py index 28bf300..517ed7b 100644 --- a/menu-ip-change.py +++ b/menu-ip-change.py @@ -46,6 +46,21 @@ except ImportError: "WMI module not found. Using alternative method for network interface detection." ) +# Add MAC vendor lookup library +try: + from mac_vendor_lookup import MacLookup + + MAC_LOOKUP_AVAILABLE = True + # Initialize the MAC lookup service + mac_lookup = MacLookup() + # Update the database if needed (this can be time-consuming) + # mac_lookup.update_vendors() # Uncomment to update database on startup +except ImportError: + MAC_LOOKUP_AVAILABLE = False + print( + "mac-vendor-lookup module not found. Install with 'pip install mac-vendor-lookup' for MAC vendor lookup functionality." + ) + @dataclass class NetworkInterface: @@ -194,6 +209,10 @@ class IPChangerApp: self.master.grid_columnconfigure(0, weight=1) self.master.grid_rowconfigure(1, weight=1) # El log expandible + # Initialize MAC lookup if available + if MAC_LOOKUP_AVAILABLE: + self.mac_lookup = MacLookup() + def setup_mask_traces(self): """Set up traces for subnet mask and CIDR fields safely""" # First initialize variables @@ -538,7 +557,7 @@ class IPChangerApp: # Replace Listbox with Treeview that has columns self.scan_results_tree = ttk.Treeview( self.results_frame, - columns=("ip", "hostname", "mac"), + columns=("ip", "hostname", "mac", "vendor"), # Add vendor column show="headings", height=10, ) @@ -547,11 +566,17 @@ class IPChangerApp: self.scan_results_tree.heading("ip", text="IP Address") self.scan_results_tree.heading("hostname", text="Hostname") self.scan_results_tree.heading("mac", text="MAC Address") + self.scan_results_tree.heading( + "vendor", text="MAC Vendor" + ) # Add vendor heading # Set column widths self.scan_results_tree.column("ip", width=120, anchor="w") self.scan_results_tree.column("hostname", width=200, anchor="w") self.scan_results_tree.column("mac", width=150, anchor="w") + self.scan_results_tree.column( + "vendor", width=180, anchor="w" + ) # Add vendor column width # Add scrollbar self.scan_results_scrollbar = ttk.Scrollbar( @@ -931,6 +956,7 @@ class IPChangerApp: return # Save the ping target when used + self.save_current_ping_target() # Check if continuous ping is enabled @@ -1114,11 +1140,18 @@ class IPChangerApp: # Try to get hostname and MAC address hostname = self.get_hostname(target) mac_address = self.get_mac_address(target) + vendor = "" + + # Look up vendor if we have a MAC + if mac_address and MAC_LOOKUP_AVAILABLE: + vendor = self.get_mac_vendor(mac_address) if hostname: self.log_message(f"Hostname: {hostname}") if mac_address: self.log_message(f"MAC Address: {mac_address}") + if vendor: + self.log_message(f"MAC Vendor: {vendor}") except Exception as e: self.log_message(f"Error executing ping: {str(e)}") @@ -1247,7 +1280,7 @@ class IPChangerApp: # Add to results tree with placeholder values self.master.after( - 0, lambda ip=ip_str: self.add_scan_result(ip, "", "") + 0, lambda ip=ip_str: self.add_scan_result(ip, "", "", "") ) # Update progress @@ -1294,6 +1327,15 @@ class IPChangerApp: # Get hostname and MAC hostname = self.get_hostname(ip) mac_address = self.get_mac_address(ip) + vendor = "" + + # Look up vendor information if we have a MAC address + if mac_address and MAC_LOOKUP_AVAILABLE: + vendor = self.get_mac_vendor(mac_address) + if vendor: + self.log_message(f" MAC Vendor: {vendor}") + else: + self.log_message(f" MAC Vendor: Unknown") # Log what we found if hostname: @@ -1306,8 +1348,8 @@ class IPChangerApp: else: self.log_message(f" MAC Address: Not found") - # Update the tree - self.update_host_in_tree(ip, hostname, mac_address) + # Update the tree with vendor information + self.update_host_in_tree(ip, hostname, mac_address, vendor) # Update progress self.scan_progress_var.set(i + 1) @@ -1317,7 +1359,7 @@ class IPChangerApp: except Exception as e: self.log_message(f"Error gathering host information: {str(e)}") - def update_host_in_tree(self, ip, hostname, mac): + def update_host_in_tree(self, ip, hostname, mac, vendor=""): """Update an existing host in the treeview with obtained information""" try: # Find the item with this IP @@ -1327,21 +1369,24 @@ class IPChangerApp: # Update the values hostname_str = hostname if hostname else "Not resolved" mac_str = mac if mac else "Not found" + vendor_str = vendor if vendor else "Unknown" + self.scan_results_tree.item( - item_id, values=(ip, hostname_str, mac_str) + item_id, values=(ip, hostname_str, mac_str, vendor_str) ) break except Exception as e: self.log_message(f"Error updating host in treeview: {str(e)}") - def add_scan_result(self, ip, hostname, mac): + def add_scan_result(self, ip, hostname, mac, vendor=""): """Helper method to add scan result to the treeview""" try: # Insert the item with all values, even if some are empty hostname = hostname if hostname else "Not resolved" mac = mac if mac else "Not found" + vendor = vendor if vendor else "Unknown" - self.scan_results_tree.insert("", "end", values=(ip, hostname, mac)) + self.scan_results_tree.insert("", "end", values=(ip, hostname, mac, vendor)) except Exception as e: self.log_message(f"Error adding scan result to UI: {str(e)}") @@ -1784,6 +1829,30 @@ class IPChangerApp: self.log_message(f"Error getting MAC address for {ip_address}: {str(e)}") return "" + def get_mac_vendor(self, mac_address): + """Look up the vendor for a MAC address""" + try: + if not MAC_LOOKUP_AVAILABLE: + return "" + + # Clean up the MAC address format - the library expects a standardized format + # Remove spaces, dashes, colons and ensure uppercase + clean_mac = ( + mac_address.replace(" ", "").replace("-", "").replace(":", "").upper() + ) + + # Add colons to form a standard MAC format for lookup + formatted_mac = ":".join( + [clean_mac[i : i + 2] for i in range(0, len(clean_mac), 2)] + ) + + # Look up the vendor + vendor = self.mac_lookup.lookup(formatted_mac) + return vendor + except Exception as e: + self.log_message(f"Error looking up MAC vendor: {str(e)}") + return "" + def main(): root = tk.Tk() diff --git a/ping_targets.json b/ping_targets.json index ea0d6d7..83e3cfe 100644 --- a/ping_targets.json +++ b/ping_targets.json @@ -1 +1 @@ -{"10.1.22": "10.1.22.11", "10.138.182": "10.138.182.94", "10.1.20": "10.1.20.11", "10.255.255": "10.255.255.1"} \ No newline at end of file +{"10.1.22": "10.1.22.11", "10.138.182": "10.138.182.94", "10.1.20": "10.1.33.11", "10.255.255": "10.255.255.1", "192.168.88": "192.168.88.1"} \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e82aa78 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +# Network-related packages +pythonping>=1.1.4 +pysnmp>=4.4.12 +wmi>=1.5.1 +mac-vendor-lookup>=0.1.11 + +# Other dependencies +ipaddress>=1.0.23