From 5b20e43af8179bd81ac8f779de64e785bb476865 Mon Sep 17 00:00:00 2001 From: Michael Tremer Date: Sun, 7 Feb 2010 16:37:55 +0100 Subject: [PATCH] network: New package. --- functions | 676 ++++++++++++++++++++++++++++++++++++++++ functions.ppp | 110 +++++++ hook-header | 38 +++ hooks/README | 86 +++++ hooks/bonding | 177 +++++++++++ hooks/ethernet | 137 ++++++++ hooks/ipv4-dhcp | 84 +++++ hooks/ipv4-static | 169 ++++++++++ hooks/ipv4-static-route | 141 +++++++++ hooks/mtu | 85 +++++ hooks/pppoe | 191 ++++++++++++ hooks/pppoe.helper | 73 +++++ hooks/stp | 97 ++++++ hooks/vlan | 120 +++++++ network | 615 ++++++++++++++++++++++++++++++++++++ ppp/ip-updown | 41 +++ zone | 93 ++++++ 17 files changed, 2933 insertions(+) create mode 100644 functions create mode 100644 functions.ppp create mode 100644 hook-header create mode 100644 hooks/README create mode 100755 hooks/bonding create mode 100755 hooks/ethernet create mode 100755 hooks/ipv4-dhcp create mode 100755 hooks/ipv4-static create mode 100755 hooks/ipv4-static-route create mode 100755 hooks/mtu create mode 100755 hooks/pppoe create mode 100755 hooks/pppoe.helper create mode 100755 hooks/stp create mode 100755 hooks/vlan create mode 100644 network create mode 100644 ppp/ip-updown create mode 100755 zone diff --git a/functions b/functions new file mode 100644 index 00000000..773463a8 --- /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 . # +# # +############################################################################### + +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}) + [ "$(/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} <. # +# # +############################################################################### + +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} < [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 index 00000000..03f0a70b --- /dev/null +++ b/hooks/bonding @@ -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 < ${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 $(" + #echo " Includes a config file." + #echo " Example: --config=/etc/sysconfig/network/green0/port-00:11:22:33:44:55" + #echo " --port=" + #echo " Passes the port to the script." + #echo " Example: --port=port0 or --port=00:11:22:33:44:55" + #echo " --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 < ${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 index 00000000..43c44199 --- /dev/null +++ b/hooks/ipv4-dhcp @@ -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 <${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 index 00000000..34af5572 --- /dev/null +++ b/hooks/ipv4-static @@ -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 <${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 index 00000000..9e389864 --- /dev/null +++ b/hooks/ipv4-static-route @@ -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 <${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 index 00000000..707345a6 --- /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 index 00000000..d27a5177 --- /dev/null +++ b/hooks/pppoe @@ -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 <${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=$(&2 + exit 1 + ;; + esac + shift + done + + UUID=$(uuid) + cat <${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 $(&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 index 00000000..693ba3de --- /dev/null +++ b/hooks/pppoe.helper @@ -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 index 00000000..9e1c465e --- /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 <${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 index 00000000..e4d99e64 --- /dev/null +++ b/hooks/vlan @@ -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 < ${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 index 00000000..2bcbbe1c --- /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 . # +# # +############################################################################### + +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] ... or" + echo " $0 [global flags] " + 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 " + 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 " + 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 ..." + 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 ..." + 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 $(/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 <. # +# # +############################################################################### + +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 index 00000000..0f5b355d --- /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 . # +# # +############################################################################### + +. /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 -- 2.39.2