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