1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
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>
33
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"
48
49 /*
50 * extern global variables
51 */
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];
61
62 /* scn message queue */
63 extern msg_queue_t *scn_q;
64
65 /*
66 * extern functions.
67 */
68
69 /*
70 * local variables
71 */
72
73 /*
74 * local functions.
75 */
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 *);
87
88 /*
89 * ****************************************************************************
90 *
91 * packet_get_source:
92 * get the source attributes of the packet.
93 *
94 * conn - the argument of the connection.
95 * return - error code.
96 *
97 * ****************************************************************************
98 */
99 static int
packet_get_source(conn_arg_t * conn)100 packet_get_source(
101 conn_arg_t *conn
102 )
103 {
104 int ec = 0;
105
106 isns_pdu_t *pdu = conn->in_packet.pdu;
107 isns_tlv_t *source = pdu_get_source(pdu);
108
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;
114 }
115
116 if (ec == 0) {
117 conn->in_packet.source = source;
118 }
119
120 return (ec);
121 }
122
123 /*
124 * ****************************************************************************
125 *
126 * packet_get_key:
127 * get the key attributes of the packet.
128 *
129 * conn - the argument of the connection.
130 * return - error code.
131 *
132 * ****************************************************************************
133 */
134 static int
packet_get_key(conn_arg_t * conn)135 packet_get_key(
136 conn_arg_t *conn
137 )
138 {
139 int ec = 0;
140
141 isns_pdu_t *pdu = conn->in_packet.pdu;
142 isns_tlv_t *key;
143 size_t key_len;
144
145 key = pdu_get_key(pdu, &key_len);
146
147 conn->in_packet.key = key;
148 conn->in_packet.key_len = key_len;
149
150 return (ec);
151 }
152
153 /*
154 * ****************************************************************************
155 *
156 * packet_get_operand:
157 * get the operating attributes of the packet.
158 *
159 * conn - the argument of the connection.
160 * return - error code.
161 *
162 * ****************************************************************************
163 */
164 static int
packet_get_operand(conn_arg_t * conn)165 packet_get_operand(
166 conn_arg_t *conn
167 )
168 {
169 int ec = 0;
170
171 isns_pdu_t *pdu = conn->in_packet.pdu;
172 isns_tlv_t *op;
173 size_t op_len;
174
175 op = pdu_get_operand(pdu, &op_len);
176
177 conn->in_packet.op = op;
178 conn->in_packet.op_len = op_len;
179
180 return (ec);
181 }
182
183 /*
184 * ****************************************************************************
185 *
186 * packet_split_verify:
187 * split and verify the packet, get the apporiate locking type and
188 * function handler for the packet.
189 *
190 * conn - the argument of the connection.
191 * return - error code.
192 *
193 * ****************************************************************************
194 */
195 int
packet_split_verify(conn_arg_t * conn)196 packet_split_verify(
197 conn_arg_t *conn
198 )
199 {
200 int ec = 0;
201
202 isns_pdu_t *pdu = conn->in_packet.pdu;
203
204 int (*handler)(conn_arg_t *) = msg_error;
205 int lock = CACHE_NO_ACTION;
206
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;
233 }
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;
241 }
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;
265 }
266 }
267
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));
278 }
279 ISNS_OPERATION_TYPE((uintptr_t)buf, pdu->func_id);
280 }
281
282 conn->lock = lock;
283 conn->handler = handler;
284
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);
292 }
293 }
294 }
295
296 conn->ec = ec;
297
298 return (ec);
299 }
300
301 /*
302 * ****************************************************************************
303 *
304 * setup_key_lcp:
305 * setup the lookup control data for looking up the object
306 * which the key attributes identify.
307 *
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.
313 *
314 * ****************************************************************************
315 */
316 static int
setup_key_lcp(lookup_ctrl_t * lcp,isns_tlv_t * key,uint16_t key_len)317 setup_key_lcp(
318 lookup_ctrl_t *lcp,
319 isns_tlv_t *key,
320 uint16_t key_len
321 )
322 {
323 int ec = 0;
324
325 uint8_t *value = &key->attr_value[0];
326
327 lcp->curr_uid = 0;
328 lcp->op[0] = 0;
329
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;
338 }
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;
349 }
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);
362 }
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;
372 }
373 break;
374 case ISNS_PG_ISCSI_NAME_ATTR_ID:
375 if (key->attr_len < 4) {
376 return (ISNS_RSP_MSG_FORMAT_ERROR);
377 }
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);
386 }
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);
396 }
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;
406 }
407
408 return (ec);
409 }
410
411 /*
412 * ****************************************************************************
413 *
414 * rsp_add_op:
415 * add the operating attributes to the response packet.
416 *
417 * conn - the argument of the connection.
418 * obj - the object which is being added as operating attributes.
419 * return - error code.
420 *
421 * ****************************************************************************
422 */
423 static int
rsp_add_op(conn_arg_t * conn,isns_obj_t * obj)424 rsp_add_op(
425 conn_arg_t *conn,
426 isns_obj_t *obj
427 )
428 {
429 int ec = 0;
430
431 isns_attr_t *attr;
432 int i;
433
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;
437
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);
447 }
448 i ++;
449 }
450
451 conn->out_packet.pdu = rsp;
452 conn->out_packet.pl = pl;
453 conn->out_packet.sz = sz;
454
455 return (ec);
456 }
457
458 /*
459 * ****************************************************************************
460 *
461 * rsp_add_key:
462 * add the key attributes to the response packet.
463 *
464 * conn - the argument of the connection.
465 * entity - the object which is being added as key attributes.
466 * return - error code.
467 *
468 * ****************************************************************************
469 */
470 static int
rsp_add_key(conn_arg_t * conn,isns_obj_t * entity)471 rsp_add_key(
472 conn_arg_t *conn,
473 isns_obj_t *entity
474 )
475 {
476 int ec = 0;
477
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;
483
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;
487
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);
502 }
503 NEXT_TLV(key, key_len);
504 }
505 }
506
507 if (ec == 0) {
508 ec = pdu_add_tlv(&rsp, &pl, &sz,
509 ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
510 }
511
512 conn->out_packet.pdu = rsp;
513 conn->out_packet.pl = pl;
514 conn->out_packet.sz = sz;
515
516 if (ec == 0) {
517 ec = rsp_add_op(conn, entity);
518 }
519
520 return (ec);
521 }
522
523 /*
524 * ****************************************************************************
525 *
526 * rsp_add_tlv:
527 * add one attribute with TLV format to the response packet.
528 *
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.
535 *
536 * ****************************************************************************
537 */
538 static int
rsp_add_tlv(conn_arg_t * conn,uint32_t tag,uint32_t len,void * value,int pflag)539 rsp_add_tlv(
540 conn_arg_t *conn,
541 uint32_t tag,
542 uint32_t len,
543 void *value,
544 int pflag
545 )
546 {
547 int ec = 0;
548
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;
552
553 ec = pdu_add_tlv(&rsp, &pl, &sz, tag, len, value, pflag);
554
555 conn->out_packet.pdu = rsp;
556 conn->out_packet.pl = pl;
557 conn->out_packet.sz = sz;
558
559 return (ec);
560 }
561
562 /*
563 * ****************************************************************************
564 *
565 * rsp_add_tlvs:
566 * add attributes with TLV format to the response packet.
567 *
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.
572 *
573 * ****************************************************************************
574 */
575 static int
rsp_add_tlvs(conn_arg_t * conn,isns_tlv_t * tlv,uint32_t tlv_len)576 rsp_add_tlvs(
577 conn_arg_t *conn,
578 isns_tlv_t *tlv,
579 uint32_t tlv_len
580 )
581 {
582 int ec = 0;
583
584 uint32_t tag;
585 uint32_t len;
586 void *value;
587
588 while (tlv_len >= 8 &&
589 ec == 0) {
590 tag = tlv->attr_id;
591 len = tlv->attr_len;
592 value = (void *)tlv->attr_value;
593
594 ec = rsp_add_tlv(conn, tag, len, value, 1);
595
596 NEXT_TLV(tlv, tlv_len);
597 }
598
599 return (ec);
600 }
601
602 /*
603 * ****************************************************************************
604 *
605 * dev_attr_reg:
606 * function which handles the isnsp DEV_ATTR_REG message.
607 *
608 * conn - the argument of the connection.
609 * return - 0: the message requires response.
610 *
611 * ****************************************************************************
612 */
613 static int
dev_attr_reg(conn_arg_t * conn)614 dev_attr_reg(
615 conn_arg_t *conn
616 )
617 {
618 int ec = 0;
619
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;
626
627 boolean_t replace =
628 ((pdu->flags & ISNS_FLAG_REPLACE_REG) == ISNS_FLAG_REPLACE_REG);
629
630 lookup_ctrl_t lc, lc_key;
631 uchar_t *iscsi_name;
632 int ctrl;
633
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;
640
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 };
645
646 void const **vpp = NULL;
647 int i = 0;
648
649 isnslog(LOG_DEBUG, "dev_attr_reg", "entered (replace: %d)", replace);
650
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;
656 }
657
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;
672 }
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);
690 }
691 }
692 }
693 }
694 if (ec != 0) {
695 goto reg_done;
696 }
697
698 /* register the network entity object */
699 ec = reg_get_entity(&ety, &op, &op_len);
700 if (ec != 0) {
701 goto reg_done;
702 }
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;
712 }
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;
719 }
720 if (ec == 0 && ety_update == 0) {
721 /* newly registered, reset the pointer */
722 ety = NULL;
723 }
724
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;
752 }
753 /* it was for updating an existing object */
754 free_one_object(obj);
755 }
756 } else {
757 /* failed registering it */
758 free_one_object(obj);
759 }
760 }
761
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);
766 }
767 if (ec != 0) {
768 goto reg_done;
769 }
770
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;
776 }
777 i ++;
778 }
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
791 }
792 if (ec != 0) {
793 goto reg_done;
794 }
795 /* add esi entry */
796 if (ety_update != 0) {
797 (void) esi_remove(puid);
798 }
799 ec = esi_add(puid, eid_attr->value.ptr, eid_attr->len);
800
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]);
808 }
809 uid ++;
810 }
811
812 if (ec != 0) {
813 isnslog(LOG_DEBUG, "dev_attr_reg", "error code: %d", ec);
814 }
815
816 return (0);
817 }
818
819 /*
820 * ****************************************************************************
821 *
822 * dev_attr_qry:
823 * function which handles the isnsp DEV_ATTR_QRY message.
824 *
825 * conn - the argument of the connection.
826 * return - 0: the message requires response.
827 *
828 * ****************************************************************************
829 */
830 static int
831 dev_attr_qry(
832 conn_arg_t *conn
833 )
834 {
835 int ec = 0;
836
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;
843
844 uchar_t *iscsi_name;
845
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;
851
852 uint32_t key_uid;
853 uint32_t op_uid;
854
855 uint32_t size_of_ops;
856 uint32_t num_of_ops;
857 uint32_t *op_uids = NULL;
858 isns_type_t op_type;
859
860 isns_tlv_t *tlv;
861 uint16_t tlv_len;
862
863 isnslog(LOG_DEBUG, "dev_attr_qry", "entered");
864
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;
870 }
871
872 /*
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. ???
876 */
877 if (op_len == 0) {
878 goto qry_done;
879 }
880
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;
886 }
887 }
888
889 size_of_ops = 0;
890 if (key != NULL) {
891 /*
892 * Return the original message key.
893 */
894 ec = rsp_add_tlvs(conn, key, key_len);
895 if (ec != 0) {
896 goto qry_done;
897 }
898
899 /*
900 * Delimiter
901 */
902 ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
903 if (ec != 0) {
904 goto qry_done;
905 }
906
907 /*
908 * Query objects which match the Key Attributes.
909 */
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;
914 }
915
916 /*
917 * Iterate thru each object identified by the message key.
918 */
919 tlv = op;
920 tlv_len = op_len;
921 FOR_EACH_OBJS(key_uids, num_of_keys, key_uid, {
922 /*
923 * Iterate thru each Operating Attributes.
924 */
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;
931 }
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;
937 }
938 /*
939 * Iterate thru each object for the Operating
940 * Attributes again.
941 */
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;
947 }
948 });
949 });
950 });
951 } else {
952 /*
953 * Iterate thru each Operating Attributes.
954 */
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;
961 }
962 /*
963 * Iterate thru each object for the Operating
964 * Attributes again.
965 */
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;
971 }
972 });
973 });
974 }
975
976 qry_done:
977 conn->ec = ec;
978
979 if (ec != 0) {
980 isnslog(LOG_DEBUG, "dev_attr_qry", "error code: %d", ec);
981 }
982
983 free(nodes_bmp);
984 free(key_uids);
985 free(op_uids);
986
987 return (0);
988 }
989
990 /*
991 * ****************************************************************************
992 *
993 * dev_get_next:
994 * function which handles the isnsp DEV_GET_NEXT message.
995 *
996 * conn - the argument of the connection.
997 * return - 0: the message requires response.
998 *
999 * ****************************************************************************
1000 */
1001 static int
1002 dev_get_next(
1003 conn_arg_t *conn
1004 )
1005 {
1006 int ec = 0;
1007
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;
1014
1015 uchar_t *iscsi_name;
1016
1017 bmp_t *nodes_bmp = NULL;
1018 uint32_t num_of_nodes;
1019
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;
1025
1026 uint32_t uid;
1027
1028 isnslog(LOG_DEBUG, "dev_get_next", "entered");
1029
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;
1035 }
1036
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;
1042 }
1043 if (ec != 0) {
1044 goto get_next_done;
1045 }
1046 }
1047
1048 /*
1049 * Get Message Key type and validate the Message Key.
1050 */
1051 key_type = TLV2TYPE(key);
1052 if (key_type == 0) {
1053 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1054 goto get_next_done;
1055 }
1056 ec = validate_qry_key(key_type, key, key_len, NULL);
1057 if (ec != 0) {
1058 goto get_next_done;
1059 }
1060
1061 size_of_obj = 0;
1062 if (op != NULL) {
1063 /*
1064 * Query the objects which match the Operating Attributes.
1065 */
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;
1070 }
1071 } else {
1072 /*
1073 * Query the objects which match the Message Key type.
1074 */
1075 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
1076 key_type, &obj_uids, &num_of_obj, &size_of_obj);
1077 }
1078 if (ec != 0) {
1079 goto get_next_done;
1080 }
1081
1082 /*
1083 * Get the object which is next to the one indicated by the
1084 * Message Key.
1085 */
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;
1090 }
1091
1092 /*
1093 * Message Key
1094 */
1095 if ((ec = get_qry_attrs1(uid, key_type, key, key_len, conn)) != 0) {
1096 goto get_next_done;
1097 }
1098
1099 /*
1100 * Delimiter
1101 */
1102 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)) != 0) {
1103 goto get_next_done;
1104 }
1105
1106 /*
1107 * Operating Attributes
1108 */
1109 if (op != NULL) {
1110 ec = get_qry_attrs(uid, op_type, op, op_len, conn);
1111 }
1112
1113 get_next_done:
1114 conn->ec = ec;
1115
1116 if (ec != 0 && ec != ISNS_RSP_NO_SUCH_ENTRY) {
1117 isnslog(LOG_DEBUG, "dev_get_next", "error code: %d", ec);
1118 }
1119
1120 free(nodes_bmp);
1121 free(obj_uids);
1122
1123 return (0);
1124 }
1125
1126 /*
1127 * ****************************************************************************
1128 *
1129 * dev_dereg:
1130 * function which handles the isnsp DEV_DEREG message.
1131 *
1132 * conn - the argument of the connection.
1133 * return - 0: the message requires response.
1134 *
1135 * ****************************************************************************
1136 */
1137 static int
1138 dev_dereg(
1139 conn_arg_t *conn
1140 )
1141 {
1142 int ec = 0;
1143
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;
1150
1151 uchar_t *iscsi_name;
1152 int ctrl;
1153 uint32_t puid;
1154
1155 lookup_ctrl_t lc;
1156 uint8_t *value;
1157
1158 isnslog(LOG_DEBUG, "dev_dereg", "entered");
1159
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);
1164 }
1165
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;
1209 }
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;
1222 }
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);
1235 }
1236 }
1237 }
1238
1239 conn->ec = ec;
1240
1241 if (ec != 0) {
1242 isnslog(LOG_DEBUG, "dev_dereg", "error code: %d", ec);
1243 }
1244
1245 return (0);
1246 }
1247
1248 /*
1249 * ****************************************************************************
1250 *
1251 * scn_reg:
1252 * function which handles the isnsp SCN_REG message.
1253 *
1254 * conn - the argument of the connection.
1255 * return - 0: the message requires response.
1256 *
1257 * ****************************************************************************
1258 */
1259 static int
1260 scn_reg(
1261 conn_arg_t *conn
1262 )
1263 {
1264 int ec = 0;
1265
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;
1272
1273 /* uchar_t *src; */
1274 uchar_t *node_name;
1275 uint32_t nlen;
1276 uint32_t scn;
1277
1278 isnslog(LOG_DEBUG, "scn_reg", "entered");
1279
1280 /* src = (uchar_t *)&source->attr_value[0]; */
1281
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;
1290 }
1291
1292 node_name = (uchar_t *)&key->attr_value[0];
1293 nlen = key->attr_len;
1294 scn = ntohl(*(uint32_t *)&op->attr_value[0]);
1295
1296 ec = add_scn_entry(node_name, nlen, scn);
1297
1298 scn_reg_done:
1299 conn->ec = ec;
1300
1301 if (ec != 0) {
1302 isnslog(LOG_DEBUG, "scn_reg", "error code: %d", ec);
1303 }
1304
1305 return (0);
1306 }
1307
1308 /*
1309 * ****************************************************************************
1310 *
1311 * scn_dereg:
1312 * function which handles the isnsp SCN_DEREG message.
1313 *
1314 * conn - the argument of the connection.
1315 * return - 0: the message requires response.
1316 *
1317 * ****************************************************************************
1318 */
1319 static int
1320 scn_dereg(
1321 conn_arg_t *conn
1322 )
1323 {
1324 int ec = 0;
1325
1326 isns_tlv_t *key = conn->in_packet.key;
1327 uint16_t key_len = conn->in_packet.key_len;
1328
1329 uchar_t *node_name;
1330
1331 isnslog(LOG_DEBUG, "scn_dereg", "entered");
1332
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;
1341 }
1342
1343 conn->ec = ec;
1344
1345 if (ec != 0) {
1346 isnslog(LOG_DEBUG, "scn_dereg", "error code: %d", ec);
1347 }
1348
1349 return (0);
1350 }
1351
1352 /*
1353 * ****************************************************************************
1354 *
1355 * setup_ddid_lcp:
1356 * setup the lookup control data for looking up the DD object
1357 * by using the dd_id attribute.
1358 *
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.
1362 *
1363 * ****************************************************************************
1364 */
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
1372 )
1373 {
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;
1380
1381 return (lcp);
1382 }
1383
1384 /*
1385 * ****************************************************************************
1386 *
1387 * setup_ddsid_lcp:
1388 * setup the lookup control data for looking up the DD-set object
1389 * by using the dds_id attribute.
1390 *
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.
1394 *
1395 * ****************************************************************************
1396 */
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
1404 )
1405 {
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;
1412
1413 return (lcp);
1414 }
1415
1416 /*
1417 * ****************************************************************************
1418 *
1419 * dd_reg:
1420 * function which handles the isnsp DD_REG message.
1421 *
1422 * conn - the argument of the connection.
1423 * return - 0: the message requires response.
1424 *
1425 * ****************************************************************************
1426 */
1427 static int
1428 dd_reg(
1429 conn_arg_t *conn
1430 )
1431 {
1432 int ec = 0;
1433
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;
1440
1441 uint32_t dd_id = 0;
1442 uint8_t *value;
1443
1444 isns_obj_t *dd = NULL;
1445
1446 uchar_t *iscsi_name;
1447
1448 lookup_ctrl_t lc;
1449 isns_assoc_iscsi_t aiscsi;
1450 isns_obj_t *assoc;
1451 isns_attr_t *attr;
1452
1453 uint32_t features;
1454
1455 isnslog(LOG_DEBUG, "dd_reg", "entered");
1456
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;
1461 }
1462
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;
1468 }
1469
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;
1479 }
1480
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;
1486 }
1487
1488 /* delimiter */
1489 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1490 NULL, 0)) != 0) {
1491 goto dd_reg_done;
1492 }
1493
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;
1502 }
1503 if (ec != 0) {
1504 free_object(dd);
1505 goto dd_reg_done;
1506 }
1507 } else {
1508 goto dd_reg_done;
1509 }
1510 }
1511
1512 /* add the newly created dd to the response */
1513 if (dd != NULL) {
1514 ec = rsp_add_op(conn, dd);
1515 }
1516
1517 aiscsi.type = OBJ_ASSOC_ISCSI;
1518 aiscsi.puid = dd_id;
1519
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);
1536 }
1537 }
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;
1549 }
1550 } else {
1551 ec = ISNS_RSP_INVALID_REGIS;
1552 }
1553 if (ec == 0) {
1554 ec = rsp_add_tlv(conn,
1555 ISNS_DD_NAME_ATTR_ID,
1556 op->attr_len, (void *)value, 1);
1557 }
1558 }
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;
1576 }
1577 if (attr->value.ptr != NULL) {
1578 free(attr->value.ptr);
1579 }
1580 } else {
1581 ec = ISNS_RSP_INVALID_REGIS;
1582 }
1583 if (ec == 0) {
1584 ec = rsp_add_tlv(conn,
1585 ISNS_DD_ISCSI_INDEX_ATTR_ID,
1586 4, (void *)attr->value.ui, 0);
1587 }
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;
1603 }
1604 } else {
1605 ec = ISNS_RSP_INVALID_REGIS;
1606 }
1607 if (ec == 0) {
1608 ec = rsp_add_tlv(conn,
1609 ISNS_DD_ISCSI_NAME_ATTR_ID,
1610 op->attr_len, (void *)value, 1);
1611 }
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;
1628 }
1629 if (ec == 0) {
1630 ec = rsp_add_tlv(conn,
1631 ISNS_DD_FEATURES_ATTR_ID,
1632 4, (void *)features, 0);
1633 }
1634 }
1635 break;
1636 default:
1637 ec = ISNS_RSP_INVALID_REGIS;
1638 break;
1639 }
1640
1641 NEXT_TLV(op, op_len);
1642 }
1643
1644 dd_reg_done:
1645 conn->ec = ec;
1646
1647 if (ec != 0) {
1648 isnslog(LOG_DEBUG, "dd_reg", "error code: %d", ec);
1649 }
1650
1651 return (0);
1652 }
1653
1654 /*
1655 * ****************************************************************************
1656 *
1657 * dds_reg:
1658 * function which handles the isnsp DDS_REG message.
1659 *
1660 * conn - the argument of the connection.
1661 * return - 0: the message requires response.
1662 *
1663 * ****************************************************************************
1664 */
1665 static int
1666 dds_reg(
1667 conn_arg_t *conn
1668 )
1669 {
1670 int ec = 0;
1671
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;
1678
1679 uint32_t dds_id = 0;
1680 uint8_t *value;
1681
1682 isns_obj_t *dds = NULL;
1683
1684 uchar_t *iscsi_name;
1685
1686 lookup_ctrl_t lc;
1687 isns_assoc_dd_t add;
1688 isns_obj_t *assoc;
1689 isns_attr_t *attr;
1690
1691 uint32_t code;
1692
1693 isnslog(LOG_DEBUG, "dds_reg", "entered");
1694
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;
1699 }
1700
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;
1706 }
1707
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;
1717 }
1718
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;
1724 }
1725
1726 /* delimiter */
1727 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1728 NULL, 0)) != 0) {
1729 goto dds_reg_done;
1730 }
1731
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;
1740 }
1741 if (ec != 0) {
1742 free_object(dds);
1743 goto dds_reg_done;
1744 }
1745 } else {
1746 goto dds_reg_done;
1747 }
1748 }
1749
1750 /* add the newly created dd to the response */
1751 if (dds != NULL) {
1752 ec = rsp_add_op(conn, dds);
1753 }
1754
1755 add.type = OBJ_ASSOC_DD;
1756 add.puid = dds_id;
1757
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);
1774 }
1775 }
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;
1787 }
1788 } else {
1789 ec = ISNS_RSP_INVALID_REGIS;
1790 }
1791 if (ec == 0) {
1792 ec = rsp_add_tlv(conn,
1793 ISNS_DD_SET_NAME_ATTR_ID,
1794 op->attr_len, (void *)value, 1);
1795 }
1796 }
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;
1807 }
1808 if (ec == 0) {
1809 ec = rsp_add_tlv(conn,
1810 ISNS_DD_SET_STATUS_ATTR_ID,
1811 4, (void *)code, 0);
1812 }
1813 }
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;
1827 }
1828 } else {
1829 ec = ISNS_RSP_INVALID_REGIS;
1830 }
1831 if (ec == 0) {
1832 ec = rsp_add_tlv(conn,
1833 ISNS_DD_ID_ATTR_ID, 4,
1834 (void *)attr->value.ui, 0);
1835 }
1836 break;
1837 default:
1838 ec = ISNS_RSP_INVALID_REGIS;
1839 break;
1840 }
1841
1842 NEXT_TLV(op, op_len);
1843 }
1844
1845 dds_reg_done:
1846 conn->ec = ec;
1847
1848 if (ec != 0) {
1849 isnslog(LOG_DEBUG, "dds_reg", "error code: %d", ec);
1850 }
1851
1852 return (0);
1853 }
1854
1855 /*
1856 * ****************************************************************************
1857 *
1858 * dd_dereg:
1859 * function which handles the isnsp DD_DEREG message.
1860 *
1861 * conn - the argument of the connection.
1862 * return - 0: the message requires response.
1863 *
1864 * ****************************************************************************
1865 */
1866 static int
1867 dd_dereg(
1868 conn_arg_t *conn
1869 )
1870 {
1871 int ec = 0;
1872
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;
1879
1880 uint32_t dd_id;
1881 uint8_t *value;
1882
1883 uchar_t *iscsi_name;
1884
1885 isns_assoc_iscsi_t aiscsi;
1886 isns_obj_t *assoc;
1887 isns_attr_t *attr;
1888
1889 isnslog(LOG_DEBUG, "dd_dereg", "entered");
1890
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;
1895 }
1896
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;
1903 }
1904
1905 if (op == NULL) {
1906 ec = remove_dd_object(dd_id);
1907 } else {
1908 aiscsi.type = OBJ_ASSOC_ISCSI;
1909 aiscsi.puid = dd_id;
1910
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;
1929 }
1930 if (attr->value.ptr != NULL) {
1931 free(attr->value.ptr);
1932 }
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;
1947 }
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;
1958 }
1959
1960 NEXT_TLV(op, op_len);
1961 }
1962 }
1963
1964 dd_dereg_done:
1965 conn->ec = ec;
1966
1967 if (ec != 0) {
1968 isnslog(LOG_DEBUG, "dd_dereg", "error code: %d", ec);
1969 }
1970
1971 return (0);
1972 }
1973
1974 /*
1975 * ****************************************************************************
1976 *
1977 * dds_dereg:
1978 * function which handles the isnsp DDS_DEREG message.
1979 *
1980 * conn - the argument of the connection.
1981 * return - 0: the message requires response.
1982 *
1983 * ****************************************************************************
1984 */
1985 static int
1986 dds_dereg(
1987 conn_arg_t *conn
1988 )
1989 {
1990 int ec = 0;
1991
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;
1998
1999 uint32_t dds_id;
2000 uint32_t uid;
2001 uint8_t *value;
2002
2003 uchar_t *iscsi_name;
2004
2005 isnslog(LOG_DEBUG, "dds_dereg", "entered");
2006
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;
2011 }
2012
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;
2019 }
2020
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;
2031 }
2032 } else {
2033 ec = ISNS_RSP_MSG_FORMAT_ERROR;
2034 }
2035
2036 NEXT_TLV(op, op_len);
2037 }
2038 }
2039
2040 dds_dereg_done:
2041 conn->ec = ec;
2042
2043 if (ec != 0) {
2044 isnslog(LOG_DEBUG, "dds_dereg", "error code: %d", ec);
2045 }
2046
2047 return (0);
2048 }
2049
2050 /*
2051 * ****************************************************************************
2052 *
2053 * msg_error:
2054 * function which handles any unknown isnsp messages or the
2055 * messages which are not supported.
2056 *
2057 * conn - the argument of the connection.
2058 * return - 0: the message requires response.
2059 *
2060 * ****************************************************************************
2061 */
2062 static int
2063 msg_error(
2064 /* LINTED E_FUNC_ARG_UNUSED */
2065 conn_arg_t *conn
2066 )
2067 {
2068 return (0);
2069 }
2070
2071 /*
2072 * ****************************************************************************
2073 *
2074 * isns_response_ec:
2075 * send the response message to the client with error code.
2076 *
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.
2081 *
2082 * ****************************************************************************
2083 */
2084 static int
2085 isns_response_ec(
2086 int so,
2087 isns_pdu_t *pdu,
2088 int ec
2089 )
2090 {
2091 int status;
2092
2093 uint8_t buff[sizeof (isns_pdu_t) + 8];
2094
2095 isns_pdu_t *rsp = (isns_pdu_t *)&buff;
2096 isns_resp_t *resp = (isns_resp_t *)rsp->payload;
2097 size_t pl = 4;
2098
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);
2103
2104 status = isns_send_pdu(so, rsp, pl);
2105
2106 return (status);
2107 }
2108
2109 /*
2110 * ****************************************************************************
2111 *
2112 * isns_response:
2113 * send the response message to the client.
2114 *
2115 * conn - the argument of the connection.
2116 * return - status of the sending operation.
2117 *
2118 * ****************************************************************************
2119 */
2120 int
2121 isns_response(
2122 conn_arg_t *conn
2123 )
2124 {
2125 int status;
2126
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;
2132
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);
2141 }
2142
2143 return (status);
2144 }
2145