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