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