From: Klemens Nanni Subject: installer: Default IPv6 router: use ask() to support ! and more To: tech@openbsd.org Date: Sat, 1 Feb 2025 18:21:00 +0000 The interactive version of this question is backed by ksh(1)'s select instead of the intaller's ask*() routines, meaning - available routers are printed before the answer (or on empty input) without explanation - none is explicitly listed - the answer is not recorded in the response file - ! does not drop into a shell - ? is not supported Network interface to configure? (name, lladdr, '?', or 'done') [done] 1) none 2) fe80::fce1:baff:fed0:9371%vio0 IPv6 default router? (list #, IPv6 address or 'none') ! route: !: non-recoverable failure in name resolution route: !: non-recoverable failure in name resolution IPv6 default router? (list #, IPv6 address or 'none') ? route: ?: non-recoverable failure in name resolution route: ?: non-recoverable failure in name resolution IPv6 default router? (list #, IPv6 address or 'none') 0 route: 0: no address associated with name route: 0: no address associated with name IPv6 default router? (list #, IPv6 address or 'none') foo route: foo: no address associated with name route: foo: no address associated with name I had to do route(8)'s last EXAMPLE when this forced me to abort the install to run commands earlier... Let's switch the only select usage to ask_until(), making it very similar to how 'Default IPv4 route?' and 'Access Point?' are done: IPv6 default router? (IPv6 address, list#, 'none' or '?') ! Type 'exit' to return to install. test# ^D IPv6 default router? (IPv6 address, list#, 'none' or '?') ? 1 fe80::fce1:baff:fed0:9371%vio0 IPv6 default router? (IPv6 address, list#, 'none' or '?') 0 0 is not a valid choice. IPv6 default router? (IPv6 address, list#, 'none' or '?') foo route: foo: no address associated with name route: foo: no address associated with name (A)utoinstall(8) is uneffected. The interactive/unattended paths could be merged, but not without more churn, so here's the first step. Feedback? OK? This code runs so early, that you can even test it locally without disk or real network; once a router is picked, the rest is the same: # vmctl start -c -i1 -b./bsd.rd foo ... IPv6 address for vio0? (or 'autoconf' or 'none') [none] 2001:db8::1/64 Available network interfaces are: vio0 vlan0. Network interface to configure? (name, lladdr, '?', or 'done') [done] IPv6 default router? (IPv6 address, list#, 'none' or '?') 2001:db8::2 add net default: gateway 2001:db8::2 Index: install.sub =================================================================== RCS file: /cvs/src/distrib/miniroot/install.sub,v diff -u -p -r1.1266 install.sub --- install.sub 9 Jul 2024 14:47:21 -0000 1.1266 +++ install.sub 1 Feb 2025 16:44:42 -0000 @@ -1146,7 +1146,7 @@ v6_info() { # in the /etc/mygate file. Ask the user to either select from a list of default # router candidates or to enter a router IPv6 address. v6_defroute() { - local _if _v6ifs _prompt _resp _routers _dr PS3 + local _if _v6ifs _prompt _resp _routers _dr # Only configure a default route if an IPv6 address was manually configured. for _if in $(get_ifs); do @@ -1179,14 +1179,30 @@ v6_defroute() { route -n add -inet6 -host default $resp && echo $resp >>/tmp/i/mygate else - PS3="$_prompt (list #, IPv6 address or 'none') " - select _resp in none $_routers; do - [[ $REPLY == none || $_resp == none ]] && break - [[ -z $_resp ]] && _resp=$REPLY + set -A _routers -- $_routers + while :; do + ask_until "$_prompt (IPv6 address, list#, 'none' or '?')" + case $resp in + none) return + ;; + '?') for _dr in ${_routers[@]}; do + echo $_dr + done | cat -n + continue + ;; + +([0-9])) + if ((resp < 1 || resp > ${#_routers[@]})); then + echo "$resp is not a valid choice." + continue + fi + resp=${_routers[$((--resp))]} + ;; + esac + # Avoid possible "file exists" errors - route -n -q delete -inet6 -host default $_resp - if route -n add -inet6 -host default $_resp; then - echo $_resp >>/tmp/i/mygate + route -n -q delete -inet6 -host default "$resp" + if route -n add -inet6 -host default "$resp"; then + echo "$resp" >>/tmp/i/mygate break fi done