Agregado funcion de CIDR para el area de Scan
This commit is contained in:
parent
61d669d83a
commit
a948581619
|
@ -472,21 +472,45 @@ class IPChangerApp:
|
|||
)
|
||||
self.scan_end_entry.grid(row=0, column=3, sticky="w", padx=5)
|
||||
|
||||
# Scan buttons
|
||||
self.scan_buttons_frame = ttk.Frame(self.scan_frame)
|
||||
self.scan_buttons_frame.grid(row=0, column=4, columnspan=2, padx=5)
|
||||
|
||||
ttk.Button(self.scan_buttons_frame, text="Start Scan", command=self.start_scan).grid(
|
||||
row=0, column=0, padx=5
|
||||
# Add CIDR field in Network Scan
|
||||
ttk.Label(self.scan_frame, text="CIDR (/bits):").grid(
|
||||
row=0, column=4, sticky="w", padx=5
|
||||
)
|
||||
ttk.Button(self.scan_buttons_frame, text="Stop Scan", command=self.stop_scan).grid(
|
||||
row=0, column=1, padx=5
|
||||
)
|
||||
ttk.Button(self.scan_buttons_frame, text="Get Host Info", command=self.gather_host_information).grid(
|
||||
row=1, column=0, columnspan=2, padx=5, pady=3
|
||||
self.scan_cidr_bits = tk.StringVar(value="24")
|
||||
self.scan_cidr_entry = ttk.Entry(
|
||||
self.scan_frame, textvariable=self.scan_cidr_bits, width=5
|
||||
)
|
||||
self.scan_cidr_entry.grid(row=0, column=5, sticky="w", padx=5)
|
||||
# Add trace to update the scan range when CIDR changes
|
||||
self.scan_cidr_bits.trace("w", self.update_scan_range_from_cidr)
|
||||
|
||||
# Scan progress
|
||||
# Display number of nodes to scan
|
||||
ttk.Label(self.scan_frame, text="Nodes to scan:").grid(
|
||||
row=1, column=0, sticky="w", padx=5
|
||||
)
|
||||
self.nodes_to_scan = tk.StringVar(value="0")
|
||||
nodes_display = ttk.Entry(
|
||||
self.scan_frame, textvariable=self.nodes_to_scan, width=10, state="readonly"
|
||||
)
|
||||
nodes_display.grid(row=1, column=1, sticky="w", padx=5)
|
||||
|
||||
# Scan buttons - move to row 1, column 2-5
|
||||
self.scan_buttons_frame = ttk.Frame(self.scan_frame)
|
||||
self.scan_buttons_frame.grid(row=1, column=2, columnspan=4, padx=5, sticky="e")
|
||||
|
||||
ttk.Button(
|
||||
self.scan_buttons_frame, text="Start Scan", command=self.start_scan
|
||||
).grid(row=0, column=0, padx=5)
|
||||
ttk.Button(
|
||||
self.scan_buttons_frame, text="Stop Scan", command=self.stop_scan
|
||||
).grid(row=0, column=1, padx=5)
|
||||
ttk.Button(
|
||||
self.scan_buttons_frame,
|
||||
text="Get Host Info",
|
||||
command=self.gather_host_information,
|
||||
).grid(row=0, column=2, padx=5)
|
||||
|
||||
# Scan progress - move to row 2
|
||||
self.scan_progress = ttk.Progressbar(
|
||||
self.scan_frame,
|
||||
orient="horizontal",
|
||||
|
@ -495,18 +519,18 @@ class IPChangerApp:
|
|||
variable=self.scan_progress_var,
|
||||
)
|
||||
self.scan_progress.grid(
|
||||
row=1, column=0, columnspan=6, sticky="ew", padx=5, pady=5
|
||||
row=2, column=0, columnspan=6, sticky="ew", padx=5, pady=5
|
||||
)
|
||||
|
||||
# Scan results
|
||||
# Scan results - update row numbers
|
||||
ttk.Label(self.scan_frame, text="Scan Results:").grid(
|
||||
row=2, column=0, sticky="w", padx=5
|
||||
row=3, column=0, sticky="w", padx=5
|
||||
)
|
||||
|
||||
# Frame for results list and scrollbar
|
||||
self.results_frame = ttk.Frame(self.scan_frame)
|
||||
self.results_frame.grid(
|
||||
row=3, column=0, columnspan=6, sticky="nsew", padx=5, pady=5
|
||||
row=4, column=0, columnspan=6, sticky="nsew", padx=5, pady=5
|
||||
)
|
||||
self.results_frame.columnconfigure(0, weight=1)
|
||||
self.results_frame.rowconfigure(0, weight=1)
|
||||
|
@ -516,25 +540,25 @@ class IPChangerApp:
|
|||
self.results_frame,
|
||||
columns=("ip", "hostname", "mac"),
|
||||
show="headings",
|
||||
height=10
|
||||
height=10,
|
||||
)
|
||||
|
||||
|
||||
# Define columns
|
||||
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")
|
||||
|
||||
|
||||
# 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")
|
||||
|
||||
|
||||
# Add scrollbar
|
||||
self.scan_results_scrollbar = ttk.Scrollbar(
|
||||
self.results_frame, orient="vertical", command=self.scan_results_tree.yview
|
||||
)
|
||||
self.scan_results_tree.configure(yscrollcommand=self.scan_results_scrollbar.set)
|
||||
|
||||
|
||||
self.scan_results_tree.grid(row=0, column=0, sticky="nsew")
|
||||
self.scan_results_scrollbar.grid(row=0, column=1, sticky="ns")
|
||||
|
||||
|
@ -711,7 +735,7 @@ class IPChangerApp:
|
|||
)
|
||||
|
||||
# Actualizar IP prefix si hay una IP válida
|
||||
if (interface.ip_address):
|
||||
if interface.ip_address:
|
||||
prefix = ".".join(interface.ip_address.split(".")[:3])
|
||||
self.ip_prefix.set(prefix)
|
||||
|
||||
|
@ -1090,7 +1114,7 @@ class IPChangerApp:
|
|||
# Try to get hostname and MAC address
|
||||
hostname = self.get_hostname(target)
|
||||
mac_address = self.get_mac_address(target)
|
||||
|
||||
|
||||
if hostname:
|
||||
self.log_message(f"Hostname: {hostname}")
|
||||
if mac_address:
|
||||
|
@ -1113,10 +1137,10 @@ class IPChangerApp:
|
|||
self.show_error("Start IP must be lower than or equal to End IP")
|
||||
return
|
||||
|
||||
# Clear previous results - FIXED: use the treeview method instead of the old listbox
|
||||
# Clear previous results
|
||||
for item in self.scan_results_tree.get_children():
|
||||
self.scan_results_tree.delete(item)
|
||||
|
||||
|
||||
self.scan_results = []
|
||||
|
||||
# Calculate total IPs to scan for progress bar
|
||||
|
@ -1124,6 +1148,9 @@ class IPChangerApp:
|
|||
self.scan_progress_var.set(0)
|
||||
self.scan_progress["maximum"] = ip_range
|
||||
|
||||
# Update nodes to scan count
|
||||
self.nodes_to_scan.set(str(ip_range))
|
||||
|
||||
self.log_message(
|
||||
f"Starting scan from {start_ip} to {end_ip} ({ip_range} addresses)..."
|
||||
)
|
||||
|
@ -1176,7 +1203,9 @@ class IPChangerApp:
|
|||
self.scan_queue.put(ipaddress.IPv4Address(ip_int))
|
||||
|
||||
# Start worker threads for parallel scanning
|
||||
max_threads = min(20, ip_range) # Limit to 20 threads or fewer if range is small
|
||||
max_threads = min(
|
||||
20, ip_range
|
||||
) # Limit to 20 threads or fewer if range is small
|
||||
for i in range(max_threads):
|
||||
thread = threading.Thread(target=self._scan_worker, daemon=True)
|
||||
thread.start()
|
||||
|
@ -1215,11 +1244,10 @@ class IPChangerApp:
|
|||
ip_str = str(ip_address)
|
||||
self.log_message(f"Host discovered: {ip_str}")
|
||||
self.scan_results.append(ip_str)
|
||||
|
||||
|
||||
# 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
|
||||
|
@ -1237,54 +1265,55 @@ class IPChangerApp:
|
|||
if not self.scan_results:
|
||||
self.show_info("No hosts discovered yet. Run a scan first.")
|
||||
return
|
||||
|
||||
|
||||
# Start the information gathering in a separate thread
|
||||
threading.Thread(
|
||||
target=self._execute_host_gathering,
|
||||
daemon=True
|
||||
).start()
|
||||
threading.Thread(target=self._execute_host_gathering, daemon=True).start()
|
||||
|
||||
def _execute_host_gathering(self):
|
||||
"""Perform the actual host information gathering"""
|
||||
try:
|
||||
self.log_message(f"Gathering information for {len(self.scan_results)} hosts...")
|
||||
|
||||
self.log_message(
|
||||
f"Gathering information for {len(self.scan_results)} hosts..."
|
||||
)
|
||||
|
||||
# Reset progress bar for this operation
|
||||
total_hosts = len(self.scan_results)
|
||||
self.scan_progress_var.set(0)
|
||||
self.scan_progress["maximum"] = total_hosts
|
||||
|
||||
|
||||
# Get information for each host
|
||||
for i, ip in enumerate(self.scan_results):
|
||||
if self.scan_stop_event.is_set():
|
||||
self.log_message("Host information gathering stopped.")
|
||||
break
|
||||
|
||||
self.log_message(f"Getting information for host {ip} ({i+1}/{total_hosts})...")
|
||||
|
||||
|
||||
self.log_message(
|
||||
f"Getting information for host {ip} ({i+1}/{total_hosts})..."
|
||||
)
|
||||
|
||||
# Get hostname and MAC
|
||||
hostname = self.get_hostname(ip)
|
||||
mac_address = self.get_mac_address(ip)
|
||||
|
||||
|
||||
# Log what we found
|
||||
if hostname:
|
||||
self.log_message(f" Hostname: {hostname}")
|
||||
else:
|
||||
self.log_message(f" Hostname: Not resolved")
|
||||
|
||||
|
||||
if mac_address:
|
||||
self.log_message(f" MAC Address: {mac_address}")
|
||||
else:
|
||||
self.log_message(f" MAC Address: Not found")
|
||||
|
||||
|
||||
# Update the tree
|
||||
self.update_host_in_tree(ip, hostname, mac_address)
|
||||
|
||||
|
||||
# Update progress
|
||||
self.scan_progress_var.set(i + 1)
|
||||
|
||||
|
||||
self.log_message("Host information gathering completed.")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"Error gathering host information: {str(e)}")
|
||||
|
||||
|
@ -1293,12 +1322,14 @@ class IPChangerApp:
|
|||
try:
|
||||
# Find the item with this IP
|
||||
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:
|
||||
# Update the values
|
||||
hostname_str = hostname if hostname else "Not resolved"
|
||||
mac_str = mac if mac else "Not found"
|
||||
self.scan_results_tree.item(item_id, values=(ip, hostname_str, mac_str))
|
||||
self.scan_results_tree.item(
|
||||
item_id, values=(ip, hostname_str, mac_str)
|
||||
)
|
||||
break
|
||||
except Exception as e:
|
||||
self.log_message(f"Error updating host in treeview: {str(e)}")
|
||||
|
@ -1309,7 +1340,7 @@ class IPChangerApp:
|
|||
# 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"
|
||||
|
||||
|
||||
self.scan_results_tree.insert("", "end", values=(ip, hostname, mac))
|
||||
except Exception as e:
|
||||
self.log_message(f"Error adding scan result to UI: {str(e)}")
|
||||
|
@ -1602,6 +1633,9 @@ class IPChangerApp:
|
|||
mask_bits = bin(int(mask_obj))[2:].zfill(32)
|
||||
network_bits = mask_bits.count("1")
|
||||
|
||||
# Update the scan CIDR field
|
||||
self.scan_cidr_bits.set(str(network_bits))
|
||||
|
||||
# Create network object
|
||||
network = ipaddress.IPv4Network(
|
||||
f"{ip_address}/{network_bits}", strict=False
|
||||
|
@ -1621,11 +1655,53 @@ class IPChangerApp:
|
|||
self.scan_start_ip.set(str(start_ip))
|
||||
self.scan_end_ip.set(str(end_ip))
|
||||
|
||||
self.log_message(f"Updated scan range: {start_ip} - {end_ip}")
|
||||
# Update the nodes to scan count
|
||||
nodes_count = int(end_ip) - int(start_ip) + 1
|
||||
self.nodes_to_scan.set(str(nodes_count))
|
||||
|
||||
self.log_message(
|
||||
f"Updated scan range: {start_ip} - {end_ip} ({nodes_count} nodes)"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
self.log_message(f"Error calculating IP range: {str(e)}")
|
||||
|
||||
def update_scan_range_from_cidr(self, *args):
|
||||
"""Update scan IP range when CIDR value changes - only modify End IP"""
|
||||
try:
|
||||
start_ip = self.scan_start_ip.get().strip()
|
||||
cidr_bits = self.scan_cidr_bits.get().strip()
|
||||
|
||||
if not start_ip or not cidr_bits.isdigit():
|
||||
return
|
||||
|
||||
# Convert CIDR to network
|
||||
bits = int(cidr_bits)
|
||||
if 0 <= bits <= 32:
|
||||
# Use the start IP as the base for the network
|
||||
network = ipaddress.IPv4Network(f"{start_ip}/{bits}", strict=False)
|
||||
|
||||
# Keep the original start IP and just update the end IP
|
||||
# For the end IP, use the broadcast address (or last usable address)
|
||||
if network.num_addresses <= 2:
|
||||
end_ip = network.broadcast_address
|
||||
else:
|
||||
end_ip = network.broadcast_address - 1
|
||||
|
||||
# Update only the end IP field
|
||||
self.scan_end_ip.set(str(end_ip))
|
||||
|
||||
# Update the nodes to scan count
|
||||
start = ipaddress.IPv4Address(start_ip)
|
||||
nodes_count = int(end_ip) - int(start) + 1
|
||||
self.nodes_to_scan.set(str(nodes_count))
|
||||
|
||||
self.log_message(
|
||||
f"Updated scan range from CIDR: {start_ip} - {end_ip} ({nodes_count} nodes)"
|
||||
)
|
||||
except Exception as e:
|
||||
self.log_message(f"Error updating scan range from CIDR: {str(e)}")
|
||||
|
||||
def get_hostname(self, ip_address):
|
||||
"""Try to resolve hostname for an IP address with better error handling"""
|
||||
try:
|
||||
|
@ -1642,9 +1718,11 @@ class IPChangerApp:
|
|||
self.log_message(f"Timeout resolving hostname for {ip_address}")
|
||||
return ""
|
||||
except Exception as e:
|
||||
self.log_message(f"Unknown error resolving hostname for {ip_address}: {str(e)}")
|
||||
self.log_message(
|
||||
f"Unknown error resolving hostname for {ip_address}: {str(e)}"
|
||||
)
|
||||
return ""
|
||||
|
||||
|
||||
def get_mac_address(self, ip_address):
|
||||
"""Get MAC address for an IP using ARP on Windows with improved parsing"""
|
||||
try:
|
||||
|
@ -1654,39 +1732,49 @@ class IPChangerApp:
|
|||
shell=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=2
|
||||
timeout=2,
|
||||
)
|
||||
|
||||
|
||||
if result.returncode == 0 and result.stdout:
|
||||
# Log the raw output for debugging
|
||||
self.log_message(f"ARP output for {ip_address}: {result.stdout.strip()}")
|
||||
|
||||
self.log_message(
|
||||
f"ARP output for {ip_address}: {result.stdout.strip()}"
|
||||
)
|
||||
|
||||
# Parse the output to find the MAC address
|
||||
# First try the typical format with hyphens or colons
|
||||
mac_match = re.search(r"([0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2})",
|
||||
result.stdout,
|
||||
re.IGNORECASE)
|
||||
mac_match = re.search(
|
||||
r"([0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2}[-:][0-9A-F]{2})",
|
||||
result.stdout,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
if mac_match:
|
||||
return mac_match.group(0)
|
||||
|
||||
|
||||
# Try an alternative format with spaces (Windows format)
|
||||
mac_match = re.search(r"([0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2})",
|
||||
result.stdout,
|
||||
re.IGNORECASE)
|
||||
mac_match = re.search(
|
||||
r"([0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2}[\s-][0-9a-f]{2})",
|
||||
result.stdout,
|
||||
re.IGNORECASE,
|
||||
)
|
||||
if mac_match:
|
||||
return mac_match.group(0)
|
||||
|
||||
|
||||
# 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")
|
||||
for line in lines:
|
||||
if ip_address in line:
|
||||
parts = line.split()
|
||||
# Usually the MAC address is the second column in the output
|
||||
if len(parts) >= 2:
|
||||
# Check if the second part looks like a MAC address
|
||||
if re.match(r"([0-9a-f]{2}[^\w]){5}[0-9a-f]{2}", parts[1], re.IGNORECASE):
|
||||
if re.match(
|
||||
r"([0-9a-f]{2}[^\w]){5}[0-9a-f]{2}",
|
||||
parts[1],
|
||||
re.IGNORECASE,
|
||||
):
|
||||
return parts[1]
|
||||
|
||||
|
||||
self.log_message(f"No MAC address found for {ip_address}")
|
||||
return ""
|
||||
except subprocess.TimeoutExpired:
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"10.1.22": "10.1.22.11", "10.138.182": "10.138.182.94", "10.1.20": "10.1.20.11"}
|
||||
{"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"}
|
Loading…
Reference in New Issue