2 # Returns a list of services from the services file, each being an array of
3 # line name port protocol aliases index
8 system("$config{'get_services_command'}") if ($config{'get_services_command'});
9 open(SERVICES, $config{services_file});
12 if (/^(\S+)\s+([0-9]+)\/(\S+)\s*(.*)$/) {
13 push(@rv, [ $l, $1, $2, $3, $4, scalar(@rv) ]);
14 if ($config{'ipv6'}) {
15 push(@rv, [ $l, $1, $2, $3.'6', $4, scalar(@rv) ]);
16 # add udp/tcp6only options for s10
17 if (($3 eq "tcp") | ($3 eq "udp")) {
18 push(@rv, [ $l, $1, $2, $3.'6only',
29 # create_service(name, port, proto, aliases)
30 # Add a new service to the list
34 if ($config{'ipv6'} && $p =~ /^(\S+)6.*$/) {
35 # don't add the service if it is already there
36 foreach $s (&list_services()) {
37 return if ($s->[1] eq $_[0] && $s->[2] == $_[1] &&
42 &open_tempfile(SERVICES, ">> $config{services_file}");
43 &print_tempfile(SERVICES, "$_[0]\t$_[1]/$p",$_[3] ? "\t$_[3]\n" : "\n");
44 &close_tempfile(SERVICES);
45 system("$config{'put_services_command'}") if ($config{'put_services_command'});
49 # modify_service(line, name, port, proto, aliases)
50 # Change an existing service
56 open(SERVICES, $config{services_file});
59 $serv[$_[0]] = "$_[1]\t$_[2]/$p".($_[4] ? "\t$_[4]\n" : "\n");
60 &open_tempfile(SERVICES, "> $config{services_file}");
61 &print_tempfile(SERVICES, @serv);
62 &close_tempfile(SERVICES);
63 system("$config{'put_services_command'}") if ($config{'put_services_command'});
66 # delete_service(line)
70 open(SERVICES, $config{services_file});
73 splice(@serv, $_[0], 1);
74 &open_tempfile(SERVICES, "> $config{services_file}");
75 &print_tempfile(SERVICES, @serv);
76 &close_tempfile(SERVICES);
77 system("$config{'put_services_command'}") if ($config{'put_services_command'});
81 # Returns a list of supported protocols on this system
85 open(PROT, $config{protocols_file});
91 if ($config{'ipv6'}) {
92 if ($1 eq 'tcp') { push(@rv, 'tcp6', 'tcp6only'); }
93 elsif ($1 eq 'udp') { push(@rv, 'udp6', 'udp6only'); }
101 # Returns a list of service details handled by inetd. RPC services
102 # will have a name like foo/1 or bar/1-3, where the thing after the / is
103 # the version or versions supported. For each service, the list contains
104 # line active? rpc? name type protocol wait user path|internal args file
107 local ($cmd, @inetadm_output, $l, $fmri, $state, @rv);
108 # for smf, we need to build a list of service instances/states
109 # using inetadm, then gather relevant properties of each instance
110 $cmd = "/usr/sbin/inetadm";
111 @inetadm_output = &backquote_logged($cmd);
112 for ($l = 1; $l < scalar @inetadm_output; $l++) {
113 # retrieve fmri, state from inetadm output
114 $inetadm_output[$l] =~ /(\S+)\s+(\S+)\s+(\S+)/;
116 $state = ($2 eq "online");
117 # get instance props for fmri
118 $cmd = "/usr/sbin/inetadm -l $fmri";
119 $instance_props = &backquote_logged($cmd);
120 $instance_props=~/(isrpc=)(\w+)/;
121 $isrpc = ($2 eq "TRUE");
123 # for rpc svc, we need version range to
126 $instance_props=~/(rpc_low_version=)(\w+)/;
128 $instance_props=~/(rpc_high_version=)(\w+)/;
130 if ($rpc_hi eq $rpc_lo) {
131 $rpc_range = "\/$rpc_lo";
133 $rpc_range = "\/$rpc_lo-$rpc_hi";
139 $instance_props=~/(name=\")([^\"]*)/;
140 $name = "$2$rpc_range";
141 $instance_props=~/(endpoint_type=\")([^\"]*)/;
143 $instance_props=~/(proto=\")([^\"]*)/;
145 $instance_props=~/(wait=)(\w+)/;
146 $wait = ($2 eq "TRUE") ? "wait" : "nowait";
147 $instance_props=~/(user=\")([^\"]*)/;
149 $instance_props=~/(exec=\")([^\"]*)/;
151 # split exec into path to command, and command with args
152 $exec =~/(\S+)[\s]*(.*)/;
155 @cmdfields = split(/\//,$cmdpath);
156 $cmd = "$cmdfields[-1] $args";
157 push(@rv, [ $l, $state , $isrpc, $name, $endpoint_type, $proto,
158 $wait, $user, $exec, $cmd, $fmri]);
163 # create_inet(enabled, name, type, protocol, wait, user, program, args)
164 # Add a new service to the main inetd config file
167 local ($proto, $name, $cmd, $retcode, $inetadm_output, $fmri);
168 # we need an ugly hack to support v6only protocols. inetconv won't
169 # accept v6only so we convert to v6, then inetadm -m proto=v6only.
172 if ($_[3] =~ /.*6only/) {
175 &open_tempfile(INET, ">$config{inetd_conf_file}");
176 &print_tempfile(INET, "$_[1]\t$_[2]\t$proto\t$_[4]\t$_[5]\t$_[6]".
177 ($_[7] ? "\t$_[7]\n" : "\n"));
178 &close_tempfile(INET);
181 $retcode = &execute_smf_cmd("/usr/sbin/inetconv -i $config{inetd_conf_file}");
182 if ($retcode) { return undef; }
183 # we need to determine fmri of just-created svc...
184 $inetadm_output = &backquote_logged("/usr/sbin/inetadm");
185 if ($inetadm_output =~ /(.*)(svc\:\/(.)*\/$name\/$proto:default)(.*)/) {
187 if ($_[3] =~ /.*6only/) {
188 # now change proto to correct v6only value. from inetconv
189 # operation we know fmri will be of form "svcname/proto"
191 &execute_smf_cmd("/usr/sbin/inetadm -m $fmri proto=$_[3]");
192 if ($retcode) { return undef; }
196 $retcode = &execute_smf_cmd("/usr/sbin/inetadm -d $fmri");
203 # modify_inet(line, enabled, name, type, protocol,
204 # wait, user, program, args, fmri)
205 # Modify an existing inetd service
208 local ($fmri, $wait, $protocol, $isrpc, $name, $rpc_lo,
209 $rpc_hi, $rpc_mods, $cmd, $args, @cmdfields, @argfields,
210 $firstarg, $argstr, $start_method, $retcode);
213 $wait = ($_[5] eq "wait") ? "TRUE" : "FALSE";
217 # for smf, cmd name must match first arg
218 @cmdfields = split(/\//, $cmd);
219 @argfields = split(/\s+/, $args);
220 $firstarg = shift(@argfields);
221 if ($firstarg eq $cmdfields[-1]) {
222 $argstr = join(" ", @argfields);
223 $start_method = "$cmd $argstr";
225 &error(&text('error_smf_cmdfield', $cmd, $cmdfields[-1]));
228 if ($name =~ /(^[^\/]*)\/([1-9]*)[\-]*([1-9]*)$/) {
232 if (!$rpc_hi) { $rpc_hi = $rpc_lo; }
234 $protocol =~ s/^(rpc\/)*//;
235 $rpc_mods = "rpc_low_version=$rpc_lo rpc_high_version=$rpc_hi";
239 $retcode = &execute_smf_cmd("/usr/sbin/inetadm -m $fmri name=$name endpoint_type=$_[3] proto=$protocol wait=$wait user=$_[6] exec=$start_method $rpc_mods");
240 if ($retcode) { return undef; }
242 # may need to clear maintenance state
243 &backquote_logged("/usr/sbin/svcadm clear $fmri");
244 $retcode = &execute_smf_cmd("/usr/sbin/inetadm -e $fmri");
246 $retcode = &execute_smf_cmd("/usr/sbin/inetadm -d $fmri");
252 # delete_inet(line, fmri)
253 # Delete an internet service
256 local ($fmri, @fields, $svc, $retcode, $out);
258 # before we delete, check if this is only instance for service.
259 # if so we svccfg delete the whole service, otherwise just the
260 # instance. this is to avoid leaving unwanted detritus lying
261 # around in the smf repository...
262 @fields = split(/:/,$fmri);
263 $svc = "svc:/$fields[1]";
264 $out = &backquote_logged("/usr/sbin/inetadm | /usr/bin/grep $svc | wc -l");
265 if ($?) { return undef; }
266 if ($out =~ /\s*1\s*/) {
267 # XXX need to remove manifest too?
268 &webmin_log("running svccfg delete on $svc");
271 $retcode = &execute_smf_cmd("/usr/sbin/svccfg delete -f $fmri");
277 local ($cmd, $out, $retcode);
279 $out = &backquote_logged($cmd);
282 &error(&text('error_smfservice', $cmd, $retcode));
287 %prot_name = ("ip", "Internet Protocol",
288 "tcp", "Transmission Control Protocol",
289 "udp", "User Datagram Protocol",
290 "tcp6", "Transmission Control Protocol IPv6",
291 "tcp6only", "Transmission Control Protocol IPv6 only, no v4",
292 "udp6", "User Datagram Protocol IPv6",
293 "udp6only", "User Datagram Protocol IPv6 only, no v4");