]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.ip
Fix creating new configs
[people/stevee/network.git] / src / functions / functions.ip
1 #!/bin/bash
2 ###############################################################################
3 # #
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 # A list of supported versions of the IP protocol
23 IP_SUPPORTED_PROTOCOLS=""
24
25 ip_split_prefix() {
26 local address=${1}
27 assert isset address
28
29 echo "${address%%/*}"
30 }
31
32 ip_get_prefix() {
33 local address=${1}
34 assert isset address
35
36 # Break if no prefix is provided
37 [[ ${address} =~ \/ ]] || return ${EXIT_OK}
38
39 echo "${address##*/}"
40 }
41
42 ip_detect_protocol() {
43 local address="${1}"
44 assert isset address
45
46 # Remove prefix so that we can handle subnet, too
47 address=$(ip_split_prefix ${address})
48
49 local protocol
50 for protocol in ${IP_SUPPORTED_PROTOCOLS}; do
51 if ${protocol}_is_valid "${address}"; then
52 echo "${protocol}"
53 return ${EXIT_OK}
54 fi
55 done
56
57 return ${EXIT_ERROR}
58 }
59
60 ip_protocol_is_supported() {
61 local proto=${1}
62
63 assert isset proto
64
65 list_match ${proto} ${IP_SUPPORTED_PROTOCOLS}
66 }
67
68 # Returns true if all IP addresses are of the same protocol
69 ip_protocol_match() {
70 local address="${1}"
71 shift
72
73 # Get protocol of the first address
74 local protocol="$(ip_detect_protocol "${address}")"
75
76 # Check if all other addresses match the protocol
77 for address in $@; do
78 local p="$(ip_detect_protocol "${address}")"
79
80 if [ "${p}" != "${protocol}" ]; then
81 return ${EXIT_FALSE}
82 fi
83 done
84
85 return ${EXIT_TRUE}
86 }
87
88 ip_is_valid() {
89 local address=${1}
90 assert isset address
91
92 local protocol
93 for protocol in ${IP_SUPPORTED_PROTOCOLS}; do
94 if ${protocol}_is_valid "${address}"; then
95 return ${EXIT_TRUE}
96 fi
97 done
98
99 return ${EXIT_FALSE}
100 }
101
102 ip_net_is_valid() {
103 local network=${1}
104 assert isset network
105
106 local protocol
107 for protocol in ${IP_SUPPORTED_PROTOCOLS}; do
108 if ${protocol}_net_is_valid "${network}"; then
109 return ${EXIT_TRUE}
110 fi
111 done
112
113 return ${EXIT_FALSE}
114 }
115
116 ip_prefix_is_valid() {
117 local proto=${1}
118 assert isset proto
119
120 local prefix=${2}
121
122 case "${proto}" in
123 ipv4)
124 ipv4_prefix_is_valid ${prefix}
125 return $?
126 ;;
127 ipv6)
128 ipv6_prefix_is_valid ${prefix}
129 return $?
130 ;;
131 esac
132
133 assert ip_protocol_is_supported ${proto}
134 }
135
136 ip_get_network() {
137 inetcalc -n "$@" && return ${EXIT_OK} || return ${EXIT_ERROR}
138 }
139
140 ip_network_is_subset_of() {
141 assert [ $# -eq 2 ]
142
143 inetcalc -s "$@" && return ${EXIT_TRUE} || return ${EXIT_FALSE}
144 }
145
146 ip_address_add() {
147 local device=${1}
148 local address=${2}
149
150 assert isset address
151 assert device_exists ${device}
152
153 local prefix=$(ip_get_prefix ${address})
154 address=$(ip_split_prefix ${address})
155
156 assert isset prefix
157 assert isset address
158
159 echo "ADDRESS = $address"
160
161 # Detect the protocol version
162 local protocol=$(ip_detect_protocol "${address}")
163 assert ip_protocol_is_supported "${protocol}"
164
165 case "${protocol}" in
166 ipv6)
167 assert ipv6_prefix_is_valid "${prefix}"
168 ;;
169 ipv4)
170 assert ipv4_prefix_is_valid "${prefix}"
171 ;;
172 esac
173
174 case "${protocol}" in
175 ipv4)
176 if ipv4_detect_duplicate ${device} ${address}; then
177 error_log "Duplicate address detected on zone '${device}' (${address})."
178 error_log "Cannot continue."
179 return ${EXIT_ERROR}
180 fi
181 ;;
182 esac
183
184 if ! device_has_ip ${device} ${address}/${prefix}; then
185 assert ip addr add ${address}/${prefix} dev ${device}
186
187 log DEBUG "IP address '${address}' (${protocol}) was successfully configured on device '${device}'."
188
189 case "${protocol}" in
190 ipv4)
191 # Announce our new address to the neighbours
192 ipv4_update_neighbours ${device} ${address}
193 ;;
194 esac
195 else
196 log DEBUG "IP address '${address}' (${protocol}) was already configured on device '${device}'."
197 fi
198
199 return ${EXIT_OK}
200 }
201
202 ip_address_del() {
203 local device=${1}
204 local address=${2}
205
206 assert isset address
207 assert device_exists ${device}
208
209 local prefix=$(ip_get_prefix ${address})
210 address=$(ip_split_prefix ${address})
211
212 assert isset prefix
213
214 # Detect the protocol version
215 local protocol=$(ip_detect_protocol "${address}")
216 assert ip_protocol_is_supported "${protocol}"
217
218 if device_has_ip ${device} ${address}/${prefix}; then
219 assert ip addr del ${address}/${prefix} dev ${device}
220
221 log DEBUG "IP address '${address}' (${protocol}) was successfully removed from device '${device}'."
222 else
223 log DEBUG "IP address '${address}' (${protocol}) was not configured on device '${device}'."
224 fi
225
226 return ${EXIT_OK}
227 }
228
229 # Get all currently assigned addresse for a given network
230 ip_get_assigned_addresses_from_net() {
231 local net=${1}
232 shift
233 local args="$@"
234
235 if ! ip_net_is_valid ${net}; then
236 log ERROR "IP net ${net} is invalid"
237 return ${EXIT_ERROR}
238 fi
239
240 local line
241 local addresses
242
243 # We read the output of $(ip addr show to ${net} ${args})
244 while read -r line; do
245 # We are only interested in lines which start with inet or inet6
246 [[ "${line}" =~ ^(inet6 |inet ) ]] || continue
247
248 # We need the second word the line
249 line=(${line})
250 list_append "addresses" "$(ip_split_prefix "${line[1]}")"
251 done <<< "$(ip addr show to "${net}" ${args})"
252
253 # We sort the list to get the lowest IP as first item
254 list_sort ${addresses}
255 }