Updated IP configuration and history format; added support for last used subnet mask and improved history management with subnet masks.
This commit is contained in:
parent
8f7bd969de
commit
f8b13c7bab
|
@ -1 +1 @@
|
||||||
{"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}}
|
{"last_interface": "Ethernet", "last_ip_prefix": "10.1.33", "previous_config": {"name": "Ethernet", "ip_address": "192.168.88.249", "subnet_mask": "255.255.255.0", "gateway": "192.168.88.1", "dhcp_enabled": false}, "last_subnet_mask": "255.240.0.0"}
|
|
@ -1 +1 @@
|
||||||
["10.1.22", "169.254.38", "10.1.20", "10.146.76", "192.168.0", "10.101.8", "10.1.33", "10.1.92", "192.168.121", "192.168.1", "169.254.3", "10.202.4", "192.168.2", "10.1.30", "192.168.88"]
|
[{"prefix": "10.1.33", "mask": "255.240.0.0"}, {"prefix": "192.168.88", "mask": "255.255.255.0"}, {"prefix": "192.168.199", "mask": "255.255.255.0"}, {"prefix": "192.168.200", "mask": "255.255.255.0"}, {"prefix": "10.202.4", "mask": "255.255.0.0"}, {"prefix": "169.254.38", "mask": "255.255.0.0"}, {"prefix": "192.168.1", "mask": "255.255.255.0"}, {"prefix": "169.254.69", "mask": "255.255.0.0"}, {"prefix": "192.168.212", "mask": "255.255.255.0"}, {"prefix": "10.1.20", "mask": "255.240.0.0"}, {"prefix": "10.1.22", "mask": "255.255.255.0"}, {"prefix": "10.146.76", "mask": "255.255.255.0"}, {"prefix": "192.168.0", "mask": "255.255.255.0"}, {"prefix": "10.101.8", "mask": "255.255.255.0"}, {"prefix": "10.1.92", "mask": "255.255.255.0"}]
|
|
@ -90,15 +90,21 @@ class IPChangeConfig:
|
||||||
self.last_interface = config.get("last_interface", "")
|
self.last_interface = config.get("last_interface", "")
|
||||||
self.last_ip_prefix = config.get("last_ip_prefix", "")
|
self.last_ip_prefix = config.get("last_ip_prefix", "")
|
||||||
self.previous_config = config.get("previous_config", {})
|
self.previous_config = config.get("previous_config", {})
|
||||||
|
# Add support for last used subnet mask
|
||||||
|
self.last_subnet_mask = config.get(
|
||||||
|
"last_subnet_mask", "255.255.255.0"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.last_interface = ""
|
self.last_interface = ""
|
||||||
self.last_ip_prefix = ""
|
self.last_ip_prefix = ""
|
||||||
self.previous_config = {}
|
self.previous_config = {}
|
||||||
|
self.last_subnet_mask = "255.255.255.0"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error loading config: {e}")
|
print(f"Error loading config: {e}")
|
||||||
self.last_interface = ""
|
self.last_interface = ""
|
||||||
self.last_ip_prefix = ""
|
self.last_ip_prefix = ""
|
||||||
self.previous_config = {}
|
self.previous_config = {}
|
||||||
|
self.last_subnet_mask = "255.255.255.0"
|
||||||
|
|
||||||
def save_config(self):
|
def save_config(self):
|
||||||
try:
|
try:
|
||||||
|
@ -106,6 +112,8 @@ class IPChangeConfig:
|
||||||
"last_interface": self.last_interface,
|
"last_interface": self.last_interface,
|
||||||
"last_ip_prefix": self.last_ip_prefix,
|
"last_ip_prefix": self.last_ip_prefix,
|
||||||
"previous_config": self.previous_config,
|
"previous_config": self.previous_config,
|
||||||
|
# Save last used subnet mask
|
||||||
|
"last_subnet_mask": self.last_subnet_mask,
|
||||||
}
|
}
|
||||||
with open(self.config_file, "w") as f:
|
with open(self.config_file, "w") as f:
|
||||||
json.dump(config, f)
|
json.dump(config, f)
|
||||||
|
@ -435,6 +443,39 @@ class IPChangerApp:
|
||||||
self.cidr_entry = ttk.Entry(subnet_frame, textvariable=self.cidr_bits, width=5)
|
self.cidr_entry = ttk.Entry(subnet_frame, textvariable=self.cidr_bits, width=5)
|
||||||
self.cidr_entry.pack(side=tk.LEFT)
|
self.cidr_entry.pack(side=tk.LEFT)
|
||||||
|
|
||||||
|
# Add CIDR preset buttons - Fix: Create a standalone function for each button
|
||||||
|
cidr_presets_frame = ttk.Frame(subnet_frame)
|
||||||
|
cidr_presets_frame.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
# Fix: Use individual buttons with direct command references, not lambda
|
||||||
|
ttk.Button(
|
||||||
|
cidr_presets_frame,
|
||||||
|
text="/8",
|
||||||
|
width=4,
|
||||||
|
command=lambda: self.set_cidr_preset(8),
|
||||||
|
).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
ttk.Button(
|
||||||
|
cidr_presets_frame,
|
||||||
|
text="/12",
|
||||||
|
width=4,
|
||||||
|
command=lambda: self.set_cidr_preset(12),
|
||||||
|
).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
ttk.Button(
|
||||||
|
cidr_presets_frame,
|
||||||
|
text="/16",
|
||||||
|
width=4,
|
||||||
|
command=lambda: self.set_cidr_preset(16),
|
||||||
|
).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
ttk.Button(
|
||||||
|
cidr_presets_frame,
|
||||||
|
text="/24",
|
||||||
|
width=4,
|
||||||
|
command=lambda: self.set_cidr_preset(24),
|
||||||
|
).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
# Sección de historial
|
# Sección de historial
|
||||||
self.history_frame = ttk.LabelFrame(
|
self.history_frame = ttk.LabelFrame(
|
||||||
self.control_frame, text="IP History", padding="5"
|
self.control_frame, text="IP History", padding="5"
|
||||||
|
@ -722,7 +763,16 @@ class IPChangerApp:
|
||||||
try:
|
try:
|
||||||
if os.path.exists(self.config.history_file):
|
if os.path.exists(self.config.history_file):
|
||||||
with open(self.config.history_file, "r") as f:
|
with open(self.config.history_file, "r") as f:
|
||||||
self.ip_history = json.load(f)
|
history_data = json.load(f)
|
||||||
|
# Check if history is in old format (just list of IPs)
|
||||||
|
if history_data and isinstance(history_data[0], str):
|
||||||
|
# Convert old format to new format with masks
|
||||||
|
self.ip_history = [
|
||||||
|
{"prefix": ip, "mask": "255.255.255.0"}
|
||||||
|
for ip in history_data
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
self.ip_history = history_data
|
||||||
else:
|
else:
|
||||||
self.ip_history = []
|
self.ip_history = []
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -737,31 +787,79 @@ class IPChangerApp:
|
||||||
self.log_message(f"Error saving IP history: {e}")
|
self.log_message(f"Error saving IP history: {e}")
|
||||||
|
|
||||||
def add_to_history(self, ip_prefix: str):
|
def add_to_history(self, ip_prefix: str):
|
||||||
if ip_prefix and ip_prefix not in self.ip_history:
|
if not ip_prefix:
|
||||||
self.ip_history.insert(0, ip_prefix)
|
return
|
||||||
self.ip_history = self.ip_history[:15] # Mantener solo las últimas 15 IPs
|
|
||||||
self.save_ip_history()
|
# Get current subnet mask
|
||||||
self.update_history_display()
|
subnet_mask = self.subnet_mask.get().strip()
|
||||||
|
|
||||||
|
# Look for this prefix in history
|
||||||
|
existing_index = -1
|
||||||
|
for i, entry in enumerate(self.ip_history):
|
||||||
|
if entry["prefix"] == ip_prefix:
|
||||||
|
existing_index = i
|
||||||
|
break
|
||||||
|
|
||||||
|
if existing_index >= 0:
|
||||||
|
# Found existing entry - update mask and move to top
|
||||||
|
entry = self.ip_history.pop(existing_index)
|
||||||
|
entry["mask"] = subnet_mask
|
||||||
|
self.ip_history.insert(0, entry)
|
||||||
|
else:
|
||||||
|
# New entry - add to top
|
||||||
|
self.ip_history.insert(0, {"prefix": ip_prefix, "mask": subnet_mask})
|
||||||
|
|
||||||
|
# Keep only the latest 15 entries
|
||||||
|
self.ip_history = self.ip_history[:15]
|
||||||
|
|
||||||
|
# Save and update display
|
||||||
|
self.save_ip_history()
|
||||||
|
self.update_history_display()
|
||||||
|
|
||||||
|
# Save the last used subnet mask
|
||||||
|
self.config.last_subnet_mask = subnet_mask
|
||||||
|
self.config.save_config()
|
||||||
|
|
||||||
def update_history_display(self):
|
def update_history_display(self):
|
||||||
self.history_combo["values"] = self.ip_history
|
# Create display values for combo box - show prefix and mask
|
||||||
if self.ip_history:
|
display_values = [
|
||||||
self.history_combo.set(self.ip_history[0])
|
f"{entry['prefix']} ({entry['mask']})" for entry in self.ip_history
|
||||||
|
]
|
||||||
|
self.history_combo["values"] = display_values
|
||||||
|
if display_values:
|
||||||
|
self.history_combo.set(display_values[0])
|
||||||
|
|
||||||
def on_history_selected(self, event):
|
def on_history_selected(self, event):
|
||||||
selected_ip = self.history_var.get()
|
selected_value = self.history_var.get()
|
||||||
if selected_ip:
|
if not selected_value:
|
||||||
# Ensure we only get the first three octets
|
return
|
||||||
ip_parts = selected_ip.split(".")
|
|
||||||
if len(ip_parts) >= 3:
|
|
||||||
ip_prefix = ".".join(ip_parts[:3])
|
|
||||||
self.ip_prefix.set(ip_prefix)
|
|
||||||
self.config.last_ip_prefix = ip_prefix
|
|
||||||
self.config.save_config()
|
|
||||||
self.log_message(f"Selected IP prefix from history: {ip_prefix}")
|
|
||||||
|
|
||||||
# Update ping target for the new IP prefix
|
# Parse the prefix from the display string
|
||||||
self.update_ping_target(ip_prefix)
|
ip_parts = selected_value.split()[0] # Get first part before space
|
||||||
|
if "(" in ip_parts: # For safety, handle both formats
|
||||||
|
ip_parts = ip_parts.split("(")[0].strip()
|
||||||
|
|
||||||
|
# Ensure we only get the first three octets
|
||||||
|
parts = ip_parts.split(".")
|
||||||
|
if len(parts) >= 3:
|
||||||
|
ip_prefix = ".".join(parts[:3])
|
||||||
|
self.ip_prefix.set(ip_prefix)
|
||||||
|
self.config.last_ip_prefix = ip_prefix
|
||||||
|
|
||||||
|
# Find the selected entry in history
|
||||||
|
for entry in self.ip_history:
|
||||||
|
if entry["prefix"] == ip_prefix:
|
||||||
|
# Set the subnet mask from history
|
||||||
|
self.subnet_mask.set(entry["mask"])
|
||||||
|
# Move this entry to top of history (most recently used)
|
||||||
|
self.add_to_history(ip_prefix)
|
||||||
|
break
|
||||||
|
|
||||||
|
self.config.save_config()
|
||||||
|
self.log_message(f"Selected IP prefix from history: {ip_prefix}")
|
||||||
|
|
||||||
|
# Update ping target for the new IP prefix
|
||||||
|
self.update_ping_target(ip_prefix)
|
||||||
|
|
||||||
def refresh_interfaces(self):
|
def refresh_interfaces(self):
|
||||||
self.interfaces.clear()
|
self.interfaces.clear()
|
||||||
|
@ -882,6 +980,10 @@ class IPChangerApp:
|
||||||
prefix = ".".join(interface.ip_address.split(".")[:3])
|
prefix = ".".join(interface.ip_address.split(".")[:3])
|
||||||
self.ip_prefix.set(prefix)
|
self.ip_prefix.set(prefix)
|
||||||
|
|
||||||
|
# Set subnet mask from interface
|
||||||
|
if interface.subnet_mask:
|
||||||
|
self.subnet_mask.set(interface.subnet_mask)
|
||||||
|
|
||||||
# Update ping target for the new IP prefix
|
# Update ping target for the new IP prefix
|
||||||
self.update_ping_target(prefix)
|
self.update_ping_target(prefix)
|
||||||
|
|
||||||
|
@ -1595,7 +1697,7 @@ class IPChangerApp:
|
||||||
ip = result
|
ip = result
|
||||||
subnet_mask = self.subnet_mask.get()
|
subnet_mask = self.subnet_mask.get()
|
||||||
|
|
||||||
# Guardar IP actual en el historial
|
# Guardar IP actual en el historial con la máscara de subred
|
||||||
self.add_to_history(self.ip_prefix.get())
|
self.add_to_history(self.ip_prefix.get())
|
||||||
|
|
||||||
# Log the actual command we'll be executing
|
# Log the actual command we'll be executing
|
||||||
|
@ -2016,6 +2118,13 @@ class IPChangerApp:
|
||||||
self.log_message(f"Error looking up MAC vendor: {str(e)}")
|
self.log_message(f"Error looking up MAC vendor: {str(e)}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
# Method to handle CIDR preset buttons
|
||||||
|
def set_cidr_preset(self, cidr_bits):
|
||||||
|
"""Set CIDR to a preset value"""
|
||||||
|
self.log_message(f"Setting CIDR to preset: /{cidr_bits}")
|
||||||
|
self.cidr_bits.set(str(cidr_bits))
|
||||||
|
# The on_cidr_bits_changed trace will update the subnet mask automatically
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
{"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"}
|
{"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", "192.168.212": "192.168.212.212", "192.168.1": "192.168.1.212", "10.1.33": "192.168.88.1", "192.168.193": "192.168.1.212"}
|
|
@ -0,0 +1,59 @@
|
||||||
|
# Network Interface IP Configuration Utility
|
||||||
|
|
||||||
|
A Python-based desktop application for managing and configuring network interfaces on Windows systems.
|
||||||
|
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Easy IP Configuration**: Quickly set static IP addresses or enable DHCP
|
||||||
|
- **IP History**: Remembers previously used IP addresses for quick switching
|
||||||
|
- **Network Tools**: Built-in ping tool with continuous ping support
|
||||||
|
- **Network Scanner**: Discover active hosts on your network
|
||||||
|
- **Host Information**: Lookup hostname and MAC address information
|
||||||
|
- **MAC Vendor Lookup**: Identify device manufacturers by MAC address
|
||||||
|
|
||||||
|
## Key Functions
|
||||||
|
|
||||||
|
- Change IP address and subnet mask with administrator privileges
|
||||||
|
- Ping hosts with detailed response information
|
||||||
|
- Scan IP ranges to discover active hosts
|
||||||
|
- Save and restore network configurations
|
||||||
|
- View MAC addresses and vendor information
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Windows operating system
|
||||||
|
- Python 3.6+
|
||||||
|
- See requirements.txt for Python dependencies
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Clone this repository:
|
||||||
|
```
|
||||||
|
git clone https://github.com/miguefinghub/IPchangeNG.git
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Install required dependencies:
|
||||||
|
```
|
||||||
|
pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run the application:
|
||||||
|
```
|
||||||
|
python menu-ip-change.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Administrative privileges are required to change network settings.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
See the [Wiki](WIKI.md) for detailed usage instructions.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](LICENSE)
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
- Uses various Python libraries for network operations
|
||||||
|
- MAC vendor lookup provided by the mac-vendor-lookup package
|
|
@ -1,8 +1,6 @@
|
||||||
# Network-related packages
|
tkinter>=8.6
|
||||||
pythonping>=1.1.4
|
pythonping>=1.1.0
|
||||||
pysnmp>=4.4.12
|
pysnmp>=4.4.12
|
||||||
wmi>=1.5.1
|
wmi>=1.5.1
|
||||||
mac-vendor-lookup>=0.1.11
|
mac-vendor-lookup>=0.1.11
|
||||||
|
ipaddress>=1.0.23
|
||||||
# Other dependencies
|
|
||||||
ipaddress>=1.0.23
|
|
Loading…
Reference in New Issue