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