7 'require tools.widgets as widgets';
9 function validateEmpty(section
, value
) {
14 return _('Expecting: non-empty value');
22 m
= new form
.Map('xinetd', _('Xinetd Settings'), _('Here you can configure Xinetd services'));
24 s
= m
.section(form
.GridSection
, 'service');
25 s
.modaltitle
= _('Service definitions to be used by Xinetd');
28 s
.addbtntitle
= _('Add new service entry');
30 // The following dummy values are used to show the table overview without the hint texts
31 o
= s
.option(form
.DummyValue
, 'port', _('Port'));
34 o
= s
.option(form
.DummyValue
, 'socket_type', _('Socket type'));
37 o
= s
.option(form
.DummyValue
, 'protocol', _('Protocol'));
40 o
= s
.option(form
.DummyValue
, 'server', _('Server'));
43 o
= s
.option(form
.DummyValue
, 'disable', _('Enabled'));
44 o
.cfgvalue = function(section
) {
45 return (uci
.get('xinetd', section
, 'disable') == "no") ? _("yes") : _("no");
49 s
.tab('basic', _('Basic Settings'));
50 s
.tab('advanced', _('Advanced Settings'));
52 // Now here follow the "real" values to be set in the modal (with the hint texts)
55 o
= s
.taboption('basic', form
.Flag
, 'disable', _('Enabled'), _('Enable or Disable this service'));
58 o
.default = o
.enabled
;
62 o
= s
.taboption('basic', form
.ListValue
, 'type', _('Type'), _('Type of service'));
63 o
.default = 'UNLISTED';
64 // FIXME for now we will only support unlisted services, maybe later we could use the (very long) list from /etc/services if needed
65 // o.value('INTERNAL', _('INTERNAL'));
66 o
.value('UNLISTED', _('UNLISTED'));
70 o
= s
.taboption('basic', form
.Value
, 'port', _('Port'), _('The port used for this service, valid range: 0 - 65535'));
72 o
.depends('type', 'UNLISTED');
75 o
.validate = function(section_id
, value
) {
76 var sections
= uci
.sections('xinetd', 'service');
78 for (var i
= 0; i
< sections
.length
; i
++) {
79 if (uci
.get('xinetd', sections
[i
]['.name'], 'port') == value
&& section_id
!= sections
[i
]['.name'])
80 return _('Port already in use by service "%s"'.format(sections
[i
]['.name']));
86 o
= s
.taboption('basic', form
.ListValue
, 'wait', _('Threading behaviour'), _('Selection of the threading for this service'));
88 o
.value('yes', _('Single-Threaded Service'));
89 o
.value('no', _('Multi-Threaded Service'));
93 o
= s
.taboption('basic', form
.ListValue
, 'socket_type', _('Socket type'), _('The type of the socket used for this service'));
95 o
.value('stream', _('stream-based service'));
96 o
.value('dgram', _('datagram-based service'));
97 o
.value('raw', _('direct access to IP service'));
98 o
.value('seqpacket', _('sequential datagram transmission service'));
102 o
= s
.taboption('basic', form
.ListValue
, 'protocol', _('Protocol'), _('The protocol to be used for this service'));
104 o
.value('tcp', _('TCP'));
105 o
.value('udp', _('UDP'));
109 o
= s
.taboption('basic', widgets
.UserSelect
, 'user', _('User (UID)'), _('User ID for the server process for this service'));
113 o
= s
.taboption('basic', form
.Value
, 'server', _('Server'), _('Complete path to the executable server file'));
114 o
.datatype
= 'string';
117 o
.validate
= validateEmpty
;
118 o
.write = function(section
, value
) {
119 return fs
.stat(value
).then(function(res
) {
120 if (res
.type
== "file") {
121 uci
.set('xinetd', section
, 'server', value
);
124 ui
.addNotification(null, E('p', _('Service "%s": Invalid server file "%s"').format(section
, value
)), 'danger');
126 }).catch(function(err
) {
127 ui
.addNotification(null, E('p', _('Service "%s": No access to server file "%s" (%s)').format(section
, value
, err
.message
)), 'danger');
132 o
= s
.taboption('basic', form
.Value
, 'server_args', _('Server arguments'), _('Additional arguments passed to the server. There is no validation of this input.'));
133 o
.datatype
= 'string';
137 o
= s
.taboption('advanced', form
.DynamicList
, 'only_from', _('Allowed hosts'), _('List of allowed hosts to access this service'));
142 o
= s
.taboption('advanced', form
.DynamicList
, 'no_access', _('Forbidden hosts'), _('List of forbidden hosts to access this service'));
147 o
= s
.taboption('advanced', form
.DynamicList
, 'access_times', _('Access times'), _('Time intervals within service is available (Format hh:mm-hh:mm)'));
148 o
.datatype
= 'string';
150 o
.validate = function(section_id
, value
) {
151 if (value
.length
== 0 || /^([01]\d|2[0-3]):[0-5]\d-([01]\d|2[0-3]):[0-5]\d$/.test(value
) == true)
154 return _('Expected \'hh:mm-hh:mm\'');
158 o
= s
.taboption('advanced', form
.Value
, 'cps', _('Connection limit'), _('Takes two arguments: [Number of connections per second] [Number of seconds to reenable service]'));
159 o
.datatype
= 'string';
160 o
.placeholder
= '50 10';
162 o
.validate = function(section_id
, value
) {
163 if (value
.length
== 0 || /^([0-9]+\s+[0-9]+$)/.test(value
) == true)
166 return _('Expected \'[Number] [Number]\'');
170 o
= s
.taboption('advanced', form
.Value
, 'instances', _('Number of instances'), _('Number of simultaneously running servers for this service. Argument is any number or the keyword \'UNLIMITED\''));
171 o
.datatype
= 'or("UNLIMITED", uinteger)';
172 o
.value('UNLIMITED', 'UNLIMITED');
175 o
= s
.taboption('advanced', form
.MultiValue
, 'log_on_success', _('Log on success'), _('Informations that should be logged for this service in case of successful connection'));
176 o
.value('PID', _('Server PID'));
177 o
.value('HOST', _('Remote host address '));
178 o
.value('USERID', _('User ID of the remote user'));
179 o
.value('EXIT', _('Server exited along with the exit status'));
180 o
.value('DURATION', _('Duration of a service session'));
181 o
.value('TRAFFIC', _('Total bytes in and out for a redirected service'));
184 o
= s
.taboption('advanced', form
.MultiValue
, 'log_on_failure', _('Log on failure'), _('Informations that should be logged for this service in case of a failed connection'));
185 o
.value('HOST', _('Remote host address '));
186 o
.value('USERID', _('User ID of the remote user'));
187 o
.value('ATTEMPT', _('Failed attempts'));