LCOV - code coverage report
Current view: top level - lib/iscsi - iscsi_rpc.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 659 0.0 %
Date: 2024-07-12 19:28:37 Functions: 0 90 0.0 %

          Line data    Source code
       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           0 : 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           0 :         if (params != NULL) {
      25           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
      26             :                                                  "iscsi_get_initiator_groups requires no parameters");
      27           0 :                 return;
      28             :         }
      29             : 
      30           0 :         w = spdk_jsonrpc_begin_result(request);
      31           0 :         spdk_json_write_array_begin(w);
      32           0 :         iscsi_init_grps_info_json(w);
      33           0 :         spdk_json_write_array_end(w);
      34             : 
      35           0 :         spdk_jsonrpc_end_result(request, w);
      36             : }
      37           0 : 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           0 : decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
      47             : {
      48           0 :         struct rpc_initiator_list *list = out;
      49             : 
      50           0 :         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           0 : free_rpc_initiator_list(struct rpc_initiator_list *list)
      56             : {
      57             :         size_t i;
      58             : 
      59           0 :         for (i = 0; i < list->num_initiators; i++) {
      60           0 :                 free(list->initiators[i]);
      61             :         }
      62           0 : }
      63             : 
      64             : struct rpc_netmask_list {
      65             :         size_t num_netmasks;
      66             :         char *netmasks[MAX_NETMASK];
      67             : };
      68             : 
      69             : static int
      70           0 : decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
      71             : {
      72           0 :         struct rpc_netmask_list *list = out;
      73             : 
      74           0 :         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           0 : free_rpc_netmask_list(struct rpc_netmask_list *list)
      80             : {
      81             :         size_t i;
      82             : 
      83           0 :         for (i = 0; i < list->num_netmasks; i++) {
      84           0 :                 free(list->netmasks[i]);
      85             :         }
      86           0 : }
      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           0 : free_rpc_initiator_group(struct rpc_initiator_group *ig)
      96             : {
      97           0 :         free_rpc_initiator_list(&ig->initiator_list);
      98           0 :         free_rpc_netmask_list(&ig->netmask_list);
      99           0 : }
     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           0 : rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request,
     109             :                                  const struct spdk_json_val *params)
     110             : {
     111           0 :         struct rpc_initiator_group req = {};
     112             : 
     113           0 :         if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
     114             :                                     SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) {
     115           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     116           0 :                 goto invalid;
     117             :         }
     118             : 
     119           0 :         if (req.initiator_list.num_initiators == 0 ||
     120           0 :             req.netmask_list.num_netmasks == 0) {
     121           0 :                 goto invalid;
     122             :         }
     123             : 
     124           0 :         if (iscsi_init_grp_create_from_initiator_list(req.tag,
     125           0 :                         req.initiator_list.num_initiators,
     126             :                         req.initiator_list.initiators,
     127           0 :                         req.netmask_list.num_netmasks,
     128             :                         req.netmask_list.netmasks)) {
     129           0 :                 SPDK_ERRLOG("create_from_initiator_list failed\n");
     130           0 :                 goto invalid;
     131             :         }
     132             : 
     133           0 :         free_rpc_initiator_group(&req);
     134             : 
     135           0 :         spdk_jsonrpc_send_bool_response(request, true);
     136           0 :         return;
     137             : 
     138           0 : invalid:
     139           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     140           0 :         free_rpc_initiator_group(&req);
     141             : }
     142           0 : 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           0 : rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request,
     153             :                 const struct spdk_json_val *params)
     154             : {
     155           0 :         struct rpc_initiator_group req = {};
     156             : 
     157           0 :         if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
     158             :                                     SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
     159           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     160           0 :                 goto invalid;
     161             :         }
     162             : 
     163           0 :         if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
     164           0 :                         req.initiator_list.num_initiators,
     165             :                         req.initiator_list.initiators,
     166           0 :                         req.netmask_list.num_netmasks,
     167             :                         req.netmask_list.netmasks)) {
     168           0 :                 SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
     169           0 :                 goto invalid;
     170             :         }
     171             : 
     172           0 :         free_rpc_initiator_group(&req);
     173             : 
     174           0 :         spdk_jsonrpc_send_bool_response(request, true);
     175           0 :         return;
     176             : 
     177           0 : invalid:
     178           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     179           0 :         free_rpc_initiator_group(&req);
     180             : }
     181           0 : SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators",
     182             :                   rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME)
     183             : 
     184             : static void
     185           0 : rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request,
     186             :                 const struct spdk_json_val *params)
     187             : {
     188           0 :         struct rpc_initiator_group req = {};
     189             : 
     190           0 :         if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
     191             :                                     SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
     192           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     193           0 :                 goto invalid;
     194             :         }
     195             : 
     196           0 :         if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
     197           0 :                         req.initiator_list.num_initiators,
     198             :                         req.initiator_list.initiators,
     199           0 :                         req.netmask_list.num_netmasks,
     200             :                         req.netmask_list.netmasks)) {
     201           0 :                 SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
     202           0 :                 goto invalid;
     203             :         }
     204             : 
     205           0 :         free_rpc_initiator_group(&req);
     206             : 
     207           0 :         spdk_jsonrpc_send_bool_response(request, true);
     208           0 :         return;
     209             : 
     210           0 : invalid:
     211           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     212           0 :         free_rpc_initiator_group(&req);
     213             : }
     214           0 : 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           0 : rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request,
     227             :                                  const struct spdk_json_val *params)
     228             : {
     229           0 :         struct rpc_iscsi_delete_initiator_group req = {};
     230             :         struct spdk_iscsi_init_grp *ig;
     231             : 
     232           0 :         if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders,
     233             :                                     SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders),
     234             :                                     &req)) {
     235           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     236           0 :                 goto invalid;
     237             :         }
     238             : 
     239           0 :         ig = iscsi_init_grp_unregister(req.tag);
     240           0 :         if (!ig) {
     241           0 :                 goto invalid;
     242             :         }
     243           0 :         iscsi_tgt_node_delete_map(NULL, ig);
     244           0 :         iscsi_init_grp_destroy(ig);
     245             : 
     246           0 :         spdk_jsonrpc_send_bool_response(request, true);
     247           0 :         return;
     248             : 
     249           0 : invalid:
     250           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     251             : }
     252           0 : SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group,
     253             :                   SPDK_RPC_RUNTIME)
     254             : 
     255             : static void
     256           0 : 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           0 :         if (params != NULL) {
     262           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     263             :                                                  "iscsi_get_target_nodes requires no parameters");
     264           0 :                 return;
     265             :         }
     266             : 
     267           0 :         w = spdk_jsonrpc_begin_result(request);
     268           0 :         spdk_json_write_array_begin(w);
     269           0 :         iscsi_tgt_nodes_info_json(w);
     270           0 :         spdk_json_write_array_end(w);
     271             : 
     272           0 :         spdk_jsonrpc_end_result(request, w);
     273             : }
     274           0 : 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           0 : decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out)
     288             : {
     289           0 :         struct rpc_pg_ig_map *pg_ig_map = out;
     290             : 
     291           0 :         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           0 : decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out)
     303             : {
     304           0 :         struct rpc_pg_ig_maps *pg_ig_maps = out;
     305             : 
     306           0 :         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           0 : decode_rpc_lun(const struct spdk_json_val *val, void *out)
     325             : {
     326           0 :         struct rpc_lun *lun = out;
     327             : 
     328           0 :         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           0 : decode_rpc_luns(const struct spdk_json_val *val, void *out)
     339             : {
     340           0 :         struct rpc_luns *luns = out;
     341             : 
     342           0 :         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           0 : free_rpc_luns(struct rpc_luns *p)
     349             : {
     350             :         size_t i;
     351             : 
     352           0 :         for (i = 0; i < p->num_luns; i++) {
     353           0 :                 free(p->luns[i].bdev_name);
     354             :         }
     355           0 : }
     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           0 : free_rpc_target_node(struct rpc_target_node *req)
     376             : {
     377           0 :         free(req->name);
     378           0 :         free(req->alias_name);
     379           0 :         free_rpc_luns(&req->luns);
     380           0 : }
     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           0 : rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request,
     398             :                              const struct spdk_json_val *params)
     399             : {
     400           0 :         struct rpc_target_node req = {};
     401             :         struct spdk_iscsi_tgt_node *target;
     402           0 :         int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
     403           0 :         char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
     404           0 :         int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
     405             :         size_t i;
     406             : 
     407           0 :         if (spdk_json_decode_object(params, rpc_target_node_decoders,
     408             :                                     SPDK_COUNTOF(rpc_target_node_decoders),
     409             :                                     &req)) {
     410           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     411           0 :                 goto invalid;
     412             :         }
     413             : 
     414           0 :         for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
     415           0 :                 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
     416           0 :                 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
     417             :         }
     418             : 
     419           0 :         for (i = 0; i < req.luns.num_luns; i++) {
     420           0 :                 bdev_names[i] = req.luns.luns[i].bdev_name;
     421           0 :                 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           0 :         target = iscsi_tgt_node_construct(-1, req.name, req.alias_name,
     430             :                                           pg_tags,
     431             :                                           ig_tags,
     432           0 :                                           req.pg_ig_maps.num_maps,
     433             :                                           (const char **)bdev_names,
     434             :                                           lun_ids,
     435           0 :                                           req.luns.num_luns,
     436             :                                           req.queue_depth,
     437           0 :                                           req.disable_chap,
     438           0 :                                           req.require_chap,
     439           0 :                                           req.mutual_chap,
     440             :                                           req.chap_group,
     441           0 :                                           req.header_digest,
     442           0 :                                           req.data_digest);
     443             : 
     444           0 :         if (target == NULL) {
     445           0 :                 goto invalid;
     446             :         }
     447             : 
     448           0 :         free_rpc_target_node(&req);
     449             : 
     450           0 :         spdk_jsonrpc_send_bool_response(request, true);
     451           0 :         return;
     452             : 
     453           0 : invalid:
     454           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     455           0 :         free_rpc_target_node(&req);
     456             : }
     457           0 : 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           0 : rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request,
     471             :                                      const struct spdk_json_val *params)
     472             : {
     473           0 :         struct rpc_tgt_node_pg_ig_maps req = {};
     474             :         struct spdk_iscsi_tgt_node *target;
     475           0 :         int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
     476             :         size_t i;
     477             :         int rc;
     478             : 
     479           0 :         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           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     483           0 :                 goto invalid;
     484             :         }
     485             : 
     486           0 :         target = iscsi_find_tgt_node(req.name);
     487           0 :         if (target == NULL) {
     488           0 :                 SPDK_ERRLOG("target is not found\n");
     489           0 :                 goto invalid;
     490             :         }
     491             : 
     492           0 :         for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
     493           0 :                 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
     494           0 :                 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
     495             :         }
     496             : 
     497           0 :         rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags,
     498           0 :                                               req.pg_ig_maps.num_maps);
     499           0 :         if (rc < 0) {
     500           0 :                 SPDK_ERRLOG("add pg-ig maps failed\n");
     501           0 :                 goto invalid;
     502             :         }
     503             : 
     504           0 :         free(req.name);
     505             : 
     506           0 :         spdk_jsonrpc_send_bool_response(request, true);
     507           0 :         return;
     508             : 
     509           0 : invalid:
     510           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     511             :                                          "Invalid parameters");
     512           0 :         free(req.name);
     513             : }
     514           0 : 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           0 : rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request,
     519             :                                         const struct spdk_json_val *params)
     520             : {
     521           0 :         struct rpc_tgt_node_pg_ig_maps req = {};
     522             :         struct spdk_iscsi_tgt_node *target;
     523           0 :         int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
     524             :         size_t i;
     525             :         int rc;
     526             : 
     527           0 :         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           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     531           0 :                 goto invalid;
     532             :         }
     533             : 
     534           0 :         target = iscsi_find_tgt_node(req.name);
     535           0 :         if (target == NULL) {
     536           0 :                 SPDK_ERRLOG("target is not found\n");
     537           0 :                 goto invalid;
     538             :         }
     539             : 
     540           0 :         for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
     541           0 :                 pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
     542           0 :                 ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
     543             :         }
     544             : 
     545           0 :         rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags,
     546           0 :                         req.pg_ig_maps.num_maps);
     547           0 :         if (rc < 0) {
     548           0 :                 SPDK_ERRLOG("remove pg-ig maps failed\n");
     549           0 :                 goto invalid;
     550             :         }
     551             : 
     552           0 :         free(req.name);
     553             : 
     554           0 :         spdk_jsonrpc_send_bool_response(request, true);
     555           0 :         return;
     556             : 
     557           0 : invalid:
     558           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     559             :                                          "Invalid parameters");
     560           0 :         free(req.name);
     561             : }
     562           0 : 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           0 : free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r)
     571             : {
     572           0 :         free(r->name);
     573           0 : }
     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           0 : rpc_iscsi_delete_target_node_done(void *cb_arg, int rc)
     586             : {
     587           0 :         struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg;
     588             : 
     589           0 :         free_rpc_iscsi_delete_target_node(&ctx->req);
     590           0 :         if (rc == 0) {
     591           0 :                 spdk_jsonrpc_send_bool_response(ctx->request, true);
     592             :         } else {
     593           0 :                 spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
     594             :         }
     595           0 :         free(ctx);
     596           0 : }
     597             : 
     598             : static void
     599           0 : 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           0 :         ctx = calloc(1, sizeof(*ctx));
     605           0 :         if (!ctx) {
     606           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     607             :                                                  spdk_strerror(ENOMEM));
     608           0 :                 return;
     609             :         }
     610             : 
     611           0 :         if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders,
     612             :                                     SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders),
     613           0 :                                     &ctx->req)) {
     614           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     615           0 :                 goto invalid;
     616             :         }
     617             : 
     618           0 :         if (ctx->req.name == NULL) {
     619           0 :                 SPDK_ERRLOG("missing name param\n");
     620           0 :                 goto invalid;
     621             :         }
     622             : 
     623           0 :         ctx->request = request;
     624             : 
     625           0 :         iscsi_shutdown_tgt_node_by_name(ctx->req.name,
     626             :                                         rpc_iscsi_delete_target_node_done, ctx);
     627           0 :         return;
     628             : 
     629           0 : invalid:
     630           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     631           0 :         free_rpc_iscsi_delete_target_node(&ctx->req);
     632           0 :         free(ctx);
     633             : }
     634           0 : SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME)
     635             : 
     636             : static void
     637           0 : 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           0 :         if (params != NULL) {
     643           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     644             :                                                  "iscsi_get_portal_groups requires no parameters");
     645           0 :                 return;
     646             :         }
     647             : 
     648           0 :         w = spdk_jsonrpc_begin_result(request);
     649           0 :         spdk_json_write_array_begin(w);
     650           0 :         iscsi_portal_grps_info_json(w);
     651           0 :         spdk_json_write_array_end(w);
     652             : 
     653           0 :         spdk_jsonrpc_end_result(request, w);
     654             : }
     655           0 : 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           0 : free_rpc_portal(struct rpc_portal *portal)
     676             : {
     677           0 :         free(portal->host);
     678           0 :         free(portal->port);
     679           0 : }
     680             : 
     681             : static void
     682           0 : free_rpc_portal_list(struct rpc_portal_list *pl)
     683             : {
     684             :         size_t i;
     685             : 
     686           0 :         for (i = 0; i < pl->num_portals; i++) {
     687           0 :                 free_rpc_portal(&pl->portals[i]);
     688             :         }
     689           0 :         pl->num_portals = 0;
     690           0 : }
     691             : 
     692             : static void
     693           0 : free_rpc_portal_group(struct rpc_portal_group *pg)
     694             : {
     695           0 :         free_rpc_portal_list(&pg->portal_list);
     696           0 : }
     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           0 : decode_rpc_portal(const struct spdk_json_val *val, void *out)
     705             : {
     706           0 :         struct rpc_portal *portal = out;
     707             : 
     708           0 :         return spdk_json_decode_object(val, rpc_portal_decoders,
     709             :                                        SPDK_COUNTOF(rpc_portal_decoders),
     710             :                                        portal);
     711             : }
     712             : 
     713             : static int
     714           0 : decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
     715             : {
     716           0 :         struct rpc_portal_list *list = out;
     717             : 
     718           0 :         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           0 : rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request,
     731             :                               const struct spdk_json_val *params)
     732             : {
     733           0 :         struct rpc_portal_group req = {};
     734           0 :         struct spdk_iscsi_portal_grp *pg = NULL;
     735             :         struct spdk_iscsi_portal *portal;
     736           0 :         size_t i = 0;
     737           0 :         int rc = -1;
     738             : 
     739           0 :         if (spdk_json_decode_object(params, rpc_portal_group_decoders,
     740             :                                     SPDK_COUNTOF(rpc_portal_group_decoders),
     741             :                                     &req)) {
     742           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     743           0 :                 goto out;
     744             :         }
     745             : 
     746           0 :         pg = iscsi_portal_grp_create(req.tag, req.is_private);
     747           0 :         if (pg == NULL) {
     748           0 :                 SPDK_ERRLOG("portal_grp_create failed\n");
     749           0 :                 goto out;
     750             :         }
     751           0 :         for (i = 0; i < req.portal_list.num_portals; i++) {
     752           0 :                 portal = iscsi_portal_create(req.portal_list.portals[i].host,
     753           0 :                                              req.portal_list.portals[i].port);
     754           0 :                 if (portal == NULL) {
     755           0 :                         SPDK_ERRLOG("portal_create failed\n");
     756           0 :                         goto out;
     757             :                 }
     758           0 :                 iscsi_portal_grp_add_portal(pg, portal);
     759             :         }
     760             : 
     761           0 :         rc = iscsi_portal_grp_open(pg, req.wait);
     762           0 :         if (rc != 0) {
     763           0 :                 SPDK_ERRLOG("portal_grp_open failed\n");
     764           0 :                 goto out;
     765             :         }
     766             : 
     767           0 :         rc = iscsi_portal_grp_register(pg);
     768           0 :         if (rc != 0) {
     769           0 :                 SPDK_ERRLOG("portal_grp_register failed\n");
     770             :         }
     771             : 
     772           0 : out:
     773           0 :         if (rc == 0) {
     774           0 :                 spdk_jsonrpc_send_bool_response(request, true);
     775             :         } else {
     776           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     777             : 
     778           0 :                 if (pg != NULL) {
     779           0 :                         iscsi_portal_grp_release(pg);
     780             :                 }
     781             :         }
     782           0 :         free_rpc_portal_group(&req);
     783           0 : }
     784           0 : 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           0 : _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           0 :         struct rpc_iscsi_change_portal_group req = {};
     802             :         int rc;
     803             : 
     804           0 :         if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders,
     805             :                                     SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders),
     806             :                                     &req)) {
     807           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     808           0 :                 goto invalid;
     809             :         }
     810             : 
     811           0 :         rc = fn(req.tag);
     812           0 :         if (rc != 0) {
     813           0 :                 goto invalid;
     814             :         }
     815             : 
     816           0 :         spdk_jsonrpc_send_bool_response(request, true);
     817           0 :         return;
     818             : 
     819           0 : invalid:
     820           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     821             : }
     822             : 
     823             : static int
     824           0 : _rpc_iscsi_delete_portal_group(int pg_tag)
     825             : {
     826             :         struct spdk_iscsi_portal_grp *pg;
     827             : 
     828           0 :         pg = iscsi_portal_grp_unregister(pg_tag);
     829           0 :         if (!pg) {
     830           0 :                 return -ENODEV;
     831             :         }
     832             : 
     833           0 :         iscsi_tgt_node_delete_map(pg, NULL);
     834           0 :         iscsi_portal_grp_release(pg);
     835           0 :         return 0;
     836             : }
     837             : 
     838             : static void
     839           0 : rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request,
     840             :                               const struct spdk_json_val *params)
     841             : {
     842           0 :         _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group);
     843           0 : }
     844           0 : SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME)
     845             : 
     846             : static int
     847           0 : _rpc_iscsi_start_portal_group(int pg_tag)
     848             : {
     849             :         struct spdk_iscsi_portal_grp *pg;
     850             : 
     851           0 :         pg = iscsi_portal_grp_find_by_tag(pg_tag);
     852           0 :         if (!pg) {
     853           0 :                 return -ENODEV;
     854             :         }
     855             : 
     856           0 :         iscsi_portal_grp_resume(pg);
     857           0 :         return 0;
     858             : }
     859             : 
     860             : static void
     861           0 : rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request,
     862             :                              const struct spdk_json_val *params)
     863             : {
     864           0 :         _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group);
     865           0 : }
     866           0 : 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           0 : rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request,
     886             :                                 const struct spdk_json_val *params)
     887             : {
     888           0 :         struct rpc_portal_group_auth req = {};
     889             :         struct spdk_iscsi_portal_grp *pg;
     890             :         int rc;
     891             : 
     892           0 :         if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders,
     893             :                                     SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) {
     894           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     895           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     896             :                                                  "Invalid parameters");
     897           0 :                 return;
     898             :         }
     899             : 
     900           0 :         pthread_mutex_lock(&g_iscsi.mutex);
     901             : 
     902           0 :         pg = iscsi_portal_grp_find_by_tag(req.tag);
     903           0 :         if (pg == NULL) {
     904           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     905             :                                                      "Could not find portal group %d", req.tag);
     906           0 :                 goto exit;
     907             :         }
     908             : 
     909           0 :         rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap,
     910           0 :                                               req.mutual_chap, req.chap_group);
     911           0 :         if (rc < 0) {
     912           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     913             :                                                  "Invalid combination of auth params");
     914           0 :                 goto exit;
     915             :         }
     916             : 
     917           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
     918             : 
     919           0 :         spdk_jsonrpc_send_bool_response(request, true);
     920           0 :         return;
     921             : 
     922           0 : exit:
     923           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
     924             : }
     925           0 : 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           0 : _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status)
     935             : {
     936           0 :         struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
     937             : 
     938           0 :         spdk_json_write_array_end(ctx->w);
     939           0 :         spdk_jsonrpc_end_result(ctx->request, ctx->w);
     940             : 
     941           0 :         free(ctx);
     942           0 : }
     943             : 
     944             : static void
     945           0 : _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i)
     946             : {
     947           0 :         struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
     948           0 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
     949           0 :         struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
     950             :         struct spdk_iscsi_conn *conn;
     951             : 
     952           0 :         STAILQ_FOREACH(conn, &pg->connections, pg_link) {
     953           0 :                 iscsi_conn_info_json(ctx->w, conn);
     954             :         }
     955             : 
     956           0 :         spdk_for_each_channel_continue(i, 0);
     957           0 : }
     958             : 
     959             : static void
     960           0 : 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           0 :         if (params != NULL) {
     966           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     967             :                                                  "iscsi_get_connections requires no parameters");
     968           0 :                 return;
     969             :         }
     970             : 
     971           0 :         ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx));
     972           0 :         if (ctx == NULL) {
     973           0 :                 SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n");
     974           0 :                 spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
     975           0 :                 return;
     976             :         }
     977             : 
     978           0 :         ctx->request = request;
     979           0 :         ctx->w = spdk_jsonrpc_begin_result(request);
     980             : 
     981           0 :         spdk_json_write_array_begin(ctx->w);
     982             : 
     983           0 :         spdk_for_each_channel(&g_iscsi,
     984             :                               _rpc_iscsi_get_connections,
     985             :                               ctx,
     986             :                               _rpc_iscsi_get_connections_done);
     987             : }
     988           0 : 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           0 : free_rpc_target_lun(struct rpc_target_lun *req)
     998             : {
     999           0 :         free(req->name);
    1000           0 :         free(req->bdev_name);
    1001           0 : }
    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           0 : rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request,
    1011             :                               const struct spdk_json_val *params)
    1012             : {
    1013           0 :         struct rpc_target_lun req = {};
    1014             :         struct spdk_iscsi_tgt_node *target;
    1015             :         int rc;
    1016             : 
    1017           0 :         req.lun_id = -1;
    1018             : 
    1019           0 :         if (spdk_json_decode_object(params, rpc_target_lun_decoders,
    1020             :                                     SPDK_COUNTOF(rpc_target_lun_decoders), &req)) {
    1021           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1022           0 :                 goto invalid;
    1023             :         }
    1024             : 
    1025           0 :         target = iscsi_find_tgt_node(req.name);
    1026           0 :         if (target == NULL) {
    1027           0 :                 SPDK_ERRLOG("target is not found\n");
    1028           0 :                 goto invalid;
    1029             :         }
    1030             : 
    1031           0 :         rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id);
    1032           0 :         if (rc < 0) {
    1033           0 :                 SPDK_ERRLOG("add lun failed\n");
    1034           0 :                 goto invalid;
    1035             :         }
    1036             : 
    1037           0 :         free_rpc_target_lun(&req);
    1038             : 
    1039           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1040           0 :         return;
    1041             : 
    1042           0 : invalid:
    1043           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1044             :                                          "Invalid parameters");
    1045           0 :         free_rpc_target_lun(&req);
    1046             : }
    1047           0 : 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           0 : free_rpc_target_auth(struct rpc_target_auth *req)
    1059             : {
    1060           0 :         free(req->name);
    1061           0 : }
    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           0 : rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request,
    1073             :                                const struct spdk_json_val *params)
    1074             : {
    1075           0 :         struct rpc_target_auth req = {};
    1076             :         struct spdk_iscsi_tgt_node *target;
    1077             :         int rc;
    1078             : 
    1079           0 :         if (spdk_json_decode_object(params, rpc_target_auth_decoders,
    1080             :                                     SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
    1081           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1082           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1083             :                                                  "Invalid parameters");
    1084           0 :                 goto exit;
    1085             :         }
    1086             : 
    1087           0 :         target = iscsi_find_tgt_node(req.name);
    1088           0 :         if (target == NULL) {
    1089           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1090             :                                                      "Could not find target %s", req.name);
    1091           0 :                 goto exit;
    1092             :         }
    1093             : 
    1094           0 :         rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
    1095           0 :                                             req.mutual_chap, req.chap_group);
    1096           0 :         if (rc < 0) {
    1097           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1098             :                                                  "Invalid combination of auth params");
    1099           0 :                 goto exit;
    1100             :         }
    1101             : 
    1102           0 :         free_rpc_target_auth(&req);
    1103             : 
    1104           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1105           0 :         return;
    1106             : 
    1107           0 : exit:
    1108           0 :         free_rpc_target_auth(&req);
    1109             : }
    1110           0 : 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           0 : free_rpc_target_redirect(struct rpc_target_redirect *req)
    1122             : {
    1123           0 :         free(req->name);
    1124           0 :         free(req->redirect_host);
    1125           0 :         free(req->redirect_port);
    1126           0 : }
    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           0 : rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request,
    1137             :                                    const struct spdk_json_val *params)
    1138             : {
    1139           0 :         struct rpc_target_redirect req = {};
    1140             :         struct spdk_iscsi_tgt_node *target;
    1141             :         int rc;
    1142             : 
    1143           0 :         if (spdk_json_decode_object(params, rpc_target_redirect_decoders,
    1144             :                                     SPDK_COUNTOF(rpc_target_redirect_decoders),
    1145             :                                     &req)) {
    1146           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1147           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1148             :                                                  "Invalid parameters");
    1149           0 :                 free_rpc_target_redirect(&req);
    1150           0 :                 return;
    1151             :         }
    1152             : 
    1153           0 :         target = iscsi_find_tgt_node(req.name);
    1154           0 :         if (target == NULL) {
    1155           0 :                 SPDK_ERRLOG("target %s is not found\n", req.name);
    1156           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1157             :                                                      "Target %s is not found", req.name);
    1158           0 :                 free_rpc_target_redirect(&req);
    1159           0 :                 return;
    1160             :         }
    1161             : 
    1162           0 :         rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port);
    1163           0 :         if (rc != 0) {
    1164           0 :                 SPDK_ERRLOG("failed to redirect target %s\n", req.name);
    1165           0 :                 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           0 :                 free_rpc_target_redirect(&req);
    1169           0 :                 return;
    1170             :         }
    1171             : 
    1172           0 :         free_rpc_target_redirect(&req);
    1173             : 
    1174           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1175             : }
    1176           0 : 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           0 : free_rpc_target_logout(struct rpc_target_logout *req)
    1186             : {
    1187           0 :         free(req->name);
    1188           0 : }
    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           0 : rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request,
    1197             :                                      const struct spdk_json_val *params)
    1198             : {
    1199           0 :         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           0 :         req.pg_tag = -1;
    1206             : 
    1207           0 :         if (spdk_json_decode_object(params, rpc_target_logout_decoders,
    1208             :                                     SPDK_COUNTOF(rpc_target_logout_decoders),
    1209             :                                     &req)) {
    1210           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1211           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1212             :                                                  "Invalid parameters");
    1213           0 :                 free_rpc_target_logout(&req);
    1214           0 :                 return;
    1215             :         }
    1216             : 
    1217           0 :         target = iscsi_find_tgt_node(req.name);
    1218           0 :         if (target == NULL) {
    1219           0 :                 SPDK_ERRLOG("target %s is not found\n", req.name);
    1220           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1221             :                                                      "Target %s is not found", req.name);
    1222           0 :                 free_rpc_target_logout(&req);
    1223           0 :                 return;
    1224             :         }
    1225             : 
    1226           0 :         iscsi_conns_request_logout(target, req.pg_tag);
    1227             : 
    1228           0 :         free_rpc_target_logout(&req);
    1229             : 
    1230           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1231             : }
    1232           0 : SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout,
    1233             :                   SPDK_RPC_RUNTIME)
    1234             : 
    1235             : static void
    1236           0 : 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           0 :         if (params != NULL) {
    1242           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1243             :                                                  "iscsi_get_options requires no parameters");
    1244           0 :                 return;
    1245             :         }
    1246             : 
    1247           0 :         w = spdk_jsonrpc_begin_result(request);
    1248           0 :         iscsi_opts_info_json(w);
    1249             : 
    1250           0 :         spdk_jsonrpc_end_result(request, w);
    1251             : }
    1252           0 : 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           0 : rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request,
    1270             :                              const struct spdk_json_val *params)
    1271             : {
    1272           0 :         struct rpc_discovery_auth req = {};
    1273             :         int rc;
    1274             : 
    1275           0 :         if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
    1276             :                                     SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
    1277           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1278           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1279             :                                                  "Invalid parameters");
    1280           0 :                 return;
    1281             :         }
    1282             : 
    1283           0 :         rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
    1284           0 :                                       req.mutual_chap, req.chap_group);
    1285           0 :         if (rc < 0) {
    1286           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1287             :                                                  "Invalid combination of CHAP params");
    1288           0 :                 return;
    1289             :         }
    1290             : 
    1291           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1292             : }
    1293           0 : 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           0 : free_rpc_auth_secret(struct rpc_auth_secret *_secret)
    1306             : {
    1307           0 :         free(_secret->user);
    1308           0 :         free(_secret->secret);
    1309           0 :         free(_secret->muser);
    1310           0 :         free(_secret->msecret);
    1311           0 : }
    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           0 : decode_rpc_auth_secret(const struct spdk_json_val *val, void *out)
    1322             : {
    1323           0 :         struct rpc_auth_secret *_secret = out;
    1324             : 
    1325           0 :         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           0 : free_rpc_auth_secrets(struct rpc_auth_secrets *secrets)
    1336             : {
    1337             :         size_t i;
    1338             : 
    1339           0 :         for (i = 0; i < secrets->num_secret; i++) {
    1340           0 :                 free_rpc_auth_secret(&secrets->secrets[i]);
    1341             :         }
    1342           0 : }
    1343             : 
    1344             : static int
    1345           0 : decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out)
    1346             : {
    1347           0 :         struct rpc_auth_secrets *secrets = out;
    1348             : 
    1349           0 :         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           0 : free_rpc_auth_group(struct rpc_auth_group *group)
    1361             : {
    1362           0 :         free_rpc_auth_secrets(&group->secrets);
    1363           0 : }
    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           0 : rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request,
    1372             :                             const struct spdk_json_val *params)
    1373             : {
    1374           0 :         struct rpc_auth_group req = {};
    1375             :         struct rpc_auth_secret *_secret;
    1376           0 :         struct spdk_iscsi_auth_group *group = NULL;
    1377             :         int rc;
    1378             :         size_t i;
    1379             : 
    1380           0 :         if (spdk_json_decode_object(params, rpc_auth_group_decoders,
    1381             :                                     SPDK_COUNTOF(rpc_auth_group_decoders), &req)) {
    1382           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1383           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1384             :                                                  "Invalid parameters");
    1385           0 :                 free_rpc_auth_group(&req);
    1386           0 :                 return;
    1387             :         }
    1388             : 
    1389           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1390             : 
    1391           0 :         rc = iscsi_add_auth_group(req.tag, &group);
    1392           0 :         if (rc != 0) {
    1393           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1394             : 
    1395           0 :                 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           0 :                 free_rpc_auth_group(&req);
    1399           0 :                 return;
    1400             :         }
    1401             : 
    1402           0 :         for (i = 0; i < req.secrets.num_secret; i++) {
    1403           0 :                 _secret = &req.secrets.secrets[i];
    1404           0 :                 rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret,
    1405           0 :                                                  _secret->muser, _secret->msecret);
    1406           0 :                 if (rc != 0) {
    1407           0 :                         iscsi_delete_auth_group(group);
    1408           0 :                         pthread_mutex_unlock(&g_iscsi.mutex);
    1409             : 
    1410           0 :                         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           0 :                         free_rpc_auth_group(&req);
    1414           0 :                         return;
    1415             :                 }
    1416             :         }
    1417             : 
    1418           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1419             : 
    1420           0 :         free_rpc_auth_group(&req);
    1421             : 
    1422           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1423             : }
    1424           0 : 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           0 : rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request,
    1436             :                             const struct spdk_json_val *params)
    1437             : {
    1438           0 :         struct rpc_delete_auth_group req = {};
    1439             :         struct spdk_iscsi_auth_group *group;
    1440             : 
    1441           0 :         if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders,
    1442             :                                     SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) {
    1443           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1444           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1445             :                                                  "Invalid parameters");
    1446           0 :                 return;
    1447             :         }
    1448             : 
    1449           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1450             : 
    1451           0 :         group = iscsi_find_auth_group_by_tag(req.tag);
    1452           0 :         if (group == NULL) {
    1453           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1454             : 
    1455           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1456             :                                                      "Could not find auth group (%d)", req.tag);
    1457           0 :                 return;
    1458             :         }
    1459             : 
    1460           0 :         iscsi_delete_auth_group(group);
    1461             : 
    1462           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1463             : 
    1464           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1465             : }
    1466           0 : 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           0 : free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret)
    1478             : {
    1479           0 :         free(_secret->user);
    1480           0 :         free(_secret->secret);
    1481           0 :         free(_secret->muser);
    1482           0 :         free(_secret->msecret);
    1483           0 : }
    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           0 : rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request,
    1495             :                                 const struct spdk_json_val *params)
    1496             : {
    1497           0 :         struct rpc_add_auth_secret req = {};
    1498             :         struct spdk_iscsi_auth_group *group;
    1499             :         int rc;
    1500             : 
    1501           0 :         if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders,
    1502             :                                     SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) {
    1503           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1504           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1505             :                                                  "Invalid parameters");
    1506           0 :                 free_rpc_add_auth_secret(&req);
    1507           0 :                 return;
    1508             :         }
    1509             : 
    1510           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1511             : 
    1512           0 :         group = iscsi_find_auth_group_by_tag(req.tag);
    1513           0 :         if (group == NULL) {
    1514           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1515             : 
    1516           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1517             :                                                      "Could not find auth group (%d)", req.tag);
    1518           0 :                 free_rpc_add_auth_secret(&req);
    1519           0 :                 return;
    1520             :         }
    1521             : 
    1522           0 :         rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret);
    1523           0 :         if (rc != 0) {
    1524           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1525             : 
    1526           0 :                 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           0 :                 free_rpc_add_auth_secret(&req);
    1530           0 :                 return;
    1531             :         }
    1532             : 
    1533           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1534             : 
    1535           0 :         free_rpc_add_auth_secret(&req);
    1536             : 
    1537           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1538             : }
    1539           0 : 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           0 : free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret)
    1550             : {
    1551           0 :         free(_secret->user);
    1552           0 : }
    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           0 : rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request,
    1561             :                                    const struct spdk_json_val *params)
    1562             : {
    1563           0 :         struct rpc_remove_auth_secret req = {};
    1564             :         struct spdk_iscsi_auth_group *group;
    1565             :         int rc;
    1566             : 
    1567           0 :         if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders,
    1568             :                                     SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) {
    1569           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
    1570           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1571             :                                                  "Invalid parameters");
    1572           0 :                 free_rpc_remove_auth_secret(&req);
    1573           0 :                 return;
    1574             :         }
    1575             : 
    1576           0 :         pthread_mutex_lock(&g_iscsi.mutex);
    1577             : 
    1578           0 :         group = iscsi_find_auth_group_by_tag(req.tag);
    1579           0 :         if (group == NULL) {
    1580           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1581             : 
    1582           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1583             :                                                      "Could not find auth group (%d)", req.tag);
    1584           0 :                 free_rpc_remove_auth_secret(&req);
    1585           0 :                 return;
    1586             :         }
    1587             : 
    1588           0 :         rc = iscsi_auth_group_delete_secret(group, req.user);
    1589           0 :         if (rc != 0) {
    1590           0 :                 pthread_mutex_unlock(&g_iscsi.mutex);
    1591             : 
    1592           0 :                 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           0 :                 free_rpc_remove_auth_secret(&req);
    1596           0 :                 return;
    1597             :         }
    1598             : 
    1599           0 :         pthread_mutex_unlock(&g_iscsi.mutex);
    1600             : 
    1601           0 :         free_rpc_remove_auth_secret(&req);
    1602             : 
    1603           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1604             : }
    1605           0 : SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret",
    1606             :                   rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME)
    1607             : 
    1608             : static void
    1609           0 : 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           0 :         if (params != NULL) {
    1615           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1616             :                                                  "iscsi_get_auth_groups requires no parameters");
    1617           0 :                 return;
    1618             :         }
    1619             : 
    1620           0 :         w = spdk_jsonrpc_begin_result(request);
    1621           0 :         spdk_json_write_array_begin(w);
    1622           0 :         iscsi_auth_groups_info_json(w);
    1623           0 :         spdk_json_write_array_end(w);
    1624             : 
    1625           0 :         spdk_jsonrpc_end_result(request, w);
    1626             : }
    1627           0 : 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           0 : 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           0 :         if (g_spdk_iscsi_opts != NULL) {
    1665           0 :                 SPDK_ERRLOG("this RPC must not be called more than once.\n");
    1666           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1667             :                                                  "Must not call more than once");
    1668           0 :                 return;
    1669             :         }
    1670             : 
    1671           0 :         opts = iscsi_opts_alloc();
    1672           0 :         if (opts == NULL) {
    1673           0 :                 SPDK_ERRLOG("iscsi_opts_alloc() failed.\n");
    1674           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1675             :                                                  "Out of memory");
    1676           0 :                 return;
    1677             :         }
    1678             : 
    1679           0 :         if (params != NULL) {
    1680           0 :                 if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders,
    1681             :                                             SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) {
    1682           0 :                         SPDK_ERRLOG("spdk_json_decode_object() failed\n");
    1683           0 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
    1684             :                                                          "Invalid parameters");
    1685           0 :                         iscsi_opts_free(opts);
    1686           0 :                         return;
    1687             :                 }
    1688             :         }
    1689             : 
    1690           0 :         g_spdk_iscsi_opts = iscsi_opts_copy(opts);
    1691           0 :         iscsi_opts_free(opts);
    1692             : 
    1693           0 :         if (g_spdk_iscsi_opts == NULL) {
    1694           0 :                 SPDK_ERRLOG("iscsi_opts_copy() failed\n");
    1695           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
    1696             :                                                  "Out of memory");
    1697           0 :                 return;
    1698             :         }
    1699             : 
    1700           0 :         spdk_jsonrpc_send_bool_response(request, true);
    1701             : }
    1702           0 : SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP)

Generated by: LCOV version 1.15