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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef _INETD_IMPL_H
27 #define	_INETD_IMPL_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 
32 /*
33  * Header file containing inetd's shared types/data structures and
34  * function declarations.
35  */
36 
37 #ifdef __cplusplus
38 extern "C" {
39 #endif
40 
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <stdarg.h>
44 #include <rpc/rpc.h>
45 #include <assert.h>
46 #include <libscf.h>
47 #include <libinetutil.h>
48 #include <inetsvc.h>
49 #include <librestart.h>
50 #include <libuutil.h>
51 #include <wordexp.h>
52 
53 
54 /*
55  * Number of consecutive retries of a repository operation that failed due
56  * to a broken connection performed before giving up and failing.
57  */
58 #define	REP_OP_RETRIES 10
59 
60 /* retryable SMF method error */
61 #define	SMF_EXIT_ERR_OTHER 1
62 
63 /* inetd's syslog ident string */
64 #define	SYSLOG_IDENT    "inetd"
65 
66 /* Is this instance currently executing a method ? */
67 #define	INST_IN_TRANSITION(i)	((i)->next_istate != IIS_NONE)
68 
69 /* Names of properties that inetd uses to store instance state. */
70 #define	PR_NAME_NON_START_PID	"non_start_pid"
71 #define	PR_NAME_START_PIDS	"start_pids"
72 #define	PR_NAME_CUR_INT_STATE	"cur_state"
73 #define	PR_NAME_NEXT_INT_STATE	"next_state"
74 
75 /* Name of the property group that holds debug flag */
76 #define	PG_NAME_APPLICATION_CONFIG	"config"
77 
78 /* Name of the property which holds the debug flag value */
79 #define	PR_NAME_DEBUG_FLAG	"debug"
80 
81 /*
82  * Instance states used internal to svc.inetd.
83  * NOTE: The states table in cmd/cmd-inetd/inetd/inetd.c relies on the
84  * ordering of this enumeration, so take care if modifying it.
85  */
86 typedef enum {
87 	IIS_UNINITIALIZED,
88 	IIS_ONLINE,
89 	IIS_IN_ONLINE_METHOD,
90 	IIS_OFFLINE,
91 	IIS_IN_OFFLINE_METHOD,
92 	IIS_DISABLED,
93 	IIS_IN_DISABLE_METHOD,
94 	IIS_IN_REFRESH_METHOD,
95 	IIS_MAINTENANCE,
96 	IIS_OFFLINE_CONRATE,
97 	IIS_OFFLINE_BIND,
98 	IIS_OFFLINE_COPIES,
99 	IIS_DEGRADED,
100 	IIS_NONE
101 } internal_inst_state_t;
102 
103 /*
104  * inetd's instance methods.
105  * NOTE: The methods table in cmd/cmd-inetd/inetd/util.c relies on the
106  * ordering of this enumeration, so take care if modifying it.
107  */
108 typedef enum {
109 	IM_START,
110 	IM_ONLINE,
111 	IM_OFFLINE,
112 	IM_DISABLE,
113 	IM_REFRESH,
114 	NUM_METHODS,
115 	IM_NONE
116 } instance_method_t;
117 
118 /* Collection of information pertaining to a method */
119 typedef struct {
120 	char *exec_path;	/* path passed to exec() */
121 
122 	/*
123 	 * Structure returned from wordexp(3c) that contains an expansion of the
124 	 * exec property into a form suitable for exec(2).
125 	 */
126 	wordexp_t	exec_args_we;
127 
128 	/*
129 	 * Copy of the first argument of the above wordexp_t structure in the
130 	 * event that an alternate arg0 is provided, and we replace the first
131 	 * argument with the alternate arg0. This is necessary so the
132 	 * contents of the wordexp_t structure can be returned to their
133 	 * original form as returned from wordexp(3c), which is a requirement
134 	 * for calling wordfree(3c), wordexp()'s associated cleanup routine.
135 	 */
136 	const char	*wordexp_arg0_backup;
137 
138 	/* time a method can run for before being considered broken */
139 	int		timeout;
140 } method_info_t;
141 
142 typedef struct {
143 	basic_cfg_t	*basic;
144 	method_info_t	*methods[NUM_METHODS];
145 } instance_cfg_t;
146 
147 /*
148  * Structure used to construct a list of int64_t's and their associated
149  * scf values. Used to store lists of process ids, internal states, and to
150  * store the associated scf value used when writing the values back to the
151  * repository.
152  */
153 typedef struct {
154 	int64_t		val;
155 	scf_value_t	*scf_val;
156 	uu_list_node_t	link;
157 } rep_val_t;
158 
159 /* Structure containing the state and configuration of a service instance. */
160 typedef struct {
161 	char			*fmri;
162 
163 	/* fd we're going to take a connection on */
164 	int			conn_fd;
165 
166 	/* number of copies of this instance active */
167 	int64_t			copies;
168 
169 	/* connection rate counters */
170 	int64_t			conn_rate_count;
171 	time_t			conn_rate_start;
172 
173 	/* failure rate counters */
174 	int64_t			fail_rate_count;
175 	time_t			fail_rate_start;
176 	/* bind failure count */
177 	int64_t			bind_fail_count;
178 
179 	/* pids of currently running methods */
180 	uu_list_t		*non_start_pid;
181 	uu_list_t		*start_pids;
182 
183 	/* ctids of currently running start methods */
184 	uu_list_t		*start_ctids;
185 
186 	/* remote address, used for TCP tracing */
187 	struct sockaddr_storage	remote_addr;
188 
189 	internal_inst_state_t	cur_istate;
190 	internal_inst_state_t	next_istate;
191 
192 	/* repository compatible versions of the above 2 states */
193 	uu_list_t		*cur_istate_rep;
194 	uu_list_t		*next_istate_rep;
195 
196 	/*
197 	 * Current instance configuration resulting from its repository
198 	 * configuration.
199 	 */
200 	instance_cfg_t		*config;
201 
202 	/*
203 	 * Soon to be applied instance configuration. This configuration was
204 	 * read during a refresh when this instance was online, and the
205 	 * instance needed taking offline for this configuration to be applied.
206 	 * The instance is currently on its way offline, and this configuration
207 	 * will become the current configuration when it arrives there.
208 	 */
209 	instance_cfg_t		*new_config;
210 
211 	/* current pending conrate-offline/method timer; -1 if none pending */
212 	iu_timer_id_t		timer_id;
213 
214 	/* current pending bind retry timer; -1 if none pending */
215 	iu_timer_id_t		bind_timer_id;
216 
217 	/*
218 	 * Flags that assist in the fanout of an instance arriving in the
219 	 * offline state on-route to some other state.
220 	 */
221 	boolean_t		disable_req;
222 	boolean_t		maintenance_req;
223 	boolean_t		conn_rate_exceeded;
224 	boolean_t		bind_retries_exceeded;
225 
226 	/*
227 	 * Event waiting to be processed. RESTARTER_EVENT_TYPE_INVALID is used
228 	 * to mean no event waiting.
229 	 */
230 	restarter_event_type_t	pending_rst_event;
231 
232 	/* link to next instance in list */
233 	uu_list_node_t		link;
234 } instance_t;
235 
236 
237 /* Structure used to store information pertaining to instance method types. */
238 typedef struct {
239 	instance_method_t	method;
240 	const char		*name;
241 	internal_inst_state_t	dst_state;
242 } method_type_info_t;
243 
244 
245 extern uu_list_t *instance_list;
246 extern struct pollfd *poll_fds;
247 extern nfds_t num_pollfds;
248 extern method_type_info_t methods[];
249 extern iu_tq_t *timer_queue;
250 extern uu_list_pool_t *conn_ind_pool;
251 extern boolean_t debug_enabled;
252 
253 /*
254  * util.c
255  */
256 extern void msg_init(void);
257 extern void msg_fini(void);
258 /* PRINTFLIKE1 */
259 extern void debug_msg(const char *, ...);
260 /* PRINTFLIKE1 */
261 extern void error_msg(const char *, ...);
262 /* PRINTFLIKE1 */
263 extern void warn_msg(const char *, ...);
264 extern void poll_fini(void);
265 extern boolean_t isset_pollfd(int);
266 extern void clear_pollfd(int);
267 extern int set_pollfd(int, uint16_t);
268 extern struct pollfd *find_pollfd(int);
269 extern int safe_read(int, void *, size_t);
270 extern boolean_t copies_limit_exceeded(instance_t *);
271 extern void cancel_inst_timer(instance_t *);
272 extern void cancel_bind_timer(instance_t *);
273 extern void enable_blocking(int);
274 extern void disable_blocking(int);
275 
276 /*
277  * tlx.c
278  */
279 extern rpc_info_t *create_rpc_info(const char *, const char *, const char *,
280     int, int);
281 extern void destroy_rpc_info(rpc_info_t *);
282 extern boolean_t rpc_info_equal(const rpc_info_t *, const rpc_info_t *);
283 extern int register_rpc_service(const char *, const rpc_info_t *);
284 extern void unregister_rpc_service(const char *, const rpc_info_t *);
285 extern int create_bound_endpoint(const instance_t *, tlx_info_t *);
286 extern void close_net_fd(instance_t *, int);
287 extern int tlx_accept(const char *, tlx_info_t *, struct sockaddr_storage *);
288 extern struct t_call *dequeue_conind(uu_list_t *);
289 extern int queue_conind(uu_list_t *, struct t_call *);
290 extern void tlx_fini(void);
291 extern int tlx_init(void);
292 extern boolean_t tlx_info_equal(const tlx_info_t *, const tlx_info_t *,
293     boolean_t);
294 extern void consume_wait_data(instance_t *, int);
295 
296 /*
297  * config.c
298  */
299 extern int config_init(void);
300 extern void config_fini(void);
301 extern boolean_t socket_info_equal(const socket_info_t *, const socket_info_t *,
302     boolean_t);
303 extern boolean_t method_info_equal(const method_info_t *,
304     const method_info_t *);
305 extern struct method_context *read_method_context(const char *, const char *,
306     const char *, const char **);
307 extern void destroy_instance_cfg(instance_cfg_t *);
308 extern instance_cfg_t *read_instance_cfg(const char *);
309 extern boolean_t bind_config_equal(const basic_cfg_t *, const basic_cfg_t *);
310 extern int read_enable_merged(const char *, boolean_t *);
311 extern void refresh_debug_flag(void);
312 
313 /*
314  * repval.c
315  */
316 extern void repval_fini(void);
317 extern int repval_init(void);
318 extern uu_list_t *create_rep_val_list(void);
319 extern void destroy_rep_val_list(uu_list_t *);
320 extern scf_error_t store_rep_vals(uu_list_t *, const char *, const char *);
321 extern scf_error_t retrieve_rep_vals(uu_list_t *, const char *, const char *);
322 extern rep_val_t *find_rep_val(uu_list_t *, int64_t);
323 extern int set_single_rep_val(uu_list_t *, int64_t);
324 extern int64_t get_single_rep_val(uu_list_t *);
325 extern int add_rep_val(uu_list_t *, int64_t);
326 extern void remove_rep_val(uu_list_t *, int64_t);
327 extern void empty_rep_val_list(uu_list_t *);
328 extern int make_handle_bound(scf_handle_t *);
329 extern int add_remove_contract(instance_t *, boolean_t, ctid_t);
330 extern int iterate_repository_contracts(instance_t *, int);
331 
332 /*
333  * contracts.c
334  */
335 extern int contract_init(void);
336 extern void contract_fini(void);
337 void contract_postfork(void);
338 int contract_prefork(const char *, int);
339 extern int get_latest_contract(ctid_t *cid);
340 extern int adopt_contract(ctid_t, const char *);
341 extern int abandon_contract(ctid_t);
342 
343 /*
344  * inetd.c
345  */
346 extern void process_offline_inst(instance_t *);
347 extern void process_non_start_term(instance_t *, int);
348 extern void process_start_term(instance_t *);
349 extern void remove_method_ids(instance_t *, pid_t, ctid_t, instance_method_t);
350 
351 /*
352  * env.c
353  */
354 char **set_smf_env(struct method_context *, instance_t *, const char *);
355 
356 /*
357  * wait.c
358  */
359 extern int register_method(instance_t *, pid_t, ctid_t cid, instance_method_t);
360 extern int method_init(void);
361 extern void method_fini(void);
362 extern void process_terminated_methods(void);
363 extern void unregister_instance_methods(const instance_t *);
364 extern void method_preexec(void);
365 
366 #ifdef __cplusplus
367 }
368 #endif
369 
370 #endif /* _INETD_IMPL_H */
371