8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / isns / isnsd / func.c
blob33818334b2ce8e23cd8dff4c44467f3f857af04c
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
34 #include "isns_server.h"
35 #include "isns_msgq.h"
36 #include "isns_func.h"
37 #include "isns_cache.h"
38 #include "isns_obj.h"
39 #include "isns_dd.h"
40 #include "isns_pdu.h"
41 #include "isns_qry.h"
42 #include "isns_scn.h"
43 #include "isns_utils.h"
44 #include "isns_cfg.h"
45 #include "isns_esi.h"
46 #include "isns_provider.h"
47 #include "isns_log.h"
50 * extern global variables
52 #ifdef DEBUG
53 extern int verbose_mc;
54 extern int verbose_tc;
55 #endif
56 extern const int NUM_OF_ATTRS[MAX_OBJ_TYPE_FOR_SIZE];
57 extern const int NUM_OF_CHILD[MAX_OBJ_TYPE];
58 extern const int TYPE_OF_PARENT[MAX_OBJ_TYPE_FOR_SIZE];
59 extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
60 extern const int TAG_RANGE[MAX_OBJ_TYPE][3];
62 /* scn message queue */
63 extern msg_queue_t *scn_q;
66 * extern functions.
70 * local variables
74 * local functions.
76 static int dev_attr_reg(conn_arg_t *);
77 static int dev_attr_qry(conn_arg_t *);
78 static int dev_get_next(conn_arg_t *);
79 static int dev_dereg(conn_arg_t *);
80 static int scn_reg(conn_arg_t *);
81 static int scn_dereg(conn_arg_t *);
82 static int dd_reg(conn_arg_t *);
83 static int dd_dereg(conn_arg_t *);
84 static int dds_reg(conn_arg_t *);
85 static int dds_dereg(conn_arg_t *);
86 static int msg_error(conn_arg_t *);
89 * ****************************************************************************
91 * packet_get_source:
92 * get the source attributes of the packet.
94 * conn - the argument of the connection.
95 * return - error code.
97 * ****************************************************************************
99 static int
100 packet_get_source(
101 conn_arg_t *conn
104 int ec = 0;
106 isns_pdu_t *pdu = conn->in_packet.pdu;
107 isns_tlv_t *source = pdu_get_source(pdu);
109 if (source == NULL) {
110 ec = ISNS_RSP_SRC_ABSENT;
111 } else if (source->attr_id != ISNS_ISCSI_NAME_ATTR_ID ||
112 source->attr_len == 0) {
113 ec = ISNS_RSP_SRC_UNKNOWN;
116 if (ec == 0) {
117 conn->in_packet.source = source;
120 return (ec);
124 * ****************************************************************************
126 * packet_get_key:
127 * get the key attributes of the packet.
129 * conn - the argument of the connection.
130 * return - error code.
132 * ****************************************************************************
134 static int
135 packet_get_key(
136 conn_arg_t *conn
139 int ec = 0;
141 isns_pdu_t *pdu = conn->in_packet.pdu;
142 isns_tlv_t *key;
143 size_t key_len;
145 key = pdu_get_key(pdu, &key_len);
147 conn->in_packet.key = key;
148 conn->in_packet.key_len = key_len;
150 return (ec);
154 * ****************************************************************************
156 * packet_get_operand:
157 * get the operating attributes of the packet.
159 * conn - the argument of the connection.
160 * return - error code.
162 * ****************************************************************************
164 static int
165 packet_get_operand(
166 conn_arg_t *conn
169 int ec = 0;
171 isns_pdu_t *pdu = conn->in_packet.pdu;
172 isns_tlv_t *op;
173 size_t op_len;
175 op = pdu_get_operand(pdu, &op_len);
177 conn->in_packet.op = op;
178 conn->in_packet.op_len = op_len;
180 return (ec);
184 * ****************************************************************************
186 * packet_split_verify:
187 * split and verify the packet, get the apporiate locking type and
188 * function handler for the packet.
190 * conn - the argument of the connection.
191 * return - error code.
193 * ****************************************************************************
196 packet_split_verify(
197 conn_arg_t *conn
200 int ec = 0;
202 isns_pdu_t *pdu = conn->in_packet.pdu;
204 int (*handler)(conn_arg_t *) = msg_error;
205 int lock = CACHE_NO_ACTION;
207 if (pdu->version != ISNSP_VERSION) {
208 ec = ISNS_RSP_VER_NOT_SUPPORTED;
209 } else {
210 switch (pdu->func_id) {
211 case ISNS_DEV_ATTR_REG:
212 lock = CACHE_WRITE;
213 handler = dev_attr_reg;
214 break;
215 case ISNS_DEV_ATTR_QRY:
216 lock = CACHE_READ;
217 handler = dev_attr_qry;
218 break;
219 case ISNS_DEV_GET_NEXT:
220 lock = CACHE_READ;
221 handler = dev_get_next;
222 break;
223 case ISNS_DEV_DEREG:
224 lock = CACHE_WRITE;
225 handler = dev_dereg;
226 break;
227 case ISNS_SCN_REG:
228 if (scn_q != NULL) {
229 lock = CACHE_WRITE;
230 handler = scn_reg;
231 } else {
232 ec = ISNS_RSP_SCN_REGIS_REJECTED;
234 break;
235 case ISNS_SCN_DEREG:
236 if (scn_q != NULL) {
237 lock = CACHE_WRITE;
238 handler = scn_dereg;
239 } else {
240 ec = ISNS_RSP_SCN_REGIS_REJECTED;
242 break;
243 case ISNS_SCN_EVENT:
244 ec = ISNS_RSP_MSG_NOT_SUPPORTED;
245 break;
246 case ISNS_DD_REG:
247 lock = CACHE_WRITE;
248 handler = dd_reg;
249 break;
250 case ISNS_DD_DEREG:
251 lock = CACHE_WRITE;
252 handler = dd_dereg;
253 break;
254 case ISNS_DDS_REG:
255 lock = CACHE_WRITE;
256 handler = dds_reg;
257 break;
258 case ISNS_DDS_DEREG:
259 lock = CACHE_WRITE;
260 handler = dds_dereg;
261 break;
262 default:
263 ec = ISNS_RSP_MSG_NOT_SUPPORTED;
264 break;
268 if (ISNS_OPERATION_TYPE_ENABLED()) {
269 char buf[INET6_ADDRSTRLEN];
270 struct sockaddr_storage *ssp = &conn->ss;
271 struct sockaddr_in *sinp = (struct sockaddr_in *)ssp;
272 if (ssp->ss_family == AF_INET) {
273 (void) inet_ntop(AF_INET, (void *)&(sinp->sin_addr),
274 buf, sizeof (buf));
275 } else {
276 (void) inet_ntop(AF_INET6, (void *)&(sinp->sin_addr),
277 buf, sizeof (buf));
279 ISNS_OPERATION_TYPE((uintptr_t)buf, pdu->func_id);
282 conn->lock = lock;
283 conn->handler = handler;
285 /* packet split & verify */
286 if (ec == 0) {
287 ec = packet_get_source(conn);
288 if (ec == 0) {
289 ec = packet_get_key(conn);
290 if (ec == 0) {
291 ec = packet_get_operand(conn);
296 conn->ec = ec;
298 return (ec);
302 * ****************************************************************************
304 * setup_key_lcp:
305 * setup the lookup control data for looking up the object
306 * which the key attributes identify.
308 * lcp - the pointer of the lookup control data.
309 * key - the key attributes.
310 * key_len - the length of the key attributes.
311 * return - the pointer of the lookup control data or
312 * NULL if there is an error.
314 * ****************************************************************************
316 static int
317 setup_key_lcp(
318 lookup_ctrl_t *lcp,
319 isns_tlv_t *key,
320 uint16_t key_len
323 int ec = 0;
325 uint8_t *value = &key->attr_value[0];
327 lcp->curr_uid = 0;
328 lcp->op[0] = 0;
330 switch (key->attr_id) {
331 case ISNS_EID_ATTR_ID:
332 if (key->attr_len >= 4) {
333 lcp->type = OBJ_ENTITY;
334 lcp->id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
335 lcp->op[0] = OP_STRING;
336 lcp->data[0].ptr = (uchar_t *)value;
337 lcp->op[1] = 0;
339 break;
340 case ISNS_ISCSI_NAME_ATTR_ID:
341 if (key->attr_len >= 4) {
342 lcp->type = OBJ_ISCSI;
343 lcp->id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
344 lcp->op[0] = OP_STRING;
345 lcp->data[0].ptr = (uchar_t *)value;
346 lcp->op[1] = 0;
347 } else {
348 ec = ISNS_RSP_MSG_FORMAT_ERROR;
350 break;
351 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
352 if (key->attr_len == sizeof (in6_addr_t)) {
353 lcp->id[0] = ATTR_INDEX_PORTAL(
354 ISNS_PORTAL_IP_ADDR_ATTR_ID);
355 lcp->op[0] = OP_MEMORY_IP6;
356 lcp->data[0].ip = (in6_addr_t *)value;
357 NEXT_TLV(key, key_len);
358 if (key_len <= 8 ||
359 key->attr_len != 4 ||
360 key->attr_id != ISNS_PORTAL_PORT_ATTR_ID) {
361 return (ISNS_RSP_MSG_FORMAT_ERROR);
363 lcp->type = OBJ_PORTAL;
364 value = &key->attr_value[0];
365 lcp->id[1] = ATTR_INDEX_PORTAL(
366 ISNS_PORTAL_PORT_ATTR_ID);
367 lcp->op[1] = OP_INTEGER;
368 lcp->data[1].ui = ntohl(*(uint32_t *)value);
369 lcp->op[2] = 0;
370 } else {
371 ec = ISNS_RSP_MSG_FORMAT_ERROR;
373 break;
374 case ISNS_PG_ISCSI_NAME_ATTR_ID:
375 if (key->attr_len < 4) {
376 return (ISNS_RSP_MSG_FORMAT_ERROR);
378 lcp->id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID);
379 lcp->op[0] = OP_STRING;
380 lcp->data[0].ptr = (uchar_t *)value;
381 NEXT_TLV(key, key_len);
382 if (key_len <= 8 ||
383 key->attr_len != sizeof (in6_addr_t) ||
384 key->attr_id != ISNS_PG_PORTAL_IP_ADDR_ATTR_ID) {
385 return (ISNS_RSP_MSG_FORMAT_ERROR);
387 value = &key->attr_value[0];
388 lcp->id[1] = ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID);
389 lcp->op[1] = OP_MEMORY_IP6;
390 lcp->data[1].ip = (in6_addr_t *)value;
391 NEXT_TLV(key, key_len);
392 if (key_len <= 8 ||
393 key->attr_len != 4 ||
394 key->attr_id != ISNS_PG_PORTAL_PORT_ATTR_ID) {
395 return (ISNS_RSP_MSG_FORMAT_ERROR);
397 value = &key->attr_value[0];
398 lcp->id[2] = ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID);
399 lcp->op[2] = OP_INTEGER;
400 lcp->data[2].ui = ntohl(*(uint32_t *)value);
401 lcp->type = OBJ_PG;
402 break;
403 default:
404 lcp->type = 0; /* invalid */
405 ec = ISNS_RSP_MSG_FORMAT_ERROR;
408 return (ec);
412 * ****************************************************************************
414 * rsp_add_op:
415 * add the operating attributes to the response packet.
417 * conn - the argument of the connection.
418 * obj - the object which is being added as operating attributes.
419 * return - error code.
421 * ****************************************************************************
423 static int
424 rsp_add_op(
425 conn_arg_t *conn,
426 isns_obj_t *obj
429 int ec = 0;
431 isns_attr_t *attr;
432 int i;
434 isns_pdu_t *rsp = conn->out_packet.pdu;
435 size_t pl = conn->out_packet.pl;
436 size_t sz = conn->out_packet.sz;
438 i = 0;
439 while (i < NUM_OF_ATTRS[obj->type] &&
440 ec == 0) {
441 attr = &obj->attrs[i];
442 /* there is an attribute, send it back */
443 if (attr->tag != 0) {
444 ec = pdu_add_tlv(&rsp, &pl, &sz,
445 attr->tag, attr->len,
446 (void *)attr->value.ptr, 0);
448 i ++;
451 conn->out_packet.pdu = rsp;
452 conn->out_packet.pl = pl;
453 conn->out_packet.sz = sz;
455 return (ec);
459 * ****************************************************************************
461 * rsp_add_key:
462 * add the key attributes to the response packet.
464 * conn - the argument of the connection.
465 * entity - the object which is being added as key attributes.
466 * return - error code.
468 * ****************************************************************************
470 static int
471 rsp_add_key(
472 conn_arg_t *conn,
473 isns_obj_t *entity
476 int ec = 0;
478 isns_tlv_t *key = conn->in_packet.key;
479 size_t key_len = conn->in_packet.key_len;
480 uint32_t tag = ISNS_EID_ATTR_ID;
481 isns_attr_t *attr = &entity->attrs[ATTR_INDEX_ENTITY(tag)];
482 uint32_t len = attr->len;
484 isns_pdu_t *rsp = conn->out_packet.pdu;
485 size_t pl = conn->out_packet.pl;
486 size_t sz = conn->out_packet.sz;
488 if (key_len == 0) {
489 ec = pdu_add_tlv(&rsp, &pl, &sz,
490 tag, len, (void *)attr->value.ptr, 0);
491 } else {
492 while (key_len >= 8 &&
493 ec == 0) {
494 if (key->attr_id == ISNS_EID_ATTR_ID) {
495 ec = pdu_add_tlv(&rsp, &pl, &sz,
496 tag, len,
497 (void *)attr->value.ptr, 0);
498 } else {
499 ec = pdu_add_tlv(&rsp, &pl, &sz,
500 key->attr_id, key->attr_len,
501 (void *)key->attr_value, 1);
503 NEXT_TLV(key, key_len);
507 if (ec == 0) {
508 ec = pdu_add_tlv(&rsp, &pl, &sz,
509 ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
512 conn->out_packet.pdu = rsp;
513 conn->out_packet.pl = pl;
514 conn->out_packet.sz = sz;
516 if (ec == 0) {
517 ec = rsp_add_op(conn, entity);
520 return (ec);
524 * ****************************************************************************
526 * rsp_add_tlv:
527 * add one attribute with TLV format to the response packet.
529 * conn - the argument of the connection.
530 * tag - the tag of the attribute.
531 * len - the length of the attribute.
532 * value- the value of the attribute.
533 * pflag- the flag of the value, 0: value; 1: pointer to value
534 * return - error code.
536 * ****************************************************************************
538 static int
539 rsp_add_tlv(
540 conn_arg_t *conn,
541 uint32_t tag,
542 uint32_t len,
543 void *value,
544 int pflag
547 int ec = 0;
549 isns_pdu_t *rsp = conn->out_packet.pdu;
550 size_t pl = conn->out_packet.pl;
551 size_t sz = conn->out_packet.sz;
553 ec = pdu_add_tlv(&rsp, &pl, &sz, tag, len, value, pflag);
555 conn->out_packet.pdu = rsp;
556 conn->out_packet.pl = pl;
557 conn->out_packet.sz = sz;
559 return (ec);
563 * ****************************************************************************
565 * rsp_add_tlvs:
566 * add attributes with TLV format to the response packet.
568 * conn - the argument of the connection.
569 * tlv - the attributes with TLV format being added.
570 * tlv_len - the length of the attributes.
571 * return - error code.
573 * ****************************************************************************
575 static int
576 rsp_add_tlvs(
577 conn_arg_t *conn,
578 isns_tlv_t *tlv,
579 uint32_t tlv_len
582 int ec = 0;
584 uint32_t tag;
585 uint32_t len;
586 void *value;
588 while (tlv_len >= 8 &&
589 ec == 0) {
590 tag = tlv->attr_id;
591 len = tlv->attr_len;
592 value = (void *)tlv->attr_value;
594 ec = rsp_add_tlv(conn, tag, len, value, 1);
596 NEXT_TLV(tlv, tlv_len);
599 return (ec);
603 * ****************************************************************************
605 * dev_attr_reg:
606 * function which handles the isnsp DEV_ATTR_REG message.
608 * conn - the argument of the connection.
609 * return - 0: the message requires response.
611 * ****************************************************************************
613 static int
614 dev_attr_reg(
615 conn_arg_t *conn
618 int ec = 0;
620 isns_pdu_t *pdu = conn->in_packet.pdu;
621 isns_tlv_t *source = conn->in_packet.source;
622 isns_tlv_t *key = conn->in_packet.key;
623 uint16_t key_len = conn->in_packet.key_len;
624 isns_tlv_t *op = conn->in_packet.op;
625 uint16_t op_len = conn->in_packet.op_len;
627 boolean_t replace =
628 ((pdu->flags & ISNS_FLAG_REPLACE_REG) == ISNS_FLAG_REPLACE_REG);
630 lookup_ctrl_t lc, lc_key;
631 uchar_t *iscsi_name;
632 int ctrl;
634 isns_obj_t *ety = NULL; /* network entity object */
635 isns_type_t ptype; /* parent object type */
636 uint32_t puid; /* parent object UID */
637 void const **child[MAX_CHILD_TYPE] = { NULL }; /* children */
638 int ety_update, obj_update;
639 isns_attr_t *eid_attr;
641 isns_obj_t *obj; /* child object */
642 isns_type_t ctype; /* child object type */
643 uint32_t uid; /* child object uid */
644 isns_attr_t pgt[3] = { NULL };
646 void const **vpp = NULL;
647 int i = 0;
649 isnslog(LOG_DEBUG, "dev_attr_reg", "entered (replace: %d)", replace);
651 ec = pdu_reset_rsp(&conn->out_packet.pdu,
652 &conn->out_packet.pl,
653 &conn->out_packet.sz);
654 if (ec != 0) {
655 goto reg_done;
658 iscsi_name = (uchar_t *)&source->attr_value[0];
659 ctrl = is_control_node(iscsi_name);
660 lc_key.type = 0;
661 if (key != NULL) {
662 /* validate key attributes and make lcp for */
663 /* the object identified by key attributes. */
664 ec = setup_key_lcp(&lc, key, key_len);
665 if (ec == 0 && lc.type != 0) {
666 lc_key = lc;
667 /* object is not found */
668 if ((uid = is_obj_there(&lc)) == 0) {
669 /* error if it is a network entity */
670 if (lc.type != OBJ_ENTITY) {
671 ec = ISNS_RSP_INVALID_REGIS;
673 /* validate for the source attribute before */
674 /* update or replace the network entity object */
675 } else if (ctrl == 0 &&
676 #ifndef SKIP_SRC_AUTH
677 reg_auth_src(lc.type, uid, iscsi_name) == 0) {
678 #else
679 0) {
680 #endif
681 ec = ISNS_RSP_SRC_UNAUTHORIZED;
682 /* de-register the network entity if replace is true */
683 } else if (replace != 0) {
684 UPDATE_LCP_UID(&lc, uid);
685 ec = dereg_object(&lc, 0);
686 /* generate a SCN */
687 if (ec == 0) {
688 (void) queue_msg_set(scn_q,
689 SCN_TRIGGER, NULL);
694 if (ec != 0) {
695 goto reg_done;
698 /* register the network entity object */
699 ec = reg_get_entity(&ety, &op, &op_len);
700 if (ec != 0) {
701 goto reg_done;
703 if (ety == NULL && lc_key.type != OBJ_ENTITY) {
704 ety = make_default_entity();
705 } else if (ety == NULL ||
706 (lc_key.type == OBJ_ENTITY &&
707 key_cmp(&lc_key, ety) != 0)) {
708 /* the eid in key attribute and */
709 /* op attribute must be the same */
710 ec = ISNS_RSP_INVALID_REGIS;
711 goto reg_done;
713 if (ety == NULL || rsp_add_key(conn, ety) != 0) {
714 ec = ISNS_RSP_INTERNAL_ERROR;
715 } else {
716 eid_attr = &ety->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)];
717 ec = register_object(ety, &puid, &ety_update);
718 ptype = OBJ_ENTITY;
720 if (ec == 0 && ety_update == 0) {
721 /* newly registered, reset the pointer */
722 ety = NULL;
725 /* register the reset of objects which are specified in */
726 /* operating attributes */
727 while (ec == 0 &&
728 (ec = reg_get_obj(&obj, &pgt[0], &op, &op_len)) == 0 &&
729 obj != NULL &&
730 (ec = rsp_add_op(conn, obj)) == 0) {
731 ctype = obj->type;
732 /* set the parent object UID */
733 (void) set_parent_obj(obj, puid);
734 /* register it */
735 ec = register_object(obj, &uid, &obj_update);
736 if (ec == 0) {
737 if (obj_update == 0 ||
738 is_obj_online(obj) == 0) {
739 /* update the ref'd object */
740 (void) update_ref_obj(obj);
741 /* add the newly registered object info */
742 /* to child info array of the parent object */
743 ec = buff_child_obj(ptype, ctype, obj, child);
744 } else {
745 if (ctrl == 0 &&
746 #ifndef SKIP_SRC_AUTH
747 puid != get_parent_uid(obj)) {
748 #else
749 0) {
750 #endif
751 ec = ISNS_RSP_SRC_UNAUTHORIZED;
753 /* it was for updating an existing object */
754 free_one_object(obj);
756 } else {
757 /* failed registering it */
758 free_one_object(obj);
762 /* update the portal group object for the associations between */
763 /* the newly registered objects and previously registered objects */
764 if (ec == 0) {
765 ec = verify_ref_obj(ptype, puid, child);
767 if (ec != 0) {
768 goto reg_done;
771 /* update the children list of the parent object */
772 while (i < MAX_CHILD_TYPE) {
773 vpp = child[i];
774 if (vpp != NULL) {
775 break;
777 i ++;
779 if (vpp != NULL) {
780 ec = update_child_obj(ptype, puid, child, 1);
781 } else {
782 #ifndef SKIP_SRC_AUTH
783 ec = ISNS_RSP_INVALID_REGIS;
784 #else
785 /* for interop-ability, we cannot treat this as */
786 /* an error, instead, remove the network entity */
787 SET_UID_LCP(&lc, OBJ_ENTITY, puid);
788 ec = dereg_object(&lc, 0);
789 goto reg_done;
790 #endif
792 if (ec != 0) {
793 goto reg_done;
795 /* add esi entry */
796 if (ety_update != 0) {
797 (void) esi_remove(puid);
799 ec = esi_add(puid, eid_attr->value.ptr, eid_attr->len);
801 reg_done:
802 conn->ec = ec;
803 free_one_object(ety);
804 uid = 0;
805 while (uid < MAX_CHILD_TYPE) {
806 if (child[uid] != NULL) {
807 free(child[uid]);
809 uid ++;
812 if (ec != 0) {
813 isnslog(LOG_DEBUG, "dev_attr_reg", "error code: %d", ec);
816 return (0);
820 * ****************************************************************************
822 * dev_attr_qry:
823 * function which handles the isnsp DEV_ATTR_QRY message.
825 * conn - the argument of the connection.
826 * return - 0: the message requires response.
828 * ****************************************************************************
830 static int
831 dev_attr_qry(
832 conn_arg_t *conn
835 int ec = 0;
837 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
838 isns_tlv_t *source = conn->in_packet.source;
839 isns_tlv_t *key = conn->in_packet.key;
840 uint16_t key_len = conn->in_packet.key_len;
841 isns_tlv_t *op = conn->in_packet.op;
842 uint16_t op_len = conn->in_packet.op_len;
844 uchar_t *iscsi_name;
846 bmp_t *nodes_bmp = NULL;
847 uint32_t num_of_nodes;
848 uint32_t *key_uids = NULL;
849 uint32_t num_of_keys;
850 isns_type_t key_type;
852 uint32_t key_uid;
853 uint32_t op_uid;
855 uint32_t size_of_ops;
856 uint32_t num_of_ops;
857 uint32_t *op_uids = NULL;
858 isns_type_t op_type;
860 isns_tlv_t *tlv;
861 uint16_t tlv_len;
863 isnslog(LOG_DEBUG, "dev_attr_qry", "entered");
865 ec = pdu_reset_rsp(&conn->out_packet.pdu,
866 &conn->out_packet.pl,
867 &conn->out_packet.sz);
868 if (ec != 0) {
869 goto qry_done;
873 * RFC 4171 section 5.7.5.2:
874 * If no Operating Attributes are included in the original query, then
875 * all Operating Attributes SHALL be returned in the response. ???
877 if (op_len == 0) {
878 goto qry_done;
881 iscsi_name = (uchar_t *)&source->attr_value[0];
882 if (is_control_node(iscsi_name) == 0) {
883 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
884 if (ec != 0 || nodes_bmp == NULL) {
885 goto qry_done;
889 size_of_ops = 0;
890 if (key != NULL) {
892 * Return the original message key.
894 ec = rsp_add_tlvs(conn, key, key_len);
895 if (ec != 0) {
896 goto qry_done;
900 * Delimiter
902 ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
903 if (ec != 0) {
904 goto qry_done;
908 * Query objects which match the Key Attributes.
910 ec = get_qry_keys(nodes_bmp, num_of_nodes, &key_type,
911 key, key_len, &key_uids, &num_of_keys);
912 if (ec != 0 || key_uids == NULL) {
913 goto qry_done;
917 * Iterate thru each object identified by the message key.
919 tlv = op;
920 tlv_len = op_len;
921 FOR_EACH_OBJS(key_uids, num_of_keys, key_uid, {
923 * Iterate thru each Operating Attributes.
925 op = tlv;
926 op_len = tlv_len;
927 FOR_EACH_OP(op, op_len, op_type, {
928 if (op_type == 0) {
929 ec = ISNS_RSP_INVALID_QRY;
930 goto qry_done;
932 ec = get_qry_ops(key_uid, key_type,
933 op_type, &op_uids,
934 &num_of_ops, &size_of_ops);
935 if (ec != 0) {
936 goto qry_done;
939 * Iterate thru each object for the Operating
940 * Attributes again.
942 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
943 ec = get_qry_attrs(op_uid, op_type,
944 op, op_len, conn);
945 if (ec != 0) {
946 goto qry_done;
951 } else {
953 * Iterate thru each Operating Attributes.
955 FOR_EACH_OP(op, op_len, op_type, {
956 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
957 op_type, &op_uids,
958 &num_of_ops, &size_of_ops);
959 if (ec != 0) {
960 goto qry_done;
963 * Iterate thru each object for the Operating
964 * Attributes again.
966 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
967 ec = get_qry_attrs(op_uid, op_type,
968 op, op_len, conn);
969 if (ec != 0) {
970 goto qry_done;
976 qry_done:
977 conn->ec = ec;
979 if (ec != 0) {
980 isnslog(LOG_DEBUG, "dev_attr_qry", "error code: %d", ec);
983 free(nodes_bmp);
984 free(key_uids);
985 free(op_uids);
987 return (0);
991 * ****************************************************************************
993 * dev_get_next:
994 * function which handles the isnsp DEV_GET_NEXT message.
996 * conn - the argument of the connection.
997 * return - 0: the message requires response.
999 * ****************************************************************************
1001 static int
1002 dev_get_next(
1003 conn_arg_t *conn
1006 int ec = 0;
1008 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1009 isns_tlv_t *source = conn->in_packet.source;
1010 isns_tlv_t *key = conn->in_packet.key;
1011 uint16_t key_len = conn->in_packet.key_len;
1012 isns_tlv_t *op = conn->in_packet.op;
1013 uint16_t op_len = conn->in_packet.op_len;
1015 uchar_t *iscsi_name;
1017 bmp_t *nodes_bmp = NULL;
1018 uint32_t num_of_nodes;
1020 isns_type_t key_type;
1021 isns_type_t op_type;
1022 uint32_t size_of_obj;
1023 uint32_t num_of_obj;
1024 uint32_t *obj_uids = NULL;
1026 uint32_t uid;
1028 isnslog(LOG_DEBUG, "dev_get_next", "entered");
1030 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1031 &conn->out_packet.pl,
1032 &conn->out_packet.sz);
1033 if (ec != 0) {
1034 goto get_next_done;
1037 iscsi_name = (uchar_t *)&source->attr_value[0];
1038 if (is_control_node(iscsi_name) == 0) {
1039 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
1040 if (nodes_bmp == NULL) {
1041 ec = ISNS_RSP_NO_SUCH_ENTRY;
1043 if (ec != 0) {
1044 goto get_next_done;
1049 * Get Message Key type and validate the Message Key.
1051 key_type = TLV2TYPE(key);
1052 if (key_type == 0) {
1053 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1054 goto get_next_done;
1056 ec = validate_qry_key(key_type, key, key_len, NULL);
1057 if (ec != 0) {
1058 goto get_next_done;
1061 size_of_obj = 0;
1062 if (op != NULL) {
1064 * Query the objects which match the Operating Attributes.
1066 ec = get_qry_keys(nodes_bmp, num_of_nodes, &op_type,
1067 op, op_len, &obj_uids, &num_of_obj);
1068 if (op_type != key_type) {
1069 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1071 } else {
1073 * Query the objects which match the Message Key type.
1075 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
1076 key_type, &obj_uids, &num_of_obj, &size_of_obj);
1078 if (ec != 0) {
1079 goto get_next_done;
1083 * Get the object which is next to the one indicated by the
1084 * Message Key.
1086 uid = get_next_obj(key, key_len, key_type, obj_uids, num_of_obj);
1087 if (uid == 0) {
1088 ec = ISNS_RSP_NO_SUCH_ENTRY;
1089 goto get_next_done;
1093 * Message Key
1095 if ((ec = get_qry_attrs1(uid, key_type, key, key_len, conn)) != 0) {
1096 goto get_next_done;
1100 * Delimiter
1102 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)) != 0) {
1103 goto get_next_done;
1107 * Operating Attributes
1109 if (op != NULL) {
1110 ec = get_qry_attrs(uid, op_type, op, op_len, conn);
1113 get_next_done:
1114 conn->ec = ec;
1116 if (ec != 0 && ec != ISNS_RSP_NO_SUCH_ENTRY) {
1117 isnslog(LOG_DEBUG, "dev_get_next", "error code: %d", ec);
1120 free(nodes_bmp);
1121 free(obj_uids);
1123 return (0);
1127 * ****************************************************************************
1129 * dev_dereg:
1130 * function which handles the isnsp DEV_DEREG message.
1132 * conn - the argument of the connection.
1133 * return - 0: the message requires response.
1135 * ****************************************************************************
1137 static int
1138 dev_dereg(
1139 conn_arg_t *conn
1142 int ec = 0;
1144 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1145 isns_tlv_t *source = conn->in_packet.source;
1146 /* isns_tlv_t *key = conn->in_packet.key; */
1147 /* uint16_t key_len = conn->in_packet.key_len; */
1148 isns_tlv_t *op = conn->in_packet.op;
1149 uint16_t op_len = conn->in_packet.op_len;
1151 uchar_t *iscsi_name;
1152 int ctrl;
1153 uint32_t puid;
1155 lookup_ctrl_t lc;
1156 uint8_t *value;
1158 isnslog(LOG_DEBUG, "dev_dereg", "entered");
1160 iscsi_name = (uchar_t *)&source->attr_value[0];
1161 ctrl = is_control_node(iscsi_name);
1162 if (ctrl == 0) {
1163 puid = is_parent_there(iscsi_name);
1166 while (op_len > 8 && ec == 0) {
1167 lc.curr_uid = 0;
1168 value = &op->attr_value[0];
1169 switch (op->attr_id) {
1170 case ISNS_EID_ATTR_ID:
1171 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
1172 lc.op[0] = OP_STRING;
1173 lc.data[0].ptr = (uchar_t *)value;
1174 lc.op[1] = 0;
1175 lc.type = OBJ_ENTITY;
1176 break;
1177 case ISNS_ISCSI_NAME_ATTR_ID:
1178 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
1179 lc.op[0] = OP_STRING;
1180 lc.data[0].ptr = (uchar_t *)value;
1181 lc.op[1] = 0;
1182 lc.type = OBJ_ISCSI;
1183 break;
1184 case ISNS_ISCSI_NODE_INDEX_ATTR_ID:
1185 lc.id[0] = ATTR_INDEX_ISCSI(
1186 ISNS_ISCSI_NODE_INDEX_ATTR_ID);
1187 lc.op[0] = OP_INTEGER;
1188 lc.data[0].ui = ntohl(*(uint32_t *)value);
1189 lc.op[1] = 0;
1190 lc.type = OBJ_ISCSI;
1191 break;
1192 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1193 lc.id[0] = ATTR_INDEX_PORTAL(
1194 ISNS_PORTAL_IP_ADDR_ATTR_ID);
1195 lc.op[0] = OP_MEMORY_IP6;
1196 lc.data[0].ip = (in6_addr_t *)value;
1197 NEXT_TLV(op, op_len);
1198 if (op_len > 8 &&
1199 op->attr_id == ISNS_PORTAL_PORT_ATTR_ID) {
1200 value = &op->attr_value[0];
1201 lc.id[1] = ATTR_INDEX_PORTAL(
1202 ISNS_PORTAL_PORT_ATTR_ID);
1203 lc.op[1] = OP_INTEGER;
1204 lc.data[1].ui = ntohl(*(uint32_t *)value);
1205 lc.op[2] = 0;
1206 lc.type = OBJ_PORTAL;
1207 } else {
1208 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1210 break;
1211 case ISNS_PORTAL_INDEX_ATTR_ID:
1212 lc.id[0] = ATTR_INDEX_PORTAL(
1213 ISNS_PORTAL_INDEX_ATTR_ID);
1214 lc.op[0] = OP_INTEGER;
1215 lc.data[0].ui = ntohl(*(uint32_t *)value);
1216 lc.op[1] = 0;
1217 lc.type = OBJ_PORTAL;
1218 break;
1219 default:
1220 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1221 break;
1223 if (ec == 0 &&
1224 (ec = dereg_object(&lc, 0)) == 0) {
1225 if (ctrl == 0 &&
1226 #ifndef SKIP_SRC_AUTH
1227 lc.curr_uid != 0 &&
1228 puid != lc.curr_uid) {
1229 #else
1230 0) {
1231 #endif
1232 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1233 } else {
1234 NEXT_TLV(op, op_len);
1239 conn->ec = ec;
1241 if (ec != 0) {
1242 isnslog(LOG_DEBUG, "dev_dereg", "error code: %d", ec);
1245 return (0);
1249 * ****************************************************************************
1251 * scn_reg:
1252 * function which handles the isnsp SCN_REG message.
1254 * conn - the argument of the connection.
1255 * return - 0: the message requires response.
1257 * ****************************************************************************
1259 static int
1260 scn_reg(
1261 conn_arg_t *conn
1264 int ec = 0;
1266 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1267 /* isns_tlv_t *source = conn->in_packet.source; */
1268 isns_tlv_t *key = conn->in_packet.key;
1269 uint16_t key_len = conn->in_packet.key_len;
1270 isns_tlv_t *op = conn->in_packet.op;
1271 uint16_t op_len = conn->in_packet.op_len;
1273 /* uchar_t *src; */
1274 uchar_t *node_name;
1275 uint32_t nlen;
1276 uint32_t scn;
1278 isnslog(LOG_DEBUG, "scn_reg", "entered");
1280 /* src = (uchar_t *)&source->attr_value[0]; */
1282 if (op == NULL ||
1283 op->attr_id != ISNS_ISCSI_SCN_BITMAP_ATTR_ID ||
1284 op_len != 12 ||
1285 key == NULL ||
1286 key->attr_id != ISNS_ISCSI_NAME_ATTR_ID ||
1287 key_len != 8 + key->attr_len) {
1288 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1289 goto scn_reg_done;
1292 node_name = (uchar_t *)&key->attr_value[0];
1293 nlen = key->attr_len;
1294 scn = ntohl(*(uint32_t *)&op->attr_value[0]);
1296 ec = add_scn_entry(node_name, nlen, scn);
1298 scn_reg_done:
1299 conn->ec = ec;
1301 if (ec != 0) {
1302 isnslog(LOG_DEBUG, "scn_reg", "error code: %d", ec);
1305 return (0);
1309 * ****************************************************************************
1311 * scn_dereg:
1312 * function which handles the isnsp SCN_DEREG message.
1314 * conn - the argument of the connection.
1315 * return - 0: the message requires response.
1317 * ****************************************************************************
1319 static int
1320 scn_dereg(
1321 conn_arg_t *conn
1324 int ec = 0;
1326 isns_tlv_t *key = conn->in_packet.key;
1327 uint16_t key_len = conn->in_packet.key_len;
1329 uchar_t *node_name;
1331 isnslog(LOG_DEBUG, "scn_dereg", "entered");
1333 if (key != NULL &&
1334 key->attr_len != 0 &&
1335 key_len == 8 + key->attr_len &&
1336 key->attr_id == ISNS_ISCSI_NAME_ATTR_ID) {
1337 node_name = (uchar_t *)&key->attr_value[0];
1338 ec = remove_scn_entry(node_name);
1339 } else {
1340 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1343 conn->ec = ec;
1345 if (ec != 0) {
1346 isnslog(LOG_DEBUG, "scn_dereg", "error code: %d", ec);
1349 return (0);
1353 * ****************************************************************************
1355 * setup_ddid_lcp:
1356 * setup the lookup control data for looking up the DD object
1357 * by using the dd_id attribute.
1359 * lcp - pointer to the lookup control data.
1360 * dd_id- the unique ID of the DD object.
1361 * return - the pointer to the lcp.
1363 * ****************************************************************************
1365 #ifndef DEBUG
1366 static
1367 #endif
1368 lookup_ctrl_t *
1369 setup_ddid_lcp(
1370 lookup_ctrl_t *lcp,
1371 uint32_t dd_id
1374 lcp->curr_uid = 0;
1375 lcp->type = OBJ_DD;
1376 lcp->id[0] = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID);
1377 lcp->op[0] = OP_INTEGER;
1378 lcp->data[0].ui = dd_id;
1379 lcp->op[1] = 0;
1381 return (lcp);
1385 * ****************************************************************************
1387 * setup_ddsid_lcp:
1388 * setup the lookup control data for looking up the DD-set object
1389 * by using the dds_id attribute.
1391 * lcp - pointer to the lookup control data.
1392 * dds_id - the unique ID of the DD-set object.
1393 * return - the pointer to the lcp.
1395 * ****************************************************************************
1397 #ifndef DEBUG
1398 static
1399 #endif
1400 lookup_ctrl_t *
1401 setup_ddsid_lcp(
1402 lookup_ctrl_t *lcp,
1403 uint32_t dds_id
1406 lcp->curr_uid = 0;
1407 lcp->type = OBJ_DDS;
1408 lcp->id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID);
1409 lcp->op[0] = OP_INTEGER;
1410 lcp->data[0].ui = dds_id;
1411 lcp->op[1] = 0;
1413 return (lcp);
1417 * ****************************************************************************
1419 * dd_reg:
1420 * function which handles the isnsp DD_REG message.
1422 * conn - the argument of the connection.
1423 * return - 0: the message requires response.
1425 * ****************************************************************************
1427 static int
1428 dd_reg(
1429 conn_arg_t *conn
1432 int ec = 0;
1434 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1435 isns_tlv_t *source = conn->in_packet.source;
1436 isns_tlv_t *key = conn->in_packet.key;
1437 uint16_t key_len = conn->in_packet.key_len;
1438 isns_tlv_t *op = conn->in_packet.op;
1439 uint16_t op_len = conn->in_packet.op_len;
1441 uint32_t dd_id = 0;
1442 uint8_t *value;
1444 isns_obj_t *dd = NULL;
1446 uchar_t *iscsi_name;
1448 lookup_ctrl_t lc;
1449 isns_assoc_iscsi_t aiscsi;
1450 isns_obj_t *assoc;
1451 isns_attr_t *attr;
1453 uint32_t features;
1455 isnslog(LOG_DEBUG, "dd_reg", "entered");
1457 iscsi_name = (uchar_t *)&source->attr_value[0];
1458 if (is_control_node(iscsi_name) == 0) {
1459 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1460 goto dd_reg_done;
1463 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1464 &conn->out_packet.pl,
1465 &conn->out_packet.sz);
1466 if (ec != 0) {
1467 goto dd_reg_done;
1470 if (op == NULL ||
1471 (key != NULL &&
1472 (key_len != 12 ||
1473 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1474 key->attr_len != 4 ||
1475 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1476 is_obj_there(setup_ddid_lcp(&lc, dd_id)) == 0))) {
1477 ec = ISNS_RSP_INVALID_REGIS;
1478 goto dd_reg_done;
1481 /* message key */
1482 if (key != NULL &&
1483 (ec = rsp_add_tlv(conn, ISNS_DD_ID_ATTR_ID, 4,
1484 (void *)dd_id, 0)) != 0) {
1485 goto dd_reg_done;
1488 /* delimiter */
1489 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1490 NULL, 0)) != 0) {
1491 goto dd_reg_done;
1494 /* A DDReg message with no Message Key SHALL result in the */
1495 /* attempted creation of a new Discovery Domain (DD). */
1496 if (dd_id == 0) {
1497 ec = create_dd_object(op, op_len, &dd);
1498 if (ec == 0) {
1499 ec = register_object(dd, &dd_id, NULL);
1500 if (ec == ERR_NAME_IN_USE) {
1501 ec = ISNS_RSP_INVALID_REGIS;
1503 if (ec != 0) {
1504 free_object(dd);
1505 goto dd_reg_done;
1507 } else {
1508 goto dd_reg_done;
1512 /* add the newly created dd to the response */
1513 if (dd != NULL) {
1514 ec = rsp_add_op(conn, dd);
1517 aiscsi.type = OBJ_ASSOC_ISCSI;
1518 aiscsi.puid = dd_id;
1520 while (op_len > 8 && ec == 0) {
1521 value = &op->attr_value[0];
1522 switch (op->attr_id) {
1523 case ISNS_DD_ID_ATTR_ID:
1524 /* if the DD_ID is included in both the Message Key */
1525 /* and Operating Attributes, then the DD_ID value */
1526 /* in the Message Key MUST be the same as the DD_ID */
1527 /* value in the Operating Attributes. */
1528 if (dd == NULL) {
1529 if (op->attr_len != 4 ||
1530 dd_id != ntohl(*(uint32_t *)value)) {
1531 ec = ISNS_RSP_INVALID_REGIS;
1532 } else {
1533 ec = rsp_add_tlv(conn,
1534 ISNS_DD_ID_ATTR_ID, 4,
1535 (void *)dd_id, 0);
1538 break;
1539 case ISNS_DD_NAME_ATTR_ID:
1540 /* It is going to modify the DD Symbolic Name. */
1541 if (dd == NULL) {
1542 if (op->attr_len > 0 && op->attr_len <= 256) {
1543 ec = update_dd_name(
1544 dd_id,
1545 op->attr_len,
1546 (uchar_t *)value);
1547 if (ec == ERR_NAME_IN_USE) {
1548 ec = ISNS_RSP_INVALID_REGIS;
1550 } else {
1551 ec = ISNS_RSP_INVALID_REGIS;
1553 if (ec == 0) {
1554 ec = rsp_add_tlv(conn,
1555 ISNS_DD_NAME_ATTR_ID,
1556 op->attr_len, (void *)value, 1);
1559 break;
1560 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1561 if (op->attr_len == 4) {
1562 /* zero the association object */
1563 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1564 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1565 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1566 attr->len = 4;
1567 attr->value.ui = ntohl(*(uint32_t *)value);
1568 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1569 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1570 attr->tag = 0; /* clear it */
1571 attr->value.ptr = NULL; /* clear it */
1572 assoc = (isns_obj_t *)&aiscsi;
1573 if ((ec = add_dd_member(assoc)) ==
1574 ERR_ALREADY_ASSOCIATED) {
1575 ec = 0;
1577 if (attr->value.ptr != NULL) {
1578 free(attr->value.ptr);
1580 } else {
1581 ec = ISNS_RSP_INVALID_REGIS;
1583 if (ec == 0) {
1584 ec = rsp_add_tlv(conn,
1585 ISNS_DD_ISCSI_INDEX_ATTR_ID,
1586 4, (void *)attr->value.ui, 0);
1588 break;
1589 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1590 if (op->attr_len > 0 && op->attr_len <= 224) {
1591 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1592 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1593 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1594 attr->len = op->attr_len;
1595 attr->value.ptr = (uchar_t *)value;
1596 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1597 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1598 attr->tag = 0; /* clear it */
1599 assoc = (isns_obj_t *)&aiscsi;
1600 if ((ec = add_dd_member(assoc)) ==
1601 ERR_ALREADY_ASSOCIATED) {
1602 ec = 0;
1604 } else {
1605 ec = ISNS_RSP_INVALID_REGIS;
1607 if (ec == 0) {
1608 ec = rsp_add_tlv(conn,
1609 ISNS_DD_ISCSI_NAME_ATTR_ID,
1610 op->attr_len, (void *)value, 1);
1612 break;
1613 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1614 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1615 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1616 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1617 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1618 break;
1619 case ISNS_DD_FEATURES_ATTR_ID:
1620 /* It is going to modify the DD Symbolic Name. */
1621 if (dd == NULL) {
1622 if (op->attr_len == 4) {
1623 features = ntohl(*(uint32_t *)value);
1624 ec = update_dd_features(
1625 dd_id, features);
1626 } else {
1627 ec = ISNS_RSP_INVALID_REGIS;
1629 if (ec == 0) {
1630 ec = rsp_add_tlv(conn,
1631 ISNS_DD_FEATURES_ATTR_ID,
1632 4, (void *)features, 0);
1635 break;
1636 default:
1637 ec = ISNS_RSP_INVALID_REGIS;
1638 break;
1641 NEXT_TLV(op, op_len);
1644 dd_reg_done:
1645 conn->ec = ec;
1647 if (ec != 0) {
1648 isnslog(LOG_DEBUG, "dd_reg", "error code: %d", ec);
1651 return (0);
1655 * ****************************************************************************
1657 * dds_reg:
1658 * function which handles the isnsp DDS_REG message.
1660 * conn - the argument of the connection.
1661 * return - 0: the message requires response.
1663 * ****************************************************************************
1665 static int
1666 dds_reg(
1667 conn_arg_t *conn
1670 int ec = 0;
1672 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1673 isns_tlv_t *source = conn->in_packet.source;
1674 isns_tlv_t *key = conn->in_packet.key;
1675 uint16_t key_len = conn->in_packet.key_len;
1676 isns_tlv_t *op = conn->in_packet.op;
1677 uint16_t op_len = conn->in_packet.op_len;
1679 uint32_t dds_id = 0;
1680 uint8_t *value;
1682 isns_obj_t *dds = NULL;
1684 uchar_t *iscsi_name;
1686 lookup_ctrl_t lc;
1687 isns_assoc_dd_t add;
1688 isns_obj_t *assoc;
1689 isns_attr_t *attr;
1691 uint32_t code;
1693 isnslog(LOG_DEBUG, "dds_reg", "entered");
1695 iscsi_name = (uchar_t *)&source->attr_value[0];
1696 if (is_control_node(iscsi_name) == 0) {
1697 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1698 goto dds_reg_done;
1701 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1702 &conn->out_packet.pl,
1703 &conn->out_packet.sz);
1704 if (ec != 0) {
1705 goto dds_reg_done;
1708 if (op == NULL ||
1709 (key != NULL &&
1710 (key_len != 12 ||
1711 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
1712 key->attr_len != 4 ||
1713 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1714 is_obj_there(setup_ddsid_lcp(&lc, dds_id)) == 0))) {
1715 ec = ISNS_RSP_INVALID_REGIS;
1716 goto dds_reg_done;
1719 /* message key */
1720 if (key != NULL &&
1721 (ec = rsp_add_tlv(conn, ISNS_DD_SET_ID_ATTR_ID, 4,
1722 (void *)dds_id, 0)) != 0) {
1723 goto dds_reg_done;
1726 /* delimiter */
1727 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1728 NULL, 0)) != 0) {
1729 goto dds_reg_done;
1732 /* A DDSReg message with no Message Key SHALL result in the */
1733 /* attempted creation of a new Discovery Domain (DD). */
1734 if (dds_id == 0) {
1735 ec = create_dds_object(op, op_len, &dds);
1736 if (ec == 0) {
1737 ec = register_object(dds, &dds_id, NULL);
1738 if (ec == ERR_NAME_IN_USE) {
1739 ec = ISNS_RSP_INVALID_REGIS;
1741 if (ec != 0) {
1742 free_object(dds);
1743 goto dds_reg_done;
1745 } else {
1746 goto dds_reg_done;
1750 /* add the newly created dd to the response */
1751 if (dds != NULL) {
1752 ec = rsp_add_op(conn, dds);
1755 add.type = OBJ_ASSOC_DD;
1756 add.puid = dds_id;
1758 while (op_len > 8 && ec == 0) {
1759 value = &op->attr_value[0];
1760 switch (op->attr_id) {
1761 case ISNS_DD_SET_ID_ATTR_ID:
1762 /* if the DDS_ID is included in both the Message Key */
1763 /* and Operating Attributes, then the DDS_ID value */
1764 /* in the Message Key MUST be the same as the DDS_ID */
1765 /* value in the Operating Attributes. */
1766 if (dds == NULL) {
1767 if (op->attr_len != 4 ||
1768 dds_id != ntohl(*(uint32_t *)value)) {
1769 ec = ISNS_RSP_INVALID_REGIS;
1770 } else {
1771 ec = rsp_add_tlv(conn,
1772 ISNS_DD_SET_ID_ATTR_ID,
1773 4, (void *)dds_id, 0);
1776 break;
1777 case ISNS_DD_SET_NAME_ATTR_ID:
1778 /* It is going to modify the DD Symbolic Name. */
1779 if (dds == NULL) {
1780 if (op->attr_len > 0 && op->attr_len <= 256) {
1781 ec = update_dds_name(
1782 dds_id,
1783 op->attr_len,
1784 (uchar_t *)value);
1785 if (ec == ERR_NAME_IN_USE) {
1786 ec = ISNS_RSP_INVALID_REGIS;
1788 } else {
1789 ec = ISNS_RSP_INVALID_REGIS;
1791 if (ec == 0) {
1792 ec = rsp_add_tlv(conn,
1793 ISNS_DD_SET_NAME_ATTR_ID,
1794 op->attr_len, (void *)value, 1);
1797 break;
1798 case ISNS_DD_SET_STATUS_ATTR_ID:
1799 /* It is going to modify the DD Symbolic Name. */
1800 if (dds == NULL) {
1801 if (op->attr_len == 4) {
1802 code = ntohl(*(uint32_t *)value);
1803 ec = update_dds_status(
1804 dds_id, code);
1805 } else {
1806 ec = ISNS_RSP_INVALID_REGIS;
1808 if (ec == 0) {
1809 ec = rsp_add_tlv(conn,
1810 ISNS_DD_SET_STATUS_ATTR_ID,
1811 4, (void *)code, 0);
1814 break;
1815 case ISNS_DD_ID_ATTR_ID:
1816 if (op->attr_len == 4) {
1817 /* zero the association object */
1818 attr = &add.attrs[ATTR_INDEX_ASSOC_DD(
1819 ISNS_DD_ID_ATTR_ID)];
1820 attr->tag = ISNS_DD_ID_ATTR_ID;
1821 attr->len = 4;
1822 attr->value.ui = ntohl(*(uint32_t *)value);
1823 assoc = (isns_obj_t *)&add;
1824 if ((ec = add_dds_member(assoc)) ==
1825 ERR_ALREADY_ASSOCIATED) {
1826 ec = 0;
1828 } else {
1829 ec = ISNS_RSP_INVALID_REGIS;
1831 if (ec == 0) {
1832 ec = rsp_add_tlv(conn,
1833 ISNS_DD_ID_ATTR_ID, 4,
1834 (void *)attr->value.ui, 0);
1836 break;
1837 default:
1838 ec = ISNS_RSP_INVALID_REGIS;
1839 break;
1842 NEXT_TLV(op, op_len);
1845 dds_reg_done:
1846 conn->ec = ec;
1848 if (ec != 0) {
1849 isnslog(LOG_DEBUG, "dds_reg", "error code: %d", ec);
1852 return (0);
1856 * ****************************************************************************
1858 * dd_dereg:
1859 * function which handles the isnsp DD_DEREG message.
1861 * conn - the argument of the connection.
1862 * return - 0: the message requires response.
1864 * ****************************************************************************
1866 static int
1867 dd_dereg(
1868 conn_arg_t *conn
1871 int ec = 0;
1873 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1874 isns_tlv_t *source = conn->in_packet.source;
1875 isns_tlv_t *key = conn->in_packet.key;
1876 uint16_t key_len = conn->in_packet.key_len;
1877 isns_tlv_t *op = conn->in_packet.op;
1878 uint16_t op_len = conn->in_packet.op_len;
1880 uint32_t dd_id;
1881 uint8_t *value;
1883 uchar_t *iscsi_name;
1885 isns_assoc_iscsi_t aiscsi;
1886 isns_obj_t *assoc;
1887 isns_attr_t *attr;
1889 isnslog(LOG_DEBUG, "dd_dereg", "entered");
1891 iscsi_name = (uchar_t *)&source->attr_value[0];
1892 if (is_control_node(iscsi_name) == 0) {
1893 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1894 goto dd_dereg_done;
1897 if (key == NULL ||
1898 key_len != 12 ||
1899 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1900 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
1901 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1902 goto dd_dereg_done;
1905 if (op == NULL) {
1906 ec = remove_dd_object(dd_id);
1907 } else {
1908 aiscsi.type = OBJ_ASSOC_ISCSI;
1909 aiscsi.puid = dd_id;
1911 while (op_len > 8 && ec == 0) {
1912 value = &op->attr_value[0];
1913 switch (op->attr_id) {
1914 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1915 /* zero the association object */
1916 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1917 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1918 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1919 attr->len = 4;
1920 attr->value.ui = ntohl(*(uint32_t *)value);
1921 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1922 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1923 attr->tag = 0; /* clear it */
1924 attr->value.ptr = NULL; /* clear it */
1925 assoc = (isns_obj_t *)&aiscsi;
1926 if ((ec = remove_dd_member(assoc)) ==
1927 ERR_NO_SUCH_ASSOCIATION) {
1928 ec = 0;
1930 if (attr->value.ptr != NULL) {
1931 free(attr->value.ptr);
1933 break;
1934 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1935 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1936 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1937 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1938 attr->len = op->attr_len;
1939 attr->value.ptr = (uchar_t *)value;
1940 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1941 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1942 attr->tag = 0; /* clear it */
1943 assoc = (isns_obj_t *)&aiscsi;
1944 if ((ec = remove_dd_member(assoc)) ==
1945 ERR_NO_SUCH_ASSOCIATION) {
1946 ec = 0;
1948 break;
1949 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1950 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1951 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1952 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1953 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1954 break;
1955 default:
1956 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1957 break;
1960 NEXT_TLV(op, op_len);
1964 dd_dereg_done:
1965 conn->ec = ec;
1967 if (ec != 0) {
1968 isnslog(LOG_DEBUG, "dd_dereg", "error code: %d", ec);
1971 return (0);
1975 * ****************************************************************************
1977 * dds_dereg:
1978 * function which handles the isnsp DDS_DEREG message.
1980 * conn - the argument of the connection.
1981 * return - 0: the message requires response.
1983 * ****************************************************************************
1985 static int
1986 dds_dereg(
1987 conn_arg_t *conn
1990 int ec = 0;
1992 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1993 isns_tlv_t *source = conn->in_packet.source;
1994 isns_tlv_t *key = conn->in_packet.key;
1995 uint16_t key_len = conn->in_packet.key_len;
1996 isns_tlv_t *op = conn->in_packet.op;
1997 uint16_t op_len = conn->in_packet.op_len;
1999 uint32_t dds_id;
2000 uint32_t uid;
2001 uint8_t *value;
2003 uchar_t *iscsi_name;
2005 isnslog(LOG_DEBUG, "dds_dereg", "entered");
2007 iscsi_name = (uchar_t *)&source->attr_value[0];
2008 if (is_control_node(iscsi_name) == 0) {
2009 ec = ISNS_RSP_SRC_UNAUTHORIZED;
2010 goto dds_dereg_done;
2013 if (key == NULL ||
2014 key_len != 12 ||
2015 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
2016 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
2017 ec = ISNS_RSP_MSG_FORMAT_ERROR;
2018 goto dds_dereg_done;
2021 if (op == NULL) {
2022 ec = remove_dds_object(dds_id);
2023 } else {
2024 while (op_len > 8 && ec == 0) {
2025 value = &op->attr_value[0];
2026 if (op->attr_id == ISNS_DD_ID_ATTR_ID) {
2027 uid = ntohl(*(uint32_t *)value);
2028 if ((ec = remove_dds_member(dds_id, uid)) ==
2029 ERR_NO_SUCH_ASSOCIATION) {
2030 ec = 0;
2032 } else {
2033 ec = ISNS_RSP_MSG_FORMAT_ERROR;
2036 NEXT_TLV(op, op_len);
2040 dds_dereg_done:
2041 conn->ec = ec;
2043 if (ec != 0) {
2044 isnslog(LOG_DEBUG, "dds_dereg", "error code: %d", ec);
2047 return (0);
2051 * ****************************************************************************
2053 * msg_error:
2054 * function which handles any unknown isnsp messages or the
2055 * messages which are not supported.
2057 * conn - the argument of the connection.
2058 * return - 0: the message requires response.
2060 * ****************************************************************************
2062 static int
2063 msg_error(
2064 /* LINTED E_FUNC_ARG_UNUSED */
2065 conn_arg_t *conn
2068 return (0);
2072 * ****************************************************************************
2074 * isns_response_ec:
2075 * send the response message to the client with error code.
2077 * so - the socket descriptor.
2078 * pdu - the received pdu.
2079 * ec - the error code which is being responsed.
2080 * return - status of the sending operation.
2082 * ****************************************************************************
2084 static int
2085 isns_response_ec(
2086 int so,
2087 isns_pdu_t *pdu,
2088 int ec
2091 int status;
2093 uint8_t buff[sizeof (isns_pdu_t) + 8];
2095 isns_pdu_t *rsp = (isns_pdu_t *)&buff;
2096 isns_resp_t *resp = (isns_resp_t *)rsp->payload;
2097 size_t pl = 4;
2099 rsp->version = htons((uint16_t)ISNSP_VERSION);
2100 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2101 rsp->xid = htons(pdu->xid);
2102 resp->status = htonl(ec);
2104 status = isns_send_pdu(so, rsp, pl);
2106 return (status);
2110 * ****************************************************************************
2112 * isns_response:
2113 * send the response message to the client.
2115 * conn - the argument of the connection.
2116 * return - status of the sending operation.
2118 * ****************************************************************************
2121 isns_response(
2122 conn_arg_t *conn
2125 int status;
2127 int so = conn->so;
2128 int ec = conn->ec;
2129 isns_pdu_t *pdu = conn->in_packet.pdu;
2130 isns_pdu_t *rsp = conn->out_packet.pdu;
2131 size_t pl = conn->out_packet.pl;
2133 if (rsp != NULL) {
2134 rsp->version = htons((uint16_t)ISNSP_VERSION);
2135 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2136 rsp->xid = htons(pdu->xid);
2137 (void) pdu_update_code(rsp, &pl, ec);
2138 status = isns_send_pdu(so, rsp, pl);
2139 } else {
2140 status = isns_response_ec(so, pdu, ec);
2143 return (status);