From: Michael Tremer Date: Thu, 3 Jun 2010 14:53:02 +0000 (+0200) Subject: network: Update codebase. X-Git-Tag: 001~111 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1848564d3b83c8d55ef908c3c8dde2d12d9e491c;p=people%2Fms%2Fnetwork.git network: Update codebase. --- diff --git a/functions b/functions index f4a7fa1c..5c5372d9 100644 --- a/functions +++ b/functions @@ -1,678 +1,8 @@ -#!/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 . # -# # -############################################################################### +#!/bin/bash -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}" +for file in /lib/network/functions.*; do + . ${file} done -COMMON_DEVICE=port+ - -EXIT_OK=0 -EXIT_ERROR=1 -EXIT_CONF_ERROR=2 - -VALID_ZONES="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 - [ -x "${hook}" ] || continue - - 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} <. # +# # +############################################################################### + +function cli_config() { + if [ -n "${1}" ]; then + network_config_set $@ + else + network_config_print + fi +} + +function cli_device() { + local action=${1} + shift + + local device + local devices=$@ + + if [ -z "${devices}" ]; then + devices=$(devices_get_all) + fi + + case "${action}" in + discover) + echo "# XXX need to implement --raw here" + for device in ${devices}; do + cli_device_discover ${device} $@ + done + ;; + + show|"") + for device in ${devices}; do + cli_device_print ${device} + done + ;; + *) + cli_usage device + ;; + esac +} + +function cli_device_print() { + local device=${1} + + if ! device_exists ${device}; then + error "Device '${device}' does not exist." + return ${EXIT_ERROR} + fi + + echo "${device}" + echo " Type: $(device_get_type ${device})" + echo " Addr: $(device_get_address ${device})" + echo +} + +function cli_device_discover() { + local device=${1} + shift + + local device_type=$(device_get_type ${device}) + if [ "${device_type}" != "real" ]; then + return ${EXIT_OK} + fi + + local raw + + while [ $# -gt 0 ]; do + case "${1}" in + --raw) + raw=1 + ;; + esac + shift + done + + local up + device_is_up ${device} && up=1 + device_set_up ${device} + + enabled raw || echo "${device}" + + local hook + local out + local ret + for hook in $(hooks_get_all); do + out=$(hook_exec ${hook} discover ${device}) + ret=$? + + [ ${ret} -eq ${DISCOVER_NOT_SUPPORTED} ] && continue + + if enabled raw; then + case "${ret}" in + ${DISCOVER_OK}) + echo "${hook}: OK" + local line + while read line; do + echo "${hook}: ${line}" + done <<<"${out}" + ;; + + ${DISCOVER_ERROR}) + echo "${hook}: FAILED" + ;; + esac + else + case "${ret}" in + ${DISCOVER_OK}) + echo " ${hook} was successful." + local line + while read line; do + echo " ${line}" + done <<<"${out}" + ;; + + ${DISCOVER_ERROR}) + echo " ${hook} failed." + ;; + esac + fi + done + + echo # New line + + [ "${up}" = "1" ] || device_set_down ${device} +} + +function cli_zone() { + local action + local zone + + if zone_name_is_valid ${1}; then + zone=${1} + action=${2} + shift 2 + + case "${action}" in + config|down|edit|port|show|status|up) + zone_${action} ${zone} $@ + ;; + esac + else + action=${1} + shift + + case "${action}" in + create|remove) + zone_${action} $@ + ;; + *) + error "Unrecognized argument: '${action}'" + ;; + esac + fi +} + +function cli_start() { + local zones=$(zones_get $@) + + local zone + for zone in ${zones}; do + zone_up ${zone} + done +} + +function cli_stop() { + local zones=$(zones_get $@) + + local zone + for zone in ${zones}; do + zone_down ${zone} + done +} + +function cli_usage() { + local what=${1} + + case "${what}" in + root) + echo "${0}: [command] " + echo + echo " start - ..." + echo " stop - ..." + echo + echo " config - ..." + echo + echo " device - ..." + echo " show - ???" + echo " zone - ..." + echo + ;; + usage) + echo + echo " Run '${0} help' to get information how to use this tool." + echo + ;; + *) + error "No help available for this command '${what}'." + ;; + esac +} diff --git a/functions.colors b/functions.colors new file mode 100644 index 00000000..19685bb5 --- /dev/null +++ b/functions.colors @@ -0,0 +1,28 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +# Define color for messages +BOLD="\\033[1;39m" +DONE="\\033[1;32m" +SKIP="\\033[1;34m" +WARN="\\033[1;35m" +FAIL="\\033[1;31m" +NORMAL="\\033[0;39m" diff --git a/functions.constants b/functions.constants new file mode 100644 index 00000000..7521e6e8 --- /dev/null +++ b/functions.constants @@ -0,0 +1,52 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +# Enable colors by default +COLORS=1 + +BASE_DIR=/lib/network +CONFIG_DIR=/etc/network +HOOKS_DIR=${BASE_DIR}/hooks +RUN_DIR=/var/run/network +ZONE_DIR=${CONFIG_DIR} + +RED_RUN=/var/run/network/red +PPP_SECRETS=/etc/ppp/secrets + +CONFIG_FILE=${CONFIG_DIR}/network_config +CONFIG_FILE_PARAMS="COLORS DEBUG SHELL" + +# Proper error codes +EXIT_OK=0 +EXIT_ERROR=1 +EXIT_CONF_ERROR=2 + +STATUS_UP=0 +STATUS_DOWN=1 + +DISCOVER_OK=0 +DISCOVER_ERROR=1 +DISCOVER_NOT_SUPPORTED=2 + +# The user is able to create zones that begin with these names +VALID_ZONES="green orange red grey" + +SYS_CLASS_NET="/sys/class/net" diff --git a/functions.device b/functions.device new file mode 100644 index 00000000..2063a83c --- /dev/null +++ b/functions.device @@ -0,0 +1,536 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +function devicify() { + local device=${1} + + if device_exists ${device}; then + echo "${device}" + return ${EXIT_OK} + fi + + local d + for d in $(devices_get_all); do + if [ "$(device_get_address ${d})" = "${device}" ]; then + echo "${d}" + return ${EXIT_OK} + fi + done + + return ${EXIT_ERROR} +} + +function macify() { + local device=${1} + + if mac_is_valid ${device}; then + echo "${device}" + return ${EXIT_OK} + fi + + if device_exists ${device}; then + device_get_address ${device} + return ${EXIT_OK} + fi + + return ${EXIT_ERROR} +} + +# Check if the device exists +function device_exists() { + local device=${1} + + # If device name was not found, exit. + [ -n "${device}" ] || return ${EXIT_ERROR} + + [ -d "${SYS_CLASS_NET}/${device}" ] +} + +# Check if the device is up +function device_is_up() { + local device=${1} + + device_exists ${device} || return ${EXIT_ERROR} + + ip link show ${device} 2>/dev/null | grep -qE "<.*UP.*>" +} + +# Check if the device is a bonding device +function device_is_bonding() { + [ -d "/sys/class/net/${1}/bonding" ] +} + +# Check if the device bonded in a bonding device +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 +} + +# Check if the device is a bridge +function device_is_bridge() { + [ -d "/sys/class/net/${1}/bridge" ] +} + +# Check if the device is a virtual device +function device_is_virtual() { + local device=${1} + + [ -e "/proc/net/vlan/${device}" ] +} + +# Check if the device has virtual devices +function device_has_virtuals() { + if [ ! -e "/proc/net/vlan/config" ]; then + return 1 + fi + grep -q "${1}$" /proc/net/vlan/config +} + +function device_is_vlan() { # XXX Compat function + log DEBUG "Deprecated function device_is_vlan() was used." + + device_is_virtual $@ +} + +# Check if the device is a ppp device +function device_is_ppp() { + local device=${1} + + ip link show ${device} 2>/dev/null | grep -qE "<.*POINTOPOINT.*>" +} + +# Check if the device is a loopback device +function device_is_loopback() { + local device=$(devicify ${1}) + [ "${device}" = "lo" ] +} + +# Check if the device is a physical network interface +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_virtual ${device} && \ + return ${EXIT_ERROR} + + return ${EXIT_OK} +} + +# Get the device type +function device_get_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_get_address() { + local device=${1} + + cat ${SYS_CLASS_NET}/${device}/address 2>/dev/null +} + +function device_set_address() { + device_set_mac $@ +} + +function devices_get_all() { + local device + for device in ${SYS_CLASS_NET}/*; do + echo "$(basename ${device})" + done | sort +} + +# Check if a device has a cable plugged in +function device_has_carrier() { + local device=$(devicify ${1}) + [ "$(<${SYS_CLASS_NET}/${device}/carrier)" = "1" ] +} + +# Check if the device is free +function device_is_free() { + local device=${1} + + device_is_used ${device} && \ + return ${EXIT_ERROR} + + return ${EXIT_OK} +} + +# Check if the device is used +function device_is_used() { + local device=$(devicify ${1}) + + device_has_vlans ${device} && \ + return ${EXIT_ERROR} + device_is_bonded ${device} && \ + return ${EXIT_ERROR} + + return ${EXIT_OK} +} + +# XXX to be removed I think +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}" +} + +# Should be renamed to device_set_name at some time +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 device_hash() { + local device=${1} + + macify ${device} | tr -d ':' +} + +# Give the device a new name +function device_set_name() { + device_rename $@ +} + +# Set device up +function device_set_up() { + local device=$(devicify ${1}) + + # Do nothing if device is already up + device_is_up ${device} && return ${EXIT_OK} + + log DEBUG "Setting up device $@" + ip link set ${device} up +} + +# Set device down +function device_set_down() { + local device=$(devicify ${1}) + + # Do nothing if device is not up + device_is_up ${device} || return ${EXIT_OK} + + log DEBUG "Tearing down device $@" + ip link set ${device} down +} + +# Set new address to a device +function device_set_mac() { + local port=${1} + local mac=${2} + + local up + if device_is_up ${port}; then + device_set_down ${port} + up=1 + fi + + ip link set ${port} address ${mac} + local ret=$? + + if [ "${up}" = "1" ]; then + device_set_up ${port} + fi + + return ${ret} +} + +function device_get_mtu() { + local device=${1} + + if ! device_exists ${device}; then + error "Device '${device}' does not exist." + return ${EXIT_ERROR} + fi + + cat ${SYS_CLASS_NET}/${device}/mtu +} + +# Set mtu to a device +function device_set_mtu() { + local port=${1} + local mtu=${2} + + local up + if device_is_up ${port}; then + device_set_down ${port} + up=1 + fi + + ip link set ${port} mtu ${mtu} + local ret=$? + + if [ "${up}" = "1" ]; then + device_set_up ${port} + fi + + return ${ret} +} + +function device_discover() { + local device=${1} + + local hook + for hook in $(hooks_get_all); do + hook_exec ${hook} discover ${device} + done +} + +function device_create_virtual() { + log WARN "Called deprecated function device_create_virtual" + device_virtual_create $@ +} + +function device_virtual_create() { + local port=$(devicify ${1}) + local vid=${2} + local mac=${3} + local newport=${port}v${vid} + + if [ -z "${mac}" ]; then + mac=$(mac_generate) + fi + + # Bring up the parent device + # XXX Do we need this here? + #device_set_up ${port} + + vconfig set_name_type DEV_PLUS_VID_NO_PAD >/dev/null + vconfig add ${port} ${vid} >/dev/null + [ $? -ne 0 ] && return ${EXIT_ERROR} + + # The device is expected to be named like ${port}.${vid} + # and will be renamed to the virtual schema + device_set_name ${port}.${vid} ${newport} + + # Setting new mac address + device_set_address ${newport} ${mac} + + # Bring up the new device + device_set_up ${newport} + + log DEBUG "Created virtual device ${newport} (${mac})" + return ${EXIT_OK} +} + +function device_virtual_remove() { + local device=$(devicify ${1}) + + device_set_down ${device} + + vconfig rem ${device} >/dev/null + [ $? -ne 0 ] && return ${EXIT_ERROR} + + log DEBUG "Removed virtual device ${device}" + return ${EXIT_OK} +} + +function device_bonding_create() { + local device=${1} + local mac=${2} + + [ -z "${mac}" ] && mac=$(mac_generate) + + echo "+${device}" > /sys/class/net/bonding_masters + device_set_mac ${mac} + device_set_up ${device} +} + +function device_bonding_remove() { + local device=$(devicify ${1}) + + device_set_down ${device} + echo "-${device}" > /sys/class/net/bonding_masters +} + +function bonding_set_mode() { + local device=${1} + local mode=${2} + + echo "${mode}" > /sys/class/net/${device}/bonding/mode +} + +function bonding_enslave_device() { + local device=$(devicify ${1}) + local slave=$(devicify ${2}) + + device_set_down ${slave} + echo "+${slave}" > /sys/class/net/${device}/bonding/slaves +} + +function bridge_attach_device() { + local bridge=${1} + local device=${2} + + if ! device_exists ${bridge}; then + error "Bridge '${bridge}' does not exist." + return ${EXIT_ERROR} + fi + + if ! device_exists ${device}; then + error "Device '${device}' does not exist." + return ${EXIT_ERROR} + fi + + # XXX device_set_up ${device} # Do we need this here? + + brctl addif ${bridge} ${device} +} + +function bridge_detach_device() { + local bridge=${1} + local device=${2} + + if ! device_exists ${bridge}; then + error "Bridge '${bridge}' does not exist." + return ${EXIT_ERROR} + fi + + if ! device_exists ${device}; then + error "Device '${device}' does not exist." + return ${EXIT_ERROR} + fi + + brctl delif ${zone} ${device} + + device_set_down ${device} +} + +function bridge_is_forwarding() { + local seconds=45 + local zone=${1} + + bridge_has_carrier ${zone} || return ${EXIT_ERROR} + + 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_has_carrier() { + local zone=${1} + + local has_carrier=${EXIT_ERROR} + + local device + for device in ${SYS_CLASS_NET}/${zone}/brif/*; do + device=$(basename ${device}) + device_exists ${device} || continue + + device_has_carrier ${device} && has_carrier=${EXIT_OK} + done + + return ${has_carrier} +} + +function device_has_ipv4() { + local device=${1} + local addr=${2} + + if ! device_exists ${device}; then + error "Device '${device}' does not exist." + return ${EXIT_ERROR} + fi + + ip addr show ${device} | grep -q -e "inet " -e "${addr}" +} diff --git a/functions.events b/functions.events new file mode 100644 index 00000000..1dd98a53 --- /dev/null +++ b/functions.events @@ -0,0 +1,28 @@ +#!/bin/bash + +function event_emit() { + local event=${1} + shift + + log DEBUG "Emitting event '${event}' ($@)" + + initctl emit ${event} $@ +} + +function event_firewall_reload() { + event_emit firewall-reload +} + +# XXX dunno what this does. +function event_interface_up() { + local iface=${1} + + event_emit network-interface-up IFACE=${iface} +} + +# XXX dunno what this does. +function event_interface_down() { + local iface=${1} + + event_emit network-interface-down IFACE=${iface} +} diff --git a/functions.hook b/functions.hook new file mode 100644 index 00000000..970e43b1 --- /dev/null +++ b/functions.hook @@ -0,0 +1,141 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +function hook_exists() { + local hook=${1} + + [ -d "${HOOKS_DIR}/${hook}" ] && return ${EXIT_ERROR} + + [ -x "${HOOKS_DIR}/${hook}" ] +} + +function hook_port_exists() { + local hook_zone=${1} + local hook_port=${2} + + hook_exists ${hook_zone} || return ${EXIT_ERROR} + + [ -x "${HOOKS_DIR}/${hook_zone}.ports/${hook_port}" ] +} + +function hook_config_exists() { + local hook_zone=${1} + local hook_config=${2} + + hook_exists ${hook_zone} || return ${EXIT_ERROR} + + [ -x "${HOOKS_DIR}/${hook_zone}.configs/${hook_config}" ] +} + +function hook_has_ports() { + local hook=${1} + + [ -d "${HOOKS_DIR}/${hook}.ports" ] +} + +function hook_has_configs() { + local hook=${1} + + [ -d "${HOOKS_DIR}/${hook}.configs" ] +} + +function hook_exec() { + local hook=${1} + shift + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + ${SHELL} ${HOOKS_DIR}/${hook} $@ +} + +function hook_port_exec() { + local hook_zone=${1} + local hook_port=${2} + shift 2 + + if ! hook_exists ${hook_zone}; then + error "Hook '${hook_zone}' does not exist." + return ${EXIT_ERROR} + fi + + if ! hook_port_exists ${hook_zone} ${hook_port}; then + error "Port hook '${hook_port}' does not exist." + return ${EXIT_ERROR} + fi + + ${SHELL} ${HOOKS_DIR}/${hook_zone}.ports/${hook_port} $@ +} + +function hook_config_exec() { + local hook_zone=${1} + local hook_config=${2} + shift 2 + + if ! hook_exists ${hook_zone}; then + error "Hook '${hook_zone}' does not exist." + return ${EXIT_ERROR} + fi + + if ! hook_config_exists ${hook_zone} ${hook_config}; then + error "Config hook '${hook_config}' does not exist." + return ${EXIT_ERROR} + fi + + ${SHELL} ${HOOKS_DIR}/${hook_zone}.configs/${hook_config} $@ +} + +function hooks_get_all() { + local type=${1} + + local hook + for hook in ${HOOKS_DIR}/*; do + hook=$(basename ${hook}) + hook_exists ${hook} && echo "${hook}" + done | sort +} + +function hook_ports_get_all() { + local hook=${1} + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + local hook + for hook in ${HOOKS_DIR}/${zone}.ports/*; do + hook=$(basename ${hook}) + ## XXX executeable? + echo "${hook}" + done | sort +} + +function config_get_hook() { + local config=${1} + + ( + . ${config} + echo "${HOOK}" + ) +} diff --git a/functions.logging b/functions.logging new file mode 100644 index 00000000..db5c8efa --- /dev/null +++ b/functions.logging @@ -0,0 +1,21 @@ +#!/bin/bash + +LOG_FACILITY="network" +LOG_LEVEL="DEBUG" + +function log() { + local level=${1} + shift + local message="$@" + + if [ -z "${DEBUG}" ] && [ "${level}" = "DEBUG" ]; then + return + fi + + # Set a prefix if we are in a hook. + if [ -n "${HOOK}" ]; then + message="${HOOK}: ${message}" + fi + + logger -t ${LOG_FACILITY} "${message}" +} diff --git a/functions.ppp b/functions.ppp index 7598f0ba..82038512 100644 --- a/functions.ppp +++ b/functions.ppp @@ -2,7 +2,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2009 Michael Tremer & Christian Schmidt # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -19,26 +19,28 @@ # # ############################################################################### -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 + if ! grep -q ^ppp_generic /proc/modules; then + modprobe -q ppp_generic + fi - connection --starting --zone=${zone} + #connection --starting --zone=${zone} } function ppp_post_up() { - : #connection --up --zone=${zone} + : + #connection --up --zone=${zone} } function ppp_pre_down() { - connection --stopping --zone=${zone} + : + # connection --stopping --zone=${zone} } function ppp_post_down() { - : #connection --down --zone=${zone} + : + #connection --down --zone=${zone} } function ppp_secret() { @@ -83,13 +85,14 @@ function ppp_linkname_get() { local config=${1} ( . ${config} - echo "${LINKNAME}" + echo "${NAME}" ) } function red_defaultroute_update() { local command="ip route replace default" + local uplink for uplink in ${RED_RUN}/*; do [ -d "${uplink}" ] || continue @@ -102,7 +105,7 @@ function red_defaultroute_update() { fi done $command - ip route flush cache + #ip route flush cache } function red_dns_update() { diff --git a/functions.util b/functions.util new file mode 100644 index 00000000..9eb5afe3 --- /dev/null +++ b/functions.util @@ -0,0 +1,198 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +# Print a pretty error message +function error() { + echo -e " ${FAIL}ERROR${NORMAL} : $@" >&2 +} + +# Print a pretty warn message +function warning() { + echo -e " ${WARN}WARNING${NORMAL}: $@" >&2 +} + +function listsort() { + local i + for i in $@; do + echo "${i}" + done | sort | tr "\n" " " +} + +function config_read() { + local config_file=${1} + + if [ -e "${config_file}" ]; then + . ${config_file} + config_check + fi +} + +function config_write() { + local config_file=${1} + shift + + # Check if all values to be written are sane + config_check + + > ${config_file} + + local param + for param in $(listsort $@); do + echo "${param}=\"${!param}\"" >> ${config_file} + done +} + +function config_print() { + local param + + for param in $(listsort $@); do + printf "%-16s = %s\n" "${param}" "${!param}" + done +} + +function config_check() { + # If there is a function defined that is called __check + # we call that function + [ -n "$(type -t _check)" ] && _check +} + +function network_config_set() { + while [ $# -gt 0 ]; do + case "${1}" in + *=*) + eval ${1} + ;; + *) + warning "Invalid parameter given: ${1}" + ;; + esac + shift + done + + # Write configuration to disk + network_config_write +} + +function network_config_read() { + config_read ${CONFIG_FILE} +} + +function network_config_write() { + config_write ${CONFIG_FILE} ${CONFIG_FILE_PARAMS} +} + +function network_config_print() { + config_print ${CONFIG_FILE_PARAMS} +} + +# Speedup function to avoid a call of the basename binary +function basename() { + echo "${1##*/}" +} + +function enabled() { + local param=${1} + + [ "${!param}" = "yes" ] || [ "${!param}" = "on" ] || [ "${!param}" = "1" ] +} + +function mac_generate() { + local mac=() + for i in $(seq 0 5); do + mac[i]="0x$(uuid | cut -c 1-2)" + done + + # Remove multicast bit + # and set address is software assigned + # XXX must doublecheck if this works + mac[0]=$((mac[0] & 0xfe)) + mac[0]=$((mac[0] | 0x02)) + + local output + for i in ${mac[*]}; do + if [ -n "${output}" ]; then + output="${output}:" + fi + + output="${output}$(printf "%02x" ${i})" + done + + # Check if output is valid + assert mac_is_valid ${output} + + echo ${output} +} + +function mac_is_valid() { + local mac=${1} + + [[ ${mac} =~ ^([0-9a-f]{2}\:){5}[0-9a-f]{2}$ ]] +} + +function uuid() { + cat /proc/sys/kernel/random/uuid +} + +function isset() { + local var=${1} + + [ -n "${!var}" ] +} + +function isoneof() { + local var=${!1} + shift + + for i in $@; do + [ "${var}" = "${i}" ] && return ${EXIT_OK} + done + + return ${EXIT_ERROR} +} + +function isbool() { + local var=${1} + + isoneof ${var} 0 1 no yes on off +} + +function isinteger() { + local var=${!1} + + [[ ${var} =~ ^[0-9]+$ ]] +} + +function ismac() { + local mac=${!1} + + mac_is_valid ${mac} +} + +function assert() { + local assertion="$@" + + if ! ${assertion}; then + error "Assertion '${assertion}' failed." + exit ${EXIT_ERROR} + fi + + return ${EXIT_OK} +} diff --git a/functions.zone b/functions.zone new file mode 100644 index 00000000..268993ae --- /dev/null +++ b/functions.zone @@ -0,0 +1,417 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +function zone_dir() { + local zone=${1} + + echo "${ZONE_DIR}/${zone}" +} + +function zone_exists() { + local zone=${1} + + [ -d "$(zone_dir ${zone})" ] +} + +function zone_match() { + local match + + local i + for i in ${VALID_ZONES}; do + match="${match}|${i}[0-9]{1,5}" + done + + echo "${match:1:${#match}}" +} + +function zone_name_is_valid() { + local zone=${1} + + [[ ${zone} =~ $(zone_match) ]] +} + +function zone_is_local() { + local zone=${1} + + if [[ ${zone} =~ ^red[0-9]{1,5} ]]; then + return ${EXIT_ERROR} + fi + return ${EXIT_OK} +} + +function zone_get_hook() { + local zone=${1} + + config_get_hook $(zone_dir ${zone})/settings +} + +function zone_create() { + local zone=${1} + local hook=${2} + shift 2 + + if ! zone_name_is_valid ${zone}; then + error "Zone name '${zone}' is not valid." + return ${EXIT_ERROR} + fi + + if zone_exists ${zone}; then + error "Zone '${zone}' does already exist." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + mkdir -p $(zone_dir ${zone}) + + hook_exec ${hook} create ${zone} $@ + local ret=$? + + # Maybe the zone create hook did not exit correctly. + # If this is the case we remove the created zone immediately. + if [ "${ret}" = "${EXIT_ERROR}" ]; then + zone_remove ${zone} + fi +} + +function zone_edit() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} edit ${zone} $@ +} + +function zone_remove() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + # XXX Tear this down here? + + rm -rf $(zone_dir ${zone}) +} + +function zone_up() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} up ${zone} $@ +} + +function zone_down() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} down ${zone} $@ +} + +function zone_status() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} status ${zone} $@ +} + +function zone_port() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} port ${zone} $@ +} + +function zone_config() { + local zone=${1} + shift + + if ! zone_exists ${zone}; then + error "Zone '${zone}' does not exist." + return ${EXIT_ERROR} + fi + + local hook=$(config_get_hook $(zone_dir ${zone})/settings) + + if [ -z "${hook}" ]; then + error "Config file did not provide any hook." + return ${EXIT_ERROR} + fi + + if ! hook_exists ${hook}; then + error "Hook '${hook}' does not exist." + return ${EXIT_ERROR} + fi + + hook_exec ${hook} config ${zone} $@ +} + +function zone_show() { + local zone=${1} + + echo "${zone}" + echo " Type: $(zone_get_hook ${zone})" + echo +} + +function zones_show() { + local zone + + for zone in $(zones_get $@); do + zone_show ${zone} + done +} + +function zones_get_all() { + local zone + for zone in ${ZONE_DIR}/*; do + zone=$(basename ${zone}) + zone_exists ${zone} || continue + + echo "${zone}" + done | sort +} + +function zones_get_local() { + local zone + for zone in $(zones_get_all); do + zone_is_local ${zone} && echo "${zone}" + done +} + +function zones_get_nonlocal() { + local zone + for zone in $(zones_get_all); do + zone_is_local ${zone} || echo "${zone}" + done +} + +function zones_get() { + local local=1 + local remote=1 + + local zones + + while [ $# -gt 0 ]; do + case "${1}" in + --local-only) + local=1 + remote=0 + ;; + --remote-only) + local=0 + remote=1 + ;; + --all) + local=1 + remote=1 + ;; + *) + if zone_name_is_valid ${1}; then + zones="${zones} ${1}" + else + warning "Unrecognized argument '${1}'" + fi + ;; + esac + shift + done + + if [ -n "${zones}" ]; then + local zone + for zone in ${zones}; do + zone_exists ${zone} && echo "${zone}" + done + exit ${EXIT_OK} + fi + + if [ ${local} -eq 1 ] && [ ${remote} -eq 1 ]; then + zones_get_all + elif [ ${local} -eq 1 ]; then + zones_get_local + elif [ ${remote} -eq 1 ]; then + zones_get_nonlocal + fi +} + +function zone_ports_list() { + local zone=${1} + + local port + for port in $(zone_dir ${zone})/port.*; do + [ -e "${port}" ] || continue + + echo $(basename ${port}) + done | sort +} + +function zone_ports_cmd() { + local cmd=${1} + local zone=${2} + shift 2 + + local hook_zone=$(config_get_hook $(zone_dir ${zone})/settings) + + local hook_port + local port + for port in $(zone_ports_list ${zone}); do + hook_port=$(config_get_hook $(zone_dir ${zone})/${port}) + + hook_port_exec ${hook_zone} ${hook_port} ${cmd} ${zone} ${port} $@ + done +} + +function zone_ports_up() { + zone_ports_cmd up $@ +} + +function zone_ports_down() { + zone_ports_cmd down $@ +} + +function zone_configs_list() { + local zone=${1} + + local config + for config in $(zone_dir ${zone})/config.*; do + [ -e "${config}" ] || continue + + echo $(basename ${config}) + done | sort +} + +function zone_configs_cmd() { + local cmd=${1} + local zone=${2} + shift 2 + + local hook_zone=$(config_get_hook $(zone_dir ${zone})/settings) + + local hook_config + local config + for config in $(zone_configs_list ${zone}); do + hook_config=$(config_get_hook $(zone_dir ${zone})/${config}) + + hook_config_exec ${hook_zone} ${hook_config} ${cmd} ${zone} ${config} $@ + done +} + +function zone_configs_up() { + zone_configs_cmd up $@ +} + +function zone_configs_down() { + zone_configs_cmd down $@ +} + +function zone_has_ipv4() { + device_has_ipv4 $@ +} + diff --git a/zone b/header-port old mode 100755 new mode 100644 similarity index 50% rename from zone rename to header-port index 0f5b355d..4f22adc4 --- a/zone +++ b/header-port @@ -2,7 +2,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2009 Michael Tremer & Christian Schmidt # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -19,75 +19,31 @@ # # ############################################################################### -. /etc/init/functions . /lib/network/functions -while [ "$#" -gt "0" ]; do +HOOK=$(basename ${0}) + +while [ $# -gt 0 ]; do case "${1}" in - --zone=*) - zone=${1#--zone=} + -*) + error "Unrecognized option: ${1}" + exit ${EXIT_ERROR} ;; *) action=${1} - break - ;; + ;; esac shift + [ -n "${action}" ] && break done -if [ -z "${zone}" ] || [ -z "${action}" ]; then - log_failure_msg "Wrong number of arguments." - exit ${EXIT_ERROR} -fi +function run() { + case "${action}" in + create|rem|up|down) + _${action} $@ + ;; + esac -if ! zone_exists ${zone}; then - echo "Zone ${zone} does not exist." + error "Port hook '${HOOK}' didn't exit properly." 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 +} diff --git a/header-zone b/header-zone new file mode 100644 index 00000000..30cb5f27 --- /dev/null +++ b/header-zone @@ -0,0 +1,254 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### +# +# Notes: +# - All functions in this scope must start with an underline (_) to not +# conflict with any functions that were defined somewhere else. +# + +. /lib/network/functions + +HOOK=$(basename ${0}) + +while [ $# -gt 0 ]; do + case "${1}" in + -*) + error "Unrecognized option: ${1}" + exit ${EXIT_ERROR} + ;; + *) + action=${1} + ;; + esac + shift + + # If action argument was given, we will exit. + [ -n "${action}" ] && break +done + +# _notimplemented +# Returns a soft error if a function was not implemented, yet. +# +function _notimplemented() { + warning "'$@' was not implemented." + exit ${EXIT_CONF_ERROR} +} + +function _info() { + echo "HOOK=\"${HOOK}\"" +} + +function _create() { + local zone=${1} + shift + + config_read ${ZONE_DIR}/${zone}/settings + + _parse_cmdline $@ + + config_write ${ZONE_DIR}/${zone}/settings ${HOOK_SETTINGS} + + exit ${EXIT_OK} +} + +function _edit() { + _create $@ +} + +function _rem() { + _notimplemented _rem +} + +function _status() { + local zone=${1} + + if device_is_up ${zone}; then + exit ${STATUS_UP} + fi + + exit ${STATUS_DOWN} +} + +function _up() { + _notimplemented _up +} + +function _down() { + _notimplemented _down +} + +function _discover() { + # This hook does not support a discovery + exit ${DISCOVER_NOT_SUPPORTED} +} + +# Do nothing +function _parse_cmdline() { + return ${EXIT_OK} +} + +function _port() { + local zone=${1} + local action=${2} + shift 2 + + local ret + + case "${action}" in + create|edit|rem|show) + _port_${action} ${zone} $@ + ret=$? + ;; + *) + error "Unrecognized argument: '${action}'" + exit ${EXIT_ERROR} + ;; + esac + + exit ${ret} +} + +# This function is not a public one +function __portcmd() { + local cmd=${1} + local zone=${2} + local hook_port=${3} + shift 3 + + local hook_zone=$(zone_get_hook ${zone}) + + if ! hook_exists ${hook_zone}; then + error "Hook '${hook}' does not exist." + exit ${EXIT_ERROR} + fi + + if ! hook_port_exists ${hook_zone} ${hook_port}; then + error "Hook '${hook_port}' is not supported for zone '${zone}'." + exit ${EXIT_ERROR} + fi + + hook_port_exec ${hook_zone} ${hook_port} ${cmd} ${zone} $@ +} + +function _port_create() { + __portcmd create $@ +} + +function _port_edit() { + __portcmd edit $@ +} + +function _port_rem() { + _notimplemented _port_rem +} + +function _port_show() { + _notimplemented _port_show +} + +function _config() { + local zone=${1} + local action=${2} + shift 2 + + local ret + + case "${action}" in + create|edit|rem|show) + _config_${action} ${zone} $@ + ret=$? + ;; + *) + error "Unrecognized argument: '${action}'" + exit ${EXIT_ERROR} + ;; + esac + + exit ${ret} +} + +# This function is not a public one +function __configcmd() { + local cmd=${1} + local zone=${2} + local hook_config=${3} + shift 3 + + local hook_zone=$(zone_get_hook ${zone}) + + if ! hook_exists ${hook_zone}; then + error "Hook '${hook}' does not exist." + exit ${EXIT_ERROR} + fi + + if ! hook_config_exists ${hook_zone} ${hook_config}; then + error "Hook '${hook_config}' is not supported for zone '${zone}'." + exit ${EXIT_ERROR} + fi + + hook_config_exec ${hook_zone} ${hook_config} ${cmd} ${zone} $@ +} + +function _config_create() { + __configcmd create $@ +} + +function _config_edit() { + __configcmd edit $@ +} + +function _config_rem() { + _notimplemented _config_rem +} + +function _config_show() { + _notimplemented _config_show +} + +function run() { + case "${action}" in + create|discover|down|edit|info|rem|status|up) + _${action} $@ + ;; + + port) + if ! hook_has_ports ${HOOK}; then + error "Hook '${HOOK}' does not support ports." + exit ${EXIT_ERROR} + fi + + _port $@ + ;; + + config) + if ! hook_has_configs ${HOOK}; then + error "Hook '${HOOK}' does not support configurations." + exit ${EXIT_ERROR} + fi + + _config $@ + ;; + + esac + + error "Hook did not exit properly." + exit ${EXIT_ERROR} +} diff --git a/hook-header b/hook-header deleted file mode 100644 index b2693b89..00000000 --- a/hook-header +++ /dev/null @@ -1,38 +0,0 @@ -#!/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 deleted file mode 100644 index 09ca2307..00000000 --- a/hooks/README +++ /dev/null @@ -1,86 +0,0 @@ -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] [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 deleted file mode 100755 index 03f0a70b..00000000 --- a/hooks/bonding +++ /dev/null @@ -1,177 +0,0 @@ -#!/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 $(. # +# # +############################################################################### + +. /lib/network/header-zone + +HOOK_SETTINGS="HOOK STP STP_FORWARD_DELAY STP_HELLO STP_MAXAGE MAC MTU" + +# Default values +MAC=$(mac_generate) +MTU=1500 +STP="on" +STP_FORWARD_DELAY=0 +STP_HELLO=2 +STP_MAXAGE=20 + +function _check() { + assert ismac MAC + assert isbool STP + assert isinteger STP_HELLO + assert isinteger STP_FORWARD_DELAY + assert isinteger MTU +} + +function _parse_cmdline() { + while [ $# -gt 0 ]; do + case "${1}" in + --stp=*) + STP=${1#--stp=} + ;; + --stp-hello=*) + STP_HELLO=${1#--stp-hello=} + ;; + --stp-forward-delay=*) + STP_FORWARD_DELAY=${1#--stp-forward-delay=} + ;; + --mtu=*) + MTU=${1#--mtu=} + ;; + --mac=*) + MAC=${1#--mac=} + ;; + *) + warning "Ignoring unknown option '${1}'" + ;; + esac + shift + done +} + +function _up() { + local zone=${1} + shift + + config_read ${ZONE_DIR}/${zone}/settings + + if ! device_exists ${zone}; then + brctl addbr ${zone} + fi + + [ -n "${MAC}" ] && device_set_mac ${zone} ${MAC} + [ -n "${MTU}" ] && device_set_mtu ${zone} ${MTU} + + # Enable STP + if enabled STP; then + brctl stp ${zone} on + + if [ -n "${STP_FORWARD_DELAY}" ]; then + brctl setfd ${zone} ${STP_FORWARD_DELAY} + fi + + if [ -n "${STP_HELLO}" ]; then + brctl sethello ${zone} ${STP_HELLO} + fi + + if [ -n "${STP_MAXAGE}" ]; then + brctl setmaxage ${zone} ${STP_MAXAGE} + fi + else + brctl stp ${zone} off + fi + + device_set_up ${zone} + + # Bring all ports up + zone_ports_up ${zone} + + # XXX Do we need this? + # Wait until bridge is forwarding + # which is needed by dhcp client + #if enabled STP; then + # bridge_is_forwarding ${zone} + #fi + + zone_configs_up ${zone} + + event_interface_up ${zone} + + exit $? +} + +function _down() { + local zone=${1} + shift + + if ! device_is_up ${zone}; then + warning "Zone '${zone}' is not up" + exit ${EXIT_OK} + fi + + event_interface_down ${zone} + + zone_configs_down ${zone} + zone_ports_down ${zone} + + device_set_down ${zone} + brctl delbr ${zone} + + exit $? +} + +function _addport() { + local zone=${1} + local hook=${2} + shift 2 + + if ! hook_exists port ${hook}; then + error "Hook does not exist '${hook}'" + exit ${EXIT_ERROR} + fi + + port_hook ${hook} add ${zone} +} + +run $@ diff --git a/hooks/bridge.configs/ipv4-static b/hooks/bridge.configs/ipv4-static new file mode 100755 index 00000000..733a43f1 --- /dev/null +++ b/hooks/bridge.configs/ipv4-static @@ -0,0 +1,135 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +. /lib/network/header-port + +HOOK_SETTINGS="HOOK ADDRESS PREFIX GATEWAY" + +function _check() { + assert isset ADDRESS + assert isinteger PREFIX + + if [ ${PREFIX} -gt 30 ]; then + error "PREFIX is greater than 30." + exit ${EXIT_ERROR} + fi +} + +function _create() { + local zone=${1} + shift + + while [ $# -gt 0 ]; do + case "${1}" in + --address=*) + ADDRESS=${1#--address=} + ;; + --netmask=*) + NETMASK=${1#--netmask=} + ;; + --prefix=*) + PREFIX=${1#--prefix=} + ;; + --gateway=*) + GATEWAY=${1#--gateway=} + ;; + esac + shift + done + + if [ -z "${PREFIX}" -a -n "${NETMASK}" ]; then + PREFIX=$(ipv4_mask_to_cidr ${NETMASK}) + fi + + config_write $(zone_dir ${zone})/config.${HOOK}.$(uuid) ${HOOK_SETTINGS} + + exit ${EXIT_OK} +} + +function _up() { + local zone=${1} + local config=${2} + shift 2 + + if ! device_exists ${zone}; then + error "Zone '${zone}' doesn't exist." + exit ${EXIT_ERROR} + fi + + config_read $(zone_dir ${zone})/${config} + + if ! zone_has_ipv4 ${zone} ${ADDRESS}/${PREFIX}; then + ip addr add ${ADDRESS}/${PREFIX} dev ${zone} + else + warning "Do not set IPv4 address '${ADDRESS}/${PREFIX}' because it was already configured on zone '${zone}'." + fi + + warning "XXX Gateway stuff has to be done." + if [ -n "${GATEWAY}" ]; then + : # What do we do with the gateway? + fi + + exit ${EXIT_OK} +} + +function _down() { + local zone=${1} + local config=${2} + shift 2 + + if ! device_exists ${zone}; then + error "Zone '${zone}' doesn't exist." + exit ${EXIT_ERROR} + fi + + config_read $(zone_dir ${zone})/${config} + + if zone_has_ipv4 ${zone} ${ADDRESS}/${PREFIX}; then + ip addr del ${ADDRESS}/${PREFIX} dev ${zone} + fi + + exit ${EXIT_OK} +} + +function ipv4_mask_to_cidr() { + local mask=0 + + local field + for field in $(tr '.' ' ' <<<${1}); do + mask=$(( $(( ${mask} << 8 )) | ${field} )) + done + + local cidr=0 + local x=$(( 128 << 24 )) # 0x80000000 + + while [ $(( ${x} & ${mask} )) -ne 0 ]; do + [ ${mask} -eq ${x} ] && mask=0 || mask=$(( ${mask} << 1 )) + cidr=$((${cidr} + 1)) + done + + if [ $(( ${mask} & 2147483647 )) -ne 0 ]; then # 2147483647 = 0x7fffffff + echo "Invalid net mask: $1" >&2 + else + echo ${cidr} + fi +} + +run $@ diff --git a/hooks/bridge.ports/ethernet b/hooks/bridge.ports/ethernet new file mode 100755 index 00000000..6428ef31 --- /dev/null +++ b/hooks/bridge.ports/ethernet @@ -0,0 +1,95 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +. /lib/network/header-port + +HOOK_SETTINGS="HOOK DEVICE" + +function _check() { + assert isset DEVICE + assert ismac DEVICE +} + +function _create() { + local zone=${1} + local device=${2} + shift 2 + + if [ -z "${device}" ]; then + error "No device given." + exit ${EXIT_ERROR} + fi + + if ! device_exists ${device}; then + warning "Device does not exist." + fi + + DEVICE=$(macify ${device}) + + config_write $(zone_dir ${zone})/port.${HOOK}.$(device_hash ${device}) ${HOOK_SETTINGS} + + exit ${EXIT_OK} +} + +function _up() { + local zone=${1} + local port=${2} + + config_read $(zone_dir ${zone})/${port} + + local device=$(devicify ${DEVICE}) + + if ! device_exists ${device}; then + warning "Device '${DEVICE}' does not exist." + exit ${EXIT_ERROR} + fi + + # Set same MTU to device that the bridge has got + device_set_mtu ${device} $(device_get_mtu ${zone}) + + device_set_up ${device} + + bridge_attach_device ${zone} ${device} + + exit ${EXIT_OK} +} + +function _down() { + local zone=${1} + local port=${2} + + config_read $(zone_dir ${zone})/${port} + + local device=$(devicify ${DEVICE}) + + if ! device_exists ${device}; then + warning "Device '${DEVICE}' does not exist." + exit ${EXIT_ERROR} + fi + + bridge_detach_device ${zone} ${device} + + device_set_down ${device} + + exit ${EXIT_OK} +} + +run $@ diff --git a/hooks/bridge.ports/virtual b/hooks/bridge.ports/virtual new file mode 100755 index 00000000..46b1088d --- /dev/null +++ b/hooks/bridge.ports/virtual @@ -0,0 +1,127 @@ +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +. /lib/network/header-port + +HOOK_SETTINGS="HOOK DEVICE DEVICE_MAC DEVICE_VID" + +DEVICE_MAC=$(mac_generate) + +function _check() { + assert ismac DEVICE + assert ismac DEVICE_MAC + + assert isinteger DEVICE_VID + + if [ ${DEVICE_VID} -gt 4096 ]; then + error "DEVICE_VID is greater than 4096." + exit ${EXIT_ERROR} + fi + + local reserved + for reserved in 0 4095; do + if [ "${DEVICE_VID}" = "${reserved}" ]; then + error "DEVICE_VID=${reserved} is reserved." + exit ${EXIT_ERROR} + fi + done +} + +function _add() { + local zone=${1} + local device=${2} + shift 2 + + while [ $# -gt 0 ]; do + case "${1}" in + --mac=*) + DEVICE_MAC=${1#--mac=} + ;; + --id=*) + DEVICE_VID=${1#--id=} + ;; + *) + warning "Unknown argument '${1}'" + ;; + esac + shift + done + + DEVICE=$(macify ${device}) + + _check + + config_write $(zone_dir ${zone})/port.${HOOK}.$(device_hash ${device}).${DEVICE_VID} ${HOOK_SETTINGS} + + exit ${EXIT_OK} +} + +function _edit() { + local zone=${1} + + error "TODO - edit mac addres" + + exit ${EXIT_ERROR} +} + +function _up() { + local zone=${1} + local port=${2} + + config_read $(zone_dir ${zone})/${port} + + if ! device_exists $(devicify ${DEVICE_MAC}); then + device_virtual_create ${DEVICE} ${DEVICE_VID} ${DEVICE_MAC} + fi + + local device=$(devicify ${DEVICE_MAC}) + + # Set same MTU to device that the bridge has got + device_set_mtu ${device} $(device_get_mtu ${zone}) + + device_set_up ${device} + + bridge_attach_device ${zone} ${device} + + exit ${EXIT_OK} +} + +function _down() { + local zone=${1} + local port=${2} + + config_read $(zone_dir ${zone})/${port} + + local device=$(devicify ${DEVICE_MAC}) + + if ! device_exists ${device}; then + error "Device '${DEVICE_MAC}' does not exist." + exit ${EXIT_ERROR} + fi + + bridge_detach_device ${zone} ${device} + + device_virtual_remove ${device} + + exit ${EXIT_OK} +} + +run $@ diff --git a/hooks/ethernet b/hooks/ethernet deleted file mode 100755 index e6e364ff..00000000 --- a/hooks/ethernet +++ /dev/null @@ -1,137 +0,0 @@ -#!/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=" - #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 deleted file mode 100755 index 43c44199..00000000 --- a/hooks/ipv4-dhcp +++ /dev/null @@ -1,84 +0,0 @@ -#!/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 deleted file mode 100755 index 34af5572..00000000 --- a/hooks/ipv4-static +++ /dev/null @@ -1,169 +0,0 @@ -#!/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 deleted file mode 100755 index 9e389864..00000000 --- a/hooks/ipv4-static-route +++ /dev/null @@ -1,141 +0,0 @@ -#!/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 deleted file mode 100755 index 707345a6..00000000 --- a/hooks/mtu +++ /dev/null @@ -1,85 +0,0 @@ -#!/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 index d27a5177..60460c92 100755 --- a/hooks/pppoe +++ b/hooks/pppoe @@ -1,72 +1,159 @@ -#!/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 +#!/bin/bash +############################################################################### +# # +# IPFire.org - A linux based firewall # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # +# # +# This program is free software: you can redistribute it and/or modify # +# it under the terms of the GNU General Public License as published by # +# the Free Software Foundation, either version 3 of the License, or # +# (at your option) any later version. # +# # +# This program is distributed in the hope that it will be useful, # +# but WITHOUT ANY WARRANTY; without even the implied warranty of # +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # +# GNU General Public License for more details. # +# # +# You should have received a copy of the GNU General Public License # +# along with this program. If not, see . # +# # +############################################################################### + +. /lib/network/header-zone + +# TODO AC name, service name, sync? + +HOOK_SETTINGS="HOOK AUTH LINKNAME USER SECRET PEERDNS DEFAULTROUTE MTU" +HOOK_SETTINGS="${HOOK_SETTINGS} DEVICE DEVICE_VID DEVICE_TYPE" + +AUTH= +DEFAULTROUTE=1 +LINKNAME="$(uuid)" +MTU=1492 +PEERDNS=1 +SECRET= +USER= + +PPPOE_ALLOWED_AUTHS="chap pap" +PPPOE_PLUGIN="rp-pppoe.so" + +function _pppoe_real_device() { + local device + if [ -n "${DEVICE_VID}" ]; then + device="${DEVICE_MAC}" + else + device="${DEVICE}" + fi + + devicify ${device} +} + +function _check() { + assert isset USER + assert isset SECRET + assert isset LINKNAME + assert isset DEFAULTROUTE + assert isset PEERDNS + assert isset DEVICE + assert isset DEVICE_TYPE + + assert isbool DEFAULTROUTE + assert isbool PEERDNS + assert ismac DEVICE + assert isoneof DEVICE_TYPE real virtual + + isset AUTH && assert isoneof AUTH ${PPPOE_ALLOWED_AUTHS} + isset DEVICE_ID && assert isinteger DEVICE_VID +} + +function _parse_cmdline() { + while [ $# -gt 0 ]; do + case "$1" in + --user=*) + USER=${1#--user=} + ;; + --secret=*) + SECRET=${1#--secret=} + ;; + --linkname=*) + LINKNAME=${1#--name=} + ;; + --mtu=*) + MTU=${1#--mtu=} + ;; + --no-defaultroute) + DEFAULTROUTE=0 + ;; + --no-dns) + PEERDNS=0 + ;; + --auth=*) + AUTH=${1#--auth=} + ;; + --device=*) + DEVICE=${1#--device=} + ;; + --device-vid=*) + DEVICE_VID=${1#--device-vid=} + ;; + *) + echo "Unknown option: $1" >&2 + exit ${EXIT_ERROR} + ;; + esac + shift + done + + if ! device_exists $(devicify ${DEVICE}); then + error "Device '${DEVICE}' does not exist." + exit ${EXIT_ERROR} + fi + + DEVICE=$(macify ${DEVICE}) + + if isset DEVICE_VID; then + DEVICE_TYPE="virtual" + else + DEVICE_TYPE="real" + fi +} + +function _up() { + local zone=${1} + shift + + config_read ${ZONE_DIR}/${zone}/settings + + ppp_pre_up + + # Creating necessary files + [ -d "${RED_RUN}/${LINKNAME}" ] || mkdir -p ${RED_RUN}/${LINKNAME} + + # Setting up the device + if [ -n "${DEVICE_VID}" ]; then + device_create_virtual ${DEVICE} ${DEVICE_VID} ${DEVICE_MAC} + else + device_set_up ${DEVICE} + fi + + ppp_secret "${USER}" "${SECRET}" + + cat <${RED_RUN}/${LINKNAME}/options # Naming options -name ${NAME} -linkname ${NAME} +ifname ${zone} +name ${LINKNAME} +linkname ${LINKNAME} -plugin ${PPPOE_PLUGIN} ${zone} +plugin ${PPPOE_PLUGIN} $(_pppoe_real_device) # User configuration user ${USER} -$([ "${PEERDNS}" = "1" ] && echo "usepeerdns") -$([ "${DEFAULTROUTE}" = "1" ] && echo "defaultroute") +$(enabled PEERDNS && echo "usepeerdns") +$(enabled DEFAULTROUTE && echo "defaultroute") noauth -$([ -n "${AUTH}" ] && echo "require-${AUTH}") +$(isset AUTH && echo "require-${AUTH}") noipdefault @@ -75,117 +162,68 @@ mtu ${MTU} mru ${MTU} # Disable the compression -noaccomp nodeflate nopcomp novj novjccomp nobsdcomp +noccp noaccomp nodeflate nopcomp novj novjccomp nobsdcomp nomppe 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]" + pppd file ${RED_RUN}/${LINKNAME}/options >/dev/null + + exit ${EXIT_OK} +} + +function _down() { + local zone=${1} + shift + + config_read ${ZONE_DIR}/${zone}/settings + + ppp_pre_down + + # Kill pppd + pid=$(cat /var/run/${zone}.pid 2>/dev/null) + if [ -n "${pid}" ]; then + kill ${pid} &>/dev/null + fi + + # Pull down device or remove virtual one + if [ -n "${DEVICE_VID}" ]; then + device_remove_virtual ${DEVICE_MAC} + else + device_set_down ${DEVICE} + fi + + exit ${EXIT_OK} +} + +function _discover() { + local device=${1} + + if [ "$(device_get_type ${device})" != "real" ]; then exit ${EXIT_ERROR} - ;; -esac + fi + + local output + output=$(pppoe-discovery -I ${device} -U $(uuid) 2>&1) + + # Exit if there was not output + [ -z "${output}" ] && exit ${DISCOVER_ERROR} + + # Exit if PADI timed out + grep -q "Timeout" <<<${output} && exit ${DISCOVER_ERROR} + + local ac + while read line; do + case "${line}" in + Access-Concentrator:*) + ac="${line#Access-Concentrator: }" + ;; + esac + done <<<"${output}" + + echo "ACCESS_CONCENTRATOR=\"$ac\"" + + exit ${DISCOVER_OK} +} -# End $NETWORK_DEVICES/services/ipv4-static +run $@ diff --git a/hooks/pppoe.helper b/hooks/pppoe.helper deleted file mode 100755 index 693ba3de..00000000 --- a/hooks/pppoe.helper +++ /dev/null @@ -1,73 +0,0 @@ -#!/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 deleted file mode 100755 index 9e1c465e..00000000 --- a/hooks/stp +++ /dev/null @@ -1,97 +0,0 @@ -#!/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 deleted file mode 100755 index e4d99e64..00000000 --- a/hooks/vlan +++ /dev/null @@ -1,120 +0,0 @@ -#!/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 old mode 100644 new mode 100755 index 2bcbbe1c..0a2cfdaa --- a/network +++ b/network @@ -2,7 +2,7 @@ ############################################################################### # # # IPFire.org - A linux based firewall # -# Copyright (C) 2009 Michael Tremer & Christian Schmidt # +# Copyright (C) 2010 Michael Tremer & Christian Schmidt # # # # This program is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # @@ -19,597 +19,55 @@ # # ############################################################################### -BOLD="\\033[1;39m" -NORMAL="\\033[0;39m" -ERROR="\\033[1;31m" +. /lib/network/functions -. /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 +# Parse the command line +while [ $# -gt 0 ]; do + case "${1}" in + -d|--debug) + DEBUG=1 + log DEBUG "Enabled debugging mode" ;; - 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 + *) + action=${1} ;; - 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 <