Introduction

In this blog we are going to talk about NetworkManager dispatcher scripts and how to utilize them as a Linux developer or admin.

NetworkManager-dispatcher is a D-Bus activated service that runs user provided scripts upon certain changes in NetworkManager. This can be useful for system admins or linux developers as it allows them to run simple commands or even complex scripts in response to network events.

Example Use Cases

The dispatcher service can be quite flexible and can be used for a variety of purposes. Some example use cases are listed below:

  1. A simple use case could be to run a script that does additional device configuration when the device is brought up.
  2. A script that adds additional routing rules for a device when it is brought up.
  3. A script that renames a devices when it is brought up.

Scripts

We will discuss the various technical details about the scripts in this section. All the dispatcher scripts should be placed in the directory /etc/NetworkManager/dispatcher.d/.

Arguments

The scripts receive two arguments as input which are as follows:

  1. Interface Name
  2. Event

Interface Name

As the name suggests this argument contains the name of the interface on which the action should be performed by NetworkManager.

Event

The event describes the action that to be performed on the given interface. NM-dispatcher scripts can be hooked onto the following events:

  • pre-up: The interface is connected to the network but is not yet fully activated.
  • up: The interface has been activated.
  • pre-down: The interface will be deactivated but has not yet been disconnected from the network.
  • down: The interface has been deactivated.
  • vpn-pre-up: VPN is connected to the network but is not yet fully activated.
  • vpn-up: A VPN connection has been activated.
  • vpn-pre-down: VPN will be deactivated but has not yet been disconnected from the network.
  • vpn-down: A VPN connection has been deactivated.
  • hostname: The system hostname has been updated. The interface name (first argument) is empty and no environment variable is set for this action.
  • dhcp4-change: The DHCPv4 lease has changed (renewed, rebound, etc).
  • dhcp6-change: The DHCPv6 lease has changed (renewed, rebound, etc).
  • connectivity-change: The network connectivity state has changed (no connectivity, went online, etc). The interface name(arg 1) is empty.
  • reapply: The connection was reapplied on the device.
  • dns-change: The DNS configuration has changed. This action is raised even if NetworkManager is configured to not manage resolv.conf. The interface name(arg 1) is empty.
  • device-add: This action is called when a connection of type generic has the generic.device-handler property set. The property indicates the name of a dispatcher script to be run in directory /{etc,usr/lib}/NetworkManager/dispatcher.d/device. Please refer to the manual page for more information on this event.
  • device-delete: This action is the counterpart of device-add and is called to delete the device for a generic connection. All the aspects described for device-add also apply to this action.

NOTE: Any of the events related to pre-up and pre-down need to have their scripts placed or symlinked into the /etc/NetworkManager/dispatcher.d/pre-up.d or /etc/NetworkManager/dispatcher.d/pre-down.d directories respectively. In the case of pre-up, NetworkManager will wait for the script to complete before indicating to applications that the interface is fully activated and for pre-down, NetworkManager will wait for the script to complete before disconnecting the interface from its network.

Environment Variables

The environment contains more information about the interface and the connection. The following variables are available for use in dispatcher scripts:

  • NM_DISPATCHER_ACTION: The dispatcher action like “up” or “dhcp4-change”, identical to the first command line argument.
  • CONNECTION_UUID: The UUID of the connection profile.
  • CONNECTION_ID: The name (ID) of the connection profile.
  • CONNECTION_DBUS_PATH: The NetworkManager D-Bus path of the connection.
  • CONNECTION_FILENAME: The backing file name of the connection profile (if any).
  • CONNECTION_EXTERNAL: If “1”, this indicates that the connection describes a network configuration created outside of NetworkManager.
  • DEVICE_IFACE: The interface name of the control interface of the device.
  • DEVICE_IP_IFACE: The IP interface name of the device. This is the network interface on which IP addresses and routes will be configured.
  • IP4_ADDRESS_N: The IPv4 address in the format “address/prefix gateway”, where N is a number from 0 to # (IPv4 addresses – 1).
  • IP4_NUM_ADDRESSES: The variable contains the number of IPv4 addresses the script may expect.
  • IP4_GATEWAY: The gateway IPv4 address in traditional numbers-and-dots notation.
  • IP4_ROUTE_N: The IPv4 route in the format “address/prefix next-hop metric”, where N is a number from 0 to # (IPv4 routes – 1).
  • IP4_NUM_ROUTES: The variable contains the number of IPv4 routes the script may expect.
  • IP4_NAMESERVERS: The variable contains a space-separated list of the DNS servers.
  • IP4_DOMAINS: The variable contains a space-separated list of the search domains.
  • DHCP4_<dhcp-option-name>: If the connection used DHCP for address configuration, the received DHCP configuration is passed in the environment using standard DHCP option names, prefixed with “DHCP4_”, like “DHCP4_HOST_NAME=foobar”.
  • IP6_<name> and DHCP6_<name>: The same variables as for IPv4 are available for IPv6, but the prefixes are IP6_ and DHCP6_ instead.
  • CONNECTIVITY_STATE: The network connectivity state, which can take the values: UNKNOWN, NONE, PORTAL, LIMITED or FULL. Note: this variable will only be set for connectivity-change actions.

NOTE: In case of VPN, VPN_IP_IFACE is set, and IP4_, IP6_ variables with VPN prefix are exported too, like VPN_IP4_ADDRESS_0, VPN_IP4_NUM_ADDRESSES.

Order of scripts:

Understanding the order of script invocations can be useful when writing your dispatcher scripts or debugging issues related to the dispatcher scripts.

The scripts placed in the /etc/NetworkManager/dispatcher.d/ directory are run alphabetically. The scripts are usually prefixed with a number xx-dispatcher-script. The lower the prefix number for the script the higher the priority for the script and will be invoked accordingly.

[root@kvm dispatcher.d]# ls
00-netreport  04-iscsi  11-dhclient  20-chrony  no-wait.d  pre-down.d  pre-up.d
[root@kvm dispatcher.d]#

Understanding Script Execution:

In the section we will talk about how the scripts are invoked and some important things to keep in mind while developing these scripts.

The first thing to discuss is when are these scripts invoked. We discussed the various events that these scripts can be used to hook on in the above section. The scripts that are placed in /etc/NetworkManager/dispatcher.d are run sequentially for every network event that occurs, with the exception of scripts placed in /etc/NetworkManager/pre-up.d and /etc/NetworkManager/pre-down.d.

So it is the responsibility of the script author to check the arguments and environment variables to correctly identify the context in which it is being run and then proceed to either continue with the script or exit if the context does not match the requirements.

Another important item to keep in mind is that when the dispatcher script is being run, it does block the NetworkManager startup process and if you have beefy scripts with long run times, this could lead to an undesirable situation where the NetworkManager startup can be delayed.

Dispatcher scripts are run one at a time and will be killed if they run for too long. If your script takes an arbitrarily long time to complete, you should spawn a child process and have the parent return immediately.

Scripts that are symbolic links pointing inside the /etc/NetworkManager/dispatcher.d/no-wait.d/ directory are run immediately, without waiting for the termination of previous scripts, and in parallel. Also beware that once a script is queued, it will always be run, even if a later event renders it obsolete.

Sample Script:

This is simple script brings up certain interfaces after checking that the Physical devices for the interfaces are up after NetworkManager has completed it’s startup process, and serves as a example of of a working script.

#!/usr/bin/env bash

INTERFACE="$1"
EVENT="$2"
DIR="/etc/sysconfig/network-scripts"

pkey_up_func() {
        ## We wait for 5 mins (300 secs) to detect NetworkManager startup. ##
        nm-online --wait-for-startup --timeout 300
        status=$?
        if [[ "$status" == "0" ]]; then
                logger "$0: nm-online detected that NetworkManager has completed start-up."
                for file in $DIR/ifcfg-*
                do
                        if [[ $file == *"clib"* || $file == *"stib"* ]]; then
                                source $file
                                ip link show $PHYSDEV
                                ret=$?
                                ip link show $DEVICE | grep UP -q
                                dev=$?
                                if [[ "$ret" == "0" && "$dev" == "1" ]]; then
                                        logger "$0: Bringing up pkey-ed device: $DEVICE."
                                        ifup $DEVICE
                                elif [[ "$dev" == "0"  ]]; then
                                        logger "$0: $DEVICE is already up."
                                else
                                        logger "$0 $PHYSDEV for device: $DEVICE was not found."
                                fi
                        fi
                done
        elif [[ "$status" == "1" ]]; then
                logger "$0: nm-online timeout exceeded while attempting to detect NetworkManager startup."
        else
                logger "$0: nm-online encountered an unexpected error."
        fi
}

if [[ "$EVENT" == "hostname" ]]; then
        ## NetworkManager should not wait while we check for nm-online, so we fork a new process and run nm-online there.  ##
        pkey_up_func &
fi

Summary

In this article, we covered the various aspects related to NetworkManager-dispatcher scripts. We covered the various arguments and environment variables that are provided to the dispatcher script and how an admin or developer can utilize them to make their own scripts that react to these network events. We also covered the ordering in which they are invoked by NetworkManager.

All that is left is now for you to get started on making your own dispatcher scripts !

References