Blame SOURCES/chrony.helper

c2c5e4
#!/bin/bash
d84c6e
# This script configures running chronyd to use NTP servers obtained from
d84c6e
# DHCP and _ntp._udp DNS SRV records. Files with servers from DHCP are managed
d84c6e
# externally (e.g. by a dhclient script). Files with servers from DNS SRV
d84c6e
# records are updated here using the dig utility.
c2c5e4
c2c5e4
chronyc=/usr/bin/chronyc
d84c6e
helper_dir=/var/run/chrony-helper
d84c6e
added_servers_file=$helper_dir/added_servers
d84c6e
d84c6e
network_sysconfig_file=/etc/sysconfig/network
d84c6e
dhclient_servers_files=/var/lib/dhclient/chrony.servers.*
d84c6e
dnssrv_servers_files=$helper_dir/dnssrv@*
d84c6e
dnssrv_timer_prefix=chrony-dnssrv@
c2c5e4
c2c5e4
chrony_command() {
d84c6e
    $chronyc -a -n -m "$1"
c2c5e4
}
c2c5e4
d84c6e
is_running() {
d84c6e
    chrony_command "tracking" &> /dev/null
c2c5e4
}
c2c5e4
d84c6e
is_update_needed() {
d84c6e
    for file in $dhclient_servers_files $dnssrv_servers_files \
d84c6e
            $added_servers_file; do
d84c6e
        [ -e "$file" ] && return 0
d84c6e
    done
d84c6e
    return 1
c2c5e4
}
c2c5e4
d84c6e
update_daemon() {
d84c6e
    local all_servers_with_args all_servers added_servers
d84c6e
d84c6e
    if ! is_running; then
d84c6e
        rm -f $added_servers_file
d84c6e
        return 0
d84c6e
    fi
d84c6e
d84c6e
    all_servers_with_args=$(
d84c6e
        cat $dhclient_servers_files $dnssrv_servers_files 2> /dev/null)
d84c6e
c2c5e4
    all_servers=$(
d84c6e
        echo "$all_servers_with_args" |
c2c5e4
            while read server serverargs; do
c2c5e4
                echo "$server"
c2c5e4
            done | sort -u)
d84c6e
    added_servers=$( (
d84c6e
        cat $added_servers_file 2> /dev/null
d84c6e
        echo "$all_servers_with_args" |
d84c6e
            while read server serverargs; do
d84c6e
                [ -z "$server" ] && continue
d84c6e
                chrony_command "add server $server $serverargs" &> /dev/null &&
d84c6e
                    echo "$server"
d84c6e
            done) | sort -u)
d84c6e
d84c6e
    comm -23 <(echo -n "$added_servers") <(echo -n "$all_servers") |
c2c5e4
        while read server; do
c2c5e4
            chrony_command "delete $server" &> /dev/null
c2c5e4
        done
d84c6e
d84c6e
    added_servers=$(comm -12 <(echo -n "$added_servers") <(echo -n "$all_servers"))
d84c6e
d84c6e
    [ -n "$added_servers" ] && echo "$added_servers" > $added_servers_file ||
d84c6e
        rm -f $added_servers_file
c2c5e4
}
c2c5e4
d84c6e
get_dnssrv_servers() {
d84c6e
    local name=$1
d84c6e
d84c6e
    if ! command -v dig &> /dev/null; then
d84c6e
        echo "Missing dig (DNS lookup utility)" >&2
d84c6e
        return 1
d84c6e
    fi
d84c6e
d84c6e
    (
d84c6e
        . $network_sysconfig_file &> /dev/null
d84c6e
d84c6e
        output=$(dig "$name" srv +short +ndots=2 +search 2> /dev/null)
d84c6e
        [ $? -ne 0 ] && return 0
d84c6e
d84c6e
        echo "$output" | while read prio weight port target; do
d84c6e
            server=${target%.}
d84c6e
            [ -z "$server" ] && continue
d84c6e
            echo "$server port $port ${NTPSERVERARGS:-iburst}"
d84c6e
        done
d84c6e
    )
d84c6e
}
d84c6e
d84c6e
check_dnssrv_name() {
d84c6e
    local name=$1
d84c6e
d84c6e
    if [ -z "$name" ]; then
d84c6e
        echo "No DNS SRV name specified" >&2
d84c6e
        return 1
d84c6e
    fi
d84c6e
d84c6e
    if [ "${name:0:9}" != _ntp._udp ]; then
d84c6e
        echo "DNS SRV name $name doesn't start with _ntp._udp" >&2
d84c6e
        return 1
d84c6e
    fi
d84c6e
}
d84c6e
d84c6e
update_dnssrv_servers() {
d84c6e
    local name=$1
d84c6e
    local srv_file=$helper_dir/dnssrv@$name servers
d84c6e
d84c6e
    check_dnssrv_name "$name" || return 1
d84c6e
d84c6e
    servers=$(get_dnssrv_servers "$name")
d84c6e
    [ -n "$servers" ] && echo "$servers" > "$srv_file" || rm -f "$srv_file"
d84c6e
}
d84c6e
d84c6e
set_dnssrv_timer() {
d84c6e
    local state=$1 name=$2
d84c6e
    local srv_file=$helper_dir/dnssrv@$name servers
d84c6e
    local timer=$dnssrv_timer_prefix$name.timer
d84c6e
d84c6e
    check_dnssrv_name "$name" || return 1
d84c6e
d84c6e
    if [ "$state" = enable ]; then
d84c6e
        systemctl enable "$timer"
d84c6e
        systemctl start "$timer"
d84c6e
    elif [ "$state" = disable ]; then
d84c6e
        systemctl stop "$timer"
d84c6e
        systemctl disable "$timer"
d84c6e
        rm -f "$srv_file"
d84c6e
    fi
d84c6e
}
d84c6e
d84c6e
list_dnssrv_timers() {
d84c6e
    systemctl --all --full -t timer list-units | grep "^$dnssrv_timer_prefix" | \
d84c6e
        sed "s|^$dnssrv_timer_prefix\(.*\)\.timer.*|\1|"
d84c6e
}
d84c6e
d84c6e
prepare_helper_dir() {
d84c6e
    mkdir -p $helper_dir
d84c6e
    exec 100> $helper_dir/lock
d84c6e
    if ! flock -w 20 100; then
d84c6e
        echo "Failed to lock $helper_dir" >&2
d84c6e
        return 1
d84c6e
    fi
d84c6e
}
d84c6e
d84c6e
print_help() {
d84c6e
    echo "Usage: $0 COMMAND"
d84c6e
    echo
d84c6e
    echo "Commands:"
d84c6e
    echo "	update-daemon"
d84c6e
    echo "	update-dnssrv-servers NAME"
d84c6e
    echo "	enable-dnssrv NAME"
d84c6e
    echo "	disable-dnssrv NAME"
d84c6e
    echo "	list-dnssrv"
d84c6e
    echo "	is-running"
d84c6e
    echo "	command CHRONYC-COMMAND"
c2c5e4
}
c2c5e4
c2c5e4
case "$1" in
d84c6e
    update-daemon|add-dhclient-servers|remove-dhclient-servers)
d84c6e
        is_update_needed || exit 0
d84c6e
        prepare_helper_dir && update_daemon
d84c6e
        ;;
d84c6e
    update-dnssrv-servers)
d84c6e
        prepare_helper_dir && update_dnssrv_servers "$2" && update_daemon
c2c5e4
        ;;
d84c6e
    enable-dnssrv)
d84c6e
        set_dnssrv_timer enable "$2"
d84c6e
        ;;
d84c6e
    disable-dnssrv)
d84c6e
        set_dnssrv_timer disable "$2" && prepare_helper_dir && update_daemon
d84c6e
        ;;
d84c6e
    list-dnssrv)
d84c6e
        list_dnssrv_timers
c2c5e4
        ;;
c2c5e4
    is-running)
c2c5e4
        is_running
c2c5e4
        ;;
d84c6e
    command|forced-command)
c2c5e4
        chrony_command "$2"
c2c5e4
        ;;
c2c5e4
    *)
d84c6e
        print_help
c2c5e4
        exit 2
c2c5e4
esac
c2c5e4
d84c6e
exit $?