]> git.ipfire.org Git - people/ms/network.git/commitdiff
network: New hook ipv6-static.
authorMichael Tremer <michael.tremer@ipfire.org>
Sat, 19 Jun 2010 13:15:44 +0000 (15:15 +0200)
committerMichael Tremer <michael.tremer@ipfire.org>
Sat, 19 Jun 2010 13:15:44 +0000 (15:15 +0200)
functions.device
functions.ipv6 [new file with mode: 0644]
functions.zone
hooks/bridge.configs/ipv6-static [new file with mode: 0755]

index 8f28871359c14ff6d13040792c4ee388c9221cd0..44a3d79d9d3ada2de00443fa9f0cd8a47c7efd63 100644 (file)
@@ -732,3 +732,22 @@ function device_has_ipv4() {
 
        ip addr show ${device} | grep -q -e "inet " -e "${addr}"
 }
+
+function device_has_ipv6() {
+       local device=${1}
+       local addr=${2}
+
+       if ! device_exists ${device}; then
+               error "Device '${device}' does not exist."
+               return ${EXIT_ERROR}
+       fi
+
+       local prefix=${addr##*/}
+       addr=$(ipv6_implode ${addr%%/*})
+
+       if [ -n "${prefix}" ]; then
+               addr="${addr}/${prefix}"
+       fi
+
+       ip addr show ${device} | grep -q "inet6 ${addr}"
+}
diff --git a/functions.ipv6 b/functions.ipv6
new file mode 100644 (file)
index 0000000..4932184
--- /dev/null
@@ -0,0 +1,229 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2010  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+function ipv6_device_autoconf_enable() {
+       local device=${1}
+
+       if ! device_exists ${device}; then
+               error "Device '${device}' does not exist."
+               return ${EXIT_ERROR}
+       fi
+
+       echo 1 > /proc/sys/net/ipv6/conf/${device}/autoconf
+}
+
+function ipv6_device_autoconf_disable() {
+       local device=${1}
+
+       if ! device_exists ${device}; then
+               error "Device '${device}' does not exist."
+               return ${EXIT_ERROR}
+       fi
+
+       echo 0 > /proc/sys/net/ipv6/conf/${device}/autoconf
+}
+
+function ipv6_is_valid() {
+       local address=${1}
+
+       # Check length
+       [ ${#address} -gt 39 ] && return ${EXIT_ERROR}
+
+       # XXX find :: twice?
+       # XXX check for documentation prefix?
+
+       # Check for bad characters
+       local char
+       for char in 0 1 2 3 4 5 6 7 8 9 a b c d e f :; do
+               address=${address//${char}/}
+       done
+       [ -n "${address}" ] && return ${EXIT_ERROR}
+
+       return ${EXIT_OK}
+}
+
+function ipv6_implode() {
+       local address=${1}
+
+       if ! ipv6_is_valid ${address}; then
+               error "IPv6 address is invalid: ${address}"
+               return ${EXIT_ERROR}
+       fi
+
+       # Make proper address in exploded format
+       address=$(ipv6_explode ${address})
+
+       local block
+       local char
+       local i
+
+       local address_new
+       local block_new
+
+       for block in ${address//:/\ }; do
+               block_new=
+               for i in $(seq 0 ${#block}); do
+                       char="${block:${i}:1}"
+
+                       [ -z "${char}" ] && continue
+
+                       if [ -z "${block_new}" ] && [ "${char}" = "0" ]; then
+                               continue
+                       fi
+
+                       block_new="${block_new}${char}"
+               done
+
+               [ -z "${block_new}" ] && block_new="0"
+
+               address_new="${address_new}:${block_new}"
+       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
+       done
+
+       local pos_best
+       local pos_best_val=0
+       for i in $(seq 0 ${#matches[@]}); do
+               [ -z "${matches[${i}]}" ] && continue
+
+               if [ ${matches[${i}]} -gt ${pos_best_val} ]; then
+                       pos_best=${i}
+                       pos_best_val=${matches[${i}]}
+               fi
+       done
+
+       if [ -n "${pos_best}" ]; then
+               address_new="${address:0:${pos_best}}::"
+
+               local pos_end=$(( ${pos_best_val} * 2 + ${pos_best} + 1))
+               
+               if [ "${pos_best}" = "0" ]; then
+                       pos_end=$(( ${pos_end} - 1 ))
+               fi
+
+               address="${address_new}${address:${pos_end}:${#address}}"
+       fi
+
+       assert ipv6_is_valid ${address}
+
+       echo "${address}"
+}
+
+function ipv6_explode() {
+       local address=${1}
+
+       if [ ${#address} -eq 39 ]; then
+               echo "${address}"
+               return ${EXIT_OK}       
+       fi
+
+       address=${address//::/:X:}
+
+       local block
+       local block_count=0
+       local block_id
+       local block_max=8
+       local blocks=()
+
+       for block in ${address//:/\ }; do
+               blocks[${block_count}]=${block}
+               
+               block_count=$(( ${block_count} + 1 ))
+       done
+
+       if [ ${#blocks[@]} -lt ${block_max} ]; then
+               for block_id in $(seq ${#blocks[@]} -1 0); do
+                       block=${blocks[${block_id}]}
+
+                       [ -z "${block}" ] && continue
+
+                       if [ "${block}" = "X" ]; then
+                               blocks[${block_id}]="0000"
+                               break
+                       fi
+
+                       blocks[$(( ${block_max} - ${block_count} + ${block_id} ))]=${block}
+                       blocks[${block_id}]="0000"
+               done
+       fi
+
+       for block_id in $(seq 0 ${#blocks[@]}); do
+               block=${blocks[${block_id}]}
+
+               [ -z "${block}" ] && block="0000"
+
+               while [ "${#block}" -lt 4 ]; do
+                       block="0${block}"
+               done
+
+               blocks[${block_id}]=${block}
+       done
+
+       address=
+       for block in ${blocks[@]}; do
+               address="${address}:${block}"
+       done
+       address=${address:1:39}
+
+       assert ipv6_is_valid ${address}
+
+       echo "${address}"
+}
+
+function ipv6_hash() {
+       local address=${1}
+
+       # Explode address
+       address=$(ipv6_explode ${address})
+
+       echo "${address//:/}"
+}
index e1b6ea54e3ae99405a14a31ad982234b8ae052d8..9fc343b01b4efdbee4a1ec7fdf6b6a74202cb7b4 100644 (file)
@@ -426,6 +426,10 @@ function zone_has_ipv4() {
        device_has_ipv4 $@
 }
 
+function zone_has_ipv6() {
+       device_has_ipv6 $@
+}
+
 function zone_db() {
        local zone=${1}
        local action=${2}
diff --git a/hooks/bridge.configs/ipv6-static b/hooks/bridge.configs/ipv6-static
new file mode 100755 (executable)
index 0000000..f39a293
--- /dev/null
@@ -0,0 +1,138 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2010  Michael Tremer & Christian Schmidt                      #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+###############################################################################
+
+. /lib/network/header-port
+
+HOOK_SETTINGS="HOOK ADDRESS PREFIX GATEWAY"
+
+function _check() {
+       assert isset ADDRESS
+       assert isinteger PREFIX
+
+       if [ ${PREFIX} -gt 64 ]; then
+               error "PREFIX is greater than 64."
+               exit ${EXIT_ERROR}
+       fi
+}
+
+function _create() {
+       local zone=${1}
+       shift
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --address=*)
+                               ADDRESS=${1#--address=}
+                               ;;
+                       --prefix=*)
+                               PREFIX=${1#--prefix=}
+                               ;;
+                       --gateway=*)
+                               GATEWAY=${1#--gateway=}
+                               ;;
+               esac
+               shift
+       done
+
+       # Store IPv6 address in full format
+       ADDRESS=$(ipv6_explode ${ADDRESS})
+
+       if [ -n "${GATEWAY}" ]; then
+               GATEWAY=$(ipv6_explode ${GATEWAY})
+       fi
+
+       config_write $(zone_dir ${zone})/config.${HOOK}.$(ipv6_hash ${ADDRESS}).${PREFIX} ${HOOK_SETTINGS}
+
+       exit ${EXIT_OK}
+}
+
+function _up() {
+       local zone=${1}
+       local config=${2}
+       shift 2
+
+       if ! device_exists ${zone}; then
+               error "Zone '${zone}' doesn't exist."
+               exit ${EXIT_ERROR}
+       fi
+       
+       config_read $(zone_dir ${zone})/${config}
+
+       if ! zone_has_ipv6 ${zone} ${ADDRESS}/${PREFIX}; then
+               ip addr add ${ADDRESS}/${PREFIX} dev ${zone}
+       else
+               warning "Do not set IPv6 address '${ADDRESS}/${PREFIX}' because it was already configured on zone '${zone}'."
+       fi
+
+       if zone_is_nonlocal ${zone} && [ -n "${GATEWAY}" ]; then
+               : # XXX to be done
+       fi
+
+       exit ${EXIT_OK}
+}
+
+function _down() {
+       local zone=${1}
+       local config=${2}
+       shift 2
+
+       if ! device_exists ${zone}; then
+               error "Zone '${zone}' doesn't exist."
+               exit ${EXIT_ERROR}
+       fi
+       
+       config_read $(zone_dir ${zone})/${config}
+
+       if zone_has_ipv6 ${zone} ${ADDRESS}/${PREFIX}; then
+               ip addr del ${ADDRESS}/${PREFIX} dev ${zone}
+       fi
+
+       exit ${EXIT_OK}
+}
+
+function _status() {
+       local zone=${1}
+       local config=${2}
+       shift 2
+
+       if ! device_exists ${zone}; then
+               error "Zone '${zone}' doesn't exist."
+               exit ${EXIT_ERROR}
+       fi
+       
+       config_read $(zone_dir ${zone})/${config}
+
+       printf "        %10s - " "${HOOK}"
+       if zone_has_ipv6 ${zone} ${ADDRESS}/${PREFIX}; then
+               echo -ne "${COLOUR_OK} OK  ${COLOUR_NORMAL}"
+       else
+               echo -ne "${COLOUR_ERROR}ERROR${COLOUR_NORMAL}"
+       fi
+       echo " - $(ipv6_implode ${ADDRESS})/${PREFIX}"
+
+       if [ -n "${GATEWAY}" ]; then
+               echo "          Gateway: ${GATEWAY}"
+       fi
+
+       exit ${EXIT_OK}
+}
+
+run $@