]> git.ipfire.org Git - people/stevee/network.git/commitdiff
Add commands to manage static routes.
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Aug 2012 13:27:23 +0000 (13:27 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 10 Aug 2012 13:27:23 +0000 (13:27 +0000)
functions.constants
functions.ip
functions.ipv4
functions.ipv6
functions.route [new file with mode: 0644]
functions.util
network

index 2cb11452f4a683cbcd3fff1dd80854516eccfc34..1fcc3a7d67a3433f3633dd892ea6eb1a978de6a5 100644 (file)
@@ -43,6 +43,10 @@ ROUTING_DB_DIR=${RUN_DIR}/routing
 
 DB_CONNECTION_FILE="${LOG_DIR}/connections.db"
 
+# (Static) route settings.
+NETWORK_CONFIG_ROUTES="${NETWORK_CONFIG_DIR}/routes"
+NETWORK_CONFIG_ROUTES_PARAMS="network gateway unreachable"
+
 # Proper error codes
 EXIT_OK=0
 EXIT_ERROR=1
index 2fa2d7624b560f3cbf9ead244143f1d4183901ea..d19c9cfad0529de95b837f9065e8a1232cbb5142 100644 (file)
@@ -73,6 +73,48 @@ function ip_is_valid() {
        isset proto && return ${EXIT_TRUE} || return ${EXIT_FALSE}
 }
 
+function ip_is_network() {
+       local network=${1}
+       assert isset network
+
+       # Get the address part.
+       local address=$(ip_split_prefix ${network})
+       isset address || return ${EXIT_FALSE}
+
+       # Get the prefix.
+       local prefix=$(ip_get_prefix ${network})
+       isset prefix || return ${EXIT_FALSE}
+
+       # Detect the protocol.
+       local proto=$(ip_detect_protocol ${address})
+       assert isset proto
+
+       # Check if the prefix is correct.
+       ip_prefix_is_valid ${proto} ${prefix} || return ${EXIT_FALSE}
+
+       return ${EXIT_TRUE}
+}
+
+function ip_prefix_is_valid() {
+       local proto=${1}
+       assert isset proto
+
+       local prefix=${2}
+
+       case "${proto}" in
+               ipv4)
+                       ipv4_prefix_is_valid ${prefix}
+                       return $?
+                       ;;
+               ipv6)
+                       ipv6_prefix_is_valid ${prefix}
+                       return $?
+                       ;;
+       esac
+
+       assert ip_protocol_is_supported ${proto}
+}
+
 function ip_address_add() {
        local device=${1}
        local address=${2}
index a3b3ce46acb9d6eeb9b6b684ed99969de57d2112..a48839dbb271743e3ff156a7c13d3caea6a3eb61 100644 (file)
@@ -34,6 +34,16 @@ function ipv4_is_valid() {
        esac
 }
 
+function ipv4_prefix_is_valid() {
+       local prefix=${1}
+       assert isset prefix
+
+       [ ${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}
index 53c79a0759ddf6e31c4de9ac7e6ba572a1ddfa41..d1a43e4d4046a810578230edbdc1d72b094ce654 100644 (file)
@@ -150,6 +150,16 @@ 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_implode() {
        local address=${1}
 
diff --git a/functions.route b/functions.route
new file mode 100644 (file)
index 0000000..65782fb
--- /dev/null
@@ -0,0 +1,232 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2012  IPFire Network Development Team                         #
+#                                                                             #
+# 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/>.       #
+#                                                                             #
+###############################################################################
+#
+# Functions for static routing.
+#
+
+function route_add() {
+       local ${NETWORK_CONFIG_ROUTES_PARAMS}
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --gateway=*)
+                               gateway=$(cli_get_val ${1})
+                               ;;
+                       --unreachable)
+                               unreachable="true"
+                               ;;
+                       *)
+                               network=${1}
+                               ;;
+               esac
+               shift
+       done
+
+       assert isset network
+
+       if ! ip_is_valid ${network}; then
+               error "The given network is invalid: ${network}"
+               return ${EXIT_ERROR}
+       fi
+
+       if route_find_duplicate ${network}; then
+               error "A route to ${network} does already exist."
+               return ${EXIT_ERROR}
+       fi
+
+       # Check if gateway and unreachable are both enabled.
+       if isset gateway && enabled unreachable; then
+               error "You cannot use both, --gateway=${gateway} and --unreachable at the same time."
+               return ${EXIT_ERROR}
+       fi
+
+       if ! ip_is_valid ${gateway}; then
+               error "--gateway= is not a valid IP address."
+               return ${EXIT_ERROR}
+       fi
+
+       # Check if network and gateway IP protocol version match.
+       if isset gateway; then
+               local network_proto=$(ip_detect_protocol ${network})
+               local gateway_proto=$(ip_detect_protocol ${gateway})
+
+               if [ "${network_proto}" != "${gateway_proto}" ]; then
+                       error "The IP protocol version of the given network and gateway did not match."
+                       return ${EXIT_ERROR}
+               fi
+       fi
+
+       local line
+       list_append line "network=\"${network}\""
+
+       # Add gateway to configuration entry when it is set.
+       if isset gateway; then
+               list_append line "gateway=\"${gateway}\""
+       fi
+
+       # Add unreachable to configuration entry when it is set.
+       if enabled unreachable; then
+               list_append line "unreachable=\"true\""
+       fi
+
+       # Write line to file.
+       print "${line}" >> ${NETWORK_CONFIG_ROUTES}
+
+       log INFO "New route to network '${network}' has been added."
+       return ${EXIT_OK}
+}
+
+function route_remove() {
+       local _network=${1}
+       assert isset _network
+
+       local found="false"
+
+       local ${NETWORK_CONFIG_ROUTES_PARAMS}
+       local line
+       while read line; do
+               route_parse_line ${line}
+               [ $? -eq ${EXIT_OK} ] || continue
+
+               # Skip the rule, we want to delete.
+               if [ "${network}" = "${_network}" ]; then
+                       found="true"
+                       continue
+               fi
+
+               print "${line}"
+       done < ${NETWORK_CONFIG_ROUTES} > ${NETWORK_CONFIG_ROUTES}.tmp
+       mv ${NETWORK_CONFIG_ROUTES}{.tmp,}
+
+       if enabled found; then
+               log INFO "Route to network '${_network}' has been removed."
+       else
+               error "No route to network '${_network}' was found."
+               return ${EXIT_ERROR}
+       fi
+
+       return ${EXIT_OK}
+}
+
+function route_list() {
+       local protocol
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --protocol=*)
+                               protocol=$(cli_get_val ${1})
+                               ;;
+                       *)
+                               warning "Unrecognized argument: ${1}"
+                               ;;
+               esac
+               shift
+       done
+
+       if [ ! -r "${NETWORK_CONFIG_ROUTES}" ]; then
+               print "No static routes defined."
+               return ${EXIT_OK}
+       fi
+
+       local format="%-40s %-20s"
+       print "${format}" "NETWORK/HOST" "GATEWAY"
+
+       local ${NETWORK_CONFIG_ROUTES_PARAMS}
+       local line
+       while read line; do
+               route_parse_line ${line}
+               [ $? -eq ${EXIT_OK} ] || continue
+
+               if enabled unreachable; then
+                       gateway="<unreachable>"
+               fi
+
+               # Filter all entries with a wrong protocol.
+               if isset protocol; then
+                       local proto=$(ip_detect_protocol ${network})
+                       [ "${protocol}" = "${proto}" ] || continue
+               fi
+
+               print "${format}" "${network}" "${gateway}"
+       done < ${NETWORK_CONFIG_ROUTES}
+}
+
+function route_find_duplicate() {
+       local _network=${1}
+
+       [ -r "${NETWORK_CONFIG_ROUTES}" ] || return ${EXIT_FALSE}
+
+       local ${NETWORK_CONFIG_ROUTES_PARAMS}
+       local line
+       while read line; do
+               route_parse_line ${line}
+
+               # Check if the network is already in use.
+               [ "${network}" = "${_network}" ] && return ${EXIT_TRUE}
+       done < ${NETWORK_CONFIG_ROUTES}
+
+       return ${EXIT_FALSE}
+}
+
+function route_parse_line() {
+       local arg
+
+       # Reset all possible settings.
+       for arg in ${NETWORK_CONFIG_ROUTES_PARAMS}; do
+               printf -v ${arg} "%s" ""
+       done
+
+       while read arg; do
+               case "${arg}" in
+                       network=*)
+                               network=$(cli_get_val ${arg})
+                               ;;
+                       gateway=*)
+                               gateway=$(cli_get_val ${arg})
+                               ;;
+                       unreachable=*)
+                               unreachable=$(cli_get_val ${arg})
+                               ;;
+               esac
+       done <<< "$(args $@)"
+
+       ### Check if all values are correctly set.
+
+       # network must be set.
+       isset network || return ${EXIT_ERROR}
+
+       # network must be a valid.
+       ip_is_network ${network} || return ${EXIT_ERROR}
+
+       # Check gateway settings.
+       if isset gateway; then
+               # When gateway is set, unreachable cannot be set.
+               isset unreachable && return ${EXIT_ERROR}
+
+               # Must be a valid IP address.
+               ip_is_valid ${gateway} || return ${EXIT_ERROR}
+       else
+               # Either gateway or unreachable must be set.
+               isset unreachable || return ${EXIT_ERROR}
+       fi
+
+       return ${EXIT_OK}
+}
index 76e5ba1209d01deec73d4c3f9a19f7993ac0f6f7..98c80d882f186cb89a3e1541d3b6f5070dbc4642 100644 (file)
@@ -26,6 +26,13 @@ function print() {
        printf -- "${fmt}\n" "$@"
 }
 
+# The args() function takes a number of arguments like
+#   var1="abc d" var2="abc" var3="abcd e"
+# and splits them into several arguments, devided by newline
+function args() {
+       echo "$@" | xargs printf "%s\n"
+}
+
 # Print a pretty error message
 function error() {
        echo -e " ${COLOUR_ERROR}ERROR${COLOUR_NORMAL}  : $@" >&2
diff --git a/network b/network
index c22b23f84fb9075c261e3a07abd939c465f43dbd..a393d357d233589e956e6435fa4d38389958b61f 100755 (executable)
--- a/network
+++ b/network
@@ -558,6 +558,39 @@ function cli_list_hooks() {
        done | sort -u
 }
 
+function cli_route() {
+       if cli_help_requested $@; then
+               cli_show_man network-route
+               exit ${EXIT_OK}
+       fi
+
+       local action=${1}
+       shift
+
+       case "${action}" in
+               # Add a new route.
+               add)
+                       route_add $@
+                       ;;
+               # Remove an existing route.
+               remove)
+                       route_remove $@
+                       ;;
+               # List all routes.
+               list)
+                       route_list $@
+                       ;;
+               *)
+                       error "Unrecognized action: ${action}"
+                       cli_run_help network route
+
+                       exit ${EXIT_ERROR}
+                       ;;
+       esac
+
+       exit ${EXIT_OK}
+}
+
 function cli_start() {
        if cli_help_requested $@; then
                cli_show_man network
@@ -752,7 +785,7 @@ case "${action}" in
                init_run
                ;;
 
-       config|hostname|port|device|zone|start|stop|restart|status|reset|dns)
+       config|hostname|port|device|zone|start|stop|restart|status|reset|dns|route)
                cli_${action} $@
                ;;