4 * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
5 * Copyright (c) Intel Corporation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
18 * * Neither the name of Intel Corporation nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include "spdk/stdinc.h"
37 #include "spdk/conf.h"
38 #include "spdk/string.h"
40 #include "spdk_internal/log.h"
42 #include "iscsi/iscsi.h"
43 #include "iscsi/init_grp.h"
45 static struct spdk_iscsi_init_grp
*
46 iscsi_init_grp_create(int tag
)
48 struct spdk_iscsi_init_grp
*ig
;
50 ig
= calloc(1, sizeof(*ig
));
52 SPDK_ERRLOG("calloc() failed for initiator group\n");
57 TAILQ_INIT(&ig
->initiator_head
);
58 TAILQ_INIT(&ig
->netmask_head
);
62 static struct spdk_iscsi_initiator_name
*
63 iscsi_init_grp_find_initiator(struct spdk_iscsi_init_grp
*ig
, char *name
)
65 struct spdk_iscsi_initiator_name
*iname
;
67 TAILQ_FOREACH(iname
, &ig
->initiator_head
, tailq
) {
68 if (!strcmp(iname
->name
, name
)) {
76 iscsi_init_grp_add_initiator(struct spdk_iscsi_init_grp
*ig
, char *name
)
78 struct spdk_iscsi_initiator_name
*iname
;
82 if (ig
->ninitiators
>= MAX_INITIATOR
) {
83 SPDK_ERRLOG("> MAX_INITIATOR(=%d) is not allowed\n", MAX_INITIATOR
);
88 if (len
> MAX_INITIATOR_NAME
) {
89 SPDK_ERRLOG("Initiator Name is larger than 223 bytes\n");
93 iname
= iscsi_init_grp_find_initiator(ig
, name
);
98 iname
= calloc(1, sizeof(*iname
));
100 SPDK_ERRLOG("malloc() failed for initiator name str\n");
104 memcpy(iname
->name
, name
, len
);
106 /* Replace "ALL" by "ANY" if set */
107 p
= strstr(iname
->name
, "ALL");
109 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL");
110 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY");
114 TAILQ_INSERT_TAIL(&ig
->initiator_head
, iname
, tailq
);
117 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "InitiatorName %s\n", name
);
122 iscsi_init_grp_delete_initiator(struct spdk_iscsi_init_grp
*ig
, char *name
)
124 struct spdk_iscsi_initiator_name
*iname
;
126 iname
= iscsi_init_grp_find_initiator(ig
, name
);
131 TAILQ_REMOVE(&ig
->initiator_head
, iname
, tailq
);
138 iscsi_init_grp_add_initiators(struct spdk_iscsi_init_grp
*ig
, int num_inames
,
144 for (i
= 0; i
< num_inames
; i
++) {
145 rc
= iscsi_init_grp_add_initiator(ig
, inames
[i
]);
154 iscsi_init_grp_delete_initiator(ig
, inames
[i
- 1]);
160 iscsi_init_grp_delete_all_initiators(struct spdk_iscsi_init_grp
*ig
)
162 struct spdk_iscsi_initiator_name
*iname
, *tmp
;
164 TAILQ_FOREACH_SAFE(iname
, &ig
->initiator_head
, tailq
, tmp
) {
165 TAILQ_REMOVE(&ig
->initiator_head
, iname
, tailq
);
172 iscsi_init_grp_delete_initiators(struct spdk_iscsi_init_grp
*ig
, int num_inames
, char **inames
)
177 for (i
= 0; i
< num_inames
; i
++) {
178 rc
= iscsi_init_grp_delete_initiator(ig
, inames
[i
]);
187 rc
= iscsi_init_grp_add_initiator(ig
, inames
[i
- 1]);
189 iscsi_init_grp_delete_all_initiators(ig
);
196 static struct spdk_iscsi_initiator_netmask
*
197 iscsi_init_grp_find_netmask(struct spdk_iscsi_init_grp
*ig
, const char *mask
)
199 struct spdk_iscsi_initiator_netmask
*netmask
;
201 TAILQ_FOREACH(netmask
, &ig
->netmask_head
, tailq
) {
202 if (!strcmp(netmask
->mask
, mask
)) {
210 iscsi_init_grp_add_netmask(struct spdk_iscsi_init_grp
*ig
, char *mask
)
212 struct spdk_iscsi_initiator_netmask
*imask
;
216 if (ig
->nnetmasks
>= MAX_NETMASK
) {
217 SPDK_ERRLOG("> MAX_NETMASK(=%d) is not allowed\n", MAX_NETMASK
);
222 if (len
> MAX_INITIATOR_ADDR
) {
223 SPDK_ERRLOG("Initiator Name is larger than %d bytes\n", MAX_INITIATOR_ADDR
);
227 imask
= iscsi_init_grp_find_netmask(ig
, mask
);
232 imask
= calloc(1, sizeof(*imask
));
234 SPDK_ERRLOG("malloc() failed for inititator mask str\n");
238 memcpy(imask
->mask
, mask
, len
);
240 /* Replace "ALL" by "ANY" if set */
241 p
= strstr(imask
->mask
, "ALL");
243 SPDK_WARNLOG("Please use \"%s\" instead of \"%s\"\n", "ANY", "ALL");
244 SPDK_WARNLOG("Converting \"%s\" to \"%s\" automatically\n", "ALL", "ANY");
248 TAILQ_INSERT_TAIL(&ig
->netmask_head
, imask
, tailq
);
251 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Netmask %s\n", mask
);
256 iscsi_init_grp_delete_netmask(struct spdk_iscsi_init_grp
*ig
, char *mask
)
258 struct spdk_iscsi_initiator_netmask
*imask
;
260 imask
= iscsi_init_grp_find_netmask(ig
, mask
);
265 TAILQ_REMOVE(&ig
->netmask_head
, imask
, tailq
);
272 iscsi_init_grp_add_netmasks(struct spdk_iscsi_init_grp
*ig
, int num_imasks
, char **imasks
)
277 for (i
= 0; i
< num_imasks
; i
++) {
278 rc
= iscsi_init_grp_add_netmask(ig
, imasks
[i
]);
287 iscsi_init_grp_delete_netmask(ig
, imasks
[i
- 1]);
293 iscsi_init_grp_delete_all_netmasks(struct spdk_iscsi_init_grp
*ig
)
295 struct spdk_iscsi_initiator_netmask
*imask
, *tmp
;
297 TAILQ_FOREACH_SAFE(imask
, &ig
->netmask_head
, tailq
, tmp
) {
298 TAILQ_REMOVE(&ig
->netmask_head
, imask
, tailq
);
305 iscsi_init_grp_delete_netmasks(struct spdk_iscsi_init_grp
*ig
, int num_imasks
, char **imasks
)
310 for (i
= 0; i
< num_imasks
; i
++) {
311 rc
= iscsi_init_grp_delete_netmask(ig
, imasks
[i
]);
320 rc
= iscsi_init_grp_add_netmask(ig
, imasks
[i
- 1]);
322 iscsi_init_grp_delete_all_netmasks(ig
);
329 /* Read spdk iscsi target's config file and create initiator group */
331 iscsi_parse_init_grp(struct spdk_conf_section
*sp
)
334 const char *val
= NULL
;
335 int num_initiator_names
;
336 int num_initiator_masks
;
337 char **initiators
= NULL
, **netmasks
= NULL
;
338 int tag
= spdk_conf_section_get_num(sp
);
340 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "add initiator group %d\n", tag
);
342 val
= spdk_conf_section_get_val(sp
, "Comment");
344 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Comment %s\n", val
);
347 /* counts number of definitions */
349 val
= spdk_conf_section_get_nval(sp
, "InitiatorName", i
);
355 SPDK_ERRLOG("num_initiator_names = 0\n");
358 num_initiator_names
= i
;
359 if (num_initiator_names
> MAX_INITIATOR
) {
360 SPDK_ERRLOG("%d > MAX_INITIATOR\n", num_initiator_names
);
364 val
= spdk_conf_section_get_nval(sp
, "Netmask", i
);
370 SPDK_ERRLOG("num_initiator_mask = 0\n");
373 num_initiator_masks
= i
;
374 if (num_initiator_masks
> MAX_NETMASK
) {
375 SPDK_ERRLOG("%d > MAX_NETMASK\n", num_initiator_masks
);
379 initiators
= calloc(num_initiator_names
, sizeof(char *));
381 SPDK_ERRLOG("calloc() failed for temp initiator name array\n");
384 for (i
= 0; i
< num_initiator_names
; i
++) {
385 val
= spdk_conf_section_get_nval(sp
, "InitiatorName", i
);
387 SPDK_ERRLOG("InitiatorName %d not found\n", i
);
391 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "InitiatorName %s\n", val
);
392 initiators
[i
] = strdup(val
);
393 if (!initiators
[i
]) {
394 SPDK_ERRLOG("strdup() failed for temp initiator name\n");
399 netmasks
= calloc(num_initiator_masks
, sizeof(char *));
401 SPDK_ERRLOG("malloc() failed for portal group\n");
405 for (i
= 0; i
< num_initiator_masks
; i
++) {
406 val
= spdk_conf_section_get_nval(sp
, "Netmask", i
);
408 SPDK_ERRLOG("Netmask %d not found\n", i
);
412 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "Netmask %s\n", val
);
413 netmasks
[i
] = strdup(val
);
415 SPDK_ERRLOG("strdup() failed for temp initiator mask\n");
421 rc
= iscsi_init_grp_create_from_initiator_list(tag
,
422 num_initiator_names
, initiators
, num_initiator_masks
, netmasks
);
426 for (i
= 0; i
< num_initiator_names
; i
++) {
434 for (i
= 0; i
< num_initiator_masks
; i
++) {
445 iscsi_init_grp_register(struct spdk_iscsi_init_grp
*ig
)
447 struct spdk_iscsi_init_grp
*tmp
;
452 pthread_mutex_lock(&g_iscsi
.mutex
);
453 tmp
= iscsi_init_grp_find_by_tag(ig
->tag
);
455 TAILQ_INSERT_TAIL(&g_iscsi
.ig_head
, ig
, tailq
);
458 pthread_mutex_unlock(&g_iscsi
.mutex
);
464 * Create initiator group from list of initiator ip/hostnames and netmasks
465 * The initiator hostname/netmask lists are allocated by the caller on the
466 * heap. Freed later by common initiator_group_destroy() code
469 iscsi_init_grp_create_from_initiator_list(int tag
,
470 int num_initiator_names
,
471 char **initiator_names
,
472 int num_initiator_masks
,
473 char **initiator_masks
)
476 struct spdk_iscsi_init_grp
*ig
= NULL
;
478 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
479 "add initiator group (from initiator list) tag=%d, #initiators=%d, #masks=%d\n",
480 tag
, num_initiator_names
, num_initiator_masks
);
482 ig
= iscsi_init_grp_create(tag
);
484 SPDK_ERRLOG("initiator group create error (%d)\n", tag
);
488 rc
= iscsi_init_grp_add_initiators(ig
, num_initiator_names
,
491 SPDK_ERRLOG("add initiator name error\n");
495 rc
= iscsi_init_grp_add_netmasks(ig
, num_initiator_masks
,
498 SPDK_ERRLOG("add initiator netmask error\n");
502 rc
= iscsi_init_grp_register(ig
);
504 SPDK_ERRLOG("initiator group register error (%d)\n", tag
);
510 iscsi_init_grp_destroy(ig
);
515 iscsi_init_grp_add_initiators_from_initiator_list(int tag
,
516 int num_initiator_names
,
517 char **initiator_names
,
518 int num_initiator_masks
,
519 char **initiator_masks
)
522 struct spdk_iscsi_init_grp
*ig
;
524 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
525 "add initiator to initiator group: tag=%d, #initiators=%d, #masks=%d\n",
526 tag
, num_initiator_names
, num_initiator_masks
);
528 pthread_mutex_lock(&g_iscsi
.mutex
);
529 ig
= iscsi_init_grp_find_by_tag(tag
);
531 pthread_mutex_unlock(&g_iscsi
.mutex
);
532 SPDK_ERRLOG("initiator group (%d) is not found\n", tag
);
536 rc
= iscsi_init_grp_add_initiators(ig
, num_initiator_names
,
539 SPDK_ERRLOG("add initiator name error\n");
543 rc
= iscsi_init_grp_add_netmasks(ig
, num_initiator_masks
,
546 SPDK_ERRLOG("add initiator netmask error\n");
547 iscsi_init_grp_delete_initiators(ig
, num_initiator_names
,
552 pthread_mutex_unlock(&g_iscsi
.mutex
);
557 iscsi_init_grp_delete_initiators_from_initiator_list(int tag
,
558 int num_initiator_names
,
559 char **initiator_names
,
560 int num_initiator_masks
,
561 char **initiator_masks
)
564 struct spdk_iscsi_init_grp
*ig
;
566 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
,
567 "delete initiator from initiator group: tag=%d, #initiators=%d, #masks=%d\n",
568 tag
, num_initiator_names
, num_initiator_masks
);
570 pthread_mutex_lock(&g_iscsi
.mutex
);
571 ig
= iscsi_init_grp_find_by_tag(tag
);
573 pthread_mutex_unlock(&g_iscsi
.mutex
);
574 SPDK_ERRLOG("initiator group (%d) is not found\n", tag
);
578 rc
= iscsi_init_grp_delete_initiators(ig
, num_initiator_names
,
581 SPDK_ERRLOG("delete initiator name error\n");
585 rc
= iscsi_init_grp_delete_netmasks(ig
, num_initiator_masks
,
588 SPDK_ERRLOG("delete initiator netmask error\n");
589 iscsi_init_grp_add_initiators(ig
, num_initiator_names
,
595 pthread_mutex_unlock(&g_iscsi
.mutex
);
600 iscsi_init_grp_destroy(struct spdk_iscsi_init_grp
*ig
)
606 iscsi_init_grp_delete_all_initiators(ig
);
607 iscsi_init_grp_delete_all_netmasks(ig
);
611 struct spdk_iscsi_init_grp
*
612 iscsi_init_grp_find_by_tag(int tag
)
614 struct spdk_iscsi_init_grp
*ig
;
616 TAILQ_FOREACH(ig
, &g_iscsi
.ig_head
, tailq
) {
617 if (ig
->tag
== tag
) {
626 iscsi_parse_init_grps(void)
628 struct spdk_conf_section
*sp
;
631 sp
= spdk_conf_first_section(NULL
);
633 if (spdk_conf_section_match_prefix(sp
, "InitiatorGroup")) {
634 if (spdk_conf_section_get_num(sp
) == 0) {
635 SPDK_ERRLOG("Group 0 is invalid\n");
638 rc
= iscsi_parse_init_grp(sp
);
640 SPDK_ERRLOG("parse_init_group() failed\n");
644 sp
= spdk_conf_next_section(sp
);
650 iscsi_init_grps_destroy(void)
652 struct spdk_iscsi_init_grp
*ig
, *tmp
;
654 SPDK_DEBUGLOG(SPDK_LOG_ISCSI
, "iscsi_init_grp_array_destroy\n");
655 pthread_mutex_lock(&g_iscsi
.mutex
);
656 TAILQ_FOREACH_SAFE(ig
, &g_iscsi
.ig_head
, tailq
, tmp
) {
657 TAILQ_REMOVE(&g_iscsi
.ig_head
, ig
, tailq
);
658 iscsi_init_grp_destroy(ig
);
660 pthread_mutex_unlock(&g_iscsi
.mutex
);
663 struct spdk_iscsi_init_grp
*
664 iscsi_init_grp_unregister(int tag
)
666 struct spdk_iscsi_init_grp
*ig
;
668 pthread_mutex_lock(&g_iscsi
.mutex
);
669 TAILQ_FOREACH(ig
, &g_iscsi
.ig_head
, tailq
) {
670 if (ig
->tag
== tag
) {
671 TAILQ_REMOVE(&g_iscsi
.ig_head
, ig
, tailq
);
672 pthread_mutex_unlock(&g_iscsi
.mutex
);
676 pthread_mutex_unlock(&g_iscsi
.mutex
);
680 static const char *initiator_group_section
= \
682 "# Users must change the InitiatorGroup section(s) to match the IP\n"
683 "# addresses and initiator configuration in their environment.\n"
684 "# Netmask can be used to specify a single IP address or a range of IP addresses\n"
685 "# Netmask 192.168.1.20 <== single IP address\n"
686 "# Netmask 192.168.1.0/24 <== IP range 192.168.1.*\n";
688 #define INITIATOR_GROUP_TMPL \
689 "[InitiatorGroup%d]\n" \
690 " Comment \"Initiator Group%d\"\n"
692 #define INITIATOR_TMPL \
695 #define NETMASK_TMPL \
699 iscsi_init_grps_config_text(FILE *fp
)
701 struct spdk_iscsi_init_grp
*ig
;
702 struct spdk_iscsi_initiator_name
*iname
;
703 struct spdk_iscsi_initiator_netmask
*imask
;
705 /* Create initiator group section */
706 fprintf(fp
, "%s", initiator_group_section
);
708 /* Dump initiator groups */
709 TAILQ_FOREACH(ig
, &g_iscsi
.ig_head
, tailq
) {
710 if (NULL
== ig
) { continue; }
711 fprintf(fp
, INITIATOR_GROUP_TMPL
, ig
->tag
, ig
->tag
);
713 /* Dump initiators */
714 fprintf(fp
, INITIATOR_TMPL
);
715 TAILQ_FOREACH(iname
, &ig
->initiator_head
, tailq
) {
716 fprintf(fp
, "%s ", iname
->name
);
721 fprintf(fp
, NETMASK_TMPL
);
722 TAILQ_FOREACH(imask
, &ig
->netmask_head
, tailq
) {
723 fprintf(fp
, "%s ", imask
->mask
);
730 iscsi_init_grp_info_json(struct spdk_iscsi_init_grp
*ig
,
731 struct spdk_json_write_ctx
*w
)
733 struct spdk_iscsi_initiator_name
*iname
;
734 struct spdk_iscsi_initiator_netmask
*imask
;
736 spdk_json_write_object_begin(w
);
738 spdk_json_write_named_int32(w
, "tag", ig
->tag
);
740 spdk_json_write_named_array_begin(w
, "initiators");
741 TAILQ_FOREACH(iname
, &ig
->initiator_head
, tailq
) {
742 spdk_json_write_string(w
, iname
->name
);
744 spdk_json_write_array_end(w
);
746 spdk_json_write_named_array_begin(w
, "netmasks");
747 TAILQ_FOREACH(imask
, &ig
->netmask_head
, tailq
) {
748 spdk_json_write_string(w
, imask
->mask
);
750 spdk_json_write_array_end(w
);
752 spdk_json_write_object_end(w
);
756 iscsi_init_grp_config_json(struct spdk_iscsi_init_grp
*ig
,
757 struct spdk_json_write_ctx
*w
)
759 spdk_json_write_object_begin(w
);
761 spdk_json_write_named_string(w
, "method", "iscsi_create_initiator_group");
763 spdk_json_write_name(w
, "params");
764 iscsi_init_grp_info_json(ig
, w
);
766 spdk_json_write_object_end(w
);
770 iscsi_init_grps_info_json(struct spdk_json_write_ctx
*w
)
772 struct spdk_iscsi_init_grp
*ig
;
774 TAILQ_FOREACH(ig
, &g_iscsi
.ig_head
, tailq
) {
775 iscsi_init_grp_info_json(ig
, w
);
780 iscsi_init_grps_config_json(struct spdk_json_write_ctx
*w
)
782 struct spdk_iscsi_init_grp
*ig
;
784 TAILQ_FOREACH(ig
, &g_iscsi
.ig_head
, tailq
) {
785 iscsi_init_grp_config_json(ig
, w
);