]> git.ipfire.org Git - people/stevee/network.git/blob - src/functions/functions.ports
port: Don't destroy if it could not be shut down
[people/stevee/network.git] / src / functions / functions.ports
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
22 port_dir() {
23 local port="${1}"
24 echo "${NETWORK_CONFIG_DIR}/ports/${port}"
25 }
26
27 port_list() {
28 local port
29 for port in $(port_dir)/*; do
30 port="$(basename "${port}")"
31 if port_exists "${port}"; then
32 print "${port}"
33 fi
34 done
35 }
36
37 port_list_in_use() {
38 local ports_in_use
39
40 # Collect all ports that are attached to a zone
41 local zone
42 for zone in $(zones_get_all); do
43 list_append ports_in_use $(zone_get_ports "${zone}")
44 done
45
46 # Collect all ports that are enslaved by an other port
47 local port
48 for port in $(port_list); do
49 list_append ports_in_use $(port_get_slaves "${port}")
50 done
51
52 list_sort ${ports_in_use}
53 }
54
55 port_list_free() {
56 local ports_in_use="$(port_list_in_use)"
57
58 local port
59 for port in $(port_list); do
60 if ! list_match "${port}" ${ports_in_use}; then
61 print "${port}"
62 fi
63 done
64
65 return ${EXIT_OK}
66 }
67
68 port_get_hook() {
69 local port=${1}
70 assert isset port
71
72 config_get_hook $(port_file ${port})
73 }
74
75 port_config_dir() {
76 local port=${1}
77
78 print "${RUN_DIR}/ports/${port}"
79 return ${EXIT_OK}
80 }
81
82 port_settings_read() {
83 local port="${1}"
84 assert isset port
85
86 # Save the HOOK variable.
87 local hook="${HOOK}"
88
89 settings_read "$(port_file "${port}")" ${HOOK_SETTINGS}
90
91 # Restore hook.
92 HOOK="${hook}"
93 }
94
95 port_settings_write() {
96 local port="${1}"
97 assert isset port
98 shift
99
100 local args
101 if function_exists "hook_check_settings"; then
102 list_append args "--check=\"hook_check_settings\""
103 fi
104 list_append args ${HOOK_SETTINGS}
105
106 settings_write "$(port_file "${port}")" ${args}
107 }
108
109 ports_get_all() {
110 port_list
111 }
112
113 port_file() {
114 local port="${1}"
115 assert isset port
116
117 echo "$(port_dir ${port})/settings"
118 }
119
120 port_exists() {
121 local port=${1}
122
123 [ -d "${NETWORK_CONFIG_DIR}/ports/${port}" ]
124 }
125
126 port_get_hook() {
127 local port=${1}
128
129 assert isset port
130
131 config_get_hook $(port_file ${port})
132 }
133
134 port_is_attached() {
135 local port=${1}
136 shift
137
138 assert isset port
139
140 local zone
141 for zone in $(zones_get_all); do
142 if list_match ${port} $(zone_get_ports ${zone}); then
143 echo "${zone}"
144 return ${EXIT_OK}
145 fi
146 done
147
148 return ${EXIT_ERROR}
149 }
150
151 port_is_up() {
152 device_is_up $@
153 }
154
155 port_new() {
156 local hook="${1}"
157 shift
158
159 if ! hook_exists port "${hook}"; then
160 error "Port hook '${hook}' does not exist."
161 return ${EXIT_ERROR}
162 fi
163
164 hook_exec port "${hook}" new $@
165 }
166
167 port_destroy() {
168 local port=${1}
169 assert isset port
170
171 # Cannot delete a port that does not exist
172 if ! port_exists ${port}; then
173 error "No such port: ${port}"
174 return ${EXIT_ERROR}
175 fi
176
177 local attached_zone=$(port_is_attached ${port})
178 if [ -n "${attached_zone}" ]; then
179 if ! zone_port_detach "${attached_zone}" "${port}"; then
180 error "Could not remove port ${port} from zone ${zone}"
181 return ${EXIT_ERROR}
182 fi
183 fi
184
185 # Check if the port is linked to any other port and don't allow the user
186 # to delete it.
187 local other_port
188 for other_port in $(ports_get); do
189 [ "${other_port}" = "${port}" ] && continue
190
191 if list_match ${port} $(port_get_children ${other_port}); then
192 log ERROR "Cannot destroy port '${port}' which is child of port '${other_port}'."
193 return ${EXIT_ERROR}
194 fi
195 done
196
197 # Shut down the port before destroying it
198 if ! port_remove "${port}"; then
199 return ${EXIT_ERROR}
200 fi
201
202 rm -rf $(port_dir ${port})
203 }
204
205 port_create() {
206 port_cmd "create" $@
207 }
208
209 port_remove() {
210 local port="${1}"
211 assert isset port
212
213 if ! port_exists "${port}"; then
214 log ERROR "Port ${port} does not exist"
215 return ${EXIT_ERROR}
216 fi
217
218 # If the device is still up, we need to bring it down first.
219 if device_is_up "${port}"; then
220 port_down "${port}"
221 fi
222
223 port_cmd "remove" "${port}"
224 }
225
226 # Restarts the port by removing it and then re-creating it
227 port_restart() {
228 local port="${1}"
229 assert isset port
230
231 port_remove "${port}"
232
233 port_create "${port}"
234 }
235
236 port_edit() {
237 port_cmd edit $@
238 }
239
240 port_up() {
241 port_cmd up $@
242 }
243
244 port_down() {
245 port_cmd down $@
246 }
247
248 port_status() {
249 port_cmd status $@
250 }
251
252 port_cmd() {
253 local cmd=${1}
254 local port=${2}
255 shift 2
256
257 assert isset cmd
258 assert isset port
259
260 local hook=$(port_get_hook ${port})
261
262 # Abort if we could not find a hook
263 if ! isset hook; then
264 log CRITICAL "Port ${port} does not have a hook associated with it"
265 return ${EXIT_ERROR}
266 fi
267
268 hook_exec port ${hook} ${cmd} ${port} $@
269 }
270
271 ports_get() {
272 local port
273 for port in $(port_dir)/*; do
274 port=$(basename ${port})
275 if port_exists ${port}; then
276 echo "${port}"
277 fi
278 done
279 }
280
281 port_find_free() {
282 local pattern=${1}
283
284 assert isset pattern
285
286 local port
287 local i=0
288
289 while [ ${i} -lt 99 ]; do
290 port=${pattern//N/${i}}
291 if ! port_exists ${port} && ! device_exists ${port}; then
292 echo "${port}"
293 return ${EXIT_OK}
294 fi
295 i=$(( ${i} + 1 ))
296 done
297
298 return ${EXIT_ERROR}
299 }
300
301 port_get_children() {
302 local port=${1}
303
304 assert port_exists "${port}"
305
306 port_cmd "children" "${port}"
307 }
308
309 port_zone() {
310 # Get name of the zones, this port is configured in.
311 local port=${1}
312 shift
313
314 assert isset port
315
316 local zone
317 for zone in $(zones_get_all); do
318 if zone_has_port ${zone} ${port}; then
319 echo "${zone}"
320 return ${EXIT_OK}
321 fi
322 done
323
324 return ${EXIT_OK}
325 }
326
327 port_hotplug_event() {
328 local port="${1}"
329 assert isset port
330
331 hotplug_assert_in_hotplug_event
332
333 port_cmd "hotplug" "${port}"
334 }
335
336 port_get_slaves() {
337 local port="${1}"
338
339 port_settings_read "${port}" \
340 --ignore-superfluous-settings SLAVES
341 print "${SLAVES}"
342 }
343
344 port_device_is_slave() {
345 assert [ $# -eq 2 ]
346
347 local port="${1}"
348 local device="${2}"
349
350 # Get slaves of port
351 local slaves="$(port_get_slaves "${port}")"
352
353 # Returns true if device is in slaves
354 list_match "${device}" ${slaves}
355 }
356
357 port_get_phy() {
358 local port="${1}"
359
360 port_settings_read "${port}" \
361 --ignore-superfluous-settings PHY
362 print "${PHY}"
363 }
364
365 port_uses_phy() {
366 assert [ $# -eq 2 ]
367
368 local port="${1}"
369 local phy="${2}"
370
371 # Nothing to do if an empty argument is given
372 if ! isset phy; then
373 return ${EXIT_FALSE}
374 fi
375
376 phy="$(phy_get_address "${phy}")"
377
378 local port_phy="$(port_get_phy "${port}")"
379 [ "${port_phy}" = "${phy}" ]
380 }
381
382 ports_lowest_address() {
383 local address
384 local addresses
385
386 local port
387 for port in $(port_list); do
388 # Skip all ports that do not exist
389 # any more or are not plugged in
390 device_exists "${port}" || continue
391
392 # Skip all ports that are not proper ethernet devices
393 device_is_wireless "${port}" && continue
394 device_is_ethernet "${port}" || continue
395
396 list_append addresses "$(device_get_address "${port}")"
397 done
398
399 # Sort the list
400 addresses="$(list_sort ${addresses})"
401
402 # Get the first element which is the lowest MAC address
403 list_head ${addresses}
404 }
405
406 port_identify() {
407 device_identify $@
408 }
409
410 port_get_color() {
411 # This function return the color of a port
412 assert [ $# -eq 1 ]
413
414 local name=${1}
415 color_read "port" ${name}
416 }
417
418 port_get_description_title() {
419 assert [ $# -eq 1 ]
420
421 local name=${1}
422 description_title_read $(description_format_filename "port" "${name}")
423 }