summaryrefslogtreecommitdiffstats
path: root/modules.d/slx-network/scripts/udhcpc-trigger.stage3
blob: 664600a67b70ea2fb38f7d58419d245157989240 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/bin/bash
#
# This script is triggered by udhcpc in stage3 and handle the
# DHCP information given as parameters

{
# for debugging
set -x
NETWORK_CONF="/run/openslx/network.conf"
. "$NETWORK_CONF"

MAIN_NETIF="$SLX_PXE_NETIF"
[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}"
[ -n "$SLX_BRIDGE" ]  && MAIN_NETIF="$SLX_BRIDGE"
readonly MAIN_NETIF

if [[ "$1" != "bound" && "$1" != "renew" ]] \
	|| [ "$interface" != "${MAIN_NETIF}" ] \
	|| [ -z "$ip" ]; then
	exit 0
fi

##
## CORE NETWORK CONFIGURATION
##
## > IP, subnet, route

# If we already got an IP from KCL, see if it differs, and remove first if so
# We just try to prevent everything from breaking if the DHCP server doesn't
# objey the renew request by the client and hands out a new address
if [ -n "$SLX_PXE_CLIENT_IP" ]; then
	#...some address is already configured...
	if [ "x${SLX_PXE_CLIENT_IP}" != "x${ip}" ]; then
		#...it's a different one, reconfigure...
		echo "..reconfiguring '${SLX_PXE_CLIENT_IP}' to '${ip}'."
		# remove default route and let it be added again below, as it might get lost when changing the primary address on the interface
		ip route del default 2>/dev/null
		ip addr del "$SLX_PXE_CLIENT_IP" dev "${interface}" 2>/dev/null
	fi
else
	#...no address configured yet, just add...
	echo "..adding ${ip}.."
fi
if ! ip addr show dev "${interface}" | grep -qF "inet ${ip}/"; then
	ip addr add "${ip}/$(ipcalc -s -p "${ip}" "${subnet}" | sed s/.*=//)" dev "${interface}"
	echo "SLX_DHCP_CLIENT_IP='$ip'" >> "$NETWORK_CONF"
fi

# Same procedure for default gateway
if [ -n "$router" ]; then
	if [ -n "$SLX_PXE_GATEWAY" ] && [ "$SLX_PXE_GATEWAY" != "$router" ]; then
		echo "..reconfiguring default gw from '$SLX_PXE_GATEWAY' to '$router'."
		ip route del default 2>/dev/null
	fi
	ip route add default via "$router"
	echo "SLX_DHCP_GATEWAY='$router'" >> "$NETWORK_CONF"
fi

##
## ADDITIONAL NETWORK CONFIGURATION
##
## > DNS, domain, hostname

rm -f -- "/etc/resolv.conf"

reverse_lookup() {
	[ -z "$dns" ] && return
	[ -z "$1" ] && return
	timeout 3 nslookup "$1" | awk '{
		if ($2 == "name") { print $4; exit; }
		if ($1 == "Name:") { ok = 1 }
		if (ok && $1 == "Address") { print $4; exit; }
	}'
}

echo "# From DHCP in stage 3.1" >> "$NETWORK_CONF"

# DNS/domain?
if [ -n "$dns" ]; then
	echo "..got DNS.."
	echo "SLX_DNS='$dns'" >> "$NETWORK_CONF"
fi
for srv in $dns; do
	echo "nameserver $srv" >> "/etc/resolv.conf"
done

# always check DNS
echo "Checking DNS record for this host..."
[ -z "$fqdn" ] && fqdn="$(reverse_lookup "$ip")"
[ -z "$fqdn" ] && [ -n "$hostname" ] && [ -n "$domain" ] && fqdn="${hostname}.${domain}"
# Otherwise, retry DNS one time
if [ -z "$fqdn" ]; then
	sleep 1
	fqdn="$(reverse_lookup "$ip")"
fi
[ -n "$fqdn" ] && fqdn_hostname="${fqdn%%.*}"

if [ -z "$domain" ]; then
	echo "Getting domain via DNS, as DHCP didn't supply one.."
	domain="${fqdn#*.}"
fi

# Add domain to list of search domains if not in there yet
if [ -n "$domain" ] && [ -n "$search" ]; then
	FOUND=no
	for sd in $search; do
		[ "x$sd" = "x$domain" ] && FOUND=yes
	done
	[ "$FOUND" = "no" ] && search="$domain $search"
elif [ -n "$domain" ]; then
	search="$domain"
fi

# Write out
if [ -n "$domain" ]; then
	echo "domain $domain" >> "/etc/resolv.conf"
	echo "SLX_NET_DOMAIN='$domain'" >> "$NETWORK_CONF"
fi

if [ -n "$search" ]; then
	echo "search $search" >> "/etc/resolv.conf"
	echo "SLX_NET_SEARCH='$search'" >> "$NETWORK_CONF"
fi

if [ -n "$ntpsrv" ]; then
	echo "SLX_DHCP_NTP='$ntpsrv'" >> "$NETWORK_CONF"
fi

# Hostname
if [ -n "$hostname" ]; then
	if [ -n "$SLX_PXE_HOSTNAME" ] && [ "$hostname" != "$SLX_PXE_HOSTNAME" ]; then
		echo "KCL and DHCP hostnames differ... assuming some KCL hack."
		echo " -> Prefering KCL: '$SLX_PXE_HOSTNAME'."
		hostname="$SLX_PXE_HOSTNAME"
	fi
	if [ -n "$fqdn_hostname" ] && [ "$hostname" != "$fqdn_hostname" ]; then
		echo "DHCP hostname differs from DNS hostname."
		echo " -> Prefering DNS: '$fqdn_hostname'."
		hostname="$fqdn_hostname"
	fi
else
	echo "No hostname specified in DHCP, checking DNS record."
	# We ignore the corner case where DHCP didn't supply a hostname but
	# there is a hardcoded one via KCL as it seems unlikely, log it nonetheless
	if [ -n "$SLX_PXE_HOSTNAME" ]; then
		echo "DHCP didn't supply a hostname but one was supplied by KCL?" \
			"This seems strange but using KCL hostname anyways."
		hostname="$SLX_PXE_HOSTNAME"
	else
		# regular fallback to DNS and noname-* if needed
		if [ -n "$fqdn_hostname" ]; then
			echo "Using DNS record hostname: '$fqdn_hostname'."
			hostname="$fqdn_hostname"
		else
			# no fallback hostname from DNS, use IP address
			hostname="noname-${ip//./-}"
			fqdn="${hostname}.invalid"
		fi
		if [ -n "$domain" ]; then
			fqdn="${hostname}.${domain%% *}" # in case domain is a list
		fi
	fi
fi

if [ -n "$hostname" ]; then
	[ -z "$fqdn" ] && fqdn="$hostname"
	echo "..setting hostname $hostname (fqdn: $fqdn).."
	echo "$hostname" > "/proc/sys/kernel/hostname"
	echo "$hostname" > "/etc/hostname"
	echo "127.0.0.1 localhost" > "/etc/hosts"
	echo "$ip $fqdn $hostname" >> "/etc/hosts"
	echo "SLX_HOSTNAME='$hostname'" >> "$NETWORK_CONF"
fi

touch /.network
set +x
} {BASH_XTRACEFD}> "/run/openslx/initramfs-udhcpc.log.$$"