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