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 /*
23  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
25  */
26 
27 #include <sys/cpuvar.h>
28 #include <sys/types.h>
29 #include <sys/conf.h>
30 #include <sys/file.h>
31 #include <sys/ddi.h>
32 #include <sys/sunddi.h>
33 #include <sys/modctl.h>
34 #include <sys/sysmacros.h>
35 #include <sys/socket.h>
36 #include <sys/strsubr.h>
37 #include <inet/tcp.h>
38 #include <sys/nvpair.h>
39 
40 #include <sys/stmf.h>
41 #include <sys/stmf_ioctl.h>
42 #include <sys/portif.h>
43 #include <sys/idm/idm.h>
44 #include <sys/idm/idm_conn_sm.h>
45 #include <sys/idm/idm_text.h>
46 #include <sys/idm/idm_so.h>
47 
48 #include "iscsit_isns.h"
49 #include "iscsit.h"
50 
51 #define	IPADDRSTRLEN	INET6_ADDRSTRLEN	/* space for ipaddr string */
52 #define	PORTALSTRLEN	(IPADDRSTRLEN+16)	/* add space for :port,tag */
53 
54 void
55 iscsit_text_cmd_fini(iscsit_conn_t *ict);
56 
57 /*
58  * The kernel inet_ntop() function formats ipv4 address fields with
59  * leading zeros which the win2k initiator interprets as octal.
60  */
61 
62 static void
63 iscsit_v4_ntop(struct in_addr *in, char a[], int size)
64 {
65 	unsigned char *p = (unsigned char *) in;
66 
67 	(void) snprintf(a, size, "%d.%d.%d.%d", *p, *(p+1), *(p+2), *(p+3));
68 }
69 
70 static void
71 iscsit_bump_ttt(iscsit_conn_t *ict)
72 {
73 	/*
74 	 * Set the target task tag. The value will be zero when
75 	 * the connection is created. Increment it and wrap it
76 	 * back to one if we hit the reserved value.
77 	 *
78 	 * The TTT is fabricated since there is no real task associated
79 	 * with a text request. The idm task range is reused here since
80 	 * no real tasks can be started from a discovery session and
81 	 * thus no conflicts are possible.
82 	 */
83 	if (++ict->ict_text_rsp_ttt == IDM_TASKIDS_MAX)
84 		ict->ict_text_rsp_ttt = 1;
85 }
86 
87 static void
88 iscsit_text_resp_complete_cb(idm_pdu_t *pdu, idm_status_t status)
89 {
90 	iscsit_conn_t *ict = pdu->isp_private;
91 
92 	idm_pdu_free(pdu);
93 	if (status != IDM_STATUS_SUCCESS) {
94 		/*
95 		 * Could not send the last text response.
96 		 * Clear any state and bump the TTT so subsequent
97 		 * requests will not match.
98 		 */
99 		iscsit_text_cmd_fini(ict);
100 		iscsit_bump_ttt(ict);
101 	}
102 	iscsit_conn_rele(ict);
103 }
104 
105 static void
106 iscsit_text_reject(idm_pdu_t *req_pdu, uint8_t reason_code)
107 {
108 	iscsit_conn_t		*ict = req_pdu->isp_ic->ic_handle;
109 
110 	/*
111 	 * A reject means abandoning this text request.
112 	 * Cleanup any state from the request and increment the TTT
113 	 * in case the initiator does not get the reject response
114 	 * and attempts to resume this request.
115 	 */
116 	iscsit_text_cmd_fini(ict);
117 	iscsit_bump_ttt(ict);
118 	iscsit_send_reject(ict, req_pdu, reason_code);
119 	idm_pdu_complete(req_pdu, IDM_STATUS_SUCCESS);
120 
121 }
122 
123 
124 /*
125  * Add individual <TargetAddress=ipaddr> tuple to the nvlist
126  */
127 static void
128 iscsit_add_portal(struct sockaddr_storage *ss, int flip_v6, int tag,
129     nvlist_t *nv_resp)
130 {
131 	char ipaddr[IPADDRSTRLEN];	/* ip address string */
132 	char ta_value[PORTALSTRLEN];	/* target address value */
133 	struct sockaddr_in *sin;
134 	struct in_addr *in;
135 	struct sockaddr_in6 *sin6;
136 	struct in6_addr *in6, flip_in6;
137 
138 	switch (ss->ss_family) {
139 	case AF_INET:
140 		sin = (struct sockaddr_in *)ss;
141 		in = &sin->sin_addr;
142 		iscsit_v4_ntop(in, ipaddr, sizeof (ipaddr));
143 		(void) snprintf(ta_value, sizeof (ta_value), "%s:%d,%d",
144 		    ipaddr, ntohs(sin->sin_port), tag);
145 		break;
146 	case AF_INET6:
147 		sin6 = (struct sockaddr_in6 *)ss;
148 		in6 = &sin6->sin6_addr;
149 		if (flip_v6) {
150 			uint16_t *v6_field_i = (uint16_t *)in6;
151 			uint16_t *v6_field_o = (uint16_t *)&flip_in6;
152 			int i;
153 
154 			/*
155 			 * Ugh. The iSCSI config data is stored in host
156 			 * order while the addresses retrieved from the
157 			 * stack come back in network order. inet_ntop
158 			 * expects network order.
159 			 */
160 			for (i = 0; i < 8; i++)
161 				*v6_field_o++ = htons(*v6_field_i++);
162 			in6 = &flip_in6;
163 		}
164 		(void) inet_ntop(AF_INET6, in6, ipaddr, sizeof (ipaddr));
165 		(void) snprintf(ta_value, sizeof (ta_value), "[%s]:%d,%d",
166 		    ipaddr, ntohs(sin6->sin6_port), tag);
167 		break;
168 	default:
169 		ASSERT(0);
170 		return;
171 	}
172 	(void) nvlist_add_string(nv_resp, "TargetAddress", ta_value);
173 }
174 
175 /*
176  * Process the special case of the default portal group.
177  * Network addresses are obtained from the network stack and
178  * require some reformatting.
179  */
180 static void
181 iscsit_add_default_portals(iscsit_conn_t *ict, idm_addr_list_t *ipaddr_p,
182     nvlist_t *nv_resp)
183 {
184 	int pass, i;
185 	idm_addr_t *tip;
186 	struct sockaddr_storage ss;
187 	struct sockaddr_in *sin;
188 	struct sockaddr_in6 *sin6;
189 
190 	/*
191 	 * If this request was received on one of the portals,
192 	 * output that portal first. Most initiators will try to
193 	 * connect on the first portal in the SendTargets response.
194 	 * For example, this will avoid the confusing situation of a
195 	 * discovery coming in on an IB interface and the initiator
196 	 * then doing the normal login on an ethernet interface.
197 	 */
198 	sin = (struct sockaddr_in *)&ss;
199 	sin6 = (struct sockaddr_in6 *)&ss;
200 	for (pass = 1; pass <= 2; pass++) {
201 		tip = &ipaddr_p->al_addrs[0];
202 		for (i = 0; i < ipaddr_p->al_out_cnt; i++, tip++) {
203 			/* Convert the address into sockaddr_storage format */
204 			switch (tip->a_addr.i_insize) {
205 			case sizeof (struct in_addr):
206 				sin->sin_family = AF_INET;
207 				sin->sin_port = htons(ISCSI_LISTEN_PORT);
208 				sin->sin_addr = tip->a_addr.i_addr.in4;
209 				break;
210 			case sizeof (struct in6_addr):
211 				sin6->sin6_family = AF_INET6;
212 				sin6->sin6_port = htons(ISCSI_LISTEN_PORT);
213 				sin6->sin6_addr = tip->a_addr.i_addr.in6;
214 				break;
215 			default:
216 				ASSERT(0);
217 				continue;
218 			}
219 			switch (pass) {
220 			case 1:
221 				/*
222 				 * On the first pass, skip portals that
223 				 * do not match the incoming connection.
224 				 */
225 				if (idm_ss_compare(&ss, &ict->ict_ic->ic_laddr,
226 				    B_TRUE, B_TRUE) != 0)
227 					continue;
228 				break;
229 			case 2:
230 				/*
231 				 * On the second pass, process the
232 				 * remaining portals.
233 				 */
234 				if (idm_ss_compare(&ss, &ict->ict_ic->ic_laddr,
235 				    B_TRUE, B_TRUE) == 0)
236 					continue;
237 				break;
238 			}
239 			/*
240 			 * Add portal to the response list.
241 			 * Do not byte swap v6 address.
242 			 * By convention, the default portal group tag == 1
243 			 */
244 			iscsit_add_portal(&ss, 0, 1, nv_resp);
245 		}
246 	}
247 }
248 
249 /*
250  * Process a portal group from the configuration database.
251  */
252 static void
253 iscsit_add_portals(iscsit_conn_t *ict, iscsit_tpgt_t *tpg_list,
254     nvlist_t *nv_resp)
255 {
256 	int pass;
257 	iscsit_portal_t *portal, *next_portal;
258 	iscsit_tpg_t *tpg;
259 	struct sockaddr_storage *ss;
260 
261 	/*
262 	 * As with the default portal group, output the portal used by
263 	 * the incoming request first.
264 	 */
265 	tpg = tpg_list->tpgt_tpg;
266 	for (pass = 1; pass <= 2; pass++) {
267 		for (portal = avl_first(&tpg->tpg_portal_list);
268 		    portal != NULL;
269 		    portal = next_portal) {
270 
271 			next_portal = AVL_NEXT(&tpg->tpg_portal_list, portal);
272 			ss = &portal->portal_addr;
273 			switch (pass) {
274 			case 1:
275 				/*
276 				 * On the first pass, skip portals that
277 				 * do not match the incoming connection.
278 				 */
279 				if (idm_ss_compare(ss, &ict->ict_ic->ic_laddr,
280 				    B_TRUE, B_TRUE) != 0)
281 					continue;
282 				break;
283 			case 2:
284 				/*
285 				 * On the second pass, process the
286 				 * remaining portals.
287 				 */
288 				if (idm_ss_compare(ss, &ict->ict_ic->ic_laddr,
289 				    B_TRUE, B_TRUE) == 0)
290 					continue;
291 				break;
292 			}
293 			/*
294 			 * Add portal to the response list.
295 			 * Need to byte swap v6 address.
296 			 */
297 			iscsit_add_portal(ss, 1, tpg_list->tpgt_tag, nv_resp);
298 		}
299 	}
300 }
301 
302 /*
303  * Process all the portal groups bound to a particular target.
304  */
305 static void
306 iscsit_add_tpgs(iscsit_conn_t *ict, iscsit_tgt_t *target,
307     idm_addr_list_t *ipaddr_p,  nvlist_t *nv_resp)
308 {
309 	iscsit_tpgt_t *tpg_list;
310 
311 	/*
312 	 * Look through the portal groups associated with this target.
313 	 */
314 	mutex_enter(&target->target_mutex);
315 	tpg_list = avl_first(&target->target_tpgt_list);
316 
317 	/* check for the default portal group */
318 	if (tpg_list->tpgt_tpg == iscsit_global.global_default_tpg) {
319 		/*
320 		 * The default portal group is a special case and will
321 		 * return all reasonable interfaces on this node.
322 		 *
323 		 * A target cannot be bound to other portal groups
324 		 * if it is bound to the default portal group.
325 		 */
326 		ASSERT(AVL_NEXT(&target->target_tpgt_list, tpg_list) == NULL);
327 
328 		if (ipaddr_p != NULL) {
329 			/* convert the ip address list to nvlist format */
330 			iscsit_add_default_portals(ict, ipaddr_p, nv_resp);
331 		}
332 		mutex_exit(&target->target_mutex);
333 		return;
334 	}
335 
336 	/*
337 	 * Not the default portal group - process the user defined tpgs
338 	 */
339 	ASSERT(tpg_list != NULL);
340 	while (tpg_list != NULL) {
341 
342 		ASSERT(tpg_list->tpgt_tpg != iscsit_global.global_default_tpg);
343 
344 		/*
345 		 * Found a defined portal group - add each portal address.
346 		 * As with the default portal group, make 2 passes over
347 		 * the addresses in order to output the connection
348 		 * address first.
349 		 */
350 		iscsit_add_portals(ict, tpg_list, nv_resp);
351 
352 		tpg_list = AVL_NEXT(&target->target_tpgt_list, tpg_list);
353 	}
354 	mutex_exit(&target->target_mutex);
355 }
356 
357 #ifdef DEBUG
358 /*
359  * To test with smaller PDUs in order to force multi-PDU responses,
360  * set this value such that: 0 < test_max_len < 8192
361  */
362 uint32_t iscsit_text_max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
363 #endif
364 
365 /*
366  * Format a text response PDU from the text buffer and send it.
367  */
368 static void
369 iscsit_send_next_text_response(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
370 {
371 	iscsi_text_hdr_t *th_req = (iscsi_text_hdr_t *)rx_pdu->isp_hdr;
372 	iscsi_text_rsp_hdr_t *th_resp;
373 	idm_pdu_t	*resp;
374 	uint32_t	len, remainder, max_len;
375 	char		*base;
376 	boolean_t	final;
377 
378 	max_len = ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
379 #ifdef DEBUG
380 	if (iscsit_text_max_len > 0 && iscsit_text_max_len < max_len)
381 		max_len = iscsit_text_max_len;
382 #endif
383 	do {
384 		remainder = ict->ict_text_rsp_valid_len - ict->ict_text_rsp_off;
385 		if (remainder <= max_len) {
386 			len = remainder;
387 			final = B_TRUE;
388 		} else {
389 			len = max_len;
390 			final = B_FALSE;
391 		}
392 		/*
393 		 * Allocate a PDU and copy in text response buffer
394 		 */
395 		resp = idm_pdu_alloc(sizeof (iscsi_hdr_t), len);
396 		idm_pdu_init(resp, ict->ict_ic, ict,
397 		    iscsit_text_resp_complete_cb);
398 		/* Advance the StatSN for each Text Response sent */
399 		resp->isp_flags |= IDM_PDU_SET_STATSN | IDM_PDU_ADVANCE_STATSN;
400 		base = ict->ict_text_rsp_buf + ict->ict_text_rsp_off;
401 		bcopy(base, resp->isp_data, len);
402 		/*
403 		 * Fill in the response header
404 		 */
405 		th_resp = (iscsi_text_rsp_hdr_t *)resp->isp_hdr;
406 		bzero(th_resp, sizeof (*th_resp));
407 		th_resp->opcode = ISCSI_OP_TEXT_RSP;
408 		th_resp->itt = th_req->itt;
409 		hton24(th_resp->dlength, len);
410 		if (final) {
411 			th_resp->flags = ISCSI_FLAG_FINAL;
412 			th_resp->ttt = ISCSI_RSVD_TASK_TAG;
413 			kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
414 			ict->ict_text_rsp_buf = NULL;
415 			ict->ict_text_rsp_len = 0;
416 			ict->ict_text_rsp_valid_len = 0;
417 			ict->ict_text_rsp_off = 0;
418 		} else {
419 			th_resp->flags = ISCSI_FLAG_TEXT_CONTINUE;
420 			th_resp->ttt = ict->ict_text_rsp_ttt;
421 			ict->ict_text_rsp_off += len;
422 		}
423 		/* Send the response on its way */
424 		iscsit_conn_hold(ict);
425 		iscsit_pdu_tx(resp);
426 	} while (!final);
427 	/* Free the request pdu */
428 	idm_pdu_complete(rx_pdu, IDM_STATUS_SUCCESS);
429 }
430 
431 /*
432  * Clean-up the text buffer if it exists.
433  */
434 void
435 iscsit_text_cmd_fini(iscsit_conn_t *ict)
436 {
437 	if (ict->ict_text_rsp_buf != NULL) {
438 		ASSERT(ict->ict_text_rsp_len != 0);
439 		kmem_free(ict->ict_text_rsp_buf, ict->ict_text_rsp_len);
440 	}
441 	ict->ict_text_rsp_buf = NULL;
442 	ict->ict_text_rsp_len = 0;
443 	ict->ict_text_rsp_valid_len = 0;
444 	ict->ict_text_rsp_off = 0;
445 }
446 
447 /*
448  * Process an iSCSI text command.
449  *
450  * This code only handles the common case of a text command
451  * containing the single tuple SendTargets=All issued during
452  * a discovery session. The request will always arrive in a
453  * single PDU, but the response may span multiple PDUs if the
454  * configuration is large. I.e. many targets and portals.
455  *
456  * The request is checked for correctness and then the response
457  * is generated from the global target into nvlist format. Then
458  * the nvlist is reformatted into idm textbuf format which reflects
459  * the iSCSI defined <name=value> specification. Finally, the
460  * textbuf is sent to the initiator in one or more text response PDUs
461  */
462 void
463 iscsit_pdu_op_text_cmd(iscsit_conn_t *ict, idm_pdu_t *rx_pdu)
464 {
465 	iscsi_text_hdr_t *th_req = (iscsi_text_hdr_t *)rx_pdu->isp_hdr;
466 	nvlist_t *nv_resp;
467 	char *kv_pair;
468 	int flags;
469 	char *textbuf;
470 	int textbuflen;
471 	int validlen;
472 	int rc;
473 
474 	flags =  th_req->flags;
475 	if ((flags & ISCSI_FLAG_FINAL) != ISCSI_FLAG_FINAL) {
476 		/* Cannot handle multi-PDU requests now */
477 		iscsit_text_reject(rx_pdu, ISCSI_REJECT_CMD_NOT_SUPPORTED);
478 		return;
479 	}
480 	if (th_req->ttt != ISCSI_RSVD_TASK_TAG) {
481 		/*
482 		 * This is the initiator acknowledging our last PDU and
483 		 * indicating it is ready for the next PDU in the sequence.
484 		 */
485 		/*
486 		 * There can only be one outstanding text request on a
487 		 * connection. Make sure this one PDU has the current TTT.
488 		 */
489 		/* XXX combine the following 3 checks after testing */
490 		if (th_req->ttt != ict->ict_text_rsp_ttt) {
491 			/* Not part of this sequence */
492 			iscsit_text_reject(rx_pdu,
493 			    ISCSI_REJECT_CMD_NOT_SUPPORTED);
494 			return;
495 		}
496 		/*
497 		 * ITT should match what was saved from first PDU.
498 		 */
499 		if (th_req->itt != ict->ict_text_req_itt) {
500 			/* Not part of this sequence */
501 			iscsit_text_reject(rx_pdu,
502 			    ISCSI_REJECT_CMD_NOT_SUPPORTED);
503 			return;
504 		}
505 		/*
506 		 * Cannot deal with more key/value pairs now.
507 		 */
508 		if (rx_pdu->isp_datalen != 0) {
509 			iscsit_text_reject(rx_pdu,
510 			    ISCSI_REJECT_CMD_NOT_SUPPORTED);
511 			return;
512 		}
513 		iscsit_send_next_text_response(ict, rx_pdu);
514 		return;
515 	}
516 
517 	/*
518 	 * Initiator has started a new text request. Only
519 	 * one can be active at a time, so abandon any previous
520 	 * text request on this connection.
521 	 */
522 	iscsit_text_cmd_fini(ict);
523 
524 	/* Set the target task tag. */
525 	iscsit_bump_ttt(ict);
526 
527 	/* Save the initiator task tag */
528 	ict->ict_text_req_itt = th_req->itt;
529 
530 	/*
531 	 * Make sure this is a proper SendTargets request
532 	 */
533 	textbuf = (char *)rx_pdu->isp_data;
534 	textbuflen = rx_pdu->isp_datalen;
535 	kv_pair = "SendTargets=All";
536 	if (textbuflen >= strlen(kv_pair) &&
537 	    strcmp(kv_pair, textbuf) == 0 &&
538 	    ict->ict_op.op_discovery_session == B_TRUE) {
539 		/*
540 		 * Most common case of SendTargets=All during discovery.
541 		 */
542 		idm_addr_list_t *ipaddr_p;
543 		iscsit_tgt_t *tgt, *ntgt;
544 		int ipsize;
545 
546 
547 		/* Create an nvlist for response */
548 		if (nvlist_alloc(&nv_resp, 0, KM_SLEEP) != 0) {
549 			iscsit_text_reject(rx_pdu,
550 			    ISCSI_REJECT_CMD_NOT_SUPPORTED);
551 			return;
552 		}
553 
554 		/* Get the list of local interface addresses */
555 		ipsize = idm_get_ipaddr(&ipaddr_p);
556 
557 		/* Add targets to the response list */
558 		ISCSIT_GLOBAL_LOCK(RW_READER);
559 		for (tgt = avl_first(&iscsit_global.global_target_list);
560 		    tgt != NULL; tgt = ntgt) {
561 			struct sockaddr_storage v4sa, *sa;
562 			iscsit_tgt_state_t state;
563 			iscsit_portal_t *portal;
564 			iscsit_tpgt_t *tpgt;
565 
566 			ntgt = AVL_NEXT(&iscsit_global.global_target_list, tgt);
567 
568 			/* Only report online and onlining targets */
569 			state = tgt->target_state;
570 			if (state != TS_ONLINING && state != TS_ONLINE &&
571 			    state != TS_STMF_ONLINE)
572 				continue;
573 
574 			/*
575 			 * Report target if:
576 			 * - it is bound to default TPG
577 			 * - one of the addresses of TPGs the target is bound
578 			 *   to matches incoming connection dst address
579 			 */
580 			sa = &ict->ict_ic->ic_laddr;
581 			mutex_enter(&tgt->target_mutex);
582 			tpgt = avl_first(&tgt->target_tpgt_list);
583 			if (!(IS_DEFAULT_TPGT(tpgt))) {
584 				portal = iscsit_tgt_lookup_portal(tgt, sa,
585 				    &tpgt);
586 				if (portal == NULL &&
587 				    iscsit_is_v4_mapped(sa, &v4sa)) {
588 					portal = iscsit_tgt_lookup_portal(tgt,
589 					    &v4sa, &tpgt);
590 				}
591 				if (portal == NULL) {
592 					mutex_exit(&tgt->target_mutex);
593 					continue;
594 				}
595 				iscsit_portal_rele(portal);
596 				iscsit_tpgt_rele(tpgt);
597 			}
598 			mutex_exit(&tgt->target_mutex);
599 
600 			if (nvlist_add_string(nv_resp, "TargetName",
601 			    tgt->target_name) == 0) {
602 				/* Add the portal groups bound to this target */
603 				iscsit_add_tpgs(ict, tgt, ipaddr_p, nv_resp);
604 			}
605 		}
606 		ISCSIT_GLOBAL_UNLOCK();
607 		if (ipsize > 0)
608 			kmem_free(ipaddr_p, ipsize);
609 
610 		/* Convert the response nvlist into an idm text buffer */
611 		textbuf = 0;
612 		textbuflen = 0;
613 		validlen = 0;
614 		rc = idm_nvlist_to_textbuf(nv_resp, &textbuf,
615 		    &textbuflen, &validlen);
616 		nvlist_free(nv_resp);
617 		if (rc != 0) {
618 			if (textbuf && textbuflen)
619 				kmem_free(textbuf, textbuflen);
620 			iscsit_text_reject(rx_pdu,
621 			    ISCSI_REJECT_CMD_NOT_SUPPORTED);
622 			return;
623 		}
624 		ict->ict_text_rsp_buf = textbuf;
625 		ict->ict_text_rsp_len = textbuflen;
626 		ict->ict_text_rsp_valid_len = validlen;
627 		ict->ict_text_rsp_off = 0;
628 		iscsit_send_next_text_response(ict, rx_pdu);
629 	} else {
630 		/*
631 		 * Other cases to handle
632 		 *    Discovery session:
633 		 *	SendTargets=<target_name>
634 		 *    Normal session
635 		 *	SendTargets=<NULL> - assume target name of session
636 		 *    All others
637 		 *	Error
638 		 */
639 		iscsit_text_reject(rx_pdu, ISCSI_REJECT_CMD_NOT_SUPPORTED);
640 		return;
641 	}
642 }
643