1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 cfg = config.services.xinetd;
8
9 inherit (pkgs) xinetd;
10
11 configFile = pkgs.writeText "xinetd.conf"
12 ''
13 defaults
14 {
15 log_type = SYSLOG daemon info
16 log_on_failure = HOST
17 log_on_success = PID HOST DURATION EXIT
18 ${cfg.extraDefaults}
19 }
20
21 ${concatMapStrings makeService cfg.services}
22 '';
23
24 makeService = srv:
25 ''
26 service ${srv.name}
27 {
28 protocol = ${srv.protocol}
29 ${optionalString srv.unlisted "type = UNLISTED"}
30 ${optionalString (srv.flags != "") "flags = ${srv.flags}"}
31 socket_type = ${if srv.protocol == "udp" then "dgram" else "stream"}
32 ${if srv.port != 0 then "port = ${toString srv.port}" else ""}
33 wait = ${if srv.protocol == "udp" then "yes" else "no"}
34 user = ${srv.user}
35 server = ${srv.server}
36 ${optionalString (srv.serverArgs != "") "server_args = ${srv.serverArgs}"}
37 ${srv.extraConfig}
38 }
39 '';
40
41in
42
43{
44
45 ###### interface
46
47 options = {
48
49 services.xinetd.enable = mkOption {
50 default = false;
51 description = ''
52 Whether to enable the xinetd super-server daemon.
53 '';
54 };
55
56 services.xinetd.extraDefaults = mkOption {
57 default = "";
58 type = types.string;
59 description = ''
60 Additional configuration lines added to the default section of xinetd's configuration.
61 '';
62 };
63
64 services.xinetd.services = mkOption {
65 default = [];
66 description = ''
67 A list of services provided by xinetd.
68 '';
69
70 type = types.listOf types.optionSet;
71
72 options = {
73
74 name = mkOption {
75 type = types.string;
76 example = "login";
77 description = "Name of the service.";
78 };
79
80 protocol = mkOption {
81 type = types.string;
82 default = "tcp";
83 description =
84 "Protocol of the service. Usually <literal>tcp</literal> or <literal>udp</literal>.";
85 };
86
87 port = mkOption {
88 type = types.int;
89 default = 0;
90 example = 123;
91 description = "Port number of the service.";
92 };
93
94 user = mkOption {
95 type = types.string;
96 default = "nobody";
97 description = "User account for the service";
98 };
99
100 server = mkOption {
101 type = types.string;
102 example = "/foo/bin/ftpd";
103 description = "Path of the program that implements the service.";
104 };
105
106 serverArgs = mkOption {
107 type = types.string;
108 default = "";
109 description = "Command-line arguments for the server program.";
110 };
111
112 flags = mkOption {
113 type = types.string;
114 default = "";
115 description = "";
116 };
117
118 unlisted = mkOption {
119 type = types.bool;
120 default = false;
121 description = ''
122 Whether this server is listed in
123 <filename>/etc/services</filename>. If so, the port
124 number can be omitted.
125 '';
126 };
127
128 extraConfig = mkOption {
129 type = types.string;
130 default = "";
131 description = "Extra configuration-lines added to the section of the service.";
132 };
133
134 };
135
136 };
137
138 };
139
140
141 ###### implementation
142
143 config = mkIf cfg.enable {
144
145 jobs.xinetd =
146 { description = "xinetd server";
147
148 startOn = "started network-interfaces";
149 stopOn = "stopping network-interfaces";
150
151 path = [ xinetd ];
152
153 exec = "xinetd -syslog daemon -dontfork -stayalive -f ${configFile}";
154 };
155
156 };
157
158}