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:
2026-03-28 07:31:23 +03:00
parent 600ece911b
commit 14fa87b7d7

View File

@@ -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"