最終更新 1 month ago

nuno revised this gist 1 month ago. Go to revision

1 file changed, 106 insertions

gistfile1.txt(file created)

@@ -0,0 +1,106 @@
1 + #!/usr/bin/env bash
2 +
3 + # ============================================
4 + # IP Assignment
5 + # ============================================
6 +
7 + function ip::assigned() {
8 + grep -h "^Address" "$(ctx::clients)"/*.conf 2>/dev/null \
9 + | awk '{print $3}' \
10 + | cut -d'/' -f1
11 + }
12 +
13 + function ip::is_assigned() {
14 + local candidate="$1"
15 + ip::assigned | grep -q "^${candidate}$"
16 + }
17 +
18 + function ip::next_for_type() {
19 + local type="$1"
20 + local subnet
21 + subnet=$(config::subnet_for "$type")
22 +
23 + if [[ -z "$subnet" ]]; then
24 + log::error "Unknown device type: ${type}"
25 + return 1
26 + fi
27 +
28 + for i in $(seq 1 254); do
29 + local candidate="${subnet}.${i}"
30 + if ! ip::is_assigned "$candidate"; then
31 + echo "$candidate"
32 + return 0
33 + fi
34 + done
35 +
36 + log::error "No available IPs in subnet ${subnet}.0/24"
37 + return 1
38 + }
39 +
40 + # ip::next_for_subnet <cidr>
41 + # Finds the next unassigned host IP within a CIDR.
42 + # Replaces ip::next_for_type for the subnet-aware allocation path.
43 + function ip::next_for_subnet() {
44 + local cidr="${1:-}"
45 +
46 + if [[ -z "$cidr" ]]; then
47 + log::error "No subnet CIDR provided for IP allocation"
48 + return 1
49 + fi
50 +
51 + local prefix
52 + prefix=$(subnet::prefix "$cidr")
53 +
54 + local candidate
55 + for i in $(subnet::host_range "$cidr"); do
56 + candidate="${prefix}.${i}"
57 + ip::is_assigned "$candidate" || { echo "$candidate"; return 0; }
58 + done
59 +
60 + log::error "No available IPs in subnet ${cidr}"
61 + return 1
62 + }
63 +
64 +
65 + # ============================================
66 + # Validation
67 + # ============================================
68 +
69 + function ip::is_valid() {
70 + local ip="$1"
71 + [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}(/([0-9]|[1-2][0-9]|3[0-2]))?$ ]]
72 + }
73 +
74 + function ip::is_cidr() {
75 + [[ "$1" == *"/"* ]]
76 + }
77 +
78 + # ip::is_valid_for_subnet <cidr> <ip>
79 + # Convenience wrapper — validates an IP against a specific subnet.
80 + # Delegates to subnet::ip_valid_for which handles all the checks.
81 + function ip::is_valid_for_subnet() {
82 + local cidr="${1:-}" ip="${2:-}"
83 + subnet::ip_valid_for "$cidr" "$ip"
84 + }
85 +
86 + # ip::require_valid_for_subnet <cidr> <ip>
87 + # Errors and returns 1 if the IP is not valid for the subnet.
88 + # Used when a manual --ip override is provided.
89 + function ip::require_valid_for_subnet() {
90 + local cidr="${1:-}" ip="${2:-}"
91 + subnet::require_ip_valid_for "$cidr" "$ip"
92 + }
93 +
94 + function ip::validate() {
95 + local ip="$1"
96 + if ! ip::is_valid "$ip"; then
97 + log::error "Invalid IP or CIDR: ${ip}"
98 + return 1
99 + fi
100 + return 0
101 + }
102 +
103 + function ip::require_valid() {
104 + local ip="$1"
105 + ip::validate "$ip" || exit 1
106 + }
Newer Older