]>
Commit | Line | Data |
---|---|---|
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 |
24 | HOOK_MANPAGE="network-zone-bridge" |
25 | ||
4e0bc093 | 26 | HOOK_SETTINGS="HOOK STP STP_FORWARD_DELAY STP_HELLO STP_MAXAGE" |
6b3f9c85 | 27 | HOOK_SETTINGS="${HOOK_SETTINGS} STP_PRIORITY MAC MTU" |
1848564d | 28 | |
828eb94a MT |
29 | HOOK_PORT_SETTINGS="COST PRIORITY" |
30 | ||
1848564d | 31 | # Default values |
0430028a | 32 | MAC="" |
1848564d MT |
33 | MTU=1500 |
34 | STP="on" | |
35 | STP_FORWARD_DELAY=0 | |
36 | STP_HELLO=2 | |
37 | STP_MAXAGE=20 | |
e266c18e | 38 | STP_PRIORITY=512 |
1848564d | 39 | |
1c6a4e30 | 40 | hook_check_settings() { |
1848564d MT |
41 | assert ismac MAC |
42 | assert isbool STP | |
43 | assert isinteger STP_HELLO | |
44 | assert isinteger STP_FORWARD_DELAY | |
d82cf370 | 45 | assert isinteger STP_PRIORITY |
1848564d MT |
46 | assert isinteger MTU |
47 | } | |
48 | ||
1c6a4e30 | 49 | hook_parse_cmdline() { |
1848564d MT |
50 | while [ $# -gt 0 ]; do |
51 | case "${1}" in | |
52 | --stp=*) | |
53 | STP=${1#--stp=} | |
54 | ;; | |
55 | --stp-hello=*) | |
56 | STP_HELLO=${1#--stp-hello=} | |
57 | ;; | |
58 | --stp-forward-delay=*) | |
59 | STP_FORWARD_DELAY=${1#--stp-forward-delay=} | |
60 | ;; | |
d82cf370 MT |
61 | --stp-priority=*) |
62 | STP_PRIORITY=${1#--stp-priority=} | |
63 | ;; | |
1848564d MT |
64 | --mtu=*) |
65 | MTU=${1#--mtu=} | |
66 | ;; | |
67 | --mac=*) | |
68 | MAC=${1#--mac=} | |
69 | ;; | |
70 | *) | |
71 | warning "Ignoring unknown option '${1}'" | |
72 | ;; | |
73 | esac | |
74 | shift | |
75 | done | |
0430028a MT |
76 | |
77 | # Generate a random MAC address if the user passed no one | |
78 | isset MAC || MAC="$(mac_generate)" | |
1848564d MT |
79 | } |
80 | ||
1c6a4e30 | 81 | hook_up() { |
1848564d | 82 | local zone=${1} |
99be6026 | 83 | assert isset zone |
1848564d | 84 | |
1e6f187e | 85 | zone_settings_read "${zone}" |
1848564d | 86 | |
99be6026 | 87 | # Create the bridge if it does not already exist. |
2a969c27 MT |
88 | if ! device_exists "${zone}"; then |
89 | bridge_create "${zone}" \ | |
90 | --address="${MAC}" \ | |
91 | --mtu="${MTU}" | |
99be6026 | 92 | fi |
1848564d MT |
93 | |
94 | # Enable STP | |
95 | if enabled STP; then | |
2a969c27 | 96 | stp_enable "${zone}" |
1848564d | 97 | |
2a969c27 MT |
98 | if isset STP_FORWARD_DELAY; then |
99 | stp_bridge_set_forward_delay "${zone}" "${STP_FORWARD_DELAY}" | |
1848564d MT |
100 | fi |
101 | ||
2a969c27 MT |
102 | if isset STP_HELLO; then |
103 | stp_bridge_set_hello_time "${zone}" "${STP_HELLO}" | |
1848564d MT |
104 | fi |
105 | ||
2a969c27 MT |
106 | if isset STP_MAXAGE; then |
107 | stp_bridge_set_max_age "${zone}" "${STP_MAXAGE}" | |
1848564d | 108 | fi |
d82cf370 | 109 | |
2a969c27 MT |
110 | if isset STP_PRIORITY; then |
111 | stp_bridge_set_priority "${zone}" "${STP_PRIORITY}" | |
d82cf370 | 112 | fi |
1848564d | 113 | else |
2a969c27 | 114 | stp_disable "${zone}" |
1848564d MT |
115 | fi |
116 | ||
2a969c27 | 117 | device_set_up "${zone}" |
1848564d | 118 | |
cf6e4606 MT |
119 | # XXX Currently, there is a bug (in the linux kernel?) that we need to |
120 | # set our bridges to promisc mode. | |
2a969c27 MT |
121 | device_set_promisc "${zone}" on |
122 | ||
123 | # Bring up all ports | |
1ba6a2bb | 124 | zone_ports_create "${zone}" |
2a969c27 MT |
125 | zone_ports_up "${zone}" |
126 | ||
127 | # Bring up all configurations | |
128 | zone_configs_up "${zone}" | |
129 | ||
130 | exit ${EXIT_OK} | |
131 | } | |
132 | ||
1c6a4e30 | 133 | hook_hotplug() { |
2a969c27 MT |
134 | local zone="${1}" |
135 | assert isset zone | |
cf6e4606 | 136 | |
2a969c27 MT |
137 | case "$(hotplug_action)" in |
138 | add) | |
139 | # Handle ports of this zone that have just been added | |
140 | if hotplug_event_interface_is_port_of_zone "${zone}"; then | |
eaa34bff MT |
141 | # Attach the device if the parent bridge is up |
142 | if zone_is_active "${zone}"; then | |
143 | hook_port_up "${zone}" "${INTERFACE}" | |
2a969c27 | 144 | fi |
2a969c27 MT |
145 | fi |
146 | ;; | |
147 | remove) | |
148 | # Handle ports of this zone that have just been removed | |
149 | if hotplug_event_interface_is_port_of_zone "${zone}"; then | |
150 | hook_port_down "${zone}" "${INTERFACE}" | |
151 | fi | |
152 | ;; | |
153 | *) | |
154 | exit ${EXIT_NOT_HANDLED} | |
155 | ;; | |
156 | esac | |
1848564d | 157 | |
8dcb2687 | 158 | exit ${EXIT_OK} |
1848564d MT |
159 | } |
160 | ||
1c6a4e30 | 161 | hook_down() { |
2a969c27 | 162 | local zone="${1}" |
99be6026 | 163 | assert isset zone |
1848564d | 164 | |
2a969c27 | 165 | if ! device_is_up "${zone}"; then |
1848564d MT |
166 | warning "Zone '${zone}' is not up" |
167 | exit ${EXIT_OK} | |
168 | fi | |
169 | ||
2a969c27 MT |
170 | # Stop all the configs. |
171 | zone_configs_down "${zone}" | |
1848564d | 172 | |
2a969c27 MT |
173 | # Bring down all the ports. |
174 | zone_ports_down "${zone}" | |
1ba6a2bb | 175 | zone_ports_remove "${zone}" |
cf6e4606 | 176 | |
2a969c27 MT |
177 | # Remove the bridge. |
178 | device_set_down "${zone}" | |
179 | bridge_delete "${zone}" | |
1848564d | 180 | |
8dcb2687 | 181 | exit ${EXIT_OK} |
1848564d MT |
182 | } |
183 | ||
1c6a4e30 | 184 | hook_status() { |
2a969c27 | 185 | local zone="${1}" |
3cb2fc42 | 186 | assert isset zone |
e84e4e76 | 187 | |
3cb2fc42 | 188 | # Print the default header. |
2a969c27 | 189 | cli_device_headline "${zone}" |
e84e4e76 MT |
190 | |
191 | # Exit if zone is down | |
2a969c27 | 192 | if ! zone_is_up "${zone}"; then |
e84e4e76 MT |
193 | echo # Empty line |
194 | exit ${EXIT_ERROR} | |
195 | fi | |
196 | ||
3cb2fc42 | 197 | cli_headline 2 "Spanning Tree Protocol information" |
2a969c27 | 198 | if stp_is_enabled "${zone}"; then |
3cb2fc42 MT |
199 | cli_print_fmt1 2 "ID" "$(stp_bridge_get_id ${zone})" |
200 | cli_print_fmt1 2 "Priority" "$(stp_bridge_get_priority ${zone})" | |
36e3fd2f MT |
201 | |
202 | if stp_bridge_is_root ${zone}; then | |
3cb2fc42 | 203 | cli_print 2 "This bridge is root." |
36e3fd2f | 204 | else |
3cb2fc42 MT |
205 | cli_print_fmt1 2 "Designated root" \ |
206 | "$(stp_bridge_get_designated_root ${zone})" | |
207 | cli_print_fmt1 2 "Root path cost" \ | |
208 | "$(stp_bridge_get_root_path_cost ${zone})" | |
36e3fd2f | 209 | fi |
3cb2fc42 | 210 | cli_space |
feb76eaf | 211 | |
36e3fd2f | 212 | # Topology information |
3cb2fc42 MT |
213 | cli_print_fmt1 2 "Topology changing" \ |
214 | "$(stp_bridge_get_topology_change_detected ${zone})" | |
215 | cli_print_fmt1 2 "Topology change time" \ | |
216 | "$(beautify_time $(stp_bridge_get_topology_change_timer ${zone}))" | |
217 | cli_print_fmt1 2 "Topology change count" \ | |
218 | "$(stp_bridge_get_topology_change_count ${zone})" | |
219 | cli_space | |
feb76eaf | 220 | else |
3cb2fc42 MT |
221 | cli_print 2 "Disabled" |
222 | cli_space | |
feb76eaf | 223 | fi |
e84e4e76 | 224 | |
50250b79 | 225 | cli_headline 2 "Ports" |
2a969c27 | 226 | zone_ports_status "${zone}" |
8e3508ac | 227 | cli_space |
e84e4e76 | 228 | |
50250b79 | 229 | cli_headline 2 "Configurations" |
2a969c27 | 230 | zone_configs_cmd status "${zone}" |
3cb2fc42 | 231 | cli_space |
8e3508ac | 232 | |
e84e4e76 MT |
233 | exit ${EXIT_OK} |
234 | } | |
828eb94a | 235 | |
1c6a4e30 | 236 | hook_check_port_settings() { |
ac694a6a MT |
237 | if isset COST; then |
238 | assert isinteger COST | |
239 | fi | |
828eb94a | 240 | |
ac694a6a MT |
241 | if isset PRIORITY; then |
242 | assert isinteger PRIORITY | |
243 | fi | |
828eb94a MT |
244 | } |
245 | ||
1c6a4e30 | 246 | hook_port_attach() { |
828eb94a MT |
247 | # Excepting at least two arguments here |
248 | assert [ $# -ge 2 ] | |
249 | ||
250 | local zone="${1}" | |
251 | local port="${2}" | |
252 | shift 2 | |
253 | ||
ac694a6a MT |
254 | if zone_has_port "${zone}" "${port}"; then |
255 | zone_port_settings_read "${zone}" "${port}" | |
256 | fi | |
828eb94a | 257 | |
ac694a6a MT |
258 | local arg |
259 | local val | |
260 | while read arg; do | |
261 | case "${arg}" in | |
262 | --cost=*) | |
263 | COST="$(cli_get_val "${arg}")" | |
264 | ;; | |
265 | --priority=*) | |
266 | PRIORITY="$(cli_get_val "${arg}")" | |
267 | ;; | |
268 | esac | |
2212045f | 269 | done <<< "$(args "$@")" |
828eb94a | 270 | |
ac694a6a MT |
271 | if ! zone_port_settings_write "${zone}" "${port}"; then |
272 | exit ${EXIT_ERROR} | |
273 | fi | |
828eb94a MT |
274 | |
275 | exit ${EXIT_OK} | |
276 | } | |
277 | ||
1c6a4e30 | 278 | hook_port_detach() { |
828eb94a MT |
279 | assert [ $# -eq 2 ] |
280 | ||
281 | local zone="${1}" | |
282 | local port="${2}" | |
283 | ||
284 | # Shut down the port (if possible) | |
285 | port_down "${port}" | |
286 | ||
ac694a6a MT |
287 | if ! zone_port_settings_remove "${zone}" "${port}"; then |
288 | exit ${EXIT_ERROR} | |
289 | fi | |
828eb94a MT |
290 | |
291 | exit ${EXIT_OK} | |
292 | } | |
293 | ||
1c6a4e30 | 294 | hook_port_edit() { |
2212045f | 295 | hook_port_attach "$@" |
ac694a6a MT |
296 | } |
297 | ||
1c6a4e30 | 298 | hook_port_up() { |
828eb94a MT |
299 | assert [ $# -eq 2 ] |
300 | ||
301 | local zone="${1}" | |
302 | local port="${2}" | |
303 | ||
2a969c27 MT |
304 | # Try bringing up the port if it has not been |
305 | # brought up before. | |
306 | # We will get here as soon as the port device has | |
307 | # been created and will then connect it with the bridge. | |
3ee5ccb1 | 308 | if ! device_exists "${port}"; then |
75985eb1 | 309 | port_create "${port}" |
2a969c27 | 310 | |
3ee5ccb1 MT |
311 | exit ${EXIT_OK} |
312 | fi | |
313 | ||
314 | # Read configuration values | |
315 | zone_port_settings_read "${zone}" "${port}" ${HOOK_PORT_SETTINGS} | |
828eb94a | 316 | |
3ee5ccb1 | 317 | # Attach the port to the bridge |
828eb94a MT |
318 | bridge_attach_device "${zone}" "${port}" |
319 | ||
3ee5ccb1 | 320 | # Set STP configuration |
2c083d57 MT |
321 | if isset COST; then |
322 | stp_port_set_cost "${zone}" "${port}" "${COST}" | |
323 | fi | |
324 | ||
424b8280 MT |
325 | if isset PRIORITY; then |
326 | stp_port_set_priority "${zone}" "${port}" "${PRIORITY}" | |
327 | fi | |
828eb94a | 328 | |
2a969c27 | 329 | # Make sure that the port is up |
1ba6a2bb | 330 | port_up "${port}" |
2a969c27 | 331 | |
828eb94a MT |
332 | exit ${EXIT_OK} |
333 | } | |
334 | ||
1c6a4e30 | 335 | hook_port_down() { |
828eb94a MT |
336 | assert [ $# -eq 2 ] |
337 | ||
338 | local zone="${1}" | |
339 | local port="${2}" | |
340 | ||
2a969c27 MT |
341 | if device_exists "${port}"; then |
342 | bridge_detach_device "${zone}" "${port}" | |
828eb94a | 343 | |
2a969c27 MT |
344 | port_down "${port}" |
345 | fi | |
828eb94a MT |
346 | |
347 | exit ${EXIT_OK} | |
348 | } | |
349 | ||
1c6a4e30 | 350 | hook_port_status() { |
828eb94a MT |
351 | assert [ $# -eq 2 ] |
352 | ||
353 | local zone="${1}" | |
354 | local port="${2}" | |
355 | ||
356 | # Do nothing for devices which are not up and running. | |
357 | device_exists "${port}" || exit ${EXIT_OK} | |
358 | ||
359 | local status | |
360 | ||
361 | # Check if the device is down. | |
362 | if ! device_is_up "${port}"; then | |
363 | status="${MSG_DEVICE_STATUS_DOWN}" | |
364 | ||
365 | # Check if the device has no carrier. | |
366 | elif ! device_has_carrier "${port}"; then | |
367 | status="${MSG_DEVICE_STATUS_NOCARRIER}" | |
368 | ||
369 | # Check for STP information. | |
370 | elif stp_is_enabled "${zone}"; then | |
371 | local state="$(stp_port_get_state "${zone}" "${port}")" | |
372 | state="MSG_STP_${state}" | |
373 | status="${!state}" | |
374 | ||
375 | status="${status} - DSR: $(stp_port_get_designated_root "${zone}" "${port}")" | |
376 | status="${status} - Cost: $(stp_port_get_cost "${zone}" "${port}")" | |
377 | else | |
378 | status="${MSG_DEVICE_STATUS_UP}" | |
379 | fi | |
380 | cli_statusline 3 "${port}" "${status}" | |
381 | ||
382 | exit ${EXIT_OK} | |
383 | } |