esac
}
+function ipv4_prefix_is_valid() {
+ local prefix=${1}
+
+ isset prefix || return ${EXIT_FALSE}
+
+ [ ${prefix} -le 0 ] && return ${EXIT_FALSE}
+ [ ${prefix} -gt 32 ] && return ${EXIT_FALSE}
+
+ return ${EXIT_TRUE}
+}
+
function ipv4_detect_duplicate() {
local device=${1}
local address=${2}
assert isset device
assert device_exists ${device}
+ # Don't check on PPP devices.
+ device_is_ppp ${device} && return ${EXIT_ERROR}
+
if ! arping -q -c 2 -w 3 -D -I ${device} ${address}; then
log DEBUG "Detected duplicate address '${address}' on device '${device}'."
return ${EXIT_OK}
local device=${1}
local address=${2}
+ # Don't do anything on PPP devices.
+ device_is_ppp ${device} && return ${EXIT_OK}
+
arping -q -A -c 1 -I ${device} ${address}
( sleep 2; arping -q -U -c 1 -I ${device} ${address} ) >/dev/null 2>&1 </dev/null &
}
assert isset address
local prefix=$(ip_get_prefix ${address})
- assert isset prefix
+ isset prefix || prefix="32"
+
+ # Assume host-only address if no prefix has been given.
+ if [ "${prefix}" = "32" ]; then
+ echo "${address}/${prefix}"
+ return ${EXIT_OK}
+ fi
local NETWORK
eval $(ipcalc --network ${address})
assert isset NETWORK
echo "${NETWORK}/${prefix}"
+ return ${EXIT_OK}
+}
+
+function ipv4_get_prefix() {
+ local address=${1}
+ local broadcast=${2}
+ assert isset address
+ assert isset broadcast
+
+ local PREFIX
+ eval $(ipcalc --prefix ${address} ${broadcast})
+ assert isset PREFIX
+
+ echo "${PREFIX}"
return ${EXIT_OK}
}
+
+function ipv4_get_netmask() {
+ local address=${1}
+ assert isset address
+
+ # Add prefix if none given.
+ local prefix=$(ip_get_prefix ${address})
+ isset prefix || address="${address}/32"
+
+ local NETMASK
+ eval $(ipcalc --netmask ${address})
+ assert isset NETMASK
+
+ print "${NETMASK}"
+ return ${EXIT_OK}
+}
+
+function ipv4_flush_device() {
+ #
+ # Flushes all routes, addresses from the device
+ # and clears the ARP cache.
+ #
+
+ local device=${1}
+ assert isset device
+
+ ip -4 addr flush dev ${device} >/dev/null 2>&1
+ ip -4 route flush dev ${device} >/dev/null 2>&1
+ ip -4 neigh flush dev ${device} >/dev/null 2>&1
+
+ return 0
+}
+
+function ipv4_prefix2netmask() {
+ local prefix=${1}
+ shift
+
+ assert isinteger prefix
+
+ # XXX this function is a stub
+
+ case "${prefix}" in
+ 24)
+ echo "255.255.255.0"
+ ;;
+ *)
+ assert false NOT IMPLEMENTED
+ ;;
+ esac
+}
+
+function ipv4_get_network() {
+ local network=$(ipv4_get_network $@)
+
+ ipv4_decode ${network}
+}
+
+function ipv4_get_network_encoded() {
+ local net=${1}
+
+ local prefix=$(ip_get_prefix ${net})
+ isset prefix || prefix=32
+
+ local mask=0
+ if [ ${prefix} -ne 0 ]; then
+ mask=$(( -1 << $(( 32 - ${prefix} )) ))
+ fi
+
+ local addr=$(ip_split_prefix ${net})
+ addr=$(ipv4_encode ${addr})
+
+ print "%d" $(( ${addr} & ${mask} ))
+}
+
+function ipv4_get_broadcast() {
+ local broadcast=$(ipv4_get_broadcast_encoded $@)
+
+ ipv4_decode ${broadcast}
+}
+
+function ipv4_get_broadcast_encoded() {
+ local net=${1}
+
+ local prefix=$(ip_get_prefix ${net})
+ assert isset prefix
+
+ prefix=$(( 32 - ${prefix} ))
+
+ local netmask=0
+ local broadcast=-1
+ if [ ${prefix} -eq 32 ]; then
+ :
+ else
+ netmask=$(( -1 << ${prefix} ))
+ broadcast=$(( $(( 1 << ${prefix} )) - 1))
+ fi
+
+ local addr=$(ip_split_prefix ${net})
+ addr=$(ipv4_encode ${addr})
+
+ print "%d" $(( $(( ${addr} & ${netmask} )) | ${broadcast} ))
+}
+
+function ipv4_encode() {
+ local addr=${1}
+ local int=0
+
+ local field
+ for field in ${addr//./ }; do
+ int=$(( $(( ${int} << 8 )) | ${field} ))
+ done
+
+ print "${int}"
+}
+
+function ipv4_decode() {
+ local int=${1}
+
+ local addr=$(( ${int} & 255 ))
+
+ local i
+ for i in 1 2 3; do
+ int=$(( ${int} >> 8 ))
+ addr="$(( ${int} & 255 )).${addr}"
+ done
+
+ print "${addr}"
+}
+
+function ipv4_addr_eq() {
+ local addr1=${1}
+ assert isset addr1
+
+ local addr2=${2}
+ assert isset addr2
+
+ [[ "${addr1}" = "${addr2}" ]] \
+ && return ${EXIT_TRUE} || return ${EXIT_FALSE}
+}
+
+function ipv4_addr_gt() {
+ local addr1=${1}
+ assert isset addr1
+
+ local addr2=${2}
+ assert isset addr2
+
+ local addr
+ for addr in addr1 addr2; do
+ printf -v ${addr} "%s" "$(ip_encode ${!addr})"
+ done
+
+ [[ ${addr1} -gt ${addr2} ]] \
+ && return ${EXIT_TRUE} || return ${EXIT_FALSE}
+}
+
+function ipv4_range() {
+ local range=${1}
+
+ local first=${1%-*}
+ local last=${1#*-}
+
+ _ipv4_range "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
+}
+
+function _ipv4_range() {
+ local first=${1}
+ local last=${2}
+
+ if [ ${first} -gt ${last} ]; then
+ local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
+
+ error "Invalid IPv4 address range: ${range}"
+ return ${EXIT_ERROR}
+ fi
+
+ last=$(( ${last} + 1 ))
+
+ local prefix
+ local x y z
+ while [ ${last} -gt ${first} ]; do
+ prefix=
+ x=31
+ y=2
+ z=1
+
+ while [ $(( ${first} % ${y} )) -eq 0 ] && [ ${last} -gt $(( ${first} + ${y} )) ]; do
+ prefix="/${x}"
+ x=$(( ${x} - 1 ))
+ z=${y}
+ y=$(( ${y} * 2 ))
+ done
+
+ print "$(ipv4_decode ${first})${prefix}"
+ first=$(( ${first} + ${z} ))
+ done
+}
+
+function ipv4_range_explicit() {
+ local range=${1}
+
+ local first last
+
+ case "${range}" in
+ *.*.*.*-*.*.*.*)
+ first=${range%-*}
+ last=${range#*-}
+ ;;
+ *.*.*.*/*)
+ first=$(ipv4_get_network ${range})
+ last=$(ipv4_get_broadcast ${range})
+ ;;
+ esac
+
+ _ipv4_range_explicit "$(ipv4_encode ${first})" "$(ipv4_encode ${last})"
+}
+
+function _ipv4_range_explicit() {
+ local first=${1}
+ local last=${2}
+
+ if [ ${first} -gt ${last} ]; then
+ local range="$(ipv4_decode ${first})-$(ipv4_decode ${last})"
+
+ error "Invalid IPv4 address range: ${range}"
+ return ${EXIT_ERROR}
+ fi
+
+ while [ ${first} -le ${last} ]; do
+ ipv4_decode ${first}
+ first=$(( ${first} + 1 ))
+ done
+}
+
+function ipv4_in_subnet() {
+ local addr=${1}
+ assert isset addr
+
+ local subnet=${2}
+ assert isset subnet
+
+ local subnet_first=$(ipv4_get_network_encoded ${subnet})
+ local subnet_last=$(ipv4_get_broadcast_encoded ${subnet})
+
+ addr=$(ipv4_encode ${addr})
+
+ if [[ "${addr}" -ge "${subnet_first}" ]] && [[ "${addr}" -le "${subnet_last}" ]]; then
+ return ${EXIT_TRUE}
+ fi
+
+ return ${EXIT_FALSE}
+}
+
+function ipv4_ttl_valid() {
+ local ttl="${1}"
+
+ isinteger ttl || return ${EXIT_FALSE}
+
+ # Must be between 10 and 255.
+ [ "${ttl}" -lt 10 ] && return ${EXIT_FALSE}
+ [ "${ttl}" -gt 255 ] && return ${EXIT_FALSE}
+
+ return ${EXIT_TRUE}
+}