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 char *cpumask; 726 }; 727 728 struct rpc_portal_list { 729 size_t num_portals; 730 struct rpc_portal portals[MAX_PORTAL]; 731 }; 732 733 struct rpc_portal_group { 734 int32_t tag; 735 struct rpc_portal_list portal_list; 736 }; 737 738 static void 739 free_rpc_portal(struct rpc_portal *portal) 740 { 741 free(portal->host); 742 free(portal->port); 743 free(portal->cpumask); 744 } 745 746 static void 747 free_rpc_portal_list(struct rpc_portal_list *pl) 748 { 749 size_t i; 750 751 for (i = 0; i < pl->num_portals; i++) { 752 free_rpc_portal(&pl->portals[i]); 753 } 754 pl->num_portals = 0; 755 } 756 757 static void 758 free_rpc_portal_group(struct rpc_portal_group *pg) 759 { 760 free_rpc_portal_list(&pg->portal_list); 761 } 762 763 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 764 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 765 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 766 {"cpumask", offsetof(struct rpc_portal, cpumask), spdk_json_decode_string, true}, 767 }; 768 769 static int 770 decode_rpc_portal(const struct spdk_json_val *val, void *out) 771 { 772 struct rpc_portal *portal = out; 773 774 return spdk_json_decode_object(val, rpc_portal_decoders, 775 SPDK_COUNTOF(rpc_portal_decoders), 776 portal); 777 } 778 779 static int 780 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 781 { 782 struct rpc_portal_list *list = out; 783 784 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 785 sizeof(struct rpc_portal)); 786 } 787 788 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 789 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 790 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 791 }; 792 793 static void 794 spdk_rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 795 const struct spdk_json_val *params) 796 { 797 struct rpc_portal_group req = {}; 798 struct spdk_iscsi_portal_grp *pg = NULL; 799 struct spdk_iscsi_portal *portal; 800 struct spdk_json_write_ctx *w; 801 size_t i = 0; 802 int rc = -1; 803 804 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 805 SPDK_COUNTOF(rpc_portal_group_decoders), 806 &req)) { 807 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 808 goto out; 809 } 810 811 pg = spdk_iscsi_portal_grp_create(req.tag); 812 if (pg == NULL) { 813 SPDK_ERRLOG("portal_grp_create failed\n"); 814 goto out; 815 } 816 for (i = 0; i < req.portal_list.num_portals; i++) { 817 if (req.portal_list.portals[i].cpumask) { 818 SPDK_WARNLOG("A portal was specified with a CPU mask which is no longer supported.\n"); 819 SPDK_WARNLOG("Ignoring the cpumask.\n"); 820 } 821 822 portal = spdk_iscsi_portal_create(req.portal_list.portals[i].host, 823 req.portal_list.portals[i].port); 824 if (portal == NULL) { 825 SPDK_ERRLOG("portal_create failed\n"); 826 goto out; 827 } 828 spdk_iscsi_portal_grp_add_portal(pg, portal); 829 } 830 831 rc = spdk_iscsi_portal_grp_open(pg); 832 if (rc != 0) { 833 SPDK_ERRLOG("portal_grp_open failed\n"); 834 goto out; 835 } 836 837 rc = spdk_iscsi_portal_grp_register(pg); 838 if (rc != 0) { 839 SPDK_ERRLOG("portal_grp_register failed\n"); 840 } 841 842 out: 843 if (rc == 0) { 844 w = spdk_jsonrpc_begin_result(request); 845 spdk_json_write_bool(w, true); 846 spdk_jsonrpc_end_result(request, w); 847 } else { 848 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 849 850 if (pg != NULL) { 851 spdk_iscsi_portal_grp_release(pg); 852 } 853 } 854 free_rpc_portal_group(&req); 855 } 856 SPDK_RPC_REGISTER("iscsi_create_portal_group", spdk_rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 857 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_portal_group, add_portal_group) 858 859 struct rpc_iscsi_delete_portal_group { 860 int32_t tag; 861 }; 862 863 static const struct spdk_json_object_decoder rpc_iscsi_delete_portal_group_decoders[] = { 864 {"tag", offsetof(struct rpc_iscsi_delete_portal_group, tag), spdk_json_decode_int32}, 865 }; 866 867 static void 868 spdk_rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 869 const struct spdk_json_val *params) 870 { 871 struct rpc_iscsi_delete_portal_group req = {}; 872 struct spdk_json_write_ctx *w; 873 struct spdk_iscsi_portal_grp *pg; 874 875 if (spdk_json_decode_object(params, rpc_iscsi_delete_portal_group_decoders, 876 SPDK_COUNTOF(rpc_iscsi_delete_portal_group_decoders), 877 &req)) { 878 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 879 goto invalid; 880 } 881 882 pg = spdk_iscsi_portal_grp_unregister(req.tag); 883 if (!pg) { 884 goto invalid; 885 } 886 887 spdk_iscsi_tgt_node_delete_map(pg, NULL); 888 spdk_iscsi_portal_grp_release(pg); 889 890 w = spdk_jsonrpc_begin_result(request); 891 spdk_json_write_bool(w, true); 892 spdk_jsonrpc_end_result(request, w); 893 return; 894 895 invalid: 896 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 897 } 898 SPDK_RPC_REGISTER("iscsi_delete_portal_group", spdk_rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 899 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_portal_group, delete_portal_group) 900 901 struct rpc_portal_group_auth { 902 int32_t tag; 903 bool disable_chap; 904 bool require_chap; 905 bool mutual_chap; 906 int32_t chap_group; 907 }; 908 909 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 910 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 911 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 912 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 913 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 914 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 915 }; 916 917 static void 918 spdk_rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 919 const struct spdk_json_val *params) 920 { 921 struct rpc_portal_group_auth req = {}; 922 struct spdk_json_write_ctx *w; 923 struct spdk_iscsi_portal_grp *pg; 924 int rc; 925 926 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 927 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 928 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 929 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 930 "Invalid parameters"); 931 return; 932 } 933 934 pthread_mutex_lock(&g_spdk_iscsi.mutex); 935 936 pg = spdk_iscsi_portal_grp_find_by_tag(req.tag); 937 if (pg == NULL) { 938 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 939 "Could not find portal group %d", req.tag); 940 goto exit; 941 } 942 943 rc = spdk_iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 944 req.mutual_chap, req.chap_group); 945 if (rc < 0) { 946 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 947 "Invalid combination of auth params"); 948 goto exit; 949 } 950 951 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 952 953 w = spdk_jsonrpc_begin_result(request); 954 spdk_json_write_bool(w, true); 955 spdk_jsonrpc_end_result(request, w); 956 957 return; 958 959 exit: 960 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 961 } 962 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", spdk_rpc_iscsi_portal_group_set_auth, 963 SPDK_RPC_RUNTIME) 964 965 struct rpc_iscsi_get_connections_ctx { 966 struct spdk_jsonrpc_request *request; 967 struct spdk_json_write_ctx *w; 968 }; 969 970 static void 971 rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 972 { 973 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 974 975 spdk_json_write_array_end(ctx->w); 976 spdk_jsonrpc_end_result(ctx->request, ctx->w); 977 978 free(ctx); 979 } 980 981 static void 982 rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 983 { 984 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 985 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 986 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 987 struct spdk_iscsi_conn *conn; 988 989 STAILQ_FOREACH(conn, &pg->connections, link) { 990 spdk_iscsi_conn_info_json(ctx->w, conn); 991 } 992 993 spdk_for_each_channel_continue(i, 0); 994 } 995 996 static void 997 spdk_rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 998 const struct spdk_json_val *params) 999 { 1000 struct rpc_iscsi_get_connections_ctx *ctx; 1001 1002 if (params != NULL) { 1003 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1004 "iscsi_get_connections requires no parameters"); 1005 return; 1006 } 1007 1008 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 1009 if (ctx == NULL) { 1010 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 1011 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 1012 return; 1013 } 1014 1015 ctx->request = request; 1016 ctx->w = spdk_jsonrpc_begin_result(request); 1017 1018 spdk_json_write_array_begin(ctx->w); 1019 1020 spdk_for_each_channel(&g_spdk_iscsi, 1021 rpc_iscsi_get_connections, 1022 ctx, 1023 rpc_iscsi_get_connections_done); 1024 } 1025 SPDK_RPC_REGISTER("iscsi_get_connections", spdk_rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 1026 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_connections, get_iscsi_connections) 1027 1028 struct rpc_target_lun { 1029 char *name; 1030 char *bdev_name; 1031 int32_t lun_id; 1032 }; 1033 1034 static void 1035 free_rpc_target_lun(struct rpc_target_lun *req) 1036 { 1037 free(req->name); 1038 free(req->bdev_name); 1039 } 1040 1041 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1042 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1043 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1044 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1045 }; 1046 1047 static void 1048 spdk_rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1049 const struct spdk_json_val *params) 1050 { 1051 struct rpc_target_lun req = {}; 1052 struct spdk_json_write_ctx *w; 1053 struct spdk_iscsi_tgt_node *target; 1054 int rc; 1055 1056 req.lun_id = -1; 1057 1058 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1059 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1060 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1061 goto invalid; 1062 } 1063 1064 target = spdk_iscsi_find_tgt_node(req.name); 1065 if (target == NULL) { 1066 SPDK_ERRLOG("target is not found\n"); 1067 goto invalid; 1068 } 1069 1070 rc = spdk_iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1071 if (rc < 0) { 1072 SPDK_ERRLOG("add lun failed\n"); 1073 goto invalid; 1074 } 1075 1076 free_rpc_target_lun(&req); 1077 1078 w = spdk_jsonrpc_begin_result(request); 1079 spdk_json_write_bool(w, true); 1080 spdk_jsonrpc_end_result(request, w); 1081 return; 1082 1083 invalid: 1084 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1085 "Invalid parameters"); 1086 free_rpc_target_lun(&req); 1087 } 1088 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", spdk_rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1089 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_add_lun, target_node_add_lun) 1090 1091 struct rpc_target_auth { 1092 char *name; 1093 bool disable_chap; 1094 bool require_chap; 1095 bool mutual_chap; 1096 int32_t chap_group; 1097 }; 1098 1099 static void 1100 free_rpc_target_auth(struct rpc_target_auth *req) 1101 { 1102 free(req->name); 1103 } 1104 1105 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1106 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1107 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1108 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1109 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1110 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1111 }; 1112 1113 static void 1114 spdk_rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1115 const struct spdk_json_val *params) 1116 { 1117 struct rpc_target_auth req = {}; 1118 struct spdk_json_write_ctx *w; 1119 struct spdk_iscsi_tgt_node *target; 1120 int rc; 1121 1122 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1123 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1124 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1125 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1126 "Invalid parameters"); 1127 goto exit; 1128 } 1129 1130 target = spdk_iscsi_find_tgt_node(req.name); 1131 if (target == NULL) { 1132 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1133 "Could not find target %s", req.name); 1134 goto exit; 1135 } 1136 1137 rc = spdk_iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1138 req.mutual_chap, req.chap_group); 1139 if (rc < 0) { 1140 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1141 "Invalid combination of auth params"); 1142 goto exit; 1143 } 1144 1145 free_rpc_target_auth(&req); 1146 1147 w = spdk_jsonrpc_begin_result(request); 1148 spdk_json_write_bool(w, true); 1149 spdk_jsonrpc_end_result(request, w); 1150 return; 1151 1152 exit: 1153 free_rpc_target_auth(&req); 1154 } 1155 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", spdk_rpc_iscsi_target_node_set_auth, 1156 SPDK_RPC_RUNTIME) 1157 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_target_node_set_auth, set_iscsi_target_node_auth) 1158 1159 static void 1160 spdk_rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1161 const struct spdk_json_val *params) 1162 { 1163 struct spdk_json_write_ctx *w; 1164 1165 if (params != NULL) { 1166 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1167 "iscsi_get_options requires no parameters"); 1168 return; 1169 } 1170 1171 w = spdk_jsonrpc_begin_result(request); 1172 spdk_iscsi_opts_info_json(w); 1173 1174 spdk_jsonrpc_end_result(request, w); 1175 } 1176 SPDK_RPC_REGISTER("iscsi_get_options", spdk_rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1177 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_options, get_iscsi_global_params) 1178 1179 struct rpc_discovery_auth { 1180 bool disable_chap; 1181 bool require_chap; 1182 bool mutual_chap; 1183 int32_t chap_group; 1184 }; 1185 1186 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1187 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1188 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1189 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1190 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1191 }; 1192 1193 static void 1194 spdk_rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1195 const struct spdk_json_val *params) 1196 { 1197 struct rpc_discovery_auth req = {}; 1198 struct spdk_json_write_ctx *w; 1199 int rc; 1200 1201 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1202 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1203 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1205 "Invalid parameters"); 1206 return; 1207 } 1208 1209 rc = spdk_iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1210 req.mutual_chap, req.chap_group); 1211 if (rc < 0) { 1212 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1213 "Invalid combination of CHAP params"); 1214 return; 1215 } 1216 1217 w = spdk_jsonrpc_begin_result(request); 1218 spdk_json_write_bool(w, true); 1219 spdk_jsonrpc_end_result(request, w); 1220 } 1221 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", spdk_rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1222 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_discovery_auth, set_iscsi_discovery_auth) 1223 1224 #define MAX_AUTH_SECRETS 64 1225 1226 struct rpc_auth_secret { 1227 char *user; 1228 char *secret; 1229 char *muser; 1230 char *msecret; 1231 }; 1232 1233 static void 1234 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1235 { 1236 free(_secret->user); 1237 free(_secret->secret); 1238 free(_secret->muser); 1239 free(_secret->msecret); 1240 } 1241 1242 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1243 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1244 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1245 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1246 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1247 }; 1248 1249 static int 1250 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1251 { 1252 struct rpc_auth_secret *_secret = out; 1253 1254 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1255 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1256 } 1257 1258 struct rpc_auth_secrets { 1259 size_t num_secret; 1260 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1261 }; 1262 1263 static void 1264 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1265 { 1266 size_t i; 1267 1268 for (i = 0; i < secrets->num_secret; i++) { 1269 free_rpc_auth_secret(&secrets->secrets[i]); 1270 } 1271 } 1272 1273 static int 1274 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1275 { 1276 struct rpc_auth_secrets *secrets = out; 1277 1278 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1279 MAX_AUTH_SECRETS, &secrets->num_secret, 1280 sizeof(struct rpc_auth_secret)); 1281 } 1282 1283 struct rpc_auth_group { 1284 int32_t tag; 1285 struct rpc_auth_secrets secrets; 1286 }; 1287 1288 static void 1289 free_rpc_auth_group(struct rpc_auth_group *group) 1290 { 1291 free_rpc_auth_secrets(&group->secrets); 1292 } 1293 1294 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1295 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1296 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1297 }; 1298 1299 static void 1300 spdk_rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1301 const struct spdk_json_val *params) 1302 { 1303 struct rpc_auth_group req = {}; 1304 struct rpc_auth_secret *_secret; 1305 struct spdk_json_write_ctx *w; 1306 struct spdk_iscsi_auth_group *group = NULL; 1307 int rc; 1308 size_t i; 1309 1310 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1311 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1312 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1313 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1314 "Invalid parameters"); 1315 free_rpc_auth_group(&req); 1316 return; 1317 } 1318 1319 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1320 1321 rc = spdk_iscsi_add_auth_group(req.tag, &group); 1322 if (rc != 0) { 1323 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1324 1325 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1326 "Could not add auth group (%d), %s", 1327 req.tag, spdk_strerror(-rc)); 1328 free_rpc_auth_group(&req); 1329 return; 1330 } 1331 1332 for (i = 0; i < req.secrets.num_secret; i++) { 1333 _secret = &req.secrets.secrets[i]; 1334 rc = spdk_iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1335 _secret->muser, _secret->msecret); 1336 if (rc != 0) { 1337 spdk_iscsi_delete_auth_group(group); 1338 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1339 1340 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1341 "Could not add secret to auth group (%d), %s", 1342 req.tag, spdk_strerror(-rc)); 1343 free_rpc_auth_group(&req); 1344 return; 1345 } 1346 } 1347 1348 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1349 1350 free_rpc_auth_group(&req); 1351 1352 w = spdk_jsonrpc_begin_result(request); 1353 spdk_json_write_bool(w, true); 1354 spdk_jsonrpc_end_result(request, w); 1355 } 1356 SPDK_RPC_REGISTER("iscsi_create_auth_group", spdk_rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1357 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_create_auth_group, add_iscsi_auth_group) 1358 1359 struct rpc_delete_auth_group { 1360 int32_t tag; 1361 }; 1362 1363 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1364 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1365 }; 1366 1367 static void 1368 spdk_rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1369 const struct spdk_json_val *params) 1370 { 1371 struct rpc_delete_auth_group req = {}; 1372 struct spdk_json_write_ctx *w; 1373 struct spdk_iscsi_auth_group *group; 1374 1375 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1376 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1377 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1378 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1379 "Invalid parameters"); 1380 return; 1381 } 1382 1383 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1384 1385 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1386 if (group == NULL) { 1387 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1388 1389 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1390 "Could not find auth group (%d)", req.tag); 1391 return; 1392 } 1393 1394 spdk_iscsi_delete_auth_group(group); 1395 1396 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1397 1398 w = spdk_jsonrpc_begin_result(request); 1399 spdk_json_write_bool(w, true); 1400 spdk_jsonrpc_end_result(request, w); 1401 } 1402 SPDK_RPC_REGISTER("iscsi_delete_auth_group", spdk_rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1403 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_delete_auth_group, delete_iscsi_auth_group) 1404 1405 struct rpc_add_auth_secret { 1406 int32_t tag; 1407 char *user; 1408 char *secret; 1409 char *muser; 1410 char *msecret; 1411 }; 1412 1413 static void 1414 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1415 { 1416 free(_secret->user); 1417 free(_secret->secret); 1418 free(_secret->muser); 1419 free(_secret->msecret); 1420 } 1421 1422 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1423 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1424 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1425 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1426 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1427 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1428 }; 1429 1430 static void 1431 spdk_rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1432 const struct spdk_json_val *params) 1433 { 1434 struct rpc_add_auth_secret req = {}; 1435 struct spdk_json_write_ctx *w; 1436 struct spdk_iscsi_auth_group *group; 1437 int rc; 1438 1439 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1440 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1441 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1442 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1443 "Invalid parameters"); 1444 free_rpc_add_auth_secret(&req); 1445 return; 1446 } 1447 1448 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1449 1450 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1451 if (group == NULL) { 1452 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1453 1454 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1455 "Could not find auth group (%d)", req.tag); 1456 free_rpc_add_auth_secret(&req); 1457 return; 1458 } 1459 1460 rc = spdk_iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1461 if (rc != 0) { 1462 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1463 1464 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1465 "Could not add secret to auth group (%d), %s", 1466 req.tag, spdk_strerror(-rc)); 1467 free_rpc_add_auth_secret(&req); 1468 return; 1469 } 1470 1471 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1472 1473 free_rpc_add_auth_secret(&req); 1474 1475 w = spdk_jsonrpc_begin_result(request); 1476 spdk_json_write_bool(w, true); 1477 spdk_jsonrpc_end_result(request, w); 1478 } 1479 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", spdk_rpc_iscsi_auth_group_add_secret, 1480 SPDK_RPC_RUNTIME) 1481 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_add_secret, add_secret_to_iscsi_auth_group) 1482 1483 1484 struct rpc_remove_auth_secret { 1485 int32_t tag; 1486 char *user; 1487 }; 1488 1489 static void 1490 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1491 { 1492 free(_secret->user); 1493 } 1494 1495 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1496 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1497 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1498 }; 1499 1500 static void 1501 spdk_rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1502 const struct spdk_json_val *params) 1503 { 1504 struct rpc_remove_auth_secret req = {}; 1505 struct spdk_json_write_ctx *w; 1506 struct spdk_iscsi_auth_group *group; 1507 int rc; 1508 1509 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1510 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1511 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1512 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1513 "Invalid parameters"); 1514 free_rpc_remove_auth_secret(&req); 1515 return; 1516 } 1517 1518 pthread_mutex_lock(&g_spdk_iscsi.mutex); 1519 1520 group = spdk_iscsi_find_auth_group_by_tag(req.tag); 1521 if (group == NULL) { 1522 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1523 1524 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1525 "Could not find auth group (%d)", req.tag); 1526 free_rpc_remove_auth_secret(&req); 1527 return; 1528 } 1529 1530 rc = spdk_iscsi_auth_group_delete_secret(group, req.user); 1531 if (rc != 0) { 1532 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1533 1534 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1535 "Could not delete secret from CHAP group (%d), %s", 1536 req.tag, spdk_strerror(-rc)); 1537 free_rpc_remove_auth_secret(&req); 1538 return; 1539 } 1540 1541 pthread_mutex_unlock(&g_spdk_iscsi.mutex); 1542 1543 free_rpc_remove_auth_secret(&req); 1544 1545 w = spdk_jsonrpc_begin_result(request); 1546 spdk_json_write_bool(w, true); 1547 spdk_jsonrpc_end_result(request, w); 1548 } 1549 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1550 spdk_rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1551 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_auth_group_remove_secret, 1552 delete_secret_from_iscsi_auth_group) 1553 1554 static void 1555 spdk_rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1556 const struct spdk_json_val *params) 1557 { 1558 struct spdk_json_write_ctx *w; 1559 1560 if (params != NULL) { 1561 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1562 "iscsi_get_auth_groups requires no parameters"); 1563 return; 1564 } 1565 1566 w = spdk_jsonrpc_begin_result(request); 1567 spdk_json_write_array_begin(w); 1568 spdk_iscsi_auth_groups_info_json(w); 1569 spdk_json_write_array_end(w); 1570 1571 spdk_jsonrpc_end_result(request, w); 1572 } 1573 SPDK_RPC_REGISTER("iscsi_get_auth_groups", spdk_rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1574 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_get_auth_groups, get_iscsi_auth_groups) 1575 1576 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1577 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1578 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1579 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1580 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1581 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1582 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1583 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1584 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1585 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1586 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1587 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1588 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1589 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1590 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1591 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1592 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1593 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1594 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1595 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1596 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1597 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1598 }; 1599 1600 static void 1601 spdk_rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1602 const struct spdk_json_val *params) 1603 { 1604 struct spdk_iscsi_opts *opts; 1605 struct spdk_json_write_ctx *w; 1606 1607 if (g_spdk_iscsi_opts != NULL) { 1608 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1609 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1610 "Must not call more than once"); 1611 return; 1612 } 1613 1614 opts = spdk_iscsi_opts_alloc(); 1615 if (opts == NULL) { 1616 SPDK_ERRLOG("spdk_iscsi_opts_alloc() failed.\n"); 1617 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1618 "Out of memory"); 1619 return; 1620 } 1621 1622 if (params != NULL) { 1623 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1624 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1625 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1626 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1627 "Invalid parameters"); 1628 spdk_iscsi_opts_free(opts); 1629 return; 1630 } 1631 } 1632 1633 g_spdk_iscsi_opts = spdk_iscsi_opts_copy(opts); 1634 spdk_iscsi_opts_free(opts); 1635 1636 if (g_spdk_iscsi_opts == NULL) { 1637 SPDK_ERRLOG("spdk_iscsi_opts_copy() failed\n"); 1638 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1639 "Out of memory"); 1640 return; 1641 } 1642 1643 w = spdk_jsonrpc_begin_result(request); 1644 spdk_json_write_bool(w, true); 1645 spdk_jsonrpc_end_result(request, w); 1646 } 1647 SPDK_RPC_REGISTER("iscsi_set_options", spdk_rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1648 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(iscsi_set_options, set_iscsi_options) 1649