A logic like this might work:
%post daemon-config-network
if test $1 -eq 1 && test ! -f %{_sysconfdir}/libvirt/qemu/networks/default.xml
; then
# Function to convert IP/CIDR to start and end integer bounds
# Handles both explicit CIDR (e.g., 192.168.64.0/18) and implicit single IPs
get_ip_bounds() {
local ip_cidr="$1"
local ip="${ip_cidr%%/*}"
local mask="${ip_cidr#*/}"
# Fallback to /32 if no mask is provided
[ "$mask" = "$ip_cidr" ] && mask=32
# Parse IP octets
IFS=. read -r o1 o2 o3 o4 <<EOF
$ip
EOF
# Calculate 32-bit integer for the base IP
local ip_num=$(( (o1 << 24) | (o2 << 16) | (o3 << 8) | o4 ))
# Calculate netmask bitmask
local mask_num=$(( 0xFFFFFFFF << (32 - mask) ))
# Output network start and end integers
echo "$(( ip_num & mask_num )) $(( ip_num | (~mask_num & 0xFFFFFFFF) ))"
}
# Internal helper to verify if two subnets overlap
check_overlap() {
local sub1_start=$1 sub1_end=$2 sub2_start=$3 sub2_end=$4
# Overlap happens if start1 <= end2 AND end1 >= start2
if [ $sub1_start -le $sub2_end ] && [ $sub1_end -le $sub2_start ]; then
return 0 # Overlap found
fi
return 1 # No overlap
}
orig_sub=122
sub=${orig_sub}
# Get active system routes
existing_routes=$(ip route show | cut -d' ' -f1)
# Loop through possible replacements until one doesn't overlap with ANY
system route
for try_sub in $(seq 122 254); do
# Generate target bounds for 192.168.${try_sub}.0/24
read -r target_start target_end <<EOF
$(get_ip_bounds "192.168.${try_sub}.0/24")
EOF
conflict=0
# Check against every route currently active on the host
while read -r route; do
[ -z "$route" ] && continue
# Skip default routes or complex targets that aren't numeric IPs
case "$route" in
default|[*a-zA-Z]*) continue ;;
esac
read -r route_start route_end <<EOF
$(get_ip_bounds "$route")
EOF
# Check overlap math
if [ $target_start -le $route_end ] && [ $target_end -ge
$route_start ]; then
conflict=1
break
fi
done <<EOF
$existing_routes
EOF
# If no conflict found for this subnet, select it and stop searching
if [ $conflict -eq 0 ]; then
sub=${try_sub}
break
fi
done
# Apply configuration with the safe subnet choice
sed -e "s/${orig_sub}/${sub}/g" \
< %{_datadir}/libvirt/networks/default.xml \
> %{_sysconfdir}/libvirt/qemu/networks/default.xml
ln -s ../default.xml
%{_sysconfdir}/libvirt/qemu/networks/autostart/default.xml
chmod 0600 %{_sysconfdir}/libvirt/qemu/networks/default.xml
fi
** Summary changed:
- libvirt-daemon-config-network.postrm.in does not check if subnet
192.168.122.0/24 is already used
+ libvirt-daemon-config-network.postinst.in does not check if subnet
192.168.122.0/24 is already used
** Description changed:
- In our packaging libvirt-daemon-config-network.postrm.in blindly copies
- default.xml to /etc/libvirt/qemu/networks/default.xml.
+ In our packaging libvirt-daemon-config-network.postinst.in blindly
+ copies default.xml to /etc/libvirt/qemu/networks/default.xml.
This leads to conflicts when installing libvirt in a VM that was
launched by libvirt.
Upstream libvirt.spec.in is a bit more refined:
In daemon-config-network it checks if there is a route involving
192.168.122.0/24.
If yes, it looks for an unused subnet 192.168.?.0/24.
At least the developer understood the problem. But the solution is bad.
E.g. a subnet already in use could be 192.168.64.0/18 which comprises
192.168.122.0/24.
** Changed in: libvirt (Ubuntu)
Importance: Undecided => Low
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/2164823
Title:
libvirt-daemon-config-network.postinst.in does not check if subnet
192.168.122.0/24 is already used
To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/2164823/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs