#!/usr/bin/env bash
#
# Usage:
# 1) Save as: set_dhcp_requested_ip.sh
# 2) Make executable:
# chmod +x set_dhcp_requested_ip.sh
# 3) Run as root, passing the desired IP:
# sudo ./set_dhcp_requested_ip.sh 192.168.1.50
#
# What it does:
# - detects the primary network interface
# - writes a Netplan config with DHCP enabled
# - adds a systemd-networkd DHCPv4 RequestAddress=<IP> override
# - applies the config
#
# Important:
# - the router/DHCP server may ignore the requested IP
# - for guaranteed assignment, make a DHCP reservation on the router too
set -euo pipefail
requested_ip="${1:-}"
if [[ -z "$requested_ip" ]]; then
echo "Error: IP address argument is required."
echo "Example: sudo $0 192.168.1.50"
exit 1
fi
if [[ "${EUID}" -ne 0 ]]; then
echo "Run this script as root: sudo $0 $requested_ip"
exit 1
fi
if ! [[ "$requested_ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "Error: invalid IPv4 format: $requested_ip"
exit 1
fi
for octet in ${requested_ip//./ }; do
if (( octet < 0 || octet > 255 )); then
echo "Error: invalid IPv4 octet in $requested_ip"
exit 1
fi
done
iface="$(ip route | awk '/^default/ {print $5; exit}')"
if [[ -z "$iface" ]]; then
echo "Error: could not detect the primary network interface."
exit 1
fi
netplan_file="/etc/netplan/99-dhcp-requested-ip.yaml"
networkd_dropin_dir="/etc/systemd/network/10-${iface}.network.d"
networkd_dropin_file="${networkd_dropin_dir}/request-address.conf"
mkdir -p "$networkd_dropin_dir"
cat > "$netplan_file" <<EOF
network:
version: 2
renderer: networkd
ethernets:
${iface}:
dhcp4: true
EOF
cat > "$networkd_dropin_file" <<EOF
[DHCPv4]
RequestAddress=${requested_ip}
EOF
chmod 600 "$netplan_file" "$networkd_dropin_file"
echo "Generated Netplan config:"
cat "$netplan_file"
echo
echo "Generated systemd-networkd DHCP override:"
cat "$networkd_dropin_file"
echo
netplan generate
netplan apply
systemctl restart systemd-networkd
echo
echo "Done."
echo "Interface: $iface"
echo "Requested DHCP IPv4: $requested_ip"
echo
echo "Current addresses on $iface:"
ip -4 addr show dev "$iface"
echo
echo "Lease info:"
networkctl status "$iface" || true