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(conn_arg_t *conn)
101 {
102 int ec = 0;
103
104 isns_pdu_t *pdu = conn->in_packet.pdu;
105 isns_tlv_t *source = pdu_get_source(pdu);
106
107 if (source == NULL) {
108 ec = ISNS_RSP_SRC_ABSENT;
109 } else if (source->attr_id != ISNS_ISCSI_NAME_ATTR_ID ||
110 source->attr_len == 0) {
111 ec = ISNS_RSP_SRC_UNKNOWN;
112 }
113
114 if (ec == 0) {
115 conn->in_packet.source = source;
116 }
117
118 return (ec);
119 }
120
121 /*
122 * ****************************************************************************
123 *
124 * packet_get_key:
125 * get the key attributes of the packet.
126 *
127 * conn - the argument of the connection.
128 * return - error code.
129 *
130 * ****************************************************************************
131 */
132 static int
packet_get_key(conn_arg_t * conn)133 packet_get_key(conn_arg_t *conn)
134 {
135 int ec = 0;
136
137 isns_pdu_t *pdu = conn->in_packet.pdu;
138 isns_tlv_t *key;
139 size_t key_len;
140
141 key = pdu_get_key(pdu, &key_len);
142
143 conn->in_packet.key = key;
144 conn->in_packet.key_len = key_len;
145
146 return (ec);
147 }
148
149 /*
150 * ****************************************************************************
151 *
152 * packet_get_operand:
153 * get the operating attributes of the packet.
154 *
155 * conn - the argument of the connection.
156 * return - error code.
157 *
158 * ****************************************************************************
159 */
160 static int
packet_get_operand(conn_arg_t * conn)161 packet_get_operand(conn_arg_t *conn)
162 {
163 int ec = 0;
164
165 isns_pdu_t *pdu = conn->in_packet.pdu;
166 isns_tlv_t *op;
167 size_t op_len;
168
169 op = pdu_get_operand(pdu, &op_len);
170
171 conn->in_packet.op = op;
172 conn->in_packet.op_len = op_len;
173
174 return (ec);
175 }
176
177 /*
178 * ****************************************************************************
179 *
180 * packet_split_verify:
181 * split and verify the packet, get the apporiate locking type and
182 * function handler for the packet.
183 *
184 * conn - the argument of the connection.
185 * return - error code.
186 *
187 * ****************************************************************************
188 */
189 int
packet_split_verify(conn_arg_t * conn)190 packet_split_verify(conn_arg_t *conn)
191 {
192 int ec = 0;
193
194 isns_pdu_t *pdu = conn->in_packet.pdu;
195
196 int (*handler)(conn_arg_t *) = msg_error;
197 int lock = CACHE_NO_ACTION;
198
199 if (pdu->version != ISNSP_VERSION) {
200 ec = ISNS_RSP_VER_NOT_SUPPORTED;
201 } else {
202 switch (pdu->func_id) {
203 case ISNS_DEV_ATTR_REG:
204 lock = CACHE_WRITE;
205 handler = dev_attr_reg;
206 break;
207 case ISNS_DEV_ATTR_QRY:
208 lock = CACHE_READ;
209 handler = dev_attr_qry;
210 break;
211 case ISNS_DEV_GET_NEXT:
212 lock = CACHE_READ;
213 handler = dev_get_next;
214 break;
215 case ISNS_DEV_DEREG:
216 lock = CACHE_WRITE;
217 handler = dev_dereg;
218 break;
219 case ISNS_SCN_REG:
220 if (scn_q != NULL) {
221 lock = CACHE_WRITE;
222 handler = scn_reg;
223 } else {
224 ec = ISNS_RSP_SCN_REGIS_REJECTED;
225 }
226 break;
227 case ISNS_SCN_DEREG:
228 if (scn_q != NULL) {
229 lock = CACHE_WRITE;
230 handler = scn_dereg;
231 } else {
232 ec = ISNS_RSP_SCN_REGIS_REJECTED;
233 }
234 break;
235 case ISNS_SCN_EVENT:
236 ec = ISNS_RSP_MSG_NOT_SUPPORTED;
237 break;
238 case ISNS_DD_REG:
239 lock = CACHE_WRITE;
240 handler = dd_reg;
241 break;
242 case ISNS_DD_DEREG:
243 lock = CACHE_WRITE;
244 handler = dd_dereg;
245 break;
246 case ISNS_DDS_REG:
247 lock = CACHE_WRITE;
248 handler = dds_reg;
249 break;
250 case ISNS_DDS_DEREG:
251 lock = CACHE_WRITE;
252 handler = dds_dereg;
253 break;
254 default:
255 ec = ISNS_RSP_MSG_NOT_SUPPORTED;
256 break;
257 }
258 }
259
260 if (ISNS_OPERATION_TYPE_ENABLED()) {
261 char buf[INET6_ADDRSTRLEN];
262 struct sockaddr_storage *ssp = &conn->ss;
263 struct sockaddr_in *sinp = (struct sockaddr_in *)ssp;
264 if (ssp->ss_family == AF_INET) {
265 (void) inet_ntop(AF_INET, (void *)&(sinp->sin_addr),
266 buf, sizeof (buf));
267 } else {
268 (void) inet_ntop(AF_INET6, (void *)&(sinp->sin_addr),
269 buf, sizeof (buf));
270 }
271 ISNS_OPERATION_TYPE((uintptr_t)buf, pdu->func_id);
272 }
273
274 conn->lock = lock;
275 conn->handler = handler;
276
277 /* packet split & verify */
278 if (ec == 0) {
279 ec = packet_get_source(conn);
280 if (ec == 0) {
281 ec = packet_get_key(conn);
282 if (ec == 0) {
283 ec = packet_get_operand(conn);
284 }
285 }
286 }
287
288 conn->ec = ec;
289
290 return (ec);
291 }
292
293 /*
294 * ****************************************************************************
295 *
296 * setup_key_lcp:
297 * setup the lookup control data for looking up the object
298 * which the key attributes identify.
299 *
300 * lcp - the pointer of the lookup control data.
301 * key - the key attributes.
302 * key_len - the length of the key attributes.
303 * return - the pointer of the lookup control data or
304 * NULL if there is an error.
305 *
306 * ****************************************************************************
307 */
308 static int
setup_key_lcp(lookup_ctrl_t * lcp,isns_tlv_t * key,uint16_t key_len)309 setup_key_lcp(lookup_ctrl_t *lcp, isns_tlv_t *key, uint16_t key_len)
310 {
311 int ec = 0;
312
313 uint8_t *value = &key->attr_value[0];
314
315 lcp->curr_uid = 0;
316 lcp->op[0] = 0;
317
318 switch (key->attr_id) {
319 case ISNS_EID_ATTR_ID:
320 if (key->attr_len >= 4) {
321 lcp->type = OBJ_ENTITY;
322 lcp->id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
323 lcp->op[0] = OP_STRING;
324 lcp->data[0].ptr = (uchar_t *)value;
325 lcp->op[1] = 0;
326 }
327 break;
328 case ISNS_ISCSI_NAME_ATTR_ID:
329 if (key->attr_len >= 4) {
330 lcp->type = OBJ_ISCSI;
331 lcp->id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
332 lcp->op[0] = OP_STRING;
333 lcp->data[0].ptr = (uchar_t *)value;
334 lcp->op[1] = 0;
335 } else {
336 ec = ISNS_RSP_MSG_FORMAT_ERROR;
337 }
338 break;
339 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
340 if (key->attr_len == sizeof (in6_addr_t)) {
341 lcp->id[0] = ATTR_INDEX_PORTAL(
342 ISNS_PORTAL_IP_ADDR_ATTR_ID);
343 lcp->op[0] = OP_MEMORY_IP6;
344 lcp->data[0].ip = (in6_addr_t *)value;
345 NEXT_TLV(key, key_len);
346 if (key_len <= 8 ||
347 key->attr_len != 4 ||
348 key->attr_id != ISNS_PORTAL_PORT_ATTR_ID) {
349 return (ISNS_RSP_MSG_FORMAT_ERROR);
350 }
351 lcp->type = OBJ_PORTAL;
352 value = &key->attr_value[0];
353 lcp->id[1] = ATTR_INDEX_PORTAL(
354 ISNS_PORTAL_PORT_ATTR_ID);
355 lcp->op[1] = OP_INTEGER;
356 lcp->data[1].ui = ntohl(*(uint32_t *)value);
357 lcp->op[2] = 0;
358 } else {
359 ec = ISNS_RSP_MSG_FORMAT_ERROR;
360 }
361 break;
362 case ISNS_PG_ISCSI_NAME_ATTR_ID:
363 if (key->attr_len < 4) {
364 return (ISNS_RSP_MSG_FORMAT_ERROR);
365 }
366 lcp->id[0] = ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID);
367 lcp->op[0] = OP_STRING;
368 lcp->data[0].ptr = (uchar_t *)value;
369 NEXT_TLV(key, key_len);
370 if (key_len <= 8 ||
371 key->attr_len != sizeof (in6_addr_t) ||
372 key->attr_id != ISNS_PG_PORTAL_IP_ADDR_ATTR_ID) {
373 return (ISNS_RSP_MSG_FORMAT_ERROR);
374 }
375 value = &key->attr_value[0];
376 lcp->id[1] = ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID);
377 lcp->op[1] = OP_MEMORY_IP6;
378 lcp->data[1].ip = (in6_addr_t *)value;
379 NEXT_TLV(key, key_len);
380 if (key_len <= 8 ||
381 key->attr_len != 4 ||
382 key->attr_id != ISNS_PG_PORTAL_PORT_ATTR_ID) {
383 return (ISNS_RSP_MSG_FORMAT_ERROR);
384 }
385 value = &key->attr_value[0];
386 lcp->id[2] = ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID);
387 lcp->op[2] = OP_INTEGER;
388 lcp->data[2].ui = ntohl(*(uint32_t *)value);
389 lcp->type = OBJ_PG;
390 break;
391 default:
392 lcp->type = 0; /* invalid */
393 ec = ISNS_RSP_MSG_FORMAT_ERROR;
394 }
395
396 return (ec);
397 }
398
399 /*
400 * ****************************************************************************
401 *
402 * rsp_add_op:
403 * add the operating attributes to the response packet.
404 *
405 * conn - the argument of the connection.
406 * obj - the object which is being added as operating attributes.
407 * return - error code.
408 *
409 * ****************************************************************************
410 */
411 static int
rsp_add_op(conn_arg_t * conn,isns_obj_t * obj)412 rsp_add_op(conn_arg_t *conn, isns_obj_t *obj)
413 {
414 int ec = 0;
415
416 isns_attr_t *attr;
417 int i;
418
419 isns_pdu_t *rsp = conn->out_packet.pdu;
420 size_t pl = conn->out_packet.pl;
421 size_t sz = conn->out_packet.sz;
422
423 i = 0;
424 while (i < NUM_OF_ATTRS[obj->type] &&
425 ec == 0) {
426 attr = &obj->attrs[i];
427 /* there is an attribute, send it back */
428 if (attr->tag != 0) {
429 ec = pdu_add_tlv(&rsp, &pl, &sz,
430 attr->tag, attr->len,
431 (void *)attr->value.ptr, 0);
432 }
433 i ++;
434 }
435
436 conn->out_packet.pdu = rsp;
437 conn->out_packet.pl = pl;
438 conn->out_packet.sz = sz;
439
440 return (ec);
441 }
442
443 /*
444 * ****************************************************************************
445 *
446 * rsp_add_key:
447 * add the key attributes to the response packet.
448 *
449 * conn - the argument of the connection.
450 * entity - the object which is being added as key attributes.
451 * return - error code.
452 *
453 * ****************************************************************************
454 */
455 static int
rsp_add_key(conn_arg_t * conn,isns_obj_t * entity)456 rsp_add_key(conn_arg_t *conn, isns_obj_t *entity)
457 {
458 int ec = 0;
459
460 isns_tlv_t *key = conn->in_packet.key;
461 size_t key_len = conn->in_packet.key_len;
462 uint32_t tag = ISNS_EID_ATTR_ID;
463 isns_attr_t *attr = &entity->attrs[ATTR_INDEX_ENTITY(tag)];
464 uint32_t len = attr->len;
465
466 isns_pdu_t *rsp = conn->out_packet.pdu;
467 size_t pl = conn->out_packet.pl;
468 size_t sz = conn->out_packet.sz;
469
470 if (key_len == 0) {
471 ec = pdu_add_tlv(&rsp, &pl, &sz,
472 tag, len, (void *)attr->value.ptr, 0);
473 } else {
474 while (key_len >= 8 &&
475 ec == 0) {
476 if (key->attr_id == ISNS_EID_ATTR_ID) {
477 ec = pdu_add_tlv(&rsp, &pl, &sz,
478 tag, len,
479 (void *)attr->value.ptr, 0);
480 } else {
481 ec = pdu_add_tlv(&rsp, &pl, &sz,
482 key->attr_id, key->attr_len,
483 (void *)key->attr_value, 1);
484 }
485 NEXT_TLV(key, key_len);
486 }
487 }
488
489 if (ec == 0) {
490 ec = pdu_add_tlv(&rsp, &pl, &sz,
491 ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
492 }
493
494 conn->out_packet.pdu = rsp;
495 conn->out_packet.pl = pl;
496 conn->out_packet.sz = sz;
497
498 if (ec == 0) {
499 ec = rsp_add_op(conn, entity);
500 }
501
502 return (ec);
503 }
504
505 /*
506 * ****************************************************************************
507 *
508 * rsp_add_tlv:
509 * add one attribute with TLV format to the response packet.
510 *
511 * conn - the argument of the connection.
512 * tag - the tag of the attribute.
513 * len - the length of the attribute.
514 * value- the value of the attribute.
515 * pflag- the flag of the value, 0: value; 1: pointer to value
516 * return - error code.
517 *
518 * ****************************************************************************
519 */
520 static int
rsp_add_tlv(conn_arg_t * conn,uint32_t tag,uint32_t len,void * value,int pflag)521 rsp_add_tlv(conn_arg_t *conn, uint32_t tag, uint32_t len, void *value,
522 int pflag)
523 {
524 int ec = 0;
525
526 isns_pdu_t *rsp = conn->out_packet.pdu;
527 size_t pl = conn->out_packet.pl;
528 size_t sz = conn->out_packet.sz;
529
530 ec = pdu_add_tlv(&rsp, &pl, &sz, tag, len, value, pflag);
531
532 conn->out_packet.pdu = rsp;
533 conn->out_packet.pl = pl;
534 conn->out_packet.sz = sz;
535
536 return (ec);
537 }
538
539 /*
540 * ****************************************************************************
541 *
542 * rsp_add_tlvs:
543 * add attributes with TLV format to the response packet.
544 *
545 * conn - the argument of the connection.
546 * tlv - the attributes with TLV format being added.
547 * tlv_len - the length of the attributes.
548 * return - error code.
549 *
550 * ****************************************************************************
551 */
552 static int
rsp_add_tlvs(conn_arg_t * conn,isns_tlv_t * tlv,uint32_t tlv_len)553 rsp_add_tlvs(conn_arg_t *conn, isns_tlv_t *tlv, uint32_t tlv_len)
554 {
555 int ec = 0;
556
557 uint32_t tag;
558 uint32_t len;
559 void *value;
560
561 while (tlv_len >= 8 &&
562 ec == 0) {
563 tag = tlv->attr_id;
564 len = tlv->attr_len;
565 value = (void *)tlv->attr_value;
566
567 ec = rsp_add_tlv(conn, tag, len, value, 1);
568
569 NEXT_TLV(tlv, tlv_len);
570 }
571
572 return (ec);
573 }
574
575 /*
576 * ****************************************************************************
577 *
578 * dev_attr_reg:
579 * function which handles the isnsp DEV_ATTR_REG message.
580 *
581 * conn - the argument of the connection.
582 * return - 0: the message requires response.
583 *
584 * ****************************************************************************
585 */
586 static int
dev_attr_reg(conn_arg_t * conn)587 dev_attr_reg(conn_arg_t *conn)
588 {
589 int ec = 0;
590
591 isns_pdu_t *pdu = conn->in_packet.pdu;
592 isns_tlv_t *source = conn->in_packet.source;
593 isns_tlv_t *key = conn->in_packet.key;
594 uint16_t key_len = conn->in_packet.key_len;
595 isns_tlv_t *op = conn->in_packet.op;
596 uint16_t op_len = conn->in_packet.op_len;
597
598 boolean_t replace =
599 ((pdu->flags & ISNS_FLAG_REPLACE_REG) == ISNS_FLAG_REPLACE_REG);
600
601 lookup_ctrl_t lc, lc_key;
602 uchar_t *iscsi_name;
603 int ctrl;
604
605 isns_obj_t *ety = NULL; /* network entity object */
606 isns_type_t ptype; /* parent object type */
607 uint32_t puid; /* parent object UID */
608 void const **child[MAX_CHILD_TYPE] = { NULL }; /* children */
609 int ety_update, obj_update;
610 isns_attr_t *eid_attr;
611
612 isns_obj_t *obj; /* child object */
613 isns_type_t ctype; /* child object type */
614 uint32_t uid; /* child object uid */
615 isns_attr_t pgt[3] = { 0 };
616
617 void const **vpp = NULL;
618 int i = 0;
619
620 isnslog(LOG_DEBUG, "dev_attr_reg", "entered (replace: %d)", replace);
621
622 ec = pdu_reset_rsp(&conn->out_packet.pdu,
623 &conn->out_packet.pl,
624 &conn->out_packet.sz);
625 if (ec != 0) {
626 goto reg_done;
627 }
628
629 iscsi_name = (uchar_t *)&source->attr_value[0];
630 ctrl = is_control_node(iscsi_name);
631 lc_key.type = 0;
632 if (key != NULL) {
633 /* validate key attributes and make lcp for */
634 /* the object identified by key attributes. */
635 ec = setup_key_lcp(&lc, key, key_len);
636 if (ec == 0 && lc.type != 0) {
637 lc_key = lc;
638 /* object is not found */
639 if ((uid = is_obj_there(&lc)) == 0) {
640 /* error if it is a network entity */
641 if (lc.type != OBJ_ENTITY) {
642 ec = ISNS_RSP_INVALID_REGIS;
643 }
644 /* validate for the source attribute before */
645 /* update or replace the network entity object */
646 } else if (ctrl == 0 &&
647 #ifndef SKIP_SRC_AUTH
648 reg_auth_src(lc.type, uid, iscsi_name) == 0) {
649 #else
650 0) {
651 #endif
652 ec = ISNS_RSP_SRC_UNAUTHORIZED;
653 /* de-register the network entity if replace is true */
654 } else if (replace != 0) {
655 UPDATE_LCP_UID(&lc, uid);
656 ec = dereg_object(&lc, 0);
657 /* generate a SCN */
658 if (ec == 0) {
659 (void) queue_msg_set(scn_q,
660 SCN_TRIGGER, NULL);
661 }
662 }
663 }
664 }
665 if (ec != 0) {
666 goto reg_done;
667 }
668
669 /* register the network entity object */
670 ec = reg_get_entity(&ety, &op, &op_len);
671 if (ec != 0) {
672 goto reg_done;
673 }
674 if (ety == NULL && lc_key.type != OBJ_ENTITY) {
675 ety = make_default_entity();
676 } else if (ety == NULL ||
677 (lc_key.type == OBJ_ENTITY &&
678 key_cmp(&lc_key, ety) != 0)) {
679 /* the eid in key attribute and */
680 /* op attribute must be the same */
681 ec = ISNS_RSP_INVALID_REGIS;
682 goto reg_done;
683 }
684 if (ety == NULL || rsp_add_key(conn, ety) != 0) {
685 ec = ISNS_RSP_INTERNAL_ERROR;
686 } else {
687 eid_attr = &ety->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)];
688 ec = register_object(ety, &puid, &ety_update);
689 ptype = OBJ_ENTITY;
690 }
691 if (ec == 0 && ety_update == 0) {
692 /* newly registered, reset the pointer */
693 ety = NULL;
694 }
695
696 /* register the reset of objects which are specified in */
697 /* operating attributes */
698 while (ec == 0 &&
699 (ec = reg_get_obj(&obj, &pgt[0], &op, &op_len)) == 0 &&
700 obj != NULL &&
701 (ec = rsp_add_op(conn, obj)) == 0) {
702 ctype = obj->type;
703 /* set the parent object UID */
704 (void) set_parent_obj(obj, puid);
705 /* register it */
706 ec = register_object(obj, &uid, &obj_update);
707 if (ec == 0) {
708 if (obj_update == 0 ||
709 is_obj_online(obj) == 0) {
710 /* update the ref'd object */
711 (void) update_ref_obj(obj);
712 /* add the newly registered object info */
713 /* to child info array of the parent object */
714 ec = buff_child_obj(ptype, ctype, obj, child);
715 } else {
716 if (ctrl == 0 &&
717 #ifndef SKIP_SRC_AUTH
718 puid != get_parent_uid(obj)) {
719 #else
720 0) {
721 #endif
722 ec = ISNS_RSP_SRC_UNAUTHORIZED;
723 }
724 /* it was for updating an existing object */
725 free_one_object(obj);
726 }
727 } else {
728 /* failed registering it */
729 free_one_object(obj);
730 }
731 }
732
733 /* update the portal group object for the associations between */
734 /* the newly registered objects and previously registered objects */
735 if (ec == 0) {
736 ec = verify_ref_obj(ptype, puid, child);
737 }
738 if (ec != 0) {
739 goto reg_done;
740 }
741
742 /* update the children list of the parent object */
743 while (i < MAX_CHILD_TYPE) {
744 vpp = child[i];
745 if (vpp != NULL) {
746 break;
747 }
748 i ++;
749 }
750 if (vpp != NULL) {
751 ec = update_child_obj(ptype, puid, child, 1);
752 } else {
753 #ifndef SKIP_SRC_AUTH
754 ec = ISNS_RSP_INVALID_REGIS;
755 #else
756 /* for interop-ability, we cannot treat this as */
757 /* an error, instead, remove the network entity */
758 SET_UID_LCP(&lc, OBJ_ENTITY, puid);
759 ec = dereg_object(&lc, 0);
760 goto reg_done;
761 #endif
762 }
763 if (ec != 0) {
764 goto reg_done;
765 }
766 /* add esi entry */
767 if (ety_update != 0) {
768 (void) esi_remove(puid);
769 }
770 ec = esi_add(puid, eid_attr->value.ptr, eid_attr->len);
771
772 reg_done:
773 conn->ec = ec;
774 free_one_object(ety);
775 uid = 0;
776 while (uid < MAX_CHILD_TYPE) {
777 if (child[uid] != NULL) {
778 free(child[uid]);
779 }
780 uid ++;
781 }
782
783 if (ec != 0) {
784 isnslog(LOG_DEBUG, "dev_attr_reg", "error code: %d", ec);
785 }
786
787 return (0);
788 }
789
790 /*
791 * ****************************************************************************
792 *
793 * dev_attr_qry:
794 * function which handles the isnsp DEV_ATTR_QRY message.
795 *
796 * conn - the argument of the connection.
797 * return - 0: the message requires response.
798 *
799 * ****************************************************************************
800 */
801 static int
802 dev_attr_qry(conn_arg_t *conn)
803 {
804 int ec = 0;
805
806 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
807 isns_tlv_t *source = conn->in_packet.source;
808 isns_tlv_t *key = conn->in_packet.key;
809 uint16_t key_len = conn->in_packet.key_len;
810 isns_tlv_t *op = conn->in_packet.op;
811 uint16_t op_len = conn->in_packet.op_len;
812
813 uchar_t *iscsi_name;
814
815 bmp_t *nodes_bmp = NULL;
816 uint32_t num_of_nodes;
817 uint32_t *key_uids = NULL;
818 uint32_t num_of_keys;
819 isns_type_t key_type;
820
821 uint32_t key_uid;
822 uint32_t op_uid;
823
824 uint32_t size_of_ops;
825 uint32_t num_of_ops;
826 uint32_t *op_uids = NULL;
827 isns_type_t op_type;
828
829 isns_tlv_t *tlv;
830 uint16_t tlv_len;
831
832 isnslog(LOG_DEBUG, "dev_attr_qry", "entered");
833
834 ec = pdu_reset_rsp(&conn->out_packet.pdu,
835 &conn->out_packet.pl,
836 &conn->out_packet.sz);
837 if (ec != 0) {
838 goto qry_done;
839 }
840
841 /*
842 * RFC 4171 section 5.7.5.2:
843 * If no Operating Attributes are included in the original query, then
844 * all Operating Attributes SHALL be returned in the response. ???
845 */
846 if (op_len == 0) {
847 goto qry_done;
848 }
849
850 iscsi_name = (uchar_t *)&source->attr_value[0];
851 if (is_control_node(iscsi_name) == 0) {
852 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
853 if (ec != 0 || nodes_bmp == NULL) {
854 goto qry_done;
855 }
856 }
857
858 size_of_ops = 0;
859 if (key != NULL) {
860 /*
861 * Return the original message key.
862 */
863 ec = rsp_add_tlvs(conn, key, key_len);
864 if (ec != 0) {
865 goto qry_done;
866 }
867
868 /*
869 * Delimiter
870 */
871 ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0);
872 if (ec != 0) {
873 goto qry_done;
874 }
875
876 /*
877 * Query objects which match the Key Attributes.
878 */
879 ec = get_qry_keys(nodes_bmp, num_of_nodes, &key_type,
880 key, key_len, &key_uids, &num_of_keys);
881 if (ec != 0 || key_uids == NULL) {
882 goto qry_done;
883 }
884
885 /*
886 * Iterate thru each object identified by the message key.
887 */
888 tlv = op;
889 tlv_len = op_len;
890 FOR_EACH_OBJS(key_uids, num_of_keys, key_uid, {
891 /*
892 * Iterate thru each Operating Attributes.
893 */
894 op = tlv;
895 op_len = tlv_len;
896 FOR_EACH_OP(op, op_len, op_type, {
897 if (op_type == 0) {
898 ec = ISNS_RSP_INVALID_QRY;
899 goto qry_done;
900 }
901 ec = get_qry_ops(key_uid, key_type,
902 op_type, &op_uids,
903 &num_of_ops, &size_of_ops);
904 if (ec != 0) {
905 goto qry_done;
906 }
907 /*
908 * Iterate thru each object for the Operating
909 * Attributes again.
910 */
911 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
912 ec = get_qry_attrs(op_uid, op_type,
913 op, op_len, conn);
914 if (ec != 0) {
915 goto qry_done;
916 }
917 });
918 });
919 });
920 } else {
921 /*
922 * Iterate thru each Operating Attributes.
923 */
924 FOR_EACH_OP(op, op_len, op_type, {
925 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
926 op_type, &op_uids,
927 &num_of_ops, &size_of_ops);
928 if (ec != 0) {
929 goto qry_done;
930 }
931 /*
932 * Iterate thru each object for the Operating
933 * Attributes again.
934 */
935 FOR_EACH_OBJS(op_uids, num_of_ops, op_uid, {
936 ec = get_qry_attrs(op_uid, op_type,
937 op, op_len, conn);
938 if (ec != 0) {
939 goto qry_done;
940 }
941 });
942 });
943 }
944
945 qry_done:
946 conn->ec = ec;
947
948 if (ec != 0) {
949 isnslog(LOG_DEBUG, "dev_attr_qry", "error code: %d", ec);
950 }
951
952 free(nodes_bmp);
953 free(key_uids);
954 free(op_uids);
955
956 return (0);
957 }
958
959 /*
960 * ****************************************************************************
961 *
962 * dev_get_next:
963 * function which handles the isnsp DEV_GET_NEXT message.
964 *
965 * conn - the argument of the connection.
966 * return - 0: the message requires response.
967 *
968 * ****************************************************************************
969 */
970 static int
971 dev_get_next(conn_arg_t *conn)
972 {
973 int ec = 0;
974
975 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
976 isns_tlv_t *source = conn->in_packet.source;
977 isns_tlv_t *key = conn->in_packet.key;
978 uint16_t key_len = conn->in_packet.key_len;
979 isns_tlv_t *op = conn->in_packet.op;
980 uint16_t op_len = conn->in_packet.op_len;
981
982 uchar_t *iscsi_name;
983
984 bmp_t *nodes_bmp = NULL;
985 uint32_t num_of_nodes;
986
987 isns_type_t key_type;
988 isns_type_t op_type;
989 uint32_t size_of_obj;
990 uint32_t num_of_obj;
991 uint32_t *obj_uids = NULL;
992
993 uint32_t uid;
994
995 isnslog(LOG_DEBUG, "dev_get_next", "entered");
996
997 ec = pdu_reset_rsp(&conn->out_packet.pdu,
998 &conn->out_packet.pl,
999 &conn->out_packet.sz);
1000 if (ec != 0) {
1001 goto get_next_done;
1002 }
1003
1004 iscsi_name = (uchar_t *)&source->attr_value[0];
1005 if (is_control_node(iscsi_name) == 0) {
1006 ec = get_scope(iscsi_name, &nodes_bmp, &num_of_nodes);
1007 if (nodes_bmp == NULL) {
1008 ec = ISNS_RSP_NO_SUCH_ENTRY;
1009 }
1010 if (ec != 0) {
1011 goto get_next_done;
1012 }
1013 }
1014
1015 /*
1016 * Get Message Key type and validate the Message Key.
1017 */
1018 key_type = TLV2TYPE(key);
1019 if (key_type == 0) {
1020 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1021 goto get_next_done;
1022 }
1023 ec = validate_qry_key(key_type, key, key_len, NULL);
1024 if (ec != 0) {
1025 goto get_next_done;
1026 }
1027
1028 size_of_obj = 0;
1029 if (op != NULL) {
1030 /*
1031 * Query the objects which match the Operating Attributes.
1032 */
1033 ec = get_qry_keys(nodes_bmp, num_of_nodes, &op_type,
1034 op, op_len, &obj_uids, &num_of_obj);
1035 if (op_type != key_type) {
1036 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1037 }
1038 } else {
1039 /*
1040 * Query the objects which match the Message Key type.
1041 */
1042 ec = get_qry_ops2(nodes_bmp, num_of_nodes,
1043 key_type, &obj_uids, &num_of_obj, &size_of_obj);
1044 }
1045 if (ec != 0) {
1046 goto get_next_done;
1047 }
1048
1049 /*
1050 * Get the object which is next to the one indicated by the
1051 * Message Key.
1052 */
1053 uid = get_next_obj(key, key_len, key_type, obj_uids, num_of_obj);
1054 if (uid == 0) {
1055 ec = ISNS_RSP_NO_SUCH_ENTRY;
1056 goto get_next_done;
1057 }
1058
1059 /*
1060 * Message Key
1061 */
1062 if ((ec = get_qry_attrs1(uid, key_type, key, key_len, conn)) != 0) {
1063 goto get_next_done;
1064 }
1065
1066 /*
1067 * Delimiter
1068 */
1069 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0, NULL, 0)) != 0) {
1070 goto get_next_done;
1071 }
1072
1073 /*
1074 * Operating Attributes
1075 */
1076 if (op != NULL) {
1077 ec = get_qry_attrs(uid, op_type, op, op_len, conn);
1078 }
1079
1080 get_next_done:
1081 conn->ec = ec;
1082
1083 if (ec != 0 && ec != ISNS_RSP_NO_SUCH_ENTRY) {
1084 isnslog(LOG_DEBUG, "dev_get_next", "error code: %d", ec);
1085 }
1086
1087 free(nodes_bmp);
1088 free(obj_uids);
1089
1090 return (0);
1091 }
1092
1093 /*
1094 * ****************************************************************************
1095 *
1096 * dev_dereg:
1097 * function which handles the isnsp DEV_DEREG message.
1098 *
1099 * conn - the argument of the connection.
1100 * return - 0: the message requires response.
1101 *
1102 * ****************************************************************************
1103 */
1104 static int
1105 dev_dereg(conn_arg_t *conn)
1106 {
1107 int ec = 0;
1108
1109 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1110 isns_tlv_t *source = conn->in_packet.source;
1111 /* isns_tlv_t *key = conn->in_packet.key; */
1112 /* uint16_t key_len = conn->in_packet.key_len; */
1113 isns_tlv_t *op = conn->in_packet.op;
1114 uint16_t op_len = conn->in_packet.op_len;
1115
1116 uchar_t *iscsi_name;
1117 int ctrl;
1118 uint32_t puid;
1119
1120 lookup_ctrl_t lc;
1121 uint8_t *value;
1122
1123 isnslog(LOG_DEBUG, "dev_dereg", "entered");
1124
1125 iscsi_name = (uchar_t *)&source->attr_value[0];
1126 ctrl = is_control_node(iscsi_name);
1127 if (ctrl == 0) {
1128 puid = is_parent_there(iscsi_name);
1129 }
1130
1131 while (op_len > 8 && ec == 0) {
1132 lc.curr_uid = 0;
1133 value = &op->attr_value[0];
1134 switch (op->attr_id) {
1135 case ISNS_EID_ATTR_ID:
1136 lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
1137 lc.op[0] = OP_STRING;
1138 lc.data[0].ptr = (uchar_t *)value;
1139 lc.op[1] = 0;
1140 lc.type = OBJ_ENTITY;
1141 break;
1142 case ISNS_ISCSI_NAME_ATTR_ID:
1143 lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
1144 lc.op[0] = OP_STRING;
1145 lc.data[0].ptr = (uchar_t *)value;
1146 lc.op[1] = 0;
1147 lc.type = OBJ_ISCSI;
1148 break;
1149 case ISNS_ISCSI_NODE_INDEX_ATTR_ID:
1150 lc.id[0] = ATTR_INDEX_ISCSI(
1151 ISNS_ISCSI_NODE_INDEX_ATTR_ID);
1152 lc.op[0] = OP_INTEGER;
1153 lc.data[0].ui = ntohl(*(uint32_t *)value);
1154 lc.op[1] = 0;
1155 lc.type = OBJ_ISCSI;
1156 break;
1157 case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1158 lc.id[0] = ATTR_INDEX_PORTAL(
1159 ISNS_PORTAL_IP_ADDR_ATTR_ID);
1160 lc.op[0] = OP_MEMORY_IP6;
1161 lc.data[0].ip = (in6_addr_t *)value;
1162 NEXT_TLV(op, op_len);
1163 if (op_len > 8 &&
1164 op->attr_id == ISNS_PORTAL_PORT_ATTR_ID) {
1165 value = &op->attr_value[0];
1166 lc.id[1] = ATTR_INDEX_PORTAL(
1167 ISNS_PORTAL_PORT_ATTR_ID);
1168 lc.op[1] = OP_INTEGER;
1169 lc.data[1].ui = ntohl(*(uint32_t *)value);
1170 lc.op[2] = 0;
1171 lc.type = OBJ_PORTAL;
1172 } else {
1173 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1174 }
1175 break;
1176 case ISNS_PORTAL_INDEX_ATTR_ID:
1177 lc.id[0] = ATTR_INDEX_PORTAL(
1178 ISNS_PORTAL_INDEX_ATTR_ID);
1179 lc.op[0] = OP_INTEGER;
1180 lc.data[0].ui = ntohl(*(uint32_t *)value);
1181 lc.op[1] = 0;
1182 lc.type = OBJ_PORTAL;
1183 break;
1184 default:
1185 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1186 break;
1187 }
1188 if (ec == 0 &&
1189 (ec = dereg_object(&lc, 0)) == 0) {
1190 if (ctrl == 0 &&
1191 #ifndef SKIP_SRC_AUTH
1192 lc.curr_uid != 0 &&
1193 puid != lc.curr_uid) {
1194 #else
1195 0) {
1196 #endif
1197 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1198 } else {
1199 NEXT_TLV(op, op_len);
1200 }
1201 }
1202 }
1203
1204 conn->ec = ec;
1205
1206 if (ec != 0) {
1207 isnslog(LOG_DEBUG, "dev_dereg", "error code: %d", ec);
1208 }
1209
1210 return (0);
1211 }
1212
1213 /*
1214 * ****************************************************************************
1215 *
1216 * scn_reg:
1217 * function which handles the isnsp SCN_REG message.
1218 *
1219 * conn - the argument of the connection.
1220 * return - 0: the message requires response.
1221 *
1222 * ****************************************************************************
1223 */
1224 static int
1225 scn_reg(conn_arg_t *conn)
1226 {
1227 int ec = 0;
1228
1229 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1230 /* isns_tlv_t *source = conn->in_packet.source; */
1231 isns_tlv_t *key = conn->in_packet.key;
1232 uint16_t key_len = conn->in_packet.key_len;
1233 isns_tlv_t *op = conn->in_packet.op;
1234 uint16_t op_len = conn->in_packet.op_len;
1235
1236 /* uchar_t *src; */
1237 uchar_t *node_name;
1238 uint32_t nlen;
1239 uint32_t scn;
1240
1241 isnslog(LOG_DEBUG, "scn_reg", "entered");
1242
1243 /* src = (uchar_t *)&source->attr_value[0]; */
1244
1245 if (op == NULL ||
1246 op->attr_id != ISNS_ISCSI_SCN_BITMAP_ATTR_ID ||
1247 op_len != 12 ||
1248 key == NULL ||
1249 key->attr_id != ISNS_ISCSI_NAME_ATTR_ID ||
1250 key_len != 8 + key->attr_len) {
1251 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1252 goto scn_reg_done;
1253 }
1254
1255 node_name = (uchar_t *)&key->attr_value[0];
1256 nlen = key->attr_len;
1257 scn = ntohl(*(uint32_t *)&op->attr_value[0]);
1258
1259 ec = add_scn_entry(node_name, nlen, scn);
1260
1261 scn_reg_done:
1262 conn->ec = ec;
1263
1264 if (ec != 0) {
1265 isnslog(LOG_DEBUG, "scn_reg", "error code: %d", ec);
1266 }
1267
1268 return (0);
1269 }
1270
1271 /*
1272 * ****************************************************************************
1273 *
1274 * scn_dereg:
1275 * function which handles the isnsp SCN_DEREG message.
1276 *
1277 * conn - the argument of the connection.
1278 * return - 0: the message requires response.
1279 *
1280 * ****************************************************************************
1281 */
1282 static int
1283 scn_dereg(conn_arg_t *conn)
1284 {
1285 int ec = 0;
1286
1287 isns_tlv_t *key = conn->in_packet.key;
1288 uint16_t key_len = conn->in_packet.key_len;
1289
1290 uchar_t *node_name;
1291
1292 isnslog(LOG_DEBUG, "scn_dereg", "entered");
1293
1294 if (key != NULL &&
1295 key->attr_len != 0 &&
1296 key_len == 8 + key->attr_len &&
1297 key->attr_id == ISNS_ISCSI_NAME_ATTR_ID) {
1298 node_name = (uchar_t *)&key->attr_value[0];
1299 ec = remove_scn_entry(node_name);
1300 } else {
1301 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1302 }
1303
1304 conn->ec = ec;
1305
1306 if (ec != 0) {
1307 isnslog(LOG_DEBUG, "scn_dereg", "error code: %d", ec);
1308 }
1309
1310 return (0);
1311 }
1312
1313 /*
1314 * ****************************************************************************
1315 *
1316 * setup_ddid_lcp:
1317 * setup the lookup control data for looking up the DD object
1318 * by using the dd_id attribute.
1319 *
1320 * lcp - pointer to the lookup control data.
1321 * dd_id- the unique ID of the DD object.
1322 * return - the pointer to the lcp.
1323 *
1324 * ****************************************************************************
1325 */
1326 #ifndef DEBUG
1327 static
1328 #endif
1329 lookup_ctrl_t *
1330 setup_ddid_lcp(lookup_ctrl_t *lcp, uint32_t dd_id)
1331 {
1332 lcp->curr_uid = 0;
1333 lcp->type = OBJ_DD;
1334 lcp->id[0] = ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID);
1335 lcp->op[0] = OP_INTEGER;
1336 lcp->data[0].ui = dd_id;
1337 lcp->op[1] = 0;
1338
1339 return (lcp);
1340 }
1341
1342 /*
1343 * ****************************************************************************
1344 *
1345 * setup_ddsid_lcp:
1346 * setup the lookup control data for looking up the DD-set object
1347 * by using the dds_id attribute.
1348 *
1349 * lcp - pointer to the lookup control data.
1350 * dds_id - the unique ID of the DD-set object.
1351 * return - the pointer to the lcp.
1352 *
1353 * ****************************************************************************
1354 */
1355 #ifndef DEBUG
1356 static
1357 #endif
1358 lookup_ctrl_t *
1359 setup_ddsid_lcp(lookup_ctrl_t *lcp, uint32_t dds_id)
1360 {
1361 lcp->curr_uid = 0;
1362 lcp->type = OBJ_DDS;
1363 lcp->id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID);
1364 lcp->op[0] = OP_INTEGER;
1365 lcp->data[0].ui = dds_id;
1366 lcp->op[1] = 0;
1367
1368 return (lcp);
1369 }
1370
1371 /*
1372 * ****************************************************************************
1373 *
1374 * dd_reg:
1375 * function which handles the isnsp DD_REG message.
1376 *
1377 * conn - the argument of the connection.
1378 * return - 0: the message requires response.
1379 *
1380 * ****************************************************************************
1381 */
1382 static int
1383 dd_reg(conn_arg_t *conn)
1384 {
1385 int ec = 0;
1386
1387 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1388 isns_tlv_t *source = conn->in_packet.source;
1389 isns_tlv_t *key = conn->in_packet.key;
1390 uint16_t key_len = conn->in_packet.key_len;
1391 isns_tlv_t *op = conn->in_packet.op;
1392 uint16_t op_len = conn->in_packet.op_len;
1393
1394 uint32_t dd_id = 0;
1395 uint8_t *value;
1396
1397 isns_obj_t *dd = NULL;
1398
1399 uchar_t *iscsi_name;
1400
1401 lookup_ctrl_t lc;
1402 isns_assoc_iscsi_t aiscsi;
1403 isns_obj_t *assoc;
1404 isns_attr_t *attr;
1405
1406 uint32_t features;
1407
1408 isnslog(LOG_DEBUG, "dd_reg", "entered");
1409
1410 iscsi_name = (uchar_t *)&source->attr_value[0];
1411 if (is_control_node(iscsi_name) == 0) {
1412 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1413 goto dd_reg_done;
1414 }
1415
1416 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1417 &conn->out_packet.pl,
1418 &conn->out_packet.sz);
1419 if (ec != 0) {
1420 goto dd_reg_done;
1421 }
1422
1423 if (op == NULL ||
1424 (key != NULL &&
1425 (key_len != 12 ||
1426 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1427 key->attr_len != 4 ||
1428 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1429 is_obj_there(setup_ddid_lcp(&lc, dd_id)) == 0))) {
1430 ec = ISNS_RSP_INVALID_REGIS;
1431 goto dd_reg_done;
1432 }
1433
1434 /* message key */
1435 if (key != NULL &&
1436 (ec = rsp_add_tlv(conn, ISNS_DD_ID_ATTR_ID, 4,
1437 (void *)dd_id, 0)) != 0) {
1438 goto dd_reg_done;
1439 }
1440
1441 /* delimiter */
1442 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1443 NULL, 0)) != 0) {
1444 goto dd_reg_done;
1445 }
1446
1447 /* A DDReg message with no Message Key SHALL result in the */
1448 /* attempted creation of a new Discovery Domain (DD). */
1449 if (dd_id == 0) {
1450 ec = create_dd_object(op, op_len, &dd);
1451 if (ec == 0) {
1452 ec = register_object(dd, &dd_id, NULL);
1453 if (ec == ERR_NAME_IN_USE) {
1454 ec = ISNS_RSP_INVALID_REGIS;
1455 }
1456 if (ec != 0) {
1457 free_object(dd);
1458 goto dd_reg_done;
1459 }
1460 } else {
1461 goto dd_reg_done;
1462 }
1463 }
1464
1465 /* add the newly created dd to the response */
1466 if (dd != NULL) {
1467 ec = rsp_add_op(conn, dd);
1468 }
1469
1470 aiscsi.type = OBJ_ASSOC_ISCSI;
1471 aiscsi.puid = dd_id;
1472
1473 while (op_len > 8 && ec == 0) {
1474 value = &op->attr_value[0];
1475 switch (op->attr_id) {
1476 case ISNS_DD_ID_ATTR_ID:
1477 /* if the DD_ID is included in both the Message Key */
1478 /* and Operating Attributes, then the DD_ID value */
1479 /* in the Message Key MUST be the same as the DD_ID */
1480 /* value in the Operating Attributes. */
1481 if (dd == NULL) {
1482 if (op->attr_len != 4 ||
1483 dd_id != ntohl(*(uint32_t *)value)) {
1484 ec = ISNS_RSP_INVALID_REGIS;
1485 } else {
1486 ec = rsp_add_tlv(conn,
1487 ISNS_DD_ID_ATTR_ID, 4,
1488 (void *)dd_id, 0);
1489 }
1490 }
1491 break;
1492 case ISNS_DD_NAME_ATTR_ID:
1493 /* It is going to modify the DD Symbolic Name. */
1494 if (dd == NULL) {
1495 if (op->attr_len > 0 && op->attr_len <= 256) {
1496 ec = update_dd_name(
1497 dd_id,
1498 op->attr_len,
1499 (uchar_t *)value);
1500 if (ec == ERR_NAME_IN_USE) {
1501 ec = ISNS_RSP_INVALID_REGIS;
1502 }
1503 } else {
1504 ec = ISNS_RSP_INVALID_REGIS;
1505 }
1506 if (ec == 0) {
1507 ec = rsp_add_tlv(conn,
1508 ISNS_DD_NAME_ATTR_ID,
1509 op->attr_len, (void *)value, 1);
1510 }
1511 }
1512 break;
1513 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1514 if (op->attr_len == 4) {
1515 /* zero the association object */
1516 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1517 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1518 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1519 attr->len = 4;
1520 attr->value.ui = ntohl(*(uint32_t *)value);
1521 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1522 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1523 attr->tag = 0; /* clear it */
1524 attr->value.ptr = NULL; /* clear it */
1525 assoc = (isns_obj_t *)&aiscsi;
1526 if ((ec = add_dd_member(assoc)) ==
1527 ERR_ALREADY_ASSOCIATED) {
1528 ec = 0;
1529 }
1530 if (attr->value.ptr != NULL) {
1531 free(attr->value.ptr);
1532 }
1533 } else {
1534 ec = ISNS_RSP_INVALID_REGIS;
1535 }
1536 if (ec == 0) {
1537 ec = rsp_add_tlv(conn,
1538 ISNS_DD_ISCSI_INDEX_ATTR_ID,
1539 4, (void *)attr->value.ui, 0);
1540 }
1541 break;
1542 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1543 if (op->attr_len > 0 && op->attr_len <= 224) {
1544 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1545 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1546 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1547 attr->len = op->attr_len;
1548 attr->value.ptr = (uchar_t *)value;
1549 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1550 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1551 attr->tag = 0; /* clear it */
1552 assoc = (isns_obj_t *)&aiscsi;
1553 if ((ec = add_dd_member(assoc)) ==
1554 ERR_ALREADY_ASSOCIATED) {
1555 ec = 0;
1556 }
1557 } else {
1558 ec = ISNS_RSP_INVALID_REGIS;
1559 }
1560 if (ec == 0) {
1561 ec = rsp_add_tlv(conn,
1562 ISNS_DD_ISCSI_NAME_ATTR_ID,
1563 op->attr_len, (void *)value, 1);
1564 }
1565 break;
1566 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1567 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1568 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1569 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1570 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1571 break;
1572 case ISNS_DD_FEATURES_ATTR_ID:
1573 /* It is going to modify the DD Symbolic Name. */
1574 if (dd == NULL) {
1575 if (op->attr_len == 4) {
1576 features = ntohl(*(uint32_t *)value);
1577 ec = update_dd_features(
1578 dd_id, features);
1579 } else {
1580 ec = ISNS_RSP_INVALID_REGIS;
1581 }
1582 if (ec == 0) {
1583 ec = rsp_add_tlv(conn,
1584 ISNS_DD_FEATURES_ATTR_ID,
1585 4, (void *)features, 0);
1586 }
1587 }
1588 break;
1589 default:
1590 ec = ISNS_RSP_INVALID_REGIS;
1591 break;
1592 }
1593
1594 NEXT_TLV(op, op_len);
1595 }
1596
1597 dd_reg_done:
1598 conn->ec = ec;
1599
1600 if (ec != 0) {
1601 isnslog(LOG_DEBUG, "dd_reg", "error code: %d", ec);
1602 }
1603
1604 return (0);
1605 }
1606
1607 /*
1608 * ****************************************************************************
1609 *
1610 * dds_reg:
1611 * function which handles the isnsp DDS_REG message.
1612 *
1613 * conn - the argument of the connection.
1614 * return - 0: the message requires response.
1615 *
1616 * ****************************************************************************
1617 */
1618 static int
1619 dds_reg(conn_arg_t *conn)
1620 {
1621 int ec = 0;
1622
1623 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1624 isns_tlv_t *source = conn->in_packet.source;
1625 isns_tlv_t *key = conn->in_packet.key;
1626 uint16_t key_len = conn->in_packet.key_len;
1627 isns_tlv_t *op = conn->in_packet.op;
1628 uint16_t op_len = conn->in_packet.op_len;
1629
1630 uint32_t dds_id = 0;
1631 uint8_t *value;
1632
1633 isns_obj_t *dds = NULL;
1634
1635 uchar_t *iscsi_name;
1636
1637 lookup_ctrl_t lc;
1638 isns_assoc_dd_t add;
1639 isns_obj_t *assoc;
1640 isns_attr_t *attr;
1641
1642 uint32_t code;
1643
1644 isnslog(LOG_DEBUG, "dds_reg", "entered");
1645
1646 iscsi_name = (uchar_t *)&source->attr_value[0];
1647 if (is_control_node(iscsi_name) == 0) {
1648 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1649 goto dds_reg_done;
1650 }
1651
1652 ec = pdu_reset_rsp(&conn->out_packet.pdu,
1653 &conn->out_packet.pl,
1654 &conn->out_packet.sz);
1655 if (ec != 0) {
1656 goto dds_reg_done;
1657 }
1658
1659 if (op == NULL ||
1660 (key != NULL &&
1661 (key_len != 12 ||
1662 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
1663 key->attr_len != 4 ||
1664 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0 ||
1665 is_obj_there(setup_ddsid_lcp(&lc, dds_id)) == 0))) {
1666 ec = ISNS_RSP_INVALID_REGIS;
1667 goto dds_reg_done;
1668 }
1669
1670 /* message key */
1671 if (key != NULL &&
1672 (ec = rsp_add_tlv(conn, ISNS_DD_SET_ID_ATTR_ID, 4,
1673 (void *)dds_id, 0)) != 0) {
1674 goto dds_reg_done;
1675 }
1676
1677 /* delimiter */
1678 if ((ec = rsp_add_tlv(conn, ISNS_DELIMITER_ATTR_ID, 0,
1679 NULL, 0)) != 0) {
1680 goto dds_reg_done;
1681 }
1682
1683 /* A DDSReg message with no Message Key SHALL result in the */
1684 /* attempted creation of a new Discovery Domain (DD). */
1685 if (dds_id == 0) {
1686 ec = create_dds_object(op, op_len, &dds);
1687 if (ec == 0) {
1688 ec = register_object(dds, &dds_id, NULL);
1689 if (ec == ERR_NAME_IN_USE) {
1690 ec = ISNS_RSP_INVALID_REGIS;
1691 }
1692 if (ec != 0) {
1693 free_object(dds);
1694 goto dds_reg_done;
1695 }
1696 } else {
1697 goto dds_reg_done;
1698 }
1699 }
1700
1701 /* add the newly created dd to the response */
1702 if (dds != NULL) {
1703 ec = rsp_add_op(conn, dds);
1704 }
1705
1706 add.type = OBJ_ASSOC_DD;
1707 add.puid = dds_id;
1708
1709 while (op_len > 8 && ec == 0) {
1710 value = &op->attr_value[0];
1711 switch (op->attr_id) {
1712 case ISNS_DD_SET_ID_ATTR_ID:
1713 /* if the DDS_ID is included in both the Message Key */
1714 /* and Operating Attributes, then the DDS_ID value */
1715 /* in the Message Key MUST be the same as the DDS_ID */
1716 /* value in the Operating Attributes. */
1717 if (dds == NULL) {
1718 if (op->attr_len != 4 ||
1719 dds_id != ntohl(*(uint32_t *)value)) {
1720 ec = ISNS_RSP_INVALID_REGIS;
1721 } else {
1722 ec = rsp_add_tlv(conn,
1723 ISNS_DD_SET_ID_ATTR_ID,
1724 4, (void *)dds_id, 0);
1725 }
1726 }
1727 break;
1728 case ISNS_DD_SET_NAME_ATTR_ID:
1729 /* It is going to modify the DD Symbolic Name. */
1730 if (dds == NULL) {
1731 if (op->attr_len > 0 && op->attr_len <= 256) {
1732 ec = update_dds_name(
1733 dds_id,
1734 op->attr_len,
1735 (uchar_t *)value);
1736 if (ec == ERR_NAME_IN_USE) {
1737 ec = ISNS_RSP_INVALID_REGIS;
1738 }
1739 } else {
1740 ec = ISNS_RSP_INVALID_REGIS;
1741 }
1742 if (ec == 0) {
1743 ec = rsp_add_tlv(conn,
1744 ISNS_DD_SET_NAME_ATTR_ID,
1745 op->attr_len, (void *)value, 1);
1746 }
1747 }
1748 break;
1749 case ISNS_DD_SET_STATUS_ATTR_ID:
1750 /* It is going to modify the DD Symbolic Name. */
1751 if (dds == NULL) {
1752 if (op->attr_len == 4) {
1753 code = ntohl(*(uint32_t *)value);
1754 ec = update_dds_status(
1755 dds_id, code);
1756 } else {
1757 ec = ISNS_RSP_INVALID_REGIS;
1758 }
1759 if (ec == 0) {
1760 ec = rsp_add_tlv(conn,
1761 ISNS_DD_SET_STATUS_ATTR_ID,
1762 4, (void *)code, 0);
1763 }
1764 }
1765 break;
1766 case ISNS_DD_ID_ATTR_ID:
1767 if (op->attr_len == 4) {
1768 /* zero the association object */
1769 attr = &add.attrs[ATTR_INDEX_ASSOC_DD(
1770 ISNS_DD_ID_ATTR_ID)];
1771 attr->tag = ISNS_DD_ID_ATTR_ID;
1772 attr->len = 4;
1773 attr->value.ui = ntohl(*(uint32_t *)value);
1774 assoc = (isns_obj_t *)&add;
1775 if ((ec = add_dds_member(assoc)) ==
1776 ERR_ALREADY_ASSOCIATED) {
1777 ec = 0;
1778 }
1779 } else {
1780 ec = ISNS_RSP_INVALID_REGIS;
1781 }
1782 if (ec == 0) {
1783 ec = rsp_add_tlv(conn,
1784 ISNS_DD_ID_ATTR_ID, 4,
1785 (void *)attr->value.ui, 0);
1786 }
1787 break;
1788 default:
1789 ec = ISNS_RSP_INVALID_REGIS;
1790 break;
1791 }
1792
1793 NEXT_TLV(op, op_len);
1794 }
1795
1796 dds_reg_done:
1797 conn->ec = ec;
1798
1799 if (ec != 0) {
1800 isnslog(LOG_DEBUG, "dds_reg", "error code: %d", ec);
1801 }
1802
1803 return (0);
1804 }
1805
1806 /*
1807 * ****************************************************************************
1808 *
1809 * dd_dereg:
1810 * function which handles the isnsp DD_DEREG message.
1811 *
1812 * conn - the argument of the connection.
1813 * return - 0: the message requires response.
1814 *
1815 * ****************************************************************************
1816 */
1817 static int
1818 dd_dereg(conn_arg_t *conn)
1819 {
1820 int ec = 0;
1821
1822 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1823 isns_tlv_t *source = conn->in_packet.source;
1824 isns_tlv_t *key = conn->in_packet.key;
1825 uint16_t key_len = conn->in_packet.key_len;
1826 isns_tlv_t *op = conn->in_packet.op;
1827 uint16_t op_len = conn->in_packet.op_len;
1828
1829 uint32_t dd_id;
1830 uint8_t *value;
1831
1832 uchar_t *iscsi_name;
1833
1834 isns_assoc_iscsi_t aiscsi;
1835 isns_obj_t *assoc;
1836 isns_attr_t *attr;
1837
1838 isnslog(LOG_DEBUG, "dd_dereg", "entered");
1839
1840 iscsi_name = (uchar_t *)&source->attr_value[0];
1841 if (is_control_node(iscsi_name) == 0) {
1842 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1843 goto dd_dereg_done;
1844 }
1845
1846 if (key == NULL ||
1847 key_len != 12 ||
1848 key->attr_id != ISNS_DD_ID_ATTR_ID ||
1849 (dd_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
1850 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1851 goto dd_dereg_done;
1852 }
1853
1854 if (op == NULL) {
1855 ec = remove_dd_object(dd_id);
1856 } else {
1857 aiscsi.type = OBJ_ASSOC_ISCSI;
1858 aiscsi.puid = dd_id;
1859
1860 while (op_len > 8 && ec == 0) {
1861 value = &op->attr_value[0];
1862 switch (op->attr_id) {
1863 case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1864 /* zero the association object */
1865 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1866 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1867 attr->tag = ISNS_DD_ISCSI_INDEX_ATTR_ID;
1868 attr->len = 4;
1869 attr->value.ui = ntohl(*(uint32_t *)value);
1870 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1871 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1872 attr->tag = 0; /* clear it */
1873 attr->value.ptr = NULL; /* clear it */
1874 assoc = (isns_obj_t *)&aiscsi;
1875 if ((ec = remove_dd_member(assoc)) ==
1876 ERR_NO_SUCH_ASSOCIATION) {
1877 ec = 0;
1878 }
1879 if (attr->value.ptr != NULL) {
1880 free(attr->value.ptr);
1881 }
1882 break;
1883 case ISNS_DD_ISCSI_NAME_ATTR_ID:
1884 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1885 ISNS_DD_ISCSI_NAME_ATTR_ID)];
1886 attr->tag = ISNS_DD_ISCSI_NAME_ATTR_ID;
1887 attr->len = op->attr_len;
1888 attr->value.ptr = (uchar_t *)value;
1889 attr = &aiscsi.attrs[ATTR_INDEX_ASSOC_ISCSI(
1890 ISNS_DD_ISCSI_INDEX_ATTR_ID)];
1891 attr->tag = 0; /* clear it */
1892 assoc = (isns_obj_t *)&aiscsi;
1893 if ((ec = remove_dd_member(assoc)) ==
1894 ERR_NO_SUCH_ASSOCIATION) {
1895 ec = 0;
1896 }
1897 break;
1898 case ISNS_DD_FC_PORT_NAME_ATTR_ID:
1899 case ISNS_DD_PORTAL_INDEX_ATTR_ID:
1900 case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
1901 case ISNS_DD_PORTAL_PORT_ATTR_ID:
1902 ec = ISNS_RSP_REGIS_NOT_SUPPORTED;
1903 break;
1904 default:
1905 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1906 break;
1907 }
1908
1909 NEXT_TLV(op, op_len);
1910 }
1911 }
1912
1913 dd_dereg_done:
1914 conn->ec = ec;
1915
1916 if (ec != 0) {
1917 isnslog(LOG_DEBUG, "dd_dereg", "error code: %d", ec);
1918 }
1919
1920 return (0);
1921 }
1922
1923 /*
1924 * ****************************************************************************
1925 *
1926 * dds_dereg:
1927 * function which handles the isnsp DDS_DEREG message.
1928 *
1929 * conn - the argument of the connection.
1930 * return - 0: the message requires response.
1931 *
1932 * ****************************************************************************
1933 */
1934 static int
1935 dds_dereg(conn_arg_t *conn)
1936 {
1937 int ec = 0;
1938
1939 /* isns_pdu_t *pdu = conn->in_packet.pdu; */
1940 isns_tlv_t *source = conn->in_packet.source;
1941 isns_tlv_t *key = conn->in_packet.key;
1942 uint16_t key_len = conn->in_packet.key_len;
1943 isns_tlv_t *op = conn->in_packet.op;
1944 uint16_t op_len = conn->in_packet.op_len;
1945
1946 uint32_t dds_id;
1947 uint32_t uid;
1948 uint8_t *value;
1949
1950 uchar_t *iscsi_name;
1951
1952 isnslog(LOG_DEBUG, "dds_dereg", "entered");
1953
1954 iscsi_name = (uchar_t *)&source->attr_value[0];
1955 if (is_control_node(iscsi_name) == 0) {
1956 ec = ISNS_RSP_SRC_UNAUTHORIZED;
1957 goto dds_dereg_done;
1958 }
1959
1960 if (key == NULL ||
1961 key_len != 12 ||
1962 key->attr_id != ISNS_DD_SET_ID_ATTR_ID ||
1963 (dds_id = ntohl(*(uint32_t *)&key->attr_value[0])) == 0) {
1964 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1965 goto dds_dereg_done;
1966 }
1967
1968 if (op == NULL) {
1969 ec = remove_dds_object(dds_id);
1970 } else {
1971 while (op_len > 8 && ec == 0) {
1972 value = &op->attr_value[0];
1973 if (op->attr_id == ISNS_DD_ID_ATTR_ID) {
1974 uid = ntohl(*(uint32_t *)value);
1975 if ((ec = remove_dds_member(dds_id, uid)) ==
1976 ERR_NO_SUCH_ASSOCIATION) {
1977 ec = 0;
1978 }
1979 } else {
1980 ec = ISNS_RSP_MSG_FORMAT_ERROR;
1981 }
1982
1983 NEXT_TLV(op, op_len);
1984 }
1985 }
1986
1987 dds_dereg_done:
1988 conn->ec = ec;
1989
1990 if (ec != 0) {
1991 isnslog(LOG_DEBUG, "dds_dereg", "error code: %d", ec);
1992 }
1993
1994 return (0);
1995 }
1996
1997 /*
1998 * ****************************************************************************
1999 *
2000 * msg_error:
2001 * function which handles any unknown isnsp messages or the
2002 * messages which are not supported.
2003 *
2004 * conn - the argument of the connection.
2005 * return - 0: the message requires response.
2006 *
2007 * ****************************************************************************
2008 */
2009 static int
2010 msg_error(conn_arg_t *conn __unused)
2011 {
2012 return (0);
2013 }
2014
2015 /*
2016 * ****************************************************************************
2017 *
2018 * isns_response_ec:
2019 * send the response message to the client with error code.
2020 *
2021 * so - the socket descriptor.
2022 * pdu - the received pdu.
2023 * ec - the error code which is being responsed.
2024 * return - status of the sending operation.
2025 *
2026 * ****************************************************************************
2027 */
2028 static int
2029 isns_response_ec(int so, isns_pdu_t *pdu, int ec)
2030 {
2031 int status;
2032
2033 uint8_t buff[sizeof (isns_pdu_t) + 8];
2034
2035 isns_pdu_t *rsp = (isns_pdu_t *)&buff;
2036 isns_resp_t *resp = (isns_resp_t *)rsp->payload;
2037 size_t pl = 4;
2038
2039 rsp->version = htons((uint16_t)ISNSP_VERSION);
2040 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2041 rsp->xid = htons(pdu->xid);
2042 resp->status = htonl(ec);
2043
2044 status = isns_send_pdu(so, rsp, pl);
2045
2046 return (status);
2047 }
2048
2049 /*
2050 * ****************************************************************************
2051 *
2052 * isns_response:
2053 * send the response message to the client.
2054 *
2055 * conn - the argument of the connection.
2056 * return - status of the sending operation.
2057 *
2058 * ****************************************************************************
2059 */
2060 int
2061 isns_response(conn_arg_t *conn)
2062 {
2063 int status;
2064
2065 int so = conn->so;
2066 int ec = conn->ec;
2067 isns_pdu_t *pdu = conn->in_packet.pdu;
2068 isns_pdu_t *rsp = conn->out_packet.pdu;
2069 size_t pl = conn->out_packet.pl;
2070
2071 if (rsp != NULL) {
2072 rsp->version = htons((uint16_t)ISNSP_VERSION);
2073 rsp->func_id = htons(pdu->func_id | ISNS_RSP_MASK);
2074 rsp->xid = htons(pdu->xid);
2075 (void) pdu_update_code(rsp, &pl, ec);
2076 status = isns_send_pdu(so, rsp, pl);
2077 } else {
2078 status = isns_response_ec(so, pdu, ec);
2079 }
2080
2081 return (status);
2082 }
2083