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