summaryrefslogtreecommitdiffstats
path: root/modules.d/slx-network/scripts/udhcpc-trigger.stage3
blob: a9eadea34b83a88f61dac1527de70fde92b4f825 (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
178
#!/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

log() {
	echo "${MAIN_NETIF}: $*"
}

##
## 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 [ "${SLX_PXE_CLIENT_IP}" != "${ip}" ]; then
		#...it's a different one, reconfigure...
		log "reconfiguring from '${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
		ip addr del "$SLX_PXE_CLIENT_IP" dev "${interface}"
	fi
else
	#...no address configured yet, just add...
	log "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
		log "reconfiguring default gw from '$SLX_PXE_GATEWAY' to '$router'"
		ip route del default
	fi
	ip route add default via "$router" dev "${MAIN_NETIF}"
	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 gensub("\\.$", "", 1, $4); exit; }
		if ($1 == "Name:") { ok = 1 }
		if (ok && $1 == "Address") { print gensub("\\.$", "", 1, $4); exit; }
	}'
}

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

# DNS/domain?
if [ -n "$dns" ]; then
	log "DNS servers: $dns"
	echo "SLX_DNS='$dns'" >> "$NETWORK_CONF"
	for srv in $dns; do
		echo "nameserver $srv" >> "/etc/resolv.conf"
	done
else
	dns="$( < /etc/resolv.conf  awk '$1 == "nameserver" {printf "%s ", $2}' )"
fi

# always check DNS
log "checking reverse DNS record for this host"
[ -n "$fqdn" ] && [[ "$fqdn" != *.* ]] && fqdn=
[ -z "$fqdn" ] && fqdn="$( reverse_lookup "$ip" )"
[ -z "$fqdn" ] && [ -n "$hostname" ] && [ -n "$domain" ] && fqdn="${hostname}.${domain}"

# retry DNS one time
if [ -z "$fqdn" ]; then
	log "found no way to generate FQDN, trying reverse lookup one more time"
	sleep 1
	fqdn="$( reverse_lookup "$ip" )"
fi
if [ -n "$fqdn" ]; then
	fqdn_hostname="${fqdn%%.*}"
	fqdn_domain="${fqdn#*.}"
fi

if [ -z "$hostname" ] && [ -n "$fqdn_hostname" ]; then
	hostname="${fqdn_hostname}"
	log "using hostname from DNS, as DHCP didn't supply one"
fi
if [ -z "$hostname" ] && [ -n "$SLX_PXE_HOSTNAME" ]; then
	hostname="$SLX_PXE_HOSTNAME"
	log "using hostname from KCL, as DHCP/DNS didn't supply one"
fi
if [ -z "$hostname" ]; then
	hostname="noname-${ip//./-}"
	log "got no hostname via DHCP, DNS or KCL, using fallback '$hostname'"
fi
if [ -z "$domain" ] && [ -n "$fqdn_domain" ]; then
	domain="${fqdn_domain}"
	log "using domain from DNS, as DHCP didn't supply one"
fi

domain="${domain%% *}" # in case domain is a list, some DHCP servers did that in the past instead of using search

# Normalize to lowercase
for var in hostname domain fqdn search fqdn_hostname fqdn_domain SLX_PXE_HOSTNAME; do
	declare "$var"="${!var~~}"
done

# 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
		[ "$sd" = "$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

declare -a localnames=()
[ -n "$fqdn" ] && localnames+=( "$fqdn" )
[ -n "$hostname" ] && localnames+=( "$hostname" )
[ -n "$fqdn_hostname" ] && [ "$hostname" != "$fqdn_hostname" ] && localnames+=( "$fqdn_hostname" )
[ -n "$SLX_PXE_HOSTNAME" ] && [ "$hostname" != "$SLX_PXE_HOSTNAME" ] && localnames+=( "$SLX_PXE_HOSTNAME" )

{
echo "127.0.0.1 localhost"
echo "127.0.1.1 ${localnames[*]}"
} > "/etc/hosts"

log "setting hostname $hostname, FQDN $fqdn"
echo "$hostname" > "/proc/sys/kernel/hostname"
echo "$hostname" > "/etc/hostname"
echo "SLX_HOSTNAME='$hostname'" >> "$NETWORK_CONF"

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