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