xref: /titanic_53/usr/src/cmd/iscsid/iscsid.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte /*
22*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fcf3ce44SJohn Forte  * Use is subject to license terms.
24*fcf3ce44SJohn Forte  */
25*fcf3ce44SJohn Forte 
26*fcf3ce44SJohn Forte #include <sys/types.h>
27*fcf3ce44SJohn Forte #include <sys/stat.h>
28*fcf3ce44SJohn Forte #include <sys/socket.h>
29*fcf3ce44SJohn Forte #include <locale.h>
30*fcf3ce44SJohn Forte #include <syslog.h>
31*fcf3ce44SJohn Forte #include <netdb.h>
32*fcf3ce44SJohn Forte #include <stdlib.h>
33*fcf3ce44SJohn Forte #include <string.h>
34*fcf3ce44SJohn Forte #include <fcntl.h>
35*fcf3ce44SJohn Forte #include <unistd.h>
36*fcf3ce44SJohn Forte #include <stdio.h>
37*fcf3ce44SJohn Forte #include <errno.h>
38*fcf3ce44SJohn Forte #include <door.h>
39*fcf3ce44SJohn Forte #include <meta.h>
40*fcf3ce44SJohn Forte #include <libsysevent.h>
41*fcf3ce44SJohn Forte #include <wait.h>
42*fcf3ce44SJohn Forte #include <semaphore.h>
43*fcf3ce44SJohn Forte #include <libscf.h>
44*fcf3ce44SJohn Forte 
45*fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_door.h>
46*fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_if.h>
47*fcf3ce44SJohn Forte 
48*fcf3ce44SJohn Forte /*
49*fcf3ce44SJohn Forte  * Local Defines
50*fcf3ce44SJohn Forte  * -------------
51*fcf3ce44SJohn Forte  */
52*fcf3ce44SJohn Forte #define	ISCSI_DOOR_DAEMON_SYSLOG_PP		"iscsid"
53*fcf3ce44SJohn Forte #define	ISCSI_DISCOVERY_POLL_DELAY1		1	/* Seconds */
54*fcf3ce44SJohn Forte #define	ISCSI_DISCOVERY_POLL_DELAY2		60	/* Seconds */
55*fcf3ce44SJohn Forte 
56*fcf3ce44SJohn Forte #if !defined(SMF_EXIT_ERR_OTHER)
57*fcf3ce44SJohn Forte #define	SMF_EXIT_ERR_OTHER	-1
58*fcf3ce44SJohn Forte #endif
59*fcf3ce44SJohn Forte 
60*fcf3ce44SJohn Forte /*
61*fcf3ce44SJohn Forte  * Global Variables related to the synchronization of the child process
62*fcf3ce44SJohn Forte  * --------------------------------------------------------------------
63*fcf3ce44SJohn Forte  */
64*fcf3ce44SJohn Forte static	pid_t		iscsi_child_pid;
65*fcf3ce44SJohn Forte static	sem_t		iscsi_child_sem;
66*fcf3ce44SJohn Forte static	int		iscsi_child_door_handle;
67*fcf3ce44SJohn Forte static	int		iscsi_child_smf_exit_code;
68*fcf3ce44SJohn Forte 
69*fcf3ce44SJohn Forte /*
70*fcf3ce44SJohn Forte  * Global Variables related to the door accessed by the kernel
71*fcf3ce44SJohn Forte  * -----------------------------------------------------------
72*fcf3ce44SJohn Forte  */
73*fcf3ce44SJohn Forte static	int		iscsi_dev_handle;
74*fcf3ce44SJohn Forte static	int		iscsi_kernel_door_handle;
75*fcf3ce44SJohn Forte 
76*fcf3ce44SJohn Forte /*
77*fcf3ce44SJohn Forte  * Prototypes of Functions the body of which is defined farther down
78*fcf3ce44SJohn Forte  * in this file.
79*fcf3ce44SJohn Forte  * -----------------------------------------------------------------
80*fcf3ce44SJohn Forte  */
81*fcf3ce44SJohn Forte static	void		call_child_door(int value);
82*fcf3ce44SJohn Forte static	void		sigchld_handler(int sig);
83*fcf3ce44SJohn Forte static	boolean_t	discovery_event_wait(int did);
84*fcf3ce44SJohn Forte 
85*fcf3ce44SJohn Forte static
86*fcf3ce44SJohn Forte void
87*fcf3ce44SJohn Forte iscsi_child_door(
88*fcf3ce44SJohn Forte 	void			*cookie,
89*fcf3ce44SJohn Forte 	char			*args,
90*fcf3ce44SJohn Forte 	size_t			alen,
91*fcf3ce44SJohn Forte 	door_desc_t		*ddp,
92*fcf3ce44SJohn Forte 	uint_t			ndid
93*fcf3ce44SJohn Forte );
94*fcf3ce44SJohn Forte 
95*fcf3ce44SJohn Forte static
96*fcf3ce44SJohn Forte void
97*fcf3ce44SJohn Forte iscsi_kernel_door(
98*fcf3ce44SJohn Forte 	void			*cookie,
99*fcf3ce44SJohn Forte 	char			*args,
100*fcf3ce44SJohn Forte 	size_t			alen,
101*fcf3ce44SJohn Forte 	door_desc_t		*ddp,
102*fcf3ce44SJohn Forte 	uint_t			ndid
103*fcf3ce44SJohn Forte );
104*fcf3ce44SJohn Forte 
105*fcf3ce44SJohn Forte static
106*fcf3ce44SJohn Forte iscsi_door_cnf_t *
107*fcf3ce44SJohn Forte _getipnodebyname_req(
108*fcf3ce44SJohn Forte 	getipnodebyname_req_t	*req,
109*fcf3ce44SJohn Forte 	int			req_len,
110*fcf3ce44SJohn Forte 	size_t			*pcnf_len
111*fcf3ce44SJohn Forte );
112*fcf3ce44SJohn Forte 
113*fcf3ce44SJohn Forte /*
114*fcf3ce44SJohn Forte  * main -- Entry point of the iSCSI door server daemon
115*fcf3ce44SJohn Forte  *
116*fcf3ce44SJohn Forte  * This function forks, waits for the child process feedback and exits.
117*fcf3ce44SJohn Forte  */
118*fcf3ce44SJohn Forte /* ARGSUSED */
119*fcf3ce44SJohn Forte int
120*fcf3ce44SJohn Forte main(
121*fcf3ce44SJohn Forte 	int	argc,
122*fcf3ce44SJohn Forte 	char	*argv[]
123*fcf3ce44SJohn Forte )
124*fcf3ce44SJohn Forte {
125*fcf3ce44SJohn Forte 	int		i;
126*fcf3ce44SJohn Forte 
127*fcf3ce44SJohn Forte 	/*
128*fcf3ce44SJohn Forte 	 * Get the locale set up before calling any other routines
129*fcf3ce44SJohn Forte 	 * with messages to ouput.
130*fcf3ce44SJohn Forte 	 */
131*fcf3ce44SJohn Forte 	(void) setlocale(LC_ALL, "");
132*fcf3ce44SJohn Forte 	openlog("ISCSI_DOOR_DAEMON_SYSLOG_PP", LOG_PID, LOG_DAEMON);
133*fcf3ce44SJohn Forte 
134*fcf3ce44SJohn Forte 	/* The child semaphore is created. */
135*fcf3ce44SJohn Forte 	if (sem_init(&iscsi_child_sem, 0, 0) == -1) {
136*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
137*fcf3ce44SJohn Forte 	}
138*fcf3ce44SJohn Forte 
139*fcf3ce44SJohn Forte 	/* The door for the child is created. */
140*fcf3ce44SJohn Forte 	iscsi_child_door_handle = door_create(iscsi_child_door, NULL, 0);
141*fcf3ce44SJohn Forte 	if (iscsi_child_door_handle == -1) {
142*fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
143*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
144*fcf3ce44SJohn Forte 	}
145*fcf3ce44SJohn Forte 
146*fcf3ce44SJohn Forte 	/* A signal handler is set for SIGCHLD. */
147*fcf3ce44SJohn Forte 	(void) signal(SIGCHLD, sigchld_handler);
148*fcf3ce44SJohn Forte 
149*fcf3ce44SJohn Forte 	/*
150*fcf3ce44SJohn Forte 	 * Here begins the daemonizing code
151*fcf3ce44SJohn Forte 	 * --------------------------------
152*fcf3ce44SJohn Forte 	 */
153*fcf3ce44SJohn Forte 	iscsi_child_pid = fork();
154*fcf3ce44SJohn Forte 	if (iscsi_child_pid < 0) {
155*fcf3ce44SJohn Forte 		/* The fork failed. */
156*fcf3ce44SJohn Forte 		syslog(LOG_DAEMON | LOG_ERR, gettext("Cannot fork"));
157*fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
158*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
159*fcf3ce44SJohn Forte 	}
160*fcf3ce44SJohn Forte 
161*fcf3ce44SJohn Forte 	if (iscsi_child_pid) {
162*fcf3ce44SJohn Forte 		/*
163*fcf3ce44SJohn Forte 		 * The parent exits after the child has provided feedback. This
164*fcf3ce44SJohn Forte 		 * waiting phase is to meet one of greenline's requirements.
165*fcf3ce44SJohn Forte 		 * We shouldn't return till we are sure the service is ready to
166*fcf3ce44SJohn Forte 		 * be provided.
167*fcf3ce44SJohn Forte 		 */
168*fcf3ce44SJohn Forte 		(void) sem_wait(&iscsi_child_sem);
169*fcf3ce44SJohn Forte 		(void) sem_destroy(&iscsi_child_sem);
170*fcf3ce44SJohn Forte 		exit(iscsi_child_smf_exit_code);
171*fcf3ce44SJohn Forte 	}
172*fcf3ce44SJohn Forte 
173*fcf3ce44SJohn Forte 	/*
174*fcf3ce44SJohn Forte 	 * stdout and stderr are redirected to "/dev/null".
175*fcf3ce44SJohn Forte 	 */
176*fcf3ce44SJohn Forte 	i = open("/dev/null", O_RDWR);
177*fcf3ce44SJohn Forte 	(void) dup2(i, 1);
178*fcf3ce44SJohn Forte 	(void) dup2(i, 2);
179*fcf3ce44SJohn Forte 
180*fcf3ce44SJohn Forte 	/*
181*fcf3ce44SJohn Forte 	 * Here ends the daemonizing code
182*fcf3ce44SJohn Forte 	 * ------------------------------
183*fcf3ce44SJohn Forte 	 */
184*fcf3ce44SJohn Forte 
185*fcf3ce44SJohn Forte 	/*
186*fcf3ce44SJohn Forte 	 * Block out the usual signals so we don't get killed unintentionally.
187*fcf3ce44SJohn Forte 	 */
188*fcf3ce44SJohn Forte 	(void) signal(SIGHUP, SIG_IGN);
189*fcf3ce44SJohn Forte 	(void) signal(SIGINT, SIG_IGN);
190*fcf3ce44SJohn Forte 	(void) signal(SIGQUIT, SIG_IGN);
191*fcf3ce44SJohn Forte 
192*fcf3ce44SJohn Forte 	/* setup the door handle */
193*fcf3ce44SJohn Forte 	iscsi_kernel_door_handle = door_create(iscsi_kernel_door, NULL, 0);
194*fcf3ce44SJohn Forte 	if (iscsi_kernel_door_handle == -1) {
195*fcf3ce44SJohn Forte 		perror(gettext("door_create failed"));
196*fcf3ce44SJohn Forte 		syslog(LOG_DAEMON | LOG_ERR, gettext("door_create failed"));
197*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
198*fcf3ce44SJohn Forte 	}
199*fcf3ce44SJohn Forte 
200*fcf3ce44SJohn Forte 	/*
201*fcf3ce44SJohn Forte 	 * The iSCSI driver is opened.
202*fcf3ce44SJohn Forte 	 */
203*fcf3ce44SJohn Forte 	iscsi_dev_handle = open(ISCSI_DRIVER_DEVCTL, O_RDWR);
204*fcf3ce44SJohn Forte 	if (iscsi_dev_handle == -1) {
205*fcf3ce44SJohn Forte 		/* The driver couldn't be opened. */
206*fcf3ce44SJohn Forte 		perror(gettext("iscsi device open failed"));
207*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
208*fcf3ce44SJohn Forte 	}
209*fcf3ce44SJohn Forte 
210*fcf3ce44SJohn Forte 	if (ioctl(
211*fcf3ce44SJohn Forte 	    iscsi_dev_handle,
212*fcf3ce44SJohn Forte 	    ISCSI_DOOR_HANDLE_SET,
213*fcf3ce44SJohn Forte 	    &iscsi_kernel_door_handle) == -1) {
214*fcf3ce44SJohn Forte 		(void) close(iscsi_dev_handle);
215*fcf3ce44SJohn Forte 		perror(gettext("ioctl: set door handle"));
216*fcf3ce44SJohn Forte 		exit(SMF_EXIT_ERR_OTHER);
217*fcf3ce44SJohn Forte 	}
218*fcf3ce44SJohn Forte 
219*fcf3ce44SJohn Forte 	/* We have to wait for the discovery process to finish. */
220*fcf3ce44SJohn Forte 	(void) discovery_event_wait(iscsi_dev_handle);
221*fcf3ce44SJohn Forte 
222*fcf3ce44SJohn Forte 	/* We don't need to keep the device opened. */
223*fcf3ce44SJohn Forte 	(void) close(iscsi_dev_handle);
224*fcf3ce44SJohn Forte 
225*fcf3ce44SJohn Forte 	/* We let know the parent that everything is ok. */
226*fcf3ce44SJohn Forte 	call_child_door(SMF_EXIT_OK);
227*fcf3ce44SJohn Forte 	for (;;) {
228*fcf3ce44SJohn Forte 		(void) pause();
229*fcf3ce44SJohn Forte 	}
230*fcf3ce44SJohn Forte }
231*fcf3ce44SJohn Forte 
232*fcf3ce44SJohn Forte /*
233*fcf3ce44SJohn Forte  * sigchld_handler -- SIGCHLD Handler
234*fcf3ce44SJohn Forte  *
235*fcf3ce44SJohn Forte  */
236*fcf3ce44SJohn Forte /* ARGSUSED */
237*fcf3ce44SJohn Forte static
238*fcf3ce44SJohn Forte void
239*fcf3ce44SJohn Forte sigchld_handler(
240*fcf3ce44SJohn Forte 	int	sig
241*fcf3ce44SJohn Forte )
242*fcf3ce44SJohn Forte {
243*fcf3ce44SJohn Forte 	int	status;
244*fcf3ce44SJohn Forte 	pid_t	ret_pid;
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte 	/* This is the default code. */
247*fcf3ce44SJohn Forte 	iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER;
248*fcf3ce44SJohn Forte 
249*fcf3ce44SJohn Forte 	ret_pid = waitpid(iscsi_child_pid, &status, WNOHANG);
250*fcf3ce44SJohn Forte 
251*fcf3ce44SJohn Forte 	if (ret_pid == iscsi_child_pid) {
252*fcf3ce44SJohn Forte 		if (WIFEXITED(status)) {
253*fcf3ce44SJohn Forte 			iscsi_child_smf_exit_code = WEXITSTATUS(status);
254*fcf3ce44SJohn Forte 		}
255*fcf3ce44SJohn Forte 	}
256*fcf3ce44SJohn Forte 	(void) sem_post(&iscsi_child_sem);
257*fcf3ce44SJohn Forte }
258*fcf3ce44SJohn Forte 
259*fcf3ce44SJohn Forte /*
260*fcf3ce44SJohn Forte  * iscsi_child_door -- Child process door entry point
261*fcf3ce44SJohn Forte  *
262*fcf3ce44SJohn Forte  * This function is executed when a driver calls door_ki_upcall().
263*fcf3ce44SJohn Forte  */
264*fcf3ce44SJohn Forte /* ARGSUSED */
265*fcf3ce44SJohn Forte static
266*fcf3ce44SJohn Forte void
267*fcf3ce44SJohn Forte iscsi_child_door(
268*fcf3ce44SJohn Forte 	void		*cookie,
269*fcf3ce44SJohn Forte 	char		*args,
270*fcf3ce44SJohn Forte 	size_t		alen,
271*fcf3ce44SJohn Forte 	door_desc_t	*ddp,
272*fcf3ce44SJohn Forte 	uint_t		ndid
273*fcf3ce44SJohn Forte )
274*fcf3ce44SJohn Forte {
275*fcf3ce44SJohn Forte 	int		*ptr = (int *)args;
276*fcf3ce44SJohn Forte 
277*fcf3ce44SJohn Forte 	iscsi_child_smf_exit_code = SMF_EXIT_ERR_OTHER;
278*fcf3ce44SJohn Forte 
279*fcf3ce44SJohn Forte 	if (alen >= sizeof (iscsi_child_smf_exit_code)) {
280*fcf3ce44SJohn Forte 		iscsi_child_smf_exit_code = *ptr;
281*fcf3ce44SJohn Forte 	}
282*fcf3ce44SJohn Forte 	(void) sem_post(&iscsi_child_sem);
283*fcf3ce44SJohn Forte 	(void) door_return(NULL, 0, NULL, 0);
284*fcf3ce44SJohn Forte }
285*fcf3ce44SJohn Forte 
286*fcf3ce44SJohn Forte /*
287*fcf3ce44SJohn Forte  * iscsi_kernel_door -- Kernel door entry point
288*fcf3ce44SJohn Forte  *
289*fcf3ce44SJohn Forte  * This function is executed when a driver calls door_ki_upcall().
290*fcf3ce44SJohn Forte  */
291*fcf3ce44SJohn Forte /* ARGSUSED */
292*fcf3ce44SJohn Forte static
293*fcf3ce44SJohn Forte void
294*fcf3ce44SJohn Forte iscsi_kernel_door(
295*fcf3ce44SJohn Forte 	void		*cookie,
296*fcf3ce44SJohn Forte 	char		*args,
297*fcf3ce44SJohn Forte 	size_t		alen,
298*fcf3ce44SJohn Forte 	door_desc_t	*ddp,
299*fcf3ce44SJohn Forte 	uint_t		ndid
300*fcf3ce44SJohn Forte )
301*fcf3ce44SJohn Forte {
302*fcf3ce44SJohn Forte 	iscsi_door_msg_hdr_t	err_ind;
303*fcf3ce44SJohn Forte 	iscsi_door_req_t	*req;
304*fcf3ce44SJohn Forte 	iscsi_door_cnf_t	*cnf;
305*fcf3ce44SJohn Forte 	size_t			cnf_len;
306*fcf3ce44SJohn Forte 	char			*err_txt;
307*fcf3ce44SJohn Forte 	int			err_code;
308*fcf3ce44SJohn Forte 
309*fcf3ce44SJohn Forte 	/* Local variables pre-initialization */
310*fcf3ce44SJohn Forte 	err_ind.signature = ISCSI_DOOR_REQ_SIGNATURE;
311*fcf3ce44SJohn Forte 	err_ind.version	  = ISCSI_DOOR_REQ_VERSION_1;
312*fcf3ce44SJohn Forte 	err_ind.opcode	  = ISCSI_DOOR_ERROR_IND;
313*fcf3ce44SJohn Forte 
314*fcf3ce44SJohn Forte 	req = (iscsi_door_req_t *)args;
315*fcf3ce44SJohn Forte 	cnf = (iscsi_door_cnf_t *)&err_ind;
316*fcf3ce44SJohn Forte 	cnf_len = sizeof (err_ind);
317*fcf3ce44SJohn Forte 
318*fcf3ce44SJohn Forte 	/*
319*fcf3ce44SJohn Forte 	 * The validity of the request is checked before going any farther.
320*fcf3ce44SJohn Forte 	 */
321*fcf3ce44SJohn Forte 	if (req == NULL) {
322*fcf3ce44SJohn Forte 		/*
323*fcf3ce44SJohn Forte 		 * A request has to be passed.
324*fcf3ce44SJohn Forte 		 */
325*fcf3ce44SJohn Forte 		err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
326*fcf3ce44SJohn Forte 	} else if (alen < sizeof (iscsi_door_msg_hdr_t)) {
327*fcf3ce44SJohn Forte 		/*
328*fcf3ce44SJohn Forte 		 * The buffer containing the request must be at least as big
329*fcf3ce44SJohn Forte 		 * as message header.
330*fcf3ce44SJohn Forte 		 */
331*fcf3ce44SJohn Forte 		err_ind.status = ISCSI_DOOR_STATUS_REQ_LENGTH;
332*fcf3ce44SJohn Forte 	} else if (req->hdr.signature != ISCSI_DOOR_REQ_SIGNATURE) {
333*fcf3ce44SJohn Forte 		/*
334*fcf3ce44SJohn Forte 		 * The request must be correctly signed.
335*fcf3ce44SJohn Forte 		 */
336*fcf3ce44SJohn Forte 		err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
337*fcf3ce44SJohn Forte 	} else if (req->hdr.version != ISCSI_DOOR_REQ_VERSION_1) {
338*fcf3ce44SJohn Forte 		/*
339*fcf3ce44SJohn Forte 		 * The version of the request must be supported by the server.
340*fcf3ce44SJohn Forte 		 */
341*fcf3ce44SJohn Forte 		err_ind.status = ISCSI_DOOR_STATUS_REQ_VERSION;
342*fcf3ce44SJohn Forte 	} else {
343*fcf3ce44SJohn Forte 		/*
344*fcf3ce44SJohn Forte 		 * The request is treated according to the opcode.
345*fcf3ce44SJohn Forte 		 */
346*fcf3ce44SJohn Forte 		switch (req->hdr.opcode) {
347*fcf3ce44SJohn Forte 
348*fcf3ce44SJohn Forte 		case ISCSI_DOOR_GETIPNODEBYNAME_REQ:
349*fcf3ce44SJohn Forte 			cnf = _getipnodebyname_req(
350*fcf3ce44SJohn Forte 			    &req->ginbn_req,
351*fcf3ce44SJohn Forte 			    alen,
352*fcf3ce44SJohn Forte 			    &cnf_len);
353*fcf3ce44SJohn Forte 			break;
354*fcf3ce44SJohn Forte 		default:
355*fcf3ce44SJohn Forte 			err_ind.status = ISCSI_DOOR_STATUS_REQ_INVALID;
356*fcf3ce44SJohn Forte 			break;
357*fcf3ce44SJohn Forte 		}
358*fcf3ce44SJohn Forte 	}
359*fcf3ce44SJohn Forte 	err_code = door_return((char *)cnf, cnf_len, NULL, 0);
360*fcf3ce44SJohn Forte 
361*fcf3ce44SJohn Forte 	switch (err_code) {
362*fcf3ce44SJohn Forte 	case E2BIG:
363*fcf3ce44SJohn Forte 		err_txt = "E2BIG";
364*fcf3ce44SJohn Forte 		break;
365*fcf3ce44SJohn Forte 	case EFAULT:
366*fcf3ce44SJohn Forte 		err_txt = "EFAULT";
367*fcf3ce44SJohn Forte 		break;
368*fcf3ce44SJohn Forte 	case EINVAL:
369*fcf3ce44SJohn Forte 		err_txt = "EINVAL";
370*fcf3ce44SJohn Forte 		break;
371*fcf3ce44SJohn Forte 	case EMFILE:
372*fcf3ce44SJohn Forte 		err_txt = "EMFILE";
373*fcf3ce44SJohn Forte 		break;
374*fcf3ce44SJohn Forte 	default:
375*fcf3ce44SJohn Forte 		err_txt = "?";
376*fcf3ce44SJohn Forte 		break;
377*fcf3ce44SJohn Forte 	}
378*fcf3ce44SJohn Forte 	(void) fprintf(stderr, "door_return error(%s,%d)", err_txt, err_code);
379*fcf3ce44SJohn Forte 	syslog(
380*fcf3ce44SJohn Forte 	    LOG_DAEMON | LOG_ERR,
381*fcf3ce44SJohn Forte 	    gettext("!door_return error(%s,%d)"),
382*fcf3ce44SJohn Forte 	    err_txt,
383*fcf3ce44SJohn Forte 	    err_code);
384*fcf3ce44SJohn Forte }
385*fcf3ce44SJohn Forte 
386*fcf3ce44SJohn Forte /*
387*fcf3ce44SJohn Forte  * _getipnodebyname_req
388*fcf3ce44SJohn Forte  *
389*fcf3ce44SJohn Forte  * This function executes the request ISCSI_DOOR_GETIPNODEBYNAME_REQ.  It
390*fcf3ce44SJohn Forte  * calls getipnodebyname() but doesn't return all the information.  The
391*fcf3ce44SJohn Forte  * confirmation structure only contains one IP address of the list returned
392*fcf3ce44SJohn Forte  * by getipnodebyname().
393*fcf3ce44SJohn Forte  */
394*fcf3ce44SJohn Forte static
395*fcf3ce44SJohn Forte iscsi_door_cnf_t *
396*fcf3ce44SJohn Forte _getipnodebyname_req(
397*fcf3ce44SJohn Forte 	getipnodebyname_req_t	*req,
398*fcf3ce44SJohn Forte 	int			req_len,
399*fcf3ce44SJohn Forte 	size_t			*pcnf_len
400*fcf3ce44SJohn Forte ) {
401*fcf3ce44SJohn Forte 	getipnodebyname_cnf_t	*cnf = (getipnodebyname_cnf_t *)req;
402*fcf3ce44SJohn Forte 	size_t			cnf_len;
403*fcf3ce44SJohn Forte 	struct hostent		*hptr;
404*fcf3ce44SJohn Forte 	char			*name;
405*fcf3ce44SJohn Forte 
406*fcf3ce44SJohn Forte 	/* The opcode is changed immediately. */
407*fcf3ce44SJohn Forte 	cnf->hdr.opcode = ISCSI_DOOR_GETIPNODEBYNAME_CNF;
408*fcf3ce44SJohn Forte 
409*fcf3ce44SJohn Forte 	/* The size of the request is checked against the minimum required. */
410*fcf3ce44SJohn Forte 	if (req_len < sizeof (getipnodebyname_cnf_t)) {
411*fcf3ce44SJohn Forte 		cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT;
412*fcf3ce44SJohn Forte 		*pcnf_len = req_len;
413*fcf3ce44SJohn Forte 		return ((iscsi_door_cnf_t *)cnf);
414*fcf3ce44SJohn Forte 	}
415*fcf3ce44SJohn Forte 
416*fcf3ce44SJohn Forte 	name = (char *)req + req->name_offset;
417*fcf3ce44SJohn Forte 
418*fcf3ce44SJohn Forte 	/*
419*fcf3ce44SJohn Forte 	 * The pointer to the name has to stay inside the request but
420*fcf3ce44SJohn Forte 	 * after the header.
421*fcf3ce44SJohn Forte 	 */
422*fcf3ce44SJohn Forte 	if ((name < ((char *)req + sizeof (getipnodebyname_req_t))) ||
423*fcf3ce44SJohn Forte 	    ((name + req->name_length) > ((char *)req + req_len))) {
424*fcf3ce44SJohn Forte 		cnf->hdr.status = ISCSI_DOOR_STATUS_REQ_FORMAT;
425*fcf3ce44SJohn Forte 		*pcnf_len = req_len;
426*fcf3ce44SJohn Forte 		return ((iscsi_door_cnf_t *)cnf);
427*fcf3ce44SJohn Forte 	}
428*fcf3ce44SJohn Forte 
429*fcf3ce44SJohn Forte 	/* The library function is called. */
430*fcf3ce44SJohn Forte 	hptr = getipnodebyname(
431*fcf3ce44SJohn Forte 			name,
432*fcf3ce44SJohn Forte 			(int)req->af,
433*fcf3ce44SJohn Forte 			(int)req->flags,
434*fcf3ce44SJohn Forte 			(int *)&cnf->error_num);
435*fcf3ce44SJohn Forte 
436*fcf3ce44SJohn Forte 	if (hptr) {
437*fcf3ce44SJohn Forte 		/*
438*fcf3ce44SJohn Forte 		 * The call was successful. Now starts the painful work of
439*fcf3ce44SJohn Forte 		 * parsing the data.  However, for version 1 we will only
440*fcf3ce44SJohn Forte 		 * return the first address.
441*fcf3ce44SJohn Forte 		 */
442*fcf3ce44SJohn Forte 		cnf_len = sizeof (getipnodebyname_cnf_t);
443*fcf3ce44SJohn Forte 		cnf->h_size_needed = sizeof (getipnodebyname_cnf_t);
444*fcf3ce44SJohn Forte 		cnf->h_alias_list_length = 0;
445*fcf3ce44SJohn Forte 		cnf->h_alias_list_offset = 0;
446*fcf3ce44SJohn Forte 		cnf->h_name_len = 0;
447*fcf3ce44SJohn Forte 		cnf->h_name_offset = 0;
448*fcf3ce44SJohn Forte 
449*fcf3ce44SJohn Forte 		cnf->h_addrlen = (uint32_t)hptr->h_length;
450*fcf3ce44SJohn Forte 		cnf->h_addrtype = (uint32_t)hptr->h_addrtype;
451*fcf3ce44SJohn Forte 		cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t);
452*fcf3ce44SJohn Forte 
453*fcf3ce44SJohn Forte 		if (*hptr->h_addr_list != NULL) {
454*fcf3ce44SJohn Forte 			(void) memcpy(
455*fcf3ce44SJohn Forte 				((char *)cnf + sizeof (getipnodebyname_cnf_t)),
456*fcf3ce44SJohn Forte 				*hptr->h_addr_list,
457*fcf3ce44SJohn Forte 				hptr->h_length);
458*fcf3ce44SJohn Forte 			cnf->h_addr_list_length = 1;
459*fcf3ce44SJohn Forte 			cnf->h_size_needed += cnf->h_addrlen;
460*fcf3ce44SJohn Forte 			cnf_len += hptr->h_length;
461*fcf3ce44SJohn Forte 		} else {
462*fcf3ce44SJohn Forte 			cnf->h_addr_list_length = 0;
463*fcf3ce44SJohn Forte 			cnf->h_size_needed += hptr->h_length;
464*fcf3ce44SJohn Forte 		}
465*fcf3ce44SJohn Forte 		*pcnf_len = cnf_len;
466*fcf3ce44SJohn Forte 		cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS;
467*fcf3ce44SJohn Forte 		freehostent(hptr);
468*fcf3ce44SJohn Forte 	} else {
469*fcf3ce44SJohn Forte 		cnf->hdr.status = ISCSI_DOOR_STATUS_SUCCESS;
470*fcf3ce44SJohn Forte 		cnf->h_addrlen = 0;
471*fcf3ce44SJohn Forte 		cnf->h_addrtype = 0;
472*fcf3ce44SJohn Forte 		cnf->h_addr_list_offset = sizeof (getipnodebyname_cnf_t);
473*fcf3ce44SJohn Forte 		cnf->h_addr_list_length = 0;
474*fcf3ce44SJohn Forte 		cnf->h_name_offset = sizeof (getipnodebyname_cnf_t);
475*fcf3ce44SJohn Forte 		cnf->h_name_len = 0;
476*fcf3ce44SJohn Forte 		cnf->h_alias_list_offset = sizeof (getipnodebyname_cnf_t);
477*fcf3ce44SJohn Forte 		cnf->h_alias_list_length = 0;
478*fcf3ce44SJohn Forte 		cnf->h_size_needed = sizeof (getipnodebyname_cnf_t);
479*fcf3ce44SJohn Forte 		*pcnf_len = sizeof (getipnodebyname_cnf_t);
480*fcf3ce44SJohn Forte 	}
481*fcf3ce44SJohn Forte 	return ((iscsi_door_cnf_t *)cnf);
482*fcf3ce44SJohn Forte }
483*fcf3ce44SJohn Forte 
484*fcf3ce44SJohn Forte /*
485*fcf3ce44SJohn Forte  * call_child_door -- This function calls the child door with the value
486*fcf3ce44SJohn Forte  *		      provided by the caller.
487*fcf3ce44SJohn Forte  *
488*fcf3ce44SJohn Forte  */
489*fcf3ce44SJohn Forte static
490*fcf3ce44SJohn Forte void
491*fcf3ce44SJohn Forte call_child_door(
492*fcf3ce44SJohn Forte 	int		value
493*fcf3ce44SJohn Forte )
494*fcf3ce44SJohn Forte {
495*fcf3ce44SJohn Forte 	door_arg_t	door_arg;
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte 	(void) memset(&door_arg, 0, sizeof (door_arg));
498*fcf3ce44SJohn Forte 	door_arg.data_ptr = (char *)&value;
499*fcf3ce44SJohn Forte 	door_arg.data_size = sizeof (value);
500*fcf3ce44SJohn Forte 	(void) door_call(iscsi_child_door_handle, &door_arg);
501*fcf3ce44SJohn Forte }
502*fcf3ce44SJohn Forte 
503*fcf3ce44SJohn Forte /*
504*fcf3ce44SJohn Forte  * get_luns_count --
505*fcf3ce44SJohn Forte  */
506*fcf3ce44SJohn Forte static
507*fcf3ce44SJohn Forte uint32_t
508*fcf3ce44SJohn Forte get_luns_count(
509*fcf3ce44SJohn Forte 	int		did
510*fcf3ce44SJohn Forte )
511*fcf3ce44SJohn Forte {
512*fcf3ce44SJohn Forte 	iscsi_lun_list_t	*lun_list;
513*fcf3ce44SJohn Forte 	iscsi_lun_list_t	*tmp;
514*fcf3ce44SJohn Forte 	size_t			len;
515*fcf3ce44SJohn Forte 	uint32_t		lun_count;
516*fcf3ce44SJohn Forte 
517*fcf3ce44SJohn Forte 	lun_list = (iscsi_lun_list_t *)malloc(sizeof (*lun_list));
518*fcf3ce44SJohn Forte 
519*fcf3ce44SJohn Forte 	(void) memset(lun_list, 0, sizeof (*lun_list));
520*fcf3ce44SJohn Forte 	lun_list->ll_vers = ISCSI_INTERFACE_VERSION;
521*fcf3ce44SJohn Forte 	lun_list->ll_in_cnt = 1;
522*fcf3ce44SJohn Forte 	lun_list->ll_all_tgts = B_TRUE;
523*fcf3ce44SJohn Forte 
524*fcf3ce44SJohn Forte 	for (;;) {
525*fcf3ce44SJohn Forte 
526*fcf3ce44SJohn Forte 		if (ioctl(
527*fcf3ce44SJohn Forte 		    did,
528*fcf3ce44SJohn Forte 		    ISCSI_LUN_OID_LIST_GET,
529*fcf3ce44SJohn Forte 		    lun_list) == -1) {
530*fcf3ce44SJohn Forte 			free(lun_list);
531*fcf3ce44SJohn Forte 			/* The Ioctl didn't go well. */
532*fcf3ce44SJohn Forte 			return (0);
533*fcf3ce44SJohn Forte 		}
534*fcf3ce44SJohn Forte 		if (lun_list->ll_in_cnt >= lun_list->ll_out_cnt) {
535*fcf3ce44SJohn Forte 			/* We got it all. */
536*fcf3ce44SJohn Forte 			break;
537*fcf3ce44SJohn Forte 		}
538*fcf3ce44SJohn Forte 		/*
539*fcf3ce44SJohn Forte 		 * We didn't get all the targets. Let's build a new Ioctl with
540*fcf3ce44SJohn Forte 		 * a new size.
541*fcf3ce44SJohn Forte 		 */
542*fcf3ce44SJohn Forte 		tmp  = lun_list;
543*fcf3ce44SJohn Forte 		len  = tmp->ll_out_cnt * sizeof (tmp->ll_luns);
544*fcf3ce44SJohn Forte 		len += sizeof (*tmp) - sizeof (tmp->ll_luns);
545*fcf3ce44SJohn Forte 		lun_list = (iscsi_lun_list_t *)malloc(len);
546*fcf3ce44SJohn Forte 		if (lun_list == NULL) {
547*fcf3ce44SJohn Forte 			/* No resources. */
548*fcf3ce44SJohn Forte 			free(tmp);
549*fcf3ce44SJohn Forte 			return (0);
550*fcf3ce44SJohn Forte 		}
551*fcf3ce44SJohn Forte 		(void) memset(lun_list, 0, len);
552*fcf3ce44SJohn Forte 		lun_list->ll_vers = ISCSI_INTERFACE_VERSION;
553*fcf3ce44SJohn Forte 		lun_list->ll_in_cnt = tmp->ll_out_cnt;
554*fcf3ce44SJohn Forte 		lun_list->ll_all_tgts = B_TRUE;
555*fcf3ce44SJohn Forte 		free(tmp);
556*fcf3ce44SJohn Forte 	}
557*fcf3ce44SJohn Forte 	lun_count = lun_list->ll_out_cnt;
558*fcf3ce44SJohn Forte 	free(lun_list);
559*fcf3ce44SJohn Forte 	return (lun_count);
560*fcf3ce44SJohn Forte }
561*fcf3ce44SJohn Forte 
562*fcf3ce44SJohn Forte /*
563*fcf3ce44SJohn Forte  * discovery_event_wait -- Waits for the discovery process to finish.
564*fcf3ce44SJohn Forte  *
565*fcf3ce44SJohn Forte  */
566*fcf3ce44SJohn Forte static
567*fcf3ce44SJohn Forte boolean_t
568*fcf3ce44SJohn Forte discovery_event_wait(
569*fcf3ce44SJohn Forte 	int		did
570*fcf3ce44SJohn Forte )
571*fcf3ce44SJohn Forte {
572*fcf3ce44SJohn Forte 	boolean_t		rc;
573*fcf3ce44SJohn Forte 	uint32_t		lun_count;
574*fcf3ce44SJohn Forte 	uint32_t		lun_timer;
575*fcf3ce44SJohn Forte 	uint32_t		tmp;
576*fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t  discovery_flags;
577*fcf3ce44SJohn Forte 	iSCSIDiscoveryMethod_t  discovery_all;
578*fcf3ce44SJohn Forte 
579*fcf3ce44SJohn Forte 	rc = B_FALSE;
580*fcf3ce44SJohn Forte 	lun_count = 0;
581*fcf3ce44SJohn Forte 	lun_timer = 0;
582*fcf3ce44SJohn Forte 	discovery_flags = 0;
583*fcf3ce44SJohn Forte 	discovery_all = iSCSIDiscoveryMethodStatic |
584*fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodSLP |
585*fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodISNS |
586*fcf3ce44SJohn Forte 	    iSCSIDiscoveryMethodSendTargets;
587*fcf3ce44SJohn Forte 
588*fcf3ce44SJohn Forte 	for (;;) {
589*fcf3ce44SJohn Forte 
590*fcf3ce44SJohn Forte 		/* The status discovery flags are read. */
591*fcf3ce44SJohn Forte 		if (ioctl(
592*fcf3ce44SJohn Forte 		    did,
593*fcf3ce44SJohn Forte 		    ISCSI_DISCOVERY_EVENTS,
594*fcf3ce44SJohn Forte 		    &discovery_flags) == -1) {
595*fcf3ce44SJohn Forte 			/* IO problem */
596*fcf3ce44SJohn Forte 			break;
597*fcf3ce44SJohn Forte 		}
598*fcf3ce44SJohn Forte 
599*fcf3ce44SJohn Forte 		if (discovery_flags == discovery_all) {
600*fcf3ce44SJohn Forte 			/* Discovery over */
601*fcf3ce44SJohn Forte 			rc = B_TRUE;
602*fcf3ce44SJohn Forte 			break;
603*fcf3ce44SJohn Forte 		}
604*fcf3ce44SJohn Forte 
605*fcf3ce44SJohn Forte 		if (lun_timer >= ISCSI_DISCOVERY_POLL_DELAY2) {
606*fcf3ce44SJohn Forte 			/* Let's check if the driver is making progress. */
607*fcf3ce44SJohn Forte 			tmp = get_luns_count(did);
608*fcf3ce44SJohn Forte 			if (tmp <= lun_count) {
609*fcf3ce44SJohn Forte 				/* No progress */
610*fcf3ce44SJohn Forte 				break;
611*fcf3ce44SJohn Forte 			}
612*fcf3ce44SJohn Forte 			lun_count = tmp;
613*fcf3ce44SJohn Forte 			lun_timer = 0;
614*fcf3ce44SJohn Forte 		}
615*fcf3ce44SJohn Forte 		(void) sleep(ISCSI_DISCOVERY_POLL_DELAY1);
616*fcf3ce44SJohn Forte 		lun_timer += ISCSI_DISCOVERY_POLL_DELAY1;
617*fcf3ce44SJohn Forte 	}
618*fcf3ce44SJohn Forte 	return (rc);
619*fcf3ce44SJohn Forte }
620