xref: /spdk/lib/iscsi/iscsi_rpc.c (revision ba909a45b8fff6f8717318f3834cb56d91059f95)
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
rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)21 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 	if (params != NULL) {
27 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
28 						 "iscsi_get_initiator_groups requires no parameters");
29 		return;
30 	}
31 
32 	w = spdk_jsonrpc_begin_result(request);
33 	spdk_json_write_array_begin(w);
34 	iscsi_init_grps_info_json(w);
35 	spdk_json_write_array_end(w);
36 
37 	spdk_jsonrpc_end_result(request, w);
38 }
39 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
decode_rpc_initiator_list(const struct spdk_json_val * val,void * out)48 decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
49 {
50 	struct rpc_initiator_list *list = out;
51 
52 	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
free_rpc_initiator_list(struct rpc_initiator_list * list)57 free_rpc_initiator_list(struct rpc_initiator_list *list)
58 {
59 	size_t i;
60 
61 	for (i = 0; i < list->num_initiators; i++) {
62 		free(list->initiators[i]);
63 	}
64 }
65 
66 struct rpc_netmask_list {
67 	size_t num_netmasks;
68 	char *netmasks[MAX_NETMASK];
69 };
70 
71 static int
decode_rpc_netmask_list(const struct spdk_json_val * val,void * out)72 decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
73 {
74 	struct rpc_netmask_list *list = out;
75 
76 	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
free_rpc_netmask_list(struct rpc_netmask_list * list)81 free_rpc_netmask_list(struct rpc_netmask_list *list)
82 {
83 	size_t i;
84 
85 	for (i = 0; i < list->num_netmasks; i++) {
86 		free(list->netmasks[i]);
87 	}
88 }
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
free_rpc_initiator_group(struct rpc_initiator_group * ig)97 free_rpc_initiator_group(struct rpc_initiator_group *ig)
98 {
99 	free_rpc_initiator_list(&ig->initiator_list);
100 	free_rpc_netmask_list(&ig->netmask_list);
101 }
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
rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)110 rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request,
111 				 const struct spdk_json_val *params)
112 {
113 	struct rpc_initiator_group req = {};
114 
115 	if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
116 				    SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) {
117 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
118 		goto invalid;
119 	}
120 
121 	if (req.initiator_list.num_initiators == 0 ||
122 	    req.netmask_list.num_netmasks == 0) {
123 		goto invalid;
124 	}
125 
126 	if (iscsi_init_grp_create_from_initiator_list(req.tag,
127 			req.initiator_list.num_initiators,
128 			req.initiator_list.initiators,
129 			req.netmask_list.num_netmasks,
130 			req.netmask_list.netmasks)) {
131 		SPDK_ERRLOG("create_from_initiator_list failed\n");
132 		goto invalid;
133 	}
134 
135 	free_rpc_initiator_group(&req);
136 
137 	spdk_jsonrpc_send_bool_response(request, true);
138 	return;
139 
140 invalid:
141 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
142 	free_rpc_initiator_group(&req);
143 }
144 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
rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)154 rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request,
155 		const struct spdk_json_val *params)
156 {
157 	struct rpc_initiator_group req = {};
158 
159 	if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
160 				    SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
161 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
162 		goto invalid;
163 	}
164 
165 	if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
166 			req.initiator_list.num_initiators,
167 			req.initiator_list.initiators,
168 			req.netmask_list.num_netmasks,
169 			req.netmask_list.netmasks)) {
170 		SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
171 		goto invalid;
172 	}
173 
174 	free_rpc_initiator_group(&req);
175 
176 	spdk_jsonrpc_send_bool_response(request, true);
177 	return;
178 
179 invalid:
180 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
181 	free_rpc_initiator_group(&req);
182 }
183 SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators",
184 		  rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME)
185 
186 static void
rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)187 rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request,
188 		const struct spdk_json_val *params)
189 {
190 	struct rpc_initiator_group req = {};
191 
192 	if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
193 				    SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
194 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
195 		goto invalid;
196 	}
197 
198 	if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
199 			req.initiator_list.num_initiators,
200 			req.initiator_list.initiators,
201 			req.netmask_list.num_netmasks,
202 			req.netmask_list.netmasks)) {
203 		SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
204 		goto invalid;
205 	}
206 
207 	free_rpc_initiator_group(&req);
208 
209 	spdk_jsonrpc_send_bool_response(request, true);
210 	return;
211 
212 invalid:
213 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
214 	free_rpc_initiator_group(&req);
215 }
216 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
rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)228 rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request,
229 				 const struct spdk_json_val *params)
230 {
231 	struct rpc_iscsi_delete_initiator_group req = {};
232 	struct spdk_iscsi_init_grp *ig;
233 
234 	if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders,
235 				    SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders),
236 				    &req)) {
237 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
238 		goto invalid;
239 	}
240 
241 	ig = iscsi_init_grp_unregister(req.tag);
242 	if (!ig) {
243 		goto invalid;
244 	}
245 	iscsi_tgt_node_delete_map(NULL, ig);
246 	iscsi_init_grp_destroy(ig);
247 
248 	spdk_jsonrpc_send_bool_response(request, true);
249 	return;
250 
251 invalid:
252 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
253 }
254 SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group,
255 		  SPDK_RPC_RUNTIME)
256 
257 static void
rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)258 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 	if (params != NULL) {
264 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
265 						 "iscsi_get_target_nodes requires no parameters");
266 		return;
267 	}
268 
269 	w = spdk_jsonrpc_begin_result(request);
270 	spdk_json_write_array_begin(w);
271 	iscsi_tgt_nodes_info_json(w);
272 	spdk_json_write_array_end(w);
273 
274 	spdk_jsonrpc_end_result(request, w);
275 }
276 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
decode_rpc_pg_ig_map(const struct spdk_json_val * val,void * out)289 decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out)
290 {
291 	struct rpc_pg_ig_map *pg_ig_map = out;
292 
293 	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
decode_rpc_pg_ig_maps(const struct spdk_json_val * val,void * out)304 decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out)
305 {
306 	struct rpc_pg_ig_maps *pg_ig_maps = out;
307 
308 	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
decode_rpc_lun(const struct spdk_json_val * val,void * out)326 decode_rpc_lun(const struct spdk_json_val *val, void *out)
327 {
328 	struct rpc_lun *lun = out;
329 
330 	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
decode_rpc_luns(const struct spdk_json_val * val,void * out)340 decode_rpc_luns(const struct spdk_json_val *val, void *out)
341 {
342 	struct rpc_luns *luns = out;
343 
344 	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
free_rpc_luns(struct rpc_luns * p)350 free_rpc_luns(struct rpc_luns *p)
351 {
352 	size_t i;
353 
354 	for (i = 0; i < p->num_luns; i++) {
355 		free(p->luns[i].bdev_name);
356 	}
357 }
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
free_rpc_target_node(struct rpc_target_node * req)377 free_rpc_target_node(struct rpc_target_node *req)
378 {
379 	free(req->name);
380 	free(req->alias_name);
381 	free_rpc_luns(&req->luns);
382 }
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
rpc_iscsi_create_target_node(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)399 rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request,
400 			     const struct spdk_json_val *params)
401 {
402 	struct rpc_target_node req = {};
403 	struct spdk_iscsi_tgt_node *target;
404 	int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
405 	char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
406 	int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
407 	size_t i;
408 
409 	if (spdk_json_decode_object(params, rpc_target_node_decoders,
410 				    SPDK_COUNTOF(rpc_target_node_decoders),
411 				    &req)) {
412 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
413 		goto invalid;
414 	}
415 
416 	for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
417 		pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
418 		ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
419 	}
420 
421 	for (i = 0; i < req.luns.num_luns; i++) {
422 		bdev_names[i] = req.luns.luns[i].bdev_name;
423 		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 	target = iscsi_tgt_node_construct(-1, req.name, req.alias_name,
432 					  pg_tags,
433 					  ig_tags,
434 					  req.pg_ig_maps.num_maps,
435 					  (const char **)bdev_names,
436 					  lun_ids,
437 					  req.luns.num_luns,
438 					  req.queue_depth,
439 					  req.disable_chap,
440 					  req.require_chap,
441 					  req.mutual_chap,
442 					  req.chap_group,
443 					  req.header_digest,
444 					  req.data_digest);
445 
446 	if (target == NULL) {
447 		goto invalid;
448 	}
449 
450 	free_rpc_target_node(&req);
451 
452 	spdk_jsonrpc_send_bool_response(request, true);
453 	return;
454 
455 invalid:
456 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
457 	free_rpc_target_node(&req);
458 }
459 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
rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)472 rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request,
473 				     const struct spdk_json_val *params)
474 {
475 	struct rpc_tgt_node_pg_ig_maps req = {};
476 	struct spdk_iscsi_tgt_node *target;
477 	int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
478 	size_t i;
479 	int rc;
480 
481 	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 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
485 		goto invalid;
486 	}
487 
488 	target = iscsi_find_tgt_node(req.name);
489 	if (target == NULL) {
490 		SPDK_ERRLOG("target is not found\n");
491 		goto invalid;
492 	}
493 
494 	for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
495 		pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
496 		ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
497 	}
498 
499 	rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags,
500 					      req.pg_ig_maps.num_maps);
501 	if (rc < 0) {
502 		SPDK_ERRLOG("add pg-ig maps failed\n");
503 		goto invalid;
504 	}
505 
506 	free(req.name);
507 
508 	spdk_jsonrpc_send_bool_response(request, true);
509 	return;
510 
511 invalid:
512 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
513 					 "Invalid parameters");
514 	free(req.name);
515 }
516 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
rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)520 rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request,
521 					const struct spdk_json_val *params)
522 {
523 	struct rpc_tgt_node_pg_ig_maps req = {};
524 	struct spdk_iscsi_tgt_node *target;
525 	int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
526 	size_t i;
527 	int rc;
528 
529 	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 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
533 		goto invalid;
534 	}
535 
536 	target = iscsi_find_tgt_node(req.name);
537 	if (target == NULL) {
538 		SPDK_ERRLOG("target is not found\n");
539 		goto invalid;
540 	}
541 
542 	for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
543 		pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
544 		ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
545 	}
546 
547 	rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags,
548 			req.pg_ig_maps.num_maps);
549 	if (rc < 0) {
550 		SPDK_ERRLOG("remove pg-ig maps failed\n");
551 		goto invalid;
552 	}
553 
554 	free(req.name);
555 
556 	spdk_jsonrpc_send_bool_response(request, true);
557 	return;
558 
559 invalid:
560 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
561 					 "Invalid parameters");
562 	free(req.name);
563 }
564 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
free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node * r)572 free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r)
573 {
574 	free(r->name);
575 }
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
rpc_iscsi_delete_target_node_done(void * cb_arg,int rc)587 rpc_iscsi_delete_target_node_done(void *cb_arg, int rc)
588 {
589 	struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg;
590 
591 	free_rpc_iscsi_delete_target_node(&ctx->req);
592 	if (rc == 0) {
593 		spdk_jsonrpc_send_bool_response(ctx->request, true);
594 	} else {
595 		spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
596 	}
597 	free(ctx);
598 }
599 
600 static void
rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)601 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 	ctx = calloc(1, sizeof(*ctx));
607 	if (!ctx) {
608 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
609 						 spdk_strerror(ENOMEM));
610 		return;
611 	}
612 
613 	if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders,
614 				    SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders),
615 				    &ctx->req)) {
616 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
617 		goto invalid;
618 	}
619 
620 	if (ctx->req.name == NULL) {
621 		SPDK_ERRLOG("missing name param\n");
622 		goto invalid;
623 	}
624 
625 	ctx->request = request;
626 
627 	iscsi_shutdown_tgt_node_by_name(ctx->req.name,
628 					rpc_iscsi_delete_target_node_done, ctx);
629 	return;
630 
631 invalid:
632 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
633 	free_rpc_iscsi_delete_target_node(&ctx->req);
634 	free(ctx);
635 }
636 SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME)
637 
638 static void
rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)639 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 	if (params != NULL) {
645 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
646 						 "iscsi_get_portal_groups requires no parameters");
647 		return;
648 	}
649 
650 	w = spdk_jsonrpc_begin_result(request);
651 	spdk_json_write_array_begin(w);
652 	iscsi_portal_grps_info_json(w);
653 	spdk_json_write_array_end(w);
654 
655 	spdk_jsonrpc_end_result(request, w);
656 }
657 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
free_rpc_portal(struct rpc_portal * portal)677 free_rpc_portal(struct rpc_portal *portal)
678 {
679 	free(portal->host);
680 	free(portal->port);
681 }
682 
683 static void
free_rpc_portal_list(struct rpc_portal_list * pl)684 free_rpc_portal_list(struct rpc_portal_list *pl)
685 {
686 	size_t i;
687 
688 	for (i = 0; i < pl->num_portals; i++) {
689 		free_rpc_portal(&pl->portals[i]);
690 	}
691 	pl->num_portals = 0;
692 }
693 
694 static void
free_rpc_portal_group(struct rpc_portal_group * pg)695 free_rpc_portal_group(struct rpc_portal_group *pg)
696 {
697 	free_rpc_portal_list(&pg->portal_list);
698 }
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
decode_rpc_portal(const struct spdk_json_val * val,void * out)706 decode_rpc_portal(const struct spdk_json_val *val, void *out)
707 {
708 	struct rpc_portal *portal = out;
709 
710 	return spdk_json_decode_object(val, rpc_portal_decoders,
711 				       SPDK_COUNTOF(rpc_portal_decoders),
712 				       portal);
713 }
714 
715 static int
decode_rpc_portal_list(const struct spdk_json_val * val,void * out)716 decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
717 {
718 	struct rpc_portal_list *list = out;
719 
720 	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
rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)732 rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request,
733 			      const struct spdk_json_val *params)
734 {
735 	struct rpc_portal_group req = {};
736 	struct spdk_iscsi_portal_grp *pg = NULL;
737 	struct spdk_iscsi_portal *portal;
738 	size_t i = 0;
739 	int rc = -1;
740 
741 	if (spdk_json_decode_object(params, rpc_portal_group_decoders,
742 				    SPDK_COUNTOF(rpc_portal_group_decoders),
743 				    &req)) {
744 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
745 		goto out;
746 	}
747 
748 	pg = iscsi_portal_grp_create(req.tag, req.is_private);
749 	if (pg == NULL) {
750 		SPDK_ERRLOG("portal_grp_create failed\n");
751 		goto out;
752 	}
753 	for (i = 0; i < req.portal_list.num_portals; i++) {
754 		portal = iscsi_portal_create(req.portal_list.portals[i].host,
755 					     req.portal_list.portals[i].port);
756 		if (portal == NULL) {
757 			SPDK_ERRLOG("portal_create failed\n");
758 			goto out;
759 		}
760 		iscsi_portal_grp_add_portal(pg, portal);
761 	}
762 
763 	rc = iscsi_portal_grp_open(pg, req.wait);
764 	if (rc != 0) {
765 		SPDK_ERRLOG("portal_grp_open failed\n");
766 		goto out;
767 	}
768 
769 	rc = iscsi_portal_grp_register(pg);
770 	if (rc != 0) {
771 		SPDK_ERRLOG("portal_grp_register failed\n");
772 	}
773 
774 out:
775 	if (rc == 0) {
776 		spdk_jsonrpc_send_bool_response(request, true);
777 	} else {
778 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
779 
780 		if (pg != NULL) {
781 			iscsi_portal_grp_release(pg);
782 		}
783 	}
784 	free_rpc_portal_group(&req);
785 }
786 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
_rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params,iscsi_change_portal_grp_fn fn)799 _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 	struct rpc_iscsi_change_portal_group req = {};
804 	int rc;
805 
806 	if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders,
807 				    SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders),
808 				    &req)) {
809 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
810 		goto invalid;
811 	}
812 
813 	rc = fn(req.tag);
814 	if (rc != 0) {
815 		goto invalid;
816 	}
817 
818 	spdk_jsonrpc_send_bool_response(request, true);
819 	return;
820 
821 invalid:
822 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
823 }
824 
825 static int
_rpc_iscsi_delete_portal_group(int pg_tag)826 _rpc_iscsi_delete_portal_group(int pg_tag)
827 {
828 	struct spdk_iscsi_portal_grp *pg;
829 
830 	pg = iscsi_portal_grp_unregister(pg_tag);
831 	if (!pg) {
832 		return -ENODEV;
833 	}
834 
835 	iscsi_tgt_node_delete_map(pg, NULL);
836 	iscsi_portal_grp_release(pg);
837 	return 0;
838 }
839 
840 static void
rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)841 rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request,
842 			      const struct spdk_json_val *params)
843 {
844 	_rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group);
845 }
846 SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME)
847 
848 static int
_rpc_iscsi_start_portal_group(int pg_tag)849 _rpc_iscsi_start_portal_group(int pg_tag)
850 {
851 	struct spdk_iscsi_portal_grp *pg;
852 
853 	pg = iscsi_portal_grp_find_by_tag(pg_tag);
854 	if (!pg) {
855 		return -ENODEV;
856 	}
857 
858 	iscsi_portal_grp_resume(pg);
859 	return 0;
860 }
861 
862 static void
rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)863 rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request,
864 			     const struct spdk_json_val *params)
865 {
866 	_rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group);
867 }
868 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
rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)887 rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request,
888 				const struct spdk_json_val *params)
889 {
890 	struct rpc_portal_group_auth req = {};
891 	struct spdk_iscsi_portal_grp *pg;
892 	int rc;
893 
894 	if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders,
895 				    SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) {
896 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
897 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
898 						 "Invalid parameters");
899 		return;
900 	}
901 
902 	pthread_mutex_lock(&g_iscsi.mutex);
903 
904 	pg = iscsi_portal_grp_find_by_tag(req.tag);
905 	if (pg == NULL) {
906 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
907 						     "Could not find portal group %d", req.tag);
908 		goto exit;
909 	}
910 
911 	rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap,
912 					      req.mutual_chap, req.chap_group);
913 	if (rc < 0) {
914 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
915 						 "Invalid combination of auth params");
916 		goto exit;
917 	}
918 
919 	pthread_mutex_unlock(&g_iscsi.mutex);
920 
921 	spdk_jsonrpc_send_bool_response(request, true);
922 	return;
923 
924 exit:
925 	pthread_mutex_unlock(&g_iscsi.mutex);
926 }
927 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
_rpc_iscsi_get_connections_done(struct spdk_io_channel_iter * i,int status)936 _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status)
937 {
938 	struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
939 
940 	spdk_json_write_array_end(ctx->w);
941 	spdk_jsonrpc_end_result(ctx->request, ctx->w);
942 
943 	free(ctx);
944 }
945 
946 static void
_rpc_iscsi_get_connections(struct spdk_io_channel_iter * i)947 _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i)
948 {
949 	struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
950 	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
951 	struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
952 	struct spdk_iscsi_conn *conn;
953 
954 	STAILQ_FOREACH(conn, &pg->connections, pg_link) {
955 		iscsi_conn_info_json(ctx->w, conn);
956 	}
957 
958 	spdk_for_each_channel_continue(i, 0);
959 }
960 
961 static void
rpc_iscsi_get_connections(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)962 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 	if (params != NULL) {
968 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
969 						 "iscsi_get_connections requires no parameters");
970 		return;
971 	}
972 
973 	ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx));
974 	if (ctx == NULL) {
975 		SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n");
976 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
977 		return;
978 	}
979 
980 	ctx->request = request;
981 	ctx->w = spdk_jsonrpc_begin_result(request);
982 
983 	spdk_json_write_array_begin(ctx->w);
984 
985 	spdk_for_each_channel(&g_iscsi,
986 			      _rpc_iscsi_get_connections,
987 			      ctx,
988 			      _rpc_iscsi_get_connections_done);
989 }
990 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
_rpc_iscsi_get_stats_done(struct spdk_io_channel_iter * i,int status)1007 _rpc_iscsi_get_stats_done(struct spdk_io_channel_iter *i, int status)
1008 {
1009 	struct spdk_json_write_ctx *w;
1010 	struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1011 
1012 	w = spdk_jsonrpc_begin_result(ctx->request);
1013 	spdk_json_write_object_begin(w);
1014 
1015 	spdk_json_write_named_uint32(w, "invalid", ctx->invalid);
1016 	spdk_json_write_named_uint32(w, "running", ctx->running);
1017 	spdk_json_write_named_uint32(w, "exiting", ctx->exiting);
1018 	spdk_json_write_named_uint32(w, "exited", ctx->exited);
1019 
1020 	spdk_json_write_object_end(w);
1021 	spdk_jsonrpc_end_result(ctx->request, w);
1022 
1023 	free(ctx);
1024 }
1025 
1026 static void
_iscsi_get_stats(struct rpc_iscsi_get_stats_ctx * ctx,struct spdk_iscsi_conn * conn)1027 _iscsi_get_stats(struct rpc_iscsi_get_stats_ctx *ctx,
1028 		 struct spdk_iscsi_conn *conn)
1029 {
1030 	switch (conn->state) {
1031 	case ISCSI_CONN_STATE_INVALID:
1032 		ctx->invalid += 1;
1033 		break;
1034 	case ISCSI_CONN_STATE_RUNNING:
1035 		ctx->running += 1;
1036 		break;
1037 	case ISCSI_CONN_STATE_EXITING:
1038 		ctx->exiting += 1;
1039 		break;
1040 	case ISCSI_CONN_STATE_EXITED:
1041 		ctx->exited += 1;
1042 		break;
1043 	}
1044 }
1045 
1046 static void
_rpc_iscsi_get_stats(struct spdk_io_channel_iter * i)1047 _rpc_iscsi_get_stats(struct spdk_io_channel_iter *i)
1048 {
1049 	struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1050 	struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
1051 	struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
1052 	struct spdk_iscsi_conn *conn;
1053 
1054 	STAILQ_FOREACH(conn, &pg->connections, pg_link) {
1055 		_iscsi_get_stats(ctx, conn);
1056 	}
1057 
1058 	spdk_for_each_channel_continue(i, 0);
1059 }
1060 
1061 
1062 
1063 static void
rpc_iscsi_get_stats(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1064 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 	if (params != NULL) {
1070 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1071 						 "iscsi_get_stats requires no parameters");
1072 		return;
1073 	}
1074 
1075 	ctx = calloc(1, sizeof(struct rpc_iscsi_get_stats_ctx));
1076 	if (ctx == NULL) {
1077 		SPDK_ERRLOG("Failed to allocate rpc_iscsi_get_stats_ctx struct\n");
1078 		spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1079 		return;
1080 	}
1081 
1082 	ctx->request = request;
1083 
1084 	spdk_for_each_channel(&g_iscsi,
1085 			      _rpc_iscsi_get_stats,
1086 			      ctx,
1087 			      _rpc_iscsi_get_stats_done);
1088 
1089 }
1090 SPDK_RPC_REGISTER("iscsi_get_stats", rpc_iscsi_get_stats, SPDK_RPC_RUNTIME)
1091 
1092 static void
free_rpc_target_lun(struct rpc_target_lun * req)1093 free_rpc_target_lun(struct rpc_target_lun *req)
1094 {
1095 	free(req->name);
1096 	free(req->bdev_name);
1097 }
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
rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1106 rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request,
1107 			      const struct spdk_json_val *params)
1108 {
1109 	struct rpc_target_lun req = {};
1110 	struct spdk_iscsi_tgt_node *target;
1111 	int rc;
1112 
1113 	req.lun_id = -1;
1114 
1115 	if (spdk_json_decode_object(params, rpc_target_lun_decoders,
1116 				    SPDK_COUNTOF(rpc_target_lun_decoders), &req)) {
1117 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1118 		goto invalid;
1119 	}
1120 
1121 	target = iscsi_find_tgt_node(req.name);
1122 	if (target == NULL) {
1123 		SPDK_ERRLOG("target is not found\n");
1124 		goto invalid;
1125 	}
1126 
1127 	rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id);
1128 	if (rc < 0) {
1129 		SPDK_ERRLOG("add lun failed\n");
1130 		goto invalid;
1131 	}
1132 
1133 	free_rpc_target_lun(&req);
1134 
1135 	spdk_jsonrpc_send_bool_response(request, true);
1136 	return;
1137 
1138 invalid:
1139 	spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1140 					 "Invalid parameters");
1141 	free_rpc_target_lun(&req);
1142 }
1143 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
free_rpc_target_auth(struct rpc_target_auth * req)1154 free_rpc_target_auth(struct rpc_target_auth *req)
1155 {
1156 	free(req->name);
1157 }
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
rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1168 rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request,
1169 			       const struct spdk_json_val *params)
1170 {
1171 	struct rpc_target_auth req = {};
1172 	struct spdk_iscsi_tgt_node *target;
1173 	int rc;
1174 
1175 	if (spdk_json_decode_object(params, rpc_target_auth_decoders,
1176 				    SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
1177 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1178 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1179 						 "Invalid parameters");
1180 		goto exit;
1181 	}
1182 
1183 	target = iscsi_find_tgt_node(req.name);
1184 	if (target == NULL) {
1185 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1186 						     "Could not find target %s", req.name);
1187 		goto exit;
1188 	}
1189 
1190 	rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
1191 					    req.mutual_chap, req.chap_group);
1192 	if (rc < 0) {
1193 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1194 						 "Invalid combination of auth params");
1195 		goto exit;
1196 	}
1197 
1198 	free_rpc_target_auth(&req);
1199 
1200 	spdk_jsonrpc_send_bool_response(request, true);
1201 	return;
1202 
1203 exit:
1204 	free_rpc_target_auth(&req);
1205 }
1206 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
free_rpc_target_redirect(struct rpc_target_redirect * req)1217 free_rpc_target_redirect(struct rpc_target_redirect *req)
1218 {
1219 	free(req->name);
1220 	free(req->redirect_host);
1221 	free(req->redirect_port);
1222 }
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
rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1232 rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request,
1233 				   const struct spdk_json_val *params)
1234 {
1235 	struct rpc_target_redirect req = {};
1236 	struct spdk_iscsi_tgt_node *target;
1237 	int rc;
1238 
1239 	if (spdk_json_decode_object(params, rpc_target_redirect_decoders,
1240 				    SPDK_COUNTOF(rpc_target_redirect_decoders),
1241 				    &req)) {
1242 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1243 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1244 						 "Invalid parameters");
1245 		free_rpc_target_redirect(&req);
1246 		return;
1247 	}
1248 
1249 	target = iscsi_find_tgt_node(req.name);
1250 	if (target == NULL) {
1251 		SPDK_ERRLOG("target %s is not found\n", req.name);
1252 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1253 						     "Target %s is not found", req.name);
1254 		free_rpc_target_redirect(&req);
1255 		return;
1256 	}
1257 
1258 	rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port);
1259 	if (rc != 0) {
1260 		SPDK_ERRLOG("failed to redirect target %s\n", req.name);
1261 		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 		free_rpc_target_redirect(&req);
1265 		return;
1266 	}
1267 
1268 	free_rpc_target_redirect(&req);
1269 
1270 	spdk_jsonrpc_send_bool_response(request, true);
1271 }
1272 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
free_rpc_target_logout(struct rpc_target_logout * req)1281 free_rpc_target_logout(struct rpc_target_logout *req)
1282 {
1283 	free(req->name);
1284 }
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
rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1292 rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request,
1293 				     const struct spdk_json_val *params)
1294 {
1295 	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 	req.pg_tag = -1;
1302 
1303 	if (spdk_json_decode_object(params, rpc_target_logout_decoders,
1304 				    SPDK_COUNTOF(rpc_target_logout_decoders),
1305 				    &req)) {
1306 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1307 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1308 						 "Invalid parameters");
1309 		free_rpc_target_logout(&req);
1310 		return;
1311 	}
1312 
1313 	target = iscsi_find_tgt_node(req.name);
1314 	if (target == NULL) {
1315 		SPDK_ERRLOG("target %s is not found\n", req.name);
1316 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1317 						     "Target %s is not found", req.name);
1318 		free_rpc_target_logout(&req);
1319 		return;
1320 	}
1321 
1322 	iscsi_conns_request_logout(target, req.pg_tag);
1323 
1324 	free_rpc_target_logout(&req);
1325 
1326 	spdk_jsonrpc_send_bool_response(request, true);
1327 }
1328 SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout,
1329 		  SPDK_RPC_RUNTIME)
1330 
1331 static void
rpc_iscsi_get_options(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1332 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 	if (params != NULL) {
1338 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1339 						 "iscsi_get_options requires no parameters");
1340 		return;
1341 	}
1342 
1343 	w = spdk_jsonrpc_begin_result(request);
1344 	iscsi_opts_info_json(w);
1345 
1346 	spdk_jsonrpc_end_result(request, w);
1347 }
1348 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
rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1365 rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request,
1366 			     const struct spdk_json_val *params)
1367 {
1368 	struct rpc_discovery_auth req = {};
1369 	int rc;
1370 
1371 	if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
1372 				    SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
1373 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1374 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1375 						 "Invalid parameters");
1376 		return;
1377 	}
1378 
1379 	rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
1380 				      req.mutual_chap, req.chap_group);
1381 	if (rc < 0) {
1382 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1383 						 "Invalid combination of CHAP params");
1384 		return;
1385 	}
1386 
1387 	spdk_jsonrpc_send_bool_response(request, true);
1388 }
1389 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
free_rpc_auth_secret(struct rpc_auth_secret * _secret)1401 free_rpc_auth_secret(struct rpc_auth_secret *_secret)
1402 {
1403 	free(_secret->user);
1404 	free(_secret->secret);
1405 	free(_secret->muser);
1406 	free(_secret->msecret);
1407 }
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
decode_rpc_auth_secret(const struct spdk_json_val * val,void * out)1417 decode_rpc_auth_secret(const struct spdk_json_val *val, void *out)
1418 {
1419 	struct rpc_auth_secret *_secret = out;
1420 
1421 	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
free_rpc_auth_secrets(struct rpc_auth_secrets * secrets)1431 free_rpc_auth_secrets(struct rpc_auth_secrets *secrets)
1432 {
1433 	size_t i;
1434 
1435 	for (i = 0; i < secrets->num_secret; i++) {
1436 		free_rpc_auth_secret(&secrets->secrets[i]);
1437 	}
1438 }
1439 
1440 static int
decode_rpc_auth_secrets(const struct spdk_json_val * val,void * out)1441 decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out)
1442 {
1443 	struct rpc_auth_secrets *secrets = out;
1444 
1445 	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
free_rpc_auth_group(struct rpc_auth_group * group)1456 free_rpc_auth_group(struct rpc_auth_group *group)
1457 {
1458 	free_rpc_auth_secrets(&group->secrets);
1459 }
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
rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1467 rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request,
1468 			    const struct spdk_json_val *params)
1469 {
1470 	struct rpc_auth_group req = {};
1471 	struct rpc_auth_secret *_secret;
1472 	struct spdk_iscsi_auth_group *group = NULL;
1473 	int rc;
1474 	size_t i;
1475 
1476 	if (spdk_json_decode_object(params, rpc_auth_group_decoders,
1477 				    SPDK_COUNTOF(rpc_auth_group_decoders), &req)) {
1478 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1479 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1480 						 "Invalid parameters");
1481 		free_rpc_auth_group(&req);
1482 		return;
1483 	}
1484 
1485 	pthread_mutex_lock(&g_iscsi.mutex);
1486 
1487 	rc = iscsi_add_auth_group(req.tag, &group);
1488 	if (rc != 0) {
1489 		pthread_mutex_unlock(&g_iscsi.mutex);
1490 
1491 		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 		free_rpc_auth_group(&req);
1495 		return;
1496 	}
1497 
1498 	for (i = 0; i < req.secrets.num_secret; i++) {
1499 		_secret = &req.secrets.secrets[i];
1500 		rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret,
1501 						 _secret->muser, _secret->msecret);
1502 		if (rc != 0) {
1503 			iscsi_delete_auth_group(group);
1504 			pthread_mutex_unlock(&g_iscsi.mutex);
1505 
1506 			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 			free_rpc_auth_group(&req);
1510 			return;
1511 		}
1512 	}
1513 
1514 	pthread_mutex_unlock(&g_iscsi.mutex);
1515 
1516 	free_rpc_auth_group(&req);
1517 
1518 	spdk_jsonrpc_send_bool_response(request, true);
1519 }
1520 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
rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1531 rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request,
1532 			    const struct spdk_json_val *params)
1533 {
1534 	struct rpc_delete_auth_group req = {};
1535 	struct spdk_iscsi_auth_group *group;
1536 
1537 	if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders,
1538 				    SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) {
1539 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1540 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1541 						 "Invalid parameters");
1542 		return;
1543 	}
1544 
1545 	pthread_mutex_lock(&g_iscsi.mutex);
1546 
1547 	group = iscsi_find_auth_group_by_tag(req.tag);
1548 	if (group == NULL) {
1549 		pthread_mutex_unlock(&g_iscsi.mutex);
1550 
1551 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1552 						     "Could not find auth group (%d)", req.tag);
1553 		return;
1554 	}
1555 
1556 	iscsi_delete_auth_group(group);
1557 
1558 	pthread_mutex_unlock(&g_iscsi.mutex);
1559 
1560 	spdk_jsonrpc_send_bool_response(request, true);
1561 }
1562 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
free_rpc_add_auth_secret(struct rpc_add_auth_secret * _secret)1573 free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret)
1574 {
1575 	free(_secret->user);
1576 	free(_secret->secret);
1577 	free(_secret->muser);
1578 	free(_secret->msecret);
1579 }
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
rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1590 rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request,
1591 				const struct spdk_json_val *params)
1592 {
1593 	struct rpc_add_auth_secret req = {};
1594 	struct spdk_iscsi_auth_group *group;
1595 	int rc;
1596 
1597 	if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders,
1598 				    SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) {
1599 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1600 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1601 						 "Invalid parameters");
1602 		free_rpc_add_auth_secret(&req);
1603 		return;
1604 	}
1605 
1606 	pthread_mutex_lock(&g_iscsi.mutex);
1607 
1608 	group = iscsi_find_auth_group_by_tag(req.tag);
1609 	if (group == NULL) {
1610 		pthread_mutex_unlock(&g_iscsi.mutex);
1611 
1612 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1613 						     "Could not find auth group (%d)", req.tag);
1614 		free_rpc_add_auth_secret(&req);
1615 		return;
1616 	}
1617 
1618 	rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret);
1619 	if (rc != 0) {
1620 		pthread_mutex_unlock(&g_iscsi.mutex);
1621 
1622 		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 		free_rpc_add_auth_secret(&req);
1626 		return;
1627 	}
1628 
1629 	pthread_mutex_unlock(&g_iscsi.mutex);
1630 
1631 	free_rpc_add_auth_secret(&req);
1632 
1633 	spdk_jsonrpc_send_bool_response(request, true);
1634 }
1635 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
free_rpc_remove_auth_secret(struct rpc_remove_auth_secret * _secret)1645 free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret)
1646 {
1647 	free(_secret->user);
1648 }
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
rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1656 rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request,
1657 				   const struct spdk_json_val *params)
1658 {
1659 	struct rpc_remove_auth_secret req = {};
1660 	struct spdk_iscsi_auth_group *group;
1661 	int rc;
1662 
1663 	if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders,
1664 				    SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) {
1665 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1666 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1667 						 "Invalid parameters");
1668 		free_rpc_remove_auth_secret(&req);
1669 		return;
1670 	}
1671 
1672 	pthread_mutex_lock(&g_iscsi.mutex);
1673 
1674 	group = iscsi_find_auth_group_by_tag(req.tag);
1675 	if (group == NULL) {
1676 		pthread_mutex_unlock(&g_iscsi.mutex);
1677 
1678 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1679 						     "Could not find auth group (%d)", req.tag);
1680 		free_rpc_remove_auth_secret(&req);
1681 		return;
1682 	}
1683 
1684 	rc = iscsi_auth_group_delete_secret(group, req.user);
1685 	if (rc != 0) {
1686 		pthread_mutex_unlock(&g_iscsi.mutex);
1687 
1688 		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 		free_rpc_remove_auth_secret(&req);
1692 		return;
1693 	}
1694 
1695 	pthread_mutex_unlock(&g_iscsi.mutex);
1696 
1697 	free_rpc_remove_auth_secret(&req);
1698 
1699 	spdk_jsonrpc_send_bool_response(request, true);
1700 }
1701 SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret",
1702 		  rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME)
1703 
1704 static void
rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1705 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 	if (params != NULL) {
1711 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1712 						 "iscsi_get_auth_groups requires no parameters");
1713 		return;
1714 	}
1715 
1716 	w = spdk_jsonrpc_begin_result(request);
1717 	spdk_json_write_array_begin(w);
1718 	iscsi_auth_groups_info_json(w);
1719 	spdk_json_write_array_end(w);
1720 
1721 	spdk_jsonrpc_end_result(request, w);
1722 }
1723 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
rpc_iscsi_set_options(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1755 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 	if (g_spdk_iscsi_opts != NULL) {
1761 		SPDK_ERRLOG("this RPC must not be called more than once.\n");
1762 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1763 						 "Must not call more than once");
1764 		return;
1765 	}
1766 
1767 	opts = iscsi_opts_alloc();
1768 	if (opts == NULL) {
1769 		SPDK_ERRLOG("iscsi_opts_alloc() failed.\n");
1770 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1771 						 "Out of memory");
1772 		return;
1773 	}
1774 
1775 	if (params != NULL) {
1776 		if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders,
1777 					    SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) {
1778 			SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1779 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1780 							 "Invalid parameters");
1781 			iscsi_opts_free(opts);
1782 			return;
1783 		}
1784 	}
1785 
1786 	g_spdk_iscsi_opts = iscsi_opts_copy(opts);
1787 	iscsi_opts_free(opts);
1788 
1789 	if (g_spdk_iscsi_opts == NULL) {
1790 		SPDK_ERRLOG("iscsi_opts_copy() failed\n");
1791 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1792 						 "Out of memory");
1793 		return;
1794 	}
1795 
1796 	spdk_jsonrpc_send_bool_response(request, true);
1797 }
1798 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
rpc_iscsi_enable_histogram_done(void * _ctx)1819 rpc_iscsi_enable_histogram_done(void *_ctx)
1820 {
1821 	struct iscsi_enable_histogram_ctx *ctx = _ctx;
1822 
1823 	if (ctx->status == 0) {
1824 		spdk_jsonrpc_send_bool_response(ctx->request, true);
1825 	} else {
1826 		spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1827 						 spdk_strerror(-ctx->status));
1828 	}
1829 
1830 	free(ctx);
1831 }
1832 
1833 static void
_iscsi_enable_histogram(void * _ctx)1834 _iscsi_enable_histogram(void *_ctx)
1835 {
1836 	struct iscsi_enable_histogram_ctx *ctx = _ctx;
1837 
1838 	ctx->status = iscsi_tgt_node_enable_histogram(ctx->target, ctx->enable);
1839 }
1840 
1841 static void
_rpc_iscsi_enable_histogram(void * _ctx)1842 _rpc_iscsi_enable_histogram(void *_ctx)
1843 {
1844 	struct iscsi_enable_histogram_ctx *ctx = _ctx;
1845 
1846 	pthread_mutex_lock(&ctx->target->mutex);
1847 	_iscsi_enable_histogram(ctx);
1848 	ctx->target->num_active_conns--;
1849 	pthread_mutex_unlock(&ctx->target->mutex);
1850 
1851 	spdk_thread_send_msg(ctx->orig_thread, rpc_iscsi_enable_histogram_done, ctx);
1852 }
1853 
1854 static void
rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1855 rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request,
1856 			   const struct spdk_json_val *params)
1857 {
1858 	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 	if (spdk_json_decode_object(params, rpc_iscsi_enable_histogram_request_decoders,
1865 				    SPDK_COUNTOF(rpc_iscsi_enable_histogram_request_decoders),
1866 				    &req)) {
1867 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1868 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1869 						 "spdk_json_decode_object failed");
1870 		return;
1871 	}
1872 
1873 	ctx = calloc(1, sizeof(*ctx));
1874 	if (ctx == NULL) {
1875 		SPDK_ERRLOG("Memory allocation failed\n");
1876 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1877 						 "Memory allocation failed");
1878 		return;
1879 	}
1880 
1881 	target = iscsi_find_tgt_node(req.name);
1882 
1883 	free(req.name);
1884 
1885 	if (target == NULL) {
1886 		SPDK_ERRLOG("target is not found\n");
1887 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1888 						 "Invalid parameters");
1889 		free(ctx);
1890 		return;
1891 	}
1892 
1893 	ctx->request = request;
1894 	ctx->target = target;
1895 	ctx->enable = req.enable;
1896 	ctx->orig_thread = spdk_get_thread();
1897 
1898 	pthread_mutex_lock(&ctx->target->mutex);
1899 	if (target->pg == NULL) {
1900 		_iscsi_enable_histogram(ctx);
1901 		thread = ctx->orig_thread;
1902 		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 		target->num_active_conns++;
1911 		thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(target->pg));
1912 		fn = _rpc_iscsi_enable_histogram;
1913 	}
1914 	pthread_mutex_unlock(&ctx->target->mutex);
1915 
1916 	spdk_thread_send_msg(thread, fn, ctx);
1917 }
1918 
1919 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
free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request * r)1930 free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request *r)
1931 {
1932 	free(r->name);
1933 }
1934 
1935 static void
rpc_iscsi_get_histogram(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)1936 rpc_iscsi_get_histogram(struct spdk_jsonrpc_request *request,
1937 			const struct spdk_json_val *params)
1938 {
1939 	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 	if (spdk_json_decode_object(params, rpc_iscsi_get_histogram_request_decoders,
1947 				    SPDK_COUNTOF(rpc_iscsi_get_histogram_request_decoders),
1948 				    &req)) {
1949 		SPDK_ERRLOG("spdk_json_decode_object failed\n");
1950 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1951 						 "spdk_json_decode_object failed");
1952 		goto free_req;
1953 	}
1954 
1955 	target = iscsi_find_tgt_node(req.name);
1956 	if (target == NULL) {
1957 		SPDK_ERRLOG("target is not found\n");
1958 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1959 						 "target not found");
1960 		goto free_req;
1961 	}
1962 
1963 	if (!target->histogram) {
1964 		SPDK_ERRLOG("target's histogram function is not enabled\n");
1965 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1966 						 "target's histogram function is not enabled");
1967 		goto free_req;
1968 	}
1969 
1970 	src_len = SPDK_HISTOGRAM_NUM_BUCKETS(target->histogram) * sizeof(uint64_t);
1971 	dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
1972 	encoded_histogram = malloc(dst_len);
1973 	if (encoded_histogram == NULL) {
1974 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1975 						 spdk_strerror(ENOMEM));
1976 		goto free_req;
1977 	}
1978 
1979 	rc = spdk_base64_encode(encoded_histogram, target->histogram->bucket, src_len);
1980 	if (rc != 0) {
1981 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1982 						 spdk_strerror(-rc));
1983 		goto free_encoded_histogram;
1984 	}
1985 
1986 	w = spdk_jsonrpc_begin_result(request);
1987 
1988 	spdk_json_write_object_begin(w);
1989 	spdk_json_write_named_string(w, "histogram", encoded_histogram);
1990 	spdk_json_write_named_int64(w, "bucket_shift", target->histogram->bucket_shift);
1991 	spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
1992 
1993 	spdk_json_write_object_end(w);
1994 	spdk_jsonrpc_end_result(request, w);
1995 
1996 free_encoded_histogram:
1997 	free(encoded_histogram);
1998 free_req:
1999 	free_rpc_iscsi_get_histogram_request(&req);
2000 }
2001 
2002 SPDK_RPC_REGISTER("iscsi_get_histogram", rpc_iscsi_get_histogram, SPDK_RPC_RUNTIME)
2003