First commit
This commit is contained in:
359
network-config.sh
Normal file
359
network-config.sh
Normal file
@@ -0,0 +1,359 @@
|
||||
#!/bin/bash
|
||||
|
||||
INTERFACES_FILE="/etc/network/interfaces"
|
||||
|
||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
get_interfaces() {
|
||||
ls /sys/class/net/ 2>/dev/null | grep -v '^lo$'
|
||||
}
|
||||
|
||||
get_ip() {
|
||||
local iface="$1"
|
||||
ip -4 addr show "$iface" 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f1
|
||||
}
|
||||
|
||||
get_netmask() {
|
||||
local iface="$1"
|
||||
local prefix
|
||||
prefix=$(ip -4 addr show "$iface" 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f2)
|
||||
[ -z "$prefix" ] && return
|
||||
python3 -c "import ipaddress; print(ipaddress.IPv4Network('0.0.0.0/$prefix', strict=False).netmask)" 2>/dev/null
|
||||
}
|
||||
|
||||
get_gateway() {
|
||||
ip route show default 2>/dev/null | awk '/default/{print $3; exit}'
|
||||
}
|
||||
|
||||
is_dhcp() {
|
||||
local iface="$1"
|
||||
grep -A5 "iface $iface" "$INTERFACES_FILE" 2>/dev/null | grep -q "dhcp"
|
||||
}
|
||||
|
||||
# ── arrow-key menu ────────────────────────────────────────────────────────────
|
||||
# Usage: arrow_menu result_var "Item 1" "Item 2" ...
|
||||
# Sets result_var to the 0-based index of the chosen item.
|
||||
|
||||
arrow_menu() {
|
||||
local -n _res="$1"; shift
|
||||
local items=("$@")
|
||||
local count=${#items[@]}
|
||||
local cur=0
|
||||
|
||||
tput civis
|
||||
trap 'tput cnorm; echo; exit 130' INT
|
||||
|
||||
_draw_menu() {
|
||||
for (( i=0; i<count; i++ )); do
|
||||
tput el
|
||||
if [ "$i" -eq "$cur" ]; then
|
||||
printf " \e[1;7m %-72s \e[0m\n" "${items[$i]}"
|
||||
else
|
||||
printf " %-72s\n" "${items[$i]}"
|
||||
fi
|
||||
done
|
||||
tput cuu "$count"
|
||||
}
|
||||
|
||||
# reserve lines
|
||||
for (( i=0; i<count; i++ )); do printf "\n"; done
|
||||
tput cuu "$count"
|
||||
_draw_menu
|
||||
|
||||
local key esc
|
||||
while true; do
|
||||
IFS= read -rsn1 key
|
||||
if [[ "$key" == $'\x1b' ]]; then
|
||||
IFS= read -rsn2 -t 0.05 esc
|
||||
key+="$esc"
|
||||
fi
|
||||
case "$key" in
|
||||
$'\x1b[A') (( cur = (cur - 1 + count) % count )); _draw_menu ;;
|
||||
$'\x1b[B') (( cur = (cur + 1) % count )); _draw_menu ;;
|
||||
'') tput cud "$count"; break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
tput cnorm
|
||||
trap - INT
|
||||
_res=$cur
|
||||
}
|
||||
|
||||
# ── status box ────────────────────────────────────────────────────────────────
|
||||
|
||||
show_status() {
|
||||
clear
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ Network Interface Status ║"
|
||||
echo "╠══════════════════════════════════════════════════════════════════════════╣"
|
||||
echo "║ ║"
|
||||
|
||||
local ifaces
|
||||
mapfile -t ifaces < <(get_interfaces)
|
||||
|
||||
if [ ${#ifaces[@]} -eq 0 ]; then
|
||||
echo "║ No interfaces found ║"
|
||||
echo "║ ║"
|
||||
else
|
||||
for iface in "${ifaces[@]}"; do
|
||||
local ip netmask gw method
|
||||
ip=$(get_ip "$iface")
|
||||
netmask=$(get_netmask "$iface")
|
||||
gw=$(get_gateway)
|
||||
ip=${ip:-"(no IP)"}
|
||||
netmask=${netmask:-"(unknown)"}
|
||||
gw=${gw:-"(none)"}
|
||||
|
||||
if is_dhcp "$iface"; then
|
||||
method="DHCP"
|
||||
elif grep -A5 "iface $iface" "$INTERFACES_FILE" 2>/dev/null | grep -q "static"; then
|
||||
method="Static"
|
||||
else
|
||||
method="Unknown"
|
||||
fi
|
||||
|
||||
printf "║ Interface : %-20s Mode: %-10s ║\n" "$iface" "$method"
|
||||
printf "║ IP Address: %-45s ║\n" "$ip"
|
||||
printf "║ Netmask : %-45s ║\n" "$netmask"
|
||||
printf "║ Gateway : %-45s ║\n" "$gw"
|
||||
echo "║ ║"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
echo " Use ↑ ↓ to navigate, Enter to select, Ctrl+C to exit"
|
||||
echo ""
|
||||
}
|
||||
|
||||
# ── select interface ──────────────────────────────────────────────────────────
|
||||
|
||||
select_interface() {
|
||||
local ifaces
|
||||
mapfile -t ifaces < <(get_interfaces)
|
||||
|
||||
if [ ${#ifaces[@]} -eq 0 ]; then
|
||||
echo "No network interfaces found."
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ${#ifaces[@]} -eq 1 ]; then
|
||||
SELECTED_IFACE="${ifaces[0]}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
clear
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ Select Interface ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
local choice
|
||||
arrow_menu choice "${ifaces[@]}"
|
||||
echo ""
|
||||
SELECTED_IFACE="${ifaces[$choice]}"
|
||||
}
|
||||
|
||||
# ── validate IPv4 ─────────────────────────────────────────────────────────────
|
||||
|
||||
valid_ip() {
|
||||
local ip="$1"
|
||||
[[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]] || return 1
|
||||
IFS='.' read -ra octets <<< "$ip"
|
||||
for octet in "${octets[@]}"; do
|
||||
[ "$octet" -le 255 ] || return 1
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# ── set static IP ─────────────────────────────────────────────────────────────
|
||||
|
||||
set_static() {
|
||||
local iface="$1"
|
||||
local new_ip new_netmask new_gw
|
||||
|
||||
clear
|
||||
echo ""
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════╗"
|
||||
printf "║ Configure Static IP ── Interface: %-34s║\n" "$iface "
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
local cur_ip cur_mask cur_gw
|
||||
cur_ip=$(get_ip "$iface")
|
||||
cur_mask=$(get_netmask "$iface")
|
||||
cur_gw=$(get_gateway)
|
||||
|
||||
while true; do
|
||||
read -rp " IP address [${cur_ip:-?}]: " new_ip
|
||||
new_ip="${new_ip:-$cur_ip}"
|
||||
valid_ip "$new_ip" && break
|
||||
echo " Invalid IP address. Try again."
|
||||
done
|
||||
|
||||
while true; do
|
||||
read -rp " Netmask [${cur_mask:-255.255.255.0}]: " new_netmask
|
||||
new_netmask="${new_netmask:-${cur_mask:-255.255.255.0}}"
|
||||
valid_ip "$new_netmask" && break
|
||||
echo " Invalid netmask. Try again."
|
||||
done
|
||||
|
||||
while true; do
|
||||
read -rp " Gateway [${cur_gw:-?}]: " new_gw
|
||||
new_gw="${new_gw:-$cur_gw}"
|
||||
valid_ip "$new_gw" && break
|
||||
echo " Invalid gateway. Try again."
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "┌──────────────────────────────────────────────────────────────────────────┐"
|
||||
echo "│ Summary │"
|
||||
printf "│ Interface : %-58s │\n" "$iface"
|
||||
printf "│ IP Address: %-58s │\n" "$new_ip"
|
||||
printf "│ Netmask : %-58s │\n" "$new_netmask"
|
||||
printf "│ Gateway : %-58s │\n" "$new_gw"
|
||||
echo "└──────────────────────────────────────────────────────────────────────────┘"
|
||||
echo ""
|
||||
read -rp "Apply these settings? [y/N]: " confirm
|
||||
[[ "$confirm" =~ ^[Yy]$ ]] || { echo "Cancelled."; return; }
|
||||
|
||||
if [ -f "$INTERFACES_FILE" ]; then
|
||||
cp "$INTERFACES_FILE" "${INTERFACES_FILE}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
fi
|
||||
|
||||
write_interfaces "$iface" "static" "$new_ip" "$new_netmask" "$new_gw"
|
||||
|
||||
echo ""
|
||||
echo " Written to $INTERFACES_FILE"
|
||||
echo " Applying configuration..."
|
||||
|
||||
if command -v ifdown &>/dev/null; then
|
||||
ifdown "$iface" 2>/dev/null
|
||||
ifup "$iface" 2>/dev/null && echo " Done." || echo " ifup failed — you may need to reconnect manually."
|
||||
else
|
||||
ip addr flush dev "$iface" 2>/dev/null
|
||||
ip addr add "${new_ip}/$(mask_to_cidr "$new_netmask")" dev "$iface" 2>/dev/null
|
||||
ip route add default via "$new_gw" 2>/dev/null
|
||||
ip link set "$iface" up 2>/dev/null
|
||||
echo " Done (applied via iproute2)."
|
||||
fi
|
||||
}
|
||||
|
||||
# ── set DHCP ──────────────────────────────────────────────────────────────────
|
||||
|
||||
set_dhcp() {
|
||||
local iface="$1"
|
||||
|
||||
echo ""
|
||||
read -rp "Switch $iface to DHCP? [y/N]: " confirm
|
||||
[[ "$confirm" =~ ^[Yy]$ ]] || { echo "Cancelled."; return; }
|
||||
|
||||
if [ -f "$INTERFACES_FILE" ]; then
|
||||
cp "$INTERFACES_FILE" "${INTERFACES_FILE}.bak.$(date +%Y%m%d%H%M%S)"
|
||||
fi
|
||||
|
||||
write_interfaces "$iface" "dhcp"
|
||||
|
||||
echo " Written to $INTERFACES_FILE"
|
||||
echo " Applying configuration..."
|
||||
|
||||
if command -v ifdown &>/dev/null; then
|
||||
ifdown "$iface" 2>/dev/null
|
||||
ifup "$iface" 2>/dev/null && echo " Done." || echo " ifup failed — check your DHCP server."
|
||||
else
|
||||
ip addr flush dev "$iface" 2>/dev/null
|
||||
dhclient "$iface" 2>/dev/null && echo " Done." || echo " dhclient failed."
|
||||
fi
|
||||
}
|
||||
|
||||
# ── write /etc/network/interfaces ────────────────────────────────────────────
|
||||
|
||||
write_interfaces() {
|
||||
local target_iface="$1"
|
||||
local method="$2"
|
||||
local new_ip="$3"
|
||||
local new_netmask="$4"
|
||||
local new_gw="$5"
|
||||
|
||||
local tmpfile
|
||||
tmpfile=$(mktemp)
|
||||
|
||||
if ! grep -q "iface lo" "$INTERFACES_FILE" 2>/dev/null; then
|
||||
printf "auto lo\niface lo inet loopback\n\n" >> "$tmpfile"
|
||||
fi
|
||||
|
||||
if [ -f "$INTERFACES_FILE" ]; then
|
||||
awk -v iface="$target_iface" '
|
||||
/^(auto|allow-hotplug|iface) / && $0 ~ iface { skip=1 }
|
||||
skip && /^(auto|allow-hotplug|iface) / && $0 !~ iface { skip=0 }
|
||||
!skip { print }
|
||||
' "$INTERFACES_FILE" >> "$tmpfile"
|
||||
fi
|
||||
|
||||
{
|
||||
echo ""
|
||||
echo "auto $target_iface"
|
||||
if [ "$method" = "static" ]; then
|
||||
echo "iface $target_iface inet static"
|
||||
echo " address $new_ip"
|
||||
echo " netmask $new_netmask"
|
||||
echo " gateway $new_gw"
|
||||
else
|
||||
echo "iface $target_iface inet dhcp"
|
||||
fi
|
||||
} >> "$tmpfile"
|
||||
|
||||
mv "$tmpfile" "$INTERFACES_FILE"
|
||||
}
|
||||
|
||||
# ── cidr helper ───────────────────────────────────────────────────────────────
|
||||
|
||||
mask_to_cidr() {
|
||||
python3 -c "
|
||||
import ipaddress
|
||||
print(ipaddress.IPv4Network('0.0.0.0/$1', strict=False).prefixlen)
|
||||
" 2>/dev/null || echo "24"
|
||||
}
|
||||
|
||||
# ── main menu ─────────────────────────────────────────────────────────────────
|
||||
|
||||
MENU_ITEMS=("Set Static IP" "Set DHCP" "Refresh")
|
||||
|
||||
main_menu() {
|
||||
local choice
|
||||
while true; do
|
||||
show_status
|
||||
arrow_menu choice "${MENU_ITEMS[@]}"
|
||||
echo ""
|
||||
|
||||
case "$choice" in
|
||||
0)
|
||||
if select_interface; then
|
||||
set_static "$SELECTED_IFACE"
|
||||
fi
|
||||
echo ""
|
||||
read -rp "Press Enter to continue..."
|
||||
;;
|
||||
1)
|
||||
if select_interface; then
|
||||
set_dhcp "$SELECTED_IFACE"
|
||||
fi
|
||||
echo ""
|
||||
read -rp "Press Enter to continue..."
|
||||
;;
|
||||
2)
|
||||
;; # just redraw
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# ── entry point ───────────────────────────────────────────────────────────────
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "This script must be run as root (use sudo)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
main_menu
|
||||
Reference in New Issue
Block a user