From fa77e0069ebee2c08060d745fe50031a823bc6ea Mon Sep 17 00:00:00 2001 From: DAProgs Date: Thu, 12 Mar 2026 21:26:54 -0400 Subject: [PATCH] First commit --- network-config.sh | 359 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 network-config.sh diff --git a/network-config.sh b/network-config.sh new file mode 100644 index 0000000..d7465e0 --- /dev/null +++ b/network-config.sh @@ -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/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