#!/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 . # # # ############################################################################### port_dir() { local port="${1}" echo "${NETWORK_CONFIG_DIR}/ports/${port}" } port_list() { local port for port in $(port_dir)/*; do port="$(basename "${port}")" if port_exists "${port}"; then print "${port}" fi done } port_list_in_use() { local ports_in_use # Collect all ports that are attached to a zone local zone for zone in $(zones_get_all); do list_append ports_in_use $(zone_get_ports "${zone}") done # Collect all ports that are enslaved by an other port local port for port in $(port_list); do list_append ports_in_use $(port_get_slaves "${port}") done list_sort ${ports_in_use} } port_list_free() { local ports_in_use="$(port_list_in_use)" local port for port in $(port_list); do if ! list_match "${port}" ${ports_in_use}; then print "${port}" fi done return ${EXIT_OK} } port_get_hook() { local port=${1} assert isset port config_get_hook $(port_file ${port}) } port_config_dir() { local port=${1} print "${RUN_DIR}/ports/${port}" return ${EXIT_OK} } port_settings_read() { local port="${1}" assert isset port # Save the HOOK variable. local hook="${HOOK}" settings_read "$(port_file "${port}")" ${HOOK_SETTINGS} # Restore hook. HOOK="${hook}" } port_settings_write() { local port="${1}" assert isset port shift local args if function_exists "hook_check_settings"; then list_append args "--check=\"hook_check_settings\"" fi list_append args ${HOOK_SETTINGS} settings_write "$(port_file "${port}")" ${args} } ports_get_all() { port_list } port_file() { local port="${1}" assert isset port echo "$(port_dir ${port})/settings" } port_exists() { local port=${1} [ -d "${NETWORK_CONFIG_DIR}/ports/${port}" ] } port_get_hook() { local port=${1} assert isset port config_get_hook $(port_file ${port}) } port_is_attached() { local port=${1} shift assert isset port local zone for zone in $(zones_get_all); do assert isset zone assert zone_exists ${zone} if list_match ${port} $(zone_get_ports ${zone}); then echo "${zone}" return ${EXIT_OK} fi done return ${EXIT_ERROR} } port_is_up() { device_is_up $@ } port_new() { local hook="${1}" shift if ! hook_exists port "${hook}"; then error "Port hook '${hook}' does not exist." return ${EXIT_ERROR} fi hook_exec port "${hook}" new $@ } port_destroy() { local port=${1} assert isset port # Cannot delete a port that does not exist if ! port_exists ${port}; then error "No such port: ${port}" return ${EXIT_ERROR} fi # Check if the port is attached to any zone and don't delete it. local ok=${EXIT_OK} local attached_zone=$(port_is_attached ${port}) if [ -n "${attached_zone}" ]; then if ! zone_port_detach "${attached_zone}" "${port}"; then error "Could not remove port ${port} from zone ${zone}" return ${EXIT_ERROR} fi fi # Check if the port is linked to any other port and don't allow the user # to delete it. local other_port for other_port in $(ports_get); do [ "${other_port}" = "${port}" ] && continue if list_match ${port} $(port_get_parents ${other_port}); then error_log "Cannot destroy port '${port}' which is a parent port to '${other_port}'." ok=${EXIT_ERROR} fi if list_match ${port} $(port_get_children ${other_port}); then error_log "Cannot destroy port '${port}' which is child of port '${other_port}'." ok=${EXIT_ERROR} fi done # If ok says we are not okay --> exit if [ ${ok} -ne ${EXIT_OK} ]; then return ${EXIT_ERROR} fi port_remove "${port}" rm -rf $(port_dir ${port}) } port_create() { port_cmd "create" $@ } port_remove() { local port="${1}" assert isset port if ! port_exists "${port}"; then log ERROR "Port ${port} does not exist" return ${EXIT_ERROR} fi # If the device is still up, we need to bring it down first. if device_is_up "${port}"; then port_down "${port}" fi port_cmd "remove" "${port}" } # Restarts the port by removing it and then re-creating it port_restart() { local port="${1}" assert isset port port_remove "${port}" port_create "${port}" } port_edit() { port_cmd edit $@ } port_up() { port_cmd up $@ } port_down() { port_cmd down $@ } port_status() { port_cmd status $@ } port_info() { port_cmd info $@ } port_cmd() { local cmd=${1} local port=${2} shift 2 assert isset cmd assert isset port local hook=$(port_get_hook ${port}) # Abort if we could not find a hook if ! isset hook; then log CRITICAL "Port ${port} does not have a hook associated with it" return ${EXIT_ERROR} fi hook_exec port ${hook} ${cmd} ${port} $@ } ports_get() { local port for port in $(port_dir)/*; do port=$(basename ${port}) if port_exists ${port}; then echo "${port}" fi done } port_find_free() { local pattern=${1} assert isset pattern local port local i=0 while [ ${i} -lt 99 ]; do port=${pattern//N/${i}} if ! port_exists ${port} && ! device_exists ${port}; then echo "${port}" return ${EXIT_OK} fi i=$(( ${i} + 1 )) done return ${EXIT_ERROR} } port_get_info() { local port=${1} local key=${2} assert isset port assert port_exists ${port} assert isset key ( eval $(port_info ${port}) echo "${!key}" ) } port_get_parents() { local port=${1} port_get_info ${port} PORT_PARENTS } port_get_children() { local port=${1} port_get_info ${port} PORT_CHILDREN } port_zone() { # Get name of the zones, this port is configured in. local port=${1} shift assert isset port local zone for zone in $(zones_get_all); do if zone_has_port ${zone} ${port}; then echo "${zone}" return ${EXIT_OK} fi done return ${EXIT_OK} } port_hotplug_event() { local port="${1}" assert isset port hotplug_assert_in_hotplug_event port_cmd "hotplug" "${port}" } port_get_slaves() { local port="${1}" port_settings_read "${port}" \ --ignore-superfluous-settings SLAVES print "${SLAVES}" } port_device_is_slave() { assert [ $# -eq 2 ] local port="${1}" local device="${2}" # Get slaves of port local slaves="$(port_get_slaves "${port}")" # Returns true if device is in slaves list_match "${device}" ${slaves} } port_get_phy() { local port="${1}" port_settings_read "${port}" \ --ignore-superfluous-settings PHY print "${PHY}" } port_uses_phy() { assert [ $# -eq 2 ] local port="${1}" local phy="${2}" # Nothing to do if an empty argument is given if ! isset phy; then return ${EXIT_FALSE} fi phy="$(phy_get_address "${phy}")" local port_phy="$(port_get_phy "${port}")" [ "${port_phy}" = "${phy}" ] } ports_lowest_address() { local address local addresses local port for port in $(port_list); do # Skip all ports that do not exist # any more or are not plugged in device_exists "${port}" || continue # Skip all ports that are not proper ethernet devices device_is_wireless "${port}" && continue device_is_ethernet "${port}" || continue list_append addresses "$(device_get_address "${port}")" done # Sort the list addresses="$(list_sort ${addresses})" # Get the first element which is the lowest MAC address list_head ${addresses} } port_identify() { device_identify $@ } port_get_color() { # This function return the color of a port assert [ $# -eq 1 ] local name=${1} color_read "port" ${name} } port_get_description_title() { assert [ $# -eq 1 ] local name=${1} description_title_read $(description_format_filename "port" "${name}") }