Blame SOURCES/chrony.helper

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