2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2012 IPFire Network Development Team #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 DHCPV6D_CONFIG_FILE
="/etc/dhcp/dhcpd6.conf"
23 DHCPV4D_CONFIG_FILE
="/etc/dhcp/dhcpd.conf"
25 DHCPV6D_CONFIG_DIR
="${NETWORK_CONFIG_DIR}/dhcpd/ipv6"
26 DHCPV4D_CONFIG_DIR
="${NETWORK_CONFIG_DIR}/dhcpd/ipv4"
28 DHCPV6D_OPTIONS_FILE
="${DHCPV6D_CONFIG_DIR}/options"
29 DHCPV4D_OPTIONS_FILE
="${DHCPV4D_CONFIG_DIR}/options"
31 DHCPV6D_SETTINGS_FILE
="${DHCPV6D_CONFIG_DIR}/settings"
32 DHCPV4D_SETTINGS_FILE
="${DHCPV4D_CONFIG_DIR}/settings"
49 DHCPD_SUBNET_PREFIX
="subnet-"
50 #DHCPD_SUBNET_POOL_PREFIX="pool-"
51 DHCPD_SUBNET_RANGE_PREFIX
="range-"
53 DHCPD_SUBNET_SETTINGS
="ADDRESS PREFIX"
54 DHCPV6D_SUBNET_SETTINGS
="${DHCPD_SUBNET_SETTINGS} PREFIX_DELEGATION \
55 DELEGATED_PREFIX_FIRST DELEGATED_PREFIX_LAST DELEGATED_PREFIX_SIZE"
56 DHCPV4D_SUBNET_SETTINGS
="${DHCPD_SUBNET_SETTINGS} ROUTERS"
58 DHCPD_SUBNET_RANGE_SETTINGS
="START END"
59 DHCPV6D_SUBNET_RANGE_SETTINGS
="${DHCPD_SUBNET_RANGE_SETTINGS}"
60 DHCPV4D_SUBNET_RANGE_SETTINGS
="${DHCPD_SUBNET_RANGE_SETTINGS}"
73 dhcp-client-identifier \
75 dhcp-max-message-size \
88 DHCPV6D_SUBNET_OPTIONS
="${DHCPV6D_OPTIONS}"
89 DHCPV4D_SUBNET_OPTIONS
="${DHCPV4D_OPTIONS}"
92 DHCP_DEFAULT_DELEGATED_PREFIX_SIZE
="64"
94 # Defaults for DHCPv6.
95 DHCPV6D_PREFERRED_LIFETIME
=""
96 DHCPV6D_VALID_LIFETIME
="43200" # 12h
98 # Defaults for DHCPv4.
99 DHCPV4D_AUTHORITATIVE
="true"
100 DHCPV4D_DEFAULT_LEASE_TIME
="43200" # 12h
101 DHCPV4D_MAX_LEASE_TIME
="86400" # 24h
102 DHCPV4D_MIN_LEASE_TIME
=""
104 function dhcpd_service
() {
107 print
"dhcpd6.service"
110 print
"dhcpd.service"
113 print
"dhcpd6.service dhcp.service"
120 function dhcpd_start
() {
121 local services
=$
(dhcpd_service $@
)
124 for service
in ${services}; do
125 service_start
${service}
129 function dhcpd_stop
() {
130 local services
=$
(dhcpd_service $@
)
133 for service
in ${services}; do
134 service_stop
${service}
138 function dhcpd_restart
() {
139 # DHCP does not support a reload, so
141 local services
=$
(dhcpd_service $@
)
144 for service
in ${services}; do
145 service_restart
${service}
149 function dhcpd_reload
() {
153 function dhcpd_edit
() {
158 local settings
=$
(dhcpd_settings
${proto})
159 assert isset settings
162 dhcpd_global_settings_read
${proto}
166 _dhcpd_edit_ipv6 $@ ||
return $?
169 _dhcpd_edit_ipv4 $@ ||
return $?
173 dhcpd_global_settings_write
${proto}
176 function _dhcpd_edit_ipv4
() {
179 while [ $# -gt 0 ]; do
182 val
=$
(cli_get_val
${1})
187 AUTHORITATIVE
="false"
190 --default-lease-time=*)
191 DEFAULT_LEASE_TIME
=$
(cli_get_val
${1})
193 if ! isinteger DEFAULT_LEASE_TIME
; then
194 error
"Invalid value for --default-lease-time."
199 MAX_LEASE_TIME
=$
(cli_get_val
${1})
201 if ! isinteger MAX_LEASE_TIME
; then
202 error
"Invalid value for --max-lease-time."
207 MIN_LEASE_TIME
=$
(cli_get_val
${1})
209 if isset MIN_LEASE_TIME
; then
210 if ! isinteger MIN_LEASE_TIME
; then
211 error
"Invalid value for --min-lease-time."
217 error
"Unrecognized argument: ${1}"
224 if [ ${MAX_LEASE_TIME} -le ${DEFAULT_LEASE_TIME} ]; then
225 error
"The max. lease time must be higher than the default lease time."
230 function _dhcpd_edit_ipv6
() {
231 while [ $# -gt 0 ]; do
233 --preferred-lifetime=*)
234 PREFERRED_LIFETIME
=$
(cli_get_val
${1})
236 if ! isinteger PREFERRED_LIFETIME
; then
237 error
"Invalid value for --preferred-lifetime."
242 VALID_LIFETIME
=$
(cli_get_val
${1})
244 if ! isinteger VALID_LIFETIME
; then
245 error
"Invalid value for --valid-lifetime."
250 error
"Unrecognized argument: ${1}"
258 function dhcpd_settings_file
() {
264 print
"${DHCPV6D_SETTINGS_FILE}"
267 print
"${DHCPV4D_SETTINGS_FILE}"
274 function dhcpd_settings
() {
280 print
"${DHCPV6D_SETTINGS}"
283 print
"${DHCPV4D_SETTINGS}"
290 function dhcpd_options_file
() {
296 print
"${DHCPV6D_OPTIONS_FILE}"
299 print
"${DHCPV4D_OPTIONS_FILE}"
306 function dhcpd_options_list
() {
312 print
"DHCPV6D_OPTIONS"
315 print
"DHCPV4D_OPTIONS"
322 function dhcpd_options
() {
328 print
"${DHCPV6D_OPTIONS}"
331 print
"${DHCPV4D_OPTIONS}"
338 function dhcpd_global_settings_list
() {
342 dhcpd_settings
"${proto}"
345 function dhcpd_global_settings_defaults
() {
349 local settings
=$
(dhcpd_settings
${proto})
350 assert isset settings
352 local prefix
="DHCPV${proto/ipv/}D_"
354 local setting setting_default
355 for setting
in ${settings}; do
356 setting_default
="${prefix}${setting}"
357 printf -v ${setting} "%s" "${!setting_default}"
361 function dhcpd_global_settings_read
() {
365 local file=$
(dhcpd_settings_file
${proto})
368 local settings
=$
(dhcpd_settings
${proto})
369 assert isset settings
371 dhcpd_global_settings_defaults
${proto}
372 settings_read
${file} ${settings}
375 function dhcpd_global_settings_write
() {
379 local file=$
(dhcpd_settings_file
${proto})
382 local settings
=$
(dhcpd_settings
${proto})
383 assert isset settings
385 settings_write
${file} ${settings}
388 function dhcpd_global_options_read
() {
392 local options_file
=$
(dhcpd_options_file
${proto})
393 local options_list
=$
(dhcpd_options_list
${proto})
395 settings_read_array
${options_file} options
${!options_list}
397 # Check if domain-name is set.
398 if [ -z "${options["domain-name"]}" ]; then
399 options
["domain-name"]=$
(config_domainname
)
403 function dhcpd_subnet_path
() {
408 assert isset subnet_id
413 path
=${DHCPV6D_CONFIG_DIR}
416 path
=${DHCPV4D_CONFIG_DIR}
421 print
"${path}/${DHCPD_SUBNET_PREFIX}${subnet_id}"
425 function dhcpd_subnet_exists
() {
430 assert isset subnet_id
432 local path
=$
(dhcpd_subnet_path
${proto} ${subnet_id})
435 [ -d "${path}" ] && return ${EXIT_TRUE} || return ${EXIT_FALSE}
438 function dhcpd_subnet_match() {
445 local settings=$(dhcpd_subnet_settings ${proto})
446 assert isset settings
448 local subnet_id ${settings}
449 for subnet_id in $(dhcpd_subnet_list ${proto}); do
450 dhcpd_subnet_read ${proto} ${subnet_id}
452 ${proto}_addr_eq "${ADDRESS}/${PREFIX}" "${subnet}" \
453 && return ${EXIT_TRUE}
459 function dhcpd_new_subnet_id
() {
465 if ! dhcpd_subnet_exists
${proto} ${id}; then
476 function dhcpd_subnet_new
() {
481 # Allocate a new subnet id.
482 local subnet_id
=$
(dhcpd_new_subnet_id
${proto})
483 assert isinteger subnet_id
485 # Create directory structure.
486 local path
=$
(dhcpd_subnet_path
${proto} ${subnet_id})
490 touch ${path}/settings
492 dhcpd_subnet_edit
${proto} ${subnet_id} $@
495 # Remove the new subnet, when the edit method returned
497 if [ ${ret} -ne ${EXIT_OK} ]; then
498 dhcpd_subnet_remove
${proto} ${subnet_id}
502 function dhcpd_subnet_edit
() {
514 settings
=${DHCPV6D_SUBNET_SETTINGS}
517 settings
=${DHCPV4D_SUBNET_SETTINGS}
520 assert isset settings
523 # Read current settings.
524 dhcpd_subnet_read
${proto} ${id} ||
:
526 while [ $# -gt 0 ]; do
527 case "${proto},${1}" in
530 ADDRESS
=$
(cli_get_val
${1})
532 local prefix
=$
(ip_get_prefix
${ADDRESS})
533 if isset prefix
; then
535 ADDRESS
=$
(ip_split_prefix
${ADDRESS})
539 PREFIX
=$
(cli_get_val
${1})
544 ipv6
,--delegated-prefix=*)
545 local subnet
="$(cli_get_val "${1}")"
546 if [[ -n "${subnet}" ]]; then
547 local delegated_prefix_first
="${subnet%-*}"
548 local delegated_prefix_last
="${subnet#*-}"
550 # Check for correct syntax
551 if ! isset delegated_prefix_first ||
! isset delegated_prefix_last
; then
552 error
"--delegated-prefix= must be formatted like 2001:db8:aaaa::-2001:db8:bbbb::"
556 # Check if the addresses are correct
558 for addr
in ${delegated_prefix_first} ${delegated_prefix_last}; do
559 if ! ipv6_is_valid
"${addr}"; then
560 error
"Invalid IP address: ${addr}"
565 # Make sure this is a range
566 if ! ipv6_addr_gt
"${delegated_prefix_last}" "${delegated_prefix_first}"; then
567 error
"--delegated-prefix: The second address must be larger than the first one"
571 PREFIX_DELEGATION
="on"
572 DELEGATED_PREFIX_FIRST
="${delegated_prefix_first}"
573 DELEGATED_PREFIX_LAST
="${delegated_prefix_last}"
575 # Prefix delegation has been disabled
577 PREFIX_DELEGATION
="off"
581 ipv6
,--delegated-prefix-size=*)
582 local prefix_size
="$(cli_get_val "${1}")"
584 if ipv6_prefix_size_is_valid_for_delegation
"${prefix_size}"; then
585 DELEGATED_PREFIX_SIZE
="${prefix_size}"
587 error
"Invalid prefix size for prefix delegation: ${prefix_size}"
595 ROUTERS
=$
(cli_get_val
${1})
598 error
"Unknown argument: ${1}"
607 if ! ipv6_is_valid
${ADDRESS}; then
608 error
"'${ADDRESS}' is not a valid IPv6 address."
612 if ! ipv6_prefix_is_valid
${PREFIX}; then
613 error
"'${PREFIX}' is not a valid IPv6 prefix."
618 if ! ipv4_is_valid
${ADDRESS}; then
619 error
"'${ADDRESS}' is not a valid IPv4 address."
623 if ! ipv4_prefix_is_valid
${PREFIX}; then
624 error
"'${PREFIX}' is not a valid IPv4 prefix."
630 # XXX Check for subnet collisions!
632 local file="$(dhcpd_subnet_path ${proto} ${id})/settings"
633 settings_write
${file} ${settings}
636 function dhcpd_subnet_remove
() {
643 local path
=$
(dhcpd_subnet_path
${proto} ${id})
646 # Remove everything of this subnet.
650 function dhcpd_subnet_list
() {
654 local path
=$
(dhcpd_subnet_path
${proto} 0)
655 path
=$
(dirname ${path})
657 # Return an error of the directory does not exist.
658 [ -d "${path}" ] ||
return ${EXIT_ERROR}
661 for p
in ${path}/${DHCPD_SUBNET_PREFIX}*; do
662 [ -d "${p}" ] ||
continue
665 print
"${p:${#DHCPD_SUBNET_PREFIX}}"
669 function dhcpd_subnet_read
() {
676 local file="$(dhcpd_subnet_path ${proto} ${id})/settings"
677 settings_read
${file}
680 function dhcpd_subnet_range_path
() {
685 assert isinteger subnet_id
688 assert isinteger range_id
690 print
"$(dhcpd_subnet_path ${proto} ${subnet_id})/${DHCPD_SUBNET_RANGE_PREFIX}${range_id}"
694 function dhcpd_subnet_range_settings
() {
699 print
"${DHCPV6D_SUBNET_RANGE_SETTINGS}"
702 print
"${DHCPV4D_SUBNET_RANGE_SETTINGS}"
709 function dhcpd_subnet_new_range_id
() {
714 assert isset subnet_id
718 path
=$
(dhcpd_subnet_range_path
${proto} ${subnet_id} ${id})
719 if [ ! -f "${path}" ]; then
730 function dhcpd_subnet_range_new
() {
736 assert isset subnet_id
739 # Allocate a new range id.
740 local range_id
=$
(dhcpd_subnet_new_range_id
${proto} ${subnet_id})
741 assert isinteger range_id
743 local path
=$
(dhcpd_subnet_range_path
${proto} ${subnet_id} ${range_id})
746 # Create file (as a placeholder).
749 dhcpd_subnet_range_edit
${proto} ${subnet_id} ${range_id} $@
752 if [ ${ret} -ne ${EXIT_OK} ]; then
753 dhcpd_subnet_range_remove
${proto} ${subnet_id} ${range_id}
760 function dhcpd_subnet_range_edit
() {
766 assert isset subnet_id
770 assert isset range_id
773 local ip_encode ip_is_valid
777 ip_encode
="ipv6_encode"
778 ip_is_valid
="ipv6_is_valid"
779 settings
=${DHCPV6D_SUBNET_RANGE_SETTINGS}
782 ip_encode
="ipv4_encode"
783 ip_is_valid
="ipv4_is_valid"
784 settings
=${DHCPV4D_SUBNET_RANGE_SETTINGS}
787 assert isset settings
790 while [ $# -gt 0 ]; do
793 START
=$
(cli_get_val
${1})
796 END
=$
(cli_get_val
${1})
799 error
"Unknown argument: ${1}"
806 if ! isset START
; then
807 error
"You need to set the start of the IP range with --start=..."
812 error
"You need to set the end of the IP range with --end=..."
817 for var
in START END
; do
818 if ! ${ip_is_valid} ${!var}; then
819 error
"'${!var}' is not a valid IP address."
824 # XXX currently, this check can only be performed for IPv4
825 if [ "${proto}" = "ipv4" ]; then
826 # Check if the end address is greater than the start address.
827 local start_encoded
=$
(${ip_encode} ${START})
828 local end_encoded
=$
(${ip_encode} ${END})
830 if [ ${start_encoded} -ge ${end_encoded} ]; then
831 error
"The start address of the range must be greater than the end address."
836 # Write the configuration to file.
837 local file=$
(dhcpd_subnet_range_path
${proto} ${subnet_id} ${range_id})
840 settings_write
${file} ${settings}
843 function dhcpd_subnet_range_remove
() {
844 local path
=$
(dhcpd_subnet_range_path $@
)
850 function dhcpd_subnet_range_list
() {
855 assert isset subnet_id
857 local path
=$
(dhcpd_subnet_range_path
${proto} ${subnet_id} 0)
858 path
=$
(dirname ${path})
861 for p
in ${path}/${DHCPD_SUBNET_RANGE_PREFIX}*; do
862 [ -r "${p}" ] ||
continue
865 print
"${p:${#DHCPD_SUBNET_RANGE_PREFIX}}"
871 function dhcpd_subnet_range_read
() {
876 assert isset subnet_id
879 assert isset range_id
881 local file=$
(dhcpd_subnet_range_path
${proto} ${subnet_id} ${range_id})
882 settings_read
${file}
885 function dhcpd_subnet_settings
() {
890 print
"${DHCPV6D_SUBNET_SETTINGS}"
893 print
"${DHCPV4D_SUBNET_SETTINGS}"
900 function dhcpd_subnet_options_file
() {
901 local path
=$
(dhcpd_subnet_path $@
)
904 print
"${path}/options"
907 function dhcpd_subnet_options_list
() {
913 print
"${DHCPV6D_SUBNET_OPTIONS}"
916 print
"${DHCPV4D_SUBNET_OPTIONS}"
923 function dhcpd_subnet_options_read
() {
928 assert isset subnet_id
930 local options_file
=$
(dhcpd_subnet_options_file
${proto} ${subnet_id})
931 local options_list
=$
(dhcpd_subnet_options_list
${proto})
933 _dhcpd_read_options
${options_file} ${options_list}
936 # Helper functions to create a DHCP configuration file.
937 function _dhcpd_write_options
() {
944 local options_list
=${3}
945 assert isset options_list
949 print
"${ident}# Options" >> ${file}
951 # Dump options array.
953 for key
in ${!options_list}; do
954 val
=${options[${key}]}
956 # Skip the rest if val is empty
957 isset val ||
continue
959 # Enable raw formatting (i.e. quote the value?)
962 # Update the formatting of some options
965 val
="$(list_join val ", ")"
970 # Prepend dhcp6 on IPv6 options.
971 if [ "${proto}" = "ipv6" ]; then
975 if isinteger val
; then
977 elif enabled raw || isipaddress val
; then
980 fmt="option %s \"%s\";"
983 print
"${ident}${fmt}" "${key}" "${val}"
990 function _dhcpd_read_options
() {
994 local options_list
=${2}
995 assert isset options_list
997 settings_read_array
${file} options
${!options_list}
1000 function _dhcpd_write_subnet
() {
1004 local subnet_id
=${2}
1005 assert isset subnet_id
1010 # Check which settings we do expect.
1014 settings
=${DHCPV6D_SUBNET_SETTINGS}
1017 settings
=${DHCPV4D_SUBNET_SETTINGS}
1020 assert isset settings
1023 # Read configuration settings.
1024 dhcpd_subnet_read
${proto} ${subnet_id}
1026 print
"# Subnet declaration for subnet id ${subnet_id}." >> ${file}
1029 print
"subnet6 ${ADDRESS}/${PREFIX} {" >> ${file}
1032 local netmask=$(ipv4_get_netmask ${ADDRESS}/${PREFIX})
1033 print "subnet
${ADDRESS} netmask ${netmask} {" >> ${file}
1038 _dhcpd_write_subnet_options
${proto} ${subnet_id} ${file}
1040 # Prefix Delegation for IPv6
1041 if [[ "${proto}" = "ipv6" ]]; then
1042 _dhcpd_write_subnet_pd
"${subnet_id}" "${file}"
1047 for range_id
in $
(dhcpd_subnet_range_list
${proto} ${subnet_id} ${range_id}); do
1048 _dhcpd_write_subnet_range
${proto} ${subnet_id} ${range_id} ${file}
1051 # End this subnet block.
1052 print
"}\n" >> ${file}
1057 function _dhcpd_write_subnet_options
() {
1061 local subnet_id
=${2}
1062 assert isset subnet_id
1068 local options_file
="$(dhcpd_subnet_path ${proto} ${subnet_id})/options"
1072 settings
=${DHCPV6D_SUBNET_SETTINGS}
1073 options_list
="DHCPV6D_OPTIONS"
1076 settings
=${DHCPV4D_SUBNET_SETTINGS}
1077 options_list
="DHCPV4D_OPTIONS"
1080 assert isset settings
1081 assert isset options_list
1084 dhcpd_subnet_read
${proto} ${subnet_id}
1087 _dhcpd_read_options
${options_file} ${options_list}
1089 # Fill in router, if not already set.
1090 if [ -z "${options["routers"]}" ]; then
1091 options
["routers"]=$
(_dhcpd_search_routers
${proto} "${ADDRESS}/${PREFIX}")
1094 _dhcpd_write_options ${proto} ${file} ${options_list} "\t"
1097 _dhcpd_write_subnet_pd() {
1098 # Nothing to do if prefix delegation is not enabled
1099 enabled PREFIX_DELEGATION || return ${EXIT_OK}
1101 local subnet_id="${1}"
1102 assert isset subnet_id
1107 local prefix_size="${DELEGATED_PREFIX_SIZE}"
1108 isset prefix_size || prefix_size="${DHCP_DEFAULT_DELEGATED_PREFIX_SIZE}"
1110 assert ipv6_is_valid "${DELEGATED_PREFIX_FIRST}"
1111 assert ipv6_is_valid "${DELEGATED_PREFIX_LAST}"
1112 assert ipv6_prefix_size_is_valid_for_delegation "${prefix_size}"
1115 print " # Prefix Delegation"
1116 print
" prefix6 ${DELEGATED_PREFIX_FIRST} ${DELEGATED_PREFIX_LAST} /${prefix_size};"
1121 function _dhcpd_search_routers
() {
1125 # Do nothing for IPv6 (yet?).
1126 [ "${proto}" = "ipv6" ] && return ${EXIT_OK}
1134 for zone
in $
(zones_get_all
); do
1135 addr
=$
(routing_db_get
${zone} ${proto} local-ip-address
)
1136 isset addr ||
continue
1138 if ipv4_in_subnet
${addr} ${subnet}; then
1139 list_append routers $
(ip_split_prefix
${addr})
1143 list_join routers
", "
1146 function _dhcpd_write_subnet_range
() {
1150 local subnet_id
=${2}
1151 assert isset subnet_id
1154 assert isset range_id
1159 local settings
=$
(dhcpd_subnet_range_settings
${proto})
1160 assert isset settings
1162 # Read the configuration settings.
1164 dhcpd_subnet_range_read
${proto} ${subnet_id} ${range_id}
1166 # Print the range line.
1167 print
" # Range id ${range_id}." >> ${file}
1171 print
" range6 ${START} ${END};" >> ${file}
1174 print " range
${START} ${END};" >> ${file}
1182 function dhcpd_write_config
() {
1186 local file options_list
1189 file=${DHCPV6D_CONFIG_FILE}
1190 options_list
="DHCPV6D_OPTIONS"
1193 file=${DHCPV4D_CONFIG_FILE}
1194 options_list
="DHCPV4D_OPTIONS"
1198 assert isset options_list
1201 config_header
"DHCP ${proto} daemon configuration file" > ${file}
1203 # Read global DHCP configuration
1204 dhcpd_global_settings_read
"${proto}"
1207 if enabled AUTHORITATIVE
; then
1209 print
"# This is an authoritative DHCP server for this network."
1210 print
"authoritative;\n"
1214 print
"# This is NOT an authoritative DHCP server for this network."
1215 print
"not authoritative;\n"
1222 if isinteger VALID_LIFETIME
; then
1223 print
"default-lease-time %d;" "${VALID_LIFETIME}" >> ${file}
1226 if isinteger PREFERRED_LIFETIME
; then
1227 print
"preferred-lifetime %d;" "${PREFERRED_LIFETIME}" >> ${file}
1232 if isinteger DEFAULT_LEASE_TIME
; then
1233 print
"default-lease-time %d;" "${DEFAULT_LEASE_TIME}" >> ${file}
1236 if isinteger MAX_LEASE_TIME
; then
1237 print
"max-lease-time %d;" "${MAX_LEASE_TIME}" >> ${file}
1240 if isinteger MIN_LEASE_TIME
; then
1241 print
"min-lease-time %d;" "${MIN_LEASE_TIME}" >> ${file}
1246 # Write the options to file.
1248 dhcpd_global_options_read
${proto}
1249 _dhcpd_write_options
${proto} ${file} ${options_list}
1251 # Add all subnet declarations.
1253 for subnet_id
in $
(dhcpd_subnet_list
${proto}); do
1254 _dhcpd_write_subnet
${proto} ${subnet_id} ${file}