]> git.ipfire.org Git - people/arne_f/network.git/blob - functions.device
network: Enhanced the logging and did minor code cleanups.
[people/arne_f/network.git] / functions.device
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 function devicify() {
23 local device=${1}
24
25 if device_exists ${device}; then
26 echo "${device}"
27 return ${EXIT_OK}
28 fi
29
30 local d
31 for d in $(devices_get_all); do
32 if [ "$(device_get_address ${d})" = "${device}" ]; then
33 echo "${d}"
34 return ${EXIT_OK}
35 fi
36 done
37
38 return ${EXIT_ERROR}
39 }
40
41 function macify() {
42 local device=${1}
43
44 if mac_is_valid ${device}; then
45 echo "${device}"
46 return ${EXIT_OK}
47 fi
48
49 if device_exists ${device}; then
50 device_get_address ${device}
51 return ${EXIT_OK}
52 fi
53
54 return ${EXIT_ERROR}
55 }
56
57 # Check if the device exists
58 function device_exists() {
59 local device=${1}
60
61 # If device name was not found, exit.
62 [ -n "${device}" ] || return ${EXIT_ERROR}
63
64 [ -d "${SYS_CLASS_NET}/${device}" ]
65 }
66
67 # Check if the device is up
68 function device_is_up() {
69 local device=${1}
70
71 device_exists ${device} || return ${EXIT_ERROR}
72
73 ip link show ${device} 2>/dev/null | grep -qE "<.*UP.*>"
74 }
75
76 # Check if the device is a bonding device
77 function device_is_bonding() {
78 [ -d "/sys/class/net/${1}/bonding" ]
79 }
80
81 # Check if the device bonded in a bonding device
82 function device_is_bonded() {
83 local dev
84 for dev in /sys/class/net/*; do
85 # Skip crappy files
86 [ -d "${dev}" ] || continue
87
88 # Continue if not a bonding device
89 device_is_bonding "${dev##*/}" || continue
90
91 if grep -q "\<${1}\>" ${dev}/bonding/slaves; then
92 return 0
93 fi
94 done
95
96 return 1
97 }
98
99 # Check if the device is a bridge
100 function device_is_bridge() {
101 [ -d "/sys/class/net/${1}/bridge" ]
102 }
103
104 # Check if the device is a virtual device
105 function device_is_virtual() {
106 local device=${1}
107
108 [ -e "/proc/net/vlan/${device}" ]
109 }
110
111 # Check if the device has virtual devices
112 function device_has_virtuals() {
113 if [ ! -e "/proc/net/vlan/config" ]; then
114 return 1
115 fi
116 grep -q "${1}$" /proc/net/vlan/config
117 }
118
119 function device_is_vlan() { # XXX Compat function
120 log DEBUG "Deprecated function device_is_vlan() was used."
121
122 device_is_virtual $@
123 }
124
125 # Check if the device is a ppp device
126 function device_is_ppp() {
127 local device=${1}
128
129 ip link show ${device} 2>/dev/null | grep -qE "<.*POINTOPOINT.*>"
130 }
131
132 # Check if the device is a loopback device
133 function device_is_loopback() {
134 local device=$(devicify ${1})
135 [ "${device}" = "lo" ]
136 }
137
138 # Check if the device is a physical network interface
139 function device_is_real() {
140 local device=${1}
141
142 device_is_loopback ${device} && \
143 return ${EXIT_ERROR}
144
145 device_is_bonding ${device} && \
146 return ${EXIT_ERROR}
147
148 device_is_bridge ${device} && \
149 return ${EXIT_ERROR}
150
151 device_is_ppp ${device} && \
152 return ${EXIT_ERROR}
153
154 device_is_virtual ${device} && \
155 return ${EXIT_ERROR}
156
157 return ${EXIT_OK}
158 }
159
160 # Get the device type
161 function device_get_type() {
162 local device=$(devicify ${1})
163
164 if device_is_vlan ${device}; then
165 echo "vlan"
166
167 elif device_is_bonding ${device}; then
168 echo "bonding"
169
170 elif device_is_bridge ${device}; then
171 echo "bridge"
172
173 elif device_is_ppp ${device}; then
174 echo "ppp"
175
176 elif device_is_loopback ${device}; then
177 echo "loopback"
178
179 elif device_is_real ${device}; then
180 echo "real"
181
182 else
183 echo "unknown"
184 fi
185 }
186
187 function device_get_address() {
188 local device=${1}
189
190 cat ${SYS_CLASS_NET}/${device}/address 2>/dev/null
191 }
192
193 function device_set_address() {
194 local device=${1}
195 local addr=${2}
196
197 if ! device_exists ${device}; then
198 error "Device '${device}' does not exist."
199 return ${EXIT_ERROR}
200 fi
201
202 log INFO "Setting address of '${device}' to '${addr}' - was $(device_get_address ${device})."
203
204 local up
205 if device_is_up ${device}; then
206 device_set_down ${device}
207 up=1
208 fi
209
210 ip link set ${device} address ${addr}
211 local ret=$?
212
213 if [ "${up}" = "1" ]; then
214 device_set_up ${device}
215 fi
216
217 if [ "${ret}" != "0" ]; then
218 error_log "Could not set address '${addr}' on device '${device}'."
219 fi
220
221 return ${ret}
222 }
223
224 function devices_get_all() {
225 local device
226 for device in ${SYS_CLASS_NET}/*; do
227 echo "$(basename ${device})"
228 done | sort
229 }
230
231 # Check if a device has a cable plugged in
232 function device_has_carrier() {
233 local device=$(devicify ${1})
234 [ "$(<${SYS_CLASS_NET}/${device}/carrier)" = "1" ]
235 }
236
237 # Check if the device is free
238 function device_is_free() {
239 local device=${1}
240
241 device_is_used ${device} && \
242 return ${EXIT_ERROR}
243
244 return ${EXIT_OK}
245 }
246
247 # Check if the device is used
248 function device_is_used() {
249 local device=$(devicify ${1})
250
251 device_has_vlans ${device} && \
252 return ${EXIT_ERROR}
253 device_is_bonded ${device} && \
254 return ${EXIT_ERROR}
255
256 return ${EXIT_OK}
257 }
258
259 # XXX to be removed I think
260 function device_get_free() {
261 local destination=${1}
262
263 # Replace + by a valid number
264 if grep -q "+$" <<<${destination}; then
265 local number=0
266 destination=$(sed -e "s/+//" <<<$destination)
267 while [ "${number}" -le "100" ]; do
268 if ! device_exists "${destination}${number}"; then
269 destination="${destination}${number}"
270 break
271 fi
272 number=$(($number + 1))
273 done
274 fi
275 echo "${destination}"
276 }
277
278 function device_rename() {
279 warning_log "Called deprecated function 'device_rename'"
280
281 device_set_name $@
282 }
283
284 function device_hash() {
285 local device=${1}
286
287 macify ${device} | tr -d ':'
288 }
289
290 # Give the device a new name
291 function device_set_name() {
292 local source=$1
293 local destination=$(device_get_free ${2})
294
295 # Check if devices exists
296 if ! device_exists ${source} || device_exists ${destination}; then
297 return 4
298 fi
299
300 local up
301 if device_is_up ${source}; then
302 ip link set ${source} down
303 up=1
304 fi
305
306 ip link set ${source} name ${destination}
307
308 if [ "${up}" = "1" ]; then
309 ip link set ${destination} up
310 fi
311 }
312
313 # Set device up
314 function device_set_up() {
315 local device=$(devicify ${1})
316
317 # Do nothing if device is already up
318 device_is_up ${device} && return ${EXIT_OK}
319
320 log DEBUG "Setting up device $@"
321 ip link set ${device} up
322 }
323
324 # Set device down
325 function device_set_down() {
326 local device=$(devicify ${1})
327
328 # Do nothing if device is not up
329 device_is_up ${device} || return ${EXIT_OK}
330
331 log DEBUG "Tearing down device $@"
332 ip link set ${device} down
333 }
334
335 # Set new address to a device
336 function device_set_mac() {
337 warning_log "Called deprecated function 'device_set_mac'"
338
339 device_set_address $@
340 }
341
342 function device_get_mtu() {
343 local device=${1}
344
345 if ! device_exists ${device}; then
346 error "Device '${device}' does not exist."
347 return ${EXIT_ERROR}
348 fi
349
350 cat ${SYS_CLASS_NET}/${device}/mtu
351 }
352
353 # Set mtu to a device
354 function device_set_mtu() {
355 local device=${1}
356 local mtu=${2}
357
358 if ! device_exists ${device}; then
359 error "Device '${device}' does not exist."
360 return ${EXIT_ERROR}
361 fi
362
363 local oldmtu=$(device_get_mtu ${device})
364
365 if [ "${oldmtu}" = "${mtu}" ]; then
366 # No need to set mtu.
367 return ${EXIT_OK}
368 fi
369
370 log INFO "Setting mtu of '${device}' to '${mtu}' - was ${oldmtu}."
371
372 local up
373 if device_is_up ${device}; then
374 device_set_down ${device}
375 up=1
376 fi
377
378 ip link set ${device} mtu ${mtu}
379 local ret=$?
380
381 if [ "${up}" = "1" ]; then
382 device_set_up ${device}
383 fi
384
385 if [ "${ret}" != "0" ]; then
386 error_log "Could not set mtu '${mtu}' on device '${device}'."
387 fi
388
389 return ${ret}
390 }
391
392 function device_discover() {
393 local device=${1}
394
395 log INFO "Running discovery process on device '${device}'."
396
397 local hook
398 for hook in $(hooks_get_all); do
399 hook_exec ${hook} discover ${device}
400 done
401 }
402
403 function device_create_virtual() {
404 log WARN "Called deprecated function device_create_virtual"
405 device_virtual_create $@
406 }
407
408 function device_virtual_create() {
409 local port=$(devicify ${1})
410 local vid=${2}
411 local mac=${3}
412 local newport=${port}v${vid}
413
414 if [ -z "${mac}" ]; then
415 mac=$(mac_generate)
416 fi
417
418 log INFO "Creating virtual device '${newport}' with address '${mac}'."
419
420 # Bring up the parent device
421 # XXX Do we need this here?
422 #device_set_up ${port}
423
424 vconfig set_name_type DEV_PLUS_VID_NO_PAD >/dev/null
425 vconfig add ${port} ${vid} >/dev/null
426
427 if [ $? -ne ${EXIT_OK} ]; then
428 error_log "Could not create virtual device '${newport}'."
429 return ${EXIT_ERROR}
430 fi
431
432 # The device is expected to be named like ${port}.${vid}
433 # and will be renamed to the virtual schema
434 device_set_name ${port}.${vid} ${newport}
435
436 if [ $? -ne ${EXIT_OK} ]; then
437 error_log "Could not set name of virtual device '${newport}'."
438 return ${EXIT_ERROR}
439 fi
440
441 # Setting new mac address
442 device_set_address ${newport} ${mac}
443
444 if [ $? -ne ${EXIT_OK} ]; then
445 error_log "Could not set address '${mac}' to virtual device '${newport}'."
446 return ${EXIT_ERROR}
447 fi
448
449 # Bring up the new device
450 device_set_up ${newport}
451
452 return ${EXIT_OK}
453 }
454
455 function device_virtual_remove() {
456 local device=$(devicify ${1})
457
458 log INFO "Removing virtual device '${device}' with address '$(macify ${devive})'."
459
460 device_set_down ${device}
461
462 vconfig rem ${device} >/dev/null
463
464 if [ $? -ne ${EXIT_OK} ]; then
465 error_log "Could not remote virtual device '${newport}'."
466 return ${EXIT_ERROR}
467 fi
468
469 return ${EXIT_OK}
470 }
471
472 function device_bonding_create() {
473 local device=${1}
474 local mac=${2}
475
476 [ -z "${mac}" ] && mac=$(mac_generate)
477
478 log INFO "Creating bonding device '${device}' (${mac})."
479
480 echo "+${device}" > /sys/class/net/bonding_masters
481 device_set_mac ${mac}
482 device_set_up ${device}
483 }
484
485 function device_bonding_remove() {
486 local device=$(devicify ${1})
487
488 log INFO "Remove bonding device '${device}'."
489
490 device_set_down ${device}
491 echo "-${device}" > /sys/class/net/bonding_masters
492 }
493
494 function bonding_set_mode() {
495 local device=${1}
496 local mode=${2}
497
498 log INFO "Setting bonding mode on '${device}' '${mode}'."
499
500 echo "${mode}" > /sys/class/net/${device}/bonding/mode
501 }
502
503 function bonding_enslave_device() {
504 local device=$(devicify ${1})
505 local slave=$(devicify ${2})
506 shift 2
507
508 log INFO "Enslaving slave '${slave}' to '${device}'."
509
510 device_set_down ${slave}
511 echo "+${slave}" > /sys/class/net/${device}/bonding/slaves
512 }
513
514 function bridge_attach_device() {
515 local bridge=${1}
516 local device=${2}
517
518 if ! device_exists ${bridge}; then
519 error "Bridge '${bridge}' does not exist."
520 return ${EXIT_ERROR}
521 fi
522
523 if ! device_exists ${device}; then
524 error "Device '${device}' does not exist."
525 return ${EXIT_ERROR}
526 fi
527
528 log INFO "Attaching device '${device}' to bridge '${bridge}'."
529
530 # XXX device_set_up ${device} # Do we need this here?
531
532 brctl addif ${bridge} ${device}
533 }
534
535 function bridge_detach_device() {
536 local bridge=${1}
537 local device=${2}
538
539 if ! device_exists ${bridge}; then
540 error "Bridge '${bridge}' does not exist."
541 return ${EXIT_ERROR}
542 fi
543
544 if ! device_exists ${device}; then
545 error "Device '${device}' does not exist."
546 return ${EXIT_ERROR}
547 fi
548
549 log INFO "Detaching device '${device}' from bridge '${bridge}'."
550
551 brctl delif ${bridge} ${device}
552
553 device_set_down ${device}
554 }
555
556 function bridge_is_forwarding() {
557 local seconds=45
558 local zone=${1}
559
560 bridge_has_carrier ${zone} || return ${EXIT_ERROR}
561
562 local device
563 while [ ${seconds} -gt 0 ]; do
564 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
565 [ -e "${device}/state" ] || continue
566 if [ "$(<${device}/state)" = "3" ]; then
567 return ${EXIT_OK}
568 fi
569 done
570 sleep 1
571 seconds=$((${seconds} - 1))
572 done
573
574 return ${EXIT_ERROR}
575 }
576
577 function bridge_has_carrier() {
578 local zone=${1}
579
580 local has_carrier=${EXIT_ERROR}
581
582 local device
583 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
584 device=$(basename ${device})
585 device_exists ${device} || continue
586
587 device_has_carrier ${device} && has_carrier=${EXIT_OK}
588 done
589
590 return ${has_carrier}
591 }
592
593 function device_has_ipv4() {
594 local device=${1}
595 local addr=${2}
596
597 if ! device_exists ${device}; then
598 error "Device '${device}' does not exist."
599 return ${EXIT_ERROR}
600 fi
601
602 ip addr show ${device} | grep -q -e "inet " -e "${addr}"
603 }