#!/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 . # # # ############################################################################### # A list of supported versions of the IP protocol IP_SUPPORTED_PROTOCOLS="" ip_split_prefix() { local address=${1} assert isset address echo "${address%%/*}" } ip_get_prefix() { local address=${1} assert isset address # Break if no prefix is provided [[ ${address} =~ \/ ]] || return ${EXIT_OK} echo "${address##*/}" } ip_detect_protocol() { local address="${1}" assert isset address # Remove prefix so that we can handle subnet, too address=$(ip_split_prefix ${address}) local protocol for protocol in ${IP_SUPPORTED_PROTOCOLS}; do if ${protocol}_is_valid "${address}"; then echo "${protocol}" return ${EXIT_OK} fi done return ${EXIT_ERROR} } ip_protocol_is_supported() { local proto=${1} assert isset proto list_match ${proto} ${IP_SUPPORTED_PROTOCOLS} } # Returns true if all IP addresses are of the same protocol ip_protocol_match() { local address="${1}" shift # Get protocol of the first address local protocol="$(ip_detect_protocol "${address}")" # Check if all other addresses match the protocol for address in $@; do local p="$(ip_detect_protocol "${address}")" if [ "${p}" != "${protocol}" ]; then return ${EXIT_FALSE} fi done return ${EXIT_TRUE} } ip_is_valid() { local address=${1} assert isset address local protocol for protocol in ${IP_SUPPORTED_PROTOCOLS}; do if ${protocol}_is_valid "${address}"; then return ${EXIT_TRUE} fi done return ${EXIT_FALSE} } ip_net_is_valid() { local network=${1} assert isset network local protocol for protocol in ${IP_SUPPORTED_PROTOCOLS}; do if ${protocol}_net_is_valid "${network}"; then return ${EXIT_TRUE} fi done return ${EXIT_FALSE} } 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} } ip_get_network() { inetcalc -n "$@" && return ${EXIT_OK} || return ${EXIT_ERROR} } ip_network_is_subset_of() { assert [ $# -eq 2 ] inetcalc -s "$@" && return ${EXIT_TRUE} || return ${EXIT_FALSE} } ip_address_add() { local device=${1} local address=${2} assert isset address assert device_exists ${device} local prefix=$(ip_get_prefix ${address}) address=$(ip_split_prefix ${address}) assert isset prefix assert isset address echo "ADDRESS = $address" # Detect the protocol version local protocol=$(ip_detect_protocol "${address}") assert ip_protocol_is_supported "${protocol}" case "${protocol}" in ipv6) assert ipv6_prefix_is_valid "${prefix}" ;; ipv4) assert ipv4_prefix_is_valid "${prefix}" ;; esac case "${protocol}" in ipv4) if ipv4_detect_duplicate ${device} ${address}; then error_log "Duplicate address detected on zone '${device}' (${address})." error_log "Cannot continue." return ${EXIT_ERROR} fi ;; esac if ! device_has_ip ${device} ${address}/${prefix}; then assert ip addr add ${address}/${prefix} dev ${device} log DEBUG "IP address '${address}' (${protocol}) was successfully configured on device '${device}'." case "${protocol}" in ipv4) # Announce our new address to the neighbours ipv4_update_neighbours ${device} ${address} ;; esac else log DEBUG "IP address '${address}' (${protocol}) was already configured on device '${device}'." fi return ${EXIT_OK} } ip_address_del() { local device=${1} local address=${2} assert isset address assert device_exists ${device} local prefix=$(ip_get_prefix ${address}) address=$(ip_split_prefix ${address}) assert isset prefix # Detect the protocol version local protocol=$(ip_detect_protocol "${address}") assert ip_protocol_is_supported "${protocol}" if device_has_ip ${device} ${address}/${prefix}; then assert ip addr del ${address}/${prefix} dev ${device} log DEBUG "IP address '${address}' (${protocol}) was successfully removed from device '${device}'." else log DEBUG "IP address '${address}' (${protocol}) was not configured on device '${device}'." fi return ${EXIT_OK} } # Get all currently assigned addresse for a given network ip_get_assigned_addresses_from_net() { local net=${1} shift local args="$@" if ! ip_net_is_valid ${net}; then log ERROR "IP net ${net} is invalid" return ${EXIT_ERROR} fi local line local addresses # We read the output of $(ip addr show to ${net} ${args}) while read -r line; do # We are only interested in lines which start with inet or inet6 [[ "${line}" =~ ^(inet6 |inet ) ]] || continue # We need the second word the line line=(${line}) list_append "addresses" "$(ip_split_prefix "${line[1]}")" done <<< "$(ip addr show to "${net}" ${args})" # We sort the list to get the lowest IP as first item list_sort ${addresses} }