2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2010 Michael Tremer & Christian Schmidt #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
22 .
/usr
/lib
/network
/header
-zone
24 HOOK_MANPAGE
="network-zone-bridge"
30 "STP_HELLO STP_MAXAGE"
42 DEFAULT_STP_FORWARD_DELAY
=0
45 DEFAULT_STP_PRIORITY
=512
47 hook_check_settings
() {
49 assert isset MTU
&& assert mtu_is_valid
"ethernet" "${MTU}"
51 # Spanning Tree Protocol
53 assert isinteger STP_HELLO
54 assert isinteger STP_FORWARD_DELAY
55 assert isinteger STP_PRIORITY
58 hook_parse_cmdline
() {
59 while [ $# -gt 0 ]; do
62 ADDRESS
="$(cli_get_val "${1}")"
64 if ! mac_is_valid
"${ADDRESS}"; then
65 error
"Invalid MAC address: ${ADDRESS}"
71 MTU
="$(cli_get_val "${1}")"
73 if ! mtu_is_valid
"ethernet" "${MTU}"; then
74 error
"Invalid MTU: ${MTU}"
80 STP
="$(cli_get_val "${1}")"
84 elif disabled STP
; then
87 error
"Invalid value for STP: ${STP}"
92 --stp-forward-delay=*)
93 STP_FORWARD_DELAY
="$(cli_get_val "${1}")"
95 if ! isinteger STP_FORWARD_DELAY
; then
96 error
"Invalid STP forwarding delay: ${STP_FORWARD_DELAY}"
102 STP_HELLO
="$(cli_get_val "${1}")"
104 if ! isinteger STP_HELLO
; then
105 error
"Invalid STP hello time: ${STP_HELLO}"
111 STP_MAXAGE
="$(cli_get_val "${1}")"
113 if ! isinteger STP_MAXAGE
; then
114 error
"Invalid STP max age: ${STP_MAXAGE}"
120 STP_PRIORITY
="$(cli_get_val "${1}")"
122 if ! isinteger STP_PRIORITY
; then
123 error
"Invalid STP priority: ${STP_PRIORITY}"
129 error
"Unknown argument: ${1}"
136 # Generate a random MAC address if the user passed none
137 if ! isset ADDRESS
; then
138 ADDRESS
="$(mac_generate)"
148 zone_settings_read
"${zone}"
150 # Create the bridge if it does not already exist.
151 if ! device_exists
"${zone}"; then
152 bridge_create
"${zone}" \
153 --address="${ADDRESS}" \
161 if isset STP_FORWARD_DELAY
; then
162 stp_bridge_set_forward_delay
"${zone}" "${STP_FORWARD_DELAY}"
165 if isset STP_HELLO
; then
166 stp_bridge_set_hello_time
"${zone}" "${STP_HELLO}"
169 if isset STP_MAXAGE
; then
170 stp_bridge_set_max_age
"${zone}" "${STP_MAXAGE}"
173 if isset STP_PRIORITY
; then
174 stp_bridge_set_priority
"${zone}" "${STP_PRIORITY}"
177 stp_disable
"${zone}"
180 device_set_up
"${zone}"
182 # XXX Currently, there is a bug (in the linux kernel?) that we need to
183 # set our bridges to promisc mode.
184 device_set_promisc
"${zone}" on
186 # Bring up all configurations
187 zone_configs_up
"${zone}"
196 if ! device_is_up
"${zone}"; then
197 warning
"Zone '${zone}' is not up"
201 # Stop all the configs.
202 zone_configs_down
"${zone}"
204 # Bring down all the ports.
205 zone_ports_down
"${zone}"
206 zone_ports_remove
"${zone}"
209 device_set_down
"${zone}"
210 bridge_delete
"${zone}"
219 # Print the default header.
220 cli_device_headline
"${zone}"
222 # Exit if zone is down
223 if ! zone_is_up
"${zone}"; then
228 cli_headline
2 "Spanning Tree Protocol information"
229 if stp_is_enabled
"${zone}"; then
230 cli_print_fmt1
2 "ID" "$(stp_bridge_get_id ${zone})"
231 cli_print_fmt1
2 "Priority" "$(stp_bridge_get_priority ${zone})"
233 if stp_bridge_is_root
${zone}; then
234 cli_print
2 "This bridge is root."
236 cli_print_fmt1
2 "Designated root" \
237 "$(stp_bridge_get_designated_root ${zone})"
238 cli_print_fmt1
2 "Root path cost" \
239 "$(stp_bridge_get_root_path_cost ${zone})"
243 # Topology information
244 cli_print_fmt1
2 "Topology changing" \
245 "$(stp_bridge_get_topology_change_detected ${zone})"
246 cli_print_fmt1
2 "Topology change time" \
247 "$(beautify_time $(stp_bridge_get_topology_change_timer ${zone}))"
248 cli_print_fmt1
2 "Topology change count" \
249 "$(stp_bridge_get_topology_change_count ${zone})"
252 cli_print
2 "Disabled"
256 cli_headline
2 "Ports"
257 zone_ports_status
"${zone}"
260 cli_headline
2 "Configurations"
261 zone_configs_cmd status
"${zone}"
271 case "$(hotplug_action)" in
273 # Attach all ports when zone is coming up
274 if hotplug_event_interface_is_zone
"${zone}"; then
277 for port
in $(zone_get_ports "${zone}"); do
278 log DEBUG
"Trying to attach port ${port} to ${zone}"
280 hook_port_up
"${zone}" "${port}"
283 # Handle ports of this zone that have just been added
284 elif hotplug_event_interface_is_port_of_zone
"${zone}"; then
285 # Attach the device if the parent bridge is up
286 if zone_is_active
"${zone}"; then
287 hook_port_up
"${zone}" "${INTERFACE}"
293 if hotplug_event_interface_is_zone
"${zone}"; then
294 # Bring down/destroy all ports
296 for port
in $(zone_get_ports "${zone}"); do
297 log DEBUG
"Trying to detach port ${port} from ${zone}"
299 hook_port_down
"${zone}" "${port}"
302 # Handle ports of this zone that have just been removed
303 elif hotplug_event_interface_is_port_of_zone
"${zone}"; then
304 hook_port_down
"${zone}" "${INTERFACE}"
309 exit ${EXIT_NOT_HANDLED}
316 hook_check_port_settings
() {
318 assert isinteger COST
321 if isset PRIORITY
; then
322 assert isinteger PRIORITY
327 # Excepting at least two arguments here
334 if zone_has_port
"${zone}" "${port}"; then
335 zone_port_settings_read
"${zone}" "${port}"
343 COST
="$(cli_get_val "${arg}")"
346 PRIORITY
="$(cli_get_val "${arg}")"
349 done <<< "$(args "$@")"
351 if ! zone_port_settings_write
"${zone}" "${port}"; then
364 # Shut down the port (if possible)
367 if ! zone_port_settings_remove
"${zone}" "${port}"; then
375 hook_port_attach
"$@"
384 # Try bringing up the port if it has not been
386 # We will get here as soon as the port device has
387 # been created and will then connect it with the bridge.
388 if ! device_exists
"${port}"; then
389 port_create
"${port}"
394 # Read configuration values
395 zone_port_settings_read
"${zone}" "${port}" ${HOOK_PORT_SETTINGS}
397 # Make sure that the port is up
400 # Attach the port to the bridge
401 bridge_attach_device
"${zone}" "${port}"
403 # Set STP configuration
405 stp_port_set_cost
"${zone}" "${port}" "${COST}"
408 if isset PRIORITY
; then
409 stp_port_set_priority
"${zone}" "${port}" "${PRIORITY}"
421 if device_exists
"${port}"; then
422 bridge_detach_device
"${zone}" "${port}"
436 # Do nothing for devices which are not up and running.
437 device_exists
"${port}" || exit ${EXIT_OK}
441 # Check if the device is down.
442 if ! device_is_up
"${port}"; then
443 status
="${MSG_DEVICE_STATUS_DOWN}"
445 # Check if the device has no carrier.
446 elif ! device_has_carrier
"${port}"; then
447 status
="${MSG_DEVICE_STATUS_NOCARRIER}"
449 # Check for STP information.
450 elif stp_is_enabled
"${zone}"; then
451 local state
="$(stp_port_get_state "${zone}" "${port}")"
452 state
="MSG_STP_${state}"
455 status
="${status} - DSR: $(stp_port_get_designated_root "${zone}" "${port}")"
456 status
="${status} - Cost: $(stp_port_get_cost "${zone}" "${port}")"
458 status
="${MSG_DEVICE_STATUS_UP}"
460 cli_statusline
3 "${port}" "${status}"