diff options
Diffstat (limited to 'nixpkgs/nixos/modules/services/networking/ndppd.nix')
-rw-r--r-- | nixpkgs/nixos/modules/services/networking/ndppd.nix | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/networking/ndppd.nix b/nixpkgs/nixos/modules/services/networking/ndppd.nix new file mode 100644 index 000000000000..ba17f1ba825a --- /dev/null +++ b/nixpkgs/nixos/modules/services/networking/ndppd.nix @@ -0,0 +1,167 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.ndppd; + + render = s: f: concatStringsSep "\n" (mapAttrsToList f s); + prefer = a: b: if a != null then a else b; + + ndppdConf = prefer cfg.configFile (pkgs.writeText "ndppd.conf" '' + route-ttl ${toString cfg.routeTTL} + ${render cfg.proxies (proxyInterfaceName: proxy: '' + proxy ${prefer proxy.interface proxyInterfaceName} { + router ${boolToString proxy.router} + timeout ${toString proxy.timeout} + ttl ${toString proxy.ttl} + ${render proxy.rules (ruleNetworkName: rule: '' + rule ${prefer rule.network ruleNetworkName} { + ${rule.method}${if rule.method == "iface" then " ${rule.interface}" else ""} + }'')} + }'')} + ''); + + proxy = types.submodule { + options = { + interface = mkOption { + type = types.nullOr types.str; + description = '' + Listen for any Neighbor Solicitation messages on this interface, + and respond to them according to a set of rules. + Defaults to the name of the attrset. + ''; + default = null; + }; + router = mkOption { + type = types.bool; + description = '' + Turns on or off the router flag for Neighbor Advertisement Messages. + ''; + default = true; + }; + timeout = mkOption { + type = types.int; + description = '' + Controls how long to wait for a Neighbor Advertisment Message before + invalidating the entry, in milliseconds. + ''; + default = 500; + }; + ttl = mkOption { + type = types.int; + description = '' + Controls how long a valid or invalid entry remains in the cache, in + milliseconds. + ''; + default = 30000; + }; + rules = mkOption { + type = types.attrsOf rule; + description = '' + This is a rule that the target address is to match against. If no netmask + is provided, /128 is assumed. You may have several rule sections, and the + addresses may or may not overlap. + ''; + default = {}; + }; + }; + }; + + rule = types.submodule { + options = { + network = mkOption { + type = types.nullOr types.str; + description = '' + This is the target address is to match against. If no netmask + is provided, /128 is assumed. The addresses of serveral rules + may or may not overlap. + Defaults to the name of the attrset. + ''; + default = null; + }; + method = mkOption { + type = types.enum [ "static" "iface" "auto" ]; + description = '' + static: Immediately answer any Neighbor Solicitation Messages + (if they match the IP rule). + iface: Forward the Neighbor Solicitation Message through the specified + interface and only respond if a matching Neighbor Advertisement + Message is received. + auto: Same as iface, but instead of manually specifying the outgoing + interface, check for a matching route in /proc/net/ipv6_route. + ''; + default = "auto"; + }; + interface = mkOption { + type = types.nullOr types.str; + description = "Interface to use when method is iface."; + default = null; + }; + }; + }; + +in { + options.services.ndppd = { + enable = mkEnableOption "daemon that proxies NDP (Neighbor Discovery Protocol) messages between interfaces"; + interface = mkOption { + type = types.nullOr types.str; + description = '' + Interface which is on link-level with router. + (Legacy option, use services.ndppd.proxies.<interface>.rules.<network> instead) + ''; + default = null; + example = "eth0"; + }; + network = mkOption { + type = types.nullOr types.str; + description = '' + Network that we proxy. + (Legacy option, use services.ndppd.proxies.<interface>.rules.<network> instead) + ''; + default = null; + example = "1111::/64"; + }; + configFile = mkOption { + type = types.nullOr types.path; + description = "Path to configuration file."; + default = null; + }; + routeTTL = mkOption { + type = types.int; + description = '' + This tells 'ndppd' how often to reload the route file /proc/net/ipv6_route, + in milliseconds. + ''; + default = 30000; + }; + proxies = mkOption { + type = types.attrsOf proxy; + description = '' + This sets up a listener, that will listen for any Neighbor Solicitation + messages, and respond to them according to a set of rules. + ''; + default = {}; + example = { "eth0".rules."1111::/64" = {}; }; + }; + }; + + config = mkIf cfg.enable { + warnings = mkIf (cfg.interface != null && cfg.network != null) [ '' + The options services.ndppd.interface and services.ndppd.network will probably be removed soon, + please use services.ndppd.proxies.<interface>.rules.<network> instead. + '' ]; + + services.ndppd.proxies = mkIf (cfg.interface != null && cfg.network != null) { + "${cfg.interface}".rules."${cfg.network}" = {}; + }; + + systemd.services.ndppd = { + description = "NDP Proxy Daemon"; + documentation = [ "man:ndppd(1)" "man:ndppd.conf(5)" ]; + after = [ "network-pre.target" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig.ExecStart = "${pkgs.ndppd}/bin/ndppd -c ${ndppdConf}"; + }; + }; +} |