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)
|