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 set -e; .
/usr
/local
/lib
/bash-bear
; set +e
23 this_file
="$(readlink -f -- "${BASH_SOURCE[0]}")"
24 readonly this_file this_dir
="${this_file%/*}"
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 # shellcheck disable=SC2087 # shellcheck being dumb
225 ssh tarantula.office.fsf.org bash
-e <<EOF
226 sed -ri 's/^( *host +$host *\{).*/\1/' /etc/dhcp/dhcpd.conf
227 systemctl restart isc-dhcp-server
229 elif [[ $cmd == fai
]]; then
230 e
"adding pxe for $host on tarantula"
231 # shellcheck disable=SC2087 # shellcheck being dumb
232 ssh tarantula.office.fsf.org bash
-e <<EOF
233 sed -ri 's/^( *host +$host *\{).*/\1 next-server faiserver.office.fsf.org; filename "pxelinux.0";/' /etc/dhcp/dhcpd.conf
234 systemctl restart isc-dhcp-server
238 e
"updating dnsmasq.conf:"
240 ${cmd:-:}|
ssh cmc
"dd of=/var/run/dnsmasq/dhcpopts.conf; /etc/init.d/dnsmasq reload
241 $([[ $type == arch || $type == parabola ]] && echo archlike-pxe-mount)"
245 type -t host &>/dev
/null || sudo apt-get
-y install dnsutils
246 faiserverip
=$
(host faiserver |
sed -rn 's/^\S+ has address //p;T;q' ||
:)
247 if [[ ! $faiserverip ||
$faiserverip =~
[[:space
:]] ]]; then
248 echo "$0: error: failed to get \$faiserverip, got: $faiserverip"
255 if [[ $type == fai
]]; then
259 m myfai-chboot
${chboot_args[@]} $host
261 # This will fail if faiserver is not setup, so ignore any
262 # failure and don't bother us about it.
263 m myfai-chboot
&>/dev
/null ||
:
268 # fai's debian jessie 8.5ish does 2 dhcp requests when booting,
269 # roughly 4 seconds apart. Earlier
270 # versions did just 1. Now testing on a vm, it does 1.
272 echo "waiting for $acks dhcp acks then disabling pxe"
278 # previously tried waiting for one more ack then disabling faiserver,
279 # since it can contain sensitive info, so turn it off when not in use,
280 # but disabling that for now as it's inconvenient to clean this
281 # up and run it in the background etc.
283 # if [[ $type == fai ]]; then
284 # echo "waiting for 1 dhcp ack then disabling fai server"