feat(netconf): add input validation, 'b' to go back, 'a' to abort
- All prompts accept 'a' = abort, 'b' = back to previous step - Interface input: validate numeric range and name existence, re-prompt on bad input - IP address: regex check x.x.x.x/prefix format - Gateway: regex check x.x.x.x format - Main loop: 'b' at mode selection goes back to interface list Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,50 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Quick network configurator for the local console.
|
# Quick network configurator for the local console.
|
||||||
|
# Type 'a' at any prompt to abort, 'b' to go back.
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# List interfaces (exclude lo)
|
abort() { echo "Aborted."; exit 0; }
|
||||||
IFACES=$(ip -o link show | awk -F': ' '$2 != "lo" {print $2}' | cut -d@ -f1)
|
|
||||||
|
|
||||||
|
ask() {
|
||||||
|
# ask VARNAME "prompt" [default]
|
||||||
|
# Sets VARNAME. Returns 1 on 'b' (back), calls abort on 'a'.
|
||||||
|
_var="$1"; _prompt="$2"; _default="$3"
|
||||||
|
while true; do
|
||||||
|
if [ -n "$_default" ]; then
|
||||||
|
printf "%s [%s] (b=back a=abort): " "$_prompt" "$_default"
|
||||||
|
else
|
||||||
|
printf "%s (b=back a=abort): " "$_prompt"
|
||||||
|
fi
|
||||||
|
read _input
|
||||||
|
case "$_input" in
|
||||||
|
a|A) abort ;;
|
||||||
|
b|B) return 1 ;;
|
||||||
|
"")
|
||||||
|
if [ -n "$_default" ]; then
|
||||||
|
eval "$_var=\"\$_default\""
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo " Required — please enter a value."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
eval "$_var=\"\$_input\""
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Step 1: choose interface ───────────────────────────────────────────────────
|
||||||
|
|
||||||
|
choose_iface() {
|
||||||
|
IFACES=$(ip -o link show | awk -F': ' '$2 != "lo" {print $2}' | cut -d@ -f1)
|
||||||
|
if [ -z "$IFACES" ]; then
|
||||||
|
echo "No network interfaces found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
echo "Interfaces:"
|
echo "Interfaces:"
|
||||||
i=1
|
i=1
|
||||||
for iface in $IFACES; do
|
for iface in $IFACES; do
|
||||||
@@ -13,49 +53,111 @@ for iface in $IFACES; do
|
|||||||
i=$((i+1))
|
i=$((i+1))
|
||||||
done
|
done
|
||||||
echo ""
|
echo ""
|
||||||
printf "Interface number or name [Enter = first]: "
|
|
||||||
read INPUT
|
|
||||||
|
|
||||||
if [ -z "$INPUT" ]; then
|
FIRST=$(echo "$IFACES" | head -1)
|
||||||
IFACE=$(echo "$IFACES" | head -1)
|
while true; do
|
||||||
elif echo "$INPUT" | grep -qE '^[0-9]+$'; then
|
printf "Interface number or name [%s] (a=abort): " "$FIRST"
|
||||||
# Numeric input — resolve to name
|
read INPUT
|
||||||
|
case "$INPUT" in
|
||||||
|
a|A) abort ;;
|
||||||
|
"")
|
||||||
|
IFACE="$FIRST"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if echo "$INPUT" | grep -qE '^[0-9]+$'; then
|
||||||
IFACE=$(echo "$IFACES" | awk "NR==$INPUT")
|
IFACE=$(echo "$IFACES" | awk "NR==$INPUT")
|
||||||
if [ -z "$IFACE" ]; then
|
if [ -z "$IFACE" ]; then
|
||||||
echo "Error: no interface with number $INPUT"
|
echo " No interface #$INPUT — try again."
|
||||||
exit 1
|
continue
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
# Validate name exists
|
||||||
|
if ! echo "$IFACES" | grep -qx "$INPUT"; then
|
||||||
|
echo " Unknown interface '$INPUT' — try again."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
IFACE="$INPUT"
|
IFACE="$INPUT"
|
||||||
fi
|
fi
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
echo "Selected: $IFACE"
|
echo "Selected: $IFACE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Step 2: choose mode ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
choose_mode() {
|
||||||
echo ""
|
echo ""
|
||||||
echo " 1) DHCP"
|
echo " 1) DHCP"
|
||||||
echo " 2) Static"
|
echo " 2) Static IP"
|
||||||
printf "Mode [1]: "
|
echo ""
|
||||||
read MODE
|
while true; do
|
||||||
MODE=${MODE:-1}
|
printf "Mode [1] (b=back a=abort): "
|
||||||
|
read INPUT
|
||||||
|
case "$INPUT" in
|
||||||
|
a|A) abort ;;
|
||||||
|
b|B) return 1 ;;
|
||||||
|
""|1) MODE=dhcp; break ;;
|
||||||
|
2) MODE=static; break ;;
|
||||||
|
*) echo " Enter 1 or 2." ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
if [ "$MODE" = "1" ]; then
|
# ── Step 3a: DHCP ─────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
run_dhcp() {
|
||||||
echo "Running DHCP on $IFACE..."
|
echo "Running DHCP on $IFACE..."
|
||||||
dhclient -v "$IFACE"
|
dhclient -v "$IFACE"
|
||||||
else
|
}
|
||||||
printf "IP address (e.g. 192.168.1.100/24): "
|
|
||||||
read ADDR
|
# ── Step 3b: Static ───────────────────────────────────────────────────────────
|
||||||
printf "Gateway (e.g. 192.168.1.1): "
|
|
||||||
read GW
|
run_static() {
|
||||||
printf "DNS [8.8.8.8]: "
|
while true; do
|
||||||
read DNS
|
ask ADDR "IP address (e.g. 192.168.1.100/24)" || return 1
|
||||||
DNS=${DNS:-8.8.8.8}
|
# Basic format check: must contain a dot and a /
|
||||||
|
if ! echo "$ADDR" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/[0-9]+$'; then
|
||||||
|
echo " Invalid format — use x.x.x.x/prefix (e.g. 192.168.1.10/24)."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
ask GW "Gateway (e.g. 192.168.1.1)" || return 1
|
||||||
|
if ! echo "$GW" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
|
||||||
|
echo " Invalid IP address."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
ask DNS "DNS server" "8.8.8.8" || return 1
|
||||||
|
|
||||||
ip addr flush dev "$IFACE"
|
ip addr flush dev "$IFACE"
|
||||||
ip addr add "$ADDR" dev "$IFACE"
|
ip addr add "$ADDR" dev "$IFACE"
|
||||||
ip link set "$IFACE" up
|
ip link set "$IFACE" up
|
||||||
ip route add default via "$GW"
|
ip route add default via "$GW" 2>/dev/null || true
|
||||||
echo "nameserver $DNS" > /etc/resolv.conf
|
echo "nameserver $DNS" > /etc/resolv.conf
|
||||||
echo "Done."
|
echo "Done."
|
||||||
|
}
|
||||||
|
|
||||||
|
# ── Main loop ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
choose_iface
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
choose_mode || { choose_iface; continue; }
|
||||||
|
|
||||||
|
if [ "$MODE" = "dhcp" ]; then
|
||||||
|
run_dhcp && break
|
||||||
|
else
|
||||||
|
run_static && break || continue
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
ip -4 addr show "$IFACE"
|
ip -4 addr show "$IFACE"
|
||||||
|
|||||||
Reference in New Issue
Block a user