]> git.ipfire.org Git - people/arne_f/network.git/blob - functions.device
network: Remove deprecated function device_set_mac.
[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 function device_is_bridge_attached() {
105 local device=${1}
106
107 [ -d "${SYS_CLASS_NET}/${device}/brport" ]
108 }
109
110 # Check if the device is a virtual device
111 function device_is_virtual() {
112 local device=${1}
113
114 [ -e "/proc/net/vlan/${device}" ]
115 }
116
117 # Check if the device has virtual devices
118 function device_has_virtuals() {
119 local device=${1}
120
121 if device_is_virtual ${device}; then
122 return 1
123 fi
124
125 if [ ! -e "/proc/net/vlan/config" ]; then
126 return 1
127 fi
128 grep -q "${1}$" /proc/net/vlan/config
129 }
130
131 function device_is_vlan() { # XXX Compat function
132 log DEBUG "Deprecated function device_is_vlan() was used."
133
134 device_is_virtual $@
135 }
136
137 # Check if the device is a ppp device
138 function device_is_ppp() {
139 local device=${1}
140
141 ip link show ${device} 2>/dev/null | grep -qE "<.*POINTOPOINT.*>"
142 }
143
144 # Check if the device is a loopback device
145 function device_is_loopback() {
146 local device=$(devicify ${1})
147 [ "${device}" = "lo" ]
148 }
149
150 # Check if the device is a physical network interface
151 function device_is_real() {
152 local device=${1}
153
154 device_is_loopback ${device} && \
155 return ${EXIT_ERROR}
156
157 device_is_bonding ${device} && \
158 return ${EXIT_ERROR}
159
160 device_is_bridge ${device} && \
161 return ${EXIT_ERROR}
162
163 device_is_ppp ${device} && \
164 return ${EXIT_ERROR}
165
166 device_is_virtual ${device} && \
167 return ${EXIT_ERROR}
168
169 return ${EXIT_OK}
170 }
171
172 # Get the device type
173 function device_get_type() {
174 local device=$(devicify ${1})
175
176 if device_is_vlan ${device}; then
177 echo "vlan"
178
179 elif device_is_bonding ${device}; then
180 echo "bonding"
181
182 elif device_is_bridge ${device}; then
183 echo "bridge"
184
185 elif device_is_ppp ${device}; then
186 echo "ppp"
187
188 elif device_is_loopback ${device}; then
189 echo "loopback"
190
191 elif device_is_real ${device}; then
192 echo "real"
193
194 else
195 echo "unknown"
196 fi
197 }
198
199 function device_get_address() {
200 local device=${1}
201
202 cat ${SYS_CLASS_NET}/${device}/address 2>/dev/null
203 }
204
205 function device_set_address() {
206 local device=${1}
207 local addr=${2}
208
209 if ! device_exists ${device}; then
210 error "Device '${device}' does not exist."
211 return ${EXIT_ERROR}
212 fi
213
214 log INFO "Setting address of '${device}' to '${addr}' - was $(device_get_address ${device})."
215
216 local up
217 if device_is_up ${device}; then
218 device_set_down ${device}
219 up=1
220 fi
221
222 ip link set ${device} address ${addr}
223 local ret=$?
224
225 if [ "${up}" = "1" ]; then
226 device_set_up ${device}
227 fi
228
229 if [ "${ret}" != "0" ]; then
230 error_log "Could not set address '${addr}' on device '${device}'."
231 fi
232
233 return ${ret}
234 }
235
236 function devices_get_all() {
237 local device
238 for device in ${SYS_CLASS_NET}/*; do
239 echo "$(basename ${device})"
240 done | sort
241 }
242
243 # Check if a device has a cable plugged in
244 function device_has_carrier() {
245 local device=$(devicify ${1})
246 [ "$(<${SYS_CLASS_NET}/${device}/carrier)" = "1" ]
247 }
248
249 # Check if the device is free
250 function device_is_free() {
251 ! device_is_used $@
252 }
253
254 # Check if the device is used
255 function device_is_used() {
256 local device=$(devicify ${1})
257
258 device_has_virtuals ${device} && \
259 return ${EXIT_OK}
260 device_is_bonded ${device} && \
261 return ${EXIT_OK}
262 device_is_bridge_attached ${device} && \
263 return ${EXIT_OK}
264
265 return ${EXIT_ERROR}
266 }
267
268 # XXX to be removed I think
269 function device_get_free() {
270 local destination=${1}
271
272 # Replace + by a valid number
273 if grep -q "+$" <<<${destination}; then
274 local number=0
275 destination=$(sed -e "s/+//" <<<$destination)
276 while [ "${number}" -le "100" ]; do
277 if ! device_exists "${destination}${number}"; then
278 destination="${destination}${number}"
279 break
280 fi
281 number=$(($number + 1))
282 done
283 fi
284 echo "${destination}"
285 }
286
287 function device_rename() {
288 warning_log "Called deprecated function 'device_rename'"
289
290 device_set_name $@
291 }
292
293 function device_hash() {
294 local device=${1}
295
296 macify ${device} | tr -d ':'
297 }
298
299 # Give the device a new name
300 function device_set_name() {
301 local source=$1
302 local destination=$(device_get_free ${2})
303
304 # Check if devices exists
305 if ! device_exists ${source} || device_exists ${destination}; then
306 return 4
307 fi
308
309 local up
310 if device_is_up ${source}; then
311 ip link set ${source} down
312 up=1
313 fi
314
315 ip link set ${source} name ${destination}
316
317 if [ "${up}" = "1" ]; then
318 ip link set ${destination} up
319 fi
320 }
321
322 # Set device up
323 function device_set_up() {
324 local device=$(devicify ${1})
325
326 # Do nothing if device is already up
327 device_is_up ${device} && return ${EXIT_OK}
328
329 device_set_parent_up ${device}
330
331 log DEBUG "Setting up device '${device}'"
332
333 ip link set ${device} up
334 }
335
336 function device_set_parent_up() {
337 local device=${1}
338 local parent
339
340 if device_is_virtual ${device}; then
341 parent=$(device_virtual_get_parent ${device})
342
343 device_is_up ${parent} && return ${EXIT_OK}
344
345 log DEBUG "Setting up parent device '${parent}' of '${device}'"
346
347 device_set_up ${parent}
348 return $?
349 fi
350
351 return ${EXIT_OK}
352 }
353
354 # Set device down
355 function device_set_down() {
356 local device=$(devicify ${1})
357
358 local ret=${EXIT_OK}
359
360 if device_is_up ${device}; then
361 log DEBUG "Tearing down device '${device}'"
362
363 ip link set ${device} down
364 ret=$?
365 fi
366
367 device_set_parent_down ${device}
368
369 return ${ret}
370 }
371
372 function device_set_parent_down() {
373 local device=${1}
374 local parent
375
376 if device_is_virtual ${device}; then
377 parent=$(device_virtual_get_parent ${device})
378
379 device_is_up ${parent} || return ${EXIT_OK}
380
381 if device_is_free ${parent}; then
382 log DEBUG "Tearing down parent device '${parent}' of '${device}'"
383
384 device_set_down ${parent}
385 fi
386 fi
387
388 return ${EXIT_OK}
389 }
390
391 function device_get_mtu() {
392 local device=${1}
393
394 if ! device_exists ${device}; then
395 error "Device '${device}' does not exist."
396 return ${EXIT_ERROR}
397 fi
398
399 cat ${SYS_CLASS_NET}/${device}/mtu
400 }
401
402 # Set mtu to a device
403 function device_set_mtu() {
404 local device=${1}
405 local mtu=${2}
406
407 if ! device_exists ${device}; then
408 error "Device '${device}' does not exist."
409 return ${EXIT_ERROR}
410 fi
411
412 local oldmtu=$(device_get_mtu ${device})
413
414 if [ "${oldmtu}" = "${mtu}" ]; then
415 # No need to set mtu.
416 return ${EXIT_OK}
417 fi
418
419 log INFO "Setting mtu of '${device}' to '${mtu}' - was ${oldmtu}."
420
421 local up
422 if device_is_up ${device}; then
423 device_set_down ${device}
424 up=1
425 fi
426
427 ip link set ${device} mtu ${mtu}
428 local ret=$?
429
430 if [ "${up}" = "1" ]; then
431 device_set_up ${device}
432 fi
433
434 if [ "${ret}" != "0" ]; then
435 error_log "Could not set mtu '${mtu}' on device '${device}'."
436 fi
437
438 return ${ret}
439 }
440
441 function device_discover() {
442 local device=${1}
443
444 log INFO "Running discovery process on device '${device}'."
445
446 local hook
447 for hook in $(hooks_get_all); do
448 hook_exec ${hook} discover ${device}
449 done
450 }
451
452 function device_create_virtual() {
453 log WARN "Called deprecated function device_create_virtual"
454 device_virtual_create $@
455 }
456
457 function device_virtual_create() {
458 local port=$(devicify ${1})
459 local vid=${2}
460 local mac=${3}
461 local newport=${port}v${vid}
462
463 if [ -z "${mac}" ]; then
464 mac=$(mac_generate)
465 fi
466
467 log INFO "Creating virtual device '${newport}' with address '${mac}'."
468
469 local oldport=$(device_virtual_get_by_parent_and_vid ${port} ${vid})
470
471 if device_exists ${oldport}; then
472 local differences
473
474 if [ "${oldport}" != "${newport}" ]; then
475 differences="${differences} name"
476 fi
477 if [ "$(device_get_address ${oldport})" != "${mac}" ]; then
478 differences="${differences} address"
479 fi
480
481 echo "differences: $differences"
482
483 if [ -n "${differences}" ]; then
484 if device_is_used ${oldport}; then
485 error_log "There was a device '${oldport}' set up with VID '${vid}' and parent '${port}' which is used somewhere else. Cannot go on."
486 return ${EXIT_ERROR}
487 else
488 log DEBUG "There is a device '${oldport}' but it not used, so we grab it to ourselves."
489 fi
490 else
491 log DEBUG "Device '${newport}' already exists and reflects our configuration. Go on."
492
493 device_set_up ${oldport}
494 return ${EXIT_OK}
495 fi
496
497 else
498 log DEBUG "Virtual device '${newport}' does not exist, yet."
499
500 vconfig set_name_type DEV_PLUS_VID_NO_PAD >/dev/null
501 vconfig add ${port} ${vid} >/dev/null
502
503 if [ $? -ne ${EXIT_OK} ]; then
504 error_log "Could not create virtual device '${newport}'."
505 return ${EXIT_ERROR}
506 fi
507
508 oldport=$(device_virtual_get_by_parent_and_vid ${port} ${vid})
509
510 fi
511
512 assert device_exists ${oldport}
513
514 if ! device_exists ${oldport}; then
515 error "Could not determine the created virtual device '${newport}'."
516 return ${EXIT_ERROR}
517 fi
518
519 # The device is expected to be named like ${port}.${vid}
520 # and will be renamed to the virtual schema
521 device_set_name ${oldport} ${newport}
522
523 if [ $? -ne ${EXIT_OK} ]; then
524 error_log "Could not set name of virtual device '${newport}'."
525 return ${EXIT_ERROR}
526 fi
527
528 assert device_exists ${newport}
529
530 # Setting new mac address
531 device_set_address ${newport} ${mac}
532
533 if [ $? -ne ${EXIT_OK} ]; then
534 error_log "Could not set address '${mac}' to virtual device '${newport}'."
535 return ${EXIT_ERROR}
536 fi
537
538 # Bring up the new device
539 device_set_up ${newport}
540
541 return ${EXIT_OK}
542 }
543
544 function device_virtual_remove() {
545 local device=$(devicify ${1})
546
547 log INFO "Removing virtual device '${device}' with address '$(macify ${device})'."
548
549 device_set_down ${device}
550
551 vconfig rem ${device} >/dev/null
552
553 if [ $? -ne ${EXIT_OK} ]; then
554 error_log "Could not remote virtual device '${newport}'."
555 return ${EXIT_ERROR}
556 fi
557
558 return ${EXIT_OK}
559 }
560
561 function device_virtual_get_parent() {
562 local device=${1}
563
564 local parent=$(grep "^${device}" < /proc/net/vlan/config | awk '{ print $NF }')
565
566 if device_exists ${parent}; then
567 echo "${parent}"
568 return ${EXIT_OK}
569 fi
570
571 return ${EXIT_ERROR}
572 }
573
574 function device_virtual_get_by_parent_and_vid() {
575 local parent=${1}
576 local vid=${2}
577
578 local v_port
579 local v_id
580 local v_parent
581
582 fgrep '|' < /proc/net/vlan/config | tr -d '|' | \
583 while read v_port v_id v_parent; do
584 if [ "${v_parent}" = "${parent}" ] && [ "${v_id}" = "${vid}" ]; then
585 echo "${v_port}"
586 return ${EXIT_OK}
587 fi
588 done
589
590 return ${EXIT_ERROR}
591 }
592
593 function device_bonding_create() {
594 local device=${1}
595 local mac=${2}
596
597 [ -z "${mac}" ] && mac=$(mac_generate)
598
599 log INFO "Creating bonding device '${device}' (${mac})."
600
601 echo "+${device}" > /sys/class/net/bonding_masters
602 device_set_address ${mac}
603 device_set_up ${device}
604 }
605
606 function device_bonding_remove() {
607 local device=$(devicify ${1})
608
609 log INFO "Remove bonding device '${device}'."
610
611 device_set_down ${device}
612 echo "-${device}" > /sys/class/net/bonding_masters
613 }
614
615 function bonding_set_mode() {
616 local device=${1}
617 local mode=${2}
618
619 log INFO "Setting bonding mode on '${device}' '${mode}'."
620
621 echo "${mode}" > /sys/class/net/${device}/bonding/mode
622 }
623
624 function bonding_enslave_device() {
625 local device=$(devicify ${1})
626 local slave=$(devicify ${2})
627 shift 2
628
629 log INFO "Enslaving slave '${slave}' to '${device}'."
630
631 device_set_down ${slave}
632 echo "+${slave}" > /sys/class/net/${device}/bonding/slaves
633 }
634
635 function bridge_attach_device() {
636 local bridge=${1}
637 local device=${2}
638
639 if ! device_exists ${bridge}; then
640 error "Bridge '${bridge}' does not exist."
641 return ${EXIT_ERROR}
642 fi
643
644 if ! device_exists ${device}; then
645 error "Device '${device}' does not exist."
646 return ${EXIT_ERROR}
647 fi
648
649 log INFO "Attaching device '${device}' to bridge '${bridge}'."
650
651 # XXX device_set_up ${device} # Do we need this here?
652
653 brctl addif ${bridge} ${device}
654 }
655
656 function bridge_detach_device() {
657 local bridge=${1}
658 local device=${2}
659
660 if ! device_exists ${bridge}; then
661 error "Bridge '${bridge}' does not exist."
662 return ${EXIT_ERROR}
663 fi
664
665 if ! device_exists ${device}; then
666 error "Device '${device}' does not exist."
667 return ${EXIT_ERROR}
668 fi
669
670 log INFO "Detaching device '${device}' from bridge '${bridge}'."
671
672 brctl delif ${bridge} ${device}
673
674 device_set_down ${device}
675 }
676
677 function bridge_is_forwarding() {
678 local seconds=45
679 local zone=${1}
680
681 bridge_has_carrier ${zone} || return ${EXIT_ERROR}
682
683 local device
684 while [ ${seconds} -gt 0 ]; do
685 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
686 [ -e "${device}/state" ] || continue
687 if [ "$(<${device}/state)" = "3" ]; then
688 return ${EXIT_OK}
689 fi
690 done
691 sleep 1
692 seconds=$((${seconds} - 1))
693 done
694
695 return ${EXIT_ERROR}
696 }
697
698 function bridge_has_carrier() {
699 local zone=${1}
700
701 local has_carrier=${EXIT_ERROR}
702
703 local device
704 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
705 device=$(basename ${device})
706 device_exists ${device} || continue
707
708 device_has_carrier ${device} && has_carrier=${EXIT_OK}
709 done
710
711 return ${has_carrier}
712 }
713
714 function device_has_ipv4() {
715 local device=${1}
716 local addr=${2}
717
718 if ! device_exists ${device}; then
719 error "Device '${device}' does not exist."
720 return ${EXIT_ERROR}
721 fi
722
723 ip addr show ${device} | grep -q -e "inet " -e "${addr}"
724 }