]> git.ipfire.org Git - people/stevee/network.git/blobdiff - src/functions/functions.dhcpd
network fix parameter passing when using ""
[people/stevee/network.git] / src / functions / functions.dhcpd
index 4a1f8ed459f9e80c9325e92e8d9ad26518c25606..3b1214fb937d0efd8ea8c3a4d4113f13bc3b5d52 100644 (file)
@@ -118,7 +118,7 @@ dhcpd_service() {
 }
 
 dhcpd_start() {
-       local services=$(dhcpd_service $@)
+       local services=$(dhcpd_service "$@")
 
        local service
        for service in ${services}; do
@@ -127,7 +127,7 @@ dhcpd_start() {
 }
 
 dhcpd_stop() {
-       local services=$(dhcpd_service $@)
+       local services=$(dhcpd_service "$@")
 
        local service
        for service in ${services}; do
@@ -138,7 +138,7 @@ dhcpd_stop() {
 dhcpd_restart() {
        # DHCP does not support a reload, so
        # we retsart it.
-       local services=$(dhcpd_service $@)
+       local services=$(dhcpd_service "$@")
 
        local service
        for service in ${services}; do
@@ -147,7 +147,25 @@ dhcpd_restart() {
 }
 
 dhcpd_reload() {
-       dhcpd_restart $@
+       dhcpd_restart "$@"
+}
+
+dhcpd_enable() {
+       local services=$(dhcpd_service "$@")
+
+       local service
+       for service in ${services}; do
+               service_enable ${service}
+       done
+}
+
+dhcpd_disable() {
+       local services=$(dhcpd_service "$@")
+
+       local service
+       for service in ${services}; do
+               service_disable ${service}
+       done
 }
 
 dhcpd_edit() {
@@ -163,10 +181,10 @@ dhcpd_edit() {
 
        case "${proto}" in
                ipv6)
-                       _dhcpd_edit_ipv6 $@ || return $?
+                       _dhcpd_edit_ipv6 "$@" || return $?
                        ;;
                ipv4)
-                       _dhcpd_edit_ipv4 $@ || return $?
+                       _dhcpd_edit_ipv4 "$@" || return $?
                        ;;
        esac
 
@@ -179,7 +197,7 @@ _dhcpd_edit_ipv4() {
        while [ $# -gt 0 ]; do
                case "${1}" in
                        --authoritative=*)
-                               val=$(cli_get_val ${1})
+                               val=$(cli_get_val "${1}")
 
                                if enabled val; then
                                        AUTHORITATIVE="true"
@@ -188,27 +206,30 @@ _dhcpd_edit_ipv4() {
                                fi
                                ;;
                        --default-lease-time=*)
-                               DEFAULT_LEASE_TIME=$(cli_get_val ${1})
+                               local val=$(cli_get_val "${1}")
+                               DEFAULT_LEASE_TIME=$(parse_time ${val})
 
                                if ! isinteger DEFAULT_LEASE_TIME; then
-                                       error "Invalid value for --default-lease-time."
+                                       error "Invalid value for --default-lease-time: ${val}"
                                        return ${EXIT_ERROR}
                                fi
                                ;;
                        --max-lease-time=*)
-                               MAX_LEASE_TIME=$(cli_get_val ${1})
+                               local val=$(cli_get_val "${1}")
+                               MAX_LEASE_TIME=$(parse_time ${val})
 
                                if ! isinteger MAX_LEASE_TIME; then
-                                       error "Invalid value for --max-lease-time."
+                                       error "Invalid value for --max-lease-time: ${val}"
                                        return ${EXIT_ERROR}
                                fi
                                ;;
                        --min-lease-time=*)
-                               MIN_LEASE_TIME=$(cli_get_val ${1})
+                               local val=$(cli_get_val "${1}")
+                               MIN_LEASE_TIME=$(parse_time ${val})
 
                                if isset MIN_LEASE_TIME; then
                                        if ! isinteger MIN_LEASE_TIME; then
-                                               error "Invalid value for --min-lease-time."
+                                               error "Invalid value for --min-lease-time: ${val}"
                                                return ${EXIT_ERROR}
                                        fi
                                fi
@@ -231,18 +252,20 @@ _dhcpd_edit_ipv6() {
        while [ $# -gt 0 ]; do
                case "${1}" in
                        --preferred-lifetime=*)
-                               PREFERRED_LIFETIME=$(cli_get_val ${1})
+                               local val=$(cli_get_val "${1}")
+                               PREFERRED_LIFETIME=$(parse_time ${val})
 
                                if ! isinteger PREFERRED_LIFETIME; then
-                                       error "Invalid value for --preferred-lifetime."
+                                       error "Invalid value for --preferred-lifetime: ${val}"
                                        return ${EXIT_ERROR}
                                fi
                                ;;
                        --valid-lifetime=*)
-                               VALID_LIFETIME=$(cli_get_val ${1})
+                               local val=$(cli_get_val "${1}")
+                               VALID_LIFETIME=$(parse_time ${val})
 
                                if ! isinteger VALID_LIFETIME; then
-                                       error "Invalid value for --valid-lifetime."
+                                       error "Invalid value for --valid-lifetime: ${val}"
                                        return ${EXIT_ERROR}
                                fi
                                ;;
@@ -489,7 +512,7 @@ dhcpd_subnet_match() {
 }
 
 dhcpd_subnet_exists() {
-       dhcpd_subnet_match $@
+       dhcpd_subnet_match "$@"
 }
 
 dhcpd_subnet_new() {
@@ -497,7 +520,7 @@ dhcpd_subnet_new() {
        assert isset proto
        shift
 
-       dhcpd_subnet_edit ${proto} "new" $@
+       dhcpd_subnet_edit ${proto} "new" "$@"
 }
 
 dhcpd_subnet_edit() {
@@ -534,7 +557,7 @@ dhcpd_subnet_edit() {
                case "${proto},${mode},${1}" in
                        # Common options
                        ipv6,new,*:*/*|ipv4,new,*.*.*.*/*)
-                               local subnet="$(cli_get_val ${1})"
+                               local subnet="$(cli_get_val "${1}")"
 
                                ADDRESS="$(ip_split_prefix ${subnet})"
                                PREFIX="$(ip_get_prefix ${subnet})"
@@ -594,7 +617,7 @@ dhcpd_subnet_edit() {
                        # IPv4 options
 
                        ipv4,*,--routers=*)
-                               ROUTERS=$(cli_get_val ${1})
+                               ROUTERS=$(cli_get_val "${1}")
                                ;;
 
                        *)
@@ -671,13 +694,21 @@ dhcpd_subnet_read() {
 }
 
 dhcpd_subnet_range_path() {
-       assert [ $# -eq 3 ]
+       assert [ $# -ge 2 -a $# -le 3 ]
 
        local proto=${1}
        local subnet=${2}
-       local range_id=${3}
 
-       print "$(dhcpd_subnet_path ${proto} ${subnet})/${DHCPD_SUBNET_RANGE_PREFIX}${range_id}"
+       local range=${3}
+       if ! isset range; then
+               dhcpd_subnet_path ${proto} ${subnet}
+               return $?
+       fi
+
+       # Add prefix
+       range="${DHCPD_SUBNET_RANGE_PREFIX}${range}"
+
+       print "$(dhcpd_subnet_path ${proto} ${subnet})/${range}"
        return ${EXIT_OK}
 }
 
@@ -696,27 +727,6 @@ dhcpd_subnet_range_settings() {
        return ${EXIT_OK}
 }
 
-dhcpd_subnet_new_range_id() {
-       local proto=${1}
-       assert isset proto
-
-       local subnet=${2}
-       assert isset subnet
-
-       local id=1 path
-       while :; do
-               path=$(dhcpd_subnet_range_path ${proto} ${subnet} ${id})
-               if [ ! -f "${path}" ]; then
-                       print "${id}"
-                       return ${EXIT_OK}
-               fi
-
-               id=$(( ${id} + 1 ))
-       done
-
-       return ${EXIT_ERROR}
-}
-
 dhcpd_subnet_range_new() {
        local proto=${1}
        assert isset proto
@@ -726,64 +736,25 @@ dhcpd_subnet_range_new() {
        assert isset subnet
        shift
 
-       # Allocate a new range id.
-       local range_id=$(dhcpd_subnet_new_range_id ${proto} ${subnet})
-       assert isinteger range_id
-
-       local path=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range_id})
-       assert isset path
-
-       # Create file (as a placeholder).
-       touch ${path}
-
-       dhcpd_subnet_range_edit ${proto} ${subnet} ${range_id} $@
-       local ret=$?
-
-       if [ ${ret} -ne ${EXIT_OK} ]; then
-               dhcpd_subnet_range_remove ${proto} ${subnet} ${range_id}
-               return ${EXIT_ERROR}
-       fi
-
-       return ${EXIT_OK}
-}
-
-dhcpd_subnet_range_edit() {
-       local proto=${1}
-       assert isset proto
-       shift
-
-       local subnet=${1}
-       assert isset subnet
-       shift
-
-       local range_id=${1}
-       assert isset range_id
-       shift
-
-       local ip_encode ip_is_valid
        local settings
        case "${proto}" in
                ipv6)
-                       ip_encode="ipv6_encode"
-                       ip_is_valid="ipv6_is_valid"
                        settings=${DHCPV6D_SUBNET_RANGE_SETTINGS}
                        ;;
                ipv4)
-                       ip_encode="ipv4_encode"
-                       ip_is_valid="ipv4_is_valid"
                        settings=${DHCPV4D_SUBNET_RANGE_SETTINGS}
                        ;;
        esac
        assert isset settings
-       local ${settings}
+       local range ${settings}
 
        while [ $# -gt 0 ]; do
                case "${1}" in
-                       --start=*)
-                               START=$(cli_get_val ${1})
-                               ;;
-                       --end=*)
-                               END=$(cli_get_val ${1})
+                       *-*)
+                               range=${1}
+
+                               START="${range%-*}"
+                               END="${range#*-}"
                                ;;
                        *)
                                error "Unknown argument: ${1}"
@@ -793,59 +764,72 @@ dhcpd_subnet_range_edit() {
                shift
        done
 
-       if ! isset START; then
-               error "You need to set the start of the IP range with --start=..."
-               return ${EXIT_ERROR}
-       fi
-
-       if ! isset END; then
-               error "You need to set the end of the IP range with --end=..."
-               return ${EXIT_ERROR}
-       fi
-
        local var
        for var in START END; do
-               if ! ${ip_is_valid} ${!var}; then
-                       error "'${!var}' is not a valid IP address."
+               if ! ${proto}_is_valid ${!var}; then
+                       error "'${!var}' is not a valid IP address"
                        return ${EXIT_ERROR}
                fi
        done
 
-       # XXX currently, this check can only be performed for IPv4
-       if [ "${proto}" = "ipv4" ]; then
-               # Check if the end address is greater than the start address.
-               local start_encoded=$(${ip_encode} ${START})
-               local end_encoded=$(${ip_encode} ${END})
+       # Check if the end address is larger than the start address
+       if ! ${proto}_addr_gt "${END}" "${START}"; then
+               error "The end address of the range must be greater than the start address"
+               return ${EXIT_ERROR}
+       fi
 
-               if [ ${start_encoded} -ge ${end_encoded} ]; then
-                       error "The start address of the range must be greater than the end address."
-                       return ${EXIT_ERROR}
-               fi
+       # Check if range already exists
+       if dhcpd_subnet_range_exists ${proto} ${subnet} ${range}; then
+               error "DHCP subnet range ${range} already exists"
+               return ${EXIT_ERROR}
+       fi
+
+       # Search for any overlaps
+       local overlaps=$(dhcpd_subnet_range_overlaps ${proto} ${subnet} ${range})
+       if isset overlaps; then
+               error "DHCP subnet range ${range} overlaps with ${overlaps}"
+               return ${EXIT_ERROR}
        fi
 
        # Write the configuration to file.
-       local file=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range_id})
+       local file=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range})
        assert isset file
 
        settings_write ${file} ${settings}
+
+       log INFO "DHCP subnet range ${range} created"
+
+       return ${EXIT_OK}
 }
 
 dhcpd_subnet_range_remove() {
-       local path=$(dhcpd_subnet_range_path $@)
+       assert [ $# -eq 3 ]
+
+       local proto=${1}
+       local subnet=${2}
+       local range=${3}
+
+       if ! dhcpd_subnet_range_exists ${proto} ${subnet} ${range}; then
+               error "DHCP subnet range ${range} does not exist"
+               return ${EXIT_ERROR}
+       fi
+
+       local path=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range})
        assert isset path
 
        rm -f ${path}
+
+       log INFO "DHCP subnet range ${range} removed"
+       return ${EXIT_OK}
 }
 
 dhcpd_subnet_range_list() {
-       local proto=${1}
-       assert isset proto
+       assert [ $# -eq 2 ]
 
+       local proto=${1}
        local subnet=${2}
-       assert isset subnet
 
-       local path=$(dhcpd_subnet_range_path ${proto} ${subnet} 0)
-       path=$(dirname ${path})
+       local path=$(dhcpd_subnet_range_path ${proto} ${subnet})
 
        local p
        for p in ${path}/${DHCPD_SUBNET_RANGE_PREFIX}*; do
@@ -859,17 +843,93 @@ dhcpd_subnet_range_list() {
 }
 
 dhcpd_subnet_range_read() {
+       assert [ $# -eq 3 ]
+
        local proto=${1}
-       assert isset proto
+       local subnet=${2}
+       local range=${3}
+
+       local file=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range})
+       settings_read ${file}
+}
+
+dhcpd_subnet_range_exists() {
+       assert [ $# -eq 3 ]
 
+       local proto=${1}
        local subnet=${2}
-       assert isset subnet
+       local range=${3}
 
-       local range_id=${3}
-       assert isset range_id
+       local start=${range%-*}
+       local end=${range#*-}
 
-       local file=$(dhcpd_subnet_range_path ${proto} ${subnet} ${range_id})
-       settings_read ${file}
+       assert isset start
+       assert isset end
+
+       local settings=$(dhcpd_subnet_range_settings ${proto})
+
+       local r ${settings}
+       for r in $(dhcpd_subnet_range_list ${proto} ${subnet}); do
+               dhcpd_subnet_range_read ${proto} ${subnet} ${r}
+
+               # If start and end addresses equal we got a match
+               if ${proto}_addr_eq "${START}" "${start}" && ${proto}_addr_eq "${END}" "${end}"; then
+                       return ${EXIT_TRUE}
+               fi
+       done
+
+       return ${EXIT_FALSE}
+}
+
+dhcpd_subnet_range_overlaps() {
+       assert [ $# -eq 3 ]
+
+       local proto=${1}
+       local subnet=${2}
+       local range=${3}
+
+       local start=${range%-*}
+       local end=${range#*-}
+
+       assert isset start
+       assert isset end
+
+       local settings=$(dhcpd_subnet_range_settings ${proto})
+
+       local r ${settings}
+       for r in $(dhcpd_subnet_range_list ${proto} ${subnet}); do
+               dhcpd_subnet_range_read ${proto} ${subnet} ${r}
+
+               # Check if the new range is a sub-range of any existing range
+
+               # Check if the start address is somewhere in this range
+               if ${proto}_addr_ge ${START} ${start} && ${proto}_addr_le ${START} ${end}; then
+                       print "${r}"
+                       return ${EXIT_TRUE}
+               fi
+
+               # Check if the end address is somewhere in this range
+               if ${proto}_addr_ge ${END} ${start} && ${proto}_addr_le ${END} ${end}; then
+                       print "${r}"
+                       return ${EXIT_TRUE}
+               fi
+
+               # Check if any existing range is a sub-range of the new range
+
+               # Check if the start address is somewhere in this range
+               if ${proto}_addr_ge ${start} ${START} && ${proto}_addr_le ${start} ${END}; then
+                       print "${r}"
+                       return ${EXIT_TRUE}
+               fi
+
+               # Check if the end address is somewhere in this range
+               if ${proto}_addr_ge ${end} ${START} && ${proto}_addr_le ${end} ${END}; then
+                       print "${r}"
+                       return ${EXIT_TRUE}
+               fi
+       done
+
+       return ${EXIT_FALSE}
 }
 
 dhcpd_subnet_settings() {
@@ -888,7 +948,7 @@ dhcpd_subnet_settings() {
 }
 
 dhcpd_subnet_options_file() {
-       local path=$(dhcpd_subnet_path $@)
+       local path=$(dhcpd_subnet_path "$@")
        assert isset path
 
        print "${path}/options"
@@ -1030,9 +1090,9 @@ _dhcpd_write_subnet() {
        fi
 
        # Add the ranges.
-       local range_id
-       for range_id in $(dhcpd_subnet_range_list ${proto} ${subnet} ${range_id}); do
-               _dhcpd_write_subnet_range ${proto} ${subnet} ${range_id} ${file}
+       local range
+       for range in $(dhcpd_subnet_range_list ${proto} ${subnet} ${range}); do
+               _dhcpd_write_subnet_range ${proto} ${subnet} ${range} ${file}
        done
 
        # End this subnet block.
@@ -1128,7 +1188,7 @@ _dhcpd_write_subnet_range() {
 
        local proto=${1}
        local subnet=${2}
-       local range_id=${3}
+       local range=${3}
        local file=${4}
 
        local settings=$(dhcpd_subnet_range_settings ${proto})
@@ -1136,10 +1196,7 @@ _dhcpd_write_subnet_range() {
 
        # Read the configuration settings.
        local ${settings}
-       dhcpd_subnet_range_read ${proto} ${subnet} ${range_id}
-
-       # Print the range line.
-       print " # Range id ${range_id}." >> ${file}
+       dhcpd_subnet_range_read ${proto} ${subnet} ${range}
 
        case "${proto}" in
                ipv6)