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"
27 local prefix
=$
(ip_get_prefix
${address})
28 address
=$
(ip_split_prefix
${address})
30 # If prefix is set, we check if it is correct
33 isinteger prefix ||
return ${EXIT_FALSE}
35 # Must be 32 if present
36 [ ${prefix} -eq 32 ] ||
return ${EXIT_FALSE}
39 inetcalc
-4 -c ${address} && return ${EXIT_TRUE} || return ${EXIT_FALSE}
42 ipv4_prefix_is_valid
() {
45 # Check if prefix is a number
46 isinteger prefix ||
return ${EXIT_FALSE}
48 [ ${prefix} -le 0 ] && return ${EXIT_FALSE}
49 [ ${prefix} -gt 32 ] && return ${EXIT_FALSE}
57 local prefix
="$(ip_get_prefix "${net}")"
58 local addr
="$(ip_split_prefix "${net}")"
60 ipv4_prefix_is_valid
"${prefix}" && ipv4_is_valid
"${addr}"
63 ipv4_netmask_is_valid
() {
66 # XXX this check could be much better by checking
67 # if the netmask only contains leading ones
69 ipv4_is_valid
"${netmask}"
72 ipv4_detect_duplicate
() {
78 assert device_exists
${device}
80 # Don't check on PPP devices.
81 device_is_ppp
${device} && return ${EXIT_ERROR}
83 if ! arping
-q -c 2 -w 3 -D -I ${device} ${address}; then
84 log DEBUG
"Detected duplicate address '${address}' on device '${device}'."
91 ipv4_update_neighbours
() {
95 # Don't do anything on PPP devices.
96 device_is_ppp
${device} && return ${EXIT_OK}
98 arping
-q -A -c 1 -I ${device} ${address}
99 ( sleep 2; arping
-q -U -c 1 -I ${device} ${address} ) >/dev
/null
2>&1 </dev
/null
&
102 ipv4_calculate_prefix
() {
106 local broadcast
="${2}"
108 inetcalc
-4 -p "${address}" "${broadcast}"
111 ipv4_flush_device
() {
113 # Flushes all routes, addresses from the device
114 # and clears the ARP cache.
120 ip
-4 addr flush dev
${device} >/dev
/null
2>&1
121 ip
-4 route flush dev
${device} >/dev
/null
2>&1
122 ip
-4 neigh flush dev
${device} >/dev
/null
2>&1
127 ipv4_prefix2netmask
() {
132 echo "255.255.255.255"
135 echo "255.255.255.254"
138 echo "255.255.255.252"
141 echo "255.255.255.248"
144 echo "255.255.255.240"
147 echo "255.255.255.224"
150 echo "255.255.255.192"
153 echo "255.255.255.128"
238 ipv4_netmask2prefix
() {
245 for field
in ${netmask//\./ }; do
246 mask
=$
(( $
(( ${mask} << 8 )) | ${field} ))
250 local x="$(( 128 << 24 ))" # 0x80000000
252 while [ $(( ${x} & ${mask} )) -ne 0 ]; do
253 [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 ))
254 cidr=$(( ${cidr} + 1 ))
257 assert [ $(( ${mask} & 2147483647 )) -eq 0 ]
266 ipv4_get_broadcast() {
267 inetcalc -4 -b "$@" && return ${EXIT_OK} || return ${EXIT_ERROR}
275 for field in ${addr//./ }; do
276 int=$(( $(( ${int} << 8 )) | ${field} ))
285 local addr=$(( ${int} & 255 ))
289 int=$(( ${int} >> 8 ))
290 addr
="$(( ${int} & 255 )).${addr}"
303 [[ "${addr1}" = "${addr2}" ]] \
304 && return ${EXIT_TRUE} ||
return ${EXIT_FALSE}
313 inetcalc
-4 -g "${addr1}" "${addr2}" \
314 && return ${EXIT_TRUE} ||
return ${EXIT_FALSE}
318 ipv4_addr_eq
"$@" || ipv4_addr_gt
"$@"
322 ! ipv4_addr_eq
"$@" && ! ipv4_addr_gt
"$@"
326 ipv4_addr_eq
"$@" ||
! ipv4_addr_gt
"$@"
335 _ipv4_range
"$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
342 if [ ${first} -gt ${last} ]; then
343 local range
="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
345 error
"Invalid IPv4 address range: ${range}"
349 last
=$
(( ${last} + 1 ))
353 while [ ${last} -gt ${first} ]; do
359 while [ $
(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
366 print
"$(ipv4_decode ${first})${prefix}"
367 first
=$
(( ${first} + ${z} ))
371 ipv4_range_explicit
() {
382 first
=$
(ipv4_get_network
${range})
383 first
="$(ip_split_prefix "${first}")"
384 last
=$
(ipv4_get_broadcast
${range})
385 last
="$(ip_split_prefix "${last}")"
389 _ipv4_range_explicit
"$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
392 _ipv4_range_explicit
() {
396 if [ ${first} -gt ${last} ]; then
397 local range
="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
399 error
"Invalid IPv4 address range: ${range}"
403 while [ ${first} -le ${last} ]; do
405 first
=$
(( ${first} + 1 ))
416 local subnet_first
=$
(ipv4_get_network_encoded
${subnet})
417 local subnet_last
=$
(ipv4_get_broadcast_encoded
${subnet})
419 addr
=$
(ipv4_encode
${addr})
421 if [[ "${addr}" -ge "${subnet_first}" ]] && [[ "${addr}" -le "${subnet_last}" ]]; then
431 isinteger ttl ||
return ${EXIT_FALSE}
433 # Must be between 10 and 255.
434 [ "${ttl}" -lt 10 ] && return ${EXIT_FALSE}
435 [ "${ttl}" -gt 255 ] && return ${EXIT_FALSE}