]> git.ipfire.org Git - network.git/blob - functions.ipv4
firewall: Make clamp PMTU configurable.
[network.git] / functions.ipv4
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 IP_SUPPORTED_PROTOCOLS="${IP_SUPPORTED_PROTOCOLS} ipv4"
23
24 function ipv4_is_valid() {
25 ipcalc --ipv4 -c $@ >/dev/null 2>&1
26
27 case "$?" in
28 0)
29 return ${EXIT_OK}
30 ;;
31 *)
32 return ${EXIT_ERROR}
33 ;;
34 esac
35 }
36
37 function ipv4_detect_duplicate() {
38 local device=${1}
39 local address=${2}
40
41 assert isset address
42 assert isset device
43 assert device_exists ${device}
44
45 # Don't check on PPP devices.
46 device_is_ppp ${device} && return ${EXIT_ERROR}
47
48 if ! arping -q -c 2 -w 3 -D -I ${device} ${address}; then
49 log DEBUG "Detected duplicate address '${address}' on device '${device}'."
50 return ${EXIT_OK}
51 fi
52
53 return ${EXIT_ERROR}
54 }
55
56 function ipv4_update_neighbours() {
57 local device=${1}
58 local address=${2}
59
60 # Don't do anything on PPP devices.
61 device_is_ppp ${device} && return ${EXIT_OK}
62
63 arping -q -A -c 1 -I ${device} ${address}
64 ( sleep 2; arping -q -U -c 1 -I ${device} ${address} ) >/dev/null 2>&1 </dev/null &
65 }
66
67 function ipv4_get_netaddress() {
68 local address=${1}
69 assert isset address
70
71 local prefix=$(ip_get_prefix ${address})
72 isset prefix || prefix="32"
73
74 # Assume host-only address if no prefix has been given.
75 if [ "${prefix}" = "32" ]; then
76 echo "${address}/${prefix}"
77 return ${EXIT_OK}
78 fi
79
80 local NETWORK
81 eval $(ipcalc --network ${address})
82 assert isset NETWORK
83
84 echo "${NETWORK}/${prefix}"
85 return ${EXIT_OK}
86 }
87
88 function ipv4_get_prefix() {
89 local address=${1}
90 local broadcast=${2}
91
92 assert isset address
93 assert isset broadcast
94
95 local PREFIX
96 eval $(ipcalc --prefix ${address} ${broadcast})
97 assert isset PREFIX
98
99 echo "${PREFIX}"
100 return ${EXIT_OK}
101 }
102
103 function ipv4_flush_device() {
104 #
105 # Flushes all routes, addresses from the device
106 # and clears the ARP cache.
107 #
108
109 local device=${1}
110 assert isset device
111
112 ip -4 addr flush dev ${device} >/dev/null 2>&1
113 ip -4 route flush dev ${device} >/dev/null 2>&1
114 ip -4 neigh flush dev ${device} >/dev/null 2>&1
115
116 return 0
117 }
118
119 function ipv4_prefix2netmask() {
120 local prefix=${1}
121 shift
122
123 assert isinteger prefix
124
125 # XXX this function is a stub
126
127 case "${prefix}" in
128 24)
129 echo "255.255.255.0"
130 ;;
131 *)
132 assert false NOT IMPLEMENTED
133 ;;
134 esac
135 }
136
137 function ipv4_get_network() {
138 local net=${1}
139
140 local prefix=$(ip_get_prefix ${net})
141 isset prefix || prefix=32
142
143 local mask=0
144 if [ ${prefix} -ne 0 ]; then
145 mask=$(( -1 << $(( 32 - ${prefix} )) ))
146 fi
147
148 local addr=$(ip_split_prefix ${net})
149 addr=$(ipv4_encode ${addr})
150
151 ipv4_decode $(( ${addr} & ${mask} ))
152 }
153
154 function ipv4_get_broadcast() {
155 local net=${1}
156
157 local prefix=$(ip_get_prefix ${net})
158 assert isset prefix
159
160 prefix=$(( 32 - ${prefix} ))
161
162 local netmask=0
163 local broadcast=-1
164 if [ ${prefix} -eq 32 ]; then
165 :
166 else
167 netmask=$(( -1 << ${prefix} ))
168 broadcast=$(( $(( 1 << ${prefix} )) - 1))
169 fi
170
171 local addr=$(ip_split_prefix ${net})
172 addr=$(ipv4_encode ${addr})
173
174 ipv4_decode $(( $(( ${addr} & ${netmask} )) | ${broadcast} ))
175 }
176
177 function ipv4_encode() {
178 local addr=${1}
179 local int=0
180
181 local field
182 for field in ${addr//./ }; do
183 int=$(( $(( ${int} << 8 )) | ${field} ))
184 done
185
186 print "${int}"
187 }
188
189 function ipv4_decode() {
190 local int=${1}
191
192 local addr=$(( ${int} & 255 ))
193
194 local i
195 for i in 1 2 3; do
196 int=$(( ${int} >> 8 ))
197 addr="$(( ${int} & 255 )).${addr}"
198 done
199
200 print "${addr}"
201 }
202
203 function ipv4_range() {
204 local range=${1}
205
206 local first=${1%-*}
207 local last=${1#*-}
208
209 _ipv4_range "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
210 }
211
212 function _ipv4_range() {
213 local first=${1}
214 local last=${2}
215
216 if [ ${first} -gt ${last} ]; then
217 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
218
219 error "Invalid IPv4 address range: ${range}"
220 return ${EXIT_ERROR}
221 fi
222
223 last=$(( ${last} + 1 ))
224
225 local prefix
226 local x y z
227 while [ ${last} -gt ${first} ]; do
228 prefix=
229 x=31
230 y=2
231 z=1
232
233 while [ $(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
234 prefix="/${x}"
235 x=$(( ${x} - 1 ))
236 z=${y}
237 y=$(( ${y} * 2 ))
238 done
239
240 print "$(ipv4_decode ${first})${prefix}"
241 first=$(( ${first} + ${z} ))
242 done
243 }
244
245 function ipv4_range_explicit() {
246 local range=${1}
247
248 local first last
249
250 case "${range}" in
251 *.*.*.*-*.*.*.*)
252 first=${range%-*}
253 last=${range#*-}
254 ;;
255 *.*.*.*/*)
256 first=$(ipv4_get_network ${range})
257 last=$(ipv4_get_broadcast ${range})
258 ;;
259 esac
260
261 _ipv4_range_explicit "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
262 }
263
264 function _ipv4_range_explicit() {
265 local first=${1}
266 local last=${2}
267
268 if [ ${first} -gt ${last} ]; then
269 local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
270
271 error "Invalid IPv4 address range: ${range}"
272 return ${EXIT_ERROR}
273 fi
274
275 while [ ${first} -le ${last} ]; do
276 ipv4_decode ${first}
277 first=$(( ${first} + 1 ))
278 done
279 }