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 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 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 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 96 ign_err(const char *unused, ...) 97 { 98 } 99 100 int 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 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