Print this page
inet_pton
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_doorclt.c
+++ new/usr/src/uts/common/io/scsi/adapters/iscsi/iscsi_doorclt.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2000 by Cisco Systems, Inc. All rights reserved.
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
25 26 *
26 27 * iSCSI Software Initiator
27 28 */
28 29
29 30 #include <sys/types.h>
30 31 #include <sys/errno.h>
31 32 #include <sys/conf.h>
32 33 #include <sys/cmn_err.h>
33 34 #include <sys/stat.h>
34 35 #include <sys/pathname.h>
35 36 #include <sys/door.h>
36 37 #include <sys/kmem.h>
37 38 #include <sys/socket.h>
38 39 #include <sys/fs/snode.h>
39 40 #include <netinet/in.h>
40 41
41 42 #include <sys/scsi/adapters/iscsi_door.h>
42 43 #include "iscsi.h"
43 44
44 45 #define ISCSI_DOOR_MAX_SEMA_VALUE 16
45 46
46 47 static boolean_t iscsi_door_init = B_FALSE;
47 48 static ksema_t iscsi_door_sema;
48 49 static krwlock_t iscsi_door_lock;
49 50 static door_handle_t iscsi_door_handle;
50 51
51 52 typedef struct _mybuffer {
52 53 size_t signature;
53 54 size_t size;
54 55 } mybuffer_t;
55 56
56 57 /*
57 58 * iscsi_door_ini
58 59 *
59 60 * This function initializes the variables needed to handle the door upcall.
60 61 */
61 62 boolean_t
62 63 iscsi_door_ini(void)
63 64 {
64 65 ASSERT(!iscsi_door_init);
65 66 if (!iscsi_door_init) {
66 67 rw_init(
67 68 &iscsi_door_lock,
68 69 NULL,
69 70 RW_DRIVER,
70 71 NULL);
71 72
72 73 sema_init(
73 74 &iscsi_door_sema,
74 75 ISCSI_DOOR_MAX_SEMA_VALUE,
75 76 NULL,
76 77 SEMA_DRIVER,
77 78 NULL);
78 79
79 80 iscsi_door_handle = NULL;
80 81 iscsi_door_init = B_TRUE;
81 82 return (B_TRUE);
82 83 }
83 84 return (B_FALSE);
84 85 }
85 86
86 87 /*
87 88 * iscsi_door_term
88 89 *
89 90 * This function releases the resources allocated to handle the door
90 91 * upcall. It disconnects from the door if currently connected.
91 92 */
92 93 boolean_t
93 94 iscsi_door_term(void)
94 95 {
95 96 ASSERT(iscsi_door_init);
96 97 if (iscsi_door_init) {
97 98 iscsi_door_init = B_FALSE;
98 99 iscsi_door_unbind();
99 100 rw_destroy(&iscsi_door_lock);
100 101 sema_destroy(&iscsi_door_sema);
101 102 return (B_TRUE);
102 103 }
103 104 return (B_FALSE);
104 105 }
105 106
106 107 /*
107 108 * iscsi_door_bind
108 109 *
109 110 * This function tries to connect the iscsi_door. If it succeeds
110 111 * it keeps the vnode.
111 112 */
112 113 boolean_t
113 114 iscsi_door_bind(
114 115 int did
115 116 )
116 117 {
117 118 door_handle_t new_handle;
118 119
119 120 new_handle = door_ki_lookup(did);
120 121 if (new_handle == NULL) {
121 122 /* The lookup failed. */
122 123 return (B_FALSE);
123 124 }
124 125
125 126 /* The new handle is stored. If we had one, it is released. */
126 127 rw_enter(&iscsi_door_lock, RW_WRITER);
127 128 if (iscsi_door_handle != NULL) {
128 129 door_ki_rele(iscsi_door_handle);
129 130 }
130 131 iscsi_door_handle = new_handle;
131 132 rw_exit(&iscsi_door_lock);
132 133
133 134 return (B_TRUE);
134 135 }
135 136
136 137 /*
137 138 * iscsi_door_unbind
138 139 *
139 140 * This function releases the current door handle.
140 141 */
141 142 void
142 143 iscsi_door_unbind(void)
143 144 {
144 145 rw_enter(&iscsi_door_lock, RW_WRITER);
145 146 if (iscsi_door_handle != NULL) {
146 147 door_ki_rele(iscsi_door_handle);
147 148 iscsi_door_handle = NULL;
148 149 }
149 150 rw_exit(&iscsi_door_lock);
150 151 }
151 152
152 153 /*
153 154 * iscsi_door_upcall
154 155 *
155 156 * This function tries to call the iscsi_door.
156 157 */
157 158 static
158 159 boolean_t
159 160 iscsi_door_upcall(door_arg_t *arg)
160 161 {
161 162 int error;
162 163
163 164 /*
164 165 * This semaphore limits the number of simultaneous calls
165 166 * to the door.
166 167 */
167 168 sema_p(&iscsi_door_sema);
168 169 /*
169 170 * The mutex protecting the iscsi_door_handle is entered.
170 171 */
171 172 rw_enter(&iscsi_door_lock, RW_READER);
172 173
173 174 if (iscsi_door_handle == NULL) {
174 175 /* There's no door handle. */
175 176 rw_exit(&iscsi_door_lock);
176 177 sema_v(&iscsi_door_sema);
177 178 return (B_FALSE);
178 179 }
179 180 error = door_ki_upcall(iscsi_door_handle, arg);
180 181
181 182 rw_exit(&iscsi_door_lock);
182 183 sema_v(&iscsi_door_sema);
183 184
184 185 if (error != 0) {
185 186 return (B_FALSE);
186 187 } else {
187 188 return (B_TRUE);
188 189 }
189 190 }
190 191
191 192 /*
192 193 * kfreehostent
193 194 *
194 195 * This function frees the memory returned by kgetipnodebyname.
195 196 */
196 197 void
197 198 kfreehostent(
198 199 struct hostent *hptr
199 200 )
200 201 {
201 202 mybuffer_t *buffer;
202 203
203 204 ASSERT(hptr != NULL);
204 205 if (hptr) {
205 206 buffer = (mybuffer_t *)((char *)hptr - sizeof (mybuffer_t));
206 207 ASSERT(buffer->signature == ISCSI_DOOR_REQ_SIGNATURE);
207 208 if (buffer->signature == ISCSI_DOOR_REQ_SIGNATURE) {
208 209 kmem_free((void *)buffer, buffer->size);
209 210 return;
210 211 }
211 212 }
212 213 /* A message should be logged here. */
213 214 }
214 215
215 216 /*
216 217 * kgetipnodebyname
217 218 *
218 219 * This function builds a request that will be sent to the iscsi_door.
219 220 * The iSCSI door after receiving the request calls getipnodebyaddr().
220 221 * for more information on the input, output parameter and return value,
221 222 * consult the man page for getipnodebyname().
222 223 *
223 224 * Before calling the iscsi door this function tries to do the conversion
224 225 * locally. If a name resolution is needed the iscsi door is called.
225 226 *
226 227 * There's some limitations to the information returned by this function.
227 228 * Only one address of the address list returned by getipnodebyname() is
228 229 * returned. The other parameters of the structure should be ignored.
229 230 */
230 231 struct hostent *
231 232 kgetipnodebyname(
232 233 const char *name,
233 234 int af,
234 235 int flags,
235 236 int *error_num
↓ open down ↓ |
201 lines elided |
↑ open up ↑ |
236 237 )
237 238 {
238 239 door_arg_t arg;
239 240 mybuffer_t *buffer;
240 241 size_t msg_size = ISCSI_DOOR_MAX_DATA_SIZE;
241 242 size_t hostent_size = ISCSI_DOOR_MAX_DATA_SIZE;
242 243 size_t buffer_size;
243 244 getipnodebyname_req_t *req;
244 245 getipnodebyname_cnf_t *cnf;
245 246 struct hostent *hptr;
246 - int i;
247 - uint16_t *swap;
248 247
249 248
250 249 buffer_size = msg_size + hostent_size + sizeof (mybuffer_t);
251 250 buffer = (mybuffer_t *)kmem_zalloc(buffer_size, KM_SLEEP);
252 251
253 252 if (buffer) {
254 253
255 254 /*
256 255 * The buffer was successfully allocated.
257 256 *
258 257 * Buffer
259 258 *
260 259 * +--------------------+ <--- buffer
261 260 * | mybuffer_t |
262 261 * +--------------------+ <--- hptr
263 262 * | |
264 263 * | |
265 264 * | hostent_size |
266 265 * | |
267 266 * | |
268 267 * | |
269 268 * +--------------------+ <--- req, cnf
270 269 * | |
271 270 * | |
272 271 * | |
273 272 * | msg_size |
274 273 * | |
275 274 * | |
276 275 * | |
277 276 * +--------------------+
278 277 */
279 278 buffer->signature = ISCSI_DOOR_REQ_SIGNATURE;
280 279 buffer->size = buffer_size;
281 280
282 281 hptr = (struct hostent *)((char *)buffer + sizeof (mybuffer_t));
283 282 req = (getipnodebyname_req_t *)((char *)hptr + hostent_size);
284 283 cnf = (getipnodebyname_cnf_t *)((char *)hptr + hostent_size);
285 284
286 285 hostent_size -= sizeof (struct hostent);
287 286
288 287 /*
289 288 * We try first locally. If the conversion cannot be done
290 289 * by inet_pton the door is called.
291 290 * The cnf address is used as output buffer.
292 291 * inet_pton returns '1' if the conversion was successful.
293 292 */
294 293 switch (af) {
295 294 case AF_INET:
296 295 hptr->h_length = sizeof (struct in_addr);
297 296 break;
298 297 case AF_INET6:
299 298 hptr->h_length = sizeof (struct in6_addr);
300 299 break;
301 300 default:
302 301 kfreehostent(hptr);
303 302 *error_num = NO_RECOVERY;
304 303 return (NULL);
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
305 304 }
306 305 if ((msg_size < hptr->h_length) ||
307 306 (hostent_size < sizeof (char *))) {
308 307 kfreehostent(hptr);
309 308 *error_num = NO_RECOVERY;
310 309 return (NULL);
311 310 }
312 311 if (inet_pton(af, (char *)name, cnf) == 1) {
313 312 /*
314 313 * inet_pton converted the string successfully.
315 - * reset to network order. swaps based on nfs code
316 314 */
317 - if (af == AF_INET) {
318 - *((uint32_t *)cnf) = htonl(*((uint32_t *)cnf));
319 - } else {
320 - for (swap = ((void *)cnf), i = 0;
321 - i < hptr->h_length / sizeof (uint16_t);
322 - i++) {
323 - swap[i] = htons(swap[i]);
324 - }
325 - }
326 315 hptr->h_addrtype = af;
327 316 hptr->h_addr_list = (char **)((char *)hptr +
328 317 sizeof (struct hostent));
329 318 *hptr->h_addr_list = (char *)cnf;
330 319 return (hptr);
331 320 }
332 321
333 322 /*
334 323 * The name couldn't ne converted by inet_pton. The door is
335 324 * called.
336 325 */
337 326
338 327 /* Header initialization. */
339 328 req->hdr.signature = ISCSI_DOOR_REQ_SIGNATURE;
340 329 req->hdr.version = ISCSI_DOOR_REQ_VERSION_1;
341 330 req->hdr.opcode = ISCSI_DOOR_GETIPNODEBYNAME_REQ;
342 331
343 332 /* Body initialization. */
344 333 req->name_length = strlen(name);
345 334 if (req->name_length >
346 335 (msg_size - sizeof (getipnodebyname_req_t) - 1)) {
347 336 kfreehostent(hptr);
348 337 *error_num = NO_RECOVERY;
349 338 return (NULL);
350 339 }
351 340
352 341 req->name_offset = sizeof (getipnodebyname_req_t);
353 342 req->af = af;
354 343 req->flags = flags;
355 344 bcopy(
356 345 name,
357 346 ((char *)req + req->name_offset),
358 347 req->name_length);
359 348
360 349 /* Door argument initialization. */
361 350 arg.data_ptr = (char *)req;
362 351 arg.data_size = msg_size;
363 352 arg.desc_num = 0;
364 353 arg.desc_ptr = NULL;
365 354 arg.rbuf = (char *)cnf;
366 355 arg.rsize = msg_size;
367 356
368 357 if (iscsi_door_upcall(&arg) == B_FALSE) {
369 358 /* The door call failed */
370 359 kfreehostent(hptr);
371 360 *error_num = NO_RECOVERY;
372 361 return (NULL);
373 362 }
374 363
375 364 /*
376 365 * The door call itself was successful. The value returned
377 366 * in arg.rbuf should be cnf, but we never know.
378 367 */
379 368 cnf = (getipnodebyname_cnf_t *)arg.rbuf;
380 369
381 370 if ((cnf == NULL) ||
382 371 (arg.rsize < sizeof (getipnodebyname_cnf_t)) ||
383 372 (cnf->hdr.signature != ISCSI_DOOR_REQ_SIGNATURE) ||
384 373 (cnf->hdr.version != ISCSI_DOOR_REQ_VERSION_1) ||
385 374 (cnf->hdr.opcode != ISCSI_DOOR_GETIPNODEBYNAME_CNF) ||
386 375 ((cnf->hdr.status != ISCSI_DOOR_STATUS_SUCCESS) &&
387 376 (cnf->hdr.status != ISCSI_DOOR_STATUS_MORE))) {
388 377 /* The door didn't like the request */
389 378 kfreehostent(hptr);
390 379 *error_num = NO_RECOVERY;
391 380 return (NULL);
392 381 }
393 382
394 383 if (cnf->h_addr_list_length == 0) {
395 384 kfreehostent(hptr);
396 385 *error_num = HOST_NOT_FOUND;
397 386 return (NULL);
398 387 }
399 388
400 389 hptr->h_addrtype = cnf->h_addrtype;
401 390 hptr->h_length = cnf->h_addrlen;
402 391 hptr->h_addr_list = (char **)((char *)hptr +
403 392 sizeof (struct hostent));
404 393 *hptr->h_addr_list = ((char *)cnf + cnf->h_addr_list_offset);
405 394 return (hptr);
406 395 } else {
407 396 *error_num = NO_RECOVERY;
408 397 return (NULL);
409 398 }
410 399 }
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX