1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2011 Gary Mills
23 *
24 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /*
28 * NOTES: To be expanded.
29 *
30 * The SMF inetd.
31 *
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.
37 *
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.
53 *
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.
63 *
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
68 * in the old inetd.
69 *
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
84 * thread to process.
85 */
86
87
88 #include <netdb.h>
89 #include <stdio.h>
90 #include <stdio_ext.h>
91 #include <stdlib.h>
92 #include <strings.h>
93 #include <unistd.h>
94 #include <assert.h>
95 #include <sys/types.h>
96 #include <sys/socket.h>
97 #include <netinet/in.h>
98 #include <fcntl.h>
99 #include <signal.h>
100 #include <errno.h>
101 #include <locale.h>
102 #include <syslog.h>
103 #include <libintl.h>
104 #include <librestart.h>
105 #include <pthread.h>
106 #include <sys/stat.h>
107 #include <time.h>
108 #include <limits.h>
109 #include <libgen.h>
110 #include <tcpd.h>
111 #include <libscf.h>
112 #include <libuutil.h>
113 #include <stddef.h>
114 #include <bsm/adt_event.h>
115 #include <ucred.h>
116 #include "inetd_impl.h"
117
118 /* path to inetd's binary */
119 #define INETD_PATH "/usr/lib/inet/inetd"
120
121 /*
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.
124 */
125 #define PRIMARY_DEFAULT_CONF_FILE "/etc/inet/inetd.conf"
126 #define SECONDARY_DEFAULT_CONF_FILE "/etc/inetd.conf"
127
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"
132
133 /* connection backlog for unix domain socket */
134 #define UDS_BACKLOG 2
135
136 /* number of retries to recv() a request on the UDS socket before giving up */
137 #define UDS_RECV_RETRIES 10
138
139 /* enumeration of the different ends of a pipe */
140 enum pipe_end {
141 PE_CONSUMER,
142 PE_PRODUCER
143 };
144
145 typedef struct {
146 internal_inst_state_t istate;
147 const char *name;
148 restarter_instance_state_t smf_state;
149 instance_method_t method_running;
150 } state_info_t;
151
152
153 /*
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.
157 */
158 static state_info_t states[] = {
159 {IIS_UNINITIALIZED, "uninitialized", RESTARTER_STATE_UNINIT,
160 IM_NONE},
161 {IIS_ONLINE, "online", RESTARTER_STATE_ONLINE, IM_START},
162 {IIS_IN_ONLINE_METHOD, "online_method", RESTARTER_STATE_OFFLINE,
163 IM_ONLINE},
164 {IIS_OFFLINE, "offline", RESTARTER_STATE_OFFLINE, IM_NONE},
165 {IIS_IN_OFFLINE_METHOD, "offline_method", RESTARTER_STATE_OFFLINE,
166 IM_OFFLINE},
167 {IIS_DISABLED, "disabled", RESTARTER_STATE_DISABLED, IM_NONE},
168 {IIS_IN_DISABLE_METHOD, "disabled_method", RESTARTER_STATE_OFFLINE,
169 IM_DISABLE},
170 {IIS_IN_REFRESH_METHOD, "refresh_method", RESTARTER_STATE_ONLINE,
171 IM_REFRESH},
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,
176 IM_NONE},
177 {IIS_DEGRADED, "degraded", RESTARTER_STATE_DEGRADED, IM_NONE},
178 {IIS_NONE, "none", RESTARTER_STATE_NONE, IM_NONE}
179 };
180
181 /*
182 * Pipe used to send events from the threads created by restarter_bind_handle()
183 * to the main thread of control.
184 */
185 static int rst_event_pipe[] = {-1, -1};
186 /*
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.
189 */
190 static pthread_mutex_t rst_event_pipe_mtx = PTHREAD_MUTEX_INITIALIZER;
191
192 /* handle used in communication with the master restarter */
193 static restarter_event_handle_t *rst_event_handle = NULL;
194
195 /* set to indicate a refresh of inetd is requested */
196 static boolean_t refresh_inetd_requested = B_FALSE;
197
198 /* set by the SIGTERM handler to flag we got a SIGTERM */
199 static boolean_t got_sigterm = B_FALSE;
200
201 /*
202 * Timer queue used to store timers for delayed event processing, such as
203 * bind retries.
204 */
205 iu_tq_t *timer_queue = NULL;
206
207 /*
208 * fd of Unix Domain socket used to communicate stop and refresh requests
209 * to the inetd start method process.
210 */
211 static int uds_fd = -1;
212
213 /*
214 * List of inetd's currently managed instances; each containing its state,
215 * and in certain states its configuration.
216 */
217 static uu_list_pool_t *instance_pool = NULL;
218 uu_list_t *instance_list = NULL;
219
220 /* set to indicate we're being stopped */
221 boolean_t inetd_stopping = B_FALSE;
222
223 /* TCP wrappers syslog globals. Consumed by libwrap. */
224 int allow_severity = LOG_INFO;
225 int deny_severity = LOG_WARNING;
226
227 /* path of the configuration file being monitored by check_conf_file() */
228 static char *conf_file = NULL;
229
230 /* Auditing session handle */
231 static adt_session_data_t *audit_handle;
232
233 /* Number of pending connections */
234 static size_t tlx_pending_counter;
235
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);
243 static 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;
246
247 /*
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.
254 */
255
256 const char *
_umem_debug_init(void)257 _umem_debug_init(void)
258 {
259 return ("default,verbose"); /* UMEM_DEBUG setting */
260 }
261
262 const char *
_umem_logging_init(void)263 _umem_logging_init(void)
264 {
265 return ("fail,contents"); /* UMEM_LOGGING setting */
266 }
267
268 static void
log_invalid_cfg(const char * fmri)269 log_invalid_cfg(const char *fmri)
270 {
271 error_msg(gettext(
272 "Invalid configuration for instance %s, placing in maintenance"),
273 fmri);
274 }
275
276 /*
277 * Returns B_TRUE if the instance is in a suitable state for inetd to stop.
278 */
279 static boolean_t
instance_stopped(const instance_t * inst)280 instance_stopped(const instance_t *inst)
281 {
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));
286 }
287
288 /*
289 * Given the instance fmri, obtain the corresonding scf_instance.
290 * Caller is responsible for freeing the returned scf_instance and
291 * its scf_handle.
292 */
293 static int
fmri_to_instance(char * fmri,scf_instance_t ** scf_instp)294 fmri_to_instance(char *fmri, scf_instance_t **scf_instp)
295 {
296 int retries, ret = 1;
297 scf_handle_t *h;
298 scf_instance_t *scf_inst;
299
300 if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
301 error_msg(gettext("Failed to get instance for %s"), fmri);
302 return (1);
303 }
304
305 if ((scf_inst = scf_instance_create(h)) == NULL)
306 goto out;
307
308 for (retries = 0; retries <= REP_OP_RETRIES; retries++) {
309 if (make_handle_bound(h) == -1)
310 break;
311
312 if (scf_handle_decode_fmri(h, fmri, NULL, NULL, scf_inst,
313 NULL, NULL, SCF_DECODE_FMRI_EXACT) == 0) {
314 ret = 0;
315 *scf_instp = scf_inst;
316 break;
317 }
318
319 if (scf_error() != SCF_ERROR_CONNECTION_BROKEN)
320 break;
321 }
322
323 out:
324 if (ret != 0) {
325 error_msg(gettext("Failed to get instance for %s"), fmri);
326 scf_instance_destroy(scf_inst);
327 scf_handle_destroy(h);
328 }
329
330 return (ret);
331 }
332
333 /*
334 * Updates the current and next repository states of instance 'inst'. If
335 * any errors occur an error message is output.
336 */
337 static void
update_instance_states(instance_t * inst,internal_inst_state_t new_cur_state,internal_inst_state_t new_next_state,restarter_error_t err)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)
340 {
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;
344 scf_error_t sret;
345 int ret;
346 restarter_str_t aux = restarter_str_none;
347
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);
355
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));
362
363 if (fmri_to_instance(inst->fmri, &scf_inst) == 0) {
364 /*
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.
370 */
371 if (new_cur_state == IIS_MAINTENANCE) {
372 if (restarter_inst_ractions_from_tty(scf_inst) == 0)
373 aux = restarter_str_service_request;
374 else
375 aux = restarter_str_administrative_request;
376 }
377
378 if (aux == restarter_str_service_request) {
379 if (restarter_inst_validate_ractions_aux_fmri(
380 scf_inst) == 0) {
381 if (restarter_inst_set_aux_fmri(scf_inst))
382 error_msg(gettext("Could not set "
383 "auxiliary_fmri property for %s"),
384 inst->fmri);
385 } else {
386 if (restarter_inst_reset_aux_fmri(scf_inst))
387 error_msg(gettext("Could not reset "
388 "auxiliary_fmri property for %s"),
389 inst->fmri);
390 }
391 }
392 scf_handle_destroy(scf_instance_handle(scf_inst));
393 scf_instance_destroy(scf_inst);
394 }
395
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,
400 err, aux)) != 0)
401 error_msg(gettext("Failed to update state of instance %s in "
402 "repository: %s"), inst->fmri, strerror(ret));
403 }
404
405 void
update_state(instance_t * inst,internal_inst_state_t new_cur,restarter_error_t err)406 update_state(instance_t *inst, internal_inst_state_t new_cur,
407 restarter_error_t err)
408 {
409 update_instance_states(inst, new_cur, IIS_NONE, err);
410 }
411
412 /*
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.
416 */
417 static int
refresh_method(void)418 refresh_method(void)
419 {
420 uds_request_t req = UR_REFRESH_INETD;
421 int fd;
422
423 if ((fd = connect_to_inetd()) < 0) {
424 error_msg(gettext("Failed to connect to inetd: %s"),
425 strerror(errno));
426 return (SMF_EXIT_ERR_OTHER);
427 }
428
429 /* write the request and return success */
430 if (safe_write(fd, &req, sizeof (req)) == -1) {
431 error_msg(
432 gettext("Failed to send refresh request to inetd: %s"),
433 strerror(errno));
434 (void) close(fd);
435 return (SMF_EXIT_ERR_OTHER);
436 }
437
438 (void) close(fd);
439
440 return (SMF_EXIT_OK);
441 }
442
443 /*
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.
447 */
448 static int
stop_method(void)449 stop_method(void)
450 {
451 uds_request_t req = UR_STOP_INETD;
452 int fd;
453 char c;
454 ssize_t ret;
455
456 if ((fd = connect_to_inetd()) == -1) {
457 debug_msg(gettext("Failed to connect to inetd: %s"),
458 strerror(errno));
459 /*
460 * Assume connect_to_inetd() failed because inetd was already
461 * stopped, and return success.
462 */
463 return (SMF_EXIT_OK);
464 }
465
466 /*
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.
470 */
471 enable_blocking(fd);
472
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"));
476 (void) close(fd);
477 return (SMF_EXIT_ERR_OTHER);
478 }
479
480 /* wait until remote end of socket is closed */
481 while (((ret = recv(fd, &c, sizeof (c), 0)) != 0) && (errno == EINTR))
482 ;
483
484 (void) close(fd);
485
486 if (ret != 0) {
487 error_msg(gettext("Failed to determine whether inetd stopped"));
488 return (SMF_EXIT_ERR_OTHER);
489 }
490
491 return (SMF_EXIT_OK);
492 }
493
494
495 /*
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.
508 * Always returns 0.
509 */
510 static int
restarter_event_proxy(restarter_event_t * event)511 restarter_event_proxy(restarter_event_t *event)
512 {
513 boolean_t processed;
514
515 (void) pthread_mutex_lock(&rst_event_pipe_mtx);
516
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)
520 goto pipe_error;
521
522 /*
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.
529 */
530 if (safe_read(rst_event_pipe[PE_PRODUCER], &processed,
531 sizeof (processed)) != 0)
532 goto pipe_error;
533
534 (void) pthread_mutex_unlock(&rst_event_pipe_mtx);
535
536 return (processed ? 0 : EAGAIN);
537
538 pipe_error:
539 /*
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
542 * inetd exits.
543 */
544 error_msg(gettext("Can't process restarter events: %s"),
545 strerror(errno));
546 (void) close(rst_event_pipe[PE_PRODUCER]);
547 for (;;)
548 (void) pause();
549
550 /* NOTREACHED */
551 }
552
553 /*
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
556 * event.
557 */
558 static void
ack_restarter_event(boolean_t processed)559 ack_restarter_event(boolean_t processed)
560 {
561 /*
562 * If safe_write returns -1 something's seriously wrong with the event
563 * pipe, so start the shutdown proceedings.
564 */
565 if (safe_write(rst_event_pipe[PE_CONSUMER], &processed,
566 sizeof (processed)) == -1)
567 inetd_stop();
568 }
569
570 /*
571 * Switch the syslog identification string to 'ident'.
572 */
573 static void
change_syslog_ident(const char * ident)574 change_syslog_ident(const char *ident)
575 {
576 closelog();
577 openlog(ident, LOG_PID|LOG_CONS, LOG_DAEMON);
578 }
579
580 /*
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.
586 */
587 static boolean_t
tcp_wrappers_ok(instance_t * instance)588 tcp_wrappers_ok(instance_t *instance)
589 {
590 boolean_t rval = B_TRUE;
591 char *daemon_name;
592 basic_cfg_t *cfg = instance->config->basic;
593 struct request_info req;
594
595 /*
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.
601 */
602 if (cfg->do_tcp_wrappers && !cfg->iswait && !cfg->istlx) {
603
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;
608
609 /*
610 * Change the syslog message identity to the name of the
611 * daemon being wrapped, as opposed to "inetd".
612 */
613 change_syslog_ident(daemon_name);
614
615 (void) request_init(&req, RQ_DAEMON, daemon_name, RQ_FILE,
616 instance->conn_fd, NULL);
617 fromhost(&req);
618
619 if (strcasecmp(eval_hostname(req.client), paranoid) == 0) {
620 syslog(deny_severity,
621 "refused connect from %s (name/address mismatch)",
622 eval_client(&req));
623 if (req.sink != NULL)
624 req.sink(instance->conn_fd);
625 rval = B_FALSE;
626 } else if (!hosts_access(&req)) {
627 syslog(deny_severity,
628 "refused connect from %s (access denied)",
629 eval_client(&req));
630 if (req.sink != NULL)
631 req.sink(instance->conn_fd);
632 rval = B_FALSE;
633 } else {
634 syslog(allow_severity, "connect from %s",
635 eval_client(&req));
636 }
637
638 /* Revert syslog identity back to "inetd". */
639 change_syslog_ident(SYSLOG_IDENT);
640 }
641 return (rval);
642 }
643
644 /*
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
647 * time.
648 */
649 /* ARGSUSED */
650 static void
conn_rate_online(iu_tq_t * tq,void * arg)651 conn_rate_online(iu_tq_t *tq, void *arg)
652 {
653 instance_t *instance = arg;
654
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);
659 }
660
661 /*
662 * Check whether this instance in the offline state is in transition to
663 * another state and do the work to continue this transition.
664 */
665 void
process_offline_inst(instance_t * inst)666 process_offline_inst(instance_t *inst)
667 {
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);
674 /*
675 * If inetd is in the process of stopping, we don't want to enter
676 * any states but offline, disabled and maintenance.
677 */
678 } else if (!inetd_stopping) {
679 if (inst->conn_rate_exceeded) {
680 basic_cfg_t *cfg = inst->config->basic;
681
682 inst->conn_rate_exceeded = B_FALSE;
683 update_state(inst, IIS_OFFLINE_CONRATE, RERR_RESTART);
684 /*
685 * Schedule a timer to bring the instance out of the
686 * connection rate offline state.
687 */
688 inst->timer_id = iu_schedule_timer(timer_queue,
689 cfg->conn_rate_offline, conn_rate_online,
690 inst);
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);
696 }
697
698 } else if (copies_limit_exceeded(inst)) {
699 update_state(inst, IIS_OFFLINE_COPIES, RERR_RESTART);
700 }
701 }
702 }
703
704 /*
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.
707 */
708 static int
create_bound_socket(const instance_t * inst,socket_info_t * sock_info)709 create_bound_socket(const instance_t *inst, socket_info_t *sock_info)
710 {
711 int fd;
712 int on = 1;
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;
716
717 fd = socket(sock_info->local_addr.ss_family, sock_info->type,
718 sock_info->protocol);
719 if (fd < 0) {
720 error_msg(gettext(
721 "Socket creation failure for instance %s, proto %s: %s"),
722 fmri, proto, strerror(errno));
723 return (-1);
724 }
725
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));
729 (void) close(fd);
730 return (-1);
731 }
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));
740 (void) close(fd);
741 return (-1);
742 }
743 }
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,
750 strerror(errno));
751 (void) close(fd);
752 return (-1);
753 }
754 }
755
756 if (rpc != NULL)
757 SS_SETPORT(sock_info->local_addr, 0);
758
759 if (bind(fd, (struct sockaddr *)&(sock_info->local_addr),
760 SS_ADDRLEN(sock_info->local_addr)) < 0) {
761 error_msg(gettext(
762 "Failed to bind to the port of service instance %s, "
763 "proto %s: %s"), fmri, proto, strerror(errno));
764 (void) close(fd);
765 return (-1);
766 }
767
768 /*
769 * Retrieve and store the address bound to for RPC services.
770 */
771 if (rpc != NULL) {
772 struct sockaddr_storage ss;
773 int ss_size = sizeof (ss);
774
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));
778 (void) close(fd);
779 return (-1);
780 }
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);
785 }
786
787 if (sock_info->type == SOCK_STREAM) {
788 int qlen = inst->config->basic->conn_backlog;
789
790 debug_msg("Listening for service %s with backlog queue"
791 " size %d", fmri, qlen);
792 (void) listen(fd, qlen);
793 }
794
795 return (fd);
796 }
797
798 /*
799 * Handler registered with the timer queue code to retry the creation
800 * of a bound fd.
801 */
802 /* ARGSUSED */
803 static void
retry_bind(iu_tq_t * tq,void * arg)804 retry_bind(iu_tq_t *tq, void *arg)
805 {
806 instance_t *instance = arg;
807
808 switch (instance->cur_istate) {
809 case IIS_OFFLINE_BIND:
810 case IIS_ONLINE:
811 case IIS_DEGRADED:
812 case IIS_IN_ONLINE_METHOD:
813 case IIS_IN_REFRESH_METHOD:
814 break;
815 default:
816 #ifndef NDEBUG
817 (void) fprintf(stderr, "%s:%d: Unknown instance state %d.\n",
818 __FILE__, __LINE__, instance->cur_istate);
819 #endif
820 abort();
821 }
822
823 instance->bind_timer_id = -1;
824 create_bound_fds(instance);
825 }
826
827 /*
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.
832 */
833 int
poll_bound_fds(instance_t * instance,boolean_t listen,char * proto_name)834 poll_bound_fds(instance_t *instance, boolean_t listen, char *proto_name)
835 {
836 basic_cfg_t *cfg = instance->config->basic;
837 proto_info_t *pi;
838 int ret = 0;
839
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,
848 POLLIN) == -1) {
849 ret = -1;
850 }
851 }
852 }
853 }
854
855 return (ret);
856 }
857
858 /*
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.
861 */
862 static void
handle_bind_failure(instance_t * instance)863 handle_bind_failure(instance_t *instance)
864 {
865 basic_cfg_t *cfg = instance->config->basic;
866
867 /*
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
870 * the work.
871 */
872 if (instance->bind_timer_id != -1)
873 return;
874
875 /*
876 * Check if the rebind retries limit is operative and if so,
877 * if it has been reached.
878 */
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)) {
884 proto_info_t *pi;
885
886 instance->bind_fail_count = 0;
887
888 switch (instance->cur_istate) {
889 case IIS_DEGRADED:
890 case IIS_ONLINE:
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))
896 break;
897 }
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"),
902 instance->fmri);
903 update_state(instance, IIS_DEGRADED, RERR_NONE);
904 instance->bind_retries_exceeded = B_TRUE;
905 break;
906 }
907
908 destroy_bound_fds(instance);
909 /*
910 * In the case we failed the 'bind' because set_pollfd()
911 * failed on all bound fds, use the offline handling.
912 */
913 /* FALLTHROUGH */
914 case IIS_OFFLINE:
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,
919 RERR_FAULT);
920 break;
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);
926 /*
927 * Set the retries exceeded flag so when the method
928 * completes the instance goes to the degraded state.
929 */
930 instance->bind_retries_exceeded = B_TRUE;
931 break;
932 default:
933 #ifndef NDEBUG
934 (void) fprintf(stderr,
935 "%s:%d: Unknown instance state %d.\n",
936 __FILE__, __LINE__, instance->cur_istate);
937 #endif
938 abort();
939 }
940 } else if (instance->cur_istate == IIS_OFFLINE) {
941 /*
942 * bind re-scheduled, so if we're offline reflect this in the
943 * state.
944 */
945 update_state(instance, IIS_OFFLINE_BIND, RERR_NONE);
946 }
947 }
948
949
950 /*
951 * Check if two transport protocols for RPC conflict.
952 */
953
954 boolean_t
is_rpc_proto_conflict(const char * proto0,const char * proto1)955 is_rpc_proto_conflict(const char *proto0, const char *proto1) {
956 if (strcmp(proto0, "tcp") == 0) {
957 if (strcmp(proto1, "tcp") == 0)
958 return (B_TRUE);
959 if (strcmp(proto1, "tcp6") == 0)
960 return (B_TRUE);
961 return (B_FALSE);
962 }
963
964 if (strcmp(proto0, "tcp6") == 0) {
965 if (strcmp(proto1, "tcp") == 0)
966 return (B_TRUE);
967 if (strcmp(proto1, "tcp6only") == 0)
968 return (B_TRUE);
969 if (strcmp(proto1, "tcp6") == 0)
970 return (B_TRUE);
971 return (B_FALSE);
972 }
973
974 if (strcmp(proto0, "tcp6only") == 0) {
975 if (strcmp(proto1, "tcp6only") == 0)
976 return (B_TRUE);
977 if (strcmp(proto1, "tcp6") == 0)
978 return (B_TRUE);
979 return (B_FALSE);
980 }
981
982 if (strcmp(proto0, "udp") == 0) {
983 if (strcmp(proto1, "udp") == 0)
984 return (B_TRUE);
985 if (strcmp(proto1, "udp6") == 0)
986 return (B_TRUE);
987 return (B_FALSE);
988 }
989
990 if (strcmp(proto0, "udp6") == 0) {
991
992 if (strcmp(proto1, "udp") == 0)
993 return (B_TRUE);
994 if (strcmp(proto1, "udp6only") == 0)
995 return (B_TRUE);
996 if (strcmp(proto1, "udp6") == 0)
997 return (B_TRUE);
998 return (B_FALSE);
999 }
1000
1001 if (strcmp(proto0, "udp6only") == 0) {
1002
1003 if (strcmp(proto1, "udp6only") == 0)
1004 return (B_TRUE);
1005 if (strcmp(proto1, "udp6") == 0)
1006 return (B_TRUE);
1007 return (0);
1008 }
1009
1010 /*
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
1013 * comparison.
1014 */
1015
1016 if (strcmp(proto0, proto1))
1017 return (FALSE);
1018
1019 return (B_TRUE);
1020 }
1021
1022
1023 /*
1024 * Check if inetd thinks this RPC program number is already registered.
1025 *
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.
1030 */
1031
1032 boolean_t
is_rpc_num_in_use(int rpc_n,char * proto,int lowver,int highver)1033 is_rpc_num_in_use(int rpc_n, char *proto, int lowver, int highver) {
1034 instance_t *i;
1035 basic_cfg_t *cfg;
1036 proto_info_t *pi;
1037
1038 for (i = uu_list_first(instance_list); i != NULL;
1039 i = uu_list_next(instance_list, i)) {
1040
1041 if (i->cur_istate != IIS_ONLINE)
1042 continue;
1043 cfg = i->config->basic;
1044
1045 for (pi = uu_list_first(cfg->proto_list); pi != NULL;
1046 pi = uu_list_next(cfg->proto_list, pi)) {
1047
1048 if (pi->ri == NULL)
1049 continue;
1050 if (pi->ri->prognum != rpc_n)
1051 continue;
1052 if (!is_rpc_proto_conflict(pi->proto, proto))
1053 continue;
1054 if ((lowver < pi->ri->lowver &&
1055 highver < pi->ri->lowver) ||
1056 (lowver > pi->ri->highver &&
1057 highver > pi->ri->highver))
1058 continue;
1059 return (B_TRUE);
1060 }
1061 }
1062 return (B_FALSE);
1063 }
1064
1065
1066 /*
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().
1074 */
1075 void
create_bound_fds(instance_t * instance)1076 create_bound_fds(instance_t *instance)
1077 {
1078 basic_cfg_t *cfg = instance->config->basic;
1079 boolean_t failure = B_FALSE;
1080 boolean_t success = B_FALSE;
1081 proto_info_t *pi;
1082
1083 /*
1084 * Loop through and try and bind any unbound protos.
1085 */
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)
1089 continue;
1090 if (cfg->istlx) {
1091 pi->listen_fd = create_bound_endpoint(instance,
1092 (tlx_info_t *)pi);
1093 } else {
1094 /*
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.
1101 */
1102 void *p = pi;
1103 pi->listen_fd = create_bound_socket(instance,
1104 (socket_info_t *)p);
1105 }
1106 if (pi->listen_fd == -1) {
1107 failure = B_TRUE;
1108 continue;
1109 }
1110
1111 if (pi->ri != NULL) {
1112
1113 /*
1114 * Don't register the same RPC program number twice.
1115 * Doing so silently discards the old service
1116 * without causing an error.
1117 */
1118 if (is_rpc_num_in_use(pi->ri->prognum, pi->proto,
1119 pi->ri->lowver, pi->ri->highver)) {
1120 failure = B_TRUE;
1121 close_net_fd(instance, pi->listen_fd);
1122 pi->listen_fd = -1;
1123 continue;
1124 }
1125
1126 unregister_rpc_service(instance->fmri, pi->ri);
1127 if (register_rpc_service(instance->fmri, pi->ri) ==
1128 -1) {
1129 close_net_fd(instance, pi->listen_fd);
1130 pi->listen_fd = -1;
1131 failure = B_TRUE;
1132 continue;
1133 }
1134 }
1135
1136 success = B_TRUE;
1137 }
1138
1139 switch (instance->cur_istate) {
1140 case IIS_OFFLINE:
1141 case IIS_OFFLINE_BIND:
1142 /*
1143 * If we've managed to bind at least one proto lets run the
1144 * online method, so we can start listening for it.
1145 */
1146 if (success && run_method(instance, IM_ONLINE, NULL) == -1)
1147 return; /* instance gone to maintenance */
1148 break;
1149 case IIS_ONLINE:
1150 case IIS_IN_REFRESH_METHOD:
1151 /*
1152 * We're 'online', so start polling on any bound fds we're
1153 * currently not.
1154 */
1155 if (poll_bound_fds(instance, B_TRUE, NULL) != 0) {
1156 failure = B_TRUE;
1157 } else if (!failure) {
1158 /*
1159 * We've successfully bound and poll'd upon all protos,
1160 * so reset the failure count.
1161 */
1162 instance->bind_fail_count = 0;
1163 }
1164 break;
1165 case IIS_IN_ONLINE_METHOD:
1166 /*
1167 * Nothing to do here as the method completion code will start
1168 * listening for any successfully bound fds.
1169 */
1170 break;
1171 default:
1172 #ifndef NDEBUG
1173 (void) fprintf(stderr, "%s:%d: Unknown instance state %d.\n",
1174 __FILE__, __LINE__, instance->cur_istate);
1175 #endif
1176 abort();
1177 }
1178
1179 if (failure)
1180 handle_bind_failure(instance);
1181 }
1182
1183 /*
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.
1187 */
1188 static void
destroy_bound_fds(instance_t * instance)1189 destroy_bound_fds(instance_t *instance)
1190 {
1191 basic_cfg_t *cfg = instance->config->basic;
1192 proto_info_t *pi;
1193
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) {
1197 if (pi->ri != NULL)
1198 unregister_rpc_service(instance->fmri, pi->ri);
1199 clear_pollfd(pi->listen_fd);
1200 close_net_fd(instance, pi->listen_fd);
1201 pi->listen_fd = -1;
1202 }
1203 }
1204
1205 /* cancel any bind retries */
1206 if (instance->bind_timer_id != -1)
1207 cancel_bind_timer(instance);
1208
1209 instance->bind_retries_exceeded = B_FALSE;
1210 }
1211
1212 /*
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.
1218 */
1219 static char **
expand_address(instance_t * inst,const proto_info_t * pi)1220 expand_address(instance_t *inst, const proto_info_t *pi)
1221 {
1222 static char addrbuf[sizeof ("ffffffff.65536")];
1223 static char *ret[3];
1224 instance_cfg_t *cfg = inst->config;
1225 /*
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.
1231 */
1232 const void *p = pi;
1233
1234 /* set ret[0] to the basename of exec path */
1235 if ((ret[0] = strrchr(cfg->methods[IM_START]->exec_path, '/'))
1236 != NULL) {
1237 ret[0]++;
1238 } else {
1239 ret[0] = cfg->methods[IM_START]->exec_path;
1240 }
1241
1242 if (!cfg->basic->istlx &&
1243 (((socket_info_t *)p)->type == SOCK_DGRAM)) {
1244 ret[1] = NULL;
1245 } else {
1246 addrbuf[0] = '\0';
1247 if (!cfg->basic->iswait &&
1248 (inst->remote_addr.ss_family == AF_INET)) {
1249 struct sockaddr_in *sp;
1250
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));
1254 }
1255 ret[1] = addrbuf;
1256 ret[2] = NULL;
1257 }
1258
1259 return (ret);
1260 }
1261
1262 /*
1263 * Returns the state associated with the supplied method being run for an
1264 * instance.
1265 */
1266 static internal_inst_state_t
get_method_state(instance_method_t method)1267 get_method_state(instance_method_t method)
1268 {
1269 state_info_t *sip;
1270
1271 for (sip = states; sip->istate != IIS_NONE; sip++) {
1272 if (sip->method_running == method)
1273 break;
1274 }
1275 assert(sip->istate != IIS_NONE);
1276
1277 return (sip->istate);
1278 }
1279
1280 /*
1281 * Store the method's PID and CID in the repository. If the store fails
1282 * we ignore it and just drive on.
1283 */
1284 static void
add_method_ids(instance_t * ins,pid_t pid,ctid_t cid,instance_method_t mthd)1285 add_method_ids(instance_t *ins, pid_t pid, ctid_t cid, instance_method_t mthd)
1286 {
1287 if (cid != -1)
1288 (void) add_remove_contract(ins, B_TRUE, cid);
1289
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);
1294 }
1295 } else {
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);
1299 }
1300 }
1301 }
1302
1303 /*
1304 * Remove the method's PID and CID from the repository. If the removal
1305 * fails we ignore it and drive on.
1306 */
1307 void
remove_method_ids(instance_t * inst,pid_t pid,ctid_t cid,instance_method_t mthd)1308 remove_method_ids(instance_t *inst, pid_t pid, ctid_t cid,
1309 instance_method_t mthd)
1310 {
1311 if (cid != -1)
1312 (void) add_remove_contract(inst, B_FALSE, cid);
1313
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);
1318 } else {
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);
1322 }
1323 }
1324
1325 static instance_t *
create_instance(const char * fmri)1326 create_instance(const char *fmri)
1327 {
1328 instance_t *ret;
1329
1330 if (((ret = calloc(1, sizeof (instance_t))) == NULL) ||
1331 ((ret->fmri = strdup(fmri)) == NULL))
1332 goto alloc_fail;
1333
1334 ret->conn_fd = -1;
1335
1336 ret->copies = 0;
1337
1338 ret->conn_rate_count = 0;
1339 ret->fail_rate_count = 0;
1340 ret->bind_fail_count = 0;
1341
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))
1345 goto alloc_fail;
1346
1347 ret->cur_istate = IIS_NONE;
1348 ret->next_istate = IIS_NONE;
1349
1350 if (((ret->cur_istate_rep = create_rep_val_list()) == NULL) ||
1351 ((ret->next_istate_rep = create_rep_val_list()) == NULL))
1352 goto alloc_fail;
1353
1354 ret->config = NULL;
1355 ret->new_config = NULL;
1356
1357 ret->timer_id = -1;
1358 ret->bind_timer_id = -1;
1359
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;
1364
1365 ret->pending_rst_event = RESTARTER_EVENT_TYPE_INVALID;
1366
1367 return (ret);
1368
1369 alloc_fail:
1370 error_msg(strerror(errno));
1371 destroy_instance(ret);
1372 return (NULL);
1373 }
1374
1375 static void
destroy_instance(instance_t * inst)1376 destroy_instance(instance_t *inst)
1377 {
1378 if (inst == NULL)
1379 return;
1380
1381 destroy_instance_cfg(inst->config);
1382 destroy_instance_cfg(inst->new_config);
1383
1384 destroy_rep_val_list(inst->cur_istate_rep);
1385 destroy_rep_val_list(inst->next_istate_rep);
1386
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);
1390
1391 free(inst->fmri);
1392
1393 free(inst);
1394 }
1395
1396 /*
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.
1404 */
1405 static scf_error_t
retrieve_instance_state(instance_t * inst)1406 retrieve_instance_state(instance_t *inst)
1407 {
1408 scf_error_t ret;
1409
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) {
1416 error_msg(gettext(
1417 "Failed to read state of instance %s: %s"),
1418 inst->fmri, scf_strerror(scf_error()));
1419 return (ret);
1420 }
1421
1422 debug_msg("instance with no previous int state - "
1423 "setting state to uninitialized");
1424
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);
1430 }
1431 }
1432
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);
1436 return (0);
1437 }
1438
1439 /*
1440 * Retrieve stored process ids and register each of them so we process their
1441 * termination.
1442 */
1443 static int
retrieve_method_pids(instance_t * inst)1444 retrieve_method_pids(instance_t *inst)
1445 {
1446 rep_val_t *rv;
1447
1448 switch (retrieve_rep_vals(inst->start_pids, inst->fmri,
1449 PR_NAME_START_PIDS)) {
1450 case 0:
1451 break;
1452 case SCF_ERROR_NOT_FOUND:
1453 return (0);
1454 default:
1455 error_msg(gettext("Failed to retrieve the start pids of "
1456 "instance %s from repository: %s"), inst->fmri,
1457 scf_strerror(scf_error()));
1458 return (-1);
1459 }
1460
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) {
1465 inst->copies++;
1466 rv = uu_list_next(inst->start_pids, rv);
1467 } else if (errno == ENOENT) {
1468 pid_t pid = (pid_t)rv->val;
1469
1470 /*
1471 * The process must have already terminated. Remove
1472 * it from the list.
1473 */
1474 rv = uu_list_next(inst->start_pids, rv);
1475 remove_rep_val(inst->start_pids, pid);
1476 } else {
1477 error_msg(gettext("Failed to listen for the completion "
1478 "of %s method of instance %s"), START_METHOD_NAME,
1479 inst->fmri);
1480 rv = uu_list_next(inst->start_pids, rv);
1481 }
1482 }
1483
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);
1486
1487 return (0);
1488 }
1489
1490 /*
1491 * Remove the passed instance from inetd control.
1492 */
1493 static void
remove_instance(instance_t * instance)1494 remove_instance(instance_t *instance)
1495 {
1496 switch (instance->cur_istate) {
1497 case IIS_ONLINE:
1498 case IIS_DEGRADED:
1499 /* stop listening for network connections */
1500 destroy_bound_fds(instance);
1501 break;
1502 case IIS_OFFLINE_BIND:
1503 cancel_bind_timer(instance);
1504 break;
1505 case IIS_OFFLINE_CONRATE:
1506 cancel_inst_timer(instance);
1507 break;
1508 }
1509
1510 /* stop listening for terminated methods */
1511 unregister_instance_methods(instance);
1512
1513 uu_list_remove(instance_list, instance);
1514 destroy_instance(instance);
1515 }
1516
1517 /*
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.
1522 */
1523 void
refresh_instance(instance_t * inst)1524 refresh_instance(instance_t *inst)
1525 {
1526 instance_cfg_t *cfg;
1527
1528 switch (inst->cur_istate) {
1529 case IIS_MAINTENANCE:
1530 case IIS_DISABLED:
1531 case IIS_UNINITIALIZED:
1532 /*
1533 * Ignore any possible changes, we'll re-read the configuration
1534 * automatically when we exit these states.
1535 */
1536 break;
1537
1538 case IIS_OFFLINE_COPIES:
1539 case IIS_OFFLINE_BIND:
1540 case IIS_OFFLINE:
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);
1549 }
1550 update_state(inst, IIS_MAINTENANCE, RERR_FAULT);
1551 } else {
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);
1557
1558 /*
1559 * Take the instance to the copies
1560 * offline state, via the offline
1561 * state.
1562 */
1563 update_state(inst, IIS_OFFLINE,
1564 RERR_RESTART);
1565 process_offline_inst(inst);
1566 }
1567 break;
1568
1569 case IIS_OFFLINE:
1570 process_offline_inst(inst);
1571 break;
1572
1573 case IIS_OFFLINE_CONRATE:
1574 /*
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().
1580 */
1581 break;
1582
1583 case IIS_OFFLINE_COPIES:
1584 /*
1585 * Check if the copies limit has been increased
1586 * above the current count.
1587 */
1588 if (!copies_limit_exceeded(inst)) {
1589 update_state(inst, IIS_OFFLINE,
1590 RERR_RESTART);
1591 process_offline_inst(inst);
1592 }
1593 break;
1594
1595 default:
1596 assert(0);
1597 }
1598 }
1599 break;
1600
1601 case IIS_DEGRADED:
1602 case IIS_ONLINE:
1603 if ((cfg = read_instance_cfg(inst->fmri)) != NULL) {
1604 instance_cfg_t *ocfg = inst->config;
1605
1606 /*
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
1615 * the instance.
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.
1626 */
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);
1633
1634 assert(inst->new_config == NULL);
1635 inst->new_config = cfg;
1636
1637 (void) run_method(inst, IM_OFFLINE, NULL);
1638 } else { /* no bind config / method changes */
1639
1640 /*
1641 * swap the proto list over from the old
1642 * configuration to the new, so we retain
1643 * our set of network fds.
1644 */
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);
1650 inst->config = cfg;
1651
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,
1656 NULL);
1657 } else {
1658 /*
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.
1666 */
1667 (void) run_method(inst, IM_REFRESH,
1668 NULL);
1669 }
1670 }
1671 } else {
1672 log_invalid_cfg(inst->fmri);
1673
1674 destroy_bound_fds(inst);
1675
1676 inst->maintenance_req = B_TRUE;
1677 (void) run_method(inst, IM_OFFLINE, NULL);
1678 }
1679 break;
1680
1681 default:
1682 debug_msg("Unhandled current state %d for instance in "
1683 "refresh_instance", inst->cur_istate);
1684 assert(0);
1685 }
1686 }
1687
1688 /*
1689 * Called by process_restarter_event() to handle a restarter event for an
1690 * instance.
1691 */
1692 static void
handle_restarter_event(instance_t * instance,restarter_event_type_t event,boolean_t send_ack)1693 handle_restarter_event(instance_t *instance, restarter_event_type_t event,
1694 boolean_t send_ack)
1695 {
1696 switch (event) {
1697 case RESTARTER_EVENT_TYPE_ADD_INSTANCE:
1698 /*
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
1703 * restarting.
1704 * update_state() is ok to be called here, as commands for
1705 * instances in transition are deferred by
1706 * process_restarter_event().
1707 */
1708 update_state(instance, instance->cur_istate, RERR_NONE);
1709 goto done;
1710 case RESTARTER_EVENT_TYPE_ADMIN_REFRESH:
1711 refresh_instance(instance);
1712 goto done;
1713 case RESTARTER_EVENT_TYPE_ADMIN_RESTART:
1714 /*
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
1718 * it back online.
1719 */
1720 switch (instance->cur_istate) {
1721 case IIS_ONLINE:
1722 case IIS_DEGRADED:
1723 destroy_bound_fds(instance);
1724 (void) run_method(instance, IM_OFFLINE, NULL);
1725 }
1726 goto done;
1727 case RESTARTER_EVENT_TYPE_REMOVE_INSTANCE:
1728 remove_instance(instance);
1729 goto done;
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:
1736 /*
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
1740 * state.
1741 */
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);
1747 }
1748 update_state(instance, IIS_OFFLINE, RERR_RESTART);
1749 goto done;
1750 }
1751 break;
1752 }
1753
1754 switch (instance->cur_istate) {
1755 case IIS_OFFLINE:
1756 switch (event) {
1757 case RESTARTER_EVENT_TYPE_START:
1758 /*
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.
1764 */
1765 if (!(instance->config->basic->iswait &&
1766 (uu_list_first(instance->start_pids) != NULL))) {
1767 create_bound_fds(instance);
1768 } else {
1769 update_state(instance, IIS_ONLINE, RERR_NONE);
1770 }
1771 break;
1772 case RESTARTER_EVENT_TYPE_DISABLE:
1773 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1774 /*
1775 * The instance should be disabled, so run the
1776 * instance's disabled method that will do the work
1777 * to take it there.
1778 */
1779 (void) run_method(instance, IM_DISABLE, NULL);
1780 break;
1781 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1782 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1783 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1784 /*
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.
1788 */
1789 update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1790 break;
1791 }
1792 break;
1793
1794 case IIS_OFFLINE_BIND:
1795 switch (event) {
1796 case RESTARTER_EVENT_TYPE_DISABLE:
1797 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1798 /*
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
1804 * disabled.
1805 */
1806 cancel_bind_timer(instance);
1807 update_state(instance, IIS_OFFLINE, RERR_RESTART);
1808 (void) run_method(instance, IM_DISABLE, NULL);
1809 break;
1810 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1811 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1812 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1813 /*
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.
1818 */
1819 cancel_bind_timer(instance);
1820 update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1821 break;
1822 }
1823 break;
1824
1825 case IIS_DEGRADED:
1826 case IIS_ONLINE:
1827 switch (event) {
1828 case RESTARTER_EVENT_TYPE_DISABLE:
1829 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1830 /*
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.
1834 */
1835 destroy_bound_fds(instance);
1836 /*
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.
1840 */
1841 instance->disable_req = B_TRUE;
1842 (void) run_method(instance, IM_OFFLINE, NULL);
1843 break;
1844 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1845 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1846 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1847 /*
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
1855 * state.
1856 */
1857 instance->maintenance_req = B_TRUE;
1858 /* FALLTHROUGH */
1859 case RESTARTER_EVENT_TYPE_STOP_RESET:
1860 case RESTARTER_EVENT_TYPE_STOP:
1861 /*
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.
1866 */
1867 destroy_bound_fds(instance);
1868 (void) run_method(instance, IM_OFFLINE, NULL);
1869 }
1870 break;
1871
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);
1876 break;
1877 } else if (event != RESTARTER_EVENT_TYPE_ENABLE) {
1878 /*
1879 * Ignore other events until we know whether we're
1880 * enabled or not.
1881 */
1882 break;
1883 }
1884
1885 /*
1886 * We've got an enabled event; make use of the handling in the
1887 * disable case.
1888 */
1889 /* FALLTHROUGH */
1890
1891 case IIS_DISABLED:
1892 switch (event) {
1893 case RESTARTER_EVENT_TYPE_ENABLE:
1894 /*
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.
1899 */
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,
1904 RERR_RESTART);
1905 process_offline_inst(instance);
1906 } else {
1907 log_invalid_cfg(instance->fmri);
1908 update_state(instance, IIS_MAINTENANCE,
1909 RERR_RESTART);
1910 }
1911
1912 break;
1913 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1914 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1915 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1916 /*
1917 * The master restarter has requested the instance be
1918 * placed in the maintenance state, so just update its
1919 * state to maintenance.
1920 */
1921 update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1922 break;
1923 }
1924 break;
1925
1926 case IIS_MAINTENANCE:
1927 switch (event) {
1928 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_OFF:
1929 case RESTARTER_EVENT_TYPE_ADMIN_DISABLE:
1930 /*
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
1935 * from there.
1936 */
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,
1941 RERR_RESTART);
1942 process_offline_inst(instance);
1943 } else {
1944 boolean_t enabled;
1945
1946 /*
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.
1958 */
1959 if ((read_enable_merged(instance->fmri,
1960 &enabled) == 0) && !enabled) {
1961 update_state(instance, IIS_DISABLED,
1962 RERR_RESTART);
1963 } else {
1964 log_invalid_cfg(instance->fmri);
1965 update_state(instance, IIS_MAINTENANCE,
1966 RERR_FAULT);
1967 }
1968 }
1969 break;
1970 }
1971 break;
1972
1973 case IIS_OFFLINE_CONRATE:
1974 switch (event) {
1975 case RESTARTER_EVENT_TYPE_DISABLE:
1976 /*
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.
1981 */
1982 cancel_inst_timer(instance);
1983 update_state(instance, IIS_OFFLINE, RERR_RESTART);
1984 (void) run_method(instance, IM_DISABLE, NULL);
1985 break;
1986 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
1987 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
1988 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
1989 /*
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
1993 * maintenance.
1994 */
1995 cancel_inst_timer(instance);
1996 update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
1997 break;
1998 }
1999 break;
2000
2001 case IIS_OFFLINE_COPIES:
2002 switch (event) {
2003 case RESTARTER_EVENT_TYPE_DISABLE:
2004 /*
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.
2008 */
2009 update_state(instance, IIS_OFFLINE, RERR_RESTART);
2010 (void) run_method(instance, IM_DISABLE, NULL);
2011 break;
2012 case RESTARTER_EVENT_TYPE_ADMIN_MAINT_ON:
2013 case RESTARTER_EVENT_TYPE_DEPENDENCY_CYCLE:
2014 case RESTARTER_EVENT_TYPE_INVALID_DEPENDENCY:
2015 /*
2016 * The master restarter has requested the instance be
2017 * placed in maintenance. Since it's already offline
2018 * simply update the state.
2019 */
2020 update_state(instance, IIS_MAINTENANCE, RERR_RESTART);
2021 break;
2022 }
2023 break;
2024
2025 default:
2026 debug_msg("handle_restarter_event: instance in an "
2027 "unexpected state");
2028 assert(0);
2029 }
2030
2031 done:
2032 if (send_ack)
2033 ack_restarter_event(B_TRUE);
2034 }
2035
2036 /*
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.
2043 */
2044 static int
process_restarter_event(void)2045 process_restarter_event(void)
2046 {
2047 char *fmri;
2048 size_t fmri_size;
2049 restarter_event_type_t event_type;
2050 instance_t *instance;
2051 restarter_event_t *event;
2052 ssize_t sz;
2053
2054 /*
2055 * Try to read an event pointer from the event pipe.
2056 */
2057 errno = 0;
2058 switch (safe_read(rst_event_pipe[PE_CONSUMER], &event,
2059 sizeof (event))) {
2060 case 0:
2061 break;
2062 case 1:
2063 if (errno == EAGAIN) /* no event to read */
2064 return (-1);
2065
2066 /* other end of pipe closed */
2067
2068 /* FALLTHROUGH */
2069 default: /* unexpected read error */
2070 /*
2071 * There's something wrong with the event pipe. Let's
2072 * shutdown and be restarted.
2073 */
2074 inetd_stop();
2075 return (-1);
2076 }
2077
2078 /*
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
2081 * list to manage.
2082 */
2083
2084 fmri_size = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
2085 if ((fmri = malloc(fmri_size)) == NULL) {
2086 error_msg(strerror(errno));
2087 goto fail;
2088 }
2089 sz = restarter_event_get_instance(event, fmri, fmri_size);
2090 if (sz >= fmri_size)
2091 assert(0);
2092
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)
2096 break;
2097 }
2098
2099 if (instance == NULL) {
2100 int err;
2101
2102 debug_msg("New instance to manage: %s", fmri);
2103
2104 if (((instance = create_instance(fmri)) == NULL) ||
2105 (retrieve_instance_state(instance) != 0) ||
2106 (retrieve_method_pids(instance) != 0)) {
2107 destroy_instance(instance);
2108 free(fmri);
2109 goto fail;
2110 }
2111
2112 if (((err = iterate_repository_contracts(instance, 0))
2113 != 0) && (err != ENOENT)) {
2114 error_msg(gettext(
2115 "Failed to adopt contracts of instance %s: %s"),
2116 instance->fmri, strerror(err));
2117 destroy_instance(instance);
2118 free(fmri);
2119 goto fail;
2120 }
2121
2122 uu_list_node_init(instance, &instance->link, instance_pool);
2123 (void) uu_list_insert_after(instance_list, NULL, instance);
2124
2125 /*
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.
2129 */
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,
2137 RERR_FAULT);
2138 }
2139 }
2140 }
2141
2142 free(fmri);
2143
2144 event_type = restarter_event_get_type(event);
2145 debug_msg("Event type: %d for instance: %s", event_type,
2146 instance->fmri);
2147
2148 /*
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.
2152 */
2153 if (INST_IN_TRANSITION(instance)) {
2154 debug_msg("storing event %d for instance %s", event_type,
2155 instance->fmri);
2156 instance->pending_rst_event = event_type;
2157 } else {
2158 handle_restarter_event(instance, event_type, B_TRUE);
2159 }
2160
2161 return (0);
2162
2163 fail:
2164 ack_restarter_event(B_FALSE);
2165 return (-1);
2166 }
2167
2168 /*
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
2171 * NULL.
2172 */
2173 void
process_start_term(instance_t * inst,char * proto_name)2174 process_start_term(instance_t *inst, char *proto_name)
2175 {
2176 basic_cfg_t *cfg;
2177
2178 inst->copies--;
2179
2180 if ((inst->cur_istate == IIS_MAINTENANCE) ||
2181 (inst->cur_istate == IIS_DISABLED)) {
2182 /* do any further processing/checks when we exit these states */
2183 return;
2184 }
2185
2186 cfg = inst->config->basic;
2187
2188 if (cfg->iswait) {
2189 proto_info_t *pi;
2190 boolean_t listen;
2191
2192 switch (inst->cur_istate) {
2193 case IIS_ONLINE:
2194 case IIS_DEGRADED:
2195 case IIS_IN_REFRESH_METHOD:
2196 /*
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.
2203 */
2204 listen = B_FALSE;
2205 for (pi = uu_list_first(cfg->proto_list); pi != NULL;
2206 pi = uu_list_next(cfg->proto_list, pi)) {
2207 /*
2208 * If a bound fd exists, the method was fired
2209 * off during this inetd's lifetime.
2210 */
2211 if (pi->listen_fd != -1) {
2212 listen = B_TRUE;
2213 if (proto_name == NULL ||
2214 strcmp(pi->proto, proto_name) == 0)
2215 break;
2216 }
2217 }
2218 if (pi != NULL) {
2219 if (poll_bound_fds(inst, B_TRUE, proto_name) !=
2220 0)
2221 handle_bind_failure(inst);
2222 } else if (listen == B_FALSE) {
2223 update_state(inst, IIS_OFFLINE, RERR_RESTART);
2224 create_bound_fds(inst);
2225 }
2226 }
2227 } else {
2228 /*
2229 * Check if a nowait service should be brought back online
2230 * after exceeding its copies limit.
2231 */
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);
2236 }
2237 }
2238 }
2239
2240 /*
2241 * If the instance has a pending event process it and initiate the
2242 * acknowledgement.
2243 */
2244 static void
process_pending_rst_event(instance_t * inst)2245 process_pending_rst_event(instance_t *inst)
2246 {
2247 if (inst->pending_rst_event != RESTARTER_EVENT_TYPE_INVALID) {
2248 restarter_event_type_t re;
2249
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);
2255 }
2256 }
2257
2258 /*
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.
2263 */
2264 void
process_non_start_term(instance_t * inst,int status)2265 process_non_start_term(instance_t *inst, int status)
2266 {
2267 boolean_t ran_online_method = B_FALSE;
2268
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,
2273 inst->fmri);
2274
2275 if ((inst->cur_istate == IIS_IN_ONLINE_METHOD) ||
2276 (inst->cur_istate == IIS_IN_REFRESH_METHOD))
2277 destroy_bound_fds(inst);
2278
2279 update_state(inst, IIS_MAINTENANCE, RERR_FAULT);
2280
2281 inst->maintenance_req = B_FALSE;
2282 inst->conn_rate_exceeded = B_FALSE;
2283
2284 if (inst->new_config != NULL) {
2285 destroy_instance_cfg(inst->new_config);
2286 inst->new_config = NULL;
2287 }
2288
2289 if (!inetd_stopping)
2290 process_pending_rst_event(inst);
2291
2292 return;
2293 }
2294
2295 /* non-failure method return */
2296
2297 if (status != IMRET_SUCCESS) {
2298 /*
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.
2302 */
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);
2307 }
2308
2309 /*
2310 * Update the state from the in-transition state.
2311 */
2312 switch (inst->cur_istate) {
2313 case IIS_IN_ONLINE_METHOD:
2314 ran_online_method = B_TRUE;
2315 /* FALLTHROUGH */
2316 case IIS_IN_REFRESH_METHOD:
2317 /*
2318 * If we've exhausted the bind retries, flag that by setting
2319 * the instance's state to degraded.
2320 */
2321 if (inst->bind_retries_exceeded) {
2322 update_state(inst, IIS_DEGRADED, RERR_NONE);
2323 break;
2324 }
2325 /* FALLTHROUGH */
2326 default:
2327 update_state(inst,
2328 methods[states[inst->cur_istate].method_running].dst_state,
2329 RERR_NONE);
2330 }
2331
2332 if (inst->cur_istate == IIS_OFFLINE) {
2333 if (inst->new_config != NULL) {
2334 /*
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.
2339 */
2340 destroy_instance_cfg(inst->config);
2341 inst->config = inst->new_config;
2342 inst->new_config = NULL;
2343 }
2344
2345 /* continue/complete any transitions that are in progress */
2346 process_offline_inst(inst);
2347
2348 } else if (ran_online_method) {
2349 /*
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.
2354 */
2355 if (poll_bound_fds(inst, B_TRUE, NULL) != 0)
2356 handle_bind_failure(inst);
2357 }
2358
2359 /*
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.
2363 */
2364 if (!INST_IN_TRANSITION(inst)) {
2365 if (inetd_stopping) {
2366 if (!instance_stopped(inst)) {
2367 /*
2368 * inetd is stopping, and this instance hasn't
2369 * been stopped. Inject a stop event.
2370 */
2371 handle_restarter_event(inst,
2372 RESTARTER_EVENT_TYPE_STOP, B_FALSE);
2373 }
2374 } else {
2375 process_pending_rst_event(inst);
2376 }
2377 }
2378 }
2379
2380 /*
2381 * Check if configuration file specified is readable. If not return B_FALSE,
2382 * else return B_TRUE.
2383 */
2384 static boolean_t
can_read_file(const char * path)2385 can_read_file(const char *path)
2386 {
2387 int ret;
2388 int serrno;
2389
2390 do {
2391 ret = access(path, R_OK);
2392 } while ((ret < 0) && (errno == EINTR));
2393 if (ret < 0) {
2394 if (errno != ENOENT) {
2395 serrno = errno;
2396 error_msg(gettext("Failed to access configuration "
2397 "file %s for performing modification checks: %s"),
2398 path, strerror(errno));
2399 errno = serrno;
2400 }
2401 return (B_FALSE);
2402 }
2403 return (B_TRUE);
2404 }
2405
2406 /*
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.
2410 */
2411 static void
check_conf_file(void)2412 check_conf_file(void)
2413 {
2414 char *new_hash;
2415 char *old_hash = NULL;
2416 scf_error_t ret;
2417 const char *file;
2418
2419 if (conf_file == NULL) {
2420 /*
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.
2424 */
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;
2430 } else {
2431 return;
2432 }
2433 } else {
2434 file = conf_file;
2435 if (!can_read_file(file))
2436 return;
2437 }
2438
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 */
2444 warn_msg(gettext(
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));
2454 }
2455 free(old_hash);
2456 free(new_hash);
2457 } else {
2458 error_msg(gettext("Failed to check whether configuration file "
2459 "%s has been modified: %s"), file, strerror(errno));
2460 }
2461 }
2462
2463 /*
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
2469 * snapshot.
2470 */
2471 static void
inetd_refresh(void)2472 inetd_refresh(void)
2473 {
2474 instance_t *inst;
2475
2476 refresh_debug_flag();
2477
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()));
2484 }
2485 }
2486
2487 /*
2488 * Log a message if the configuration file has changed since inetconv
2489 * was last run.
2490 */
2491 check_conf_file();
2492 }
2493
2494 /*
2495 * Initiate inetd's shutdown.
2496 */
2497 static void
inetd_stop(void)2498 inetd_stop(void)
2499 {
2500 instance_t *inst;
2501
2502 /* Block handling signals for stop and refresh */
2503 (void) sighold(SIGHUP);
2504 (void) sighold(SIGTERM);
2505
2506 /* Indicate inetd is coming down */
2507 inetd_stopping = B_TRUE;
2508
2509 /* Stop polling on restarter events. */
2510 clear_pollfd(rst_event_pipe[PE_CONSUMER]);
2511
2512 /* Stop polling for any more stop/refresh requests. */
2513 clear_pollfd(uds_fd);
2514
2515 /*
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.
2519 */
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);
2525 }
2526 }
2527
2528 /*
2529 * Sets up the intra-inetd-process Unix Domain Socket.
2530 * Returns -1 on error, else 0.
2531 */
2532 static int
uds_init(void)2533 uds_init(void)
2534 {
2535 struct sockaddr_un addr;
2536
2537 if ((uds_fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
2538 error_msg("socket: %s", strerror(errno));
2539 return (-1);
2540 }
2541
2542 disable_blocking(uds_fd);
2543
2544 (void) unlink(INETD_UDS_PATH); /* clean-up any stale files */
2545
2546 (void) memset(&addr, 0, sizeof (addr));
2547 addr.sun_family = AF_UNIX;
2548 /* CONSTCOND */
2549 assert(sizeof (INETD_UDS_PATH) <= sizeof (addr.sun_path));
2550 (void) strlcpy(addr.sun_path, INETD_UDS_PATH, sizeof (addr.sun_path));
2551
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);
2556 return (-1);
2557 }
2558
2559 (void) listen(uds_fd, UDS_BACKLOG);
2560
2561 if ((set_pollfd(uds_fd, POLLIN)) == -1) {
2562 (void) close(uds_fd);
2563 (void) unlink(INETD_UDS_PATH);
2564 return (-1);
2565 }
2566
2567 return (0);
2568 }
2569
2570 static void
uds_fini(void)2571 uds_fini(void)
2572 {
2573 if (uds_fd != -1)
2574 (void) close(uds_fd);
2575 (void) unlink(INETD_UDS_PATH);
2576 }
2577
2578 /*
2579 * Handle an incoming request on the Unix Domain Socket. Returns -1 if there
2580 * was an error handling the event, else 0.
2581 */
2582 static int
process_uds_event(void)2583 process_uds_event(void)
2584 {
2585 uds_request_t req;
2586 int fd;
2587 struct sockaddr_un addr;
2588 socklen_t len = sizeof (addr);
2589 int ret;
2590 uint_t retries = 0;
2591 ucred_t *ucred = NULL;
2592 uid_t euid;
2593
2594 do {
2595 fd = accept(uds_fd, (struct sockaddr *)&addr, &len);
2596 } while ((fd < 0) && (errno == EINTR));
2597 if (fd < 0) {
2598 if (errno != EWOULDBLOCK)
2599 error_msg("accept failed: %s", strerror(errno));
2600 return (-1);
2601 }
2602
2603 if (getpeerucred(fd, &ucred) == -1) {
2604 error_msg("getpeerucred failed: %s", strerror(errno));
2605 (void) close(fd);
2606 return (-1);
2607 }
2608
2609 /* Check peer credentials before acting on the request */
2610 euid = ucred_geteuid(ucred);
2611 ucred_free(ucred);
2612 if (euid != 0 && getuid() != euid) {
2613 debug_msg("peer euid %u != uid %u",
2614 (uint_t)euid, (uint_t)getuid());
2615 (void) close(fd);
2616 return (-1);
2617 }
2618
2619 for (retries = 0; retries < UDS_RECV_RETRIES; retries++) {
2620 if (((ret = safe_read(fd, &req, sizeof (req))) != 1) ||
2621 (errno != EAGAIN))
2622 break;
2623
2624 (void) poll(NULL, 0, 100); /* 100ms pause */
2625 }
2626
2627 if (ret != 0) {
2628 error_msg(gettext("Failed read: %s"), strerror(errno));
2629 (void) close(fd);
2630 return (-1);
2631 }
2632
2633 switch (req) {
2634 case UR_REFRESH_INETD:
2635 /* flag the request for event_loop() to process */
2636 refresh_inetd_requested = B_TRUE;
2637 (void) close(fd);
2638 break;
2639 case UR_STOP_INETD:
2640 inetd_stop();
2641 break;
2642 default:
2643 error_msg("unexpected UDS request");
2644 (void) close(fd);
2645 return (-1);
2646 }
2647
2648 return (0);
2649 }
2650
2651 /*
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
2656 * errors here.
2657 */
2658 static boolean_t
passes_basic_exec_checks(const char * instance,const char * method,const char * path)2659 passes_basic_exec_checks(const char *instance, const char *method,
2660 const char *path)
2661 {
2662 struct stat sbuf;
2663
2664 /* check the file exists */
2665 while (stat(path, &sbuf) == -1) {
2666 if (errno != EINTR) {
2667 error_msg(gettext(
2668 "Can't stat the %s method of instance %s: %s"),
2669 method, instance, strerror(errno));
2670 return (B_FALSE);
2671 }
2672 }
2673
2674 /*
2675 * Check if the file is a regular file and has at least one execute
2676 * bit set.
2677 */
2678 if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
2679 error_msg(gettext(
2680 "The %s method of instance %s isn't a regular file"),
2681 method, instance);
2682 return (B_FALSE);
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);
2686 return (B_FALSE);
2687 }
2688
2689 return (B_TRUE);
2690 }
2691
2692 static void
exec_method(instance_t * instance,instance_method_t method,method_info_t * mi,struct method_context * mthd_ctxt,const proto_info_t * pi)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)
2695 {
2696 char **args;
2697 char **env;
2698 const char *errf;
2699 int serrno;
2700 sigset_t mtset;
2701 basic_cfg_t *cfg = instance->config->basic;
2702
2703 if (method == IM_START) {
2704 /*
2705 * If wrappers checks fail, pretend the method was exec'd and
2706 * failed.
2707 */
2708 if (!tcp_wrappers_ok(instance))
2709 exit(IMRET_FAILURE);
2710 }
2711
2712 /*
2713 * Revert the disposition of handled signals and ignored signals to
2714 * their defaults, unblocking any blocked ones as a side effect.
2715 */
2716 (void) sigset(SIGHUP, SIG_DFL);
2717 (void) sigset(SIGTERM, SIG_DFL);
2718 (void) sigset(SIGINT, SIG_DFL);
2719
2720 /*
2721 * Ensure that other signals are unblocked
2722 */
2723 (void) sigemptyset(&mtset);
2724 (void) sigprocmask(SIG_SETMASK, &mtset, (sigset_t *)NULL);
2725
2726 /*
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
2729 * expand_address().
2730 */
2731 if ((method == IM_START) &&
2732 (strcmp(mi->exec_args_we.we_wordv[0], "%A") == 0)) {
2733 args = expand_address(instance, pi);
2734 } else {
2735 args = mi->exec_args_we.we_wordv;
2736 }
2737
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);
2744
2745 if ((ae = adt_alloc_event(audit_handle, ADT_inetd_connect))
2746 == NULL) {
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);
2751 }
2752
2753 /*
2754 * The inetd_connect audit record consists of:
2755 * Service name
2756 * Execution path
2757 * Remote address and port
2758 * Local port
2759 * Process privileges
2760 */
2761 ae->adt_inetd_connect.service_name = cfg->svc_name;
2762 ae->adt_inetd_connect.cmd = mi->exec_path;
2763
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;
2768 } else {
2769 uint32_t *addr6;
2770 int i;
2771
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];
2776 }
2777
2778 ae->adt_inetd_connect.ip_remote_port =
2779 ntohs(SS_PORT(instance->remote_addr));
2780
2781 if (getsockname(instance->conn_fd, (struct sockaddr *)&ss,
2782 &sslen) == 0)
2783 ae->adt_inetd_connect.ip_local_port =
2784 ntohs(SS_PORT(ss));
2785
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);
2792 privset = NULL;
2793 }
2794 }
2795
2796 ae->adt_inetd_connect.privileges = privset;
2797
2798 (void) adt_put_event(ae, ADT_SUCCESS, ADT_SUCCESS);
2799 adt_free_event(ae);
2800
2801 if (privset != NULL && mthd_ctxt->priv_set == NULL)
2802 priv_freeset(privset);
2803 }
2804
2805 /*
2806 * Set method context before the fd setup below so we can output an
2807 * error message if it fails.
2808 */
2809 if ((errno = restarter_set_method_context(mthd_ctxt, &errf)) != 0) {
2810 const char *msg;
2811
2812 if (errno == -1) {
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 "
2822 "error");
2823 } else {
2824 assert(0);
2825 abort();
2826 }
2827
2828 error_msg(msg, methods[method].name, instance->fmri);
2829
2830 exit(IMRET_FAILURE);
2831 }
2832
2833 if (errf != NULL && strcmp(errf, "pool_set_binding") == 0) {
2834 switch (errno) {
2835 case ENOENT:
2836 msg = gettext("Failed to find resource pool "
2837 "for the %s method of instance %s");
2838 break;
2839
2840 case EBADF:
2841 msg = gettext("Failed to bind the %s method of "
2842 "instance %s to a pool due to invalid "
2843 "configuration");
2844 break;
2845
2846 case EINVAL:
2847 msg = gettext("Failed to bind the %s method of "
2848 "instance %s to a pool due to invalid "
2849 "pool name");
2850 break;
2851
2852 default:
2853 assert(0);
2854 abort();
2855 }
2856
2857 exit(IMRET_FAILURE);
2858 }
2859
2860 if (errf != NULL) {
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,
2864 strerror(errno));
2865 exit(IMRET_FAILURE);
2866 }
2867
2868 switch (errno) {
2869 case ENOMEM:
2870 msg = gettext("Failed to set credentials for the %s "
2871 "method of instance %s (out of memory)");
2872 break;
2873
2874 case ENOENT:
2875 msg = gettext("Failed to set credentials for the %s "
2876 "method of instance %s (no passwd or shadow "
2877 "entry for user)");
2878 break;
2879
2880 default:
2881 assert(0);
2882 abort();
2883 }
2884
2885 error_msg(msg, methods[method].name, instance->fmri);
2886 exit(IMRET_FAILURE);
2887 }
2888
2889 /* let exec() free mthd_ctxt */
2890
2891 /* setup standard fds */
2892 if (method == IM_START) {
2893 (void) dup2(instance->conn_fd, STDIN_FILENO);
2894 } else {
2895 (void) close(STDIN_FILENO);
2896 (void) open("/dev/null", O_RDONLY);
2897 }
2898 (void) dup2(STDIN_FILENO, STDOUT_FILENO);
2899 (void) dup2(STDIN_FILENO, STDERR_FILENO);
2900
2901 closefrom(STDERR_FILENO + 1);
2902
2903 method_preexec();
2904
2905 env = set_smf_env(mthd_ctxt, instance, methods[method].name);
2906
2907 if (env != NULL) {
2908 do {
2909 (void) execve(mi->exec_path, args, env);
2910 } while (errno == EINTR);
2911 }
2912
2913 serrno = errno;
2914 /* start up logging again to report the error */
2915 msg_init();
2916 errno = serrno;
2917
2918 error_msg(
2919 gettext("Failed to exec %s method of instance %s: %s"),
2920 methods[method].name, instance->fmri, strerror(errno));
2921
2922 if ((method == IM_START) && (instance->config->basic->iswait)) {
2923 /*
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.
2932 */
2933 consume_wait_data(instance, 0);
2934 }
2935
2936 exit(IMRET_FAILURE);
2937 }
2938
2939 static restarter_error_t
get_method_error_success(instance_method_t method)2940 get_method_error_success(instance_method_t method)
2941 {
2942 switch (method) {
2943 case IM_OFFLINE:
2944 return (RERR_RESTART);
2945 case IM_ONLINE:
2946 return (RERR_RESTART);
2947 case IM_DISABLE:
2948 return (RERR_RESTART);
2949 case IM_REFRESH:
2950 return (RERR_REFRESH);
2951 case IM_START:
2952 return (RERR_RESTART);
2953 }
2954 (void) fprintf(stderr, gettext("Internal fatal error in inetd.\n"));
2955
2956 abort();
2957 /* NOTREACHED */
2958 }
2959
2960 static int
smf_kill_process(instance_t * instance,int sig)2961 smf_kill_process(instance_t *instance, int sig)
2962 {
2963 rep_val_t *rv;
2964 int ret = IMRET_SUCCESS;
2965
2966 /* Carry out process assassination */
2967 for (rv = uu_list_first(instance->start_pids);
2968 rv != NULL;
2969 rv = uu_list_next(instance->start_pids, rv)) {
2970 if ((kill((pid_t)rv->val, sig) != 0) &&
2971 (errno != ESRCH)) {
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));
2976 }
2977 }
2978 return (ret);
2979 }
2980
2981 /*
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.
2992 */
2993 int
run_method(instance_t * instance,instance_method_t method,const proto_info_t * start_info)2994 run_method(instance_t *instance, instance_method_t method,
2995 const proto_info_t *start_info)
2996 {
2997 pid_t child_pid;
2998 method_info_t *mi;
2999 struct method_context *mthd_ctxt = NULL;
3000 int sig = 0;
3001 int ret;
3002 instance_cfg_t *cfg = instance->config;
3003 ctid_t cid;
3004 boolean_t trans_failure = B_TRUE;
3005 int serrno;
3006
3007 /*
3008 * Don't bother updating the instance's state for the start method
3009 * as there isn't a separate start method state.
3010 */
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));
3015
3016 if ((mi = cfg->methods[method]) == NULL) {
3017 /*
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.
3021 */
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."),
3025 instance->fmri);
3026 (void) str2sig("TERM", &sig);
3027 ret = smf_kill_process(instance, sig);
3028 process_non_start_term(instance, ret);
3029 return (0);
3030 } else {
3031 process_non_start_term(instance, IMRET_SUCCESS);
3032 return (0);
3033 }
3034 }
3035
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);
3041 return (0);
3042 }
3043
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;
3053 } else {
3054 process_non_start_term(instance, IMRET_SUCCESS);
3055 return (0);
3056 }
3057 }
3058
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);
3062 return (0);
3063 }
3064 }
3065
3066 /*
3067 * Get the associated method context before the fork so we can
3068 * modify the instances state if things go wrong.
3069 */
3070 if ((mthd_ctxt = read_method_context(instance->fmri,
3071 methods[method].name, mi->exec_path)) == NULL)
3072 goto prefork_failure;
3073
3074 /*
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.
3077 */
3078 if (!passes_basic_exec_checks(instance->fmri, methods[method].name,
3079 mi->exec_path)) {
3080 trans_failure = B_FALSE;
3081 goto prefork_failure;
3082 }
3083
3084 if (contract_prefork(instance->fmri, method) == -1)
3085 goto prefork_failure;
3086 child_pid = fork();
3087 serrno = errno;
3088 contract_postfork();
3089
3090 switch (child_pid) {
3091 case -1:
3092 error_msg(gettext(
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;
3098 case 0: /* child */
3099 exec_method(instance, method, mi, mthd_ctxt, start_info);
3100 /* NOTREACHED */
3101 default: /* parent */
3102 restarter_free_method_context(mthd_ctxt);
3103 mthd_ctxt = NULL;
3104
3105 if (get_latest_contract(&cid) < 0)
3106 cid = -1;
3107
3108 /*
3109 * Register this method so its termination is noticed and
3110 * the state transition this method participates in is
3111 * continued.
3112 */
3113 if (register_method(instance, child_pid, cid, method,
3114 start_info->proto) != 0) {
3115 /*
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
3120 * running state.
3121 */
3122 error_msg(gettext("Failed to monitor status of "
3123 "%s method of instance %s"), methods[method].name,
3124 instance->fmri);
3125 if (method != IM_START)
3126 process_non_start_term(instance, IMRET_FAILURE);
3127 }
3128
3129 add_method_ids(instance, child_pid, cid, method);
3130
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];
3135
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,
3140 sizeof (buf)),
3141 ntohs(SS_PORT(instance->remote_addr)));
3142 }
3143 }
3144
3145 return (0);
3146
3147 prefork_failure:
3148 if (mthd_ctxt != NULL) {
3149 restarter_free_method_context(mthd_ctxt);
3150 mthd_ctxt = NULL;
3151 }
3152
3153 if (method == IM_START) {
3154 /*
3155 * Only place a start method in maintenance if we're sure
3156 * that the failure was non-transient.
3157 */
3158 if (!trans_failure) {
3159 destroy_bound_fds(instance);
3160 update_state(instance, IIS_MAINTENANCE, RERR_FAULT);
3161 }
3162 } else {
3163 /* treat the failure as if the method ran and failed */
3164 process_non_start_term(instance, IMRET_FAILURE);
3165 }
3166
3167 return (-1);
3168 }
3169
3170 static int
pending_connections(instance_t * instance,proto_info_t * pi)3171 pending_connections(instance_t *instance, proto_info_t *pi)
3172 {
3173 if (instance->config->basic->istlx) {
3174 tlx_info_t *tl = (tlx_info_t *)pi;
3175
3176 return (uu_list_numnodes(tl->conn_ind_queue) != 0);
3177 } else {
3178 return (0);
3179 }
3180 }
3181
3182 static int
accept_connection(instance_t * instance,proto_info_t * pi)3183 accept_connection(instance_t *instance, proto_info_t *pi)
3184 {
3185 int fd;
3186 socklen_t size;
3187
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);
3192
3193 fd = tlx_accept(instance->fmri, (tlx_info_t *)pi,
3194 &(instance->remote_addr));
3195
3196 tlx_pending_counter = \
3197 tlx_pending_counter + uu_list_numnodes(tl->conn_ind_queue);
3198 } else {
3199 size = sizeof (instance->remote_addr);
3200 fd = accept(pi->listen_fd,
3201 (struct sockaddr *)&(instance->remote_addr), &size);
3202 if (fd < 0)
3203 error_msg("accept: %s", strerror(errno));
3204 }
3205
3206 return (fd);
3207 }
3208
3209 /*
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.
3217 */
3218 static void
process_nowait_request(instance_t * instance,proto_info_t * pi)3219 process_nowait_request(instance_t *instance, proto_info_t *pi)
3220 {
3221 basic_cfg_t *cfg = instance->config->basic;
3222 int ret;
3223 adt_event_data_t *ae;
3224 char buf[BUFSIZ];
3225
3226 /* accept nowait service connections on a new fd */
3227 if ((instance->conn_fd = accept_connection(instance, pi)) == -1) {
3228 /*
3229 * Failed accept. Return and allow the event loop to initiate
3230 * another attempt later if the request is still present.
3231 */
3232 return;
3233 }
3234
3235 /*
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.
3241 */
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);
3248
3249 if ((now - instance->conn_rate_start) > 1) {
3250 instance->conn_rate_start = now;
3251 instance->conn_rate_count = 1;
3252 } else {
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"));
3258 } else {
3259 adt_inetd_ratelimit_t *rl =
3260 &ae->adt_inetd_ratelimit;
3261 /*
3262 * The inetd_ratelimit audit
3263 * record consists of:
3264 * Service name
3265 * Connection rate limit
3266 */
3267 rl->service_name = cfg->svc_name;
3268 (void) snprintf(buf, sizeof (buf),
3269 "limit=%lld", cfg->conn_rate_max);
3270 rl->limit = buf;
3271 (void) adt_put_event(ae, ADT_SUCCESS,
3272 ADT_SUCCESS);
3273 adt_free_event(ae);
3274 }
3275
3276 error_msg(gettext(
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);
3281
3282 close_net_fd(instance, instance->conn_fd);
3283 instance->conn_fd = -1;
3284
3285 destroy_bound_fds(instance);
3286
3287 instance->conn_rate_count = 0;
3288
3289 instance->conn_rate_exceeded = B_TRUE;
3290 (void) run_method(instance, IM_OFFLINE, NULL);
3291
3292 return;
3293 }
3294 }
3295 }
3296
3297 ret = run_method(instance, IM_START, pi);
3298
3299 close_net_fd(instance, instance->conn_fd);
3300 instance->conn_fd = -1;
3301
3302 if (ret == -1) /* the method wasn't forked */
3303 return;
3304
3305 instance->copies++;
3306
3307 /*
3308 * Limit concurrent connections of nowait services.
3309 */
3310 if (copies_limit_exceeded(instance)) {
3311 /* Generate audit record */
3312 if ((ae = adt_alloc_event(audit_handle, ADT_inetd_copylimit))
3313 == NULL) {
3314 error_msg(gettext("Unable to allocate copy limit "
3315 "audit event"));
3316 } else {
3317 /*
3318 * The inetd_copylimit audit record consists of:
3319 * Service name
3320 * Copy limit
3321 */
3322 ae->adt_inetd_copylimit.service_name = cfg->svc_name;
3323 (void) snprintf(buf, sizeof (buf), "limit=%lld",
3324 cfg->max_copies);
3325 ae->adt_inetd_copylimit.limit = buf;
3326 (void) adt_put_event(ae, ADT_SUCCESS, ADT_SUCCESS);
3327 adt_free_event(ae);
3328 }
3329
3330 warn_msg(gettext("Instance %s has reached its maximum "
3331 "configured copies, no new connections will be accepted"),
3332 instance->fmri);
3333 destroy_bound_fds(instance);
3334 (void) run_method(instance, IM_OFFLINE, NULL);
3335 }
3336 }
3337
3338 /*
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.
3343 */
3344 static void
process_wait_request(instance_t * instance,const proto_info_t * pi)3345 process_wait_request(instance_t *instance, const proto_info_t *pi)
3346 {
3347 basic_cfg_t *cfg = instance->config->basic;
3348 int ret;
3349 adt_event_data_t *ae;
3350 char buf[BUFSIZ];
3351
3352 instance->conn_fd = pi->listen_fd;
3353
3354 /*
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.
3361 */
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);
3367
3368 if ((now - instance->fail_rate_start) >
3369 cfg->wait_fail_interval) {
3370 instance->fail_rate_start = now;
3371 instance->fail_rate_count = 1;
3372 } else {
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"));
3378 } else {
3379 adt_inetd_failrate_t *fr =
3380 &ae->adt_inetd_failrate;
3381 /*
3382 * The inetd_failrate audit record
3383 * consists of:
3384 * Service name
3385 * Failure rate
3386 * Interval
3387 * Last two are expressed as k=v pairs
3388 * in the values field.
3389 */
3390 fr->service_name = cfg->svc_name;
3391 (void) snprintf(buf, sizeof (buf),
3392 "limit=%lld,interval=%d",
3393 cfg->wait_fail_cnt,
3394 cfg->wait_fail_interval);
3395 fr->values = buf;
3396 (void) adt_put_event(ae, ADT_SUCCESS,
3397 ADT_SUCCESS);
3398 adt_free_event(ae);
3399 }
3400
3401 error_msg(gettext(
3402 "Instance %s has exceeded its configured "
3403 "failure rate, transitioning to "
3404 "maintenance"), instance->fmri);
3405 instance->fail_rate_count = 0;
3406
3407 destroy_bound_fds(instance);
3408
3409 instance->maintenance_req = B_TRUE;
3410 (void) run_method(instance, IM_OFFLINE, NULL);
3411 return;
3412 }
3413 }
3414 }
3415
3416 ret = run_method(instance, IM_START, pi);
3417
3418 instance->conn_fd = -1;
3419
3420 if (ret == 0) {
3421 /*
3422 * Stop listening for connections now we've fired off the
3423 * server for a wait type instance.
3424 */
3425 (void) poll_bound_fds(instance, B_FALSE, pi->proto);
3426 }
3427 }
3428
3429 /*
3430 * Process any networks requests for each proto for each instance.
3431 */
3432 void
process_network_events(void)3433 process_network_events(void)
3434 {
3435 instance_t *instance;
3436
3437 for (instance = uu_list_first(instance_list); instance != NULL;
3438 instance = uu_list_next(instance_list, instance)) {
3439 basic_cfg_t *cfg;
3440 proto_info_t *pi;
3441
3442 /*
3443 * Ignore instances in states that definitely don't have any
3444 * listening fds.
3445 */
3446 switch (instance->cur_istate) {
3447 case IIS_ONLINE:
3448 case IIS_DEGRADED:
3449 case IIS_IN_REFRESH_METHOD:
3450 break;
3451 default:
3452 continue;
3453 }
3454
3455 cfg = instance->config->basic;
3456
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)) {
3462 if (cfg->iswait) {
3463 process_wait_request(instance, pi);
3464 } else {
3465 process_nowait_request(instance, pi);
3466 }
3467 }
3468 }
3469 }
3470 }
3471
3472 /* ARGSUSED0 */
3473 static void
sigterm_handler(int sig)3474 sigterm_handler(int sig)
3475 {
3476 got_sigterm = B_TRUE;
3477 }
3478
3479 /* ARGSUSED0 */
3480 static void
sighup_handler(int sig)3481 sighup_handler(int sig)
3482 {
3483 refresh_inetd_requested = B_TRUE;
3484 }
3485
3486 /*
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
3492 * network events.
3493 * The loop is exited when a stop request is received and processed, and
3494 * all the instances have reached a suitable 'stopping' state.
3495 */
3496 static void
event_loop(void)3497 event_loop(void)
3498 {
3499 instance_t *instance;
3500 int timeout;
3501
3502 for (;;) {
3503 int pret = -1;
3504
3505 if (tlx_pending_counter != 0)
3506 timeout = 0;
3507 else
3508 timeout = iu_earliest_timer(timer_queue);
3509
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"),
3514 strerror(errno));
3515 continue;
3516 }
3517 }
3518
3519 if (got_sigterm) {
3520 msg_fini();
3521 inetd_stop();
3522 got_sigterm = B_FALSE;
3523 goto check_if_stopped;
3524 }
3525
3526 /*
3527 * Process any stop/refresh requests from the Unix Domain
3528 * Socket.
3529 */
3530 if ((pret != -1) && isset_pollfd(uds_fd)) {
3531 while (process_uds_event() == 0)
3532 ;
3533 }
3534
3535 /*
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.
3540 */
3541 if (refresh_inetd_requested) {
3542 refresh_inetd_requested = B_FALSE;
3543 if (!inetd_stopping)
3544 inetd_refresh();
3545 }
3546
3547 /*
3548 * We were interrupted by a signal. Don't waste any more
3549 * time processing a potentially inaccurate poll return.
3550 */
3551 if (pret == -1)
3552 continue;
3553
3554 /*
3555 * Process any instance restarter events.
3556 */
3557 if (isset_pollfd(rst_event_pipe[PE_CONSUMER])) {
3558 while (process_restarter_event() == 0)
3559 ;
3560 }
3561
3562 /*
3563 * Process any expired timers (bind retry, con-rate offline,
3564 * method timeouts).
3565 */
3566 (void) iu_expire_timers(timer_queue);
3567
3568 process_terminated_methods();
3569
3570 /*
3571 * If inetd is stopping, check whether all our managed
3572 * instances have been stopped and we can return.
3573 */
3574 if (inetd_stopping) {
3575 check_if_stopped:
3576 for (instance = uu_list_first(instance_list);
3577 instance != NULL;
3578 instance = uu_list_next(instance_list, instance)) {
3579 if (!instance_stopped(instance)) {
3580 debug_msg("%s not yet stopped",
3581 instance->fmri);
3582 break;
3583 }
3584 }
3585 /* if all instances are stopped, return */
3586 if (instance == NULL)
3587 return;
3588 }
3589
3590 process_network_events();
3591 }
3592 }
3593
3594 static void
fini(void)3595 fini(void)
3596 {
3597 method_fini();
3598 uds_fini();
3599 if (timer_queue != NULL)
3600 iu_tq_destroy(timer_queue);
3601
3602
3603 /*
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.
3610 *
3611 * By keeping the event pipe open but ignoring it, any events which
3612 * occur will cause restarter_event_proxy to hang without breaking
3613 * anything.
3614 */
3615
3616 if (instance_list != NULL) {
3617 void *cookie = NULL;
3618 instance_t *inst;
3619
3620 while ((inst = uu_list_teardown(instance_list, &cookie)) !=
3621 NULL)
3622 destroy_instance(inst);
3623 uu_list_destroy(instance_list);
3624 }
3625 if (instance_pool != NULL)
3626 uu_list_pool_destroy(instance_pool);
3627 tlx_fini();
3628 config_fini();
3629 repval_fini();
3630 poll_fini();
3631
3632 /* Close audit session */
3633 (void) adt_end_session(audit_handle);
3634 }
3635
3636 static int
init(void)3637 init(void)
3638 {
3639 int err;
3640
3641 if (repval_init() < 0)
3642 goto failed;
3643
3644 if (config_init() < 0)
3645 goto failed;
3646
3647 refresh_debug_flag();
3648
3649 if (tlx_init() < 0)
3650 goto failed;
3651
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) {
3656 error_msg("%s: %s",
3657 gettext("Failed to create instance pool"),
3658 uu_strerror(uu_error()));
3659 goto failed;
3660 }
3661 if ((instance_list = uu_list_create(instance_pool, NULL, 0)) == NULL) {
3662 error_msg("%s: %s",
3663 gettext("Failed to create instance list"),
3664 uu_strerror(uu_error()));
3665 goto failed;
3666 }
3667
3668 /*
3669 * Create event pipe to communicate events with the main event
3670 * loop and add it to the event loop's fdset.
3671 */
3672 if (pipe(rst_event_pipe) < 0) {
3673 error_msg("pipe: %s", strerror(errno));
3674 goto failed;
3675 }
3676 /*
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.
3681 */
3682 disable_blocking(rst_event_pipe[PE_CONSUMER]);
3683 if ((set_pollfd(rst_event_pipe[PE_CONSUMER], POLLIN)) == -1)
3684 goto failed;
3685
3686 /*
3687 * Register with master restarter for managed service events. This
3688 * will fail, amongst other reasons, if inetd is already running.
3689 */
3690 if ((err = restarter_bind_handle(RESTARTER_EVENT_VERSION,
3691 INETD_INSTANCE_FMRI, restarter_event_proxy, 0,
3692 &rst_event_handle)) != 0) {
3693 error_msg(gettext(
3694 "Failed to register for restarter events: %s"),
3695 strerror(err));
3696 goto failed;
3697 }
3698
3699 if (contract_init() < 0)
3700 goto failed;
3701
3702 if ((timer_queue = iu_tq_create()) == NULL) {
3703 error_msg(gettext("Failed to create timer queue."));
3704 goto failed;
3705 }
3706
3707 if (uds_init() < 0)
3708 goto failed;
3709
3710 if (method_init() < 0)
3711 goto failed;
3712
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"));
3716 }
3717
3718 /*
3719 * Initialize signal dispositions/masks
3720 */
3721 (void) sigset(SIGHUP, sighup_handler);
3722 (void) sigset(SIGTERM, sigterm_handler);
3723 (void) sigignore(SIGINT);
3724
3725 return (0);
3726
3727 failed:
3728 fini();
3729 return (-1);
3730 }
3731
3732 static int
start_method(void)3733 start_method(void)
3734 {
3735 int i;
3736 int pipe_fds[2];
3737 int child;
3738
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);
3743 }
3744
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 */
3751
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) ||
3755 (i < 0)) {
3756 error_msg(gettext(
3757 "Initialization failed, unable to start"));
3758 (void) close(pipe_fds[PE_CONSUMER]);
3759 /*
3760 * Batch all initialization errors as 'other' errors,
3761 * resulting in retries being attempted.
3762 */
3763 return (SMF_EXIT_ERR_OTHER);
3764 } else {
3765 (void) close(pipe_fds[PE_CONSUMER]);
3766 return (SMF_EXIT_OK);
3767 }
3768 } else { /* child */
3769 /*
3770 * Perform initialization and return success code down
3771 * the pipe.
3772 */
3773 (void) close(pipe_fds[PE_CONSUMER]);
3774 i = init();
3775 if ((safe_write(pipe_fds[PE_PRODUCER], &i, sizeof (i)) < 0) ||
3776 (i < 0)) {
3777 error_msg(gettext("pipe write failure: %s"),
3778 strerror(errno));
3779 exit(1);
3780 }
3781 (void) close(pipe_fds[PE_PRODUCER]);
3782
3783 (void) setsid();
3784
3785 /*
3786 * Log a message if the configuration file has changed since
3787 * inetconv was last run.
3788 */
3789 check_conf_file();
3790
3791 event_loop();
3792
3793 fini();
3794 debug_msg("inetd stopped");
3795 msg_fini();
3796 exit(0);
3797 }
3798 /* NOTREACHED */
3799 }
3800
3801 /*
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
3806 * it is possible.
3807 */
3808 static void
legacy_usage(void)3809 legacy_usage(void)
3810 {
3811 (void) fprintf(stderr,
3812 "inetd is now an smf(5) managed service and can no longer be run "
3813 "from the\n"
3814 "command line. To enable or disable inetd refer to svcadm(1M) on\n"
3815 "how to enable \"%s\", the inetd instance.\n"
3816 "\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"
3822 "\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"
3827 "\n"
3828 "For further information on inetd see inetd(1M).\n",
3829 INETD_INSTANCE_FMRI, START_METHOD_ARG, SCF_PROPERTY_EXEC,
3830 INETD_PATH);
3831 }
3832
3833 /*
3834 * Usage message printed out for usage errors when running under the SMF.
3835 */
3836 static void
smf_usage(const char * arg0)3837 smf_usage(const char *arg0)
3838 {
3839 error_msg("Usage: %s [alt_conf_file] %s|%s|%s", arg0, START_METHOD_ARG,
3840 STOP_METHOD_ARG, REFRESH_METHOD_ARG);
3841 }
3842
3843 /*
3844 * Returns B_TRUE if we're being run from within the SMF, else B_FALSE.
3845 */
3846 static boolean_t
run_through_smf(void)3847 run_through_smf(void)
3848 {
3849 char *fmri;
3850
3851 /*
3852 * check if the instance fmri environment variable has been set by
3853 * our restarter.
3854 */
3855 return (((fmri = getenv("SMF_FMRI")) != NULL) &&
3856 (strcmp(fmri, INETD_INSTANCE_FMRI) == 0));
3857 }
3858
3859 int
main(int argc,char * argv[])3860 main(int argc, char *argv[])
3861 {
3862 char *method;
3863 int ret;
3864
3865 #if !defined(TEXT_DOMAIN)
3866 #define TEXT_DOMAIN "SYS_TEST"
3867 #endif
3868 (void) textdomain(TEXT_DOMAIN);
3869 (void) setlocale(LC_ALL, "");
3870
3871 if (!run_through_smf()) {
3872 legacy_usage();
3873 return (SMF_EXIT_ERR_NOSMF);
3874 }
3875
3876 msg_init(); /* setup logging */
3877
3878 (void) enable_extended_FILE_stdio(-1, -1);
3879
3880 /* inetd invocation syntax is inetd [alt_conf_file] method_name */
3881
3882 switch (argc) {
3883 case 2:
3884 method = argv[1];
3885 break;
3886 case 3:
3887 conf_file = argv[1];
3888 method = argv[2];
3889 break;
3890 default:
3891 smf_usage(argv[0]);
3892 return (SMF_EXIT_ERR_CONFIG);
3893
3894 }
3895
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();
3902 } else {
3903 smf_usage(argv[0]);
3904 return (SMF_EXIT_ERR_CONFIG);
3905 }
3906
3907 return (ret);
3908 }
3909