src/hooks/configs/ipv4-dhcp \
src/hooks/configs/ipv4-static \
src/hooks/configs/ipv6-auto \
+ src/hooks/configs/ipv6-dhcp \
src/hooks/configs/ipv6-static \
src/hooks/configs/pppoe-server
case "${action}" in
start)
+ leases_file=""
+
# Create dhclient configuration file.
case "${proto}" in
ipv4)
;;
ipv6)
config_file="${RUN_DIR}/dhclient/${interface}/dhclient6.conf"
+ leases_file="/var/lib/dhclient/dhclient6-${interface}.leases"
;;
esac
assert isset config_file
- dhclient_write_config ${interface} ${config_file} \
- --hostname="${HOSTNAME%%.*}"
+ # Update the dhclient configuration files
+ dhclient_write_config "${interface}" \
+ --config-file="${config_file}" \
+ --leases-file="${leases_file}" || exit $?
exit ${EXIT_OK}
;;
# #
###############################################################################
+NETWORK_DHCP_DUID_FILE="${NETWORK_CONFIG_DIR}/dhcp-duid"
+
dhclient_start() {
local interface=${1}
local proto=${2}
}
dhclient_write_config() {
- local interface=${1}
- local file=${2}
- shift 2
+ local interface="${1}"
+ shift
assert isset interface
- assert isset file
- local hostname=${HOSTNAME%%.*}
- local vendor=$(distro_get_pretty_name)
+ local hostname
+ local vendor
+
+ local config_file
+ local leases_file
while [ $# -gt 0 ]; do
case "${1}" in
+ --config-file=*)
+ config_file="$(cli_get_val "${1}")"
+ ;;
--hostname=*)
- hostname=$(cli_get_val ${1})
+ hostname="$(cli_get_val "${1}")"
+ ;;
+ --leases-file=*)
+ leases_file="$(cli_get_val "${1}")"
;;
--vendor=*)
- vendor=$(cli_get_val ${1})
+ vendor="$(cli_get_val "${1}")"
;;
*)
log WARNING $"Unknown configuration option passed: ${1}."
shift
done
+ assert isset config_file
+
+ # Set default values
+ if ! isset hostname; then
+ hostname="$(config_hostname)"
+ fi
+
+ if ! isset vendor; then
+ vendor="$(distro_get_pretty_name)"
+ fi
+
# Clear configuration file (if any).
- mkdir -p $(dirname ${file}) 2>/dev/null
+ mkdir -p $(dirname ${config_file}) 2>/dev/null
: > ${file}
# Print the header.
echo "# $(date -u)"
echo "#"
echo
- ) >>${file}
+ ) >> "${config_file}"
# Global options.
- echo "send vendor-class-identifier \"${vendor}\";" >>${file}
- echo
+ fwrite "${config_file}" "send vendor-class-identifier \"${vendor}\";"
+ fwrite "${config_file}" # empty line
# Interface options.
(
fi
echo "}"
- ) >>${file}
+ ) >> "${config_file}"
+
+ # Update leases file
+ if isset leases_file; then
+ __dhclient_update_leases_file "${leases_file}" || return $?
+ fi
+
+ return ${EXIT_OK}
+}
+
+dhclient_get_duid() {
+ # If the DUID already exists, we do not do anything at all.
+ if [ -s "${NETWORK_DHCP_DUID_FILE}" ]; then
+ print "$(<${NETWORK_DHCP_DUID_FILE})"
+ return ${EXIT_OK}
+ fi
+
+ # If no DUID exists, we will need to create a new one
+ local duid="$(dhclient_generate_duid)"
+ log DEBUG "Created new DHCP DUID: ${duid}"
+
+ # Save the new DUID to file and return it
+ print "${duid}" > "${NETWORK_DHCP_DUID_FILE}"
+
+ print "${duid}"
+ return ${EXIT_OK}
+}
+
+
+dhclient_generate_duid() {
+ # Find lowest MAC/link-local address
+ local address="$(ports_lowest_address)"
+
+ # Use a random MAC address if no physical address could
+ # be found.
+ if ! isset address; then
+ log WARNING "Could not determine the lowest MAC/link-local address"
+ address="$(mac_generate)"
+ fi
+ log DEBUG "Using '${address}' to generate the DHCP DUID"
+
+ print "00030001${address//\:/}"
return ${EXIT_OK}
}
+
+__dhclient_update_leases_file() {
+ local file="${1}"
+
+ local duid="$(dhclient_get_duid)"
+
+ if [ -e "${leases_file}" ]; then
+ local old_duid="$(__dhclient_get_duid_from_leases_file "${leases_file}")"
+
+ if [ "${duid}" = "${old_duid}" ]; then
+ log DEBUG "DUID in leases file matches. Nothing to do"
+ return ${EXIT_OK}
+ fi
+ fi
+
+ # If the leases file does not exist, yet, or the
+ # DUID in there is different, we will create/overwrite
+ # the leases file with the correct DUID.
+
+ (
+ printf "default-duid \""
+
+ local i=0
+ while [ ${i} -lt ${#duid} ]; do
+ printf "\\\\\\\\"
+ printf "x${duid:${i}:2}"
+ i=$(( ${i} + 2 ))
+ done
+
+ print "\";"
+ ) > "${leases_file}"
+
+ return ${EXIT_OK}
+}
+
+__dhclient_get_duid_from_leases_file() {
+ local file="${1}"
+
+ # Do nothing if the leases file cannot be read
+ [ -r "${file}" ] || return ${EXIT_OK}
+
+ local line
+ while read line; do
+ if [[ ${line} =~ ^default-duid ]]; then
+ line="${line/default-duid/}"
+ line="${line//\\\\x/}"
+ line="${line//;/}"
+
+ line="$(strip "${line}")"
+ unquote "${line}"
+ return ${EXIT_OK}
+ fi
+ done < "${file}"
+
+ return ${EXIT_ERROR}
+}
print "${reversed}"
return ${EXIT_OK}
}
+
+function list_head() {
+ local arg
+ for arg in $@; do
+ print "${arg}"
+ return ${EXIT_OK}
+ done
+
+ return ${EXIT_ERROR}
+}
local port_phy="$(port_get_phy "${port}")"
[ "${port_phy}" = "${phy}" ]
}
+
+function ports_lowest_address() {
+ local address
+ local addresses
+
+ local port
+ for port in $(port_list); do
+ # Skip all ports that do not exist
+ # any more or are not plugged in
+ device_exists "${port}" || continue
+
+ # Skip all ports that are not proper ethernet devices
+ device_is_wireless "${port}" && continue
+ device_is_ethernet "${port}" || continue
+
+ list_append addresses "$(device_get_address "${port}")"
+ done
+
+ # Sort the list
+ addresses="$(list_sort ${addresses})"
+
+ # Get the first element which is the lowest MAC address
+ list_head ${addresses}
+}
--- /dev/null
+#!/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 <http://www.gnu.org/licenses/>. #
+# #
+###############################################################################
+
+. /usr/lib/network/header-config
+
+HOOK_CONFIG_SETTINGS="HOOK"
+
+function hook_create() {
+ local zone="${1}"
+ shift
+
+ zone_config_settings_write "${zone}" "${HOOK}"
+
+ exit ${EXIT_OK}
+}
+
+function hook_up() {
+ local zone="${1}"
+ local config="${2}"
+ shift 2
+
+ if ! device_exists "${zone}"; then
+ error "Zone '${zone}' doesn't exist."
+ exit ${EXIT_ERROR}
+ fi
+
+ # Start dhclient for IPv6 on this zone.
+ dhclient_start "${zone}" "ipv6"
+
+ exit ${EXIT_OK}
+}
+
+function hook_down() {
+ local zone="${1}"
+ local config="${2}"
+ shift 2
+
+ if ! device_exists "${zone}"; then
+ error "Zone '${zone}' doesn't exist."
+ exit ${EXIT_ERROR}
+ fi
+
+ # Stop dhclient for IPv6 on this zone.
+ dhclient_stop "${zone}" "ipv6"
+
+ exit ${EXIT_OK}
+}
+
+function hook_status() {
+ local zone="${1}"
+ local config="${2}"
+ shift 2
+
+ if ! device_exists "${zone}"; then
+ error "Zone '${zone}' doesn't exist."
+ exit ${EXIT_ERROR}
+ fi
+
+ zone_config_settings_read "${zone}" "${config}"
+
+ local status
+ if dhclient_status "${zone}" "ipv6"; then
+ status="${MSG_HOOK_UP}"
+ else
+ status="${MSG_HOOK_DOWN}"
+ fi
+ cli_statusline 3 "${HOOK}" "${status}"
+
+ cli_print_fmt1 3 "IPv6 address" "$(routing_db_get "${zone}" "ipv6" "local-ip-address")"
+ local gateway=$(routing_db_get ${zone} ipv6 remote-ip-address)
+ if isset gateway; then
+ cli_print_fmt1 3 "Gateway" "${gateway}"
+ fi
+ cli_space
+
+ exit ${EXIT_OK}
+}