Index | Thread | Search

From:
Florian Obser <florian@openbsd.org>
Subject:
Re: installer: Default IPv6 router: use ask() to support ! and more
To:
tech@openbsd.org
Date:
Sat, 01 Feb 2025 19:32:37 +0100

Download raw body.

Thread
I like what this does. I'm not a shell hacker so I don't feel
comfortable reviewing or giving an OK.

That being said, if nobody steps up I think you should just jam this
in...

On 2025-02-01 18:21 UTC, Klemens Nanni <kn@openbsd.org> wrote:
> 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
>

-- 
In my defence, I have been left unsupervised.