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.
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.
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]
22 * Copyright (c) 2011 Gary Mills
24 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
28 * NOTES: To be expanded.
32 * Below are some high level notes of the operation of the SMF inetd. The
33 * notes don't go into any real detail, and the viewer of this file is
34 * encouraged to look at the code and its associated comments to better
35 * understand inetd's operation. This saves the potential for the code
36 * and these notes diverging over time.
38 * Inetd's major work is done from the context of event_loop(). Within this
39 * loop, inetd polls for events arriving from a number of different file
40 * descriptors, representing the following event types, and initiates
41 * any necessary event processing:
42 * - incoming network connections/datagrams.
43 * - notification of terminated processes (discovered via contract events).
44 * - instance specific events originating from the SMF master restarter.
45 * - stop/refresh requests from the inetd method processes (coming in on a
46 * Unix Domain socket).
47 * There's also a timeout set for the poll, which is set to the nearest
48 * scheduled timer in a timer queue that inetd uses to perform delayed
49 * processing, such as bind retries.
50 * The SIGHUP and SIGINT signals can also interrupt the poll, and will
51 * result in inetd being refreshed or stopped respectively, as was the
52 * behavior with the old inetd.
54 * Inetd implements a state machine for each instance. The states within the
55 * machine are: offline, online, disabled, maintenance, uninitialized and
56 * specializations of the offline state for when an instance exceeds one of
57 * its DOS limits. The state of an instance can be changed as a
58 * result/side-effect of one of the above events occurring, or inetd being
59 * started up. The ongoing state of an instance is stored in the SMF
60 * repository, as required of SMF restarters. This enables an administrator
61 * to view the state of each instance, and, if inetd was to terminate
62 * unexpectedly, it could use the stored state to re-commence where it left off.
64 * Within the state machine a number of methods are run (if provided) as part
65 * of a state transition to aid/ effect a change in an instance's state. The
66 * supported methods are: offline, online, disable, refresh and start. The
67 * latter of these is the equivalent of the server program and its arguments
70 * Events from the SMF master restarter come in on a number of threads
71 * created in the registration routine of librestart, the delegated restarter
72 * library. These threads call into the restart_event_proxy() function
73 * when an event arrives. To serialize the processing of instances, these events
74 * are then written down a pipe to the process's main thread, which listens
75 * for these events via a poll call, with the file descriptor of the other
76 * end of the pipe in its read set, and processes the event appropriately.
77 * When the event has been processed (which may be delayed if the instance
78 * for which the event is for is in the process of executing one of its methods
79 * as part of a state transition) it writes an acknowledgement back down the
80 * pipe the event was received on. The thread in restart_event_proxy() that
81 * wrote the event will read the acknowledgement it was blocked upon, and will
82 * then be able to return to its caller, thus implicitly acknowledging the
83 * event, and allowing another event to be written down the pipe for the main
90 #include <stdio_ext.h>
95 #include <sys/types.h>
96 #include <sys/socket.h>
97 #include <netinet/in.h>
104 #include <librestart.h>
106 #include <sys/stat.h>
112 #include <libuutil.h>
114 #include <bsm/adt_event.h>
116 #include "inetd_impl.h"
118 /* path to inetd's binary */
119 #define INETD_PATH "/usr/lib/inet/inetd"
122 * inetd's default configuration file paths. /etc/inetd/inetd.conf is set
123 * be be the primary file, so it is checked before /etc/inetd.conf.
125 #define PRIMARY_DEFAULT_CONF_FILE "/etc/inet/inetd.conf"
126 #define SECONDARY_DEFAULT_CONF_FILE "/etc/inetd.conf"
128 /* Arguments passed to this binary to request which method to execute. */
129 #define START_METHOD_ARG "start"
130 #define STOP_METHOD_ARG "stop"
131 #define REFRESH_METHOD_ARG "refresh"
133 /* connection backlog for unix domain socket */
134 #define UDS_BACKLOG 2
136 /* number of retries to recv() a request on the UDS socket before giving up */
137 #define UDS_RECV_RETRIES 10
139 /* enumeration of the different ends of a pipe */
146 internal_inst_state_t istate
;
148 restarter_instance_state_t smf_state
;
149 instance_method_t method_running
;
154 * Collection of information for each state.
155 * NOTE: This table is indexed into using the internal_inst_state_t
156 * enumeration, so the ordering needs to be kept in synch.
158 static state_info_t states
[] = {
159 {IIS_UNINITIALIZED
, "uninitialized", RESTARTER_STATE_UNINIT
,
161 {IIS_ONLINE
, "online", RESTARTER_STATE_ONLINE
, IM_START
},
162 {IIS_IN_ONLINE_METHOD
, "online_method", RESTARTER_STATE_OFFLINE
,
164 {IIS_OFFLINE
, "offline", RESTARTER_STATE_OFFLINE
, IM_NONE
},
165 {IIS_IN_OFFLINE_METHOD
, "offline_method", RESTARTER_STATE_OFFLINE
,
167 {IIS_DISABLED
, "disabled", RESTARTER_STATE_DISABLED
, IM_NONE
},
168 {IIS_IN_DISABLE_METHOD
, "disabled_method", RESTARTER_STATE_OFFLINE
,
170 {IIS_IN_REFRESH_METHOD
, "refresh_method", RESTARTER_STATE_ONLINE
,
172 {IIS_MAINTENANCE
, "maintenance", RESTARTER_STATE_MAINT
, IM_NONE
},
173 {IIS_OFFLINE_CONRATE
, "cr_offline", RESTARTER_STATE_OFFLINE
, IM_NONE
},
174 {IIS_OFFLINE_BIND
, "bind_offline", RESTARTER_STATE_OFFLINE
, IM_NONE
},
175 {IIS_OFFLINE_COPIES
, "copies_offline", RESTARTER_STATE_OFFLINE
,
177 {IIS_DEGRADED
, "degraded", RESTARTER_STATE_DEGRADED
, IM_NONE
},
178 {IIS_NONE
, "none", RESTARTER_STATE_NONE
, IM_NONE
}
182 * Pipe used to send events from the threads created by restarter_bind_handle()
183 * to the main thread of control.
185 static int rst_event_pipe
[] = {-1, -1};
187 * Used to protect the critical section of code in restarter_event_proxy() that
188 * involves writing an event down the event pipe and reading an acknowledgement.
190 static pthread_mutex_t rst_event_pipe_mtx
= PTHREAD_MUTEX_INITIALIZER
;
192 /* handle used in communication with the master restarter */
193 static restarter_event_handle_t
*rst_event_handle
= NULL
;
195 /* set to indicate a refresh of inetd is requested */
196 static boolean_t refresh_inetd_requested
= B_FALSE
;
198 /* set by the SIGTERM handler to flag we got a SIGTERM */
199 static boolean_t got_sigterm
= B_FALSE
;
202 * Timer queue used to store timers for delayed event processing, such as
205 iu_tq_t
*timer_queue
= NULL
;
208 * fd of Unix Domain socket used to communicate stop and refresh requests
209 * to the inetd start method process.
211 static int uds_fd
= -1;
214 * List of inetd's currently managed instances; each containing its state,
215 * and in certain states its configuration.
217 static uu_list_pool_t
*instance_pool
= NULL
;
218 uu_list_t
*instance_list
= NULL
;
220 /* set to indicate we're being stopped */
221 boolean_t inetd_stopping
= B_FALSE
;
223 /* TCP wrappers syslog globals. Consumed by libwrap. */
224 int allow_severity
= LOG_INFO
;
225 int deny_severity
= LOG_WARNING
;
227 /* path of the configuration file being monitored by check_conf_file() */
228 static char *conf_file
= NULL
;
230 /* Auditing session handle */
231 static adt_session_data_t
*audit_handle
;
233 /* Number of pending connections */
234 static size_t tlx_pending_counter
;
236 static void uds_fini(void);
237 static int uds_init(void);
238 static int run_method(instance_t
*, instance_method_t
, const proto_info_t
*);
239 static void create_bound_fds(instance_t
*);
240 static void destroy_bound_fds(instance_t
*);
241 static void destroy_instance(instance_t
*);
242 static void inetd_stop(void);
244 exec_method(instance_t
*instance
, instance_method_t method
, method_info_t
*mi
,
245 struct method_context
*mthd_ctxt
, const proto_info_t
*pi
) __NORETURN
;
248 * The following two functions are callbacks that libumem uses to determine
249 * inetd's desired debugging/logging levels. The interface they consume is
250 * exported by FMA and is consolidation private. The comments in the two
251 * functions give the environment variable that will effectively be set to
252 * their returned value, and thus whose behavior for this value, described in
253 * umem_debug(3MALLOC), will be followed.
257 _umem_debug_init(void)
259 return ("default,verbose"); /* UMEM_DEBUG setting */
263 _umem_logging_init(void)
265 return ("fail,contents"); /* UMEM_LOGGING setting */
269 log_invalid_cfg(const char *fmri
)
272 "Invalid configuration for instance %s, placing in maintenance"),
277 * Returns B_TRUE if the instance is in a suitable state for inetd to stop.
280 instance_stopped(const instance_t
*inst
)
282 return ((inst
->cur_istate
== IIS_OFFLINE
) ||
283 (inst
->cur_istate
== IIS_MAINTENANCE
) ||
284 (inst
->cur_istate
== IIS_DISABLED
) ||
285 (inst
->cur_istate
== IIS_UNINITIALIZED
));
289 * Given the instance fmri, obtain the corresonding scf_instance.
290 * Caller is responsible for freeing the returned scf_instance and
294 fmri_to_instance(char *fmri
, scf_instance_t
**scf_instp
)
296 int retries
, ret
= 1;
298 scf_instance_t
*scf_inst
;
300 if ((h
= scf_handle_create(SCF_VERSION
)) == NULL
) {
301 error_msg(gettext("Failed to get instance for %s"), fmri
);
305 if ((scf_inst
= scf_instance_create(h
)) == NULL
)
308 for (retries
= 0; retries
<= REP_OP_RETRIES
; retries
++) {
309 if (make_handle_bound(h
) == -1)
312 if (scf_handle_decode_fmri(h
, fmri
, NULL
, NULL
, scf_inst
,
313 NULL
, NULL
, SCF_DECODE_FMRI_EXACT
) == 0) {
315 *scf_instp
= scf_inst
;
319 if (scf_error() != SCF_ERROR_CONNECTION_BROKEN
)
325 error_msg(gettext("Failed to get instance for %s"), fmri
);
326 scf_instance_destroy(scf_inst
);
327 scf_handle_destroy(h
);
334 * Updates the current and next repository states of instance 'inst'. If
335 * any errors occur an error message is output.
338 update_instance_states(instance_t
*inst
, internal_inst_state_t new_cur_state
,
339 internal_inst_state_t new_next_state
, restarter_error_t err
)
341 internal_inst_state_t old_cur
= inst
->cur_istate
;
342 internal_inst_state_t old_next
= inst
->next_istate
;
343 scf_instance_t
*scf_inst
= NULL
;
346 restarter_str_t aux
= restarter_str_none
;
348 /* update the repository/cached internal state */
349 inst
->cur_istate
= new_cur_state
;
350 inst
->next_istate
= new_next_state
;
351 (void) set_single_rep_val(inst
->cur_istate_rep
,
352 (int64_t)new_cur_state
);
353 (void) set_single_rep_val(inst
->next_istate_rep
,
354 (int64_t)new_next_state
);
356 if (((sret
= store_rep_vals(inst
->cur_istate_rep
, inst
->fmri
,
357 PR_NAME_CUR_INT_STATE
)) != 0) ||
358 ((sret
= store_rep_vals(inst
->next_istate_rep
, inst
->fmri
,
359 PR_NAME_NEXT_INT_STATE
)) != 0))
360 error_msg(gettext("Failed to update state of instance %s in "
361 "repository: %s"), inst
->fmri
, scf_strerror(sret
));
363 if (fmri_to_instance(inst
->fmri
, &scf_inst
) == 0) {
365 * If transitioning to maintenance, check auxiliary_tty set
366 * by svcadm and assign appropriate value to auxiliary_state.
367 * If the maintenance event comes from a service request,
368 * validate auxiliary_fmri and copy it to
369 * restarter/auxiliary_fmri.
371 if (new_cur_state
== IIS_MAINTENANCE
) {
372 if (restarter_inst_ractions_from_tty(scf_inst
) == 0)
373 aux
= restarter_str_service_request
;
375 aux
= restarter_str_administrative_request
;
378 if (aux
== restarter_str_service_request
) {
379 if (restarter_inst_validate_ractions_aux_fmri(
381 if (restarter_inst_set_aux_fmri(scf_inst
))
382 error_msg(gettext("Could not set "
383 "auxiliary_fmri property for %s"),
386 if (restarter_inst_reset_aux_fmri(scf_inst
))
387 error_msg(gettext("Could not reset "
388 "auxiliary_fmri property for %s"),
392 scf_handle_destroy(scf_instance_handle(scf_inst
));
393 scf_instance_destroy(scf_inst
);
396 /* update the repository SMF state */
397 if ((ret
= restarter_set_states(rst_event_handle
, inst
->fmri
,
398 states
[old_cur
].smf_state
, states
[new_cur_state
].smf_state
,
399 states
[old_next
].smf_state
, states
[new_next_state
].smf_state
,
401 error_msg(gettext("Failed to update state of instance %s in "
402 "repository: %s"), inst
->fmri
, strerror(ret
));
406 update_state(instance_t
*inst
, internal_inst_state_t new_cur
,
407 restarter_error_t err
)
409 update_instance_states(inst
, new_cur
, IIS_NONE
, err
);
413 * Sends a refresh event to the inetd start method process and returns
414 * SMF_EXIT_OK if it managed to send it. If it fails to send the request for
415 * some reason it returns SMF_EXIT_ERR_OTHER.
420 uds_request_t req
= UR_REFRESH_INETD
;
423 if ((fd
= connect_to_inetd()) < 0) {
424 error_msg(gettext("Failed to connect to inetd: %s"),
426 return (SMF_EXIT_ERR_OTHER
);
429 /* write the request and return success */
430 if (safe_write(fd
, &req
, sizeof (req
)) == -1) {
432 gettext("Failed to send refresh request to inetd: %s"),
435 return (SMF_EXIT_ERR_OTHER
);
440 return (SMF_EXIT_OK
);
444 * Sends a stop event to the inetd start method process and wait till it goes
445 * away. If inetd is determined to have stopped SMF_EXIT_OK is returned, else
446 * SMF_EXIT_ERR_OTHER is returned.
451 uds_request_t req
= UR_STOP_INETD
;
456 if ((fd
= connect_to_inetd()) == -1) {
457 debug_msg(gettext("Failed to connect to inetd: %s"),
460 * Assume connect_to_inetd() failed because inetd was already
461 * stopped, and return success.
463 return (SMF_EXIT_OK
);
467 * This is safe to do since we're fired off in a separate process
468 * than inetd and in the case we get wedged, the stop method timeout
469 * will occur and we'd be killed by our restarter.
473 /* write the stop request to inetd and wait till it goes away */
474 if (safe_write(fd
, &req
, sizeof (req
)) != 0) {
475 error_msg(gettext("Failed to send stop request to inetd"));
477 return (SMF_EXIT_ERR_OTHER
);
480 /* wait until remote end of socket is closed */
481 while (((ret
= recv(fd
, &c
, sizeof (c
), 0)) != 0) && (errno
== EINTR
))
487 error_msg(gettext("Failed to determine whether inetd stopped"));
488 return (SMF_EXIT_ERR_OTHER
);
491 return (SMF_EXIT_OK
);
496 * This function is called to handle restarter events coming in from the
497 * master restarter. It is registered with the master restarter via
498 * restarter_bind_handle() and simply passes a pointer to the event down
499 * the event pipe, which will be discovered by the poll in the event loop
500 * and processed there. It waits for an acknowledgement to be written back down
501 * the pipe before returning.
502 * Writing a pointer to the function's 'event' parameter down the pipe will
503 * be safe, as the thread in restarter_event_proxy() doesn't return until
504 * the main thread has finished its processing of the passed event, thus
505 * the referenced event will remain around until the function returns.
506 * To impose the limit of only one event being in the pipe and processed
507 * at once, a lock is taken on entry to this function and returned on exit.
511 restarter_event_proxy(restarter_event_t
*event
)
515 (void) pthread_mutex_lock(&rst_event_pipe_mtx
);
517 /* write the event to the main worker thread down the pipe */
518 if (safe_write(rst_event_pipe
[PE_PRODUCER
], &event
,
519 sizeof (event
)) != 0)
523 * Wait for an acknowledgement that the event has been processed from
524 * the same pipe. In the case that inetd is stopping, any thread in
525 * this function will simply block on this read until inetd eventually
526 * exits. This will result in this function not returning success to
527 * its caller, and the event that was being processed when the
528 * function exited will be re-sent when inetd is next started.
530 if (safe_read(rst_event_pipe
[PE_PRODUCER
], &processed
,
531 sizeof (processed
)) != 0)
534 (void) pthread_mutex_unlock(&rst_event_pipe_mtx
);
536 return (processed
? 0 : EAGAIN
);
540 * Something's seriously wrong with the event pipe. Notify the
541 * worker thread by closing this end of the event pipe and pause till
544 error_msg(gettext("Can't process restarter events: %s"),
546 (void) close(rst_event_pipe
[PE_PRODUCER
]);
554 * Let restarter_event_proxy() know we're finished with the event it's blocked
555 * upon. The 'processed' argument denotes whether we successfully processed the
559 ack_restarter_event(boolean_t processed
)
562 * If safe_write returns -1 something's seriously wrong with the event
563 * pipe, so start the shutdown proceedings.
565 if (safe_write(rst_event_pipe
[PE_CONSUMER
], &processed
,
566 sizeof (processed
)) == -1)
571 * Switch the syslog identification string to 'ident'.
574 change_syslog_ident(const char *ident
)
577 openlog(ident
, LOG_PID
|LOG_CONS
, LOG_DAEMON
);
581 * Perform TCP wrappers checks on this instance. Due to the fact that the
582 * current wrappers code used in Solaris is taken untouched from the open
583 * source version, we're stuck with using the daemon name for the checks, as
584 * opposed to making use of instance FMRIs. Sigh.
585 * Returns B_TRUE if the check passed, else B_FALSE.
588 tcp_wrappers_ok(instance_t
*instance
)
590 boolean_t rval
= B_TRUE
;
592 basic_cfg_t
*cfg
= instance
->config
->basic
;
593 struct request_info req
;
596 * Wrap the service using libwrap functions. The code below implements
597 * the functionality of tcpd. This is done only for stream,nowait
598 * services, following the convention of other vendors. udp/dgram and
599 * stream/wait can NOT be wrapped with this libwrap, so be wary of
600 * changing the test below.
602 if (cfg
->do_tcp_wrappers
&& !cfg
->iswait
&& !cfg
->istlx
) {
604 daemon_name
= instance
->config
->methods
[
605 IM_START
]->exec_args_we
.we_wordv
[0];
606 if (*daemon_name
== '/')
607 daemon_name
= strrchr(daemon_name
, '/') + 1;
610 * Change the syslog message identity to the name of the
611 * daemon being wrapped, as opposed to "inetd".
613 change_syslog_ident(daemon_name
);
615 (void) request_init(&req
, RQ_DAEMON
, daemon_name
, RQ_FILE
,
616 instance
->conn_fd
, NULL
);
619 if (strcasecmp(eval_hostname(req
.client
), paranoid
) == 0) {
620 syslog(deny_severity
,
621 "refused connect from %s (name/address mismatch)",
623 if (req
.sink
!= NULL
)
624 req
.sink(instance
->conn_fd
);
626 } else if (!hosts_access(&req
)) {
627 syslog(deny_severity
,
628 "refused connect from %s (access denied)",
630 if (req
.sink
!= NULL
)
631 req
.sink(instance
->conn_fd
);
634 syslog(allow_severity
, "connect from %s",
638 /* Revert syslog identity back to "inetd". */
639 change_syslog_ident(SYSLOG_IDENT
);
645 * Handler registered with the timer queue code to remove an instance from
646 * the connection rate offline state when it has been there for its allotted
651 conn_rate_online(iu_tq_t
*tq
, void *arg
)
653 instance_t
*instance
= arg
;
655 assert(instance
->cur_istate
== IIS_OFFLINE_CONRATE
);
656 instance
->timer_id
= -1;
657 update_state(instance
, IIS_OFFLINE
, RERR_RESTART
);
658 process_offline_inst(instance
);
662 * Check whether this instance in the offline state is in transition to
663 * another state and do the work to continue this transition.
666 process_offline_inst(instance_t
*inst
)
668 if (inst
->disable_req
) {
669 inst
->disable_req
= B_FALSE
;
670 (void) run_method(inst
, IM_DISABLE
, NULL
);
671 } else if (inst
->maintenance_req
) {
672 inst
->maintenance_req
= B_FALSE
;
673 update_state(inst
, IIS_MAINTENANCE
, RERR_RESTART
);
675 * If inetd is in the process of stopping, we don't want to enter
676 * any states but offline, disabled and maintenance.
678 } else if (!inetd_stopping
) {
679 if (inst
->conn_rate_exceeded
) {
680 basic_cfg_t
*cfg
= inst
->config
->basic
;
682 inst
->conn_rate_exceeded
= B_FALSE
;
683 update_state(inst
, IIS_OFFLINE_CONRATE
, RERR_RESTART
);
685 * Schedule a timer to bring the instance out of the
686 * connection rate offline state.
688 inst
->timer_id
= iu_schedule_timer(timer_queue
,
689 cfg
->conn_rate_offline
, conn_rate_online
,
691 if (inst
->timer_id
== -1) {
692 error_msg(gettext("%s unable to set timer, "
693 "won't be brought on line after %d "
694 "seconds."), inst
->fmri
,
695 cfg
->conn_rate_offline
);
698 } else if (copies_limit_exceeded(inst
)) {
699 update_state(inst
, IIS_OFFLINE_COPIES
, RERR_RESTART
);
705 * Create a socket bound to the instance's configured address. If the
706 * bind fails, returns -1, else the fd of the bound socket.
709 create_bound_socket(const instance_t
*inst
, socket_info_t
*sock_info
)
713 const char *fmri
= inst
->fmri
;
714 rpc_info_t
*rpc
= sock_info
->pr_info
.ri
;
715 const char *proto
= sock_info
->pr_info
.proto
;
717 fd
= socket(sock_info
->local_addr
.ss_family
, sock_info
->type
,
718 sock_info
->protocol
);
721 "Socket creation failure for instance %s, proto %s: %s"),
722 fmri
, proto
, strerror(errno
));
726 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &on
, sizeof (on
)) == -1) {
727 error_msg(gettext("setsockopt SO_REUSEADDR failed for service "
728 "instance %s, proto %s: %s"), fmri
, proto
, strerror(errno
));
732 if (inst
->config
->basic
->do_tcp_keepalive
&&
733 !inst
->config
->basic
->iswait
&& !inst
->config
->basic
->istlx
) {
734 /* set the keepalive option */
735 if (setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, &on
,
736 sizeof (on
)) == -1) {
737 error_msg(gettext("setsockopt SO_KEEPALIVE failed for "
738 "service instance %s, proto %s: %s"), fmri
,
739 proto
, strerror(errno
));
744 if (sock_info
->pr_info
.v6only
) {
745 /* restrict socket to IPv6 communications only */
746 if (setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &on
,
747 sizeof (on
)) == -1) {
748 error_msg(gettext("setsockopt IPV6_V6ONLY failed for "
749 "service instance %s, proto %s: %s"), fmri
, proto
,
757 SS_SETPORT(sock_info
->local_addr
, 0);
759 if (bind(fd
, (struct sockaddr
*)&(sock_info
->local_addr
),
760 SS_ADDRLEN(sock_info
->local_addr
)) < 0) {
762 "Failed to bind to the port of service instance %s, "
763 "proto %s: %s"), fmri
, proto
, strerror(errno
));
769 * Retrieve and store the address bound to for RPC services.
772 struct sockaddr_storage ss
;
773 int ss_size
= sizeof (ss
);
775 if (getsockname(fd
, (struct sockaddr
*)&ss
, &ss_size
) < 0) {
776 error_msg(gettext("Failed getsockname for instance %s, "
777 "proto %s: %s"), fmri
, proto
, strerror(errno
));
781 (void) memcpy(rpc
->netbuf
.buf
, &ss
,
782 sizeof (struct sockaddr_storage
));
783 rpc
->netbuf
.len
= SS_ADDRLEN(ss
);
784 rpc
->netbuf
.maxlen
= SS_ADDRLEN(ss
);
787 if (sock_info
->type
== SOCK_STREAM
) {
788 int qlen
= inst
->config
->basic
->conn_backlog
;
790 debug_msg("Listening for service %s with backlog queue"
791 " size %d", fmri
, qlen
);
792 (void) listen(fd
, qlen
);
799 * Handler registered with the timer queue code to retry the creation
804 retry_bind(iu_tq_t
*tq
, void *arg
)
806 instance_t
*instance
= arg
;
808 switch (instance
->cur_istate
) {
809 case IIS_OFFLINE_BIND
:
812 case IIS_IN_ONLINE_METHOD
:
813 case IIS_IN_REFRESH_METHOD
:
817 (void) fprintf(stderr
, "%s:%d: Unknown instance state %d.\n",
818 __FILE__
, __LINE__
, instance
->cur_istate
);
823 instance
->bind_timer_id
= -1;
824 create_bound_fds(instance
);
828 * For each of the fds for the given instance that are bound, if 'listen' is
829 * set add them to the poll set, else remove them from it. If proto_name is
830 * not NULL then apply the change only to this specific protocol endpoint.
831 * If any additions fail, returns -1, else 0 on success.
834 poll_bound_fds(instance_t
*instance
, boolean_t listen
, char *proto_name
)
836 basic_cfg_t
*cfg
= instance
->config
->basic
;
840 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
841 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
842 if (pi
->listen_fd
!= -1) { /* fd bound */
843 if (proto_name
== NULL
||
844 strcmp(pi
->proto
, proto_name
) == 0) {
845 if (listen
== B_FALSE
) {
846 clear_pollfd(pi
->listen_fd
);
847 } else if (set_pollfd(pi
->listen_fd
,
859 * Handle the case were we either fail to create a bound fd or we fail
860 * to add a bound fd to the poll set for the given instance.
863 handle_bind_failure(instance_t
*instance
)
865 basic_cfg_t
*cfg
= instance
->config
->basic
;
868 * We must be being called as a result of a failed poll_bound_fds()
869 * as a bind retry is already scheduled. Just return and let it do
872 if (instance
->bind_timer_id
!= -1)
876 * Check if the rebind retries limit is operative and if so,
877 * if it has been reached.
879 if (((cfg
->bind_fail_interval
<= 0) || /* no retries */
880 ((cfg
->bind_fail_max
>= 0) && /* limit reached */
881 (++instance
->bind_fail_count
> cfg
->bind_fail_max
))) ||
882 ((instance
->bind_timer_id
= iu_schedule_timer(timer_queue
,
883 cfg
->bind_fail_interval
, retry_bind
, instance
)) == -1)) {
886 instance
->bind_fail_count
= 0;
888 switch (instance
->cur_istate
) {
891 /* check if any of the fds are being poll'd upon */
892 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
893 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
894 if ((pi
->listen_fd
!= -1) &&
895 (find_pollfd(pi
->listen_fd
) != NULL
))
898 if (pi
!= NULL
) { /* polling on > 0 fds */
899 warn_msg(gettext("Failed to bind on "
900 "all protocols for instance %s, "
901 "transitioning to degraded"),
903 update_state(instance
, IIS_DEGRADED
, RERR_NONE
);
904 instance
->bind_retries_exceeded
= B_TRUE
;
908 destroy_bound_fds(instance
);
910 * In the case we failed the 'bind' because set_pollfd()
911 * failed on all bound fds, use the offline handling.
915 case IIS_OFFLINE_BIND
:
916 error_msg(gettext("Too many bind failures for instance "
917 "%s, transitioning to maintenance"), instance
->fmri
);
918 update_state(instance
, IIS_MAINTENANCE
,
921 case IIS_IN_ONLINE_METHOD
:
922 case IIS_IN_REFRESH_METHOD
:
923 warn_msg(gettext("Failed to bind on all "
924 "protocols for instance %s, instance will go to "
925 "degraded"), instance
->fmri
);
927 * Set the retries exceeded flag so when the method
928 * completes the instance goes to the degraded state.
930 instance
->bind_retries_exceeded
= B_TRUE
;
934 (void) fprintf(stderr
,
935 "%s:%d: Unknown instance state %d.\n",
936 __FILE__
, __LINE__
, instance
->cur_istate
);
940 } else if (instance
->cur_istate
== IIS_OFFLINE
) {
942 * bind re-scheduled, so if we're offline reflect this in the
945 update_state(instance
, IIS_OFFLINE_BIND
, RERR_NONE
);
951 * Check if two transport protocols for RPC conflict.
955 is_rpc_proto_conflict(const char *proto0
, const char *proto1
) {
956 if (strcmp(proto0
, "tcp") == 0) {
957 if (strcmp(proto1
, "tcp") == 0)
959 if (strcmp(proto1
, "tcp6") == 0)
964 if (strcmp(proto0
, "tcp6") == 0) {
965 if (strcmp(proto1
, "tcp") == 0)
967 if (strcmp(proto1
, "tcp6only") == 0)
969 if (strcmp(proto1
, "tcp6") == 0)
974 if (strcmp(proto0
, "tcp6only") == 0) {
975 if (strcmp(proto1
, "tcp6only") == 0)
977 if (strcmp(proto1
, "tcp6") == 0)
982 if (strcmp(proto0
, "udp") == 0) {
983 if (strcmp(proto1
, "udp") == 0)
985 if (strcmp(proto1
, "udp6") == 0)
990 if (strcmp(proto0
, "udp6") == 0) {
992 if (strcmp(proto1
, "udp") == 0)
994 if (strcmp(proto1
, "udp6only") == 0)
996 if (strcmp(proto1
, "udp6") == 0)
1001 if (strcmp(proto0
, "udp6only") == 0) {
1003 if (strcmp(proto1
, "udp6only") == 0)
1005 if (strcmp(proto1
, "udp6") == 0)
1011 * If the protocol isn't TCP/IP or UDP/IP assume that it has its own
1012 * port namepsace and that conflicts can be detected by literal string
1016 if (strcmp(proto0
, proto1
))
1024 * Check if inetd thinks this RPC program number is already registered.
1026 * An RPC protocol conflict occurs if
1027 * a) the program numbers are the same and,
1028 * b) the version numbers overlap,
1029 * c) the protocols (TCP vs UDP vs tic*) are the same.
1033 is_rpc_num_in_use(int rpc_n
, char *proto
, int lowver
, int highver
) {
1038 for (i
= uu_list_first(instance_list
); i
!= NULL
;
1039 i
= uu_list_next(instance_list
, i
)) {
1041 if (i
->cur_istate
!= IIS_ONLINE
)
1043 cfg
= i
->config
->basic
;
1045 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
1046 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
1050 if (pi
->ri
->prognum
!= rpc_n
)
1052 if (!is_rpc_proto_conflict(pi
->proto
, proto
))
1054 if ((lowver
< pi
->ri
->lowver
&&
1055 highver
< pi
->ri
->lowver
) ||
1056 (lowver
> pi
->ri
->highver
&&
1057 highver
> pi
->ri
->highver
))
1067 * Independent of the transport, for each of the entries in the instance's
1068 * proto list this function first attempts to create an associated network fd;
1069 * for RPC services these are then bound to a kernel chosen port and the
1070 * fd is registered with rpcbind; for non-RPC services the fds are bound
1071 * to the port associated with the instance's service name. On any successful
1072 * binds the instance is taken online. Failed binds are handled by
1073 * handle_bind_failure().
1076 create_bound_fds(instance_t
*instance
)
1078 basic_cfg_t
*cfg
= instance
->config
->basic
;
1079 boolean_t failure
= B_FALSE
;
1080 boolean_t success
= B_FALSE
;
1084 * Loop through and try and bind any unbound protos.
1086 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
1087 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
1088 if (pi
->listen_fd
!= -1)
1091 pi
->listen_fd
= create_bound_endpoint(instance
,
1095 * We cast pi to a void so we can then go on to cast
1096 * it to a socket_info_t without lint complaining
1097 * about alignment. This is done because the x86
1098 * version of lint thinks a lint suppression directive
1099 * is unnecessary and flags it as such, yet the sparc
1100 * version complains if it's absent.
1103 pi
->listen_fd
= create_bound_socket(instance
,
1104 (socket_info_t
*)p
);
1106 if (pi
->listen_fd
== -1) {
1111 if (pi
->ri
!= NULL
) {
1114 * Don't register the same RPC program number twice.
1115 * Doing so silently discards the old service
1116 * without causing an error.
1118 if (is_rpc_num_in_use(pi
->ri
->prognum
, pi
->proto
,
1119 pi
->ri
->lowver
, pi
->ri
->highver
)) {
1121 close_net_fd(instance
, pi
->listen_fd
);
1126 unregister_rpc_service(instance
->fmri
, pi
->ri
);
1127 if (register_rpc_service(instance
->fmri
, pi
->ri
) ==
1129 close_net_fd(instance
, pi
->listen_fd
);
1139 switch (instance
->cur_istate
) {
1141 case IIS_OFFLINE_BIND
:
1143 * If we've managed to bind at least one proto lets run the
1144 * online method, so we can start listening for it.
1146 if (success
&& run_method(instance
, IM_ONLINE
, NULL
) == -1)
1147 return; /* instance gone to maintenance */
1150 case IIS_IN_REFRESH_METHOD
:
1152 * We're 'online', so start polling on any bound fds we're
1155 if (poll_bound_fds(instance
, B_TRUE
, NULL
) != 0) {
1157 } else if (!failure
) {
1159 * We've successfully bound and poll'd upon all protos,
1160 * so reset the failure count.
1162 instance
->bind_fail_count
= 0;
1165 case IIS_IN_ONLINE_METHOD
:
1167 * Nothing to do here as the method completion code will start
1168 * listening for any successfully bound fds.
1173 (void) fprintf(stderr
, "%s:%d: Unknown instance state %d.\n",
1174 __FILE__
, __LINE__
, instance
->cur_istate
);
1180 handle_bind_failure(instance
);
1184 * Counter to create_bound_fds(), for each of the bound network fds this
1185 * function unregisters the instance from rpcbind if it's an RPC service,
1186 * stops listening for new connections for it and then closes the listening fd.
1189 destroy_bound_fds(instance_t
*instance
)
1191 basic_cfg_t
*cfg
= instance
->config
->basic
;
1194 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
1195 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
1196 if (pi
->listen_fd
!= -1) {
1198 unregister_rpc_service(instance
->fmri
, pi
->ri
);
1199 clear_pollfd(pi
->listen_fd
);
1200 close_net_fd(instance
, pi
->listen_fd
);
1205 /* cancel any bind retries */
1206 if (instance
->bind_timer_id
!= -1)
1207 cancel_bind_timer(instance
);
1209 instance
->bind_retries_exceeded
= B_FALSE
;
1213 * Perform %A address expansion and return a pointer to a static string
1214 * array containing crafted arguments. This expansion is provided for
1215 * compatibility with 4.2BSD daemons, and as such we've copied the logic of
1216 * the legacy inetd to maintain this compatibility as much as possible. This
1217 * logic is a bit scatty, but it dates back at least as far as SunOS 4.x.
1220 expand_address(instance_t
*inst
, const proto_info_t
*pi
)
1222 static char addrbuf
[sizeof ("ffffffff.65536")];
1223 static char *ret
[3];
1224 instance_cfg_t
*cfg
= inst
->config
;
1226 * We cast pi to a void so we can then go on to cast it to a
1227 * socket_info_t without lint complaining about alignment. This
1228 * is done because the x86 version of lint thinks a lint suppression
1229 * directive is unnecessary and flags it as such, yet the sparc
1230 * version complains if it's absent.
1234 /* set ret[0] to the basename of exec path */
1235 if ((ret
[0] = strrchr(cfg
->methods
[IM_START
]->exec_path
, '/'))
1239 ret
[0] = cfg
->methods
[IM_START
]->exec_path
;
1242 if (!cfg
->basic
->istlx
&&
1243 (((socket_info_t
*)p
)->type
== SOCK_DGRAM
)) {
1247 if (!cfg
->basic
->iswait
&&
1248 (inst
->remote_addr
.ss_family
== AF_INET
)) {
1249 struct sockaddr_in
*sp
;
1251 sp
= (struct sockaddr_in
*)&(inst
->remote_addr
);
1252 (void) snprintf(addrbuf
, sizeof (addrbuf
), "%x.%hu",
1253 ntohl(sp
->sin_addr
.s_addr
), ntohs(sp
->sin_port
));
1263 * Returns the state associated with the supplied method being run for an
1266 static internal_inst_state_t
1267 get_method_state(instance_method_t method
)
1271 for (sip
= states
; sip
->istate
!= IIS_NONE
; sip
++) {
1272 if (sip
->method_running
== method
)
1275 assert(sip
->istate
!= IIS_NONE
);
1277 return (sip
->istate
);
1281 * Store the method's PID and CID in the repository. If the store fails
1282 * we ignore it and just drive on.
1285 add_method_ids(instance_t
*ins
, pid_t pid
, ctid_t cid
, instance_method_t mthd
)
1288 (void) add_remove_contract(ins
, B_TRUE
, cid
);
1290 if (mthd
== IM_START
) {
1291 if (add_rep_val(ins
->start_pids
, (int64_t)pid
) == 0) {
1292 (void) store_rep_vals(ins
->start_pids
, ins
->fmri
,
1293 PR_NAME_START_PIDS
);
1296 if (add_rep_val(ins
->non_start_pid
, (int64_t)pid
) == 0) {
1297 (void) store_rep_vals(ins
->non_start_pid
, ins
->fmri
,
1298 PR_NAME_NON_START_PID
);
1304 * Remove the method's PID and CID from the repository. If the removal
1305 * fails we ignore it and drive on.
1308 remove_method_ids(instance_t
*inst
, pid_t pid
, ctid_t cid
,
1309 instance_method_t mthd
)
1312 (void) add_remove_contract(inst
, B_FALSE
, cid
);
1314 if (mthd
== IM_START
) {
1315 remove_rep_val(inst
->start_pids
, (int64_t)pid
);
1316 (void) store_rep_vals(inst
->start_pids
, inst
->fmri
,
1317 PR_NAME_START_PIDS
);
1319 remove_rep_val(inst
->non_start_pid
, (int64_t)pid
);
1320 (void) store_rep_vals(inst
->non_start_pid
, inst
->fmri
,
1321 PR_NAME_NON_START_PID
);
1326 create_instance(const char *fmri
)
1330 if (((ret
= calloc(1, sizeof (instance_t
))) == NULL
) ||
1331 ((ret
->fmri
= strdup(fmri
)) == NULL
))
1338 ret
->conn_rate_count
= 0;
1339 ret
->fail_rate_count
= 0;
1340 ret
->bind_fail_count
= 0;
1342 if (((ret
->non_start_pid
= create_rep_val_list()) == NULL
) ||
1343 ((ret
->start_pids
= create_rep_val_list()) == NULL
) ||
1344 ((ret
->start_ctids
= create_rep_val_list()) == NULL
))
1347 ret
->cur_istate
= IIS_NONE
;
1348 ret
->next_istate
= IIS_NONE
;
1350 if (((ret
->cur_istate_rep
= create_rep_val_list()) == NULL
) ||
1351 ((ret
->next_istate_rep
= create_rep_val_list()) == NULL
))
1355 ret
->new_config
= NULL
;
1358 ret
->bind_timer_id
= -1;
1360 ret
->disable_req
= B_FALSE
;
1361 ret
->maintenance_req
= B_FALSE
;
1362 ret
->conn_rate_exceeded
= B_FALSE
;
1363 ret
->bind_retries_exceeded
= B_FALSE
;
1365 ret
->pending_rst_event
= RESTARTER_EVENT_TYPE_INVALID
;
1370 error_msg(strerror(errno
));
1371 destroy_instance(ret
);
1376 destroy_instance(instance_t
*inst
)
1381 destroy_instance_cfg(inst
->config
);
1382 destroy_instance_cfg(inst
->new_config
);
1384 destroy_rep_val_list(inst
->cur_istate_rep
);
1385 destroy_rep_val_list(inst
->next_istate_rep
);
1387 destroy_rep_val_list(inst
->start_pids
);
1388 destroy_rep_val_list(inst
->non_start_pid
);
1389 destroy_rep_val_list(inst
->start_ctids
);
1397 * Retrieves the current and next states internal states. Returns 0 on success,
1398 * else returns one of the following on error:
1399 * SCF_ERROR_NO_MEMORY if memory allocation failed.
1400 * SCF_ERROR_CONNECTION_BROKEN if the connection to the repository was broken.
1401 * SCF_ERROR_TYPE_MISMATCH if the property was of an unexpected type.
1402 * SCF_ERROR_NO_RESOURCES if the server doesn't have adequate resources.
1403 * SCF_ERROR_NO_SERVER if the server isn't running.
1406 retrieve_instance_state(instance_t
*inst
)
1410 /* retrieve internal states */
1411 if (((ret
= retrieve_rep_vals(inst
->cur_istate_rep
, inst
->fmri
,
1412 PR_NAME_CUR_INT_STATE
)) != 0) ||
1413 ((ret
= retrieve_rep_vals(inst
->next_istate_rep
, inst
->fmri
,
1414 PR_NAME_NEXT_INT_STATE
)) != 0)) {
1415 if (ret
!= SCF_ERROR_NOT_FOUND
) {
1417 "Failed to read state of instance %s: %s"),
1418 inst
->fmri
, scf_strerror(scf_error()));
1422 debug_msg("instance with no previous int state - "
1423 "setting state to uninitialized");
1425 if ((set_single_rep_val(inst
->cur_istate_rep
,
1426 (int64_t)IIS_UNINITIALIZED
) == -1) ||
1427 (set_single_rep_val(inst
->next_istate_rep
,
1428 (int64_t)IIS_NONE
) == -1)) {
1429 return (SCF_ERROR_NO_MEMORY
);
1433 /* update convenience states */
1434 inst
->cur_istate
= get_single_rep_val(inst
->cur_istate_rep
);
1435 inst
->next_istate
= get_single_rep_val(inst
->next_istate_rep
);
1440 * Retrieve stored process ids and register each of them so we process their
1444 retrieve_method_pids(instance_t
*inst
)
1448 switch (retrieve_rep_vals(inst
->start_pids
, inst
->fmri
,
1449 PR_NAME_START_PIDS
)) {
1452 case SCF_ERROR_NOT_FOUND
:
1455 error_msg(gettext("Failed to retrieve the start pids of "
1456 "instance %s from repository: %s"), inst
->fmri
,
1457 scf_strerror(scf_error()));
1461 rv
= uu_list_first(inst
->start_pids
);
1462 while (rv
!= NULL
) {
1463 if (register_method(inst
, (pid_t
)rv
->val
, (ctid_t
)-1,
1464 IM_START
, NULL
) == 0) {
1466 rv
= uu_list_next(inst
->start_pids
, rv
);
1467 } else if (errno
== ENOENT
) {
1468 pid_t pid
= (pid_t
)rv
->val
;
1471 * The process must have already terminated. Remove
1474 rv
= uu_list_next(inst
->start_pids
, rv
);
1475 remove_rep_val(inst
->start_pids
, pid
);
1477 error_msg(gettext("Failed to listen for the completion "
1478 "of %s method of instance %s"), START_METHOD_NAME
,
1480 rv
= uu_list_next(inst
->start_pids
, rv
);
1484 /* synch the repository pid list to remove any terminated pids */
1485 (void) store_rep_vals(inst
->start_pids
, inst
->fmri
, PR_NAME_START_PIDS
);
1491 * Remove the passed instance from inetd control.
1494 remove_instance(instance_t
*instance
)
1496 switch (instance
->cur_istate
) {
1499 /* stop listening for network connections */
1500 destroy_bound_fds(instance
);
1502 case IIS_OFFLINE_BIND
:
1503 cancel_bind_timer(instance
);
1505 case IIS_OFFLINE_CONRATE
:
1506 cancel_inst_timer(instance
);
1510 /* stop listening for terminated methods */
1511 unregister_instance_methods(instance
);
1513 uu_list_remove(instance_list
, instance
);
1514 destroy_instance(instance
);
1518 * Refresh the configuration of instance 'inst'. This method gets called as
1519 * a result of a refresh event for the instance from the master restarter, so
1520 * we can rely upon the instance's running snapshot having been updated from
1521 * its configuration snapshot.
1524 refresh_instance(instance_t
*inst
)
1526 instance_cfg_t
*cfg
;
1528 switch (inst
->cur_istate
) {
1529 case IIS_MAINTENANCE
:
1531 case IIS_UNINITIALIZED
:
1533 * Ignore any possible changes, we'll re-read the configuration
1534 * automatically when we exit these states.
1538 case IIS_OFFLINE_COPIES
:
1539 case IIS_OFFLINE_BIND
:
1541 case IIS_OFFLINE_CONRATE
:
1542 destroy_instance_cfg(inst
->config
);
1543 if ((inst
->config
= read_instance_cfg(inst
->fmri
)) == NULL
) {
1544 log_invalid_cfg(inst
->fmri
);
1545 if (inst
->cur_istate
== IIS_OFFLINE_BIND
) {
1546 cancel_bind_timer(inst
);
1547 } else if (inst
->cur_istate
== IIS_OFFLINE_CONRATE
) {
1548 cancel_inst_timer(inst
);
1550 update_state(inst
, IIS_MAINTENANCE
, RERR_FAULT
);
1552 switch (inst
->cur_istate
) {
1553 case IIS_OFFLINE_BIND
:
1554 if (copies_limit_exceeded(inst
)) {
1555 /* Cancel scheduled bind retries. */
1556 cancel_bind_timer(inst
);
1559 * Take the instance to the copies
1560 * offline state, via the offline
1563 update_state(inst
, IIS_OFFLINE
,
1565 process_offline_inst(inst
);
1570 process_offline_inst(inst
);
1573 case IIS_OFFLINE_CONRATE
:
1575 * Since we're already in a DOS state,
1576 * don't bother evaluating the copies
1577 * limit. This will be evaluated when
1578 * we leave this state in
1579 * process_offline_inst().
1583 case IIS_OFFLINE_COPIES
:
1585 * Check if the copies limit has been increased
1586 * above the current count.
1588 if (!copies_limit_exceeded(inst
)) {
1589 update_state(inst
, IIS_OFFLINE
,
1591 process_offline_inst(inst
);
1603 if ((cfg
= read_instance_cfg(inst
->fmri
)) != NULL
) {
1604 instance_cfg_t
*ocfg
= inst
->config
;
1607 * Try to avoid the overhead of taking an instance
1608 * offline and back on again. We do this by limiting
1609 * this behavior to two eventualities:
1610 * - there needs to be a re-bind to listen on behalf
1611 * of the instance with its new configuration. This
1612 * could be because for example its service has been
1613 * associated with a different port, or because the
1614 * v6only protocol option has been newly applied to
1616 * - one or both of the start or online methods of the
1617 * instance have changed in the new configuration.
1618 * Without taking the instance offline when the
1619 * start method changed the instance may be running
1620 * with unwanted parameters (or event an unwanted
1621 * binary); and without taking the instance offline
1622 * if its online method was to change, some part of
1623 * its running environment may have changed and would
1624 * not be picked up until the instance next goes
1625 * offline for another reason.
1627 if ((!bind_config_equal(ocfg
->basic
, cfg
->basic
)) ||
1628 !method_info_equal(ocfg
->methods
[IM_ONLINE
],
1629 cfg
->methods
[IM_ONLINE
]) ||
1630 !method_info_equal(ocfg
->methods
[IM_START
],
1631 cfg
->methods
[IM_START
])) {
1632 destroy_bound_fds(inst
);
1634 assert(inst
->new_config
== NULL
);
1635 inst
->new_config
= cfg
;
1637 (void) run_method(inst
, IM_OFFLINE
, NULL
);
1638 } else { /* no bind config / method changes */
1641 * swap the proto list over from the old
1642 * configuration to the new, so we retain
1643 * our set of network fds.
1645 destroy_proto_list(cfg
->basic
);
1646 cfg
->basic
->proto_list
=
1647 ocfg
->basic
->proto_list
;
1648 ocfg
->basic
->proto_list
= NULL
;
1649 destroy_instance_cfg(ocfg
);
1652 /* re-evaluate copies limits based on new cfg */
1653 if (copies_limit_exceeded(inst
)) {
1654 destroy_bound_fds(inst
);
1655 (void) run_method(inst
, IM_OFFLINE
,
1659 * Since the instance isn't being
1660 * taken offline, where we assume it
1661 * would pick-up any configuration
1662 * changes automatically when it goes
1663 * back online, run its refresh method
1664 * to allow it to pick-up any changes
1665 * whilst still online.
1667 (void) run_method(inst
, IM_REFRESH
,
1672 log_invalid_cfg(inst
->fmri
);
1674 destroy_bound_fds(inst
);
1676 inst
->maintenance_req
= B_TRUE
;
1677 (void) run_method(inst
, IM_OFFLINE
, NULL
);
1682 debug_msg("Unhandled current state %d for instance in "
1683 "refresh_instance", inst
->cur_istate
);
1689 * Called by process_restarter_event() to handle a restarter event for an
1693 handle_restarter_event(instance_t
*instance
, restarter_event_type_t event
,
1697 case RESTARTER_EVENT_TYPE_ADD_INSTANCE
:
1699 * When startd restarts, it sends _ADD_INSTANCE to delegated
1700 * restarters for all those services managed by them. We should
1701 * acknowledge this event, as startd's graph needs to be updated
1702 * about the current state of the service, when startd is
1704 * update_state() is ok to be called here, as commands for
1705 * instances in transition are deferred by
1706 * process_restarter_event().
1708 update_state(instance
, instance
->cur_istate
, RERR_NONE
);
1710 case RESTARTER_EVENT_TYPE_ADMIN_REFRESH
:
1711 refresh_instance(instance
);
1713 case RESTARTER_EVENT_TYPE_ADMIN_RESTART
:
1715 * We've got a restart event, so if the instance is online
1716 * in any way initiate taking it offline, and rely upon
1717 * our restarter to send us an online event to bring
1720 switch (instance
->cur_istate
) {
1723 destroy_bound_fds(instance
);
1724 (void) run_method(instance
, IM_OFFLINE
, NULL
);
1727 case RESTARTER_EVENT_TYPE_REMOVE_INSTANCE
:
1728 remove_instance(instance
);
1730 case RESTARTER_EVENT_TYPE_STOP_RESET
:
1731 case RESTARTER_EVENT_TYPE_STOP
:
1732 switch (instance
->cur_istate
) {
1733 case IIS_OFFLINE_CONRATE
:
1734 case IIS_OFFLINE_BIND
:
1735 case IIS_OFFLINE_COPIES
:
1737 * inetd must be closing down as we wouldn't get this
1738 * event in one of these states from the master
1739 * restarter. Take the instance to the offline resting
1742 if (instance
->cur_istate
== IIS_OFFLINE_BIND
) {
1743 cancel_bind_timer(instance
);
1744 } else if (instance
->cur_istate
==
1745 IIS_OFFLINE_CONRATE
) {
1746 cancel_inst_timer(instance
);
1748 update_state(instance
, IIS_OFFLINE
, RERR_RESTART
);
1754 switch (instance
->cur_istate
) {
1757 case RESTARTER_EVENT_TYPE_START
:
1759 * Dependencies are met, let's take the service online.
1760 * Only try and bind for a wait type service if
1761 * no process is running on its behalf. Otherwise, just
1762 * mark the service online and binding will be attempted
1763 * when the process exits.
1765 if (!(instance
->config
->basic
->iswait
&&
1766 (uu_list_first(instance
->start_pids
) != NULL
))) {
1767 create_bound_fds(instance
);
1769 update_state(instance
, IIS_ONLINE
, RERR_NONE
);
1772 case RESTARTER_EVENT_TYPE_DISABLE
:
1773 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE
:
1775 * The instance should be disabled, so run the
1776 * instance's disabled method that will do the work
1779 (void) run_method(instance
, IM_DISABLE
, NULL
);
1781 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
1782 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
1783 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
1785 * The master restarter has requested the instance
1786 * go to maintenance; since we're already offline
1787 * just update the state to the maintenance state.
1789 update_state(instance
, IIS_MAINTENANCE
, RERR_RESTART
);
1794 case IIS_OFFLINE_BIND
:
1796 case RESTARTER_EVENT_TYPE_DISABLE
:
1797 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE
:
1799 * The instance should be disabled. Firstly, as for
1800 * the above dependencies unmet comment, cancel
1801 * the bind retry timer and update the state to
1802 * offline. Then, run the disable method to do the
1803 * work to take the instance from offline to
1806 cancel_bind_timer(instance
);
1807 update_state(instance
, IIS_OFFLINE
, RERR_RESTART
);
1808 (void) run_method(instance
, IM_DISABLE
, NULL
);
1810 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
1811 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
1812 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
1814 * The master restarter has requested the instance
1815 * be placed in the maintenance state. Cancel the
1816 * outstanding retry timer, and since we're already
1817 * offline, update the state to maintenance.
1819 cancel_bind_timer(instance
);
1820 update_state(instance
, IIS_MAINTENANCE
, RERR_RESTART
);
1828 case RESTARTER_EVENT_TYPE_DISABLE
:
1829 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE
:
1831 * The instance needs to be disabled. Do the same work
1832 * as for the dependencies unmet event below to
1833 * take the instance offline.
1835 destroy_bound_fds(instance
);
1837 * Indicate that the offline method is being run
1838 * as part of going to the disabled state, and to
1839 * carry on this transition.
1841 instance
->disable_req
= B_TRUE
;
1842 (void) run_method(instance
, IM_OFFLINE
, NULL
);
1844 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
1845 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
1846 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
1848 * The master restarter has requested the instance be
1849 * placed in the maintenance state. This involves
1850 * firstly taking the service offline, so do the
1851 * same work as for the dependencies unmet event
1852 * below. We set the maintenance_req flag to
1853 * indicate that when we get to the offline state
1854 * we should be placed directly into the maintenance
1857 instance
->maintenance_req
= B_TRUE
;
1859 case RESTARTER_EVENT_TYPE_STOP_RESET
:
1860 case RESTARTER_EVENT_TYPE_STOP
:
1862 * Dependencies have become unmet. Close and
1863 * stop listening on the instance's network file
1864 * descriptor, and run the offline method to do
1865 * any work required to take us to the offline state.
1867 destroy_bound_fds(instance
);
1868 (void) run_method(instance
, IM_OFFLINE
, NULL
);
1872 case IIS_UNINITIALIZED
:
1873 if (event
== RESTARTER_EVENT_TYPE_DISABLE
||
1874 event
== RESTARTER_EVENT_TYPE_ADMIN_DISABLE
) {
1875 update_state(instance
, IIS_DISABLED
, RERR_NONE
);
1877 } else if (event
!= RESTARTER_EVENT_TYPE_ENABLE
) {
1879 * Ignore other events until we know whether we're
1886 * We've got an enabled event; make use of the handling in the
1893 case RESTARTER_EVENT_TYPE_ENABLE
:
1895 * The instance needs enabling. Commence reading its
1896 * configuration and if successful place the instance
1897 * in the offline state and let process_offline_inst()
1898 * take it from there.
1900 destroy_instance_cfg(instance
->config
);
1901 instance
->config
= read_instance_cfg(instance
->fmri
);
1902 if (instance
->config
!= NULL
) {
1903 update_state(instance
, IIS_OFFLINE
,
1905 process_offline_inst(instance
);
1907 log_invalid_cfg(instance
->fmri
);
1908 update_state(instance
, IIS_MAINTENANCE
,
1913 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
1914 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
1915 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
1917 * The master restarter has requested the instance be
1918 * placed in the maintenance state, so just update its
1919 * state to maintenance.
1921 update_state(instance
, IIS_MAINTENANCE
, RERR_RESTART
);
1926 case IIS_MAINTENANCE
:
1928 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF
:
1929 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE
:
1931 * The master restarter has requested that the instance
1932 * be taken out of maintenance. Read its configuration,
1933 * and if successful place the instance in the offline
1934 * state and call process_offline_inst() to take it
1937 destroy_instance_cfg(instance
->config
);
1938 instance
->config
= read_instance_cfg(instance
->fmri
);
1939 if (instance
->config
!= NULL
) {
1940 update_state(instance
, IIS_OFFLINE
,
1942 process_offline_inst(instance
);
1947 * The configuration was invalid. If the
1948 * service has disabled requested, let's
1949 * just place the instance in disabled even
1950 * though we haven't been able to run its
1951 * disable method, as the slightly incorrect
1952 * state is likely to be less of an issue to
1953 * an administrator than refusing to move an
1954 * instance to disabled. If disable isn't
1955 * requested, re-mark the service's state
1956 * as maintenance, so the administrator can
1957 * see the request was processed.
1959 if ((read_enable_merged(instance
->fmri
,
1960 &enabled
) == 0) && !enabled
) {
1961 update_state(instance
, IIS_DISABLED
,
1964 log_invalid_cfg(instance
->fmri
);
1965 update_state(instance
, IIS_MAINTENANCE
,
1973 case IIS_OFFLINE_CONRATE
:
1975 case RESTARTER_EVENT_TYPE_DISABLE
:
1977 * The instance wants disabling. Take the instance
1978 * offline as for the dependencies unmet event above,
1979 * and then from there run the disable method to do
1980 * the work to take the instance to the disabled state.
1982 cancel_inst_timer(instance
);
1983 update_state(instance
, IIS_OFFLINE
, RERR_RESTART
);
1984 (void) run_method(instance
, IM_DISABLE
, NULL
);
1986 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
1987 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
1988 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
1990 * The master restarter has requested the instance
1991 * be taken to maintenance. Cancel the timer setup
1992 * when we entered this state, and go directly to
1995 cancel_inst_timer(instance
);
1996 update_state(instance
, IIS_MAINTENANCE
, RERR_RESTART
);
2001 case IIS_OFFLINE_COPIES
:
2003 case RESTARTER_EVENT_TYPE_DISABLE
:
2005 * The instance wants disabling. Update the state
2006 * to offline, and run the disable method to do the
2007 * work to take it to the disabled state.
2009 update_state(instance
, IIS_OFFLINE
, RERR_RESTART
);
2010 (void) run_method(instance
, IM_DISABLE
, NULL
);
2012 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON
:
2013 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE
:
2014 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY
:
2016 * The master restarter has requested the instance be
2017 * placed in maintenance. Since it's already offline
2018 * simply update the state.
2020 update_state(instance
, IIS_MAINTENANCE
, RERR_RESTART
);
2026 debug_msg("handle_restarter_event: instance in an "
2027 "unexpected state");
2033 ack_restarter_event(B_TRUE
);
2037 * Tries to read and process an event from the event pipe. If there isn't one
2038 * or an error occurred processing the event it returns -1. Else, if the event
2039 * is for an instance we're not already managing we read its state, add it to
2040 * our list to manage, and if appropriate read its configuration. Whether it's
2041 * new to us or not, we then handle the specific event.
2042 * Returns 0 if an event was read and processed successfully, else -1.
2045 process_restarter_event(void)
2049 restarter_event_type_t event_type
;
2050 instance_t
*instance
;
2051 restarter_event_t
*event
;
2055 * Try to read an event pointer from the event pipe.
2058 switch (safe_read(rst_event_pipe
[PE_CONSUMER
], &event
,
2063 if (errno
== EAGAIN
) /* no event to read */
2066 /* other end of pipe closed */
2069 default: /* unexpected read error */
2071 * There's something wrong with the event pipe. Let's
2072 * shutdown and be restarted.
2079 * Check if we're currently managing the instance which the event
2080 * pertains to. If not, read its complete state and add it to our
2084 fmri_size
= scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH
);
2085 if ((fmri
= malloc(fmri_size
)) == NULL
) {
2086 error_msg(strerror(errno
));
2089 sz
= restarter_event_get_instance(event
, fmri
, fmri_size
);
2090 if (sz
>= fmri_size
)
2093 for (instance
= uu_list_first(instance_list
); instance
!= NULL
;
2094 instance
= uu_list_next(instance_list
, instance
)) {
2095 if (strcmp(instance
->fmri
, fmri
) == 0)
2099 if (instance
== NULL
) {
2102 debug_msg("New instance to manage: %s", fmri
);
2104 if (((instance
= create_instance(fmri
)) == NULL
) ||
2105 (retrieve_instance_state(instance
) != 0) ||
2106 (retrieve_method_pids(instance
) != 0)) {
2107 destroy_instance(instance
);
2112 if (((err
= iterate_repository_contracts(instance
, 0))
2113 != 0) && (err
!= ENOENT
)) {
2115 "Failed to adopt contracts of instance %s: %s"),
2116 instance
->fmri
, strerror(err
));
2117 destroy_instance(instance
);
2122 uu_list_node_init(instance
, &instance
->link
, instance_pool
);
2123 (void) uu_list_insert_after(instance_list
, NULL
, instance
);
2126 * Only read configuration for instances that aren't in any of
2127 * the disabled, maintenance or uninitialized states, since
2128 * they'll read it on state exit.
2130 if ((instance
->cur_istate
!= IIS_DISABLED
) &&
2131 (instance
->cur_istate
!= IIS_MAINTENANCE
) &&
2132 (instance
->cur_istate
!= IIS_UNINITIALIZED
)) {
2133 instance
->config
= read_instance_cfg(instance
->fmri
);
2134 if (instance
->config
== NULL
) {
2135 log_invalid_cfg(instance
->fmri
);
2136 update_state(instance
, IIS_MAINTENANCE
,
2144 event_type
= restarter_event_get_type(event
);
2145 debug_msg("Event type: %d for instance: %s", event_type
,
2149 * If the instance is currently running a method, don't process the
2150 * event now, but attach it to the instance for processing when
2151 * the instance finishes its transition.
2153 if (INST_IN_TRANSITION(instance
)) {
2154 debug_msg("storing event %d for instance %s", event_type
,
2156 instance
->pending_rst_event
= event_type
;
2158 handle_restarter_event(instance
, event_type
, B_TRUE
);
2164 ack_restarter_event(B_FALSE
);
2169 * Do the state machine processing associated with the termination of instance
2170 * 'inst''s start method for the 'proto_name' protocol if this parameter is not
2174 process_start_term(instance_t
*inst
, char *proto_name
)
2180 if ((inst
->cur_istate
== IIS_MAINTENANCE
) ||
2181 (inst
->cur_istate
== IIS_DISABLED
)) {
2182 /* do any further processing/checks when we exit these states */
2186 cfg
= inst
->config
->basic
;
2192 switch (inst
->cur_istate
) {
2195 case IIS_IN_REFRESH_METHOD
:
2197 * A wait type service's start method has exited.
2198 * Check if the method was fired off in this inetd's
2199 * lifetime, or a previous one; if the former,
2200 * re-commence listening on the service's behalf; if
2201 * the latter, mark the service offline and let bind
2202 * attempts commence.
2205 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
2206 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
2208 * If a bound fd exists, the method was fired
2209 * off during this inetd's lifetime.
2211 if (pi
->listen_fd
!= -1) {
2213 if (proto_name
== NULL
||
2214 strcmp(pi
->proto
, proto_name
) == 0)
2219 if (poll_bound_fds(inst
, B_TRUE
, proto_name
) !=
2221 handle_bind_failure(inst
);
2222 } else if (listen
== B_FALSE
) {
2223 update_state(inst
, IIS_OFFLINE
, RERR_RESTART
);
2224 create_bound_fds(inst
);
2229 * Check if a nowait service should be brought back online
2230 * after exceeding its copies limit.
2232 if ((inst
->cur_istate
== IIS_OFFLINE_COPIES
) &&
2233 !copies_limit_exceeded(inst
)) {
2234 update_state(inst
, IIS_OFFLINE
, RERR_NONE
);
2235 process_offline_inst(inst
);
2241 * If the instance has a pending event process it and initiate the
2245 process_pending_rst_event(instance_t
*inst
)
2247 if (inst
->pending_rst_event
!= RESTARTER_EVENT_TYPE_INVALID
) {
2248 restarter_event_type_t re
;
2250 debug_msg("Injecting pending event %d for instance %s",
2251 inst
->pending_rst_event
, inst
->fmri
);
2252 re
= inst
->pending_rst_event
;
2253 inst
->pending_rst_event
= RESTARTER_EVENT_TYPE_INVALID
;
2254 handle_restarter_event(inst
, re
, B_TRUE
);
2259 * Do the state machine processing associated with the termination
2260 * of the specified instance's non-start method with the specified status.
2261 * Once the processing of the termination is done, the function also picks up
2262 * any processing that was blocked on the method running.
2265 process_non_start_term(instance_t
*inst
, int status
)
2267 boolean_t ran_online_method
= B_FALSE
;
2269 if (status
== IMRET_FAILURE
) {
2270 error_msg(gettext("The %s method of instance %s failed, "
2271 "transitioning to maintenance"),
2272 methods
[states
[inst
->cur_istate
].method_running
].name
,
2275 if ((inst
->cur_istate
== IIS_IN_ONLINE_METHOD
) ||
2276 (inst
->cur_istate
== IIS_IN_REFRESH_METHOD
))
2277 destroy_bound_fds(inst
);
2279 update_state(inst
, IIS_MAINTENANCE
, RERR_FAULT
);
2281 inst
->maintenance_req
= B_FALSE
;
2282 inst
->conn_rate_exceeded
= B_FALSE
;
2284 if (inst
->new_config
!= NULL
) {
2285 destroy_instance_cfg(inst
->new_config
);
2286 inst
->new_config
= NULL
;
2289 if (!inetd_stopping
)
2290 process_pending_rst_event(inst
);
2295 /* non-failure method return */
2297 if (status
!= IMRET_SUCCESS
) {
2299 * An instance method never returned a supported return code.
2300 * We'll assume this means the method succeeded for now whilst
2301 * non-GL-cognizant methods are used - eg. pkill.
2303 debug_msg("The %s method of instance %s returned "
2304 "non-compliant exit code: %d, assuming success",
2305 methods
[states
[inst
->cur_istate
].method_running
].name
,
2306 inst
->fmri
, status
);
2310 * Update the state from the in-transition state.
2312 switch (inst
->cur_istate
) {
2313 case IIS_IN_ONLINE_METHOD
:
2314 ran_online_method
= B_TRUE
;
2316 case IIS_IN_REFRESH_METHOD
:
2318 * If we've exhausted the bind retries, flag that by setting
2319 * the instance's state to degraded.
2321 if (inst
->bind_retries_exceeded
) {
2322 update_state(inst
, IIS_DEGRADED
, RERR_NONE
);
2328 methods
[states
[inst
->cur_istate
].method_running
].dst_state
,
2332 if (inst
->cur_istate
== IIS_OFFLINE
) {
2333 if (inst
->new_config
!= NULL
) {
2335 * This instance was found during refresh to need
2336 * taking offline because its newly read configuration
2337 * was sufficiently different. Now we're offline,
2338 * activate this new configuration.
2340 destroy_instance_cfg(inst
->config
);
2341 inst
->config
= inst
->new_config
;
2342 inst
->new_config
= NULL
;
2345 /* continue/complete any transitions that are in progress */
2346 process_offline_inst(inst
);
2348 } else if (ran_online_method
) {
2350 * We've just successfully executed the online method. We have
2351 * a set of bound network fds that were created before running
2352 * this method, so now we're online start listening for
2353 * connections on them.
2355 if (poll_bound_fds(inst
, B_TRUE
, NULL
) != 0)
2356 handle_bind_failure(inst
);
2360 * If we're now out of transition (process_offline_inst() could have
2361 * fired off another method), carry out any jobs that were blocked by
2362 * us being in transition.
2364 if (!INST_IN_TRANSITION(inst
)) {
2365 if (inetd_stopping
) {
2366 if (!instance_stopped(inst
)) {
2368 * inetd is stopping, and this instance hasn't
2369 * been stopped. Inject a stop event.
2371 handle_restarter_event(inst
,
2372 RESTARTER_EVENT_TYPE_STOP
, B_FALSE
);
2375 process_pending_rst_event(inst
);
2381 * Check if configuration file specified is readable. If not return B_FALSE,
2382 * else return B_TRUE.
2385 can_read_file(const char *path
)
2391 ret
= access(path
, R_OK
);
2392 } while ((ret
< 0) && (errno
== EINTR
));
2394 if (errno
!= ENOENT
) {
2396 error_msg(gettext("Failed to access configuration "
2397 "file %s for performing modification checks: %s"),
2398 path
, strerror(errno
));
2407 * Check whether the configuration file has changed contents since inetd
2408 * was last started/refreshed, and if so, log a message indicating that
2409 * inetconv needs to be run.
2412 check_conf_file(void)
2415 char *old_hash
= NULL
;
2419 if (conf_file
== NULL
) {
2421 * No explicit config file specified, so see if one of the
2422 * default two are readable, checking the primary one first
2423 * followed by the secondary.
2425 if (can_read_file(PRIMARY_DEFAULT_CONF_FILE
)) {
2426 file
= PRIMARY_DEFAULT_CONF_FILE
;
2427 } else if ((errno
== ENOENT
) &&
2428 can_read_file(SECONDARY_DEFAULT_CONF_FILE
)) {
2429 file
= SECONDARY_DEFAULT_CONF_FILE
;
2435 if (!can_read_file(file
))
2439 if (calculate_hash(file
, &new_hash
) == 0) {
2440 ret
= retrieve_inetd_hash(&old_hash
);
2441 if (((ret
== SCF_ERROR_NONE
) &&
2442 (strcmp(old_hash
, new_hash
) != 0))) {
2443 /* modified config file */
2445 "Configuration file %s has been modified since "
2446 "inetconv was last run. \"inetconv -i %s\" must be "
2447 "run to apply any changes to the SMF"), file
, file
);
2448 } else if ((ret
!= SCF_ERROR_NOT_FOUND
) &&
2449 (ret
!= SCF_ERROR_NONE
)) {
2450 /* No message if hash not yet computed */
2451 error_msg(gettext("Failed to check whether "
2452 "configuration file %s has been modified: %s"),
2453 file
, scf_strerror(ret
));
2458 error_msg(gettext("Failed to check whether configuration file "
2459 "%s has been modified: %s"), file
, strerror(errno
));
2464 * Refresh all inetd's managed instances and check the configuration file
2465 * for any updates since inetconv was last run, logging a message if there
2466 * are. We call the SMF refresh function to refresh each instance so that
2467 * the refresh request goes through the framework, and thus results in the
2468 * running snapshot of each instance being updated from the configuration
2476 refresh_debug_flag();
2478 /* call libscf to send refresh requests for all managed instances */
2479 for (inst
= uu_list_first(instance_list
); inst
!= NULL
;
2480 inst
= uu_list_next(instance_list
, inst
)) {
2481 if (smf_refresh_instance(inst
->fmri
) < 0) {
2482 error_msg(gettext("Failed to refresh instance %s: %s"),
2483 inst
->fmri
, scf_strerror(scf_error()));
2488 * Log a message if the configuration file has changed since inetconv
2495 * Initiate inetd's shutdown.
2502 /* Block handling signals for stop and refresh */
2503 (void) sighold(SIGHUP
);
2504 (void) sighold(SIGTERM
);
2506 /* Indicate inetd is coming down */
2507 inetd_stopping
= B_TRUE
;
2509 /* Stop polling on restarter events. */
2510 clear_pollfd(rst_event_pipe
[PE_CONSUMER
]);
2512 /* Stop polling for any more stop/refresh requests. */
2513 clear_pollfd(uds_fd
);
2516 * Send a stop event to all currently unstopped instances that
2517 * aren't in transition. For those that are in transition, the
2518 * event will get sent when the transition completes.
2520 for (inst
= uu_list_first(instance_list
); inst
!= NULL
;
2521 inst
= uu_list_next(instance_list
, inst
)) {
2522 if (!instance_stopped(inst
) && !INST_IN_TRANSITION(inst
))
2523 handle_restarter_event(inst
,
2524 RESTARTER_EVENT_TYPE_STOP
, B_FALSE
);
2529 * Sets up the intra-inetd-process Unix Domain Socket.
2530 * Returns -1 on error, else 0.
2535 struct sockaddr_un addr
;
2537 if ((uds_fd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) < 0) {
2538 error_msg("socket: %s", strerror(errno
));
2542 disable_blocking(uds_fd
);
2544 (void) unlink(INETD_UDS_PATH
); /* clean-up any stale files */
2546 (void) memset(&addr
, 0, sizeof (addr
));
2547 addr
.sun_family
= AF_UNIX
;
2549 assert(sizeof (INETD_UDS_PATH
) <= sizeof (addr
.sun_path
));
2550 (void) strlcpy(addr
.sun_path
, INETD_UDS_PATH
, sizeof (addr
.sun_path
));
2552 if (bind(uds_fd
, (struct sockaddr
*)(&addr
), sizeof (addr
)) < 0) {
2553 error_msg(gettext("Failed to bind socket to %s: %s"),
2554 INETD_UDS_PATH
, strerror(errno
));
2555 (void) close(uds_fd
);
2559 (void) listen(uds_fd
, UDS_BACKLOG
);
2561 if ((set_pollfd(uds_fd
, POLLIN
)) == -1) {
2562 (void) close(uds_fd
);
2563 (void) unlink(INETD_UDS_PATH
);
2574 (void) close(uds_fd
);
2575 (void) unlink(INETD_UDS_PATH
);
2579 * Handle an incoming request on the Unix Domain Socket. Returns -1 if there
2580 * was an error handling the event, else 0.
2583 process_uds_event(void)
2587 struct sockaddr_un addr
;
2588 socklen_t len
= sizeof (addr
);
2591 ucred_t
*ucred
= NULL
;
2595 fd
= accept(uds_fd
, (struct sockaddr
*)&addr
, &len
);
2596 } while ((fd
< 0) && (errno
== EINTR
));
2598 if (errno
!= EWOULDBLOCK
)
2599 error_msg("accept failed: %s", strerror(errno
));
2603 if (getpeerucred(fd
, &ucred
) == -1) {
2604 error_msg("getpeerucred failed: %s", strerror(errno
));
2609 /* Check peer credentials before acting on the request */
2610 euid
= ucred_geteuid(ucred
);
2612 if (euid
!= 0 && getuid() != euid
) {
2613 debug_msg("peer euid %u != uid %u",
2614 (uint_t
)euid
, (uint_t
)getuid());
2619 for (retries
= 0; retries
< UDS_RECV_RETRIES
; retries
++) {
2620 if (((ret
= safe_read(fd
, &req
, sizeof (req
))) != 1) ||
2624 (void) poll(NULL
, 0, 100); /* 100ms pause */
2628 error_msg(gettext("Failed read: %s"), strerror(errno
));
2634 case UR_REFRESH_INETD
:
2635 /* flag the request for event_loop() to process */
2636 refresh_inetd_requested
= B_TRUE
;
2643 error_msg("unexpected UDS request");
2652 * Perform checks for common exec string errors. We limit the checks to
2653 * whether the file exists, is a regular file, and has at least one execute
2654 * bit set. We leave the core security checks to exec() so as not to duplicate
2655 * and thus incur the associated drawbacks, but hope to catch the common
2659 passes_basic_exec_checks(const char *instance
, const char *method
,
2664 /* check the file exists */
2665 while (stat(path
, &sbuf
) == -1) {
2666 if (errno
!= EINTR
) {
2668 "Can't stat the %s method of instance %s: %s"),
2669 method
, instance
, strerror(errno
));
2675 * Check if the file is a regular file and has at least one execute
2678 if ((sbuf
.st_mode
& S_IFMT
) != S_IFREG
) {
2680 "The %s method of instance %s isn't a regular file"),
2683 } else if ((sbuf
.st_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)) == 0) {
2684 error_msg(gettext("The %s method instance %s doesn't have "
2685 "any execute permissions set"), method
, instance
);
2693 exec_method(instance_t
*instance
, instance_method_t method
, method_info_t
*mi
,
2694 struct method_context
*mthd_ctxt
, const proto_info_t
*pi
)
2701 basic_cfg_t
*cfg
= instance
->config
->basic
;
2703 if (method
== IM_START
) {
2705 * If wrappers checks fail, pretend the method was exec'd and
2708 if (!tcp_wrappers_ok(instance
))
2709 exit(IMRET_FAILURE
);
2713 * Revert the disposition of handled signals and ignored signals to
2714 * their defaults, unblocking any blocked ones as a side effect.
2716 (void) sigset(SIGHUP
, SIG_DFL
);
2717 (void) sigset(SIGTERM
, SIG_DFL
);
2718 (void) sigset(SIGINT
, SIG_DFL
);
2721 * Ensure that other signals are unblocked
2723 (void) sigemptyset(&mtset
);
2724 (void) sigprocmask(SIG_SETMASK
, &mtset
, (sigset_t
*)NULL
);
2727 * Setup exec arguments. Do this before the fd setup below, so our
2728 * logging related file fd doesn't get taken over before we call
2731 if ((method
== IM_START
) &&
2732 (strcmp(mi
->exec_args_we
.we_wordv
[0], "%A") == 0)) {
2733 args
= expand_address(instance
, pi
);
2735 args
= mi
->exec_args_we
.we_wordv
;
2738 /* Generate audit trail for start operations */
2739 if (method
== IM_START
) {
2740 adt_event_data_t
*ae
;
2741 struct sockaddr_storage ss
;
2742 priv_set_t
*privset
;
2743 socklen_t sslen
= sizeof (ss
);
2745 if ((ae
= adt_alloc_event(audit_handle
, ADT_inetd_connect
))
2747 error_msg(gettext("Unable to allocate audit event for "
2748 "the %s method of instance %s"),
2749 methods
[method
].name
, instance
->fmri
);
2750 exit(IMRET_FAILURE
);
2754 * The inetd_connect audit record consists of:
2757 * Remote address and port
2759 * Process privileges
2761 ae
->adt_inetd_connect
.service_name
= cfg
->svc_name
;
2762 ae
->adt_inetd_connect
.cmd
= mi
->exec_path
;
2764 if (instance
->remote_addr
.ss_family
== AF_INET
) {
2765 struct in_addr
*in
= SS_SINADDR(instance
->remote_addr
);
2766 ae
->adt_inetd_connect
.ip_adr
[0] = in
->s_addr
;
2767 ae
->adt_inetd_connect
.ip_type
= ADT_IPv4
;
2772 ae
->adt_inetd_connect
.ip_type
= ADT_IPv6
;
2773 addr6
= (uint32_t *)SS_SINADDR(instance
->remote_addr
);
2774 for (i
= 0; i
< 4; ++i
)
2775 ae
->adt_inetd_connect
.ip_adr
[i
] = addr6
[i
];
2778 ae
->adt_inetd_connect
.ip_remote_port
=
2779 ntohs(SS_PORT(instance
->remote_addr
));
2781 if (getsockname(instance
->conn_fd
, (struct sockaddr
*)&ss
,
2783 ae
->adt_inetd_connect
.ip_local_port
=
2786 privset
= mthd_ctxt
->priv_set
;
2787 if (privset
== NULL
) {
2788 privset
= priv_allocset();
2789 if (privset
!= NULL
&&
2790 getppriv(PRIV_EFFECTIVE
, privset
) != 0) {
2791 priv_freeset(privset
);
2796 ae
->adt_inetd_connect
.privileges
= privset
;
2798 (void) adt_put_event(ae
, ADT_SUCCESS
, ADT_SUCCESS
);
2801 if (privset
!= NULL
&& mthd_ctxt
->priv_set
== NULL
)
2802 priv_freeset(privset
);
2806 * Set method context before the fd setup below so we can output an
2807 * error message if it fails.
2809 if ((errno
= restarter_set_method_context(mthd_ctxt
, &errf
)) != 0) {
2813 if (strcmp(errf
, "core_set_process_path") == 0) {
2814 msg
= gettext("Failed to set the corefile path "
2815 "for the %s method of instance %s");
2816 } else if (strcmp(errf
, "setproject") == 0) {
2817 msg
= gettext("Failed to assign a resource "
2818 "control for the %s method of instance %s");
2819 } else if (strcmp(errf
, "pool_set_binding") == 0) {
2820 msg
= gettext("Failed to bind the %s method of "
2821 "instance %s to a pool due to a system "
2828 error_msg(msg
, methods
[method
].name
, instance
->fmri
);
2830 exit(IMRET_FAILURE
);
2833 if (errf
!= NULL
&& strcmp(errf
, "pool_set_binding") == 0) {
2836 msg
= gettext("Failed to find resource pool "
2837 "for the %s method of instance %s");
2841 msg
= gettext("Failed to bind the %s method of "
2842 "instance %s to a pool due to invalid "
2847 msg
= gettext("Failed to bind the %s method of "
2848 "instance %s to a pool due to invalid "
2857 exit(IMRET_FAILURE
);
2861 error_msg(gettext("Failed to set credentials for the "
2862 "%s method of instance %s (%s: %s)"),
2863 methods
[method
].name
, instance
->fmri
, errf
,
2865 exit(IMRET_FAILURE
);
2870 msg
= gettext("Failed to set credentials for the %s "
2871 "method of instance %s (out of memory)");
2875 msg
= gettext("Failed to set credentials for the %s "
2876 "method of instance %s (no passwd or shadow "
2885 error_msg(msg
, methods
[method
].name
, instance
->fmri
);
2886 exit(IMRET_FAILURE
);
2889 /* let exec() free mthd_ctxt */
2891 /* setup standard fds */
2892 if (method
== IM_START
) {
2893 (void) dup2(instance
->conn_fd
, STDIN_FILENO
);
2895 (void) close(STDIN_FILENO
);
2896 (void) open("/dev/null", O_RDONLY
);
2898 (void) dup2(STDIN_FILENO
, STDOUT_FILENO
);
2899 (void) dup2(STDIN_FILENO
, STDERR_FILENO
);
2901 closefrom(STDERR_FILENO
+ 1);
2905 env
= set_smf_env(mthd_ctxt
, instance
, methods
[method
].name
);
2909 (void) execve(mi
->exec_path
, args
, env
);
2910 } while (errno
== EINTR
);
2914 /* start up logging again to report the error */
2919 gettext("Failed to exec %s method of instance %s: %s"),
2920 methods
[method
].name
, instance
->fmri
, strerror(errno
));
2922 if ((method
== IM_START
) && (instance
->config
->basic
->iswait
)) {
2924 * We couldn't exec the start method for a wait type service.
2925 * Eat up data from the endpoint, so that hopefully the
2926 * service's fd won't wake poll up on the next time round
2927 * event_loop(). This behavior is carried over from the old
2928 * inetd, and it seems somewhat arbitrary that it isn't
2929 * also done in the case of fork failures; but I guess
2930 * it assumes an exec failure is less likely to be the result
2931 * of a resource shortage, and is thus not worth retrying.
2933 consume_wait_data(instance
, 0);
2936 exit(IMRET_FAILURE
);
2939 static restarter_error_t
2940 get_method_error_success(instance_method_t method
)
2944 return (RERR_RESTART
);
2946 return (RERR_RESTART
);
2948 return (RERR_RESTART
);
2950 return (RERR_REFRESH
);
2952 return (RERR_RESTART
);
2954 (void) fprintf(stderr
, gettext("Internal fatal error in inetd.\n"));
2961 smf_kill_process(instance_t
*instance
, int sig
)
2964 int ret
= IMRET_SUCCESS
;
2966 /* Carry out process assassination */
2967 for (rv
= uu_list_first(instance
->start_pids
);
2969 rv
= uu_list_next(instance
->start_pids
, rv
)) {
2970 if ((kill((pid_t
)rv
->val
, sig
) != 0) &&
2972 ret
= IMRET_FAILURE
;
2973 error_msg(gettext("Unable to kill "
2974 "start process (%ld) of instance %s: %s"),
2975 rv
->val
, instance
->fmri
, strerror(errno
));
2982 * Runs the specified method of the specified service instance.
2983 * If the method was never specified, we handle it the same as if the
2984 * method was called and returned success, carrying on any transition the
2985 * instance may be in the midst of.
2986 * If the method isn't executable in its specified profile or an error occurs
2987 * forking a process to run the method in the function returns -1.
2988 * If a method binary is successfully executed, the function switches the
2989 * instance's cur state to the method's associated 'run' state and the next
2990 * state to the methods associated next state.
2991 * Returns -1 if there's an error before forking, else 0.
2994 run_method(instance_t
*instance
, instance_method_t method
,
2995 const proto_info_t
*start_info
)
2999 struct method_context
*mthd_ctxt
= NULL
;
3002 instance_cfg_t
*cfg
= instance
->config
;
3004 boolean_t trans_failure
= B_TRUE
;
3008 * Don't bother updating the instance's state for the start method
3009 * as there isn't a separate start method state.
3011 if (method
!= IM_START
)
3012 update_instance_states(instance
, get_method_state(method
),
3013 methods
[method
].dst_state
,
3014 get_method_error_success(method
));
3016 if ((mi
= cfg
->methods
[method
]) == NULL
) {
3018 * If the absent method is IM_OFFLINE, default action needs
3019 * to be taken to avoid lingering processes which can prevent
3020 * the upcoming rebinding from happening.
3022 if ((method
== IM_OFFLINE
) && instance
->config
->basic
->iswait
) {
3023 warn_msg(gettext("inetd_offline method for instance %s "
3024 "is unspecified. Taking default action: kill."),
3026 (void) str2sig("TERM", &sig
);
3027 ret
= smf_kill_process(instance
, sig
);
3028 process_non_start_term(instance
, ret
);
3031 process_non_start_term(instance
, IMRET_SUCCESS
);
3036 /* Handle special method tokens, not allowed on start */
3037 if (method
!= IM_START
) {
3038 if (restarter_is_null_method(mi
->exec_path
)) {
3039 /* :true means nothing should be done */
3040 process_non_start_term(instance
, IMRET_SUCCESS
);
3044 if ((sig
= restarter_is_kill_method(mi
->exec_path
)) >= 0) {
3045 /* Carry out contract assassination */
3046 ret
= iterate_repository_contracts(instance
, sig
);
3047 /* ENOENT means we didn't find any contracts */
3048 if (ret
!= 0 && ret
!= ENOENT
) {
3049 error_msg(gettext("Failed to send signal %d "
3050 "to contracts of instance %s: %s"), sig
,
3051 instance
->fmri
, strerror(ret
));
3052 goto prefork_failure
;
3054 process_non_start_term(instance
, IMRET_SUCCESS
);
3059 if ((sig
= restarter_is_kill_proc_method(mi
->exec_path
)) >= 0) {
3060 ret
= smf_kill_process(instance
, sig
);
3061 process_non_start_term(instance
, ret
);
3067 * Get the associated method context before the fork so we can
3068 * modify the instances state if things go wrong.
3070 if ((mthd_ctxt
= read_method_context(instance
->fmri
,
3071 methods
[method
].name
, mi
->exec_path
)) == NULL
)
3072 goto prefork_failure
;
3075 * Perform some basic checks before we fork to limit the possibility
3076 * of exec failures, so we can modify the instance state if necessary.
3078 if (!passes_basic_exec_checks(instance
->fmri
, methods
[method
].name
,
3080 trans_failure
= B_FALSE
;
3081 goto prefork_failure
;
3084 if (contract_prefork(instance
->fmri
, method
) == -1)
3085 goto prefork_failure
;
3088 contract_postfork();
3090 switch (child_pid
) {
3093 "Unable to fork %s method of instance %s: %s"),
3094 methods
[method
].name
, instance
->fmri
, strerror(serrno
));
3095 if ((serrno
!= EAGAIN
) && (serrno
!= ENOMEM
))
3096 trans_failure
= B_FALSE
;
3097 goto prefork_failure
;
3099 exec_method(instance
, method
, mi
, mthd_ctxt
, start_info
);
3101 default: /* parent */
3102 restarter_free_method_context(mthd_ctxt
);
3105 if (get_latest_contract(&cid
) < 0)
3109 * Register this method so its termination is noticed and
3110 * the state transition this method participates in is
3113 if (register_method(instance
, child_pid
, cid
, method
,
3114 start_info
->proto
) != 0) {
3116 * Since we will never find out about the termination
3117 * of this method, if it's a non-start method treat
3118 * is as a failure so we don't block restarter event
3119 * processing on it whilst it languishes in a method
3122 error_msg(gettext("Failed to monitor status of "
3123 "%s method of instance %s"), methods
[method
].name
,
3125 if (method
!= IM_START
)
3126 process_non_start_term(instance
, IMRET_FAILURE
);
3129 add_method_ids(instance
, child_pid
, cid
, method
);
3131 /* do tcp tracing for those nowait instances that request it */
3132 if ((method
== IM_START
) && cfg
->basic
->do_tcp_trace
&&
3133 !cfg
->basic
->iswait
) {
3134 char buf
[INET6_ADDRSTRLEN
];
3136 syslog(LOG_NOTICE
, "%s[%d] from %s %d",
3137 cfg
->basic
->svc_name
, child_pid
,
3138 inet_ntop_native(instance
->remote_addr
.ss_family
,
3139 SS_SINADDR(instance
->remote_addr
), buf
,
3141 ntohs(SS_PORT(instance
->remote_addr
)));
3148 if (mthd_ctxt
!= NULL
) {
3149 restarter_free_method_context(mthd_ctxt
);
3153 if (method
== IM_START
) {
3155 * Only place a start method in maintenance if we're sure
3156 * that the failure was non-transient.
3158 if (!trans_failure
) {
3159 destroy_bound_fds(instance
);
3160 update_state(instance
, IIS_MAINTENANCE
, RERR_FAULT
);
3163 /* treat the failure as if the method ran and failed */
3164 process_non_start_term(instance
, IMRET_FAILURE
);
3171 pending_connections(instance_t
*instance
, proto_info_t
*pi
)
3173 if (instance
->config
->basic
->istlx
) {
3174 tlx_info_t
*tl
= (tlx_info_t
*)pi
;
3176 return (uu_list_numnodes(tl
->conn_ind_queue
) != 0);
3183 accept_connection(instance_t
*instance
, proto_info_t
*pi
)
3188 if (instance
->config
->basic
->istlx
) {
3189 tlx_info_t
*tl
= (tlx_info_t
*)pi
;
3190 tlx_pending_counter
= \
3191 tlx_pending_counter
- uu_list_numnodes(tl
->conn_ind_queue
);
3193 fd
= tlx_accept(instance
->fmri
, (tlx_info_t
*)pi
,
3194 &(instance
->remote_addr
));
3196 tlx_pending_counter
= \
3197 tlx_pending_counter
+ uu_list_numnodes(tl
->conn_ind_queue
);
3199 size
= sizeof (instance
->remote_addr
);
3200 fd
= accept(pi
->listen_fd
,
3201 (struct sockaddr
*)&(instance
->remote_addr
), &size
);
3203 error_msg("accept: %s", strerror(errno
));
3210 * Handle an incoming connection request for a nowait service.
3211 * This involves accepting the incoming connection on a new fd. Connection
3212 * rate checks are then performed, transitioning the service to the
3213 * conrate offline state if these fail. Otherwise, the service's start method
3214 * is run (performing TCP wrappers checks if applicable as we do), and on
3215 * success concurrent copies checking is done, transitioning the service to the
3216 * copies offline state if this fails.
3219 process_nowait_request(instance_t
*instance
, proto_info_t
*pi
)
3221 basic_cfg_t
*cfg
= instance
->config
->basic
;
3223 adt_event_data_t
*ae
;
3226 /* accept nowait service connections on a new fd */
3227 if ((instance
->conn_fd
= accept_connection(instance
, pi
)) == -1) {
3229 * Failed accept. Return and allow the event loop to initiate
3230 * another attempt later if the request is still present.
3236 * Limit connection rate of nowait services. If either conn_rate_max
3237 * or conn_rate_offline are <= 0, no connection rate limit checking
3238 * is done. If the configured rate is exceeded, the instance is taken
3239 * to the connrate_offline state and a timer scheduled to try and
3240 * bring the instance back online after the configured offline time.
3242 if ((cfg
->conn_rate_max
> 0) && (cfg
->conn_rate_offline
> 0)) {
3243 if (instance
->conn_rate_count
++ == 0) {
3244 instance
->conn_rate_start
= time(NULL
);
3245 } else if (instance
->conn_rate_count
>
3246 cfg
->conn_rate_max
) {
3247 time_t now
= time(NULL
);
3249 if ((now
- instance
->conn_rate_start
) > 1) {
3250 instance
->conn_rate_start
= now
;
3251 instance
->conn_rate_count
= 1;
3253 /* Generate audit record */
3254 if ((ae
= adt_alloc_event(audit_handle
,
3255 ADT_inetd_ratelimit
)) == NULL
) {
3256 error_msg(gettext("Unable to allocate "
3257 "rate limit audit event"));
3259 adt_inetd_ratelimit_t
*rl
=
3260 &ae
->adt_inetd_ratelimit
;
3262 * The inetd_ratelimit audit
3263 * record consists of:
3265 * Connection rate limit
3267 rl
->service_name
= cfg
->svc_name
;
3268 (void) snprintf(buf
, sizeof (buf
),
3269 "limit=%lld", cfg
->conn_rate_max
);
3271 (void) adt_put_event(ae
, ADT_SUCCESS
,
3277 "Instance %s has exceeded its configured "
3278 "connection rate, additional connections "
3279 "will not be accepted for %d seconds"),
3280 instance
->fmri
, cfg
->conn_rate_offline
);
3282 close_net_fd(instance
, instance
->conn_fd
);
3283 instance
->conn_fd
= -1;
3285 destroy_bound_fds(instance
);
3287 instance
->conn_rate_count
= 0;
3289 instance
->conn_rate_exceeded
= B_TRUE
;
3290 (void) run_method(instance
, IM_OFFLINE
, NULL
);
3297 ret
= run_method(instance
, IM_START
, pi
);
3299 close_net_fd(instance
, instance
->conn_fd
);
3300 instance
->conn_fd
= -1;
3302 if (ret
== -1) /* the method wasn't forked */
3308 * Limit concurrent connections of nowait services.
3310 if (copies_limit_exceeded(instance
)) {
3311 /* Generate audit record */
3312 if ((ae
= adt_alloc_event(audit_handle
, ADT_inetd_copylimit
))
3314 error_msg(gettext("Unable to allocate copy limit "
3318 * The inetd_copylimit audit record consists of:
3322 ae
->adt_inetd_copylimit
.service_name
= cfg
->svc_name
;
3323 (void) snprintf(buf
, sizeof (buf
), "limit=%lld",
3325 ae
->adt_inetd_copylimit
.limit
= buf
;
3326 (void) adt_put_event(ae
, ADT_SUCCESS
, ADT_SUCCESS
);
3330 warn_msg(gettext("Instance %s has reached its maximum "
3331 "configured copies, no new connections will be accepted"),
3333 destroy_bound_fds(instance
);
3334 (void) run_method(instance
, IM_OFFLINE
, NULL
);
3339 * Handle an incoming request for a wait type service.
3340 * Failure rate checking is done first, taking the service to the maintenance
3341 * state if the checks fail. Following this, the service's start method is run,
3342 * and on success, we stop listening for new requests for this service.
3345 process_wait_request(instance_t
*instance
, const proto_info_t
*pi
)
3347 basic_cfg_t
*cfg
= instance
->config
->basic
;
3349 adt_event_data_t
*ae
;
3352 instance
->conn_fd
= pi
->listen_fd
;
3355 * Detect broken servers and transition them to maintenance. If a
3356 * wait type service exits without accepting the connection or
3357 * consuming (reading) the datagram, that service's descriptor will
3358 * select readable again, and inetd will fork another instance of
3359 * the server. If either wait_fail_cnt or wait_fail_interval are <= 0,
3360 * no failure rate detection is done.
3362 if ((cfg
->wait_fail_cnt
> 0) && (cfg
->wait_fail_interval
> 0)) {
3363 if (instance
->fail_rate_count
++ == 0) {
3364 instance
->fail_rate_start
= time(NULL
);
3365 } else if (instance
->fail_rate_count
> cfg
->wait_fail_cnt
) {
3366 time_t now
= time(NULL
);
3368 if ((now
- instance
->fail_rate_start
) >
3369 cfg
->wait_fail_interval
) {
3370 instance
->fail_rate_start
= now
;
3371 instance
->fail_rate_count
= 1;
3373 /* Generate audit record */
3374 if ((ae
= adt_alloc_event(audit_handle
,
3375 ADT_inetd_failrate
)) == NULL
) {
3376 error_msg(gettext("Unable to allocate "
3377 "failure rate audit event"));
3379 adt_inetd_failrate_t
*fr
=
3380 &ae
->adt_inetd_failrate
;
3382 * The inetd_failrate audit record
3387 * Last two are expressed as k=v pairs
3388 * in the values field.
3390 fr
->service_name
= cfg
->svc_name
;
3391 (void) snprintf(buf
, sizeof (buf
),
3392 "limit=%lld,interval=%d",
3394 cfg
->wait_fail_interval
);
3396 (void) adt_put_event(ae
, ADT_SUCCESS
,
3402 "Instance %s has exceeded its configured "
3403 "failure rate, transitioning to "
3404 "maintenance"), instance
->fmri
);
3405 instance
->fail_rate_count
= 0;
3407 destroy_bound_fds(instance
);
3409 instance
->maintenance_req
= B_TRUE
;
3410 (void) run_method(instance
, IM_OFFLINE
, NULL
);
3416 ret
= run_method(instance
, IM_START
, pi
);
3418 instance
->conn_fd
= -1;
3422 * Stop listening for connections now we've fired off the
3423 * server for a wait type instance.
3425 (void) poll_bound_fds(instance
, B_FALSE
, pi
->proto
);
3430 * Process any networks requests for each proto for each instance.
3433 process_network_events(void)
3435 instance_t
*instance
;
3437 for (instance
= uu_list_first(instance_list
); instance
!= NULL
;
3438 instance
= uu_list_next(instance_list
, instance
)) {
3443 * Ignore instances in states that definitely don't have any
3446 switch (instance
->cur_istate
) {
3449 case IIS_IN_REFRESH_METHOD
:
3455 cfg
= instance
->config
->basic
;
3457 for (pi
= uu_list_first(cfg
->proto_list
); pi
!= NULL
;
3458 pi
= uu_list_next(cfg
->proto_list
, pi
)) {
3459 if (((pi
->listen_fd
!= -1) &&
3460 isset_pollfd(pi
->listen_fd
)) ||
3461 pending_connections(instance
, pi
)) {
3463 process_wait_request(instance
, pi
);
3465 process_nowait_request(instance
, pi
);
3474 sigterm_handler(int sig
)
3476 got_sigterm
= B_TRUE
;
3481 sighup_handler(int sig
)
3483 refresh_inetd_requested
= B_TRUE
;
3487 * inetd's major work loop. This function sits in poll waiting for events
3488 * to occur, processing them when they do. The possible events are
3489 * master restarter requests, expired timer queue timers, stop/refresh signal
3490 * requests, contract events indicating process termination, stop/refresh
3491 * requests originating from one of the stop/refresh inetd processes and
3493 * The loop is exited when a stop request is received and processed, and
3494 * all the instances have reached a suitable 'stopping' state.
3499 instance_t
*instance
;
3505 if (tlx_pending_counter
!= 0)
3508 timeout
= iu_earliest_timer(timer_queue
);
3510 if (!got_sigterm
&& !refresh_inetd_requested
) {
3511 pret
= poll(poll_fds
, num_pollfds
, timeout
);
3512 if ((pret
== -1) && (errno
!= EINTR
)) {
3513 error_msg(gettext("poll failure: %s"),
3522 got_sigterm
= B_FALSE
;
3523 goto check_if_stopped
;
3527 * Process any stop/refresh requests from the Unix Domain
3530 if ((pret
!= -1) && isset_pollfd(uds_fd
)) {
3531 while (process_uds_event() == 0)
3536 * Process refresh request. We do this check after the UDS
3537 * event check above, as it would be wasted processing if we
3538 * started refreshing inetd based on a SIGHUP, and then were
3539 * told to shut-down via a UDS event.
3541 if (refresh_inetd_requested
) {
3542 refresh_inetd_requested
= B_FALSE
;
3543 if (!inetd_stopping
)
3548 * We were interrupted by a signal. Don't waste any more
3549 * time processing a potentially inaccurate poll return.
3555 * Process any instance restarter events.
3557 if (isset_pollfd(rst_event_pipe
[PE_CONSUMER
])) {
3558 while (process_restarter_event() == 0)
3563 * Process any expired timers (bind retry, con-rate offline,
3566 (void) iu_expire_timers(timer_queue
);
3568 process_terminated_methods();
3571 * If inetd is stopping, check whether all our managed
3572 * instances have been stopped and we can return.
3574 if (inetd_stopping
) {
3576 for (instance
= uu_list_first(instance_list
);
3578 instance
= uu_list_next(instance_list
, instance
)) {
3579 if (!instance_stopped(instance
)) {
3580 debug_msg("%s not yet stopped",
3585 /* if all instances are stopped, return */
3586 if (instance
== NULL
)
3590 process_network_events();
3599 if (timer_queue
!= NULL
)
3600 iu_tq_destroy(timer_queue
);
3604 * We don't bother to undo the restarter interface at all.
3605 * Because of quirks in the interface, there is no way to
3606 * disconnect from the channel and cause any new events to be
3607 * queued. However, any events which are received and not
3608 * acknowledged will be re-sent when inetd restarts as long as inetd
3609 * uses the same subscriber ID, which it does.
3611 * By keeping the event pipe open but ignoring it, any events which
3612 * occur will cause restarter_event_proxy to hang without breaking
3616 if (instance_list
!= NULL
) {
3617 void *cookie
= NULL
;
3620 while ((inst
= uu_list_teardown(instance_list
, &cookie
)) !=
3622 destroy_instance(inst
);
3623 uu_list_destroy(instance_list
);
3625 if (instance_pool
!= NULL
)
3626 uu_list_pool_destroy(instance_pool
);
3632 /* Close audit session */
3633 (void) adt_end_session(audit_handle
);
3641 if (repval_init() < 0)
3644 if (config_init() < 0)
3647 refresh_debug_flag();
3652 /* Setup instance list. */
3653 if ((instance_pool
= uu_list_pool_create("instance_pool",
3654 sizeof (instance_t
), offsetof(instance_t
, link
), NULL
,
3655 UU_LIST_POOL_DEBUG
)) == NULL
) {
3657 gettext("Failed to create instance pool"),
3658 uu_strerror(uu_error()));
3661 if ((instance_list
= uu_list_create(instance_pool
, NULL
, 0)) == NULL
) {
3663 gettext("Failed to create instance list"),
3664 uu_strerror(uu_error()));
3669 * Create event pipe to communicate events with the main event
3670 * loop and add it to the event loop's fdset.
3672 if (pipe(rst_event_pipe
) < 0) {
3673 error_msg("pipe: %s", strerror(errno
));
3677 * We only leave the producer end to block on reads/writes as we
3678 * can't afford to block in the main thread, yet need to in
3679 * the restarter event thread, so it can sit and wait for an
3680 * acknowledgement to be written to the pipe.
3682 disable_blocking(rst_event_pipe
[PE_CONSUMER
]);
3683 if ((set_pollfd(rst_event_pipe
[PE_CONSUMER
], POLLIN
)) == -1)
3687 * Register with master restarter for managed service events. This
3688 * will fail, amongst other reasons, if inetd is already running.
3690 if ((err
= restarter_bind_handle(RESTARTER_EVENT_VERSION
,
3691 INETD_INSTANCE_FMRI
, restarter_event_proxy
, 0,
3692 &rst_event_handle
)) != 0) {
3694 "Failed to register for restarter events: %s"),
3699 if (contract_init() < 0)
3702 if ((timer_queue
= iu_tq_create()) == NULL
) {
3703 error_msg(gettext("Failed to create timer queue."));
3710 if (method_init() < 0)
3713 /* Initialize auditing session */
3714 if (adt_start_session(&audit_handle
, NULL
, ADT_USE_PROC_DATA
) != 0) {
3715 error_msg(gettext("Unable to start audit session"));
3719 * Initialize signal dispositions/masks
3721 (void) sigset(SIGHUP
, sighup_handler
);
3722 (void) sigset(SIGTERM
, sigterm_handler
);
3723 (void) sigignore(SIGINT
);
3739 /* Create pipe for child to notify parent of initialization success. */
3740 if (pipe(pipe_fds
) < 0) {
3741 error_msg("pipe: %s", strerror(errno
));
3742 return (SMF_EXIT_ERR_OTHER
);
3745 if ((child
= fork()) == -1) {
3746 error_msg("fork: %s", strerror(errno
));
3747 (void) close(pipe_fds
[PE_CONSUMER
]);
3748 (void) close(pipe_fds
[PE_PRODUCER
]);
3749 return (SMF_EXIT_ERR_OTHER
);
3750 } else if (child
> 0) { /* parent */
3752 /* Wait on child to return success of initialization. */
3753 (void) close(pipe_fds
[PE_PRODUCER
]);
3754 if ((safe_read(pipe_fds
[PE_CONSUMER
], &i
, sizeof (i
)) != 0) ||
3757 "Initialization failed, unable to start"));
3758 (void) close(pipe_fds
[PE_CONSUMER
]);
3760 * Batch all initialization errors as 'other' errors,
3761 * resulting in retries being attempted.
3763 return (SMF_EXIT_ERR_OTHER
);
3765 (void) close(pipe_fds
[PE_CONSUMER
]);
3766 return (SMF_EXIT_OK
);
3768 } else { /* child */
3770 * Perform initialization and return success code down
3773 (void) close(pipe_fds
[PE_CONSUMER
]);
3775 if ((safe_write(pipe_fds
[PE_PRODUCER
], &i
, sizeof (i
)) < 0) ||
3777 error_msg(gettext("pipe write failure: %s"),
3781 (void) close(pipe_fds
[PE_PRODUCER
]);
3786 * Log a message if the configuration file has changed since
3787 * inetconv was last run.
3794 debug_msg("inetd stopped");
3802 * When inetd is run from outside the SMF, this message is output to provide
3803 * the person invoking inetd with further information that will help them
3804 * understand how to start and stop inetd, and to achieve the other
3805 * behaviors achievable with the legacy inetd command line interface, if
3811 (void) fprintf(stderr
,
3812 "inetd is now an smf(5) managed service and can no longer be run "
3814 "command line. To enable or disable inetd refer to svcadm(1M) on\n"
3815 "how to enable \"%s\", the inetd instance.\n"
3817 "The traditional inetd command line option mappings are:\n"
3818 "\t-d : there is no supported debug output\n"
3819 "\t-s : inetd is only runnable from within the SMF\n"
3820 "\t-t : See inetadm(1M) on how to enable TCP tracing\n"
3821 "\t-r : See inetadm(1M) on how to set a failure rate\n"
3823 "To specify an alternative configuration file see svccfg(1M)\n"
3824 "for how to modify the \"%s/%s\" string type property of\n"
3825 "the inetd instance, and modify it according to the syntax:\n"
3826 "\"%s [alt_config_file] %%m\".\n"
3828 "For further information on inetd see inetd(1M).\n",
3829 INETD_INSTANCE_FMRI
, START_METHOD_ARG
, SCF_PROPERTY_EXEC
,
3834 * Usage message printed out for usage errors when running under the SMF.
3837 smf_usage(const char *arg0
)
3839 error_msg("Usage: %s [alt_conf_file] %s|%s|%s", arg0
, START_METHOD_ARG
,
3840 STOP_METHOD_ARG
, REFRESH_METHOD_ARG
);
3844 * Returns B_TRUE if we're being run from within the SMF, else B_FALSE.
3847 run_through_smf(void)
3852 * check if the instance fmri environment variable has been set by
3855 return (((fmri
= getenv("SMF_FMRI")) != NULL
) &&
3856 (strcmp(fmri
, INETD_INSTANCE_FMRI
) == 0));
3860 main(int argc
, char *argv
[])
3865 #if !defined(TEXT_DOMAIN)
3866 #define TEXT_DOMAIN "SYS_TEST"
3868 (void) textdomain(TEXT_DOMAIN
);
3869 (void) setlocale(LC_ALL
, "");
3871 if (!run_through_smf()) {
3873 return (SMF_EXIT_ERR_NOSMF
);
3876 msg_init(); /* setup logging */
3878 (void) enable_extended_FILE_stdio(-1, -1);
3880 /* inetd invocation syntax is inetd [alt_conf_file] method_name */
3887 conf_file
= argv
[1];
3892 return (SMF_EXIT_ERR_CONFIG
);
3896 if (strcmp(method
, START_METHOD_ARG
) == 0) {
3897 ret
= start_method();
3898 } else if (strcmp(method
, STOP_METHOD_ARG
) == 0) {
3899 ret
= stop_method();
3900 } else if (strcmp(method
, REFRESH_METHOD_ARG
) == 0) {
3901 ret
= refresh_method();
3904 return (SMF_EXIT_ERR_CONFIG
);