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, or when using fai-cd.
51 -k Pass -k to myfai-chboot.
52 -r Don't redeploy fai config. For example, if there is a different host
55 -S sets FAI_ACTION=sysinfo, see myfai-chboot for more info.
56 -w Setup pxe, then wait like -a.
57 -h|--help Print help and exit
60 Note, when switching between plain and arch or parabola, you will need to
65 ln -s <arch/parabola/debian iso dir> tftpboot
68 Notes on debugging pxe dhcp tftp:
70 For debugging dhcp, add to /etc/dnsmasq.conf: log-dhcp
72 Newer openwrt runs dnsmasq with a whitelist of readable files and dirs:
75 /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
77 logging tftp requests:
78 /etc/default/tftpd-hpa:
80 TFTP_OPTIONS="--secure -vv"
83 Note: Uses GNU getopt options parsing style
89 m
() { printf "$pre %s\n" "$*"; "$@"; }
90 e
() { printf "$pre %s\n" "$*"; }
91 err
() { echo "[$(date +'%Y-%m-%d %H:%M:%S%z')]: $pre: $*" >&2; }
95 ##### begin command line parsing ########
104 x3|kw
) fsf_office
=true
;;
108 temp
=$
(getopt
-l help adkrSwh
"$@") || usage
1
112 -a) wait=true
; set=false
; shift ;;
113 -d) dhcp
=false
; shift ;;
114 -k) chboot_args
+=(-k); shift ;;
115 -r) redep
=false
; shift ;;
116 -S) chboot_args
+=(-S); shift ;;
117 -w) wait=true
; set=true
; shift ;;
120 *) echo "$0: Internal error!" ; exit 1 ;;
124 read -r host type <<<"$@"
130 arch|parabola
) cmd
=archlike
;;
133 echo "$0: error expected type of arch|parabola|fai"
140 echo "$0: error: expected 0-2 arguments"
147 if $wait && ! $dhcp; then
148 echo "$0: error -w conflicts with -d, choose one or other" >&2
152 if $fsf_office && [[ ! $host ]]; then
153 echo "$0: at fsf_office, provide HOST arg" >&2
157 if [[ $host && $host != default
]]; then
158 host_tag
="tag:$host,"
161 ##### end command line parsing ########
165 ${host_tag}209,boot/syslinux/${type}iso.cfg
166 ${host_tag}210,/${type}/
167 ${host_tag}option:bootfile-name,/${type}/boot/syslinux/lpxelinux.0
172 # if arch based was used before, this additionally needs
173 # the tftp link in /mnt/usb to be changed.
175 ${host_tag}option:bootfile-name,pxelinux.0
181 ${host_tag}option:bootfile-name,pxelinux.0
182 ${host_tag}option:server-ip-address,$faiserverip
183 ${host_tag}option:tftp-server,$faiserverip
185 # Note, previously used normal dnsmasq option, but it requires dnsmasq
186 # restart, which causes momentary dns failures, which can bork an
189 # dhcp-boot=${host_tag}pxelinux.0,faiserver.b8.nz,faiserver.b8.nz
194 wait_cmd
="ssh tarantula.office.fsf.org tail -n0 -f /var/log/syslog"
196 wait_cmd
="ssh cmc logread -f"
201 host_regex
=" $(getent hosts kw | awk '{print $1}' | sed 's/\./\\./g')"
206 regex
=".*DHCPACK.*$host_regex\b"
208 while (( i
!= wait_count
)) && read -r line
; do
209 if [[ $line =~
$regex ]]; then
213 done < <($wait_cmd ||
:) # tail returns 2 it seems
220 if [[ ! $cmd ]]; then
221 e
"removing pxe for $host on tarantula"
222 ssh tarantula.office.fsf.org bash
-e <<EOF
223 sed -ri 's/^( *host +$host *\{).*/\1/' /etc/dhcp/dhcpd.conf
224 systemctl restart isc-dhcp-server
226 elif [[ $cmd == fai
]]; then
227 e
"adding pxe for $host on tarantula"
228 ssh tarantula.office.fsf.org bash
-e <<EOF
229 sed -ri 's/^( *host +$host *\{).*/\1 next-server faiserver.office.fsf.org; filename "pxelinux.0";/' /etc/dhcp/dhcpd.conf
230 systemctl restart isc-dhcp-server
234 e
"updating dnsmasq.conf:"
236 ${cmd:-:}|
ssh cmc
"dd of=/var/run/dnsmasq/dhcpopts.conf; /etc/init.d/dnsmasq reload
237 $([[ $type == arch || $type == parabola ]] && echo archlike-pxe-mount)"
241 type -t host &>/dev
/null || sudo apt-get
-y install dnsutils
242 faiserverip
=$
(host faiserver |
sed -rn 's/^\S+ has address //p;T;q' ||
:)
243 if [[ ! $faiserverip ||
$faiserverip =~
[[:space
:]] ]]; then
244 echo "$0: error: failed to get \$faiserverip, got: $faiserverip"
251 if [[ $type == fai
]]; then
255 m myfai-chboot
${chboot_args[@]} $host
257 # This will fail if faiserver is not setup, so ignore any
258 # failure and don't bother us about it.
259 m myfai-chboot
&>/dev
/null ||
:
264 # fai's debian jessie 8.5ish does 2 dhcp requests when booting,
265 # roughly 4 seconds apart. Earlier
266 # versions did just 1. Now testing on a vm, it does 1.
268 echo "waiting for $acks dhcp acks then disabling pxe"
274 # previously tried waiting for one more ack then disabling faiserver,
275 # since it can contain sensitive info, so turn it off when not in use,
276 # but disabling that for now as it's inconvenient to clean this
277 # up and run it in the background etc.
279 # if [[ $type == fai ]]; then
280 # echo "waiting for 1 dhcp ack then disabling fai server"