inetd.c revision 8823:000507e9108d
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * NOTES: To be expanded.
28 *
29 * The SMF inetd.
30 *
31 * Below are some high level notes of the operation of the SMF inetd. The
32 * notes don't go into any real detail, and the viewer of this file is
33 * encouraged to look at the code and its associated comments to better
34 * understand inetd's operation. This saves the potential for the code
35 * and these notes diverging over time.
36 *
37 * Inetd's major work is done from the context of event_loop(). Within this
38 * loop, inetd polls for events arriving from a number of different file
39 * descriptors, representing the following event types, and initiates
40 * any necessary event processing:
41 * - incoming network connections/datagrams.
42 * - notification of terminated processes (discovered via contract events).
43 * - instance specific events originating from the SMF master restarter.
44 * - stop/refresh requests from the inetd method processes (coming in on a
45 *   Unix Domain socket).
46 * There's also a timeout set for the poll, which is set to the nearest
47 * scheduled timer in a timer queue that inetd uses to perform delayed
48 * processing, such as bind retries.
49 * The SIGHUP and SIGINT signals can also interrupt the poll, and will
50 * result in inetd being refreshed or stopped respectively, as was the
51 * behavior with the old inetd.
52 *
53 * Inetd implements a state machine for each instance. The states within the
54 * machine are: offline, online, disabled, maintenance, uninitialized and
55 * specializations of the offline state for when an instance exceeds one of
56 * its DOS limits. The state of an instance can be changed as a
57 * result/side-effect of one of the above events occurring, or inetd being
58 * started up. The ongoing state of an instance is stored in the SMF
59 * repository, as required of SMF restarters. This enables an administrator
60 * to view the state of each instance, and, if inetd was to terminate
61 * unexpectedly, it could use the stored state to re-commence where it left off.
62 *
63 * Within the state machine a number of methods are run (if provided) as part
64 * of a state transition to aid/ effect a change in an instance's state. The
65 * supported methods are: offline, online, disable, refresh and start. The
66 * latter of these is the equivalent of the server program and its arguments
67 * in the old inetd.
68 *
69 * Events from the SMF master restarter come in on a number of threads
70 * created in the registration routine of librestart, the delegated restarter
71 * library. These threads call into the restart_event_proxy() function
72 * when an event arrives. To serialize the processing of instances, these events
73 * are then written down a pipe to the process's main thread, which listens
74 * for these events via a poll call, with the file descriptor of the other
75 * end of the pipe in its read set, and processes the event appropriately.
76 * When the event has been  processed (which may be delayed if the instance
77 * for which the event is for is in the process of executing one of its methods
78 * as part of a state transition) it writes an acknowledgement back down the
79 * pipe the event was received on. The thread in restart_event_proxy() that
80 * wrote the event will read the acknowledgement it was blocked upon, and will
81 * then be able to return to its caller, thus implicitly acknowledging the
82 * event, and allowing another event to be written down the pipe for the main
83 * thread to process.
84 */
85
86
87#include <netdb.h>
88#include <stdio.h>
89#include <stdio_ext.h>
90#include <stdlib.h>
91#include <strings.h>
92#include <unistd.h>
93#include <assert.h>
94#include <sys/types.h>
95#include <sys/socket.h>
96#include <netinet/in.h>
97#include <fcntl.h>
98#include <signal.h>
99#include <errno.h>
100#include <locale.h>
101#include <syslog.h>
102#include <libintl.h>
103#include <librestart.h>
104#include <pthread.h>
105#include <sys/stat.h>
106#include <time.h>
107#include <limits.h>
108#include <libgen.h>
109#include <tcpd.h>
110#include <libscf.h>
111#include <libuutil.h>
112#include <stddef.h>
113#include <bsm/adt_event.h>
114#include <ucred.h>
115#include "inetd_impl.h"
116
117/* path to inetd's binary */
118#define	INETD_PATH	"/usr/lib/inet/inetd"
119
120/*
121 * inetd's default configuration file paths. /etc/inetd/inetd.conf is set
122 * be be the primary file, so it is checked before /etc/inetd.conf.
123 */
124#define	PRIMARY_DEFAULT_CONF_FILE	"/etc/inet/inetd.conf"
125#define	SECONDARY_DEFAULT_CONF_FILE	"/etc/inetd.conf"
126
127/* Arguments passed to this binary to request which method to execute. */
128#define	START_METHOD_ARG	"start"
129#define	STOP_METHOD_ARG		"stop"
130#define	REFRESH_METHOD_ARG	"refresh"
131
132/* connection backlog for unix domain socket */
133#define	UDS_BACKLOG	2
134
135/* number of retries to recv() a request on the UDS socket before giving up */
136#define	UDS_RECV_RETRIES	10
137
138/* enumeration of the different ends of a pipe */
139enum pipe_end {
140	PE_CONSUMER,
141	PE_PRODUCER
142};
143
144typedef struct {
145	internal_inst_state_t		istate;
146	const char			*name;
147	restarter_instance_state_t	smf_state;
148	instance_method_t		method_running;
149} state_info_t;
150
151
152/*
153 * Collection of information for each state.
154 * NOTE:  This table is indexed into using the internal_inst_state_t
155 * enumeration, so the ordering needs to be kept in synch.
156 */
157static state_info_t states[] = {
158	{IIS_UNINITIALIZED, "uninitialized", RESTARTER_STATE_UNINIT,
159	    IM_NONE},
160	{IIS_ONLINE, "online", RESTARTER_STATE_ONLINE, IM_START},
161	{IIS_IN_ONLINE_METHOD, "online_method", RESTARTER_STATE_OFFLINE,
162	    IM_ONLINE},
163	{IIS_OFFLINE, "offline", RESTARTER_STATE_OFFLINE, IM_NONE},
164	{IIS_IN_OFFLINE_METHOD, "offline_method", RESTARTER_STATE_OFFLINE,
165	    IM_OFFLINE},
166	{IIS_DISABLED, "disabled", RESTARTER_STATE_DISABLED, IM_NONE},
167	{IIS_IN_DISABLE_METHOD, "disabled_method", RESTARTER_STATE_OFFLINE,
168	    IM_DISABLE},
169	{IIS_IN_REFRESH_METHOD, "refresh_method", RESTARTER_STATE_ONLINE,
170	    IM_REFRESH},
171	{IIS_MAINTENANCE, "maintenance", RESTARTER_STATE_MAINT, IM_NONE},
172	{IIS_OFFLINE_CONRATE, "cr_offline", RESTARTER_STATE_OFFLINE, IM_NONE},
173	{IIS_OFFLINE_BIND, "bind_offline", RESTARTER_STATE_OFFLINE, IM_NONE},
174	{IIS_OFFLINE_COPIES, "copies_offline", RESTARTER_STATE_OFFLINE,
175	    IM_NONE},
176	{IIS_DEGRADED, "degraded", RESTARTER_STATE_DEGRADED, IM_NONE},
177	{IIS_NONE, "none", RESTARTER_STATE_NONE, IM_NONE}
178};
179
180/*
181 * Pipe used to send events from the threads created by restarter_bind_handle()
182 * to the main thread of control.
183 */
184static int			rst_event_pipe[] = {-1, -1};
185/*
186 * Used to protect the critical section of code in restarter_event_proxy() that
187 * involves writing an event down the event pipe and reading an acknowledgement.
188 */
189static pthread_mutex_t		rst_event_pipe_mtx = PTHREAD_MUTEX_INITIALIZER;
190
191/* handle used in communication with the master restarter */
192static restarter_event_handle_t *rst_event_handle = NULL;
193
194/* set to indicate a refresh of inetd is requested */
195static boolean_t		refresh_inetd_requested = B_FALSE;
196
197/* set by the SIGTERM handler to flag we got a SIGTERM */
198static boolean_t		got_sigterm = B_FALSE;
199
200/*
201 * Timer queue used to store timers for delayed event processing, such as
202 * bind retries.
203 */
204iu_tq_t				*timer_queue = NULL;
205
206/*
207 * fd of Unix Domain socket used to communicate stop and refresh requests
208 * to the inetd start method process.
209 */
210static int			uds_fd = -1;
211
212/*
213 * List of inetd's currently managed instances; each containing its state,
214 * and in certain states its configuration.
215 */
216static uu_list_pool_t		*instance_pool = NULL;
217uu_list_t			*instance_list = NULL;
218
219/* set to indicate we're being stopped */
220boolean_t			inetd_stopping = B_FALSE;
221
222/* TCP wrappers syslog globals. Consumed by libwrap. */
223int				allow_severity = LOG_INFO;
224int				deny_severity = LOG_WARNING;
225
226/* path of the configuration file being monitored by check_conf_file() */
227static char			*conf_file = NULL;
228
229/* Auditing session handle */
230static adt_session_data_t	*audit_handle;
231
232/* Number of pending connections */
233static size_t			tlx_pending_counter;
234
235static void uds_fini(void);
236static int uds_init(void);
237static int run_method(instance_t *, instance_method_t, const proto_info_t *);
238static void create_bound_fds(instance_t *);
239static void destroy_bound_fds(instance_t *);
240static void destroy_instance(instance_t *);
241static void inetd_stop(void);
242static void
243exec_method(instance_t *instance, instance_method_t method, method_info_t *mi,
244    struct method_context *mthd_ctxt, const proto_info_t *pi) __NORETURN;
245
246/*
247 * The following two functions are callbacks that libumem uses to determine
248 * inetd's desired debugging/logging levels. The interface they consume is
249 * exported by FMA and is consolidation private. The comments in the two
250 * functions give the environment variable that will effectively be set to
251 * their returned value, and thus whose behavior for this value, described in
252 * umem_debug(3MALLOC), will be followed.
253 */
254
255const char *
256_umem_debug_init(void)
257{
258	return ("default,verbose");	/* UMEM_DEBUG setting */
259}
260
261const char *
262_umem_logging_init(void)
263{
264	return ("fail,contents");	/* UMEM_LOGGING setting */
265}
266
267static void
268log_invalid_cfg(const char *fmri)
269{
270	error_msg(gettext(
271	    "Invalid configuration for instance %s, placing in maintenance"),
272	    fmri);
273}
274
275/*
276 * Returns B_TRUE if the instance is in a suitable state for inetd to stop.
277 */
278static boolean_t
279instance_stopped(const instance_t *inst)
280{
281	return ((inst->cur_istate == IIS_OFFLINE) ||
282	    (inst->cur_istate == IIS_MAINTENANCE) ||
283	    (inst->cur_istate == IIS_DISABLED) ||
284	    (inst->cur_istate == IIS_UNINITIALIZED));
285}
286
287/*
288 * Given the instance fmri, obtain the corresonding scf_instance.
289 * Caller is responsible for freeing the returned scf_instance and
290 * its scf_handle.
291 */
292static int
293fmri_to_instance(char *fmri, scf_instance_t **scf_instp)
294{
295	int retries, ret = 1;
296	scf_handle_t	*h;
297	scf_instance_t *scf_inst;
298
299	if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
300		error_msg(gettext("Failed to get instance for %s"), fmri);
301		return (1);
302	}
303
304	if ((scf_inst = scf_instance_create(h)) == NULL)
305		goto out;
306
307	for (retries = 0; retries <= REP_OP_RETRIES; retries++) {
308		if (make_handle_bound(h) == -1)
309			break;
310
311		if (scf_handle_decode_fmri(h, fmri, NULL, NULL, scf_inst,
312		    NULL, NULL, SCF_DECODE_FMRI_EXACT) == 0) {
313			ret = 0;
314			*scf_instp = scf_inst;
315			break;
316		}
317
318		if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
319			break;
320	}
321
322out:
323	if (ret != 0) {
324		error_msg(gettext("Failed to get instance for %s"), fmri);
325		scf_instance_destroy(scf_inst);
326		scf_handle_destroy(h);
327	}
328
329	return (ret);
330}
331
332/*
333 * Updates the current and next repository states of instance 'inst'. If
334 * any errors occur an error message is output.
335 */
336static void
337update_instance_states(instance_t *inst, internal_inst_state_t new_cur_state,
338    internal_inst_state_t new_next_state, restarter_error_t err)
339{
340	internal_inst_state_t	old_cur = inst->cur_istate;
341	internal_inst_state_t	old_next = inst->next_istate;
342	scf_instance_t		*scf_inst = NULL;
343	scf_error_t		sret;
344	int			ret;
345	char			*aux = "none";
346
347	/* update the repository/cached internal state */
348	inst->cur_istate = new_cur_state;
349	inst->next_istate = new_next_state;
350	(void) set_single_rep_val(inst->cur_istate_rep,
351	    (int64_t)new_cur_state);
352	(void) set_single_rep_val(inst->next_istate_rep,
353	    (int64_t)new_next_state);
354
355	if (((sret = store_rep_vals(inst->cur_istate_rep, inst->fmri,
356	    PR_NAME_CUR_INT_STATE)) != 0) ||
357	    ((sret = store_rep_vals(inst->next_istate_rep, inst->fmri,
358	    PR_NAME_NEXT_INT_STATE)) != 0))
359		error_msg(gettext("Failed to update state of instance %s in "
360		    "repository: %s"), inst->fmri, scf_strerror(sret));
361
362	if (fmri_to_instance(inst->fmri, &scf_inst) == 0) {
363		/*
364		 * If transitioning to maintenance, check auxiliary_tty set
365		 * by svcadm and assign appropriate value to auxiliary_state.
366		 * If the maintenance event comes from a service request,
367		 * validate auxiliary_fmri and copy it to
368		 * restarter/auxiliary_fmri.
369		 */
370		if (new_cur_state == IIS_MAINTENANCE) {
371			if (restarter_inst_ractions_from_tty(scf_inst) == 0)
372				aux = "service_request";
373			else
374				aux = "administrative_request";
375		}
376
377		if (strcmp(aux, "service_request") == 0) {
378			if (restarter_inst_validate_ractions_aux_fmri(
379			    scf_inst) == 0) {
380				if (restarter_inst_set_aux_fmri(scf_inst))
381					error_msg(gettext("Could not set "
382					    "auxiliary_fmri property for %s"),
383					    inst->fmri);
384			} else {
385				if (restarter_inst_reset_aux_fmri(scf_inst))
386					error_msg(gettext("Could not reset "
387					    "auxiliary_fmri property for %s"),
388					    inst->fmri);
389			}
390		}
391		scf_handle_destroy(scf_instance_handle(scf_inst));
392		scf_instance_destroy(scf_inst);
393	}
394
395	/* update the repository SMF state */
396	if ((ret = restarter_set_states(rst_event_handle, inst->fmri,
397	    states[old_cur].smf_state, states[new_cur_state].smf_state,
398	    states[old_next].smf_state, states[new_next_state].smf_state,
399	    err, aux)) != 0)
400		error_msg(gettext("Failed to update state of instance %s in "
401		    "repository: %s"), inst->fmri, strerror(ret));
402}
403
404void
405update_state(instance_t *inst, internal_inst_state_t new_cur,
406    restarter_error_t err)
407{
408	update_instance_states(inst, new_cur, IIS_NONE, err);
409}
410
411/*
412 * Sends a refresh event to the inetd start method process and returns
413 * SMF_EXIT_OK if it managed to send it. If it fails to send the request for
414 * some reason it returns SMF_EXIT_ERR_OTHER.
415 */
416static int
417refresh_method(void)
418{
419	uds_request_t   req = UR_REFRESH_INETD;
420	int		fd;
421
422	if ((fd = connect_to_inetd()) < 0) {
423		error_msg(gettext("Failed to connect to inetd: %s"),
424		    strerror(errno));
425		return (SMF_EXIT_ERR_OTHER);
426	}
427
428	/* write the request and return success */
429	if (safe_write(fd, &req, sizeof (req)) == -1) {
430		error_msg(
431		    gettext("Failed to send refresh request to inetd: %s"),
432		    strerror(errno));
433		(void) close(fd);
434		return (SMF_EXIT_ERR_OTHER);
435	}
436
437	(void) close(fd);
438
439	return (SMF_EXIT_OK);
440}
441
442/*
443 * Sends a stop event to the inetd start method process and wait till it goes
444 * away. If inetd is determined to have stopped SMF_EXIT_OK is returned, else
445 * SMF_EXIT_ERR_OTHER is returned.
446 */
447static int
448stop_method(void)
449{
450	uds_request_t   req = UR_STOP_INETD;
451	int		fd;
452	char		c;
453	ssize_t		ret;
454
455	if ((fd = connect_to_inetd()) == -1) {
456		debug_msg(gettext("Failed to connect to inetd: %s"),
457		    strerror(errno));
458		/*
459		 * Assume connect_to_inetd() failed because inetd was already
460		 * stopped, and return success.
461		 */
462		return (SMF_EXIT_OK);
463	}
464
465	/*
466	 * This is safe to do since we're fired off in a separate process
467	 * than inetd and in the case we get wedged, the stop method timeout
468	 * will occur and we'd be killed by our restarter.
469	 */
470	enable_blocking(fd);
471
472	/* write the stop request to inetd and wait till it goes away */
473	if (safe_write(fd, &req, sizeof (req)) != 0) {
474		error_msg(gettext("Failed to send stop request to inetd"));
475		(void) close(fd);
476		return (SMF_EXIT_ERR_OTHER);
477	}
478
479	/* wait until remote end of socket is closed */
480	while (((ret = recv(fd, &c, sizeof (c), 0)) != 0) && (errno == EINTR))
481		;
482
483	(void) close(fd);
484
485	if (ret != 0) {
486		error_msg(gettext("Failed to determine whether inetd stopped"));
487		return (SMF_EXIT_ERR_OTHER);
488	}
489
490	return (SMF_EXIT_OK);
491}
492
493
494/*
495 * This function is called to handle restarter events coming in from the
496 * master restarter. It is registered with the master restarter via
497 * restarter_bind_handle() and simply passes a pointer to the event down
498 * the event pipe, which will be discovered by the poll in the event loop
499 * and processed there. It waits for an acknowledgement to be written back down
500 * the pipe before returning.
501 * Writing a pointer to the function's 'event' parameter down the pipe will
502 * be safe, as the thread in restarter_event_proxy() doesn't return until
503 * the main thread has finished its processing of the passed event, thus
504 * the referenced event will remain around until the function returns.
505 * To impose the limit of only one event being in the pipe and processed
506 * at once, a lock is taken on entry to this function and returned on exit.
507 * Always returns 0.
508 */
509static int
510restarter_event_proxy(restarter_event_t *event)
511{
512	boolean_t		processed;
513
514	(void) pthread_mutex_lock(&rst_event_pipe_mtx);
515
516	/* write the event to the main worker thread down the pipe */
517	if (safe_write(rst_event_pipe[PE_PRODUCER], &event,
518	    sizeof (event)) != 0)
519		goto pipe_error;
520
521	/*
522	 * Wait for an acknowledgement that the event has been processed from
523	 * the same pipe. In the case that inetd is stopping, any thread in
524	 * this function will simply block on this read until inetd eventually
525	 * exits. This will result in this function not returning success to
526	 * its caller, and the event that was being processed when the
527	 * function exited will be re-sent when inetd is next started.
528	 */
529	if (safe_read(rst_event_pipe[PE_PRODUCER], &processed,
530	    sizeof (processed)) != 0)
531		goto pipe_error;
532
533	(void) pthread_mutex_unlock(&rst_event_pipe_mtx);
534
535	return (processed ? 0 : EAGAIN);
536
537pipe_error:
538	/*
539	 * Something's seriously wrong with the event pipe. Notify the
540	 * worker thread by closing this end of the event pipe and pause till
541	 * inetd exits.
542	 */
543	error_msg(gettext("Can't process restarter events: %s"),
544	    strerror(errno));
545	(void) close(rst_event_pipe[PE_PRODUCER]);
546	for (;;)
547		(void) pause();
548
549	/* NOTREACHED */
550}
551
552/*
553 * Let restarter_event_proxy() know we're finished with the event it's blocked
554 * upon. The 'processed' argument denotes whether we successfully processed the
555 * event.
556 */
557static void
558ack_restarter_event(boolean_t processed)
559{
560	/*
561	 * If safe_write returns -1 something's seriously wrong with the event
562	 * pipe, so start the shutdown proceedings.
563	 */
564	if (safe_write(rst_event_pipe[PE_CONSUMER], &processed,
565	    sizeof (processed)) == -1)
566		inetd_stop();
567}
568
569/*
570 * Switch the syslog identification string to 'ident'.
571 */
572static void
573change_syslog_ident(const char *ident)
574{
575	closelog();
576	openlog(ident, LOG_PID|LOG_CONS, LOG_DAEMON);
577}
578
579/*
580 * Perform TCP wrappers checks on this instance. Due to the fact that the
581 * current wrappers code used in Solaris is taken untouched from the open
582 * source version, we're stuck with using the daemon name for the checks, as
583 * opposed to making use of instance FMRIs. Sigh.
584 * Returns B_TRUE if the check passed, else B_FALSE.
585 */
586static boolean_t
587tcp_wrappers_ok(instance_t *instance)
588{
589	boolean_t		rval = B_TRUE;
590	char			*daemon_name;
591	basic_cfg_t		*cfg = instance->config->basic;
592	struct request_info	req;
593
594	/*
595	 * Wrap the service using libwrap functions. The code below implements
596	 * the functionality of tcpd. This is done only for stream,nowait
597	 * services, following the convention of other vendors.  udp/dgram and
598	 * stream/wait can NOT be wrapped with this libwrap, so be wary of
599	 * changing the test below.
600	 */
601	if (cfg->do_tcp_wrappers && !cfg->iswait && !cfg->istlx) {
602
603		daemon_name = instance->config->methods[
604		    IM_START]->exec_args_we.we_wordv[0];
605		if (*daemon_name == '/')
606			daemon_name = strrchr(daemon_name, '/') + 1;
607
608		/*
609		 * Change the syslog message identity to the name of the
610		 * daemon being wrapped, as opposed to "inetd".
611		 */
612		change_syslog_ident(daemon_name);
613
614		(void) request_init(&req, RQ_DAEMON, daemon_name, RQ_FILE,
615		    instance->conn_fd, NULL);
616		fromhost(&req);
617
618		if (strcasecmp(eval_hostname(req.client), paranoid) == 0) {
619			syslog(deny_severity,
620			    "refused connect from %s (name/address mismatch)",
621			    eval_client(&req));
622			if (req.sink != NULL)
623				req.sink(instance->conn_fd);
624			rval = B_FALSE;
625		} else if (!hosts_access(&req)) {
626			syslog(deny_severity,
627			    "refused connect from %s (access denied)",
628			    eval_client(&req));
629			if (req.sink != NULL)
630				req.sink(instance->conn_fd);
631			rval = B_FALSE;
632		} else {
633			syslog(allow_severity, "connect from %s",
634			    eval_client(&req));
635		}
636
637		/* Revert syslog identity back to "inetd". */
638		change_syslog_ident(SYSLOG_IDENT);
639	}
640	return (rval);
641}
642
643/*
644 * Handler registered with the timer queue code to remove an instance from
645 * the connection rate offline state when it has been there for its allotted
646 * time.
647 */
648/* ARGSUSED */
649static void
650conn_rate_online(iu_tq_t *tq, void *arg)
651{
652	instance_t *instance = arg;
653
654	assert(instance->cur_istate == IIS_OFFLINE_CONRATE);
655	instance->timer_id = -1;
656	update_state(instance, IIS_OFFLINE, RERR_RESTART);
657	process_offline_inst(instance);
658}
659
660/*
661 * Check whether this instance in the offline state is in transition to
662 * another state and do the work to continue this transition.
663 */
664void
665process_offline_inst(instance_t *inst)
666{
667	if (inst->disable_req) {
668		inst->disable_req = B_FALSE;
669		(void) run_method(inst, IM_DISABLE, NULL);
670	} else if (inst->maintenance_req) {
671		inst->maintenance_req = B_FALSE;
672		update_state(inst, IIS_MAINTENANCE, RERR_RESTART);
673	/*
674	 * If inetd is in the process of stopping, we don't want to enter
675	 * any states but offline, disabled and maintenance.
676	 */
677	} else if (!inetd_stopping) {
678		if (inst->conn_rate_exceeded) {
679			basic_cfg_t *cfg = inst->config->basic;
680
681			inst->conn_rate_exceeded = B_FALSE;
682			update_state(inst, IIS_OFFLINE_CONRATE, RERR_RESTART);
683			/*
684			 * Schedule a timer to bring the instance out of the
685			 * connection rate offline state.
686			 */
687			inst->timer_id = iu_schedule_timer(timer_queue,
688			    cfg->conn_rate_offline, conn_rate_online,
689			    inst);
690			if (inst->timer_id == -1) {
691				error_msg(gettext("%s unable to set timer, "
692				    "won't be brought on line after %d "
693				    "seconds."), inst->fmri,
694				    cfg->conn_rate_offline);
695			}
696
697		} else if (copies_limit_exceeded(inst)) {
698			update_state(inst, IIS_OFFLINE_COPIES, RERR_RESTART);
699		}
700	}
701}
702
703/*
704 * Create a socket bound to the instance's configured address. If the
705 * bind fails, returns -1, else the fd of the bound socket.
706 */
707static int
708create_bound_socket(const instance_t *inst, socket_info_t *sock_info)
709{
710	int		fd;
711	int		on = 1;
712	const char	*fmri = inst->fmri;
713	rpc_info_t	*rpc = sock_info->pr_info.ri;
714	const char	*proto = sock_info->pr_info.proto;
715
716	fd = socket(sock_info->local_addr.ss_family, sock_info->type,
717	    sock_info->protocol);
718	if (fd < 0) {
719		error_msg(gettext(
720		    "Socket creation failure for instance %s, proto %s: %s"),
721		    fmri, proto, strerror(errno));
722		return (-1);
723	}
724
725	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) == -1) {
726		error_msg(gettext("setsockopt SO_REUSEADDR failed for service "
727		    "instance %s, proto %s: %s"), fmri, proto, strerror(errno));
728		(void) close(fd);
729		return (-1);
730	}
731	if (sock_info->pr_info.v6only) {
732		/* restrict socket to IPv6 communications only */
733		if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on,
734		    sizeof (on)) == -1) {
735			error_msg(gettext("setsockopt IPV6_V6ONLY failed for "
736			    "service instance %s, proto %s: %s"), fmri, proto,
737			    strerror(errno));
738			(void) close(fd);
739			return (-1);
740		}
741	}
742
743	if (rpc != NULL)
744		SS_SETPORT(sock_info->local_addr, 0);
745
746	if (bind(fd, (struct sockaddr *)&(sock_info->local_addr),
747	    SS_ADDRLEN(sock_info->local_addr)) < 0) {
748		error_msg(gettext(
749		    "Failed to bind to the port of service instance %s, "
750		    "proto %s: %s"), fmri, proto, strerror(errno));
751		(void) close(fd);
752		return (-1);
753	}
754
755	/*
756	 * Retrieve and store the address bound to for RPC services.
757	 */
758	if (rpc != NULL) {
759		struct sockaddr_storage	ss;
760		int			ss_size = sizeof (ss);
761
762		if (getsockname(fd, (struct sockaddr *)&ss, &ss_size) < 0) {
763			error_msg(gettext("Failed getsockname for instance %s, "
764			    "proto %s: %s"), fmri, proto, strerror(errno));
765			(void) close(fd);
766			return (-1);
767		}
768		(void) memcpy(rpc->netbuf.buf, &ss,
769		    sizeof (struct sockaddr_storage));
770		rpc->netbuf.len = SS_ADDRLEN(ss);
771		rpc->netbuf.maxlen = SS_ADDRLEN(ss);
772	}
773
774	if (sock_info->type == SOCK_STREAM) {
775		int qlen = inst->config->basic->conn_backlog;
776
777		debug_msg("Listening for service %s with backlog queue"
778		    " size %d", fmri, qlen);
779		(void) listen(fd, qlen);
780	}
781
782	return (fd);
783}
784
785/*
786 * Handler registered with the timer queue code to retry the creation
787 * of a bound fd.
788 */
789/* ARGSUSED */
790static void
791retry_bind(iu_tq_t *tq, void *arg)
792{
793	instance_t *instance = arg;
794
795	switch (instance->cur_istate) {
796	case IIS_OFFLINE_BIND:
797	case IIS_ONLINE:
798	case IIS_DEGRADED:
799	case IIS_IN_ONLINE_METHOD:
800	case IIS_IN_REFRESH_METHOD:
801		break;
802	default:
803#ifndef NDEBUG
804		(void) fprintf(stderr, "%s:%d: Unknown instance state %d.\n",
805		    __FILE__, __LINE__, instance->cur_istate);
806#endif
807		abort();
808	}
809
810	instance->bind_timer_id = -1;
811	create_bound_fds(instance);
812}
813
814/*
815 * For each of the fds for the given instance that are bound, if 'listen' is
816 * set add them to the poll set, else remove them from it. If any additions
817 * fail, returns -1, else 0 on success.
818 */
819int
820poll_bound_fds(instance_t *instance, boolean_t listen)
821{
822	basic_cfg_t	*cfg = instance->config->basic;
823	proto_info_t	*pi;
824	int		ret = 0;
825
826	for (pi = uu_list_first(cfg->proto_list); pi != NULL;
827	    pi = uu_list_next(cfg->proto_list, pi)) {
828		if (pi->listen_fd != -1) {	/* fd bound */
829			if (!listen) {
830				clear_pollfd(pi->listen_fd);
831			} else if (set_pollfd(pi->listen_fd, POLLIN) == -1) {
832				ret = -1;
833			}
834		}
835	}
836
837	return (ret);
838}
839
840/*
841 * Handle the case were we either fail to create a bound fd or we fail
842 * to add a bound fd to the poll set for the given instance.
843 */
844static void
845handle_bind_failure(instance_t *instance)
846{
847	basic_cfg_t *cfg = instance->config->basic;
848
849	/*
850	 * We must be being called as a result of a failed poll_bound_fds()
851	 * as a bind retry is already scheduled. Just return and let it do
852	 * the work.
853	 */
854	if (instance->bind_timer_id != -1)
855		return;
856
857	/*
858	 * Check if the rebind retries limit is operative and if so,
859	 * if it has been reached.
860	 */
861	if (((cfg->bind_fail_interval <= 0) ||		/* no retries */
862	    ((cfg->bind_fail_max >= 0) &&		/* limit reached */
863	    (++instance->bind_fail_count > cfg->bind_fail_max))) ||
864	    ((instance->bind_timer_id = iu_schedule_timer(timer_queue,
865	    cfg->bind_fail_interval, retry_bind, instance)) == -1)) {
866		proto_info_t *pi;
867
868		instance->bind_fail_count = 0;
869
870		switch (instance->cur_istate) {
871		case IIS_DEGRADED:
872		case IIS_ONLINE:
873			/* check if any of the fds are being poll'd upon */
874			for (pi = uu_list_first(cfg->proto_list); pi != NULL;
875			    pi = uu_list_next(cfg->proto_list, pi)) {
876				if ((pi->listen_fd != -1) &&
877				    (find_pollfd(pi->listen_fd) != NULL))
878					break;
879			}
880			if (pi != NULL)	{	/* polling on > 0 fds */
881				warn_msg(gettext("Failed to bind on "
882				    "all protocols for instance %s, "
883				    "transitioning to degraded"),
884				    instance->fmri);
885				update_state(instance, IIS_DEGRADED, RERR_NONE);
886				instance->bind_retries_exceeded = B_TRUE;
887				break;
888			}
889
890			destroy_bound_fds(instance);
891			/*
892			 * In the case we failed the 'bind' because set_pollfd()
893			 * failed on all bound fds, use the offline handling.
894			 */
895			/* FALLTHROUGH */
896		case IIS_OFFLINE:
897		case IIS_OFFLINE_BIND:
898			error_msg(gettext("Too many bind failures for instance "
899			"%s, transitioning to maintenance"), instance->fmri);
900			update_state(instance, IIS_MAINTENANCE,
901			    RERR_FAULT);
902			break;
903		case IIS_IN_ONLINE_METHOD:
904		case IIS_IN_REFRESH_METHOD:
905			warn_msg(gettext("Failed to bind on all "
906			    "protocols for instance %s, instance will go to "
907			    "degraded"), instance->fmri);
908			/*
909			 * Set the retries exceeded flag so when the method
910			 * completes the instance goes to the degraded state.
911			 */
912			instance->bind_retries_exceeded = B_TRUE;
913			break;
914		default:
915#ifndef NDEBUG
916			(void) fprintf(stderr,
917			    "%s:%d: Unknown instance state %d.\n",
918			    __FILE__, __LINE__, instance->cur_istate);
919#endif
920			abort();
921		}
922	} else if (instance->cur_istate == IIS_OFFLINE) {
923		/*
924		 * bind re-scheduled, so if we're offline reflect this in the
925		 * state.
926		 */
927		update_state(instance, IIS_OFFLINE_BIND, RERR_NONE);
928	}
929}
930
931
932/*
933 * Check if two transport protocols for RPC conflict.
934 */
935
936boolean_t
937is_rpc_proto_conflict(const char *proto0, const char *proto1) {
938	if (strcmp(proto0, "tcp") == 0) {
939		if (strcmp(proto1, "tcp") == 0)
940			return (B_TRUE);
941		if (strcmp(proto1, "tcp6") == 0)
942			return (B_TRUE);
943		return (B_FALSE);
944	}
945
946	if (strcmp(proto0, "tcp6") == 0) {
947		if (strcmp(proto1, "tcp") == 0)
948			return (B_TRUE);
949		if (strcmp(proto1, "tcp6only") == 0)
950			return (B_TRUE);
951		if (strcmp(proto1, "tcp6") == 0)
952			return (B_TRUE);
953		return (B_FALSE);
954	}
955
956	if (strcmp(proto0, "tcp6only") == 0) {
957		if (strcmp(proto1, "tcp6only") == 0)
958			return (B_TRUE);
959		if (strcmp(proto1, "tcp6") == 0)
960			return (B_TRUE);
961		return (B_FALSE);
962	}
963
964	if (strcmp(proto0, "udp") == 0) {
965		if (strcmp(proto1, "udp") == 0)
966			return (B_TRUE);
967		if (strcmp(proto1, "udp6") == 0)
968			return (B_TRUE);
969		return (B_FALSE);
970	}
971
972	if (strcmp(proto0, "udp6") == 0) {
973
974		if (strcmp(proto1, "udp") == 0)
975			return (B_TRUE);
976		if (strcmp(proto1, "udp6only") == 0)
977			return (B_TRUE);
978		if (strcmp(proto1, "udp6") == 0)
979			return (B_TRUE);
980		return (B_FALSE);
981	}
982
983	if (strcmp(proto0, "udp6only") == 0) {
984
985		if (strcmp(proto1, "udp6only") == 0)
986			return (B_TRUE);
987		if (strcmp(proto1, "udp6") == 0)
988			return (B_TRUE);
989		return (0);
990	}
991
992	/*
993	 * If the protocol isn't TCP/IP or UDP/IP assume that it has its own
994	 * port namepsace and that conflicts can be detected by literal string
995	 * comparison.
996	 */
997
998	if (strcmp(proto0, proto1))
999		return (FALSE);
1000
1001	return (B_TRUE);
1002}
1003
1004
1005/*
1006 * Check if inetd thinks this RPC program number is already registered.
1007 *
1008 * An RPC protocol conflict occurs if
1009 * 	a) the program numbers are the same and,
1010 * 	b) the version numbers overlap,
1011 * 	c) the protocols (TCP vs UDP vs tic*) are the same.
1012 */
1013
1014boolean_t
1015is_rpc_num_in_use(int rpc_n, char *proto, int lowver, int highver) {
1016	instance_t *i;
1017	basic_cfg_t *cfg;
1018	proto_info_t *pi;
1019
1020	for (i = uu_list_first(instance_list); i != NULL;
1021	    i = uu_list_next(instance_list, i)) {
1022
1023		if (i->cur_istate != IIS_ONLINE)
1024			continue;
1025		cfg = i->config->basic;
1026
1027		for (pi = uu_list_first(cfg->proto_list); pi != NULL;
1028		    pi = uu_list_next(cfg->proto_list, pi)) {
1029
1030			if (pi->ri == NULL)
1031				continue;
1032			if (pi->ri->prognum != rpc_n)
1033				continue;
1034			if (!is_rpc_proto_conflict(pi->proto, proto))
1035				continue;
1036			if ((lowver < pi->ri->lowver &&
1037			    highver < pi->ri->lowver) ||
1038			    (lowver > pi->ri->highver &&
1039			    highver > pi->ri->highver))
1040				continue;
1041			return (B_TRUE);
1042		}
1043	}
1044	return (B_FALSE);
1045}
1046
1047
1048/*
1049 * Independent of the transport, for each of the entries in the instance's
1050 * proto list this function first attempts to create an associated network fd;
1051 * for RPC services these are then bound to a kernel chosen port and the
1052 * fd is registered with rpcbind; for non-RPC services the fds are bound
1053 * to the port associated with the instance's service name. On any successful
1054 * binds the instance is taken online. Failed binds are handled by
1055 * handle_bind_failure().
1056 */
1057void
1058create_bound_fds(instance_t *instance)
1059{
1060	basic_cfg_t	*cfg = instance->config->basic;
1061	boolean_t	failure = B_FALSE;
1062	boolean_t	success = B_FALSE;
1063	proto_info_t	*pi;
1064
1065	/*
1066	 * Loop through and try and bind any unbound protos.
1067	 */
1068	for (pi = uu_list_first(cfg->proto_list); pi != NULL;
1069	    pi = uu_list_next(cfg->proto_list, pi)) {
1070		if (pi->listen_fd != -1)
1071			continue;
1072		if (cfg->istlx) {
1073			pi->listen_fd = create_bound_endpoint(instance,
1074			    (tlx_info_t *)pi);
1075		} else {
1076			/*
1077			 * We cast pi to a void so we can then go on to cast
1078			 * it to a socket_info_t without lint complaining
1079			 * about alignment. This is done because the x86
1080			 * version of lint thinks a lint suppression directive
1081			 * is unnecessary and flags it as such, yet the sparc
1082			 * version complains if it's absent.
1083			 */
1084			void *p = pi;
1085			pi->listen_fd = create_bound_socket(instance,
1086			    (socket_info_t *)p);
1087		}
1088		if (pi->listen_fd == -1) {
1089			failure = B_TRUE;
1090			continue;
1091		}
1092
1093		if (pi->ri != NULL) {
1094
1095			/*
1096			 * Don't register the same RPC program number twice.
1097			 * Doing so silently discards the old service
1098			 * without causing an error.
1099			 */
1100			if (is_rpc_num_in_use(pi->ri->prognum, pi->proto,
1101			    pi->ri->lowver, pi->ri->highver)) {
1102				failure = B_TRUE;
1103				close_net_fd(instance, pi->listen_fd);
1104				pi->listen_fd = -1;
1105				continue;
1106			}
1107
1108			unregister_rpc_service(instance->fmri, pi->ri);
1109			if (register_rpc_service(instance->fmri, pi->ri) ==
1110			    -1) {
1111				close_net_fd(instance, pi->listen_fd);
1112				pi->listen_fd = -1;
1113				failure = B_TRUE;
1114				continue;
1115			}
1116		}
1117
1118		success = B_TRUE;
1119	}
1120
1121	switch (instance->cur_istate) {
1122	case IIS_OFFLINE:
1123	case IIS_OFFLINE_BIND:
1124		/*
1125		 * If we've managed to bind at least one proto lets run the
1126		 * online method, so we can start listening for it.
1127		 */
1128		if (success && run_method(instance, IM_ONLINE, NULL) == -1)
1129			return;	/* instance gone to maintenance */
1130		break;
1131	case IIS_ONLINE:
1132	case IIS_IN_REFRESH_METHOD:
1133		/*
1134		 * We're 'online', so start polling on any bound fds we're
1135		 * currently not.
1136		 */
1137		if (poll_bound_fds(instance, B_TRUE) != 0) {
1138			failure = B_TRUE;
1139		} else if (!failure) {
1140			/*
1141			 * We've successfully bound and poll'd upon all protos,
1142			 * so reset the failure count.
1143			 */
1144			instance->bind_fail_count = 0;
1145		}
1146		break;
1147	case IIS_IN_ONLINE_METHOD:
1148		/*
1149		 * Nothing to do here as the method completion code will start
1150		 * listening for any successfully bound fds.
1151		 */
1152		break;
1153	default:
1154#ifndef NDEBUG
1155		(void) fprintf(stderr, "%s:%d: Unknown instance state %d.\n",
1156		    __FILE__, __LINE__, instance->cur_istate);
1157#endif
1158		abort();
1159	}
1160
1161	if (failure)
1162		handle_bind_failure(instance);
1163}
1164
1165/*
1166 * Counter to create_bound_fds(), for each of the bound network fds this
1167 * function unregisters the instance from rpcbind if it's an RPC service,
1168 * stops listening for new connections for it and then closes the listening fd.
1169 */
1170static void
1171destroy_bound_fds(instance_t *instance)
1172{
1173	basic_cfg_t	*cfg = instance->config->basic;
1174	proto_info_t	*pi;
1175
1176	for (pi = uu_list_first(cfg->proto_list); pi != NULL;
1177	    pi = uu_list_next(cfg->proto_list, pi)) {
1178		if (pi->listen_fd != -1) {
1179			if (pi->ri != NULL)
1180				unregister_rpc_service(instance->fmri, pi->ri);
1181			clear_pollfd(pi->listen_fd);
1182			close_net_fd(instance, pi->listen_fd);
1183			pi->listen_fd = -1;
1184		}
1185	}
1186
1187	/* cancel any bind retries */
1188	if (instance->bind_timer_id != -1)
1189		cancel_bind_timer(instance);
1190
1191	instance->bind_retries_exceeded = B_FALSE;
1192}
1193
1194/*
1195 * Perform %A address expansion and return a pointer to a static string
1196 * array containing crafted arguments. This expansion is provided for
1197 * compatibility with 4.2BSD daemons, and as such we've copied the logic of
1198 * the legacy inetd to maintain this compatibility as much as possible. This
1199 * logic is a bit scatty, but it dates back at least as far as SunOS 4.x.
1200 */
1201static char **
1202expand_address(instance_t *inst, const proto_info_t *pi)
1203{
1204	static char	addrbuf[sizeof ("ffffffff.65536")];
1205	static char	*ret[3];
1206	instance_cfg_t	*cfg = inst->config;
1207	/*
1208	 * We cast pi to a void so we can then go on to cast it to a
1209	 * socket_info_t without lint complaining about alignment. This
1210	 * is done because the x86 version of lint thinks a lint suppression
1211	 * directive is unnecessary and flags it as such, yet the sparc
1212	 * version complains if it's absent.
1213	 */
1214	const void	*p = pi;
1215
1216	/* set ret[0] to the basename of exec path */
1217	if ((ret[0] = strrchr(cfg->methods[IM_START]->exec_path, '/'))
1218	    != NULL) {
1219		ret[0]++;
1220	} else {
1221		ret[0] = cfg->methods[IM_START]->exec_path;
1222	}
1223
1224	if (!cfg->basic->istlx &&
1225	    (((socket_info_t *)p)->type == SOCK_DGRAM)) {
1226		ret[1] = NULL;
1227	} else {
1228		addrbuf[0] = '\0';
1229		if (!cfg->basic->iswait &&
1230		    (inst->remote_addr.ss_family == AF_INET)) {
1231			struct sockaddr_in *sp;
1232
1233			sp = (struct sockaddr_in *)&(inst->remote_addr);
1234			(void) snprintf(addrbuf, sizeof (addrbuf), "%x.%hu",
1235			    ntohl(sp->sin_addr.s_addr), ntohs(sp->sin_port));
1236		}
1237		ret[1] = addrbuf;
1238		ret[2] = NULL;
1239	}
1240
1241	return (ret);
1242}
1243
1244/*
1245 * Returns the state associated with the supplied method being run for an
1246 * instance.
1247 */
1248static internal_inst_state_t
1249get_method_state(instance_method_t method)
1250{
1251	state_info_t *sip;
1252
1253	for (sip = states; sip->istate != IIS_NONE; sip++) {
1254		if (sip->method_running == method)
1255			break;
1256	}
1257	assert(sip->istate != IIS_NONE);
1258
1259	return (sip->istate);
1260}
1261
1262/*
1263 * Store the method's PID and CID in the repository. If the store fails
1264 * we ignore it and just drive on.
1265 */
1266static void
1267add_method_ids(instance_t *ins, pid_t pid, ctid_t cid, instance_method_t mthd)
1268{
1269	if (cid != -1)
1270		(void) add_remove_contract(ins, B_TRUE, cid);
1271
1272	if (mthd == IM_START) {
1273		if (add_rep_val(ins->start_pids, (int64_t)pid) == 0) {
1274			(void) store_rep_vals(ins->start_pids, ins->fmri,
1275			    PR_NAME_START_PIDS);
1276		}
1277	} else {
1278		if (add_rep_val(ins->non_start_pid, (int64_t)pid) == 0) {
1279			(void) store_rep_vals(ins->non_start_pid, ins->fmri,
1280			    PR_NAME_NON_START_PID);
1281		}
1282	}
1283}
1284
1285/*
1286 * Remove the method's PID and CID from the repository. If the removal
1287 * fails we ignore it and drive on.
1288 */
1289void
1290remove_method_ids(instance_t *inst, pid_t pid, ctid_t cid,
1291    instance_method_t mthd)
1292{
1293	if (cid != -1)
1294		(void) add_remove_contract(inst, B_FALSE, cid);
1295
1296	if (mthd == IM_START) {
1297		remove_rep_val(inst->start_pids, (int64_t)pid);
1298		(void) store_rep_vals(inst->start_pids, inst->fmri,
1299		    PR_NAME_START_PIDS);
1300	} else {
1301		remove_rep_val(inst->non_start_pid, (int64_t)pid);
1302		(void) store_rep_vals(inst->non_start_pid, inst->fmri,
1303		    PR_NAME_NON_START_PID);
1304	}
1305}
1306
1307static instance_t *
1308create_instance(const char *fmri)
1309{
1310	instance_t *ret;
1311
1312	if (((ret = calloc(1, sizeof (instance_t))) == NULL) ||
1313	    ((ret->fmri = strdup(fmri)) == NULL))
1314		goto alloc_fail;
1315
1316	ret->conn_fd = -1;
1317
1318	ret->copies = 0;
1319
1320	ret->conn_rate_count = 0;
1321	ret->fail_rate_count = 0;
1322	ret->bind_fail_count = 0;
1323
1324	if (((ret->non_start_pid = create_rep_val_list()) == NULL) ||
1325	    ((ret->start_pids = create_rep_val_list()) == NULL) ||
1326	    ((ret->start_ctids = create_rep_val_list()) == NULL))
1327		goto alloc_fail;
1328
1329	ret->cur_istate = IIS_NONE;
1330	ret->next_istate = IIS_NONE;
1331
1332	if (((ret->cur_istate_rep = create_rep_val_list()) == NULL) ||
1333	    ((ret->next_istate_rep = create_rep_val_list()) == NULL))
1334		goto alloc_fail;
1335
1336	ret->config = NULL;
1337	ret->new_config = NULL;
1338
1339	ret->timer_id = -1;
1340	ret->bind_timer_id = -1;
1341
1342	ret->disable_req = B_FALSE;
1343	ret->maintenance_req = B_FALSE;
1344	ret->conn_rate_exceeded = B_FALSE;
1345	ret->bind_retries_exceeded = B_FALSE;
1346
1347	ret->pending_rst_event = RESTARTER_EVENT_TYPE_INVALID;
1348
1349	return (ret);
1350
1351alloc_fail:
1352	error_msg(strerror(errno));
1353	destroy_instance(ret);
1354	return (NULL);
1355}
1356
1357static void
1358destroy_instance(instance_t *inst)
1359{
1360	if (inst == NULL)
1361		return;
1362
1363	destroy_instance_cfg(inst->config);
1364	destroy_instance_cfg(inst->new_config);
1365
1366	destroy_rep_val_list(inst->cur_istate_rep);
1367	destroy_rep_val_list(inst->next_istate_rep);
1368
1369	destroy_rep_val_list(inst->start_pids);
1370	destroy_rep_val_list(inst->non_start_pid);
1371	destroy_rep_val_list(inst->start_ctids);
1372
1373	free(inst->fmri);
1374
1375	free(inst);
1376}
1377
1378/*
1379 * Retrieves the current and next states internal states. Returns 0 on success,
1380 * else returns one of the following on error:
1381 * SCF_ERROR_NO_MEMORY if memory allocation failed.
1382 * SCF_ERROR_CONNECTION_BROKEN if the connection to the repository was broken.
1383 * SCF_ERROR_TYPE_MISMATCH if the property was of an unexpected type.
1384 * SCF_ERROR_NO_RESOURCES if the server doesn't have adequate resources.
1385 * SCF_ERROR_NO_SERVER if the server isn't running.
1386 */
1387static scf_error_t
1388retrieve_instance_state(instance_t *inst)
1389{
1390	scf_error_t	ret;
1391
1392	/* retrieve internal states */
1393	if (((ret = retrieve_rep_vals(inst->cur_istate_rep, inst->fmri,
1394	    PR_NAME_CUR_INT_STATE)) != 0) ||
1395	    ((ret = retrieve_rep_vals(inst->next_istate_rep, inst->fmri,
1396	    PR_NAME_NEXT_INT_STATE)) != 0)) {
1397		if (ret != SCF_ERROR_NOT_FOUND) {
1398			error_msg(gettext(
1399			    "Failed to read state of instance %s: %s"),
1400			    inst->fmri, scf_strerror(scf_error()));
1401			return (ret);
1402		}
1403
1404		debug_msg("instance with no previous int state - "
1405		    "setting state to uninitialized");
1406
1407		if ((set_single_rep_val(inst->cur_istate_rep,
1408		    (int64_t)IIS_UNINITIALIZED) == -1) ||
1409		    (set_single_rep_val(inst->next_istate_rep,
1410		    (int64_t)IIS_NONE) == -1)) {
1411			return (SCF_ERROR_NO_MEMORY);
1412		}
1413	}
1414
1415	/* update convenience states */
1416	inst->cur_istate = get_single_rep_val(inst->cur_istate_rep);
1417	inst->next_istate = get_single_rep_val(inst->next_istate_rep);
1418	return (0);
1419}
1420
1421/*
1422 * Retrieve stored process ids and register each of them so we process their
1423 * termination.
1424 */
1425static int
1426retrieve_method_pids(instance_t *inst)
1427{
1428	rep_val_t	*rv;
1429
1430	switch (retrieve_rep_vals(inst->start_pids, inst->fmri,
1431	    PR_NAME_START_PIDS)) {
1432	case 0:
1433		break;
1434	case SCF_ERROR_NOT_FOUND:
1435		return (0);
1436	default:
1437		error_msg(gettext("Failed to retrieve the start pids of "
1438		    "instance %s from repository: %s"), inst->fmri,
1439		    scf_strerror(scf_error()));
1440		return (-1);
1441	}
1442
1443	rv = uu_list_first(inst->start_pids);
1444	while (rv != NULL) {
1445		if (register_method(inst, (pid_t)rv->val, (ctid_t)-1,
1446		    IM_START) == 0) {
1447			inst->copies++;
1448			rv = uu_list_next(inst->start_pids, rv);
1449		} else if (errno == ENOENT) {
1450			pid_t pid = (pid_t)rv->val;
1451
1452			/*
1453			 * The process must have already terminated. Remove
1454			 * it from the list.
1455			 */
1456			rv = uu_list_next(inst->start_pids, rv);
1457			remove_rep_val(inst->start_pids, pid);
1458		} else {
1459			error_msg(gettext("Failed to listen for the completion "
1460			    "of %s method of instance %s"), START_METHOD_NAME,
1461			    inst->fmri);
1462			rv = uu_list_next(inst->start_pids, rv);
1463		}
1464	}
1465
1466	/* synch the repository pid list to remove any terminated pids */
1467	(void) store_rep_vals(inst->start_pids, inst->fmri, PR_NAME_START_PIDS);
1468
1469	return (0);
1470}
1471
1472/*
1473 * Remove the passed instance from inetd control.
1474 */
1475static void
1476remove_instance(instance_t *instance)
1477{
1478	switch (instance->cur_istate) {
1479	case IIS_ONLINE:
1480	case IIS_DEGRADED:
1481		/* stop listening for network connections */
1482		destroy_bound_fds(instance);
1483		break;
1484	case IIS_OFFLINE_BIND:
1485		cancel_bind_timer(instance);
1486		break;
1487	case IIS_OFFLINE_CONRATE:
1488		cancel_inst_timer(instance);
1489		break;
1490	}
1491
1492	/* stop listening for terminated methods */
1493	unregister_instance_methods(instance);
1494
1495	uu_list_remove(instance_list, instance);
1496	destroy_instance(instance);
1497}
1498
1499/*
1500 * Refresh the configuration of instance 'inst'. This method gets called as
1501 * a result of a refresh event for the instance from the master restarter, so
1502 * we can rely upon the instance's running snapshot having been updated from
1503 * its configuration snapshot.
1504 */
1505void
1506refresh_instance(instance_t *inst)
1507{
1508	instance_cfg_t	*cfg;
1509
1510	switch (inst->cur_istate) {
1511	case IIS_MAINTENANCE:
1512	case IIS_DISABLED:
1513	case IIS_UNINITIALIZED:
1514		/*
1515		 * Ignore any possible changes, we'll re-read the configuration
1516		 * automatically when we exit these states.
1517		 */
1518		break;
1519
1520	case IIS_OFFLINE_COPIES:
1521	case IIS_OFFLINE_BIND:
1522	case IIS_OFFLINE:
1523	case IIS_OFFLINE_CONRATE:
1524		destroy_instance_cfg(inst->config);
1525		if ((inst->config = read_instance_cfg(inst->fmri)) == NULL) {
1526			log_invalid_cfg(inst->fmri);
1527			if (inst->cur_istate == IIS_OFFLINE_BIND) {
1528				cancel_bind_timer(inst);
1529			} else if (inst->cur_istate == IIS_OFFLINE_CONRATE) {
1530				cancel_inst_timer(inst);
1531			}
1532			update_state(inst, IIS_MAINTENANCE, RERR_FAULT);
1533		} else {
1534			switch (inst->cur_istate) {
1535			case IIS_OFFLINE_BIND:
1536				if (copies_limit_exceeded(inst)) {
1537					/* Cancel scheduled bind retries. */
1538					cancel_bind_timer(inst);
1539
1540					/*
1541					 * Take the instance to the copies
1542					 * offline state, via the offline
1543					 * state.
1544					 */
1545					update_state(inst, IIS_OFFLINE,
1546					    RERR_RESTART);
1547					process_offline_inst(inst);
1548				}
1549				break;
1550
1551			case IIS_OFFLINE:
1552				process_offline_inst(inst);
1553				break;
1554
1555			case IIS_OFFLINE_CONRATE:
1556				/*
1557				 * Since we're already in a DOS state,
1558				 * don't bother evaluating the copies
1559				 * limit. This will be evaluated when
1560				 * we leave this state in
1561				 * process_offline_inst().
1562				 */
1563				break;
1564
1565			case IIS_OFFLINE_COPIES:
1566				/*
1567				 * Check if the copies limit has been increased
1568				 * above the current count.
1569				 */
1570				if (!copies_limit_exceeded(inst)) {
1571					update_state(inst, IIS_OFFLINE,
1572					    RERR_RESTART);
1573					process_offline_inst(inst);
1574				}
1575				break;
1576
1577			default:
1578				assert(0);
1579			}
1580		}
1581		break;
1582
1583	case IIS_DEGRADED:
1584	case IIS_ONLINE:
1585		if ((cfg = read_instance_cfg(inst->fmri)) != NULL) {
1586			instance_cfg_t *ocfg = inst->config;
1587
1588			/*
1589			 * Try to avoid the overhead of taking an instance
1590			 * offline and back on again. We do this by limiting
1591			 * this behavior to two eventualities:
1592			 * - there needs to be a re-bind to listen on behalf
1593			 *   of the instance with its new configuration. This
1594			 *   could be because for example its service has been
1595			 *   associated with a different port, or because the
1596			 *   v6only protocol option has been newly applied to
1597			 *   the instance.
1598			 * - one or both of the start or online methods of the
1599			 *   instance have changed in the new configuration.
1600			 *   Without taking the instance offline when the
1601			 *   start method changed the instance may be running
1602			 *   with unwanted parameters (or event an unwanted
1603			 *   binary); and without taking the instance offline
1604			 *   if its online method was to change, some part of
1605			 *   its running environment may have changed and would
1606			 *   not be picked up until the instance next goes
1607			 *   offline for another reason.
1608			 */
1609			if ((!bind_config_equal(ocfg->basic, cfg->basic)) ||
1610			    !method_info_equal(ocfg->methods[IM_ONLINE],
1611			    cfg->methods[IM_ONLINE]) ||
1612			    !method_info_equal(ocfg->methods[IM_START],
1613			    cfg->methods[IM_START])) {
1614				destroy_bound_fds(inst);
1615
1616				assert(inst->new_config == NULL);
1617				inst->new_config = cfg;
1618
1619				(void) run_method(inst, IM_OFFLINE, NULL);
1620			} else {	/* no bind config / method changes */
1621
1622				/*
1623				 * swap the proto list over from the old
1624				 * configuration to the new, so we retain
1625				 * our set of network fds.
1626				 */
1627				destroy_proto_list(cfg->basic);
1628				cfg->basic->proto_list =
1629				    ocfg->basic->proto_list;
1630				ocfg->basic->proto_list = NULL;
1631				destroy_instance_cfg(ocfg);
1632				inst->config = cfg;
1633
1634				/* re-evaluate copies limits based on new cfg */
1635				if (copies_limit_exceeded(inst)) {
1636					destroy_bound_fds(inst);
1637					(void) run_method(inst, IM_OFFLINE,
1638					    NULL);
1639				} else {
1640					/*
1641					 * Since the instance isn't being
1642					 * taken offline, where we assume it
1643					 * would pick-up any configuration
1644					 * changes automatically when it goes
1645					 * back online, run its refresh method
1646					 * to allow it to pick-up any changes
1647					 * whilst still online.
1648					 */
1649					(void) run_method(inst, IM_REFRESH,
1650					    NULL);
1651				}
1652			}
1653		} else {
1654			log_invalid_cfg(inst->fmri);
1655
1656			destroy_bound_fds(inst);
1657
1658			inst->maintenance_req = B_TRUE;
1659			(void) run_method(inst, IM_OFFLINE, NULL);
1660		}
1661		break;
1662
1663	default:
1664		debug_msg("Unhandled current state %d for instance in "
1665		    "refresh_instance", inst->cur_istate);
1666		assert(0);
1667	}
1668}
1669
1670/*
1671 * Called by process_restarter_event() to handle a restarter event for an
1672 * instance.
1673 */
1674static void
1675handle_restarter_event(instance_t *instance, restarter_event_type_t event,
1676    boolean_t send_ack)
1677{
1678	switch (event) {
1679	case RESTARTER_EVENT_TYPE_ADD_INSTANCE:
1680		/*
1681		 * When startd restarts, it sends _ADD_INSTANCE to delegated
1682		 * restarters for all those services managed by them. We should
1683		 * acknowledge this event, as startd's graph needs to be updated
1684		 * about the current state of the service, when startd is
1685		 * restarting.
1686		 * update_state() is ok to be called here, as commands for
1687		 * instances in transition are deferred by
1688		 * process_restarter_event().
1689		 */
1690		update_state(instance, instance->cur_istate, RERR_NONE);
1691		goto done;
1692	case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
1693		refresh_instance(instance);
1694		goto done;
1695	case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
1696		/*
1697		 * We've got a restart event, so if the instance is online
1698		 * in any way initiate taking it offline, and rely upon
1699		 * our restarter to send us an online event to bring
1700		 * it back online.
1701		 */
1702		switch (instance->cur_istate) {
1703		case IIS_ONLINE:
1704		case IIS_DEGRADED:
1705			destroy_bound_fds(instance);
1706			(void) run_method(instance, IM_OFFLINE, NULL);
1707		}
1708		goto done;
1709	case RESTARTER_EVENT_TYPE_REMOVE_INSTANCE:
1710		remove_instance(instance);
1711		goto done;
1712	case RESTARTER_EVENT_TYPE_STOP:
1713		switch (instance->cur_istate) {
1714		case IIS_OFFLINE_CONRATE:
1715		case IIS_OFFLINE_BIND:
1716		case IIS_OFFLINE_COPIES:
1717			/*
1718			 * inetd must be closing down as we wouldn't get this
1719			 * event in one of these states from the master
1720			 * restarter. Take the instance to the offline resting
1721			 * state.
1722			 */
1723			if (instance->cur_istate == IIS_OFFLINE_BIND) {
1724				cancel_bind_timer(instance);
1725			} else if (instance->cur_istate ==
1726			    IIS_OFFLINE_CONRATE) {
1727				cancel_inst_timer(instance);
1728			}
1729			update_state(instance, IIS_OFFLINE, RERR_RESTART);
1730			goto done;
1731		}
1732		break;
1733	}
1734
1735	switch (instance->cur_istate) {
1736	case IIS_OFFLINE:
1737		switch (event) {
1738		case RESTARTER_EVENT_TYPE_START:
1739			/*
1740			 * Dependencies are met, let's take the service online.
1741			 * Only try and bind for a wait type service if
1742			 * no process is running on its behalf. Otherwise, just
1743			 * mark the service online and binding will be attempted
1744			 * when the process exits.
1745			 */
1746			if (!(instance->config->basic->iswait &&
1747			    (uu_list_first(instance->start_pids) != NULL))) {
1748				create_bound_fds(instance);
1749			} else {
1750				update_state(instance, IIS_ONLINE, RERR_NONE);
1751			}
1752			break;
1753		case RESTARTER_EVENT_TYPE_DISABLE:
1754		case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1755			/*
1756			 * The instance should be disabled, so run the
1757			 * instance's disabled method that will do the work
1758			 * to take it there.
1759			 */
1760			(void) run_method(instance, IM_DISABLE, NULL);
1761			break;
1762		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1763		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1764		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1765			/*
1766			 * The master restarter has requested the instance
1767			 * go to maintenance; since we're already offline
1768			 * just update the state to the maintenance state.
1769			 */
1770			update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1771			break;
1772		}
1773		break;
1774
1775	case IIS_OFFLINE_BIND:
1776		switch (event) {
1777		case RESTARTER_EVENT_TYPE_DISABLE:
1778		case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1779			/*
1780			 * The instance should be disabled. Firstly, as for
1781			 * the above dependencies unmet comment, cancel
1782			 * the bind retry timer and update the state to
1783			 * offline. Then, run the disable method to do the
1784			 * work to take the instance from offline to
1785			 * disabled.
1786			 */
1787			cancel_bind_timer(instance);
1788			update_state(instance, IIS_OFFLINE, RERR_RESTART);
1789			(void) run_method(instance, IM_DISABLE, NULL);
1790			break;
1791		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1792		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1793		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1794			/*
1795			 * The master restarter has requested the instance
1796			 * be placed in the maintenance state. Cancel the
1797			 * outstanding retry timer, and since we're already
1798			 * offline, update the state to maintenance.
1799			 */
1800			cancel_bind_timer(instance);
1801			update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1802			break;
1803		}
1804		break;
1805
1806	case IIS_DEGRADED:
1807	case IIS_ONLINE:
1808		switch (event) {
1809		case RESTARTER_EVENT_TYPE_DISABLE:
1810		case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1811			/*
1812			 * The instance needs to be disabled. Do the same work
1813			 * as for the dependencies unmet event below to
1814			 * take the instance offline.
1815			 */
1816			destroy_bound_fds(instance);
1817			/*
1818			 * Indicate that the offline method is being run
1819			 * as part of going to the disabled state, and to
1820			 * carry on this transition.
1821			 */
1822			instance->disable_req = B_TRUE;
1823			(void) run_method(instance, IM_OFFLINE, NULL);
1824			break;
1825		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1826		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1827		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1828			/*
1829			 * The master restarter has requested the instance be
1830			 * placed in the maintenance state. This involves
1831			 * firstly taking the service offline, so do the
1832			 * same work as for the dependencies unmet event
1833			 * below. We set the maintenance_req flag to
1834			 * indicate that when we get to the offline state
1835			 * we should be placed directly into the maintenance
1836			 * state.
1837			 */
1838			instance->maintenance_req = B_TRUE;
1839			/* FALLTHROUGH */
1840		case RESTARTER_EVENT_TYPE_STOP:
1841			/*
1842			 * Dependencies have become unmet. Close and
1843			 * stop listening on the instance's network file
1844			 * descriptor, and run the offline method to do
1845			 * any work required to take us to the offline state.
1846			 */
1847			destroy_bound_fds(instance);
1848			(void) run_method(instance, IM_OFFLINE, NULL);
1849		}
1850		break;
1851
1852	case IIS_UNINITIALIZED:
1853		if (event == RESTARTER_EVENT_TYPE_DISABLE ||
1854		    event == RESTARTER_EVENT_TYPE_ADMIN_DISABLE) {
1855			update_state(instance, IIS_DISABLED, RERR_NONE);
1856			break;
1857		} else if (event != RESTARTER_EVENT_TYPE_ENABLE) {
1858			/*
1859			 * Ignore other events until we know whether we're
1860			 * enabled or not.
1861			 */
1862			break;
1863		}
1864
1865		/*
1866		 * We've got an enabled event; make use of the handling in the
1867		 * disable case.
1868		 */
1869		/* FALLTHROUGH */
1870
1871	case IIS_DISABLED:
1872		switch (event) {
1873		case RESTARTER_EVENT_TYPE_ENABLE:
1874			/*
1875			 * The instance needs enabling. Commence reading its
1876			 * configuration and if successful place the instance
1877			 * in the offline state and let process_offline_inst()
1878			 * take it from there.
1879			 */
1880			destroy_instance_cfg(instance->config);
1881			instance->config = read_instance_cfg(instance->fmri);
1882			if (instance->config != NULL) {
1883				update_state(instance, IIS_OFFLINE,
1884				    RERR_RESTART);
1885				process_offline_inst(instance);
1886			} else {
1887				log_invalid_cfg(instance->fmri);
1888				update_state(instance, IIS_MAINTENANCE,
1889				    RERR_RESTART);
1890			}
1891
1892			break;
1893		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1894		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1895		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1896			/*
1897			 * The master restarter has requested the instance be
1898			 * placed in the maintenance state, so just update its
1899			 * state to maintenance.
1900			 */
1901			update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1902			break;
1903		}
1904		break;
1905
1906	case IIS_MAINTENANCE:
1907		switch (event) {
1908		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
1909		case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1910			/*
1911			 * The master restarter has requested that the instance
1912			 * be taken out of maintenance. Read its configuration,
1913			 * and if successful place the instance in the offline
1914			 * state and call process_offline_inst() to take it
1915			 * from there.
1916			 */
1917			destroy_instance_cfg(instance->config);
1918			instance->config = read_instance_cfg(instance->fmri);
1919			if (instance->config != NULL) {
1920				update_state(instance, IIS_OFFLINE,
1921				    RERR_RESTART);
1922				process_offline_inst(instance);
1923			} else {
1924				boolean_t enabled;
1925
1926				/*
1927				 * The configuration was invalid. If the
1928				 * service has disabled requested, let's
1929				 * just place the instance in disabled even
1930				 * though we haven't been able to run its
1931				 * disable method, as the slightly incorrect
1932				 * state is likely to be less of an issue to
1933				 * an administrator than refusing to move an
1934				 * instance to disabled. If disable isn't
1935				 * requested, re-mark the service's state
1936				 * as maintenance, so the administrator can
1937				 * see the request was processed.
1938				 */
1939				if ((read_enable_merged(instance->fmri,
1940				    &enabled) == 0) && !enabled) {
1941					update_state(instance, IIS_DISABLED,
1942					    RERR_RESTART);
1943				} else {
1944					log_invalid_cfg(instance->fmri);
1945					update_state(instance, IIS_MAINTENANCE,
1946					    RERR_FAULT);
1947				}
1948			}
1949			break;
1950		}
1951		break;
1952
1953	case IIS_OFFLINE_CONRATE:
1954		switch (event) {
1955		case RESTARTER_EVENT_TYPE_DISABLE:
1956			/*
1957			 * The instance wants disabling. Take the instance
1958			 * offline as for the dependencies unmet event above,
1959			 * and then from there run the disable method to do
1960			 * the work to take the instance to the disabled state.
1961			 */
1962			cancel_inst_timer(instance);
1963			update_state(instance, IIS_OFFLINE, RERR_RESTART);
1964			(void) run_method(instance, IM_DISABLE, NULL);
1965			break;
1966		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1967		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1968		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1969			/*
1970			 * The master restarter has requested the instance
1971			 * be taken to maintenance. Cancel the timer setup
1972			 * when we entered this state, and go directly to
1973			 * maintenance.
1974			 */
1975			cancel_inst_timer(instance);
1976			update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1977			break;
1978		}
1979		break;
1980
1981	case IIS_OFFLINE_COPIES:
1982		switch (event) {
1983		case RESTARTER_EVENT_TYPE_DISABLE:
1984			/*
1985			 * The instance wants disabling. Update the state
1986			 * to offline, and run the disable method to do the
1987			 * work to take it to the disabled state.
1988			 */
1989			update_state(instance, IIS_OFFLINE, RERR_RESTART);
1990			(void) run_method(instance, IM_DISABLE, NULL);
1991			break;
1992		case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1993		case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1994		case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1995			/*
1996			 * The master restarter has requested the instance be
1997			 * placed in maintenance. Since it's already offline
1998			 * simply update the state.
1999			 */
2000			update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
2001			break;
2002		}
2003		break;
2004
2005	default:
2006		debug_msg("handle_restarter_event: instance in an "
2007		    "unexpected state");
2008		assert(0);
2009	}
2010
2011done:
2012	if (send_ack)
2013		ack_restarter_event(B_TRUE);
2014}
2015
2016/*
2017 * Tries to read and process an event from the event pipe. If there isn't one
2018 * or an error occurred processing the event it returns -1. Else, if the event
2019 * is for an instance we're not already managing we read its state, add it to
2020 * our list to manage, and if appropriate read its configuration. Whether it's
2021 * new to us or not, we then handle the specific event.
2022 * Returns 0 if an event was read and processed successfully, else -1.
2023 */
2024static int
2025process_restarter_event(void)
2026{
2027	char			*fmri;
2028	size_t			fmri_size;
2029	restarter_event_type_t  event_type;
2030	instance_t		*instance;
2031	restarter_event_t	*event;
2032	ssize_t			sz;
2033
2034	/*
2035	 * Try to read an event pointer from the event pipe.
2036	 */
2037	errno = 0;
2038	switch (safe_read(rst_event_pipe[PE_CONSUMER], &event,
2039	    sizeof (event))) {
2040	case 0:
2041		break;
2042	case  1:
2043		if (errno == EAGAIN)	/* no event to read */
2044			return (-1);
2045
2046		/* other end of pipe closed */
2047
2048		/* FALLTHROUGH */
2049	default:			/* unexpected read error */
2050		/*
2051		 * There's something wrong with the event pipe. Let's
2052		 * shutdown and be restarted.
2053		 */
2054		inetd_stop();
2055		return (-1);
2056	}
2057
2058	/*
2059	 * Check if we're currently managing the instance which the event
2060	 * pertains to. If not, read its complete state and add it to our
2061	 * list to manage.
2062	 */
2063
2064	fmri_size = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
2065	if ((fmri = malloc(fmri_size)) == NULL) {
2066		error_msg(strerror(errno));
2067		goto fail;
2068	}
2069	sz = restarter_event_get_instance(event, fmri, fmri_size);
2070	if (sz >= fmri_size)
2071		assert(0);
2072
2073	for (instance = uu_list_first(instance_list); instance != NULL;
2074	    instance = uu_list_next(instance_list, instance)) {
2075		if (strcmp(instance->fmri, fmri) == 0)
2076			break;
2077	}
2078
2079	if (instance == NULL) {
2080		int err;
2081
2082		debug_msg("New instance to manage: %s", fmri);
2083
2084		if (((instance = create_instance(fmri)) == NULL) ||
2085		    (retrieve_instance_state(instance) != 0) ||
2086		    (retrieve_method_pids(instance) != 0)) {
2087			destroy_instance(instance);
2088			free(fmri);
2089			goto fail;
2090		}
2091
2092		if (((err = iterate_repository_contracts(instance, 0))
2093		    != 0) && (err != ENOENT)) {
2094			error_msg(gettext(
2095			    "Failed to adopt contracts of instance %s: %s"),
2096			    instance->fmri, strerror(err));
2097			destroy_instance(instance);
2098			free(fmri);
2099			goto fail;
2100		}
2101
2102		uu_list_node_init(instance, &instance->link, instance_pool);
2103		(void) uu_list_insert_after(instance_list, NULL, instance);
2104
2105		/*
2106		 * Only read configuration for instances that aren't in any of
2107		 * the disabled, maintenance or uninitialized states, since
2108		 * they'll read it on state exit.
2109		 */
2110		if ((instance->cur_istate != IIS_DISABLED) &&
2111		    (instance->cur_istate != IIS_MAINTENANCE) &&
2112		    (instance->cur_istate != IIS_UNINITIALIZED)) {
2113			instance->config = read_instance_cfg(instance->fmri);
2114			if (instance->config == NULL) {
2115				log_invalid_cfg(instance->fmri);
2116				update_state(instance, IIS_MAINTENANCE,
2117				    RERR_FAULT);
2118			}
2119		}
2120	}
2121
2122	free(fmri);
2123
2124	event_type = restarter_event_get_type(event);
2125	debug_msg("Event type: %d for instance: %s", event_type,
2126	    instance->fmri);
2127
2128	/*
2129	 * If the instance is currently running a method, don't process the
2130	 * event now, but attach it to the instance for processing when
2131	 * the instance finishes its transition.
2132	 */
2133	if (INST_IN_TRANSITION(instance)) {
2134		debug_msg("storing event %d for instance %s", event_type,
2135		    instance->fmri);
2136		instance->pending_rst_event = event_type;
2137	} else {
2138		handle_restarter_event(instance, event_type, B_TRUE);
2139	}
2140
2141	return (0);
2142
2143fail:
2144	ack_restarter_event(B_FALSE);
2145	return (-1);
2146}
2147
2148/*
2149 * Do the state machine processing associated with the termination of instance
2150 * 'inst''s start method.
2151 */
2152void
2153process_start_term(instance_t *inst)
2154{
2155	basic_cfg_t	*cfg;
2156
2157	inst->copies--;
2158
2159	if ((inst->cur_istate == IIS_MAINTENANCE) ||
2160	    (inst->cur_istate == IIS_DISABLED)) {
2161		/* do any further processing/checks when we exit these states */
2162		return;
2163	}
2164
2165	cfg = inst->config->basic;
2166
2167	if (cfg->iswait) {
2168		proto_info_t	*pi;
2169
2170		switch (inst->cur_istate) {
2171		case IIS_ONLINE:
2172		case IIS_DEGRADED:
2173		case IIS_IN_REFRESH_METHOD:
2174			/*
2175			 * A wait type service's start method has exited.
2176			 * Check if the method was fired off in this inetd's
2177			 * lifetime, or a previous one; if the former,
2178			 * re-commence listening on the service's behalf; if
2179			 * the latter, mark the service offline and let bind
2180			 * attempts commence.
2181			 */
2182			for (pi = uu_list_first(cfg->proto_list); pi != NULL;
2183			    pi = uu_list_next(cfg->proto_list, pi)) {
2184				/*
2185				 * If a bound fd exists, the method was fired
2186				 * off during this inetd's lifetime.
2187				 */
2188				if (pi->listen_fd != -1)
2189					break;
2190			}
2191			if (pi != NULL) {
2192				if (poll_bound_fds(inst, B_TRUE) != 0)
2193					handle_bind_failure(inst);
2194			} else {
2195				update_state(inst, IIS_OFFLINE, RERR_RESTART);
2196				create_bound_fds(inst);
2197			}
2198		}
2199	} else {
2200		/*
2201		 * Check if a nowait service should be brought back online
2202		 * after exceeding its copies limit.
2203		 */
2204		if ((inst->cur_istate == IIS_OFFLINE_COPIES) &&
2205		    !copies_limit_exceeded(inst)) {
2206			update_state(inst, IIS_OFFLINE, RERR_NONE);
2207			process_offline_inst(inst);
2208		}
2209	}
2210}
2211
2212/*
2213 * If the instance has a pending event process it and initiate the
2214 * acknowledgement.
2215 */
2216static void
2217process_pending_rst_event(instance_t *inst)
2218{
2219	if (inst->pending_rst_event != RESTARTER_EVENT_TYPE_INVALID) {
2220		restarter_event_type_t re;
2221
2222		debug_msg("Injecting pending event %d for instance %s",
2223		    inst->pending_rst_event, inst->fmri);
2224		re = inst->pending_rst_event;
2225		inst->pending_rst_event = RESTARTER_EVENT_TYPE_INVALID;
2226		handle_restarter_event(inst, re, B_TRUE);
2227	}
2228}
2229
2230/*
2231 * Do the state machine processing associated with the termination
2232 * of the specified instance's non-start method with the specified status.
2233 * Once the processing of the termination is done, the function also picks up
2234 * any processing that was blocked on the method running.
2235 */
2236void
2237process_non_start_term(instance_t *inst, int status)
2238{
2239	boolean_t ran_online_method = B_FALSE;
2240
2241	if (status == IMRET_FAILURE) {
2242		error_msg(gettext("The %s method of instance %s failed, "
2243		    "transitioning to maintenance"),
2244		    methods[states[inst->cur_istate].method_running].name,
2245		    inst->fmri);
2246
2247		if ((inst->cur_istate == IIS_IN_ONLINE_METHOD) ||
2248		    (inst->cur_istate == IIS_IN_REFRESH_METHOD))
2249			destroy_bound_fds(inst);
2250
2251		update_state(inst, IIS_MAINTENANCE, RERR_FAULT);
2252
2253		inst->maintenance_req = B_FALSE;
2254		inst->conn_rate_exceeded = B_FALSE;
2255
2256		if (inst->new_config != NULL) {
2257			destroy_instance_cfg(inst->new_config);
2258			inst->new_config = NULL;
2259		}
2260
2261		if (!inetd_stopping)
2262			process_pending_rst_event(inst);
2263
2264		return;
2265	}
2266
2267	/* non-failure method return */
2268
2269	if (status != IMRET_SUCCESS) {
2270		/*
2271		 * An instance method never returned a supported return code.
2272		 * We'll assume this means the method succeeded for now whilst
2273		 * non-GL-cognizant methods are used - eg. pkill.
2274		 */
2275		debug_msg("The %s method of instance %s returned "
2276		    "non-compliant exit code: %d, assuming success",
2277		    methods[states[inst->cur_istate].method_running].name,
2278		    inst->fmri, status);
2279	}
2280
2281	/*
2282	 * Update the state from the in-transition state.
2283	 */
2284	switch (inst->cur_istate) {
2285	case IIS_IN_ONLINE_METHOD:
2286		ran_online_method = B_TRUE;
2287		/* FALLTHROUGH */
2288	case IIS_IN_REFRESH_METHOD:
2289		/*
2290		 * If we've exhausted the bind retries, flag that by setting
2291		 * the instance's state to degraded.
2292		 */
2293		if (inst->bind_retries_exceeded) {
2294			update_state(inst, IIS_DEGRADED, RERR_NONE);
2295			break;
2296		}
2297		/* FALLTHROUGH */
2298	default:
2299		update_state(inst,
2300		    methods[states[inst->cur_istate].method_running].dst_state,
2301		    RERR_NONE);
2302	}
2303
2304	if (inst->cur_istate == IIS_OFFLINE) {
2305		if (inst->new_config != NULL) {
2306			/*
2307			 * This instance was found during refresh to need
2308			 * taking offline because its newly read configuration
2309			 * was sufficiently different. Now we're offline,
2310			 * activate this new configuration.
2311			 */
2312			destroy_instance_cfg(inst->config);
2313			inst->config = inst->new_config;
2314			inst->new_config = NULL;
2315		}
2316
2317		/* continue/complete any transitions that are in progress */
2318		process_offline_inst(inst);
2319
2320	} else if (ran_online_method) {
2321		/*
2322		 * We've just successfully executed the online method. We have
2323		 * a set of bound network fds that were created before running
2324		 * this method, so now we're online start listening for
2325		 * connections on them.
2326		 */
2327		if (poll_bound_fds(inst, B_TRUE) != 0)
2328			handle_bind_failure(inst);
2329	}
2330
2331	/*
2332	 * If we're now out of transition (process_offline_inst() could have
2333	 * fired off another method), carry out any jobs that were blocked by
2334	 * us being in transition.
2335	 */
2336	if (!INST_IN_TRANSITION(inst)) {
2337		if (inetd_stopping) {
2338			if (!instance_stopped(inst)) {
2339				/*
2340				 * inetd is stopping, and this instance hasn't
2341				 * been stopped. Inject a stop event.
2342				 */
2343				handle_restarter_event(inst,
2344				    RESTARTER_EVENT_TYPE_STOP, B_FALSE);
2345			}
2346		} else {
2347			process_pending_rst_event(inst);
2348		}
2349	}
2350}
2351
2352/*
2353 * Check if configuration file specified is readable. If not return B_FALSE,
2354 * else return B_TRUE.
2355 */
2356static boolean_t
2357can_read_file(const char *path)
2358{
2359	int	ret;
2360	int	serrno;
2361
2362	do {
2363		ret = access(path, R_OK);
2364	} while ((ret < 0) && (errno == EINTR));
2365	if (ret < 0) {
2366		if (errno != ENOENT) {
2367			serrno = errno;
2368			error_msg(gettext("Failed to access configuration "
2369			    "file %s for performing modification checks: %s"),
2370			    path, strerror(errno));
2371			errno = serrno;
2372		}
2373		return (B_FALSE);
2374	}
2375	return (B_TRUE);
2376}
2377
2378/*
2379 * Check whether the configuration file has changed contents since inetd
2380 * was last started/refreshed, and if so, log a message indicating that
2381 * inetconv needs to be run.
2382 */
2383static void
2384check_conf_file(void)
2385{
2386	char		*new_hash;
2387	char		*old_hash = NULL;
2388	scf_error_t	ret;
2389	const char	*file;
2390
2391	if (conf_file == NULL) {
2392		/*
2393		 * No explicit config file specified, so see if one of the
2394		 * default two are readable, checking the primary one first
2395		 * followed by the secondary.
2396		 */
2397		if (can_read_file(PRIMARY_DEFAULT_CONF_FILE)) {
2398			file = PRIMARY_DEFAULT_CONF_FILE;
2399		} else if ((errno == ENOENT) &&
2400		    can_read_file(SECONDARY_DEFAULT_CONF_FILE)) {
2401			file = SECONDARY_DEFAULT_CONF_FILE;
2402		} else {
2403			return;
2404		}
2405	} else {
2406		file = conf_file;
2407		if (!can_read_file(file))
2408			return;
2409	}
2410
2411	if (calculate_hash(file, &new_hash) == 0) {
2412		ret = retrieve_inetd_hash(&old_hash);
2413		if (((ret == SCF_ERROR_NONE) &&
2414		    (strcmp(old_hash, new_hash) != 0))) {
2415			/* modified config file */
2416			warn_msg(gettext(
2417			    "Configuration file %s has been modified since "
2418			    "inetconv was last run. \"inetconv -i %s\" must be "
2419			    "run to apply any changes to the SMF"), file, file);
2420		} else if ((ret != SCF_ERROR_NOT_FOUND) &&
2421		    (ret != SCF_ERROR_NONE)) {
2422			/* No message if hash not yet computed */
2423			error_msg(gettext("Failed to check whether "
2424			    "configuration file %s has been modified: %s"),
2425			    file, scf_strerror(ret));
2426		}
2427		free(old_hash);
2428		free(new_hash);
2429	} else {
2430		error_msg(gettext("Failed to check whether configuration file "
2431		    "%s has been modified: %s"), file, strerror(errno));
2432	}
2433}
2434
2435/*
2436 * Refresh all inetd's managed instances and check the configuration file
2437 * for any updates since inetconv was last run, logging a message if there
2438 * are. We call the SMF refresh function to refresh each instance so that
2439 * the refresh request goes through the framework, and thus results in the
2440 * running snapshot of each instance being updated from the configuration
2441 * snapshot.
2442 */
2443static void
2444inetd_refresh(void)
2445{
2446	instance_t	*inst;
2447
2448	refresh_debug_flag();
2449
2450	/* call libscf to send refresh requests for all managed instances */
2451	for (inst = uu_list_first(instance_list); inst != NULL;
2452	    inst = uu_list_next(instance_list, inst)) {
2453		if (smf_refresh_instance(inst->fmri) < 0) {
2454			error_msg(gettext("Failed to refresh instance %s: %s"),
2455			    inst->fmri, scf_strerror(scf_error()));
2456		}
2457	}
2458
2459	/*
2460	 * Log a message if the configuration file has changed since inetconv
2461	 * was last run.
2462	 */
2463	check_conf_file();
2464}
2465
2466/*
2467 * Initiate inetd's shutdown.
2468 */
2469static void
2470inetd_stop(void)
2471{
2472	instance_t *inst;
2473
2474	/* Block handling signals for stop and refresh */
2475	(void) sighold(SIGHUP);
2476	(void) sighold(SIGTERM);
2477
2478	/* Indicate inetd is coming down */
2479	inetd_stopping = B_TRUE;
2480
2481	/* Stop polling on restarter events. */
2482	clear_pollfd(rst_event_pipe[PE_CONSUMER]);
2483
2484	/* Stop polling for any more stop/refresh requests. */
2485	clear_pollfd(uds_fd);
2486
2487	/*
2488	 * Send a stop event to all currently unstopped instances that
2489	 * aren't in transition. For those that are in transition, the
2490	 * event will get sent when the transition completes.
2491	 */
2492	for (inst = uu_list_first(instance_list); inst != NULL;
2493	    inst = uu_list_next(instance_list, inst)) {
2494		if (!instance_stopped(inst) && !INST_IN_TRANSITION(inst))
2495			handle_restarter_event(inst,
2496			    RESTARTER_EVENT_TYPE_STOP, B_FALSE);
2497	}
2498}
2499
2500/*
2501 * Sets up the intra-inetd-process Unix Domain Socket.
2502 * Returns -1 on error, else 0.
2503 */
2504static int
2505uds_init(void)
2506{
2507	struct sockaddr_un addr;
2508
2509	if ((uds_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
2510		error_msg("socket: %s", strerror(errno));
2511		return (-1);
2512	}
2513
2514	disable_blocking(uds_fd);
2515
2516	(void) unlink(INETD_UDS_PATH);  /* clean-up any stale files */
2517
2518	(void) memset(&addr, 0, sizeof (addr));
2519	addr.sun_family = AF_UNIX;
2520	/* CONSTCOND */
2521	assert(sizeof (INETD_UDS_PATH) <= sizeof (addr.sun_path));
2522	(void) strlcpy(addr.sun_path, INETD_UDS_PATH, sizeof (addr.sun_path));
2523
2524	if (bind(uds_fd, (struct sockaddr *)(&addr), sizeof (addr)) < 0) {
2525		error_msg(gettext("Failed to bind socket to %s: %s"),
2526		    INETD_UDS_PATH, strerror(errno));
2527		(void) close(uds_fd);
2528		return (-1);
2529	}
2530
2531	(void) listen(uds_fd, UDS_BACKLOG);
2532
2533	if ((set_pollfd(uds_fd, POLLIN)) == -1) {
2534		(void) close(uds_fd);
2535		(void) unlink(INETD_UDS_PATH);
2536		return (-1);
2537	}
2538
2539	return (0);
2540}
2541
2542static void
2543uds_fini(void)
2544{
2545	if (uds_fd != -1)
2546		(void) close(uds_fd);
2547	(void) unlink(INETD_UDS_PATH);
2548}
2549
2550/*
2551 * Handle an incoming request on the Unix Domain Socket. Returns -1 if there
2552 * was an error handling the event, else 0.
2553 */
2554static int
2555process_uds_event(void)
2556{
2557	uds_request_t		req;
2558	int			fd;
2559	struct sockaddr_un	addr;
2560	socklen_t		len = sizeof (addr);
2561	int			ret;
2562	uint_t			retries = 0;
2563	ucred_t			*ucred = NULL;
2564	uid_t			euid;
2565
2566	do {
2567		fd = accept(uds_fd, (struct sockaddr *)&addr, &len);
2568	} while ((fd < 0) && (errno == EINTR));
2569	if (fd < 0) {
2570		if (errno != EWOULDBLOCK)
2571			error_msg("accept failed: %s", strerror(errno));
2572		return (-1);
2573	}
2574
2575	if (getpeerucred(fd, &ucred) == -1) {
2576		error_msg("getpeerucred failed: %s", strerror(errno));
2577		(void) close(fd);
2578		return (-1);
2579	}
2580
2581	/* Check peer credentials before acting on the request */
2582	euid = ucred_geteuid(ucred);
2583	ucred_free(ucred);
2584	if (euid != 0 && getuid() != euid) {
2585		debug_msg("peer euid %u != uid %u",
2586		    (uint_t)euid, (uint_t)getuid());
2587		(void) close(fd);
2588		return (-1);
2589	}
2590
2591	for (retries = 0; retries < UDS_RECV_RETRIES; retries++) {
2592		if (((ret = safe_read(fd, &req, sizeof (req))) != 1) ||
2593		    (errno != EAGAIN))
2594			break;
2595
2596		(void) poll(NULL, 0, 100);	/* 100ms pause */
2597	}
2598
2599	if (ret != 0) {
2600		error_msg(gettext("Failed read: %s"), strerror(errno));
2601		(void) close(fd);
2602		return (-1);
2603	}
2604
2605	switch (req) {
2606	case UR_REFRESH_INETD:
2607		/* flag the request for event_loop() to process */
2608		refresh_inetd_requested = B_TRUE;
2609		(void) close(fd);
2610		break;
2611	case UR_STOP_INETD:
2612		inetd_stop();
2613		break;
2614	default:
2615		error_msg("unexpected UDS request");
2616		(void) close(fd);
2617		return (-1);
2618	}
2619
2620	return (0);
2621}
2622
2623/*
2624 * Perform checks for common exec string errors. We limit the checks to
2625 * whether the file exists, is a regular file, and has at least one execute
2626 * bit set. We leave the core security checks to exec() so as not to duplicate
2627 * and thus incur the associated drawbacks, but hope to catch the common
2628 * errors here.
2629 */
2630static boolean_t
2631passes_basic_exec_checks(const char *instance, const char *method,
2632    const char *path)
2633{
2634	struct stat	sbuf;
2635
2636	/* check the file exists */
2637	while (stat(path, &sbuf) == -1) {
2638		if (errno != EINTR) {
2639			error_msg(gettext(
2640			    "Can't stat the %s method of instance %s: %s"),
2641			    method, instance, strerror(errno));
2642			return (B_FALSE);
2643		}
2644	}
2645
2646	/*
2647	 * Check if the file is a regular file and has at least one execute
2648	 * bit set.
2649	 */
2650	if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
2651		error_msg(gettext(
2652		    "The %s method of instance %s isn't a regular file"),
2653		    method, instance);
2654		return (B_FALSE);
2655	} else if ((sbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) == 0) {
2656		error_msg(gettext("The %s method instance %s doesn't have "
2657		    "any execute permissions set"), method, instance);
2658		return (B_FALSE);
2659	}
2660
2661	return (B_TRUE);
2662}
2663
2664static void
2665exec_method(instance_t *instance, instance_method_t method, method_info_t *mi,
2666    struct method_context *mthd_ctxt, const proto_info_t *pi)
2667{
2668	char		**args;
2669	char 		**env;
2670	const char	*errf;
2671	int		serrno;
2672	basic_cfg_t	*cfg = instance->config->basic;
2673
2674	if (method == IM_START) {
2675		/*
2676		 * If wrappers checks fail, pretend the method was exec'd and
2677		 * failed.
2678		 */
2679		if (!tcp_wrappers_ok(instance))
2680			exit(IMRET_FAILURE);
2681	}
2682
2683	/*
2684	 * Revert the disposition of handled signals and ignored signals to
2685	 * their defaults, unblocking any blocked ones as a side effect.
2686	 */
2687	(void) sigset(SIGHUP, SIG_DFL);
2688	(void) sigset(SIGTERM, SIG_DFL);
2689	(void) sigset(SIGINT, SIG_DFL);
2690
2691	/*
2692	 * Setup exec arguments. Do this before the fd setup below, so our
2693	 * logging related file fd doesn't get taken over before we call
2694	 * expand_address().
2695	 */
2696	if ((method == IM_START) &&
2697	    (strcmp(mi->exec_args_we.we_wordv[0], "%A") == 0)) {
2698		args = expand_address(instance, pi);
2699	} else {
2700		args = mi->exec_args_we.we_wordv;
2701	}
2702
2703	/* Generate audit trail for start operations */
2704	if (method == IM_START) {
2705		adt_event_data_t *ae;
2706		struct sockaddr_storage ss;
2707		priv_set_t *privset;
2708		socklen_t sslen = sizeof (ss);
2709
2710		if ((ae = adt_alloc_event(audit_handle, ADT_inetd_connect))
2711		    == NULL) {
2712			error_msg(gettext("Unable to allocate audit event for "
2713			    "the %s method of instance %s"),
2714			    methods[method].name, instance->fmri);
2715			exit(IMRET_FAILURE);
2716		}
2717
2718		/*
2719		 * The inetd_connect audit record consists of:
2720		 *	Service name
2721		 *	Execution path
2722		 *	Remote address and port
2723		 *	Local port
2724		 *	Process privileges
2725		 */
2726		ae->adt_inetd_connect.service_name = cfg->svc_name;
2727		ae->adt_inetd_connect.cmd = mi->exec_path;
2728
2729		if (instance->remote_addr.ss_family == AF_INET) {
2730			struct in_addr *in = SS_SINADDR(instance->remote_addr);
2731			ae->adt_inetd_connect.ip_adr[0] = in->s_addr;
2732			ae->adt_inetd_connect.ip_type = ADT_IPv4;
2733		} else {
2734			uint32_t *addr6;
2735			int i;
2736
2737			ae->adt_inetd_connect.ip_type = ADT_IPv6;
2738			addr6 = (uint32_t *)SS_SINADDR(instance->remote_addr);
2739			for (i = 0; i < 4; ++i)
2740				ae->adt_inetd_connect.ip_adr[i] = addr6[i];
2741		}
2742
2743		ae->adt_inetd_connect.ip_remote_port =
2744		    ntohs(SS_PORT(instance->remote_addr));
2745
2746		if (getsockname(instance->conn_fd, (struct sockaddr *)&ss,
2747		    &sslen) == 0)
2748			ae->adt_inetd_connect.ip_local_port =
2749			    ntohs(SS_PORT(ss));
2750
2751		privset = mthd_ctxt->priv_set;
2752		if (privset == NULL) {
2753			privset = priv_allocset();
2754			if (privset != NULL &&
2755			    getppriv(PRIV_EFFECTIVE, privset) != 0) {
2756				priv_freeset(privset);
2757				privset = NULL;
2758			}
2759		}
2760
2761		ae->adt_inetd_connect.privileges = privset;
2762
2763		(void) adt_put_event(ae, ADT_SUCCESS, ADT_SUCCESS);
2764		adt_free_event(ae);
2765
2766		if (privset != NULL && mthd_ctxt->priv_set == NULL)
2767			priv_freeset(privset);
2768	}
2769
2770	/*
2771	 * Set method context before the fd setup below so we can output an
2772	 * error message if it fails.
2773	 */
2774	if ((errno = restarter_set_method_context(mthd_ctxt, &errf)) != 0) {
2775		const char *msg;
2776
2777		if (errno == -1) {
2778			if (strcmp(errf, "core_set_process_path") == 0) {
2779				msg = gettext("Failed to set the corefile path "
2780				    "for the %s method of instance %s");
2781			} else if (strcmp(errf, "setproject") == 0) {
2782				msg = gettext("Failed to assign a resource "
2783				    "control for the %s method of instance %s");
2784			} else if (strcmp(errf, "pool_set_binding") == 0) {
2785				msg = gettext("Failed to bind the %s method of "
2786				    "instance %s to a pool due to a system "
2787				    "error");
2788			} else {
2789				assert(0);
2790				abort();
2791			}
2792
2793			error_msg(msg, methods[method].name, instance->fmri);
2794
2795			exit(IMRET_FAILURE);
2796		}
2797
2798		if (errf != NULL && strcmp(errf, "pool_set_binding") == 0) {
2799			switch (errno) {
2800			case ENOENT:
2801				msg = gettext("Failed to find resource pool "
2802				    "for the %s method of instance %s");
2803				break;
2804
2805			case EBADF:
2806				msg = gettext("Failed to bind the %s method of "
2807				    "instance %s to a pool due to invalid "
2808				    "configuration");
2809				break;
2810
2811			case EINVAL:
2812				msg = gettext("Failed to bind the %s method of "
2813				    "instance %s to a pool due to invalid "
2814				    "pool name");
2815				break;
2816
2817			default:
2818				assert(0);
2819				abort();
2820			}
2821
2822			exit(IMRET_FAILURE);
2823		}
2824
2825		if (errf != NULL) {
2826			error_msg(gettext("Failed to set credentials for the "
2827			    "%s method of instance %s (%s: %s)"),
2828			    methods[method].name, instance->fmri, errf,
2829			    strerror(errno));
2830			exit(IMRET_FAILURE);
2831		}
2832
2833		switch (errno) {
2834		case ENOMEM:
2835			msg = gettext("Failed to set credentials for the %s "
2836			    "method of instance %s (out of memory)");
2837			break;
2838
2839		case ENOENT:
2840			msg = gettext("Failed to set credentials for the %s "
2841			    "method of instance %s (no passwd or shadow "
2842			    "entry for user)");
2843			break;
2844
2845		default:
2846			assert(0);
2847			abort();
2848		}
2849
2850		error_msg(msg, methods[method].name, instance->fmri);
2851		exit(IMRET_FAILURE);
2852	}
2853
2854	/* let exec() free mthd_ctxt */
2855
2856	/* setup standard fds */
2857	if (method == IM_START) {
2858		(void) dup2(instance->conn_fd, STDIN_FILENO);
2859	} else {
2860		(void) close(STDIN_FILENO);
2861		(void) open("/dev/null", O_RDONLY);
2862	}
2863	(void) dup2(STDIN_FILENO, STDOUT_FILENO);
2864	(void) dup2(STDIN_FILENO, STDERR_FILENO);
2865
2866	closefrom(STDERR_FILENO + 1);
2867
2868	method_preexec();
2869
2870	env = set_smf_env(mthd_ctxt, instance, methods[method].name);
2871
2872	if (env != NULL) {
2873		do {
2874			(void) execve(mi->exec_path, args, env);
2875		} while (errno == EINTR);
2876	}
2877
2878	serrno = errno;
2879	/* start up logging again to report the error */
2880	msg_init();
2881	errno = serrno;
2882
2883	error_msg(
2884	    gettext("Failed to exec %s method of instance %s: %s"),
2885	    methods[method].name, instance->fmri, strerror(errno));
2886
2887	if ((method == IM_START) && (instance->config->basic->iswait)) {
2888		/*
2889		 * We couldn't exec the start method for a wait type service.
2890		 * Eat up data from the endpoint, so that hopefully the
2891		 * service's fd won't wake poll up on the next time round
2892		 * event_loop(). This behavior is carried over from the old
2893		 * inetd, and it seems somewhat arbitrary that it isn't
2894		 * also done in the case of fork failures; but I guess
2895		 * it assumes an exec failure is less likely to be the result
2896		 * of a resource shortage, and is thus not worth retrying.
2897		 */
2898		consume_wait_data(instance, 0);
2899	}
2900
2901	exit(IMRET_FAILURE);
2902}
2903
2904static restarter_error_t
2905get_method_error_success(instance_method_t method)
2906{
2907	switch (method) {
2908	case IM_OFFLINE:
2909		return (RERR_RESTART);
2910	case IM_ONLINE:
2911		return (RERR_RESTART);
2912	case IM_DISABLE:
2913		return (RERR_RESTART);
2914	case IM_REFRESH:
2915		return (RERR_REFRESH);
2916	case IM_START:
2917		return (RERR_RESTART);
2918	}
2919	(void) fprintf(stderr, gettext("Internal fatal error in inetd.\n"));
2920
2921	abort();
2922	/* NOTREACHED */
2923}
2924
2925static int
2926smf_kill_process(instance_t *instance, int sig)
2927{
2928	rep_val_t	*rv;
2929	int		ret = IMRET_SUCCESS;
2930
2931	/* Carry out process assassination */
2932	for (rv = uu_list_first(instance->start_pids);
2933	    rv != NULL;
2934	    rv = uu_list_next(instance->start_pids, rv)) {
2935		if ((kill((pid_t)rv->val, sig) != 0) &&
2936		    (errno != ESRCH)) {
2937			ret = IMRET_FAILURE;
2938			error_msg(gettext("Unable to kill "
2939			    "start process (%ld) of instance %s: %s"),
2940			    rv->val, instance->fmri, strerror(errno));
2941		}
2942	}
2943	return (ret);
2944}
2945
2946/*
2947 * Runs the specified method of the specified service instance.
2948 * If the method was never specified, we handle it the same as if the
2949 * method was called and returned success, carrying on any transition the
2950 * instance may be in the midst of.
2951 * If the method isn't executable in its specified profile or an error occurs
2952 * forking a process to run the method in the function returns -1.
2953 * If a method binary is successfully executed, the function switches the
2954 * instance's cur state to the method's associated 'run' state and the next
2955 * state to the methods associated next state.
2956 * Returns -1 if there's an error before forking, else 0.
2957 */
2958int
2959run_method(instance_t *instance, instance_method_t method,
2960    const proto_info_t *start_info)
2961{
2962	pid_t			child_pid;
2963	method_info_t		*mi;
2964	struct method_context	*mthd_ctxt = NULL;
2965	const char		*errstr;
2966	int			sig = 0;
2967	int			ret;
2968	instance_cfg_t		*cfg = instance->config;
2969	ctid_t			cid;
2970	boolean_t		trans_failure = B_TRUE;
2971	int			serrno;
2972
2973	/*
2974	 * Don't bother updating the instance's state for the start method
2975	 * as there isn't a separate start method state.
2976	 */
2977	if (method != IM_START)
2978		update_instance_states(instance, get_method_state(method),
2979		    methods[method].dst_state,
2980		    get_method_error_success(method));
2981
2982	if ((mi = cfg->methods[method]) == NULL) {
2983		/*
2984		 * If the absent method is IM_OFFLINE, default action needs
2985		 * to be taken to avoid lingering processes which can prevent
2986		 * the upcoming rebinding from happening.
2987		 */
2988		if ((method == IM_OFFLINE) && instance->config->basic->iswait) {
2989			warn_msg(gettext("inetd_offline method for instance %s "
2990			    "is unspecified.  Taking default action: kill."),
2991			    instance->fmri);
2992			(void) str2sig("TERM", &sig);
2993			ret = smf_kill_process(instance, sig);
2994			process_non_start_term(instance, ret);
2995			return (0);
2996		} else {
2997			process_non_start_term(instance, IMRET_SUCCESS);
2998			return (0);
2999		}
3000	}
3001
3002	/* Handle special method tokens, not allowed on start */
3003	if (method != IM_START) {
3004		if (restarter_is_null_method(mi->exec_path)) {
3005			/* :true means nothing should be done */
3006			process_non_start_term(instance, IMRET_SUCCESS);
3007			return (0);
3008		}
3009
3010		if ((sig = restarter_is_kill_method(mi->exec_path)) >= 0) {
3011			/* Carry out contract assassination */
3012			ret = iterate_repository_contracts(instance, sig);
3013			/* ENOENT means we didn't find any contracts */
3014			if (ret != 0 && ret != ENOENT) {
3015				error_msg(gettext("Failed to send signal %d "
3016				    "to contracts of instance %s: %s"), sig,
3017				    instance->fmri, strerror(ret));
3018				goto prefork_failure;
3019			} else {
3020				process_non_start_term(instance, IMRET_SUCCESS);
3021				return (0);
3022			}
3023		}
3024
3025		if ((sig = restarter_is_kill_proc_method(mi->exec_path)) >= 0) {
3026			ret = smf_kill_process(instance, sig);
3027			process_non_start_term(instance, ret);
3028			return (0);
3029		}
3030	}
3031
3032	/*
3033	 * Get the associated method context before the fork so we can
3034	 * modify the instances state if things go wrong.
3035	 */
3036	if ((mthd_ctxt = read_method_context(instance->fmri,
3037	    methods[method].name, mi->exec_path, &errstr)) == NULL) {
3038		error_msg(gettext("Failed to retrieve method context for the "
3039		    "%s method of instance %s: %s"), methods[method].name,
3040		    instance->fmri, errstr);
3041		goto prefork_failure;
3042	}
3043
3044	/*
3045	 * Perform some basic checks before we fork to limit the possibility
3046	 * of exec failures, so we can modify the instance state if necessary.
3047	 */
3048	if (!passes_basic_exec_checks(instance->fmri, methods[method].name,
3049	    mi->exec_path)) {
3050		trans_failure = B_FALSE;
3051		goto prefork_failure;
3052	}
3053
3054	if (contract_prefork(instance->fmri, method) == -1)
3055		goto prefork_failure;
3056	child_pid = fork();
3057	serrno = errno;
3058	contract_postfork();
3059
3060	switch (child_pid) {
3061	case -1:
3062		error_msg(gettext(
3063		    "Unable to fork %s method of instance %s: %s"),
3064		    methods[method].name, instance->fmri, strerror(serrno));
3065		if ((serrno != EAGAIN) && (serrno != ENOMEM))
3066			trans_failure = B_FALSE;
3067		goto prefork_failure;
3068	case 0:				/* child */
3069		exec_method(instance, method, mi, mthd_ctxt, start_info);
3070		/* NOTREACHED */
3071	default:			/* parent */
3072		restarter_free_method_context(mthd_ctxt);
3073		mthd_ctxt = NULL;
3074
3075		if (get_latest_contract(&cid) < 0)
3076			cid = -1;
3077
3078		/*
3079		 * Register this method so its termination is noticed and
3080		 * the state transition this method participates in is
3081		 * continued.
3082		 */
3083		if (register_method(instance, child_pid, cid, method) != 0) {
3084			/*
3085			 * Since we will never find out about the termination
3086			 * of this method, if it's a non-start method treat
3087			 * is as a failure so we don't block restarter event
3088			 * processing on it whilst it languishes in a method
3089			 * running state.
3090			 */
3091			error_msg(gettext("Failed to monitor status of "
3092			    "%s method of instance %s"), methods[method].name,
3093			    instance->fmri);
3094			if (method != IM_START)
3095				process_non_start_term(instance, IMRET_FAILURE);
3096		}
3097
3098		add_method_ids(instance, child_pid, cid, method);
3099
3100		/* do tcp tracing for those nowait instances that request it */
3101		if ((method == IM_START) && cfg->basic->do_tcp_trace &&
3102		    !cfg->basic->iswait) {
3103			char buf[INET6_ADDRSTRLEN];
3104
3105			syslog(LOG_NOTICE, "%s[%d] from %s %d",
3106			    cfg->basic->svc_name, child_pid,
3107			    inet_ntop_native(instance->remote_addr.ss_family,
3108			    SS_SINADDR(instance->remote_addr), buf,
3109			    sizeof (buf)),
3110			    ntohs(SS_PORT(instance->remote_addr)));
3111		}
3112	}
3113
3114	return (0);
3115
3116prefork_failure:
3117	if (mthd_ctxt != NULL) {
3118		restarter_free_method_context(mthd_ctxt);
3119		mthd_ctxt = NULL;
3120	}
3121
3122	if (method == IM_START) {
3123		/*
3124		 * Only place a start method in maintenance if we're sure
3125		 * that the failure was non-transient.
3126		 */
3127		if (!trans_failure) {
3128			destroy_bound_fds(instance);
3129			update_state(instance, IIS_MAINTENANCE, RERR_FAULT);
3130		}
3131	} else {
3132		/* treat the failure as if the method ran and failed */
3133		process_non_start_term(instance, IMRET_FAILURE);
3134	}
3135
3136	return (-1);
3137}
3138
3139static int
3140pending_connections(instance_t *instance, proto_info_t *pi)
3141{
3142	if (instance->config->basic->istlx) {
3143		tlx_info_t *tl = (tlx_info_t *)pi;
3144
3145		return (uu_list_numnodes(tl->conn_ind_queue) != 0);
3146	} else {
3147		return (0);
3148	}
3149}
3150
3151static int
3152accept_connection(instance_t *instance, proto_info_t *pi)
3153{
3154	int		fd;
3155	socklen_t	size;
3156
3157	if (instance->config->basic->istlx) {
3158		tlx_info_t *tl = (tlx_info_t *)pi;
3159		tlx_pending_counter = \
3160		    tlx_pending_counter - uu_list_numnodes(tl->conn_ind_queue);
3161
3162		fd = tlx_accept(instance->fmri, (tlx_info_t *)pi,
3163		    &(instance->remote_addr));
3164
3165		tlx_pending_counter = \
3166		    tlx_pending_counter + uu_list_numnodes(tl->conn_ind_queue);
3167	} else {
3168		size = sizeof (instance->remote_addr);
3169		fd = accept(pi->listen_fd,
3170		    (struct sockaddr *)&(instance->remote_addr), &size);
3171		if (fd < 0)
3172			error_msg("accept: %s", strerror(errno));
3173	}
3174
3175	return (fd);
3176}
3177
3178/*
3179 * Handle an incoming connection request for a nowait service.
3180 * This involves accepting the incoming connection on a new fd. Connection
3181 * rate checks are then performed, transitioning the service to the
3182 * conrate offline state if these fail. Otherwise, the service's start method
3183 * is run (performing TCP wrappers checks if applicable as we do), and on
3184 * success concurrent copies checking is done, transitioning the service to the
3185 * copies offline state if this fails.
3186 */
3187static void
3188process_nowait_request(instance_t *instance, proto_info_t *pi)
3189{
3190	basic_cfg_t		*cfg = instance->config->basic;
3191	int			ret;
3192	adt_event_data_t	*ae;
3193	char			buf[BUFSIZ];
3194
3195	/* accept nowait service connections on a new fd */
3196	if ((instance->conn_fd = accept_connection(instance, pi)) == -1) {
3197		/*
3198		 * Failed accept. Return and allow the event loop to initiate
3199		 * another attempt later if the request is still present.
3200		 */
3201		return;
3202	}
3203
3204	/*
3205	 * Limit connection rate of nowait services. If either conn_rate_max
3206	 * or conn_rate_offline are <= 0, no connection rate limit checking
3207	 * is done. If the configured rate is exceeded, the instance is taken
3208	 * to the connrate_offline state and a timer scheduled to try and
3209	 * bring the instance back online after the configured offline time.
3210	 */
3211	if ((cfg->conn_rate_max > 0) && (cfg->conn_rate_offline > 0)) {
3212		if (instance->conn_rate_count++ == 0) {
3213			instance->conn_rate_start = time(NULL);
3214		} else if (instance->conn_rate_count >
3215		    cfg->conn_rate_max) {
3216			time_t now = time(NULL);
3217
3218			if ((now - instance->conn_rate_start) > 1) {
3219				instance->conn_rate_start = now;
3220				instance->conn_rate_count = 1;
3221			} else {
3222				/* Generate audit record */
3223				if ((ae = adt_alloc_event(audit_handle,
3224				    ADT_inetd_ratelimit)) == NULL) {
3225					error_msg(gettext("Unable to allocate "
3226					    "rate limit audit event"));
3227				} else {
3228					adt_inetd_ratelimit_t *rl =
3229					    &ae->adt_inetd_ratelimit;
3230					/*
3231					 * The inetd_ratelimit audit
3232					 * record consists of:
3233					 * 	Service name
3234					 *	Connection rate limit
3235					 */
3236					rl->service_name = cfg->svc_name;
3237					(void) snprintf(buf, sizeof (buf),
3238					    "limit=%lld", cfg->conn_rate_max);
3239					rl->limit = buf;
3240					(void) adt_put_event(ae, ADT_SUCCESS,
3241					    ADT_SUCCESS);
3242					adt_free_event(ae);
3243				}
3244
3245				error_msg(gettext(
3246				    "Instance %s has exceeded its configured "
3247				    "connection rate, additional connections "
3248				    "will not be accepted for %d seconds"),
3249				    instance->fmri, cfg->conn_rate_offline);
3250
3251				close_net_fd(instance, instance->conn_fd);
3252				instance->conn_fd = -1;
3253
3254				destroy_bound_fds(instance);
3255
3256				instance->conn_rate_count = 0;
3257
3258				instance->conn_rate_exceeded = B_TRUE;
3259				(void) run_method(instance, IM_OFFLINE, NULL);
3260
3261				return;
3262			}
3263		}
3264	}
3265
3266	ret = run_method(instance, IM_START, pi);
3267
3268	close_net_fd(instance, instance->conn_fd);
3269	instance->conn_fd = -1;
3270
3271	if (ret == -1) /* the method wasn't forked  */
3272		return;
3273
3274	instance->copies++;
3275
3276	/*
3277	 * Limit concurrent connections of nowait services.
3278	 */
3279	if (copies_limit_exceeded(instance)) {
3280		/* Generate audit record */
3281		if ((ae = adt_alloc_event(audit_handle, ADT_inetd_copylimit))
3282		    == NULL) {
3283			error_msg(gettext("Unable to allocate copy limit "
3284			    "audit event"));
3285		} else {
3286			/*
3287			 * The inetd_copylimit audit record consists of:
3288			 *	Service name
3289			 * 	Copy limit
3290			 */
3291			ae->adt_inetd_copylimit.service_name = cfg->svc_name;
3292			(void) snprintf(buf, sizeof (buf), "limit=%lld",
3293			    cfg->max_copies);
3294			ae->adt_inetd_copylimit.limit = buf;
3295			(void) adt_put_event(ae, ADT_SUCCESS, ADT_SUCCESS);
3296			adt_free_event(ae);
3297		}
3298
3299		warn_msg(gettext("Instance %s has reached its maximum "
3300		    "configured copies, no new connections will be accepted"),
3301		    instance->fmri);
3302		destroy_bound_fds(instance);
3303		(void) run_method(instance, IM_OFFLINE, NULL);
3304	}
3305}
3306
3307/*
3308 * Handle an incoming request for a wait type service.
3309 * Failure rate checking is done first, taking the service to the maintenance
3310 * state if the checks fail. Following this, the service's start method is run,
3311 * and on success, we stop listening for new requests for this service.
3312 */
3313static void
3314process_wait_request(instance_t *instance, const proto_info_t *pi)
3315{
3316	basic_cfg_t		*cfg = instance->config->basic;
3317	int			ret;
3318	adt_event_data_t	*ae;
3319	char			buf[BUFSIZ];
3320
3321	instance->conn_fd = pi->listen_fd;
3322
3323	/*
3324	 * Detect broken servers and transition them to maintenance. If a
3325	 * wait type service exits without accepting the connection or
3326	 * consuming (reading) the datagram, that service's descriptor will
3327	 * select readable again, and inetd will fork another instance of
3328	 * the server. If either wait_fail_cnt or wait_fail_interval are <= 0,
3329	 * no failure rate detection is done.
3330	 */
3331	if ((cfg->wait_fail_cnt > 0) && (cfg->wait_fail_interval > 0)) {
3332		if (instance->fail_rate_count++ == 0) {
3333			instance->fail_rate_start = time(NULL);
3334		} else if (instance->fail_rate_count > cfg->wait_fail_cnt) {
3335			time_t now = time(NULL);
3336
3337			if ((now - instance->fail_rate_start) >
3338			    cfg->wait_fail_interval) {
3339				instance->fail_rate_start = now;
3340				instance->fail_rate_count = 1;
3341			} else {
3342				/* Generate audit record */
3343				if ((ae = adt_alloc_event(audit_handle,
3344				    ADT_inetd_failrate)) == NULL) {
3345					error_msg(gettext("Unable to allocate "
3346					    "failure rate audit event"));
3347				} else {
3348					adt_inetd_failrate_t *fr =
3349					    &ae->adt_inetd_failrate;
3350					/*
3351					 * The inetd_failrate audit record
3352					 * consists of:
3353					 * 	Service name
3354					 * 	Failure rate
3355					 *	Interval
3356					 * Last two are expressed as k=v pairs
3357					 * in the values field.
3358					 */
3359					fr->service_name = cfg->svc_name;
3360					(void) snprintf(buf, sizeof (buf),
3361					    "limit=%lld,interval=%d",
3362					    cfg->wait_fail_cnt,
3363					    cfg->wait_fail_interval);
3364					fr->values = buf;
3365					(void) adt_put_event(ae, ADT_SUCCESS,
3366					    ADT_SUCCESS);
3367					adt_free_event(ae);
3368				}
3369
3370				error_msg(gettext(
3371				    "Instance %s has exceeded its configured "
3372				    "failure rate, transitioning to "
3373				    "maintenance"), instance->fmri);
3374				instance->fail_rate_count = 0;
3375
3376				destroy_bound_fds(instance);
3377
3378				instance->maintenance_req = B_TRUE;
3379				(void) run_method(instance, IM_OFFLINE, NULL);
3380				return;
3381			}
3382		}
3383	}
3384
3385	ret = run_method(instance, IM_START, pi);
3386
3387	instance->conn_fd = -1;
3388
3389	if (ret == 0) {
3390		/*
3391		 * Stop listening for connections now we've fired off the
3392		 * server for a wait type instance.
3393		 */
3394		(void) poll_bound_fds(instance, B_FALSE);
3395	}
3396}
3397
3398/*
3399 * Process any networks requests for each proto for each instance.
3400 */
3401void
3402process_network_events(void)
3403{
3404	instance_t	*instance;
3405
3406	for (instance = uu_list_first(instance_list); instance != NULL;
3407	    instance = uu_list_next(instance_list, instance)) {
3408		basic_cfg_t	*cfg;
3409		proto_info_t	*pi;
3410
3411		/*
3412		 * Ignore instances in states that definitely don't have any
3413		 * listening fds.
3414		 */
3415		switch (instance->cur_istate) {
3416		case IIS_ONLINE:
3417		case IIS_DEGRADED:
3418		case IIS_IN_REFRESH_METHOD:
3419			break;
3420		default:
3421			continue;
3422		}
3423
3424		cfg = instance->config->basic;
3425
3426		for (pi = uu_list_first(cfg->proto_list); pi != NULL;
3427		    pi = uu_list_next(cfg->proto_list, pi)) {
3428			if (((pi->listen_fd != -1) &&
3429			    isset_pollfd(pi->listen_fd)) ||
3430			    pending_connections(instance, pi)) {
3431				if (cfg->iswait) {
3432					process_wait_request(instance, pi);
3433				} else {
3434					process_nowait_request(instance, pi);
3435				}
3436			}
3437		}
3438	}
3439}
3440
3441/* ARGSUSED0 */
3442static void
3443sigterm_handler(int sig)
3444{
3445	got_sigterm = B_TRUE;
3446}
3447
3448/* ARGSUSED0 */
3449static void
3450sighup_handler(int sig)
3451{
3452	refresh_inetd_requested = B_TRUE;
3453}
3454
3455/*
3456 * inetd's major work loop. This function sits in poll waiting for events
3457 * to occur, processing them when they do. The possible events are
3458 * master restarter requests, expired timer queue timers, stop/refresh signal
3459 * requests, contract events indicating process termination, stop/refresh
3460 * requests originating from one of the stop/refresh inetd processes and
3461 * network events.
3462 * The loop is exited when a stop request is received and processed, and
3463 * all the instances have reached a suitable 'stopping' state.
3464 */
3465static void
3466event_loop(void)
3467{
3468	instance_t		*instance;
3469	int			timeout;
3470
3471	for (;;) {
3472		int	pret = -1;
3473
3474		if (tlx_pending_counter != 0)
3475			timeout = 0;
3476		else
3477			timeout = iu_earliest_timer(timer_queue);
3478
3479		if (!got_sigterm && !refresh_inetd_requested) {
3480			pret = poll(poll_fds, num_pollfds, timeout);
3481			if ((pret == -1) && (errno != EINTR)) {
3482				error_msg(gettext("poll failure: %s"),
3483				    strerror(errno));
3484				continue;
3485			}
3486		}
3487
3488		if (got_sigterm) {
3489			msg_fini();
3490			inetd_stop();
3491			got_sigterm = B_FALSE;
3492			goto check_if_stopped;
3493		}
3494
3495		/*
3496		 * Process any stop/refresh requests from the Unix Domain
3497		 * Socket.
3498		 */
3499		if ((pret != -1) && isset_pollfd(uds_fd)) {
3500			while (process_uds_event() == 0)
3501				;
3502		}
3503
3504		/*
3505		 * Process refresh request. We do this check after the UDS
3506		 * event check above, as it would be wasted processing if we
3507		 * started refreshing inetd based on a SIGHUP, and then were
3508		 * told to shut-down via a UDS event.
3509		 */
3510		if (refresh_inetd_requested) {
3511			refresh_inetd_requested = B_FALSE;
3512			if (!inetd_stopping)
3513				inetd_refresh();
3514		}
3515
3516		/*
3517		 * We were interrupted by a signal. Don't waste any more
3518		 * time processing a potentially inaccurate poll return.
3519		 */
3520		if (pret == -1)
3521			continue;
3522
3523		/*
3524		 * Process any instance restarter events.
3525		 */
3526		if (isset_pollfd(rst_event_pipe[PE_CONSUMER])) {
3527			while (process_restarter_event() == 0)
3528				;
3529		}
3530
3531		/*
3532		 * Process any expired timers (bind retry, con-rate offline,
3533		 * method timeouts).
3534		 */
3535		(void) iu_expire_timers(timer_queue);
3536
3537		process_terminated_methods();
3538
3539		/*
3540		 * If inetd is stopping, check whether all our managed
3541		 * instances have been stopped and we can return.
3542		 */
3543		if (inetd_stopping) {
3544check_if_stopped:
3545			for (instance = uu_list_first(instance_list);
3546			    instance != NULL;
3547			    instance = uu_list_next(instance_list, instance)) {
3548				if (!instance_stopped(instance)) {
3549					debug_msg("%s not yet stopped",
3550					    instance->fmri);
3551					break;
3552				}
3553			}
3554			/* if all instances are stopped, return */
3555			if (instance == NULL)
3556				return;
3557		}
3558
3559		process_network_events();
3560	}
3561}
3562
3563static void
3564fini(void)
3565{
3566	method_fini();
3567	uds_fini();
3568	if (timer_queue != NULL)
3569		iu_tq_destroy(timer_queue);
3570
3571
3572	/*
3573	 * We don't bother to undo the restarter interface at all.
3574	 * Because of quirks in the interface, there is no way to
3575	 * disconnect from the channel and cause any new events to be
3576	 * queued.  However, any events which are received and not
3577	 * acknowledged will be re-sent when inetd restarts as long as inetd
3578	 * uses the same subscriber ID, which it does.
3579	 *
3580	 * By keeping the event pipe open but ignoring it, any events which
3581	 * occur will cause restarter_event_proxy to hang without breaking
3582	 * anything.
3583	 */
3584
3585	if (instance_list != NULL) {
3586		void		*cookie = NULL;
3587		instance_t	*inst;
3588
3589		while ((inst = uu_list_teardown(instance_list, &cookie)) !=
3590		    NULL)
3591			destroy_instance(inst);
3592		uu_list_destroy(instance_list);
3593	}
3594	if (instance_pool != NULL)
3595		uu_list_pool_destroy(instance_pool);
3596	tlx_fini();
3597	config_fini();
3598	repval_fini();
3599	poll_fini();
3600
3601	/* Close audit session */
3602	(void) adt_end_session(audit_handle);
3603}
3604
3605static int
3606init(void)
3607{
3608	int err;
3609
3610	if (repval_init() < 0)
3611		goto failed;
3612
3613	if (config_init() < 0)
3614		goto failed;
3615
3616	refresh_debug_flag();
3617
3618	if (tlx_init() < 0)
3619		goto failed;
3620
3621	/* Setup instance list. */
3622	if ((instance_pool = uu_list_pool_create("instance_pool",
3623	    sizeof (instance_t), offsetof(instance_t, link), NULL,
3624	    UU_LIST_POOL_DEBUG)) == NULL) {
3625		error_msg("%s: %s",
3626		    gettext("Failed to create instance pool"),
3627		    uu_strerror(uu_error()));
3628		goto failed;
3629	}
3630	if ((instance_list = uu_list_create(instance_pool, NULL, 0)) == NULL) {
3631		error_msg("%s: %s",
3632		    gettext("Failed to create instance list"),
3633		    uu_strerror(uu_error()));
3634		goto failed;
3635	}
3636
3637	/*
3638	 * Create event pipe to communicate events with the main event
3639	 * loop and add it to the event loop's fdset.
3640	 */
3641	if (pipe(rst_event_pipe) < 0) {
3642		error_msg("pipe: %s", strerror(errno));
3643		goto failed;
3644	}
3645	/*
3646	 * We only leave the producer end to block on reads/writes as we
3647	 * can't afford to block in the main thread, yet need to in
3648	 * the restarter event thread, so it can sit and wait for an
3649	 * acknowledgement to be written to the pipe.
3650	 */
3651	disable_blocking(rst_event_pipe[PE_CONSUMER]);
3652	if ((set_pollfd(rst_event_pipe[PE_CONSUMER], POLLIN)) == -1)
3653		goto failed;
3654
3655	/*
3656	 * Register with master restarter for managed service events. This
3657	 * will fail, amongst other reasons, if inetd is already running.
3658	 */
3659	if ((err = restarter_bind_handle(RESTARTER_EVENT_VERSION,
3660	    INETD_INSTANCE_FMRI, restarter_event_proxy, 0,
3661	    &rst_event_handle)) != 0) {
3662		error_msg(gettext(
3663		    "Failed to register for restarter events: %s"),
3664		    strerror(err));
3665		goto failed;
3666	}
3667
3668	if (contract_init() < 0)
3669		goto failed;
3670
3671	if ((timer_queue = iu_tq_create()) == NULL) {
3672		error_msg(gettext("Failed to create timer queue."));
3673		goto failed;
3674	}
3675
3676	if (uds_init() < 0)
3677		goto failed;
3678
3679	if (method_init() < 0)
3680		goto failed;
3681
3682	/* Initialize auditing session */
3683	if (adt_start_session(&audit_handle, NULL, ADT_USE_PROC_DATA) != 0) {
3684		error_msg(gettext("Unable to start audit session"));
3685	}
3686
3687	/*
3688	 * Initialize signal dispositions/masks
3689	 */
3690	(void) sigset(SIGHUP, sighup_handler);
3691	(void) sigset(SIGTERM, sigterm_handler);
3692	(void) sigignore(SIGINT);
3693
3694	return (0);
3695
3696failed:
3697	fini();
3698	return (-1);
3699}
3700
3701static int
3702start_method(void)
3703{
3704	int	i;
3705	int	pipe_fds[2];
3706	int	child;
3707
3708	/* Create pipe for child to notify parent of initialization success. */
3709	if (pipe(pipe_fds) < 0) {
3710		error_msg("pipe: %s", strerror(errno));
3711		return (SMF_EXIT_ERR_OTHER);
3712	}
3713
3714	if ((child = fork()) == -1) {
3715		error_msg("fork: %s", strerror(errno));
3716		(void) close(pipe_fds[PE_CONSUMER]);
3717		(void) close(pipe_fds[PE_PRODUCER]);
3718		return (SMF_EXIT_ERR_OTHER);
3719	} else if (child > 0) {			/* parent */
3720
3721		/* Wait on child to return success of initialization. */
3722		(void) close(pipe_fds[PE_PRODUCER]);
3723		if ((safe_read(pipe_fds[PE_CONSUMER], &i, sizeof (i)) != 0) ||
3724		    (i < 0)) {
3725			error_msg(gettext(
3726			    "Initialization failed, unable to start"));
3727			(void) close(pipe_fds[PE_CONSUMER]);
3728			/*
3729			 * Batch all initialization errors as 'other' errors,
3730			 * resulting in retries being attempted.
3731			 */
3732			return (SMF_EXIT_ERR_OTHER);
3733		} else {
3734			(void) close(pipe_fds[PE_CONSUMER]);
3735			return (SMF_EXIT_OK);
3736		}
3737	} else {				/* child */
3738		/*
3739		 * Perform initialization and return success code down
3740		 * the pipe.
3741		 */
3742		(void) close(pipe_fds[PE_CONSUMER]);
3743		i = init();
3744		if ((safe_write(pipe_fds[PE_PRODUCER], &i, sizeof (i)) < 0) ||
3745		    (i < 0)) {
3746			error_msg(gettext("pipe write failure: %s"),
3747			    strerror(errno));
3748			exit(1);
3749		}
3750		(void) close(pipe_fds[PE_PRODUCER]);
3751
3752		(void) setsid();
3753
3754		/*
3755		 * Log a message if the configuration file has changed since
3756		 * inetconv was last run.
3757		 */
3758		check_conf_file();
3759
3760		event_loop();
3761
3762		fini();
3763		debug_msg("inetd stopped");
3764		msg_fini();
3765		exit(0);
3766	}
3767	/* NOTREACHED */
3768}
3769
3770/*
3771 * When inetd is run from outside the SMF, this message is output to provide
3772 * the person invoking inetd with further information that will help them
3773 * understand how to start and stop inetd, and to achieve the other
3774 * behaviors achievable with the legacy inetd command line interface, if
3775 * it is possible.
3776 */
3777static void
3778legacy_usage(void)
3779{
3780	(void) fprintf(stderr,
3781	    "inetd is now an smf(5) managed service and can no longer be run "
3782	    "from the\n"
3783	    "command line. To enable or disable inetd refer to svcadm(1M) on\n"
3784	    "how to enable \"%s\", the inetd instance.\n"
3785	    "\n"
3786	    "The traditional inetd command line option mappings are:\n"
3787	    "\t-d : there is no supported debug output\n"
3788	    "\t-s : inetd is only runnable from within the SMF\n"
3789	    "\t-t : See inetadm(1M) on how to enable TCP tracing\n"
3790	    "\t-r : See inetadm(1M) on how to set a failure rate\n"
3791	    "\n"
3792	    "To specify an alternative configuration file see svccfg(1M)\n"
3793	    "for how to modify the \"%s/%s\" string type property of\n"
3794	    "the inetd instance, and modify it according to the syntax:\n"
3795	    "\"%s [alt_config_file] %%m\".\n"
3796	    "\n"
3797	    "For further information on inetd see inetd(1M).\n",
3798	    INETD_INSTANCE_FMRI, START_METHOD_ARG, SCF_PROPERTY_EXEC,
3799	    INETD_PATH);
3800}
3801
3802/*
3803 * Usage message printed out for usage errors when running under the SMF.
3804 */
3805static void
3806smf_usage(const char *arg0)
3807{
3808	error_msg("Usage: %s [alt_conf_file] %s|%s|%s", arg0, START_METHOD_ARG,
3809	    STOP_METHOD_ARG, REFRESH_METHOD_ARG);
3810}
3811
3812/*
3813 * Returns B_TRUE if we're being run from within the SMF, else B_FALSE.
3814 */
3815static boolean_t
3816run_through_smf(void)
3817{
3818	char *fmri;
3819
3820	/*
3821	 * check if the instance fmri environment variable has been set by
3822	 * our restarter.
3823	 */
3824	return (((fmri = getenv("SMF_FMRI")) != NULL) &&
3825	    (strcmp(fmri, INETD_INSTANCE_FMRI) == 0));
3826}
3827
3828int
3829main(int argc, char *argv[])
3830{
3831	char		*method;
3832	int		ret;
3833
3834#if	!defined(TEXT_DOMAIN)
3835#define	TEXT_DOMAIN "SYS_TEST"
3836#endif
3837	(void) textdomain(TEXT_DOMAIN);
3838	(void) setlocale(LC_ALL, "");
3839
3840	if (!run_through_smf()) {
3841		legacy_usage();
3842		return (SMF_EXIT_ERR_NOSMF);
3843	}
3844
3845	msg_init();	/* setup logging */
3846
3847	(void) enable_extended_FILE_stdio(-1, -1);
3848
3849	/* inetd invocation syntax is inetd [alt_conf_file] method_name */
3850
3851	switch (argc) {
3852	case 2:
3853		method = argv[1];
3854		break;
3855	case 3:
3856		conf_file = argv[1];
3857		method = argv[2];
3858		break;
3859	default:
3860		smf_usage(argv[0]);
3861		return (SMF_EXIT_ERR_CONFIG);
3862
3863	}
3864
3865	if (strcmp(method, START_METHOD_ARG) == 0) {
3866		ret = start_method();
3867	} else if (strcmp(method, STOP_METHOD_ARG) == 0) {
3868		ret = stop_method();
3869	} else if (strcmp(method, REFRESH_METHOD_ARG) == 0) {
3870		ret = refresh_method();
3871	} else {
3872		smf_usage(argv[0]);
3873		return (SMF_EXIT_ERR_CONFIG);
3874	}
3875
3876	return (ret);
3877}
3878