}
dhcpd_start() {
- local services=$(dhcpd_service $@)
+ local services=$(dhcpd_service "$@")
local service
for service in ${services}; do
}
dhcpd_stop() {
- local services=$(dhcpd_service $@)
+ local services=$(dhcpd_service "$@")
local service
for service in ${services}; do
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
}
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() {
case "${proto}" in
ipv6)
- _dhcpd_edit_ipv6 $@ || return $?
+ _dhcpd_edit_ipv6 "$@" || return $?
;;
ipv4)
- _dhcpd_edit_ipv4 $@ || return $?
+ _dhcpd_edit_ipv4 "$@" || return $?
;;
esac
while [ $# -gt 0 ]; do
case "${1}" in
--authoritative=*)
- val=$(cli_get_val ${1})
+ val=$(cli_get_val "${1}")
if enabled val; then
AUTHORITATIVE="true"
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
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
;;
}
dhcpd_subnet_exists() {
- dhcpd_subnet_match $@
+ dhcpd_subnet_match "$@"
}
dhcpd_subnet_new() {
assert isset proto
shift
- dhcpd_subnet_edit ${proto} "new" $@
+ dhcpd_subnet_edit ${proto} "new" "$@"
}
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})"
# IPv4 options
ipv4,*,--routers=*)
- ROUTERS=$(cli_get_val ${1})
+ ROUTERS=$(cli_get_val "${1}")
;;
*)
}
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}
}
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
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}"
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
}
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() {
}
dhcpd_subnet_options_file() {
- local path=$(dhcpd_subnet_path $@)
+ local path=$(dhcpd_subnet_path "$@")
assert isset path
print "${path}/options"
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.
local proto=${1}
local subnet=${2}
- local range_id=${3}
+ local range=${3}
local file=${4}
local settings=$(dhcpd_subnet_range_settings ${proto})
# 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)