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