Agregado del tiempo de cada ping a la lista
This commit is contained in:
parent
ee37a10a97
commit
8f7bd969de
|
@ -173,6 +173,9 @@ class IPChangerApp:
|
||||||
self.continuous_ping = tk.BooleanVar(value=False)
|
self.continuous_ping = tk.BooleanVar(value=False)
|
||||||
self.ping_running = False
|
self.ping_running = False
|
||||||
self.ping_stop_event = threading.Event()
|
self.ping_stop_event = threading.Event()
|
||||||
|
self.last_ping_time = tk.StringVar(
|
||||||
|
value="N/A"
|
||||||
|
) # Add variable for last ping time
|
||||||
|
|
||||||
# Variables for IP scanning
|
# Variables for IP scanning
|
||||||
self.scan_results = []
|
self.scan_results = []
|
||||||
|
@ -263,7 +266,32 @@ class IPChangerApp:
|
||||||
self.log_frame = ttk.LabelFrame(self.master, text="Operation Log", padding="5")
|
self.log_frame = ttk.LabelFrame(self.master, text="Operation Log", padding="5")
|
||||||
self.log_frame.grid(row=1, column=0, sticky="nsew", padx=10, pady=(0, 10))
|
self.log_frame.grid(row=1, column=0, sticky="nsew", padx=10, pady=(0, 10))
|
||||||
|
|
||||||
self.log_text = tk.Text(self.log_frame, wrap="none", height=10)
|
# Use a better font and enable tag configuration
|
||||||
|
log_font = (
|
||||||
|
"Consolas",
|
||||||
|
10,
|
||||||
|
) # Use a monospaced font like Consolas or Courier New
|
||||||
|
self.log_text = tk.Text(self.log_frame, wrap="none", height=10, font=log_font)
|
||||||
|
|
||||||
|
# Create tags for different message types with specific formatting
|
||||||
|
self.log_text.tag_configure("INFO", foreground="blue")
|
||||||
|
self.log_text.tag_configure(
|
||||||
|
"ERROR", foreground="red", font=(log_font[0], log_font[1], "bold")
|
||||||
|
)
|
||||||
|
self.log_text.tag_configure(
|
||||||
|
"SUCCESS", foreground="green", font=(log_font[0], log_font[1], "bold")
|
||||||
|
)
|
||||||
|
self.log_text.tag_configure("WARN", foreground="orange")
|
||||||
|
self.log_text.tag_configure("PING", foreground="purple")
|
||||||
|
self.log_text.tag_configure(
|
||||||
|
"DISCOVERY", foreground="navy", font=(log_font[0], log_font[1], "bold")
|
||||||
|
)
|
||||||
|
self.log_text.tag_configure("HOSTNAME", foreground="teal")
|
||||||
|
self.log_text.tag_configure("MAC", foreground="maroon")
|
||||||
|
self.log_text.tag_configure("COMMAND", foreground="sienna")
|
||||||
|
self.log_text.tag_configure("VENDOR", foreground="#8B008B") # Dark magenta
|
||||||
|
|
||||||
|
# Continue with existing scrollbar setup
|
||||||
self.log_scrollbar_y = ttk.Scrollbar(
|
self.log_scrollbar_y = ttk.Scrollbar(
|
||||||
self.log_frame, orient="vertical", command=self.log_text.yview
|
self.log_frame, orient="vertical", command=self.log_text.yview
|
||||||
)
|
)
|
||||||
|
@ -459,7 +487,7 @@ class IPChangerApp:
|
||||||
1, weight=1
|
1, weight=1
|
||||||
) # Make the scan frame expandable
|
) # Make the scan frame expandable
|
||||||
|
|
||||||
# Network Tools section (moved from original layout)
|
# Network Tools section (ping tool)
|
||||||
self.ping_frame = ttk.LabelFrame(
|
self.ping_frame = ttk.LabelFrame(
|
||||||
self.tools_control_frame, text="Ping Tool", padding="5"
|
self.tools_control_frame, text="Ping Tool", padding="5"
|
||||||
)
|
)
|
||||||
|
@ -479,17 +507,27 @@ class IPChangerApp:
|
||||||
# Bind the FocusOut event to save the ping target
|
# Bind the FocusOut event to save the ping target
|
||||||
self.ping_entry.bind("<FocusOut>", self.save_current_ping_target)
|
self.ping_entry.bind("<FocusOut>", self.save_current_ping_target)
|
||||||
|
|
||||||
|
# Add last ping time display field
|
||||||
|
ttk.Label(self.ping_frame, text="Last RTT:").grid(
|
||||||
|
row=0, column=2, sticky="w", padx=5
|
||||||
|
)
|
||||||
|
self.last_ping_time = tk.StringVar(value="N/A")
|
||||||
|
ping_time_display = ttk.Entry(
|
||||||
|
self.ping_frame, textvariable=self.last_ping_time, width=8, state="readonly"
|
||||||
|
)
|
||||||
|
ping_time_display.grid(row=0, column=3, padx=5)
|
||||||
|
|
||||||
# Add continuous ping checkbox
|
# Add continuous ping checkbox
|
||||||
self.continuous_ping_check = ttk.Checkbutton(
|
self.continuous_ping_check = ttk.Checkbutton(
|
||||||
self.ping_frame, text="Continuous Ping", variable=self.continuous_ping
|
self.ping_frame, text="Continuous Ping", variable=self.continuous_ping
|
||||||
)
|
)
|
||||||
self.continuous_ping_check.grid(row=0, column=2, padx=5)
|
self.continuous_ping_check.grid(row=0, column=4, padx=5)
|
||||||
|
|
||||||
ttk.Button(self.ping_frame, text="Ping", command=self.do_ping).grid(
|
ttk.Button(self.ping_frame, text="Ping", command=self.do_ping).grid(
|
||||||
row=0, column=3, padx=5
|
row=0, column=5, padx=5
|
||||||
)
|
)
|
||||||
ttk.Button(self.ping_frame, text="Stop", command=self.stop_ping).grid(
|
ttk.Button(self.ping_frame, text="Stop", command=self.stop_ping).grid(
|
||||||
row=0, column=4, padx=5
|
row=0, column=6, padx=5
|
||||||
)
|
)
|
||||||
|
|
||||||
# Network Scan section - make it expand both horizontally and vertically
|
# Network Scan section - make it expand both horizontally and vertically
|
||||||
|
@ -586,29 +624,33 @@ class IPChangerApp:
|
||||||
# Replace Listbox with Treeview that has columns - make sure it expands
|
# Replace Listbox with Treeview that has columns - make sure it expands
|
||||||
self.scan_results_tree = ttk.Treeview(
|
self.scan_results_tree = ttk.Treeview(
|
||||||
self.results_frame,
|
self.results_frame,
|
||||||
columns=("ip", "hostname", "mac", "vendor"), # Add vendor column
|
columns=("ip", "delay", "hostname", "mac", "vendor"), # Added delay column
|
||||||
show="headings",
|
show="headings",
|
||||||
height=10,
|
height=10,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Define columns
|
# Define columns
|
||||||
self.scan_results_tree.heading("ip", text="IP Address")
|
self.scan_results_tree.heading("ip", text="IP Address")
|
||||||
|
self.scan_results_tree.heading(
|
||||||
|
"delay", text="Ping (ms)"
|
||||||
|
) # New column for ping delay
|
||||||
self.scan_results_tree.heading("hostname", text="Hostname")
|
self.scan_results_tree.heading("hostname", text="Hostname")
|
||||||
self.scan_results_tree.heading("mac", text="MAC Address")
|
self.scan_results_tree.heading("mac", text="MAC Address")
|
||||||
self.scan_results_tree.heading(
|
self.scan_results_tree.heading("vendor", text="MAC Vendor")
|
||||||
"vendor", text="MAC Vendor"
|
|
||||||
) # Add vendor heading
|
|
||||||
|
|
||||||
# Set column widths
|
# Set column widths with adjusted proportions
|
||||||
total_width = 650 # Base total width for the columns
|
total_width = 650 # Base total width for the columns
|
||||||
self.scan_results_tree.column(
|
self.scan_results_tree.column(
|
||||||
"ip", width=int(total_width * 0.18), anchor="w", stretch=True
|
"ip", width=int(total_width * 0.15), anchor="w", stretch=True
|
||||||
)
|
)
|
||||||
self.scan_results_tree.column(
|
self.scan_results_tree.column(
|
||||||
"hostname", width=int(total_width * 0.30), anchor="w", stretch=True
|
"delay", width=int(total_width * 0.08), anchor="center", stretch=True
|
||||||
)
|
)
|
||||||
self.scan_results_tree.column(
|
self.scan_results_tree.column(
|
||||||
"mac", width=int(total_width * 0.22), anchor="w", stretch=True
|
"hostname", width=int(total_width * 0.27), anchor="w", stretch=True
|
||||||
|
)
|
||||||
|
self.scan_results_tree.column(
|
||||||
|
"mac", width=int(total_width * 0.20), anchor="w", stretch=True
|
||||||
)
|
)
|
||||||
self.scan_results_tree.column(
|
self.scan_results_tree.column(
|
||||||
"vendor", width=int(total_width * 0.30), anchor="w", stretch=True
|
"vendor", width=int(total_width * 0.30), anchor="w", stretch=True
|
||||||
|
@ -627,8 +669,52 @@ class IPChangerApp:
|
||||||
def clear_log(self):
|
def clear_log(self):
|
||||||
self.log_text.delete("1.0", tk.END)
|
self.log_text.delete("1.0", tk.END)
|
||||||
|
|
||||||
def log_message(self, message: str):
|
def log_message(self, message: str, tag: str = None):
|
||||||
self.log_text.insert(tk.END, f"{message}\n")
|
"""Enhanced log function with tags for color and formatting"""
|
||||||
|
# Try to automatically detect message type if tag not specified
|
||||||
|
if tag is None:
|
||||||
|
if "ERROR:" in message or "Error" in message or "failed" in message.lower():
|
||||||
|
tag = "ERROR"
|
||||||
|
elif (
|
||||||
|
"SUCCESS" in message
|
||||||
|
or "Successfully" in message
|
||||||
|
or "completed" in message
|
||||||
|
):
|
||||||
|
tag = "SUCCESS"
|
||||||
|
elif "WARNING" in message or "Warn" in message:
|
||||||
|
tag = "WARN"
|
||||||
|
elif "Host discovered:" in message:
|
||||||
|
tag = "DISCOVERY"
|
||||||
|
elif (
|
||||||
|
"Reply from" in message
|
||||||
|
or "ping" in message.lower()
|
||||||
|
or "Request timed out" in message
|
||||||
|
):
|
||||||
|
tag = "PING"
|
||||||
|
elif "Hostname:" in message:
|
||||||
|
tag = "HOSTNAME"
|
||||||
|
elif "MAC Address:" in message:
|
||||||
|
tag = "MAC"
|
||||||
|
elif "MAC Vendor:" in message or "Vendor:" in message:
|
||||||
|
tag = "VENDOR"
|
||||||
|
elif "Executing" in message and "command" in message.lower():
|
||||||
|
tag = "COMMAND"
|
||||||
|
elif "INFO:" in message:
|
||||||
|
tag = "INFO"
|
||||||
|
else:
|
||||||
|
tag = None
|
||||||
|
|
||||||
|
# Insert the timestamp and message
|
||||||
|
timestamp = time.strftime("%H:%M:%S", time.localtime())
|
||||||
|
self.log_text.insert(tk.END, f"[{timestamp}] ", "timestamp")
|
||||||
|
|
||||||
|
# Insert the message with appropriate tag
|
||||||
|
if tag:
|
||||||
|
self.log_text.insert(tk.END, f"{message}\n", tag)
|
||||||
|
else:
|
||||||
|
self.log_text.insert(tk.END, f"{message}\n")
|
||||||
|
|
||||||
|
# Scroll to see the latest message
|
||||||
self.log_text.see(tk.END)
|
self.log_text.see(tk.END)
|
||||||
self.log_text.update_idletasks()
|
self.log_text.update_idletasks()
|
||||||
|
|
||||||
|
@ -1017,6 +1103,7 @@ class IPChangerApp:
|
||||||
self.log_message("Stopping continuous ping...")
|
self.log_message("Stopping continuous ping...")
|
||||||
self.ping_stop_event.set()
|
self.ping_stop_event.set()
|
||||||
self.ping_running = False
|
self.ping_running = False
|
||||||
|
self.last_ping_time.set("N/A") # Reset when stopped
|
||||||
|
|
||||||
def _execute_continuous_ping(self, target: str):
|
def _execute_continuous_ping(self, target: str):
|
||||||
"""Execute continuous ping until stopped"""
|
"""Execute continuous ping until stopped"""
|
||||||
|
@ -1039,13 +1126,17 @@ class IPChangerApp:
|
||||||
for reply in response:
|
for reply in response:
|
||||||
if reply.success:
|
if reply.success:
|
||||||
rtt = reply.time_elapsed_ms
|
rtt = reply.time_elapsed_ms
|
||||||
|
# Update the last ping time field
|
||||||
|
self.last_ping_time.set(f"{rtt:.1f} ms")
|
||||||
self.log_message(
|
self.log_message(
|
||||||
f"Reply from {target}: time={rtt:.2f}ms (seq={count})"
|
f"Reply from {target}: time={rtt:.2f}ms (seq={count})"
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
|
self.last_ping_time.set("Timeout")
|
||||||
self.log_message(f"Request timed out (seq={count})")
|
self.log_message(f"Request timed out (seq={count})")
|
||||||
except Exception as ping_error:
|
except Exception as ping_error:
|
||||||
|
self.last_ping_time.set("Error")
|
||||||
self.log_message(f"Ping error: {str(ping_error)} (seq={count})")
|
self.log_message(f"Ping error: {str(ping_error)} (seq={count})")
|
||||||
else:
|
else:
|
||||||
# Fallback to socket
|
# Fallback to socket
|
||||||
|
@ -1058,14 +1149,18 @@ class IPChangerApp:
|
||||||
s.close()
|
s.close()
|
||||||
|
|
||||||
if result == 0:
|
if result == 0:
|
||||||
|
# Update the last ping time field
|
||||||
|
self.last_ping_time.set(f"{elapsed_time:.1f} ms")
|
||||||
self.log_message(
|
self.log_message(
|
||||||
f"Connected to {target}:80 in {elapsed_time:.2f}ms (seq={count})"
|
f"Connected to {target}:80 in {elapsed_time:.2f}ms (seq={count})"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
self.last_ping_time.set("Failed")
|
||||||
self.log_message(
|
self.log_message(
|
||||||
f"Failed to connect to {target}:80 (seq={count})"
|
f"Failed to connect to {target}:80 (seq={count})"
|
||||||
)
|
)
|
||||||
except Exception as socket_error:
|
except Exception as socket_error:
|
||||||
|
self.last_ping_time.set("Error")
|
||||||
self.log_message(
|
self.log_message(
|
||||||
f"Connection error: {str(socket_error)} (seq={count})"
|
f"Connection error: {str(socket_error)} (seq={count})"
|
||||||
)
|
)
|
||||||
|
@ -1086,23 +1181,40 @@ class IPChangerApp:
|
||||||
self.log_message(f"Error in continuous ping: {str(e)}")
|
self.log_message(f"Error in continuous ping: {str(e)}")
|
||||||
finally:
|
finally:
|
||||||
self.ping_running = False
|
self.ping_running = False
|
||||||
|
self.last_ping_time.set("N/A") # Reset on stop
|
||||||
|
|
||||||
def _execute_ping(self, target: str):
|
def _execute_ping(self, target: str):
|
||||||
"""Execute a single ping and display the results"""
|
"""Execute a single ping and display the results"""
|
||||||
try:
|
try:
|
||||||
self.log_message(f"Pinging {target} with 4 echo requests...")
|
# Reset the last ping time to "Testing..."
|
||||||
|
self.last_ping_time.set("Testing...")
|
||||||
|
|
||||||
|
self.log_message(f"Pinging {target} with 4 echo requests...", "PING")
|
||||||
|
|
||||||
if PING_LIBRARY_AVAILABLE:
|
if PING_LIBRARY_AVAILABLE:
|
||||||
# Use PythonPing library
|
# Use PythonPing library
|
||||||
response = pythonping(target, count=4, timeout=1)
|
response = pythonping(target, count=4, timeout=1)
|
||||||
|
|
||||||
# Display individual replies
|
# Display individual replies with PING tag
|
||||||
|
total_rtt = 0
|
||||||
|
successful_pings = 0
|
||||||
|
|
||||||
for i, reply in enumerate(response):
|
for i, reply in enumerate(response):
|
||||||
if reply.success:
|
if reply.success:
|
||||||
rtt = reply.time_elapsed_ms
|
rtt = reply.time_elapsed_ms
|
||||||
self.log_message(f"Reply from {target}: time={rtt:.2f}ms")
|
total_rtt += rtt
|
||||||
|
successful_pings += 1
|
||||||
|
self.log_message(
|
||||||
|
f"Reply from {target}: time={rtt:.2f}ms", "PING"
|
||||||
|
)
|
||||||
|
# Update the last ping time with the most recent successful ping
|
||||||
|
self.last_ping_time.set(f"{rtt:.1f} ms")
|
||||||
else:
|
else:
|
||||||
self.log_message(f"Request timed out (seq={i+1})")
|
self.log_message(f"Request timed out (seq={i+1})", "PING")
|
||||||
|
|
||||||
|
# If all pings failed, update the last ping time appropriately
|
||||||
|
if successful_pings == 0:
|
||||||
|
self.last_ping_time.set("Timeout")
|
||||||
|
|
||||||
# Display statistics
|
# Display statistics
|
||||||
success_count = sum(1 for r in response if r.success)
|
success_count = sum(1 for r in response if r.success)
|
||||||
|
@ -1179,14 +1291,15 @@ class IPChangerApp:
|
||||||
vendor = self.get_mac_vendor(mac_address)
|
vendor = self.get_mac_vendor(mac_address)
|
||||||
|
|
||||||
if hostname:
|
if hostname:
|
||||||
self.log_message(f"Hostname: {hostname}")
|
self.log_message(f"Hostname: {hostname}", "HOSTNAME")
|
||||||
if mac_address:
|
if mac_address:
|
||||||
self.log_message(f"MAC Address: {mac_address}")
|
self.log_message(f"MAC Address: {mac_address}", "MAC")
|
||||||
if vendor:
|
if vendor:
|
||||||
self.log_message(f"MAC Vendor: {vendor}")
|
self.log_message(f"MAC Vendor: {vendor}", "VENDOR")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log_message(f"Error executing ping: {str(e)}")
|
self.last_ping_time.set("Error")
|
||||||
|
self.log_message(f"Error executing ping: {str(e)}", "ERROR")
|
||||||
|
|
||||||
def start_scan(self):
|
def start_scan(self):
|
||||||
"""Start network scanning between IP range"""
|
"""Start network scanning between IP range"""
|
||||||
|
@ -1291,7 +1404,7 @@ class IPChangerApp:
|
||||||
self.scan_running = False
|
self.scan_running = False
|
||||||
|
|
||||||
def _scan_worker(self):
|
def _scan_worker(self):
|
||||||
"""Worker thread function to scan IPs from the queue - now only performs ping scan"""
|
"""Worker thread function to scan IPs from the queue - now with ping time recording"""
|
||||||
while not self.scan_stop_event.is_set():
|
while not self.scan_stop_event.is_set():
|
||||||
try:
|
try:
|
||||||
# Get next IP from queue with timeout
|
# Get next IP from queue with timeout
|
||||||
|
@ -1301,18 +1414,24 @@ class IPChangerApp:
|
||||||
# No more IPs to scan
|
# No more IPs to scan
|
||||||
break
|
break
|
||||||
|
|
||||||
# Ping the IP
|
# Ping the IP and measure the time
|
||||||
is_active = self._ping_host(str(ip_address))
|
ping_time = 0
|
||||||
|
ip_str = str(ip_address)
|
||||||
|
is_active, ping_delay = self._ping_host_with_time(ip_str)
|
||||||
|
|
||||||
# If active, add to results - but don't get host info yet
|
# If active, add to results - but don't get host info yet
|
||||||
if is_active:
|
if is_active:
|
||||||
ip_str = str(ip_address)
|
self.log_message(
|
||||||
self.log_message(f"Host discovered: {ip_str}")
|
f"Host discovered: {ip_str} ({ping_delay:.1f}ms)", "DISCOVERY"
|
||||||
|
)
|
||||||
self.scan_results.append(ip_str)
|
self.scan_results.append(ip_str)
|
||||||
|
|
||||||
# Add to results tree with placeholder values
|
# Add to results tree with placeholder values and ping time
|
||||||
self.master.after(
|
self.master.after(
|
||||||
0, lambda ip=ip_str: self.add_scan_result(ip, "", "", "")
|
0,
|
||||||
|
lambda ip=ip_str, delay=ping_delay: self.add_scan_result(
|
||||||
|
ip, delay, "", "", ""
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Update progress
|
# Update progress
|
||||||
|
@ -1338,7 +1457,7 @@ class IPChangerApp:
|
||||||
"""Perform the actual host information gathering"""
|
"""Perform the actual host information gathering"""
|
||||||
try:
|
try:
|
||||||
self.log_message(
|
self.log_message(
|
||||||
f"Gathering information for {len(self.scan_results)} hosts..."
|
f"Gathering information for {len(self.scan_results)} hosts...", "INFO"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Reset progress bar for this operation
|
# Reset progress bar for this operation
|
||||||
|
@ -1349,7 +1468,7 @@ class IPChangerApp:
|
||||||
# Get information for each host
|
# Get information for each host
|
||||||
for i, ip in enumerate(self.scan_results):
|
for i, ip in enumerate(self.scan_results):
|
||||||
if self.scan_stop_event.is_set():
|
if self.scan_stop_event.is_set():
|
||||||
self.log_message("Host information gathering stopped.")
|
self.log_message("Host information gathering stopped.", "WARN")
|
||||||
break
|
break
|
||||||
|
|
||||||
self.log_message(
|
self.log_message(
|
||||||
|
@ -1364,21 +1483,20 @@ class IPChangerApp:
|
||||||
# Look up vendor information if we have a MAC address
|
# Look up vendor information if we have a MAC address
|
||||||
if mac_address and MAC_LOOKUP_AVAILABLE:
|
if mac_address and MAC_LOOKUP_AVAILABLE:
|
||||||
vendor = self.get_mac_vendor(mac_address)
|
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
|
# Log the results in a cleaner format
|
||||||
|
result_parts = []
|
||||||
if hostname:
|
if hostname:
|
||||||
self.log_message(f" Hostname: {hostname}")
|
result_parts.append(f"Hostname: {hostname}")
|
||||||
else:
|
|
||||||
self.log_message(f" Hostname: Not resolved")
|
|
||||||
|
|
||||||
if mac_address:
|
if mac_address:
|
||||||
self.log_message(f" MAC Address: {mac_address}")
|
result_parts.append(f"MAC: {mac_address}")
|
||||||
|
if vendor:
|
||||||
|
result_parts.append(f"Vendor: {vendor}")
|
||||||
|
|
||||||
|
if result_parts:
|
||||||
|
self.log_message(f" {ip} → " + " | ".join(result_parts))
|
||||||
else:
|
else:
|
||||||
self.log_message(f" MAC Address: Not found")
|
self.log_message(f" {ip} → No additional information found")
|
||||||
|
|
||||||
# Update the tree with vendor information
|
# Update the tree with vendor information
|
||||||
self.update_host_in_tree(ip, hostname, mac_address, vendor)
|
self.update_host_in_tree(ip, hostname, mac_address, vendor)
|
||||||
|
@ -1386,10 +1504,10 @@ class IPChangerApp:
|
||||||
# Update progress
|
# Update progress
|
||||||
self.scan_progress_var.set(i + 1)
|
self.scan_progress_var.set(i + 1)
|
||||||
|
|
||||||
self.log_message("Host information gathering completed.")
|
self.log_message("Host information gathering completed.", "SUCCESS")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log_message(f"Error gathering host information: {str(e)}")
|
self.log_message(f"Error gathering host information: {str(e)}", "ERROR")
|
||||||
|
|
||||||
def update_host_in_tree(self, ip, hostname, mac, vendor=""):
|
def update_host_in_tree(self, ip, hostname, mac, vendor=""):
|
||||||
"""Update an existing host in the treeview with obtained information"""
|
"""Update an existing host in the treeview with obtained information"""
|
||||||
|
@ -1398,46 +1516,66 @@ class IPChangerApp:
|
||||||
for item_id in self.scan_results_tree.get_children():
|
for item_id in self.scan_results_tree.get_children():
|
||||||
values = self.scan_results_tree.item(item_id, "values")
|
values = self.scan_results_tree.item(item_id, "values")
|
||||||
if values and values[0] == ip:
|
if values and values[0] == ip:
|
||||||
# Update the values
|
# Get the current delay value (to preserve it)
|
||||||
|
delay = values[1] if len(values) > 1 else ""
|
||||||
|
|
||||||
|
# Update the values, preserving the delay value
|
||||||
hostname_str = hostname if hostname else "Not resolved"
|
hostname_str = hostname if hostname else "Not resolved"
|
||||||
mac_str = mac if mac else "Not found"
|
mac_str = (
|
||||||
|
mac.upper() if mac else "Not found"
|
||||||
|
) # Ensure uppercase MAC
|
||||||
vendor_str = vendor if vendor else "Unknown"
|
vendor_str = vendor if vendor else "Unknown"
|
||||||
|
|
||||||
self.scan_results_tree.item(
|
self.scan_results_tree.item(
|
||||||
item_id, values=(ip, hostname_str, mac_str, vendor_str)
|
item_id, values=(ip, delay, hostname_str, mac_str, vendor_str)
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log_message(f"Error updating host in treeview: {str(e)}")
|
self.log_message(f"Error updating host in treeview: {str(e)}")
|
||||||
|
|
||||||
def add_scan_result(self, ip, hostname, mac, vendor=""):
|
def add_scan_result(self, ip, delay=0, hostname="", mac="", vendor=""):
|
||||||
"""Helper method to add scan result to the treeview"""
|
"""Helper method to add scan result to the treeview"""
|
||||||
try:
|
try:
|
||||||
# Insert the item with all values, even if some are empty
|
# Insert the item with all values
|
||||||
hostname = hostname if hostname else "Not resolved"
|
hostname = hostname if hostname else "Not resolved"
|
||||||
mac = mac if mac else "Not found"
|
mac = mac if mac else "Not found"
|
||||||
vendor = vendor if vendor else "Unknown"
|
vendor = vendor if vendor else "Unknown"
|
||||||
|
delay_str = f"{delay:.1f}" if delay > 0 else ""
|
||||||
|
|
||||||
self.scan_results_tree.insert("", "end", values=(ip, hostname, mac, vendor))
|
self.scan_results_tree.insert(
|
||||||
|
"", "end", values=(ip, delay_str, hostname, mac, vendor)
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.log_message(f"Error adding scan result to UI: {str(e)}")
|
self.log_message(f"Error adding scan result to UI: {str(e)}")
|
||||||
|
|
||||||
def _ping_host(self, host: str) -> bool:
|
def _ping_host_with_time(self, host: str) -> tuple[bool, float]:
|
||||||
"""Ping a host to check if it's active, returns True if host responds"""
|
"""Ping a host to check if it's active, returns (success, delay_in_ms)"""
|
||||||
try:
|
try:
|
||||||
if PING_LIBRARY_AVAILABLE:
|
if PING_LIBRARY_AVAILABLE:
|
||||||
# Use PythonPing with shorter timeout for scanning
|
# Use PythonPing with shorter timeout for scanning
|
||||||
|
start_time = time.time()
|
||||||
response = pythonping(host, count=1, timeout=0.5)
|
response = pythonping(host, count=1, timeout=0.5)
|
||||||
return response.success()
|
ping_time = 0
|
||||||
|
|
||||||
|
if response.success():
|
||||||
|
# Get the actual ping time from the response
|
||||||
|
for reply in response:
|
||||||
|
if reply.success:
|
||||||
|
ping_time = reply.time_elapsed_ms
|
||||||
|
break
|
||||||
|
return True, ping_time
|
||||||
|
return False, 0
|
||||||
else:
|
else:
|
||||||
# Fallback using socket
|
# Fallback using socket with timing
|
||||||
|
start_time = time.time()
|
||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
s.settimeout(0.5)
|
s.settimeout(0.5)
|
||||||
result = s.connect_ex((host, 80)) # Try common port
|
result = s.connect_ex((host, 80)) # Try common port
|
||||||
|
ping_time = (time.time() - start_time) * 1000 # ms
|
||||||
s.close()
|
s.close()
|
||||||
return result == 0
|
return result == 0, ping_time if result == 0 else 0
|
||||||
except:
|
except:
|
||||||
return False
|
return False, 0
|
||||||
|
|
||||||
def set_static_ip(self):
|
def set_static_ip(self):
|
||||||
interface = self.if_var.get()
|
interface = self.if_var.get()
|
||||||
|
@ -1553,11 +1691,11 @@ class IPChangerApp:
|
||||||
self.show_error("Failed to elevate privileges")
|
self.show_error("Failed to elevate privileges")
|
||||||
|
|
||||||
def show_error(self, message: str):
|
def show_error(self, message: str):
|
||||||
self.log_message(f"ERROR: {message}")
|
self.log_message(f"ERROR: {message}", "ERROR")
|
||||||
messagebox.showerror("Error", message)
|
messagebox.showerror("Error", message)
|
||||||
|
|
||||||
def show_info(self, message: str):
|
def show_info(self, message: str):
|
||||||
self.log_message(f"INFO: {message}")
|
self.log_message(f"INFO: {message}", "INFO")
|
||||||
messagebox.showinfo("Information", message)
|
messagebox.showinfo("Information", message)
|
||||||
|
|
||||||
# Add new methods for subnet mask conversion
|
# Add new methods for subnet mask conversion
|
||||||
|
@ -1782,22 +1920,17 @@ class IPChangerApp:
|
||||||
def get_hostname(self, ip_address):
|
def get_hostname(self, ip_address):
|
||||||
"""Try to resolve hostname for an IP address with better error handling"""
|
"""Try to resolve hostname for an IP address with better error handling"""
|
||||||
try:
|
try:
|
||||||
self.log_message(f"Resolving hostname for {ip_address}...")
|
# Silently try to resolve without logging the attempt
|
||||||
hostname, _, _ = socket.gethostbyaddr(ip_address)
|
hostname, _, _ = socket.gethostbyaddr(ip_address)
|
||||||
return hostname
|
return hostname
|
||||||
except socket.herror as e:
|
except socket.herror:
|
||||||
self.log_message(f"Hostname resolution error for {ip_address}: {e}")
|
# Don't log the error details - just return empty
|
||||||
return ""
|
return ""
|
||||||
except socket.gaierror as e:
|
except socket.gaierror:
|
||||||
self.log_message(f"Address-related error for {ip_address}: {e}")
|
|
||||||
return ""
|
return ""
|
||||||
except socket.timeout:
|
except socket.timeout:
|
||||||
self.log_message(f"Timeout resolving hostname for {ip_address}")
|
|
||||||
return ""
|
return ""
|
||||||
except Exception as e:
|
except Exception:
|
||||||
self.log_message(
|
|
||||||
f"Unknown error resolving hostname for {ip_address}: {str(e)}"
|
|
||||||
)
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_mac_address(self, ip_address):
|
def get_mac_address(self, ip_address):
|
||||||
|
@ -1813,10 +1946,7 @@ class IPChangerApp:
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode == 0 and result.stdout:
|
if result.returncode == 0 and result.stdout:
|
||||||
# Log the raw output for debugging
|
# Don't log the raw ARP output anymore
|
||||||
self.log_message(
|
|
||||||
f"ARP output for {ip_address}: {result.stdout.strip()}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Parse the output to find the MAC address
|
# Parse the output to find the MAC address
|
||||||
# First try the typical format with hyphens or colons
|
# First try the typical format with hyphens or colons
|
||||||
|
@ -1826,7 +1956,8 @@ class IPChangerApp:
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
if mac_match:
|
if mac_match:
|
||||||
return mac_match.group(0)
|
# Convert to uppercase for consistent display
|
||||||
|
return mac_match.group(0).upper()
|
||||||
|
|
||||||
# Try an alternative format with spaces (Windows format)
|
# Try an alternative format with spaces (Windows format)
|
||||||
mac_match = re.search(
|
mac_match = re.search(
|
||||||
|
@ -1835,7 +1966,8 @@ class IPChangerApp:
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
)
|
)
|
||||||
if mac_match:
|
if mac_match:
|
||||||
return mac_match.group(0)
|
# Convert to uppercase for consistent display
|
||||||
|
return mac_match.group(0).upper()
|
||||||
|
|
||||||
# Try yet another approach - look for any string of hex digits with separators
|
# Try yet another approach - look for any string of hex digits with separators
|
||||||
lines = result.stdout.strip().split("\n")
|
lines = result.stdout.strip().split("\n")
|
||||||
|
@ -1850,15 +1982,14 @@ class IPChangerApp:
|
||||||
parts[1],
|
parts[1],
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
):
|
):
|
||||||
return parts[1]
|
# Convert to uppercase for consistent display
|
||||||
|
return parts[1].upper()
|
||||||
|
|
||||||
self.log_message(f"No MAC address found for {ip_address}")
|
# Only return empty string if MAC not found - don't log the failure
|
||||||
return ""
|
return ""
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
self.log_message(f"Timeout running ARP command for {ip_address}")
|
|
||||||
return ""
|
return ""
|
||||||
except Exception as e:
|
except Exception:
|
||||||
self.log_message(f"Error getting MAC address for {ip_address}: {str(e)}")
|
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_mac_vendor(self, mac_address):
|
def get_mac_vendor(self, mac_address):
|
||||||
|
|
Loading…
Reference in New Issue