2 # Copyright (C) 2016 Ian Kelling
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 [[ $EUID == 0 ]] ||
exec sudo
-E "${BASH_SOURCE[0]}" "$@"
21 readonly this_file
="$(readlink -f -- "${BASH_SOURCE[0]}")"
22 script_dir
="${this_file%/*}"
23 # shellcheck source=./bash-trace
24 source "${script_dir}/bash-trace"
31 Usage: ${0##*/} [OPTIONS] [HOST] [TYPE]
32 Configure dnsmasq boot options and fai-chboot if appropriate. This is
33 not general purpose, it has code specific to dhcp servers I run.
35 Without TYPE, disable server and fai server. In that case, HOST is only
36 needed for fsf office network.
38 HOST Only do dhcp pxe for HOST. The hostname must be known to the dhcp
39 server to target its mac. Use "default" for all hosts.
40 Required in fsf office environment.
42 TYPE One of arch, parabola, plain, fai.
44 -a Don't setup pxe, just Wait for 2 dhcp acks, then disable the pxe
45 server after a delay. First ack is for pxe boot, 2nd ack is
46 for os boot. Sometimes on debian, there is a 3rd one shortly
47 after the 2nd. I can't remember exactly why this caused a
48 problem, but I'm hoping the sleep will take care of it.
49 -d Don't alter dhcp config. Only make sense for fai type, and on network
50 other than home or fsf, when using fai-cd, or pxe-kexec.
51 -k Pass -k to myfai-chboot.
52 --no-r Pass --no-r to myfai-chboot.
53 -r Don't redeploy fai config. For example, if there is a different host
56 -S sets FAI_ACTION=sysinfo, see myfai-chboot for more info.
57 -w Setup pxe, then wait like -a.
58 -h|--help Print help and exit
61 Note, when switching between plain and arch or parabola, you will need to
66 ln -s <arch/parabola/debian iso dir> tftpboot
69 Notes on debugging pxe dhcp tftp:
71 For debugging dhcp, add to /etc/dnsmasq.conf: log-dhcp
73 Newer openwrt runs dnsmasq with a whitelist of readable files and dirs:
76 /sbin/ujail -t 5 -n dnsmasq -u -l -r /bin/ubus -r /etc/TZ -r /etc/dnsmasq.conf -r /etc/ethers -r /etc/group -r /etc/hosts -r /etc/passwd -w /tmp/dhcp.leases -r /tmp/dnsmasq.d -r /tmp/hosts -r /tmp/resolv.conf.d -r /usr/bin/jshn -r /usr/lib/dnsmasq/dhcp-script.sh -r /usr/share/dnsmasq/dhcpbogushostname.conf -r /usr/share/dnsmasq/rfc6761.conf -r /usr/share/dnsmasq/trust-anchors.conf -r /usr/share/libubox/jshn.sh -r /var/etc/dnsmasq.conf.cfg01411c -w /var/run/dnsmasq/ -- /usr/sbin/dnsmasq -C /var/etc/dnsmasq.conf.cfg01411c -k -x /var/run/dnsmasq/dnsmasq.cfg01411c.pid
78 logging tftp requests:
79 /etc/default/tftpd-hpa:
81 TFTP_OPTIONS="--secure -vv"
84 Note: Uses GNU getopt options parsing style
90 m
() { printf "$pre %s\n" "$*"; "$@"; }
91 e
() { printf "$pre %s\n" "$*"; }
92 err
() { echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: $pre: $*" >&2; }
96 ##### begin command line parsing ########
105 x3|kw
) fsf_office
=true
;;
109 temp
=$
(getopt
-l no-r
,help adkrSwh
"$@") || usage
1
113 -a) wait=true
; set=false
; shift ;;
114 -d) dhcp
=false
; shift ;;
115 -k) chboot_args
+=(-k); shift ;;
116 --no-r) chboot_args
+=(--no-r); shift ;;
117 -r) redep
=false
; shift ;;
118 -S) chboot_args
+=(-S); shift ;;
119 -w) wait=true
; set=true
; shift ;;
122 *) echo "$0: Internal error!" ; exit 1 ;;
126 read -r host type <<<"$@"
132 arch|parabola
) cmd
=archlike
;;
135 echo "$0: error expected type of arch|parabola|fai"
142 echo "$0: error: expected 0-2 arguments"
149 if $wait && ! $dhcp; then
150 echo "$0: error -w conflicts with -d, choose one or other" >&2
154 if $fsf_office && [[ ! $host ]]; then
155 echo "$0: at fsf_office, provide HOST arg" >&2
159 if [[ $host && $host != default
]]; then
160 host_tag
="tag:$host,"
163 ##### end command line parsing ########
167 ${host_tag}209,boot/syslinux/${type}iso.cfg
168 ${host_tag}210,/${type}/
169 ${host_tag}option:bootfile-name,/${type}/boot/syslinux/lpxelinux.0
174 # if arch based was used before, this additionally needs
175 # the tftp link in /mnt/usb to be changed.
177 ${host_tag}option:bootfile-name,pxelinux.0
183 ${host_tag}option:bootfile-name,pxelinux.0
184 ${host_tag}option:server-ip-address,$faiserverip
185 ${host_tag}option:tftp-server,$faiserverip
187 # Note, previously used normal dnsmasq option, but it requires dnsmasq
188 # restart, which causes momentary dns failures, which can bork an
191 # dhcp-boot=${host_tag}pxelinux.0,faiserver.b8.nz,faiserver.b8.nz
196 wait_cmd
="ssh tarantula.office.fsf.org tail -n0 -f /var/log/syslog"
198 wait_cmd
="ssh cmc logread -f"
203 host_regex
=" $(getent hosts kw | awk '{print $1}' | sed 's/\./\\./g')"
208 regex
=".*DHCPACK.*$host_regex\b"
210 while (( i
!= wait_count
)) && read -r line
; do
211 if [[ $line =~
$regex ]]; then
215 done < <($wait_cmd ||
:) # tail returns 2 it seems
222 if [[ ! $cmd ]]; then
223 e
"removing pxe for $host on tarantula"
224 ssh tarantula.office.fsf.org bash
-e <<EOF
225 sed -ri 's/^( *host +$host *\{).*/\1/' /etc/dhcp/dhcpd.conf
226 systemctl restart isc-dhcp-server
228 elif [[ $cmd == fai
]]; then
229 e
"adding pxe for $host on tarantula"
230 ssh tarantula.office.fsf.org bash
-e <<EOF
231 sed -ri 's/^( *host +$host *\{).*/\1 next-server faiserver.office.fsf.org; filename "pxelinux.0";/' /etc/dhcp/dhcpd.conf
232 systemctl restart isc-dhcp-server
236 e
"updating dnsmasq.conf:"
238 ${cmd:-:}|
ssh cmc
"dd of=/var/run/dnsmasq/dhcpopts.conf; /etc/init.d/dnsmasq reload
239 $([[ $type == arch || $type == parabola ]] && echo archlike-pxe-mount)"
243 type -t host &>/dev
/null || sudo apt-get
-y install dnsutils
244 faiserverip
=$
(host faiserver |
sed -rn 's/^\S+ has address //p;T;q' ||
:)
245 if [[ ! $faiserverip ||
$faiserverip =~
[[:space
:]] ]]; then
246 echo "$0: error: failed to get \$faiserverip, got: $faiserverip"
253 if [[ $type == fai
]]; then
257 m myfai-chboot
${chboot_args[@]} $host
259 # This will fail if faiserver is not setup, so ignore any
260 # failure and don't bother us about it.
261 m myfai-chboot
&>/dev
/null ||
:
266 # fai's debian jessie 8.5ish does 2 dhcp requests when booting,
267 # roughly 4 seconds apart. Earlier
268 # versions did just 1. Now testing on a vm, it does 1.
270 echo "waiting for $acks dhcp acks then disabling pxe"
276 # previously tried waiting for one more ack then disabling faiserver,
277 # since it can contain sensitive info, so turn it off when not in use,
278 # but disabling that for now as it's inconvenient to clean this
279 # up and run it in the background etc.
281 # if [[ $type == fai ]]; then
282 # echo "waiting for 1 dhcp ack then disabling fai server"