xref: /netbsd-src/sys/dev/iscsi/iscsi_ioctl.c (revision 6a493d6bc668897c91594964a732d38505b70cbb)
1 /*	$NetBSD: iscsi_ioctl.c,v 1.6 2012/12/29 11:05:29 mlelstv Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Wasabi Systems, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "iscsi_globals.h"
33 
34 #include <sys/file.h>
35 #include <sys/filedesc.h>
36 #include <sys/proc.h>
37 
38 #ifndef ISCSI_MINIMAL
39 #include <uvm/uvm.h>
40 #include <uvm/uvm_pmap.h>
41 #endif
42 
43 static uint16_t current_id = 0;	/* Global session ID counter */
44 
45 /* list of event handlers */
46 static event_handler_list_t event_handlers =
47 	TAILQ_HEAD_INITIALIZER(event_handlers);
48 
49 static uint32_t handler_id = 0;	/* Handler ID counter */
50 
51 /* -------------------------------------------------------------------------- */
52 
53 /* Event management functions */
54 
55 /*
56  * find_handler:
57  *    Search the event handler list for the given ID.
58  *
59  *    Parameter:
60  *          id    The handler ID.
61  *
62  *    Returns:
63  *          Pointer to handler if found, else NULL.
64  */
65 
66 
67 STATIC event_handler_t *
68 find_handler(uint32_t id)
69 {
70 	event_handler_t *curr;
71 
72 	TAILQ_FOREACH(curr, &event_handlers, link)
73 		if (curr->id == id)
74 			break;
75 
76 	return curr;
77 }
78 
79 
80 /*
81  * register_event:
82  *    Create event handler entry, return ID.
83  *
84  *    Parameter:
85  *          par   The parameter.
86  */
87 
88 STATIC void
89 register_event(iscsi_register_event_parameters_t *par)
90 {
91 	event_handler_t *handler;
92 	int was_empty;
93 	int s;
94 
95 	handler = malloc(sizeof(event_handler_t), M_DEVBUF, M_WAITOK | M_ZERO);
96 	if (handler == NULL) {
97 		DEBOUT(("No mem for event handler\n"));
98 		par->status = ISCSI_STATUS_NO_RESOURCES;
99 		return;
100 	}
101 
102 	TAILQ_INIT(&handler->events);
103 
104 	/* create a unique ID */
105 	s = splbio();
106 	do {
107 		++handler_id;
108 	} while (!handler_id || find_handler(handler_id) != NULL);
109 	par->event_id = handler->id = handler_id;
110 
111 	was_empty = TAILQ_FIRST(&event_handlers) == NULL;
112 
113 	TAILQ_INSERT_TAIL(&event_handlers, handler, link);
114 
115 	if (was_empty) {
116 		wakeup(&iscsi_cleanupc_list);
117 	}
118 	splx(s);
119 
120 	par->status = ISCSI_STATUS_SUCCESS;
121 	DEB(5, ("Register Event OK, ID %d\n", par->event_id));
122 }
123 
124 
125 /*
126  * deregister_event:
127  *    Destroy handler entry and any waiting events, wake up waiter.
128  *
129  *    Parameter:
130  *          par   The parameter.
131  */
132 
133 STATIC void
134 deregister_event(iscsi_register_event_parameters_t *par)
135 {
136 	event_handler_t *handler;
137 	event_t *evt;
138 	int s;
139 
140 	handler = find_handler(par->event_id);
141 	if (handler == NULL) {
142 		DEB(1, ("Deregister Event ID %d not found\n", par->event_id));
143 		par->status = ISCSI_STATUS_INVALID_EVENT_ID;
144 		return;
145 	}
146 
147 	s = splbio();
148 	TAILQ_REMOVE(&event_handlers, handler, link);
149 	splx(s);
150 
151 	if (handler->waiter != NULL) {
152 		handler->waiter->status = ISCSI_STATUS_EVENT_DEREGISTERED;
153 		wakeup(handler->waiter);
154 	}
155 
156 	while ((evt = TAILQ_FIRST(&handler->events)) != NULL) {
157 		TAILQ_REMOVE(&handler->events, evt, link);
158 		free(evt, M_TEMP);
159 	}
160 
161 	free(handler, M_DEVBUF);
162 	par->status = ISCSI_STATUS_SUCCESS;
163 	DEB(5, ("Deregister Event ID %d complete\n", par->event_id));
164 }
165 
166 
167 /*
168  * check_event:
169  *    Return first queued event. Optionally wait for arrival of event.
170  *
171  *    Parameter:
172  *          par   The parameter.
173  *          wait  Wait for event if true
174  */
175 
176 STATIC void
177 check_event(iscsi_wait_event_parameters_t *par, bool wait)
178 {
179 	event_handler_t *handler;
180 	event_t *evt;
181 
182 	handler = find_handler(par->event_id);
183 	if (handler == NULL) {
184 		DEBOUT(("Wait Event ID %d not found\n", par->event_id));
185 		par->status = ISCSI_STATUS_INVALID_EVENT_ID;
186 		return;
187 	}
188 	if (handler->waiter != NULL) {
189 		DEBOUT(("Wait Event ID %d already waiting\n", par->event_id));
190 		par->status = ISCSI_STATUS_EVENT_WAITING;
191 		return;
192 	}
193 	par->status = ISCSI_STATUS_SUCCESS;
194 	DEB(99, ("Wait Event ID %d\n", par->event_id));
195 
196 	do {
197 		int s = splbio();
198 		evt = TAILQ_FIRST(&handler->events);
199 		if (evt != NULL) {
200 			TAILQ_REMOVE(&handler->events, evt, link);
201 			splx(s);
202 		} else {
203 			if (!wait) {
204 				splx(s);
205 				par->status = ISCSI_STATUS_LIST_EMPTY;
206 				return;
207 			}
208 			if (par->status != ISCSI_STATUS_SUCCESS) {
209 				splx(s);
210 				return;
211 			}
212 			handler->waiter = par;
213 			splx(s);
214 			if (tsleep(par, PRIBIO | PCATCH, "iscsievtwait", 0))
215 				return;
216 		}
217 	} while (evt == NULL);
218 
219 	par->connection_id = evt->connection_id;
220 	par->session_id = evt->session_id;
221 	par->event_kind = evt->event_kind;
222 	par->reason = evt->reason;
223 
224 	free(evt, M_TEMP);
225 }
226 
227 /*
228  * add_event
229  *    Adds an event entry to each registered handler queue.
230  *    Note that events are simply duplicated because we expect the number of
231  *    handlers to be very small, usually 1 (the daemon).
232  *
233  *    Parameters:
234  *       kind     The event kind
235  *       sid      The ID of the affected session
236  *       cid      The ID of the affected connection
237  *       reason   The reason code
238  */
239 
240 void
241 add_event(iscsi_event_t kind, uint32_t sid, uint32_t cid, uint32_t reason)
242 {
243 	event_handler_t *curr;
244 	event_t *evt;
245 	int s;
246 
247 	DEB(9, ("Add_event kind %d, sid %d, cid %d, reason %d\n",
248 		kind, sid, cid, reason));
249 
250 	s = splbio();
251 	TAILQ_FOREACH(curr, &event_handlers, link) {
252 		evt = malloc(sizeof(*evt), M_TEMP, M_WAITOK);
253 		if (evt == NULL) {
254 			panic("iSCSI: add_event failed to alloc memory");
255 		}
256 		evt->event_kind = kind;
257 		evt->session_id = sid;
258 		evt->connection_id = cid;
259 		evt->reason = reason;
260 
261 		TAILQ_INSERT_TAIL(&curr->events, evt, link);
262 		if (curr->waiter != NULL) {
263 			wakeup(curr->waiter);
264 			curr->waiter = NULL;
265 		}
266 	}
267 	splx(s);
268 }
269 
270 
271 /*
272  * check_event_handlers
273  *    Checks for dead event handlers. A dead event handler would deplete
274  *    memory over time, so we have to make sure someone at the other
275  *    end is actively monitoring events.
276  *    This function is called every 30 seconds or so (less frequent if there
277  *    is other activity for the cleanup thread to deal with) to go through
278  *    the list of handlers and check whether the first element in the event
279  *    list has changed at all. If not, the event is deregistered.
280  *    Note that this will not detect dead handlers if no events are pending,
281  *    but we don't care as long as events don't accumulate in the list.
282  *
283  *    this function must be called at splbio
284  */
285 
286 STATIC void
287 check_event_handlers(void)
288 {
289 	event_handler_t *curr, *next;
290 	event_t *evt;
291 
292 	for (curr = TAILQ_FIRST(&event_handlers); curr != NULL; curr = next) {
293 		next = TAILQ_NEXT(curr, link);
294 		evt = TAILQ_FIRST(&curr->events);
295 
296 		if (evt != NULL && evt == curr->first_in_list) {
297 			DEBOUT(("Found Dead Event Handler %d, removing\n", curr->id));
298 
299 			TAILQ_REMOVE(&event_handlers, curr, link);
300 			while ((evt = TAILQ_FIRST(&curr->events)) != NULL) {
301 				TAILQ_REMOVE(&curr->events, evt, link);
302 				free(evt, M_TEMP);
303 			}
304 			free(curr, M_DEVBUF);
305 		} else
306 			curr->first_in_list = evt;
307 	}
308 }
309 
310 
311 /* -------------------------------------------------------------------------- */
312 
313 /*
314  * get_socket:
315  *    Get the file pointer from the socket handle passed into login.
316  *
317  *    Parameter:
318  *          fdes     IN: The socket handle
319  *          fpp      OUT: The pointer to the resulting file pointer
320  *
321  *    Returns:    0 on success, else an error code.
322  *
323  */
324 
325 STATIC int
326 get_socket(int fdes, struct file **fpp)
327 {
328 	struct file *fp;
329 
330 	if ((fp = fd_getfile(fdes)) == NULL) {
331 		return EBADF;
332 	}
333 	if (fp->f_type != DTYPE_SOCKET) {
334 		return ENOTSOCK;
335 	}
336 
337 	/* Add the reference */
338 	mutex_enter(&fp->f_lock);
339 	fp->f_count++;
340 	mutex_exit(&fp->f_lock);
341 
342 	*fpp = fp;
343 	return 0;
344 }
345 
346 /*
347  * release_socket:
348  *    Release the file pointer from the socket handle passed into login.
349  *
350  *    Parameter:
351  *          fp       IN: The pointer to the resulting file pointer
352  *
353  */
354 
355 STATIC void
356 release_socket(struct file *fp)
357 {
358 	/* Add the reference */
359 	mutex_enter(&fp->f_lock);
360 	fp->f_count--;
361 	mutex_exit(&fp->f_lock);
362 }
363 
364 
365 /*
366  * find_session:
367  *    Find a session by ID.
368  *
369  *    Parameter:  the session ID
370  *
371  *    Returns:    The pointer to the session (or NULL if not found)
372  */
373 
374 session_t *
375 find_session(uint32_t id)
376 {
377 	session_t *curr;
378 	int s;
379 
380 	s = splbio();
381 	TAILQ_FOREACH(curr, &iscsi_sessions, sessions)
382 		if (curr->id == id) {
383 			break;
384 		}
385 	splx(s);
386 	return curr;
387 }
388 
389 
390 /*
391  * find_connection:
392  *    Find a connection by ID.
393  *
394  *    Parameter:  the session pointer and the connection ID
395  *
396  *    Returns:    The pointer to the connection (or NULL if not found)
397  */
398 
399 connection_t *
400 find_connection(session_t *session, uint32_t id)
401 {
402 	connection_t *curr;
403 	int s;
404 
405 	s = splbio();
406 	TAILQ_FOREACH(curr, &session->conn_list, connections)
407 		if (curr->id == id) {
408 			break;
409 		}
410 	splx(s);
411 	return curr;
412 }
413 
414 
415 /*
416  * kill_connection:
417  *    Terminate the connection as gracefully as possible.
418  *
419  *    Parameter:
420  *		conn		The connection to terminate
421  *		status		The status code for the connection's "terminating" field
422  *		logout		The logout reason code
423  *		recover	Attempt to recover connection
424  */
425 
426 void
427 kill_connection(connection_t *conn, uint32_t status, int logout, bool recover)
428 {
429 	session_t *sess = conn->session;
430 	int s;
431 
432 	DEBC(conn, 1, ("Kill_connection: terminating=%d, status=%d, logout=%d, "
433 			   "state=%d\n",
434 			   conn->terminating, status, logout, conn->state));
435 
436 	if (recover &&
437 	    !conn->destroy &&
438 	    conn->recover > MAX_RECOVERY_ATTEMPTS) {
439 		DEBC(conn, 1,
440 			  ("Kill_connection: Too many recovery attempts, destroying\n"));
441 		conn->destroy = TRUE;
442 	}
443 
444 	if (!recover || conn->destroy) {
445 
446 		s = splbio();
447 		if (conn->in_session) {
448 			conn->in_session = FALSE;
449 			TAILQ_REMOVE(&sess->conn_list, conn, connections);
450 			sess->mru_connection = TAILQ_FIRST(&sess->conn_list);
451 		}
452 		splx(s);
453 
454 		if (!conn->destroy) {
455 			DEBC(conn, 1, ("Kill_connection setting destroy flag\n"));
456 			conn->destroy = TRUE;
457 		}
458 		/* in case it was already terminated earlier and rcv/send-threads */
459 		/* are waiting */
460 		wakeup(conn);
461 	}
462 
463 	/* Don't recurse */
464 	if (conn->terminating) {
465 		DEBC(conn, 1, ("Kill_connection exiting (already terminating)\n"));
466 		return;
467 	}
468 
469 	if (conn->state == ST_FULL_FEATURE) {
470 		sess->active_connections--;
471 
472 		/* If this is the last connection and ERL < 2, reset TSIH */
473 		if (!sess->active_connections && sess->ErrorRecoveryLevel < 2)
474 			sess->TSIH = 0;
475 
476 		/* Don't try to log out if the socket is broken or we're in the middle */
477 		/* of logging in */
478 		if (logout >= 0) {
479 			conn->state = ST_WINDING_DOWN;
480 			SET_CONN_TIMEOUT(conn, CONNECTION_TIMEOUT);
481 
482 			if (sess->ErrorRecoveryLevel < 2 &&
483 			    logout == RECOVER_CONNECTION) {
484 				logout = LOGOUT_CONNECTION;
485 			}
486 			if (!sess->active_connections &&
487 			    logout == LOGOUT_CONNECTION) {
488 				logout = LOGOUT_SESSION;
489 			}
490 			if (!send_logout(conn, conn, logout, FALSE)) {
491 				return;
492 			}
493 			/*
494 			 * if the logout request was successfully sent, the logout response
495 			 * handler will do the rest of the termination processing. If the
496 			 * logout doesn't get a response, we'll get back in here once
497 			 * the timeout hits.
498 			 */
499 		}
500 	}
501 
502 #ifdef ISCSI_TEST_MODE
503 	test_remove_connection(conn);
504 #endif
505 
506 	conn->terminating = status;
507 	conn->state = ST_SETTLING;
508 
509 	/* let send thread take over next step of cleanup */
510 	wakeup(&conn->pdus_to_send);
511 
512 	DEBC(conn, 5, ("kill_connection returns\n"));
513 }
514 
515 
516 /*
517  * kill_session:
518  *    Terminate the session as gracefully as possible.
519  *
520  *    Parameter:
521  *		session		Session to terminate
522  *		status		The status code for the termination
523  *		logout		The logout reason code
524 
525  */
526 
527 void
528 kill_session(session_t *session, uint32_t status, int logout, bool recover)
529 {
530 	connection_t *curr;
531 	ccb_t *ccb;
532 	int s;
533 
534 	DEB(1, ("ISCSI: kill_session %d, status %d, logout %d, recover %d\n",
535 			session->id, status, logout, recover));
536 
537 	/*
538 	 * don't do anything if session isn't established yet, termination will be
539 	 * handled elsewhere
540 	 */
541 	if (session->sessions.tqe_next == NULL &&
542 	    session->sessions.tqe_prev == NULL) {
543 		return;
544 	}
545 
546 	if (recover) {
547 		/*
548 		 * Only recover when there's just one active connection left.
549 		 * Otherwise we get in all sorts of timing problems, and it doesn't
550 		 * make much sense anyway to recover when the other side has
551 		 * requested that we kill a multipathed session.
552 		 */
553 		if (session->active_connections == 1) {
554 			curr = assign_connection(session, FALSE);
555 			if (curr != NULL)
556 				kill_connection(curr, status, logout, TRUE);
557 		}
558 		/* don't allow the session to disappear when the target */
559 		/* requested the logout */
560 		return;
561 	}
562 
563 	/* remove from session list */
564 	s = splbio();
565 	TAILQ_REMOVE(&iscsi_sessions, session, sessions);
566 	splx(s);
567 	session->sessions.tqe_next = NULL;
568 	session->sessions.tqe_prev = NULL;
569 
570 	/* complete any throttled CCBs */
571 	s = splbio();
572 	while ((ccb = TAILQ_FIRST(&session->ccbs_throttled)) != NULL) {
573 		throttle_ccb(ccb, FALSE);
574 		splx(s);
575 		wake_ccb(ccb, ISCSI_STATUS_LOGOUT);
576 		s = splbio();
577 	}
578 	splx(s);
579 
580 	/*
581 	 * unmap first to give the system an opportunity to flush its buffers,
582 	 * but don't try to unmap if it's a forced termination (connection is dead)
583 	 * to avoid waiting for pending commands that can't complete anyway.
584 	 */
585 	if (logout >= 0) {
586 		unmap_session(session);
587 		DEB(5, ("Unmap Returns\n"));
588 	}
589 
590 	/* kill all connections */
591 	while ((curr = TAILQ_FIRST(&session->conn_list)) != NULL) {
592 		kill_connection(curr, status, logout, FALSE);
593 		logout = NO_LOGOUT;
594 	}
595 }
596 
597 
598 /*
599  * create_connection:
600  *    Create and init the necessary framework for a connection:
601  *       Alloc the connection structure itself
602  *       Copy connection parameters
603  *       Create the send and receive threads
604  *       And finally, log in.
605  *
606  *    Parameter:
607  *          par      IN/OUT: The login parameters
608  *          session  IN: The owning session
609  *          p        IN: The proc pointer of the caller
610  *
611  *    Returns:    0 on success
612  *                >0 on failure, connection structure deleted
613  *                <0 on failure, connection is still terminating
614  */
615 
616 STATIC int
617 create_connection(iscsi_login_parameters_t *par, session_t *session,
618 				  PTHREADOBJ p)
619 {
620 	connection_t *connection;
621 	int rc, s;
622 
623 	DEB(1, ("Create Connection for Session %d\n", session->id));
624 
625 	if (session->MaxConnections &&
626 	    session->active_connections >= session->MaxConnections) {
627 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
628 				session->MaxConnections, session->active_connections));
629 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
630 		return EIO;
631 	}
632 
633 	connection = malloc(sizeof(*connection), M_DEVBUF, M_WAITOK | M_ZERO);
634 	if (connection == NULL) {
635 		DEBOUT(("No mem for connection\n"));
636 		par->status = ISCSI_STATUS_NO_RESOURCES;
637 		return EIO;
638 	}
639 
640 	/* create a unique ID */
641 	do {
642 		++session->conn_id;
643 	} while (!session->conn_id ||
644 		 find_connection(session, session->conn_id) != NULL);
645 
646 	par->connection_id = connection->id = session->conn_id;
647 	DEB(99, ("Connection ID = %d\n", connection->id));
648 
649 	connection->session = session;
650 
651 	TAILQ_INIT(&connection->ccbs_waiting);
652 	TAILQ_INIT(&connection->pdus_to_send);
653 	TAILQ_INIT(&connection->pdu_pool);
654 
655 	callout_init(&connection->timeout, 0);
656 	callout_setfunc(&connection->timeout, connection_timeout, connection);
657 	connection->idle_timeout_val = CONNECTION_IDLE_TIMEOUT;
658 
659 	init_sernum(&connection->StatSN_buf);
660 	create_pdus(connection);
661 
662 	if ((rc = get_socket(par->socket, &connection->sock)) != 0) {
663 		DEBOUT(("Invalid socket %d\n", par->socket));
664 
665 		free(connection, M_DEVBUF);
666 		par->status = ISCSI_STATUS_INVALID_SOCKET;
667 		return rc;
668 	}
669 	DEBC(connection, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
670 			par->socket, connection->sock));
671 
672 	/* close the file descriptor */
673 	fd_close(par->socket);
674 
675 	connection->threadobj = p;
676 	connection->login_par = par;
677 
678 	/*DEBOUT (("Creating receive thread\n")); */
679 	if ((rc = kthread_create(PRI_NONE, 0, NULL, iscsi_rcv_thread,
680 				connection, &connection->rcvproc,
681 				"ConnRcv")) != 0) {
682 		DEBOUT(("Can't create rcv thread (rc %d)\n", rc));
683 
684 		release_socket(connection->sock);
685 		free(connection, M_DEVBUF);
686 		par->status = ISCSI_STATUS_NO_RESOURCES;
687 		return rc;
688 	}
689 	/*DEBOUT (("Creating send thread\n")); */
690 	if ((rc = kthread_create(PRI_NONE, 0, NULL, iscsi_send_thread,
691 				connection, &connection->sendproc,
692 				"ConnSend")) != 0) {
693 		DEBOUT(("Can't create send thread (rc %d)\n", rc));
694 
695 		connection->terminating = ISCSI_STATUS_NO_RESOURCES;
696 
697 		/*
698 		 * We must close the socket here to force the receive
699 		 * thread to wake up
700 		 */
701 		DEBC(connection, 1,
702 			("Closing Socket %p\n", connection->sock));
703 		mutex_enter(&connection->sock->f_lock);
704 		connection->sock->f_count += 1;
705 		mutex_exit(&connection->sock->f_lock);
706 		closef(connection->sock);
707 
708 		/* give receive thread time to exit */
709 		tsleep(connection, PWAIT, "settle", 2 * hz);
710 
711 		release_socket(connection->sock);
712 		free(connection, M_DEVBUF);
713 		par->status = ISCSI_STATUS_NO_RESOURCES;
714 		return rc;
715 	}
716 
717 	/*
718 	 * At this point, each thread will tie 'sock' into its own file descriptor
719 	 * tables w/o increasing the use count - they will inherit the use
720 	 * increments performed in get_socket().
721 	 */
722 
723 #ifdef ISCSI_TEST_MODE
724 	test_assign_connection(connection);
725 #endif
726 
727 	if ((rc = send_login(connection)) != 0) {
728 		DEBC(connection, 0, ("Login failed (rc %d)\n", rc));
729 		/* Don't attempt to recover, there seems to be something amiss */
730 		kill_connection(connection, rc, NO_LOGOUT, FALSE);
731 		par->status = rc;
732 		return -1;
733 	}
734 
735 	s = splbio();
736 	connection->state = ST_FULL_FEATURE;
737 	TAILQ_INSERT_TAIL(&session->conn_list, connection, connections);
738 	connection->in_session = TRUE;
739 	session->total_connections++;
740 	session->active_connections++;
741 	session->mru_connection = connection;
742 	splx(s);
743 
744 	DEBC(connection, 5, ("Connection created successfully!\n"));
745 	return 0;
746 }
747 
748 
749 /*
750  * recreate_connection:
751  *    Revive dead connection
752  *
753  *    Parameter:
754  *          par      IN/OUT: The login parameters
755  *          conn     IN: The connection
756  *          p        IN: The proc pointer of the caller
757  *
758  *    Returns:    0 on success
759  *                >0 on failure, connection structure deleted
760  *                <0 on failure, connection is still terminating
761  */
762 
763 STATIC int
764 recreate_connection(iscsi_login_parameters_t *par, session_t *session,
765 					connection_t *connection, PTHREADOBJ p)
766 {
767 	int rc, s;
768 	ccb_t *ccb;
769 	ccb_list_t old_waiting;
770 
771 	DEB(1, ("ReCreate Connection %d for Session %d, ERL=%d\n",
772 		connection->id, connection->session->id,
773 		connection->session->ErrorRecoveryLevel));
774 
775 	if (session->MaxConnections &&
776 	    session->active_connections >= session->MaxConnections) {
777 		DEBOUT(("Too many connections (max = %d, curr = %d)\n",
778 			session->MaxConnections, session->active_connections));
779 		par->status = ISCSI_STATUS_MAXED_CONNECTIONS;
780 		return EIO;
781 	}
782 
783 	/* close old socket */
784 	if (connection->sock != NULL) {
785 		closef(connection->sock);
786 		connection->sock = NULL;
787 	}
788 
789 	if ((rc = get_socket(par->socket, &connection->sock)) != 0) {
790 		DEBOUT(("Invalid socket %d\n", par->socket));
791 		par->status = ISCSI_STATUS_INVALID_SOCKET;
792 		return rc;
793 	}
794 	DEBC(connection, 1, ("get_socket: par_sock=%d, fdesc=%p\n",
795 			par->socket, connection->sock));
796 
797 	/* close the file descriptor */
798 	fd_close(par->socket);
799 
800 	connection->threadobj = p;
801 	connection->login_par = par;
802 	connection->terminating = ISCSI_STATUS_SUCCESS;
803 	connection->recover++;
804 	connection->num_timeouts = 0;
805 	connection->state = ST_SEC_NEG;
806 	connection->HeaderDigest = 0;
807 	connection->DataDigest = 0;
808 
809 	session->active_connections++;
810 
811 	TAILQ_INIT(&old_waiting);
812 	s = splbio();
813 	TAILQ_CONCAT(&old_waiting, &connection->ccbs_waiting, chain);
814 	splx(s);
815 
816 	init_sernum(&connection->StatSN_buf);
817 	wakeup(connection);
818 
819 	if ((rc = send_login(connection)) != 0) {
820 		DEBOUT(("Login failed (rc %d)\n", rc));
821 		while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
822 			TAILQ_REMOVE(&old_waiting, ccb, chain);
823 			wake_ccb(ccb, rc);
824 		}
825 		/* Don't attempt to recover, there seems to be something amiss */
826 		kill_connection(connection, rc, NO_LOGOUT, FALSE);
827 		par->status = rc;
828 		return -1;
829 	}
830 
831 	DEBC(connection, 9, ("Re-Login successful\n"));
832 	par->status = ISCSI_STATUS_SUCCESS;
833 
834 	s = splbio();
835 	connection->state = ST_FULL_FEATURE;
836 	session->mru_connection = connection;
837 	splx(s);
838 
839 	while ((ccb = TAILQ_FIRST(&old_waiting)) != NULL) {
840 		TAILQ_REMOVE(&old_waiting, ccb, chain);
841 		s = splbio();
842 		suspend_ccb(ccb, TRUE);
843 		splx(s);
844 
845 		rc = send_task_management(connection, ccb, NULL, TASK_REASSIGN);
846 		/* if we get an error on reassign, restart the original request */
847 		if (rc && ccb->pdu_waiting != NULL) {
848 			if (ccb->CmdSN < session->ExpCmdSN) {
849 				pdu_t *pdu = ccb->pdu_waiting;
850 
851 				/* update CmdSN */
852 				DEBC(connection, 1, ("Resend Updating CmdSN - old %d, new %d\n",
853 					   ccb->CmdSN, session->CmdSN));
854 				ccb->CmdSN = session->CmdSN;
855 				if (!(pdu->pdu.Opcode & OP_IMMEDIATE))
856 					session->CmdSN++;
857 				pdu->pdu.p.command.CmdSN = htonl(ccb->CmdSN);
858 			}
859 			resend_pdu(ccb);
860 		} else {
861 			SET_CCB_TIMEOUT(connection, ccb, COMMAND_TIMEOUT);
862 		}
863 	}
864 
865 	wakeup(session);
866 
867 	DEBC(connection, 5, ("Connection ReCreated successfully - status %d\n",
868 						 par->status));
869 
870 	return 0;
871 }
872 
873 /* -------------------------------------------------------------------------- */
874 
875 /*
876  * check_login_pars:
877  *    Check the parameters passed into login/add_connection
878  *    for validity and consistency.
879  *
880  *    Parameter:
881  *          par      The login parameters
882  *
883  *    Returns:    0 on success, else an error code.
884  */
885 
886 STATIC int
887 check_login_pars(iscsi_login_parameters_t *par)
888 {
889 	int i, n;
890 
891 	if (par->is_present.auth_info) {
892 		/* check consistency of authentication parameters */
893 
894 		if (par->auth_info.auth_number > ISCSI_AUTH_OPTIONS) {
895 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
896 			return ISCSI_STATUS_PARAMETER_INVALID;
897 		}
898 
899 		if (par->auth_info.auth_number > 2) {
900 			DEBOUT(("Auth number invalid: %d\n", par->auth_info.auth_number));
901 			return ISCSI_STATUS_NOTIMPL;
902 		}
903 
904 		for (i = 0, n = 0; i < par->auth_info.auth_number; i++) {
905 #if 0
906 			if (par->auth_info.auth_type[i] < ISCSI_AUTH_None) {
907 				DEBOUT(("Auth type invalid: %d\n",
908 						par->auth_info.auth_type[i]));
909 				return ISCSI_STATUS_PARAMETER_INVALID;
910 			}
911 #endif
912 			if (par->auth_info.auth_type[i] > ISCSI_AUTH_CHAP) {
913 				DEBOUT(("Auth type invalid: %d\n",
914 						par->auth_info.auth_type[i]));
915 				return ISCSI_STATUS_NOTIMPL;
916 			}
917 			n = max(n, par->auth_info.auth_type[i]);
918 		}
919 		if (n) {
920 			if (!par->is_present.password ||
921 				(par->auth_info.mutual_auth &&
922 				 !par->is_present.target_password)) {
923 				DEBOUT(("Password missing\n"));
924 				return ISCSI_STATUS_PARAMETER_MISSING;
925 			}
926 			/* Note: Default for user-name is initiator name */
927 		}
928 	}
929 	if (par->login_type != ISCSI_LOGINTYPE_DISCOVERY &&
930 	    !par->is_present.TargetName) {
931 		DEBOUT(("Target name missing, login type %d\n", par->login_type));
932 		return ISCSI_STATUS_PARAMETER_MISSING;
933 	}
934 	if (par->is_present.MaxRecvDataSegmentLength) {
935 		if (par->MaxRecvDataSegmentLength < 512 ||
936 			par->MaxRecvDataSegmentLength > 0xffffff) {
937 			DEBOUT(("MaxRecvDataSegmentLength invalid: %d\n",
938 					par->MaxRecvDataSegmentLength));
939 			return ISCSI_STATUS_PARAMETER_INVALID;
940 		}
941 	}
942 	return 0;
943 }
944 
945 
946 /*
947  * login:
948  *    Handle the login ioctl - Create a session:
949  *       Alloc the session structure
950  *       Copy session parameters
951  *       And call create_connection to establish the connection.
952  *
953  *    Parameter:
954  *          par      IN/OUT: The login parameters
955  *          p        IN: The proc pointer of the caller
956  */
957 
958 STATIC void
959 login(iscsi_login_parameters_t *par, PTHREADOBJ p)
960 {
961 	session_t *session;
962 	int rc, s;
963 
964 	DEB(99, ("ISCSI: login\n"));
965 
966 	if (!iscsi_InitiatorName[0]) {
967 		DEB(1, ("No Initiator Name\n"));
968 		par->status = ISCSI_STATUS_NO_INITIATOR_NAME;
969 		return;
970 	}
971 
972 	if ((par->status = check_login_pars(par)) != 0)
973 		return;
974 
975 	/* alloc the session */
976 	session = malloc(sizeof(*session), M_DEVBUF, M_WAITOK | M_ZERO);
977 	if (session == NULL) {
978 		DEBOUT(("No mem for session\n"));
979 		par->status = ISCSI_STATUS_NO_RESOURCES;
980 		return;
981 	}
982 	TAILQ_INIT(&session->conn_list);
983 	TAILQ_INIT(&session->ccb_pool);
984 	TAILQ_INIT(&session->ccbs_throttled);
985 
986 	/* create a unique ID */
987 	do {
988 		++current_id;
989 	} while (!current_id || find_session(current_id) != NULL);
990 	par->session_id = session->id = current_id;
991 
992 	create_ccbs(session);
993 	session->login_type = par->login_type;
994 	session->CmdSN = 1;
995 
996 	if ((rc = create_connection(par, session, p)) != 0) {
997 		if (rc > 0) {
998 			free(session, M_DEVBUF);
999 		}
1000 		return;
1001 	}
1002 
1003 	s = splbio();
1004 	TAILQ_INSERT_HEAD(&iscsi_sessions, session, sessions);
1005 	splx(s);
1006 
1007 	/* Session established, map LUNs? */
1008 	if (par->login_type == ISCSI_LOGINTYPE_MAP) {
1009 		copyinstr(par->TargetName, session->tgtname,
1010 		    sizeof(session->tgtname), NULL);
1011 		if (!map_session(session)) {
1012 			kill_session(session, ISCSI_STATUS_MAP_FAILED,
1013 					LOGOUT_SESSION, FALSE);
1014 			par->status = ISCSI_STATUS_MAP_FAILED;
1015 			return;
1016 		}
1017 	}
1018 }
1019 
1020 
1021 /*
1022  * logout:
1023  *    Handle the logout ioctl - Kill a session.
1024  *
1025  *    Parameter:
1026  *          par      IN/OUT: The login parameters
1027  */
1028 
1029 STATIC void
1030 logout(iscsi_logout_parameters_t *par)
1031 {
1032 	session_t *session;
1033 
1034 	DEB(5, ("ISCSI: logout session %d\n", par->session_id));
1035 
1036 	if ((session = find_session(par->session_id)) == NULL) {
1037 		DEBOUT(("Session %d not found\n", par->session_id));
1038 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1039 		return;
1040 	}
1041 	/* If the session exists, this always succeeds */
1042 	par->status = ISCSI_STATUS_SUCCESS;
1043 
1044 	kill_session(session, ISCSI_STATUS_LOGOUT, LOGOUT_SESSION, FALSE);
1045 }
1046 
1047 
1048 /*
1049  * add_connection:
1050  *    Handle the add_connection ioctl.
1051  *
1052  *    Parameter:
1053  *          par      IN/OUT: The login parameters
1054  *          p        IN: The proc pointer of the caller
1055  */
1056 
1057 STATIC void
1058 add_connection(iscsi_login_parameters_t *par, PTHREADOBJ p)
1059 {
1060 	session_t *session;
1061 
1062 	DEB(5, ("ISCSI: add_connection to session %d\n", par->session_id));
1063 
1064 	if ((session = find_session(par->session_id)) == NULL) {
1065 		DEBOUT(("Session %d not found\n", par->session_id));
1066 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1067 		return;
1068 	}
1069 	if ((par->status = check_login_pars(par)) == 0) {
1070 		create_connection(par, session, p);
1071 	}
1072 }
1073 
1074 
1075 /*
1076  * remove_connection:
1077  *    Handle the remove_connection ioctl.
1078  *
1079  *    Parameter:
1080  *          par      IN/OUT: The remove parameters
1081  */
1082 
1083 STATIC void
1084 remove_connection(iscsi_remove_parameters_t *par)
1085 {
1086 	connection_t *conn;
1087 	session_t *session;
1088 
1089 	DEB(5, ("ISCSI: remove_connection %d from session %d\n",
1090 			par->connection_id, par->session_id));
1091 
1092 	if ((session = find_session(par->session_id)) == NULL) {
1093 		DEBOUT(("Session %d not found\n", par->session_id));
1094 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1095 		return;
1096 	}
1097 
1098 	if ((conn = find_connection(session, par->connection_id)) == NULL) {
1099 		DEBOUT(("Connection %d not found in session %d\n",
1100 				par->connection_id, par->session_id));
1101 
1102 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1103 	} else {
1104 		kill_connection(conn, ISCSI_STATUS_LOGOUT, LOGOUT_CONNECTION,
1105 					FALSE);
1106 		par->status = ISCSI_STATUS_SUCCESS;
1107 	}
1108 }
1109 
1110 
1111 /*
1112  * restore_connection:
1113  *    Handle the restore_connection ioctl.
1114  *
1115  *    Parameter:
1116  *          par      IN/OUT: The login parameters
1117  *          p        IN: The proc pointer of the caller
1118  */
1119 
1120 STATIC void
1121 restore_connection(iscsi_login_parameters_t *par, PTHREADOBJ p)
1122 {
1123 	session_t *session;
1124 	connection_t *connection;
1125 
1126 	DEB(1, ("ISCSI: restore_connection %d of session %d\n",
1127 			par->connection_id, par->session_id));
1128 
1129 	if ((session = find_session(par->session_id)) == NULL) {
1130 		DEBOUT(("Session %d not found\n", par->session_id));
1131 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1132 		return;
1133 	}
1134 
1135 	if ((connection = find_connection(session, par->connection_id)) == NULL) {
1136 		DEBOUT(("Connection %d not found in session %d\n",
1137 				par->connection_id, par->session_id));
1138 		par->status = ISCSI_STATUS_INVALID_CONNECTION_ID;
1139 		return;
1140 	}
1141 
1142 	if ((par->status = check_login_pars(par)) == 0) {
1143 		recreate_connection(par, session, connection, p);
1144 	}
1145 }
1146 
1147 
1148 #ifndef ISCSI_MINIMAL
1149 
1150 /*
1151  * map_databuf:
1152  *    Map user-supplied data buffer into kernel space.
1153  *
1154  *    Parameter:
1155  *          p        IN: The proc pointer of the caller
1156  *          buf      IN/OUT: The virtual address of the buffer, modified
1157  *                   on exit to reflect kernel VA.
1158  *          datalen  IN: The size of the data buffer
1159  *
1160  *    Returns:
1161  *          An ISCSI status code on error, else 0.
1162  */
1163 
1164 uint32_t
1165 map_databuf(struct proc *p, void **buf, uint32_t datalen)
1166 {
1167 	vaddr_t kva, databuf, offs;
1168 	int error;
1169 
1170 	/* page align address */
1171 	databuf = (vaddr_t) * buf & ~PAGE_MASK;
1172 	/* offset of VA into page */
1173 	offs = (vaddr_t) * buf & PAGE_MASK;
1174 	/* round to full page including offset */
1175 	datalen = (datalen + offs + PAGE_MASK) & ~PAGE_MASK;
1176 
1177 	/* Do some magic to the vm space reference count (copied from "copyin_proc") */
1178 	if ((p->p_sflag & PS_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) {
1179 		return ISCSI_STATUS_NO_RESOURCES;
1180 	}
1181 	p->p_vmspace->vm_refcnt++;
1182 
1183 	/* this is lifted from uvm_io */
1184 	error = uvm_map_extract(&p->p_vmspace->vm_map, databuf, datalen,
1185 			kernel_map, &kva,
1186 			UVM_EXTRACT_QREF | UVM_EXTRACT_CONTIG |
1187 				UVM_EXTRACT_FIXPROT);
1188 	if (error) {
1189 		DEBOUT(("uvm_map_extract failed, error = %d\n", error));
1190 		return ISCSI_STATUS_NO_RESOURCES;
1191 	}
1192 	/* add offset back into kernel VA */
1193 	*buf = (void *) (kva + offs);
1194 
1195 	return 0;
1196 }
1197 
1198 
1199 /*
1200  * unmap_databuf:
1201  *    Remove kernel space mapping of data buffer.
1202  *
1203  *    Parameter:
1204  *          p        IN: The proc pointer of the caller
1205  *          buf      IN: The kernel virtual address of the buffer
1206  *          datalen  IN: The size of the data buffer
1207  *
1208  *    Returns:
1209  *          An ISCSI status code on error, else 0.
1210  */
1211 
1212 void
1213 unmap_databuf(struct proc *p, void *buf, uint32_t datalen)
1214 {
1215 	struct vm_map_entry *dead_entries;
1216 	vaddr_t databuf;
1217 
1218 	/* round to full page */
1219 	datalen = (datalen + ((uintptr_t) buf & PAGE_MASK) + PAGE_MASK) & ~PAGE_MASK;
1220 	/* page align address */
1221 	databuf = (vaddr_t) buf & ~PAGE_MASK;
1222 
1223 	/* following code lifted almost verbatim from uvm_io.c */
1224 	vm_map_lock(kernel_map);
1225 	uvm_unmap_remove(kernel_map, databuf, databuf + datalen, &dead_entries
1226 #if (__NetBSD_Version__ >= 399000500)
1227 					 , 0
1228 #elif   (__NetBSD_Version__ >= 300000000)
1229 					 , NULL
1230 #endif
1231 		);
1232 	vm_map_unlock(kernel_map);
1233 	if (dead_entries != NULL) {
1234 		uvm_unmap_detach(dead_entries, AMAP_REFALL);
1235 	}
1236 	/* this apparently reverses the magic to the vm ref count, from copyin_proc */
1237 	uvmspace_free(p->p_vmspace);
1238 }
1239 
1240 
1241 /*
1242  * io_command:
1243  *    Handle the io_command ioctl.
1244  *
1245  *    Parameter:
1246  *          par      IN/OUT: The iocommand parameters
1247  *          p        IN: The proc pointer of the caller
1248  */
1249 
1250 STATIC void
1251 io_command(iscsi_iocommand_parameters_t *par, PTHREADOBJ p)
1252 {
1253 	uint32_t datalen = par->req.datalen;
1254 	void *databuf = par->req.databuf;
1255 	session_t *session;
1256 
1257 	DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
1258 	if ((session = find_session(par->session_id)) == NULL) {
1259 		DEBOUT(("Session %d not found\n", par->session_id));
1260 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1261 		return;
1262 	}
1263 
1264 	par->req.senselen_used = 0;
1265 	par->req.datalen_used = 0;
1266 	par->req.error = 0;
1267 	par->req.status = 0;
1268 	par->req.retsts = SCCMD_UNKNOWN;	/* init to failure code */
1269 
1270 	if (par->req.cmdlen > 16 || par->req.senselen > sizeof(par->req.sense)) {
1271 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1272 		return;
1273 	}
1274 
1275 	if (datalen && (par->status = map_databuf(PROCP(p),
1276 			&par->req.databuf, datalen)) != 0) {
1277 		return;
1278 	}
1279 	par->status = send_io_command(session, par->lun, &par->req,
1280 								  par->options.immediate, par->connection_id);
1281 
1282 	if (datalen) {
1283 		unmap_databuf(PROCP(p), par->req.databuf, datalen);
1284 		par->req.databuf = databuf;	/* restore original addr */
1285 	}
1286 
1287 	switch (par->status) {
1288 	case ISCSI_STATUS_SUCCESS:
1289 		par->req.retsts = SCCMD_OK;
1290 		break;
1291 
1292 	case ISCSI_STATUS_TARGET_BUSY:
1293 		par->req.retsts = SCCMD_BUSY;
1294 		break;
1295 
1296 	case ISCSI_STATUS_TIMEOUT:
1297 	case ISCSI_STATUS_SOCKET_ERROR:
1298 		par->req.retsts = SCCMD_TIMEOUT;
1299 		break;
1300 
1301 	default:
1302 		par->req.retsts = (par->req.senselen_used) ? SCCMD_SENSE
1303 												   : SCCMD_UNKNOWN;
1304 		break;
1305 	}
1306 }
1307 #endif
1308 
1309 /*
1310  * send_targets:
1311  *    Handle the send_targets ioctl.
1312  *    Note: If the passed buffer is too small to hold the complete response,
1313  *    the response is kept in the session structure so it can be
1314  *    retrieved with the next call to this function without having to go to
1315  *    the target again. Once the complete response has been retrieved, it
1316  *    is discarded.
1317  *
1318  *    Parameter:
1319  *          par      IN/OUT: The send_targets parameters
1320  */
1321 
1322 STATIC void
1323 send_targets(iscsi_send_targets_parameters_t *par)
1324 {
1325 	int rc;
1326 	uint32_t rlen, cplen;
1327 	session_t *session;
1328 
1329 	if ((session = find_session(par->session_id)) == NULL) {
1330 		DEBOUT(("Session %d not found\n", par->session_id));
1331 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1332 		return;
1333 	}
1334 
1335 	DEB(9, ("ISCSI: send_targets, rsp_size=%d; Saved list: %p\n",
1336 			par->response_size, session->target_list));
1337 
1338 	if (session->target_list == NULL) {
1339 		rc = send_send_targets(session, par->key);
1340 		if (rc) {
1341 			par->status = rc;
1342 			return;
1343 		}
1344 	}
1345 	rlen = session->target_list_len;
1346 	par->response_total = rlen;
1347 	cplen = min(par->response_size, rlen);
1348 	if (cplen) {
1349 		copyout(session->target_list, par->response_buffer, cplen);
1350 	}
1351 	par->response_used = cplen;
1352 
1353 	/* If all of the response was copied, don't keep it around */
1354 	if (rlen && par->response_used == rlen) {
1355 		free(session->target_list, M_TEMP);
1356 		session->target_list = NULL;
1357 	}
1358 
1359 	par->status = ISCSI_STATUS_SUCCESS;
1360 }
1361 
1362 
1363 /*
1364  * set_node_name:
1365  *    Handle the set_node_name ioctl.
1366  *
1367  *    Parameter:
1368  *          par      IN/OUT: The set_node_name parameters
1369  */
1370 
1371 STATIC void
1372 set_node_name(iscsi_set_node_name_parameters_t *par)
1373 {
1374 
1375 	if (strlen(par->InitiatorName) >= ISCSI_STRING_LENGTH ||
1376 		strlen(par->InitiatorAlias) >= ISCSI_STRING_LENGTH) {
1377 		DEBOUT(("*** set_node_name string too long!\n"));
1378 		par->status = ISCSI_STATUS_PARAMETER_INVALID;
1379 		return;
1380 	}
1381 	strlcpy(iscsi_InitiatorName, par->InitiatorName, sizeof(iscsi_InitiatorName));
1382 	strlcpy(iscsi_InitiatorAlias, par->InitiatorAlias, sizeof(iscsi_InitiatorAlias));
1383 	memcpy(&iscsi_InitiatorISID, par->ISID, 6);
1384 	DEB(5, ("ISCSI: set_node_name, ISID A=%x, B=%x, C=%x, D=%x\n",
1385 			iscsi_InitiatorISID.ISID_A, iscsi_InitiatorISID.ISID_B,
1386 			iscsi_InitiatorISID.ISID_C, iscsi_InitiatorISID.ISID_D));
1387 
1388 	if (!iscsi_InitiatorISID.ISID_A && !iscsi_InitiatorISID.ISID_B &&
1389 		!iscsi_InitiatorISID.ISID_C && !iscsi_InitiatorISID.ISID_D) {
1390 		iscsi_InitiatorISID.ISID_A = T_FORMAT_EN;
1391 		iscsi_InitiatorISID.ISID_B = htons(0x1);
1392 		iscsi_InitiatorISID.ISID_C = 0x37;
1393 		iscsi_InitiatorISID.ISID_D = 0;
1394 	}
1395 
1396 	par->status = ISCSI_STATUS_SUCCESS;
1397 }
1398 
1399 
1400 /*
1401  * connection_status:
1402  *    Handle the connection_status ioctl.
1403  *
1404  *    Parameter:
1405  *          par      IN/OUT: The status parameters
1406  */
1407 
1408 STATIC void
1409 connection_status(iscsi_conn_status_parameters_t *par)
1410 {
1411 	connection_t *conn;
1412 	session_t *session;
1413 
1414 	if ((session = find_session(par->session_id)) == NULL) {
1415 		par->status = ISCSI_STATUS_INVALID_SESSION_ID;
1416 		return;
1417 	}
1418 
1419 	if (par->connection_id) {
1420 		conn = find_connection(session, par->connection_id);
1421 	} else {
1422 		conn = TAILQ_FIRST(&session->conn_list);
1423 	}
1424 	par->status = (conn == NULL) ? ISCSI_STATUS_INVALID_CONNECTION_ID :
1425 					ISCSI_STATUS_SUCCESS;
1426 	DEB(9, ("ISCSI: connection_status, session %d connection %d --> %d\n",
1427 			par->session_id, par->connection_id, par->status));
1428 }
1429 
1430 
1431 /*
1432  * get_version:
1433  *    Handle the get_version ioctl.
1434  *
1435  *    Parameter:
1436  *          par      IN/OUT: The version parameters
1437  */
1438 
1439 STATIC void
1440 get_version(iscsi_get_version_parameters_t *par)
1441 {
1442 	par->status = ISCSI_STATUS_SUCCESS;
1443 	par->interface_version = INTERFACE_VERSION;
1444 	par->major = VERSION_MAJOR;
1445 	par->minor = VERSION_MINOR;
1446 	strlcpy(par->version_string, VERSION_STRING,
1447 		sizeof(par->version_string));
1448 }
1449 
1450 
1451 /* -------------------------------------------------------------------- */
1452 
1453 /*
1454  * kill_all_sessions:
1455  *    Terminate all sessions (called when the driver unloads).
1456  */
1457 
1458 void
1459 kill_all_sessions(void)
1460 {
1461 	session_t *sess;
1462 
1463 	while ((sess = TAILQ_FIRST(&iscsi_sessions)) != NULL) {
1464 		kill_session(sess, ISCSI_STATUS_DRIVER_UNLOAD, LOGOUT_SESSION,
1465 				FALSE);
1466 	}
1467 }
1468 
1469 /*
1470  * handle_connection_error:
1471  *    Deal with a problem during send or receive.
1472  *
1473  *    Parameter:
1474  *       conn        The connection the problem is associated with
1475  *       status      The status code to insert into any unfinished CCBs
1476  *       dologout    Whether Logout should be attempted
1477  */
1478 
1479 void
1480 handle_connection_error(connection_t *conn, uint32_t status, int dologout)
1481 {
1482 
1483 	DEBC(conn, 0, ("*** Connection Error, status=%d, logout=%d, state=%d\n",
1484 				   status, dologout, conn->state));
1485 
1486 	if (!conn->terminating && conn->state <= ST_LOGOUT_SENT) {
1487 		/* if we get an error while winding down, escalate it */
1488 		if (dologout >= 0 && conn->state >= ST_WINDING_DOWN) {
1489 			dologout = NO_LOGOUT;
1490 		}
1491 		kill_connection(conn, status, dologout, TRUE);
1492 	}
1493 }
1494 
1495 
1496 /*
1497  * iscsi_cleanup_thread
1498  *    Global thread to handle connection and session cleanup after termination.
1499  */
1500 
1501 void
1502 iscsi_cleanup_thread(void *par)
1503 {
1504 	int s, rc;
1505 	connection_t *conn;
1506 	session_t *sess, *nxt;
1507 	uint32_t status;
1508 
1509 	s = splbio();
1510 	while ((conn = TAILQ_FIRST(&iscsi_cleanupc_list)) != NULL ||
1511 		iscsi_num_send_threads ||
1512 		!iscsi_detaching) {
1513 		if (conn != NULL) {
1514 			TAILQ_REMOVE(&iscsi_cleanupc_list, conn, connections);
1515 			splx(s);
1516 
1517 			sess = conn->session;
1518 			status = conn->terminating;
1519 
1520 			DEBC(conn, 5, ("Cleanup: Waiting for threads to exit\n"));
1521 			while (conn->sendproc || conn->rcvproc)
1522 				tsleep(conn, PWAIT, "termwait", hz);
1523 
1524 			while (conn->usecount > 0)
1525 				tsleep(conn, PWAIT, "finalwait", hz);
1526 
1527 			callout_stop(&conn->timeout);
1528 			closef(conn->sock);
1529 			free(conn, M_DEVBUF);
1530 
1531 			--sess->total_connections;
1532 
1533 			s = splbio();
1534 			TAILQ_FOREACH_SAFE(sess, &iscsi_cleanups_list, sessions, nxt) {
1535 				if (sess->total_connections != 0)
1536 					continue;
1537 
1538 				TAILQ_REMOVE(&iscsi_cleanups_list, sess, sessions);
1539 				splx(s);
1540 
1541 				DEB(1, ("Cleanup: Unmap session %d\n", sess->id));
1542 
1543 				rc = unmap_session(sess);
1544 				if (rc == 0) {
1545 					DEB(1, ("Cleanup: Unmap session %d failed\n", sess->id));
1546 					s = splbio();
1547 					TAILQ_INSERT_HEAD(&iscsi_cleanups_list, sess, sessions);
1548 					splx(s);
1549 				}
1550 
1551 				if (sess->target_list != NULL)
1552 					free(sess->target_list, M_TEMP);
1553 				/* notify event handlers of session shutdown */
1554 				add_event(ISCSI_SESSION_TERMINATED, sess->id, 0, status);
1555 				free(sess, M_DEVBUF);
1556 
1557 				DEB(1, ("Cleanup: session ended %d\n", sess->id));
1558 				s = splbio();
1559 			}
1560 			splx(s);
1561 
1562 			DEB(5, ("Cleanup: Done\n"));
1563 
1564 			s = splbio();
1565 		} else {
1566 			/* Go to sleep, but wake up every 30 seconds to
1567 			 * check for dead event handlers */
1568 			splx(s);
1569 			rc = tsleep(&iscsi_cleanupc_list, PWAIT, "cleanup",
1570 				(TAILQ_FIRST(&event_handlers)) ? 30 * hz : 0);
1571 			s = splbio();
1572 			/* if timed out, not woken up */
1573 			if (rc == EWOULDBLOCK)
1574 				check_event_handlers();
1575 		}
1576 	}
1577 	splx(s);
1578 
1579 	add_event(ISCSI_DRIVER_TERMINATING, 0, 0, ISCSI_STATUS_DRIVER_UNLOAD);
1580 
1581 	/*
1582      * Wait for all event handlers to deregister, but don't wait more
1583      * than 1 minute (assume registering app has died if it takes longer).
1584 	 */
1585 	for (s = 0; TAILQ_FIRST(&event_handlers) != NULL && s < 60; s++)
1586 		tsleep(&s, PWAIT, "waiteventclr", hz);
1587 
1588 	iscsi_cleanproc = NULL;
1589 	DEB(5, ("Cleanup thread exits\n"));
1590 	kthread_exit(0);
1591 }
1592 
1593 
1594 /* -------------------------------------------------------------------- */
1595 
1596 /*
1597  * iscsi_ioctl:
1598  *    Driver ioctl entry.
1599  *
1600  *    Parameter:
1601  *       dev      The device (ignored)
1602  *       cmd      The ioctl Command
1603  *       addr     IN/OUT: The command parameter
1604  *       flag     Flags (ignored)
1605  *       p        IN: The thread object of the caller
1606  */
1607 
1608 int
1609 iscsiioctl(dev_t dev, u_long cmd, void *addr, int flag, PTHREADOBJ p)
1610 {
1611 
1612 	DEB(1, ("ISCSI Ioctl cmd = %x\n", (int) cmd));
1613 
1614 	switch (cmd) {
1615 	case ISCSI_GET_VERSION:
1616 		get_version((iscsi_get_version_parameters_t *) addr);
1617 		break;
1618 
1619 	case ISCSI_LOGIN:
1620 		login((iscsi_login_parameters_t *) addr, p);
1621 		break;
1622 
1623 	case ISCSI_ADD_CONNECTION:
1624 		add_connection((iscsi_login_parameters_t *) addr, p);
1625 		break;
1626 
1627 	case ISCSI_RESTORE_CONNECTION:
1628 		restore_connection((iscsi_login_parameters_t *) addr, p);
1629 		break;
1630 
1631 	case ISCSI_LOGOUT:
1632 		logout((iscsi_logout_parameters_t *) addr);
1633 		break;
1634 
1635 	case ISCSI_REMOVE_CONNECTION:
1636 		remove_connection((iscsi_remove_parameters_t *) addr);
1637 		break;
1638 
1639 #ifndef ISCSI_MINIMAL
1640 	case ISCSI_IO_COMMAND:
1641 		io_command((iscsi_iocommand_parameters_t *) addr, p);
1642 		break;
1643 #endif
1644 
1645 	case ISCSI_SEND_TARGETS:
1646 		send_targets((iscsi_send_targets_parameters_t *) addr);
1647 		break;
1648 
1649 	case ISCSI_SET_NODE_NAME:
1650 		set_node_name((iscsi_set_node_name_parameters_t *) addr);
1651 		break;
1652 
1653 	case ISCSI_CONNECTION_STATUS:
1654 		connection_status((iscsi_conn_status_parameters_t *) addr);
1655 		break;
1656 
1657 	case ISCSI_REGISTER_EVENT:
1658 		register_event((iscsi_register_event_parameters_t *) addr);
1659 		break;
1660 
1661 	case ISCSI_DEREGISTER_EVENT:
1662 		deregister_event((iscsi_register_event_parameters_t *) addr);
1663 		break;
1664 
1665 	case ISCSI_WAIT_EVENT:
1666 		check_event((iscsi_wait_event_parameters_t *) addr, TRUE);
1667 		break;
1668 
1669 	case ISCSI_POLL_EVENT:
1670 		check_event((iscsi_wait_event_parameters_t *) addr, FALSE);
1671 		break;
1672 
1673 #ifdef ISCSI_PERFTEST
1674 	case ISCSI_PERFDATA_START:
1675 		perf_start((iscsi_perf_startstop_parameters_t *) addr);
1676 		break;
1677 
1678 	case ISCSI_PERFDATA_STOP:
1679 		perf_stop((iscsi_perf_startstop_parameters_t *) addr);
1680 		break;
1681 
1682 	case ISCSI_PERFDATA_GET:
1683 		perf_get((iscsi_perf_get_parameters_t *) addr);
1684 		break;
1685 #endif
1686 
1687 #ifdef ISCSI_TEST_MODE
1688 	case ISCSI_TEST_DEFINE:
1689 		test_define((iscsi_test_define_parameters_t *) addr);
1690 		break;
1691 
1692 	case ISCSI_TEST_ADD_NEGOTIATION:
1693 		test_add_neg((iscsi_test_add_negotiation_parameters_t *) addr);
1694 		break;
1695 
1696 	case ISCSI_TEST_ADD_MODIFICATION:
1697 		test_add_mod(PROCP(p), (iscsi_test_add_modification_parameters_t *) addr);
1698 		break;
1699 
1700 	case ISCSI_TEST_SEND_PDU:
1701 		test_send_pdu(PROCP(p), (iscsi_test_send_pdu_parameters_t *) addr);
1702 		break;
1703 
1704 	case ISCSI_TEST_CANCEL:
1705 		test_cancel((iscsi_test_cancel_parameters_t *) addr);
1706 		break;
1707 #endif
1708 
1709 	default:
1710 		DEBOUT(("Invalid IO-Control Code\n"));
1711 		return ENOTTY;
1712 	}
1713 
1714     /*
1715      * NOTE: We return 0 even if the function fails as long as the ioctl code
1716      * is good, so the status code is copied back to the caller.
1717 	 */
1718 	return 0;
1719 }
1720