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