xref: /spdk/lib/iscsi/init_grp.c (revision fecffda6ecf8853b82edccde429b68252f0a62c5)
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 "spdk/stdinc.h"
8 
9 #include "spdk/string.h"
10 
11 #include "spdk/log.h"
12 
13 #include "iscsi/iscsi.h"
14 #include "iscsi/init_grp.h"
15 
16 static struct spdk_iscsi_init_grp *
17 iscsi_init_grp_create(int tag)
18 {
19 	struct spdk_iscsi_init_grp *ig;
20 
21 	ig = calloc(1, sizeof(*ig));
22 	if (ig == NULL) {
23 		SPDK_ERRLOG("calloc() failed for initiator group\n");
24 		return NULL;
25 	}
26 
27 	ig->tag = tag;
28 	TAILQ_INIT(&ig->initiator_head);
29 	TAILQ_INIT(&ig->netmask_head);
30 	return ig;
31 }
32 
33 static struct spdk_iscsi_initiator_name *
34 iscsi_init_grp_find_initiator(struct spdk_iscsi_init_grp *ig, char *name)
35 {
36 	struct spdk_iscsi_initiator_name *iname;
37 
38 	TAILQ_FOREACH(iname, &ig->initiator_head, tailq) {
39 		if (!strcmp(iname->name, name)) {
40 			return iname;
41 		}
42 	}
43 	return NULL;
44 }
45 
46 static int
47 iscsi_init_grp_add_initiator(struct spdk_iscsi_init_grp *ig, char *name)
48 {
49 	struct spdk_iscsi_initiator_name *iname;
50 	char *p;
51 	size_t len;
52 
53 	if (ig->ninitiators >= MAX_INITIATOR) {
54 		SPDK_ERRLOG("> MAX_INITIATOR(=%d) is not allowed\n", MAX_INITIATOR);
55 		return -EPERM;
56 	}
57 
58 	len = strlen(name);
59 	if (len > MAX_INITIATOR_NAME) {
60 		SPDK_ERRLOG("Initiator Name is larger than 223 bytes\n");
61 		return -EINVAL;
62 	}
63 
64 	iname = iscsi_init_grp_find_initiator(ig, name);
65 	if (iname != NULL) {
66 		return -EEXIST;
67 	}
68 
69 	iname = calloc(1, sizeof(*iname));
70 	if (iname == NULL) {
71 		SPDK_ERRLOG("malloc() failed for initiator name str\n");
72 		return -ENOMEM;
73 	}
74 
75 	memcpy(iname->name, name, len);
76 
77 	/* Replace "ALL" by "ANY" if set */
78 	p = strstr(iname->name, "ALL");
79 	if (p != NULL) {
80 		SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL");
81 		SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY");
82 		memcpy(p, "ANY", 3);
83 	}
84 
85 	TAILQ_INSERT_TAIL(&ig->initiator_head, iname, tailq);
86 	ig->ninitiators++;
87 
88 	SPDK_DEBUGLOG(iscsi, "InitiatorName %s\n", name);
89 	return 0;
90 }
91 
92 static int
93 iscsi_init_grp_delete_initiator(struct spdk_iscsi_init_grp *ig, char *name)
94 {
95 	struct spdk_iscsi_initiator_name *iname;
96 
97 	iname = iscsi_init_grp_find_initiator(ig, name);
98 	if (iname == NULL) {
99 		return -ENOENT;
100 	}
101 
102 	TAILQ_REMOVE(&ig->initiator_head, iname, tailq);
103 	ig->ninitiators--;
104 	free(iname);
105 	return 0;
106 }
107 
108 static int
109 iscsi_init_grp_add_initiators(struct spdk_iscsi_init_grp *ig, int num_inames,
110 			      char **inames)
111 {
112 	int i;
113 	int rc;
114 
115 	for (i = 0; i < num_inames; i++) {
116 		rc = iscsi_init_grp_add_initiator(ig, inames[i]);
117 		if (rc < 0) {
118 			goto cleanup;
119 		}
120 	}
121 	return 0;
122 
123 cleanup:
124 	for (; i > 0; --i) {
125 		iscsi_init_grp_delete_initiator(ig, inames[i - 1]);
126 	}
127 	return rc;
128 }
129 
130 static void
131 iscsi_init_grp_delete_all_initiators(struct spdk_iscsi_init_grp *ig)
132 {
133 	struct spdk_iscsi_initiator_name *iname, *tmp;
134 
135 	TAILQ_FOREACH_SAFE(iname, &ig->initiator_head, tailq, tmp) {
136 		TAILQ_REMOVE(&ig->initiator_head, iname, tailq);
137 		ig->ninitiators--;
138 		free(iname);
139 	}
140 }
141 
142 static int
143 iscsi_init_grp_delete_initiators(struct spdk_iscsi_init_grp *ig, int num_inames, char **inames)
144 {
145 	int i;
146 	int rc;
147 
148 	for (i = 0; i < num_inames; i++) {
149 		rc = iscsi_init_grp_delete_initiator(ig, inames[i]);
150 		if (rc < 0) {
151 			goto cleanup;
152 		}
153 	}
154 	return 0;
155 
156 cleanup:
157 	for (; i > 0; --i) {
158 		rc = iscsi_init_grp_add_initiator(ig, inames[i - 1]);
159 		if (rc != 0) {
160 			iscsi_init_grp_delete_all_initiators(ig);
161 			break;
162 		}
163 	}
164 	return -1;
165 }
166 
167 static struct spdk_iscsi_initiator_netmask *
168 iscsi_init_grp_find_netmask(struct spdk_iscsi_init_grp *ig, const char *mask)
169 {
170 	struct spdk_iscsi_initiator_netmask *netmask;
171 
172 	TAILQ_FOREACH(netmask, &ig->netmask_head, tailq) {
173 		if (!strcmp(netmask->mask, mask)) {
174 			return netmask;
175 		}
176 	}
177 	return NULL;
178 }
179 
180 static int
181 iscsi_init_grp_add_netmask(struct spdk_iscsi_init_grp *ig, char *mask)
182 {
183 	struct spdk_iscsi_initiator_netmask *imask;
184 	char *p;
185 	size_t len;
186 
187 	if (ig->nnetmasks >= MAX_NETMASK) {
188 		SPDK_ERRLOG("> MAX_NETMASK(=%d) is not allowed\n", MAX_NETMASK);
189 		return -EPERM;
190 	}
191 
192 	len = strlen(mask);
193 	if (len > MAX_INITIATOR_ADDR) {
194 		SPDK_ERRLOG("Initiator Name is larger than %d bytes\n", MAX_INITIATOR_ADDR);
195 		return -EINVAL;
196 	}
197 
198 	imask = iscsi_init_grp_find_netmask(ig, mask);
199 	if (imask != NULL) {
200 		return -EEXIST;
201 	}
202 
203 	imask = calloc(1, sizeof(*imask));
204 	if (imask == NULL) {
205 		SPDK_ERRLOG("malloc() failed for initiator mask str\n");
206 		return -ENOMEM;
207 	}
208 
209 	memcpy(imask->mask, mask, len);
210 
211 	/* Replace "ALL" by "ANY" if set */
212 	p = strstr(imask->mask, "ALL");
213 	if (p != NULL) {
214 		SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL");
215 		SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY");
216 		memcpy(p, "ANY", 3);
217 	}
218 
219 	TAILQ_INSERT_TAIL(&ig->netmask_head, imask, tailq);
220 	ig->nnetmasks++;
221 
222 	SPDK_DEBUGLOG(iscsi, "Netmask %s\n", mask);
223 	return 0;
224 }
225 
226 static int
227 iscsi_init_grp_delete_netmask(struct spdk_iscsi_init_grp *ig, char *mask)
228 {
229 	struct spdk_iscsi_initiator_netmask *imask;
230 
231 	imask = iscsi_init_grp_find_netmask(ig, mask);
232 	if (imask == NULL) {
233 		return -ENOENT;
234 	}
235 
236 	TAILQ_REMOVE(&ig->netmask_head, imask, tailq);
237 	ig->nnetmasks--;
238 	free(imask);
239 	return 0;
240 }
241 
242 static int
243 iscsi_init_grp_add_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks)
244 {
245 	int i;
246 	int rc;
247 
248 	for (i = 0; i < num_imasks; i++) {
249 		rc = iscsi_init_grp_add_netmask(ig, imasks[i]);
250 		if (rc != 0) {
251 			goto cleanup;
252 		}
253 	}
254 	return 0;
255 
256 cleanup:
257 	for (; i > 0; --i) {
258 		iscsi_init_grp_delete_netmask(ig, imasks[i - 1]);
259 	}
260 	return rc;
261 }
262 
263 static void
264 iscsi_init_grp_delete_all_netmasks(struct spdk_iscsi_init_grp *ig)
265 {
266 	struct spdk_iscsi_initiator_netmask *imask, *tmp;
267 
268 	TAILQ_FOREACH_SAFE(imask, &ig->netmask_head, tailq, tmp) {
269 		TAILQ_REMOVE(&ig->netmask_head, imask, tailq);
270 		ig->nnetmasks--;
271 		free(imask);
272 	}
273 }
274 
275 static int
276 iscsi_init_grp_delete_netmasks(struct spdk_iscsi_init_grp *ig, int num_imasks, char **imasks)
277 {
278 	int i;
279 	int rc;
280 
281 	for (i = 0; i < num_imasks; i++) {
282 		rc = iscsi_init_grp_delete_netmask(ig, imasks[i]);
283 		if (rc != 0) {
284 			goto cleanup;
285 		}
286 	}
287 	return 0;
288 
289 cleanup:
290 	for (; i > 0; --i) {
291 		rc = iscsi_init_grp_add_netmask(ig, imasks[i - 1]);
292 		if (rc != 0) {
293 			iscsi_init_grp_delete_all_netmasks(ig);
294 			break;
295 		}
296 	}
297 	return -1;
298 }
299 
300 int
301 iscsi_init_grp_register(struct spdk_iscsi_init_grp *ig)
302 {
303 	struct spdk_iscsi_init_grp *tmp;
304 	int rc = -1;
305 
306 	assert(ig != NULL);
307 
308 	pthread_mutex_lock(&g_iscsi.mutex);
309 	tmp = iscsi_init_grp_find_by_tag(ig->tag);
310 	if (tmp == NULL) {
311 		TAILQ_INSERT_TAIL(&g_iscsi.ig_head, ig, tailq);
312 		rc = 0;
313 	}
314 	pthread_mutex_unlock(&g_iscsi.mutex);
315 
316 	return rc;
317 }
318 
319 /*
320  * Create initiator group from list of initiator ip/hostnames and netmasks
321  * The initiator hostname/netmask lists are allocated by the caller on the
322  * heap.  Freed later by common initiator_group_destroy() code
323  */
324 int
325 iscsi_init_grp_create_from_initiator_list(int tag,
326 		int num_initiator_names,
327 		char **initiator_names,
328 		int num_initiator_masks,
329 		char **initiator_masks)
330 {
331 	int rc = -1;
332 	struct spdk_iscsi_init_grp *ig = NULL;
333 
334 	SPDK_DEBUGLOG(iscsi,
335 		      "add initiator group (from initiator list) tag=%d, #initiators=%d, #masks=%d\n",
336 		      tag, num_initiator_names, num_initiator_masks);
337 
338 	ig = iscsi_init_grp_create(tag);
339 	if (!ig) {
340 		SPDK_ERRLOG("initiator group create error (%d)\n", tag);
341 		return rc;
342 	}
343 
344 	rc = iscsi_init_grp_add_initiators(ig, num_initiator_names,
345 					   initiator_names);
346 	if (rc < 0) {
347 		SPDK_ERRLOG("add initiator name error\n");
348 		goto cleanup;
349 	}
350 
351 	rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks,
352 					 initiator_masks);
353 	if (rc < 0) {
354 		SPDK_ERRLOG("add initiator netmask error\n");
355 		goto cleanup;
356 	}
357 
358 	rc = iscsi_init_grp_register(ig);
359 	if (rc < 0) {
360 		SPDK_ERRLOG("initiator group register error (%d)\n", tag);
361 		goto cleanup;
362 	}
363 	return 0;
364 
365 cleanup:
366 	iscsi_init_grp_destroy(ig);
367 	return rc;
368 }
369 
370 int
371 iscsi_init_grp_add_initiators_from_initiator_list(int tag,
372 		int num_initiator_names,
373 		char **initiator_names,
374 		int num_initiator_masks,
375 		char **initiator_masks)
376 {
377 	int rc = -1;
378 	struct spdk_iscsi_init_grp *ig;
379 
380 	SPDK_DEBUGLOG(iscsi,
381 		      "add initiator to initiator group: tag=%d, #initiators=%d, #masks=%d\n",
382 		      tag, num_initiator_names, num_initiator_masks);
383 
384 	pthread_mutex_lock(&g_iscsi.mutex);
385 	ig = iscsi_init_grp_find_by_tag(tag);
386 	if (!ig) {
387 		pthread_mutex_unlock(&g_iscsi.mutex);
388 		SPDK_ERRLOG("initiator group (%d) is not found\n", tag);
389 		return rc;
390 	}
391 
392 	rc = iscsi_init_grp_add_initiators(ig, num_initiator_names,
393 					   initiator_names);
394 	if (rc < 0) {
395 		SPDK_ERRLOG("add initiator name error\n");
396 		goto error;
397 	}
398 
399 	rc = iscsi_init_grp_add_netmasks(ig, num_initiator_masks,
400 					 initiator_masks);
401 	if (rc < 0) {
402 		SPDK_ERRLOG("add initiator netmask error\n");
403 		iscsi_init_grp_delete_initiators(ig, num_initiator_names,
404 						 initiator_names);
405 	}
406 
407 error:
408 	pthread_mutex_unlock(&g_iscsi.mutex);
409 	return rc;
410 }
411 
412 int
413 iscsi_init_grp_delete_initiators_from_initiator_list(int tag,
414 		int num_initiator_names,
415 		char **initiator_names,
416 		int num_initiator_masks,
417 		char **initiator_masks)
418 {
419 	int rc = -1;
420 	struct spdk_iscsi_init_grp *ig;
421 
422 	SPDK_DEBUGLOG(iscsi,
423 		      "delete initiator from initiator group: tag=%d, #initiators=%d, #masks=%d\n",
424 		      tag, num_initiator_names, num_initiator_masks);
425 
426 	pthread_mutex_lock(&g_iscsi.mutex);
427 	ig = iscsi_init_grp_find_by_tag(tag);
428 	if (!ig) {
429 		pthread_mutex_unlock(&g_iscsi.mutex);
430 		SPDK_ERRLOG("initiator group (%d) is not found\n", tag);
431 		return rc;
432 	}
433 
434 	rc = iscsi_init_grp_delete_initiators(ig, num_initiator_names,
435 					      initiator_names);
436 	if (rc < 0) {
437 		SPDK_ERRLOG("delete initiator name error\n");
438 		goto error;
439 	}
440 
441 	rc = iscsi_init_grp_delete_netmasks(ig, num_initiator_masks,
442 					    initiator_masks);
443 	if (rc < 0) {
444 		SPDK_ERRLOG("delete initiator netmask error\n");
445 		iscsi_init_grp_add_initiators(ig, num_initiator_names,
446 					      initiator_names);
447 		goto error;
448 	}
449 
450 error:
451 	pthread_mutex_unlock(&g_iscsi.mutex);
452 	return rc;
453 }
454 
455 void
456 iscsi_init_grp_destroy(struct spdk_iscsi_init_grp *ig)
457 {
458 	if (!ig) {
459 		return;
460 	}
461 
462 	iscsi_init_grp_delete_all_initiators(ig);
463 	iscsi_init_grp_delete_all_netmasks(ig);
464 	free(ig);
465 };
466 
467 struct spdk_iscsi_init_grp *
468 iscsi_init_grp_find_by_tag(int tag)
469 {
470 	struct spdk_iscsi_init_grp *ig;
471 
472 	TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) {
473 		if (ig->tag == tag) {
474 			return ig;
475 		}
476 	}
477 
478 	return NULL;
479 }
480 
481 void
482 iscsi_init_grps_destroy(void)
483 {
484 	struct spdk_iscsi_init_grp *ig, *tmp;
485 
486 	SPDK_DEBUGLOG(iscsi, "iscsi_init_grp_array_destroy\n");
487 	pthread_mutex_lock(&g_iscsi.mutex);
488 	TAILQ_FOREACH_SAFE(ig, &g_iscsi.ig_head, tailq, tmp) {
489 		TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq);
490 		iscsi_init_grp_destroy(ig);
491 	}
492 	pthread_mutex_unlock(&g_iscsi.mutex);
493 }
494 
495 struct spdk_iscsi_init_grp *
496 iscsi_init_grp_unregister(int tag)
497 {
498 	struct spdk_iscsi_init_grp *ig;
499 
500 	pthread_mutex_lock(&g_iscsi.mutex);
501 	TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) {
502 		if (ig->tag == tag) {
503 			TAILQ_REMOVE(&g_iscsi.ig_head, ig, tailq);
504 			pthread_mutex_unlock(&g_iscsi.mutex);
505 			return ig;
506 		}
507 	}
508 	pthread_mutex_unlock(&g_iscsi.mutex);
509 	return NULL;
510 }
511 
512 static void
513 iscsi_init_grp_info_json(struct spdk_iscsi_init_grp *ig,
514 			 struct spdk_json_write_ctx *w)
515 {
516 	struct spdk_iscsi_initiator_name *iname;
517 	struct spdk_iscsi_initiator_netmask *imask;
518 
519 	spdk_json_write_object_begin(w);
520 
521 	spdk_json_write_named_int32(w, "tag", ig->tag);
522 
523 	spdk_json_write_named_array_begin(w, "initiators");
524 	TAILQ_FOREACH(iname, &ig->initiator_head, tailq) {
525 		spdk_json_write_string(w, iname->name);
526 	}
527 	spdk_json_write_array_end(w);
528 
529 	spdk_json_write_named_array_begin(w, "netmasks");
530 	TAILQ_FOREACH(imask, &ig->netmask_head, tailq) {
531 		spdk_json_write_string(w, imask->mask);
532 	}
533 	spdk_json_write_array_end(w);
534 
535 	spdk_json_write_object_end(w);
536 }
537 
538 static void
539 iscsi_init_grp_config_json(struct spdk_iscsi_init_grp *ig,
540 			   struct spdk_json_write_ctx *w)
541 {
542 	spdk_json_write_object_begin(w);
543 
544 	spdk_json_write_named_string(w, "method", "iscsi_create_initiator_group");
545 
546 	spdk_json_write_name(w, "params");
547 	iscsi_init_grp_info_json(ig, w);
548 
549 	spdk_json_write_object_end(w);
550 }
551 
552 void
553 iscsi_init_grps_info_json(struct spdk_json_write_ctx *w)
554 {
555 	struct spdk_iscsi_init_grp *ig;
556 
557 	TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) {
558 		iscsi_init_grp_info_json(ig, w);
559 	}
560 }
561 
562 void
563 iscsi_init_grps_config_json(struct spdk_json_write_ctx *w)
564 {
565 	struct spdk_iscsi_init_grp *ig;
566 
567 	TAILQ_FOREACH(ig, &g_iscsi.ig_head, tailq) {
568 		iscsi_init_grp_config_json(ig, w);
569 	}
570 }
571