improvements
[automated-distro-installer] / fai / config / distro-install-common / ethusb-static
1 #!/bin/bash
2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to switch
7 # its license to GPL.
8
9 # Copyright 2024 Ian Kelling
10
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
14
15 # http://www.apache.org/licenses/LICENSE-2.0
16
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
22
23 # usage $0 [-c] [off]
24 # off: Turn off static ip.
25 # -c config only, don't tell networkmanager to change anything
26 # -f force interface reup
27
28 if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi
29 shopt -s inherit_errexit 2>/dev/null ||: # ignore fail in bash < 4.4
30 set -eE -o pipefail
31 trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" returned $?" >&2' ERR
32
33 m() { printf "%s\n" "$*"; "$@"; }
34
35
36 set-dynamic() {
37
38 reup=false
39 if [[ $cur_state == activated ]]; then
40 reup=true
41 fi
42
43 if [[ $cur_method != auto ]]; then
44 args+=(ipv4.method auto)
45 fi
46 if [[ $cur_ip != -- ]]; then
47 args+=(-ipv4.addresses "$ipv4_addresses")
48 fi
49 if [[ $cur_dns != -- ]]; then
50 args+=(-ipv4.dns "$ipv4_dns")
51 fi
52 if [[ $cur_gateway != -- ]]; then
53 # undocumented in t11 man nmcli. guessed randomly
54 args+=(ipv4.gateway 0.0.0.0)
55 fi
56 if (( ${#args[@]} >= 1 )); then
57 m nmcli con mod "$nm_con" "${args[@]}"
58 if $reup; then
59 m nmcli con up "$nm_con"
60 fi
61 else
62 echo "$0: found expected state, nothing to do."
63 fi
64 exit 0
65 set-nm
66 }
67
68 detect-net() {
69
70 # this assumes we have wifi up
71 if [[ $(timeout 1 dig +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]] \
72 && ip n show 10.2.0.1 | grep . &>/dev/null; then
73 net=home
74 elif ip r show default | grep 'via 10.0.3.1 dev wlan0' &>/dev/null && [[ $(timeout 1 dig +short @10.0.3.1 -x 10.0.3.1) == cmc1.lan. ]]; then
75 net=work
76 else
77 echo "$0: error could not detect network"
78 exit 1
79 fi
80
81 }
82
83 set-nm() {
84 m nmcli con mod "$nm_con" ipv4.method manual ipv4.addresses $ip ipv4.gateway $gateway ipv4.dns $dns
85 state=$(nmcli con show "$nm_con" 2>/dev/null | awk '$1 == "GENERAL.STATE:" {print $2}')
86 if [[ $state == activated ]]; then
87 m nmcli con up "$nm_con"
88 fi
89
90 }
91
92 get-ip() {
93
94 case $net in
95 home)
96
97 while read -r ip_suf host mac; do
98 if [[ ! $ip_suf || $ip_suf == \#* ]]; then
99 continue
100 fi
101 if [[ $mac != usb ]]; then
102 continue
103 fi
104 if [[ $host == ${HOSTNAME}c ]]; then
105
106 ip=10.2.0.$ip_suf/16
107 gateway=10.2.0.1
108 dns=8.8.8.4,8.8.8.8
109 break
110 fi
111 done </p/c/host-info
112
113 if [[ ! $ip_suf ]]; then
114 echo "$0: error: failed to find ${HOSTNAME}c ip suffix in /p/c/host-info"
115 exit 1
116 fi
117 ;;
118 work)
119
120 if ! ip r show default | grep 'via 192.168.0.1 dev eth' &>/dev/null; then
121 if [[ $cur_method != manual ]]; then
122 echo "$0: error. Need to be on wired network to get our ip"
123 exit 1
124 fi
125 set-dynamic
126 sleep 10
127 fi
128 myip=$(timeout 1 dig +short @192.168.0.25 $HOSTNAME.office.fsf.org)
129 if [[ ! $myip ]]; then
130 echo "$0: error: didnt detect home network and failed to get office ip"
131 exit 1
132 fi
133 dns=192.168.0.10,192.168.0.25
134 gateway=192.168.0.1
135 ip=$myip/24
136
137 ;;
138 esac
139 }
140
141
142 get-cur-val() {
143 local key
144 key=$1
145 printf "%s\n" "$tmpstr" | awk '$1 == "'$key':" {print $2}'
146 }
147
148 get-cur() {
149 tmpstr=$(nmcli con show "$nm_con" 2>/dev/null)
150
151 cur_method=$(get-cur-val ipv4.method)
152 cur_ip=$(get-cur-val ipv4.addresses)
153 cur_gateway=$(get-cur-val ipv4.gateway)
154 cur_dns=$(get-cur-val ipv4.dns)
155 cur_state=$(get-cur-val GENERAL.STATE)
156 }
157
158
159 ## begin arg parsing ##
160
161 force=false
162 off=false
163 while [[ $1 ]]; do
164 case $1 in
165 -f)
166 force=true
167 ;;
168 off)
169 off=true
170 ;;
171 *)
172 echo "$0: error unexpected argument: $1" >&2
173 exit 1
174 ;;
175 esac
176 shift
177 done
178
179 ## end arg parsing ##
180
181 ## begin common setup / detection ##
182 shopt -s nullglob
183
184 wiredx=1
185 declare -a args
186
187 # device that has an eth0, but we aren't using it because it is
188 # broken. We could just hardcode a mac comparison with `cat
189 # /sys/class/net/eth0/address` but this is cooler.
190 if [[ -e /sys/class/net/eth0 ]]; then
191 bus_info=$(ethtool -i eth0 | awk '$1 == "bus-info:" { print $2 }')
192 if [[ $bus_info != usb* ]]; then
193 wiredx=2
194 fi
195 fi
196
197 eth_dev=eth$(( wiredx - 1 ))
198
199 nm_con=$(nmcli device show $eth_dev | \
200 awk '$1 == "GENERAL.CONNECTION:" {out=$2; for(i=3;i<=NF;i++){out=out" "$i}; print out}' ||:)
201
202 if [[ ! $nm_con || $nm_con == -- ]]; then
203 nm_con="Wired connection $wiredx"
204 fi
205
206 if ! nmcli con | grep -q "^$nm_con " &>/dev/null; then
207 # Note: we could support creation through a file or via
208 # nmcli, but right now I'm ok with just having plugged in a device once
209 # since this os was installed.
210 echo "error: no existing connection: $nm_con found in output of nmcli con"
211 exit 0
212 fi
213
214
215 if ! type -p dig &>/dev/null; then
216 apt-get install dig
217 fi
218
219 get-cur
220 ## end common setup / detection ##
221
222 if $off; then
223 set-dynamic
224 exit 0
225 fi
226
227 detect-net
228 get-ip
229
230 if ! $force && [[ "$cur_method $cur_gateway $cur_dns $cur_ip" == "manual $gateway $dns $ip" ]]; then
231 echo "$0: found expected state, nothing to do."
232 exit 0
233 fi
234
235 set-nm
236
237
238
239 # example of down cli
240 #nmcli con mod 'Wired connection 1' ipv4.method auto -ipv4.addresses 10.2.0.9/16 ipv4.gateway 0.0.0.0 -ipv4.dns "8.8.8.4,8.8.8.8"
241
242
243 # FYI: the result of running, for example
244 # nmcli con mod "Wired connection 1" \
245 # ipv4.method manual \
246 # ipv4.addresses "10.2.0.23/24" \
247 # ipv4.gateway "10.2.0.1" \
248 # ipv4.dns "8.8.8.4,8.8.8.8"
249
250 # creates a fille named "/etc/NetworkManager/system-connections/Wired connection 1.nmconnection",
251 # below.
252 #
253 # The nmcli man page says you should just edit files in that dir and
254 # then run nmcli con reload to reread them all to load your changes, but
255 # I've found that to be unreliable, the systemd journal would say
256 # something like "reload happened" then nothing would change in the
257 # connect that the file clearly modifies, so I switched over to using
258 # the command line and just ignoring those files.
259 #
260 # I see no reason to keep the same file name, or a bunch of
261 # setting that seem irrelevant, and empty sections don't seem to do
262 # anything according to the man page.
263 #
264
265 # [connection]
266 # id=Wired connection 1
267 # uuid=b0fb7694-dfe6-31a1-81fa-7c17b61515a7
268 # type=ethernet
269 # interface-name=eth1
270 # timestamp=1715728264
271
272 # [ethernet]
273
274 # [ipv4]
275 # address1=10.2.0.23/16,10.2.0.1
276 # dns=8.8.8.4;8.8.8.8;
277 # method=manual
278
279 # [ipv6]
280 # addr-gen-mode=stable-privacy
281 # method=auto
282
283 # [proxy]