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() {
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//\./ }
}