Add script for IP address configuration

This commit is contained in:
Joris van Rantwijk 2024-09-22 21:11:14 +02:00
parent 5ceb5ad882
commit c3398e9e1d
3 changed files with 375 additions and 1 deletions

3
sw/.gitignore vendored
View File

@ -1,5 +1,6 @@
devicetree/devicetree.dtb
buildroot_overlay/opt/
buildroot_overlay/opt/puzzlefw/bin/puzzlecmd
buildroot_overlay/opt/puzzlefw/driver/
downloads/
buildroot-2023.02.8/
u-boot/

View File

@ -0,0 +1,310 @@
#!/bin/sh
#
# Manage IP address configuration.
#
# The IP address configuration exists in 3 places:
#
# - The persistent configuration is stored in network.conf on
# the configuration partition of the SD card.
# This configuration is activated on boot.
#
# The syntax of this file is as follows:
#
# MODE=dhcp / MODE=static
# IPADDR=172.16.3.4
# NETMASK=255.255.0.0
# GATEWAY=172.16.0.1
#
# - The active configuration, which determines the actual IP address,
# is stored in /var/lib/puzzlefw/cfg/network_active.conf in
# the RAM filesystem. It has the same format as described above.
#
# The same information is also present in /etc/network/interfaces.
#
. /opt/puzzlefw/lib/functions.sh
# Load the persistent or active configuration.
# $1 = file name to read
load_network_config() {
if [ ! -f ${CONFIG_DIR}/${1} ]; then
echo "ERROR: File not found ${CONFIG_DIR}/${1}" >&2
exit 1
fi
. ${CONFIG_DIR}/${1}
}
# Write configuration to file.
# $1 = file name to write
write_network_config() {
mkdir -p ${CONFIG_DIR}
cat >${CONFIG_DIR}/${1} <<EOF
MODE=${MODE}
IPADDR=${IPADDR}
NETMASK=${NETMASK}
GATEWAY=${GATEWAY}
EOF
}
# Write /etc/network/interfaces
write_network_interfaces() {
IF_METHOD="dhcp"
IF_ADDRESS=""
IF_NETMASK=""
IF_GATEWAY=""
if [ "$MODE" = "static" ]; then
IF_METHOD="static"
IF_ADDRESS=" address ${IPADDR}"
IF_NETMASK=" netmask ${NETMASK}"
if [ -n "$GATEWAY" ]; then
IF_GATEWAY=" gateway ${GATEWAY}"
fi
fi
echo "Writing /etc/network/interfaces ..."
cat >/etc/network/interfaces.new <<EOF
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet $IF_METHOD
$IF_ADDRESS
$IF_NETMASK
$IF_GATEWAY
EOF
mv /etc/network/interfaces.new /etc/network/interfaces
}
# Initialize configuration from SD card.
ipcfg_init() {
echo "Loading IP address configuration from SD card ..."
# Copy configuration from SD card.
lock_config || exit 1
read_config || exit 1
# Copy persistent configuration to active configuration.
cp -a ${CONFIG_DIR}/network.conf ${CONFIG_DIR}/network_active.conf
# Load persistent configuration.
load_network_config network.conf
# Write /etc/network/interfaces
write_network_interfaces
}
# Show loaded network configuration.
show_network_config() {
echo " Mode: $MODE"
if [ "$MODE" = "static" ]; then
echo " IP address: $IPADDR"
echo " Netmask: $NETMASK"
echo " Gateway: $GATEWAY"
fi
}
# Display configuration.
ipcfg_show() {
load_network_config network_active.conf
echo "Active IP address configuration:"
show_network_config
load_network_config network.conf
echo "Saved IP address configuration:"
show_network_config
}
# Check that parameter is a well-formed IPv4 address.
check_ipaddr() {
IFS="." read a b c d <<EOF
$1
EOF
for i in "$a" "$b" "$c" "$d" ; do
if ! [ "$i" -ge 0 -a "$i" -le 255 ]; then
echo "ERROR: Invalid IP address '$1'" >&2
exit 1
fi
done
}
# Check that parameter is a valid IPv4 netmask.
check_netmask() {
IFS="." read a b c d <<EOF
$1
EOF
netmask_force_zero=0
for i in "$a" "$b" "$c" "$d" ; do
if [ "$netmask_force_zero" = "1" -a "$i" != "0" ]; then
echo "ERROR: Invalid netmask '$1'" >&2
exit 1
fi
if [ "$i" != "255" ]; then
netmask_force_zero=1
netmask_ok=0
for k in 254 252 248 240 224 192 128 0 ; do
if [ "$i" = "$k" ]; then
netmask_ok=1
fi
done
if [ "$netmask_ok" != "1" ]; then
echo "ERROR: Invalid netmask '$1'" >&2
exit 1
fi
fi
done
}
# Parse IP address options.
parse_options() {
while [ -n "$1" ]; do
case "$1" in
--mode)
if [ "$2" != "dhcp" -a "$2" != "static" ]; then
echo "ERROR: Unknown mode '$2'" >&2
exit 1
fi
MODE="$2"
;;
--ipaddr)
check_ipaddr "$2"
IPADDR="$2"
;;
--netmask)
check_netmask "$2"
NETMASK="$2"
;;
--gateway)
[ -z "$2" ] || check_ipaddr "$2"
GATEWAY="$2"
;;
*)
echo "ERROR: Unknown option '$1'" >&2
exit 1
esac
shift 2
done
if [ -z "$MODE" ]; then
echo "ERROR: Missing mode" >&2
exit 1
fi
if [ "$MODE" = "static" ]; then
if [ -z "$IPADDR" ]; then
echo "ERROR: Missing IP address" >&2
exit 1
fi
if [ -z "$NETMASK" ]; then
echo "ERROR: Missing netmask" >&2
exit 1
fi
else
IPADDR=""
NETMASK=""
GATEWAY=""
fi
}
# Change active IP address configuration.
ipcfg_config() {
# Lock to avoid conflicting changes.
lock_config || exit 1
echo "Changing active IP address configuration ..."
write_network_config network_active.conf.new
mv ${CONFIG_DIR}/network_active.conf.new ${CONFIG_DIR}/network_active.conf
echo "Shutting down eth0 ..."
/sbin/ifdown eth0
sleep 2
write_network_interfaces
echo "Starting eth0 ..."
/sbin/ifup eth0 || exit 1
}
# Change the persistent IP address configuration on the SD card.
ipcfg_save() {
# Lock to avoid conflicting changes.
lock_config || exit 1
echo "Changing saved IP address configuration ..."
write_network_config network.conf.new || exit 1
sync_config network.conf || exit 1
}
case "$1" in
init)
ipcfg_init
;;
show)
ipcfg_show
;;
config)
shift
parse_options "$@"
ipcfg_config
;;
save)
shift
parse_options "$@"
ipcfg_save
;;
*)
cat <<EOF
Usage: $0 {init|show|config|save|restart}
Manage IP address configuration.
$0 init
Initialize IP address from saved configuration on SD card.
This command is used during boot and should not be invoked manually.
$0 show
Display active and saved IP address configuration.
$0 config {options}
Change active IP address configuration.
The new configuration is not written to the SD card.
options:
--mode dhcp Enable configuration via DHCP.
--mode static Enable static IP address configuration.
--ipaddr n.n.n.n Specify static IPv4 address.
--netmask n.n.n.n Specify netmask.
--gateway n.n.n.n Specify gateway address, or "" to disable gateway.
$0 save {options}
Change the saved IP address configuration on the SD card.
Options are the same as for command 'config'.
EOF
exit 1
;;
esac
exit $?

View File

@ -0,0 +1,63 @@
#
# Settings and functions for shell scripts.
#
CONFIG_PARTITION=mmcblk0p2
CONFIG_MOUNTPOINT=/mnt/cfg
CONFIG_DIR=/var/lib/puzzlefw/cfg
# Lock the configuration files.
lock_config() {
# Make config directory in RAM filesystem.
mkdir -p $CONFIG_DIR
# Create or open lock file.
# The file remains open until the calling script ends.
exec 3>>${CONFIG_DIR}/lockfile
# Get exclusive lock on the file.
if ! flock -n 3 ; then
echo "ERROR: Configuration locked" >&2
return 1
fi
}
# Read configuration files from the SD card.
# This is only used during boot.
read_config() {
# Mount config filesystem read-only.
mkdir -p $CONFIG_MOUNTPOINT
mount -t ext4 -r -o noatime,data=journal /dev/${CONFIG_PARTITION} $CONFIG_MOUNTPOINT || return 1
# Copy config files to RAM filesystem.
cp -a ${CONFIG_MOUNTPOINT}/*.conf $CONFIG_DIR
umount $CONFIG_MOUNTPOINT
}
# Write changed configuration files to the SD card.
# Parameters: names of config files to synchronize
sync_config() {
# Mount config filesystem.
mkdir -p $CONFIG_MOUNTPOINT
mount -t ext4 -o noatime,data=journal /dev/${CONFIG_PARTITION} $CONFIG_MOUNTPOINT || return 1
for fname in "$@" ; do
# Copy new version of file to SD card.
cp ${CONFIG_DIR}/${fname}.new $CONFIG_MOUNTPOINT
# Atomically replace the old file on the SD card.
mv ${CONFIG_MOUNTPOINT}/${fname}.new ${CONFIG_MOUNTPOINT}/${fname}
# Replace the old file in te RAM filesystem.
mv ${CONFIG_DIR}/${fname}.new ${CONFIG_DIR}/${fname}
done
umount $CONFIG_MOUNTPOINT
sync
}