1 2314 mcneal /* 2 2314 mcneal * CDDL HEADER START 3 2314 mcneal * 4 2314 mcneal * The contents of this file are subject to the terms of the 5 2314 mcneal * Common Development and Distribution License (the "License"). 6 2314 mcneal * You may not use this file except in compliance with the License. 7 2314 mcneal * 8 2314 mcneal * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 2314 mcneal * or http://www.opensolaris.org/os/licensing. 10 2314 mcneal * See the License for the specific language governing permissions 11 2314 mcneal * and limitations under the License. 12 2314 mcneal * 13 2314 mcneal * When distributing Covered Code, include this CDDL HEADER in each 14 2314 mcneal * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 2314 mcneal * If applicable, add the following below this CDDL HEADER, with the 16 2314 mcneal * fields enclosed by brackets "[]" replaced with your own identifying 17 2314 mcneal * information: Portions Copyright [yyyy] [name of copyright owner] 18 2314 mcneal * 19 2314 mcneal * CDDL HEADER END 20 2314 mcneal */ 21 2314 mcneal 22 2314 mcneal /* 23 5806 zl149053 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 2314 mcneal * Use is subject to license terms. 25 2314 mcneal */ 26 2314 mcneal 27 2314 mcneal #include <sys/types.h> 28 2314 mcneal #include <time.h> 29 2314 mcneal #include <sys/utsname.h> 30 2314 mcneal #include <unistd.h> 31 2314 mcneal #include <sys/param.h> 32 2314 mcneal #include <fcntl.h> 33 2314 mcneal #include <sys/stat.h> 34 2314 mcneal #include <errno.h> 35 2314 mcneal #include <strings.h> 36 2314 mcneal #include <assert.h> 37 2314 mcneal #include <sys/socket.h> 38 2314 mcneal #include <netdb.h> 39 4483 zl149053 #include <libgen.h> 40 6761 nbhavyan #include <libzfs.h> 41 7018 ks202890 #include <syslog.h> 42 2314 mcneal 43 3126 ahl #include <iscsitgt_impl.h> 44 2314 mcneal #include "queue.h" 45 2314 mcneal #include "utility.h" 46 2314 mcneal #include "iscsi_cmd.h" 47 2314 mcneal #include "target.h" 48 2314 mcneal #include "errcode.h" 49 4348 ts143224 #include "isns_client.h" 50 5137 zl149053 #include "mgmt_scf.h" 51 2314 mcneal 52 6278 jdunham static char *modify_target(tgt_node_t *x, ucred_t *cred); 53 5137 zl149053 static char *modify_initiator(tgt_node_t *x); 54 5137 zl149053 static char *modify_admin(tgt_node_t *x); 55 5137 zl149053 static char *modify_tpgt(tgt_node_t *x); 56 6278 jdunham static char *modify_zfs(tgt_node_t *x, ucred_t *cred); 57 6761 nbhavyan static char *validate_zfs_iscsitgt(tgt_node_t *x); 58 3126 ahl static Boolean_t modify_element(char *, char *, tgt_node_t *, match_type_t); 59 6783 pc198268 static Boolean_t delete_element(char *, tgt_node_t *, match_type_t); 60 2314 mcneal 61 2314 mcneal /* 62 2314 mcneal * []---- 63 2314 mcneal * | modify_func -- dispatch routine for objects 64 2314 mcneal * []---- 65 2314 mcneal */ 66 2314 mcneal /*ARGSUSED*/ 67 2314 mcneal void 68 3545 mcneal modify_func(tgt_node_t *p, target_queue_t *reply, target_queue_t *mgmt, 69 3545 mcneal ucred_t *cred) 70 2314 mcneal { 71 3126 ahl tgt_node_t *x; 72 2314 mcneal char *reply_msg = NULL; 73 2314 mcneal 74 5806 zl149053 x = p->x_child; 75 5806 zl149053 76 5806 zl149053 if (p->x_child == NULL) { 77 5806 zl149053 xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT); 78 5806 zl149053 } else if (strcmp(x->x_name, XML_ELEMENT_ZFS) == 0) { 79 6278 jdunham reply_msg = modify_zfs(x, cred); 80 5806 zl149053 } else if (check_auth_modify(cred) != True) { 81 5137 zl149053 xml_rtn_msg(&reply_msg, ERR_NO_PERMISSION); 82 2314 mcneal } else { 83 2314 mcneal if (x->x_name == NULL) { 84 2314 mcneal xml_rtn_msg(&reply_msg, ERR_SYNTAX_MISSING_OBJECT); 85 2314 mcneal } else if (strcmp(x->x_name, XML_ELEMENT_TARG) == 0) { 86 6278 jdunham reply_msg = modify_target(x, cred); 87 2314 mcneal } else if (strcmp(x->x_name, XML_ELEMENT_INIT) == 0) { 88 5137 zl149053 reply_msg = modify_initiator(x); 89 2314 mcneal } else if (strcmp(x->x_name, XML_ELEMENT_ADMIN) == 0) { 90 5137 zl149053 reply_msg = modify_admin(x); 91 2314 mcneal } else if (strcmp(x->x_name, XML_ELEMENT_TPGT) == 0) { 92 5137 zl149053 reply_msg = modify_tpgt(x); 93 2314 mcneal } else { 94 2314 mcneal xml_rtn_msg(&reply_msg, ERR_INVALID_OBJECT); 95 2314 mcneal } 96 2314 mcneal } 97 2314 mcneal queue_message_set(reply, 0, msg_mgmt_rply, reply_msg); 98 2314 mcneal } 99 2314 mcneal 100 2314 mcneal /* 101 2314 mcneal * []---- 102 2314 mcneal * | modify_target -- updates one or more properties for a target 103 2314 mcneal * []---- 104 2314 mcneal */ 105 2314 mcneal static char * 106 6278 jdunham modify_target(tgt_node_t *x, ucred_t *cred) 107 2314 mcneal { 108 4348 ts143224 char *msg = NULL; 109 4348 ts143224 char *name = NULL; 110 4483 zl149053 char iscsi_path[MAXPATHLEN]; 111 5137 zl149053 char targ_name[64]; 112 4483 zl149053 char *iscsi = NULL; 113 4348 ts143224 char *prop = NULL; 114 4348 ts143224 char path[MAXPATHLEN]; 115 4348 ts143224 char *m; 116 4348 ts143224 char buf[512]; /* one sector size block */ 117 4348 ts143224 tgt_node_t *t = NULL; 118 4348 ts143224 tgt_node_t *list = NULL; 119 4348 ts143224 tgt_node_t *c = NULL; 120 7857 Tim tgt_node_t *node = NULL; 121 4348 ts143224 tgt_node_t *tpgt = NULL; 122 2314 mcneal Boolean_t change_made = False; 123 4348 ts143224 int lun = 0; 124 5137 zl149053 int fd; 125 4348 ts143224 uint64_t val, new_lu_size, cur_lu_size; 126 2314 mcneal struct stat st; 127 6278 jdunham uint32_t isns_mods = 0; 128 2314 mcneal 129 7725 Tim (void) pthread_rwlock_wrlock(&targ_config_mutex); 130 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { 131 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); 132 7725 Tim goto error; 133 2314 mcneal } 134 2314 mcneal 135 6653 ts143224 while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 136 2314 mcneal t)) != NULL) { 137 2314 mcneal if (strcmp(t->x_value, name) == 0) { 138 2314 mcneal break; 139 2314 mcneal } 140 6278 jdunham } 141 6278 jdunham if (t == NULL) { 142 6278 jdunham free(name); 143 6278 jdunham xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); 144 7725 Tim goto error; 145 6278 jdunham } 146 6278 jdunham 147 6278 jdunham if (tgt_find_attr_str(t, XML_ELEMENT_INCORE, &m) == True) { 148 6278 jdunham if (strcmp(m, "true") == 0) { 149 6278 jdunham free(m); 150 7984 Tim free(name); 151 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 152 6278 jdunham return (modify_zfs(x, cred)); 153 6278 jdunham } 154 6278 jdunham free(m); 155 2314 mcneal } 156 2314 mcneal 157 4483 zl149053 /* 158 4483 zl149053 * Under base dir, file 'target name' is a symbolic link 159 4483 zl149053 * to the real directory 'IQN name' which stores params and back 160 4483 zl149053 * storage. Therefore we can easily get IQN name from target 161 4483 zl149053 * name by read the symbolic link content. 162 4483 zl149053 */ 163 6821 nbhavyan (void) snprintf(path, sizeof (path), "%s/%s", target_basedir, name); 164 4483 zl149053 bzero(iscsi_path, sizeof (iscsi_path)); 165 6821 nbhavyan (void) readlink(path, iscsi_path, sizeof (iscsi_path)); 166 4483 zl149053 iscsi = basename(iscsi_path); 167 4483 zl149053 168 2314 mcneal /* ---- Finished with these so go ahead and release the memory ---- */ 169 6821 nbhavyan (void) strncpy(targ_name, name, sizeof (targ_name)); 170 2314 mcneal free(name); 171 2314 mcneal 172 2314 mcneal /* 173 2314 mcneal * Grow the LU. We currently do not support shrinking the LU and 174 2314 mcneal * that is only because it's unknown if any applications could support 175 2314 mcneal * that type of data loss. To support shrinking all that would be 176 2314 mcneal * needed is to remove the new/old size check and perform a truncation. 177 2314 mcneal * The actually truncation request should be shipped off to the T10 178 2314 mcneal * layer so that the LU thread can remap the smaller size without 179 2314 mcneal * anyone accessing the data. 180 2314 mcneal */ 181 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_SIZE, &prop) == True) { 182 2314 mcneal if (prop == NULL) { 183 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); 184 7725 Tim goto error; 185 2314 mcneal } 186 2314 mcneal if (strtoll_multiplier(prop, &new_lu_size) == False) { 187 2314 mcneal free(prop); 188 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_SIZE); 189 7725 Tim goto error; 190 2314 mcneal } 191 2314 mcneal free(prop); 192 2314 mcneal if ((new_lu_size % 512LL) != 0) { 193 2314 mcneal xml_rtn_msg(&msg, ERR_SIZE_MOD_BLOCK); 194 7725 Tim goto error; 195 2314 mcneal } 196 2314 mcneal new_lu_size /= 512LL; 197 2314 mcneal 198 2314 mcneal /* ---- default to LUN 0 ---- */ 199 3126 ahl (void) tgt_find_value_int(x, XML_ELEMENT_LUN, &lun); 200 2314 mcneal 201 4487 zl149053 /* ---- read in current parameters ---- */ 202 7857 Tim if (mgmt_get_param(&node, targ_name, lun) == False) { 203 7857 Tim xml_rtn_msg(&msg, ERR_OPEN_PARAM_FILE_FAILED); 204 7857 Tim goto error; 205 7857 Tim } 206 2314 mcneal 207 2314 mcneal /* ---- validate that we're indeed growing the LU ---- */ 208 3126 ahl if (tgt_find_value_str(node, XML_ELEMENT_SIZE, &prop) == 209 2314 mcneal False) { 210 2314 mcneal xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED); 211 7725 Tim goto error; 212 2314 mcneal } 213 2314 mcneal if (strtoll_multiplier(prop, &cur_lu_size) == False) { 214 2314 mcneal free(prop); 215 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_SIZE); 216 7725 Tim goto error; 217 2314 mcneal } 218 2314 mcneal free(prop); 219 2314 mcneal 220 2314 mcneal if (new_lu_size < cur_lu_size) { 221 2314 mcneal xml_rtn_msg(&msg, ERR_CANT_SHRINK_LU); 222 7725 Tim goto error; 223 2314 mcneal } 224 2314 mcneal 225 2314 mcneal /* ---- check that this LU is of type 'disk' or 'tape' ---- */ 226 3126 ahl if (tgt_find_value_str(node, XML_ELEMENT_DTYPE, &prop) == 227 2314 mcneal False) { 228 2314 mcneal xml_rtn_msg(&msg, ERR_INIT_XML_READER_FAILED); 229 7725 Tim goto error; 230 2314 mcneal } 231 2314 mcneal if ((strcmp(prop, TGT_TYPE_DISK) != 0) && 232 2314 mcneal (strcmp(prop, TGT_TYPE_TAPE) != 0)) { 233 2314 mcneal xml_rtn_msg(&msg, ERR_RESIZE_WRONG_DTYPE); 234 7984 Tim free(prop); 235 7725 Tim goto error; 236 2314 mcneal } 237 2314 mcneal free(prop); 238 2314 mcneal 239 2314 mcneal /* ---- validate the backing store is a regular file ---- */ 240 6821 nbhavyan (void) snprintf(path, sizeof (path), "%s/%s/%s%d", 241 6821 nbhavyan target_basedir, iscsi, LUNBASE, lun); 242 2314 mcneal if (stat(path, &st) == -1) { 243 2314 mcneal xml_rtn_msg(&msg, ERR_STAT_BACKING_FAILED); 244 7725 Tim goto error; 245 2314 mcneal } 246 2314 mcneal if ((st.st_mode & S_IFMT) != S_IFREG) { 247 2314 mcneal xml_rtn_msg(&msg, 248 2314 mcneal ERR_DISK_BACKING_MUST_BE_REGULAR_FILE); 249 7725 Tim goto error; 250 2314 mcneal } 251 2314 mcneal 252 2314 mcneal /* ---- update the parameter node with new size ---- */ 253 4483 zl149053 if ((c = tgt_node_alloc(XML_ELEMENT_SIZE, Uint64, &new_lu_size)) 254 7984 Tim == NULL) { 255 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 256 7725 Tim goto error; 257 2314 mcneal } 258 3126 ahl tgt_node_replace(node, c, MatchName); 259 3126 ahl tgt_node_free(c); 260 2314 mcneal 261 2314 mcneal /* ---- now update params file ---- */ 262 6821 nbhavyan (void) mgmt_param_save2scf(node, targ_name, lun); 263 2314 mcneal 264 2314 mcneal /* ---- grow lu backing store ---- */ 265 6821 nbhavyan (void) snprintf(path, sizeof (path), "%s/%s/%s%d", 266 6821 nbhavyan target_basedir, iscsi, LUNBASE, lun); 267 2314 mcneal if ((fd = open(path, O_RDWR|O_CREAT|O_LARGEFILE, 0600)) < 0) { 268 2314 mcneal xml_rtn_msg(&msg, ERR_LUN_NOT_FOUND); 269 7725 Tim goto error; 270 2314 mcneal } 271 2314 mcneal (void) lseek(fd, (new_lu_size * 512LL) - 512LL, 0); 272 2314 mcneal bzero(buf, sizeof (buf)); 273 2314 mcneal if (write(fd, buf, sizeof (buf)) != sizeof (buf)) { 274 2314 mcneal xml_rtn_msg(&msg, ERR_LUN_NOT_GROWN); 275 7984 Tim (void) close(fd); 276 7725 Tim goto error; 277 2314 mcneal } 278 2314 mcneal (void) close(fd); 279 2314 mcneal 280 2314 mcneal /* ---- send updates to current initiators via ASC/ASCQ ---- */ 281 2314 mcneal iscsi_capacity_change(iscsi, lun); 282 2314 mcneal 283 2314 mcneal prop = NULL; 284 3126 ahl tgt_node_free(node); 285 7984 Tim node = NULL; 286 4483 zl149053 change_made = True; 287 2314 mcneal } 288 2314 mcneal 289 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { 290 2314 mcneal if (prop == NULL) { 291 4348 ts143224 xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); 292 7725 Tim goto error; 293 2314 mcneal } 294 2314 mcneal 295 2314 mcneal /* 296 2314 mcneal * Validate that the Target Portal Group Tag is reasonable. 297 2314 mcneal */ 298 2314 mcneal val = strtoll(prop, &m, 0); 299 2314 mcneal if ((val < TPGT_MIN) || (val > TPGT_MAX) || 300 2314 mcneal ((m != NULL) && (*m != '\0'))) { 301 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_TPGT); 302 2314 mcneal free(prop); 303 7725 Tim goto error; 304 4348 ts143224 } 305 4348 ts143224 306 4348 ts143224 /* update isns only if TPGT contains ip_addr */ 307 6653 ts143224 tpgt = NULL; 308 6653 ts143224 while ((tpgt = tgt_node_next_child(main_config, 309 6653 ts143224 XML_ELEMENT_TPGT, tpgt)) != NULL) { 310 4348 ts143224 if (strcmp(prop, tpgt->x_value) != 0) 311 4348 ts143224 continue; 312 4348 ts143224 if (tgt_node_next(tpgt, XML_ELEMENT_IPADDR, NULL) 313 4348 ts143224 != NULL) { 314 4348 ts143224 isns_mods |= ISNS_MOD_TPGT; 315 4348 ts143224 break; 316 5137 zl149053 } else { 317 5137 zl149053 xml_rtn_msg(&msg, ERR_TPGT_NO_IPADDR); 318 7984 Tim free(prop); 319 7725 Tim goto error; 320 4348 ts143224 } 321 2314 mcneal } 322 2314 mcneal 323 3126 ahl if ((c = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) == 324 2314 mcneal NULL) { 325 2314 mcneal free(prop); 326 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 327 7725 Tim goto error; 328 2314 mcneal } 329 2314 mcneal 330 3126 ahl if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, 331 2314 mcneal NULL)) != NULL) { 332 3126 ahl tgt_node_replace(list, c, MatchBoth); 333 2314 mcneal /* 334 3126 ahl * tgt_node_replace will duplicate the child node 335 3126 ahl * tgt_node_add which is used below just links it 336 2314 mcneal * into the tree. 337 2314 mcneal */ 338 3126 ahl tgt_node_free(c); 339 2314 mcneal } else { 340 3126 ahl list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, ""); 341 2314 mcneal if (list == NULL) { 342 2314 mcneal free(prop); 343 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 344 7725 Tim goto error; 345 2314 mcneal } 346 3126 ahl tgt_node_add(list, c); 347 3126 ahl tgt_node_add(t, list); 348 2314 mcneal } 349 4348 ts143224 350 2314 mcneal free(prop); 351 2314 mcneal prop = NULL; 352 2314 mcneal change_made = True; 353 2314 mcneal } 354 2314 mcneal 355 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { 356 2314 mcneal if (prop == NULL) { 357 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); 358 7725 Tim goto error; 359 2314 mcneal } 360 2314 mcneal 361 6653 ts143224 c = tgt_node_alloc(XML_ELEMENT_INIT, String, prop); 362 2314 mcneal if (c == NULL) { 363 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 364 7984 Tim free(prop); 365 7725 Tim goto error; 366 2314 mcneal } 367 3126 ahl if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, 368 2314 mcneal NULL)) != NULL) { 369 3126 ahl tgt_node_replace(list, c, MatchBoth); 370 2314 mcneal /* ---- See above usage ---- */ 371 3126 ahl tgt_node_free(c); 372 2314 mcneal } else { 373 3126 ahl list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, ""); 374 2314 mcneal if (list == NULL) { 375 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 376 7984 Tim free(prop); 377 7725 Tim goto error; 378 2314 mcneal } 379 3126 ahl tgt_node_add(list, c); 380 3126 ahl tgt_node_add(t, list); 381 2314 mcneal } 382 2314 mcneal free(prop); 383 2314 mcneal prop = NULL; 384 2314 mcneal change_made = True; 385 2314 mcneal } 386 2314 mcneal 387 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_ALIAS, &prop) == True) { 388 2314 mcneal if (prop == NULL) { 389 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ALIAS); 390 7725 Tim goto error; 391 2314 mcneal } 392 2314 mcneal 393 2314 mcneal if (modify_element(XML_ELEMENT_ALIAS, prop, t, MatchName) == 394 2314 mcneal False) { 395 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 396 7984 Tim free(prop); 397 7725 Tim goto error; 398 2314 mcneal } 399 2314 mcneal free(prop); 400 2314 mcneal prop = NULL; 401 4348 ts143224 isns_mods |= ISNS_MOD_ALIAS; 402 2314 mcneal change_made = True; 403 2314 mcneal } 404 2314 mcneal 405 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_MAXRECV, &prop) == True) { 406 2314 mcneal if (prop == NULL) { 407 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_MAXRECV); 408 7725 Tim goto error; 409 2314 mcneal } 410 2314 mcneal 411 2314 mcneal if ((strtoll_multiplier(prop, &val) == False) || 412 2314 mcneal (val < MAXRCVDATA_MIN) || (val > MAXRCVDATA_MAX)) { 413 2314 mcneal free(prop); 414 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_MAXRECV); 415 7725 Tim goto error; 416 2314 mcneal } 417 2314 mcneal free(prop); 418 2314 mcneal if ((prop = malloc(32)) == NULL) { 419 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 420 7725 Tim goto error; 421 2314 mcneal } 422 6821 nbhavyan (void) snprintf(prop, 32, "%d", val); 423 2314 mcneal 424 2314 mcneal if (modify_element(XML_ELEMENT_MAXRECV, prop, t, MatchName) == 425 2314 mcneal False) { 426 2314 mcneal free(prop); 427 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 428 7725 Tim goto error; 429 2314 mcneal } 430 2314 mcneal free(prop); 431 2314 mcneal prop = NULL; 432 2314 mcneal change_made = True; 433 2314 mcneal } 434 2314 mcneal 435 2314 mcneal if (change_made == True) { 436 5137 zl149053 if (mgmt_config_save2scf() == False) { 437 4348 ts143224 xml_rtn_msg(&msg, ERR_UPDATE_TARGCFG_FAILED); 438 7725 Tim goto error; 439 4348 ts143224 } 440 4348 ts143224 if (isns_enabled() == True) { 441 4348 ts143224 if (isns_dev_update(t->x_value, isns_mods) != 0) { 442 7018 ks202890 xml_rtn_msg(&msg, ERR_ISNS_ERROR); 443 7725 Tim goto error; 444 4348 ts143224 } 445 4348 ts143224 } 446 4348 ts143224 xml_rtn_msg(&msg, ERR_SUCCESS); 447 2314 mcneal } else { 448 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); 449 2314 mcneal } 450 2314 mcneal 451 7725 Tim error: 452 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 453 7857 Tim if (node) 454 7857 Tim tgt_node_free(node); 455 2314 mcneal return (msg); 456 2314 mcneal } 457 2314 mcneal 458 2314 mcneal /* 459 2314 mcneal * []---- 460 2314 mcneal * | modify_initiator -- store the CHAP information for an initiator 461 2314 mcneal * []---- 462 2314 mcneal */ 463 2314 mcneal static char * 464 5137 zl149053 modify_initiator(tgt_node_t *x) 465 2314 mcneal { 466 4348 ts143224 char *msg = NULL; 467 4348 ts143224 char *name = NULL; 468 4348 ts143224 char *prop = NULL; 469 3126 ahl tgt_node_t *inode = NULL; 470 2314 mcneal Boolean_t changes_made = False; 471 2314 mcneal 472 7725 Tim (void) pthread_rwlock_wrlock(&targ_config_mutex); 473 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { 474 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); 475 7725 Tim goto error; 476 2314 mcneal } 477 2314 mcneal 478 6653 ts143224 while ((inode = tgt_node_next_child(main_config, XML_ELEMENT_INIT, 479 2314 mcneal inode)) != NULL) { 480 2314 mcneal if (strcmp(inode->x_value, name) == 0) 481 2314 mcneal break; 482 2314 mcneal } 483 2314 mcneal 484 2314 mcneal /* 485 2314 mcneal * We no longer need the name since we should have found the node 486 2314 mcneal * it refers to and this way we don't have to worry about freeing 487 2314 mcneal * the storage later. 488 2314 mcneal */ 489 2314 mcneal free(name); 490 2314 mcneal 491 2314 mcneal if (inode == NULL) { 492 2314 mcneal xml_rtn_msg(&msg, ERR_INIT_NOT_FOUND); 493 7725 Tim goto error; 494 2314 mcneal } 495 2314 mcneal 496 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_CHAPSECRET, &prop) == True) { 497 2314 mcneal if (prop == NULL) { 498 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPSECRET); 499 7725 Tim goto error; 500 2314 mcneal } 501 2314 mcneal 502 2314 mcneal if (modify_element(XML_ELEMENT_CHAPSECRET, prop, inode, 503 2314 mcneal MatchName) == False) { 504 6783 pc198268 free(prop); 505 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 506 7725 Tim goto error; 507 2314 mcneal } 508 2314 mcneal free(prop); 509 6783 pc198268 changes_made = True; 510 6783 pc198268 } 511 6783 pc198268 512 6783 pc198268 if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPSECRET, 513 6783 pc198268 &prop) == True) { 514 6783 pc198268 if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) { 515 6783 pc198268 if (prop != NULL) 516 6783 pc198268 free(prop); 517 6783 pc198268 xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); 518 7725 Tim goto error; 519 6783 pc198268 } 520 6783 pc198268 free(prop); 521 6783 pc198268 522 6783 pc198268 if (delete_element(XML_ELEMENT_CHAPSECRET, inode, 523 6783 pc198268 MatchName) == False) { 524 6783 pc198268 xml_rtn_msg(&msg, ERR_NO_MEM); 525 7725 Tim goto error; 526 6783 pc198268 } 527 2314 mcneal changes_made = True; 528 2314 mcneal } 529 2314 mcneal 530 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_CHAPNAME, &prop) == True) { 531 2314 mcneal if (prop == NULL) { 532 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_CHAPNAME); 533 7725 Tim goto error; 534 2314 mcneal } 535 2314 mcneal 536 2314 mcneal if (modify_element(XML_ELEMENT_CHAPNAME, prop, inode, 537 2314 mcneal MatchName) == False) { 538 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 539 7725 Tim free(prop); 540 7725 Tim goto error; 541 2314 mcneal } 542 2314 mcneal free(prop); 543 6783 pc198268 changes_made = True; 544 6783 pc198268 } 545 6783 pc198268 546 6783 pc198268 if (tgt_find_value_str(x, XML_ELEMENT_DELETE_CHAPNAME, &prop) == True) { 547 6783 pc198268 if (prop == NULL || strcmp(prop, XML_VALUE_TRUE) != 0) { 548 6783 pc198268 if (prop != NULL) 549 6783 pc198268 free(prop); 550 6783 pc198268 xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); 551 7725 Tim goto error; 552 6783 pc198268 } 553 6783 pc198268 free(prop); 554 6783 pc198268 555 6783 pc198268 556 6783 pc198268 if (delete_element(XML_ELEMENT_CHAPNAME, inode, 557 6783 pc198268 MatchName) == False) { 558 6783 pc198268 xml_rtn_msg(&msg, ERR_NO_MEM); 559 7725 Tim goto error; 560 6783 pc198268 } 561 2314 mcneal changes_made = True; 562 2314 mcneal } 563 2314 mcneal 564 2314 mcneal if (changes_made == True) { 565 6861 htk if (mgmt_config_save2scf() == True) { 566 2314 mcneal xml_rtn_msg(&msg, ERR_SUCCESS); 567 6861 htk } else { 568 6861 htk xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); 569 6861 htk } 570 2314 mcneal } else { 571 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); 572 2314 mcneal } 573 2314 mcneal 574 7725 Tim error: 575 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 576 2314 mcneal return (msg); 577 2314 mcneal } 578 2314 mcneal 579 2314 mcneal /* 580 2314 mcneal * []---- 581 2314 mcneal * | modify_admin -- modify one or more of the admin related props 582 2314 mcneal * []---- 583 2314 mcneal */ 584 2314 mcneal static char * 585 5137 zl149053 modify_admin(tgt_node_t *x) 586 2314 mcneal { 587 4348 ts143224 char *msg = NULL; 588 4348 ts143224 char *prop; 589 2314 mcneal Boolean_t changes_made = False; 590 6920 ks202890 Boolean_t update_isns = False; 591 2314 mcneal admin_table_t *ap; 592 2314 mcneal 593 2314 mcneal for (ap = admin_prop_list; ap->name; ap++) { 594 3126 ahl if (tgt_find_value_str(x, ap->name, &prop) == True) { 595 6920 ks202890 596 2314 mcneal if ((prop == NULL) || (strlen(prop) == 0)) 597 2314 mcneal break; 598 2314 mcneal 599 2314 mcneal /* 600 2314 mcneal * Do the function call first if it exists which 601 2314 mcneal * will allow possible checking to be done first. 602 2314 mcneal */ 603 2314 mcneal if (ap->func) { 604 6783 pc198268 msg = (*ap->func)(ap->name, prop); 605 6783 pc198268 if (msg != NULL) { 606 6783 pc198268 free(prop); 607 2314 mcneal return (msg); 608 6783 pc198268 } 609 2314 mcneal } 610 6783 pc198268 611 7725 Tim (void) pthread_rwlock_wrlock(&targ_config_mutex); 612 6783 pc198268 if (ap->delete_name == NULL) { 613 6783 pc198268 if (modify_element(ap->name, prop, main_config, 614 6783 pc198268 MatchName) == False) { 615 6783 pc198268 xml_rtn_msg(&msg, ERR_NO_MEM); 616 6783 pc198268 free(prop); 617 7725 Tim (void) pthread_rwlock_unlock( 618 7725 Tim &targ_config_mutex); 619 6783 pc198268 return (msg); 620 6783 pc198268 } 621 6783 pc198268 } else { 622 6783 pc198268 if (strcmp(prop, XML_VALUE_TRUE) != 0) { 623 6783 pc198268 xml_rtn_msg(&msg, 624 6783 pc198268 ERR_SYNTAX_MISSING_OPERAND); 625 6783 pc198268 free(prop); 626 7725 Tim (void) pthread_rwlock_unlock( 627 7725 Tim &targ_config_mutex); 628 6783 pc198268 return (msg); 629 6783 pc198268 } 630 6783 pc198268 if (delete_element(ap->delete_name, 631 6783 pc198268 main_config, MatchName) == False) { 632 6783 pc198268 xml_rtn_msg(&msg, ERR_NO_MEM); 633 6783 pc198268 free(prop); 634 7725 Tim (void) pthread_rwlock_unlock( 635 7725 Tim &targ_config_mutex); 636 6783 pc198268 return (msg); 637 6783 pc198268 } 638 2314 mcneal } 639 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 640 6920 ks202890 if (0 == strcmp(ap->name, XML_ELEMENT_ISNS_ACCESS) || 641 6920 ks202890 0 == strcmp(ap->name, XML_ELEMENT_ISNS_SERV)) { 642 6920 ks202890 update_isns = True; 643 6920 ks202890 } 644 2314 mcneal free(prop); 645 2314 mcneal changes_made = True; 646 2314 mcneal } 647 2314 mcneal } 648 2314 mcneal 649 2314 mcneal if (changes_made == True) { 650 4348 ts143224 /* isns_update updates isns_access & isns server name */ 651 6920 ks202890 if (update_isns == True) { 652 6920 ks202890 if (isns_update() != 0) { 653 6920 ks202890 xml_rtn_msg(&msg, ERR_ISNS_ERROR); 654 6920 ks202890 return (msg); 655 6920 ks202890 } 656 4348 ts143224 } 657 6861 htk if (mgmt_config_save2scf() == True) { 658 2314 mcneal xml_rtn_msg(&msg, ERR_SUCCESS); 659 6861 htk } else { 660 6861 htk xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); 661 6861 htk } 662 2314 mcneal } else { 663 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_OPERAND); 664 2314 mcneal } 665 2314 mcneal 666 2314 mcneal return (msg); 667 2314 mcneal } 668 2314 mcneal 669 2314 mcneal /* 670 2314 mcneal * []---- 671 2314 mcneal * | modify_tpgt -- add an IP-address to a target portal group 672 2314 mcneal * []---- 673 2314 mcneal */ 674 2314 mcneal static char * 675 5137 zl149053 modify_tpgt(tgt_node_t *x) 676 2314 mcneal { 677 2314 mcneal struct addrinfo *res = NULL; 678 4348 ts143224 char *msg = NULL; 679 4348 ts143224 char *name = NULL; 680 4348 ts143224 char *ip_str = NULL; 681 3126 ahl tgt_node_t *tnode = NULL; 682 8007 Charles tgt_node_t *list = NULL; 683 2314 mcneal 684 7725 Tim (void) pthread_rwlock_wrlock(&targ_config_mutex); 685 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_NAME, &name) == False) { 686 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); 687 2314 mcneal goto error; 688 2314 mcneal } 689 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_IPADDR, &ip_str) == False) { 690 2314 mcneal xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_IPADDR); 691 2314 mcneal goto error; 692 2314 mcneal } 693 2314 mcneal if ((getaddrinfo(ip_str, NULL, NULL, &res) != 0) || (res == NULL)) { 694 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_IP); 695 2314 mcneal goto error; 696 2314 mcneal } 697 6653 ts143224 while ((tnode = tgt_node_next_child(main_config, XML_ELEMENT_TPGT, 698 2314 mcneal tnode)) != NULL) { 699 2314 mcneal if (strcmp(tnode->x_value, name) == 0) 700 2314 mcneal break; 701 2314 mcneal } 702 2314 mcneal if (tnode == NULL) { 703 2314 mcneal xml_rtn_msg(&msg, ERR_TPGT_NOT_FOUND); 704 2314 mcneal goto error; 705 2314 mcneal } 706 8007 Charles 707 8007 Charles if ((list = tgt_node_next(tnode, XML_ELEMENT_IPADDRLIST, NULL)) 708 8007 Charles == NULL) { 709 8007 Charles list = tgt_node_alloc(XML_ELEMENT_IPADDRLIST, String, ""); 710 8007 Charles if (list == NULL) { 711 8007 Charles xml_rtn_msg(&msg, ERR_NO_MEM); 712 8007 Charles goto error; 713 8007 Charles } 714 8007 Charles tgt_node_add(tnode, list); 715 8007 Charles } 716 8007 Charles if (modify_element(XML_ELEMENT_IPADDR, ip_str, list, MatchBoth) == 717 2314 mcneal False) { 718 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 719 7725 Tim goto error; 720 2314 mcneal } 721 2314 mcneal 722 6861 htk if (mgmt_config_save2scf() == True) { 723 2314 mcneal xml_rtn_msg(&msg, ERR_SUCCESS); 724 6861 htk } else { 725 6861 htk /* tpgt change should be updated to smf */ 726 6861 htk xml_rtn_msg(&msg, ERR_INTERNAL_ERROR); 727 6861 htk } 728 2314 mcneal 729 4348 ts143224 /* 730 4348 ts143224 * Re-register all targets, currently there's no method to 731 4348 ts143224 * update TPGT for individual target 732 4348 ts143224 */ 733 4348 ts143224 if (isns_enabled() == True) { 734 6821 nbhavyan (void) isns_reg_all(); 735 4348 ts143224 } 736 4348 ts143224 737 2314 mcneal error: 738 2314 mcneal if (name) 739 2314 mcneal free(name); 740 2314 mcneal if (ip_str) 741 2314 mcneal free(ip_str); 742 7857 Tim if (res) 743 7857 Tim freeaddrinfo(res); 744 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 745 2314 mcneal return (msg); 746 2314 mcneal } 747 2314 mcneal 748 3545 mcneal /* 749 3545 mcneal * modify_zfs -- test for the existence of a certain dataset being shared 750 3545 mcneal * 751 3545 mcneal * Called when someone uses the iscsitgt_is_shared() function from libiscsitgt. 752 3545 mcneal * All that 753 3545 mcneal */ 754 3126 ahl static char * 755 6278 jdunham modify_zfs(tgt_node_t *x, ucred_t *cred) 756 3126 ahl { 757 4348 ts143224 char *msg = NULL; 758 4348 ts143224 char *dataset = NULL; 759 6278 jdunham char *prop; 760 6278 jdunham char *m; 761 3126 ahl tgt_node_t *n = NULL; 762 6278 jdunham tgt_node_t *t = NULL; 763 6278 jdunham tgt_node_t *list = NULL; 764 6278 jdunham tgt_node_t *c1, *c2; 765 6278 jdunham Boolean_t change_made = False; 766 6278 jdunham uint64_t size; 767 6278 jdunham int status; 768 6278 jdunham int val; 769 6761 nbhavyan char *tru = "true"; 770 3126 ahl 771 7725 Tim (void) pthread_rwlock_wrlock(&targ_config_mutex); 772 3126 ahl if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { 773 3126 ahl xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); 774 7725 Tim goto error; 775 6761 nbhavyan } 776 6761 nbhavyan 777 6761 nbhavyan /* 778 6761 nbhavyan * Validate request 779 6761 nbhavyan */ 780 6761 nbhavyan if (tgt_find_value_str(x, XML_ELEMENT_VALIDATE, &tru)) { 781 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 782 7857 Tim if (tru) 783 7857 Tim free(tru); 784 7857 Tim free(dataset); 785 6761 nbhavyan return (validate_zfs_iscsitgt(x)); 786 3126 ahl } 787 3126 ahl 788 6278 jdunham /* 789 6278 jdunham * Check for existance of ZFS shareiscsi properties 790 6278 jdunham */ 791 6278 jdunham status = get_zfs_shareiscsi(dataset, &n, &size, cred); 792 6278 jdunham if ((status != ERR_SUCCESS) && (status != ERR_NULL_XML_MESSAGE)) { 793 3126 ahl xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); 794 3126 ahl goto error; 795 3126 ahl } 796 3126 ahl 797 6653 ts143224 while ((t = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, t)) 798 6278 jdunham != NULL) { 799 6278 jdunham if (strcmp(t->x_value, dataset) == 0) 800 3126 ahl break; 801 3126 ahl } 802 6278 jdunham if (t == NULL) { 803 3126 ahl xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); 804 3126 ahl goto error; 805 3126 ahl } 806 3126 ahl 807 6278 jdunham if (tgt_find_value_str(x, XML_ELEMENT_TPGT, &prop) == True) { 808 6278 jdunham if (prop == NULL) { 809 6278 jdunham xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_TPGT); 810 6278 jdunham goto error; 811 6278 jdunham } 812 6278 jdunham 813 6278 jdunham /* 814 6278 jdunham * Validate that the Target Portal Group Tag is reasonable. 815 6278 jdunham */ 816 6278 jdunham val = strtoll(prop, &m, 0); 817 6278 jdunham if ((val < TPGT_MIN) || (val > TPGT_MAX) || 818 6278 jdunham ((m != NULL) && (*m != '\0'))) { 819 6278 jdunham xml_rtn_msg(&msg, ERR_INVALID_TPGT); 820 6278 jdunham goto error; 821 6278 jdunham } 822 6278 jdunham 823 6278 jdunham if ((c1 = tgt_node_alloc(XML_ELEMENT_TPGT, String, prop)) == 824 6278 jdunham NULL) { 825 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 826 6278 jdunham goto error; 827 6278 jdunham } 828 6278 jdunham 829 6278 jdunham /* 830 6278 jdunham * Due to the fact that the targets_config differs from the 831 6278 jdunham * ZVOL properties stored in zfs_shareiscsi, two lists need to 832 6278 jdunham * be updated 833 6278 jdunham */ 834 6278 jdunham c2 = tgt_node_dup(c1); 835 6278 jdunham if ((list = tgt_node_next(t, XML_ELEMENT_TPGTLIST, NULL)) 836 6278 jdunham != NULL) { 837 6278 jdunham /* 838 6278 jdunham * tgt_node_replace will duplicate the child node 839 6278 jdunham * tgt_node_add which is used below just links it 840 6278 jdunham * into the tree. 841 6278 jdunham */ 842 6278 jdunham tgt_node_replace(list, c1, MatchBoth); 843 6278 jdunham tgt_node_free(c1); 844 6278 jdunham } else { 845 6278 jdunham list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, ""); 846 6278 jdunham if (list == NULL) { 847 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 848 6278 jdunham goto error; 849 6278 jdunham } 850 6278 jdunham tgt_node_add(list, c1); 851 6278 jdunham tgt_node_add(t, list); 852 6278 jdunham } 853 6278 jdunham if ((list = tgt_node_next(n, XML_ELEMENT_TPGTLIST, NULL)) 854 6278 jdunham != NULL) { 855 6278 jdunham /* 856 6278 jdunham * tgt_node_replace will duplicate the child node 857 6278 jdunham * tgt_node_add which is used below just links it 858 6278 jdunham * into the tree. 859 6278 jdunham */ 860 6278 jdunham tgt_node_replace(list, c2, MatchBoth); 861 6278 jdunham tgt_node_free(c2); 862 6278 jdunham } else { 863 6278 jdunham list = tgt_node_alloc(XML_ELEMENT_TPGTLIST, String, ""); 864 6278 jdunham if (list == NULL) { 865 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 866 6278 jdunham goto error; 867 6278 jdunham } 868 6278 jdunham tgt_node_add(list, c2); 869 6278 jdunham tgt_node_add(n, list); 870 6278 jdunham } 871 6278 jdunham change_made = True; 872 6278 jdunham } 873 6278 jdunham 874 6278 jdunham if (tgt_find_value_str(x, XML_ELEMENT_ACL, &prop) == True) { 875 6278 jdunham if (prop == NULL) { 876 6278 jdunham xml_rtn_msg(&msg, ERR_SYNTAX_EMPTY_ACL); 877 6278 jdunham goto error; 878 6278 jdunham } 879 6278 jdunham 880 6278 jdunham c1 = tgt_node_alloc(XML_ELEMENT_INIT, String, prop); 881 6278 jdunham if (c1 == NULL) { 882 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 883 6278 jdunham goto error; 884 6278 jdunham } 885 6278 jdunham 886 6278 jdunham /* 887 6278 jdunham * Due to the fact that the targets_config differs from the 888 6278 jdunham * ZVOL properties stored in zfs_shareiscsi, two lists need to 889 6278 jdunham * be updated 890 6278 jdunham */ 891 6278 jdunham c2 = tgt_node_dup(c1); 892 6278 jdunham if ((list = tgt_node_next(t, XML_ELEMENT_ACLLIST, NULL)) 893 6278 jdunham != NULL) { 894 6278 jdunham /* 895 6278 jdunham * tgt_node_replace will duplicate the child node 896 6278 jdunham * tgt_node_add which is used below just links it 897 6278 jdunham * into the tree. 898 6278 jdunham */ 899 6278 jdunham tgt_node_replace(list, c1, MatchBoth); 900 6278 jdunham tgt_node_free(c1); 901 6278 jdunham } else { 902 6278 jdunham list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, ""); 903 6278 jdunham if (list == NULL) { 904 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 905 6278 jdunham goto error; 906 6278 jdunham } 907 6278 jdunham tgt_node_add(list, c1); 908 6278 jdunham tgt_node_add(t, list); 909 6278 jdunham } 910 6278 jdunham if ((list = tgt_node_next(n, XML_ELEMENT_ACLLIST, NULL)) 911 6278 jdunham != NULL) { 912 6278 jdunham /* 913 6278 jdunham * tgt_node_replace will duplicate the child node 914 6278 jdunham * tgt_node_add which is used below just links it 915 6278 jdunham * into the tree. 916 6278 jdunham */ 917 6278 jdunham tgt_node_replace(list, c2, MatchBoth); 918 6278 jdunham tgt_node_free(c2); 919 6278 jdunham } else { 920 6278 jdunham list = tgt_node_alloc(XML_ELEMENT_ACLLIST, String, ""); 921 6278 jdunham if (list == NULL) { 922 6278 jdunham xml_rtn_msg(&msg, ERR_NO_MEM); 923 6278 jdunham goto error; 924 6278 jdunham } 925 6278 jdunham tgt_node_add(list, c2); 926 6278 jdunham tgt_node_add(n, list); 927 6278 jdunham } 928 6278 jdunham 929 6278 jdunham change_made = True; 930 6278 jdunham } 931 6278 jdunham 932 6278 jdunham if (change_made == True) { 933 6278 jdunham status = put_zfs_shareiscsi(dataset, n); 934 6278 jdunham if (status != ERR_SUCCESS) { 935 6278 jdunham xml_rtn_msg(&msg, status); 936 6278 jdunham goto error; 937 6278 jdunham } else { 938 6278 jdunham xml_rtn_msg(&msg, ERR_SUCCESS); 939 6278 jdunham } 940 6278 jdunham } else { 941 6278 jdunham xml_rtn_msg(&msg, ERR_SUCCESS); 942 6278 jdunham } 943 3126 ahl 944 3126 ahl error: 945 6278 jdunham if (n) 946 6278 jdunham tgt_node_free(n); 947 3126 ahl if (dataset) 948 3126 ahl free(dataset); 949 3126 ahl 950 7725 Tim (void) pthread_rwlock_unlock(&targ_config_mutex); 951 3126 ahl return (msg); 952 3126 ahl } 953 3126 ahl 954 2314 mcneal /* 955 6761 nbhavyan * Just checking the existance of the given target. Here we check whether 956 6761 nbhavyan * both zfs and iscsitarget aware of the given target/volume. It neither 957 6761 nbhavyan * care about the credentials nor SHAREISCSI properties. 958 6761 nbhavyan */ 959 6761 nbhavyan static char * 960 6761 nbhavyan validate_zfs_iscsitgt(tgt_node_t *x) 961 6761 nbhavyan { 962 6761 nbhavyan char *msg = NULL; 963 6761 nbhavyan char *prop = NULL; 964 6761 nbhavyan char *dataset = NULL; 965 6761 nbhavyan libzfs_handle_t *zh = NULL; 966 6761 nbhavyan zfs_handle_t *zfsh = NULL; 967 6761 nbhavyan tgt_node_t *n = NULL; 968 6761 nbhavyan 969 6761 nbhavyan if (tgt_find_value_str(x, XML_ELEMENT_NAME, &dataset) == False) { 970 6761 nbhavyan xml_rtn_msg(&msg, ERR_SYNTAX_MISSING_NAME); 971 6761 nbhavyan return (msg); 972 6761 nbhavyan } 973 6761 nbhavyan 974 6761 nbhavyan if (((zh = libzfs_init()) == NULL) || 975 6761 nbhavyan ((zfsh = zfs_open(zh, dataset, ZFS_TYPE_DATASET)) == NULL)) { 976 6761 nbhavyan xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); 977 6761 nbhavyan goto error; 978 6761 nbhavyan } 979 6761 nbhavyan 980 6761 nbhavyan while ((n = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, n)) != 981 6761 nbhavyan NULL) { 982 6761 nbhavyan if (strcmp(n->x_value, dataset) == 0) 983 6761 nbhavyan break; 984 6761 nbhavyan } 985 6761 nbhavyan if (n == NULL) { 986 6761 nbhavyan xml_rtn_msg(&msg, ERR_TARG_NOT_FOUND); 987 6761 nbhavyan goto error; 988 6761 nbhavyan } 989 6761 nbhavyan 990 6761 nbhavyan xml_rtn_msg(&msg, ERR_SUCCESS); 991 6761 nbhavyan 992 6761 nbhavyan error: 993 6761 nbhavyan if (zfsh) 994 6761 nbhavyan zfs_close(zfsh); 995 6761 nbhavyan if (prop) 996 6761 nbhavyan free(prop); 997 6761 nbhavyan if (zh) 998 6761 nbhavyan libzfs_fini(zh); 999 6761 nbhavyan if (dataset) 1000 6761 nbhavyan free(dataset); 1001 6761 nbhavyan 1002 6761 nbhavyan return (msg); 1003 6761 nbhavyan 1004 6761 nbhavyan } 1005 6761 nbhavyan 1006 6761 nbhavyan 1007 6761 nbhavyan /* 1008 2314 mcneal * []---- 1009 2314 mcneal * | modify_element -- helper function to create node and add it to parent 1010 2314 mcneal * | 1011 2314 mcneal * | A False return value indicates a failure to allocate enough memory. 1012 2314 mcneal * []---- 1013 2314 mcneal */ 1014 2314 mcneal static Boolean_t 1015 3126 ahl modify_element(char *name, char *value, tgt_node_t *p, match_type_t m) 1016 2314 mcneal { 1017 3126 ahl tgt_node_t *c; 1018 2314 mcneal 1019 5137 zl149053 1020 5137 zl149053 if ((c = tgt_node_alloc(name, String, value)) == NULL) { 1021 2314 mcneal return (False); 1022 5137 zl149053 } else { 1023 3126 ahl tgt_node_replace(p, c, m); 1024 3126 ahl tgt_node_free(c); 1025 2314 mcneal return (True); 1026 2314 mcneal } 1027 2314 mcneal } 1028 2314 mcneal 1029 2314 mcneal /* 1030 2314 mcneal * []---- 1031 6783 pc198268 * | delete_element -- helper function to remove a node from a parent 1032 6783 pc198268 * | 1033 6783 pc198268 * | A False return value indicates a failure to allocate enough memory. 1034 6783 pc198268 * []---- 1035 6783 pc198268 */ 1036 6783 pc198268 static Boolean_t 1037 6783 pc198268 delete_element(char *name, tgt_node_t *p, match_type_t m) 1038 6783 pc198268 { 1039 6783 pc198268 tgt_node_t *c; 1040 6783 pc198268 1041 6783 pc198268 if ((c = tgt_node_alloc(name, String, NULL)) == NULL) { 1042 6783 pc198268 return (False); 1043 6783 pc198268 } 1044 6783 pc198268 tgt_node_remove(p, c, m); 1045 6783 pc198268 tgt_node_free(c); 1046 6783 pc198268 return (True); 1047 6783 pc198268 } 1048 6783 pc198268 1049 6783 pc198268 /* 1050 6783 pc198268 * []---- 1051 2314 mcneal * | update_basedir -- update the global target directory 1052 2314 mcneal * | 1053 2314 mcneal * | Most of the properties when updated require no futher processing. The 1054 2314 mcneal * | target base directory however must be updated if it hasn't been set. 1055 2314 mcneal * | On a new system the daemon will not have any location to place the 1056 2314 mcneal * | backing store and target configuration files. On a live system we would 1057 2314 mcneal * | screw things up if we changed the global variable if it was already 1058 2314 mcneal * | in use, so we only allow the updating to occur if there are no targets. 1059 2314 mcneal * []---- 1060 2314 mcneal */ 1061 2314 mcneal /*ARGSUSED*/ 1062 2314 mcneal char * 1063 2314 mcneal update_basedir(char *name, char *prop) 1064 2314 mcneal { 1065 3126 ahl tgt_node_t *targ = NULL; 1066 4348 ts143224 char *msg = NULL; 1067 6278 jdunham char *v; 1068 2314 mcneal 1069 2314 mcneal if ((prop == NULL) || (strlen(prop) == 0) || (prop[0] != '/')) { 1070 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_BASEDIR); 1071 2314 mcneal return (msg); 1072 2314 mcneal } 1073 2314 mcneal 1074 6653 ts143224 while ((targ = tgt_node_next_child(targets_config, XML_ELEMENT_TARG, 1075 6653 ts143224 targ)) != NULL) { 1076 3282 mcneal /* 1077 6278 jdunham * Traverse the list of configured targets, serching for any 1078 6278 jdunham * target that is using the current base-directory. Fail the 1079 6278 jdunham * update if found. 1080 6278 jdunham * 1081 6278 jdunham * The only targets that do not use the base-directory at this 1082 6278 jdunham * time are those targets persisted in ZFS. 1083 3282 mcneal */ 1084 6278 jdunham if (tgt_find_attr_str(targ, XML_ELEMENT_INCORE, &v) == True) { 1085 6278 jdunham if (v != NULL) { 1086 6278 jdunham if (strcmp(v, XML_VALUE_TRUE) == 0) { 1087 6278 jdunham free(v); 1088 6278 jdunham continue; 1089 6278 jdunham } 1090 6278 jdunham free(v); 1091 6278 jdunham } 1092 3282 mcneal } 1093 6278 jdunham 1094 6278 jdunham /* 1095 6278 jdunham * Found at least one target, so fail 1096 6278 jdunham */ 1097 6278 jdunham xml_rtn_msg(&msg, ERR_VALID_TARG_EXIST); 1098 6278 jdunham return (msg); 1099 2314 mcneal } 1100 2314 mcneal 1101 6278 jdunham if (target_basedir) { 1102 2314 mcneal free(target_basedir); 1103 6278 jdunham } 1104 6278 jdunham target_basedir = strdup(prop); 1105 6278 jdunham if ((mkdir(target_basedir, 0700) != 0) && (errno != EEXIST)) { 1106 6278 jdunham xml_rtn_msg(&msg, ERR_CREATE_TARGET_DIR_FAILED); 1107 6278 jdunham free(target_basedir); 1108 6278 jdunham target_basedir = NULL; 1109 2314 mcneal } 1110 2314 mcneal return (msg); 1111 2314 mcneal } 1112 2314 mcneal 1113 2314 mcneal /* 1114 2314 mcneal * []---- 1115 2314 mcneal * | validate_radius -- validate that server[:port] are valid 1116 2314 mcneal * []---- 1117 2314 mcneal */ 1118 2314 mcneal char * 1119 2314 mcneal valid_radius_srv(char *name, char *prop) 1120 2314 mcneal { 1121 2314 mcneal struct addrinfo *res = NULL; 1122 4348 ts143224 char *msg = NULL; 1123 4348 ts143224 char *sp, *p; 1124 2314 mcneal int port; 1125 2314 mcneal 1126 2314 mcneal if ((sp = strdup(prop)) == NULL) { 1127 2314 mcneal xml_rtn_msg(&msg, ERR_NO_MEM); 1128 2314 mcneal return (msg); 1129 2314 mcneal } else if ((p = strrchr(sp, ':')) != NULL) { 1130 2314 mcneal *p++ = '\0'; 1131 2314 mcneal port = atoi(p); 1132 2314 mcneal if ((port < 1) || (port > 65535)) { 1133 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_RADSRV); 1134 2314 mcneal free(sp); 1135 2314 mcneal return (msg); 1136 2314 mcneal } 1137 2314 mcneal } 1138 2314 mcneal if ((getaddrinfo(sp, NULL, NULL, &res) != 0) || (res == NULL)) 1139 2314 mcneal xml_rtn_msg(&msg, ERR_INVALID_RADSRV); 1140 2314 mcneal else 1141 2314 mcneal freeaddrinfo(res); 1142 2314 mcneal free(sp); 1143 2314 mcneal return (msg); 1144 2314 mcneal } 1145 4348 ts143224 1146 4348 ts143224 /* 1147 4348 ts143224 * []---- 1148 4348 ts143224 * | validate_isns_server -- validate that server[:port] are valid 1149 4348 ts143224 * []---- 1150 4348 ts143224 */ 1151 4348 ts143224 char * 1152 4348 ts143224 valid_isns_srv(char *name, char *prop) 1153 4348 ts143224 { 1154 4348 ts143224 char *msg = NULL; 1155 4348 ts143224 char *sp, *p; 1156 6086 ts143224 int so; 1157 4348 ts143224 int port; 1158 4348 ts143224 1159 7018 ks202890 if (strlen(prop) > MAXHOSTNAMELEN) { 1160 7018 ks202890 xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV); 1161 7018 ks202890 return (msg); 1162 7018 ks202890 } 1163 7018 ks202890 1164 4348 ts143224 if ((sp = strdup(prop)) == NULL) { 1165 4348 ts143224 xml_rtn_msg(&msg, ERR_NO_MEM); 1166 4348 ts143224 return (msg); 1167 6086 ts143224 } 1168 6086 ts143224 if ((p = strrchr(sp, ':')) != NULL) { 1169 4348 ts143224 *p++ = '\0'; 1170 4348 ts143224 port = atoi(p); 1171 4348 ts143224 if ((port < 1) || (port > 65535)) { 1172 4348 ts143224 xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV); 1173 4348 ts143224 free(sp); 1174 4348 ts143224 return (msg); 1175 4348 ts143224 } 1176 4348 ts143224 } 1177 6086 ts143224 1178 6086 ts143224 so = isns_open(sp); 1179 7018 ks202890 if (so < 0) { 1180 7018 ks202890 if (isns_enabled() == True) { 1181 7018 ks202890 xml_rtn_msg(&msg, ERR_INVALID_ISNS_SRV); 1182 7018 ks202890 } else { /* Just print a warning and accept the server */ 1183 7018 ks202890 syslog(LOG_ALERT, 1184 7018 ks202890 "Check if the server:%s is valid", sp); 1185 7018 ks202890 } 1186 7018 ks202890 } else { 1187 6086 ts143224 isns_close(so); 1188 7018 ks202890 } 1189 4348 ts143224 free(sp); 1190 4348 ts143224 return (msg); 1191 4348 ts143224 } 1192