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