]> git.ipfire.org Git - people/stevee/network.git/commitdiff
network: New package.
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 7 Feb 2010 15:37:55 +0000 (16:37 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 8 Feb 2010 16:08:52 +0000 (17:08 +0100)
17 files changed:
functions [new file with mode: 0644]
functions.ppp [new file with mode: 0644]
hook-header [new file with mode: 0644]
hooks/README [new file with mode: 0644]
hooks/bonding [new file with mode: 0755]
hooks/ethernet [new file with mode: 0755]
hooks/ipv4-dhcp [new file with mode: 0755]
hooks/ipv4-static [new file with mode: 0755]
hooks/ipv4-static-route [new file with mode: 0755]
hooks/mtu [new file with mode: 0755]
hooks/pppoe [new file with mode: 0755]
hooks/pppoe.helper [new file with mode: 0755]
hooks/stp [new file with mode: 0755]
hooks/vlan [new file with mode: 0755]
network [new file with mode: 0644]
ppp/ip-updown [new file with mode: 0644]
zone [new file with mode: 0755]

diff --git a/functions b/functions
new file mode 100644 (file)
index 0000000..773463a
--- /dev/null
+++ b/functions
@@ -0,0 +1,676 @@
+#!/bin/sh
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2009  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/>.       #
+#                                                                             #
+###############################################################################
+
+HOME_DIR=${HOME_DIR-/lib/network}
+CONFIG_DIR=/etc/network
+HOOKS_DIR=${HOME_DIR}/hooks
+LOG_DIR=/var/log/network
+
+CONNECTIONS_FILE=/var/log/network/connections.db
+
+CONFIG_ZONES=${CONFIG_DIR}/zones
+CONFIG_PORTS=${CONFIG_DIR}/ports
+CONFIG_HOOKS=${CONFIG_DIR}/hooks
+CONFIG_PPP=${CONFIG_DIR}/ppp
+CONFIG_UUIDS=${CONFIG_DIR}/uuids
+
+# Create config directories
+for dir in ${CONFIG_ZONES} ${CONFIG_PORTS} ${CONFIG_HOOKS} ${CONFIG_PPP} ${CONFIG_UUIDS}; do
+       [ -d "${dir}" ] && continue
+       mkdir -p "${dir}"
+done
+
+COMMON_DEVICE=port+
+
+EXIT_OK=0
+EXIT_ERROR=1
+EXIT_CONF_ERROR=2
+
+VALID_ZONES="blue green orange red grey"
+
+[ -n "${DEBUG}"   ] || DEBUG=
+[ -n "${VERBOSE}" ] || VERBOSE=
+
+function is_mac() {
+       [[ $1 =~ ^[0-9a-f][0-9a-f]\:[0-9a-f][0-9a-f]\:[0-9a-f][0-9a-f]\:[0-9a-f][0-9a-f]\:[0-9a-f][0-9a-f]\:[0-9a-f][0-9a-f]$ ]]
+}
+
+function is_uuid() {
+       local string=${1}
+       
+       # Length must be 37 characters
+       if [ ${#string} -eq 36 ] \
+               && [ "${string:8:1}" = "-" ] \
+               && [ "${string:13:1}" = "-" ] \
+               && [ "${string:18:1}" = "-" ] \
+               && [ "${string:23:1}" = "-" ]; then
+               return ${EXIT_OK}
+       fi
+       return ${EXIT_ERROR}
+}
+
+function get_device_by_mac() {
+       local mac=${1}
+       local device
+
+       for device in /sys/class/net/*; do
+               [ -d "${device}" ] || continue
+               if [ "$(cat $device/address)" = "$mac" ]; then
+                       device=${device##*/}
+                       # Skip virtual devices
+                       if [ -e "/proc/net/vlan/$device" ]; then
+                               continue
+                       fi
+                       # Skip zones
+                       if zone_exists ${device}; then
+                               continue
+                       fi
+                       echo ${device}
+                       return 0
+               fi
+       done
+       return 1
+}
+
+function get_device_by_mac_and_vid() {
+       local mac=$1
+       local vid=$2
+
+       local i
+       local VID
+       local DEVICE
+       if [ -e "/proc/net/vlan/config" ]; then
+               grep '|' /proc/net/vlan/config | sed "s/|//g" | \
+                       while read DEVICE VID PARENT; do
+                               if [ "${vid}" = "${VID}" ] && [ "$(macify ${PARENT})" = "${mac}" ]; then
+                                       echo "${DEVICE}"
+                                       return 0
+                               fi
+                       done
+       fi
+       return 1
+}
+
+function get_device() {
+       if [ ${#@} -gt 1 ]; then
+               get_device_by_mac_and_vid $@
+       else
+               get_device_by_mac $@
+       fi
+}
+
+function get_mac_by_device() {
+       local device
+       device=$1
+       if [ -d "/sys/class/net/$device" ]; then
+               cat /sys/class/net/$device/address
+               return 0
+       fi
+       return 1
+}
+
+function get_mac() {
+       get_mac_by_device $@
+}
+
+function devicify() {
+       local device=${1}
+       local mac
+
+       [ -n "${device}" ] || return 1
+
+       if is_mac ${device}; then
+               mac=${device}
+               device=$(get_device_by_mac ${device})
+       fi
+       if [ -n "${device}" ]; then
+               echo ${device}
+               return 0
+       else
+               echo "devicify: Could not find device of $@" >&2
+               return 1
+       fi
+}
+
+function macify() {
+       local input=${1}
+       local mac
+       
+       if is_mac ${input}; then
+               mac=${input}
+       else
+               mac=$(get_mac_by_device ${input})
+       fi
+       echo ${mac}
+}
+
+function device_exists() {
+       [ -n "${1}" ] || return ${EXIT_ERROR}
+       local device=$(devicify ${1})
+       [ -n "${device}" ] || return ${EXIT_ERROR}
+       ip link show ${device} &>/dev/null
+}
+
+function device_is_bonding() {
+       [ -d "/sys/class/net/${1}/bonding" ]
+}
+
+function device_is_bonded() {
+       local dev
+       for dev in /sys/class/net/*; do
+               # Skip crappy files
+               [ -d "${dev}" ] || continue
+
+               # Continue if not a bonding device
+               device_is_bonding "${dev##*/}" || continue
+
+               if grep -q "\<${1}\>" ${dev}/bonding/slaves; then
+                       return 0
+               fi
+       done
+       return 1
+}
+
+function device_is_bridge() {
+       [ -d "/sys/class/net/${1}/bridge" ]
+}
+
+function device_is_up() {
+       ip link show $(devicify ${1}) 2>/dev/null | grep -qE "<.*UP.*>"
+}
+
+function device_is_vlan() {
+       if [ ! -e "/proc/net/vlan/config" ]; then
+               return 1
+       fi
+       grep -q "^${1}" /proc/net/vlan/config
+}
+
+function device_is_ppp() {
+       # XXX need something better
+       [ "${1:0:3}" = "ppp" ]
+}
+
+function device_is_loopback() {
+       local device=$(devicify ${1})
+       [ "${device}" = "lo" ]
+}
+
+function device_is_real() {
+       local device=${1}
+
+       device_is_loopback ${device} && \
+               return ${EXIT_ERROR}
+
+       device_is_bonding ${device} &&  \
+               return ${EXIT_ERROR}
+
+       device_is_bridge ${device} && \
+               return ${EXIT_ERROR}
+
+       device_is_ppp ${device} && \
+               return ${EXIT_ERROR}
+
+       device_is_vlan ${device} && \
+               return ${EXIT_ERROR}
+
+       return ${EXIT_OK}
+}
+
+function device_type() {
+       local device=$(devicify ${1})
+
+       if device_is_vlan ${device}; then
+               echo "vlan"
+
+       elif device_is_bonding ${device}; then
+               echo "bonding"
+
+       elif device_is_bridge ${device}; then
+               echo "bridge"
+
+       elif device_is_ppp ${device}; then
+               echo "ppp"
+
+       elif device_is_loopback ${device}; then
+               echo "loopback"
+
+       elif device_is_real ${device}; then
+               echo "real"
+
+       else
+               echo "unknown"
+       fi
+}
+
+function device_has_vlans() {
+       if [ ! -e "/proc/net/vlan/config" ]; then
+               return 1
+       fi
+       grep -q "${1}$" /proc/net/vlan/config
+}
+
+function device_has_carrier() {
+       local device=$(devicify ${1})
+       [ "$(</sys/class/net/${device}/carrier)" = "1" ]
+}
+
+function device_get_free() {
+       local destination=${1}
+
+       # Replace + by a valid number
+       if grep -q "+$" <<<${destination}; then
+               local number=0
+               destination=$(sed -e "s/+//" <<<$destination)
+               while [ "${number}" -le "100" ]; do
+                       if ! device_exists "${destination}${number}"; then
+                               destination="${destination}${number}"
+                               break
+                       fi
+                       number=$(($number + 1))
+               done
+       fi
+       echo "${destination}"
+}
+
+function device_rename() {
+       local source=$1
+       local destination=$(device_get_free ${2})
+
+       # Check if devices exists
+       if ! device_exists ${source} || device_exists ${destination}; then
+               return 4
+       fi
+
+       local up
+       if device_is_up ${source}; then
+               ip link set ${source} down
+               up=1
+       fi
+
+       ip link set ${source} name ${destination}
+
+       if [ "${up}" = "1" ]; then
+               ip link set ${destination} up
+       fi
+}
+
+function hook_exists() {
+       [ -x "${HOOKS_DIR}/${1}" ]
+}
+
+function port_exists() {
+       device_exists $@
+}
+
+function port_is_up() {
+       port_exists $@ && device_is_up $@
+}
+
+function zone_exists() {
+       [ -e "$CONFIG_ZONES/${1}" ]
+}
+
+function zone_is_up() {
+       zone_exists $@ && device_is_up $@
+}
+
+function zone_is_forwarding() {
+       local seconds=45
+       local zone=${1}
+       
+       local device
+       while [ ${seconds} -gt 0 ]; do
+               for device in /sys/class/net/${zone}/brif/*; do
+                       [ -e "${device}/state" ] || continue
+                       if [ "$(<${device}/state)" = "3" ]; then
+                               return ${EXIT_OK}
+                       fi
+               done
+               sleep 1
+               seconds=$((${seconds} - 1))
+       done
+       return ${EXIT_ERROR}
+}
+
+function bridge_devices() {
+       local bridge=$1
+       [ -z "${bridge}" ] && return 2
+       brctl show | grep "^${bridge}" | awk '{ print $NF }' | grep -v "^interfaces$"
+}
+
+function zone_add_port() {
+       local zone=${1}
+       local port=${2}
+
+       brctl addif ${zone} ${port}
+}
+
+function zone_del_port() {
+       local zone=${1}
+       local port=${2}
+
+       brctl delif ${zone} ${port}
+}
+
+function zone_list() {
+       local zone
+       for zone in $(find ${CONFIG_ZONES}/* 2>/dev/null); do
+               [ -d "${zone}" ] && echo ${zone}
+       done
+}
+
+function zone_is_red() {
+       local zone=${1}
+       [ "${zone#red}" != "${zone}" ]
+}
+
+function _run_hooks() {
+       local action
+       local type
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --type=*)
+                               type=${1#--type=}
+                               ;;
+                       *)
+                               action="${1}"
+                               shift; break
+                               ;;
+               esac
+               shift
+       done
+
+       local dir=${1}; shift
+       local failed
+       local hook
+       local hooks
+
+       if [ -z "${action}" ] || [ -z "${dir}" ]; then
+               echo "Not enough parameters given." >&2
+               return 1
+       fi
+
+       for hook in $(find ${dir}); do
+               # Skip dirs
+               [ -d "${hook}" ] && continue
+
+               (
+                       . ${hook}
+                       # Skip hooks that are not of the given type
+                       if [ -n "${type}" ] && [ "$(hook_type ${HOOK})" != "${type}" ]; then
+                               continue
+                       fi
+                       if [ -n "${HOOK}" ]; then
+                               hook_run ${HOOK} --config=${hook} $@ ${action}
+                               RET=$?
+                       else
+                               echo -e "${FAILURE}Unable to process ${hook}. Either"
+                               echo -e "${FAILURE}the HOOK variable was not set,"
+                               echo -e "${FAILURE}or the specified hook cannot be executed."
+                               message=""
+                               log_failure_msg
+                       fi
+                       exit ${RET}
+               ) || failed=1
+       done
+
+       return ${failed}
+}
+
+function hooks_run_all() {
+       _run_hooks $@
+}
+
+function hooks_run_ports() {
+       _run_hooks --type="port" $@
+}
+
+function hooks_run_zones() {
+       _run_hooks --type="zone" $@
+}
+
+function hook_type() {
+       local hook=${1}
+       (
+               eval $(${HOOKS_DIR}/${hook} info)
+               echo "${HOOK_TYPE}"
+       )
+}
+
+function hook_list() {
+       local type=${1}
+       local hook
+       for hook in ${HOOKS_DIR}/*; do
+               hook=${hook##*/}
+               
+               [[ ${hook} =~ helper$ ]] && continue
+               
+               if [ -n "${type}" ] && [ "$(hook_type ${hook})" != "${type}" ]; then
+                       continue
+               fi
+               echo "${hook}"
+       done
+}
+
+function config_get_hook() {
+       local config=${1}
+       if [ ! -e "${config}" ]; then
+               log_failure_msg "Config file \"${config}\" does not exist."
+               return ${EXIT_ERROR}
+       fi
+       ( . ${config}; echo ${HOOK}     )
+}
+
+function hook_run() {
+       local hook=${1}
+       shift
+
+       if ! hook_exists ${hook}; then
+               log_failure_msg "Hook ${hook} cannot be found or is not executeable."
+               return ${EXIT_ERROR}
+       fi
+       [ -n "${DEBUG}" ] && echo "Running hook: ${hook} $@"
+       DEBUG=${DEBUG} VERBOSE=${VERBOSE} ${HOOKS_DIR}/${hook} $@
+       return $?
+}
+
+function hook_run_multiple() {
+       local zone
+       local config
+       local hook
+       local hook_type2
+       local type
+       
+       while [ "$#" -gt "0" ]; do
+               case "${1}" in
+                       --type=*)
+                               type=${1#--type=}
+                               ;;
+                       *)
+                               zone=${1}
+                               break
+                               ;;                      
+               esac
+               shift
+       done
+
+       if ! zone_exists ${zone}; then
+               return ${EXIT_ERROR}
+       fi
+
+       for config in $(find ${CONFIG_ZONES}/${zone} 2>/dev/null); do
+               hook=$(config_get_hook ${config})
+               if [ -n "${type}" ]; then
+                       hook_type2=$(hook_type ${hook})
+                       if [ "${type}" != "${hook_type2}" ]; then
+                               continue
+                       fi
+               fi
+               hook_run ${hook} $@
+       done
+}
+
+function zone_run() {
+       local zone=${1}
+       shift
+
+       if ! zone_exists ${zone}; then
+               log_failure_msg "Zone ${zone} does not exist."
+               exit ${EXIT_ERROR}
+       fi
+       decho "Running zone: ${zone} $@"
+       DEBUG=${DEBUG} VERBOSE=${VERBOSE} ${HOME_DIR}/zone --zone=${zone} $@
+}
+
+function zone_valid_name() {
+       local zone=${1}
+       local match
+
+       local i
+       for i in ${VALID_ZONES}; do
+               match="${match}|${i}[0-9]{1,5}"
+       done
+       [[ ${zone} =~ ${match:1:${#match}} ]]
+}
+
+function isset() {
+       local key=${1}
+       [ -n "${!key}" ] && return
+       if [[ ${key} =~ port|zone ]]; then
+               echo "ERROR: The --${key} flag is not set." >&2
+       else
+               echo "ERROR: The \"${key}\" variable is not set properly." >&2
+       fi
+       return 1
+}
+
+# Test if device is attached to the given bridge
+function zone_has_device_attached () {
+       local zone=${1}
+       local device=${2}
+
+       [ -d "/sys/class/net/${zone}/brif/${device}" ]
+}
+
+function device_has_ipv4() {
+       local device=${1}
+       local ip=${2}
+       ip addr show ${device} | grep inet | fgrep -q ${ip}
+}
+
+function check_config() {
+       local failed
+       local i
+
+       for i in $@; do
+               isset ${i} || failed=1
+       done
+       if [ "${failed}" = "1" ]; then
+               echo "Exiting..."
+               exit ${EXIT_ERROR}
+       fi
+}
+
+function mac_generate() {
+       local mac="00"
+       while [ "${#mac}" -lt 15 ]; do
+               mac="${mac}:$(cut -c 1-2 /proc/sys/kernel/random/uuid)"
+       done
+       echo "${mac}"
+}
+
+function connection() {
+       local action
+
+       local dns
+       local interface
+       local iplocal
+       local ipremote
+       local name
+       local status
+       local weight
+       local zone
+
+       while [ $# -gt 0 ]; do
+               case "${1}" in
+                       --up)
+                               action="up"
+                               ;;
+                       --down)
+                               action="down"
+                               ;;
+                       --starting)
+                               action="starting"
+                               ;;
+                       --stopping)
+                               action="stopping"
+                               ;;
+                       --name=*)
+                               name=${1#--name=}
+                               ;;
+                       --zone=*)
+                               zone=${1#--zone=}
+                               zone_is_red ${zone} || return 0
+                               ;;
+                       --interface=*)
+                               interface=${1#--interface=}
+                               ;;
+                       --iplocal=*)
+                               iplocal=${1#--iplocal=}
+                               ;;
+                       --ipremote=*)
+                               ipremote=${1#--ipremote=}
+                               ;;
+                       --weight=*)
+                               weight=${1#--weight=}
+                               ;;
+                       --dns=*)
+                               dns=${1#--dns=}
+                               ;;
+               esac
+               shift
+       done
+
+       if [ ! -e "${CONNECTIONS_FILE}" ]; then
+               sqlite3 -batch ${CONNECTIONS_FILE} <<EOF
+CREATE TABLE connections(name, zone, interface, iplocal, ipremote, weight, dns, status);
+EOF
+       fi
+
+       if [ -z "${zone}" ]; then
+               return 2
+       fi
+
+       status=${action}
+
+       sqlite3 -batch ${CONNECTIONS_FILE} <<EOF
+DELETE FROM connections WHERE zone = '${zone}';
+INSERT INTO connections(name, zone, interface, iplocal, ipremote, weight, dns, status)
+       VALUES('${name}', '${zone}', '${interface}', '${iplocal}', '${ipremote}', '${weight}', '${dns}', '${status}');
+EOF
+
+}
+
+function uuid() {
+       cat /proc/sys/kernel/random/uuid
+}
diff --git a/functions.ppp b/functions.ppp
new file mode 100644 (file)
index 0000000..7598f0b
--- /dev/null
@@ -0,0 +1,110 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2009  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/>.       #
+#                                                                             #
+###############################################################################
+
+RED_RUN=/var/run/network/red
+PPP_SECRETS=/etc/ppp/secrets
+
+function ppp_pre_up() {
+       # Load the ppp_generic module if not already done
+       grep -q ^ppp_generic /proc/modules || modprobe ppp_generic
+
+       connection --starting --zone=${zone}
+}
+
+function ppp_post_up() {
+       : #connection --up --zone=${zone}
+}
+
+function ppp_pre_down() {
+       connection --stopping --zone=${zone}
+}
+
+function ppp_post_down() {
+       : #connection --down --zone=${zone}
+}
+
+function ppp_secret() {
+       local USER=${1}
+       local SECRET=${2}
+       local a
+       local secret
+       local user
+
+       # Updateing secret file
+       > ${PPP_SECRETS}.tmp
+       while read user a secret; do
+               if [ "'${USER}'" != "${user}" ]; then
+                       echo "${user} ${a} ${secret}" >> ${PPP_SECRETS}.tmp
+               fi
+       done < ${PPP_SECRETS}
+       echo "'${USER}' * '${SECRET}'" >> ${PPP_SECRETS}.tmp
+       cat ${PPP_SECRETS}.tmp > ${PPP_SECRETS}
+       rm -f ${PPP_SECRETS}.tmp
+}
+
+function ppp_stat() {
+       local name=${1}
+       local time=${2}
+       local rcvd=${3}
+       local sent=${4}
+
+       local file="${LOG_DIR}/ppp_${name}.db"
+       if ! [ -e "${file}" ]; then
+       sqlite3 -batch ${file} <<EOF
+CREATE TABLE connections(date, duration, rcvd, sent);
+EOF
+       fi
+       ppp_stat_init ${file}
+
+       sqlite3 -batch ${file} <<EOF
+INSERT INTO connections(date, duration, rcvd, sent) VALUES('$(date -u '+%s')', '${time}', '${rcvd}', '${sent}');
+EOF
+}
+
+function ppp_linkname_get() {
+       local config=${1}
+       (
+               . ${config}
+               echo "${LINKNAME}"
+       )
+}
+
+function red_defaultroute_update() {
+       local command="ip route replace default"
+
+       for uplink in ${RED_RUN}/*; do
+               [ -d "${uplink}" ] || continue
+
+               # Skip if no gateway given
+               [ -e "${uplink}/gateway" ] || continue
+
+               command="${command} nexthop via $(<${uplink}/gateway)"
+               if [ -e "${uplink}/weight" ]; then
+                       command="${command} weight $(<${uplink}/weight)"
+               fi
+       done
+       $command
+       ip route flush cache
+}
+
+function red_dns_update() {
+       : # XXX todo
+}
diff --git a/hook-header b/hook-header
new file mode 100644 (file)
index 0000000..b2693b8
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+. /etc/init/functions
+. /lib/network/functions
+
+INDENT=" "
+
+HOOK_PRIO=100
+
+# Parse the command line
+action=
+port=
+zone=
+
+while [ $# -gt 0 ]; do
+       case "${1}" in
+               --zone=*)
+                       zone=${1#--zone=}
+                       ;;
+               --config=*)
+                       . ${1#--config=}
+                       ;;
+               --port=*)
+                       port=${1#--port=}
+                       ;;
+               -*)
+                       log_failure_msg "Unrecognized option: ${1}"
+                       exit ${EXIT_ERROR}
+                       ;;
+               *)
+                       action=${1}
+                       shift
+                       break
+                       ;;
+       esac
+       shift
+done
+
diff --git a/hooks/README b/hooks/README
new file mode 100644 (file)
index 0000000..09ca230
--- /dev/null
@@ -0,0 +1,86 @@
+HOOKS README
+
+A hook is file that can configure a specific network connection (e.g. ethernet)
+or protocol (e.g. ipv4-static).
+
+They are expandable and standalone. Means, when you call a file, you will
+run it and pass some options and an action to it.
+
+  /lib/network/hooks/HOOOK [options] <action> [options to action]
+
+There are two types of hooks:
+       zone
+               These hooks applies to a zone and does configuration on it.
+               Mainly, it configures the IP protocol or something else.
+       
+       port
+               These hooks add ports to zones.
+
+DEFINES:
+       So, to know what type of hook this is, we have to define some variables
+       in the header of the file.
+       
+       HOOK_NAME
+               The name of the hook. This is normally the file name.
+       
+       HOOK_TYPE
+               zone or port. See section above.
+
+               
+INLCUDES:
+       These files get included in the header.
+
+       /lib/lsb/init-functions
+               For pretty messages
+
+       /lib/network/functions
+               Our networking funktions.
+
+               
+OPTIONS:
+       Options have at least to be for zone file:
+
+       --config=CONFIG
+               Includes the given config file CONFIG.
+               If there is an error when loading the config file or the parameters are
+               wrong or invalid, the script will pass an error with code ${EXIT_CONF_ERROR}!
+
+       --port=PORT
+               Takes a port (either as device (eth0) or as mac (00:11:22:33:44:55)).
+
+       --zone=ZONE
+               Takes the name of a zone.
+
+
+ACTION:
+       Actions that always have to be defined:
+               help
+                       Gives the user a short help how to use the command and its arguments.
+
+               info
+                       Gives some information about the hook (mainly for internal use of the scripts).
+                       See below.
+
+               status
+                       Gives information if the hook is active or not.
+
+               config
+                       This is the command that creates the configuration for each hook.
+                       It will accept some more arguments in the command line
+                       and return either ${EXIT_OK} or ${EXIT_ERROR}.
+
+       Actions that have to be defined for a zone hook:
+               pre-up
+                       This gets runned before the zone gets up.
+               
+               pre-down.
+                       This is runned before the zone is set down.
+               
+               post-up
+                       After setting up the zone, this command will be executed.
+               
+               post-down
+                       After the zone has vanished, this part of the script is called.
+
+               All these actions will return ${EXIT_OK} when everything went fine.
+               If not, they will return ${EXIT_ERROR}.
diff --git a/hooks/bonding b/hooks/bonding
new file mode 100755 (executable)
index 0000000..03f0a70
--- /dev/null
@@ -0,0 +1,177 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/bonding
+#
+# Description : Bonding Script
+#
+# Authors     : Michael Tremer - michael.tremer@ipfire.org
+#
+# Version     : 00.00
+#
+# Notes       : This script adds bonding support.
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=bonding
+HOOK_TYPE=port
+HOOK_PRIO=50
+
+DEFAULT_MODE=
+
+function port_name() {
+       echo "${zone}t+"
+}
+
+case "${action}" in
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=${HOOK_NAME}"
+               echo "HOOK_TYPE=${HOOK_TYPE}"
+               ;;
+
+       pre-up)
+               if ! grep -q ^bonding /proc/modules; then
+                       modprobe bonding
+                       echo "-bond0" > /sys/class/net/bonding_masters
+               fi
+
+               if device_exists ${MAC}; then
+                       device=$(devicify ${MAC})
+                       if ! device_is_bonding ${device}; then
+                               log_failure_msg "Device \"${device}\" is up, but not a bonding device."
+                               exit ${EXIT_ERR}
+                       fi
+                       exit ${EXIT_OK}
+               fi
+
+               device=$(device_get_free $(port_name))
+               echo "+${device}" > /sys/class/net/bonding_masters
+               ip link set ${device} address ${MAC}
+       
+               [ -n "${MODE}" ] && \
+                       echo "${MODE}" > /sys/class/net/${device}/bonding/mode
+
+               echo "${MIIMON-100}" > /sys/class/net/${device}/bonding/miimon
+
+               for slave in ${SLAVES}; do
+                       if device_exists ${slave}; then
+                               if device_is_up ${slave}; then
+                                       log_warning_msg "Cannot enslave device \"${slave}\"."
+                                       continue
+                               fi
+                               device_rename "$(devicify ${slave})" "${device}s+"
+                               echo "+$(devicify ${slave})" > /sys/class/net/${device}/bonding/slaves
+                       else
+                               log_warning_msg "Device ${slave} does not exist."
+                       fi
+               done
+       
+               ip link set ${device} up
+       
+               log_success_msg "Setting up trunk ${MAC}..."
+               ;;
+
+       post-up)
+               device=$(devicify ${MAC})
+               if ! zone_has_device_attached ${zone} ${device}; then
+                       zone_add_port ${zone} ${device}
+               fi
+               ;;
+
+       pre-down)
+               device=$(devicify ${MAC})
+               if zone_has_device_attached ${zone} ${device}; then
+                       zone_del_port ${zone} ${device}
+               fi
+               ;;
+
+       post-down)
+               device=$(devicify ${MAC})
+               if port_is_up ${device}; then
+                       MESSAGE="Pulling down trunk ${MAC}..."
+                       ip link set ${device} down
+                       evaluate_retval
+                       echo "-${device}" > /sys/class/net/bonding_masters
+               fi
+               ;;
+
+       add)
+               MAC=$(mac_generate)
+               MODE=${DEFAULT_MODE}
+
+               while [ $# -gt 0 ]; do
+                       case "${1}" in
+                               --mac=*)
+                                       MAC=${1#--mac=}
+                                       ;;
+                               --mode=*)
+                                       MODE=${1#--mode=}
+                                       ;;
+                               *)
+                                       SLAVES="${SLAVES} $(macify ${1})"
+                                       ;;
+                       esac
+                       shift
+               done
+
+               UUID=$(uuid)
+               cat <<EOF > ${CONFIG_UUIDS}/${UUID}
+HOOK="${HOOK_NAME}"
+MAC="${MAC}"
+MODE="${MODE}"
+SLAVES="$(echo ${SLAVES})"
+EOF
+               ln -sf ${CONFIG_UUIDS}/${UUID} \
+                       ${CONFIG_ZONES}/${zone}/${HOOK_NAME}-${UUID}
+
+               log_success_msg "Configuration successfully saved!"
+               echo    "      MAC address : ${MAC}"
+               echo    "      Mode        : ${MODE}"
+               echo    "      Slaves      : $(echo ${SLAVES})"
+               ;;
+
+       rem)
+               ;;
+
+       status)
+               DEVICE=$(devicify ${MAC})
+               echo -e "#  ${CLR_BOLD_CYN}Trunk ${DEVICE} (${MAC})${NORMAL}"
+               if device_is_up ${MAC}; then
+                        echo -e "#    State: ${CLR_BOLD_GRN}up${NORMAL}"
+                        echo    "#"
+                        for slave in $(</sys/class/net/${DEVICE}/bonding/slaves); do
+                               echo -e "#    ${CLR_BOLD_CYN}Slave port ${slave}${NORMAL}"
+
+                               echo -n "#      State: " 
+                               if device_is_up ${slave}; then
+                                       echo -e "${CLR_BOLD_GRN}up${NORMAL}"
+                               else
+                                       echo -e "${CLR_BOLD_RED}down${NORMAL}"
+                               fi
+
+                               echo -n "#      Link : "
+                               if device_has_carrier ${slave}; then
+                                       echo -e "${CLR_BOLD_GRN}yes${NORMAL}"
+                               else
+                                       echo -e "${CLR_BOLD_RED}no${NORMAL}" 
+                               fi
+                        done
+               else
+                       echo -e "#    State: ${CLR_BOLD_RED}down${NORMAL}"
+               fi
+
+               device_is_up ${MAC}
+               exit ${?}
+               ;;
+
+       *)
+               echo "Usage: ${0} [interface] {up|down|add|remove|attach|detach|status}"
+               exit 1
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/bonding
diff --git a/hooks/ethernet b/hooks/ethernet
new file mode 100755 (executable)
index 0000000..e6e364f
--- /dev/null
@@ -0,0 +1,137 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/ethernet
+#
+# Description : Ethernet Script
+#
+# Authors     : Michael Tremer - michael.tremer@ipfire.org
+#
+# Version     : 00.00
+#
+# Notes       : This script adds ethernet support.
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=ethernet
+HOOK_TYPE=port
+
+function port_name() {
+       echo ${zone}p+
+}
+
+case "${action}" in
+       help)
+               echo -e "${BOLD}Hook (${HOOK_NAME}) help:"
+               echo
+               echo -e "    ${BOLD}Summary:${NORMAL}"
+               echo    "        The ethernet-hook controls connection via ethernet."
+               echo    "        You will need this to access your local lan."
+               echo
+               echo -e "    ${BOLD}Usage:${NORMAL}"
+               #echo    "        --config=<FILE>"
+               #echo    "            Includes a config file."
+               #echo    "            Example: --config=/etc/sysconfig/network/green0/port-00:11:22:33:44:55"
+               #echo    "        --port=<MAC or Name>"
+               #echo    "            Passes the port to the script."
+               #echo    "            Example: --port=port0 or --port=00:11:22:33:44:55"
+               #echo    "        --zone=<zone>"
+               #echo    "            Passes the zone to the script."
+               #echo    "            Example: --zone=green0"
+               #echo
+               #echo -e "    ${BOLD}Commands:${NORMAL}"
+               #echo
+               echo     "        This hook only needs the name of the network device"
+               echo     "        that should be attached to the zone."
+               echo     "        The device identifier can either be a mac address or"
+               echo     "        a device name."
+               echo
+               echo     "            Example: network zone addport green0 ethernet port0"
+               echo     "                     network zone addport green0 ethernet 00:11:22:33:44:55"
+               echo
+               ;;
+
+       info)
+               echo "HOOK_NAME=${HOOK_NAME}"
+               echo "HOOK_TYPE=${HOOK_TYPE}"
+               ;;
+
+       pre-up)
+               device_is_up ${MAC} || ip link set $(devicify ${MAC}) up
+               ;;
+       
+       post-up)
+               if zone_has_device_attached ${zone} $(get_device ${MAC}); then
+                       # Device is already attached to the bridge
+                       exit ${EXIT_OK}
+               fi
+               message="Attaching ethernet port ${MAC}..."
+               device_rename $(get_device ${MAC}) $(port_name)
+               zone_add_port ${zone} $(get_device_by_mac ${MAC})
+               evaluate_retval
+               ;;
+               
+       pre-down)
+               if zone_has_device_attached ${zone} $(get_device ${MAC}); then
+                       message="Detatching ethernet port ${MAC}..."
+                       zone_del_port ${zone} $(get_device_by_mac ${MAC})
+                       device_rename $(get_device_by_mac ${MAC}) ${COMMON_DEVICE}
+                       evaluate_retval
+               fi
+               ;;
+       
+       post-down)
+               ## Possibly pull down the device (if there are no more vlan devices up...)
+               ;;
+
+       add)
+               ### XXX error handling
+
+               for dev in $@; do
+                       MAC=$(macify ${dev})
+                       UUID=$(uuid)
+                       cat <<EOF > ${CONFIG_UUIDS}/${UUID}
+HOOK="${HOOK_NAME}"
+MAC="${MAC}"
+EOF
+                       ln -sf ${CONFIG_UUIDS}/${UUID} \
+                               ${CONFIG_ZONES}/${zone}/${HOOK_NAME}-${UUID}
+
+                       log_success_msg "Configuration successfully saved!"
+                       echo    "      Device      : $(devicify ${MAC})"
+                       echo    "      MAC address : ${MAC}"
+               done
+               ;;
+
+       rem)
+               # XXX to be done
+               ;;
+
+       status)
+               echo -e "#  ${CLR_BOLD_CYN}Ethernet port $(devicify ${MAC}) (${MAC})${NORMAL}"
+               echo -n "#   State: "
+               if device_is_up ${MAC}; then
+                       echo -e "${CLR_BOLD_GRN}up${NORMAL}"
+               else
+                       echo -e "${CLR_BOLD_RED}down${NORMAL}"
+               fi
+               echo -n "#   Link : "
+               if device_has_carrier ${MAC}; then
+                       echo -e "${CLR_BOLD_GRN}yes${NORMAL}"
+               else
+                       echo -e "${CLR_BOLD_RED}no${NORMAL}" 
+               fi
+               echo "#"
+
+               device_is_up ${MAC}
+               exit ${?}
+               ;;
+
+       *)
+               echo "Usage: ${0} [interface] {up|down|add|remove|attach|detach|status}"
+               exit 1
+               ;;
+esac
+
+# End $NETWORK_DEVICES/services/ethernet
diff --git a/hooks/ipv4-dhcp b/hooks/ipv4-dhcp
new file mode 100755 (executable)
index 0000000..43c4419
--- /dev/null
@@ -0,0 +1,84 @@
+#!/bin/sh
+
+. /lib/network/hook-header
+
+HOOK_NAME="ipv4-dhcp"
+HOOK_TYPE="zone"
+
+MESSAGE="DHCP Daemon..."
+EXECUTEABLE="/sbin/dhclient"
+
+case "${action}" in
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=$HOOK_NAME"
+               echo "HOOK_TYPE=$HOOK_TYPE"
+               ;;
+
+       status)
+               check_config zone
+               pidfile="/var/run/dhclient_${zone}.pid"
+               pidofproc -p ${pidfile} ${EXECUTEABLE} &>/dev/null
+               exit $? 
+               ;;
+
+       pre-up)
+               ;;
+
+       post-up)
+               check_config zone
+               pidfile="/var/run/dhclient_${zone}.pid"
+               if [ -e "${pidfile}" ]; then
+                       kill $(<${pidfile}) &>/dev/null
+                       sleep 1
+               fi
+               ${EXECUTEABLE} -pf ${pidfile} ${zone}
+               evaluate_retval start
+               ;;
+
+       pre-down)
+               check_config zone
+               pidfile="/var/run/dhclient_${zone}.pid"
+               killproc -p ${pidfile} ${EXECUTEABLE}
+               evaluate_retval stop
+               ;;
+
+       post-down)
+               ;;
+
+       add)
+               while [ $# -gt 0 ]; do
+                       case "$1" in
+                               --hostname=*)
+                                       HOSTNAME=${1#--hostname=}
+                                       ;;
+                               *)
+                                       echo "Unknown option: $1" >&2
+                                       exit 1
+                                       ;;
+                       esac
+                       shift
+               done
+               cat <<EOF >${CONFIG_ZONES}/${zone}/ipv4-dhcp
+HOOK="${HOOK_NAME}"
+HOSTNAME="${HOSTNAME}"
+EOF
+               [ "$?" = "0" ] && exit ${EXIT_OK} || exit ${EXIT_ERROR}
+               ;;
+
+       rem)
+               ;;
+
+       discover)
+               exit ${EXIT_ERROR}
+               ;;
+
+       *)
+               echo "Usage: ${0} {config|pre-up|post-up|pre-down|post-down|status} [interface]"
+               exit ${EXIT_ERROR}
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/ipv4-dhcp
diff --git a/hooks/ipv4-static b/hooks/ipv4-static
new file mode 100755 (executable)
index 0000000..34af557
--- /dev/null
@@ -0,0 +1,169 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/ipv4-static
+#
+# Description : IPV4 Static Boot Script
+#
+# Authors     : Nathan Coulson - nathan@linuxfromscratch.org
+#               Kevin P. Fleming - kpfleming@linuxfromscratch.org
+#
+# Version     : 00.00
+#
+# Notes       :
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME="ipv4-static"
+HOOK_TYPE="zone"
+
+function check_config() {
+       args=
+       if [ -z "${IP}" ]; then
+               log_failure_msg "IP variable missing, cannot continue."
+               exit ${EXIT_CONF_ERROR}
+       fi
+       
+       if [ -z "${PREFIX}" -a -z "${PEER}" ]; then
+               log_warning_msg "PREFIX variable missing, assuming 24."
+               PREFIX=24
+               args="${args} ${IP}/${PREFIX}"
+       elif [ -n "${PREFIX}" -a -n "${PEER}" ]; then
+               log_failure_msg "PREFIX and PEER both specified, cannot continue."
+               exit ${EXIT_CONF_ERROR}
+       elif [ -n "${PREFIX}" ]; then
+               args="${args} ${IP}/${PREFIX}"
+       elif [ -n "${PEER}" ]; then
+               args="${args} ${IP} peer ${PEER}"
+       fi
+       
+       if [ -n "${BROADCAST}" ]; then
+               args="${args} broadcast ${BROADCAST}"
+       fi
+       
+       if [ -n "${SOURCE}" ]; then
+               args="${args} src ${SOURCE}"
+       fi
+}
+
+case "${action}" in
+       help)
+               ;;
+
+    info)
+        echo "HOOK_NAME=$HOOK_NAME"
+        echo "HOOK_TYPE=$HOOK_TYPE"
+        ;;
+
+       status)
+               check_config
+               echo -e "#  ${CLR_BOLD_CYN}IPv4 static: ${IP}/${PREFIX}${NORMAL}"
+               if [ -n "${GATEWAY}" ]; then
+                       echo    "#    Gateway: ${GATEWAY}"
+                       echo -n "#      Reachable: "
+                       if ping -c1 -w1 -I ${zone} ${GATEWAY} &>/dev/null; then
+                               echo -e "${CLR_BOLD_GRN}yes${NORMAL}"
+                       else
+                               echo -e "${CLR_BOLD_RED}no${NORMAL}"
+                       fi
+               fi
+               ip addr show ${zone} | grep "inet " | fgrep -q "${IP}/${PREFIX}"
+               exit ${?}
+               ;;
+
+       pre-up)
+               ;;
+
+       post-up)
+               check_config
+               if ! device_has_ipv4 ${zone} ${IP}; then
+                       MESSAGE="Adding IPv4 address ${IP} to zone ${zone} interface..."
+                       ip addr add ${args} dev ${zone}
+                       evaluate_retval
+               fi
+       
+               if [ -n "${GATEWAY}" ]; then
+                       if ip route | grep -q default; then
+                               log_warning_msg "Gateway already setup; skipping." ${WARNING}
+                       else
+                               MESSAGE="Setting up default gateway..."
+                               ip route add default via ${GATEWAY} dev ${zone}
+                               evaluate_retval
+                        fi
+               fi
+       ;;
+
+       pre-down)
+               check_config
+               if [ -n "${GATEWAY}" ]; then
+                       MESSAGE="Removing default gateway..."
+                       ip route del default
+                       evaluate_retval
+               fi
+       
+               if device_has_ipv4 ${zone} ${IP}; then
+                       MESSAGE="Removing IPv4 address ${IP} from zone ${zone}..."
+                       ip addr del ${args} dev ${zone}
+                       evaluate_retval
+               fi
+               ;;
+
+       post-down)
+               ;;
+
+       add)
+               while [ $# -gt 0 ]; do
+                       case "$1" in
+                               --ip=*)
+                                       IP=${1#--ip=}
+                                       ;;
+                               --prefix=*)
+                                       PREFIX=${1#--prefix=}
+                                       ;;
+                               --peer=*)
+                                       PEER=${1#--peer=}
+                                       ;;
+                               --broadcast=*)
+                                       BROADCAST=${1#--broadcast=}
+                                       ;;
+                               --source=*)
+                                       SOURCE=${1#--source=}
+                                       ;;
+                               --gateway=*)
+                                       GATEWAY=${1#--gateway=}
+                                       ;;
+                               *)
+                                       echo "Unknown option: $1" >&2
+                                       exit 1
+                                       ;;
+                       esac
+                       shift
+               done
+               #check_config
+               cat <<EOF >${CONFIG_ZONES}/${zone}/ipv4-static_$IP
+HOOK="${HOOK_NAME}"
+IP="${IP}"
+PREFIX="${PREFIX}"
+PEER="${PEER}"
+BROADCAST="${BROADCAST}"
+SOURCE="${SOURCE}"
+GATEWAY="${GATEWAY}"
+EOF
+               [ "$?" = "0" ] && exit ${EXIT_OK} || exit ${EXIT_ERROR}
+               ;;
+
+       rem)
+               ;;
+       
+       discover)
+               exit ${EXIT_ERROR}
+               ;;
+
+       *)
+               echo "Usage: ${0} {config|pre-up|post-up|pre-down|post-down|status} [interface]"
+               exit ${EXIT_ERROR}
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/ipv4-static
diff --git a/hooks/ipv4-static-route b/hooks/ipv4-static-route
new file mode 100755 (executable)
index 0000000..9e38986
--- /dev/null
@@ -0,0 +1,141 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/ipv4-static-route
+#
+# Description : IPV4 Static Route Script
+#
+# Authors     : Kevin P. Fleming - kpfleming@linuxfromscratch.org
+#
+# Version     : 00.00
+#
+# Notes       :
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=ipv4-static-route
+HOOK_TYPE=zone
+
+function check_config() {
+       args=
+       case "${TYPE}" in
+               ""|network)
+                       need_ip=1
+                       need_gateway=1
+                       ;;
+       
+               default)
+                       need_gateway=1
+                       args="${args} default"
+                       desc="default"
+                       ;;
+       
+               host)
+                       need_ip=1
+                       ;;
+       
+               unreachable)
+                       need_ip=1
+                       args="${args} unreachable"
+                       desc="unreachable"
+                       ;;
+       
+               *)
+                       log_failure_msg "Unknown route type (${TYPE}) in ${CONFIG}, cannot continue."
+                       exit ${EXIT_CONF_ERROR}
+                       ;;
+       esac
+       
+       if [ -n "${need_ip}" ]; then
+               if [ -z "${IP}" ]; then
+                       log_failure_msg "IP variable missing from ${CONFIG}, cannot continue."
+                       exit ${EXIT_CONF_ERROR}
+               fi
+       
+               if [ -z "${PREFIX}" ]; then
+                       log_failure_msg "PREFIX variable missing from ${CONFIG}, cannot continue."
+                       exit ${EXIT_CONF_ERROR}
+               fi
+               
+               args="${args} ${IP}/${PREFIX}"
+               desc="${desc}${IP}/${PREFIX}"
+       fi
+       
+       if [ -n "${need_gateway}" ]; then
+               if [ -z "${GATEWAY}" ]; then
+                       log_failure_msg "GATEWAY variable missing from ${CONFIG}, cannot continue."
+                       exit ${EXIT_CONF_ERROR}
+               fi
+               args="${args} via ${GATEWAY}"
+       fi
+}
+
+case "${action}" in
+       add)
+               while [ $# -gt 0 ]; do
+                       case "${1}" in
+                               --ip=*)
+                                       IP=${1#--ip=}
+                                       ;;
+                               --gateway=*)
+                                       GATEWAY=${1#--gateway=}
+                                       ;;
+                               --prefix=*)
+                                       PREFIX=${1#--prefix=}
+                                       ;;
+                               --type=*)
+                                       TYPE=${1#--type=}
+                                       ;;
+                       esac
+                       shift
+               done
+               check_config
+               cat <<EOF >${CONFIG_ZONES}/${zone}/${HOOK_NAME}_${IP-${GATEWAY}}
+HOOK="${HOOK_NAME}"
+IP="${IP}"
+GATEWAY="${GATEWAY}"
+PREFIX="${PREFIX}"
+TYPE="${TYPE}"
+EOF
+               [ "$?" = "0" ] && exit ${EXIT_OK} || exit ${EXIT_ERROR}
+               ;;
+
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=${HOOK_NAME}"
+               echo "HOOK_TYPE=${HOOK_TYPE}"
+               ;;
+
+       pre-up)
+               ;;
+
+       post-up)
+               boot_mesg "Adding '${desc}' route to zone ${zone}..."
+               ip route add ${args} dev ${zone}
+               evaluate_retval
+               ;;
+       
+       pre-down)
+               boot_mesg "Removing '${desc}' route from zone ${zone}..."
+               ip route del ${args} dev ${zone}
+               evaluate_retval
+               ;;
+       
+       post-down)
+               ;;
+       
+       discover)
+
+               exit ${EXIT_ERROR}
+               ;;
+       
+       *)
+               echo "Usage: ${0} [interface] {up|down}"
+               exit 1
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/ipv4-static-route
diff --git a/hooks/mtu b/hooks/mtu
new file mode 100755 (executable)
index 0000000..707345a
--- /dev/null
+++ b/hooks/mtu
@@ -0,0 +1,85 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/mtu
+#
+# Description : Sets MTU per interface
+#
+# Authors     : Nathan Coulson - nathan@linuxfromscratch.org
+#               Jim Gifford - jim@linuxfromscratch.org
+#
+# Version     : 00.00
+#
+# Notes       : This sets the maximum amount of bytes that can be
+#               transmitted within a packet. By default, this
+#               value is set to 1500.
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=mtu
+HOOK_TYPE=zone
+
+DEFAULT_MTU=1500
+
+function usage() {
+       echo "Usage: ${0} {pre-up|post-up|pre-down|post-down|config} [interface]"
+}
+
+case "${action}" in
+       help)
+               ;;
+       
+       info)
+               echo "HOOK_NAME=$HOOK_NAME"
+               echo "HOOK_TYPE=$HOOK_TYPE"
+               ;;
+
+       status)
+               check_config zone MTU
+               mtu=$(cat /sys/class/net/${zone}/mtu 2>/dev/null)
+               [ "$MTU" = "$mtu" ]
+               exit $?
+               ;;
+
+       pre-up)
+               ;;
+
+       post-up)
+               check_config zone MTU
+               message="Setting the MTU for ${zone} to ${MTU}..."
+               echo "${MTU}" > "/sys/class/net/${zone}/mtu"
+               evaluate_retval standard
+               ;;
+
+       pre-down)
+               check_config zone MTU
+               message="Resetting MTU for ${zone} to 1500..."
+               echo ${DEFAULT_MTU} > "/sys/class/net/${zone}/mtu"
+               evaluate_retval standard
+               ;;
+
+       post-down)
+               ;;
+
+       config)
+               MTU=$1
+               check_config zone MTU
+               cat << EOF >> ${CONFIG_ZONES}/${zone}/${HOOK_NAME}
+HOOK="${HOOK_NAME}"
+MTU="${MTU}"
+EOF
+               exit $?
+               ;;
+       
+       discover)
+               exit ${EXIT_ERROR}
+               ;;
+
+       *)
+               usage
+               exit 1
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/mtu
diff --git a/hooks/pppoe b/hooks/pppoe
new file mode 100755 (executable)
index 0000000..d27a517
--- /dev/null
@@ -0,0 +1,191 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/ipv4-static
+#
+# Description : IPV4 Static Boot Script
+#
+# Authors     : Nathan Coulson - nathan@linuxfromscratch.org
+#               Kevin P. Fleming - kpfleming@linuxfromscratch.org
+#
+# Version     : 00.00
+#
+# Notes       :
+#
+########################################################################
+
+. /lib/network/hook-header
+. /lib/network/functions.ppp
+
+HOOK_NAME="pppoe"
+HOOK_TYPE="zone"
+
+PPPOE_PLUGIN=rp-pppoe.so
+
+case "${action}" in
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=$HOOK_NAME"
+               echo "HOOK_TYPE=$HOOK_TYPE"
+               ;;
+
+       status)
+               echo -e "#  ${CLR_BOLD_CYN}PPPoE: ${NAME}${NORMAL}"
+               echo -n "#    pppd's PID: "
+               pid=$(head -n1 /var/run/ppp-${NAME}.pid 2>/dev/null)
+               if [ -n "${pid}" ] && [ -d "/proc/${pid}" ]; then
+                       echo -e "${CLR_BOLD_GRN}${pid}${NORMAL}"
+                       exit ${EXIT_OK}
+               else
+                       echo -e "${CLR_BOLD_RED}${pid-off}${NORMAL}"
+                       exit ${EXIT_OK}
+               fi
+               ;;
+
+       pre-up)
+               ppp_pre_up
+
+               check_config NAME
+               # Creating necessary files
+               [ -d "${RED_RUN}/${NAME}" ] || mkdir -p ${RED_RUN}/${NAME}
+
+               ppp_secret "${USER}" "${SECRET}"
+
+               cat <<EOF >${RED_RUN}/${NAME}/options
+# Naming options
+name ${NAME}
+linkname ${NAME}
+
+plugin ${PPPOE_PLUGIN} ${zone}
+
+# User configuration
+user ${USER}
+
+$([ "${PEERDNS}" = "1" ] && echo "usepeerdns")
+$([ "${DEFAULTROUTE}" = "1" ] && echo "defaultroute")
+
+noauth
+$([ -n "${AUTH}" ] && echo "require-${AUTH}")
+
+noipdefault
+
+# Maximum transmission/receive unit
+mtu ${MTU}
+mru ${MTU}
+
+# Disable the compression
+noaccomp nodeflate nopcomp novj novjccomp nobsdcomp
+
+debug
+EOF
+               ;;
+
+       post-up)
+               check_config zone NAME
+               MESSAGE="Starting PPP Daemon on interface ${zone}..."
+               if zone_is_forwarding ${zone}; then
+                       pppd file ${RED_RUN}/${NAME}/options >/dev/null
+                       evaluate_retval
+               else
+                       log_failure_msg "Zone ${zone} is not forwaring any traffic..."
+                       exit ${EXIT_ERROR}
+               fi
+
+               ppp_post_up
+               ;;
+
+       pre-down)
+               ppp_pre_down
+
+               MESSAGE="Stopping PPP Daemon on interface ${zone}..."
+               pid=$(head -n1 /var/run/ppp-${NAME}.pid 2>/dev/null)
+               if [ -n "${pid}" ]; then
+                       kill ${pid} &>/dev/null
+                       evaluate_retval
+               fi
+               ;;
+
+       post-down)
+               ppp_post_down
+               ;;
+
+       add)
+               # A pregenerated connection name
+               NAME=$(</proc/sys/kernel/random/uuid)
+               DEFAULTROUTE=1
+               PEERDNS=1
+               MTU=1492
+
+               while [ $# -gt 0 ]; do
+                       case "$1" in
+                               --user=*)
+                                       USER=${1#--user=}
+                                       ;;
+                               --secret=*)
+                                       SECRET=${1#--secret=}
+                                       ;;
+                               --name=*)
+                                       NAME=${1#--name=}
+                                       ;;
+                               --mtu=*)
+                                       MTU=${1#--mtu=}
+                                       ;;
+                               --no-defaultroute)
+                                       DEFAULTROUTE=0
+                                       ;;
+                               --no-dns)
+                                       PEERDNS=0
+                                       ;;
+                               --auth=*)
+                                       AUTH=${1#--auth=}
+                                       ;;
+                               *)
+                                       echo "Unknown option: $1" >&2
+                                       exit 1
+                                       ;;
+                       esac
+                       shift
+               done
+
+               UUID=$(uuid)
+               cat <<EOF >${CONFIG_UUIDS}/${UUID}
+HOOK="${HOOK_NAME}"
+USER="${USER}"
+SECRET="${SECRET}"
+NAME="${NAME}"
+MTU="${MTU}"
+DEFAULTROUTE="${DEFAULTROUTE}"
+PEERDNS="${PEERDNS}"
+AUTH="${AUTH}"
+EOF
+
+               ln -sf ${CONFIG_UUIDS}/${UUID} \
+                       ${CONFIG_ZONES}/${zone}/${HOOK_NAME}-${UUID}
+
+               exit ${EXIT_OK}
+               ;;
+
+       discover)
+               output=$(pppoe-discovery -I ${zone} \
+                       -U $(</proc/sys/kernel/random/uuid) 2>&1)
+               if grep -q "Timeout" <<<${output}; then
+                       echo "${HOOK_NAME}: FAILED"
+                       exit ${EXIT_ERROR}
+               else
+                       echo "${HOOK_NAME}: OK"
+                       echo "${output}" | while read line; do
+                               [ "${line:0:1}" = "A" ] || continue
+                               echo "${HOOK_NAME}: ${line}"
+                       done
+                       exit ${EXIT_OK}
+               fi
+               ;;
+       
+       *)
+               echo "Usage: ${0} {config|pre-up|post-up|pre-down|post-down|status} [interface]"
+               exit ${EXIT_ERROR}
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/ipv4-static
diff --git a/hooks/pppoe.helper b/hooks/pppoe.helper
new file mode 100755 (executable)
index 0000000..693ba3d
--- /dev/null
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+. /lib/network/functions
+. /lib/network/functions.ppp
+
+while [ $# -gt 0 ]; do
+       case "${1}" in
+               --config=*)
+                       . ${1#--config=}
+                       ;;
+               *)
+                       action=${1}
+                       break
+                       ;;
+       esac
+       shift
+done
+
+zone=${DEVICE}
+
+DIR=${RED_RUN}/${LINKNAME}
+
+case "${action}" in
+       ip-up)
+               mkdir -p ${DIR} 2>/dev/null
+
+               echo "${IPREMOTE}" > ${DIR}/remote-ip-address
+               echo "${IPLOCAL}"  > ${DIR}/local-ip-address
+
+               # Update firewall with new IP address(es)
+
+               # Prepare main routing table
+               ip route add ${IPREMOTE}/32 dev ${IFNAME} src ${IPLOCAL}
+
+               # Configure our own routing table
+               ip route add table ${zone} default via ${IPREMOTE} dev ${IFNAME}
+
+               if [ "${DEFAULTROUTE}" = "1" ]; then
+                       ln -sf remote-ip-address ${DIR}/gateway
+                       [ -n "${WEIGHT}" ] && \
+                               echo "${WEIGHT}" > ${DIR}/weight
+
+                       red_defaultroute_update
+               fi
+
+               if [ "${PEERDNS}" = "1" ]; then
+                       echo "${DNS1}" > ${DIR}/dns
+                       if [ -n "${DNS2}" ] && [ "${DNS1}" != "${DNS2}" ]; then
+                               echo "${DNS2}" > ${DIR}/dns
+                       fi
+                       red_dns_update
+               fi
+               ;;
+
+       ip-down)
+               # Flush firewall
+
+               if [ "${DEFAULTROUTE}" = "1" ]; then
+                       :
+               fi
+
+               ip route flush table ${zone}
+
+               if [ "${PEERDNS}" = "1" ]; then
+                       :
+               fi
+
+               # Save statistics
+               ppp_stat "${NAME}" "${CONNECT_TIME}" "${BYTES_RCVD}" "${BYTES_SENT}"
+               ;;
+esac
+
+exit 0
diff --git a/hooks/stp b/hooks/stp
new file mode 100755 (executable)
index 0000000..9e1c465
--- /dev/null
+++ b/hooks/stp
@@ -0,0 +1,97 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/stp
+#
+# Description : Spanning Tree Protocol Script
+#
+# Authors     : Michael Tremer - michael.tremer@ipfire.org
+#
+# Version     : 00.00
+#
+# Notes       : This script adds stp support to a bridge.
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=stp
+HOOK_TYPE=zone
+
+case "${action}" in
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=$HOOK_NAME"
+               echo "HOOK_TYPE=$HOOK_TYPE"
+               ;;
+
+       pre-up)
+               ;;
+
+       post-up)
+               MESSAGE="Enabling Spanning Tree Protocol on zone ${zone}..."
+               brctl stp ${zone} on
+               evaluate_retval
+               ;;
+
+       pre-down)
+               MESSAGE="Disabling Spanning Tree Protocol on zone ${zone}..."
+               brctl stp ${zone} off
+               evaluate_retval
+               ;;
+
+       post-down)
+               ;;
+
+       add)
+               shift 2
+               while [ $# -gt 0 ]; do
+                       case "$1" in
+                               --ageing=*)
+                                       AGEING=${1#--ageing=}
+                                       ;;
+                               --priority=*)
+                                       PRIORITY=${1#--priority=}
+                                       ;;
+                               --delay=*)
+                                       DELAY=${1#--delay=}
+                                       ;;
+                               --hello=*)
+                                       HELLO=${1#--hello=}
+                                       ;;
+                               --maxage=*)
+                                       MAXAGE=${1#--maxage=}
+                                       ;;
+                               *)
+                                       echo "Unknown option: $1" >&2
+                                       exit 1
+                                       ;;
+                       esac
+                       shift
+               done
+               cat <<EOF >${CONFIG_ZONES}/${zone}/${HOOK_NAME}
+HOOK="${HOOK_NAME}"
+AGEING="${AGEING}"
+PRIORITY="${PRIORITY}"
+DELAY="${DELAY}"
+HELLO="${HELLO}"
+MAXAGE="${MAXAGE}"
+EOF
+               exit $?
+               ;;
+
+       rem)
+               ;;
+       
+       discover)
+               exit ${EXIT_ERROR}
+               ;;
+
+       *)
+               echo "Usage: ${0} {pre-up|post-up|pre-down|post-down|config} [interface]"
+               exit 1
+               ;;
+esac
+
+# End $NETWORK_DEVICES/services/stp
diff --git a/hooks/vlan b/hooks/vlan
new file mode 100755 (executable)
index 0000000..e4d99e6
--- /dev/null
@@ -0,0 +1,120 @@
+#!/bin/sh
+########################################################################
+# Begin $NETWORK_DEVICES/services/vlan
+#
+# Description : VLAN Script
+#
+# Authors     : Michael Tremer - michael.tremer@ipfire.org
+#
+# Version     : 00.00
+#
+# Notes       : This script adds vlan support.
+#
+########################################################################
+
+. /lib/network/hook-header
+
+HOOK_NAME=vlan
+HOOK_TYPE=port
+
+function port_name() {
+       echo "${zone}v${ID}"
+}
+
+case "${action}" in
+       help)
+               ;;
+
+       info)
+               echo "HOOK_NAME=${HOOK_NAME}"
+               echo "HOOK_TYPE=${HOOK_TYPE}"
+               ;;
+
+       pre-up)
+               # Load the kernel module
+               grep -q ^8021q /proc/modules || modprobe 8021q
+
+               if ! port_is_up $(port_name); then
+                       MESSAGE="Adding VLAN ${ID} to port ${MAC}..."
+
+                       if ! device_is_up $(devicify ${MAC}); then
+                               ip link set $(devicify ${MAC}) up
+                       fi
+                       vconfig add $(devicify ${MAC}) ${ID} >/dev/null
+                       evaluate_retval
+
+                       device_rename $(get_device_by_mac_and_vid ${MAC} ${ID}) $(port_name)
+                       ip link set $(port_name) up
+
+                       ebtables -t broute -A BROUTING -p 802_1Q --vlan-id=${ID} -j DROP
+               fi
+               ;;
+
+       post-up)
+               if ! zone_has_device_attached ${zone} $(port_name); then
+                       zone_add_port ${zone} $(get_device ${MAC} ${ID})
+               fi
+               ;;
+       
+       pre-down)
+               if zone_has_device_attached ${zone} $(port_name); then
+                       zone_del_port ${zone} $(get_device_by_mac_and_vid ${MAC} ${ID})
+               fi
+               ;;
+               
+       post-down)
+               if port_is_up $(port_name); then
+                       MESSAGE="Removing VLAN ${ID} from port ${MAC}..."
+
+                       vconfig rem $(get_device_by_mac_and_vid ${MAC} ${ID}) >/dev/null
+                       evaluate_retval
+
+                       ebtables -t broute -D BROUTING -p 802_1Q --vlan-id=${ID} -j DROP
+               fi
+               ;;
+
+       add)
+               MAC=$(macify ${1})
+               ID=${2} # Must be integer between 1 and 4096
+
+               UUID=$(uuid)
+               cat <<EOF > ${CONFIG_UUIDS}/${UUID}
+HOOK="${HOOK_NAME}"
+ID="${ID}"
+MAC="${MAC}"
+EOF
+               ln -sf ${CONFIG_UUIDS}/${UUID} \
+                       ${CONFIG_ZONES}/${zone}/${HOOK_NAME}-${UUID}
+
+               log_success_msg "Configuration successfully saved!"
+               echo    "      Device      : $(devicify ${MAC})"
+               echo    "      MAC address : ${MAC}"
+               echo    "      VLAN tag    : ${ID}"
+               ;;
+
+       rem)
+               # XXX to be done
+               ;;
+
+       status)
+               echo -e "#  ${CLR_BOLD_CYN}VLAN port $(port_name)${NORMAL}"
+               echo -n "#    State: "
+               if device_is_up $(port_name); then
+                       echo -e "${CLR_BOLD_GRN}up${NORMAL}"
+                       RET=${EXIT_OK}
+               else
+                       echo -e "${CLR_BOLD_RED}down${NORMAL}"
+                       RET=${EXIT_ERROR}
+               fi
+               echo "#    ID   : ${ID}"
+               echo "#"
+               exit ${RET}
+               ;;
+
+       *)
+               echo "Usage: ${0} [interface] {up|down|add|remove|attach|detach|status}"
+               exit 1
+       ;;
+esac
+
+# End $NETWORK_DEVICES/services/vlan
diff --git a/network b/network
new file mode 100644 (file)
index 0000000..2bcbbe1
--- /dev/null
+++ b/network
@@ -0,0 +1,615 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2009  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/>.       #
+#                                                                             #
+###############################################################################
+
+BOLD="\\033[1;39m"
+NORMAL="\\033[0;39m"
+ERROR="\\033[1;31m"
+
+. /etc/init/functions
+
+if [ -e "/lib/network/functions" ]; then
+       . /lib/network/functions
+elif [ -e "lib/functions" ]; then
+       HOME_DIR="lib"
+       . lib/functions
+else
+       echo "Cannot find functions library. Exiting." >&2
+       exit 1
+fi
+
+function usage() {
+       echo -e "${BOLD}Usage $0${NORMAL}:\n"
+       case "$1" in
+               main|"")
+                       echo    "This script will help you configuring your network."
+                       echo
+                       echo    "You should know that there are three different things:"
+                       echo
+                       echo    "    hook: A script to control connections and protocols."
+                       echo    "    port: A physical connection to somewhere."
+                       echo    "    zone: A group of ports."
+                       echo
+                       echo    "    $0 [global flags] <hook|port|zone> ... or"
+                       echo    "    $0 [global flags] <cmd line options...>"
+                       echo
+                       echo -e "${BOLD}Global flags:${NORMAL}"
+                       echo    "    --verbose -v  - Turn on verbose mode."
+                       echo    "    --debug   -d  - Turn on debug mode."
+                       echo
+                       echo -e "${BOLD}Command line options:${NORMAL}"
+                       echo    "    help          - Prints this help message."
+                       echo    "    start         - Starts the whole network."
+                       echo    "    stop          - Stops the whole network."
+                       echo    "    restart       - Restarts the whole network."
+                       echo    "    reload        - Reloads the whole network."
+                       echo
+                       echo    "    hook - Run \"$0 hook help\" for more information."
+                       echo    "    port - Run \"$0 port help\" for more information."
+                       echo    "    zone - Run \"$0 zone help\" for more information."
+                       echo
+                       ;;
+               hook*)
+                       echo -e "${BOLD}Hook configuration:${NORMAL}"
+                       echo
+                       echo    "    ${0} [global options] hook <command>"
+                       echo
+                       echo -e "${BOLD}1st level commands:${NORMAL}"
+                       echo -e "    ${BOLD}list:${NORMAL}"
+                       echo    "        Returns a list of all available hooks."
+                       echo
+                       echo
+                       echo    "    ${0} [global options] hook <hook> <command>"
+                       echo
+                       echo -e "${BOLD}2nd level commands:${NORMAL}"
+                       echo -e "    ${BOLD}help:${NORMAL}"
+                       echo    "        Displays some help about the given hook."
+                       echo
+                       echo    "        Example: $0 hook ethernet help"
+                       echo
+                       ;;
+               port)
+                       echo -e "${BOLD}Port Configuration:${NORMAL}"
+                       echo
+                       echo    "    $0 [global options] port <command> ..."
+                       echo
+                       echo -e "${BOLD}Commands:${NORMAL}"
+                       echo -e "    ${BOLD}show:${NORMAL}"
+                       echo    "        Displays information about a given port."
+                       echo
+                       echo    "        Requires a \"port\"."
+                       echo    "        Example: $0 port show 00:11:22:33:44:55"
+                       echo    "                 $0 port show port0"
+                       echo
+                       ;;
+               zone)
+                       echo -e "${BOLD}Zone Configuration:${NORMAL}"
+                       echo
+                       echo    "    $0 [global options] zone <command> ..."
+                       echo
+                       echo -e "${BOLD}Commands:${NORMAL}"
+                       echo -e "    ${BOLD}show:${NORMAL}"
+                       echo    "        Displays information about a given zone."
+                       echo
+                       echo    "        Requires a \"zone\"."
+                       echo    "        Example: $0 zone show green0"
+                       echo
+                       echo -e "    ${BOLD}add:${NORMAL}"
+                       echo    "        Adds a new zone."
+                       echo
+                       echo    "        Requires a \"zone\"."
+                       echo    "        Example: $0 zone add green0"
+                       echo
+                       echo -e "    ${BOLD}del:${NORMAL}"
+                       echo    "        Deletes a zone."
+                       echo
+                       echo    "        Requires a \"zone\"."
+                       echo    "        Example: $0 zone del green0"
+                       echo
+                       echo -e "    ${BOLD}addport:${NORMAL}"
+                       echo    "        Adds a port to a zone."
+                       echo
+                       echo    "        Requires a \"zone\" and \"port\"."
+                       echo    "        Example: $0 zone addport green0 port0"
+                       echo
+                       echo    "        You may also pass a hook and its parameters:"
+                       echo    "            $0 zone addport green0 port0 vlan 10"
+                       echo
+                       echo -e "    ${BOLD}delport:${NORMAL}"
+                       echo    "        Deletes a port from a zone."
+                       echo
+                       echo    "        Requires a \"zone\" and \"port\"."
+                       echo    "        Example: $0 zone delport green0"
+                       echo
+                       echo    "        You may also pass a hook and its parameters:"
+                       echo    "            $0 zone delport green0 port0 vlan 10"
+                       echo
+       esac
+       _exit ${2-1}
+}
+
+function debug() {
+       if [ -n "$1" ]; then
+               DEBUG=$1
+               verbose $1
+               return
+       else
+               if [ "$DEBUG" = "1" ]; then
+                       return 0
+               else
+                       return 1
+               fi
+       fi
+}
+
+function verbose() {
+       if [ -n "$1" ]; then
+               VERBOSE=$1
+               return
+       else
+               if [ "$VERBOSE" = "1" ]; then
+                       return 0
+               else
+                       return 1
+               fi
+       fi
+}
+
+function decho() {
+       debug && echo -e "${ERROR}$@${NORMAL}" >&2
+}
+
+function vecho() {
+       verbose && echo -e "$@" >&2
+}
+
+function error() {
+       echo -e "${ERROR}ERROR${NORMAL}: $@" >&2
+       _exit 1
+}
+
+function _exit() {
+       local code
+       local reload
+
+       while [ $# -gt 0 ]; do
+               case "$1" in
+                       --reload)
+                               reload=1
+                               ;;
+                       [0-9]*)
+                               code=$1
+                               ;;
+                       *)
+                               error "Unrecognized argument: $1"
+                               ;;
+               esac
+               shift
+       done
+
+       if [ "${reload}" = "1" ]; then
+               # Reloading network to apply changes immediately
+               vecho "Reloading network settings..."
+               cmd $0 reload
+               
+               # Reload firewall, too
+               firewall=$(which firewall 2>/dev/null)
+               if [ -n "${firewall}" ]; then
+                       vecho "Reloading firewall..."
+                       cmd ${firewall} reload
+               fi
+       fi
+
+       decho "Exiting with code ${code}."
+       exit ${code}
+}
+
+function cmd() {
+       decho "Running command: $@"
+       if debug; then
+               DEBUG=${DEBUG} VERBOSE=${VERBOSE} $@
+       else
+               DEBUG=${DEBUG} VERBOSE=${VERBOSE} $@ >/dev/null
+       fi
+}
+
+function size() {
+       local size=${1}
+
+       local units
+       units[0]="Bytes "
+       units[1]="kBytes"
+       units[2]="MBytes"
+       units[3]="GBytes"
+       units[4]="TBytes"
+       
+       local count=${#units}
+       while [ ${count} -gt 0 ]; do
+               if [ ${size} -lt 1024 ]; then
+                       break
+               fi
+               size=$((${size} / 1024))
+               count=$((${count} - 1))
+       done
+       printf "%4d %s\n" "${size}" "${units[$((${#units} - ${count}))]}"
+}
+
+function port_show() {
+       local port
+       if [ $# -eq 0 ]; then
+               for port in /sys/class/net/*; do
+                       port=${port##*/}
+                       device_is_real ${port} || continue
+                       port_show ${port}
+               done
+               return
+       fi
+
+       port=$(devicify $1)
+
+       echo    "##################################################"
+       echo    "#"
+       echo -e "# Port ${CLR_BOLD_BLU}${port}${NORMAL}"
+       echo    "# ------------------------------------------------"
+
+       echo -n "# State: "
+       if device_is_up ${port}; then
+               echo -e "${CLR_BOLD_GRN}up${NORMAL}"
+       else
+               echo -e "${CLR_BOLD_RED}down${NORMAL}"
+       fi
+
+       echo -n "# Link : "
+       if device_has_carrier ${port}; then
+               echo -e "${CLR_BOLD_GRN}yes${NORMAL}"
+       else
+               echo -e "${CLR_BOLD_RED}no${NORMAL}"
+       fi
+
+       if device_is_up ${port}; then
+               echo "#"
+               echo "# Statistics:"
+               echo -n "#   RX: $(size $(</sys/class/net/${port}/statistics/rx_bytes))"
+               echo    " ($(</sys/class/net/${port}/statistics/rx_packets) packets)"
+               echo -n "#   TX: $(size $(</sys/class/net/${port}/statistics/tx_bytes))"
+               echo    " ($(</sys/class/net/${port}/statistics/tx_packets) packets)"
+       fi
+
+       echo "#"
+}
+
+function port_raw() {
+       local port
+       if [ $# -eq 0 ]; then
+               for port in /sys/class/net/*; do
+                       port=${port##*/}
+                       device_is_real ${port} || continue
+                       port_raw ${port}
+               done
+               return
+       fi
+
+       port=$(devicify $1)
+
+       cat <<EOF
+[${port}]
+type=$(device_type ${port})
+mac=$(macify ${port})
+carrier=$(device_has_carrier ${port} && echo "1" || echo "0")
+up=$(device_is_up ${port} && echo "1" || echo "0")
+
+EOF
+}
+
+function port_add() {
+       local zone=${1}
+       local hook=${2}
+       shift 2
+
+       if ! zone_exists ${zone}; then
+               error "Zone ${BOLD}${zone}${NORMAL} does not exist."
+               return 1
+       fi
+
+       mkdir -p ${CONFIG_PORTS}/${port} 2>/dev/null
+       if hook_exists ${hook}; then
+               /lib/network/hooks/${hook} --zone=${zone} add $@
+               RET=$?
+               if [ "$RET" -eq "0" ]; then
+                       vecho "Successfully added port to ${BOLD}${zone}${NORMAL}."
+               else
+                       error "Hook ${BOLD}${hook}${NORMAL} exited with $RET."
+                       return $RET
+               fi
+       else
+               error "Hook ${BOLD}${hook}${NORMAL} does not exist or is not executeable."
+               return 1
+       fi
+}
+
+function port_del() {
+       local config
+       local hook
+       local uuid
+
+       local zone=${1}
+       shift
+
+       if is_uuid ${1}; then
+               uuid=${1}
+               config="${CONFIG_UUIDS}/${uuid}"
+
+               if [ -e "${config}" ]; then
+                       hook=$(config_get_hook ${config})
+               else
+                       error "Given config file does not exist: ${config}."
+                       return 1
+               fi
+       fi
+
+       hook_run --config=${config} pre-down
+       hook_run --config=${config} post-down
+       hook_run --config=${config} rem
+}
+
+function zone_discover() {
+       local zone=${1}
+
+       for hook in $(hook_list zone); do
+               hook_run ${hook} --zone=${zone} discover
+       done
+}
+
+function zone_show() {
+       local zone
+       zone=$1
+
+       if [ -z "$zone" ]; then
+               for zone in ${CONFIG_ZONES}/*; do
+                       zone_show $(basename $zone)
+               done
+               return
+       fi
+
+       if ! zone_exists ${zone}; then
+               error "Zone ${BOLD}${zone}${NORMAL} does not exist."
+               return 2
+       fi
+
+       echo    "##################################################"
+       echo    "#"
+       echo -e "# Zone ${CLR_BOLD_BLU}${zone}${NORMAL}"
+       echo    "# ------------------------------------------------"
+
+       # Up or down?
+       if zone_is_up ${zone}; then
+               echo -e "# Status: ${CLR_BOLD_GRN}up${NORMAL}"
+       else
+               echo -e "# Status: ${CLR_BOLD_RED}down${NORMAL}"
+       fi
+       echo "#"
+
+       # Ports
+       echo -e "# ${CLR_BOLD_BLU}Ports:${NORMAL}"
+       hooks_run_ports status ${CONFIG_ZONES}/${zone} --zone=${zone}
+       
+       echo    "#"
+       echo -e "# ${CLR_BOLD_BLU}Zone configurations:${NORMAL}"
+       hooks_run_zones status ${CONFIG_ZONES}/${zone} --zone=${zone}
+       echo    "#"
+
+}
+
+function zone_raw() {
+       local zone
+       if [ $# -eq 0 ]; then
+               for zone in $(zone_list); do
+                       zone_raw ${zone##*/}
+               done
+               return
+       fi
+
+       zone=${1}
+
+cat <<EOF
+[${zone}]
+up=$(zone_is_up ${zone} && echo "1" || echo "0")
+
+EOF
+}
+
+function zone_add() {
+       local zone=$1
+
+       if zone_exists ${zone}; then
+               error "Zone ${BOLD}${zone}${NORMAL} already exists."
+               return 1
+       fi
+       
+       if ! zone_valid_name ${zone}; then
+               error "The given zone name is not valid."
+               return 1
+       fi
+
+       mkdir -p ${CONFIG_ZONES}/${zone}
+       vecho "Successfully added zone ${BOLD}${zone}${NORMAL}."
+}
+
+function zone_del() {
+       local zone=$1
+
+       if ! zone_exists ${zone}; then
+               error "Zone ${BOLD}${zone}${NORMAL} does not exist."
+               return 1
+       fi
+
+       cmd /lib/network/zone --zone=${zone} down
+       rm -rf ${CONFIG_ZONES}/${zone}
+       vecho "Successfully removed zone ${BOLD}${zone}${NORMAL}."
+}
+
+# See what to do
+while [ "$#" -gt 0 ]; do
+       arg=$1
+       shift
+
+       case "$arg" in
+               --debug|-d)
+                       debug 1
+                       decho "Debug mode enabled."
+                       ;;
+               --verbose|-v)
+                       verbose 1
+                       vecho "${BOLD}Verbose mode enabled.${NORMAL}"
+                       ;;
+               help|-h|--help)
+                       usage main 0
+                       ;;
+               start|stop|reload)
+                       action=${arg}
+                       for zone in $(zone_list); do
+                               zone=${zone##*/}
+                               decho "Running command: ${HOME_DIR}/zone --zone=${zone} ${action}"
+                               DEBUG=${DEBUG} VERBOSE=${VERBOSE} ${HOME_DIR}/zone --zone=${zone} ${action}
+                       done
+                       _exit $?
+                       ;;
+               restart)
+                       DEBUG=${DEBUG} VERBOSE=${VERBOSE} $0 stop $@
+                       sleep 1
+                       DEBUG=${DEBUG} VERBOSE=${VERBOSE} $0 start $@
+                       _exit $?
+                       ;;
+               hook|hooks)
+                       case "$1" in
+                               list)
+                                       hook_list
+                                       _exit $?
+                                       ;;
+                               *)
+                                       if hook_exists ${1}; then
+                                               hook=${1}
+                                       else
+                                               usage hook
+                                       fi
+                       esac
+                       shift
+                       case "$1" in
+                               help|info)
+                                       if hook_exists ${hook}; then
+                                               hook_run ${hook} ${1}
+                                               _exit $?
+                                       else
+                                               error "Hook ${hook} does not exist or is not executeable."
+                                               _exit 1
+                                       fi
+                                       ;;
+                               *)
+                                       usage hook
+                                       ;;
+                       esac
+                       ;;
+               p*)
+                       arg=$1
+                       shift
+                       case "$arg" in
+                               help)
+                                       usage port 0
+                                       ;;
+                               show)
+                                       port_show $@
+                                       _exit $?
+                                       ;;
+                               _raw)
+                                       port_raw $@
+                                       _exit $?
+                                       ;;
+                       esac
+                       ;;
+               z*)
+                       arg=$1
+                       shift
+                       case "$arg" in
+                               add)
+                                       zone_add $@
+                                       _exit --reload $?
+                                       ;;
+                               addport)
+                                       port_add $@
+                                       _exit --reload $?
+                                       ;;
+                               config)
+                                       zone=$1; hook=$2; shift 2
+                                       if [ -z "${zone}" ] || [ -z "${hook}" ]; then
+                                               usage config
+                                       fi
+                                       hook_run ${hook} --zone=${zone} add $@
+                                       _exit --reload $?
+                                       ;;
+                               del)
+                                       zone_del $@
+                                       _exit --reload $?
+                                       ;;
+                               delport)
+                                       port_del $@
+                                       _exit --reload $?
+                                       ;;
+                               discover)
+                                       zone_discover $@
+                                       _exit $?
+                                       ;;
+                               help)
+                                       usage zone 0
+                                       ;;
+                               list)
+                                       zone_list
+                                       _exit $?
+                                       ;;
+                               show)
+                                       zone_show $@
+                                       _exit $?
+                                       ;;
+                               start|stop)
+                                       zone=$1; shift
+                                       zone_run --zone=${zone} ${arg} $@
+                                       ;;
+                               _raw)
+                                       zone_raw $@
+                                       _exit $?
+                                       ;;
+                       esac
+                       ;;
+               show)
+                       arg=${1}
+                       shift
+                       case "${arg}" in
+                               ports)
+                                       port_show $@
+                                       _exit 0
+                                       ;;
+                       esac
+                       ;;
+               -*)
+                       error "Option \"$arg\" is not known."
+                       ;;
+       esac
+done
+
+usage main
diff --git a/ppp/ip-updown b/ppp/ip-updown
new file mode 100644 (file)
index 0000000..24f60d3
--- /dev/null
@@ -0,0 +1,41 @@
+#!/bin/sh
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2007  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/>.       #
+#                                                                             #
+###############################################################################
+
+umask 022
+export PATH=/usr/sbin:/sbin:/usr/bin:/bin
+
+. /lib/network/functions
+. /lib/network/functions.ppp
+
+for config in ${CONFIG_ZONES}/${DEVICE}/*; do
+       if [ "$(ppp_linkname_get ${config})" = "${LINKNAME}" ]; then
+               CONFIG=${config}
+               . ${CONFIG}
+               break
+       fi
+done
+
+if [ -n "${HOOK}" ] && [ -x "${HOOKS_DIR}/${HOOK}.helper" ]; then
+       exec ${HOOKS_DIR}/${HOOK}.helper --config=${CONFIG} \
+               $(basename $0) $@
+fi
+
+exit ${EXIT_ERROR}
diff --git a/zone b/zone
new file mode 100755 (executable)
index 0000000..0f5b355
--- /dev/null
+++ b/zone
@@ -0,0 +1,93 @@
+#!/bin/bash
+###############################################################################
+#                                                                             #
+# IPFire.org - A linux based firewall                                         #
+# Copyright (C) 2009  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/>.       #
+#                                                                             #
+###############################################################################
+
+. /etc/init/functions
+. /lib/network/functions
+
+while [ "$#" -gt "0" ]; do
+       case "${1}" in
+               --zone=*)
+                       zone=${1#--zone=}
+                       ;;
+               *)
+                       action=${1}
+                       break
+                       ;;              
+       esac
+       shift
+done
+
+if [ -z "${zone}" ] || [ -z "${action}" ]; then
+       log_failure_msg "Wrong number of arguments."
+       exit ${EXIT_ERROR}
+fi
+
+if ! zone_exists ${zone}; then
+       echo "Zone ${zone} does not exist."
+       exit ${EXIT_ERROR}
+fi
+
+case "$action" in
+       start|up|reload)
+               message="Bringing up zone ${zone}..."
+
+               hooks_run_all pre-up ${CONFIG_ZONES}/${zone} --zone=${zone}
+
+               if ! zone_is_up ${zone}; then   
+                       # Create and bring up the zone
+                       brctl addbr ${zone} || failed=1
+                       brctl stp ${zone} on || failed=1
+                       brctl setfd ${zone} 0 || failed=1
+                       ip link set ${zone} up || failed=1
+                       (exit ${failed})
+                       evaluate_retval standard
+               fi
+
+               # First bring up the ports to be able to start something like
+               # a dhcp client that needs a running interface.
+               hooks_run_ports post-up ${CONFIG_ZONES}/${zone} --zone=${zone}
+               hooks_run_zones post-up ${CONFIG_ZONES}/${zone} --zone=${zone}
+               ;;
+
+       stop|down)
+               message="Bringing down zone ${zone}..."
+
+               if zone_is_up ${zone}; then
+                       hooks_run_zones pre-down ${CONFIG_ZONES}/${zone} --zone=${zone}
+                       hooks_run_ports pre-down ${CONFIG_ZONES}/${zone} --zone=${zone}
+
+                       # Bring down the zone and delete it
+                       ip link set ${zone} down || failed=1
+                       brctl delbr ${zone} || failed=1
+                       (exit ${failed})
+                       evaluate_retval standard
+
+                       hooks_run_all post-down ${CONFIG_ZONES}/${zone} --zone=${zone}
+               else
+                       log_warning_msg ${message}
+                       log_warning_msg "Zone ${zone} does not exist."
+               fi
+               ;;
+
+       *)
+               exit 1
+               ;;      
+esac