1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>. 5 * Copyright (c) Intel Corporation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * * Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * * Neither the name of Intel Corporation nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "iscsi/iscsi.h" 36 #include "iscsi/conn.h" 37 #include "iscsi/tgt_node.h" 38 #include "iscsi/portal_grp.h" 39 #include "iscsi/init_grp.h" 40 41 #include "spdk/rpc.h" 42 #include "spdk/util.h" 43 #include "spdk/event.h" 44 #include "spdk/string.h" 45 #include "spdk_internal/log.h" 46 47 static void 48 spdk_rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request, 49 const struct spdk_json_val *params) 50 { 51 struct spdk_json_write_ctx *w; 52 53 if (params != NULL) { 54 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 55 "iscsi_get_initiator_groups requires no parameters"); 56 return; 57 } 58 59 w = spdk_jsonrpc_begin_result(request); 60 spdk_json_write_array_begin(w); 61 spdk_iscsi_init_grps_info_json(w); 62 spdk_json_write_array_end(w); 63 64 spdk_jsonrpc_end_result(request, w); 65 } 66 SPDK_RPC_REGISTER("iscsi_get_initiator_groups", spdk_rpc_iscsi_get_initiator_groups, 67 SPDK_RPC_RUNTIME) 68 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_initiator_groups, get_initiator_groups) 69 70 struct rpc_initiator_list { 71 size_t num_initiators; 72 char *initiators[MAX_INITIATOR]; 73 }; 74 75 static int 76 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out) 77 { 78 struct rpc_initiator_list *list = out; 79 80 return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR, 81 &list->num_initiators, sizeof(char *)); 82 } 83 84 static void 85 free_rpc_initiator_list(struct rpc_initiator_list *list) 86 { 87 size_t i; 88 89 for (i = 0; i < list->num_initiators; i++) { 90 free(list->initiators[i]); 91 } 92 } 93 94 struct rpc_netmask_list { 95 size_t num_netmasks; 96 char *netmasks[MAX_NETMASK]; 97 }; 98 99 static int 100 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out) 101 { 102 struct rpc_netmask_list *list = out; 103 104 return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK, 105 &list->num_netmasks, sizeof(char *)); 106 } 107 108 static void 109 free_rpc_netmask_list(struct rpc_netmask_list *list) 110 { 111 size_t i; 112 113 for (i = 0; i < list->num_netmasks; i++) { 114 free(list->netmasks[i]); 115 } 116 } 117 118 struct rpc_initiator_group { 119 int32_t tag; 120 struct rpc_initiator_list initiator_list; 121 struct rpc_netmask_list netmask_list; 122 }; 123 124 static void 125 free_rpc_initiator_group(struct rpc_initiator_group *ig) 126 { 127 free_rpc_initiator_list(&ig->initiator_list); 128 free_rpc_netmask_list(&ig->netmask_list); 129 } 130 131 static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = { 132 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 133 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list}, 134 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list}, 135 }; 136 137 static void 138 spdk_rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request, 139 const struct spdk_json_val *params) 140 { 141 struct rpc_initiator_group req = {}; 142 struct spdk_json_write_ctx *w; 143 144 if (spdk_json_decode_object(params, rpc_initiator_group_decoders, 145 SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) { 146 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 147 goto invalid; 148 } 149 150 if (req.initiator_list.num_initiators == 0 || 151 req.netmask_list.num_netmasks == 0) { 152 goto invalid; 153 } 154 155 if (spdk_iscsi_init_grp_create_from_initiator_list(req.tag, 156 req.initiator_list.num_initiators, 157 req.initiator_list.initiators, 158 req.netmask_list.num_netmasks, 159 req.netmask_list.netmasks)) { 160 SPDK_ERRLOG("create_from_initiator_list failed\n"); 161 goto invalid; 162 } 163 164 free_rpc_initiator_group(&req); 165 166 w = spdk_jsonrpc_begin_result(request); 167 spdk_json_write_bool(w, true); 168 spdk_jsonrpc_end_result(request, w); 169 return; 170 171 invalid: 172 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 173 free_rpc_initiator_group(&req); 174 } 175 SPDK_RPC_REGISTER("iscsi_create_initiator_group", spdk_rpc_iscsi_create_initiator_group, 176 SPDK_RPC_RUNTIME) 177 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_initiator_group, add_initiator_group) 178 179 static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = { 180 {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32}, 181 {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true}, 182 {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true}, 183 }; 184 185 static void 186 spdk_rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request, 187 const struct spdk_json_val *params) 188 { 189 struct rpc_initiator_group req = {}; 190 struct spdk_json_write_ctx *w; 191 192 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 193 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 194 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 195 goto invalid; 196 } 197 198 if (spdk_iscsi_init_grp_add_initiators_from_initiator_list(req.tag, 199 req.initiator_list.num_initiators, 200 req.initiator_list.initiators, 201 req.netmask_list.num_netmasks, 202 req.netmask_list.netmasks)) { 203 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n"); 204 goto invalid; 205 } 206 207 free_rpc_initiator_group(&req); 208 209 w = spdk_jsonrpc_begin_result(request); 210 spdk_json_write_bool(w, true); 211 spdk_jsonrpc_end_result(request, w); 212 return; 213 214 invalid: 215 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 216 free_rpc_initiator_group(&req); 217 } 218 SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators", 219 spdk_rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME) 220 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_initiator_group_add_initiators, 221 add_initiators_to_initiator_group) 222 223 static void 224 spdk_rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request, 225 const struct spdk_json_val *params) 226 { 227 struct rpc_initiator_group req = {}; 228 struct spdk_json_write_ctx *w; 229 230 if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders, 231 SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) { 232 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 233 goto invalid; 234 } 235 236 if (spdk_iscsi_init_grp_delete_initiators_from_initiator_list(req.tag, 237 req.initiator_list.num_initiators, 238 req.initiator_list.initiators, 239 req.netmask_list.num_netmasks, 240 req.netmask_list.netmasks)) { 241 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n"); 242 goto invalid; 243 } 244 245 free_rpc_initiator_group(&req); 246 247 w = spdk_jsonrpc_begin_result(request); 248 spdk_json_write_bool(w, true); 249 spdk_jsonrpc_end_result(request, w); 250 return; 251 252 invalid: 253 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 254 free_rpc_initiator_group(&req); 255 } 256 SPDK_RPC_REGISTER("iscsi_initiator_group_remove_initiators", 257 spdk_rpc_iscsi_initiator_group_remove_initiators, SPDK_RPC_RUNTIME) 258 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_initiator_group_remove_initiators, 259 delete_initiators_from_initiator_group) 260 261 struct rpc_iscsi_delete_initiator_group { 262 int32_t tag; 263 }; 264 265 static const struct spdk_json_object_decoder rpc_iscsi_delete_initiator_group_decoders[] = { 266 {"tag", offsetof(struct rpc_iscsi_delete_initiator_group, tag), spdk_json_decode_int32}, 267 }; 268 269 static void 270 spdk_rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request, 271 const struct spdk_json_val *params) 272 { 273 struct rpc_iscsi_delete_initiator_group req = {}; 274 struct spdk_json_write_ctx *w; 275 struct spdk_iscsi_init_grp *ig; 276 277 if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders, 278 SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders), 279 &req)) { 280 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 281 goto invalid; 282 } 283 284 ig = spdk_iscsi_init_grp_unregister(req.tag); 285 if (!ig) { 286 goto invalid; 287 } 288 spdk_iscsi_tgt_node_delete_map(NULL, ig); 289 spdk_iscsi_init_grp_destroy(ig); 290 291 w = spdk_jsonrpc_begin_result(request); 292 spdk_json_write_bool(w, true); 293 spdk_jsonrpc_end_result(request, w); 294 return; 295 296 invalid: 297 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 298 } 299 SPDK_RPC_REGISTER("iscsi_delete_initiator_group", spdk_rpc_iscsi_delete_initiator_group, 300 SPDK_RPC_RUNTIME) 301 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_initiator_group, delete_initiator_group) 302 303 static void 304 spdk_rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request *request, 305 const struct spdk_json_val *params) 306 { 307 struct spdk_json_write_ctx *w; 308 309 if (params != NULL) { 310 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 311 "iscsi_get_target_nodes requires no parameters"); 312 return; 313 } 314 315 w = spdk_jsonrpc_begin_result(request); 316 spdk_json_write_array_begin(w); 317 spdk_iscsi_tgt_nodes_info_json(w); 318 spdk_json_write_array_end(w); 319 320 spdk_jsonrpc_end_result(request, w); 321 } 322 SPDK_RPC_REGISTER("iscsi_get_target_nodes", spdk_rpc_iscsi_get_target_nodes, SPDK_RPC_RUNTIME) 323 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_target_nodes, get_target_nodes) 324 325 struct rpc_pg_ig_map { 326 int32_t pg_tag; 327 int32_t ig_tag; 328 }; 329 330 static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = { 331 {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32}, 332 {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32}, 333 }; 334 335 static int 336 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out) 337 { 338 struct rpc_pg_ig_map *pg_ig_map = out; 339 340 return spdk_json_decode_object(val, rpc_pg_ig_map_decoders, 341 SPDK_COUNTOF(rpc_pg_ig_map_decoders), 342 pg_ig_map); 343 } 344 345 struct rpc_pg_ig_maps { 346 size_t num_maps; 347 struct rpc_pg_ig_map maps[MAX_TARGET_MAP]; 348 }; 349 350 static int 351 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out) 352 { 353 struct rpc_pg_ig_maps *pg_ig_maps = out; 354 355 return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps, 356 MAX_TARGET_MAP, &pg_ig_maps->num_maps, 357 sizeof(struct rpc_pg_ig_map)); 358 } 359 360 #define RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN 64 361 362 struct rpc_lun { 363 char *bdev_name; 364 int32_t lun_id; 365 }; 366 367 static const struct spdk_json_object_decoder rpc_lun_decoders[] = { 368 {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string}, 369 {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32}, 370 }; 371 372 static int 373 decode_rpc_lun(const struct spdk_json_val *val, void *out) 374 { 375 struct rpc_lun *lun = out; 376 377 return spdk_json_decode_object(val, rpc_lun_decoders, 378 SPDK_COUNTOF(rpc_lun_decoders), lun); 379 } 380 381 struct rpc_luns { 382 size_t num_luns; 383 struct rpc_lun luns[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN]; 384 }; 385 386 static int 387 decode_rpc_luns(const struct spdk_json_val *val, void *out) 388 { 389 struct rpc_luns *luns = out; 390 391 return spdk_json_decode_array(val, decode_rpc_lun, luns->luns, 392 RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN, 393 &luns->num_luns, sizeof(struct rpc_lun)); 394 } 395 396 static void 397 free_rpc_luns(struct rpc_luns *p) 398 { 399 size_t i; 400 401 for (i = 0; i < p->num_luns; i++) { 402 free(p->luns[i].bdev_name); 403 } 404 } 405 406 struct rpc_target_node { 407 char *name; 408 char *alias_name; 409 410 struct rpc_pg_ig_maps pg_ig_maps; 411 struct rpc_luns luns; 412 413 int32_t queue_depth; 414 bool disable_chap; 415 bool require_chap; 416 bool mutual_chap; 417 int32_t chap_group; 418 419 bool header_digest; 420 bool data_digest; 421 }; 422 423 static void 424 free_rpc_target_node(struct rpc_target_node *req) 425 { 426 free(req->name); 427 free(req->alias_name); 428 free_rpc_luns(&req->luns); 429 } 430 431 static const struct spdk_json_object_decoder rpc_target_node_decoders[] = { 432 {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string}, 433 {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string}, 434 {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps}, 435 {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns}, 436 {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32}, 437 {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true}, 438 {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true}, 439 {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true}, 440 {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true}, 441 {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true}, 442 {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true}, 443 }; 444 445 static void 446 spdk_rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request, 447 const struct spdk_json_val *params) 448 { 449 struct rpc_target_node req = {}; 450 struct spdk_json_write_ctx *w; 451 struct spdk_iscsi_tgt_node *target; 452 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 453 char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 454 int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0}; 455 size_t i; 456 457 if (spdk_json_decode_object(params, rpc_target_node_decoders, 458 SPDK_COUNTOF(rpc_target_node_decoders), 459 &req)) { 460 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 461 goto invalid; 462 } 463 464 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 465 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 466 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 467 } 468 469 for (i = 0; i < req.luns.num_luns; i++) { 470 bdev_names[i] = req.luns.luns[i].bdev_name; 471 lun_ids[i] = req.luns.luns[i].lun_id; 472 } 473 474 /* 475 * Use default parameters in a few places: 476 * index = -1 : automatically pick an index for the new target node 477 * alias = NULL 478 */ 479 target = spdk_iscsi_tgt_node_construct(-1, req.name, req.alias_name, 480 pg_tags, 481 ig_tags, 482 req.pg_ig_maps.num_maps, 483 (const char **)bdev_names, 484 lun_ids, 485 req.luns.num_luns, 486 req.queue_depth, 487 req.disable_chap, 488 req.require_chap, 489 req.mutual_chap, 490 req.chap_group, 491 req.header_digest, 492 req.data_digest); 493 494 if (target == NULL) { 495 goto invalid; 496 } 497 498 free_rpc_target_node(&req); 499 500 w = spdk_jsonrpc_begin_result(request); 501 spdk_json_write_bool(w, true); 502 spdk_jsonrpc_end_result(request, w); 503 return; 504 505 invalid: 506 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 507 free_rpc_target_node(&req); 508 } 509 SPDK_RPC_REGISTER("iscsi_create_target_node", spdk_rpc_iscsi_create_target_node, SPDK_RPC_RUNTIME) 510 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_target_node, construct_target_node) 511 512 struct rpc_tgt_node_pg_ig_maps { 513 char *name; 514 struct rpc_pg_ig_maps pg_ig_maps; 515 }; 516 517 static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = { 518 {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string}, 519 {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps}, 520 }; 521 522 static void 523 spdk_rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request, 524 const struct spdk_json_val *params) 525 { 526 struct rpc_tgt_node_pg_ig_maps req = {}; 527 struct spdk_json_write_ctx *w; 528 struct spdk_iscsi_tgt_node *target; 529 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 530 size_t i; 531 int rc; 532 533 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 534 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 535 &req)) { 536 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 537 goto invalid; 538 } 539 540 target = spdk_iscsi_find_tgt_node(req.name); 541 if (target == NULL) { 542 SPDK_ERRLOG("target is not found\n"); 543 goto invalid; 544 } 545 546 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 547 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 548 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 549 } 550 551 rc = spdk_iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags, 552 req.pg_ig_maps.num_maps); 553 if (rc < 0) { 554 SPDK_ERRLOG("add pg-ig maps failed\n"); 555 goto invalid; 556 } 557 558 free(req.name); 559 560 w = spdk_jsonrpc_begin_result(request); 561 spdk_json_write_bool(w, true); 562 spdk_jsonrpc_end_result(request, w); 563 return; 564 565 invalid: 566 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 567 "Invalid parameters"); 568 free(req.name); 569 } 570 SPDK_RPC_REGISTER("iscsi_target_node_add_pg_ig_maps", 571 spdk_rpc_iscsi_target_node_add_pg_ig_maps, SPDK_RPC_RUNTIME) 572 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_pg_ig_maps, add_pg_ig_maps) 573 574 static void 575 spdk_rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request, 576 const struct spdk_json_val *params) 577 { 578 struct rpc_tgt_node_pg_ig_maps req = {}; 579 struct spdk_json_write_ctx *w; 580 struct spdk_iscsi_tgt_node *target; 581 int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0}; 582 size_t i; 583 int rc; 584 585 if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders, 586 SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders), 587 &req)) { 588 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 589 goto invalid; 590 } 591 592 target = spdk_iscsi_find_tgt_node(req.name); 593 if (target == NULL) { 594 SPDK_ERRLOG("target is not found\n"); 595 goto invalid; 596 } 597 598 for (i = 0; i < req.pg_ig_maps.num_maps; i++) { 599 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag; 600 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag; 601 } 602 603 rc = spdk_iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags, 604 req.pg_ig_maps.num_maps); 605 if (rc < 0) { 606 SPDK_ERRLOG("remove pg-ig maps failed\n"); 607 goto invalid; 608 } 609 610 free(req.name); 611 612 w = spdk_jsonrpc_begin_result(request); 613 spdk_json_write_bool(w, true); 614 spdk_jsonrpc_end_result(request, w); 615 return; 616 617 invalid: 618 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 619 "Invalid parameters"); 620 free(req.name); 621 } 622 SPDK_RPC_REGISTER("iscsi_target_node_remove_pg_ig_maps", 623 spdk_rpc_iscsi_target_node_remove_pg_ig_maps, SPDK_RPC_RUNTIME) 624 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_remove_pg_ig_maps, 625 delete_pg_ig_maps) 626 627 struct rpc_iscsi_delete_target_node { 628 char *name; 629 }; 630 631 static void 632 free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r) 633 { 634 free(r->name); 635 } 636 637 static const struct spdk_json_object_decoder rpc_iscsi_delete_target_node_decoders[] = { 638 {"name", offsetof(struct rpc_iscsi_delete_target_node, name), spdk_json_decode_string}, 639 }; 640 641 struct rpc_iscsi_delete_target_node_ctx { 642 struct rpc_iscsi_delete_target_node req; 643 struct spdk_jsonrpc_request *request; 644 }; 645 646 static void 647 rpc_iscsi_delete_target_node_done(void *cb_arg, int rc) 648 { 649 struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg; 650 struct spdk_json_write_ctx *w; 651 652 free_rpc_iscsi_delete_target_node(&ctx->req); 653 654 w = spdk_jsonrpc_begin_result(ctx->request); 655 spdk_json_write_bool(w, rc == 0); 656 spdk_jsonrpc_end_result(ctx->request, w); 657 658 free(ctx); 659 } 660 661 static void 662 spdk_rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request, 663 const struct spdk_json_val *params) 664 { 665 struct rpc_iscsi_delete_target_node_ctx *ctx; 666 667 ctx = calloc(1, sizeof(*ctx)); 668 if (!ctx) { 669 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 670 spdk_strerror(ENOMEM)); 671 return; 672 } 673 674 if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders, 675 SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders), 676 &ctx->req)) { 677 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 678 goto invalid; 679 } 680 681 if (ctx->req.name == NULL) { 682 SPDK_ERRLOG("missing name param\n"); 683 goto invalid; 684 } 685 686 ctx->request = request; 687 688 spdk_iscsi_shutdown_tgt_node_by_name(ctx->req.name, 689 rpc_iscsi_delete_target_node_done, ctx); 690 return; 691 692 invalid: 693 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 694 free_rpc_iscsi_delete_target_node(&ctx->req); 695 free(ctx); 696 } 697 SPDK_RPC_REGISTER("iscsi_delete_target_node", spdk_rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME) 698 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_target_node, delete_target_node) 699 700 static void 701 spdk_rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request, 702 const struct spdk_json_val *params) 703 { 704 struct spdk_json_write_ctx *w; 705 706 if (params != NULL) { 707 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 708 "iscsi_get_portal_groups requires no parameters"); 709 return; 710 } 711 712 w = spdk_jsonrpc_begin_result(request); 713 spdk_json_write_array_begin(w); 714 spdk_iscsi_portal_grps_info_json(w); 715 spdk_json_write_array_end(w); 716 717 spdk_jsonrpc_end_result(request, w); 718 } 719 SPDK_RPC_REGISTER("iscsi_get_portal_groups", spdk_rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME) 720 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_portal_groups, get_portal_groups) 721 722 struct rpc_portal { 723 char *host; 724 char *port; 725 }; 726 727 struct rpc_portal_list { 728 size_t num_portals; 729 struct rpc_portal portals[MAX_PORTAL]; 730 }; 731 732 struct rpc_portal_group { 733 int32_t tag; 734 struct rpc_portal_list portal_list; 735 }; 736 737 static void 738 free_rpc_portal(struct rpc_portal *portal) 739 { 740 free(portal->host); 741 free(portal->port); 742 } 743 744 static void 745 free_rpc_portal_list(struct rpc_portal_list *pl) 746 { 747 size_t i; 748 749 for (i = 0; i < pl->num_portals; i++) { 750 free_rpc_portal(&pl->portals[i]); 751 } 752 pl->num_portals = 0; 753 } 754 755 static void 756 free_rpc_portal_group(struct rpc_portal_group *pg) 757 { 758 free_rpc_portal_list(&pg->portal_list); 759 } 760 761 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 762 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 763 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 764 }; 765 766 static int 767 decode_rpc_portal(const struct spdk_json_val *val, void *out) 768 { 769 struct rpc_portal *portal = out; 770 771 return spdk_json_decode_object(val, rpc_portal_decoders, 772 SPDK_COUNTOF(rpc_portal_decoders), 773 portal); 774 } 775 776 static int 777 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 778 { 779 struct rpc_portal_list *list = out; 780 781 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 782 sizeof(struct rpc_portal)); 783 } 784 785 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 786 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 787 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 788 }; 789 790 static void 791 spdk_rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 792 const struct spdk_json_val *params) 793 { 794 struct rpc_portal_group req = {}; 795 struct spdk_iscsi_portal_grp *pg = NULL; 796 struct spdk_iscsi_portal *portal; 797 struct spdk_json_write_ctx *w; 798 size_t i = 0; 799 int rc = -1; 800 801 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 802 SPDK_COUNTOF(rpc_portal_group_decoders), 803 &req)) { 804 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 805 goto out; 806 } 807 808 pg = spdk_iscsi_portal_grp_create(req.tag); 809 if (pg == NULL) { 810 SPDK_ERRLOG("portal_grp_create failed\n"); 811 goto out; 812 } 813 for (i = 0; i < req.portal_list.num_portals; i++) { 814 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 815 req.portal_list.portals[i].port); 816 if (portal == NULL) { 817 SPDK_ERRLOG("portal_create failed\n"); 818 goto out; 819 } 820 spdk_iscsi_portal_grp_add_portal(pg, portal); 821 } 822 823 rc = spdk_iscsi_portal_grp_open(pg); 824 if (rc != 0) { 825 SPDK_ERRLOG("portal_grp_open failed\n"); 826 goto out; 827 } 828 829 rc = spdk_iscsi_portal_grp_register(pg); 830 if (rc != 0) { 831 SPDK_ERRLOG("portal_grp_register failed\n"); 832 } 833 834 out: 835 if (rc == 0) { 836 w = spdk_jsonrpc_begin_result(request); 837 spdk_json_write_bool(w, true); 838 spdk_jsonrpc_end_result(request, w); 839 } else { 840 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 841 842 if (pg != NULL) { 843 spdk_iscsi_portal_grp_release(pg); 844 } 845 } 846 free_rpc_portal_group(&req); 847 } 848 SPDK_RPC_REGISTER("iscsi_create_portal_group", spdk_rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 849 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_portal_group, add_portal_group) 850 851 struct rpc_iscsi_delete_portal_group { 852 int32_t tag; 853 }; 854 855 static const struct spdk_json_object_decoder rpc_iscsi_delete_portal_group_decoders[] = { 856 {"tag", offsetof(struct rpc_iscsi_delete_portal_group, tag), spdk_json_decode_int32}, 857 }; 858 859 static void 860 spdk_rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 861 const struct spdk_json_val *params) 862 { 863 struct rpc_iscsi_delete_portal_group req = {}; 864 struct spdk_json_write_ctx *w; 865 struct spdk_iscsi_portal_grp *pg; 866 867 if (spdk_json_decode_object(params, rpc_iscsi_delete_portal_group_decoders, 868 SPDK_COUNTOF(rpc_iscsi_delete_portal_group_decoders), 869 &req)) { 870 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 871 goto invalid; 872 } 873 874 pg = spdk_iscsi_portal_grp_unregister(req.tag); 875 if (!pg) { 876 goto invalid; 877 } 878 879 spdk_iscsi_tgt_node_delete_map(pg, NULL); 880 spdk_iscsi_portal_grp_release(pg); 881 882 w = spdk_jsonrpc_begin_result(request); 883 spdk_json_write_bool(w, true); 884 spdk_jsonrpc_end_result(request, w); 885 return; 886 887 invalid: 888 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 889 } 890 SPDK_RPC_REGISTER("iscsi_delete_portal_group", spdk_rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 891 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_portal_group, delete_portal_group) 892 893 struct rpc_portal_group_auth { 894 int32_t tag; 895 bool disable_chap; 896 bool require_chap; 897 bool mutual_chap; 898 int32_t chap_group; 899 }; 900 901 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 902 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 903 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 904 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 905 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 906 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 907 }; 908 909 static void 910 spdk_rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 911 const struct spdk_json_val *params) 912 { 913 struct rpc_portal_group_auth req = {}; 914 struct spdk_json_write_ctx *w; 915 struct spdk_iscsi_portal_grp *pg; 916 int rc; 917 918 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 919 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 920 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 921 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 922 "Invalid parameters"); 923 return; 924 } 925 926 pthread_mutex_lock(&g_spdk_iscsi.mutex); 927 928 pg = spdk_iscsi_portal_grp_find_by_tag(req.tag); 929 if (pg == NULL) { 930 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 931 "Could not find portal group %d", req.tag); 932 goto exit; 933 } 934 935 rc = spdk_iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 936 req.mutual_chap, req.chap_group); 937 if (rc < 0) { 938 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 939 "Invalid combination of auth params"); 940 goto exit; 941 } 942 943 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 944 945 w = spdk_jsonrpc_begin_result(request); 946 spdk_json_write_bool(w, true); 947 spdk_jsonrpc_end_result(request, w); 948 949 return; 950 951 exit: 952 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 953 } 954 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", spdk_rpc_iscsi_portal_group_set_auth, 955 SPDK_RPC_RUNTIME) 956 957 struct rpc_iscsi_get_connections_ctx { 958 struct spdk_jsonrpc_request *request; 959 struct spdk_json_write_ctx *w; 960 }; 961 962 static void 963 rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 964 { 965 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 966 967 spdk_json_write_array_end(ctx->w); 968 spdk_jsonrpc_end_result(ctx->request, ctx->w); 969 970 free(ctx); 971 } 972 973 static void 974 rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 975 { 976 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 977 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 978 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 979 struct spdk_iscsi_conn *conn; 980 981 STAILQ_FOREACH(conn, &pg->connections, link) { 982 spdk_iscsi_conn_info_json(ctx->w, conn); 983 } 984 985 spdk_for_each_channel_continue(i, 0); 986 } 987 988 static void 989 spdk_rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 990 const struct spdk_json_val *params) 991 { 992 struct rpc_iscsi_get_connections_ctx *ctx; 993 994 if (params != NULL) { 995 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 996 "iscsi_get_connections requires no parameters"); 997 return; 998 } 999 1000 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 1001 if (ctx == NULL) { 1002 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 1003 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1004 return; 1005 } 1006 1007 ctx->request = request; 1008 ctx->w = spdk_jsonrpc_begin_result(request); 1009 1010 spdk_json_write_array_begin(ctx->w); 1011 1012 spdk_for_each_channel(&g_spdk_iscsi, 1013 rpc_iscsi_get_connections, 1014 ctx, 1015 rpc_iscsi_get_connections_done); 1016 } 1017 SPDK_RPC_REGISTER("iscsi_get_connections", spdk_rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 1018 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_connections, get_iscsi_connections) 1019 1020 struct rpc_target_lun { 1021 char *name; 1022 char *bdev_name; 1023 int32_t lun_id; 1024 }; 1025 1026 static void 1027 free_rpc_target_lun(struct rpc_target_lun *req) 1028 { 1029 free(req->name); 1030 free(req->bdev_name); 1031 } 1032 1033 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1034 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1035 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1036 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1037 }; 1038 1039 static void 1040 spdk_rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1041 const struct spdk_json_val *params) 1042 { 1043 struct rpc_target_lun req = {}; 1044 struct spdk_json_write_ctx *w; 1045 struct spdk_iscsi_tgt_node *target; 1046 int rc; 1047 1048 req.lun_id = -1; 1049 1050 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1051 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1052 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1053 goto invalid; 1054 } 1055 1056 target = spdk_iscsi_find_tgt_node(req.name); 1057 if (target == NULL) { 1058 SPDK_ERRLOG("target is not found\n"); 1059 goto invalid; 1060 } 1061 1062 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1063 if (rc < 0) { 1064 SPDK_ERRLOG("add lun failed\n"); 1065 goto invalid; 1066 } 1067 1068 free_rpc_target_lun(&req); 1069 1070 w = spdk_jsonrpc_begin_result(request); 1071 spdk_json_write_bool(w, true); 1072 spdk_jsonrpc_end_result(request, w); 1073 return; 1074 1075 invalid: 1076 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1077 "Invalid parameters"); 1078 free_rpc_target_lun(&req); 1079 } 1080 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", spdk_rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1081 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_lun, target_node_add_lun) 1082 1083 struct rpc_target_auth { 1084 char *name; 1085 bool disable_chap; 1086 bool require_chap; 1087 bool mutual_chap; 1088 int32_t chap_group; 1089 }; 1090 1091 static void 1092 free_rpc_target_auth(struct rpc_target_auth *req) 1093 { 1094 free(req->name); 1095 } 1096 1097 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1098 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1099 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1100 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1101 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1102 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1103 }; 1104 1105 static void 1106 spdk_rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1107 const struct spdk_json_val *params) 1108 { 1109 struct rpc_target_auth req = {}; 1110 struct spdk_json_write_ctx *w; 1111 struct spdk_iscsi_tgt_node *target; 1112 int rc; 1113 1114 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1115 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1116 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1117 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1118 "Invalid parameters"); 1119 goto exit; 1120 } 1121 1122 target = spdk_iscsi_find_tgt_node(req.name); 1123 if (target == NULL) { 1124 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1125 "Could not find target %s", req.name); 1126 goto exit; 1127 } 1128 1129 rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1130 req.mutual_chap, req.chap_group); 1131 if (rc < 0) { 1132 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1133 "Invalid combination of auth params"); 1134 goto exit; 1135 } 1136 1137 free_rpc_target_auth(&req); 1138 1139 w = spdk_jsonrpc_begin_result(request); 1140 spdk_json_write_bool(w, true); 1141 spdk_jsonrpc_end_result(request, w); 1142 return; 1143 1144 exit: 1145 free_rpc_target_auth(&req); 1146 } 1147 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", spdk_rpc_iscsi_target_node_set_auth, 1148 SPDK_RPC_RUNTIME) 1149 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_set_auth, set_iscsi_target_node_auth) 1150 1151 static void 1152 spdk_rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1153 const struct spdk_json_val *params) 1154 { 1155 struct spdk_json_write_ctx *w; 1156 1157 if (params != NULL) { 1158 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1159 "iscsi_get_options requires no parameters"); 1160 return; 1161 } 1162 1163 w = spdk_jsonrpc_begin_result(request); 1164 spdk_iscsi_opts_info_json(w); 1165 1166 spdk_jsonrpc_end_result(request, w); 1167 } 1168 SPDK_RPC_REGISTER("iscsi_get_options", spdk_rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1169 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_options, get_iscsi_global_params) 1170 1171 struct rpc_discovery_auth { 1172 bool disable_chap; 1173 bool require_chap; 1174 bool mutual_chap; 1175 int32_t chap_group; 1176 }; 1177 1178 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1179 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1180 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1181 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1182 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1183 }; 1184 1185 static void 1186 spdk_rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1187 const struct spdk_json_val *params) 1188 { 1189 struct rpc_discovery_auth req = {}; 1190 struct spdk_json_write_ctx *w; 1191 int rc; 1192 1193 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1194 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1195 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1196 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1197 "Invalid parameters"); 1198 return; 1199 } 1200 1201 rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1202 req.mutual_chap, req.chap_group); 1203 if (rc < 0) { 1204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1205 "Invalid combination of CHAP params"); 1206 return; 1207 } 1208 1209 w = spdk_jsonrpc_begin_result(request); 1210 spdk_json_write_bool(w, true); 1211 spdk_jsonrpc_end_result(request, w); 1212 } 1213 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", spdk_rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1214 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_discovery_auth, set_iscsi_discovery_auth) 1215 1216 #define MAX_AUTH_SECRETS 64 1217 1218 struct rpc_auth_secret { 1219 char *user; 1220 char *secret; 1221 char *muser; 1222 char *msecret; 1223 }; 1224 1225 static void 1226 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1227 { 1228 free(_secret->user); 1229 free(_secret->secret); 1230 free(_secret->muser); 1231 free(_secret->msecret); 1232 } 1233 1234 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1235 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1236 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1237 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1238 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1239 }; 1240 1241 static int 1242 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1243 { 1244 struct rpc_auth_secret *_secret = out; 1245 1246 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1247 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1248 } 1249 1250 struct rpc_auth_secrets { 1251 size_t num_secret; 1252 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1253 }; 1254 1255 static void 1256 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1257 { 1258 size_t i; 1259 1260 for (i = 0; i < secrets->num_secret; i++) { 1261 free_rpc_auth_secret(&secrets->secrets[i]); 1262 } 1263 } 1264 1265 static int 1266 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1267 { 1268 struct rpc_auth_secrets *secrets = out; 1269 1270 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1271 MAX_AUTH_SECRETS, &secrets->num_secret, 1272 sizeof(struct rpc_auth_secret)); 1273 } 1274 1275 struct rpc_auth_group { 1276 int32_t tag; 1277 struct rpc_auth_secrets secrets; 1278 }; 1279 1280 static void 1281 free_rpc_auth_group(struct rpc_auth_group *group) 1282 { 1283 free_rpc_auth_secrets(&group->secrets); 1284 } 1285 1286 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1287 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1288 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1289 }; 1290 1291 static void 1292 spdk_rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1293 const struct spdk_json_val *params) 1294 { 1295 struct rpc_auth_group req = {}; 1296 struct rpc_auth_secret *_secret; 1297 struct spdk_json_write_ctx *w; 1298 struct spdk_iscsi_auth_group *group = NULL; 1299 int rc; 1300 size_t i; 1301 1302 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1303 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1304 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1305 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1306 "Invalid parameters"); 1307 free_rpc_auth_group(&req); 1308 return; 1309 } 1310 1311 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1312 1313 rc = spdk_iscsi_add_auth_group(req.tag, &group); 1314 if (rc != 0) { 1315 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1316 1317 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1318 "Could not add auth group (%d), %s", 1319 req.tag, spdk_strerror(-rc)); 1320 free_rpc_auth_group(&req); 1321 return; 1322 } 1323 1324 for (i = 0; i < req.secrets.num_secret; i++) { 1325 _secret = &req.secrets.secrets[i]; 1326 rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1327 _secret->muser, _secret->msecret); 1328 if (rc != 0) { 1329 spdk_iscsi_delete_auth_group(group); 1330 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1331 1332 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1333 "Could not add secret to auth group (%d), %s", 1334 req.tag, spdk_strerror(-rc)); 1335 free_rpc_auth_group(&req); 1336 return; 1337 } 1338 } 1339 1340 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1341 1342 free_rpc_auth_group(&req); 1343 1344 w = spdk_jsonrpc_begin_result(request); 1345 spdk_json_write_bool(w, true); 1346 spdk_jsonrpc_end_result(request, w); 1347 } 1348 SPDK_RPC_REGISTER("iscsi_create_auth_group", spdk_rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1349 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_auth_group, add_iscsi_auth_group) 1350 1351 struct rpc_delete_auth_group { 1352 int32_t tag; 1353 }; 1354 1355 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1356 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1357 }; 1358 1359 static void 1360 spdk_rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1361 const struct spdk_json_val *params) 1362 { 1363 struct rpc_delete_auth_group req = {}; 1364 struct spdk_json_write_ctx *w; 1365 struct spdk_iscsi_auth_group *group; 1366 1367 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1368 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1369 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1370 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1371 "Invalid parameters"); 1372 return; 1373 } 1374 1375 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1376 1377 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1378 if (group == NULL) { 1379 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1380 1381 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1382 "Could not find auth group (%d)", req.tag); 1383 return; 1384 } 1385 1386 spdk_iscsi_delete_auth_group(group); 1387 1388 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1389 1390 w = spdk_jsonrpc_begin_result(request); 1391 spdk_json_write_bool(w, true); 1392 spdk_jsonrpc_end_result(request, w); 1393 } 1394 SPDK_RPC_REGISTER("iscsi_delete_auth_group", spdk_rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1395 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_auth_group, delete_iscsi_auth_group) 1396 1397 struct rpc_add_auth_secret { 1398 int32_t tag; 1399 char *user; 1400 char *secret; 1401 char *muser; 1402 char *msecret; 1403 }; 1404 1405 static void 1406 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1407 { 1408 free(_secret->user); 1409 free(_secret->secret); 1410 free(_secret->muser); 1411 free(_secret->msecret); 1412 } 1413 1414 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1415 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1416 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1417 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1418 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1419 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1420 }; 1421 1422 static void 1423 spdk_rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1424 const struct spdk_json_val *params) 1425 { 1426 struct rpc_add_auth_secret req = {}; 1427 struct spdk_json_write_ctx *w; 1428 struct spdk_iscsi_auth_group *group; 1429 int rc; 1430 1431 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1432 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1433 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1434 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1435 "Invalid parameters"); 1436 free_rpc_add_auth_secret(&req); 1437 return; 1438 } 1439 1440 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1441 1442 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1443 if (group == NULL) { 1444 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1445 1446 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1447 "Could not find auth group (%d)", req.tag); 1448 free_rpc_add_auth_secret(&req); 1449 return; 1450 } 1451 1452 rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1453 if (rc != 0) { 1454 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1455 1456 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1457 "Could not add secret to auth group (%d), %s", 1458 req.tag, spdk_strerror(-rc)); 1459 free_rpc_add_auth_secret(&req); 1460 return; 1461 } 1462 1463 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1464 1465 free_rpc_add_auth_secret(&req); 1466 1467 w = spdk_jsonrpc_begin_result(request); 1468 spdk_json_write_bool(w, true); 1469 spdk_jsonrpc_end_result(request, w); 1470 } 1471 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", spdk_rpc_iscsi_auth_group_add_secret, 1472 SPDK_RPC_RUNTIME) 1473 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_add_secret, add_secret_to_iscsi_auth_group) 1474 1475 1476 struct rpc_remove_auth_secret { 1477 int32_t tag; 1478 char *user; 1479 }; 1480 1481 static void 1482 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1483 { 1484 free(_secret->user); 1485 } 1486 1487 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1488 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1489 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1490 }; 1491 1492 static void 1493 spdk_rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1494 const struct spdk_json_val *params) 1495 { 1496 struct rpc_remove_auth_secret req = {}; 1497 struct spdk_json_write_ctx *w; 1498 struct spdk_iscsi_auth_group *group; 1499 int rc; 1500 1501 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1502 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1503 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1504 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1505 "Invalid parameters"); 1506 free_rpc_remove_auth_secret(&req); 1507 return; 1508 } 1509 1510 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1511 1512 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1513 if (group == NULL) { 1514 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1515 1516 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1517 "Could not find auth group (%d)", req.tag); 1518 free_rpc_remove_auth_secret(&req); 1519 return; 1520 } 1521 1522 rc = spdk_iscsi_auth_group_delete_secret(group, req.user); 1523 if (rc != 0) { 1524 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1525 1526 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1527 "Could not delete secret from CHAP group (%d), %s", 1528 req.tag, spdk_strerror(-rc)); 1529 free_rpc_remove_auth_secret(&req); 1530 return; 1531 } 1532 1533 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1534 1535 free_rpc_remove_auth_secret(&req); 1536 1537 w = spdk_jsonrpc_begin_result(request); 1538 spdk_json_write_bool(w, true); 1539 spdk_jsonrpc_end_result(request, w); 1540 } 1541 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1542 spdk_rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1543 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_remove_secret, 1544 delete_secret_from_iscsi_auth_group) 1545 1546 static void 1547 spdk_rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1548 const struct spdk_json_val *params) 1549 { 1550 struct spdk_json_write_ctx *w; 1551 1552 if (params != NULL) { 1553 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1554 "iscsi_get_auth_groups requires no parameters"); 1555 return; 1556 } 1557 1558 w = spdk_jsonrpc_begin_result(request); 1559 spdk_json_write_array_begin(w); 1560 spdk_iscsi_auth_groups_info_json(w); 1561 spdk_json_write_array_end(w); 1562 1563 spdk_jsonrpc_end_result(request, w); 1564 } 1565 SPDK_RPC_REGISTER("iscsi_get_auth_groups", spdk_rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1566 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_auth_groups, get_iscsi_auth_groups) 1567 1568 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1569 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1570 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1571 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1572 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1573 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1574 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1575 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1576 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1577 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1578 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1579 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1580 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1581 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1582 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1583 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1584 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1585 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1586 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1587 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1588 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1589 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1590 }; 1591 1592 static void 1593 spdk_rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1594 const struct spdk_json_val *params) 1595 { 1596 struct spdk_iscsi_opts *opts; 1597 struct spdk_json_write_ctx *w; 1598 1599 if (g_spdk_iscsi_opts != NULL) { 1600 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1601 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1602 "Must not call more than once"); 1603 return; 1604 } 1605 1606 opts = spdk_iscsi_opts_alloc(); 1607 if (opts == NULL) { 1608 SPDK_ERRLOG("spdk_iscsi_opts_alloc() failed.\n"); 1609 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1610 "Out of memory"); 1611 return; 1612 } 1613 1614 if (params != NULL) { 1615 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1616 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1617 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1618 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1619 "Invalid parameters"); 1620 spdk_iscsi_opts_free(opts); 1621 return; 1622 } 1623 } 1624 1625 g_spdk_iscsi_opts = spdk_iscsi_opts_copy(opts); 1626 spdk_iscsi_opts_free(opts); 1627 1628 if (g_spdk_iscsi_opts == NULL) { 1629 SPDK_ERRLOG("spdk_iscsi_opts_copy() failed\n"); 1630 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1631 "Out of memory"); 1632 return; 1633 } 1634 1635 w = spdk_jsonrpc_begin_result(request); 1636 spdk_json_write_bool(w, true); 1637 spdk_jsonrpc_end_result(request, w); 1638 } 1639 SPDK_RPC_REGISTER("iscsi_set_options", spdk_rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1640 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_options, set_iscsi_options) 1641