]> git.ipfire.org Git - network.git/commitdiff
Add basic support as a DHCP client.
authorMichael Tremer <michael.tremer@ipfire.org>
Thu, 17 May 2012 15:23:58 +0000 (15:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Thu, 17 May 2012 15:23:58 +0000 (15:23 +0000)
Makefile
dhclient-helper [new file with mode: 0644]
dhclient-script [new file with mode: 0644]
functions
functions.cli
functions.constants
functions.dhclient [new file with mode: 0644]
functions.distro [new file with mode: 0644]
functions.ipv4
hooks/zones/bridge.configs/ipv4-dhcp [new file with mode: 0755]

index 7d51cc620ee39c7bd54460259db8d32664c2256a..3be147e1ddbf39f8828a64befec77299410c8e3a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -26,6 +26,10 @@ install:
        # Install bridge-stp. 
        install -m 755 bridge-stp $(DESTDIR)/sbin/
 
+       # Install dhclient script and helper.
+       install -m 755 dhclient-helper ${DESTDIR}/usr/lib/network/
+       install -m 755 dhclient-script ${DESTDIR}/sbin/
+
        install -m 755 -v ppp/ip-updown $(DESTDIR)/etc/ppp
        ln -svf ip-updown $(DESTDIR)/etc/ppp/ip-pre-up
        ln -svf ip-updown $(DESTDIR)/etc/ppp/ip-up
diff --git a/dhclient-helper b/dhclient-helper
new file mode 100644 (file)
index 0000000..8401146
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+. /usr/lib/network/functions
+
+action="${1}"
+assert isset action
+
+interface="${2}"
+assert isset interface
+
+proto=${3}
+assert isset proto
+
+# Check if the given interface is a zone.
+assert zone_exists ${interface}
+
+case "${action}" in
+       start)
+               # Create dhclient configuration file.
+               case "${proto}" in
+                       ipv4)
+                               config_file="${RUN_DIR}/dhclient/${interface}/dhclient4.conf"
+                               ;;
+                       ipv6)
+                               config_file="${RUN_DIR}/dhclient/${interface}/dhclient6.conf"
+                               ;;
+               esac
+               assert isset config_file
+
+               dhclient_write_config ${interface} ${config_file} \
+                       --hostname="${HOSTNAME%%.*}"
+
+               exit ${EXIT_OK}
+               ;;
+
+       stop)
+               case "${proto}" in
+                       ipv4)
+                               reason="STOP"
+                               ;;
+                       ipv6)
+                               reason="STOP6"
+                               ;;
+               esac
+               assert isset reason
+
+               export interface
+               export reason
+
+               exec /usr/sbin/dhclient-script
+
+               log ERROR $"execing dhclient-script has failed."
+               exit ${EXIT_ERROR}
+               ;;
+
+       *)
+               log ERROR "Unknown action passed: ${action}"
+               exit ${EXIT_ERROR}
+               ;;
+esac
diff --git a/dhclient-script b/dhclient-script
new file mode 100644 (file)
index 0000000..e56c096
--- /dev/null
@@ -0,0 +1,122 @@
+#!/bin/bash
+
+. /usr/lib/network/functions
+
+# Configure logging
+LOG_FACILITY="dhclient-script"
+
+assert isset interface
+assert isset reason
+
+assert device_exists ${interface}
+
+# XXX LOAD ZONE CONFIGURATION
+
+basename="$(basename $0)"
+log DEBUG "${basename} called for interface=${interface} reason=${reason}"
+
+# Main pitchfork.
+case "${reason}" in
+       MEDIUM)
+               # Linux does not handle MEDIUM.
+               exit 0
+               ;;
+
+       PREINIT)
+               # Bring up the device if it hasn't been done before.
+               if ! device_is_up ${interface}; then
+                       log DEBUG "The interface '${interface}' does not appear to be up."
+
+                       zone_up ${interface}
+               fi
+
+               # If the use configured a delay, we will honour that.
+               if [ -n "${DELAY}"  ]; then
+                       assert isinteger DELAY
+                       sleep ${DELAY}
+
+               # If he didn't, we will try to detect is STP has brought the
+               # bridge up.
+               elif device_is_bridge ${interface}; then
+                       counter=60
+
+                       while [ ${counter} -gt 0 ]; do
+                               # We may end this, when the bridge is in forwarding mode.
+                               if bridge_is_forwarding ${interface}; then
+                                       log DEBUG "Bridge '${interface}' is in forwarding mode."
+                                       break
+                               fi
+
+                               counter=$(( ${counter} - 1 ))
+                               sleep 1
+                       done
+
+                       # Tell the daemon, that we are not ready to go on.
+                       if [ ${counter} -eq 0 ]; then
+                               log ERROR "Bridge '${interface}' is not in forwarding mode."
+                               log ERROR "Could not go on with getting a DHCP lease. Exiting."
+
+                               exit 1
+                       fi
+               fi
+
+               exit 0
+               ;;
+
+
+       BOUND|RENEW|REBIND|REBOOT)
+               # Check if the IP address has changed. If so, delete all routes and stuff.
+               if [ -n "${old_ip_address}" -a "${old_ip_address}" != "${new_ip_address}" ]; then
+                       ipv4_flush_device ${interface}
+               fi
+
+               case "${reason}" in
+                       BOUND|REBOOT)
+                               if [ ! "${old_ip_address}" = "${new_ip_address}" ] || \
+                                       [ ! "${old_subnet_mask}" = "${new_subnet_mask}" ] || \
+                                       [ ! "${old_network_number}" = "${new_network_number}" ] || \
+                                       [ ! "${old_broadcast_address}" = "${new_broadcast_address}" ] || \
+                                       [ ! "${old_routers}" = "${new_routers}" ] || \
+                                       [ ! "${old_interface_mtu}" = "${new_interface_mtu}" ]; then
+
+
+                                       # Calc a prefix out of address and subnet mask.
+                                       new_prefix="$(ipv4_get_prefix ${new_ip_address} ${new_subnet_mask})"
+
+                                       # Set the new ip address.
+                                       ip_address_add ${interface} ${new_ip_address}/${new_prefix}
+                                       device_set_up ${interface}
+
+
+                                       # A MTU of 576 is used for X.25 and dialup connections. Some broken DHCP
+                                       # servers send out an MTU of 576 bytes, which will be ignored.
+                                       if [ -n "${new_interface_mtu}" ] && [ ${new_interface_mtu} -gt 576 ]; then
+                                               device_set_mtu ${interface} ${new_interface_mtu}
+                                       fi
+
+                                       # Save configuration
+                                       routing_db_set ${interface} ipv4 type "ipv4-dhcp"
+                                       routing_db_set ${interface} ipv4 local-ip-address "${new_ip_address}/${new_prefix}"
+                                       routing_db_set ${interface} ipv4 remote-ip-address "${new_router}"
+                                       routing_db_set ${interface} ipv4 active 1
+
+                                       # Update the routing tables.
+                                       routing_update ${interface} ipv4
+                               fi
+                               ;;
+               esac
+
+               exit 0
+               ;;
+
+       EXPIRE|FAIL|RELEASE|STOP)
+               # Remove the currently configured addresses from the device.
+               if [ -n "${old_ip_address}" ]; then
+                       ipv4_flush_device ${interface}
+               fi
+
+               exit 0
+               ;;
+esac
+
+exit 1
index e3d95fb42305a53241a0d064f0993f0ab85997ad..6ced711ef5dca64fbbdb034b3bb39abe4c7bf0a3 100644 (file)
--- a/functions
+++ b/functions
@@ -17,9 +17,9 @@ function init_run() {
 }
 
 # Include version information.
-. /lib/network/version
+. /usr/lib/network/version
 
-for file in /lib/network/functions.*; do
+for file in /usr/lib/network/functions.*; do
        . ${file}
 done
 
index 411188da899269e18917c9cbf42fe7f4434a7e74..e25996377e9733f42e72215c50986e28feb97ffc 100644 (file)
@@ -541,5 +541,5 @@ function cli_get_key() {
 }
 
 function cli_get_val() {
-       echo "${1##*=}"
+       echo "${@##*=}"
 }
index 90c1409b688056f3933a0ad919ab8d2b55bdea88..b73b92671cb00e53394dc5844e8098259c1d7bbe 100644 (file)
@@ -19,6 +19,9 @@
 #                                                                             #
 ###############################################################################
 
+# Set gettext text domain.
+TEXTDOMAIN="network"
+
 # Enable colors by default
 COLOURS="auto"
 
diff --git a/functions.dhclient b/functions.dhclient
new file mode 100644 (file)
index 0000000..e20ad14
--- /dev/null
@@ -0,0 +1,126 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2012  IPFire Network Development Team                         #
+#                                                                             #
+# 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/>.       #
+#                                                                             #
+###############################################################################
+
+dhclient_start() {
+       local interface=${1}
+       local proto=${2}
+
+       assert isset interface
+       assert device_exists ${interface}
+
+       local service=$(dhclient_proto2service ${proto})
+       assert isset service
+
+       service_start "${service}@${interface}"
+}
+
+dhclient_stop() {
+       local interface=${1}
+       local proto=${2}
+
+       local service=$(dhclient_proto2service ${proto})
+       assert isset service
+
+       service_stop "${service}@${interface}"
+}
+
+dhclient_proto2service() {
+       local proto=${1}
+       assert isset proto
+
+       local service
+
+       case "${proto}" in
+               ipv4)
+                       service="dhclient4"
+                       ;;
+               ipv6)
+                       service="dhclient6"
+                       ;;
+               *)
+                       return ${EXIT_ERROR}
+                       ;;
+       esac
+
+       assert isset service
+
+       echo "${service}"
+       return ${EXIT_OK}
+}
+
+dhclient_write_config() {
+       local interface=${1}
+       local file=${2}
+       shift 2
+
+       assert isset interface
+       assert isset file
+
+       local hostname=${HOSTNAME%%.*}
+       local vendor=$(distro_get_pretty_name)
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --hostname=*)
+                               hostname=$(cli_get_val ${1})
+                               ;;
+                       --vendor=*)
+                               vendor=$(cli_get_val ${1})
+                               ;;
+                       *)
+                               log WARNING $"Unknown configuration option passed: ${1}."
+                               ;;
+               esac
+               shift
+       done
+
+       # Clear configuration file (if any).
+       mkdir -p $(dirname ${file}) 2>/dev/null
+       : > ${file}
+
+       # Print the header.
+       (       echo "#"
+               echo "# This is a dhclient daemon configuration file for ${interface}."
+               echo "# THIS FILE IS AUTOMATICALLY GENERATED AND WILL OVERWRITE"
+               echo "# ANY CUSTOM CHANGES!"
+               echo "#"
+               echo "# $(date -u)"
+               echo "#"
+               echo
+       ) >>${file}
+
+       # Global options.
+       echo "send vendor-class-identifier \"${vendor}\";" >>${file}
+       echo
+
+       # Interface options.
+       (
+               echo "interface \"${interface}\" {"
+
+               if isset hostname; then
+                       echo "  send host-name \"${hostname}\";"
+               fi
+
+               echo "}"
+       ) >>${file}
+
+       return ${EXIT_OK}
+}
diff --git a/functions.distro b/functions.distro
new file mode 100644 (file)
index 0000000..4dc831b
--- /dev/null
@@ -0,0 +1,57 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2012  IPFire Network Development Team                         #
+#                                                                             #
+# 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/>.       #
+#                                                                             #
+###############################################################################
+
+__os_release() {
+       local what=${1}
+
+       assert [ -e "/etc/os-release" ]
+
+       local line k v
+       while read line; do
+               k=$(cli_get_key ${line})
+               v=$(cli_get_val ${line})
+
+               if [ "${what}" = "${k}" ]; then
+                       echo "${v//\"/}"
+                       break
+               fi
+       done < /etc/os-release
+}
+
+distro_get_name() {
+       __os_release NAME
+}
+
+distro_get_version() {
+       __os_release VERSION
+}
+
+distro_get_id() {
+       __os_release ID
+}
+
+distro_get_version_id() {
+       __os_release VERSION_ID
+}
+
+distro_get_pretty_name() {
+       __os_release PRETTY_NAME
+}
index d074ca940ab35408876d6be8e446d445b5ec20a3..1220d491883729c30a8b67e095da09ad05153933 100644 (file)
@@ -73,3 +73,34 @@ function ipv4_get_netaddress() {
 
        return ${EXIT_OK}
 }
+
+function ipv4_get_prefix() {
+       local address=${1}
+       local broadcast=${2}
+
+       assert isset address
+       assert isset broadcast
+
+       local PREFIX
+       eval $(ipcalc --prefix ${address} ${broadcast})
+       assert isset PREFIX
+
+       echo "${PREFIX}"
+       return ${EXIT_OK}
+}
+
+function ipv4_flush_device() {
+       #
+       # Flushes all routes, addresses from the device
+       # and clears the ARP cache.
+       #
+
+       local device=${1}
+       assert isset device
+
+       ip -4 addr flush dev ${device} >/dev/null 2>&1
+       ip -4 route flush dev ${device} >/dev/null 2>&1
+       ip -4 neigh flush dev ${device} >/dev/null 2>&1
+
+       return 0
+}
diff --git a/hooks/zones/bridge.configs/ipv4-dhcp b/hooks/zones/bridge.configs/ipv4-dhcp
new file mode 100755 (executable)
index 0000000..fd5f1c6
--- /dev/null
@@ -0,0 +1,111 @@
+#!/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/>.       #
+#                                                                             #
+###############################################################################
+
+. /lib/network/header-config
+
+HOOK_SETTINGS="HOOK DELAY"
+
+# Default settings.
+DELAY=0
+
+function _check() {
+       assert isset DELAY
+       assert isinteger DELAY
+}
+
+function _create() {
+       local zone=${1}
+       shift
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --delay=*)
+                               DELAY=${1#--delay=}
+                               ;;
+               esac
+               shift
+       done
+
+       config_write $(zone_dir ${zone})/configs/${HOOK} ${HOOK_SETTINGS}
+
+       exit ${EXIT_OK}
+}
+
+function _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 IPv4 on this zone.
+       dhclient_start ${zone} ipv4
+
+       exit ${EXIT_OK}
+}
+
+function _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 IPv4 on this zone.
+       dhclient_stop ${zone} ipv4
+
+       exit ${EXIT_OK}
+}
+
+function _status() {
+       local zone=${1}
+       local config=${2}
+       shift 2
+
+       if ! device_exists ${zone}; then
+               error "Zone '${zone}' doesn't exist."
+               exit ${EXIT_ERROR}
+       fi
+       
+       config_read $(zone_dir ${zone})/configs/${config}
+
+       printf "        %10s - " "${HOOK}"
+       if zone_has_ip ${zone} ${ADDRESS}/${PREFIX}; then
+               echo -ne "${COLOUR_UP} UP ${COLOUR_NORMAL}"
+       else
+               echo -ne "${COLOUR_DOWN}DOWN${COLOUR_NORMAL}"
+       fi
+       echo " - ${ADDRESS}/${PREFIX}"
+
+       if [ -n "${GATEWAY}" ]; then
+               echo "          Gateway: ${GATEWAY}"
+       fi
+
+       exit ${EXIT_OK}
+}
+
+run $@