]> git.ipfire.org Git - people/arne_f/network.git/blob - functions.device
network: Update codebase.
[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 device_set_mac $@
195 }
196
197 function devices_get_all() {
198 local device
199 for device in ${SYS_CLASS_NET}/*; do
200 echo "$(basename ${device})"
201 done | sort
202 }
203
204 # Check if a device has a cable plugged in
205 function device_has_carrier() {
206 local device=$(devicify ${1})
207 [ "$(<${SYS_CLASS_NET}/${device}/carrier)" = "1" ]
208 }
209
210 # Check if the device is free
211 function device_is_free() {
212 local device=${1}
213
214 device_is_used ${device} && \
215 return ${EXIT_ERROR}
216
217 return ${EXIT_OK}
218 }
219
220 # Check if the device is used
221 function device_is_used() {
222 local device=$(devicify ${1})
223
224 device_has_vlans ${device} && \
225 return ${EXIT_ERROR}
226 device_is_bonded ${device} && \
227 return ${EXIT_ERROR}
228
229 return ${EXIT_OK}
230 }
231
232 # XXX to be removed I think
233 function device_get_free() {
234 local destination=${1}
235
236 # Replace + by a valid number
237 if grep -q "+$" <<<${destination}; then
238 local number=0
239 destination=$(sed -e "s/+//" <<<$destination)
240 while [ "${number}" -le "100" ]; do
241 if ! device_exists "${destination}${number}"; then
242 destination="${destination}${number}"
243 break
244 fi
245 number=$(($number + 1))
246 done
247 fi
248 echo "${destination}"
249 }
250
251 # Should be renamed to device_set_name at some time
252 function device_rename() {
253 local source=$1
254 local destination=$(device_get_free ${2})
255
256 # Check if devices exists
257 if ! device_exists ${source} || device_exists ${destination}; then
258 return 4
259 fi
260
261 local up
262 if device_is_up ${source}; then
263 ip link set ${source} down
264 up=1
265 fi
266
267 ip link set ${source} name ${destination}
268
269 if [ "${up}" = "1" ]; then
270 ip link set ${destination} up
271 fi
272 }
273
274 function device_hash() {
275 local device=${1}
276
277 macify ${device} | tr -d ':'
278 }
279
280 # Give the device a new name
281 function device_set_name() {
282 device_rename $@
283 }
284
285 # Set device up
286 function device_set_up() {
287 local device=$(devicify ${1})
288
289 # Do nothing if device is already up
290 device_is_up ${device} && return ${EXIT_OK}
291
292 log DEBUG "Setting up device $@"
293 ip link set ${device} up
294 }
295
296 # Set device down
297 function device_set_down() {
298 local device=$(devicify ${1})
299
300 # Do nothing if device is not up
301 device_is_up ${device} || return ${EXIT_OK}
302
303 log DEBUG "Tearing down device $@"
304 ip link set ${device} down
305 }
306
307 # Set new address to a device
308 function device_set_mac() {
309 local port=${1}
310 local mac=${2}
311
312 local up
313 if device_is_up ${port}; then
314 device_set_down ${port}
315 up=1
316 fi
317
318 ip link set ${port} address ${mac}
319 local ret=$?
320
321 if [ "${up}" = "1" ]; then
322 device_set_up ${port}
323 fi
324
325 return ${ret}
326 }
327
328 function device_get_mtu() {
329 local device=${1}
330
331 if ! device_exists ${device}; then
332 error "Device '${device}' does not exist."
333 return ${EXIT_ERROR}
334 fi
335
336 cat ${SYS_CLASS_NET}/${device}/mtu
337 }
338
339 # Set mtu to a device
340 function device_set_mtu() {
341 local port=${1}
342 local mtu=${2}
343
344 local up
345 if device_is_up ${port}; then
346 device_set_down ${port}
347 up=1
348 fi
349
350 ip link set ${port} mtu ${mtu}
351 local ret=$?
352
353 if [ "${up}" = "1" ]; then
354 device_set_up ${port}
355 fi
356
357 return ${ret}
358 }
359
360 function device_discover() {
361 local device=${1}
362
363 local hook
364 for hook in $(hooks_get_all); do
365 hook_exec ${hook} discover ${device}
366 done
367 }
368
369 function device_create_virtual() {
370 log WARN "Called deprecated function device_create_virtual"
371 device_virtual_create $@
372 }
373
374 function device_virtual_create() {
375 local port=$(devicify ${1})
376 local vid=${2}
377 local mac=${3}
378 local newport=${port}v${vid}
379
380 if [ -z "${mac}" ]; then
381 mac=$(mac_generate)
382 fi
383
384 # Bring up the parent device
385 # XXX Do we need this here?
386 #device_set_up ${port}
387
388 vconfig set_name_type DEV_PLUS_VID_NO_PAD >/dev/null
389 vconfig add ${port} ${vid} >/dev/null
390 [ $? -ne 0 ] && return ${EXIT_ERROR}
391
392 # The device is expected to be named like ${port}.${vid}
393 # and will be renamed to the virtual schema
394 device_set_name ${port}.${vid} ${newport}
395
396 # Setting new mac address
397 device_set_address ${newport} ${mac}
398
399 # Bring up the new device
400 device_set_up ${newport}
401
402 log DEBUG "Created virtual device ${newport} (${mac})"
403 return ${EXIT_OK}
404 }
405
406 function device_virtual_remove() {
407 local device=$(devicify ${1})
408
409 device_set_down ${device}
410
411 vconfig rem ${device} >/dev/null
412 [ $? -ne 0 ] && return ${EXIT_ERROR}
413
414 log DEBUG "Removed virtual device ${device}"
415 return ${EXIT_OK}
416 }
417
418 function device_bonding_create() {
419 local device=${1}
420 local mac=${2}
421
422 [ -z "${mac}" ] && mac=$(mac_generate)
423
424 echo "+${device}" > /sys/class/net/bonding_masters
425 device_set_mac ${mac}
426 device_set_up ${device}
427 }
428
429 function device_bonding_remove() {
430 local device=$(devicify ${1})
431
432 device_set_down ${device}
433 echo "-${device}" > /sys/class/net/bonding_masters
434 }
435
436 function bonding_set_mode() {
437 local device=${1}
438 local mode=${2}
439
440 echo "${mode}" > /sys/class/net/${device}/bonding/mode
441 }
442
443 function bonding_enslave_device() {
444 local device=$(devicify ${1})
445 local slave=$(devicify ${2})
446
447 device_set_down ${slave}
448 echo "+${slave}" > /sys/class/net/${device}/bonding/slaves
449 }
450
451 function bridge_attach_device() {
452 local bridge=${1}
453 local device=${2}
454
455 if ! device_exists ${bridge}; then
456 error "Bridge '${bridge}' does not exist."
457 return ${EXIT_ERROR}
458 fi
459
460 if ! device_exists ${device}; then
461 error "Device '${device}' does not exist."
462 return ${EXIT_ERROR}
463 fi
464
465 # XXX device_set_up ${device} # Do we need this here?
466
467 brctl addif ${bridge} ${device}
468 }
469
470 function bridge_detach_device() {
471 local bridge=${1}
472 local device=${2}
473
474 if ! device_exists ${bridge}; then
475 error "Bridge '${bridge}' does not exist."
476 return ${EXIT_ERROR}
477 fi
478
479 if ! device_exists ${device}; then
480 error "Device '${device}' does not exist."
481 return ${EXIT_ERROR}
482 fi
483
484 brctl delif ${zone} ${device}
485
486 device_set_down ${device}
487 }
488
489 function bridge_is_forwarding() {
490 local seconds=45
491 local zone=${1}
492
493 bridge_has_carrier ${zone} || return ${EXIT_ERROR}
494
495 local device
496 while [ ${seconds} -gt 0 ]; do
497 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
498 [ -e "${device}/state" ] || continue
499 if [ "$(<${device}/state)" = "3" ]; then
500 return ${EXIT_OK}
501 fi
502 done
503 sleep 1
504 seconds=$((${seconds} - 1))
505 done
506
507 return ${EXIT_ERROR}
508 }
509
510 function bridge_has_carrier() {
511 local zone=${1}
512
513 local has_carrier=${EXIT_ERROR}
514
515 local device
516 for device in ${SYS_CLASS_NET}/${zone}/brif/*; do
517 device=$(basename ${device})
518 device_exists ${device} || continue
519
520 device_has_carrier ${device} && has_carrier=${EXIT_OK}
521 done
522
523 return ${has_carrier}
524 }
525
526 function device_has_ipv4() {
527 local device=${1}
528 local addr=${2}
529
530 if ! device_exists ${device}; then
531 error "Device '${device}' does not exist."
532 return ${EXIT_ERROR}
533 fi
534
535 ip addr show ${device} | grep -q -e "inet " -e "${addr}"
536 }