diff --git a/hosts/pre-yate-n0emis/configuration.nix b/hosts/pre-yate-n0emis/configuration.nix index dab932e..8fbbee5 100644 --- a/hosts/pre-yate-n0emis/configuration.nix +++ b/hosts/pre-yate-n0emis/configuration.nix @@ -13,6 +13,11 @@ networking.hostName = "pre-yate-n0emis"; + boot.kernel.sysctl = { + "net.ipv4.conf.all.forwarding" = true; + "net.ipv6.conf.all.forwarding" = true; + }; + networking.useNetworkd = true; systemd.network = { links."10-eth0" = { @@ -25,9 +30,67 @@ }; DHCP = "yes"; }; + + links."20-vlan132" = { + matchConfig.MACAddress = "8e:50:2d:73:27:51"; + linkConfig.Name = "vlan132"; + }; + networks."20-vlan132" = { + matchConfig = { + Name = "vlan132"; + }; + address = [ "10.42.132.1/24" ]; + }; + }; + + services.fieldpoc = { + enable = true; + dhcp = { + enable = true; + interface = "vlan132"; + subnet = "10.42.132.0/24"; + pool = "10.42.132.200 - 10.42.132.250"; + router = "10.42.132.1"; + dnsServers = "1.1.1.1,9.9.9.9"; + omm = "10.42.132.11"; + reservations = [ + { + name = "rfp-01"; + macAddress = "00:30:42:1B:8C:7A"; + ipAddress = "10.42.132.11"; + } + ]; + }; + }; + services.yate.config = { + yate.ygi = { + sndpath = "/opt/sounds"; + sndformats = "slin,gsm,wav"; + }; + accfile.dialout = { + enabled = "yes"; + protocol = "sip"; + username = "iocaste"; + password = "iocaste"; + registrar = "172.16.1.1"; + }; + regexroute = "[default] +\${username}^$=-;error=noauth +^iocaste$=goto dialin +^99991001$=tone/dial +^99991002$=tone/busy +^99991003$=tone/ring +^99991004$=tone/specdial +^99991005$=tone/congestion +^99991006$=tone/outoforder +^99991007$=tone/milliwatt +^99991008$=tone/info +^.*$=line/\\0;line=dialout + +[dialin] +\${sip_x-called}^.*$=lateroute/\\1"; }; - environment.systemPackages = with pkgs; [ python3.pkgs.fieldpoc ]; # This value determines the NixOS release from which the default # settings for stateful data, like file locations and database versions diff --git a/modules/default.nix b/modules/default.nix index a1e96dd..2096759 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -3,5 +3,6 @@ { imports = [ ./yate + ./fieldpoc ]; } diff --git a/modules/fieldpoc/default.nix b/modules/fieldpoc/default.nix new file mode 100644 index 0000000..135a1d9 --- /dev/null +++ b/modules/fieldpoc/default.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let cfg = config.services.fieldpoc; +in { + imports = [ + ./dhcp.nix + ]; + + options = { + services.fieldpoc = { + enable = mkEnableOption "fieldpoc"; + # TODO: config + #config = mkOption { + # type = with types; attrsOf anything; + # default = { }; + #}; + }; + }; + + config = mkIf cfg.enable { + services.postgresql = { + enable = true; + initialScript = pkgs.writeText "backend-initScript" '' + CREATE ROLE nixcloud WITH LOGIN PASSWORD 'nixcloud' CREATEDB; + CREATE DATABASE nixcloud; + GRANT ALL PRIVILEGES ON DATABASE nixcloud TO nixcloud; + ''; + }; + + services.yate = { + enable = true; + config = { + extmodule."listener ywsd" = { + type = "tcp"; + addr = "127.0.0.1"; + port = "5039"; + }; + cdrbuild.parameters.X-Eventphone-Id = "false"; + pgsqldb.default = { + host = "localhost"; + port = "5432"; + database = "fieldpoc"; + user = "fieldpoc"; + password = "fieldpoc"; + }; + register = { + general = { + expires = 30; + "user.auth" = "yes"; + "user.register" = "yes"; + "user.unregister" = "yes"; + "engine.timer" = "yes"; + "call.cdr" = "yes"; + "linetracker" = "yes"; + }; + default = { + priority = 30; + account = "default"; + }; + "user.auth" = { + query = "SELECT password FROM users WHERE username='\${username}' AND password IS NOT NULL AND password<>'' AND type='user' LIMIT 1;"; + result = "password"; + }; + "user.register".query = "INSERT INTO registrations (username, location, oconnection_id, expires) VALUES ('\${username}', '\${data}', '\${oconnection_id}', NOW() + INTERVAL '\${expires} s') ON CONFLICT ON CONSTRAINT uniq_registrations DO UPDATE SET expires = NOW() + INTERVAL '\${expires} s'"; + "user.unregister".query = "DELETE FROM registrations WHERE (username = '\${username}' AND location = '\${data}' AND oconnection_id = '\${connection_id}') OR ('\${username}' = '' AND '\${data}' = '' AND oconnection_id = '\${connection_id}')"; + "engine.timer".query = "DELETE FROM registrations WHERE expires<=CURRENT_TIMESTAMP;"; + "call.cdr".critial = "no"; + "linetracker" = { + critical = "yes"; + initquery = "UPDATE users SET inuse=0 WHERE inuse is not NULL;DELETE from active_calls;"; + cdr_initialize = "UPDATE users SET inuse=inuse+1 WHERE username='\${external}';INSERT INTO active_calls SELECT username, x_eventphone_id FROM (SELECT '\${external}' as username, '\${X-Eventphone-Id}' as x_eventphone_id, '\${direction}' as direction) as active_call WHERE x_eventphone_id != '' AND x_eventphone_id IS NOT NULL and direction = 'outgoing';"; + cdr_finalize = "UPDATE users SET inuse=(CASE WHEN inuse>0 THEN inuse-1 ELSE 0 END) WHERE username='\${external}';DELETE FROM active_calls WHERE username = '\${external}' AND x_eventphone_id = '\${X-Eventphone-Id}' AND '\${direction}' = 'outgoing';"; + }; + }; + }; + }; + }; +} diff --git a/modules/fieldpoc/dhcp.nix b/modules/fieldpoc/dhcp.nix new file mode 100644 index 0000000..602457b --- /dev/null +++ b/modules/fieldpoc/dhcp.nix @@ -0,0 +1,139 @@ +{ config, pkgs, lib, ... }: + +with lib; + +let cfg = config.services.fieldpoc.dhcp; +in { + options.services.fieldpoc.dhcp = { + enable = mkEnableOption "fieldpoc-dhcp"; + interface = mkOption { + type = types.str; + }; + subnet = mkOption { + type = types.str; + }; + pool = mkOption { + type = types.str; + }; + router = mkOption { + type = types.str; + }; + dnsServers = mkOption { + type = types.str; + }; + omm = mkOption { + type = types.str; + }; + reservations = mkOption { + type = with types; listOf (submodule { + options = { + name = mkOption { + type = types.str; + }; + macAddress = mkOption { + type = types.str; + }; + ipAddress = mkOption { + type = types.str; + }; + }; + }); + default = []; + }; + }; + + config = mkIf cfg.enable { + services.kea.dhcp4 = { + enable = true; + settings = { + interfaces-config = { + interfaces = [ cfg.interface ]; + }; + option-def = [ + { + space = "dhcp4"; + name = "vendor-encapsulated-options"; + code = 43; + type = "empty"; + encapsulate = "sipdect"; + } + { + space = "sipdect"; + name = "ommip1"; + code = 10; + type = "ipv4-address"; + } + { + space = "sipdect"; + name = "ommip2"; + code = 19; + type = "ipv4-address"; + } + { + space = "sipdect"; + name = "syslogip"; + code = 14; + type = "ipv4-address"; + } + { + space = "sipdect"; + name = "syslogport"; + code = 15; + type = "int16"; + } + { + space = "dhcp4"; + name = "magic_str"; + code = 224; + type = "string"; + } + ]; + + subnet4 = [ + { + subnet = cfg.subnet; + pools = [ + { + pool = cfg.pool; + } + ]; + option-data = [ + { + name = "routers"; + data = cfg.router; + } + { + name = "domain-name-servers"; + data = cfg.dnsServers; + } + { + name = "vendor-encapsulated-options"; + } + { + space = "sipdect"; + name = "ommip1"; + data = cfg.omm; + } + { + name = "magic_str"; + data = "OpenMobilitySIP-DECT"; + } + ]; + + reservations = map (r: { + hostname = r.name; + hw-address = r.macAddress; + ip-address = r.ipAddress; + option-data = [ + { + name = "host-name"; + data = r.name; + } + ]; + }) cfg.reservations; + } + ]; + }; + }; + }; +} diff --git a/packages/python/fieldpoc/default.nix b/packages/python/fieldpoc/default.nix index 16e626f..5c82944 100644 --- a/packages/python/fieldpoc/default.nix +++ b/packages/python/fieldpoc/default.nix @@ -5,9 +5,9 @@ buildPythonApplication rec { version = "0.11.0"; src = fetchGit { - url = "https://git.clerie.de/clerie/fieldpoc.git"; + url = "https://git.n0emis.eu/n0emis/fieldpoc.git"; ref = "main"; - rev = "c2ef36c5a7a31ea39f51c91c7ba76430f0aaa048"; + rev = "d6d664b4690189a7ed54be65ceef8cb3d79a6bfb"; }; format = "pyproject";