2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
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. #
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. #
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/>. #
20 ###############################################################################
22 IP_SUPPORTED_PROTOCOLS
="${IP_SUPPORTED_PROTOCOLS} ipv4"
25 ipcalc
--ipv4 -c $@
>/dev
/null
2>&1
37 ipv4_prefix_is_valid
() {
40 isset prefix ||
return ${EXIT_FALSE}
42 [ ${prefix} -le 0 ] && return ${EXIT_FALSE}
43 [ ${prefix} -gt 32 ] && return ${EXIT_FALSE}
48 ipv4_netmask_is_valid
() {
51 # XXX this check could be much better by checking
52 # if the netmask only contains leading ones
54 ipv4_is_valid
"${netmask}"
57 ipv4_detect_duplicate
() {
63 assert device_exists
${device}
65 # Don't check on PPP devices.
66 device_is_ppp
${device} && return ${EXIT_ERROR}
68 if ! arping
-q -c 2 -w 3 -D -I ${device} ${address}; then
69 log DEBUG
"Detected duplicate address '${address}' on device '${device}'."
76 ipv4_update_neighbours
() {
80 # Don't do anything on PPP devices.
81 device_is_ppp
${device} && return ${EXIT_OK}
83 arping
-q -A -c 1 -I ${device} ${address}
84 ( sleep 2; arping
-q -U -c 1 -I ${device} ${address} ) >/dev
/null
2>&1 </dev
/null
&
87 ipv4_get_netaddress
() {
91 local prefix
=$
(ip_get_prefix
${address})
92 isset prefix || prefix
="32"
94 # Assume host-only address if no prefix has been given.
95 if [ "${prefix}" = "32" ]; then
96 echo "${address}/${prefix}"
101 eval $
(ipcalc
--network ${address})
104 echo "${NETWORK}/${prefix}"
113 assert isset broadcast
116 eval $
(ipcalc
--prefix ${address} ${broadcast})
127 # Add prefix if none given.
128 local prefix
=$
(ip_get_prefix
${address})
129 isset prefix || address
="${address}/32"
132 eval $
(ipcalc
--netmask ${address})
139 ipv4_flush_device
() {
141 # Flushes all routes, addresses from the device
142 # and clears the ARP cache.
148 ip
-4 addr flush dev
${device} >/dev
/null
2>&1
149 ip
-4 route flush dev
${device} >/dev
/null
2>&1
150 ip
-4 neigh flush dev
${device} >/dev
/null
2>&1
155 ipv4_prefix2netmask
() {
159 assert isinteger prefix
161 # XXX this function is a stub
168 assert false NOT IMPLEMENTED
173 ipv4_netmask2prefix
() {
180 for field
in ${netmask//\./ }; do
181 mask
=$
(( $
(( ${mask} << 8 )) | ${field} ))
185 local x="$(( 128 << 24 ))" # 0x80000000
187 while [ $(( ${x} & ${mask} )) -ne 0 ]; do
188 [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
189 cidr=$(( ${cidr} + 1 ))
192 assert [ $(( ${mask} & 2147483647 )) -eq 0 ]
198 local network=$(ipv4_get_network_encoded $@)
200 ipv4_decode ${network}
203 ipv4_get_network_encoded() {
206 local prefix=$(ip_get_prefix ${net})
207 isset prefix || prefix=32
210 if [ ${prefix} -ne 0 ]; then
211 mask=$(( -1 << $(( 32 - ${prefix} )) ))
214 local addr=$(ip_split_prefix ${net})
215 addr=$(ipv4_encode ${addr})
217 print "%d" $(( ${addr} & ${mask} ))
220 ipv4_get_broadcast() {
221 local broadcast=$(ipv4_get_broadcast_encoded $@)
223 ipv4_decode ${broadcast}
226 ipv4_get_broadcast_encoded() {
229 local prefix=$(ip_get_prefix ${net})
232 prefix=$(( 32 - ${prefix} ))
236 if [ ${prefix} -eq 32 ]; then
239 netmask=$(( -1 << ${prefix} ))
240 broadcast=$(( $(( 1 << ${prefix} )) - 1))
243 local addr=$(ip_split_prefix ${net})
244 addr=$(ipv4_encode ${addr})
246 print "%d" $(( $(( ${addr} & ${netmask} )) | ${broadcast} ))
254 for field in ${addr//./ }; do
255 int=$(( $(( ${int} << 8 )) | ${field} ))
264 local addr=$(( ${int} & 255 ))
268 int=$(( ${int} >> 8 ))
269 addr
="$(( ${int} & 255 )).${addr}"
282 [[ "${addr1}" = "${addr2}" ]] \
283 && return ${EXIT_TRUE} ||
return ${EXIT_FALSE}
294 for addr
in addr1 addr2
; do
295 printf -v ${addr} "%s" "$(ip_encode ${!addr})"
298 [[ ${addr1} -gt ${addr2} ]] \
299 && return ${EXIT_TRUE} ||
return ${EXIT_FALSE}
308 _ipv4_range
"$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
315 if [ ${first} -gt ${last} ]; then
316 local range
="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
318 error
"Invalid IPv4 address range: ${range}"
322 last
=$
(( ${last} + 1 ))
326 while [ ${last} -gt ${first} ]; do
332 while [ $
(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
339 print
"$(ipv4_decode ${first})${prefix}"
340 first
=$
(( ${first} + ${z} ))
344 ipv4_range_explicit
() {
355 first
=$
(ipv4_get_network
${range})
356 last
=$
(ipv4_get_broadcast
${range})
360 _ipv4_range_explicit
"$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
363 _ipv4_range_explicit
() {
367 if [ ${first} -gt ${last} ]; then
368 local range
="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
370 error
"Invalid IPv4 address range: ${range}"
374 while [ ${first} -le ${last} ]; do
376 first
=$
(( ${first} + 1 ))
387 local subnet_first
=$
(ipv4_get_network_encoded
${subnet})
388 local subnet_last
=$
(ipv4_get_broadcast_encoded
${subnet})
390 addr
=$
(ipv4_encode
${addr})
392 if [[ "${addr}" -ge "${subnet_first}" ]] && [[ "${addr}" -le "${subnet_last}" ]]; then
402 isinteger ttl ||
return ${EXIT_FALSE}
404 # Must be between 10 and 255.
405 [ "${ttl}" -lt 10 ] && return ${EXIT_FALSE}
406 [ "${ttl}" -gt 255 ] && return ${EXIT_FALSE}