]>
Commit | Line | Data |
---|---|---|
17e7e3d5 | 1 | #!/bin/bash |
fa424239 MT |
2 | HEADER="\ |
3 | ############################################################################### | |
4 | # # | |
5 | # IPFire.org - A linux based firewall # | |
6 | # Copyright (C) 2009 Michael Tremer & Christian Schmidt # | |
7 | # # | |
8 | # This program is free software: you can redistribute it and/or modify # | |
9 | # it under the terms of the GNU General Public License as published by # | |
10 | # the Free Software Foundation, either version 3 of the License, or # | |
11 | # (at your option) any later version. # | |
12 | # # | |
13 | # This program is distributed in the hope that it will be useful, # | |
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
16 | # GNU General Public License for more details. # | |
17 | # # | |
18 | # You should have received a copy of the GNU General Public License # | |
19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
20 | # # | |
21 | ############################################################################### | |
22 | " | |
23 | ||
24 | ## GLOBAL VARIABLES ARE UPPERCASE | |
25 | ## LOCAL VARIABLES ARE LOWERCASE | |
26 | ||
27 | VERBOSE= | |
28 | FORCE= | |
29 | TARGET= | |
30 | KERNEL=$(uname -r) | |
31 | MODULES= | |
32 | ||
33 | TMPDIR=$(mktemp -d) | |
34 | ||
35 | # Check if we are root | |
36 | if [ $UID != 0 ]; then | |
37 | error "$0 must be run as root." | |
38 | exit 1 | |
39 | fi | |
40 | ||
41 | # Usage | |
42 | function usage() { | |
43 | echo "$0 [--help] [-f] [-v] <out-initrd-image> <kernel-version>" | |
44 | echo " [--with=<module>]" | |
45 | echo | |
46 | echo "example: $0 /boot/myinitramfs.img \`uname -r\`" | |
47 | } | |
48 | ||
49 | # Setting verbose mode | |
17e7e3d5 | 50 | function set_verbose() { |
fa424239 MT |
51 | case "$1" in |
52 | yes|y|on|1) | |
53 | VERBOSE=-v | |
54 | ;; | |
55 | no|n|off|0) | |
56 | VERBOSE= | |
57 | ;; | |
58 | esac | |
17e7e3d5 MT |
59 | } |
60 | ||
fa424239 | 61 | # Returns if verbose is on or not |
17e7e3d5 | 62 | function is_verbose() { |
fa424239 MT |
63 | [ -n "$VERBOSE" ] && return 0 |
64 | return 1 | |
17e7e3d5 MT |
65 | } |
66 | ||
fa424239 MT |
67 | # Like is_verbose but prints |
68 | # the content of $VERBOSE | |
17e7e3d5 | 69 | function get_verbose() { |
fa424239 MT |
70 | echo "$VERBOSE" |
71 | is_verbose | |
17e7e3d5 MT |
72 | } |
73 | ||
fa424239 | 74 | # Prints text if verbose is on |
17e7e3d5 | 75 | function vecho() { |
fa424239 | 76 | is_verbose && echo "$@" |
17e7e3d5 MT |
77 | } |
78 | ||
fa424239 | 79 | # Prints error if verbose is on |
17e7e3d5 | 80 | function error() { |
fa424239 MT |
81 | vecho "$@" >&2 |
82 | } | |
83 | ||
84 | function compress() { | |
85 | cd - >/dev/null | |
86 | IMAGE=$(mktemp) | |
87 | vecho "[TASK] Compressing image $TARGET..." | |
88 | (cd $TMPDIR && find . | cpio -H newc --quiet -o >| $IMAGE) || exit 1 | |
89 | gzip -c9 $IMAGE > $TARGET | |
90 | } | |
91 | ||
92 | function findone() { | |
93 | find "$@" | awk '{ print $1; exit; }' | |
94 | } | |
95 | ||
96 | function findall() { | |
97 | find "$@" | |
98 | } | |
99 | ||
100 | qpushd() { | |
101 | pushd "$1" >/dev/null 2>&1 | |
102 | } | |
103 | ||
104 | qpopd() { | |
105 | popd >/dev/null 2>&1 | |
106 | } | |
107 | ||
108 | function read_link() { | |
109 | READLINK=$(readlink $1) | |
110 | if grep -q "^/" <<< $READLINK; then | |
111 | echo $READLINK | |
112 | else | |
113 | echo "$(dirname $1)/$READLINK" | |
114 | fi | |
17e7e3d5 MT |
115 | } |
116 | ||
17e7e3d5 | 117 | function get_dso_deps() { |
fa424239 MT |
118 | local bin="$1" |
119 | shift | |
120 | ||
121 | declare -a FILES | |
122 | declare -a NAMES | |
123 | ||
124 | local LDSO="/lib/ld-linux.so.2" | |
125 | ||
126 | declare -i n=0 | |
127 | while read NAME I0 FILE ADDR I1 ; do | |
128 | [ "$FILE" == "not" ] && FILE="$FILE $ADDR" | |
129 | [ "$NAME" == "not" ] && NAME="$NAME $I0" | |
130 | NAMES[$n]="$NAME" | |
131 | FILES[$n]="$FILE" | |
132 | let n++ | |
133 | done << EOF | |
134 | $(LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 \ | |
135 | $LDSO $bin 2>/dev/null) | |
17e7e3d5 MT |
136 | EOF |
137 | ||
fa424239 MT |
138 | [ ${#FILES[*]} -eq 0 ] && return 1 |
139 | ||
140 | # we don't want the name of the binary in the list | |
141 | if [ "${FILES[0]}" == "$bin" ]; then | |
142 | FILES[0]="" | |
143 | NAMES[0]="" | |
144 | [ ${#FILES[*]} -eq 1 ] && return 1 | |
145 | fi | |
146 | ||
147 | declare -i n=0 | |
148 | while [ $n -lt ${#FILES[*]} ]; do | |
149 | local FILE="${FILES[$n]}" | |
150 | local NAME="${NAMES[$n]}" | |
151 | if [ "$FILE" == "not found" -o "$NAME" == "not found" ]; then | |
152 | cat 1>&2 <<EOF | |
17e7e3d5 | 153 | There are missing files on your system. The dynamic object $bin |
fa424239 | 154 | requires ${NAMES[$n]} n order to properly function. mkinitramfs cannot continue. |
17e7e3d5 | 155 | EOF |
fa424239 MT |
156 | return 1 |
157 | fi | |
158 | case "$FILE" in | |
159 | /lib*) | |
160 | TLIBDIR=`echo "$FILE" | sed 's,\(/lib[^/]*\)/.*$,\1,'` | |
161 | BASE=`basename "$FILE"` | |
162 | if [ -f "$TLIBDIR/$BASE" ]; then | |
163 | FILE="$TLIBDIR/$BASE" | |
164 | fi | |
165 | FILES[$n]="$FILE" | |
166 | ;; | |
167 | esac | |
168 | let n++ | |
169 | done | |
170 | echo "${FILES[@]}" | |
171 | } | |
172 | ||
173 | function install() { | |
174 | local file dest | |
175 | for file in $@; do | |
176 | local msg="[FILE]" | |
177 | ||
178 | ## Check if this is an absolute path | |
179 | if [ "$(basename $file)" = "$file" ]; then | |
180 | file=$(which $file) | |
181 | fi | |
182 | ||
183 | # Destination file | |
184 | dest="$TMPDIR$file" | |
a86bcb1d | 185 | [ -e "$dest" ] && continue |
fa424239 MT |
186 | |
187 | mkdir -p "$(dirname $dest)" 2>/dev/null | |
188 | ||
189 | local old_indent=$INDENT | |
190 | INDENT=" $INDENT" | |
191 | ||
192 | [ "${file%%.ko}" != "${file}" ] && msg="[KMOD]" | |
193 | [ -L "$file" ] && msg="[SYML]" | |
194 | #vecho "$msg$INDENT$file -> $dest" | |
195 | vecho "$msg$INDENT$file" | |
196 | ||
197 | # Check if $file is a symlink | |
198 | if [ -L "$file" ]; then | |
199 | install $(read_link $file) | |
200 | fi | |
201 | ||
202 | if [ "${file%%.ko}" != "${file}" ]; then | |
203 | for i in $(moduledep $file); do | |
204 | [ "$(locatemodule $i)" = "$file" ] && continue | |
205 | installmodule $i | |
206 | done | |
207 | fi | |
208 | ||
209 | cp -ld $file $dest | |
210 | ||
211 | # Check if file is a script file | |
212 | if [ "$(dd if=$file bs=2 count=1 2>/dev/null)" = "#!" ]; then | |
213 | install $(head -n 1 $file | cut -c3-) | |
214 | # Check if file is a kernel module | |
215 | elif [ "${file%%.ko}" != "${file}" ]; then | |
216 | local firmware | |
217 | for firmware in $(modinfo -F firmware $file 2>/dev/null); do | |
218 | firmware="/lib/firmware/$firmware" | |
219 | [ -e "$firmware" ] && install $firmware | |
220 | done | |
221 | else | |
222 | for dep in $(get_dso_deps "$file"); do | |
223 | install $dep | |
224 | done | |
225 | fi | |
226 | ||
227 | INDENT=$old_indent | |
228 | done | |
229 | } | |
230 | ||
231 | # find module dependencies | |
232 | function moduledep() { | |
233 | local deps mpargs | |
234 | if [ "$1" == "--ignore-install" ]; then | |
235 | mpargs="$mpargs --ignore-install" | |
236 | shift | |
237 | fi | |
238 | local module=$(basename ${1%%.ko}) | |
239 | modprobe $mpargs --set-version $KERNEL --show-depends $module 2>/dev/null | \ | |
240 | awk '/^insmod / { print gensub(".*/","","g",$2) }' | \ | |
241 | while read foo; do \ | |
242 | [ "${foo%%.ko}" != "$1" ] && \ | |
243 | echo -n "${foo%%.ko} "; \ | |
244 | done | |
245 | } | |
246 | ||
247 | # XXX May be, we can drop this... | |
248 | # This loops to make sure it resolves dependencies of dependencies of... | |
249 | function resolvemoduledeps () { | |
250 | local dep | |
251 | local deps | |
252 | local module | |
253 | local newmodules | |
254 | local modules=$@ | |
255 | ||
256 | before=0; after=1 | |
257 | while [ $before != $after ]; do | |
258 | newmodules= | |
259 | before=$(wc -c <<< $modules) | |
260 | for module in $modules; do | |
261 | deps=$(moduledep $module) | |
262 | is_verbose && echo "Module $module depends on: $deps" | |
263 | newmodules="$newmodules $module $deps" | |
264 | done | |
265 | modules=$(for i in $newmodules; do echo $i; done | sort -u) | |
266 | after=$(wc -c <<< $modules) | |
267 | done | |
268 | echo $modules | |
269 | } | |
270 | ||
271 | function locatemodule() { | |
272 | local mpargs="" | |
273 | if [ "$1" == "--ignore-install" ]; then | |
274 | mpargs="$mpargs --ignore-install" | |
275 | shift | |
276 | fi | |
277 | local path=$(modprobe $mpargs --set-version $KERNEL --show-depends $1 2>/dev/null | \ | |
278 | awk '/^insmod / { print $2; }' | tail -n 1) | |
279 | [ -n "$path" -a -f "$path" ] && echo $path | |
280 | } | |
281 | ||
282 | function installmodule() { | |
283 | local module | |
9bf81f83 | 284 | local load |
fa424239 | 285 | for module in $@; do |
9bf81f83 | 286 | [ "$module" = "--load" ] && load=1 |
fa424239 MT |
287 | module=$(locatemodule $module) |
288 | [ -z "$module" ] && continue | |
289 | ||
290 | install $module | |
291 | done | |
9bf81f83 MT |
292 | if [ "$load" = "1" ]; then |
293 | for module in $@; do | |
294 | [ "$module" = "--load" ] && continue | |
295 | cat >> $TMPDIR/sbin/real-init <<EOF | |
296 | vecho "Loading module $i..." | |
297 | modprobe $i | |
298 | EOF | |
299 | done | |
300 | fi | |
fa424239 MT |
301 | } |
302 | ||
303 | resolve_device_name() { | |
304 | if [[ "$1" =~ ^/dev ]]; then | |
305 | echo $1 | |
306 | else | |
307 | findfs $1 | |
308 | fi | |
309 | } | |
310 | ||
311 | function finalize() { | |
312 | qpopd | |
313 | ||
314 | # Adding modules | |
315 | installmodule $MODULES | |
316 | ||
317 | # Build module deps file so we can use modprobe | |
318 | vecho "[TASK] Running depmod..." | |
319 | depmod -a -b "$TMPDIR" $KERNEL | |
320 | ||
321 | # ldconfig | |
322 | install /etc/ld.so.conf | |
323 | [ -d "/etc/ld.so.conf.d" ] && \ | |
324 | for i in $(find /etc/ld.so.conf.d -type f); do | |
325 | install $i | |
326 | done | |
327 | vecho "[TASK] Running ldconfig..." | |
328 | ldconfig -r $TMPDIR | |
329 | ||
330 | # Compressing | |
331 | compress | |
332 | rm -rf $TMPDIR 2>/dev/null | |
333 | } | |
334 | ||
335 | # resolve a device node to its major:minor numbers in decimal or hex | |
336 | function get_numeric_dev() { | |
337 | ( fmt="%d:%d" | |
338 | if [ "$1" == "hex" ]; then | |
339 | fmt="%x:%x" | |
340 | fi | |
341 | ls -lH "$2" | awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }' | |
342 | ) 2>/dev/null | |
343 | } | |
344 | ||
345 | function resolve_device_name() { | |
346 | if [[ "$1" =~ ^/dev ]]; then | |
347 | echo $1 | |
17e7e3d5 | 348 | else |
fa424239 MT |
349 | findfs $1 |
350 | fi | |
351 | } | |
352 | ||
353 | function finddevnoinsys() { | |
354 | majmin="$1" | |
355 | if [ -n "$majmin" ]; then | |
356 | dev=$(for x in /sys/block/* ; do find $x/ -name dev ; done | while read device ; do \ | |
357 | echo "$majmin" | cmp -s $device && echo $device ; done) | |
358 | if [ -n "$dev" ]; then | |
359 | dev=${dev%%/dev} | |
360 | dev=${dev%%/} | |
361 | echo "$dev" | |
362 | return 0 | |
363 | fi | |
17e7e3d5 | 364 | fi |
fa424239 | 365 | return 1 |
17e7e3d5 MT |
366 | } |
367 | ||
fa424239 MT |
368 | findblockdevinsys() { |
369 | devname=$(resolve_device_name "$1") | |
370 | if [[ "$devname" =~ ^/sys/block/ ]]; then | |
371 | echo "$devname" | |
372 | fi | |
373 | majmin=$(get_numeric_dev dec $devname) | |
374 | finddevnoinsys "$majmin" | |
375 | } | |
376 | ||
377 | findstoragedriverinsys () { | |
378 | while [ ! -L device ]; do | |
379 | for slave in $(ls -d slaves/* 2>/dev/null) ; do | |
380 | slavename=${slave##*/} | |
381 | case " $slavestried " in | |
382 | *" $slavename "*) | |
383 | continue | |
384 | ;; | |
385 | *) | |
386 | slavestried="$slavestried $slavename" | |
387 | qpushd $slave | |
388 | findstoragedriverinsys | |
389 | qpopd | |
390 | ;; | |
391 | esac | |
392 | done | |
393 | [ "$PWD" = "/sys" ] && return | |
394 | cd .. | |
395 | done | |
396 | cd $(read_link ./device) | |
397 | if echo $PWD | grep -q /virtio-pci/ ; then | |
9bf81f83 | 398 | installmodule --load virtio_pci |
fa424239 MT |
399 | fi |
400 | while [ "$PWD" != "/sys/devices" ]; do | |
401 | deps= | |
402 | if [ -f modalias ]; then | |
9bf81f83 | 403 | installmodule --load $(cat modalias) |
fa424239 MT |
404 | fi |
405 | ||
406 | [ -z "$deps" -a -L driver/module ] && \ | |
407 | deps=$(basename $(read_link driver/module)) | |
9bf81f83 | 408 | installmodule --load $deps |
fa424239 MT |
409 | cd .. |
410 | done | |
411 | } | |
412 | ||
413 | function findstoragedriver() { | |
414 | for device in $@; do | |
415 | case " $handleddevices " in | |
416 | *" $device "*) | |
417 | continue ;; | |
418 | *) handleddevices="$handleddevices $device" ;; | |
419 | esac | |
420 | vecho "[INFO] Looking for driver for device $device" | |
421 | if [[ "$device" =~ ^/sys ]]; then | |
422 | device=${device##*/} | |
423 | fi | |
424 | sysfs="" | |
425 | device=$(echo "$device" | sed 's,/,!,g') | |
426 | if [ -d /sys/block/$device/ ]; then | |
427 | sysfs="/sys/block/$device" | |
428 | else | |
429 | sysfs=$(for x in /sys/block/*; do findone $x/ -type d -name $device; done) | |
430 | fi | |
431 | [ -z "$sysfs" ] && return | |
432 | qpushd $sysfs | |
433 | findstoragedriverinsys | |
434 | qpopd | |
435 | done | |
436 | } | |
437 | ||
438 | # Main | |
439 | while [ $# -gt 0 ] ; do | |
440 | case $1 in | |
441 | --help) | |
442 | usage | |
443 | exit 0 | |
444 | ;; | |
445 | -f|--force) | |
446 | FORCE=yes | |
447 | ;; | |
448 | -v|--verbose) | |
449 | set_verbose on | |
450 | ;; | |
451 | --with=*) | |
452 | MODULES="$MODULES ${1#--with=*}" | |
453 | ;; | |
03ff757e MT |
454 | --with-net) |
455 | WITH_NET=1 | |
456 | ;; | |
fa424239 MT |
457 | *) |
458 | if [ -z "$target" ] ; then | |
459 | target=$1 | |
460 | elif [ -z "$kernel" ] ; then | |
461 | kernel=$1 | |
462 | else | |
463 | echo "Unknown option or parameter \"$1\"" | |
464 | usage | |
465 | exit 1 | |
466 | fi | |
467 | ;; | |
468 | esac | |
469 | ||
470 | shift | |
471 | done | |
472 | ||
473 | TARGET=${target-$TARGET} | |
474 | KERNEL=${kernel-$KERNEL} | |
475 | ||
476 | if [ -z "$TARGET" ]; then | |
477 | usage | |
478 | exit 1 | |
479 | fi | |
480 | ||
481 | [[ "$TARGET" =~ "^/" ]] && TARGET="$PWD/$TARGET" | |
482 | ||
483 | if [ -z "$FORCE" ] && [ -e "$TARGET" ]; then | |
484 | echo "Image $TARGET already exists. Use -f to overwrite" | |
485 | exit 1 | |
486 | fi | |
487 | ||
488 | # Changing to our dir, where we do our actions in | |
489 | qpushd $TMPDIR || exit 1 | |
490 | ||
491 | # Make directory structure | |
492 | mkdir -p bin sbin dev sys proc sysroot \ | |
493 | etc/udev/rules.d lib/udev/rules.d | |
494 | ||
495 | # Install some essential binaries | |
b6d6f925 | 496 | install bash blkid chmod cat cut dmesg env find grep head ip kbd_mode \ |
e79e1f30 | 497 | kill killall5 less ln \ |
16d10a88 | 498 | ls lsmod mkdir mknod modprobe mount mountpoint openvt pidof ps rm sed \ |
fbfa5187 | 499 | setfont sh sleep switch_root udevadm udevd umount \ |
d876bb14 | 500 | /lib/udev/console_init |
fa424239 | 501 | |
fa424239 MT |
502 | # Copy modprobe.conf and friends over |
503 | [ -e /etc/modprobe.conf ] && install /etc/modprobe.conf | |
504 | for f in $(find /etc/modprobe.d -type f); do | |
505 | install $f | |
506 | done | |
507 | ||
9bf81f83 MT |
508 | # Install an empty fstab |
509 | touch $TMPDIR/etc/fstab | |
510 | ||
fa424239 MT |
511 | # terminfo bits make things work better if you fall into interactive mode |
512 | [ -d "/usr/lib/terminfo" ] && \ | |
513 | for f in $(find /usr/lib/terminfo -type f); do | |
514 | install $f | |
515 | done | |
516 | ||
517 | # Add localization | |
eee16110 MT |
518 | if [ -e "/etc/sysconfig/console" ]; then |
519 | install /etc/sysconfig/console | |
520 | . /etc/sysconfig/console | |
521 | fi | |
3e1d8f2b | 522 | [ -z "$FONT" ] && FONT="LatArCyrHeb-16" |
fa424239 MT |
523 | for i in /lib/kbd/consolefonts/$FONT.*; do |
524 | mkdir -p $TMPDIR/$(dirname $i) 2>/dev/null || true | |
525 | cp -f $i $TMPDIR/$i | |
526 | case "$i" in | |
527 | *.gz) | |
528 | gzip -fd $TMPDIR/$i | |
529 | ;; | |
530 | *.bz2) | |
531 | bzip2 -fd $TMPDIR/$i | |
532 | ;; | |
533 | esac | |
534 | done | |
535 | ||
536 | cat > init <<'EOF' | |
537 | #!/bin/sh | |
538 | ||
539 | # Mounting directories | |
540 | mount -t proc proc /proc | |
541 | mount -t sysfs /sys /sys | |
542 | mount -t tmpfs -o mode=0755 udev /dev | |
543 | ||
544 | # Silencing kernel | |
545 | echo > /proc/sys/kernel/printk "1 4 1 7" | |
546 | ||
547 | # Adding important dev nodes | |
548 | mknod /dev/console c 5 1 | |
549 | mknod /dev/null c 1 3 | |
550 | mknod /dev/kmsg c 1 11 | |
551 | mknod /dev/ptmx c 5 2 | |
552 | mknod /dev/fb c 29 0 | |
553 | mknod /dev/systty c 4 0 | |
554 | ||
555 | # XXX really we need to openvt too, in case someting changes the | |
556 | # color palette and then changes vts on fbcon before gettys start. | |
557 | # (yay, fbcon bugs!) | |
558 | for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 ; do | |
559 | mknod /dev/tty$i c 4 $i | |
560 | done | |
561 | ||
562 | for i in 0 1 2 3 ; do | |
563 | mknod /dev/ttyS$i c 4 $(($i + 64)) | |
564 | done | |
565 | ||
566 | mkdir -m 1777 /dev/shm | |
567 | ln -s /proc/self/fd /dev/fd | |
568 | ln -s fd/0 /dev/stdin | |
569 | ln -s fd/1 /dev/stdout | |
570 | ln -s fd/2 /dev/stderr | |
571 | ||
572 | mkdir /dev/pts | |
573 | mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts | |
574 | ||
575 | exec sbin/real-init | |
576 | EOF | |
577 | chmod 755 init | |
578 | ||
579 | # Write out real-init | |
580 | touch sbin/real-init; chmod 755 sbin/real-init | |
581 | cat > sbin/real-init <<'EOF' | |
582 | #!/bin/bash | |
583 | $HEADER | |
584 | ||
585 | export PATH=/sbin:/bin:/usr/sbin:/usr/bin | |
586 | export TERM=linux | |
587 | ||
c8b7be54 | 588 | init="/sbin/init" |
fa424239 MT |
589 | VERBOSE=-v |
590 | ||
591 | READONLY=0 | |
592 | SHELL=0 | |
593 | ESHELL=0 | |
594 | ||
595 | function emergency_shell() | |
17e7e3d5 | 596 | { |
fa424239 MT |
597 | echo "Bug in initramfs /init detected. Dropping to a shell. Good luck!" |
598 | echo | |
599 | bash | |
17e7e3d5 | 600 | } |
fa424239 | 601 | trap "emergency_shell" 0 2 |
17e7e3d5 | 602 | |
fa424239 MT |
603 | # exit immediately if a command fails |
604 | set -e | |
605 | ||
606 | # Setting verbose mode | |
607 | function set_verbose() { | |
608 | case "$1" in | |
609 | yes|y|on|1) | |
610 | VERBOSE=-v | |
611 | ;; | |
612 | no|n|off|0) | |
613 | VERBOSE= | |
614 | ;; | |
615 | esac | |
17e7e3d5 MT |
616 | } |
617 | ||
fa424239 MT |
618 | # Returns if verbose is on or not |
619 | function is_verbose() { | |
620 | [ -n "$VERBOSE" ] && return 0 | |
621 | return 1 | |
a2402ae4 MT |
622 | } |
623 | ||
fa424239 MT |
624 | # Like is_verbose but prints |
625 | # the content of $VERBOSE | |
626 | function get_verbose() { | |
627 | echo "$VERBOSE" | |
628 | is_verbose | |
629 | } | |
630 | ||
631 | # Prints text if verbose is on | |
632 | function vecho() { | |
633 | if is_verbose; then echo "$@"; fi | |
a2402ae4 | 634 | } |
17e7e3d5 | 635 | |
fa424239 MT |
636 | # Prints error if verbose is on |
637 | function error() { | |
638 | vecho "$@" >&2 | |
639 | } | |
17e7e3d5 | 640 | |
fa424239 MT |
641 | /lib/udev/console_init tty0 |
642 | ||
643 | # Disable hotplugging | |
644 | echo "" > /proc/sys/kernel/hotplug | |
645 | ||
646 | # Parse kernel commandline options | |
647 | for o in $(cat /proc/cmdline) ; do | |
648 | case $o in | |
649 | init=*) | |
c8b7be54 | 650 | init=${o#init=} |
fa424239 MT |
651 | ;; |
652 | ro) | |
653 | READONLY=1 | |
654 | ;; | |
655 | rw) | |
656 | READONLY=0 | |
657 | ;; | |
658 | quiet) | |
659 | set_verbose no | |
660 | ;; | |
661 | shell) | |
662 | SHELL=1 | |
663 | ;; | |
664 | eshell) | |
665 | ESHELL=1 | |
666 | ;; | |
667 | blacklist=*) | |
668 | echo "blacklist ${o#blacklist=}" >> /etc/modprobe.conf | |
669 | ;; | |
670 | *) | |
671 | m=$(echo $o |cut -s -d . -f 1) | |
672 | opt=$(echo $o |cut -s -d . -f 2-) | |
673 | if [ -z "$m" -o -z "$opt" ]; then | |
674 | continue | |
675 | fi | |
676 | p=$(echo $opt |cut -s -d = -f 1) | |
677 | v=$(echo $opt |cut -s -d = -f 2-) | |
678 | if [ -z "$p" -o -z "$v" ]; then | |
679 | continue | |
680 | fi | |
681 | echo "options $m $p=$v" >> /etc/modprobe.conf | |
682 | ;; | |
683 | esac | |
684 | done | |
685 | ||
686 | vecho "kernel commandline: $(cat /proc/cmdline)" | |
687 | EOF | |
77f077f3 MT |
688 | |
689 | if [ "${WITH_NET}" = "1" ]; then | |
690 | MODULES="$MODULES af_packet" | |
691 | for module in /lib/modules/$KERNEL/kernel/drivers/net/{,*/}*; do | |
692 | MODULES="$MODULES $(basename ${module/.ko})" | |
693 | done | |
694 | ||
695 | install arping curl dhclient ip ping sha1sum /etc/nsswitch.conf \ | |
696 | /usr/lib/libnsl.so /usr/lib/libnss_{dns,files}.so | |
697 | mkdir -p $TMPDIR/var/lib/dhclient 2>/dev/null | |
698 | ||
699 | cat > sbin/dhclient-script <<'EOF' | |
700 | #!/bin/sh | |
701 | ||
702 | PATH=/usr/sbin:/sbin:/usr/bin:/bin | |
703 | ||
704 | function ip_encode() { | |
705 | IFS=. | |
706 | ||
707 | local int=0 | |
708 | for field in $1; do | |
709 | int=$(( $(( $int << 8 )) | $field )) | |
710 | done | |
711 | ||
712 | echo $int | |
713 | unset IFS | |
714 | } | |
715 | ||
716 | function mask_to_cidr() { | |
717 | local mask | |
718 | mask=$(ip_encode $1) | |
719 | local cidr | |
720 | cidr=0 | |
721 | local x | |
722 | x=$(( 128 << 24 )) # 0x80000000 | |
723 | ||
724 | while [ $(( $x & $mask )) -ne 0 ]; do | |
725 | [ $mask -eq $x ] && mask=0 || mask=$(( $mask << 1 )) | |
726 | cidr=$(($cidr + 1)) | |
727 | done | |
728 | ||
729 | if [ $(( $mask & 2147483647 )) -ne 0 ]; then # 2147483647 = 0x7fffffff | |
730 | echo "Invalid net mask: $1" >&2 | |
731 | else | |
732 | echo $cidr | |
733 | fi | |
734 | } | |
735 | ||
736 | function ip_in_subnet() { | |
737 | local netmask | |
738 | netmask=$(_netmask $2) | |
739 | [ $(( $(ip_encode $1) & $netmask)) = $(( $(ip_encode ${2%/*}) & $netmask )) ] | |
740 | } | |
741 | ||
742 | function _netmask() { | |
743 | local vlsm | |
744 | vlsm=${1#*/} | |
745 | [ $vlsm -eq 0 ] && echo 0 || echo $(( -1 << $(( 32 - $vlsm )) )) | |
746 | } | |
747 | ||
748 | dhconfig() { | |
749 | if [ -n "${old_ip_address}" ] && | |
750 | [ ! "${old_ip_address}" = "${new_ip_address}" ]; then | |
751 | # IP address changed. Bringing down the interface will delete all | |
752 | # routes, and clear the ARP cache. | |
753 | ip -family inet addr flush dev ${interface} >/dev/null 2>&1 | |
754 | ip -family inet link set dev ${interface} down | |
755 | fi | |
756 | ||
757 | if [ "${reason}" = "BOUND" ] || [ "${reason}" = "REBOOT" ] || | |
758 | [ ! "${old_ip_address}" = "${new_ip_address}" ] || | |
759 | [ ! "${old_subnet_mask}" = "${new_subnet_mask}" ] || | |
760 | [ ! "${old_network_number}" = "${new_network_number}" ] || | |
761 | [ ! "${old_broadcast_address}" = "${new_broadcast_address}" ] || | |
762 | [ ! "${old_routers}" = "${new_routers}" ] || | |
763 | [ ! "${old_interface_mtu}" = "${new_interface_mtu}" ]; then | |
764 | ip -family inet addr add ${new_ip_address}/${new_prefix} \ | |
765 | broadcast ${new_broadcast_address} dev ${interface} | |
766 | ||
767 | if [ -n "${new_interface_mtu}" ]; then | |
768 | ip link set ${interface} mtu ${new_interface_mtu} | |
769 | fi | |
770 | ||
771 | for router in ${new_routers}; do | |
772 | if ! ip_in_subnet ${router} ${new_ip_address}/${new_prefix}; then | |
773 | continue | |
774 | fi | |
775 | ip route replace default via ${router} | |
776 | break | |
777 | done | |
778 | fi | |
779 | ||
780 | if [ "${reason}" = "RENEW" ] && \ | |
781 | [ "${new_domain_name}" = "${old_domain_name}" ] && \ | |
782 | [ "${new_domain_name_servers}" = "${old_domain_name_servers}" ]; then | |
783 | return | |
784 | fi | |
785 | ||
786 | if [ -n "${new_domain_name}" ] || [ -n "${new_domain_name_servers}" ] || \ | |
787 | [ -n "${new_domain_search}" ]; then | |
788 | ||
789 | echo "; generated by $0" > /etc/resolv.conf | |
790 | ||
791 | if [ -n "${new_domain_search}" ]; then | |
792 | echo "search ${new_domain_search//\\032/ }" >> /etc/resolv.conf | |
793 | elif [ -n "${new_domain_name}" ]; then | |
794 | echo "search ${new_domain_name//\\032/ }" >> /etc/resolv.conf | |
795 | fi | |
796 | ||
797 | for nameserver in ${new_domain_name_servers} ; do | |
798 | echo "nameserver ${nameserver}" >> /etc/resolv.conf | |
799 | done | |
800 | fi | |
801 | ||
802 | if [ -n "${new_host_name}" ]; then | |
803 | hostname ${new_host_name} | |
804 | fi | |
805 | } | |
806 | ||
807 | new_prefix=$(mask_to_cidr ${new_subnet_mask}) | |
808 | ||
809 | case "${reason}" in | |
810 | MEDIUM) | |
811 | exit 0 | |
812 | ;; | |
813 | ||
814 | PREINIT) | |
815 | ip -family inet addr flush dev ${interface} >/dev/null 2>&1 | |
816 | ip -family inet link set ${interface} up | |
817 | exit 0 | |
818 | ;; | |
819 | ||
820 | ARPCHECK|ARPSEND) | |
821 | if [ -z "${new_ip_address}" ] || [ -z "${interface}" ] || \ | |
822 | arping -q -f -c 2 -w 3 -D -I ${interface} ${new_ip_address}; then | |
823 | exit 0 | |
824 | else | |
825 | exit 1 | |
826 | fi | |
827 | ;; | |
828 | ||
829 | BOUND|RENEW|REBIND|REBOOT) | |
830 | dhconfig | |
831 | exit 0 | |
832 | ;; | |
833 | ||
834 | EXPIRE|FAIL|RELEASE|STOP) | |
835 | if [ -n "${old_ip_address}" ]; then | |
836 | # Shut down interface, which will delete routes and clear arp cache. | |
837 | ip -family inet addr flush dev ${interface} >/dev/null 2>&1 | |
838 | ip -family inet link set ${interface} down | |
839 | fi | |
840 | exit 0 | |
841 | ;; | |
842 | ||
843 | *) | |
844 | echo "Unhandled state: ${reason}" >&2 | |
845 | exit 1 | |
846 | ;; | |
847 | esac | |
848 | ||
849 | EOF | |
850 | chmod 755 sbin/dhclient-script | |
851 | fi |