]> git.ipfire.org Git - people/stevee/network.git/blame - src/hooks/zones/bridge
Convert HOOK_SETTINGS into an array
[people/stevee/network.git] / src / hooks / zones / bridge
CommitLineData
1848564d
MT
1#!/bin/bash
2###############################################################################
3# #
4# IPFire.org - A linux based firewall #
5# Copyright (C) 2010 Michael Tremer & Christian Schmidt #
6# #
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. #
11# #
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. #
16# #
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/>. #
19# #
20###############################################################################
21
e2aa12b3 22. /usr/lib/network/header-zone
1848564d 23
de125810
MT
24HOOK_MANPAGE="network-zone-bridge"
25
d389e96b
MT
26HOOK_SETTINGS=(
27 "ADDRESS"
28 "STP"
29 "STP_FORWARD_DELAY"
30 "STP_HELLO STP_MAXAGE"
31 "STP_PRIORITY"
32 "MTU"
33)
34
35HOOK_PORT_SETTINGS=(
36 "COST"
37 "PRIORITY"
38)
828eb94a 39
1848564d 40# Default values
53e764a7 41DEFAULT_STP="on"
c259c985
MT
42DEFAULT_STP_FORWARD_DELAY=0
43DEFAULT_STP_HELLO=2
44DEFAULT_STP_MAXAGE=20
45DEFAULT_STP_PRIORITY=512
1848564d 46
1c6a4e30 47hook_check_settings() {
b99bbd83 48 assert ismac ADDRESS
d95e2fdc 49 assert isset MTU && assert mtu_is_valid "ethernet" "${MTU}"
b99bbd83
MT
50
51 # Spanning Tree Protocol
1848564d
MT
52 assert isbool STP
53 assert isinteger STP_HELLO
54 assert isinteger STP_FORWARD_DELAY
d82cf370 55 assert isinteger STP_PRIORITY
1848564d
MT
56}
57
1c6a4e30 58hook_parse_cmdline() {
1848564d
MT
59 while [ $# -gt 0 ]; do
60 case "${1}" in
b99bbd83
MT
61 --address=*)
62 ADDRESS="$(cli_get_val "${1}")"
63
64 if ! mac_is_valid "${ADDRESS}"; then
65 error "Invalid MAC address: ${ADDRESS}"
66 return ${EXIT_ERROR}
67 fi
68 ;;
69
70 --mtu=*)
71 MTU="$(cli_get_val "${1}")"
72
73 if ! mtu_is_valid "ethernet" "${MTU}"; then
74 error "Invalid MTU: ${MTU}"
75 return ${EXIT_ERROR}
76 fi
77 ;;
78
1848564d 79 --stp=*)
b99bbd83
MT
80 STP="$(cli_get_val "${1}")"
81
82 if enabled STP; then
83 STP="on"
84 elif disabled STP; then
85 STP="off"
86 else
87 error "Invalid value for STP: ${STP}"
88 return ${EXIT_ERROR}
89 fi
1848564d 90 ;;
b99bbd83 91
b76b7d88
MT
92 --stp-forward-delay=*)
93 STP_FORWARD_DELAY="$(cli_get_val "${1}")"
b99bbd83 94
b76b7d88
MT
95 if ! isinteger STP_FORWARD_DELAY; then
96 error "Invalid STP forwarding delay: ${STP_FORWARD_DELAY}"
b99bbd83
MT
97 return ${EXIT_ERROR}
98 fi
1848564d 99 ;;
b99bbd83 100
b76b7d88
MT
101 --stp-hello=*)
102 STP_HELLO="$(cli_get_val "${1}")"
b99bbd83 103
b76b7d88
MT
104 if ! isinteger STP_HELLO; then
105 error "Invalid STP hello time: ${STP_HELLO}"
b99bbd83
MT
106 return ${EXIT_ERROR}
107 fi
0f8d4705
MT
108 ;;
109
110 --stp-max-age=*)
111 STP_MAXAGE="$(cli_get_val "${1}")"
112
113 if ! isinteger STP_MAXAGE; then
114 error "Invalid STP max age: ${STP_MAXAGE}"
115 return ${EXIT_ERROR}
116 fi
1848564d 117 ;;
b99bbd83 118
d82cf370 119 --stp-priority=*)
b99bbd83
MT
120 STP_PRIORITY="$(cli_get_val "${1}")"
121
122 if ! isinteger STP_PRIORITY; then
123 error "Invalid STP priority: ${STP_PRIORITY}"
124 return ${EXIT_ERROR}
125 fi
1848564d 126 ;;
b99bbd83 127
1848564d 128 *)
b99bbd83
MT
129 error "Unknown argument: ${1}"
130 return ${EXIT_ERROR}
1848564d
MT
131 ;;
132 esac
133 shift
134 done
0430028a 135
53e764a7 136 # Generate a random MAC address if the user passed none
c259c985 137 if ! isset ADDRESS; then
b99bbd83
MT
138 ADDRESS="$(mac_generate)"
139 fi
140
141 return ${EXIT_OK}
1848564d
MT
142}
143
1c6a4e30 144hook_up() {
1848564d 145 local zone=${1}
99be6026 146 assert isset zone
1848564d 147
1e6f187e 148 zone_settings_read "${zone}"
1848564d 149
99be6026 150 # Create the bridge if it does not already exist.
2a969c27
MT
151 if ! device_exists "${zone}"; then
152 bridge_create "${zone}" \
b99bbd83 153 --address="${ADDRESS}" \
2a969c27 154 --mtu="${MTU}"
99be6026 155 fi
1848564d
MT
156
157 # Enable STP
158 if enabled STP; then
2a969c27 159 stp_enable "${zone}"
1848564d 160
2a969c27
MT
161 if isset STP_FORWARD_DELAY; then
162 stp_bridge_set_forward_delay "${zone}" "${STP_FORWARD_DELAY}"
1848564d
MT
163 fi
164
2a969c27
MT
165 if isset STP_HELLO; then
166 stp_bridge_set_hello_time "${zone}" "${STP_HELLO}"
1848564d
MT
167 fi
168
2a969c27
MT
169 if isset STP_MAXAGE; then
170 stp_bridge_set_max_age "${zone}" "${STP_MAXAGE}"
1848564d 171 fi
d82cf370 172
2a969c27
MT
173 if isset STP_PRIORITY; then
174 stp_bridge_set_priority "${zone}" "${STP_PRIORITY}"
d82cf370 175 fi
1848564d 176 else
2a969c27 177 stp_disable "${zone}"
1848564d
MT
178 fi
179
2a969c27 180 device_set_up "${zone}"
1848564d 181
cf6e4606
MT
182 # XXX Currently, there is a bug (in the linux kernel?) that we need to
183 # set our bridges to promisc mode.
2a969c27
MT
184 device_set_promisc "${zone}" on
185
2a969c27
MT
186 # Bring up all configurations
187 zone_configs_up "${zone}"
188
189 exit ${EXIT_OK}
190}
191
1c6a4e30 192hook_down() {
2a969c27 193 local zone="${1}"
99be6026 194 assert isset zone
1848564d 195
2a969c27 196 if ! device_is_up "${zone}"; then
1848564d
MT
197 warning "Zone '${zone}' is not up"
198 exit ${EXIT_OK}
199 fi
200
2a969c27
MT
201 # Stop all the configs.
202 zone_configs_down "${zone}"
1848564d 203
2a969c27
MT
204 # Bring down all the ports.
205 zone_ports_down "${zone}"
1ba6a2bb 206 zone_ports_remove "${zone}"
cf6e4606 207
2a969c27
MT
208 # Remove the bridge.
209 device_set_down "${zone}"
210 bridge_delete "${zone}"
1848564d 211
8dcb2687 212 exit ${EXIT_OK}
1848564d
MT
213}
214
1c6a4e30 215hook_status() {
2a969c27 216 local zone="${1}"
3cb2fc42 217 assert isset zone
e84e4e76 218
3cb2fc42 219 # Print the default header.
2a969c27 220 cli_device_headline "${zone}"
e84e4e76
MT
221
222 # Exit if zone is down
2a969c27 223 if ! zone_is_up "${zone}"; then
e84e4e76
MT
224 echo # Empty line
225 exit ${EXIT_ERROR}
226 fi
227
3cb2fc42 228 cli_headline 2 "Spanning Tree Protocol information"
2a969c27 229 if stp_is_enabled "${zone}"; then
3cb2fc42
MT
230 cli_print_fmt1 2 "ID" "$(stp_bridge_get_id ${zone})"
231 cli_print_fmt1 2 "Priority" "$(stp_bridge_get_priority ${zone})"
36e3fd2f
MT
232
233 if stp_bridge_is_root ${zone}; then
3cb2fc42 234 cli_print 2 "This bridge is root."
36e3fd2f 235 else
3cb2fc42
MT
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})"
36e3fd2f 240 fi
3cb2fc42 241 cli_space
feb76eaf 242
36e3fd2f 243 # Topology information
3cb2fc42
MT
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})"
250 cli_space
feb76eaf 251 else
3cb2fc42
MT
252 cli_print 2 "Disabled"
253 cli_space
feb76eaf 254 fi
e84e4e76 255
50250b79 256 cli_headline 2 "Ports"
2a969c27 257 zone_ports_status "${zone}"
8e3508ac 258 cli_space
e84e4e76 259
50250b79 260 cli_headline 2 "Configurations"
2a969c27 261 zone_configs_cmd status "${zone}"
3cb2fc42 262 cli_space
8e3508ac 263
e84e4e76
MT
264 exit ${EXIT_OK}
265}
828eb94a 266
1fc4b3ca
MT
267hook_hotplug() {
268 local zone="${1}"
269 assert isset zone
270
271 case "$(hotplug_action)" in
272 add)
273 # Attach all ports when zone is coming up
274 if hotplug_event_interface_is_zone "${zone}"; then
275 # Bring up all ports
276 local port
277 for port in $(zone_get_ports "${zone}"); do
278 log DEBUG "Trying to attach port ${port} to ${zone}"
279
280 hook_port_up "${zone}" "${port}"
281 done
282
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}"
288 fi
289 fi
290 ;;
291
292 remove)
293 if hotplug_event_interface_is_zone "${zone}"; then
294 # Bring down/destroy all ports
295 local port
296 for port in $(zone_get_ports "${zone}"); do
297 log DEBUG "Trying to detach port ${port} from ${zone}"
298
299 hook_port_down "${zone}" "${port}"
300 done
301
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}"
305 fi
306 ;;
307
308 *)
309 exit ${EXIT_NOT_HANDLED}
310 ;;
311 esac
312
313 exit ${EXIT_OK}
314}
315
1c6a4e30 316hook_check_port_settings() {
ac694a6a
MT
317 if isset COST; then
318 assert isinteger COST
319 fi
828eb94a 320
ac694a6a
MT
321 if isset PRIORITY; then
322 assert isinteger PRIORITY
323 fi
828eb94a
MT
324}
325
1c6a4e30 326hook_port_attach() {
828eb94a
MT
327 # Excepting at least two arguments here
328 assert [ $# -ge 2 ]
329
330 local zone="${1}"
331 local port="${2}"
332 shift 2
333
ac694a6a
MT
334 if zone_has_port "${zone}" "${port}"; then
335 zone_port_settings_read "${zone}" "${port}"
336 fi
828eb94a 337
ac694a6a
MT
338 local arg
339 local val
340 while read arg; do
341 case "${arg}" in
342 --cost=*)
343 COST="$(cli_get_val "${arg}")"
344 ;;
345 --priority=*)
346 PRIORITY="$(cli_get_val "${arg}")"
347 ;;
348 esac
2212045f 349 done <<< "$(args "$@")"
828eb94a 350
ac694a6a
MT
351 if ! zone_port_settings_write "${zone}" "${port}"; then
352 exit ${EXIT_ERROR}
353 fi
828eb94a
MT
354
355 exit ${EXIT_OK}
356}
357
1c6a4e30 358hook_port_detach() {
828eb94a
MT
359 assert [ $# -eq 2 ]
360
361 local zone="${1}"
362 local port="${2}"
363
364 # Shut down the port (if possible)
365 port_down "${port}"
366
ac694a6a
MT
367 if ! zone_port_settings_remove "${zone}" "${port}"; then
368 exit ${EXIT_ERROR}
369 fi
828eb94a
MT
370
371 exit ${EXIT_OK}
372}
373
1c6a4e30 374hook_port_edit() {
2212045f 375 hook_port_attach "$@"
ac694a6a
MT
376}
377
1c6a4e30 378hook_port_up() {
828eb94a
MT
379 assert [ $# -eq 2 ]
380
381 local zone="${1}"
382 local port="${2}"
383
2a969c27
MT
384 # Try bringing up the port if it has not been
385 # brought up before.
386 # We will get here as soon as the port device has
387 # been created and will then connect it with the bridge.
3ee5ccb1 388 if ! device_exists "${port}"; then
75985eb1 389 port_create "${port}"
2a969c27 390
9b47451e 391 return ${EXIT_OK}
3ee5ccb1
MT
392 fi
393
394 # Read configuration values
395 zone_port_settings_read "${zone}" "${port}" ${HOOK_PORT_SETTINGS}
828eb94a 396
8707df4b
MT
397 # Make sure that the port is up
398 port_up "${port}"
399
3ee5ccb1 400 # Attach the port to the bridge
828eb94a
MT
401 bridge_attach_device "${zone}" "${port}"
402
3ee5ccb1 403 # Set STP configuration
2c083d57
MT
404 if isset COST; then
405 stp_port_set_cost "${zone}" "${port}" "${COST}"
406 fi
407
424b8280
MT
408 if isset PRIORITY; then
409 stp_port_set_priority "${zone}" "${port}" "${PRIORITY}"
410 fi
828eb94a 411
9b47451e 412 return ${EXIT_OK}
828eb94a
MT
413}
414
1c6a4e30 415hook_port_down() {
828eb94a
MT
416 assert [ $# -eq 2 ]
417
418 local zone="${1}"
419 local port="${2}"
420
2a969c27
MT
421 if device_exists "${port}"; then
422 bridge_detach_device "${zone}" "${port}"
828eb94a 423
2a969c27
MT
424 port_down "${port}"
425 fi
828eb94a 426
9b47451e 427 return ${EXIT_OK}
828eb94a
MT
428}
429
1c6a4e30 430hook_port_status() {
828eb94a
MT
431 assert [ $# -eq 2 ]
432
433 local zone="${1}"
434 local port="${2}"
435
436 # Do nothing for devices which are not up and running.
437 device_exists "${port}" || exit ${EXIT_OK}
438
439 local status
440
441 # Check if the device is down.
442 if ! device_is_up "${port}"; then
443 status="${MSG_DEVICE_STATUS_DOWN}"
444
445 # Check if the device has no carrier.
446 elif ! device_has_carrier "${port}"; then
447 status="${MSG_DEVICE_STATUS_NOCARRIER}"
448
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}"
453 status="${!state}"
454
455 status="${status} - DSR: $(stp_port_get_designated_root "${zone}" "${port}")"
456 status="${status} - Cost: $(stp_port_get_cost "${zone}" "${port}")"
457 else
458 status="${MSG_DEVICE_STATUS_UP}"
459 fi
460 cli_statusline 3 "${port}" "${status}"
461
462 exit ${EXIT_OK}
463}