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 : #include "spdk/base64.h"
18 : #include "spdk/histogram_data.h"
19 :
20 : static void
21 0 : rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request,
22 : const struct spdk_json_val *params)
23 : {
24 : struct spdk_json_write_ctx *w;
25 :
26 0 : if (params != NULL) {
27 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
28 : "iscsi_get_initiator_groups requires no parameters");
29 0 : return;
30 : }
31 :
32 0 : w = spdk_jsonrpc_begin_result(request);
33 0 : spdk_json_write_array_begin(w);
34 0 : iscsi_init_grps_info_json(w);
35 0 : spdk_json_write_array_end(w);
36 :
37 0 : spdk_jsonrpc_end_result(request, w);
38 : }
39 0 : SPDK_RPC_REGISTER("iscsi_get_initiator_groups", rpc_iscsi_get_initiator_groups,
40 : SPDK_RPC_RUNTIME)
41 :
42 : struct rpc_initiator_list {
43 : size_t num_initiators;
44 : char *initiators[MAX_INITIATOR];
45 : };
46 :
47 : static int
48 0 : decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
49 : {
50 0 : struct rpc_initiator_list *list = out;
51 :
52 0 : return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR,
53 : &list->num_initiators, sizeof(char *));
54 : }
55 :
56 : static void
57 0 : free_rpc_initiator_list(struct rpc_initiator_list *list)
58 : {
59 : size_t i;
60 :
61 0 : for (i = 0; i < list->num_initiators; i++) {
62 0 : free(list->initiators[i]);
63 : }
64 0 : }
65 :
66 : struct rpc_netmask_list {
67 : size_t num_netmasks;
68 : char *netmasks[MAX_NETMASK];
69 : };
70 :
71 : static int
72 0 : decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
73 : {
74 0 : struct rpc_netmask_list *list = out;
75 :
76 0 : return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK,
77 : &list->num_netmasks, sizeof(char *));
78 : }
79 :
80 : static void
81 0 : free_rpc_netmask_list(struct rpc_netmask_list *list)
82 : {
83 : size_t i;
84 :
85 0 : for (i = 0; i < list->num_netmasks; i++) {
86 0 : free(list->netmasks[i]);
87 : }
88 0 : }
89 :
90 : struct rpc_initiator_group {
91 : int32_t tag;
92 : struct rpc_initiator_list initiator_list;
93 : struct rpc_netmask_list netmask_list;
94 : };
95 :
96 : static void
97 0 : free_rpc_initiator_group(struct rpc_initiator_group *ig)
98 : {
99 0 : free_rpc_initiator_list(&ig->initiator_list);
100 0 : free_rpc_netmask_list(&ig->netmask_list);
101 0 : }
102 :
103 : static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = {
104 : {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
105 : {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list},
106 : {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list},
107 : };
108 :
109 : static void
110 0 : rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request,
111 : const struct spdk_json_val *params)
112 : {
113 0 : struct rpc_initiator_group req = {};
114 :
115 0 : if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
116 : SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) {
117 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
118 0 : goto invalid;
119 : }
120 :
121 0 : if (req.initiator_list.num_initiators == 0 ||
122 0 : req.netmask_list.num_netmasks == 0) {
123 0 : goto invalid;
124 : }
125 :
126 0 : if (iscsi_init_grp_create_from_initiator_list(req.tag,
127 0 : req.initiator_list.num_initiators,
128 : req.initiator_list.initiators,
129 0 : req.netmask_list.num_netmasks,
130 : req.netmask_list.netmasks)) {
131 0 : SPDK_ERRLOG("create_from_initiator_list failed\n");
132 0 : goto invalid;
133 : }
134 :
135 0 : free_rpc_initiator_group(&req);
136 :
137 0 : spdk_jsonrpc_send_bool_response(request, true);
138 0 : return;
139 :
140 0 : invalid:
141 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
142 0 : free_rpc_initiator_group(&req);
143 : }
144 0 : SPDK_RPC_REGISTER("iscsi_create_initiator_group", rpc_iscsi_create_initiator_group,
145 : SPDK_RPC_RUNTIME)
146 :
147 : static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = {
148 : {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
149 : {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true},
150 : {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true},
151 : };
152 :
153 : static void
154 0 : rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request,
155 : const struct spdk_json_val *params)
156 : {
157 0 : struct rpc_initiator_group req = {};
158 :
159 0 : if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
160 : SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
161 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
162 0 : goto invalid;
163 : }
164 :
165 0 : if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
166 0 : req.initiator_list.num_initiators,
167 : req.initiator_list.initiators,
168 0 : req.netmask_list.num_netmasks,
169 : req.netmask_list.netmasks)) {
170 0 : SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
171 0 : goto invalid;
172 : }
173 :
174 0 : free_rpc_initiator_group(&req);
175 :
176 0 : spdk_jsonrpc_send_bool_response(request, true);
177 0 : return;
178 :
179 0 : invalid:
180 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
181 0 : free_rpc_initiator_group(&req);
182 : }
183 0 : SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators",
184 : rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME)
185 :
186 : static void
187 0 : rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request,
188 : const struct spdk_json_val *params)
189 : {
190 0 : struct rpc_initiator_group req = {};
191 :
192 0 : if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
193 : SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
194 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
195 0 : goto invalid;
196 : }
197 :
198 0 : if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
199 0 : req.initiator_list.num_initiators,
200 : req.initiator_list.initiators,
201 0 : req.netmask_list.num_netmasks,
202 : req.netmask_list.netmasks)) {
203 0 : SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
204 0 : goto invalid;
205 : }
206 :
207 0 : free_rpc_initiator_group(&req);
208 :
209 0 : spdk_jsonrpc_send_bool_response(request, true);
210 0 : return;
211 :
212 0 : invalid:
213 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
214 0 : free_rpc_initiator_group(&req);
215 : }
216 0 : SPDK_RPC_REGISTER("iscsi_initiator_group_remove_initiators",
217 : rpc_iscsi_initiator_group_remove_initiators, SPDK_RPC_RUNTIME)
218 :
219 : struct rpc_iscsi_delete_initiator_group {
220 : int32_t tag;
221 : };
222 :
223 : static const struct spdk_json_object_decoder rpc_iscsi_delete_initiator_group_decoders[] = {
224 : {"tag", offsetof(struct rpc_iscsi_delete_initiator_group, tag), spdk_json_decode_int32},
225 : };
226 :
227 : static void
228 0 : rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request,
229 : const struct spdk_json_val *params)
230 : {
231 0 : struct rpc_iscsi_delete_initiator_group req = {};
232 : struct spdk_iscsi_init_grp *ig;
233 :
234 0 : if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders,
235 : SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders),
236 : &req)) {
237 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
238 0 : goto invalid;
239 : }
240 :
241 0 : ig = iscsi_init_grp_unregister(req.tag);
242 0 : if (!ig) {
243 0 : goto invalid;
244 : }
245 0 : iscsi_tgt_node_delete_map(NULL, ig);
246 0 : iscsi_init_grp_destroy(ig);
247 :
248 0 : spdk_jsonrpc_send_bool_response(request, true);
249 0 : return;
250 :
251 0 : invalid:
252 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
253 : }
254 0 : SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group,
255 : SPDK_RPC_RUNTIME)
256 :
257 : static void
258 0 : rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request *request,
259 : const struct spdk_json_val *params)
260 : {
261 : struct spdk_json_write_ctx *w;
262 :
263 0 : if (params != NULL) {
264 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
265 : "iscsi_get_target_nodes requires no parameters");
266 0 : return;
267 : }
268 :
269 0 : w = spdk_jsonrpc_begin_result(request);
270 0 : spdk_json_write_array_begin(w);
271 0 : iscsi_tgt_nodes_info_json(w);
272 0 : spdk_json_write_array_end(w);
273 :
274 0 : spdk_jsonrpc_end_result(request, w);
275 : }
276 0 : SPDK_RPC_REGISTER("iscsi_get_target_nodes", rpc_iscsi_get_target_nodes, SPDK_RPC_RUNTIME)
277 :
278 : struct rpc_pg_ig_map {
279 : int32_t pg_tag;
280 : int32_t ig_tag;
281 : };
282 :
283 : static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = {
284 : {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32},
285 : {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32},
286 : };
287 :
288 : static int
289 0 : decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out)
290 : {
291 0 : struct rpc_pg_ig_map *pg_ig_map = out;
292 :
293 0 : return spdk_json_decode_object(val, rpc_pg_ig_map_decoders,
294 : SPDK_COUNTOF(rpc_pg_ig_map_decoders),
295 : pg_ig_map);
296 : }
297 :
298 : struct rpc_pg_ig_maps {
299 : size_t num_maps;
300 : struct rpc_pg_ig_map maps[MAX_TARGET_MAP];
301 : };
302 :
303 : static int
304 0 : decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out)
305 : {
306 0 : struct rpc_pg_ig_maps *pg_ig_maps = out;
307 :
308 0 : return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps,
309 : MAX_TARGET_MAP, &pg_ig_maps->num_maps,
310 : sizeof(struct rpc_pg_ig_map));
311 : }
312 :
313 : #define RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN 64
314 :
315 : struct rpc_lun {
316 : char *bdev_name;
317 : int32_t lun_id;
318 : };
319 :
320 : static const struct spdk_json_object_decoder rpc_lun_decoders[] = {
321 : {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string},
322 : {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32},
323 : };
324 :
325 : static int
326 0 : decode_rpc_lun(const struct spdk_json_val *val, void *out)
327 : {
328 0 : struct rpc_lun *lun = out;
329 :
330 0 : return spdk_json_decode_object(val, rpc_lun_decoders,
331 : SPDK_COUNTOF(rpc_lun_decoders), lun);
332 : }
333 :
334 : struct rpc_luns {
335 : size_t num_luns;
336 : struct rpc_lun luns[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN];
337 : };
338 :
339 : static int
340 0 : decode_rpc_luns(const struct spdk_json_val *val, void *out)
341 : {
342 0 : struct rpc_luns *luns = out;
343 :
344 0 : return spdk_json_decode_array(val, decode_rpc_lun, luns->luns,
345 : RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN,
346 : &luns->num_luns, sizeof(struct rpc_lun));
347 : }
348 :
349 : static void
350 0 : free_rpc_luns(struct rpc_luns *p)
351 : {
352 : size_t i;
353 :
354 0 : for (i = 0; i < p->num_luns; i++) {
355 0 : free(p->luns[i].bdev_name);
356 : }
357 0 : }
358 :
359 : struct rpc_target_node {
360 : char *name;
361 : char *alias_name;
362 :
363 : struct rpc_pg_ig_maps pg_ig_maps;
364 : struct rpc_luns luns;
365 :
366 : int32_t queue_depth;
367 : bool disable_chap;
368 : bool require_chap;
369 : bool mutual_chap;
370 : int32_t chap_group;
371 :
372 : bool header_digest;
373 : bool data_digest;
374 : };
375 :
376 : static void
377 0 : free_rpc_target_node(struct rpc_target_node *req)
378 : {
379 0 : free(req->name);
380 0 : free(req->alias_name);
381 0 : free_rpc_luns(&req->luns);
382 0 : }
383 :
384 : static const struct spdk_json_object_decoder rpc_target_node_decoders[] = {
385 : {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string},
386 : {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string},
387 : {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps},
388 : {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns},
389 : {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32},
390 : {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true},
391 : {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true},
392 : {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true},
393 : {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true},
394 : {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true},
395 : {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true},
396 : };
397 :
398 : static void
399 0 : rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request,
400 : const struct spdk_json_val *params)
401 : {
402 0 : struct rpc_target_node req = {};
403 : struct spdk_iscsi_tgt_node *target;
404 0 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
405 0 : char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
406 0 : int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
407 : size_t i;
408 :
409 0 : if (spdk_json_decode_object(params, rpc_target_node_decoders,
410 : SPDK_COUNTOF(rpc_target_node_decoders),
411 : &req)) {
412 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
413 0 : goto invalid;
414 : }
415 :
416 0 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
417 0 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
418 0 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
419 : }
420 :
421 0 : for (i = 0; i < req.luns.num_luns; i++) {
422 0 : bdev_names[i] = req.luns.luns[i].bdev_name;
423 0 : lun_ids[i] = req.luns.luns[i].lun_id;
424 : }
425 :
426 : /*
427 : * Use default parameters in a few places:
428 : * index = -1 : automatically pick an index for the new target node
429 : * alias = NULL
430 : */
431 0 : target = iscsi_tgt_node_construct(-1, req.name, req.alias_name,
432 : pg_tags,
433 : ig_tags,
434 0 : req.pg_ig_maps.num_maps,
435 : (const char **)bdev_names,
436 : lun_ids,
437 0 : req.luns.num_luns,
438 : req.queue_depth,
439 0 : req.disable_chap,
440 0 : req.require_chap,
441 0 : req.mutual_chap,
442 : req.chap_group,
443 0 : req.header_digest,
444 0 : req.data_digest);
445 :
446 0 : if (target == NULL) {
447 0 : goto invalid;
448 : }
449 :
450 0 : free_rpc_target_node(&req);
451 :
452 0 : spdk_jsonrpc_send_bool_response(request, true);
453 0 : return;
454 :
455 0 : invalid:
456 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
457 0 : free_rpc_target_node(&req);
458 : }
459 0 : SPDK_RPC_REGISTER("iscsi_create_target_node", rpc_iscsi_create_target_node, SPDK_RPC_RUNTIME)
460 :
461 : struct rpc_tgt_node_pg_ig_maps {
462 : char *name;
463 : struct rpc_pg_ig_maps pg_ig_maps;
464 : };
465 :
466 : static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = {
467 : {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string},
468 : {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps},
469 : };
470 :
471 : static void
472 0 : rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request,
473 : const struct spdk_json_val *params)
474 : {
475 0 : struct rpc_tgt_node_pg_ig_maps req = {};
476 : struct spdk_iscsi_tgt_node *target;
477 0 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
478 : size_t i;
479 : int rc;
480 :
481 0 : if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
482 : SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
483 : &req)) {
484 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
485 0 : goto invalid;
486 : }
487 :
488 0 : target = iscsi_find_tgt_node(req.name);
489 0 : if (target == NULL) {
490 0 : SPDK_ERRLOG("target is not found\n");
491 0 : goto invalid;
492 : }
493 :
494 0 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
495 0 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
496 0 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
497 : }
498 :
499 0 : rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags,
500 0 : req.pg_ig_maps.num_maps);
501 0 : if (rc < 0) {
502 0 : SPDK_ERRLOG("add pg-ig maps failed\n");
503 0 : goto invalid;
504 : }
505 :
506 0 : free(req.name);
507 :
508 0 : spdk_jsonrpc_send_bool_response(request, true);
509 0 : return;
510 :
511 0 : invalid:
512 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
513 : "Invalid parameters");
514 0 : free(req.name);
515 : }
516 0 : SPDK_RPC_REGISTER("iscsi_target_node_add_pg_ig_maps",
517 : rpc_iscsi_target_node_add_pg_ig_maps, SPDK_RPC_RUNTIME)
518 :
519 : static void
520 0 : rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request,
521 : const struct spdk_json_val *params)
522 : {
523 0 : struct rpc_tgt_node_pg_ig_maps req = {};
524 : struct spdk_iscsi_tgt_node *target;
525 0 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
526 : size_t i;
527 : int rc;
528 :
529 0 : if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
530 : SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
531 : &req)) {
532 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
533 0 : goto invalid;
534 : }
535 :
536 0 : target = iscsi_find_tgt_node(req.name);
537 0 : if (target == NULL) {
538 0 : SPDK_ERRLOG("target is not found\n");
539 0 : goto invalid;
540 : }
541 :
542 0 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
543 0 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
544 0 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
545 : }
546 :
547 0 : rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags,
548 0 : req.pg_ig_maps.num_maps);
549 0 : if (rc < 0) {
550 0 : SPDK_ERRLOG("remove pg-ig maps failed\n");
551 0 : goto invalid;
552 : }
553 :
554 0 : free(req.name);
555 :
556 0 : spdk_jsonrpc_send_bool_response(request, true);
557 0 : return;
558 :
559 0 : invalid:
560 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
561 : "Invalid parameters");
562 0 : free(req.name);
563 : }
564 0 : SPDK_RPC_REGISTER("iscsi_target_node_remove_pg_ig_maps",
565 : rpc_iscsi_target_node_remove_pg_ig_maps, SPDK_RPC_RUNTIME)
566 :
567 : struct rpc_iscsi_delete_target_node {
568 : char *name;
569 : };
570 :
571 : static void
572 0 : free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r)
573 : {
574 0 : free(r->name);
575 0 : }
576 :
577 : static const struct spdk_json_object_decoder rpc_iscsi_delete_target_node_decoders[] = {
578 : {"name", offsetof(struct rpc_iscsi_delete_target_node, name), spdk_json_decode_string},
579 : };
580 :
581 : struct rpc_iscsi_delete_target_node_ctx {
582 : struct rpc_iscsi_delete_target_node req;
583 : struct spdk_jsonrpc_request *request;
584 : };
585 :
586 : static void
587 0 : rpc_iscsi_delete_target_node_done(void *cb_arg, int rc)
588 : {
589 0 : struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg;
590 :
591 0 : free_rpc_iscsi_delete_target_node(&ctx->req);
592 0 : if (rc == 0) {
593 0 : spdk_jsonrpc_send_bool_response(ctx->request, true);
594 : } else {
595 0 : spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
596 : }
597 0 : free(ctx);
598 0 : }
599 :
600 : static void
601 0 : rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request,
602 : const struct spdk_json_val *params)
603 : {
604 : struct rpc_iscsi_delete_target_node_ctx *ctx;
605 :
606 0 : ctx = calloc(1, sizeof(*ctx));
607 0 : if (!ctx) {
608 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
609 : spdk_strerror(ENOMEM));
610 0 : return;
611 : }
612 :
613 0 : if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders,
614 : SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders),
615 0 : &ctx->req)) {
616 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
617 0 : goto invalid;
618 : }
619 :
620 0 : if (ctx->req.name == NULL) {
621 0 : SPDK_ERRLOG("missing name param\n");
622 0 : goto invalid;
623 : }
624 :
625 0 : ctx->request = request;
626 :
627 0 : iscsi_shutdown_tgt_node_by_name(ctx->req.name,
628 : rpc_iscsi_delete_target_node_done, ctx);
629 0 : return;
630 :
631 0 : invalid:
632 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
633 0 : free_rpc_iscsi_delete_target_node(&ctx->req);
634 0 : free(ctx);
635 : }
636 0 : SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME)
637 :
638 : static void
639 0 : rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request,
640 : const struct spdk_json_val *params)
641 : {
642 : struct spdk_json_write_ctx *w;
643 :
644 0 : if (params != NULL) {
645 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
646 : "iscsi_get_portal_groups requires no parameters");
647 0 : return;
648 : }
649 :
650 0 : w = spdk_jsonrpc_begin_result(request);
651 0 : spdk_json_write_array_begin(w);
652 0 : iscsi_portal_grps_info_json(w);
653 0 : spdk_json_write_array_end(w);
654 :
655 0 : spdk_jsonrpc_end_result(request, w);
656 : }
657 0 : SPDK_RPC_REGISTER("iscsi_get_portal_groups", rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME)
658 :
659 : struct rpc_portal {
660 : char *host;
661 : char *port;
662 : };
663 :
664 : struct rpc_portal_list {
665 : size_t num_portals;
666 : struct rpc_portal portals[MAX_PORTAL];
667 : };
668 :
669 : struct rpc_portal_group {
670 : int32_t tag;
671 : struct rpc_portal_list portal_list;
672 : bool is_private;
673 : bool wait;
674 : };
675 :
676 : static void
677 0 : free_rpc_portal(struct rpc_portal *portal)
678 : {
679 0 : free(portal->host);
680 0 : free(portal->port);
681 0 : }
682 :
683 : static void
684 0 : free_rpc_portal_list(struct rpc_portal_list *pl)
685 : {
686 : size_t i;
687 :
688 0 : for (i = 0; i < pl->num_portals; i++) {
689 0 : free_rpc_portal(&pl->portals[i]);
690 : }
691 0 : pl->num_portals = 0;
692 0 : }
693 :
694 : static void
695 0 : free_rpc_portal_group(struct rpc_portal_group *pg)
696 : {
697 0 : free_rpc_portal_list(&pg->portal_list);
698 0 : }
699 :
700 : static const struct spdk_json_object_decoder rpc_portal_decoders[] = {
701 : {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string},
702 : {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string},
703 : };
704 :
705 : static int
706 0 : decode_rpc_portal(const struct spdk_json_val *val, void *out)
707 : {
708 0 : struct rpc_portal *portal = out;
709 :
710 0 : return spdk_json_decode_object(val, rpc_portal_decoders,
711 : SPDK_COUNTOF(rpc_portal_decoders),
712 : portal);
713 : }
714 :
715 : static int
716 0 : decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
717 : {
718 0 : struct rpc_portal_list *list = out;
719 :
720 0 : return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals,
721 : sizeof(struct rpc_portal));
722 : }
723 :
724 : static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = {
725 : {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32},
726 : {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list},
727 : {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true},
728 : {"wait", offsetof(struct rpc_portal_group, wait), spdk_json_decode_bool, true},
729 : };
730 :
731 : static void
732 0 : rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request,
733 : const struct spdk_json_val *params)
734 : {
735 0 : struct rpc_portal_group req = {};
736 0 : struct spdk_iscsi_portal_grp *pg = NULL;
737 : struct spdk_iscsi_portal *portal;
738 0 : size_t i = 0;
739 0 : int rc = -1;
740 :
741 0 : if (spdk_json_decode_object(params, rpc_portal_group_decoders,
742 : SPDK_COUNTOF(rpc_portal_group_decoders),
743 : &req)) {
744 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
745 0 : goto out;
746 : }
747 :
748 0 : pg = iscsi_portal_grp_create(req.tag, req.is_private);
749 0 : if (pg == NULL) {
750 0 : SPDK_ERRLOG("portal_grp_create failed\n");
751 0 : goto out;
752 : }
753 0 : for (i = 0; i < req.portal_list.num_portals; i++) {
754 0 : portal = iscsi_portal_create(req.portal_list.portals[i].host,
755 0 : req.portal_list.portals[i].port);
756 0 : if (portal == NULL) {
757 0 : SPDK_ERRLOG("portal_create failed\n");
758 0 : goto out;
759 : }
760 0 : iscsi_portal_grp_add_portal(pg, portal);
761 : }
762 :
763 0 : rc = iscsi_portal_grp_open(pg, req.wait);
764 0 : if (rc != 0) {
765 0 : SPDK_ERRLOG("portal_grp_open failed\n");
766 0 : goto out;
767 : }
768 :
769 0 : rc = iscsi_portal_grp_register(pg);
770 0 : if (rc != 0) {
771 0 : SPDK_ERRLOG("portal_grp_register failed\n");
772 : }
773 :
774 0 : out:
775 0 : if (rc == 0) {
776 0 : spdk_jsonrpc_send_bool_response(request, true);
777 : } else {
778 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
779 :
780 0 : if (pg != NULL) {
781 0 : iscsi_portal_grp_release(pg);
782 : }
783 : }
784 0 : free_rpc_portal_group(&req);
785 0 : }
786 0 : SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME)
787 :
788 : struct rpc_iscsi_change_portal_group {
789 : int32_t tag;
790 : };
791 :
792 : static const struct spdk_json_object_decoder rpc_iscsi_change_portal_group_decoders[] = {
793 : {"tag", offsetof(struct rpc_iscsi_change_portal_group, tag), spdk_json_decode_int32},
794 : };
795 :
796 : typedef int (*iscsi_change_portal_grp_fn)(int pg_tag);
797 :
798 : static void
799 0 : _rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request *request,
800 : const struct spdk_json_val *params,
801 : iscsi_change_portal_grp_fn fn)
802 : {
803 0 : struct rpc_iscsi_change_portal_group req = {};
804 : int rc;
805 :
806 0 : if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders,
807 : SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders),
808 : &req)) {
809 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
810 0 : goto invalid;
811 : }
812 :
813 0 : rc = fn(req.tag);
814 0 : if (rc != 0) {
815 0 : goto invalid;
816 : }
817 :
818 0 : spdk_jsonrpc_send_bool_response(request, true);
819 0 : return;
820 :
821 0 : invalid:
822 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
823 : }
824 :
825 : static int
826 0 : _rpc_iscsi_delete_portal_group(int pg_tag)
827 : {
828 : struct spdk_iscsi_portal_grp *pg;
829 :
830 0 : pg = iscsi_portal_grp_unregister(pg_tag);
831 0 : if (!pg) {
832 0 : return -ENODEV;
833 : }
834 :
835 0 : iscsi_tgt_node_delete_map(pg, NULL);
836 0 : iscsi_portal_grp_release(pg);
837 0 : return 0;
838 : }
839 :
840 : static void
841 0 : rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request,
842 : const struct spdk_json_val *params)
843 : {
844 0 : _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group);
845 0 : }
846 0 : SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME)
847 :
848 : static int
849 0 : _rpc_iscsi_start_portal_group(int pg_tag)
850 : {
851 : struct spdk_iscsi_portal_grp *pg;
852 :
853 0 : pg = iscsi_portal_grp_find_by_tag(pg_tag);
854 0 : if (!pg) {
855 0 : return -ENODEV;
856 : }
857 :
858 0 : iscsi_portal_grp_resume(pg);
859 0 : return 0;
860 : }
861 :
862 : static void
863 0 : rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request,
864 : const struct spdk_json_val *params)
865 : {
866 0 : _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group);
867 0 : }
868 0 : SPDK_RPC_REGISTER("iscsi_start_portal_group", rpc_iscsi_start_portal_group, SPDK_RPC_RUNTIME)
869 :
870 : struct rpc_portal_group_auth {
871 : int32_t tag;
872 : bool disable_chap;
873 : bool require_chap;
874 : bool mutual_chap;
875 : int32_t chap_group;
876 : };
877 :
878 : static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = {
879 : {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32},
880 : {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true},
881 : {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true},
882 : {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true},
883 : {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true},
884 : };
885 :
886 : static void
887 0 : rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request,
888 : const struct spdk_json_val *params)
889 : {
890 0 : struct rpc_portal_group_auth req = {};
891 : struct spdk_iscsi_portal_grp *pg;
892 : int rc;
893 :
894 0 : if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders,
895 : SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) {
896 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
897 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
898 : "Invalid parameters");
899 0 : return;
900 : }
901 :
902 0 : pthread_mutex_lock(&g_iscsi.mutex);
903 :
904 0 : pg = iscsi_portal_grp_find_by_tag(req.tag);
905 0 : if (pg == NULL) {
906 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
907 : "Could not find portal group %d", req.tag);
908 0 : goto exit;
909 : }
910 :
911 0 : rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap,
912 0 : req.mutual_chap, req.chap_group);
913 0 : if (rc < 0) {
914 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
915 : "Invalid combination of auth params");
916 0 : goto exit;
917 : }
918 :
919 0 : pthread_mutex_unlock(&g_iscsi.mutex);
920 :
921 0 : spdk_jsonrpc_send_bool_response(request, true);
922 0 : return;
923 :
924 0 : exit:
925 0 : pthread_mutex_unlock(&g_iscsi.mutex);
926 : }
927 0 : SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth,
928 : SPDK_RPC_RUNTIME)
929 :
930 : struct rpc_iscsi_get_connections_ctx {
931 : struct spdk_jsonrpc_request *request;
932 : struct spdk_json_write_ctx *w;
933 : };
934 :
935 : static void
936 0 : _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status)
937 : {
938 0 : struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
939 :
940 0 : spdk_json_write_array_end(ctx->w);
941 0 : spdk_jsonrpc_end_result(ctx->request, ctx->w);
942 :
943 0 : free(ctx);
944 0 : }
945 :
946 : static void
947 0 : _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i)
948 : {
949 0 : struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
950 0 : struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
951 0 : struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
952 : struct spdk_iscsi_conn *conn;
953 :
954 0 : STAILQ_FOREACH(conn, &pg->connections, pg_link) {
955 0 : iscsi_conn_info_json(ctx->w, conn);
956 : }
957 :
958 0 : spdk_for_each_channel_continue(i, 0);
959 0 : }
960 :
961 : static void
962 0 : rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request,
963 : const struct spdk_json_val *params)
964 : {
965 : struct rpc_iscsi_get_connections_ctx *ctx;
966 :
967 0 : if (params != NULL) {
968 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
969 : "iscsi_get_connections requires no parameters");
970 0 : return;
971 : }
972 :
973 0 : ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx));
974 0 : if (ctx == NULL) {
975 0 : SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n");
976 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
977 0 : return;
978 : }
979 :
980 0 : ctx->request = request;
981 0 : ctx->w = spdk_jsonrpc_begin_result(request);
982 :
983 0 : spdk_json_write_array_begin(ctx->w);
984 :
985 0 : spdk_for_each_channel(&g_iscsi,
986 : _rpc_iscsi_get_connections,
987 : ctx,
988 : _rpc_iscsi_get_connections_done);
989 : }
990 0 : SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME)
991 :
992 : struct rpc_target_lun {
993 : char *name;
994 : char *bdev_name;
995 : int32_t lun_id;
996 : };
997 :
998 : struct rpc_iscsi_get_stats_ctx {
999 : struct spdk_jsonrpc_request *request;
1000 : uint32_t invalid;
1001 : uint32_t running;
1002 : uint32_t exiting;
1003 : uint32_t exited;
1004 : };
1005 :
1006 : static void
1007 0 : _rpc_iscsi_get_stats_done(struct spdk_io_channel_iter *i, int status)
1008 : {
1009 : struct spdk_json_write_ctx *w;
1010 0 : struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1011 :
1012 0 : w = spdk_jsonrpc_begin_result(ctx->request);
1013 0 : spdk_json_write_object_begin(w);
1014 :
1015 0 : spdk_json_write_named_uint32(w, "invalid", ctx->invalid);
1016 0 : spdk_json_write_named_uint32(w, "running", ctx->running);
1017 0 : spdk_json_write_named_uint32(w, "exiting", ctx->exiting);
1018 0 : spdk_json_write_named_uint32(w, "exited", ctx->exited);
1019 :
1020 0 : spdk_json_write_object_end(w);
1021 0 : spdk_jsonrpc_end_result(ctx->request, w);
1022 :
1023 0 : free(ctx);
1024 0 : }
1025 :
1026 : static void
1027 0 : _iscsi_get_stats(struct rpc_iscsi_get_stats_ctx *ctx,
1028 : struct spdk_iscsi_conn *conn)
1029 : {
1030 0 : switch (conn->state) {
1031 0 : case ISCSI_CONN_STATE_INVALID:
1032 0 : ctx->invalid += 1;
1033 0 : break;
1034 0 : case ISCSI_CONN_STATE_RUNNING:
1035 0 : ctx->running += 1;
1036 0 : break;
1037 0 : case ISCSI_CONN_STATE_EXITING:
1038 0 : ctx->exiting += 1;
1039 0 : break;
1040 0 : case ISCSI_CONN_STATE_EXITED:
1041 0 : ctx->exited += 1;
1042 0 : break;
1043 : }
1044 0 : }
1045 :
1046 : static void
1047 0 : _rpc_iscsi_get_stats(struct spdk_io_channel_iter *i)
1048 : {
1049 0 : struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1050 0 : struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
1051 0 : struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
1052 : struct spdk_iscsi_conn *conn;
1053 :
1054 0 : STAILQ_FOREACH(conn, &pg->connections, pg_link) {
1055 0 : _iscsi_get_stats(ctx, conn);
1056 : }
1057 :
1058 0 : spdk_for_each_channel_continue(i, 0);
1059 0 : }
1060 :
1061 :
1062 :
1063 : static void
1064 0 : rpc_iscsi_get_stats(struct spdk_jsonrpc_request *request,
1065 : const struct spdk_json_val *params)
1066 : {
1067 : struct rpc_iscsi_get_stats_ctx *ctx;
1068 :
1069 0 : if (params != NULL) {
1070 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1071 : "iscsi_get_stats requires no parameters");
1072 0 : return;
1073 : }
1074 :
1075 0 : ctx = calloc(1, sizeof(struct rpc_iscsi_get_stats_ctx));
1076 0 : if (ctx == NULL) {
1077 0 : SPDK_ERRLOG("Failed to allocate rpc_iscsi_get_stats_ctx struct\n");
1078 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1079 0 : return;
1080 : }
1081 :
1082 0 : ctx->request = request;
1083 :
1084 0 : spdk_for_each_channel(&g_iscsi,
1085 : _rpc_iscsi_get_stats,
1086 : ctx,
1087 : _rpc_iscsi_get_stats_done);
1088 :
1089 : }
1090 0 : SPDK_RPC_REGISTER("iscsi_get_stats", rpc_iscsi_get_stats, SPDK_RPC_RUNTIME)
1091 :
1092 : static void
1093 0 : free_rpc_target_lun(struct rpc_target_lun *req)
1094 : {
1095 0 : free(req->name);
1096 0 : free(req->bdev_name);
1097 0 : }
1098 :
1099 : static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = {
1100 : {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string},
1101 : {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string},
1102 : {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true},
1103 : };
1104 :
1105 : static void
1106 0 : rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request,
1107 : const struct spdk_json_val *params)
1108 : {
1109 0 : struct rpc_target_lun req = {};
1110 : struct spdk_iscsi_tgt_node *target;
1111 : int rc;
1112 :
1113 0 : req.lun_id = -1;
1114 :
1115 0 : if (spdk_json_decode_object(params, rpc_target_lun_decoders,
1116 : SPDK_COUNTOF(rpc_target_lun_decoders), &req)) {
1117 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1118 0 : goto invalid;
1119 : }
1120 :
1121 0 : target = iscsi_find_tgt_node(req.name);
1122 0 : if (target == NULL) {
1123 0 : SPDK_ERRLOG("target is not found\n");
1124 0 : goto invalid;
1125 : }
1126 :
1127 0 : rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id);
1128 0 : if (rc < 0) {
1129 0 : SPDK_ERRLOG("add lun failed\n");
1130 0 : goto invalid;
1131 : }
1132 :
1133 0 : free_rpc_target_lun(&req);
1134 :
1135 0 : spdk_jsonrpc_send_bool_response(request, true);
1136 0 : return;
1137 :
1138 0 : invalid:
1139 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1140 : "Invalid parameters");
1141 0 : free_rpc_target_lun(&req);
1142 : }
1143 0 : SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME)
1144 :
1145 : struct rpc_target_auth {
1146 : char *name;
1147 : bool disable_chap;
1148 : bool require_chap;
1149 : bool mutual_chap;
1150 : int32_t chap_group;
1151 : };
1152 :
1153 : static void
1154 0 : free_rpc_target_auth(struct rpc_target_auth *req)
1155 : {
1156 0 : free(req->name);
1157 0 : }
1158 :
1159 : static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = {
1160 : {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string},
1161 : {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true},
1162 : {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true},
1163 : {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true},
1164 : {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true},
1165 : };
1166 :
1167 : static void
1168 0 : rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request,
1169 : const struct spdk_json_val *params)
1170 : {
1171 0 : struct rpc_target_auth req = {};
1172 : struct spdk_iscsi_tgt_node *target;
1173 : int rc;
1174 :
1175 0 : if (spdk_json_decode_object(params, rpc_target_auth_decoders,
1176 : SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
1177 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1178 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1179 : "Invalid parameters");
1180 0 : goto exit;
1181 : }
1182 :
1183 0 : target = iscsi_find_tgt_node(req.name);
1184 0 : if (target == NULL) {
1185 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1186 : "Could not find target %s", req.name);
1187 0 : goto exit;
1188 : }
1189 :
1190 0 : rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
1191 0 : req.mutual_chap, req.chap_group);
1192 0 : if (rc < 0) {
1193 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1194 : "Invalid combination of auth params");
1195 0 : goto exit;
1196 : }
1197 :
1198 0 : free_rpc_target_auth(&req);
1199 :
1200 0 : spdk_jsonrpc_send_bool_response(request, true);
1201 0 : return;
1202 :
1203 0 : exit:
1204 0 : free_rpc_target_auth(&req);
1205 : }
1206 0 : SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth,
1207 : SPDK_RPC_RUNTIME)
1208 :
1209 : struct rpc_target_redirect {
1210 : char *name;
1211 : int32_t pg_tag;
1212 : char *redirect_host;
1213 : char *redirect_port;
1214 : };
1215 :
1216 : static void
1217 0 : free_rpc_target_redirect(struct rpc_target_redirect *req)
1218 : {
1219 0 : free(req->name);
1220 0 : free(req->redirect_host);
1221 0 : free(req->redirect_port);
1222 0 : }
1223 :
1224 : static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = {
1225 : {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string},
1226 : {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32},
1227 : {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true},
1228 : {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true},
1229 : };
1230 :
1231 : static void
1232 0 : rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request,
1233 : const struct spdk_json_val *params)
1234 : {
1235 0 : struct rpc_target_redirect req = {};
1236 : struct spdk_iscsi_tgt_node *target;
1237 : int rc;
1238 :
1239 0 : if (spdk_json_decode_object(params, rpc_target_redirect_decoders,
1240 : SPDK_COUNTOF(rpc_target_redirect_decoders),
1241 : &req)) {
1242 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1243 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1244 : "Invalid parameters");
1245 0 : free_rpc_target_redirect(&req);
1246 0 : return;
1247 : }
1248 :
1249 0 : target = iscsi_find_tgt_node(req.name);
1250 0 : if (target == NULL) {
1251 0 : SPDK_ERRLOG("target %s is not found\n", req.name);
1252 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1253 : "Target %s is not found", req.name);
1254 0 : free_rpc_target_redirect(&req);
1255 0 : return;
1256 : }
1257 :
1258 0 : rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port);
1259 0 : if (rc != 0) {
1260 0 : SPDK_ERRLOG("failed to redirect target %s\n", req.name);
1261 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1262 : "Failed to redirect target %s, (%d): %s",
1263 : req.name, rc, spdk_strerror(-rc));
1264 0 : free_rpc_target_redirect(&req);
1265 0 : return;
1266 : }
1267 :
1268 0 : free_rpc_target_redirect(&req);
1269 :
1270 0 : spdk_jsonrpc_send_bool_response(request, true);
1271 : }
1272 0 : SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect,
1273 : SPDK_RPC_RUNTIME)
1274 :
1275 : struct rpc_target_logout {
1276 : char *name;
1277 : int32_t pg_tag;
1278 : };
1279 :
1280 : static void
1281 0 : free_rpc_target_logout(struct rpc_target_logout *req)
1282 : {
1283 0 : free(req->name);
1284 0 : }
1285 :
1286 : static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = {
1287 : {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string},
1288 : {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true},
1289 : };
1290 :
1291 : static void
1292 0 : rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request,
1293 : const struct spdk_json_val *params)
1294 : {
1295 0 : struct rpc_target_logout req = {};
1296 : struct spdk_iscsi_tgt_node *target;
1297 :
1298 : /* If pg_tag is omitted, request all connections to the specified target
1299 : * to logout.
1300 : */
1301 0 : req.pg_tag = -1;
1302 :
1303 0 : if (spdk_json_decode_object(params, rpc_target_logout_decoders,
1304 : SPDK_COUNTOF(rpc_target_logout_decoders),
1305 : &req)) {
1306 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1307 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1308 : "Invalid parameters");
1309 0 : free_rpc_target_logout(&req);
1310 0 : return;
1311 : }
1312 :
1313 0 : target = iscsi_find_tgt_node(req.name);
1314 0 : if (target == NULL) {
1315 0 : SPDK_ERRLOG("target %s is not found\n", req.name);
1316 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1317 : "Target %s is not found", req.name);
1318 0 : free_rpc_target_logout(&req);
1319 0 : return;
1320 : }
1321 :
1322 0 : iscsi_conns_request_logout(target, req.pg_tag);
1323 :
1324 0 : free_rpc_target_logout(&req);
1325 :
1326 0 : spdk_jsonrpc_send_bool_response(request, true);
1327 : }
1328 0 : SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout,
1329 : SPDK_RPC_RUNTIME)
1330 :
1331 : static void
1332 0 : rpc_iscsi_get_options(struct spdk_jsonrpc_request *request,
1333 : const struct spdk_json_val *params)
1334 : {
1335 : struct spdk_json_write_ctx *w;
1336 :
1337 0 : if (params != NULL) {
1338 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1339 : "iscsi_get_options requires no parameters");
1340 0 : return;
1341 : }
1342 :
1343 0 : w = spdk_jsonrpc_begin_result(request);
1344 0 : iscsi_opts_info_json(w);
1345 :
1346 0 : spdk_jsonrpc_end_result(request, w);
1347 : }
1348 0 : SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME)
1349 :
1350 : struct rpc_discovery_auth {
1351 : bool disable_chap;
1352 : bool require_chap;
1353 : bool mutual_chap;
1354 : int32_t chap_group;
1355 : };
1356 :
1357 : static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = {
1358 : {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true},
1359 : {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true},
1360 : {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true},
1361 : {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true},
1362 : };
1363 :
1364 : static void
1365 0 : rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request,
1366 : const struct spdk_json_val *params)
1367 : {
1368 0 : struct rpc_discovery_auth req = {};
1369 : int rc;
1370 :
1371 0 : if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
1372 : SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
1373 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1374 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1375 : "Invalid parameters");
1376 0 : return;
1377 : }
1378 :
1379 0 : rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
1380 0 : req.mutual_chap, req.chap_group);
1381 0 : if (rc < 0) {
1382 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1383 : "Invalid combination of CHAP params");
1384 0 : return;
1385 : }
1386 :
1387 0 : spdk_jsonrpc_send_bool_response(request, true);
1388 : }
1389 0 : SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME)
1390 :
1391 : #define MAX_AUTH_SECRETS 64
1392 :
1393 : struct rpc_auth_secret {
1394 : char *user;
1395 : char *secret;
1396 : char *muser;
1397 : char *msecret;
1398 : };
1399 :
1400 : static void
1401 0 : free_rpc_auth_secret(struct rpc_auth_secret *_secret)
1402 : {
1403 0 : free(_secret->user);
1404 0 : free(_secret->secret);
1405 0 : free(_secret->muser);
1406 0 : free(_secret->msecret);
1407 0 : }
1408 :
1409 : static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = {
1410 : {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string},
1411 : {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string},
1412 : {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true},
1413 : {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true},
1414 : };
1415 :
1416 : static int
1417 0 : decode_rpc_auth_secret(const struct spdk_json_val *val, void *out)
1418 : {
1419 0 : struct rpc_auth_secret *_secret = out;
1420 :
1421 0 : return spdk_json_decode_object(val, rpc_auth_secret_decoders,
1422 : SPDK_COUNTOF(rpc_auth_secret_decoders), _secret);
1423 : }
1424 :
1425 : struct rpc_auth_secrets {
1426 : size_t num_secret;
1427 : struct rpc_auth_secret secrets[MAX_AUTH_SECRETS];
1428 : };
1429 :
1430 : static void
1431 0 : free_rpc_auth_secrets(struct rpc_auth_secrets *secrets)
1432 : {
1433 : size_t i;
1434 :
1435 0 : for (i = 0; i < secrets->num_secret; i++) {
1436 0 : free_rpc_auth_secret(&secrets->secrets[i]);
1437 : }
1438 0 : }
1439 :
1440 : static int
1441 0 : decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out)
1442 : {
1443 0 : struct rpc_auth_secrets *secrets = out;
1444 :
1445 0 : return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets,
1446 : MAX_AUTH_SECRETS, &secrets->num_secret,
1447 : sizeof(struct rpc_auth_secret));
1448 : }
1449 :
1450 : struct rpc_auth_group {
1451 : int32_t tag;
1452 : struct rpc_auth_secrets secrets;
1453 : };
1454 :
1455 : static void
1456 0 : free_rpc_auth_group(struct rpc_auth_group *group)
1457 : {
1458 0 : free_rpc_auth_secrets(&group->secrets);
1459 0 : }
1460 :
1461 : static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = {
1462 : {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32},
1463 : {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true},
1464 : };
1465 :
1466 : static void
1467 0 : rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request,
1468 : const struct spdk_json_val *params)
1469 : {
1470 0 : struct rpc_auth_group req = {};
1471 : struct rpc_auth_secret *_secret;
1472 0 : struct spdk_iscsi_auth_group *group = NULL;
1473 : int rc;
1474 : size_t i;
1475 :
1476 0 : if (spdk_json_decode_object(params, rpc_auth_group_decoders,
1477 : SPDK_COUNTOF(rpc_auth_group_decoders), &req)) {
1478 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1479 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1480 : "Invalid parameters");
1481 0 : free_rpc_auth_group(&req);
1482 0 : return;
1483 : }
1484 :
1485 0 : pthread_mutex_lock(&g_iscsi.mutex);
1486 :
1487 0 : rc = iscsi_add_auth_group(req.tag, &group);
1488 0 : if (rc != 0) {
1489 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1490 :
1491 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1492 : "Could not add auth group (%d), %s",
1493 : req.tag, spdk_strerror(-rc));
1494 0 : free_rpc_auth_group(&req);
1495 0 : return;
1496 : }
1497 :
1498 0 : for (i = 0; i < req.secrets.num_secret; i++) {
1499 0 : _secret = &req.secrets.secrets[i];
1500 0 : rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret,
1501 0 : _secret->muser, _secret->msecret);
1502 0 : if (rc != 0) {
1503 0 : iscsi_delete_auth_group(group);
1504 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1505 :
1506 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1507 : "Could not add secret to auth group (%d), %s",
1508 : req.tag, spdk_strerror(-rc));
1509 0 : free_rpc_auth_group(&req);
1510 0 : return;
1511 : }
1512 : }
1513 :
1514 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1515 :
1516 0 : free_rpc_auth_group(&req);
1517 :
1518 0 : spdk_jsonrpc_send_bool_response(request, true);
1519 : }
1520 0 : SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME)
1521 :
1522 : struct rpc_delete_auth_group {
1523 : int32_t tag;
1524 : };
1525 :
1526 : static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = {
1527 : {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32},
1528 : };
1529 :
1530 : static void
1531 0 : rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request,
1532 : const struct spdk_json_val *params)
1533 : {
1534 0 : struct rpc_delete_auth_group req = {};
1535 : struct spdk_iscsi_auth_group *group;
1536 :
1537 0 : if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders,
1538 : SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) {
1539 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1540 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1541 : "Invalid parameters");
1542 0 : return;
1543 : }
1544 :
1545 0 : pthread_mutex_lock(&g_iscsi.mutex);
1546 :
1547 0 : group = iscsi_find_auth_group_by_tag(req.tag);
1548 0 : if (group == NULL) {
1549 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1550 :
1551 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1552 : "Could not find auth group (%d)", req.tag);
1553 0 : return;
1554 : }
1555 :
1556 0 : iscsi_delete_auth_group(group);
1557 :
1558 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1559 :
1560 0 : spdk_jsonrpc_send_bool_response(request, true);
1561 : }
1562 0 : SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME)
1563 :
1564 : struct rpc_add_auth_secret {
1565 : int32_t tag;
1566 : char *user;
1567 : char *secret;
1568 : char *muser;
1569 : char *msecret;
1570 : };
1571 :
1572 : static void
1573 0 : free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret)
1574 : {
1575 0 : free(_secret->user);
1576 0 : free(_secret->secret);
1577 0 : free(_secret->muser);
1578 0 : free(_secret->msecret);
1579 0 : }
1580 :
1581 : static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = {
1582 : {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32},
1583 : {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string},
1584 : {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string},
1585 : {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true},
1586 : {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true},
1587 : };
1588 :
1589 : static void
1590 0 : rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request,
1591 : const struct spdk_json_val *params)
1592 : {
1593 0 : struct rpc_add_auth_secret req = {};
1594 : struct spdk_iscsi_auth_group *group;
1595 : int rc;
1596 :
1597 0 : if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders,
1598 : SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) {
1599 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1600 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1601 : "Invalid parameters");
1602 0 : free_rpc_add_auth_secret(&req);
1603 0 : return;
1604 : }
1605 :
1606 0 : pthread_mutex_lock(&g_iscsi.mutex);
1607 :
1608 0 : group = iscsi_find_auth_group_by_tag(req.tag);
1609 0 : if (group == NULL) {
1610 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1611 :
1612 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1613 : "Could not find auth group (%d)", req.tag);
1614 0 : free_rpc_add_auth_secret(&req);
1615 0 : return;
1616 : }
1617 :
1618 0 : rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret);
1619 0 : if (rc != 0) {
1620 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1621 :
1622 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1623 : "Could not add secret to auth group (%d), %s",
1624 : req.tag, spdk_strerror(-rc));
1625 0 : free_rpc_add_auth_secret(&req);
1626 0 : return;
1627 : }
1628 :
1629 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1630 :
1631 0 : free_rpc_add_auth_secret(&req);
1632 :
1633 0 : spdk_jsonrpc_send_bool_response(request, true);
1634 : }
1635 0 : SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret,
1636 : SPDK_RPC_RUNTIME)
1637 :
1638 :
1639 : struct rpc_remove_auth_secret {
1640 : int32_t tag;
1641 : char *user;
1642 : };
1643 :
1644 : static void
1645 0 : free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret)
1646 : {
1647 0 : free(_secret->user);
1648 0 : }
1649 :
1650 : static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = {
1651 : {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32},
1652 : {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string},
1653 : };
1654 :
1655 : static void
1656 0 : rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request,
1657 : const struct spdk_json_val *params)
1658 : {
1659 0 : struct rpc_remove_auth_secret req = {};
1660 : struct spdk_iscsi_auth_group *group;
1661 : int rc;
1662 :
1663 0 : if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders,
1664 : SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) {
1665 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1666 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1667 : "Invalid parameters");
1668 0 : free_rpc_remove_auth_secret(&req);
1669 0 : return;
1670 : }
1671 :
1672 0 : pthread_mutex_lock(&g_iscsi.mutex);
1673 :
1674 0 : group = iscsi_find_auth_group_by_tag(req.tag);
1675 0 : if (group == NULL) {
1676 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1677 :
1678 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1679 : "Could not find auth group (%d)", req.tag);
1680 0 : free_rpc_remove_auth_secret(&req);
1681 0 : return;
1682 : }
1683 :
1684 0 : rc = iscsi_auth_group_delete_secret(group, req.user);
1685 0 : if (rc != 0) {
1686 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1687 :
1688 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1689 : "Could not delete secret from CHAP group (%d), %s",
1690 : req.tag, spdk_strerror(-rc));
1691 0 : free_rpc_remove_auth_secret(&req);
1692 0 : return;
1693 : }
1694 :
1695 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1696 :
1697 0 : free_rpc_remove_auth_secret(&req);
1698 :
1699 0 : spdk_jsonrpc_send_bool_response(request, true);
1700 : }
1701 0 : SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret",
1702 : rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME)
1703 :
1704 : static void
1705 0 : rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request,
1706 : const struct spdk_json_val *params)
1707 : {
1708 : struct spdk_json_write_ctx *w;
1709 :
1710 0 : if (params != NULL) {
1711 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1712 : "iscsi_get_auth_groups requires no parameters");
1713 0 : return;
1714 : }
1715 :
1716 0 : w = spdk_jsonrpc_begin_result(request);
1717 0 : spdk_json_write_array_begin(w);
1718 0 : iscsi_auth_groups_info_json(w);
1719 0 : spdk_json_write_array_end(w);
1720 :
1721 0 : spdk_jsonrpc_end_result(request, w);
1722 : }
1723 0 : SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME)
1724 :
1725 : static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = {
1726 : {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true},
1727 : {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true},
1728 : {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true},
1729 : {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true},
1730 : {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true},
1731 : {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true},
1732 : {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true},
1733 : {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true},
1734 : {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true},
1735 : {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true},
1736 : {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true},
1737 : {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true},
1738 : {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true},
1739 : {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true},
1740 : {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true},
1741 : {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true},
1742 : {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true},
1743 : {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true},
1744 : {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true},
1745 : {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true},
1746 : {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true},
1747 : {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true},
1748 : {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true},
1749 : {"pdu_pool_size", offsetof(struct spdk_iscsi_opts, pdu_pool_size), spdk_json_decode_uint32, true},
1750 : {"immediate_data_pool_size", offsetof(struct spdk_iscsi_opts, immediate_data_pool_size), spdk_json_decode_uint32, true},
1751 : {"data_out_pool_size", offsetof(struct spdk_iscsi_opts, data_out_pool_size), spdk_json_decode_uint32, true},
1752 : };
1753 :
1754 : static void
1755 0 : rpc_iscsi_set_options(struct spdk_jsonrpc_request *request,
1756 : const struct spdk_json_val *params)
1757 : {
1758 : struct spdk_iscsi_opts *opts;
1759 :
1760 0 : if (g_spdk_iscsi_opts != NULL) {
1761 0 : SPDK_ERRLOG("this RPC must not be called more than once.\n");
1762 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1763 : "Must not call more than once");
1764 0 : return;
1765 : }
1766 :
1767 0 : opts = iscsi_opts_alloc();
1768 0 : if (opts == NULL) {
1769 0 : SPDK_ERRLOG("iscsi_opts_alloc() failed.\n");
1770 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1771 : "Out of memory");
1772 0 : return;
1773 : }
1774 :
1775 0 : if (params != NULL) {
1776 0 : if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders,
1777 : SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) {
1778 0 : SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1779 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1780 : "Invalid parameters");
1781 0 : iscsi_opts_free(opts);
1782 0 : return;
1783 : }
1784 : }
1785 :
1786 0 : g_spdk_iscsi_opts = iscsi_opts_copy(opts);
1787 0 : iscsi_opts_free(opts);
1788 :
1789 0 : if (g_spdk_iscsi_opts == NULL) {
1790 0 : SPDK_ERRLOG("iscsi_opts_copy() failed\n");
1791 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1792 : "Out of memory");
1793 0 : return;
1794 : }
1795 :
1796 0 : spdk_jsonrpc_send_bool_response(request, true);
1797 : }
1798 0 : SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP)
1799 :
1800 : struct rpc_iscsi_enable_histogram_request {
1801 : char *name;
1802 : bool enable;
1803 : };
1804 :
1805 : static const struct spdk_json_object_decoder rpc_iscsi_enable_histogram_request_decoders[] = {
1806 : {"name", offsetof(struct rpc_iscsi_enable_histogram_request, name), spdk_json_decode_string},
1807 : {"enable", offsetof(struct rpc_iscsi_enable_histogram_request, enable), spdk_json_decode_bool},
1808 : };
1809 :
1810 : struct iscsi_enable_histogram_ctx {
1811 : struct spdk_jsonrpc_request *request;
1812 : struct spdk_iscsi_tgt_node *target;
1813 : bool enable;
1814 : int status;
1815 : struct spdk_thread *orig_thread;
1816 : };
1817 :
1818 : static void
1819 0 : rpc_iscsi_enable_histogram_done(void *_ctx)
1820 : {
1821 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1822 :
1823 0 : if (ctx->status == 0) {
1824 0 : spdk_jsonrpc_send_bool_response(ctx->request, true);
1825 : } else {
1826 0 : spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1827 0 : spdk_strerror(-ctx->status));
1828 : }
1829 :
1830 0 : free(ctx);
1831 0 : }
1832 :
1833 : static void
1834 0 : _iscsi_enable_histogram(void *_ctx)
1835 : {
1836 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1837 :
1838 0 : ctx->status = iscsi_tgt_node_enable_histogram(ctx->target, ctx->enable);
1839 0 : }
1840 :
1841 : static void
1842 0 : _rpc_iscsi_enable_histogram(void *_ctx)
1843 : {
1844 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1845 :
1846 0 : pthread_mutex_lock(&ctx->target->mutex);
1847 0 : _iscsi_enable_histogram(ctx);
1848 0 : ctx->target->num_active_conns--;
1849 0 : pthread_mutex_unlock(&ctx->target->mutex);
1850 :
1851 0 : spdk_thread_send_msg(ctx->orig_thread, rpc_iscsi_enable_histogram_done, ctx);
1852 0 : }
1853 :
1854 : static void
1855 0 : rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request,
1856 : const struct spdk_json_val *params)
1857 : {
1858 0 : struct rpc_iscsi_enable_histogram_request req = {NULL};
1859 : struct iscsi_enable_histogram_ctx *ctx;
1860 : struct spdk_iscsi_tgt_node *target;
1861 : struct spdk_thread *thread;
1862 : spdk_msg_fn fn;
1863 :
1864 0 : if (spdk_json_decode_object(params, rpc_iscsi_enable_histogram_request_decoders,
1865 : SPDK_COUNTOF(rpc_iscsi_enable_histogram_request_decoders),
1866 : &req)) {
1867 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1868 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1869 : "spdk_json_decode_object failed");
1870 0 : return;
1871 : }
1872 :
1873 0 : ctx = calloc(1, sizeof(*ctx));
1874 0 : if (ctx == NULL) {
1875 0 : SPDK_ERRLOG("Memory allocation failed\n");
1876 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1877 : "Memory allocation failed");
1878 0 : return;
1879 : }
1880 :
1881 0 : target = iscsi_find_tgt_node(req.name);
1882 :
1883 0 : free(req.name);
1884 :
1885 0 : if (target == NULL) {
1886 0 : SPDK_ERRLOG("target is not found\n");
1887 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1888 : "Invalid parameters");
1889 0 : free(ctx);
1890 0 : return;
1891 : }
1892 :
1893 0 : ctx->request = request;
1894 0 : ctx->target = target;
1895 0 : ctx->enable = req.enable;
1896 0 : ctx->orig_thread = spdk_get_thread();
1897 :
1898 0 : pthread_mutex_lock(&ctx->target->mutex);
1899 0 : if (target->pg == NULL) {
1900 0 : _iscsi_enable_histogram(ctx);
1901 0 : thread = ctx->orig_thread;
1902 0 : fn = rpc_iscsi_enable_histogram_done;
1903 : } else {
1904 : /**
1905 : * We get spdk thread of the target by using target->pg.
1906 : * If target->num_active_conns >= 1, target->pg will not change.
1907 : * So, It is safer to increase and decrease target->num_active_conns
1908 : * while updating target->histogram.
1909 : */
1910 0 : target->num_active_conns++;
1911 0 : thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(target->pg));
1912 0 : fn = _rpc_iscsi_enable_histogram;
1913 : }
1914 0 : pthread_mutex_unlock(&ctx->target->mutex);
1915 :
1916 0 : spdk_thread_send_msg(thread, fn, ctx);
1917 : }
1918 :
1919 0 : SPDK_RPC_REGISTER("iscsi_enable_histogram", rpc_iscsi_enable_histogram, SPDK_RPC_RUNTIME)
1920 :
1921 : struct rpc_iscsi_get_histogram_request {
1922 : char *name;
1923 : };
1924 :
1925 : static const struct spdk_json_object_decoder rpc_iscsi_get_histogram_request_decoders[] = {
1926 : {"name", offsetof(struct rpc_iscsi_get_histogram_request, name), spdk_json_decode_string}
1927 : };
1928 :
1929 : static void
1930 0 : free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request *r)
1931 : {
1932 0 : free(r->name);
1933 0 : }
1934 :
1935 : static void
1936 0 : rpc_iscsi_get_histogram(struct spdk_jsonrpc_request *request,
1937 : const struct spdk_json_val *params)
1938 : {
1939 0 : struct rpc_iscsi_get_histogram_request req = {NULL};
1940 : struct spdk_iscsi_tgt_node *target;
1941 : struct spdk_json_write_ctx *w;
1942 : char *encoded_histogram;
1943 : size_t src_len, dst_len;
1944 : int rc;
1945 :
1946 0 : if (spdk_json_decode_object(params, rpc_iscsi_get_histogram_request_decoders,
1947 : SPDK_COUNTOF(rpc_iscsi_get_histogram_request_decoders),
1948 : &req)) {
1949 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1950 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1951 : "spdk_json_decode_object failed");
1952 0 : goto free_req;
1953 : }
1954 :
1955 0 : target = iscsi_find_tgt_node(req.name);
1956 0 : if (target == NULL) {
1957 0 : SPDK_ERRLOG("target is not found\n");
1958 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1959 : "target not found");
1960 0 : goto free_req;
1961 : }
1962 :
1963 0 : if (!target->histogram) {
1964 0 : SPDK_ERRLOG("target's histogram function is not enabled\n");
1965 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1966 : "target's histogram function is not enabled");
1967 0 : goto free_req;
1968 : }
1969 :
1970 0 : src_len = SPDK_HISTOGRAM_NUM_BUCKETS(target->histogram) * sizeof(uint64_t);
1971 0 : dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
1972 0 : encoded_histogram = malloc(dst_len);
1973 0 : if (encoded_histogram == NULL) {
1974 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1975 : spdk_strerror(ENOMEM));
1976 0 : goto free_req;
1977 : }
1978 :
1979 0 : rc = spdk_base64_encode(encoded_histogram, target->histogram->bucket, src_len);
1980 0 : if (rc != 0) {
1981 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1982 : spdk_strerror(-rc));
1983 0 : goto free_encoded_histogram;
1984 : }
1985 :
1986 0 : w = spdk_jsonrpc_begin_result(request);
1987 :
1988 0 : spdk_json_write_object_begin(w);
1989 0 : spdk_json_write_named_string(w, "histogram", encoded_histogram);
1990 0 : spdk_json_write_named_int64(w, "bucket_shift", target->histogram->bucket_shift);
1991 0 : spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
1992 :
1993 0 : spdk_json_write_object_end(w);
1994 0 : spdk_jsonrpc_end_result(request, w);
1995 :
1996 0 : free_encoded_histogram:
1997 0 : free(encoded_histogram);
1998 0 : free_req:
1999 0 : free_rpc_iscsi_get_histogram_request(&req);
2000 0 : }
2001 :
2002 0 : SPDK_RPC_REGISTER("iscsi_get_histogram", rpc_iscsi_get_histogram, SPDK_RPC_RUNTIME)
|