218 lines
4.4 KiB
Nix
218 lines
4.4 KiB
Nix
{ lib, config, ... }:
|
|
let
|
|
types = {
|
|
portList = lib.types.listOf lib.types.int;
|
|
|
|
service = lib.types.submodule {
|
|
options = {
|
|
tcp = lib.mkOption {
|
|
type = types.portList;
|
|
default = [ ];
|
|
};
|
|
udp = lib.mkOption {
|
|
type = types.portList;
|
|
default = [ ];
|
|
};
|
|
};
|
|
};
|
|
|
|
vlan = lib.types.submodule {
|
|
options = {
|
|
id = lib.mkOption {
|
|
type = lib.types.int;
|
|
};
|
|
staticLeases = lib.mkOption {
|
|
type = lib.types.attrsOf lib.types.str;
|
|
default = { };
|
|
};
|
|
ipv6 = lib.mkEnableOption "ipv6";
|
|
domain = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "home.arpa";
|
|
description = "Domain name to advertise via DHCP";
|
|
};
|
|
};
|
|
};
|
|
|
|
bridge = lib.types.submodule {
|
|
options = {
|
|
enable = lib.mkEnableOption "Enable bridge";
|
|
|
|
pvid = lib.mkOption {
|
|
type = lib.types.int;
|
|
};
|
|
bindNetwork = lib.mkOption {
|
|
type = lib.types.str;
|
|
};
|
|
network = lib.mkOption {
|
|
type = lib.types.str;
|
|
};
|
|
netdev = lib.mkOption {
|
|
type = lib.types.str;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
cfg = config.modules.vlans;
|
|
vlans = lib.mapAttrsToList (
|
|
attrName:
|
|
{
|
|
name ? attrName,
|
|
...
|
|
}@vlan:
|
|
({ inherit name; } // vlan)
|
|
) cfg.networks;
|
|
vlanAttrs = lib.listToAttrs (
|
|
lib.map (
|
|
{ name, ... }@value:
|
|
{
|
|
inherit name value;
|
|
}
|
|
) vlans
|
|
);
|
|
|
|
buildNetdev =
|
|
name:
|
|
{ id, ... }:
|
|
{
|
|
name = "20-${name}";
|
|
value = {
|
|
netdevConfig = {
|
|
Name = name;
|
|
Kind = "vlan";
|
|
MACAddress = "00:0d:b9:49:d2:${toString id}";
|
|
};
|
|
vlanConfig = {
|
|
Id = id;
|
|
};
|
|
};
|
|
};
|
|
|
|
buildStaticLease = macAddress: address: ''
|
|
[DHCPServerStaticLease]
|
|
MACAddress=${macAddress}
|
|
Address=${address}
|
|
'';
|
|
|
|
buildNetwork =
|
|
name:
|
|
{
|
|
id,
|
|
ipv6,
|
|
staticLeases,
|
|
domain,
|
|
...
|
|
}:
|
|
{
|
|
name = "30-${name}";
|
|
value = {
|
|
matchConfig = {
|
|
Name = name;
|
|
};
|
|
networkConfig = {
|
|
Address = "10.${toString id}.0.1/23";
|
|
IPMasquerade = "ipv4";
|
|
DHCPServer = true;
|
|
IPv6AcceptRA = false;
|
|
IPv6SendRA = ipv6;
|
|
DHCPPrefixDelegation = ipv6;
|
|
};
|
|
dhcpServerConfig = {
|
|
PoolOffset = 255;
|
|
DNS = "10.${toString id}.0.1";
|
|
EmitDNS = true;
|
|
};
|
|
extraConfig = lib.concatLines (
|
|
(lib.mapAttrsToList buildStaticLease staticLeases)
|
|
++ [
|
|
''
|
|
[DHCPServer]
|
|
SendOption=15:string:${domain}
|
|
''
|
|
]
|
|
);
|
|
};
|
|
};
|
|
|
|
vlanIds = lib.mapAttrsToList (_: { id, ... }: id) vlanAttrs;
|
|
|
|
vlanRange = {
|
|
min = lib.foldr lib.min 999 vlanIds;
|
|
max = lib.foldr lib.max 0 vlanIds;
|
|
};
|
|
|
|
bridgeVLANConfig = ''
|
|
[BridgeVLAN]
|
|
VLAN=${toString vlanRange.min}-${toString vlanRange.max}
|
|
EgressUntagged=${toString cfg.bridge.pvid}
|
|
PVID=${toString cfg.bridge.pvid}
|
|
'';
|
|
|
|
bridgeNetDev =
|
|
if (cfg.bridge.enable) then
|
|
{
|
|
"${cfg.bridge.netdev}".bridgeConfig = {
|
|
VLANFiltering = true;
|
|
DefaultPVID = cfg.bridge.pvid;
|
|
};
|
|
}
|
|
else
|
|
{ };
|
|
|
|
bridgeBindNetwork =
|
|
if (cfg.bridge.enable) then
|
|
{
|
|
${cfg.bridge.bindNetwork}.extraConfig = bridgeVLANConfig;
|
|
}
|
|
else
|
|
{ };
|
|
|
|
bridgeNetwork =
|
|
if (cfg.bridge.enable) then
|
|
{
|
|
"${cfg.bridge.network}" = {
|
|
vlan = lib.map ({ name, ... }: name) vlans;
|
|
bridgeVLANs = lib.map (
|
|
{ id, ... }:
|
|
{
|
|
VLAN = id;
|
|
}
|
|
) vlans;
|
|
};
|
|
}
|
|
else
|
|
{ };
|
|
|
|
netdevs = lib.mergeAttrsList [
|
|
(lib.mapAttrs' buildNetdev vlanAttrs)
|
|
bridgeNetDev
|
|
];
|
|
|
|
networks = lib.mergeAttrsList [
|
|
(lib.mapAttrs' buildNetwork vlanAttrs)
|
|
bridgeBindNetwork
|
|
bridgeNetwork
|
|
];
|
|
in
|
|
{
|
|
options.modules.vlans = {
|
|
enable = lib.mkEnableOption "Enable VLANs";
|
|
|
|
networks = lib.mkOption {
|
|
type = lib.types.attrsOf types.vlan;
|
|
};
|
|
|
|
bridge = lib.mkOption {
|
|
type = types.bridge;
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
systemd.network = {
|
|
enable = lib.mkDefault true;
|
|
inherit netdevs networks;
|
|
};
|
|
};
|
|
}
|