99 lines
2.3 KiB
Bash
99 lines
2.3 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# ============================================
|
|
# IP Assignment
|
|
# ============================================
|
|
|
|
function ip::assigned() {
|
|
grep -h "^Address" "$(ctx::clients)"/*.conf 2>/dev/null \
|
|
| awk '{print $3}' \
|
|
| cut -d'/' -f1
|
|
}
|
|
|
|
function ip::is_assigned() {
|
|
local candidate="$1"
|
|
ip::assigned | grep -q "^${candidate}$"
|
|
}
|
|
|
|
# ip::next_for_subnet <cidr>
|
|
# Finds the next unassigned host IP within a CIDR.
|
|
# Replaces ip::next_for_type for the subnet-aware allocation path.
|
|
function ip::next_for_subnet() {
|
|
local cidr="${1:-}"
|
|
|
|
if [[ -z "$cidr" ]]; then
|
|
log::error "No subnet CIDR provided for IP allocation"
|
|
return 1
|
|
fi
|
|
|
|
local prefix
|
|
prefix=$(subnet::prefix "$cidr")
|
|
|
|
local candidate
|
|
for i in $(subnet::host_range "$cidr"); do
|
|
candidate="${prefix}.${i}"
|
|
ip::is_assigned "$candidate" || { echo "$candidate"; return 0; }
|
|
done
|
|
|
|
log::error "No available IPs in subnet ${cidr}"
|
|
return 1
|
|
}
|
|
|
|
|
|
# ============================================
|
|
# Validation
|
|
# ============================================
|
|
|
|
function ip::is_valid() {
|
|
local ip="${1:-}"
|
|
[[ -z "$ip" ]] && return 1
|
|
|
|
# Strip CIDR mask if present
|
|
local addr="${ip%%/*}"
|
|
|
|
# Structural check — 4 octets, optional /mask
|
|
[[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$ ]] || return 1
|
|
|
|
# Octet range check — each must be 0-255
|
|
local IFS='.'
|
|
local -a octets
|
|
read -ra octets <<< "$addr"
|
|
for octet in "${octets[@]}"; do
|
|
(( octet >= 0 && octet <= 255 )) || return 1
|
|
done
|
|
|
|
return 0
|
|
}
|
|
function ip::is_cidr() {
|
|
[[ "$1" == *"/"* ]]
|
|
}
|
|
|
|
# ip::is_valid_for_subnet <cidr> <ip>
|
|
# Convenience wrapper — validates an IP against a specific subnet.
|
|
# Delegates to subnet::ip_valid_for which handles all the checks.
|
|
function ip::is_valid_for_subnet() {
|
|
local cidr="${1:-}" ip="${2:-}"
|
|
subnet::ip_valid_for "$cidr" "$ip"
|
|
}
|
|
|
|
# ip::require_valid_for_subnet <cidr> <ip>
|
|
# Errors and returns 1 if the IP is not valid for the subnet.
|
|
# Used when a manual --ip override is provided.
|
|
function ip::require_valid_for_subnet() {
|
|
local cidr="${1:-}" ip="${2:-}"
|
|
subnet::require_ip_valid_for "$cidr" "$ip"
|
|
}
|
|
|
|
function ip::validate() {
|
|
local ip="$1"
|
|
if ! ip::is_valid "$ip"; then
|
|
log::error "Invalid IP or CIDR: ${ip}"
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function ip::require_valid() {
|
|
local ip="$1"
|
|
ip::validate "$ip" || exit 1
|
|
}
|