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