xref: /titanic_50/usr/src/cmd/cmd-inet/usr.sbin/kssl/ksslcfg/ksslcfg_delete.c (revision dd49f125507979bb2ab505a8daf2a46d1be27051)
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) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
23  */
24 
25 #include <libscf.h>
26 #include <libscf_priv.h>
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdlib.h>
30 #include <strings.h>
31 #include <sys/types.h>
32 #include "ksslcfg.h"
33 
34 void
usage_delete(boolean_t do_print)35 usage_delete(boolean_t do_print)
36 {
37 	if (do_print)
38 		(void) fprintf(stderr, gettext("Usage:\n"));
39 	(void) fprintf(stderr,
40 	    "ksslcfg delete [-v] [<server_address>] <server_port>\n");
41 }
42 
43 #define	DEFAULT_TIMEOUT	60000000
44 #define	INIT_WAIT_USECS	50000
45 
46 void
wait_till_to(char * fmri)47 wait_till_to(char *fmri)
48 {
49 	char *state;
50 	useconds_t max;
51 	useconds_t usecs;
52 	uint64_t *cp = NULL;
53 	scf_simple_prop_t *sp = NULL;
54 
55 	max = DEFAULT_TIMEOUT;
56 
57 	if (((sp = scf_simple_prop_get(NULL, fmri, "stop",
58 	    SCF_PROPERTY_TIMEOUT)) != NULL) &&
59 	    ((cp = scf_simple_prop_next_count(sp)) != NULL) && (*cp != 0))
60 		max = (*cp) * 1000000;	/* convert to usecs */
61 
62 	if (sp != NULL)
63 		scf_simple_prop_free(sp);
64 
65 	for (usecs = INIT_WAIT_USECS; max > 0; max -= usecs) {
66 		/* incremental wait */
67 		usecs *= 2;
68 		usecs = (usecs > max) ? max : usecs;
69 
70 		(void) usleep(usecs);
71 
72 		/* Check state after the wait */
73 		if ((state = smf_get_state(fmri)) != NULL) {
74 			if (strcmp(state, "disabled") == 0)
75 				return;
76 		}
77 	}
78 
79 	(void) fprintf(stderr, gettext("Warning: delete %s timed out.\n"),
80 	    fmri);
81 }
82 
83 static int
count_inst_cb(void * arg,scf_walkinfo_t * wip)84 count_inst_cb(void *arg, scf_walkinfo_t *wip)
85 {
86 	int *num_inst = arg;
87 
88 	if (wip->inst != NULL)
89 		(*num_inst)++;
90 
91 	return (0);
92 }
93 
94 /*ARGSUSED*/
95 static void
ign_err(const char * unused,...)96 ign_err(const char *unused, ...)
97 {
98 }
99 
100 int
delete_instance(const char * instance_name)101 delete_instance(const char *instance_name)
102 {
103 	int status = FAILURE;
104 	char *buf;
105 	boolean_t errflag = B_FALSE;
106 	ssize_t max_fmri_len;
107 	scf_scope_t *scope;
108 	scf_service_t *svc;
109 	scf_handle_t *handle;
110 	scf_instance_t *instance;
111 	int num_inst = 0, exit_status = 0;
112 
113 	handle = scf_handle_create(SCF_VERSION);
114 	if (handle == NULL) {
115 		errflag = B_TRUE;
116 		KSSL_DEBUG("scf_handle_create failed: %s\n",
117 		    scf_strerror(scf_error()));
118 		goto out1;
119 	}
120 	KSSL_DEBUG("scf_handle_create succeeded\n");
121 
122 	if (scf_handle_bind(handle) == -1) {
123 		errflag = B_TRUE;
124 		KSSL_DEBUG("scf_handle_bind failed: %s\n",
125 		    scf_strerror(scf_error()));
126 		goto out1;
127 	}
128 	KSSL_DEBUG("scf_handle_bind succeeded\n");
129 
130 	if ((scope = scf_scope_create(handle)) == NULL) {
131 		errflag = B_TRUE;
132 		KSSL_DEBUG("scf_scope_create failed: %s\n",
133 		    scf_strerror(scf_error()));
134 		goto out2;
135 	}
136 	KSSL_DEBUG("scf_scope_create succeeded\n");
137 
138 	if ((svc = scf_service_create(handle)) == NULL) {
139 		errflag = B_TRUE;
140 		KSSL_DEBUG("scf_service_create failed: %s\n",
141 		    scf_strerror(scf_error()));
142 		goto out3;
143 	}
144 	KSSL_DEBUG("scf_service_create succeeded\n");
145 
146 	if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) == -1) {
147 		errflag = B_TRUE;
148 		KSSL_DEBUG("scf_handle_get_scope failed: %s\n",
149 		    scf_strerror(scf_error()));
150 		goto out4;
151 	}
152 	KSSL_DEBUG("scf_handle_get_scope succeeded\n");
153 
154 	if (scf_scope_get_service(scope, SERVICE_NAME, svc) < 0) {
155 		scf_error_t scf_errnum = scf_error();
156 
157 		if (scf_errnum != SCF_ERROR_NOT_FOUND) {
158 			errflag = B_TRUE;
159 			KSSL_DEBUG(
160 			    "ERROR scf_scope_get_service failed: %s\n",
161 			    scf_strerror(scf_errnum));
162 		}
163 		goto out4;
164 	} else {
165 		KSSL_DEBUG("scf_scope_get_service succeeded\n");
166 	}
167 
168 	instance = scf_instance_create(handle);
169 	if (instance == NULL) {
170 		errflag = B_TRUE;
171 		KSSL_DEBUG("scf_instance_create failed: %s\n",
172 		    scf_strerror(scf_error()));
173 		goto out4;
174 	}
175 
176 	if (scf_service_get_instance(svc, instance_name, instance) != 0) {
177 		scf_error_t scf_errnum = scf_error();
178 
179 		if (scf_errnum == SCF_ERROR_NOT_FOUND) {
180 			status = SUCCESS;
181 		} else {
182 			errflag = B_TRUE;
183 			KSSL_DEBUG(
184 			    "ERROR scf_scope_get_service failed: %s\n",
185 			    scf_strerror(scf_errnum));
186 		}
187 		scf_instance_destroy(instance);
188 		goto out4;
189 	}
190 
191 	max_fmri_len = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH);
192 	if ((buf = malloc(max_fmri_len + 1)) == NULL)
193 		goto out4;
194 
195 	if (scf_instance_to_fmri(instance, buf, max_fmri_len + 1) > 0) {
196 		char *state;
197 
198 		KSSL_DEBUG("instance_fmri=%s\n", buf);
199 		state = smf_get_state(buf);
200 		if (state)
201 			KSSL_DEBUG("state=%s\n", state);
202 		if (state && strcmp(state, "online") == 0) {
203 			if (smf_disable_instance(buf, 0) != 0) {
204 				errflag = B_TRUE;
205 				KSSL_DEBUG(
206 				    "smf_disable_instance failed: %s\n",
207 				    scf_strerror(scf_error()));
208 			} else {
209 				/*
210 				 * Wait for some time till timeout to avoid
211 				 * a race with scf_instance_delete() below.
212 				 */
213 				wait_till_to(buf);
214 			}
215 		}
216 	}
217 
218 	if (scf_instance_delete(instance) != 0) {
219 		errflag = B_TRUE;
220 		KSSL_DEBUG(
221 		    "ERROR scf_instance_delete failed: %s\n",
222 		    scf_strerror(scf_error()));
223 		goto out4;
224 	} else {
225 		KSSL_DEBUG("deleted %s\n", instance_name);
226 	}
227 
228 	if (scf_walk_fmri(handle, 1, (char **)&SERVICE_NAME,
229 	    SCF_WALK_MULTIPLE, count_inst_cb, &num_inst, &exit_status,
230 	    ign_err) == 0) {
231 		/*
232 		 * Disable the kssl socket filter if this is the last
233 		 * kssl instance.
234 		 */
235 		if (num_inst == 0) {
236 			if (smf_disable_instance(KSSL_FILTER_SVC_NAME, 0) != 0)
237 				(void) fprintf(stderr,
238 				    gettext("Unable to disable service \"%s\". "
239 				    "Error: %s"), KSSL_FILTER_SVC_NAME,
240 				    scf_strerror(scf_error()));
241 		}
242 	}
243 
244 	status = SUCCESS;
245 
246 out4:
247 	scf_service_destroy(svc);
248 out3:
249 	scf_scope_destroy(scope);
250 out2:
251 	(void) scf_handle_unbind(handle);
252 out1:
253 	if (handle != NULL)
254 		scf_handle_destroy(handle);
255 	if (errflag)
256 		(void) fprintf(stderr, gettext(
257 		    "Unexpected fatal libscf error: %s.  Exiting.\n"),
258 		    scf_strerror(scf_error()));
259 	return (status);
260 }
261 
262 int
do_delete(int argc,char * argv[])263 do_delete(int argc, char *argv[])
264 {
265 	char c;
266 	int status, len, pcnt;
267 	char address_port[MAX_ADRPORT_LEN + 1];
268 	char *instance_name;
269 
270 	if (argc < 3) {
271 		goto err;
272 	}
273 
274 	argc -= 1;
275 	argv += 1;
276 
277 	while ((c = getopt(argc, argv, "v")) != -1) {
278 		switch (c) {
279 		case 'v':
280 			verbose = B_TRUE;
281 			break;
282 		default:
283 			goto err;
284 		}
285 	}
286 
287 	pcnt = argc - optind;
288 	if (pcnt == 1) {
289 		if (strlen(argv[optind]) < MAX_ADRPORT_LEN) {
290 			(void) strcpy(address_port, argv[optind]);
291 		} else {
292 			(void) fprintf(stderr, gettext(
293 			    "argument too long -- %s\n"),
294 			    argv[optind]);
295 			return (FAILURE);
296 		}
297 	} else if (pcnt == 2) {
298 		if ((len = strlen(argv[optind])) +
299 		    (strlen(argv[optind + 1])) < MAX_ADRPORT_LEN) {
300 			(void) strcpy(address_port, argv[optind]);
301 			address_port[len] = ' ';
302 			(void) strcpy(address_port + len + 1, argv[optind + 1]);
303 		} else {
304 			(void) fprintf(stderr, gettext(
305 			    "arguments too long -- %s %s\n"),
306 			    argv[optind], argv[optind + 1]);
307 			return (FAILURE);
308 		}
309 	} else {
310 		goto err;
311 	}
312 
313 	instance_name = create_instance_name(address_port, NULL, B_FALSE);
314 	if (instance_name == NULL) {
315 		return (FAILURE);
316 	}
317 
318 	KSSL_DEBUG("instance_name=%s\n", instance_name);
319 	status = delete_instance(instance_name);
320 	free(instance_name);
321 
322 	return (status);
323 
324 err:
325 	usage_delete(B_TRUE);
326 	return (ERROR_USAGE);
327 }
328