diff options
Diffstat (limited to 'nixos/modules/services/networking/dhclient.nix')
-rw-r--r-- | nixos/modules/services/networking/dhclient.nix | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/nixos/modules/services/networking/dhclient.nix b/nixos/modules/services/networking/dhclient.nix new file mode 100644 index 00000000000..1e343443899 --- /dev/null +++ b/nixos/modules/services/networking/dhclient.nix @@ -0,0 +1,111 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + inherit (pkgs) nettools dhcp lib; + + # Don't start dhclient on explicitly configured interfaces or on + # interfaces that are part of a bridge. + ignoredInterfaces = + map (i: i.name) (lib.filter (i: i ? ipAddress && i.ipAddress != "" ) config.networking.interfaces) + ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)); + + stateDir = "/var/lib/dhcp"; # Don't use /var/state/dhcp; not FHS-compliant. + + dhclientExitHooks = pkgs.writeText "dhclient-exit-hooks" + '' + #echo "$reason" >> /tmp/dhcp-exit + #echo "$exit_status" >> /tmp/dhcp-exit + + if test "$reason" = BOUND -o "$reason" = REBOOT; then + # Restart ntpd. (The "ip-up" event below will trigger the + # restart.) We need to restart it to make sure that it will + # actually do something: if ntpd cannot resolve the server + # hostnames in its config file, then it will never do + # anything ever again ("couldn't resolve ..., giving up on + # it"), so we silently lose time synchronisation. + ${config.system.build.upstart}/sbin/initctl stop ntpd + + ${config.system.build.upstart}/sbin/initctl emit -n ip-up + fi + + if test "$reason" = EXPIRE -o "$reason" = RELEASE; then + ${config.system.build.upstart}/sbin/initctl emit -n ip-down + fi + ''; + +in + +{ + + ###### implementation + + config = mkIf config.networking.useDHCP { + + # dhclient barfs if /proc/net/if_inet6 doesn't exist. + boot.kernelModules = [ "ipv6" ]; + + jobs.dhclient = + { startOn = "started network-interfaces"; + stopOn = "stopping network-interfaces"; + + path = [ dhcp ]; + + script = + '' + # Determine the interface on which to start dhclient. + interfaces= + + for i in $(cd /sys/class/net && ls -d *); do + # Only run dhclient on interfaces of type ARPHRD_ETHER + # (1), i.e. Ethernet. Ignore peth* devices; on Xen, + # they're renamed physical Ethernet cards used for + # bridging. Likewise for vif* and tap* (Xen) and + # virbr* and vnet* (libvirt). + if [ "$(cat /sys/class/net/$i/type)" = 1 ]; then + if ! for j in ${toString ignoredInterfaces}; do echo $j; done | grep -F -x -q "$i" && + ! echo "$i" | grep -x -q "peth.*\|vif.*\|tap.*\|virbr.*\|vnet.*"; + then + echo "Running dhclient on $i" + interfaces="$interfaces $i" + fi + fi + done + + if test -z "$interfaces"; then + echo 'No interfaces on which to start dhclient!' + exit 1 + fi + + mkdir -m 755 -p ${stateDir} + + exec dhclient -d $interfaces -e "PATH=$PATH" -lf ${stateDir}/dhclient.leases -sf ${dhcp}/sbin/dhclient-script + ''; + }; + + environment.systemPackages = [dhcp]; + + environment.etc = + [ # Dhclient hooks for emitting ip-up/ip-down events. + { source = dhclientExitHooks; + target = "dhclient-exit-hooks"; + } + ]; + + powerManagement.resumeCommands = + '' + ${config.system.build.upstart}/sbin/restart dhclient + ''; + + networking.interfaceMonitor.commands = + '' + if [ "$status" = up ]; then + ${config.system.build.upstart}/sbin/restart dhclient + fi + ''; + + }; + +} |