dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / isns / isnsd / func.c
blob706c281bbaa52566e51a8241d4d241a48334b10c
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] = { 0 };
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 #ifndef SKIP_SRC_AUTH
676 } else if (ctrl == 0 &&
677 reg_auth_src(lc.type, uid, iscsi_name) == 0) {
678 ec = ISNS_RSP_SRC_UNAUTHORIZED;
679 #endif
680 /* de-register the network entity if replace is true */
681 } else if (replace != 0) {
682 UPDATE_LCP_UID(&lc, uid);
683 ec = dereg_object(&lc, 0);
684 /* generate a SCN */
685 if (ec == 0) {
686 (void) queue_msg_set(scn_q,
687 SCN_TRIGGER, NULL);
692 if (ec != 0) {
693 goto reg_done;
696 /* register the network entity object */
697 ec = reg_get_entity(&ety, &op, &op_len);
698 if (ec != 0) {
699 goto reg_done;
701 if (ety == NULL && lc_key.type != OBJ_ENTITY) {
702 ety = make_default_entity();
703 } else if (ety == NULL ||
704 (lc_key.type == OBJ_ENTITY &&
705 key_cmp(&lc_key, ety) != 0)) {
706 /* the eid in key attribute and */
707 /* op attribute must be the same */
708 ec = ISNS_RSP_INVALID_REGIS;
709 goto reg_done;
711 if (ety == NULL || rsp_add_key(conn, ety) != 0) {
712 ec = ISNS_RSP_INTERNAL_ERROR;
713 } else {
714 eid_attr = &ety->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)];
715 ec = register_object(ety, &puid, &ety_update);
716 ptype = OBJ_ENTITY;
718 if (ec == 0 && ety_update == 0) {
719 /* newly registered, reset the pointer */
720 ety = NULL;
723 /* register the reset of objects which are specified in */
724 /* operating attributes */
725 while (ec == 0 &&
726 (ec = reg_get_obj(&obj, &pgt[0], &op, &op_len)) == 0 &&
727 obj != NULL &&
728 (ec = rsp_add_op(conn, obj)) == 0) {
729 ctype = obj->type;
730 /* set the parent object UID */
731 (void) set_parent_obj(obj, puid);
732 /* register it */
733 ec = register_object(obj, &uid, &obj_update);
734 if (ec == 0) {
735 if (obj_update == 0 ||
736 is_obj_online(obj) == 0) {
737 /* update the ref'd object */
738 (void) update_ref_obj(obj);
739 /* add the newly registered object info */
740 /* to child info array of the parent object */
741 ec = buff_child_obj(ptype, ctype, obj, child);
742 } else {
743 #ifndef SKIP_SRC_AUTH
744 if (ctrl == 0 &&
745 puid != get_parent_uid(obj)) {
746 ec = ISNS_RSP_SRC_UNAUTHORIZED;
748 #endif
749 /* it was for updating an existing object */
750 free_one_object(obj);
752 } else {
753 /* failed registering it */
754 free_one_object(obj);
758 /* update the portal group object for the associations between */
759 /* the newly registered objects and previously registered objects */
760 if (ec == 0) {
761 ec = verify_ref_obj(ptype, puid, child);
763 if (ec != 0) {
764 goto reg_done;
767 /* update the children list of the parent object */
768 while (i < MAX_CHILD_TYPE) {
769 vpp = child[i];
770 if (vpp != NULL) {
771 break;
773 i ++;
775 if (vpp != NULL) {
776 ec = update_child_obj(ptype, puid, child, 1);
777 } else {
778 #ifndef SKIP_SRC_AUTH
779 ec = ISNS_RSP_INVALID_REGIS;
780 #else
781 /* for interop-ability, we cannot treat this as */
782 /* an error, instead, remove the network entity */
783 SET_UID_LCP(&lc, OBJ_ENTITY, puid);
784 ec = dereg_object(&lc, 0);
785 goto reg_done;
786 #endif
788 if (ec != 0) {
789 goto reg_done;
791 /* add esi entry */
792 if (ety_update != 0) {
793 (void) esi_remove(puid);
795 ec = esi_add(puid, eid_attr->value.ptr, eid_attr->len);
797 reg_done:
798 conn->ec = ec;
799 free_one_object(ety);
800 uid = 0;
801 while (uid < MAX_CHILD_TYPE) {
802 if (child[uid] != NULL) {
803 free(child[uid]);
805 uid ++;
808 if (ec != 0) {
809 isnslog(LOG_DEBUG, "dev_attr_reg", "error code: %d", ec);
812 return (0);
816 * ****************************************************************************
818 * dev_attr_qry:
819 * function which handles the isnsp DEV_ATTR_QRY message.
821 * conn - the argument of the connection.
822 * return - 0: the message requires response.
824 * ****************************************************************************
826 static int
827 dev_attr_qry(
828 conn_arg_t *conn
831 int ec = 0;
833 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
834 isns_tlv_t *source = conn->in_packet.source;
835 isns_tlv_t *key = conn->in_packet.key;
836 uint16_t key_len = conn->in_packet.key_len;
837 isns_tlv_t *op = conn->in_packet.op;
838 uint16_t op_len = conn->in_packet.op_len;
840 uchar_t *iscsi_name;
842 bmp_t *nodes_bmp = NULL;
843 uint32_t num_of_nodes;
844 uint32_t *key_uids = NULL;
845 uint32_t num_of_keys;
846 isns_type_t key_type;
848 uint32_t key_uid;
849 uint32_t op_uid;
851 uint32_t size_of_ops;
852 uint32_t num_of_ops;
853 uint32_t *op_uids = NULL;
854 isns_type_t op_type;
856 isns_tlv_t *tlv;
857 uint16_t tlv_len;
859 isnslog(LOG_DEBUG, "dev_attr_qry", "entered");
861 ec = pdu_reset_rsp(&conn->out_packet.pdu,
862 &conn->out_packet.pl,
863 &conn->out_packet.sz);
864 if (ec != 0) {
865 goto qry_done;
869 * RFC 4171 section 5.7.5.2:
870 * If no Operating Attributes are included in the original query, then
871 * all Operating Attributes SHALL be returned in the response. ???
873 if (op_len == 0) {
874 goto qry_done;
877 iscsi_name = (uchar_t *)&source->attr_value[0];
878 if (is_control_node(iscsi_name) == 0) {
879 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
880 if (ec != 0 || nodes_bmp == NULL) {
881 goto qry_done;
885 size_of_ops = 0;
886 if (key != NULL) {
888 * Return the original message key.
890 ec = rsp_add_tlvs(conn, key, key_len);
891 if (ec != 0) {
892 goto qry_done;
896 * Delimiter
898 ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
899 if (ec != 0) {
900 goto qry_done;
904 * Query objects which match the Key Attributes.
906 ec = get_qry_keys(nodes_bmp, num_of_nodes, &key_type,
907 key, key_len, &key_uids, &num_of_keys);
908 if (ec != 0 || key_uids == NULL) {
909 goto qry_done;
913 * Iterate thru each object identified by the message key.
915 tlv = op;
916 tlv_len = op_len;
917 FOR_EACH_OBJS(key_uids, num_of_keys, key_uid, {
919 * Iterate thru each Operating Attributes.
921 op = tlv;
922 op_len = tlv_len;
923 FOR_EACH_OP(op, op_len, op_type, {
924 if (op_type == 0) {
925 ec = ISNS_RSP_INVALID_QRY;
926 goto qry_done;
928 ec = get_qry_ops(key_uid, key_type,
929 op_type, &op_uids,
930 &num_of_ops, &size_of_ops);
931 if (ec != 0) {
932 goto qry_done;
935 * Iterate thru each object for the Operating
936 * Attributes again.
938 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
939 ec = get_qry_attrs(op_uid, op_type,
940 op, op_len, conn);
941 if (ec != 0) {
942 goto qry_done;
947 } else {
949 * Iterate thru each Operating Attributes.
951 FOR_EACH_OP(op, op_len, op_type, {
952 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
953 op_type, &op_uids,
954 &num_of_ops, &size_of_ops);
955 if (ec != 0) {
956 goto qry_done;
959 * Iterate thru each object for the Operating
960 * Attributes again.
962 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
963 ec = get_qry_attrs(op_uid, op_type,
964 op, op_len, conn);
965 if (ec != 0) {
966 goto qry_done;
972 qry_done:
973 conn->ec = ec;
975 if (ec != 0) {
976 isnslog(LOG_DEBUG, "dev_attr_qry", "error code: %d", ec);
979 free(nodes_bmp);
980 free(key_uids);
981 free(op_uids);
983 return (0);
987 * ****************************************************************************
989 * dev_get_next:
990 * function which handles the isnsp DEV_GET_NEXT message.
992 * conn - the argument of the connection.
993 * return - 0: the message requires response.
995 * ****************************************************************************
997 static int
998 dev_get_next(
999 conn_arg_t *conn
1002 int ec = 0;
1004 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1005 isns_tlv_t *source = conn->in_packet.source;
1006 isns_tlv_t *key = conn->in_packet.key;
1007 uint16_t key_len = conn->in_packet.key_len;
1008 isns_tlv_t *op = conn->in_packet.op;
1009 uint16_t op_len = conn->in_packet.op_len;
1011 uchar_t *iscsi_name;
1013 bmp_t *nodes_bmp = NULL;
1014 uint32_t num_of_nodes;
1016 isns_type_t key_type;
1017 isns_type_t op_type;
1018 uint32_t size_of_obj;
1019 uint32_t num_of_obj;
1020 uint32_t *obj_uids = NULL;
1022 uint32_t uid;
1024 isnslog(LOG_DEBUG, "dev_get_next", "entered");
1026 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1027 &conn->out_packet.pl,
1028 &conn->out_packet.sz);
1029 if (ec != 0) {
1030 goto get_next_done;
1033 iscsi_name = (uchar_t *)&source->attr_value[0];
1034 if (is_control_node(iscsi_name) == 0) {
1035 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
1036 if (nodes_bmp == NULL) {
1037 ec = ISNS_RSP_NO_SUCH_ENTRY;
1039 if (ec != 0) {
1040 goto get_next_done;
1045 * Get Message Key type and validate the Message Key.
1047 key_type = TLV2TYPE(key);
1048 if (key_type == 0) {
1049 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1050 goto get_next_done;
1052 ec = validate_qry_key(key_type, key, key_len, NULL);
1053 if (ec != 0) {
1054 goto get_next_done;
1057 size_of_obj = 0;
1058 if (op != NULL) {
1060 * Query the objects which match the Operating Attributes.
1062 ec = get_qry_keys(nodes_bmp, num_of_nodes, &op_type,
1063 op, op_len, &obj_uids, &num_of_obj);
1064 if (op_type != key_type) {
1065 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1067 } else {
1069 * Query the objects which match the Message Key type.
1071 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
1072 key_type, &obj_uids, &num_of_obj, &size_of_obj);
1074 if (ec != 0) {
1075 goto get_next_done;
1079 * Get the object which is next to the one indicated by the
1080 * Message Key.
1082 uid = get_next_obj(key, key_len, key_type, obj_uids, num_of_obj);
1083 if (uid == 0) {
1084 ec = ISNS_RSP_NO_SUCH_ENTRY;
1085 goto get_next_done;
1089 * Message Key
1091 if ((ec = get_qry_attrs1(uid, key_type, key, key_len, conn)) != 0) {
1092 goto get_next_done;
1096 * Delimiter
1098 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)) != 0) {
1099 goto get_next_done;
1103 * Operating Attributes
1105 if (op != NULL) {
1106 ec = get_qry_attrs(uid, op_type, op, op_len, conn);
1109 get_next_done:
1110 conn->ec = ec;
1112 if (ec != 0 && ec != ISNS_RSP_NO_SUCH_ENTRY) {
1113 isnslog(LOG_DEBUG, "dev_get_next", "error code: %d", ec);
1116 free(nodes_bmp);
1117 free(obj_uids);
1119 return (0);
1123 * ****************************************************************************
1125 * dev_dereg:
1126 * function which handles the isnsp DEV_DEREG message.
1128 * conn - the argument of the connection.
1129 * return - 0: the message requires response.
1131 * ****************************************************************************
1133 static int
1134 dev_dereg(
1135 conn_arg_t *conn
1138 int ec = 0;
1140 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1141 isns_tlv_t *source = conn->in_packet.source;
1142 /* isns_tlv_t *key = conn->in_packet.key; */
1143 /* uint16_t key_len = conn->in_packet.key_len; */
1144 isns_tlv_t *op = conn->in_packet.op;
1145 uint16_t op_len = conn->in_packet.op_len;
1147 uchar_t *iscsi_name;
1148 int ctrl;
1149 uint32_t puid;
1151 lookup_ctrl_t lc;
1152 uint8_t *value;
1154 isnslog(LOG_DEBUG, "dev_dereg", "entered");
1156 iscsi_name = (uchar_t *)&source->attr_value[0];
1157 ctrl = is_control_node(iscsi_name);
1158 if (ctrl == 0) {
1159 puid = is_parent_there(iscsi_name);
1162 while (op_len > 8 && ec == 0) {
1163 lc.curr_uid = 0;
1164 value = &op->attr_value[0];
1165 switch (op->attr_id) {
1166 case ISNS_EID_ATTR_ID:
1167 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
1168 lc.op[0] = OP_STRING;
1169 lc.data[0].ptr = (uchar_t *)value;
1170 lc.op[1] = 0;
1171 lc.type = OBJ_ENTITY;
1172 break;
1173 case ISNS_ISCSI_NAME_ATTR_ID:
1174 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
1175 lc.op[0] = OP_STRING;
1176 lc.data[0].ptr = (uchar_t *)value;
1177 lc.op[1] = 0;
1178 lc.type = OBJ_ISCSI;
1179 break;
1180 case ISNS_ISCSI_NODE_INDEX_ATTR_ID:
1181 lc.id[0] = ATTR_INDEX_ISCSI(
1182 ISNS_ISCSI_NODE_INDEX_ATTR_ID);
1183 lc.op[0] = OP_INTEGER;
1184 lc.data[0].ui = ntohl(*(uint32_t *)value);
1185 lc.op[1] = 0;
1186 lc.type = OBJ_ISCSI;
1187 break;
1188 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1189 lc.id[0] = ATTR_INDEX_PORTAL(
1190 ISNS_PORTAL_IP_ADDR_ATTR_ID);
1191 lc.op[0] = OP_MEMORY_IP6;
1192 lc.data[0].ip = (in6_addr_t *)value;
1193 NEXT_TLV(op, op_len);
1194 if (op_len > 8 &&
1195 op->attr_id == ISNS_PORTAL_PORT_ATTR_ID) {
1196 value = &op->attr_value[0];
1197 lc.id[1] = ATTR_INDEX_PORTAL(
1198 ISNS_PORTAL_PORT_ATTR_ID);
1199 lc.op[1] = OP_INTEGER;
1200 lc.data[1].ui = ntohl(*(uint32_t *)value);
1201 lc.op[2] = 0;
1202 lc.type = OBJ_PORTAL;
1203 } else {
1204 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1206 break;
1207 case ISNS_PORTAL_INDEX_ATTR_ID:
1208 lc.id[0] = ATTR_INDEX_PORTAL(
1209 ISNS_PORTAL_INDEX_ATTR_ID);
1210 lc.op[0] = OP_INTEGER;
1211 lc.data[0].ui = ntohl(*(uint32_t *)value);
1212 lc.op[1] = 0;
1213 lc.type = OBJ_PORTAL;
1214 break;
1215 default:
1216 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1217 break;
1219 if (ec == 0 &&
1220 (ec = dereg_object(&lc, 0)) == 0) {
1221 #ifndef SKIP_SRC_AUTH
1222 if (ctrl == 0 &&
1223 lc.curr_uid != 0 &&
1224 puid != lc.curr_uid) {
1225 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1226 } else {
1227 #endif
1228 NEXT_TLV(op, op_len);
1233 conn->ec = ec;
1235 if (ec != 0) {
1236 isnslog(LOG_DEBUG, "dev_dereg", "error code: %d", ec);
1239 return (0);
1243 * ****************************************************************************
1245 * scn_reg:
1246 * function which handles the isnsp SCN_REG message.
1248 * conn - the argument of the connection.
1249 * return - 0: the message requires response.
1251 * ****************************************************************************
1253 static int
1254 scn_reg(
1255 conn_arg_t *conn
1258 int ec = 0;
1260 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1261 /* isns_tlv_t *source = conn->in_packet.source; */
1262 isns_tlv_t *key = conn->in_packet.key;
1263 uint16_t key_len = conn->in_packet.key_len;
1264 isns_tlv_t *op = conn->in_packet.op;
1265 uint16_t op_len = conn->in_packet.op_len;
1267 /* uchar_t *src; */
1268 uchar_t *node_name;
1269 uint32_t nlen;
1270 uint32_t scn;
1272 isnslog(LOG_DEBUG, "scn_reg", "entered");
1274 /* src = (uchar_t *)&source->attr_value[0]; */
1276 if (op == NULL ||
1277 op->attr_id != ISNS_ISCSI_SCN_BITMAP_ATTR_ID ||
1278 op_len != 12 ||
1279 key == NULL ||
1280 key->attr_id != ISNS_ISCSI_NAME_ATTR_ID ||
1281 key_len != 8 + key->attr_len) {
1282 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1283 goto scn_reg_done;
1286 node_name = (uchar_t *)&key->attr_value[0];
1287 nlen = key->attr_len;
1288 scn = ntohl(*(uint32_t *)&op->attr_value[0]);
1290 ec = add_scn_entry(node_name, nlen, scn);
1292 scn_reg_done:
1293 conn->ec = ec;
1295 if (ec != 0) {
1296 isnslog(LOG_DEBUG, "scn_reg", "error code: %d", ec);
1299 return (0);
1303 * ****************************************************************************
1305 * scn_dereg:
1306 * function which handles the isnsp SCN_DEREG message.
1308 * conn - the argument of the connection.
1309 * return - 0: the message requires response.
1311 * ****************************************************************************
1313 static int
1314 scn_dereg(
1315 conn_arg_t *conn
1318 int ec = 0;
1320 isns_tlv_t *key = conn->in_packet.key;
1321 uint16_t key_len = conn->in_packet.key_len;
1323 uchar_t *node_name;
1325 isnslog(LOG_DEBUG, "scn_dereg", "entered");
1327 if (key != NULL &&
1328 key->attr_len != 0 &&
1329 key_len == 8 + key->attr_len &&
1330 key->attr_id == ISNS_ISCSI_NAME_ATTR_ID) {
1331 node_name = (uchar_t *)&key->attr_value[0];
1332 ec = remove_scn_entry(node_name);
1333 } else {
1334 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1337 conn->ec = ec;
1339 if (ec != 0) {
1340 isnslog(LOG_DEBUG, "scn_dereg", "error code: %d", ec);
1343 return (0);
1347 * ****************************************************************************
1349 * setup_ddid_lcp:
1350 * setup the lookup control data for looking up the DD object
1351 * by using the dd_id attribute.
1353 * lcp - pointer to the lookup control data.
1354 * dd_id- the unique ID of the DD object.
1355 * return - the pointer to the lcp.
1357 * ****************************************************************************
1359 #ifndef DEBUG
1360 static
1361 #endif
1362 lookup_ctrl_t *
1363 setup_ddid_lcp(
1364 lookup_ctrl_t *lcp,
1365 uint32_t dd_id
1368 lcp->curr_uid = 0;
1369 lcp->type = OBJ_DD;
1370 lcp->id[0] = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID);
1371 lcp->op[0] = OP_INTEGER;
1372 lcp->data[0].ui = dd_id;
1373 lcp->op[1] = 0;
1375 return (lcp);
1379 * ****************************************************************************
1381 * setup_ddsid_lcp:
1382 * setup the lookup control data for looking up the DD-set object
1383 * by using the dds_id attribute.
1385 * lcp - pointer to the lookup control data.
1386 * dds_id - the unique ID of the DD-set object.
1387 * return - the pointer to the lcp.
1389 * ****************************************************************************
1391 #ifndef DEBUG
1392 static
1393 #endif
1394 lookup_ctrl_t *
1395 setup_ddsid_lcp(
1396 lookup_ctrl_t *lcp,
1397 uint32_t dds_id
1400 lcp->curr_uid = 0;
1401 lcp->type = OBJ_DDS;
1402 lcp->id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID);
1403 lcp->op[0] = OP_INTEGER;
1404 lcp->data[0].ui = dds_id;
1405 lcp->op[1] = 0;
1407 return (lcp);
1411 * ****************************************************************************
1413 * dd_reg:
1414 * function which handles the isnsp DD_REG message.
1416 * conn - the argument of the connection.
1417 * return - 0: the message requires response.
1419 * ****************************************************************************
1421 static int
1422 dd_reg(
1423 conn_arg_t *conn
1426 int ec = 0;
1428 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1429 isns_tlv_t *source = conn->in_packet.source;
1430 isns_tlv_t *key = conn->in_packet.key;
1431 uint16_t key_len = conn->in_packet.key_len;
1432 isns_tlv_t *op = conn->in_packet.op;
1433 uint16_t op_len = conn->in_packet.op_len;
1435 uint32_t dd_id = 0;
1436 uint8_t *value;
1438 isns_obj_t *dd = NULL;
1440 uchar_t *iscsi_name;
1442 lookup_ctrl_t lc;
1443 isns_assoc_iscsi_t aiscsi;
1444 isns_obj_t *assoc;
1445 isns_attr_t *attr;
1447 uint32_t features;
1449 isnslog(LOG_DEBUG, "dd_reg", "entered");
1451 iscsi_name = (uchar_t *)&source->attr_value[0];
1452 if (is_control_node(iscsi_name) == 0) {
1453 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1454 goto dd_reg_done;
1457 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1458 &conn->out_packet.pl,
1459 &conn->out_packet.sz);
1460 if (ec != 0) {
1461 goto dd_reg_done;
1464 if (op == NULL ||
1465 (key != NULL &&
1466 (key_len != 12 ||
1467 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1468 key->attr_len != 4 ||
1469 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1470 is_obj_there(setup_ddid_lcp(&lc, dd_id)) == 0))) {
1471 ec = ISNS_RSP_INVALID_REGIS;
1472 goto dd_reg_done;
1475 /* message key */
1476 if (key != NULL &&
1477 (ec = rsp_add_tlv(conn, ISNS_DD_ID_ATTR_ID, 4,
1478 (void *)dd_id, 0)) != 0) {
1479 goto dd_reg_done;
1482 /* delimiter */
1483 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1484 NULL, 0)) != 0) {
1485 goto dd_reg_done;
1488 /* A DDReg message with no Message Key SHALL result in the */
1489 /* attempted creation of a new Discovery Domain (DD). */
1490 if (dd_id == 0) {
1491 ec = create_dd_object(op, op_len, &dd);
1492 if (ec == 0) {
1493 ec = register_object(dd, &dd_id, NULL);
1494 if (ec == ERR_NAME_IN_USE) {
1495 ec = ISNS_RSP_INVALID_REGIS;
1497 if (ec != 0) {
1498 free_object(dd);
1499 goto dd_reg_done;
1501 } else {
1502 goto dd_reg_done;
1506 /* add the newly created dd to the response */
1507 if (dd != NULL) {
1508 ec = rsp_add_op(conn, dd);
1511 aiscsi.type = OBJ_ASSOC_ISCSI;
1512 aiscsi.puid = dd_id;
1514 while (op_len > 8 && ec == 0) {
1515 value = &op->attr_value[0];
1516 switch (op->attr_id) {
1517 case ISNS_DD_ID_ATTR_ID:
1518 /* if the DD_ID is included in both the Message Key */
1519 /* and Operating Attributes, then the DD_ID value */
1520 /* in the Message Key MUST be the same as the DD_ID */
1521 /* value in the Operating Attributes. */
1522 if (dd == NULL) {
1523 if (op->attr_len != 4 ||
1524 dd_id != ntohl(*(uint32_t *)value)) {
1525 ec = ISNS_RSP_INVALID_REGIS;
1526 } else {
1527 ec = rsp_add_tlv(conn,
1528 ISNS_DD_ID_ATTR_ID, 4,
1529 (void *)dd_id, 0);
1532 break;
1533 case ISNS_DD_NAME_ATTR_ID:
1534 /* It is going to modify the DD Symbolic Name. */
1535 if (dd == NULL) {
1536 if (op->attr_len > 0 && op->attr_len <= 256) {
1537 ec = update_dd_name(
1538 dd_id,
1539 op->attr_len,
1540 (uchar_t *)value);
1541 if (ec == ERR_NAME_IN_USE) {
1542 ec = ISNS_RSP_INVALID_REGIS;
1544 } else {
1545 ec = ISNS_RSP_INVALID_REGIS;
1547 if (ec == 0) {
1548 ec = rsp_add_tlv(conn,
1549 ISNS_DD_NAME_ATTR_ID,
1550 op->attr_len, (void *)value, 1);
1553 break;
1554 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1555 if (op->attr_len == 4) {
1556 /* zero the association object */
1557 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1558 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1559 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1560 attr->len = 4;
1561 attr->value.ui = ntohl(*(uint32_t *)value);
1562 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1563 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1564 attr->tag = 0; /* clear it */
1565 attr->value.ptr = NULL; /* clear it */
1566 assoc = (isns_obj_t *)&aiscsi;
1567 if ((ec = add_dd_member(assoc)) ==
1568 ERR_ALREADY_ASSOCIATED) {
1569 ec = 0;
1571 if (attr->value.ptr != NULL) {
1572 free(attr->value.ptr);
1574 } else {
1575 ec = ISNS_RSP_INVALID_REGIS;
1577 if (ec == 0) {
1578 ec = rsp_add_tlv(conn,
1579 ISNS_DD_ISCSI_INDEX_ATTR_ID,
1580 4, (void *)attr->value.ui, 0);
1582 break;
1583 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1584 if (op->attr_len > 0 && op->attr_len <= 224) {
1585 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1586 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1587 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1588 attr->len = op->attr_len;
1589 attr->value.ptr = (uchar_t *)value;
1590 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1591 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1592 attr->tag = 0; /* clear it */
1593 assoc = (isns_obj_t *)&aiscsi;
1594 if ((ec = add_dd_member(assoc)) ==
1595 ERR_ALREADY_ASSOCIATED) {
1596 ec = 0;
1598 } else {
1599 ec = ISNS_RSP_INVALID_REGIS;
1601 if (ec == 0) {
1602 ec = rsp_add_tlv(conn,
1603 ISNS_DD_ISCSI_NAME_ATTR_ID,
1604 op->attr_len, (void *)value, 1);
1606 break;
1607 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1608 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1609 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1610 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1611 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1612 break;
1613 case ISNS_DD_FEATURES_ATTR_ID:
1614 /* It is going to modify the DD Symbolic Name. */
1615 if (dd == NULL) {
1616 if (op->attr_len == 4) {
1617 features = ntohl(*(uint32_t *)value);
1618 ec = update_dd_features(
1619 dd_id, features);
1620 } else {
1621 ec = ISNS_RSP_INVALID_REGIS;
1623 if (ec == 0) {
1624 ec = rsp_add_tlv(conn,
1625 ISNS_DD_FEATURES_ATTR_ID,
1626 4, (void *)features, 0);
1629 break;
1630 default:
1631 ec = ISNS_RSP_INVALID_REGIS;
1632 break;
1635 NEXT_TLV(op, op_len);
1638 dd_reg_done:
1639 conn->ec = ec;
1641 if (ec != 0) {
1642 isnslog(LOG_DEBUG, "dd_reg", "error code: %d", ec);
1645 return (0);
1649 * ****************************************************************************
1651 * dds_reg:
1652 * function which handles the isnsp DDS_REG message.
1654 * conn - the argument of the connection.
1655 * return - 0: the message requires response.
1657 * ****************************************************************************
1659 static int
1660 dds_reg(
1661 conn_arg_t *conn
1664 int ec = 0;
1666 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1667 isns_tlv_t *source = conn->in_packet.source;
1668 isns_tlv_t *key = conn->in_packet.key;
1669 uint16_t key_len = conn->in_packet.key_len;
1670 isns_tlv_t *op = conn->in_packet.op;
1671 uint16_t op_len = conn->in_packet.op_len;
1673 uint32_t dds_id = 0;
1674 uint8_t *value;
1676 isns_obj_t *dds = NULL;
1678 uchar_t *iscsi_name;
1680 lookup_ctrl_t lc;
1681 isns_assoc_dd_t add;
1682 isns_obj_t *assoc;
1683 isns_attr_t *attr;
1685 uint32_t code;
1687 isnslog(LOG_DEBUG, "dds_reg", "entered");
1689 iscsi_name = (uchar_t *)&source->attr_value[0];
1690 if (is_control_node(iscsi_name) == 0) {
1691 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1692 goto dds_reg_done;
1695 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1696 &conn->out_packet.pl,
1697 &conn->out_packet.sz);
1698 if (ec != 0) {
1699 goto dds_reg_done;
1702 if (op == NULL ||
1703 (key != NULL &&
1704 (key_len != 12 ||
1705 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
1706 key->attr_len != 4 ||
1707 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1708 is_obj_there(setup_ddsid_lcp(&lc, dds_id)) == 0))) {
1709 ec = ISNS_RSP_INVALID_REGIS;
1710 goto dds_reg_done;
1713 /* message key */
1714 if (key != NULL &&
1715 (ec = rsp_add_tlv(conn, ISNS_DD_SET_ID_ATTR_ID, 4,
1716 (void *)dds_id, 0)) != 0) {
1717 goto dds_reg_done;
1720 /* delimiter */
1721 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1722 NULL, 0)) != 0) {
1723 goto dds_reg_done;
1726 /* A DDSReg message with no Message Key SHALL result in the */
1727 /* attempted creation of a new Discovery Domain (DD). */
1728 if (dds_id == 0) {
1729 ec = create_dds_object(op, op_len, &dds);
1730 if (ec == 0) {
1731 ec = register_object(dds, &dds_id, NULL);
1732 if (ec == ERR_NAME_IN_USE) {
1733 ec = ISNS_RSP_INVALID_REGIS;
1735 if (ec != 0) {
1736 free_object(dds);
1737 goto dds_reg_done;
1739 } else {
1740 goto dds_reg_done;
1744 /* add the newly created dd to the response */
1745 if (dds != NULL) {
1746 ec = rsp_add_op(conn, dds);
1749 add.type = OBJ_ASSOC_DD;
1750 add.puid = dds_id;
1752 while (op_len > 8 && ec == 0) {
1753 value = &op->attr_value[0];
1754 switch (op->attr_id) {
1755 case ISNS_DD_SET_ID_ATTR_ID:
1756 /* if the DDS_ID is included in both the Message Key */
1757 /* and Operating Attributes, then the DDS_ID value */
1758 /* in the Message Key MUST be the same as the DDS_ID */
1759 /* value in the Operating Attributes. */
1760 if (dds == NULL) {
1761 if (op->attr_len != 4 ||
1762 dds_id != ntohl(*(uint32_t *)value)) {
1763 ec = ISNS_RSP_INVALID_REGIS;
1764 } else {
1765 ec = rsp_add_tlv(conn,
1766 ISNS_DD_SET_ID_ATTR_ID,
1767 4, (void *)dds_id, 0);
1770 break;
1771 case ISNS_DD_SET_NAME_ATTR_ID:
1772 /* It is going to modify the DD Symbolic Name. */
1773 if (dds == NULL) {
1774 if (op->attr_len > 0 && op->attr_len <= 256) {
1775 ec = update_dds_name(
1776 dds_id,
1777 op->attr_len,
1778 (uchar_t *)value);
1779 if (ec == ERR_NAME_IN_USE) {
1780 ec = ISNS_RSP_INVALID_REGIS;
1782 } else {
1783 ec = ISNS_RSP_INVALID_REGIS;
1785 if (ec == 0) {
1786 ec = rsp_add_tlv(conn,
1787 ISNS_DD_SET_NAME_ATTR_ID,
1788 op->attr_len, (void *)value, 1);
1791 break;
1792 case ISNS_DD_SET_STATUS_ATTR_ID:
1793 /* It is going to modify the DD Symbolic Name. */
1794 if (dds == NULL) {
1795 if (op->attr_len == 4) {
1796 code = ntohl(*(uint32_t *)value);
1797 ec = update_dds_status(
1798 dds_id, code);
1799 } else {
1800 ec = ISNS_RSP_INVALID_REGIS;
1802 if (ec == 0) {
1803 ec = rsp_add_tlv(conn,
1804 ISNS_DD_SET_STATUS_ATTR_ID,
1805 4, (void *)code, 0);
1808 break;
1809 case ISNS_DD_ID_ATTR_ID:
1810 if (op->attr_len == 4) {
1811 /* zero the association object */
1812 attr = &add.attrs[ATTR_INDEX_ASSOC_DD(
1813 ISNS_DD_ID_ATTR_ID)];
1814 attr->tag = ISNS_DD_ID_ATTR_ID;
1815 attr->len = 4;
1816 attr->value.ui = ntohl(*(uint32_t *)value);
1817 assoc = (isns_obj_t *)&add;
1818 if ((ec = add_dds_member(assoc)) ==
1819 ERR_ALREADY_ASSOCIATED) {
1820 ec = 0;
1822 } else {
1823 ec = ISNS_RSP_INVALID_REGIS;
1825 if (ec == 0) {
1826 ec = rsp_add_tlv(conn,
1827 ISNS_DD_ID_ATTR_ID, 4,
1828 (void *)attr->value.ui, 0);
1830 break;
1831 default:
1832 ec = ISNS_RSP_INVALID_REGIS;
1833 break;
1836 NEXT_TLV(op, op_len);
1839 dds_reg_done:
1840 conn->ec = ec;
1842 if (ec != 0) {
1843 isnslog(LOG_DEBUG, "dds_reg", "error code: %d", ec);
1846 return (0);
1850 * ****************************************************************************
1852 * dd_dereg:
1853 * function which handles the isnsp DD_DEREG message.
1855 * conn - the argument of the connection.
1856 * return - 0: the message requires response.
1858 * ****************************************************************************
1860 static int
1861 dd_dereg(
1862 conn_arg_t *conn
1865 int ec = 0;
1867 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1868 isns_tlv_t *source = conn->in_packet.source;
1869 isns_tlv_t *key = conn->in_packet.key;
1870 uint16_t key_len = conn->in_packet.key_len;
1871 isns_tlv_t *op = conn->in_packet.op;
1872 uint16_t op_len = conn->in_packet.op_len;
1874 uint32_t dd_id;
1875 uint8_t *value;
1877 uchar_t *iscsi_name;
1879 isns_assoc_iscsi_t aiscsi;
1880 isns_obj_t *assoc;
1881 isns_attr_t *attr;
1883 isnslog(LOG_DEBUG, "dd_dereg", "entered");
1885 iscsi_name = (uchar_t *)&source->attr_value[0];
1886 if (is_control_node(iscsi_name) == 0) {
1887 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1888 goto dd_dereg_done;
1891 if (key == NULL ||
1892 key_len != 12 ||
1893 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1894 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
1895 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1896 goto dd_dereg_done;
1899 if (op == NULL) {
1900 ec = remove_dd_object(dd_id);
1901 } else {
1902 aiscsi.type = OBJ_ASSOC_ISCSI;
1903 aiscsi.puid = dd_id;
1905 while (op_len > 8 && ec == 0) {
1906 value = &op->attr_value[0];
1907 switch (op->attr_id) {
1908 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1909 /* zero the association object */
1910 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1911 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1912 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1913 attr->len = 4;
1914 attr->value.ui = ntohl(*(uint32_t *)value);
1915 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1916 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1917 attr->tag = 0; /* clear it */
1918 attr->value.ptr = NULL; /* clear it */
1919 assoc = (isns_obj_t *)&aiscsi;
1920 if ((ec = remove_dd_member(assoc)) ==
1921 ERR_NO_SUCH_ASSOCIATION) {
1922 ec = 0;
1924 if (attr->value.ptr != NULL) {
1925 free(attr->value.ptr);
1927 break;
1928 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1929 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1930 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1931 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1932 attr->len = op->attr_len;
1933 attr->value.ptr = (uchar_t *)value;
1934 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1935 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1936 attr->tag = 0; /* clear it */
1937 assoc = (isns_obj_t *)&aiscsi;
1938 if ((ec = remove_dd_member(assoc)) ==
1939 ERR_NO_SUCH_ASSOCIATION) {
1940 ec = 0;
1942 break;
1943 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1944 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1945 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1946 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1947 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1948 break;
1949 default:
1950 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1951 break;
1954 NEXT_TLV(op, op_len);
1958 dd_dereg_done:
1959 conn->ec = ec;
1961 if (ec != 0) {
1962 isnslog(LOG_DEBUG, "dd_dereg", "error code: %d", ec);
1965 return (0);
1969 * ****************************************************************************
1971 * dds_dereg:
1972 * function which handles the isnsp DDS_DEREG message.
1974 * conn - the argument of the connection.
1975 * return - 0: the message requires response.
1977 * ****************************************************************************
1979 static int
1980 dds_dereg(
1981 conn_arg_t *conn
1984 int ec = 0;
1986 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1987 isns_tlv_t *source = conn->in_packet.source;
1988 isns_tlv_t *key = conn->in_packet.key;
1989 uint16_t key_len = conn->in_packet.key_len;
1990 isns_tlv_t *op = conn->in_packet.op;
1991 uint16_t op_len = conn->in_packet.op_len;
1993 uint32_t dds_id;
1994 uint32_t uid;
1995 uint8_t *value;
1997 uchar_t *iscsi_name;
1999 isnslog(LOG_DEBUG, "dds_dereg", "entered");
2001 iscsi_name = (uchar_t *)&source->attr_value[0];
2002 if (is_control_node(iscsi_name) == 0) {
2003 ec = ISNS_RSP_SRC_UNAUTHORIZED;
2004 goto dds_dereg_done;
2007 if (key == NULL ||
2008 key_len != 12 ||
2009 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
2010 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
2011 ec = ISNS_RSP_MSG_FORMAT_ERROR;
2012 goto dds_dereg_done;
2015 if (op == NULL) {
2016 ec = remove_dds_object(dds_id);
2017 } else {
2018 while (op_len > 8 && ec == 0) {
2019 value = &op->attr_value[0];
2020 if (op->attr_id == ISNS_DD_ID_ATTR_ID) {
2021 uid = ntohl(*(uint32_t *)value);
2022 if ((ec = remove_dds_member(dds_id, uid)) ==
2023 ERR_NO_SUCH_ASSOCIATION) {
2024 ec = 0;
2026 } else {
2027 ec = ISNS_RSP_MSG_FORMAT_ERROR;
2030 NEXT_TLV(op, op_len);
2034 dds_dereg_done:
2035 conn->ec = ec;
2037 if (ec != 0) {
2038 isnslog(LOG_DEBUG, "dds_dereg", "error code: %d", ec);
2041 return (0);
2045 * ****************************************************************************
2047 * msg_error:
2048 * function which handles any unknown isnsp messages or the
2049 * messages which are not supported.
2051 * conn - the argument of the connection.
2052 * return - 0: the message requires response.
2054 * ****************************************************************************
2056 static int
2057 msg_error(
2058 /* LINTED E_FUNC_ARG_UNUSED */
2059 conn_arg_t *conn
2062 return (0);
2066 * ****************************************************************************
2068 * isns_response_ec:
2069 * send the response message to the client with error code.
2071 * so - the socket descriptor.
2072 * pdu - the received pdu.
2073 * ec - the error code which is being responsed.
2074 * return - status of the sending operation.
2076 * ****************************************************************************
2078 static int
2079 isns_response_ec(
2080 int so,
2081 isns_pdu_t *pdu,
2082 int ec
2085 int status;
2087 uint8_t buff[sizeof (isns_pdu_t) + 8];
2089 isns_pdu_t *rsp = (isns_pdu_t *)&buff;
2090 isns_resp_t *resp = (isns_resp_t *)rsp->payload;
2091 size_t pl = 4;
2093 rsp->version = htons((uint16_t)ISNSP_VERSION);
2094 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2095 rsp->xid = htons(pdu->xid);
2096 resp->status = htonl(ec);
2098 status = isns_send_pdu(so, rsp, pl);
2100 return (status);
2104 * ****************************************************************************
2106 * isns_response:
2107 * send the response message to the client.
2109 * conn - the argument of the connection.
2110 * return - status of the sending operation.
2112 * ****************************************************************************
2115 isns_response(
2116 conn_arg_t *conn
2119 int status;
2121 int so = conn->so;
2122 int ec = conn->ec;
2123 isns_pdu_t *pdu = conn->in_packet.pdu;
2124 isns_pdu_t *rsp = conn->out_packet.pdu;
2125 size_t pl = conn->out_packet.pl;
2127 if (rsp != NULL) {
2128 rsp->version = htons((uint16_t)ISNSP_VERSION);
2129 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2130 rsp->xid = htons(pdu->xid);
2131 (void) pdu_update_code(rsp, &pl, ec);
2132 status = isns_send_pdu(so, rsp, pl);
2133 } else {
2134 status = isns_response_ec(so, pdu, ec);
2137 return (status);