at 15.09-beta 6.8 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 dhcpcd = if !config.boot.isContainer then pkgs.dhcpcd else pkgs.dhcpcd.override { udev = null; }; 8 9 cfg = config.networking.dhcpcd; 10 11 interfaces = attrValues config.networking.interfaces; 12 13 enableDHCP = config.networking.useDHCP || any (i: i.useDHCP == true) interfaces; 14 15 # Don't start dhcpcd on explicitly configured interfaces or on 16 # interfaces that are part of a bridge, bond or sit device. 17 ignoredInterfaces = 18 map (i: i.name) (filter (i: if i.useDHCP != null then !i.useDHCP else i.ip4 != [ ] || i.ipAddress != null) interfaces) 19 ++ mapAttrsToList (i: _: i) config.networking.sits 20 ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bridges)) 21 ++ concatLists (attrValues (mapAttrs (n: v: v.interfaces) config.networking.bonds)) 22 ++ config.networking.dhcpcd.denyInterfaces; 23 24 arrayAppendOrNull = a1: a2: if a1 == null && a2 == null then null 25 else if a1 == null then a2 else if a2 == null then a1 26 else a1 ++ a2; 27 28 # If dhcp is disabled but explicit interfaces are enabled, 29 # we need to provide dhcp just for those interfaces. 30 allowInterfaces = arrayAppendOrNull cfg.allowInterfaces 31 (if !config.networking.useDHCP && enableDHCP then 32 map (i: i.name) (filter (i: i.useDHCP == true) interfaces) else null); 33 34 # Config file adapted from the one that ships with dhcpcd. 35 dhcpcdConf = pkgs.writeText "dhcpcd.conf" 36 '' 37 # Inform the DHCP server of our hostname for DDNS. 38 hostname 39 40 # A list of options to request from the DHCP server. 41 option domain_name_servers, domain_name, domain_search, host_name 42 option classless_static_routes, ntp_servers, interface_mtu 43 44 # A ServerID is required by RFC2131. 45 # Commented out because of many non-compliant DHCP servers in the wild :( 46 #require dhcp_server_identifier 47 48 # A hook script is provided to lookup the hostname if not set by 49 # the DHCP server, but it should not be run by default. 50 nohook lookup-hostname 51 52 # Ignore peth* devices; on Xen, they're renamed physical 53 # Ethernet cards used for bridging. Likewise for vif* and tap* 54 # (Xen) and virbr* and vnet* (libvirt). 55 denyinterfaces ${toString ignoredInterfaces} lo peth* vif* tap* tun* virbr* vnet* vboxnet* sit* 56 57 # Use the list of allowed interfaces if specified 58 ${optionalString (allowInterfaces != null) "allowinterfaces ${toString allowInterfaces}"} 59 60 ${cfg.extraConfig} 61 ''; 62 63 # Hook for emitting ip-up/ip-down events. 64 exitHook = pkgs.writeText "dhcpcd.exit-hook" 65 '' 66 if [ "$reason" = BOUND -o "$reason" = REBOOT ]; then 67 # Restart ntpd. We need to restart it to make sure that it 68 # will actually do something: if ntpd cannot resolve the 69 # server hostnames in its config file, then it will never do 70 # anything ever again ("couldn't resolve ..., giving up on 71 # it"), so we silently lose time synchronisation. This also 72 # applies to openntpd. 73 ${config.systemd.package}/bin/systemctl try-restart ntpd.service 74 ${config.systemd.package}/bin/systemctl try-restart openntpd.service 75 76 ${config.systemd.package}/bin/systemctl start ip-up.target 77 fi 78 79 #if [ "$reason" = EXPIRE -o "$reason" = RELEASE -o "$reason" = NOCARRIER ] ; then 80 # ${config.systemd.package}/bin/systemctl start ip-down.target 81 #fi 82 83 ${cfg.runHook} 84 ''; 85 86in 87 88{ 89 90 ###### interface 91 92 options = { 93 94 networking.dhcpcd.persistent = mkOption { 95 type = types.bool; 96 default = false; 97 description = '' 98 Whenever to leave interfaces configured on dhcpcd daemon 99 shutdown. Set to true if you have your root or store mounted 100 over the network or this machine accepts SSH connections 101 through DHCP interfaces and clients should be notified when 102 it shuts down. 103 ''; 104 }; 105 106 networking.dhcpcd.denyInterfaces = mkOption { 107 type = types.listOf types.str; 108 default = []; 109 description = '' 110 Disable the DHCP client for any interface whose name matches 111 any of the shell glob patterns in this list. The purpose of 112 this option is to blacklist virtual interfaces such as those 113 created by Xen, libvirt, LXC, etc. 114 ''; 115 }; 116 117 networking.dhcpcd.allowInterfaces = mkOption { 118 type = types.nullOr (types.listOf types.str); 119 default = null; 120 description = '' 121 Enable the DHCP client for any interface whose name matches 122 any of the shell glob patterns in this list. Any interface not 123 explicitly matched by this pattern will be denied. This pattern only 124 applies when non-null. 125 ''; 126 }; 127 128 networking.dhcpcd.extraConfig = mkOption { 129 type = types.lines; 130 default = ""; 131 description = '' 132 Literal string to append to the config file generated for dhcpcd. 133 ''; 134 }; 135 136 networking.dhcpcd.runHook = mkOption { 137 type = types.lines; 138 default = ""; 139 example = "if [[ $reason =~ BOUND ]]; then echo $interface: Routers are $new_routers - were $old_routers; fi"; 140 description = '' 141 Shell code that will be run after all other hooks. See 142 `man dhcpcd-run-hooks` for details on what is possible. 143 ''; 144 }; 145 146 }; 147 148 149 ###### implementation 150 151 config = mkIf enableDHCP { 152 153 systemd.services.dhcpcd = 154 { description = "DHCP Client"; 155 156 wantedBy = [ "network.target" ]; 157 # Work-around to deal with problems where the kernel would remove & 158 # re-create Wifi interfaces early during boot. 159 after = [ "network-interfaces.target" ]; 160 161 # Stopping dhcpcd during a reconfiguration is undesirable 162 # because it brings down the network interfaces configured by 163 # dhcpcd. So do a "systemctl restart" instead. 164 stopIfChanged = false; 165 166 path = [ dhcpcd pkgs.nettools pkgs.openresolv ]; 167 168 unitConfig.ConditionCapability = "CAP_NET_ADMIN"; 169 170 serviceConfig = 171 { Type = "forking"; 172 PIDFile = "/run/dhcpcd.pid"; 173 ExecStart = "@${dhcpcd}/sbin/dhcpcd dhcpcd --quiet ${optionalString cfg.persistent "--persistent"} --config ${dhcpcdConf}"; 174 ExecReload = "${dhcpcd}/sbin/dhcpcd --rebind"; 175 Restart = "always"; 176 }; 177 }; 178 179 environment.systemPackages = [ dhcpcd ]; 180 181 environment.etc = 182 [ { source = exitHook; 183 target = "dhcpcd.exit-hook"; 184 } 185 ]; 186 187 powerManagement.resumeCommands = mkIf config.systemd.services.dhcpcd.enable 188 '' 189 # Tell dhcpcd to rebind its interfaces if it's running. 190 ${config.systemd.package}/bin/systemctl reload dhcpcd.service 191 ''; 192 193 }; 194 195}