diff --git a/modules/services/networking/dhcpcd.nix b/modules/services/networking/dhcpcd.nix new file mode 100644 index 00000000000..ce0c08dda3a --- /dev/null +++ b/modules/services/networking/dhcpcd.nix @@ -0,0 +1,92 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + inherit (pkgs) dhcpcd; + + # Don't start dhclient on explicitly configured interfaces or on + # interfaces that are part of a bridge. + ignoredInterfaces = + map (i: i.name) (filter (i: i ? ipAddress && i.ipAddress != "" ) config.networking.interfaces) + ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)); + +in + +{ + + ###### interface + + options = { + + networking.useDHCP = mkOption { + default = true; + merge = mergeEnableOption; + description = " + Whether to use DHCP to obtain an IP adress and other + configuration for all network interfaces that are not manually + configured. + "; + }; + + }; + + + ###### implementation + + config = mkIf config.networking.useDHCP { + + jobs.dhcpcd = + { startOn = "started network-interfaces"; + stopOn = "stopping network-interfaces"; + + path = [ dhcpcd pkgs.nettools pkgs.openresolv ]; + + script = + '' + # Determine the interface on which to start dhcpcd. + interfaces= + + for i in $(cd /sys/class/net && ls -d *); do + # Only run dhcpcd 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 dhcpcd on $i" + interfaces="$interfaces $i" + fi + fi + done + + if [ -z "$interfaces" ]; then + echo 'No interfaces on which to start dhcpcd!' + exit 1 + fi + + exec dhcpcd --nobackground --persistent $interfaces + ''; + }; + + environment.systemPackages = [ dhcpcd ]; + + powerManagement.resumeCommands = + '' + ${config.system.build.upstart}/sbin/restart dhcpcd + ''; + + networking.interfaceMonitor.commands = + '' + if [ "$status" = up ]; then + ${config.system.build.upstart}/sbin/restart dhcpcd + fi + ''; + + }; + +}