]> git.ipfire.org Git - people/stevee/network.git/blobdiff - functions.ipv6
headers: Add missing function and rename existing ones.
[people/stevee/network.git] / functions.ipv6
index 53c79a0759ddf6e31c4de9ac7e6ba572a1ddfa41..2667ae0b0036d912fc306bd224295c585b276b28 100644 (file)
 
 IP_SUPPORTED_PROTOCOLS="${IP_SUPPORTED_PROTOCOLS} ipv6"
 
-function ipv6_init() {
-       log INFO "Initializing IPv6 networking."
-
-       # Enable forwarding on all devices
-       #ipv6_device_forwarding_disable all
-       #ipv6_device_forwarding_disable default
-
-       # Disable autoconfiguration on all devices per default
-       #ipv6_device_autoconf_disable all
-       #ipv6_device_autoconf_disable default
-
-       # XXX do we need this?
-       #local device
-       #for device in $(devices_get_all); do
-       #       ipv6_device_forwarding_disable ${device}
-       #       ipv6_device_autoconf_disable ${device}
-       #done
-}
-
-init_register ipv6_init
-
 function ipv6_device_autoconf_enable() {
-       local device=${1}
-
-       assert isset device
-
-       # Allow setting default and all settings
-       if ! isoneof device all default; then
-               assert device_exists ${device}
-       fi
+       local device="${1}"
+       assert device_exists "${device}"
 
-       local val
-       for val in accept_ra accept_redirects; do
-               echo 1 > /proc/sys/net/ipv6/conf/${device}/${val}
-       done
+       sysctl_set "net.ipv6.conf.${device}.accept_ra" 1
+       sysctl_set "net.ipv6.conf.${device}.autoconf" 1
 }
 
 function ipv6_device_autoconf_disable() {
-       local device=${1}
-
-       assert isset device
+       local device="${1}"
+       assert device_exists "${device}"
 
-       # Allow setting default and all settings
-       if ! isoneof device all default; then
-               assert device_exists ${device}
-       fi
-
-       local val
-       for val in accept_ra accept_redirects; do
-               echo 0 > /proc/sys/net/ipv6/conf/${device}/${val}
-       done
-}
-
-function ipv6_device_forwarding_enable() {
-       local device=${1}
-
-       assert isset device
-
-       # Allow setting default and all settings
-       if ! isoneof device all default; then
-               assert device_exists ${device}
-       fi
-
-       echo 1 > /proc/sys/net/ipv6/conf/${device}/forwarding
-}
-
-function ipv6_device_forwarding_disable() {
-       local device=${1}
-
-       assert isset device
-
-       # Allow setting default and all settings
-       if ! isoneof device all default; then
-               assert device_exists ${device}
-       fi
-
-       echo 0 > /proc/sys/net/ipv6/conf/${device}/forwarding
+       sysctl_set "net.ipv6.conf.${device}.accept_ra" 0
+       sysctl_set "net.ipv6.conf.${device}.autoconf" 0
 }
 
 # Enable IPv6 RFC3041 privacy extensions if desired
 function ipv6_device_privacy_extensions_enable() {
-       local device=${1}
-       local type=${2}
-
-       assert isset device
-       assert device_exists ${device}
-
-       # Default value is rfc3041
-       if [ -z "${type}" ]; then
-               type="rfc3041"
-       fi
-
-       assert isset type
-
-       case "${type}" in
-               rfc3041)
-                       echo 2 > /proc/sys/net/ipv6/conf/${device}/use_tempaddr
-                       ;;
-               *)
-                       error_log "Given type '${type}' is not supported."
-                       return ${EXIT_ERROR}
-                       ;;
-       esac
+       local device="${1}"
+       assert device_exists "${device}"
 
-       return ${EXIT_OK}
+       sysctl_set "net.ipv6.conf.${device}.use_tempaddr" 2
 }
 
 function ipv6_device_privacy_extensions_disable() {
-       local device=${1}
-
-       assert isset device
-       assert device_exists ${device}
+       local device="${1}"
+       assert device_exists "${device}"
 
-       echo 0 > /proc/sys/net/ipv6/conf/${device}/use_tempaddr
+       sysctl_set "net.ipv6.conf.${device}.use_tempaddr" 0
 }
 
 function ipv6_is_valid() {
@@ -150,189 +65,186 @@ function ipv6_is_valid() {
        esac
 }
 
+function ipv6_prefix_is_valid() {
+       local prefix=${1}
+       assert isset prefix
+
+       [ ${prefix} -le   0 ] && return ${EXIT_FALSE}
+       [ ${prefix} -gt 128 ] && return ${EXIT_FALSE}
+
+       return ${EXIT_TRUE}
+}
+
+function ipv6_get_prefix() {
+       ip_get_prefix "$@"
+}
+
+function ipv6_split_prefix() {
+       ip_split_prefix "$@"
+}
+
 function ipv6_implode() {
        local address=${1}
+       assert isset address
+
+       local ADDRESS6_IMPL
+       eval $(ipcalc -6 -i ${address} 2>/dev/null)
+       assert isset ADDRESS6_IMPL
 
+       print "${ADDRESS6_IMPL}"
+}
+
+function ipv6_explode() {
+       local address=${1}
        assert isset address
 
-       if ! ipv6_is_valid ${address}; then
-               error "IPv6 address is invalid: ${address}"
-               return ${EXIT_ERROR}
+       # Nothing to do if the length of the address is 39.
+       if [ ${#address} -eq 39 ]; then
+               print "${address}"
+               return ${EXIT_OK}
        fi
 
-       # Save prefix
-       local prefix=$(ip_get_prefix ${address})
-       address=$(ip_split_prefix ${address})
+       local ADDRESS6_EXPL
+       eval $(ipcalc -6 -e ${address} 2>/dev/null)
+       assert isset ADDRESS6_EXPL
 
-       # Make proper address in exploded format
-       address=$(ipv6_explode ${address})
-
-       local block
-       local char
-       local i
+       print "${ADDRESS6_EXPL}"
+}
 
-       local address_new
-       local block_new
+function ipv6_addr_eq() {
+       local addr1=${1}
+       assert isset addr1
 
-       for block in ${address//:/\ }; do
-               block_new=
-               for i in $(seq 0 ${#block}); do
-                       char="${block:${i}:1}"
+       local addr2=${2}
+       assert isset addr2
 
-                       [ -z "${char}" ] && continue
+       local addr
+       for addr in addr1 addr2; do
+               printf -v ${addr} "%s" $(ipv6_explode ${!addr})
+       done
 
-                       if [ -z "${block_new}" ] && [ "${char}" = "0" ]; then
-                               continue
-                       fi
+       [[ "${addr1}" = "${addr2}" ]] \
+               && return ${EXIT_TRUE} || return ${EXIT_FALSE}
+}
 
-                       block_new="${block_new}${char}"
-               done
+function ipv6_addr_gt() {
+       local addr1=${1}
+       assert isset addr1
 
-               [ -z "${block_new}" ] && block_new="0"
+       local addr2=${2}
+       assert isset addr2
 
-               address_new="${address_new}:${block_new}"
+       local addr
+       for addr in addr1 addr2; do
+               printf -v ${addr} "%s" $(ipv6_explode ${!addr})
        done
 
-       # Cut first colon (:)
-       address="${address_new:1:${#address_new}}"
-
-       local match
-       local matches=()
-       local pattern
-       local pos_start
-       local pos_next
-       for pos_start in $(seq 0 ${#address}); do
-               matches["${pos_start}"]=0
-
-               for pos_next in $(seq ${pos_start} 2 ${#address}); do
-                       case "${pos_start}" in
-                               0)
-                                       match="${address:${pos_next}:2}"
-                                       pattern="0:"
-                                       ;;
-                               *)
-                                       match="${address:${pos_next}:2}"
-                                       pattern=":0"
-                                       ;;
-                       esac
-
-                       [ -z "${match}" ] && continue
-
-                       if [ "${match}" = "${pattern}" ]; then
-                               matches[${pos_start}]=$(( matches[${pos_start}] + 1))
-                       else
-                               break
-                       fi
-               done
+       local i addr1_oct addr2_oct
+       for i in 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30; do
+               addr1_oct="0x${addr1:${i}:2}"
+               addr2_oct="0x${addr2:${i}:2}"
+
+               [[ ${addr1_oct} -gt ${addr2_oct} ]] && return ${EXIT_TRUE}
        done
 
-       local pos_best
-       local pos_best_val=0
-       for i in $(seq 0 ${#matches[@]}); do
-               [ -z "${matches[${i}]}" ] && continue
+       return ${EXIT_FALSE}
+}
 
-               if [ ${matches[${i}]} -gt ${pos_best_val} ]; then
-                       pos_best=${i}
-                       pos_best_val=${matches[${i}]}
-               fi
-       done
+function ipv6_hash() {
+       local address=${1}
 
-       if [ -n "${pos_best}" ]; then
-               address_new="${address:0:${pos_best}}::"
+       assert isset address
 
-               local pos_end=$(( ${pos_best_val} * 2 + ${pos_best} + 1))
-               
-               if [ "${pos_best}" = "0" ]; then
-                       pos_end=$(( ${pos_end} - 1 ))
-               fi
+       # Explode address
+       address=$(ipv6_explode ${address})
 
-               address="${address_new}${address:${pos_end}:${#address}}"
-       fi
+       echo "${address//:/}"
+}
 
-       # If a prefix was provided we append it in the end
-       [ -n "${prefix}" ] && address="${address}/${prefix}"
+function ipv6_get_network() {
+       local addr=${1}
+       assert isset addr
 
-       assert ipv6_is_valid ${address}
+       # Check if a prefix (e.g. /64) is provided.
+       local prefix=$(ip_get_prefix ${addr})
+       assert ipv6_prefix_is_valid ${prefix}
 
-       echo "${address}"
+       local PREFIX6
+       eval $(ipcalc --ipv6 -p ${addr})
+       assert isset PREFIX6
+
+       print "${PREFIX6}/${prefix}"
 }
 
-function ipv6_explode() {
-       local address=${1}
+function ipv6_6rd_format_address() {
+       local isp_prefix="${1}"
+       assert ipv6_is_valid "${isp_prefix}"
 
-       assert isset address
+       local client_address="${2}"
+       assert ipv4_is_valid "${client_address}"
 
-       local prefix=$(ip_get_prefix ${address})
-       address=$(ip_split_prefix ${address})
+       local prefix="$(ipv6_get_prefix "${isp_prefix}")"
+       isp_prefix="$(ipv6_split_prefix "${isp_prefix}")"
 
-       if [ ${#address} -eq 39 ]; then
-               echo "${address}$([ -n "${prefix}" ] && echo "/${prefix}")"
-               return ${EXIT_OK}       
-       fi
+       # This only works for prefix lengths up to 32 bit.
+       assert [ "${prefix}" -le 32 ]
+       assert [ "${prefix}" -gt  0 ]
 
-       address=${address//::/:X:}
+       # Explode the address and throw away the second 32 bit.
+       local address="$(ipv6_explode "${isp_prefix}")"
 
-       local block
-       local block_count=0
-       local block_id
-       local block_max=8
-       local blocks=()
+       client_address="$(ipv6_6rd_format_client_address ${client_address})"
+       assert isset client_address
 
-       for block in ${address//:/\ }; do
-               blocks[${block_count}]=${block}
-               
-               block_count=$(( ${block_count} + 1 ))
-       done
+       local block1="0x${address:0:4}"
+       local block2="0x${address:5:4}"
+       local block3="0x${address:10:4}"
+       local block4="0x${address:15:4}"
 
-       if [ ${#blocks[@]} -lt ${block_max} ]; then
-               for block_id in $(seq ${#blocks[@]} -1 0); do
-                       block=${blocks[${block_id}]}
+       address="$(( (${block1} << 48) + (${block2} << 32) + (${block3} << 16) + ${block4} ))"
+       assert [ "${address}" -gt 0 ]
 
-                       [ -z "${block}" ] && continue
+       block1="0x${client_address:0:4}"
+       block2="0x${client_address:5:4}"
 
-                       if [ "${block}" = "X" ]; then
-                               blocks[${block_id}]="0000"
-                               break
-                       fi
+       client_address="$(( (${block1} << 48) + (${block2} << 32) ))"
 
-                       blocks[$(( ${block_max} - ${block_count} + ${block_id} ))]=${block}
-                       blocks[${block_id}]="0000"
-               done
+       # Fix for numbers that are interpreted by bash as negative
+       # numbers and therefore filled up with ones when shifted to
+       # the right. Weird.
+       if [ "${client_address}" -gt 0 ]; then
+               client_address="$(( ${client_address} >> ${prefix} ))"
+       else
+               local bitmask="$(( 1 << 63 ))"
+               client_address="$(( ${client_address} >> 1 ))"
+               client_address="$(( ${client_address} ^ ${bitmask} ))"
+               client_address="$(( ${client_address} >> $(( ${prefix} - 1 )) ))"
        fi
+       assert [ "${client_address}" -gt 0 ]
 
-       for block_id in $(seq 0 ${#blocks[@]}); do
-               block=${blocks[${block_id}]}
+       # XOR everything together
+       address="$(( ${address} ^ ${client_address} ))"
+       prefix="$(( ${prefix} + 32 ))"
 
-               [ -z "${block}" ] && block="0000"
+       local block formatted_address=":"
+       while [ ${address} -gt 0 ]; do
+               printf -v block "%x" "$(( ${address} & 0xffff ))"
+               formatted_address="${block}:${formatted_address}"
 
-               while [ "${#block}" -lt 4 ]; do
-                       block="0${block}"
-               done
-
-               blocks[${block_id}]=${block}
-       done
-
-       address=
-       for block in ${blocks[@]}; do
-               address="${address}:${block}"
+               address="$(( ${address} >> 16 ))"
        done
-       address=${address:1:39}
 
-       # If a prefix was provided we append it in the end again
-       [ -n "${prefix}" ] && address="${address}/${prefix}"
+       assert ipv6_is_valid "${formatted_address}"
 
-       assert ipv6_is_valid ${address}
+       # Implode the output IP address.
+       formatted_address="$(ipv6_implode "${formatted_address}")"
 
-       echo "${address}"
+       print "${formatted_address}/${prefix}"
 }
 
-function ipv6_hash() {
-       local address=${1}
-
+function ipv6_6rd_format_client_address() {
+       local address="${1}"
        assert isset address
 
-       # Explode address
-       address=$(ipv6_explode ${address})
-
-       echo "${address//:/}"
+       print "%02x%02x:%02x%02x" ${address//\./ }
 }