anchor.diff:      fi
     '';
   
  -in
  -
  -{
  -
  -  ###### interface
  -
  -  options = {
  -
  -    networking.firewall.enable = mkOption {
  -      type = types.bool;
  -      default = true;
  -      description =
  -        ''
  -          Whether to enable the firewall.  This is a simple stateful
  -          firewall that blocks connection attempts to unauthorised TCP
  -          or UDP ports on this machine.  It does not affect packet
  -          forwarding.
  -        '';
  -    };
  -
  -    networking.firewall.logRefusedConnections = mkOption {
  -      type = types.bool;
  -      default = true;
  -      description =
  -        ''
  -          Whether to log rejected or dropped incoming connections.
  -        '';
  -    };
  -
  -    networking.firewall.logRefusedPackets = mkOption {
  -      type = types.bool;
  -      default = false;
  -      description =
  -        ''
  -          Whether to log all rejected or dropped incoming packets.
  -          This tends to give a lot of log messages, so it's mostly
  -          useful for debugging.
  -        '';
  -    };
  -
  -    networking.firewall.logRefusedUnicastsOnly = mkOption {
  -      type = types.bool;
  -      default = true;
  -      description =
  -        ''
  -          If <option>networking.firewall.logRefusedPackets</option>
  -          and this option are enabled, then only log packets
  -          specifically directed at this machine, i.e., not broadcasts
  -          or multicasts.
  -        '';
  -    };
  -
  -    networking.firewall.rejectPackets = mkOption {
  -      type = types.bool;
  -      default = false;
  -      description =
  -        ''
  -          If set, refused packets are rejected rather than dropped
  -          (ignored).  This means that an ICMP "port unreachable" error
  -          message is sent back to the client (or a TCP RST packet in
  -          case of an existing connection).  Rejecting packets makes
  -          port scanning somewhat easier.
  -        '';
  -    };
  -
  -    networking.firewall.trustedInterfaces = mkOption {
  -      type = types.listOf types.str;
  -      default = [ ];
  -      example = [ "enp0s2" ];
  -      description =
  -        ''
  -          Traffic coming in from these interfaces will be accepted
  -          unconditionally.  Traffic from the loopback (lo) interface
  -          will always be accepted.
  -        '';
  -    };
  -
  -    networking.firewall.allowedTCPPorts = mkOption {
  +  commonOptions = {
  +    allowedTCPPorts = mkOption {
         type = types.listOf types.int;
         default = [ ];
         example = [ 22 80 ];
         description =
  -        ''
  +        '' 
             List of TCP ports on which incoming connections are
             accepted.
           '';
       };
   
  -    networking.firewall.allowedTCPPortRanges = mkOption {
  +    allowedTCPPortRanges = mkOption {
         type = types.listOf (types.attrsOf types.int);
         default = [ ];
         example = [ { from = 8999; to = 9003; } ];
         description =
  -        ''
  +        '' 
             A range of TCP ports on which incoming connections are
             accepted.
           '';
       };
   
  -    networking.firewall.allowedUDPPorts = mkOption {
  +    allowedUDPPorts = mkOption {
         type = types.listOf types.int;
         default = [ ];
         example = [ 53 ];
  
positive.code:     ip46tables -A nixos-fw -m conntrack --ctstate ESTABLISHED,RELATED -j nixos-fw-accept
  
      # Accept connections to the allowed TCP ports.
      ${concatMapStrings (port:
          ''
            ip46tables -A nixos-fw -p tcp --dport ${toString port} -j nixos-fw-accept
          ''
        ) cfg.allowedTCPPorts
      }
  
      # Accept connections to the allowed TCP port ranges.
      ${concatMapStrings (rangeAttr:
          let range = toString rangeAttr.from + ":" + toString rangeAttr.to; in
          ''
            ip46tables -A nixos-fw -p tcp --dport ${range} -j nixos-fw-accept
          ''
        ) cfg.allowedTCPPortRanges
      }
  
      # Accept packets on the allowed UDP ports.
      ${concatMapStrings (port:
          ''
            ip46tables -A nixos-fw -p udp --dport ${toString port} -j nixos-fw-accept
          ''
        ) cfg.allowedUDPPorts
      }
  
      # Accept packets on the allowed UDP port ranges.
      ${concatMapStrings (rangeAttr:
          let range = toString rangeAttr.from + ":" + toString rangeAttr.to; in
          ''
            ip46tables -A nixos-fw -p udp --dport ${range} -j nixos-fw-accept
          ''
        ) cfg.allowedUDPPortRanges
      }
  
      # Accept IPv4 multicast.  Not a big security risk since
      # probably nobody is listening anyway.
  
negative.code:           Range of open UDP ports.
          '';
      };
    };
  
  in
  
  {
  
    ###### interface
  
    options = {
  
      networking.firewall = {
        enable = mkOption {
          type = types.bool;
          default = true;
          description =
            ''
              Whether to enable the firewall.  This is a simple stateful
              firewall that blocks connection attempts to unauthorised TCP
              or UDP ports on this machine.  It does not affect packet
              forwarding.
            '';
        };
  
        logRefusedConnections = mkOption {
          type = types.bool;
          default = true;
          description =
            ''
              Whether to log rejected or dropped incoming connections.
            '';
        };
  
        logRefusedPackets = mkOption {
          type = types.bool;
          default = false;
          description =
            ''
              Whether to log all rejected or dropped incoming packets.
              This tends to give a lot of log messages, so it's mostly
              useful for debugging.
            '';
        };
  
        logRefusedUnicastsOnly = mkOption {
          type = types.bool;
          default = true;
          description =
            ''
              If <option>networking.firewall.logRefusedPackets</option>
              and this option are enabled, then only log packets
              specifically directed at this machine, i.e., not broadcasts
              or multicasts.
            '';
        };
  
        rejectPackets = mkOption {
          type = types.bool;
          default = false;
          description =
            ''
              If set, refused packets are rejected rather than dropped
              (ignored).  This means that an ICMP "port unreachable" error
              message is sent back to the client (or a TCP RST packet in
              case of an existing connection).  Rejecting packets makes
              port scanning somewhat easier.
            '';
        };
  
        trustedInterfaces = mkOption {
          type = types.listOf types.str;
          default = [ ];
          example = [ "enp0s2" ];
          description =
            ''
              Traffic coming in from these interfaces will be accepted
              unconditionally.  Traffic from the loopback (lo) interface
              will always be accepted.
            '';
        };
  
        allowPing = mkOption {
          type = types.bool;
          default = true;
          description =
            ''
              Whether to respond to incoming ICMPv4 echo requests
              ("pings").  ICMPv6 pings are always allowed because the
              larger address space of IPv6 makes network scanning much
              less effective.
            '';
        };
  
        pingLimit = mkOption {
          type = types.nullOr (types.separatedString " ");
          default = null;
          example = "--limit 1/minute --limit-burst 5";
          description =
            ''
              If pings are allowed, this allows setting rate limits
              on them.  If non-null, this option should be in the form of
              flags like "--limit 1/minute --limit-burst 5"
            '';
        };
  
        checkReversePath = mkOption {
          type = types.either types.bool (types.enum ["strict" "loose"]);
          default = kernelHasRPFilter;
          example = "loose";
          description =
            ''
              Performs a reverse path filter test on a packet.  If a reply
              to the packet would not be sent via the same interface that
              the packet arrived on, it is refused.
  
              If using asymmetric routing or other complicated routing, set
              this option to loose mode or disable it and setup your own
              counter-measures.
  
              This option can be either true (or "strict"), "loose" (only
              drop the packet if the source address is not reachable via any
              interface) or false.  Defaults to the value of
              kernelHasRPFilter.
  
              (needs kernel 3.3+)
            '';
        };
  
        logReversePathDrops = mkOption {
          type = types.bool;
          default = false;
          description =
            ''
              Logs dropped packets failing the reverse path filter test if
              the option networking.firewall.checkReversePath is enabled.
            '';
        };
  
        connectionTrackingModules = mkOption {
          type = types.listOf types.str;
          default = [ ];
          example = [ "ftp" "irc" "sane" "sip" "tftp" "amanda" "h323" "netbios_sn" "pptp" "snmp" ];
          description =
            ''
              List of connection-tracking helpers that are auto-loaded.
              The complete list of possible values is given in the example.
  
              As helpers can pose as a security risk, it is advised to
              set this to an empty list and disable the setting
              networking.firewall.autoLoadConntrackHelpers unless you
              know what you are doing. Connection tracking is disabled
              by default.
  
              Loading of helpers is recommended to be done through the
              CT target.  More info:
              https://home.regit.org/netfilter-en/secure-use-of-helpers/
            '';
        };
  
        autoLoadConntrackHelpers = mkOption {
          type = types.bool;
          default = false;
          description =
            ''
              Whether to auto-load connection-tracking helpers.
              See the description at networking.firewall.connectionTrackingModules
  
              (needs kernel 3.5+)
            '';
        };
  
        extraCommands = mkOption {
          type = types.lines;
          default = "";
          example = "iptables -A INPUT -p icmp -j ACCEPT";
          description =
            ''
              Additional shell commands executed as part of the firewall
              initialisation script.  These are executed just before the
              final "reject" firewall rule is added, so they can be used
              to allow packets that would otherwise be refused.
            '';
        };
  
        extraPackages = mkOption {
          type = types.listOf types.package;
          default = [ ];
          example = literalExample "[ pkgs.ipset ]";
          description =
            ''
              Additional packages to be included in the environment of the system
              as well as the path of networking.firewall.extraCommands.
            '';
        };
  
        extraStopCommands = mkOption {
          type = types.lines;
          default = "";
          example = "iptables -P INPUT ACCEPT";
          description =
            ''
              Additional shell commands executed as part of the firewall
              shutdown script.  These are executed just after the removal
              of the NixOS input rule, or if the service enters a failed
              state.
            '';
        };
  
        interfaces = mkOption {
          default = {
            default = mapAttrs (name: value: cfg."${name}") commonOptions;
          };
          type = with types; attrsOf (submodule [ { options = commonOptions; } ]);
          description =
            ''
              Interface-specific open ports. Setting this value will override
              all values of the <literal>networking.firewall.allowed*</literal>
              options.
            '';
        };
      } // commonOptions;
  
    };
  
  