xref: /illumos-gate/usr/src/uts/common/io/idm/idm_so.c (revision 9c57abc8d70cb139020be846baec0a9c4d9a73cd)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/conf.h>
27 #include <sys/stat.h>
28 #include <sys/file.h>
29 #include <sys/ddi.h>
30 #include <sys/sunddi.h>
31 #include <sys/modctl.h>
32 #include <sys/priv.h>
33 #include <sys/cpuvar.h>
34 #include <sys/socket.h>
35 #include <sys/strsubr.h>
36 #include <sys/sysmacros.h>
37 #include <sys/sdt.h>
38 #include <netinet/tcp.h>
39 #include <inet/tcp.h>
40 #include <sys/socketvar.h>
41 #include <sys/pathname.h>
42 #include <sys/fs/snode.h>
43 #include <sys/fs/dv_node.h>
44 #include <sys/vnode.h>
45 #include <netinet/in.h>
46 #include <net/if.h>
47 #include <sys/sockio.h>
48 #include <sys/ksocket.h>
49 #include <sys/idm/idm.h>
50 #include <sys/idm/idm_so.h>
51 #include <sys/idm/idm_text.h>
52 
53 /*
54  * in6addr_any is currently all zeroes, but use the macro in case this
55  * ever changes.
56  */
57 const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
58 
59 static void idm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
60 static void idm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
61 static void idm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
62 
63 static idm_status_t idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so);
64 static void idm_so_conn_destroy_common(idm_conn_t *ic);
65 static void idm_so_conn_connect_common(idm_conn_t *ic);
66 
67 static void idm_set_ini_preconnect_options(idm_so_conn_t *sc);
68 static void idm_set_ini_postconnect_options(idm_so_conn_t *sc);
69 static void idm_set_tgt_connect_options(ksocket_t so);
70 static idm_status_t idm_i_so_tx(idm_pdu_t *pdu);
71 
72 static idm_status_t idm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu);
73 static idm_status_t idm_so_send_buf_region(idm_task_t *idt, uint8_t opcode,
74     idm_buf_t *idb, uint32_t buf_region_offset, uint32_t buf_region_length);
75 
76 static uint32_t idm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb,
77     uint32_t ro, uint32_t dlength);
78 
79 static idm_status_t idm_so_handle_digest(idm_conn_t *it,
80     nvpair_t *digest_choice, const idm_kv_xlate_t *ikvx);
81 
82 /*
83  * Transport ops prototypes
84  */
85 static void idm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu);
86 static idm_status_t idm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb);
87 static idm_status_t idm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb);
88 static void idm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu);
89 static void idm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu);
90 static void idm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu);
91 static idm_status_t idm_so_free_task_rsrc(idm_task_t *idt);
92 static kv_status_t idm_so_negotiate_key_values(idm_conn_t *it,
93     nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
94 static idm_status_t idm_so_notice_key_values(idm_conn_t *it,
95     nvlist_t *negotiated_nvl);
96 static boolean_t idm_so_conn_is_capable(idm_conn_req_t *ic,
97     idm_transport_caps_t *caps);
98 static idm_status_t idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen);
99 static void idm_so_buf_free(idm_buf_t *idb);
100 static idm_status_t idm_so_buf_setup(idm_buf_t *idb);
101 static void idm_so_buf_teardown(idm_buf_t *idb);
102 static idm_status_t idm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is);
103 static void idm_so_tgt_svc_destroy(idm_svc_t *is);
104 static idm_status_t idm_so_tgt_svc_online(idm_svc_t *is);
105 static void idm_so_tgt_svc_offline(idm_svc_t *is);
106 static void idm_so_tgt_conn_destroy(idm_conn_t *ic);
107 static idm_status_t idm_so_tgt_conn_connect(idm_conn_t *ic);
108 static void idm_so_conn_disconnect(idm_conn_t *ic);
109 static idm_status_t idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic);
110 static void idm_so_ini_conn_destroy(idm_conn_t *ic);
111 static idm_status_t idm_so_ini_conn_connect(idm_conn_t *ic);
112 
113 /*
114  * IDM Native Sockets transport operations
115  */
116 static
117 idm_transport_ops_t idm_so_transport_ops = {
118 	idm_so_tx,			/* it_tx_pdu */
119 	idm_so_buf_tx_to_ini,		/* it_buf_tx_to_ini */
120 	idm_so_buf_rx_from_ini,		/* it_buf_rx_from_ini */
121 	idm_so_rx_datain,		/* it_rx_datain */
122 	idm_so_rx_rtt,			/* it_rx_rtt */
123 	idm_so_rx_dataout,		/* it_rx_dataout */
124 	NULL,				/* it_alloc_conn_rsrc */
125 	NULL,				/* it_free_conn_rsrc */
126 	NULL,				/* it_tgt_enable_datamover */
127 	NULL,				/* it_ini_enable_datamover */
128 	NULL,				/* it_conn_terminate */
129 	idm_so_free_task_rsrc,		/* it_free_task_rsrc */
130 	idm_so_negotiate_key_values,	/* it_negotiate_key_values */
131 	idm_so_notice_key_values,	/* it_notice_key_values */
132 	idm_so_conn_is_capable,		/* it_conn_is_capable */
133 	idm_so_buf_alloc,		/* it_buf_alloc */
134 	idm_so_buf_free,		/* it_buf_free */
135 	idm_so_buf_setup,		/* it_buf_setup */
136 	idm_so_buf_teardown,		/* it_buf_teardown */
137 	idm_so_tgt_svc_create,		/* it_tgt_svc_create */
138 	idm_so_tgt_svc_destroy,		/* it_tgt_svc_destroy */
139 	idm_so_tgt_svc_online,		/* it_tgt_svc_online */
140 	idm_so_tgt_svc_offline,		/* it_tgt_svc_offline */
141 	idm_so_tgt_conn_destroy,	/* it_tgt_conn_destroy */
142 	idm_so_tgt_conn_connect,	/* it_tgt_conn_connect */
143 	idm_so_conn_disconnect,		/* it_tgt_conn_disconnect */
144 	idm_so_ini_conn_create,		/* it_ini_conn_create */
145 	idm_so_ini_conn_destroy,	/* it_ini_conn_destroy */
146 	idm_so_ini_conn_connect,	/* it_ini_conn_connect */
147 	idm_so_conn_disconnect		/* it_ini_conn_disconnect */
148 };
149 
150 /*
151  * idm_so_init()
152  * Sockets transport initialization
153  */
154 void
155 idm_so_init(idm_transport_t *it)
156 {
157 	/* Cache for IDM Data and R2T Transmit PDU's */
158 	idm.idm_sotx_pdu_cache = kmem_cache_create("idm_tx_pdu_cache",
159 	    sizeof (idm_pdu_t) + sizeof (iscsi_hdr_t), 8,
160 	    &idm_sotx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP);
161 
162 	/* Cache for IDM Receive PDU's */
163 	idm.idm_sorx_pdu_cache = kmem_cache_create("idm_rx_pdu_cache",
164 	    sizeof (idm_pdu_t) + IDM_SORX_CACHE_HDRLEN, 8,
165 	    &idm_sorx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP);
166 
167 	/* Set the sockets transport ops */
168 	it->it_ops = &idm_so_transport_ops;
169 }
170 
171 /*
172  * idm_so_fini()
173  * Sockets transport teardown
174  */
175 void
176 idm_so_fini(void)
177 {
178 	kmem_cache_destroy(idm.idm_sotx_pdu_cache);
179 	kmem_cache_destroy(idm.idm_sorx_pdu_cache);
180 }
181 
182 ksocket_t
183 idm_socreate(int domain, int type, int protocol)
184 {
185 	ksocket_t ks;
186 
187 	if (!ksocket_socket(&ks, domain, type, protocol, KSOCKET_NOSLEEP,
188 	    CRED())) {
189 		return (ks);
190 	} else {
191 		return (NULL);
192 	}
193 }
194 
195 /*
196  * idm_soshutdown will disconnect the socket and prevent subsequent PDU
197  * reception and transmission.  The sonode still exists but its state
198  * gets modified to indicate it is no longer connected.  Calls to
199  * idm_sorecv/idm_iov_sorecv will return so idm_soshutdown can be used
200  * regain control of a thread stuck in idm_sorecv.
201  */
202 void
203 idm_soshutdown(ksocket_t so)
204 {
205 	(void) ksocket_shutdown(so, SHUT_RDWR, CRED());
206 }
207 
208 /*
209  * idm_sodestroy releases all resources associated with a socket previously
210  * created with idm_socreate.  The socket must be shutdown using
211  * idm_soshutdown before the socket is destroyed with idm_sodestroy,
212  * otherwise undefined behavior will result.
213  */
214 void
215 idm_sodestroy(ksocket_t ks)
216 {
217 	(void) ksocket_close(ks, CRED());
218 }
219 
220 /*
221  * IP address filter functions to flag addresses that should not
222  * go out to initiators through discovery.
223  */
224 static boolean_t
225 idm_v4_addr_okay(struct in_addr *in_addr)
226 {
227 	in_addr_t addr = ntohl(in_addr->s_addr);
228 
229 	if ((INADDR_NONE == addr) ||
230 	    (IN_MULTICAST(addr)) ||
231 	    ((addr >> IN_CLASSA_NSHIFT) == 0) ||
232 	    ((addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
233 		return (B_FALSE);
234 	}
235 	return (B_TRUE);
236 }
237 
238 static boolean_t
239 idm_v6_addr_okay(struct in6_addr *addr6)
240 {
241 
242 	if ((IN6_IS_ADDR_UNSPECIFIED(addr6)) ||
243 	    (IN6_IS_ADDR_LOOPBACK(addr6)) ||
244 	    (IN6_IS_ADDR_MULTICAST(addr6)) ||
245 	    (IN6_IS_ADDR_V4MAPPED(addr6)) ||
246 	    (IN6_IS_ADDR_V4COMPAT(addr6)) ||
247 	    (IN6_IS_ADDR_LINKLOCAL(addr6))) {
248 		return (B_FALSE);
249 	}
250 	return (B_TRUE);
251 }
252 
253 /*
254  * idm_get_ipaddr will retrieve a list of IP Addresses which the host is
255  * configured with by sending down a sequence of kernel ioctl to IP STREAMS.
256  */
257 int
258 idm_get_ipaddr(idm_addr_list_t **ipaddr_p)
259 {
260 	ksocket_t 		so4, so6;
261 	struct lifnum		lifn;
262 	struct lifconf		lifc;
263 	struct lifreq		*lp;
264 	int			rval;
265 	int			numifs;
266 	int			bufsize;
267 	void			*buf;
268 	int			i, j, n, rc;
269 	struct sockaddr_storage	ss;
270 	struct sockaddr_in	*sin;
271 	struct sockaddr_in6	*sin6;
272 	idm_addr_t		*ip;
273 	idm_addr_list_t		*ipaddr;
274 	int			size_ipaddr;
275 
276 	*ipaddr_p = NULL;
277 	size_ipaddr = 0;
278 	buf = NULL;
279 
280 	/* create an ipv4 and ipv6 UDP socket */
281 	if ((so6 = idm_socreate(PF_INET6, SOCK_DGRAM, 0)) == NULL)
282 		return (0);
283 	if ((so4 = idm_socreate(PF_INET, SOCK_DGRAM, 0)) == NULL) {
284 		idm_sodestroy(so6);
285 		return (0);
286 	}
287 
288 
289 retry_count:
290 	/* snapshot the current number of interfaces */
291 	lifn.lifn_family = PF_UNSPEC;
292 	lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
293 	lifn.lifn_count = 0;
294 	/* use vp6 for ioctls with unspecified families by default */
295 	if (ksocket_ioctl(so6, SIOCGLIFNUM, (intptr_t)&lifn, &rval, CRED())
296 	    != 0) {
297 		goto cleanup;
298 	}
299 
300 	numifs = lifn.lifn_count;
301 	if (numifs <= 0) {
302 		goto cleanup;
303 	}
304 
305 	/* allocate extra room in case more interfaces appear */
306 	numifs += 10;
307 
308 	/* get the interface names and ip addresses */
309 	bufsize = numifs * sizeof (struct lifreq);
310 	buf = kmem_alloc(bufsize, KM_SLEEP);
311 
312 	lifc.lifc_family = AF_UNSPEC;
313 	lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
314 	lifc.lifc_len = bufsize;
315 	lifc.lifc_buf = buf;
316 	rc = ksocket_ioctl(so6, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED());
317 	if (rc != 0) {
318 		goto cleanup;
319 	}
320 	/* if our extra room is used up, try again */
321 	if (bufsize <= lifc.lifc_len) {
322 		kmem_free(buf, bufsize);
323 		buf = NULL;
324 		goto retry_count;
325 	}
326 	/* calc actual number of ifconfs */
327 	n = lifc.lifc_len / sizeof (struct lifreq);
328 
329 	/* get ip address */
330 	if (n > 0) {
331 		size_ipaddr = sizeof (idm_addr_list_t) +
332 		    (n - 1) * sizeof (idm_addr_t);
333 		ipaddr = kmem_zalloc(size_ipaddr, KM_SLEEP);
334 	} else {
335 		goto cleanup;
336 	}
337 
338 	/*
339 	 * Examine the array of interfaces and filter uninteresting ones
340 	 */
341 	for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
342 
343 		/*
344 		 * Copy the address as the SIOCGLIFFLAGS ioctl is destructive
345 		 */
346 		ss = lp->lifr_addr;
347 		/*
348 		 * fetch the flags using the socket of the correct family
349 		 */
350 		switch (ss.ss_family) {
351 		case AF_INET:
352 			rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)lp,
353 			    &rval, CRED());
354 			break;
355 		case AF_INET6:
356 			rc = ksocket_ioctl(so6, SIOCGLIFFLAGS, (intptr_t)lp,
357 			    &rval, CRED());
358 			break;
359 		default:
360 			continue;
361 		}
362 		if (rc == 0) {
363 			/*
364 			 * If we got the flags, skip uninteresting
365 			 * interfaces based on flags
366 			 */
367 			if ((lp->lifr_flags & IFF_UP) != IFF_UP)
368 				continue;
369 			if (lp->lifr_flags &
370 			    (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
371 				continue;
372 		}
373 
374 		/* save ip address */
375 		ip = &ipaddr->al_addrs[j];
376 		switch (ss.ss_family) {
377 		case AF_INET:
378 			sin = (struct sockaddr_in *)&ss;
379 			if (!idm_v4_addr_okay(&sin->sin_addr))
380 				continue;
381 			ip->a_addr.i_addr.in4 = sin->sin_addr;
382 			ip->a_addr.i_insize = sizeof (struct in_addr);
383 			break;
384 		case AF_INET6:
385 			sin6 = (struct sockaddr_in6 *)&ss;
386 			if (!idm_v6_addr_okay(&sin6->sin6_addr))
387 				continue;
388 			ip->a_addr.i_addr.in6 = sin6->sin6_addr;
389 			ip->a_addr.i_insize = sizeof (struct in6_addr);
390 			break;
391 		default:
392 			continue;
393 		}
394 		j++;
395 	}
396 
397 	if (j == 0) {
398 		/* no valid ifaddr */
399 		kmem_free(ipaddr, size_ipaddr);
400 		size_ipaddr = 0;
401 		ipaddr = NULL;
402 	} else {
403 		ipaddr->al_out_cnt = j;
404 	}
405 
406 
407 cleanup:
408 	idm_sodestroy(so6);
409 	idm_sodestroy(so4);
410 
411 	if (buf != NULL)
412 		kmem_free(buf, bufsize);
413 
414 	*ipaddr_p = ipaddr;
415 	return (size_ipaddr);
416 }
417 
418 int
419 idm_sorecv(ksocket_t so, void *msg, size_t len)
420 {
421 	iovec_t iov;
422 
423 	ASSERT(so != NULL);
424 	ASSERT(len != 0);
425 
426 	/*
427 	 * Fill in iovec and receive data
428 	 */
429 	iov.iov_base = msg;
430 	iov.iov_len = len;
431 
432 	return (idm_iov_sorecv(so, &iov, 1, len));
433 }
434 
435 /*
436  * idm_sosendto - Sends a buffered data on a non-connected socket.
437  *
438  * This function puts the data provided on the wire by calling sosendmsg.
439  * It will return only when all the data has been sent or if an error
440  * occurs.
441  *
442  * Returns 0 for success, the socket errno value if sosendmsg fails, and
443  * -1 if sosendmsg returns success but uio_resid != 0
444  */
445 int
446 idm_sosendto(ksocket_t so, void *buff, size_t len,
447     struct sockaddr *name, socklen_t namelen)
448 {
449 	struct msghdr		msg;
450 	struct iovec		iov[1];
451 	int			error;
452 	size_t			sent = 0;
453 
454 	iov[0].iov_base	= buff;
455 	iov[0].iov_len	= len;
456 
457 	/* Initialization of the message header. */
458 	bzero(&msg, sizeof (msg));
459 	msg.msg_iov	= iov;
460 	msg.msg_iovlen	= 1;
461 	msg.msg_name	= name;
462 	msg.msg_namelen	= namelen;
463 
464 	if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED())) == 0) {
465 		/* Data sent */
466 		if (sent == len) {
467 			/* All data sent.  Success. */
468 			return (0);
469 		} else {
470 			/* Not all data was sent.  Failure */
471 			return (-1);
472 		}
473 	}
474 
475 	/* Send failed */
476 	return (error);
477 }
478 
479 /*
480  * idm_iov_sosend - Sends an iovec on a connection.
481  *
482  * This function puts the data provided on the wire by calling sosendmsg.
483  * It will return only when all the data has been sent or if an error
484  * occurs.
485  *
486  * Returns 0 for success, the socket errno value if sosendmsg fails, and
487  * -1 if sosendmsg returns success but uio_resid != 0
488  */
489 int
490 idm_iov_sosend(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len)
491 {
492 	struct msghdr		msg;
493 	int			error;
494 	size_t 			sent = 0;
495 
496 	ASSERT(iop != NULL);
497 
498 	/* Initialization of the message header. */
499 	bzero(&msg, sizeof (msg));
500 	msg.msg_iov	= iop;
501 	msg.msg_iovlen	= iovlen;
502 
503 	if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED()))
504 	    == 0) {
505 		/* Data sent */
506 		if (sent == total_len) {
507 			/* All data sent.  Success. */
508 			return (0);
509 		} else {
510 			/* Not all data was sent.  Failure */
511 			return (-1);
512 		}
513 	}
514 
515 	/* Send failed */
516 	return (error);
517 }
518 
519 /*
520  * idm_iov_sorecv - Receives an iovec from a connection
521  *
522  * This function gets the data asked for from the socket.  It will return
523  * only when all the requested data has been retrieved or if an error
524  * occurs.
525  *
526  * Returns 0 for success, the socket errno value if sorecvmsg fails, and
527  * -1 if sorecvmsg returns success but uio_resid != 0
528  */
529 int
530 idm_iov_sorecv(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len)
531 {
532 	struct msghdr		msg;
533 	int			error;
534 	size_t			recv;
535 	int 			flags;
536 
537 	ASSERT(iop != NULL);
538 
539 	/* Initialization of the message header. */
540 	bzero(&msg, sizeof (msg));
541 	msg.msg_iov	= iop;
542 	msg.msg_iovlen	= iovlen;
543 	flags		= MSG_WAITALL;
544 
545 	if ((error = ksocket_recvmsg(so, &msg, flags, &recv, CRED()))
546 	    == 0) {
547 		/* Received data */
548 		if (recv == total_len) {
549 			/* All requested data received.  Success */
550 			return (0);
551 		} else {
552 			/*
553 			 * Not all data was received.  The connection has
554 			 * probably failed.
555 			 */
556 			return (-1);
557 		}
558 	}
559 
560 	/* Receive failed */
561 	return (error);
562 }
563 
564 static void
565 idm_set_ini_preconnect_options(idm_so_conn_t *sc)
566 {
567 	int	conn_abort = 10000;
568 	int	conn_notify = 2000;
569 	int	abort = 30000;
570 
571 	/* Pre-connect socket options */
572 	(void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
573 	    TCP_CONN_NOTIFY_THRESHOLD, (char *)&conn_notify, sizeof (int),
574 	    CRED());
575 	(void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
576 	    TCP_CONN_ABORT_THRESHOLD, (char *)&conn_abort, sizeof (int),
577 	    CRED());
578 	(void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, TCP_ABORT_THRESHOLD,
579 	    (char *)&abort, sizeof (int), CRED());
580 }
581 
582 static void
583 idm_set_ini_postconnect_options(idm_so_conn_t *sc)
584 {
585 	int32_t		rcvbuf = IDM_RCVBUF_SIZE;
586 	int32_t		sndbuf = IDM_SNDBUF_SIZE;
587 	const int	on = 1;
588 
589 	/* Set postconnect options */
590 	(void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP, TCP_NODELAY,
591 	    (char *)&on, sizeof (int), CRED());
592 	(void) ksocket_setsockopt(sc->ic_so, SOL_SOCKET, SO_RCVBUF,
593 	    (char *)&rcvbuf, sizeof (int), CRED());
594 	(void) ksocket_setsockopt(sc->ic_so, SOL_SOCKET, SO_SNDBUF,
595 	    (char *)&sndbuf, sizeof (int), CRED());
596 }
597 
598 static void
599 idm_set_tgt_connect_options(ksocket_t ks)
600 {
601 	int32_t		rcvbuf = IDM_RCVBUF_SIZE;
602 	int32_t		sndbuf = IDM_SNDBUF_SIZE;
603 	const int	on = 1;
604 
605 	/* Set connect options */
606 	(void) ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVBUF,
607 	    (char *)&rcvbuf, sizeof (int), CRED());
608 	(void) ksocket_setsockopt(ks, SOL_SOCKET, SO_SNDBUF,
609 	    (char *)&sndbuf, sizeof (int), CRED());
610 	(void) ksocket_setsockopt(ks, IPPROTO_TCP, TCP_NODELAY,
611 	    (char *)&on, sizeof (on), CRED());
612 }
613 
614 static uint32_t
615 n2h24(const uchar_t *ptr)
616 {
617 	return ((ptr[0] << 16) | (ptr[1] << 8) | ptr[2]);
618 }
619 
620 
621 static idm_status_t
622 idm_sorecvhdr(idm_conn_t *ic, idm_pdu_t *pdu)
623 {
624 	iscsi_hdr_t	*bhs;
625 	uint32_t	hdr_digest_crc;
626 	uint32_t	crc_calculated;
627 	void		*new_hdr;
628 	int		ahslen = 0;
629 	int		total_len = 0;
630 	int		iovlen = 0;
631 	struct iovec	iov[2];
632 	idm_so_conn_t	*so_conn;
633 	int		rc;
634 
635 	so_conn = ic->ic_transport_private;
636 
637 	/*
638 	 * Read BHS
639 	 */
640 	bhs = pdu->isp_hdr;
641 	rc = idm_sorecv(so_conn->ic_so, pdu->isp_hdr, sizeof (iscsi_hdr_t));
642 	if (rc != IDM_STATUS_SUCCESS) {
643 		return (IDM_STATUS_FAIL);
644 	}
645 
646 	/*
647 	 * Check actual AHS length against the amount available in the buffer
648 	 */
649 	pdu->isp_hdrlen = sizeof (iscsi_hdr_t) +
650 	    (bhs->hlength * sizeof (uint32_t));
651 	pdu->isp_datalen = n2h24(bhs->dlength);
652 	if (bhs->hlength > IDM_SORX_CACHE_AHSLEN) {
653 		/* Allocate a new header segment and change the callback */
654 		new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP);
655 		bcopy(pdu->isp_hdr, new_hdr, sizeof (iscsi_hdr_t));
656 		pdu->isp_hdr = new_hdr;
657 		pdu->isp_flags |= IDM_PDU_ADDL_HDR;
658 
659 		/*
660 		 * This callback will restore the expected values after
661 		 * the RX PDU has been processed.
662 		 */
663 		pdu->isp_callback = idm_sorx_addl_pdu_cb;
664 	}
665 
666 	/*
667 	 * Setup receipt of additional header and header digest (if enabled).
668 	 */
669 	if (bhs->hlength > 0) {
670 		iov[iovlen].iov_base = (caddr_t)(pdu->isp_hdr + 1);
671 		ahslen = pdu->isp_hdrlen - sizeof (iscsi_hdr_t);
672 		iov[iovlen].iov_len = ahslen;
673 		total_len += iov[iovlen].iov_len;
674 		iovlen++;
675 	}
676 
677 	if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) {
678 		iov[iovlen].iov_base = (caddr_t)&hdr_digest_crc;
679 		iov[iovlen].iov_len = sizeof (hdr_digest_crc);
680 		total_len += iov[iovlen].iov_len;
681 		iovlen++;
682 	}
683 
684 	if ((iovlen != 0) &&
685 	    (idm_iov_sorecv(so_conn->ic_so, &iov[0], iovlen,
686 	    total_len) != 0)) {
687 		return (IDM_STATUS_FAIL);
688 	}
689 
690 	/*
691 	 * Validate header digest if enabled
692 	 */
693 	if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) {
694 		crc_calculated = idm_crc32c(pdu->isp_hdr,
695 		    sizeof (iscsi_hdr_t) + ahslen);
696 		if (crc_calculated != hdr_digest_crc) {
697 			/* Invalid Header Digest */
698 			return (IDM_STATUS_HEADER_DIGEST);
699 		}
700 	}
701 
702 	return (0);
703 }
704 
705 /*
706  * idm_so_ini_conn_create()
707  * Allocate the sockets transport connection resources.
708  */
709 static idm_status_t
710 idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic)
711 {
712 	ksocket_t	so;
713 	idm_so_conn_t	*so_conn;
714 	idm_status_t	idmrc;
715 
716 	so = idm_socreate(cr->cr_domain, cr->cr_type,
717 	    cr->cr_protocol);
718 	if (so == NULL) {
719 		return (IDM_STATUS_FAIL);
720 	}
721 
722 	/* Bind the socket if configured to do so */
723 	if (cr->cr_bound) {
724 		if (ksocket_bind(so, &cr->cr_bound_addr.sin,
725 		    SIZEOF_SOCKADDR(&cr->cr_bound_addr.sin), CRED()) != 0) {
726 			idm_sodestroy(so);
727 			return (IDM_STATUS_FAIL);
728 		}
729 	}
730 
731 	idmrc = idm_so_conn_create_common(ic, so);
732 	if (idmrc != IDM_STATUS_SUCCESS) {
733 		idm_soshutdown(so);
734 		idm_sodestroy(so);
735 		return (IDM_STATUS_FAIL);
736 	}
737 
738 	so_conn = ic->ic_transport_private;
739 	/* Set up socket options */
740 	idm_set_ini_preconnect_options(so_conn);
741 
742 	return (IDM_STATUS_SUCCESS);
743 }
744 
745 /*
746  * idm_so_ini_conn_destroy()
747  * Tear down the sockets transport connection resources.
748  */
749 static void
750 idm_so_ini_conn_destroy(idm_conn_t *ic)
751 {
752 	idm_so_conn_destroy_common(ic);
753 }
754 
755 /*
756  * idm_so_ini_conn_connect()
757  * Establish the connection referred to by the handle previously allocated via
758  * idm_so_ini_conn_create().
759  */
760 static idm_status_t
761 idm_so_ini_conn_connect(idm_conn_t *ic)
762 {
763 	idm_so_conn_t	*so_conn;
764 
765 	so_conn = ic->ic_transport_private;
766 
767 	if (ksocket_connect(so_conn->ic_so, &ic->ic_ini_dst_addr.sin,
768 	    (SIZEOF_SOCKADDR(&ic->ic_ini_dst_addr.sin)), CRED()) != 0) {
769 		idm_soshutdown(so_conn->ic_so);
770 		return (IDM_STATUS_FAIL);
771 	}
772 
773 	idm_so_conn_connect_common(ic);
774 
775 	idm_set_ini_postconnect_options(so_conn);
776 
777 	return (IDM_STATUS_SUCCESS);
778 }
779 
780 idm_status_t
781 idm_so_tgt_conn_create(idm_conn_t *ic, ksocket_t new_so)
782 {
783 	idm_status_t	idmrc;
784 
785 	idmrc = idm_so_conn_create_common(ic, new_so);
786 
787 	return (idmrc);
788 }
789 
790 static void
791 idm_so_tgt_conn_destroy(idm_conn_t *ic)
792 {
793 	idm_so_conn_destroy_common(ic);
794 }
795 
796 /*
797  * idm_so_tgt_conn_connect()
798  * Establish the connection in ic, passed from idm_tgt_conn_finish(), which
799  * is invoked from the SM as a result of an inbound connection request.
800  */
801 static idm_status_t
802 idm_so_tgt_conn_connect(idm_conn_t *ic)
803 {
804 	idm_so_conn_connect_common(ic);
805 
806 	return (IDM_STATUS_SUCCESS);
807 }
808 
809 static idm_status_t
810 idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so)
811 {
812 	idm_so_conn_t	*so_conn;
813 
814 	so_conn = kmem_zalloc(sizeof (idm_so_conn_t), KM_SLEEP);
815 	so_conn->ic_so = new_so;
816 
817 	ic->ic_transport_private = so_conn;
818 	ic->ic_transport_hdrlen = 0;
819 
820 	/* Set the scoreboarding flag on this connection */
821 	ic->ic_conn_flags |= IDM_CONN_USE_SCOREBOARD;
822 
823 	/*
824 	 * Initialize tx thread mutex and list
825 	 */
826 	mutex_init(&so_conn->ic_tx_mutex, NULL, MUTEX_DEFAULT, NULL);
827 	cv_init(&so_conn->ic_tx_cv, NULL, CV_DEFAULT, NULL);
828 	list_create(&so_conn->ic_tx_list, sizeof (idm_pdu_t),
829 	    offsetof(idm_pdu_t, idm_tx_link));
830 
831 	return (IDM_STATUS_SUCCESS);
832 }
833 
834 static void
835 idm_so_conn_destroy_common(idm_conn_t *ic)
836 {
837 	idm_so_conn_t	*so_conn = ic->ic_transport_private;
838 
839 	ic->ic_transport_private = NULL;
840 	idm_sodestroy(so_conn->ic_so);
841 	list_destroy(&so_conn->ic_tx_list);
842 	mutex_destroy(&so_conn->ic_tx_mutex);
843 	cv_destroy(&so_conn->ic_tx_cv);
844 
845 	kmem_free(so_conn, sizeof (idm_so_conn_t));
846 }
847 
848 static void
849 idm_so_conn_connect_common(idm_conn_t *ic)
850 {
851 	idm_so_conn_t	*so_conn;
852 	struct sockaddr_in6	t_addr;
853 	socklen_t	t_addrlen = 0;
854 
855 	so_conn = ic->ic_transport_private;
856 	bzero(&t_addr, sizeof (struct sockaddr_in6));
857 	t_addrlen = sizeof (struct sockaddr_in6);
858 
859 	/* Set the local and remote addresses in the idm conn handle */
860 	ksocket_getsockname(so_conn->ic_so, (struct sockaddr *)&t_addr,
861 	    &t_addrlen, CRED());
862 	bcopy(&t_addr, &ic->ic_laddr, t_addrlen);
863 	ksocket_getpeername(so_conn->ic_so, (struct sockaddr *)&t_addr,
864 	    &t_addrlen, CRED());
865 	bcopy(&t_addr, &ic->ic_raddr, t_addrlen);
866 
867 	mutex_enter(&ic->ic_mutex);
868 	so_conn->ic_tx_thread = thread_create(NULL, 0, idm_sotx_thread, ic, 0,
869 	    &p0, TS_RUN, minclsyspri);
870 	so_conn->ic_rx_thread = thread_create(NULL, 0, idm_sorx_thread, ic, 0,
871 	    &p0, TS_RUN, minclsyspri);
872 
873 	while (!so_conn->ic_rx_thread_running || !so_conn->ic_tx_thread_running)
874 		cv_wait(&ic->ic_cv, &ic->ic_mutex);
875 	mutex_exit(&ic->ic_mutex);
876 }
877 
878 /*
879  * idm_so_conn_disconnect()
880  * Shutdown the socket connection and stop the thread
881  */
882 static void
883 idm_so_conn_disconnect(idm_conn_t *ic)
884 {
885 	idm_so_conn_t	*so_conn;
886 
887 	so_conn = ic->ic_transport_private;
888 
889 	mutex_enter(&ic->ic_mutex);
890 	so_conn->ic_rx_thread_running = B_FALSE;
891 	so_conn->ic_tx_thread_running = B_FALSE;
892 	/* We need to wakeup the TX thread */
893 	mutex_enter(&so_conn->ic_tx_mutex);
894 	cv_signal(&so_conn->ic_tx_cv);
895 	mutex_exit(&so_conn->ic_tx_mutex);
896 	mutex_exit(&ic->ic_mutex);
897 
898 	/* This should wakeup the RX thread if it is sleeping */
899 	idm_soshutdown(so_conn->ic_so);
900 
901 	thread_join(so_conn->ic_tx_thread_did);
902 	thread_join(so_conn->ic_rx_thread_did);
903 }
904 
905 /*
906  * idm_so_tgt_svc_create()
907  * Establish a service on an IP address and port.  idm_svc_req_t contains
908  * the service parameters.
909  */
910 /*ARGSUSED*/
911 static idm_status_t
912 idm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is)
913 {
914 	idm_so_svc_t		*so_svc;
915 
916 	so_svc = kmem_zalloc(sizeof (idm_so_svc_t), KM_SLEEP);
917 
918 	/* Set the new sockets service in svc handle */
919 	is->is_so_svc = (void *)so_svc;
920 
921 	return (IDM_STATUS_SUCCESS);
922 }
923 
924 /*
925  * idm_so_tgt_svc_destroy()
926  * Teardown sockets resources allocated in idm_so_tgt_svc_create()
927  */
928 static void
929 idm_so_tgt_svc_destroy(idm_svc_t *is)
930 {
931 	/* the socket will have been torn down; free the service */
932 	kmem_free(is->is_so_svc, sizeof (idm_so_svc_t));
933 }
934 
935 /*
936  * idm_so_tgt_svc_online()
937  * Launch a watch thread on the svc allocated in idm_so_tgt_svc_create()
938  */
939 
940 static idm_status_t
941 idm_so_tgt_svc_online(idm_svc_t *is)
942 {
943 	idm_so_svc_t		*so_svc;
944 	idm_svc_req_t		*sr = &is->is_svc_req;
945 	struct sockaddr_in6	sin6_ip;
946 	const uint32_t		on = 1;
947 	const uint32_t		off = 0;
948 
949 	mutex_enter(&is->is_mutex);
950 	so_svc = (idm_so_svc_t *)is->is_so_svc;
951 
952 	/*
953 	 * Try creating an IPv6 socket first
954 	 */
955 	if ((so_svc->is_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) == NULL) {
956 		mutex_exit(&is->is_mutex);
957 		return (IDM_STATUS_FAIL);
958 	} else {
959 		bzero(&sin6_ip, sizeof (sin6_ip));
960 		sin6_ip.sin6_family = AF_INET6;
961 		sin6_ip.sin6_port = htons(sr->sr_port);
962 		sin6_ip.sin6_addr = in6addr_any;
963 
964 		(void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET,
965 		    SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
966 		/*
967 		 * Turn off SO_MAC_EXEMPT so future sobinds succeed
968 		 */
969 		(void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET,
970 		    SO_MAC_EXEMPT, (char *)&off, sizeof (off), CRED());
971 
972 		if (ksocket_bind(so_svc->is_so, (struct sockaddr *)&sin6_ip,
973 		    sizeof (sin6_ip), CRED()) != 0) {
974 			mutex_exit(&is->is_mutex);
975 			idm_sodestroy(so_svc->is_so);
976 			return (IDM_STATUS_FAIL);
977 		}
978 	}
979 
980 	idm_set_tgt_connect_options(so_svc->is_so);
981 
982 	if (ksocket_listen(so_svc->is_so, 5, CRED()) != 0) {
983 		mutex_exit(&is->is_mutex);
984 		idm_soshutdown(so_svc->is_so);
985 		idm_sodestroy(so_svc->is_so);
986 		return (IDM_STATUS_FAIL);
987 	}
988 
989 	/* Launch a watch thread */
990 	so_svc->is_thread = thread_create(NULL, 0, idm_so_svc_port_watcher,
991 	    is, 0, &p0, TS_RUN, minclsyspri);
992 
993 	if (so_svc->is_thread == NULL) {
994 		/* Failure to launch; teardown the socket */
995 		mutex_exit(&is->is_mutex);
996 		idm_soshutdown(so_svc->is_so);
997 		idm_sodestroy(so_svc->is_so);
998 		return (IDM_STATUS_FAIL);
999 	}
1000 	ksocket_hold(so_svc->is_so);
1001 	/* Wait for the port watcher thread to start */
1002 	while (!so_svc->is_thread_running)
1003 		cv_wait(&is->is_cv, &is->is_mutex);
1004 	mutex_exit(&is->is_mutex);
1005 
1006 	return (IDM_STATUS_SUCCESS);
1007 }
1008 
1009 /*
1010  * idm_so_tgt_svc_offline
1011  *
1012  * Stop listening on the IP address and port identified by idm_svc_t.
1013  */
1014 static void
1015 idm_so_tgt_svc_offline(idm_svc_t *is)
1016 {
1017 	idm_so_svc_t		*so_svc;
1018 	mutex_enter(&is->is_mutex);
1019 	so_svc = (idm_so_svc_t *)is->is_so_svc;
1020 	so_svc->is_thread_running = B_FALSE;
1021 	mutex_exit(&is->is_mutex);
1022 
1023 	/*
1024 	 * Teardown socket
1025 	 */
1026 	idm_sodestroy(so_svc->is_so);
1027 
1028 	/*
1029 	 * Now we expect the port watcher thread to terminate
1030 	 */
1031 	thread_join(so_svc->is_thread_did);
1032 }
1033 
1034 /*
1035  * Watch thread for target service connection establishment.
1036  */
1037 void
1038 idm_so_svc_port_watcher(void *arg)
1039 {
1040 	idm_svc_t		*svc = arg;
1041 	ksocket_t		new_so;
1042 	idm_conn_t		*ic;
1043 	idm_status_t		idmrc;
1044 	idm_so_svc_t		*so_svc;
1045 	int			rc;
1046 	const uint32_t		off = 0;
1047 	struct sockaddr_in6 	t_addr;
1048 	socklen_t		t_addrlen;
1049 
1050 	bzero(&t_addr, sizeof (struct sockaddr_in6));
1051 	t_addrlen = sizeof (struct sockaddr_in6);
1052 	mutex_enter(&svc->is_mutex);
1053 
1054 	so_svc = svc->is_so_svc;
1055 	so_svc->is_thread_running = B_TRUE;
1056 	so_svc->is_thread_did = so_svc->is_thread->t_did;
1057 
1058 	cv_signal(&svc->is_cv);
1059 
1060 	IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) online", (void *)svc,
1061 	    svc->is_svc_req.sr_port);
1062 
1063 	while (so_svc->is_thread_running) {
1064 		mutex_exit(&svc->is_mutex);
1065 
1066 		if ((rc = ksocket_accept(so_svc->is_so,
1067 		    (struct sockaddr *)&t_addr, &t_addrlen,
1068 		    &new_so, CRED())) != 0) {
1069 			mutex_enter(&svc->is_mutex);
1070 			if (rc == ECONNABORTED)
1071 				continue;
1072 			/* Connection problem */
1073 			break;
1074 		}
1075 		/*
1076 		 * Turn off SO_MAC_EXEMPT so future sobinds succeed
1077 		 */
1078 		(void) ksocket_setsockopt(new_so, SOL_SOCKET, SO_MAC_EXEMPT,
1079 		    (char *)&off, sizeof (off), CRED());
1080 
1081 		idmrc = idm_svc_conn_create(svc, IDM_TRANSPORT_TYPE_SOCKETS,
1082 		    &ic);
1083 		if (idmrc != IDM_STATUS_SUCCESS) {
1084 			/* Drop connection */
1085 			idm_soshutdown(new_so);
1086 			idm_sodestroy(new_so);
1087 			mutex_enter(&svc->is_mutex);
1088 			continue;
1089 		}
1090 
1091 		idmrc = idm_so_tgt_conn_create(ic, new_so);
1092 		if (idmrc != IDM_STATUS_SUCCESS) {
1093 			idm_svc_conn_destroy(ic);
1094 			idm_soshutdown(new_so);
1095 			idm_sodestroy(new_so);
1096 			mutex_enter(&svc->is_mutex);
1097 			continue;
1098 		}
1099 
1100 		/*
1101 		 * Kick the state machine.  At CS_S3_XPT_UP the state machine
1102 		 * will notify the client (target) about the new connection.
1103 		 */
1104 		idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL);
1105 
1106 		mutex_enter(&svc->is_mutex);
1107 	}
1108 	ksocket_rele(so_svc->is_so);
1109 	so_svc->is_thread_running = B_FALSE;
1110 	mutex_exit(&svc->is_mutex);
1111 
1112 	IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) offline", (void *)svc,
1113 	    svc->is_svc_req.sr_port);
1114 
1115 	thread_exit();
1116 }
1117 
1118 /*
1119  * idm_so_free_task_rsrc() stops any ongoing processing of the task and
1120  * frees resources associated with the task.
1121  *
1122  * It's not clear that this should return idm_status_t.  What do we do
1123  * if it fails?
1124  */
1125 static idm_status_t
1126 idm_so_free_task_rsrc(idm_task_t *idt)
1127 {
1128 	idm_buf_t	*idb;
1129 
1130 	/*
1131 	 * If this is a target connection, call idm_buf_rx_from_ini_done for
1132 	 * any buffer on the "outbufv" list with idb->idb_in_transport==B_TRUE.
1133 	 *
1134 	 * In addition, remove any buffers associated with this task from
1135 	 * the ic_tx_list.  We'll do this by walking the idt_inbufv list, but
1136 	 * items don't actually get removed from that list (and completion
1137 	 * routines called) until idm_task_cleanup.
1138 	 */
1139 	mutex_enter(&idt->idt_mutex);
1140 
1141 	for (idb = list_head(&idt->idt_outbufv); idb != NULL;
1142 	    idb = list_next(&idt->idt_outbufv, idb)) {
1143 		if (idb->idb_in_transport) {
1144 			/*
1145 			 * idm_buf_rx_from_ini_done releases idt->idt_mutex
1146 			 */
1147 			idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_ABORTED);
1148 			mutex_enter(&idt->idt_mutex);
1149 		}
1150 	}
1151 
1152 	for (idb = list_head(&idt->idt_inbufv); idb != NULL;
1153 	    idb = list_next(&idt->idt_inbufv, idb)) {
1154 		/*
1155 		 * We want to remove these items from the tx_list as well,
1156 		 * but knowing it's in the idt_inbufv list is not a guarantee
1157 		 * that it's in the tx_list.  If it's on the tx list then
1158 		 * let idm_sotx_thread() clean it up.
1159 		 */
1160 		if (idb->idb_in_transport && !idb->idb_tx_thread) {
1161 			/*
1162 			 * idm_buf_tx_to_ini_done releases idt->idt_mutex
1163 			 */
1164 			idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
1165 			mutex_enter(&idt->idt_mutex);
1166 		}
1167 	}
1168 
1169 	mutex_exit(&idt->idt_mutex);
1170 
1171 	return (IDM_STATUS_SUCCESS);
1172 }
1173 
1174 /*
1175  * idm_so_negotiate_key_values() validates the key values for this connection
1176  */
1177 /* ARGSUSED */
1178 static kv_status_t
1179 idm_so_negotiate_key_values(idm_conn_t *it, nvlist_t *request_nvl,
1180     nvlist_t *response_nvl, nvlist_t *negotiated_nvl)
1181 {
1182 	/* All parameters are negotiated at the iscsit level */
1183 	return (KV_HANDLED);
1184 }
1185 
1186 /*
1187  * idm_so_notice_key_values() activates the negotiated key values for
1188  * this connection.
1189  */
1190 static idm_status_t
1191 idm_so_notice_key_values(idm_conn_t *it, nvlist_t *negotiated_nvl)
1192 {
1193 	char			*nvp_name;
1194 	nvpair_t		*nvp;
1195 	nvpair_t		*next_nvp;
1196 	int			nvrc;
1197 	idm_status_t		idm_status;
1198 	const idm_kv_xlate_t	*ikvx;
1199 
1200 	for (nvp = nvlist_next_nvpair(negotiated_nvl, NULL);
1201 	    nvp != NULL; nvp = next_nvp) {
1202 		next_nvp = nvlist_next_nvpair(negotiated_nvl, nvp);
1203 		nvp_name = nvpair_name(nvp);
1204 
1205 		ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name));
1206 		switch (ikvx->ik_key_id) {
1207 		case KI_HEADER_DIGEST:
1208 		case KI_DATA_DIGEST:
1209 			idm_status = idm_so_handle_digest(it, nvp, ikvx);
1210 			ASSERT(idm_status == 0);
1211 
1212 			/* Remove processed item from negotiated_nvl list */
1213 			nvrc = nvlist_remove_all(
1214 			    negotiated_nvl, ikvx->ik_key_name);
1215 			ASSERT(nvrc == 0);
1216 			break;
1217 		default:
1218 			break;
1219 		}
1220 	}
1221 	return (IDM_STATUS_SUCCESS);
1222 }
1223 
1224 
1225 static idm_status_t
1226 idm_so_handle_digest(idm_conn_t *it, nvpair_t *digest_choice,
1227     const idm_kv_xlate_t *ikvx)
1228 {
1229 	int			nvrc;
1230 	char			*digest_choice_string;
1231 
1232 	nvrc = nvpair_value_string(digest_choice,
1233 	    &digest_choice_string);
1234 	ASSERT(nvrc == 0);
1235 	if (strcasecmp(digest_choice_string, "crc32c") == 0) {
1236 		switch (ikvx->ik_key_id) {
1237 		case KI_HEADER_DIGEST:
1238 			it->ic_conn_flags |= IDM_CONN_HEADER_DIGEST;
1239 			break;
1240 		case KI_DATA_DIGEST:
1241 			it->ic_conn_flags |= IDM_CONN_DATA_DIGEST;
1242 			break;
1243 		default:
1244 			ASSERT(0);
1245 			break;
1246 		}
1247 	} else if (strcasecmp(digest_choice_string, "none") == 0) {
1248 		switch (ikvx->ik_key_id) {
1249 		case KI_HEADER_DIGEST:
1250 			it->ic_conn_flags &= ~IDM_CONN_HEADER_DIGEST;
1251 			break;
1252 		case KI_DATA_DIGEST:
1253 			it->ic_conn_flags &= ~IDM_CONN_DATA_DIGEST;
1254 			break;
1255 		default:
1256 			ASSERT(0);
1257 			break;
1258 		}
1259 	} else {
1260 		ASSERT(0);
1261 	}
1262 
1263 	return (IDM_STATUS_SUCCESS);
1264 }
1265 
1266 
1267 /*
1268  * idm_so_conn_is_capable() verifies that the passed connection is provided
1269  * for by the sockets interface.
1270  */
1271 /* ARGSUSED */
1272 static boolean_t
1273 idm_so_conn_is_capable(idm_conn_req_t *ic, idm_transport_caps_t *caps)
1274 {
1275 	return (B_TRUE);
1276 }
1277 
1278 /*
1279  * idm_so_rx_datain() validates the Data Sequence number of the PDU. The
1280  * idm_sorecv_scsidata() function invoked earlier actually reads the data
1281  * off the socket into the appropriate buffers.
1282  */
1283 static void
1284 idm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu)
1285 {
1286 	iscsi_data_hdr_t	*bhs;
1287 	idm_task_t		*idt;
1288 	idm_buf_t		*idb;
1289 	uint32_t		datasn;
1290 	size_t			offset;
1291 	iscsi_hdr_t		*ihp = (iscsi_hdr_t *)pdu->isp_hdr;
1292 	iscsi_data_rsp_hdr_t    *idrhp = (iscsi_data_rsp_hdr_t *)ihp;
1293 
1294 	ASSERT(ic != NULL);
1295 	ASSERT(pdu != NULL);
1296 
1297 	bhs	= (iscsi_data_hdr_t *)pdu->isp_hdr;
1298 	datasn	= ntohl(bhs->datasn);
1299 	offset	= ntohl(bhs->offset);
1300 
1301 	ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA_RSP);
1302 
1303 	/*
1304 	 * Look up the task corresponding to the initiator task tag
1305 	 * to get the buffers affiliated with the task.
1306 	 */
1307 	idt = idm_task_find(ic, bhs->itt, bhs->ttt);
1308 	if (idt == NULL) {
1309 		IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: failed to find task");
1310 		idm_pdu_rx_protocol_error(ic, pdu);
1311 		return;
1312 	}
1313 
1314 	idb = pdu->isp_sorx_buf;
1315 	if (idb == NULL) {
1316 		IDM_CONN_LOG(CE_WARN,
1317 		    "idm_so_rx_datain: failed to find buffer");
1318 		idm_task_rele(idt);
1319 		idm_pdu_rx_protocol_error(ic, pdu);
1320 		return;
1321 	}
1322 
1323 	/*
1324 	 * DataSN values should be sequential and should not have any gaps or
1325 	 * repetitions. Check the DataSN with the one stored in the task.
1326 	 */
1327 	if (datasn == idt->idt_exp_datasn) {
1328 		idt->idt_exp_datasn++; /* keep track of DataSN received */
1329 	} else {
1330 		IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: datasn out of order");
1331 		idm_task_rele(idt);
1332 		idm_pdu_rx_protocol_error(ic, pdu);
1333 		return;
1334 	}
1335 	idm_task_rele(idt);
1336 
1337 	/*
1338 	 * PDUs in a sequence should be in continuously increasing
1339 	 * address offset
1340 	 */
1341 	if (offset != idb->idb_exp_offset) {
1342 		IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: unexpected offset");
1343 		idm_pdu_rx_protocol_error(ic, pdu);
1344 		return;
1345 	}
1346 	/* Expected next relative buffer offset */
1347 	idb->idb_exp_offset += n2h24(bhs->dlength);
1348 
1349 	/*
1350 	 * For now call scsi_rsp which will process the data rsp
1351 	 * Revisit, need to provide an explicit client entry point for
1352 	 * phase collapse completions.
1353 	 */
1354 	if (((ihp->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_DATA_RSP) &&
1355 	    (idrhp->flags & ISCSI_FLAG_DATA_STATUS)) {
1356 		(*ic->ic_conn_ops.icb_rx_scsi_rsp)(ic, pdu);
1357 	}
1358 
1359 	idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
1360 }
1361 
1362 /*
1363  * The idm_so_rx_dataout() function is used by the iSCSI target to read
1364  * data from the Data-Out PDU sent by the iSCSI initiator.
1365  *
1366  * This function gets the Initiator Task Tag from the PDU BHS and looks up the
1367  * task to get the buffers associated with the PDU. A PDU might span buffers.
1368  * The data is then read into the respective buffer.
1369  */
1370 static void
1371 idm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu)
1372 {
1373 
1374 	iscsi_data_hdr_t	*bhs;
1375 	idm_task_t		*idt;
1376 	idm_buf_t		*idb;
1377 	size_t			offset;
1378 
1379 	ASSERT(ic != NULL);
1380 	ASSERT(pdu != NULL);
1381 
1382 	bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
1383 	offset = ntohl(bhs->offset);
1384 	ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA);
1385 
1386 	/*
1387 	 * Look up the task corresponding to the initiator task tag
1388 	 * to get the buffers affiliated with the task.
1389 	 */
1390 	idt = idm_task_find(ic, bhs->itt, bhs->ttt);
1391 	if (idt == NULL) {
1392 		IDM_CONN_LOG(CE_WARN,
1393 		    "idm_so_rx_dataout: failed to find task");
1394 		idm_pdu_rx_protocol_error(ic, pdu);
1395 		return;
1396 	}
1397 
1398 	idb = pdu->isp_sorx_buf;
1399 	if (idb == NULL) {
1400 		IDM_CONN_LOG(CE_WARN,
1401 		    "idm_so_rx_dataout: failed to find buffer");
1402 		idm_task_rele(idt);
1403 		idm_pdu_rx_protocol_error(ic, pdu);
1404 		return;
1405 	}
1406 
1407 	/* Keep track of data transferred - check data offsets */
1408 	if (offset != idb->idb_exp_offset) {
1409 		IDM_CONN_LOG(CE_NOTE, "idm_so_rx_dataout: offset out of seq: "
1410 		    "%ld, %d", offset, idb->idb_exp_offset);
1411 		idm_task_rele(idt);
1412 		idm_pdu_rx_protocol_error(ic, pdu);
1413 		return;
1414 	}
1415 	/* Expected next relative offset */
1416 	idb->idb_exp_offset += ntoh24(bhs->dlength);
1417 
1418 	/*
1419 	 * Call the buffer callback when the transfer is complete
1420 	 *
1421 	 * The connection state machine should only abort tasks after
1422 	 * shutting down the connection so we are assured that there
1423 	 * won't be a simultaneous attempt to abort this task at the
1424 	 * same time as we are processing this PDU (due to a connection
1425 	 * state change).
1426 	 */
1427 	if (bhs->flags & ISCSI_FLAG_FINAL) {
1428 		/*
1429 		 * We only want to call idm_buf_rx_from_ini_done once
1430 		 * per transfer.  It's possible that this task has
1431 		 * already been aborted in which case
1432 		 * idm_so_free_task_rsrc will call idm_buf_rx_from_ini_done
1433 		 * for each buffer with idb_in_transport==B_TRUE.  To
1434 		 * close this window and ensure that this doesn't happen,
1435 		 * we'll clear idb->idb_in_transport now while holding
1436 		 * the task mutex.   This is only really an issue for
1437 		 * SCSI task abort -- if tasks were being aborted because
1438 		 * of a connection state change the state machine would
1439 		 * have already stopped the receive thread.
1440 		 */
1441 		mutex_enter(&idt->idt_mutex);
1442 
1443 		/*
1444 		 * Release the task hold here (obtained in idm_task_find)
1445 		 * because the task may complete synchronously during
1446 		 * idm_buf_rx_from_ini_done.  Since we still have an active
1447 		 * buffer we know there is at least one additional hold on idt.
1448 		 */
1449 		idm_task_rele(idt);
1450 
1451 		/*
1452 		 * idm_buf_rx_from_ini_done releases idt->idt_mutex
1453 		 */
1454 		idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_SUCCESS);
1455 		idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
1456 		return;
1457 	}
1458 
1459 	idm_task_rele(idt);
1460 	idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
1461 }
1462 
1463 /*
1464  * The idm_so_rx_rtt() function is used by the iSCSI initiator to handle
1465  * the R2T PDU sent by the iSCSI target indicating that it is ready to
1466  * accept data. This gets the Initiator Task Tag (itt) from the PDU BHS
1467  * and looks up the task in the task tree using the itt to get the output
1468  * buffers associated the task. The R2T PDU contains the offset of the
1469  * requested data and the data length. This function then constructs a
1470  * sequence of iSCSI PDUs and outputs the requested data. Each Data-Out
1471  * PDU is associated with the R2T by the Target Transfer Tag  (ttt).
1472  */
1473 static void
1474 idm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu)
1475 {
1476 	idm_task_t		*idt;
1477 	idm_buf_t		*idb;
1478 	iscsi_rtt_hdr_t		*rtt_hdr;
1479 	uint32_t		data_offset;
1480 
1481 	ASSERT(ic != NULL);
1482 	ASSERT(pdu != NULL);
1483 
1484 	rtt_hdr	= (iscsi_rtt_hdr_t *)pdu->isp_hdr;
1485 	data_offset = ntohl(rtt_hdr->data_offset);
1486 
1487 	idt	= idm_task_find(ic, rtt_hdr->itt, rtt_hdr->ttt);
1488 
1489 	if (idt == NULL) {
1490 		IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find task");
1491 		idm_pdu_rx_protocol_error(ic, pdu);
1492 		return;
1493 	}
1494 
1495 	/* Find the buffer bound to the task by the iSCSI initiator */
1496 	mutex_enter(&idt->idt_mutex);
1497 	idb = idm_buf_find(&idt->idt_outbufv, data_offset);
1498 	idt->idt_r2t_ttt = rtt_hdr->ttt;
1499 	/* reset to zero */
1500 	idt->idt_exp_datasn = 0;
1501 	if (idb == NULL) {
1502 		mutex_exit(&idt->idt_mutex);
1503 		idm_task_rele(idt);
1504 		IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find buffer");
1505 		idm_pdu_rx_protocol_error(ic, pdu);
1506 		return;
1507 	}
1508 
1509 	(void) idm_so_send_buf_region(idt, ISCSI_OP_SCSI_DATA, idb,
1510 	    data_offset, ntohl(rtt_hdr->data_length));
1511 	mutex_exit(&idt->idt_mutex);
1512 
1513 	idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
1514 	idm_task_rele(idt);
1515 
1516 }
1517 
1518 idm_status_t
1519 idm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu)
1520 {
1521 	uint8_t		pad[ISCSI_PAD_WORD_LEN];
1522 	int		pad_len;
1523 	uint32_t	data_digest_crc;
1524 	uint32_t	crc_calculated;
1525 	int		total_len;
1526 	idm_so_conn_t	*so_conn;
1527 
1528 	so_conn = ic->ic_transport_private;
1529 
1530 	pad_len = ((ISCSI_PAD_WORD_LEN -
1531 	    (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) &
1532 	    (ISCSI_PAD_WORD_LEN - 1));
1533 
1534 	ASSERT(pdu->isp_iovlen < (PDU_MAX_IOVLEN - 2)); /* pad + data digest */
1535 
1536 	total_len = pdu->isp_datalen;
1537 
1538 	if (pad_len) {
1539 		pdu->isp_iov[pdu->isp_iovlen].iov_base	= (char *)&pad;
1540 		pdu->isp_iov[pdu->isp_iovlen].iov_len	= pad_len;
1541 		total_len		+= pad_len;
1542 		pdu->isp_iovlen++;
1543 	}
1544 
1545 	/* setup data digest */
1546 	if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) {
1547 		pdu->isp_iov[pdu->isp_iovlen].iov_base =
1548 		    (char *)&data_digest_crc;
1549 		pdu->isp_iov[pdu->isp_iovlen].iov_len =
1550 		    sizeof (data_digest_crc);
1551 		total_len		+= sizeof (data_digest_crc);
1552 		pdu->isp_iovlen++;
1553 	}
1554 
1555 	if (idm_iov_sorecv(so_conn->ic_so, &pdu->isp_iov[0],
1556 	    pdu->isp_iovlen, total_len) != 0) {
1557 		return (IDM_STATUS_IO);
1558 	}
1559 
1560 	if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) {
1561 		crc_calculated = idm_crc32c(pdu->isp_data,
1562 		    pdu->isp_datalen);
1563 		if (pad_len) {
1564 			crc_calculated = idm_crc32c_continued((char *)&pad,
1565 			    pad_len, crc_calculated);
1566 		}
1567 		if (crc_calculated != data_digest_crc) {
1568 			IDM_CONN_LOG(CE_WARN,
1569 			    "idm_sorecvdata: "
1570 			    "CRC error: actual 0x%x, calc 0x%x",
1571 			    data_digest_crc, crc_calculated);
1572 
1573 			/* Invalid Data Digest */
1574 			return (IDM_STATUS_DATA_DIGEST);
1575 		}
1576 	}
1577 
1578 	return (IDM_STATUS_SUCCESS);
1579 }
1580 
1581 /*
1582  * idm_sorecv_scsidata() is used to receive scsi data from the socket. The
1583  * Data-type PDU header must be read into the idm_pdu_t structure prior to
1584  * calling this function.
1585  */
1586 idm_status_t
1587 idm_sorecv_scsidata(idm_conn_t *ic, idm_pdu_t *pdu)
1588 {
1589 	iscsi_data_hdr_t	*bhs;
1590 	idm_task_t		*task;
1591 	uint32_t		offset;
1592 	uint8_t			opcode;
1593 	uint32_t		dlength;
1594 	list_t			*buflst;
1595 	uint32_t		xfer_bytes;
1596 	idm_status_t		status;
1597 
1598 	ASSERT(ic != NULL);
1599 	ASSERT(pdu != NULL);
1600 
1601 	bhs	= (iscsi_data_hdr_t *)pdu->isp_hdr;
1602 
1603 	offset	= ntohl(bhs->offset);
1604 	opcode	= bhs->opcode;
1605 	dlength = n2h24(bhs->dlength);
1606 
1607 	ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
1608 	    (opcode == ISCSI_OP_SCSI_DATA));
1609 
1610 	/*
1611 	 * Successful lookup implicitly gets a "hold" on the task.  This
1612 	 * hold must be released before leaving this function.  At one
1613 	 * point we were caching this task context and retaining the hold
1614 	 * but it turned out to be very difficult to release the hold properly.
1615 	 * The task can be aborted and the connection shutdown between this
1616 	 * call and the subsequent expected call to idm_so_rx_datain/
1617 	 * idm_so_rx_dataout (in which case those functions are not called).
1618 	 * Releasing the hold in the PDU callback doesn't work well either
1619 	 * because the whole task may be completed by then at which point
1620 	 * it is too late to release the hold -- for better or worse this
1621 	 * code doesn't wait on the refcnts during normal operation.
1622 	 * idm_task_find() is very fast and it is not a huge burden if we
1623 	 * have to do it twice.
1624 	 */
1625 	task = idm_task_find(ic, bhs->itt, bhs->ttt);
1626 	if (task == NULL) {
1627 		IDM_CONN_LOG(CE_WARN,
1628 		    "idm_sorecv_scsidata: could not find task");
1629 		return (IDM_STATUS_FAIL);
1630 	}
1631 
1632 	mutex_enter(&task->idt_mutex);
1633 	buflst	= (opcode == ISCSI_OP_SCSI_DATA_RSP) ?
1634 	    &task->idt_inbufv : &task->idt_outbufv;
1635 	pdu->isp_sorx_buf = idm_buf_find(buflst, offset);
1636 	mutex_exit(&task->idt_mutex);
1637 
1638 	if (pdu->isp_sorx_buf == NULL) {
1639 		idm_task_rele(task);
1640 		IDM_CONN_LOG(CE_WARN, "idm_sorecv_scsidata: could not find "
1641 		    "buffer for offset %x opcode=%x",
1642 		    offset, opcode);
1643 		return (IDM_STATUS_FAIL);
1644 	}
1645 
1646 	xfer_bytes = idm_fill_iov(pdu, pdu->isp_sorx_buf, offset, dlength);
1647 	ASSERT(xfer_bytes != 0);
1648 	if (xfer_bytes != dlength) {
1649 		idm_task_rele(task);
1650 		/*
1651 		 * Buffer overflow, connection error.  The PDU data is still
1652 		 * sitting in the socket so we can't use the connection
1653 		 * again until that data is drained.
1654 		 */
1655 		return (IDM_STATUS_FAIL);
1656 	}
1657 
1658 	status = idm_sorecvdata(ic, pdu);
1659 
1660 	idm_task_rele(task);
1661 
1662 	return (status);
1663 }
1664 
1665 static uint32_t
1666 idm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb, uint32_t ro, uint32_t dlength)
1667 {
1668 	uint32_t	buf_ro = ro - idb->idb_bufoffset;
1669 	uint32_t	xfer_len = min(dlength, idb->idb_buflen - buf_ro);
1670 
1671 	ASSERT(ro >= idb->idb_bufoffset);
1672 
1673 	pdu->isp_iov[pdu->isp_iovlen].iov_base	=
1674 	    (caddr_t)idb->idb_buf + buf_ro;
1675 	pdu->isp_iov[pdu->isp_iovlen].iov_len	= xfer_len;
1676 	pdu->isp_iovlen++;
1677 
1678 	return (xfer_len);
1679 }
1680 
1681 int
1682 idm_sorecv_nonscsidata(idm_conn_t *ic, idm_pdu_t *pdu)
1683 {
1684 	pdu->isp_data = kmem_alloc(pdu->isp_datalen, KM_SLEEP);
1685 	ASSERT(pdu->isp_data != NULL);
1686 
1687 	pdu->isp_databuflen = pdu->isp_datalen;
1688 	pdu->isp_iov[0].iov_base = (caddr_t)pdu->isp_data;
1689 	pdu->isp_iov[0].iov_len = pdu->isp_datalen;
1690 	pdu->isp_iovlen = 1;
1691 	/*
1692 	 * Since we are associating a new data buffer with this received
1693 	 * PDU we need to set a specific callback to free the data
1694 	 * after the PDU is processed.
1695 	 */
1696 	pdu->isp_flags |= IDM_PDU_ADDL_DATA;
1697 	pdu->isp_callback = idm_sorx_addl_pdu_cb;
1698 
1699 	return (idm_sorecvdata(ic, pdu));
1700 }
1701 
1702 void
1703 idm_sorx_thread(void *arg)
1704 {
1705 	boolean_t	conn_failure = B_FALSE;
1706 	idm_conn_t	*ic = (idm_conn_t *)arg;
1707 	idm_so_conn_t	*so_conn;
1708 	idm_pdu_t	*pdu;
1709 	idm_status_t	rc;
1710 
1711 	idm_conn_hold(ic);
1712 
1713 	mutex_enter(&ic->ic_mutex);
1714 
1715 	so_conn = ic->ic_transport_private;
1716 	so_conn->ic_rx_thread_running = B_TRUE;
1717 	so_conn->ic_rx_thread_did = so_conn->ic_rx_thread->t_did;
1718 	cv_signal(&ic->ic_cv);
1719 
1720 	while (so_conn->ic_rx_thread_running) {
1721 		mutex_exit(&ic->ic_mutex);
1722 
1723 		/*
1724 		 * Get PDU with default header size (large enough for
1725 		 * BHS plus any anticipated AHS).  PDU from
1726 		 * the cache will have all values set correctly
1727 		 * for sockets RX including callback.
1728 		 */
1729 		pdu = kmem_cache_alloc(idm.idm_sorx_pdu_cache, KM_SLEEP);
1730 		pdu->isp_ic = ic;
1731 		pdu->isp_flags = 0;
1732 		pdu->isp_transport_hdrlen = 0;
1733 
1734 		if ((rc = idm_sorecvhdr(ic, pdu)) != 0) {
1735 			/*
1736 			 * Call idm_pdu_complete so that we call the callback
1737 			 * and ensure any memory allocated in idm_sorecvhdr
1738 			 * gets freed up.
1739 			 */
1740 			idm_pdu_complete(pdu, IDM_STATUS_FAIL);
1741 
1742 			/*
1743 			 * If ic_rx_thread_running is still set then
1744 			 * this is some kind of connection problem
1745 			 * on the socket.  In this case we want to
1746 			 * generate an event.  Otherwise some other
1747 			 * thread closed the socket due to another
1748 			 * issue in which case we don't need to
1749 			 * generate an event.
1750 			 */
1751 			mutex_enter(&ic->ic_mutex);
1752 			if (so_conn->ic_rx_thread_running) {
1753 				conn_failure = B_TRUE;
1754 				so_conn->ic_rx_thread_running = B_FALSE;
1755 			}
1756 
1757 			continue;
1758 		}
1759 
1760 		/*
1761 		 * Header has been read and validated.  Now we need
1762 		 * to read the PDU data payload (if present).  SCSI data
1763 		 * need to be transferred from the socket directly into
1764 		 * the associated transfer buffer for the SCSI task.
1765 		 */
1766 		if (pdu->isp_datalen != 0) {
1767 			if ((IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA) ||
1768 			    (IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA_RSP)) {
1769 				rc = idm_sorecv_scsidata(ic, pdu);
1770 				/*
1771 				 * All SCSI errors are fatal to the
1772 				 * connection right now since we have no
1773 				 * place to put the data.  What we need
1774 				 * is some kind of sink to dispose of unwanted
1775 				 * SCSI data.  For example an invalid task tag
1776 				 * should not kill the connection (although
1777 				 * we may want to drop the connection).
1778 				 */
1779 			} else {
1780 				/*
1781 				 * Not data PDUs so allocate a buffer for the
1782 				 * data segment and read the remaining data.
1783 				 */
1784 				rc = idm_sorecv_nonscsidata(ic, pdu);
1785 			}
1786 			if (rc != 0) {
1787 				/*
1788 				 * Call idm_pdu_complete so that we call the
1789 				 * callback and ensure any memory allocated
1790 				 * in idm_sorecvhdr gets freed up.
1791 				 */
1792 				idm_pdu_complete(pdu, IDM_STATUS_FAIL);
1793 
1794 				/*
1795 				 * If ic_rx_thread_running is still set then
1796 				 * this is some kind of connection problem
1797 				 * on the socket.  In this case we want to
1798 				 * generate an event.  Otherwise some other
1799 				 * thread closed the socket due to another
1800 				 * issue in which case we don't need to
1801 				 * generate an event.
1802 				 */
1803 				mutex_enter(&ic->ic_mutex);
1804 				if (so_conn->ic_rx_thread_running) {
1805 					conn_failure = B_TRUE;
1806 					so_conn->ic_rx_thread_running = B_FALSE;
1807 				}
1808 				continue;
1809 			}
1810 		}
1811 
1812 		/*
1813 		 * Process RX PDU
1814 		 */
1815 		idm_pdu_rx(ic, pdu);
1816 
1817 		mutex_enter(&ic->ic_mutex);
1818 	}
1819 
1820 	mutex_exit(&ic->ic_mutex);
1821 
1822 	/*
1823 	 * If we dropped out of the RX processing loop because of
1824 	 * a socket problem or other connection failure (including
1825 	 * digest errors) then we need to generate a state machine
1826 	 * event to shut the connection down.
1827 	 * If the state machine is already in, for example, INIT_ERROR, this
1828 	 * event will get dropped, and the TX thread will never be notified
1829 	 * to shut down.  To be safe, we'll just notify it here.
1830 	 */
1831 	if (conn_failure) {
1832 		if (so_conn->ic_tx_thread_running) {
1833 			so_conn->ic_tx_thread_running = B_FALSE;
1834 			mutex_enter(&so_conn->ic_tx_mutex);
1835 			cv_signal(&so_conn->ic_tx_cv);
1836 			mutex_exit(&so_conn->ic_tx_mutex);
1837 		}
1838 
1839 		idm_conn_event(ic, CE_TRANSPORT_FAIL, rc);
1840 	}
1841 
1842 	idm_conn_rele(ic);
1843 
1844 	thread_exit();
1845 }
1846 
1847 /*
1848  * idm_so_tx
1849  *
1850  * This is the implementation of idm_transport_ops_t's it_tx_pdu entry
1851  * point.  By definition, it is supposed to be fast.  So, simply queue
1852  * the entry and return.  The real work is done by idm_i_so_tx() via
1853  * idm_sotx_thread().
1854  */
1855 
1856 static void
1857 idm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu)
1858 {
1859 	idm_so_conn_t *so_conn = ic->ic_transport_private;
1860 
1861 	ASSERT(pdu->isp_ic == ic);
1862 	mutex_enter(&so_conn->ic_tx_mutex);
1863 
1864 	if (!so_conn->ic_tx_thread_running) {
1865 		mutex_exit(&so_conn->ic_tx_mutex);
1866 		idm_pdu_complete(pdu, IDM_STATUS_ABORTED);
1867 		return;
1868 	}
1869 
1870 	list_insert_tail(&so_conn->ic_tx_list, (void *)pdu);
1871 	cv_signal(&so_conn->ic_tx_cv);
1872 	mutex_exit(&so_conn->ic_tx_mutex);
1873 }
1874 
1875 static idm_status_t
1876 idm_i_so_tx(idm_pdu_t *pdu)
1877 {
1878 	idm_conn_t	*ic = pdu->isp_ic;
1879 	idm_status_t	status = IDM_STATUS_SUCCESS;
1880 	uint8_t		pad[ISCSI_PAD_WORD_LEN];
1881 	int		pad_len;
1882 	uint32_t	hdr_digest_crc;
1883 	uint32_t	data_digest_crc = 0;
1884 	int		total_len = 0;
1885 	int		iovlen = 0;
1886 	struct iovec	iov[6];
1887 	idm_so_conn_t	*so_conn;
1888 
1889 	so_conn = ic->ic_transport_private;
1890 
1891 	/* Setup BHS */
1892 	iov[iovlen].iov_base	= (caddr_t)pdu->isp_hdr;
1893 	iov[iovlen].iov_len	= pdu->isp_hdrlen;
1894 	total_len		+= iov[iovlen].iov_len;
1895 	iovlen++;
1896 
1897 	/* Setup header digest */
1898 	if (((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) &&
1899 	    (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST)) {
1900 		hdr_digest_crc = idm_crc32c(pdu->isp_hdr, pdu->isp_hdrlen);
1901 
1902 		iov[iovlen].iov_base	= (caddr_t)&hdr_digest_crc;
1903 		iov[iovlen].iov_len	= sizeof (hdr_digest_crc);
1904 		total_len		+= iov[iovlen].iov_len;
1905 		iovlen++;
1906 	}
1907 
1908 	/* Setup the data */
1909 	if (pdu->isp_datalen) {
1910 		idm_task_t		*idt;
1911 		idm_buf_t		*idb;
1912 		iscsi_data_hdr_t	*ihp;
1913 		ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
1914 		/* Write of immediate data */
1915 		if (ic->ic_ffp &&
1916 		    (ihp->opcode == ISCSI_OP_SCSI_CMD ||
1917 		    ihp->opcode == ISCSI_OP_SCSI_DATA)) {
1918 			idt = idm_task_find(ic, ihp->itt, ihp->ttt);
1919 			if (idt) {
1920 				mutex_enter(&idt->idt_mutex);
1921 				idb = idm_buf_find(&idt->idt_outbufv, 0);
1922 				mutex_exit(&idt->idt_mutex);
1923 				idb->idb_xfer_len += pdu->isp_datalen;
1924 			}
1925 		}
1926 
1927 		iov[iovlen].iov_base = (caddr_t)pdu->isp_data;
1928 		iov[iovlen].iov_len  = pdu->isp_datalen;
1929 		total_len += iov[iovlen].iov_len;
1930 		iovlen++;
1931 	}
1932 
1933 	/* Setup the data pad if necessary */
1934 	pad_len = ((ISCSI_PAD_WORD_LEN -
1935 	    (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) &
1936 	    (ISCSI_PAD_WORD_LEN - 1));
1937 
1938 	if (pad_len) {
1939 		bzero(pad, sizeof (pad));
1940 		iov[iovlen].iov_base = (void *)&pad;
1941 		iov[iovlen].iov_len  = pad_len;
1942 		total_len		+= iov[iovlen].iov_len;
1943 		iovlen++;
1944 	}
1945 
1946 	/*
1947 	 * Setup the data digest if enabled.  Data-digest is not sent
1948 	 * for login-phase PDUs.
1949 	 */
1950 	if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) &&
1951 	    ((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) &&
1952 	    (pdu->isp_datalen || pad_len)) {
1953 		/*
1954 		 * RFC3720/10.2.3: A zero-length Data Segment also
1955 		 * implies a zero-length data digest.
1956 		 */
1957 		if (pdu->isp_datalen) {
1958 			data_digest_crc = idm_crc32c(pdu->isp_data,
1959 			    pdu->isp_datalen);
1960 		}
1961 		if (pad_len) {
1962 			data_digest_crc = idm_crc32c_continued(&pad,
1963 			    pad_len, data_digest_crc);
1964 		}
1965 
1966 		iov[iovlen].iov_base	= (caddr_t)&data_digest_crc;
1967 		iov[iovlen].iov_len	= sizeof (data_digest_crc);
1968 		total_len		+= iov[iovlen].iov_len;
1969 		iovlen++;
1970 	}
1971 
1972 	/* Transmit the PDU */
1973 	if (idm_iov_sosend(so_conn->ic_so, &iov[0], iovlen,
1974 	    total_len) != 0) {
1975 		/* Set error status */
1976 		IDM_CONN_LOG(CE_WARN,
1977 		    "idm_so_tx: failed to transmit the PDU, so: %p ic: %p "
1978 		    "data: %p", (void *) so_conn->ic_so, (void *) ic,
1979 		    (void *) pdu->isp_data);
1980 		status = IDM_STATUS_IO;
1981 	}
1982 
1983 	/*
1984 	 * Success does not mean that the PDU actually reached the
1985 	 * remote node since it could get dropped along the way.
1986 	 */
1987 	idm_pdu_complete(pdu, status);
1988 
1989 	return (status);
1990 }
1991 
1992 /*
1993  * The idm_so_buf_tx_to_ini() is used by the target iSCSI layer to transmit the
1994  * Data-In PDUs using sockets. Based on the negotiated MaxRecvDataSegmentLength,
1995  * the buffer is segmented into a sequence of Data-In PDUs, ordered by DataSN.
1996  * A target can invoke this function multiple times for a single read command
1997  * (identified by the same ITT) to split the input into several sequences.
1998  *
1999  * DataSN starts with 0 for the first data PDU of an input command and advances
2000  * by 1 for each subsequent data PDU. Each sequence will have its own F bit,
2001  * which is set to 1 for the last data PDU of a sequence.
2002  *
2003  * Scope for Prototype build:
2004  * The data PDUs within a sequence will be sent in order with the buffer offset
2005  * in increasing order. i.e. initiator and target must have negotiated the
2006  * "DataPDUInOrder" to "Yes". The order between sequences is not enforced.
2007  *
2008  * Caller holds idt->idt_mutex
2009  */
2010 static idm_status_t
2011 idm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb)
2012 {
2013 	idm_so_conn_t	*so_conn = idb->idb_ic->ic_transport_private;
2014 	idm_pdu_t	tmppdu;
2015 
2016 	ASSERT(mutex_owned(&idt->idt_mutex));
2017 
2018 	/*
2019 	 * Put the idm_buf_t on the tx queue.  It will be transmitted by
2020 	 * idm_sotx_thread.
2021 	 */
2022 	mutex_enter(&so_conn->ic_tx_mutex);
2023 
2024 	if (!so_conn->ic_tx_thread_running) {
2025 		mutex_exit(&so_conn->ic_tx_mutex);
2026 		/*
2027 		 * Don't release idt->idt_mutex since we're supposed to hold
2028 		 * in when calling idm_buf_tx_to_ini_done
2029 		 */
2030 		idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
2031 		return (IDM_STATUS_FAIL);
2032 	}
2033 
2034 	/*
2035 	 * Build a template for the data PDU headers we will use so that
2036 	 * the SN values will stay consistent with other PDU's we are
2037 	 * transmitting like R2T and SCSI status.
2038 	 */
2039 	bzero(&idb->idb_data_hdr_tmpl, sizeof (iscsi_hdr_t));
2040 	tmppdu.isp_hdr = &idb->idb_data_hdr_tmpl;
2041 	(*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, &tmppdu,
2042 	    ISCSI_OP_SCSI_DATA_RSP);
2043 	idb->idb_tx_thread = B_TRUE;
2044 	list_insert_tail(&so_conn->ic_tx_list, (void *)idb);
2045 	cv_signal(&so_conn->ic_tx_cv);
2046 	mutex_exit(&so_conn->ic_tx_mutex);
2047 	mutex_exit(&idt->idt_mutex);
2048 
2049 	/*
2050 	 * Returning success here indicates the transfer was successfully
2051 	 * dispatched -- it does not mean that the transfer completed
2052 	 * successfully.
2053 	 */
2054 	return (IDM_STATUS_SUCCESS);
2055 }
2056 
2057 /*
2058  * The idm_so_buf_rx_from_ini() is used by the target iSCSI layer to specify the
2059  * data blocks it is ready to receive from the initiator in response to a WRITE
2060  * SCSI command. The target iSCSI layer passes the information about the desired
2061  * data blocks to the initiator in one R2T PDU. The receiving buffer, the buffer
2062  * offset and datalen are passed via the 'idb' argument.
2063  *
2064  * Scope for Prototype build:
2065  * R2Ts are required for any Data-Out PDU, i.e. initiator and target must have
2066  * negotiated the "InitialR2T" to "Yes".
2067  *
2068  * Caller holds idt->idt_mutex
2069  */
2070 static idm_status_t
2071 idm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb)
2072 {
2073 	idm_pdu_t		*pdu;
2074 	iscsi_rtt_hdr_t		*rtt;
2075 
2076 	ASSERT(mutex_owned(&idt->idt_mutex));
2077 
2078 	pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP);
2079 	pdu->isp_ic = idt->idt_ic;
2080 	bzero(pdu->isp_hdr, sizeof (iscsi_rtt_hdr_t));
2081 
2082 	/* iSCSI layer fills the TTT, ITT, StatSN, ExpCmdSN, MaxCmdSN */
2083 	(*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, pdu, ISCSI_OP_RTT_RSP);
2084 
2085 	/* set the rttsn, rtt.flags, rtt.data_offset and rtt.data_length */
2086 	rtt = (iscsi_rtt_hdr_t *)(pdu->isp_hdr);
2087 
2088 	rtt->opcode		= ISCSI_OP_RTT_RSP;
2089 	rtt->flags		= ISCSI_FLAG_FINAL;
2090 	rtt->data_offset	= htonl(idb->idb_bufoffset);
2091 	rtt->data_length	= htonl(idb->idb_xfer_len);
2092 	rtt->rttsn		= htonl(idt->idt_exp_rttsn++);
2093 
2094 	/* Keep track of buffer offsets */
2095 	idb->idb_exp_offset	= idb->idb_bufoffset;
2096 	mutex_exit(&idt->idt_mutex);
2097 
2098 	/*
2099 	 * Transmit the PDU.
2100 	 */
2101 	idm_pdu_tx(pdu);
2102 
2103 	return (IDM_STATUS_SUCCESS);
2104 }
2105 
2106 static idm_status_t
2107 idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen)
2108 {
2109 	idb->idb_buf = kmem_alloc(buflen, KM_NOSLEEP);
2110 	if (idb->idb_buf == NULL) {
2111 		IDM_CONN_LOG(CE_NOTE,
2112 		    "idm_so_buf_alloc: failed buffer allocation");
2113 		return (IDM_STATUS_FAIL);
2114 	}
2115 	return (IDM_STATUS_SUCCESS);
2116 }
2117 
2118 /* ARGSUSED */
2119 static idm_status_t
2120 idm_so_buf_setup(idm_buf_t *idb)
2121 {
2122 	/* nothing to do here */
2123 	return (IDM_STATUS_SUCCESS);
2124 }
2125 
2126 /* ARGSUSED */
2127 static void
2128 idm_so_buf_teardown(idm_buf_t *idb)
2129 {
2130 	/* nothing to do here */
2131 }
2132 
2133 static void
2134 idm_so_buf_free(idm_buf_t *idb)
2135 {
2136 	kmem_free(idb->idb_buf, idb->idb_buflen);
2137 }
2138 
2139 idm_status_t
2140 idm_so_send_buf_region(idm_task_t *idt, uint8_t opcode, idm_buf_t *idb,
2141     uint32_t buf_region_offset, uint32_t buf_region_length)
2142 {
2143 	idm_conn_t		*ic;
2144 	uint32_t		max_dataseglen;
2145 	size_t			remainder, chunk;
2146 	uint32_t		data_offset = buf_region_offset;
2147 	iscsi_data_hdr_t	*bhs;
2148 	idm_pdu_t		*pdu;
2149 
2150 	ASSERT(mutex_owned(&idt->idt_mutex));
2151 
2152 	ic = idt->idt_ic;
2153 
2154 	max_dataseglen = 8192; /* Need value from login negotiation */
2155 	remainder = buf_region_length;
2156 
2157 	while (remainder) {
2158 		if (idt->idt_state != TASK_ACTIVE) {
2159 			ASSERT((idt->idt_state != TASK_IDLE) &&
2160 			    (idt->idt_state != TASK_COMPLETE));
2161 			return (IDM_STATUS_ABORTED);
2162 		}
2163 
2164 		/* check to see if we need to chunk the data */
2165 		if (remainder > max_dataseglen) {
2166 			chunk = max_dataseglen;
2167 		} else {
2168 			chunk = remainder;
2169 		}
2170 
2171 		/* Data PDU headers will always be sizeof (iscsi_hdr_t) */
2172 		pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP);
2173 		pdu->isp_ic = ic;
2174 
2175 		/*
2176 		 * For target we've already built a build a header template
2177 		 * to use during the transfer.  Use this template so that
2178 		 * the SN values stay consistent with any unrelated PDU's
2179 		 * being transmitted.
2180 		 */
2181 		if (opcode == ISCSI_OP_SCSI_DATA_RSP) {
2182 			bcopy(&idb->idb_data_hdr_tmpl, pdu->isp_hdr,
2183 			    sizeof (iscsi_hdr_t));
2184 		} else {
2185 			/*
2186 			 * OK for now, but we should remove this bzero and
2187 			 * make sure the build_hdr function is initializing the
2188 			 * header properly
2189 			 */
2190 			bzero(pdu->isp_hdr, sizeof (iscsi_hdr_t));
2191 
2192 			/*
2193 			 * setup iscsi data hdr
2194 			 * callback to the iSCSI layer to fill in the BHS
2195 			 * CmdSN, StatSN, ExpCmdSN, MaxCmdSN, TTT, ITT and
2196 			 * opcode
2197 			 */
2198 			(*ic->ic_conn_ops.icb_build_hdr)(idt, pdu, opcode);
2199 		}
2200 
2201 		/*
2202 		 * Set DataSN, data offset, and flags in BHS
2203 		 * For the prototype build, A = 0, S = 0, U = 0
2204 		 */
2205 		bhs = (iscsi_data_hdr_t *)(pdu->isp_hdr);
2206 
2207 		bhs->datasn		= htonl(idt->idt_exp_datasn++);
2208 
2209 		hton24(bhs->dlength, chunk);
2210 		bhs->offset = htonl(idb->idb_bufoffset + data_offset);
2211 
2212 		if (chunk == remainder) {
2213 			bhs->flags = ISCSI_FLAG_FINAL; /* F bit set to 1 */
2214 		}
2215 
2216 		/* setup data */
2217 		pdu->isp_data	=  (uint8_t *)idb->idb_buf + data_offset;
2218 		pdu->isp_datalen = (uint_t)chunk;
2219 		remainder	-= chunk;
2220 		data_offset	+= chunk;
2221 
2222 		/*
2223 		 * Now that we're done working with idt_exp_datasn,
2224 		 * idt->idt_state and idb->idb_bufoffset we can release
2225 		 * the task lock -- don't want to hold it across the
2226 		 * call to idm_i_so_tx since we could block.
2227 		 */
2228 		mutex_exit(&idt->idt_mutex);
2229 
2230 		/*
2231 		 * Transmit the PDU.  Call the internal routine directly
2232 		 * as there is already implicit ordering.
2233 		 */
2234 		(void) idm_i_so_tx(pdu);
2235 
2236 		mutex_enter(&idt->idt_mutex);
2237 	}
2238 
2239 	return (IDM_STATUS_SUCCESS);
2240 }
2241 
2242 /*
2243  * TX PDU cache
2244  */
2245 /* ARGSUSED */
2246 int
2247 idm_sotx_pdu_constructor(void *hdl, void *arg, int flags)
2248 {
2249 	idm_pdu_t	*pdu = hdl;
2250 
2251 	bzero(pdu, sizeof (idm_pdu_t));
2252 	pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */
2253 	pdu->isp_hdrlen = sizeof (iscsi_hdr_t);
2254 	pdu->isp_callback = idm_sotx_cache_pdu_cb;
2255 	pdu->isp_magic = IDM_PDU_MAGIC;
2256 	bzero(pdu->isp_hdr, sizeof (iscsi_hdr_t));
2257 
2258 	return (0);
2259 }
2260 
2261 /* ARGSUSED */
2262 void
2263 idm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
2264 {
2265 	/* reset values between use */
2266 	pdu->isp_datalen = 0;
2267 
2268 	kmem_cache_free(idm.idm_sotx_pdu_cache, pdu);
2269 }
2270 
2271 /*
2272  * RX PDU cache
2273  */
2274 /* ARGSUSED */
2275 int
2276 idm_sorx_pdu_constructor(void *hdl, void *arg, int flags)
2277 {
2278 	idm_pdu_t	*pdu = hdl;
2279 
2280 	bzero(pdu, sizeof (idm_pdu_t));
2281 	pdu->isp_magic = IDM_PDU_MAGIC;
2282 	pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */
2283 	pdu->isp_callback = idm_sorx_cache_pdu_cb;
2284 
2285 	return (0);
2286 }
2287 
2288 /* ARGSUSED */
2289 static void
2290 idm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
2291 {
2292 	pdu->isp_iovlen = 0;
2293 	pdu->isp_sorx_buf = 0;
2294 	kmem_cache_free(idm.idm_sorx_pdu_cache, pdu);
2295 }
2296 
2297 static void
2298 idm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
2299 {
2300 	/*
2301 	 * We had to modify our cached RX PDU with a longer header buffer
2302 	 * and/or a longer data buffer.  Release the new buffers and fix
2303 	 * the fields back to what we would expect for a cached RX PDU.
2304 	 */
2305 	if (pdu->isp_flags & IDM_PDU_ADDL_HDR) {
2306 		kmem_free(pdu->isp_hdr, pdu->isp_hdrlen);
2307 	}
2308 	if (pdu->isp_flags & IDM_PDU_ADDL_DATA) {
2309 		kmem_free(pdu->isp_data, pdu->isp_datalen);
2310 	}
2311 	pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1);
2312 	pdu->isp_hdrlen = sizeof (iscsi_hdr_t);
2313 	pdu->isp_data = NULL;
2314 	pdu->isp_datalen = 0;
2315 	pdu->isp_sorx_buf = 0;
2316 	pdu->isp_callback = idm_sorx_cache_pdu_cb;
2317 	idm_sorx_cache_pdu_cb(pdu, status);
2318 }
2319 
2320 /*
2321  * This thread is only active when I/O is queued for transmit
2322  * because the socket is busy.
2323  */
2324 void
2325 idm_sotx_thread(void *arg)
2326 {
2327 	idm_conn_t	*ic = arg;
2328 	idm_tx_obj_t	*object, *next;
2329 	idm_so_conn_t	*so_conn;
2330 	idm_status_t	status = IDM_STATUS_SUCCESS;
2331 
2332 	idm_conn_hold(ic);
2333 
2334 	mutex_enter(&ic->ic_mutex);
2335 	so_conn = ic->ic_transport_private;
2336 	so_conn->ic_tx_thread_running = B_TRUE;
2337 	so_conn->ic_tx_thread_did = so_conn->ic_tx_thread->t_did;
2338 	cv_signal(&ic->ic_cv);
2339 	mutex_exit(&ic->ic_mutex);
2340 
2341 	mutex_enter(&so_conn->ic_tx_mutex);
2342 
2343 	while (so_conn->ic_tx_thread_running) {
2344 		while (list_is_empty(&so_conn->ic_tx_list)) {
2345 			DTRACE_PROBE1(soconn__tx__sleep, idm_conn_t *, ic);
2346 			cv_wait(&so_conn->ic_tx_cv, &so_conn->ic_tx_mutex);
2347 			DTRACE_PROBE1(soconn__tx__wakeup, idm_conn_t *, ic);
2348 
2349 			if (!so_conn->ic_tx_thread_running) {
2350 				goto tx_bail;
2351 			}
2352 		}
2353 
2354 		object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list);
2355 		list_remove(&so_conn->ic_tx_list, object);
2356 		mutex_exit(&so_conn->ic_tx_mutex);
2357 
2358 		switch (object->idm_tx_obj_magic) {
2359 		case IDM_PDU_MAGIC:
2360 			DTRACE_PROBE2(soconn__tx__pdu, idm_conn_t *, ic,
2361 			    idm_pdu_t *, (idm_pdu_t *)object);
2362 
2363 			status = idm_i_so_tx((idm_pdu_t *)object);
2364 			break;
2365 
2366 		case IDM_BUF_MAGIC: {
2367 			idm_buf_t *idb = (idm_buf_t *)object;
2368 			idm_task_t *idt = idb->idb_task_binding;
2369 
2370 			DTRACE_PROBE2(soconn__tx__buf, idm_conn_t *, ic,
2371 			    idm_buf_t *, idb);
2372 
2373 			mutex_enter(&idt->idt_mutex);
2374 			status = idm_so_send_buf_region(idt,
2375 			    ISCSI_OP_SCSI_DATA_RSP, idb, 0, idb->idb_xfer_len);
2376 
2377 			/*
2378 			 * TX thread owns the buffer so we expect it to
2379 			 * be "in transport"
2380 			 */
2381 			ASSERT(idb->idb_in_transport);
2382 			/*
2383 			 * idm_buf_tx_to_ini_done releases idt->idt_mutex
2384 			 */
2385 			idm_buf_tx_to_ini_done(idt, idb, status);
2386 			break;
2387 		}
2388 
2389 		default:
2390 			IDM_CONN_LOG(CE_WARN, "idm_sotx_thread: Unknown magic "
2391 			    "(0x%08x)", object->idm_tx_obj_magic);
2392 			status = IDM_STATUS_FAIL;
2393 		}
2394 
2395 		mutex_enter(&so_conn->ic_tx_mutex);
2396 
2397 		if (status != IDM_STATUS_SUCCESS) {
2398 			so_conn->ic_tx_thread_running = B_FALSE;
2399 			idm_conn_event(ic, CE_TRANSPORT_FAIL, status);
2400 		}
2401 	}
2402 
2403 	/*
2404 	 * Before we leave, we need to abort every item remaining in the
2405 	 * TX list.
2406 	 */
2407 
2408 tx_bail:
2409 	object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list);
2410 
2411 	while (object != NULL) {
2412 		next = list_next(&so_conn->ic_tx_list, object);
2413 
2414 		list_remove(&so_conn->ic_tx_list, object);
2415 		switch (object->idm_tx_obj_magic) {
2416 		case IDM_PDU_MAGIC:
2417 			idm_pdu_complete((idm_pdu_t *)object,
2418 			    IDM_STATUS_ABORTED);
2419 			break;
2420 
2421 		case IDM_BUF_MAGIC: {
2422 			idm_buf_t *idb = (idm_buf_t *)object;
2423 			idm_task_t *idt = idb->idb_task_binding;
2424 			mutex_exit(&so_conn->ic_tx_mutex);
2425 			mutex_enter(&idt->idt_mutex);
2426 			/*
2427 			 * TX thread owns the buffer so we expect it to
2428 			 * be "in transport"
2429 			 */
2430 			ASSERT(idb->idb_in_transport);
2431 			/*
2432 			 * idm_buf_tx_to_ini_done releases idt->idt_mutex
2433 			 */
2434 			idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
2435 			mutex_enter(&so_conn->ic_tx_mutex);
2436 			break;
2437 		}
2438 		default:
2439 			IDM_CONN_LOG(CE_WARN,
2440 			    "idm_sotx_thread: Unexpected magic "
2441 			    "(0x%08x)", object->idm_tx_obj_magic);
2442 		}
2443 
2444 		object = next;
2445 	}
2446 
2447 	mutex_exit(&so_conn->ic_tx_mutex);
2448 	idm_conn_rele(ic);
2449 	thread_exit();
2450 	/*NOTREACHED*/
2451 }
2452