summaryrefslogtreecommitdiffstats
path: root/builder/modules.d/systemd-networkd-ext/hooks/parse-kcl-for-networkd.sh
blob: cdf080a35afce76066aa63c6b2edc982021f2832 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/bin/bash
#
# This script was mostly stolen from 40network/parse-ip-opts.sh.  Its
# actions are adapted to write .network files to /etc/systemd/network
# in the initramfs instead o

command -v getarg >/dev/null || . /lib/dracut-lib.sh

main_work() {
	local IPCONF="$(getarg ip=)"
	local BOOTIF="$(getarg BOOTIF=)"

	if [ -z "${IPCONF}" ] && [ -z "${BOOTIF}" ]; then
		# No ip= argument(s) given by PXE, TODO try dhcp 
		return;
	fi

	# ip= is expected in following format (syslinux IPAPPEND3):
	# <CLIENT_IP>:<PXE_SERVER_IP>:<GATEWAY_IP>:<NETMASK>
	local CLIENT_IP=
	local SERVER_IP=
	local GATEWAY_IP=
	local NETMASK=
	read -r CLIENT_IP SERVER_IP GATEWAY_IP NETMASK <<< $( awk -F: '{print $1" "$2" "$3" "$4}' <<< "${IPCONF}" )

	# BOOTIF= contains the MAC address of the boot interface
	# and a hardware type prefix of length 2, e.g. "01-"
	# So if BOOTIF has 20 chars, then we got the prefix.
	# This needs to be stripped to get the MAC address only
	[ -n "${BOOTIF}" ] && [ ${#BOOTIF} -eq 20 ] && BOOTIF="${BOOTIF#???}"
	BOOTIF="$(tr '-' ':' <<< $BOOTIF)"

	# TODO sanity checks
  
	# Taken from parse-ip-opts.sh
	# Convert the netmask to CIDR notation
	if [[ "x$NETMASK" =~ ^x[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
		CIDR=$(mask2cidr "$NETMASK")
	elif [ -n "$NETMASK" -a "x${NETMASK//[0-9]/}" = 'x' ]; then
		# The mask is already a prefix length (uint), so validate it
		[[ "x$CLIENT_IP" == x*:*:* && "$NETMASK" -le 128 || "$NETMASK" -le 32 ]] && CIDR=$NETMASK
	fi


	# Generate network and link file for networkd
	NETWORK_FILE=/etc/systemd/network/01-boot-lan.network
	mkdir -p $(dirname $NETWORK_FILE)
	echo '[Match]' > $NETWORK_FILE
	echo 'Name=bootnet' >> $NETWORK_FILE
	# Hardcode bootnet as our boot interface
	[ -n "$BOOTIF" ] && echo "MACAddress=$BOOTIF" >> $NETWORK_FILE
	echo '[Network]' >> $NETWORK_FILE
	echo 'Bridge=br0' >> $NETWORK_FILE

	## Boot interface has 'bootnet' as dedicated name
	LINK_FILE=/etc/systemd/network/00-boot-lan.link
	echo '[Match]' > $LINK_FILE
	[ -n "$BOOTIF" ] && echo "MACAddress=$BOOTIF" >> $LINK_FILE
	echo '[Link]' >> $LINK_FILE
	echo "Name=bootnet" >> $LINK_FILE

	# HACK pro bridge setup
	BRIDGE_DEV_CONF=/etc/systemd/network/10-bridge-lan.netdev
	echo '[NetDev]' > $BRIDGE_DEV_CONF
	echo 'Name=br0' >> $BRIDGE_DEV_CONF
	echo 'Kind=bridge' >> $BRIDGE_DEV_CONF

	BRIDGE_IF_CONF=/etc/systemd/network/11-bridge-lan.network
	echo '[Match]' > $BRIDGE_IF_CONF
	echo "Name=br0" >> $BRIDGE_IF_CONF
	echo '[Network]' >> $BRIDGE_IF_CONF
	[ -n "$CLIENT_IP" ] && echo "Address=${CLIENT_IP}/${CIDR:-24}" >> $BRIDGE_IF_CONF
	[ -n "$GATEWAY_IP" ] && echo "Gateway=${GATEWAY_IP}" >> $BRIDGE_IF_CONF

}
# from parse-ip-opts.sh
# Takes a netmask and outputs the corresponding CIDR
# e.g.
#   mask2cidr 255.255.255.0
#   returns:  24
function mask2cidr() {
    local -i bits=0
    for octet in ${1//./ }; do
        for i in {0..8}; do
            [ "$octet" -eq $(( 256 - (1 << i) )) ] && bits+=$((8-i)) && break
        done
        [ $i -eq 8 -a "$octet" -ne 0 ] && warn "Bad netmask $mask" && return
        [ $i -gt 0 ] && break
    done
    echo $bits
}

main_work

# HACK to wait for network during udev loop...
touch /lib/dracut/need-initqueue
/sbin/initqueue --finished /bin/busybox timeout -t 10 /lib/systemd/systemd-networkd-wait-online -i br0