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 if (rc == 0) { 591 spdk_jsonrpc_send_bool_response(ctx->request, true); 592 } else { 593 spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc)); 594 } 595 free(ctx); 596 } 597 598 static void 599 rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request, 600 const struct spdk_json_val *params) 601 { 602 struct rpc_iscsi_delete_target_node_ctx *ctx; 603 604 ctx = calloc(1, sizeof(*ctx)); 605 if (!ctx) { 606 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 607 spdk_strerror(ENOMEM)); 608 return; 609 } 610 611 if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders, 612 SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders), 613 &ctx->req)) { 614 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 615 goto invalid; 616 } 617 618 if (ctx->req.name == NULL) { 619 SPDK_ERRLOG("missing name param\n"); 620 goto invalid; 621 } 622 623 ctx->request = request; 624 625 iscsi_shutdown_tgt_node_by_name(ctx->req.name, 626 rpc_iscsi_delete_target_node_done, ctx); 627 return; 628 629 invalid: 630 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 631 free_rpc_iscsi_delete_target_node(&ctx->req); 632 free(ctx); 633 } 634 SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME) 635 636 static void 637 rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request, 638 const struct spdk_json_val *params) 639 { 640 struct spdk_json_write_ctx *w; 641 642 if (params != NULL) { 643 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 644 "iscsi_get_portal_groups requires no parameters"); 645 return; 646 } 647 648 w = spdk_jsonrpc_begin_result(request); 649 spdk_json_write_array_begin(w); 650 iscsi_portal_grps_info_json(w); 651 spdk_json_write_array_end(w); 652 653 spdk_jsonrpc_end_result(request, w); 654 } 655 SPDK_RPC_REGISTER("iscsi_get_portal_groups", rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME) 656 657 struct rpc_portal { 658 char *host; 659 char *port; 660 }; 661 662 struct rpc_portal_list { 663 size_t num_portals; 664 struct rpc_portal portals[MAX_PORTAL]; 665 }; 666 667 struct rpc_portal_group { 668 int32_t tag; 669 struct rpc_portal_list portal_list; 670 bool is_private; 671 bool wait; 672 }; 673 674 static void 675 free_rpc_portal(struct rpc_portal *portal) 676 { 677 free(portal->host); 678 free(portal->port); 679 } 680 681 static void 682 free_rpc_portal_list(struct rpc_portal_list *pl) 683 { 684 size_t i; 685 686 for (i = 0; i < pl->num_portals; i++) { 687 free_rpc_portal(&pl->portals[i]); 688 } 689 pl->num_portals = 0; 690 } 691 692 static void 693 free_rpc_portal_group(struct rpc_portal_group *pg) 694 { 695 free_rpc_portal_list(&pg->portal_list); 696 } 697 698 static const struct spdk_json_object_decoder rpc_portal_decoders[] = { 699 {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string}, 700 {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string}, 701 }; 702 703 static int 704 decode_rpc_portal(const struct spdk_json_val *val, void *out) 705 { 706 struct rpc_portal *portal = out; 707 708 return spdk_json_decode_object(val, rpc_portal_decoders, 709 SPDK_COUNTOF(rpc_portal_decoders), 710 portal); 711 } 712 713 static int 714 decode_rpc_portal_list(const struct spdk_json_val *val, void *out) 715 { 716 struct rpc_portal_list *list = out; 717 718 return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals, 719 sizeof(struct rpc_portal)); 720 } 721 722 static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { 723 {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, 724 {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, 725 {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true}, 726 {"wait", offsetof(struct rpc_portal_group, wait), spdk_json_decode_bool, true}, 727 }; 728 729 static void 730 rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, 731 const struct spdk_json_val *params) 732 { 733 struct rpc_portal_group req = {}; 734 struct spdk_iscsi_portal_grp *pg = NULL; 735 struct spdk_iscsi_portal *portal; 736 size_t i = 0; 737 int rc = -1; 738 739 if (spdk_json_decode_object(params, rpc_portal_group_decoders, 740 SPDK_COUNTOF(rpc_portal_group_decoders), 741 &req)) { 742 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 743 goto out; 744 } 745 746 pg = iscsi_portal_grp_create(req.tag, req.is_private); 747 if (pg == NULL) { 748 SPDK_ERRLOG("portal_grp_create failed\n"); 749 goto out; 750 } 751 for (i = 0; i < req.portal_list.num_portals; i++) { 752 portal = iscsi_portal_create(req.portal_list.portals[i].host, 753 req.portal_list.portals[i].port); 754 if (portal == NULL) { 755 SPDK_ERRLOG("portal_create failed\n"); 756 goto out; 757 } 758 iscsi_portal_grp_add_portal(pg, portal); 759 } 760 761 rc = iscsi_portal_grp_open(pg, req.wait); 762 if (rc != 0) { 763 SPDK_ERRLOG("portal_grp_open failed\n"); 764 goto out; 765 } 766 767 rc = iscsi_portal_grp_register(pg); 768 if (rc != 0) { 769 SPDK_ERRLOG("portal_grp_register failed\n"); 770 } 771 772 out: 773 if (rc == 0) { 774 spdk_jsonrpc_send_bool_response(request, true); 775 } else { 776 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 777 778 if (pg != NULL) { 779 iscsi_portal_grp_release(pg); 780 } 781 } 782 free_rpc_portal_group(&req); 783 } 784 SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME) 785 786 struct rpc_iscsi_change_portal_group { 787 int32_t tag; 788 }; 789 790 static const struct spdk_json_object_decoder rpc_iscsi_change_portal_group_decoders[] = { 791 {"tag", offsetof(struct rpc_iscsi_change_portal_group, tag), spdk_json_decode_int32}, 792 }; 793 794 typedef int (*iscsi_change_portal_grp_fn)(int pg_tag); 795 796 static void 797 _rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request *request, 798 const struct spdk_json_val *params, 799 iscsi_change_portal_grp_fn fn) 800 { 801 struct rpc_iscsi_change_portal_group req = {}; 802 int rc; 803 804 if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders, 805 SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders), 806 &req)) { 807 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 808 goto invalid; 809 } 810 811 rc = fn(req.tag); 812 if (rc != 0) { 813 goto invalid; 814 } 815 816 spdk_jsonrpc_send_bool_response(request, true); 817 return; 818 819 invalid: 820 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters"); 821 } 822 823 static int 824 _rpc_iscsi_delete_portal_group(int pg_tag) 825 { 826 struct spdk_iscsi_portal_grp *pg; 827 828 pg = iscsi_portal_grp_unregister(pg_tag); 829 if (!pg) { 830 return -ENODEV; 831 } 832 833 iscsi_tgt_node_delete_map(pg, NULL); 834 iscsi_portal_grp_release(pg); 835 return 0; 836 } 837 838 static void 839 rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request, 840 const struct spdk_json_val *params) 841 { 842 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group); 843 } 844 SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME) 845 846 static int 847 _rpc_iscsi_start_portal_group(int pg_tag) 848 { 849 struct spdk_iscsi_portal_grp *pg; 850 851 pg = iscsi_portal_grp_find_by_tag(pg_tag); 852 if (!pg) { 853 return -ENODEV; 854 } 855 856 iscsi_portal_grp_resume(pg); 857 return 0; 858 } 859 860 static void 861 rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request, 862 const struct spdk_json_val *params) 863 { 864 _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group); 865 } 866 SPDK_RPC_REGISTER("iscsi_start_portal_group", rpc_iscsi_start_portal_group, SPDK_RPC_RUNTIME) 867 868 struct rpc_portal_group_auth { 869 int32_t tag; 870 bool disable_chap; 871 bool require_chap; 872 bool mutual_chap; 873 int32_t chap_group; 874 }; 875 876 static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = { 877 {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32}, 878 {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true}, 879 {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true}, 880 {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true}, 881 {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true}, 882 }; 883 884 static void 885 rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request, 886 const struct spdk_json_val *params) 887 { 888 struct rpc_portal_group_auth req = {}; 889 struct spdk_iscsi_portal_grp *pg; 890 int rc; 891 892 if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders, 893 SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) { 894 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 895 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 896 "Invalid parameters"); 897 return; 898 } 899 900 pthread_mutex_lock(&g_iscsi.mutex); 901 902 pg = iscsi_portal_grp_find_by_tag(req.tag); 903 if (pg == NULL) { 904 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 905 "Could not find portal group %d", req.tag); 906 goto exit; 907 } 908 909 rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap, 910 req.mutual_chap, req.chap_group); 911 if (rc < 0) { 912 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 913 "Invalid combination of auth params"); 914 goto exit; 915 } 916 917 pthread_mutex_unlock(&g_iscsi.mutex); 918 919 spdk_jsonrpc_send_bool_response(request, true); 920 return; 921 922 exit: 923 pthread_mutex_unlock(&g_iscsi.mutex); 924 } 925 SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth, 926 SPDK_RPC_RUNTIME) 927 928 struct rpc_iscsi_get_connections_ctx { 929 struct spdk_jsonrpc_request *request; 930 struct spdk_json_write_ctx *w; 931 }; 932 933 static void 934 _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status) 935 { 936 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 937 938 spdk_json_write_array_end(ctx->w); 939 spdk_jsonrpc_end_result(ctx->request, ctx->w); 940 941 free(ctx); 942 } 943 944 static void 945 _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i) 946 { 947 struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 948 struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i); 949 struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch); 950 struct spdk_iscsi_conn *conn; 951 952 STAILQ_FOREACH(conn, &pg->connections, pg_link) { 953 iscsi_conn_info_json(ctx->w, conn); 954 } 955 956 spdk_for_each_channel_continue(i, 0); 957 } 958 959 static void 960 rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request, 961 const struct spdk_json_val *params) 962 { 963 struct rpc_iscsi_get_connections_ctx *ctx; 964 965 if (params != NULL) { 966 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 967 "iscsi_get_connections requires no parameters"); 968 return; 969 } 970 971 ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx)); 972 if (ctx == NULL) { 973 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n"); 974 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 975 return; 976 } 977 978 ctx->request = request; 979 ctx->w = spdk_jsonrpc_begin_result(request); 980 981 spdk_json_write_array_begin(ctx->w); 982 983 spdk_for_each_channel(&g_iscsi, 984 _rpc_iscsi_get_connections, 985 ctx, 986 _rpc_iscsi_get_connections_done); 987 } 988 SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME) 989 990 struct rpc_target_lun { 991 char *name; 992 char *bdev_name; 993 int32_t lun_id; 994 }; 995 996 static void 997 free_rpc_target_lun(struct rpc_target_lun *req) 998 { 999 free(req->name); 1000 free(req->bdev_name); 1001 } 1002 1003 static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = { 1004 {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string}, 1005 {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string}, 1006 {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true}, 1007 }; 1008 1009 static void 1010 rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request, 1011 const struct spdk_json_val *params) 1012 { 1013 struct rpc_target_lun req = {}; 1014 struct spdk_iscsi_tgt_node *target; 1015 int rc; 1016 1017 req.lun_id = -1; 1018 1019 if (spdk_json_decode_object(params, rpc_target_lun_decoders, 1020 SPDK_COUNTOF(rpc_target_lun_decoders), &req)) { 1021 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1022 goto invalid; 1023 } 1024 1025 target = iscsi_find_tgt_node(req.name); 1026 if (target == NULL) { 1027 SPDK_ERRLOG("target is not found\n"); 1028 goto invalid; 1029 } 1030 1031 rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id); 1032 if (rc < 0) { 1033 SPDK_ERRLOG("add lun failed\n"); 1034 goto invalid; 1035 } 1036 1037 free_rpc_target_lun(&req); 1038 1039 spdk_jsonrpc_send_bool_response(request, true); 1040 return; 1041 1042 invalid: 1043 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1044 "Invalid parameters"); 1045 free_rpc_target_lun(&req); 1046 } 1047 SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME) 1048 1049 struct rpc_target_auth { 1050 char *name; 1051 bool disable_chap; 1052 bool require_chap; 1053 bool mutual_chap; 1054 int32_t chap_group; 1055 }; 1056 1057 static void 1058 free_rpc_target_auth(struct rpc_target_auth *req) 1059 { 1060 free(req->name); 1061 } 1062 1063 static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = { 1064 {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string}, 1065 {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true}, 1066 {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true}, 1067 {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true}, 1068 {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true}, 1069 }; 1070 1071 static void 1072 rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request, 1073 const struct spdk_json_val *params) 1074 { 1075 struct rpc_target_auth req = {}; 1076 struct spdk_iscsi_tgt_node *target; 1077 int rc; 1078 1079 if (spdk_json_decode_object(params, rpc_target_auth_decoders, 1080 SPDK_COUNTOF(rpc_target_auth_decoders), &req)) { 1081 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1082 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1083 "Invalid parameters"); 1084 goto exit; 1085 } 1086 1087 target = iscsi_find_tgt_node(req.name); 1088 if (target == NULL) { 1089 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1090 "Could not find target %s", req.name); 1091 goto exit; 1092 } 1093 1094 rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap, 1095 req.mutual_chap, req.chap_group); 1096 if (rc < 0) { 1097 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1098 "Invalid combination of auth params"); 1099 goto exit; 1100 } 1101 1102 free_rpc_target_auth(&req); 1103 1104 spdk_jsonrpc_send_bool_response(request, true); 1105 return; 1106 1107 exit: 1108 free_rpc_target_auth(&req); 1109 } 1110 SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth, 1111 SPDK_RPC_RUNTIME) 1112 1113 struct rpc_target_redirect { 1114 char *name; 1115 int32_t pg_tag; 1116 char *redirect_host; 1117 char *redirect_port; 1118 }; 1119 1120 static void 1121 free_rpc_target_redirect(struct rpc_target_redirect *req) 1122 { 1123 free(req->name); 1124 free(req->redirect_host); 1125 free(req->redirect_port); 1126 } 1127 1128 static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = { 1129 {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string}, 1130 {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32}, 1131 {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true}, 1132 {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true}, 1133 }; 1134 1135 static void 1136 rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request, 1137 const struct spdk_json_val *params) 1138 { 1139 struct rpc_target_redirect req = {}; 1140 struct spdk_iscsi_tgt_node *target; 1141 int rc; 1142 1143 if (spdk_json_decode_object(params, rpc_target_redirect_decoders, 1144 SPDK_COUNTOF(rpc_target_redirect_decoders), 1145 &req)) { 1146 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1147 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1148 "Invalid parameters"); 1149 free_rpc_target_redirect(&req); 1150 return; 1151 } 1152 1153 target = iscsi_find_tgt_node(req.name); 1154 if (target == NULL) { 1155 SPDK_ERRLOG("target %s is not found\n", req.name); 1156 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1157 "Target %s is not found", req.name); 1158 free_rpc_target_redirect(&req); 1159 return; 1160 } 1161 1162 rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port); 1163 if (rc != 0) { 1164 SPDK_ERRLOG("failed to redirect target %s\n", req.name); 1165 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1166 "Failed to redirect target %s, (%d): %s", 1167 req.name, rc, spdk_strerror(-rc)); 1168 free_rpc_target_redirect(&req); 1169 return; 1170 } 1171 1172 free_rpc_target_redirect(&req); 1173 1174 spdk_jsonrpc_send_bool_response(request, true); 1175 } 1176 SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect, 1177 SPDK_RPC_RUNTIME) 1178 1179 struct rpc_target_logout { 1180 char *name; 1181 int32_t pg_tag; 1182 }; 1183 1184 static void 1185 free_rpc_target_logout(struct rpc_target_logout *req) 1186 { 1187 free(req->name); 1188 } 1189 1190 static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = { 1191 {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string}, 1192 {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true}, 1193 }; 1194 1195 static void 1196 rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request, 1197 const struct spdk_json_val *params) 1198 { 1199 struct rpc_target_logout req = {}; 1200 struct spdk_iscsi_tgt_node *target; 1201 1202 /* If pg_tag is omitted, request all connections to the specified target 1203 * to logout. 1204 */ 1205 req.pg_tag = -1; 1206 1207 if (spdk_json_decode_object(params, rpc_target_logout_decoders, 1208 SPDK_COUNTOF(rpc_target_logout_decoders), 1209 &req)) { 1210 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1211 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1212 "Invalid parameters"); 1213 free_rpc_target_logout(&req); 1214 return; 1215 } 1216 1217 target = iscsi_find_tgt_node(req.name); 1218 if (target == NULL) { 1219 SPDK_ERRLOG("target %s is not found\n", req.name); 1220 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1221 "Target %s is not found", req.name); 1222 free_rpc_target_logout(&req); 1223 return; 1224 } 1225 1226 iscsi_conns_request_logout(target, req.pg_tag); 1227 1228 free_rpc_target_logout(&req); 1229 1230 spdk_jsonrpc_send_bool_response(request, true); 1231 } 1232 SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout, 1233 SPDK_RPC_RUNTIME) 1234 1235 static void 1236 rpc_iscsi_get_options(struct spdk_jsonrpc_request *request, 1237 const struct spdk_json_val *params) 1238 { 1239 struct spdk_json_write_ctx *w; 1240 1241 if (params != NULL) { 1242 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1243 "iscsi_get_options requires no parameters"); 1244 return; 1245 } 1246 1247 w = spdk_jsonrpc_begin_result(request); 1248 iscsi_opts_info_json(w); 1249 1250 spdk_jsonrpc_end_result(request, w); 1251 } 1252 SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME) 1253 1254 struct rpc_discovery_auth { 1255 bool disable_chap; 1256 bool require_chap; 1257 bool mutual_chap; 1258 int32_t chap_group; 1259 }; 1260 1261 static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = { 1262 {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true}, 1263 {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true}, 1264 {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true}, 1265 {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true}, 1266 }; 1267 1268 static void 1269 rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request, 1270 const struct spdk_json_val *params) 1271 { 1272 struct rpc_discovery_auth req = {}; 1273 int rc; 1274 1275 if (spdk_json_decode_object(params, rpc_discovery_auth_decoders, 1276 SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) { 1277 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1278 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1279 "Invalid parameters"); 1280 return; 1281 } 1282 1283 rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap, 1284 req.mutual_chap, req.chap_group); 1285 if (rc < 0) { 1286 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1287 "Invalid combination of CHAP params"); 1288 return; 1289 } 1290 1291 spdk_jsonrpc_send_bool_response(request, true); 1292 } 1293 SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME) 1294 1295 #define MAX_AUTH_SECRETS 64 1296 1297 struct rpc_auth_secret { 1298 char *user; 1299 char *secret; 1300 char *muser; 1301 char *msecret; 1302 }; 1303 1304 static void 1305 free_rpc_auth_secret(struct rpc_auth_secret *_secret) 1306 { 1307 free(_secret->user); 1308 free(_secret->secret); 1309 free(_secret->muser); 1310 free(_secret->msecret); 1311 } 1312 1313 static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = { 1314 {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string}, 1315 {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string}, 1316 {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true}, 1317 {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true}, 1318 }; 1319 1320 static int 1321 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out) 1322 { 1323 struct rpc_auth_secret *_secret = out; 1324 1325 return spdk_json_decode_object(val, rpc_auth_secret_decoders, 1326 SPDK_COUNTOF(rpc_auth_secret_decoders), _secret); 1327 } 1328 1329 struct rpc_auth_secrets { 1330 size_t num_secret; 1331 struct rpc_auth_secret secrets[MAX_AUTH_SECRETS]; 1332 }; 1333 1334 static void 1335 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets) 1336 { 1337 size_t i; 1338 1339 for (i = 0; i < secrets->num_secret; i++) { 1340 free_rpc_auth_secret(&secrets->secrets[i]); 1341 } 1342 } 1343 1344 static int 1345 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out) 1346 { 1347 struct rpc_auth_secrets *secrets = out; 1348 1349 return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets, 1350 MAX_AUTH_SECRETS, &secrets->num_secret, 1351 sizeof(struct rpc_auth_secret)); 1352 } 1353 1354 struct rpc_auth_group { 1355 int32_t tag; 1356 struct rpc_auth_secrets secrets; 1357 }; 1358 1359 static void 1360 free_rpc_auth_group(struct rpc_auth_group *group) 1361 { 1362 free_rpc_auth_secrets(&group->secrets); 1363 } 1364 1365 static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = { 1366 {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32}, 1367 {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true}, 1368 }; 1369 1370 static void 1371 rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request, 1372 const struct spdk_json_val *params) 1373 { 1374 struct rpc_auth_group req = {}; 1375 struct rpc_auth_secret *_secret; 1376 struct spdk_iscsi_auth_group *group = NULL; 1377 int rc; 1378 size_t i; 1379 1380 if (spdk_json_decode_object(params, rpc_auth_group_decoders, 1381 SPDK_COUNTOF(rpc_auth_group_decoders), &req)) { 1382 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1383 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1384 "Invalid parameters"); 1385 free_rpc_auth_group(&req); 1386 return; 1387 } 1388 1389 pthread_mutex_lock(&g_iscsi.mutex); 1390 1391 rc = iscsi_add_auth_group(req.tag, &group); 1392 if (rc != 0) { 1393 pthread_mutex_unlock(&g_iscsi.mutex); 1394 1395 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1396 "Could not add auth group (%d), %s", 1397 req.tag, spdk_strerror(-rc)); 1398 free_rpc_auth_group(&req); 1399 return; 1400 } 1401 1402 for (i = 0; i < req.secrets.num_secret; i++) { 1403 _secret = &req.secrets.secrets[i]; 1404 rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret, 1405 _secret->muser, _secret->msecret); 1406 if (rc != 0) { 1407 iscsi_delete_auth_group(group); 1408 pthread_mutex_unlock(&g_iscsi.mutex); 1409 1410 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1411 "Could not add secret to auth group (%d), %s", 1412 req.tag, spdk_strerror(-rc)); 1413 free_rpc_auth_group(&req); 1414 return; 1415 } 1416 } 1417 1418 pthread_mutex_unlock(&g_iscsi.mutex); 1419 1420 free_rpc_auth_group(&req); 1421 1422 spdk_jsonrpc_send_bool_response(request, true); 1423 } 1424 SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME) 1425 1426 struct rpc_delete_auth_group { 1427 int32_t tag; 1428 }; 1429 1430 static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = { 1431 {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32}, 1432 }; 1433 1434 static void 1435 rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request, 1436 const struct spdk_json_val *params) 1437 { 1438 struct rpc_delete_auth_group req = {}; 1439 struct spdk_iscsi_auth_group *group; 1440 1441 if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders, 1442 SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) { 1443 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1444 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1445 "Invalid parameters"); 1446 return; 1447 } 1448 1449 pthread_mutex_lock(&g_iscsi.mutex); 1450 1451 group = iscsi_find_auth_group_by_tag(req.tag); 1452 if (group == NULL) { 1453 pthread_mutex_unlock(&g_iscsi.mutex); 1454 1455 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1456 "Could not find auth group (%d)", req.tag); 1457 return; 1458 } 1459 1460 iscsi_delete_auth_group(group); 1461 1462 pthread_mutex_unlock(&g_iscsi.mutex); 1463 1464 spdk_jsonrpc_send_bool_response(request, true); 1465 } 1466 SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME) 1467 1468 struct rpc_add_auth_secret { 1469 int32_t tag; 1470 char *user; 1471 char *secret; 1472 char *muser; 1473 char *msecret; 1474 }; 1475 1476 static void 1477 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret) 1478 { 1479 free(_secret->user); 1480 free(_secret->secret); 1481 free(_secret->muser); 1482 free(_secret->msecret); 1483 } 1484 1485 static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = { 1486 {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32}, 1487 {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string}, 1488 {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string}, 1489 {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true}, 1490 {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true}, 1491 }; 1492 1493 static void 1494 rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request, 1495 const struct spdk_json_val *params) 1496 { 1497 struct rpc_add_auth_secret req = {}; 1498 struct spdk_iscsi_auth_group *group; 1499 int rc; 1500 1501 if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders, 1502 SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) { 1503 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1504 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1505 "Invalid parameters"); 1506 free_rpc_add_auth_secret(&req); 1507 return; 1508 } 1509 1510 pthread_mutex_lock(&g_iscsi.mutex); 1511 1512 group = iscsi_find_auth_group_by_tag(req.tag); 1513 if (group == NULL) { 1514 pthread_mutex_unlock(&g_iscsi.mutex); 1515 1516 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1517 "Could not find auth group (%d)", req.tag); 1518 free_rpc_add_auth_secret(&req); 1519 return; 1520 } 1521 1522 rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret); 1523 if (rc != 0) { 1524 pthread_mutex_unlock(&g_iscsi.mutex); 1525 1526 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1527 "Could not add secret to auth group (%d), %s", 1528 req.tag, spdk_strerror(-rc)); 1529 free_rpc_add_auth_secret(&req); 1530 return; 1531 } 1532 1533 pthread_mutex_unlock(&g_iscsi.mutex); 1534 1535 free_rpc_add_auth_secret(&req); 1536 1537 spdk_jsonrpc_send_bool_response(request, true); 1538 } 1539 SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret, 1540 SPDK_RPC_RUNTIME) 1541 1542 1543 struct rpc_remove_auth_secret { 1544 int32_t tag; 1545 char *user; 1546 }; 1547 1548 static void 1549 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret) 1550 { 1551 free(_secret->user); 1552 } 1553 1554 static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = { 1555 {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32}, 1556 {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string}, 1557 }; 1558 1559 static void 1560 rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request, 1561 const struct spdk_json_val *params) 1562 { 1563 struct rpc_remove_auth_secret req = {}; 1564 struct spdk_iscsi_auth_group *group; 1565 int rc; 1566 1567 if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders, 1568 SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) { 1569 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 1570 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1571 "Invalid parameters"); 1572 free_rpc_remove_auth_secret(&req); 1573 return; 1574 } 1575 1576 pthread_mutex_lock(&g_iscsi.mutex); 1577 1578 group = iscsi_find_auth_group_by_tag(req.tag); 1579 if (group == NULL) { 1580 pthread_mutex_unlock(&g_iscsi.mutex); 1581 1582 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1583 "Could not find auth group (%d)", req.tag); 1584 free_rpc_remove_auth_secret(&req); 1585 return; 1586 } 1587 1588 rc = iscsi_auth_group_delete_secret(group, req.user); 1589 if (rc != 0) { 1590 pthread_mutex_unlock(&g_iscsi.mutex); 1591 1592 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1593 "Could not delete secret from CHAP group (%d), %s", 1594 req.tag, spdk_strerror(-rc)); 1595 free_rpc_remove_auth_secret(&req); 1596 return; 1597 } 1598 1599 pthread_mutex_unlock(&g_iscsi.mutex); 1600 1601 free_rpc_remove_auth_secret(&req); 1602 1603 spdk_jsonrpc_send_bool_response(request, true); 1604 } 1605 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret", 1606 rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME) 1607 1608 static void 1609 rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request, 1610 const struct spdk_json_val *params) 1611 { 1612 struct spdk_json_write_ctx *w; 1613 1614 if (params != NULL) { 1615 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1616 "iscsi_get_auth_groups requires no parameters"); 1617 return; 1618 } 1619 1620 w = spdk_jsonrpc_begin_result(request); 1621 spdk_json_write_array_begin(w); 1622 iscsi_auth_groups_info_json(w); 1623 spdk_json_write_array_end(w); 1624 1625 spdk_jsonrpc_end_result(request, w); 1626 } 1627 SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME) 1628 1629 static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = { 1630 {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true}, 1631 {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true}, 1632 {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true}, 1633 {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true}, 1634 {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1635 {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1636 {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1637 {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1638 {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true}, 1639 {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true}, 1640 {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true}, 1641 {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true}, 1642 {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true}, 1643 {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true}, 1644 {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true}, 1645 {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true}, 1646 {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true}, 1647 {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true}, 1648 {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true}, 1649 {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true}, 1650 {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true}, 1651 {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true}, 1652 {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true}, 1653 {"pdu_pool_size", offsetof(struct spdk_iscsi_opts, pdu_pool_size), spdk_json_decode_uint32, true}, 1654 {"immediate_data_pool_size", offsetof(struct spdk_iscsi_opts, immediate_data_pool_size), spdk_json_decode_uint32, true}, 1655 {"data_out_pool_size", offsetof(struct spdk_iscsi_opts, data_out_pool_size), spdk_json_decode_uint32, true}, 1656 }; 1657 1658 static void 1659 rpc_iscsi_set_options(struct spdk_jsonrpc_request *request, 1660 const struct spdk_json_val *params) 1661 { 1662 struct spdk_iscsi_opts *opts; 1663 1664 if (g_spdk_iscsi_opts != NULL) { 1665 SPDK_ERRLOG("this RPC must not be called more than once.\n"); 1666 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1667 "Must not call more than once"); 1668 return; 1669 } 1670 1671 opts = iscsi_opts_alloc(); 1672 if (opts == NULL) { 1673 SPDK_ERRLOG("iscsi_opts_alloc() failed.\n"); 1674 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1675 "Out of memory"); 1676 return; 1677 } 1678 1679 if (params != NULL) { 1680 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders, 1681 SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) { 1682 SPDK_ERRLOG("spdk_json_decode_object() failed\n"); 1683 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 1684 "Invalid parameters"); 1685 iscsi_opts_free(opts); 1686 return; 1687 } 1688 } 1689 1690 g_spdk_iscsi_opts = iscsi_opts_copy(opts); 1691 iscsi_opts_free(opts); 1692 1693 if (g_spdk_iscsi_opts == NULL) { 1694 SPDK_ERRLOG("iscsi_opts_copy() failed\n"); 1695 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 1696 "Out of memory"); 1697 return; 1698 } 1699 1700 spdk_jsonrpc_send_bool_response(request, true); 1701 } 1702 SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP) 1703