1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * iSCSI session interfaces
26  */
27 
28 #include "iscsi.h"		/* main header */
29 #include <sys/scsi/adapters/iscsi_if.h>		/* ioctl interfaces */
30 /* protocol structs and defines */
31 #include <sys/iscsi_protocol.h>
32 #include "iscsi_targetparam.h"
33 #include "persistent.h"
34 #include <sys/scsi/adapters/iscsi_door.h>
35 #include <sys/dlpi.h>
36 #include <sys/ethernet.h>
37 #include <sys/utsname.h>
38 
39 static iscsi_targetparams_t iscsi_targets;
40 static iscsi_targetparam_entry_t *iscsi_targetparam_create();
41 
42 /*
43  * Initializes the target list structure.  Called from iscsi_attach.
44  */
45 void
iscsi_targetparam_init()46 iscsi_targetparam_init() {
47     iscsi_targets.target_list = NULL;
48     rw_init(&(iscsi_targets.target_list_lock), NULL,
49 	    RW_DRIVER, NULL);
50 }
51 
52 /*
53  * Frees target param list and destroys the list lock.
54  */
55 void
iscsi_targetparam_cleanup()56 iscsi_targetparam_cleanup() {
57 	iscsi_targetparam_entry_t *curr_entry, *tmp_entry;
58 
59 	iscsi_targetparam_lock_list(RW_WRITER);
60 
61 	curr_entry = iscsi_targets.target_list;
62 	while (curr_entry) {
63 		tmp_entry = curr_entry->next;
64 		kmem_free(curr_entry, sizeof (iscsi_targetparam_entry_t));
65 		curr_entry = tmp_entry;
66 	}
67 
68 	iscsi_targetparam_unlock_list();
69 	rw_destroy(&iscsi_targets.target_list_lock);
70 }
71 
72 /*
73  * Creates a target param entry and adds it to the target param
74  * entry list.
75  *
76  */
77 static iscsi_targetparam_entry_t *
iscsi_targetparam_create(uchar_t * name)78 iscsi_targetparam_create(uchar_t *name) {
79 	iscsi_targetparam_entry_t *target;
80 
81 	ASSERT(name != NULL);
82 
83 	target = kmem_alloc(sizeof (iscsi_targetparam_entry_t),
84 		KM_SLEEP);
85 	(void) strlcpy((char *)target->target_name, (char *)name,
86 		sizeof (target->target_name));
87 
88 	/* assign unique key for the target */
89 	mutex_enter(&iscsi_oid_mutex);
90 	target->target_oid = iscsi_oid++;
91 	mutex_exit(&iscsi_oid_mutex);
92 
93 	/* Add new target to the target list */
94 	iscsi_targetparam_lock_list(RW_WRITER);
95 	if (iscsi_targets.target_list == NULL) {
96 		iscsi_targets.target_list = target;
97 		iscsi_targets.target_list->next = NULL;
98 	} else {
99 		target->next = iscsi_targets.target_list;
100 		iscsi_targets.target_list = target;
101 	}
102 	iscsi_targetparam_unlock_list();
103 	return (target);
104 }
105 
106 /*
107  * Returns a target param entry's oid given the target name.  If the target
108  * param entry cannot be found one is created and the new oid is returned.
109  *
110  */
111 uint32_t
iscsi_targetparam_get_oid(uchar_t * name)112 iscsi_targetparam_get_oid(uchar_t *name) {
113 	int name_length;
114 	iscsi_targetparam_entry_t *curr_entry;
115 
116 	ASSERT(name != NULL);
117 	name_length = strlen((char *)name);
118 
119 	iscsi_targetparam_lock_list(RW_READER);
120 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
121 	while (curr_entry != NULL) {
122 		if ((name_length == strlen((char *)curr_entry->target_name)) &&
123 		(bcmp(curr_entry->target_name,
124 		(char *)name, name_length) == 0)) {
125 			iscsi_targetparam_unlock_list();
126 			return (curr_entry->target_oid);
127 		}
128 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
129 	}
130 	iscsi_targetparam_unlock_list();
131 
132 	curr_entry = iscsi_targetparam_create(name);
133 	return (curr_entry->target_oid);
134 }
135 
136 /*
137  * Returns a target param entry's target name given its oid.  If the oid cannot
138  * be found, NULL is returned.
139  *
140  */
iscsi_targetparam_get_name(uint32_t oid)141 uchar_t *iscsi_targetparam_get_name(uint32_t oid) {
142 	iscsi_targetparam_entry_t *curr_entry;
143 
144 	iscsi_targetparam_lock_list(RW_READER);
145 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
146 	while (curr_entry != NULL) {
147 		if (curr_entry->target_oid == oid) {
148 		iscsi_targetparam_unlock_list();
149 			return (curr_entry->target_name);
150 		}
151 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
152 	}
153 	iscsi_targetparam_unlock_list();
154 	return (NULL);
155 }
156 
157 
158 /*
159  * Removes a target param entry from the target param entry list.  The
160  * oid is used to lookup the entry to be removed.
161  *
162  */
163 int
iscsi_targetparam_remove_target(uint32_t oid)164 iscsi_targetparam_remove_target(uint32_t oid) {
165 	iscsi_targetparam_entry_t *prev_entry, *curr_entry;
166 
167 	prev_entry = NULL;
168 
169 	iscsi_targetparam_lock_list(RW_WRITER);
170 	curr_entry = iscsi_targetparam_get_next_entry(NULL);
171 	while (curr_entry != NULL) {
172 		if (curr_entry->target_oid == oid) {
173 
174 			if (prev_entry == NULL) {
175 				iscsi_targets.target_list = curr_entry->next;
176 			} else if (curr_entry->next == NULL) {
177 				ASSERT(prev_entry != NULL);
178 				prev_entry->next = NULL;
179 			} else {
180 				ASSERT(prev_entry != NULL);
181 				ASSERT(curr_entry != NULL);
182 				prev_entry->next = curr_entry->next;
183 			}
184 
185 			kmem_free(curr_entry,
186 			sizeof (iscsi_targetparam_entry_t));
187 
188 			iscsi_targetparam_unlock_list();
189 			return (0);
190 		}
191 
192 		prev_entry = curr_entry;
193 		curr_entry = iscsi_targetparam_get_next_entry(curr_entry);
194 	}
195 
196 	iscsi_targetparam_unlock_list();
197 	return (0);
198 }
199 
200 /*
201  * Returns the next element in the target param entry list.  If
202  * NULL is passed as the reference entry then the first item in
203  * the list is returned.  NULL will be returned when the last
204  * element in the list is used as the reference entry.
205  *
206  */
207 iscsi_targetparam_entry_t *
iscsi_targetparam_get_next_entry(iscsi_targetparam_entry_t * ref_entry)208 iscsi_targetparam_get_next_entry(iscsi_targetparam_entry_t *ref_entry) {
209     iscsi_targetparam_entry_t *entry;
210 
211 	if (ref_entry == NULL) {
212 		entry = iscsi_targets.target_list;
213 	} else {
214 		entry = ref_entry->next;
215 	}
216 	return (entry);
217 }
218 
219 /*
220  * Lock target param list.
221  *
222  */
223 void
iscsi_targetparam_lock_list(krw_t type)224 iscsi_targetparam_lock_list(krw_t type) {
225 	rw_enter(&(iscsi_targets.target_list_lock), type);
226 }
227 
228 /*
229  * Unlock target param list.
230  *
231  */
232 void
iscsi_targetparam_unlock_list()233 iscsi_targetparam_unlock_list() {
234 	rw_exit(&(iscsi_targets.target_list_lock));
235 }
236