#!/bin/bash
# -*- mode: sh; sh-basic-offset: 2; indent-tabs-mode: nil; -*-
# vim:set ft=sh et sw=2 ts=2:
#
# interface-dispatcher v1.2 - service restart on interface change
# Author: Scott Shambarger <devel@shambarger.net>
#
# Copyright (C) 2015-2019 Scott Shambarger
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Copy this file to /usr/lib/NetworkManager/dispatcher.d/<##>-<service>
# (or wherever your distro has these files) where <##> is a 2-digit
# number, and <service> is a systemd service name.  This dispatcher
# will then restart or stop <service> based on interface availability
# (ie, if daemon has a UDP listener)
#
# Config file required for operation:
#   /etc/nmutils/conf/ifd-<service>-<interface>.conf (config)
#
# Config options are:
#
#   RESTART_UP, RESTART_DOWN, RESTART_CHANGE, RESTART_CHANGE6 -
#     Non-empty values restart service on interface "up", "down" or
#     ipv4 or ipv6 address changes (respectively).  Only active services
#     are restarted.
#
#   STOP_UP, STOP_DOWN, STOP_CHANGE -
#     Stops the service on the based on the new interface state.
#
#   STATE_FILE - if not empty, writes RESTART_UP/CHANGE/DOWN value to a file
#     with this name before restarting the service, or removes the file
#     if STOP_UP/DOWN/CHANGE is set (may be used for conditional service
#     starts on boot)
#
interface="$1"
action="$2"

# set NMUTILS/NMCONF early, and allow environment to override
NMUTILS="${NMUTILS:-/etc/nmutils}"
NMCONF="${NMCONF:-$NMUTILS/conf}"

########## SCRIPT START

# anything for us to do?
[ -n "$interface" -a -n "$action" ] || exit 0

# load general-functions
NMG="${NMG:-$NMUTILS/general-functions}"
[ -f "$NMG" -a -r "$NMG" ] && . "$NMG" || {
    echo 1>&2 "Unable to load $NMG" && exit 2
  }

# check dispatcher name format for ##-service
echo $0 | /bin/grep -q '^.*[0-9][0-9]-'
[ $? -ne 0 ] && nmg_err "Invalid command name: $0" && exit 3

SVC_UNIT=$(echo $0 | sed 's/^.*[0-9][0-9]-//')
[ -z "$SVC_UNIT" ] && nmg_err "Missing service name on $0" && exit 4

SVC_CONFIG="$NMCONF/ifd-${SVC_UNIT}-${interface}.conf"

# see if we're configured for this interface
nmg_read_config "$SVC_CONFIG" || exit 0

function svc_action() {
  # <restart-value> <stop-value>
  local restart="$1" stop="$2"
  if [ -n "$restart" ]; then
    [ -n "$STATE_FILE" ] && nmg_write "$STATE_FILE" "$restart"
    /usr/bin/systemctl 2>/dev/null -q is-enabled "$SVC_UNIT" || return 0
    /usr/bin/systemctl reload-or-restart "$SVC_UNIT"
  elif [ -n "$stop" ]; then
    [ -n "$STATE_FILE" ] && nmg_remove "$STATE_FILE"
    /usr/bin/systemctl stop "$SVC_UNIT"
  fi
}

case "$action" in
  up)
    svc_action "$RESTART_UP" "$STOP_UP"
    ;;
  down)
    svc_action "$RESTART_DOWN" "$STOP_DOWN"
    ;;
  dhcp4-change)
    svc_action "$RESTART_CHANGE" "$STOP_CHANGE"
    ;;
  dhcp6-change)
    svc_action "$RESTART_CHANGE6" "$STOP_CHANGE6"
    ;;
esac

exit 0
