Browse Source

Introduce a new function parse_hn_line() that replaces the existing

hostname.if(5) parsing code in ifstart().
Add a -n option to netstart to only print the interface configuration
commands instead of executing them.
Add a HN_DIR variable, that points to the directory of the hostname.if
files (default /etc) that allows for future regression tests.
- add new parse_hn_line() function
- change ifstart()
- rename $if to $_if
- don't ifconfig or ifconfig create if -n option is used
- replace hostname.if(5) parsing code with new parse_hn_line()
- just print configuration commands if -n option is used
- autoconf now happens in ifstart(), remove ifv6autoconf()
- introduce HN_DIR variable for the hostname.if file location
- add handling of the -n option to only print config commands
- ensure -n is only used if interfaces are specified as parameters
Discussed with and positive feedback from many
'commit' deraadt@
OK sthen@
OPENBSD_6_2
rpe 7 years ago
parent
commit
e160122c5d
1 changed files with 103 additions and 94 deletions
  1. +103
    -94
      src/etc/netstart

+ 103
- 94
src/etc/netstart View File

@ -1,6 +1,6 @@
#!/bin/sh - #!/bin/sh -
# #
# $OpenBSD: netstart,v 1.176 2017/04/08 08:33:05 rpe Exp $
# $OpenBSD: netstart,v 1.177 2017/04/24 20:31:48 rpe Exp $
# Turn off Strict Bourne shell mode. # Turn off Strict Bourne shell mode.
set +o sh set +o sh
@ -19,21 +19,80 @@ stripcom() {
done <$_file done <$_file
} }
# Parse and "unpack" a hostname.if(5) line given as positional parameters.
# Fill the _cmds array with the resulting interface configuration commands.
parse_hn_line() {
local _af=0 _name=1 _mask=2 _bc=3 _prefix=2 _c _cmd _prev _daddr
set -A _c -- "$@"
set -o noglob
case ${_c[_af]} in
''|*([[:blank:]])'#'*)
return
;;
inet) ((${#_c[*]} > 1)) || return
[[ ${_c[_name]} == alias ]] && _mask=3 _bc=4
[[ -n ${_c[_mask]} ]] && _c[_mask]="netmask ${_c[_mask]}"
if [[ -n ${_c[_bc]} ]]; then
_c[_bc]="broadcast ${_c[_bc]}"
[[ ${_c[_bc]} == *NONE ]] && _c[_bc]=
fi
_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
;;
inet6) ((${#_c[*]} > 1)) || return
if [[ ${_c[_name]} == autoconf ]]; then
_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
rtsolif="$rtsolif $_if"
return
fi
[[ ${_c[_name]} == alias ]] && _prefix=3
[[ -n ${_c[_prefix]} ]] && _c[_prefix]="prefixlen ${_c[_prefix]}"
_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
;;
dest) ((${#_c[*]} == 2)) && _daddr=${_c[1]} || return
_prev=$((${#_cmds[*]} - 1))
((_prev >= 0)) || return
set -A _c -- ${_cmds[_prev]}
_name=3
[[ ${_c[_name]} == alias ]] && _name=4
_c[_name]="${_c[_name]} $_daddr"
_cmds[$_prev]="${_c[@]}"
;;
dhcp) _c[0]=
_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} down;dhclient $_if"
dhcpif="$dhcpif $_if"
;;
rtsol) # XXX Support the rtsol keyword for some time to enable a smooth
# XXX transition to autoconf.
_c[0]=
_cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]} up"
_cmds[${#_cmds[*]}]="ifconfig $_if inet6 autoconf"
rtsolif="$rtsolif $_if"
;;
'!'*) _cmd=$(print -- "${_c[@]}" | sed 's/\$if/'$_if'/g')
_cmds[${#_cmds[*]}]="${_cmd#!}"
;;
*) _cmds[${#_cmds[*]}]="ifconfig $_if ${_c[@]}"
;;
esac
unset _c
}
# Start a single interface. # Start a single interface.
# Usage: ifstart if1 # Usage: ifstart if1
ifstart() { ifstart() {
# Note: Do not rename the 'if' variable which is documented as being
# usable in hostname.if(5) files.
local if=$1 _file=/etc/hostname.$1 _stat
local _if=$1 _file=$HN_DIR/hostname.$1 _cmds _i=0 _line _stat
set -A _cmds
# Interface names must be alphanumeric only. We check to avoid # Interface names must be alphanumeric only. We check to avoid
# configuring backup or temp files, and to catch the "*" case. # configuring backup or temp files, and to catch the "*" case.
[[ $if != +([[:alpha:]])+([[:digit:]]) ]] && return
[[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return
if [[ ! -f $_file ]]; then if [[ ! -f $_file ]]; then
echo "netstart: $_file: No such file or directory" echo "netstart: $_file: No such file or directory"
return return
fi fi
# Not using stat(1), we can't rely on having /usr yet. # Not using stat(1), we can't rely on having /usr yet.
set -A _stat -- $(ls -nL $_file) set -A _stat -- $(ls -nL $_file)
if [ "${_stat[0]#???????} ${_stat[2]} ${_stat[3]}" != "--- 0 0" ]; then if [ "${_stat[0]#???????} ${_stat[2]} ${_stat[3]}" != "--- 0 0" ]; then
@ -41,97 +100,30 @@ ifstart() {
chmod -LR o-rwx $_file chmod -LR o-rwx $_file
chown -LR root.wheel $_file chown -LR root.wheel $_file
fi fi
# Check for ifconfig'able interface.
(ifconfig $if || ifconfig $if create) >/dev/null 2>&1 || return
# Now parse the hostname.* file.
while :; do
if [ "$cmd2" ]; then
# We are carrying over from the 'read dt dtaddr'
# last time.
set -- $cmd2
af=$1 name=$2 mask=$3 bcaddr=$4 ext1=$5 cmd2=
# Make sure and get any remaining args in ext2,
# like the read below.
i=1
while [ $i -lt 6 -a -n "$1" ]; do shift; let i=i+1; done
ext2="$@"
# Check for ifconfig'able interface, except if -n option is specified.
if ! $PRINT_ONLY; then
(ifconfig $_if || ifconfig $_if create) >/dev/null 2>&1 ||
return
fi
# Parse the hostname.if(5) file and fill _cmds array with interface
# configuration commands.
set -o noglob
while IFS= read -- _line; do
parse_hn_line $_line
done <$_file
# Apply the interface configuration commands stored in _cmds array.
while ((_i < ${#_cmds[*]})); do
if $PRINT_ONLY; then
print -r -- "${_cmds[_i]}"
else else
# Read the next line or exit the while loop.
read af name mask bcaddr ext1 ext2 || break
eval "${_cmds[_i]}"
fi fi
# $af can be "dhcp", "up", "rtsol", an address family, commands,
# or a comment.
case "$af" in
"#"*|"")
# Skip comments and empty lines.
continue
;;
"!"*) # Parse commands.
cmd="${af#*!} ${name} ${mask} ${bcaddr} ${ext1} ${ext2}"
;;
"dhcp")
[ "$name" = "NONE" ] && name=
[ "$mask" = "NONE" ] && mask=
[ "$bcaddr" = "NONE" ] && bcaddr=
cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 down"
cmd="$cmd;dhclient $if"
dhcpif="$dhcpif $if"
;;
"rtsol")
rtsolif="$rtsolif $if"
cmd="ifconfig $if $name $mask $bcaddr $ext1 $ext2 up"
;;
*)
read dt dtaddr
if [ "$name" = "alias" ]; then
# Perform a 'shift' of sorts.
alias=$name
name=$mask
mask=$bcaddr
bcaddr=$ext1
ext1=$ext2
ext2=
else
alias=
fi
cmd="ifconfig $if $af $alias $name"
case "$dt" in
dest)
cmd="$cmd $dtaddr"
;;
*)
cmd2="$dt $dtaddr"
;;
esac
case $af in
inet)
if [ ! -n "$name" ]; then
echo "/etc/hostname.$if: inet alone is invalid"
return
fi
[ "$mask" ] && cmd="$cmd netmask $mask"
if [ "$bcaddr" -a "X$bcaddr" != "XNONE" ]; then
cmd="$cmd broadcast $bcaddr"
fi
;;
inet6)
if [ ! -n "$name" ]; then
echo "/etc/hostname.$if: inet6 alone is invalid"
return
fi
[ "$mask" ] && cmd="$cmd prefixlen $mask"
cmd="$cmd $bcaddr"
;;
*)
cmd="$cmd $mask $bcaddr"
;;
esac
cmd="$cmd $ext1 $ext2"
;;
esac
eval "$cmd"
done <$_file
((_i++))
done
unset _cmds
} }
# Start multiple interfaces by driver name. # Start multiple interfaces by driver name.
@ -196,6 +188,23 @@ fi
FUNCS_ONLY=1 . /etc/rc.d/rc.subr FUNCS_ONLY=1 . /etc/rc.d/rc.subr
_rc_parse_conf _rc_parse_conf
HN_DIR=${HN_DIR:-/etc}
PRINT_ONLY=false
USAGE="USAGE: ${0##*/} [-n] [interface ...]"
while getopts ":n" opt; do
case $opt in
n) PRINT_ONLY=true;;
*) print -u2 "$USAGE"; exit 1;;
esac
done
shift $((OPTIND-1))
# Option -n is only supported if interface names are specified as parameters.
if $PRINT_ONLY && (($# == 0)); then
print -u2 "Missing parameters.\n$USAGE"
exit 1
fi
# If we were invoked with a list of interface names, just reconfigure these # If we were invoked with a list of interface names, just reconfigure these
# interfaces (or bridges), add default routes and return. # interfaces (or bridges), add default routes and return.
if (($# > 0)); then if (($# > 0)); then


Loading…
Cancel
Save