xref: /illumos-gate/usr/src/cmd/isns/isnsd/obj.c (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
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 2009 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 <string.h>
30 #include <pthread.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 
36 #include "isns_server.h"
37 #include "isns_msgq.h"
38 #include "isns_htab.h"
39 #include "isns_cache.h"
40 #include "isns_pdu.h"
41 #include "isns_obj.h"
42 #include "isns_dd.h"
43 #include "isns_func.h"
44 #include "isns_dseng.h"
45 #include "isns_log.h"
46 #include "isns_scn.h"
47 #include "isns_utils.h"
48 #include "isns_esi.h"
49 
50 /*
51  * external variables
52  */
53 #ifdef DEBUG
54 extern int verbose_mc;
55 extern void print_object(char *, isns_obj_t *);
56 #endif
57 
58 extern msg_queue_t *sys_q;
59 extern msg_queue_t *scn_q;
60 
61 extern pthread_mutex_t el_mtx;
62 
63 extern int cache_flag;
64 
65 /*
66  * global data
67  */
68 
69 /*
70  * local variables
71  */
72 /* type of parent object */
73 const int TYPE_OF_PARENT[MAX_OBJ_TYPE_FOR_SIZE] = {
74 	0,
75 	0,
76 	ISCSI_PARENT_TYPE,
77 	PORTAL_PARENT_TYPE,
78 	PG_PARENT_TYPE,
79 	0,	/* OBJ_DD */
80 	0,	/* OBJ_DDS */
81 	0,	/* MAX_OBJ_TYPE */
82 	0,	/* OBJ_DUMMY1 */
83 	0,	/* OBJ_DUMMY2 */
84 	0,	/* OBJ_DUMMY3 */
85 	0,	/* OBJ_DUMMY4 */
86 	ASSOC_ISCSI_PARENT_TYPE,
87 	ASSOC_DD_PARENT_TYPE
88 };
89 
90 /* number of children object type */
91 const int NUM_OF_CHILD[MAX_OBJ_TYPE] = {
92 	0,
93 	MAX_ENTITY_CHILD,
94 	MAX_ISCSI_CHILD,
95 	MAX_PORTAL_CHILD,
96 	MAX_PG_CHILD,
97 	0,
98 	0
99 };
100 
101 /* type of a child object */
102 const int TYPE_OF_CHILD[MAX_OBJ_TYPE][MAX_CHILD_TYPE] = {
103 	{ 0, 0 },
104 	{ OBJ_ISCSI, OBJ_PORTAL },
105 	{ 0, 0 },
106 	{ 0, 0 },
107 	{ 0, 0 },
108 	{ 0, 0 },
109 	{ 0, 0 }
110 };
111 
112 /* number of attributes of certain type of object */
113 const int NUM_OF_ATTRS[MAX_OBJ_TYPE_FOR_SIZE] = {
114 	0,
115 	NUM_OF_ENTITY_ATTRS,
116 	NUM_OF_ISCSI_ATTRS,
117 	NUM_OF_PORTAL_ATTRS,
118 	NUM_OF_PG_ATTRS,
119 	NUM_OF_DD_ATTRS,
120 	NUM_OF_DDS_ATTRS,
121 	0,			/* MAX_OBJ_TYPE */
122 	0,			/* OBJ_DUMMY1 */
123 	0,			/* OBJ_DUMMY2 */
124 	0,			/* OBJ_DUMMY3 */
125 	0,			/* OBJ_DUMMY4 */
126 	NUM_OF_ASSOC_ISCSI_ATTRS,
127 	NUM_OF_ASSOC_DD_ATTRS
128 };
129 
130 /* the tag of UID of each type of object */
131 static const int UID_TAG[MAX_OBJ_TYPE_FOR_SIZE] = {
132 	0,
133 	ISNS_ENTITY_INDEX_ATTR_ID,
134 	ISNS_ISCSI_NODE_INDEX_ATTR_ID,
135 	ISNS_PORTAL_INDEX_ATTR_ID,
136 	ISNS_PG_INDEX_ATTR_ID,
137 	ISNS_DD_ID_ATTR_ID,
138 	ISNS_DD_SET_ID_ATTR_ID,
139 	0,			/* MAX_OBJ_TYPE */
140 	0,			/* OBJ_DUMMY1 */
141 	0,			/* OBJ_DUMMY2 */
142 	0,			/* OBJ_DUMMY3 */
143 	0,			/* OBJ_DUMMY4 */
144 	ISNS_DD_ISCSI_INDEX_ATTR_ID,
145 	ISNS_DD_ID_ATTR_ID
146 };
147 
148 /* the index of UID of each type of object */
149 const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE] = {
150 	0,
151 	ATTR_INDEX_ENTITY(ISNS_ENTITY_INDEX_ATTR_ID),
152 	ATTR_INDEX_ISCSI(ISNS_ISCSI_NODE_INDEX_ATTR_ID),
153 	ATTR_INDEX_PORTAL(ISNS_PORTAL_INDEX_ATTR_ID),
154 	ATTR_INDEX_PG(ISNS_PG_INDEX_ATTR_ID),
155 	ATTR_INDEX_DD(ISNS_DD_ID_ATTR_ID),
156 	ATTR_INDEX_DDS(ISNS_DD_SET_ID_ATTR_ID),
157 	0,			/* MAX_OBJ_TYPE */
158 	0,			/* OBJ_DUMMY1 */
159 	0,			/* OBJ_DUMMY2 */
160 	0,			/* OBJ_DUMMY3 */
161 	0,			/* OBJ_DUMMY4 */
162 	ATTR_INDEX_ASSOC_ISCSI(ISNS_DD_ISCSI_INDEX_ATTR_ID),
163 	ATTR_INDEX_ASSOC_DD(ISNS_DD_ID_ATTR_ID)
164 };
165 
166 /* the index of the key attributes of each type of object */
167 static const int KEY_ATTR_INDEX[MAX_OBJ_TYPE][MAX_KEY_ATTRS] = {
168 	{ 0 },
169 	{ ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID), 0 },
170 	{ ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID),
171 		0 },
172 	{ ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID),
173 		ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID),
174 		0 },
175 	{ ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID),
176 		ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID),
177 		ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID) },
178 	{ ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID), 0 },
179 	{ ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID), 0 }
180 };
181 
182 /* the operating methods for key attributes of each type of object */
183 static const int KEY_ATTR_OP[MAX_OBJ_TYPE][MAX_KEY_ATTRS] = {
184 	{ 0 },
185 	{ OP_STRING, 0 },
186 	{ OP_STRING, 0 },
187 	{ OP_MEMORY_IP6, OP_INTEGER, 0 },
188 	{ OP_STRING, OP_MEMORY_IP6, OP_INTEGER },
189 	{ OP_STRING, 0 },
190 	{ OP_STRING, 0 }
191 };
192 
193 /* the size of each type of object */
194 static const int SIZEOF_OBJ[MAX_OBJ_TYPE_FOR_SIZE] = {
195 	0,
196 	sizeof (isns_entity_t),
197 	sizeof (isns_iscsi_t),
198 	sizeof (isns_portal_t),
199 	sizeof (isns_pg_t),
200 	sizeof (isns_dd_t),
201 	sizeof (isns_dds_t),
202 	0,
203 	0,
204 	0,
205 	0,
206 	0,
207 	sizeof (isns_assoc_iscsi_t),
208 	sizeof (isns_assoc_dd_t)
209 };
210 
211 #ifdef DEBUG
212 const int NUM_OF_REF[MAX_OBJ_TYPE_FOR_SIZE] = {
213 #else
214 static const int NUM_OF_REF[MAX_OBJ_TYPE_FOR_SIZE] = {
215 #endif
216 	0,
217 	0,
218 	0,
219 	0,
220 	PG_REF_COUNT,
221 	0,
222 	0,
223 	0,
224 	0,
225 	0,
226 	0,
227 	0,
228 	0,
229 	0
230 };
231 
232 /* the type of the reference object */
233 static const int TYPE_OF_REF[MAX_OBJ_TYPE][MAX_REF_COUNT + 1] = {
234 	{ 0 },
235 	{ 0 },
236 	{ OBJ_PG, OBJ_PORTAL, 0 },
237 	{ OBJ_PG, OBJ_ISCSI, 0 },
238 	{ 0, OBJ_ISCSI, OBJ_PORTAL },
239 	{ 0 },
240 	{ 0 }
241 };
242 
243 /* the operating method for match operation of the reference object */
244 #define	MAX_REF_MATCH	(2)
245 static const int REF_MATCH_OPS[MAX_OBJ_TYPE][MAX_REF_MATCH] = {
246 	{ 0, 0 },
247 	{ 0, 0 },
248 	{ OP_STRING, 0 },
249 	{ OP_MEMORY_IP6, OP_INTEGER },
250 	{ 0, 0 },
251 	{ 0, 0 },
252 	{ 0, 0 }
253 };
254 
255 /* the index of the attribute of being matched object */
256 static const int REF_MATCH_ID1[MAX_OBJ_TYPE][MAX_REF_MATCH] = {
257 	{ 0, 0 },
258 	{ 0, 0 },
259 	{ ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID), 0 },
260 	{ ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID),
261 		ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID) },
262 	{ 0, 0 },
263 	{ 0, 0 },
264 	{ 0, 0 }
265 };
266 
267 /* the index of the attribute of matching object */
268 static const int REF_MATCH_ID2[MAX_OBJ_TYPE][MAX_REF_MATCH] = {
269 	{ 0, 0 },
270 	{ 0, 0 },
271 	{ ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID), 0 },
272 	{ ATTR_INDEX_PG(ISNS_PG_PORTAL_IP_ADDR_ATTR_ID),
273 		ATTR_INDEX_PG(ISNS_PG_PORTAL_PORT_ATTR_ID) },
274 	{ 0, 0 },
275 	{ 0, 0 },
276 	{ 0, 0 }
277 };
278 
279 /*
280  * local functions.
281  */
282 static uint32_t get_reg_period();
283 static char *make_unique_name(int *, uint32_t);
284 static lookup_ctrl_t *set_lookup_ctrl(lookup_ctrl_t *, isns_obj_t *);
285 static int setup_ref_lcp(lookup_ctrl_t *,
286 	const isns_obj_t *, const isns_obj_t *);
287 static int setup_deref_lcp(lookup_ctrl_t *,
288 	const isns_obj_t *, isns_type_t);
289 static int cb_get_parent(void *, void *);
290 static int cb_node_child(void *, void *);
291 static int cb_set_ref(void *, void *);
292 static int cb_clear_ref(void *, void *);
293 static int cb_add_child(void *, void *);
294 static int cb_remove_child(void *, void *);
295 static int cb_verify_ref(void *, void *);
296 static int cb_ref_new2old(void *, void *);
297 static int cb_new_ref(void *, void *);
298 static int ref_new2old(
299 	lookup_ctrl_t *, isns_type_t, uint32_t, const isns_obj_t *);
300 static int ref_new2new(
301 	lookup_ctrl_t *, const isns_obj_t *, const isns_obj_t *);
302 static int new_ref(const isns_obj_t *, const isns_obj_t *);
303 static uint32_t setup_parent_lcp(lookup_ctrl_t *, isns_obj_t *);
304 static int set_obj_offline(isns_obj_t *);
305 static int copy_attrs(isns_obj_t *, const isns_obj_t *);
306 
307 static isns_obj_t *make_default_pg(const isns_obj_t *, const isns_obj_t *);
308 static isns_obj_t *(*const make_ref[MAX_OBJ_TYPE])
309 	(const isns_obj_t *, const isns_obj_t *) = {
310 		NULL,
311 		NULL,
312 		&make_default_pg,
313 		&make_default_pg,
314 		NULL,
315 		NULL,
316 		NULL
317 };
318 
319 static uint32_t entity_hval(void *, uint16_t, uint32_t *);
320 static uint32_t iscsi_hval(void *, uint16_t, uint32_t *);
321 static uint32_t portal_hval(void *, uint16_t, uint32_t *);
322 static uint32_t pg_hval(void *, uint16_t, uint32_t *);
323 static uint32_t dd_hval(void *, uint16_t, uint32_t *);
324 static uint32_t dds_hval(void *, uint16_t, uint32_t *);
325 static uint32_t (*const hval_func[MAX_OBJ_TYPE])
326 	(void *, uint16_t, uint32_t *) = {
327 		NULL,
328 		&entity_hval,
329 		&iscsi_hval,
330 		&portal_hval,
331 		&pg_hval,
332 		&dd_hval,
333 		&dds_hval
334 };
335 
336 /*
337  * ****************************************************************************
338  *
339  * entity_hval:
340  *	caculate the hash value of a network entity object.
341  *
342  * p	- the pointer pointers to network entity object or
343  *	  the lookup control data, both have the key attribute
344  *	  of a network entity object.
345  * chunk- which chunk of the hash table.
346  * flags- pointer to flags.
347  * return - the hash value.
348  *
349  * ****************************************************************************
350  */
351 static uint32_t
352 entity_hval(
353 	void *p,
354 	/* LINTED E_FUNC_ARG_UNUSED */
355 	uint16_t chunk,
356 	uint32_t *flags
357 )
358 {
359 	uchar_t *key;
360 	isns_obj_t *obj;
361 	lookup_ctrl_t *lcp;
362 
363 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
364 		/* p pointers to a network entity object */
365 		obj = (isns_obj_t *)p;
366 		key = obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)].
367 		    value.ptr;
368 	} else {
369 		/* p is lookup control data */
370 		lcp = (lookup_ctrl_t *)p;
371 		key = lcp->data[0].ptr;
372 	}
373 
374 	return (htab_compute_hval(key));
375 }
376 
377 /*
378  * ****************************************************************************
379  *
380  * iscsi_hval:
381  *	caculate the hash value of an iscsi storage node object.
382  *
383  * p	- the pointer pointers to iscsi storage node object or
384  *	  the lookup control data, both have the key attribute
385  *	  of an iscsi storage node object.
386  * chunk- which chunk of the hash table.
387  * flags- pointer to flags.
388  * return - the hash value.
389  *
390  * ****************************************************************************
391  */
392 static uint32_t
393 iscsi_hval(
394 	void *p,
395 	/* LINTED E_FUNC_ARG_UNUSED */
396 	uint16_t chunk,
397 	uint32_t *flags
398 )
399 {
400 	uchar_t *key;
401 	isns_obj_t *obj;
402 	lookup_ctrl_t *lcp;
403 
404 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
405 		/* p pointers to an iscsi storage node object */
406 		obj = (isns_obj_t *)p;
407 		key = obj->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)].
408 		    value.ptr;
409 	} else {
410 		/* p is lookup control data */
411 		lcp = (lookup_ctrl_t *)p;
412 		key = lcp->data[0].ptr;
413 	}
414 
415 	return (htab_compute_hval(key));
416 }
417 
418 /*
419  * ****************************************************************************
420  *
421  * portal_hval:
422  *	caculate the hash value of a portal object.
423  *
424  * p	- the pointer pointers to a portal object or the lookup control
425  *	  data, both have the key attributes of a portal object.
426  * chunk- which chunk of the hash table.
427  * flags- pointer to flags.
428  * return - the hash value.
429  *
430  * ****************************************************************************
431  */
432 static uint32_t
433 portal_hval(
434 	void *p,
435 	/* LINTED E_FUNC_ARG_UNUSED */
436 	uint16_t chunk,
437 	uint32_t *flags
438 )
439 {
440 	char buff[INET6_ADDRSTRLEN + 8] = { 0 };
441 	char buff2[8] = { 0 };
442 	uchar_t *key;
443 	isns_obj_t *obj;
444 	lookup_ctrl_t *lcp;
445 
446 	in6_addr_t *ip;
447 	uint32_t port;
448 
449 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
450 		/* p pointers to a portal object */
451 		obj = (isns_obj_t *)p;
452 		ip = obj->attrs[ATTR_INDEX_PORTAL
453 		    (ISNS_PORTAL_IP_ADDR_ATTR_ID)].value.ip;
454 		port = obj->attrs[ATTR_INDEX_PORTAL
455 		    (ISNS_PORTAL_PORT_ATTR_ID)].value.ui;
456 	} else {
457 		/* p is lookup control data */
458 		lcp = (lookup_ctrl_t *)p;
459 		ip = lcp->data[0].ip;
460 		port = lcp->data[1].ui;
461 	}
462 
463 	key = (uchar_t *)inet_ntop(AF_INET6, (void *)ip,
464 	    buff, sizeof (buff));
465 	(void) snprintf(buff2, sizeof (buff2), "%d", port);
466 	(void) strcat((char *)key, buff2);
467 
468 	return (htab_compute_hval(key));
469 }
470 
471 /*
472  * ****************************************************************************
473  *
474  * pg_hval:
475  *	caculate the hash value of a portal group object.
476  *
477  * p	- the pointer pointers to a portal group object or the lookup
478  *	  control data, both have the key attributes of a portal object.
479  * chunk- which chunk of the hash table.
480  * flags- pointer to flags.
481  * return - the hash value.
482  *
483  * ****************************************************************************
484  */
485 static uint32_t
486 pg_hval(
487 	void *p,
488 	uint16_t chunk,
489 	uint32_t *flags
490 )
491 {
492 	char buff[INET6_ADDRSTRLEN + 8] = { 0 };
493 	char buff2[8] = { 0 };
494 	uchar_t *key = NULL;
495 	isns_obj_t *obj;
496 	lookup_ctrl_t *lcp;
497 
498 	in6_addr_t *ip = NULL;
499 	uint32_t port;
500 
501 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
502 		/* p is a portal group object */
503 		obj = (isns_obj_t *)p;
504 		if (chunk == 0) {
505 			/* the first chunk */
506 			key = obj->attrs[ATTR_INDEX_PG
507 			    (ISNS_PG_ISCSI_NAME_ATTR_ID)].value.ptr;
508 		} else {
509 			/* another chunk */
510 			ip = obj->attrs[ATTR_INDEX_PG
511 			    (ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)].value.ip;
512 			port = obj->attrs[ATTR_INDEX_PG
513 			    (ISNS_PG_PORTAL_PORT_ATTR_ID)].value.ui;
514 		}
515 	} else {
516 		/* p is a lookup control data */
517 		lcp = (lookup_ctrl_t *)p;
518 		/* clear the chunk flags */
519 		*flags &= ~FLAGS_CHUNK_MASK;
520 		if (lcp->op[0] == OP_STRING) {
521 			/* the first chunk */
522 			key = lcp->data[0].ptr;
523 		} else {
524 			/* another chunk */
525 			ip = lcp->data[0].ip;
526 			port = lcp->data[1].ui;
527 			*flags |= 1;
528 		}
529 	}
530 
531 	if (key == NULL) {
532 		key = (uchar_t *)inet_ntop(AF_INET6, (void *)ip,
533 		    buff, sizeof (buff));
534 		(void) snprintf(buff2, sizeof (buff2), "%d", port);
535 		(void) strcat((char *)key, buff2);
536 	}
537 
538 	return (htab_compute_hval(key));
539 }
540 
541 /*
542  * ****************************************************************************
543  *
544  * dd_hval:
545  *	caculate the hash value of a DD object.
546  *
547  * p	- the pointer pointers to a DD object or the lookup control data,
548  *	  both have the key attributes of a DD object.
549  * chunk- which chunk of the hash table.
550  * flags- pointer to flags.
551  * return - the hash value.
552  *
553  * ****************************************************************************
554  */
555 static uint32_t
556 dd_hval(
557 	void *p,
558 	/* LINTED E_FUNC_ARG_UNUSED */
559 	uint16_t chunk,
560 	uint32_t *flags
561 )
562 {
563 	uchar_t *key;
564 	isns_obj_t *obj;
565 	lookup_ctrl_t *lcp;
566 
567 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
568 		/* p is a DD object */
569 		obj = (isns_obj_t *)p;
570 		key = obj->attrs[ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID)].
571 		    value.ptr;
572 	} else {
573 		/* p is a lookup control data */
574 		lcp = (lookup_ctrl_t *)p;
575 		key = lcp->data[0].ptr;
576 	}
577 
578 	return (htab_compute_hval(key));
579 }
580 
581 /*
582  * ****************************************************************************
583  *
584  * dds_hval:
585  *	caculate the hash value of a DD-set object.
586  *
587  * p	- the pointer pointers to a DD-set object or the lookup control data,
588  *	  both have the key attributes of a DD-set object.
589  * chunk- which chunk of the hash table.
590  * flags- pointer to flags.
591  * return - the hash value.
592  *
593  * ****************************************************************************
594  */
595 static uint32_t
596 dds_hval(
597 	void *p,
598 	/* LINTED E_FUNC_ARG_UNUSED */
599 	uint16_t chunk,
600 	uint32_t *flags
601 )
602 {
603 	uchar_t *key;
604 	isns_obj_t *obj;
605 	lookup_ctrl_t *lcp;
606 
607 	if ((*flags & FLAGS_CTRL_MASK) == 0) {
608 		/* p is a DD-set object */
609 		obj = (isns_obj_t *)p;
610 		key = obj->attrs[ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID)].
611 		    value.ptr;
612 	} else {
613 		/* p is lookup control data */
614 		lcp = (lookup_ctrl_t *)p;
615 		key = lcp->data[0].ptr;
616 	}
617 
618 	return (htab_compute_hval(key));
619 }
620 
621 /*
622  * ****************************************************************************
623  *
624  * obj_hval:
625  *	caculate the hash value of an object.
626  *
627  * p	- the pointer pointers to an object or lookup control data,
628  *	  both has the object type and the key attributes of an object.
629  * chunk- which chunk of the hash table.
630  * flags- pointer to flags.
631  * return - the hash value.
632  *
633  * ****************************************************************************
634  */
635 uint32_t
636 obj_hval(
637 	void *p,
638 	uint16_t chunk,
639 	uint32_t *flags
640 )
641 {
642 	isns_type_t type = ((isns_obj_t *)p)->type;
643 
644 	return (hval_func[type](p, chunk, flags));
645 }
646 
647 /*
648  * ****************************************************************************
649  *
650  * get_obj_uid:
651  *	get the UID of an object.
652  *
653  * p	- the pointer pointers to an object.
654  * return - the UID.
655  *
656  * ****************************************************************************
657  */
658 uint32_t
659 get_obj_uid(
660 	const void *p
661 )
662 {
663 	isns_obj_t *obj = (isns_obj_t *)p;
664 	isns_attr_t *attr = &obj->attrs[UID_ATTR_INDEX[obj->type]];
665 	uint32_t uid = attr->value.ui;
666 	return (uid);
667 }
668 
669 /*
670  * ****************************************************************************
671  *
672  * set_obj_uid:
673  *	set the UID of an object.
674  *
675  * p	- the pointer pointers to an object.
676  * uid	- the UID.
677  * return - the UID.
678  *
679  * ****************************************************************************
680  */
681 uint32_t
682 set_obj_uid(
683 	void *p,
684 	uint32_t uid
685 )
686 {
687 	isns_obj_t *obj = (isns_obj_t *)p;
688 	isns_attr_t *attr = &obj->attrs[UID_ATTR_INDEX[obj->type]];
689 
690 	/* set the tag, len and value */
691 	attr->tag = UID_TAG[obj->type];
692 	attr->len = 4;
693 	attr->value.ui = uid;
694 
695 	return (uid);
696 }
697 
698 /*
699  * ****************************************************************************
700  *
701  * obj_cmp:
702  *	compare between two objects or an object with a lookup control data.
703  *
704  * p1	- the pointer points to an object.
705  * p2	- the pointer points to an object or a lookup control data.
706  * flags- 0: p2 is an object; otherwise p2 is a lookup control data.
707  * return - the comparsion result.
708  *
709  * ****************************************************************************
710  */
711 int
712 obj_cmp(
713 	void *p1,
714 	void *p2,
715 	int flags
716 )
717 {
718 	isns_obj_t *obj = (isns_obj_t *)p1;
719 	lookup_ctrl_t buff = { 0 };
720 	lookup_ctrl_t *lcp;
721 	uint32_t uid;
722 
723 	if (flags == 0) {
724 		lcp = set_lookup_ctrl(&buff, (isns_obj_t *)p2);
725 	} else {
726 		lcp = (lookup_ctrl_t *)p2;
727 		uid = get_obj_uid(obj);
728 		/* the object are linked with decending order by */
729 		/* the object UID, if the object UID is greater than */
730 		/* or equal to the current UID, it needs to compare */
731 		/* for the next one. */
732 		if (lcp->curr_uid != 0 && uid >= lcp->curr_uid) {
733 			return (-1);
734 		}
735 	}
736 
737 	return (key_cmp(lcp, obj));
738 }
739 
740 /*
741  * ****************************************************************************
742  *
743  * replace_object:
744  *	replace an existing object with the new one.
745  *
746  * p1	- the pointer points to an object being replaced.
747  * p2	- the pointer points to a new object.
748  * uid_p- points to uid for returning.
749  * flag	- 0: do not free the source object, otherwise free it.
750  * return - error code.
751  *
752  * ****************************************************************************
753  */
754 int
755 replace_object(
756 	void *p1,
757 	void *p2,
758 	uint32_t *uid_p,
759 	int flag
760 )
761 {
762 	int ec = 0;
763 
764 #ifndef SKIP_SRC_AUTH
765 	uint32_t *pp_dst, *pp_src, swap;
766 #endif
767 	int online;
768 
769 	isns_obj_t *dst = (isns_obj_t *)p1;
770 	isns_obj_t *src = (isns_obj_t *)p2;
771 
772 	if (src->type == OBJ_DD || src->type == OBJ_DDS) {
773 		/* replace not allowed */
774 		return (ERR_NAME_IN_USE);
775 	}
776 
777 	online = is_obj_online(dst);
778 
779 	/* set cache update flag */
780 	SET_CACHE_UPDATED();
781 
782 	/* update parent uid */
783 #ifndef SKIP_SRC_AUTH
784 	pp_dst = get_parent_p(dst);
785 	if (pp_dst != NULL) {
786 		pp_src = get_parent_p(src);
787 		swap = *pp_dst;
788 		*pp_dst = *pp_src;
789 		if (swap != 0) {
790 			*pp_src = swap;
791 		}
792 	}
793 #endif
794 
795 	/* update all of attributes */
796 	if (copy_attrs(dst, src) != 0) {
797 		return (ISNS_RSP_INTERNAL_ERROR);
798 	}
799 
800 	/* free up the src object */
801 	if (flag != 0) {
802 		(void) free_object(src);
803 	} else if (online == 0) {
804 		(void) set_obj_uid(src, get_obj_uid(dst));
805 		(void) set_obj_offline(src);
806 	}
807 
808 	/* update data store */
809 	if (sys_q != NULL) {
810 		ec = write_data(DATA_UPDATE, dst);
811 	} else {
812 		/* we should never have duplicated entry in data store */
813 		ec = ISNS_RSP_INTERNAL_ERROR;
814 	}
815 
816 	/* trigger a scn */
817 	if (ec == 0) {
818 		if (scn_q != NULL) {
819 			(void) make_scn((online == 0) ?
820 			    ISNS_OBJECT_ADDED :
821 			    ISNS_OBJECT_UPDATED,
822 			    dst);
823 		}
824 		if (uid_p != NULL) {
825 			*uid_p = get_obj_uid(dst);
826 		}
827 	}
828 
829 	return (ec);
830 }
831 
832 /*
833  * ****************************************************************************
834  *
835  * add_object:
836  *	post function after adding a new object.
837  *
838  * p	- object which has been added.
839  * return - error code.
840  *
841  * ****************************************************************************
842  */
843 int
844 add_object(
845 	void *p
846 )
847 {
848 	int ec = 0;
849 
850 	isns_obj_t *obj = (isns_obj_t *)p;
851 
852 	/* add the new object to data store */
853 	if (sys_q != NULL) {
854 		ec = write_data(DATA_ADD, obj);
855 	}
856 
857 	/* trigger a scn */
858 	if (ec == 0 && scn_q != NULL) {
859 		(void) make_scn(ISNS_OBJECT_ADDED, obj);
860 	}
861 
862 	return (ec);
863 }
864 
865 /*
866  * ****************************************************************************
867  *
868  * obj_tab_init:
869  *	initialize the object hash tables.
870  *
871  * c	- points to the cache.
872  * return - error code.
873  *
874  * ****************************************************************************
875  */
876 int
877 obj_tab_init(
878 	struct cache *c
879 )
880 {
881 	htab_t *t;
882 
883 	htab_init();
884 
885 	/*
886 	 * allocate an array of pointer for the object hash tables.
887 	 */
888 	c->t = (struct htab **)calloc(sizeof (struct htab *), MAX_OBJ_TYPE);
889 	if (c->t == NULL) {
890 		return (1);
891 	}
892 
893 	/*
894 	 * hash table for network entity objects.
895 	 */
896 	t = htab_create(UID_FLAGS_SEQ, 8, 1);
897 	if (t != NULL) {
898 		t->c = c;
899 		c->t[OBJ_ENTITY] = t;
900 	} else {
901 		return (1);
902 	}
903 
904 	/*
905 	 * hash table for iscsi storage node objects.
906 	 */
907 	t = htab_create(UID_FLAGS_SEQ, 8, 1);
908 	if (t != NULL) {
909 		t->c = c;
910 		c->t[OBJ_ISCSI] = t;
911 	} else {
912 		return (1);
913 	}
914 
915 	/*
916 	 * hash table for portal objects.
917 	 */
918 	t = htab_create(UID_FLAGS_SEQ, 8, 1);
919 	if (t != NULL) {
920 		t->c = c;
921 		c->t[OBJ_PORTAL] = t;
922 	} else {
923 		return (1);
924 	}
925 
926 	/*
927 	 * hash table for portal group objects.
928 	 */
929 	t = htab_create(UID_FLAGS_SEQ, 8, 2);
930 	if (t != NULL) {
931 		t->c = c;
932 		c->t[OBJ_PG] = t;
933 	} else {
934 		return (1);
935 	}
936 
937 	/*
938 	 * hash table for discovery domain objects.
939 	 */
940 	t = htab_create(0, 6, 1);
941 	if (t != NULL) {
942 		t->c = c;
943 		c->t[OBJ_DD] = t;
944 	} else {
945 		return (1);
946 	}
947 
948 	/*
949 	 * hash table for discovery domain set objects.
950 	 */
951 	t = htab_create(0, 4, 1);
952 	if (t != NULL) {
953 		t->c = c;
954 		c->t[OBJ_DDS] = t;
955 	} else {
956 		return (1);
957 	}
958 
959 	return (0);
960 }
961 
962 /*
963  * ****************************************************************************
964  *
965  * get_ref_np:
966  *	get the ref pointer of the portal group object.
967  *
968  * obj	- portal group object.
969  * return - ref pointer.
970  *
971  * ****************************************************************************
972  */
973 static uint32_t *
974 get_ref_np(
975 	isns_obj_t *obj,
976 	int n
977 )
978 {
979 	uint32_t *refp =
980 	    obj->type == OBJ_PG ? &((isns_pg_t *)obj)->ref[n] : NULL;
981 
982 	return (refp);
983 }
984 
985 #ifdef DEBUG
986 uint32_t
987 #else
988 static uint32_t
989 #endif
990 get_ref_n(
991 	isns_obj_t *obj,
992 	int n
993 )
994 {
995 	return (*get_ref_np(obj, n));
996 }
997 
998 static uint32_t *
999 get_ref_p(
1000 	isns_obj_t *obj,
1001 	isns_type_t rt
1002 )
1003 {
1004 	isns_type_t t = obj->type;
1005 
1006 	int i = 0;
1007 	while (i < NUM_OF_REF[t]) {
1008 		if (rt == TYPE_OF_REF[t][i + 1]) {
1009 			return (get_ref_np(obj, i));
1010 		}
1011 		i ++;
1012 	}
1013 
1014 	return (NULL);
1015 }
1016 
1017 uint32_t
1018 get_ref_t(
1019 	isns_obj_t *obj,
1020 	isns_type_t type
1021 )
1022 {
1023 	uint32_t *refp = get_ref_p(obj, type);
1024 
1025 	if (refp != NULL) {
1026 		return (*refp);
1027 	/* LINTED E_NOP_ELSE_STMT */
1028 	} else {
1029 		ASSERT(0);
1030 	}
1031 
1032 	return (0);
1033 }
1034 
1035 /*
1036  * ****************************************************************************
1037  *
1038  * get_parent_p:
1039  *	get the pointer of the parent object.
1040  *
1041  * obj	- an object.
1042  * return - parent object pointer.
1043  *
1044  * ****************************************************************************
1045  */
1046 uint32_t *const
1047 get_parent_p(
1048 	const isns_obj_t *obj
1049 )
1050 {
1051 	uint32_t *pp;
1052 	switch (obj->type) {
1053 	case OBJ_ISCSI:
1054 		pp = &((isns_iscsi_t *)obj)->puid;
1055 		break;
1056 	case OBJ_PORTAL:
1057 		pp = &((isns_portal_t *)obj)->puid;
1058 		break;
1059 	case OBJ_PG:
1060 		pp = &((isns_pg_t *)obj)->puid;
1061 		break;
1062 	case OBJ_ASSOC_ISCSI:
1063 		pp = &((isns_assoc_iscsi_t *)obj)->puid;
1064 		break;
1065 	case OBJ_ASSOC_DD:
1066 		pp = &((isns_assoc_dd_t *)obj)->puid;
1067 		break;
1068 	default:
1069 		pp = NULL;
1070 		break;
1071 	}
1072 
1073 	return (pp);
1074 }
1075 
1076 uint32_t
1077 get_parent_uid(
1078 	const isns_obj_t *obj
1079 )
1080 {
1081 	uint32_t *pp = get_parent_p(obj);
1082 	if (pp != NULL) {
1083 		return (*pp);
1084 	}
1085 
1086 	return (0);
1087 }
1088 
1089 /*
1090  * ****************************************************************************
1091  *
1092  * get_child_np:
1093  *	get the pointer of the UID array of the n'th child of an object.
1094  *
1095  * obj	- an object.
1096  * n	- the child index.
1097  * return - the pointer of the UID array.
1098  *
1099  * ****************************************************************************
1100  */
1101 static uint32_t **
1102 get_child_np(
1103 	isns_obj_t *obj,
1104 	int n
1105 )
1106 {
1107 	uint32_t **pp =
1108 	    obj->type == OBJ_ENTITY ? &((isns_entity_t *)obj)->cuid[n] : NULL;
1109 
1110 	return (pp);
1111 }
1112 
1113 /*
1114  * ****************************************************************************
1115  *
1116  * get_child_n:
1117  *	get the UID array of the n'th child of an object.
1118  *
1119  * obj	- an object.
1120  * n	- the child index.
1121  * return - the UID array.
1122  *
1123  * ****************************************************************************
1124  */
1125 #ifdef DEBUG
1126 uint32_t *
1127 #else
1128 static uint32_t *
1129 #endif
1130 get_child_n(
1131 	isns_obj_t *obj,
1132 	int n
1133 )
1134 {
1135 	uint32_t **pp = get_child_np(obj, n);
1136 
1137 	if (pp != NULL) {
1138 		return (*pp);
1139 	}
1140 
1141 	ASSERT(0);
1142 	return (NULL);
1143 }
1144 
1145 /*
1146  * ****************************************************************************
1147  *
1148  * get_child_p:
1149  *	get the pointer of the UID array of the child matching the type.
1150  *
1151  * base	- an object.
1152  * child_type	- the child object type.
1153  * return - the pointer of the UID array.
1154  *
1155  * ****************************************************************************
1156  */
1157 static uint32_t **
1158 get_child_p(
1159 	isns_obj_t *base,
1160 	int child_type
1161 )
1162 {
1163 	uint32_t **pp = NULL;
1164 	int i = 0;
1165 	while (i < NUM_OF_CHILD[base->type]) {
1166 		if (child_type == TYPE_OF_CHILD[base->type][i]) {
1167 			pp = get_child_np(base, i);
1168 			break;
1169 		}
1170 		i ++;
1171 	}
1172 
1173 	return (pp);
1174 }
1175 
1176 /*
1177  * ****************************************************************************
1178  *
1179  * get_child_t:
1180  *	get the UID array of the child object matching the type.
1181  *
1182  * base	- an object.
1183  * child_type	- the child object type.
1184  * return - the UID array.
1185  *
1186  * ****************************************************************************
1187  */
1188 uint32_t *
1189 get_child_t(
1190 	isns_obj_t *base,
1191 	int child_type
1192 )
1193 {
1194 	uint32_t **pp = get_child_p(base, child_type);
1195 
1196 	if (pp != NULL) {
1197 		return (*pp);
1198 	} else {
1199 		return (NULL);
1200 	}
1201 }
1202 
1203 /*
1204  * ****************************************************************************
1205  *
1206  * key_cmp:
1207  *	compare the object against the lookup control data.
1208  *
1209  * lcp	- the lookup control data.
1210  * obj	- an object.
1211  * return - comparison result.
1212  *
1213  * ****************************************************************************
1214  */
1215 int
1216 key_cmp(
1217 	lookup_ctrl_t *lcp,
1218 	isns_obj_t *obj
1219 )
1220 {
1221 	int i = 0;
1222 	int match = 1;
1223 	while (i < MAX_LOOKUP_CTRL && lcp->op[i] > 0 && match) {
1224 		isns_attr_t *attr = &obj->attrs[lcp->id[i]];
1225 		switch (lcp->op[i]) {
1226 			case OP_STRING:
1227 				match = (strcmp((const char *)lcp->data[i].ptr,
1228 				    (const char *)attr->value.ptr) == 0);
1229 				break;
1230 			case OP_INTEGER:
1231 				match = (lcp->data[i].ui == attr->value.ui);
1232 				break;
1233 			case OP_MEMORY_IP6:
1234 				match = !memcmp((void *)lcp->data[i].ip,
1235 				    (void *)attr->value.ip,
1236 				    sizeof (in6_addr_t));
1237 				break;
1238 			default:
1239 				ASSERT(0);
1240 				match = 0;
1241 				break;
1242 		}
1243 		i ++;
1244 	}
1245 
1246 	if (i && match) {
1247 		return (0);
1248 	} else {
1249 		return (1);
1250 	}
1251 }
1252 
1253 /*
1254  * ****************************************************************************
1255  *
1256  * set_lookup_ctrl:
1257  *	fill in the lookup control data for an object.
1258  *
1259  * lcp	- the lookup control data.
1260  * obj	- an object.
1261  * return - the lookup control data.
1262  *
1263  * ****************************************************************************
1264  */
1265 static lookup_ctrl_t *
1266 set_lookup_ctrl(
1267 	lookup_ctrl_t *lcp,
1268 	isns_obj_t *obj
1269 )
1270 {
1271 	isns_type_t type = obj->type;
1272 	uint32_t id, op;
1273 	int i = 0;
1274 
1275 	lcp->type = type;
1276 	while (i < MAX_KEY_ATTRS) {
1277 		op = KEY_ATTR_OP[type][i];
1278 		if (op != 0) {
1279 			id = KEY_ATTR_INDEX[type][i];
1280 			lcp->id[i] = id;
1281 			lcp->op[i] = op;
1282 			lcp->data[i].ui = obj->attrs[id].value.ui;
1283 		} else {
1284 			break;
1285 		}
1286 		i ++;
1287 	}
1288 
1289 	return (lcp);
1290 }
1291 
1292 /*
1293  * ****************************************************************************
1294  *
1295  * assign_attr:
1296  *	assign an attribute.
1297  *
1298  * attr	- the attribute being assigned.
1299  * tmp	- the attribute.
1300  * return - error code.
1301  *
1302  * ****************************************************************************
1303  */
1304 int
1305 assign_attr(
1306 	isns_attr_t *attr,
1307 	const isns_attr_t *tmp
1308 )
1309 {
1310 	uint32_t t;
1311 
1312 	switch (tmp->tag) {
1313 	case ISNS_EID_ATTR_ID:
1314 	case ISNS_DD_SET_NAME_ATTR_ID:
1315 	case ISNS_DD_NAME_ATTR_ID:
1316 		if (tmp->len == 0 && attr->len == 0) {
1317 			int len;
1318 			char *name = make_unique_name(&len, tmp->tag);
1319 			if (name != NULL) {
1320 				attr->value.ptr = (uchar_t *)name;
1321 				attr->tag = tmp->tag;
1322 				attr->len = len;
1323 			} else {
1324 				/* memory exhausted */
1325 				return (1);
1326 			}
1327 		}
1328 		/* FALLTHROUGH */
1329 	case ISNS_PORTAL_NAME_ATTR_ID:
1330 	case ISNS_ISCSI_NAME_ATTR_ID:
1331 	case ISNS_ISCSI_ALIAS_ATTR_ID:
1332 	case ISNS_ISCSI_AUTH_METHOD_ATTR_ID:
1333 	case ISNS_PG_ISCSI_NAME_ATTR_ID:
1334 	case ISNS_DD_ISCSI_NAME_ATTR_ID:
1335 		if (tmp->len == 0) {
1336 			return (0);
1337 		} else if (tmp->len >= attr->len) {
1338 			attr->value.ptr = realloc(
1339 			    attr->value.ptr, tmp->len + 1);
1340 		}
1341 		if (attr->value.ptr != NULL) {
1342 			(void) strncpy((char *)attr->value.ptr,
1343 			    (char *)tmp->value.ptr, tmp->len);
1344 			attr->value.ptr[tmp->len] = 0;
1345 			attr->tag = tmp->tag;
1346 			attr->len = tmp->len;
1347 		} else {
1348 			/* memory exhausted */
1349 			return (1);
1350 		}
1351 		break;
1352 	case ISNS_MGMT_IP_ADDR_ATTR_ID:
1353 	case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1354 	case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
1355 		if (attr->value.ip == NULL) {
1356 			attr->value.ip = (in6_addr_t *)calloc(1, tmp->len);
1357 		}
1358 		if (attr->value.ip != NULL) {
1359 			(void) memcpy((void *)attr->value.ip,
1360 			    (void *)tmp->value.ip, tmp->len);
1361 			attr->tag = tmp->tag;
1362 			attr->len = tmp->len;
1363 		} else {
1364 			/* memory exhausted */
1365 			return (1);
1366 		}
1367 		break;
1368 	case ISNS_ENTITY_INDEX_ATTR_ID:
1369 	case ISNS_PORTAL_INDEX_ATTR_ID:
1370 	case ISNS_ISCSI_NODE_INDEX_ATTR_ID:
1371 	case ISNS_PG_INDEX_ATTR_ID:
1372 	case ISNS_DD_SET_ID_ATTR_ID:
1373 	case ISNS_DD_ID_ATTR_ID:
1374 		if (attr->value.ui != 0) {
1375 			break;
1376 		}
1377 		/* FALLTHROUGH */
1378 	case ISNS_ENTITY_PROTOCOL_ATTR_ID:
1379 	case ISNS_VERSION_RANGE_ATTR_ID:
1380 
1381 	case ISNS_PORTAL_PORT_ATTR_ID:
1382 	case ISNS_ESI_PORT_ATTR_ID:
1383 	case ISNS_SCN_PORT_ATTR_ID:
1384 
1385 	case ISNS_ISCSI_NODE_TYPE_ATTR_ID:
1386 	case ISNS_ISCSI_SCN_BITMAP_ATTR_ID:
1387 
1388 	case ISNS_PG_PORTAL_PORT_ATTR_ID:
1389 	case ISNS_PG_TAG_ATTR_ID:
1390 
1391 	case ISNS_DD_SET_STATUS_ATTR_ID:
1392 	case ISNS_DD_ISCSI_INDEX_ATTR_ID:
1393 		attr->tag = tmp->tag;
1394 		attr->len = tmp->len;
1395 		attr->value.ui = tmp->value.ui;
1396 		break;
1397 	case ISNS_ENTITY_REG_PERIOD_ATTR_ID:
1398 		attr->tag = tmp->tag;
1399 		attr->len = tmp->len;
1400 		attr->value.ui = tmp->value.ui;
1401 		t = get_reg_period();
1402 		if (attr->value.ui > t) {
1403 			attr->value.ui = t;
1404 		} else if (attr->value.ui < ONE_DAY) {
1405 			attr->value.ui = ONE_DAY;
1406 		}
1407 		break;
1408 	case ISNS_ESI_INTERVAL_ATTR_ID:
1409 		attr->tag = tmp->tag;
1410 		attr->len = tmp->len;
1411 		attr->value.ui = tmp->value.ui;
1412 		if (attr->value.ui > ONE_DAY) {
1413 			attr->value.ui = ONE_DAY;
1414 		} else if (attr->value.ui < MIN_ESI_INTVAL) {
1415 			attr->value.ui = MIN_ESI_INTVAL; /* 20 seconds */
1416 		}
1417 		break;
1418 	default:
1419 		ASSERT(0);
1420 		/* don't assign the attribute */
1421 		break;
1422 	}
1423 	return (0);
1424 }
1425 
1426 /*
1427  * ****************************************************************************
1428  *
1429  * copy_attrs:
1430  *	copy all of attributes from one object to another.
1431  *
1432  * dst	- the destination object.
1433  * tmp	- the source object.
1434  * return - error code.
1435  *
1436  * ****************************************************************************
1437  */
1438 static int
1439 copy_attrs(
1440 	isns_obj_t *dst,
1441 	const isns_obj_t *src
1442 )
1443 {
1444 	int i = 0;
1445 	int n = NUM_OF_ATTRS[dst->type];
1446 
1447 	isns_attr_t *dst_attr;
1448 	const isns_attr_t *src_attr;
1449 
1450 	while (i < n) {
1451 		src_attr = &(src->attrs[i]);
1452 		if (src_attr->tag != 0) {
1453 			dst_attr = &(dst->attrs[i]);
1454 			if (assign_attr(dst_attr, src_attr) != 0) {
1455 				return (1);
1456 			}
1457 		}
1458 		i ++;
1459 	}
1460 
1461 	return (0);
1462 }
1463 
1464 /*
1465  * ****************************************************************************
1466  *
1467  * extract_attr:
1468  *	extract an attribute from a TLV format data.
1469  *
1470  * attr	- the attribute.
1471  * tlv	- the TLV format data.
1472  * return - error code.
1473  *
1474  * ****************************************************************************
1475  */
1476 int
1477 extract_attr(
1478 	isns_attr_t *attr,
1479 	const isns_tlv_t *tlv,
1480 	int flag
1481 )
1482 {
1483 	int ec = 0;
1484 
1485 	uint32_t min_len = 4, max_len = 224;
1486 
1487 	switch (tlv->attr_id) {
1488 	case ISNS_EID_ATTR_ID:
1489 		min_len = 0;
1490 		/* FALLTHROUGH */
1491 	case ISNS_PORTAL_NAME_ATTR_ID:
1492 	case ISNS_ISCSI_ALIAS_ATTR_ID:
1493 	case ISNS_DD_SET_NAME_ATTR_ID:
1494 	case ISNS_DD_NAME_ATTR_ID:
1495 		max_len = 256;
1496 		/* FALLTHROUGH */
1497 	case ISNS_ISCSI_NAME_ATTR_ID:
1498 	case ISNS_PG_ISCSI_NAME_ATTR_ID:
1499 		if (tlv->attr_len < min_len || tlv->attr_len > max_len) {
1500 			ec = ISNS_RSP_MSG_FORMAT_ERROR;
1501 		} else {
1502 			attr->tag = tlv->attr_id;
1503 			attr->len = tlv->attr_len;
1504 			attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]);
1505 		}
1506 		break;
1507 	case ISNS_ISCSI_AUTH_METHOD_ATTR_ID:
1508 		attr->tag = tlv->attr_id;
1509 		attr->len = tlv->attr_len;
1510 		attr->value.ptr = (uchar_t *)&(tlv->attr_value[0]);
1511 		break;
1512 	case ISNS_MGMT_IP_ADDR_ATTR_ID:
1513 	case ISNS_PORTAL_IP_ADDR_ATTR_ID:
1514 	case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
1515 		if (tlv->attr_len != 16) {
1516 			ec = ISNS_RSP_MSG_FORMAT_ERROR;
1517 		} else {
1518 			attr->tag = tlv->attr_id;
1519 			attr->len = tlv->attr_len;
1520 			attr->value.ip = (void *)&(tlv->attr_value[0]);
1521 		}
1522 		break;
1523 	case ISNS_ENTITY_PROTOCOL_ATTR_ID:
1524 	case ISNS_VERSION_RANGE_ATTR_ID:
1525 	case ISNS_ENTITY_REG_PERIOD_ATTR_ID:
1526 		/* fall throught */
1527 	case ISNS_PORTAL_PORT_ATTR_ID:
1528 	case ISNS_ESI_INTERVAL_ATTR_ID:
1529 	case ISNS_ESI_PORT_ATTR_ID:
1530 	case ISNS_SCN_PORT_ATTR_ID:
1531 		/* fall throught */
1532 	case ISNS_ISCSI_NODE_TYPE_ATTR_ID:
1533 		/* fall throught */
1534 	case ISNS_PG_PORTAL_PORT_ATTR_ID:
1535 		/* fall throught */
1536 	case ISNS_DD_SET_ID_ATTR_ID:
1537 	case ISNS_DD_SET_STATUS_ATTR_ID:
1538 		/* fall throught */
1539 	case ISNS_DD_ID_ATTR_ID:
1540 		if (tlv->attr_len != 4) {
1541 			ec = ISNS_RSP_MSG_FORMAT_ERROR;
1542 			break;
1543 		}
1544 		/* FALLTHROUGH */
1545 	case ISNS_PG_TAG_ATTR_ID:
1546 		attr->tag = tlv->attr_id;
1547 		attr->len = tlv->attr_len;
1548 		if (tlv->attr_len == 4) {
1549 			attr->value.ui = ntohl(*(uint32_t *)
1550 			    &(tlv->attr_value[0]));
1551 		} else {
1552 			attr->value.ui = 0;
1553 		}
1554 		break;
1555 	case ISNS_ISCSI_SCN_BITMAP_ATTR_ID:
1556 		/* ignore scn bitmap attribute during object registration, */
1557 		/* it is registered by scn_reg message. */
1558 	case ISNS_ENTITY_ISAKMP_P1_ATTR_ID:
1559 	case ISNS_ENTITY_CERT_ATTR_ID:
1560 	case ISNS_PORTAL_SEC_BMP_ATTR_ID:
1561 	case ISNS_PORTAL_ISAKMP_P1_ATTR_ID:
1562 	case ISNS_PORTAL_ISAKMP_P2_ATTR_ID:
1563 	case ISNS_PORTAL_CERT_ATTR_ID:
1564 		break;
1565 	case ISNS_PORTAL_INDEX_ATTR_ID:
1566 	case ISNS_ISCSI_NODE_INDEX_ATTR_ID:
1567 	case ISNS_PG_INDEX_ATTR_ID:
1568 		if (flag == 0) {
1569 			if (tlv->attr_len != 4) {
1570 				ec = ISNS_RSP_MSG_FORMAT_ERROR;
1571 			} else {
1572 				attr->tag = tlv->attr_id;
1573 				attr->len = tlv->attr_len;
1574 				attr->value.ui = ntohl(*(uint32_t *)
1575 				    &(tlv->attr_value[0]));
1576 			}
1577 			break;
1578 		}
1579 		/* FALLTHROUGH */
1580 	case ISNS_ENTITY_INDEX_ATTR_ID:
1581 	case ISNS_TIMESTAMP_ATTR_ID:
1582 	default:
1583 		if (flag == 0) {
1584 			ec = ISNS_RSP_INVALID_QRY;
1585 		} else {
1586 			ec = ISNS_RSP_INVALID_REGIS;
1587 		}
1588 		break;
1589 	}
1590 
1591 	return (ec);
1592 }
1593 
1594 /*
1595  * ****************************************************************************
1596  *
1597  * copy_attr:
1598  *	copy an attribute from a TLV format data.
1599  *
1600  * attr	- the attribute.
1601  * tlv	- the TLV format data.
1602  * return - error code.
1603  *
1604  * ****************************************************************************
1605  */
1606 static int
1607 copy_attr(
1608 	isns_attr_t *attr,
1609 	const isns_tlv_t *tlv
1610 )
1611 {
1612 	int ec = 0;
1613 
1614 	isns_attr_t tmp = { 0 };
1615 
1616 	/* extract the attribute first */
1617 	ec = extract_attr(&tmp, tlv, 1);
1618 
1619 	/* assign the attribute */
1620 	if (ec == 0 && tmp.tag != 0) {
1621 		if (assign_attr(attr, &tmp) != 0) {
1622 			ec = ISNS_RSP_INTERNAL_ERROR;
1623 		}
1624 	}
1625 
1626 	return (ec);
1627 }
1628 
1629 /*
1630  * ****************************************************************************
1631  *
1632  * get_timestamp:
1633  *	get current timestamp.
1634  *
1635  * return - current timestamp.
1636  *
1637  * ****************************************************************************
1638  */
1639 uint32_t
1640 get_timestamp(
1641 )
1642 {
1643 	uint32_t t;
1644 	int flag;
1645 
1646 	/* block the scheduler */
1647 	(void) pthread_mutex_lock(&el_mtx);
1648 
1649 	/* get most current time */
1650 	if (sys_q != NULL) {
1651 		/* need to wakeup idle */
1652 		flag = 1;
1653 	} else {
1654 		flag = 0;
1655 	}
1656 	t = get_stopwatch(flag);
1657 
1658 	/* unblock it */
1659 	(void) pthread_mutex_unlock(&el_mtx);
1660 
1661 	return (t);
1662 }
1663 
1664 /*
1665  * ****************************************************************************
1666  *
1667  * get_reg_period:
1668  *	get the longest registration period.
1669  *
1670  * return - the longest registration period.
1671  *
1672  * ****************************************************************************
1673  */
1674 static uint32_t
1675 get_reg_period(
1676 )
1677 {
1678 	uint32_t t;
1679 	uint32_t period;
1680 
1681 	/* get most current time */
1682 	t = get_timestamp();
1683 
1684 	/* just one second before the end of the world */
1685 	period = INFINITY - t - 1;
1686 
1687 	return (period);
1688 }
1689 
1690 /*
1691  * ****************************************************************************
1692  *
1693  * obj_calloc:
1694  *	allocate memory space for an object.
1695  *
1696  * type	- the object type.
1697  * return - pointer of the object being allocated.
1698  *
1699  * ****************************************************************************
1700  */
1701 isns_obj_t *
1702 obj_calloc(
1703 	int type
1704 )
1705 {
1706 	isns_obj_t *obj = NULL;
1707 
1708 	obj = (isns_obj_t *)calloc(1, SIZEOF_OBJ[type]);
1709 	if (obj != NULL) {
1710 		obj->type = type;
1711 #ifdef DEBUG
1712 	if (verbose_mc) {
1713 		printf("object(%d) allocated\n", type);
1714 	}
1715 #endif
1716 	}
1717 
1718 	return (obj);
1719 }
1720 
1721 /*
1722  * ****************************************************************************
1723  *
1724  * make_default_entity:
1725  *	generate a default network entity object.
1726  *
1727  * return - pointer of the default network entity object.
1728  *
1729  * ****************************************************************************
1730  */
1731 isns_obj_t *
1732 make_default_entity(
1733 )
1734 {
1735 	uint32_t t;
1736 
1737 	isns_obj_t *obj = obj_calloc(OBJ_ENTITY);
1738 	isns_attr_t *attr;
1739 	if (obj != NULL) {
1740 		int len;
1741 		char *eid = make_unique_name(&len, ISNS_EID_ATTR_ID);
1742 		if (!eid) {
1743 			free(obj);
1744 			return (NULL);
1745 		}
1746 		attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID)];
1747 
1748 		/* set default entity name */
1749 		attr->tag = ISNS_EID_ATTR_ID;
1750 		attr->len = len;
1751 		attr->value.ptr = (uchar_t *)eid;
1752 
1753 		/* set default registration period */
1754 		attr = &obj->attrs[
1755 		    ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)];
1756 		if (attr->tag == 0) {
1757 			attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID;
1758 			attr->len = 4;
1759 			t = get_reg_period();
1760 			attr->value.ui = t;
1761 		}
1762 	}
1763 
1764 	return (obj);
1765 }
1766 
1767 /*
1768  * ****************************************************************************
1769  *
1770  * make_default_pg:
1771  *	generate a default portal group object.
1772  *
1773  * iscsi  - the iscsi storage node object.
1774  * portal - the portal object.
1775  * return - pointer of the default portal group object.
1776  *
1777  * ****************************************************************************
1778  */
1779 static isns_obj_t *
1780 make_default_pg(
1781 	const isns_obj_t *p1,
1782 	const isns_obj_t *p2
1783 )
1784 {
1785 	const isns_obj_t *iscsi, *portal;
1786 	const isns_attr_t *name, *addr, *port;
1787 	isns_obj_t *pg;
1788 
1789 	uchar_t *pg_name;
1790 	in6_addr_t *pg_addr;
1791 
1792 	isns_attr_t *attr;
1793 
1794 	uint32_t *refp;
1795 
1796 	if (p1->type == OBJ_ISCSI) {
1797 		iscsi = p1;
1798 		portal = p2;
1799 	} else {
1800 		iscsi = p2;
1801 		portal = p1;
1802 	}
1803 	name = &iscsi->attrs[ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID)];
1804 	addr = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_IP_ADDR_ATTR_ID)];
1805 	port = &portal->attrs[ATTR_INDEX_PORTAL(ISNS_PORTAL_PORT_ATTR_ID)];
1806 
1807 	pg = obj_calloc(OBJ_PG);
1808 	pg_name = (uchar_t *)malloc(name->len);
1809 	pg_addr = (in6_addr_t *)malloc(addr->len);
1810 	if (pg != NULL && pg_name != NULL && pg_addr != NULL) {
1811 		(void) strcpy((char *)pg_name, (char *)name->value.ptr);
1812 		attr = &pg->attrs[ATTR_INDEX_PG(ISNS_PG_ISCSI_NAME_ATTR_ID)];
1813 		attr->tag = ISNS_PG_ISCSI_NAME_ATTR_ID;
1814 		attr->len = name->len;
1815 		attr->value.ptr = pg_name;
1816 
1817 		(void) memcpy((void *)pg_addr,
1818 		    (void *)addr->value.ip, addr->len);
1819 		attr = &pg->attrs[ATTR_INDEX_PG(
1820 		    ISNS_PG_PORTAL_IP_ADDR_ATTR_ID)];
1821 		attr->tag = ISNS_PG_PORTAL_IP_ADDR_ATTR_ID;
1822 		attr->len = addr->len;
1823 		attr->value.ip = pg_addr;
1824 
1825 		attr = &pg->attrs[ATTR_INDEX_PG(
1826 		    ISNS_PG_PORTAL_PORT_ATTR_ID)];
1827 		attr->tag = ISNS_PG_PORTAL_PORT_ATTR_ID;
1828 		attr->len = port->len;
1829 		attr->value.ui = port->value.ui;
1830 
1831 		attr = &pg->attrs[ATTR_INDEX_PG(
1832 		    ISNS_PG_TAG_ATTR_ID)];
1833 		attr->tag = ISNS_PG_TAG_ATTR_ID;
1834 		attr->len = 4;
1835 		attr->value.ui = ISNS_DEFAULT_PGT;
1836 
1837 		refp = get_ref_p(pg, OBJ_ISCSI);
1838 		*refp = get_obj_uid(iscsi);
1839 
1840 		refp = get_ref_p(pg, OBJ_PORTAL);
1841 		*refp = get_obj_uid(portal);
1842 
1843 		(void) set_parent_obj(pg, get_parent_uid(iscsi));
1844 	} else {
1845 		free(pg);
1846 		free(pg_name);
1847 		free(pg_addr);
1848 		pg = NULL;
1849 	}
1850 
1851 	return (pg);
1852 }
1853 
1854 /*
1855  * ****************************************************************************
1856  *
1857  * reg_get_entity:
1858  *	parse the Operating Attributes of the DevAttrReg message and
1859  *	create the Network Entity object if it has one.
1860  *
1861  * p	- the pointer of the object for returning.
1862  * op	- the operating attributes.
1863  * op_len - the length of the operating attributes.
1864  * return - error code.
1865  *
1866  * ****************************************************************************
1867  */
1868 int
1869 reg_get_entity(
1870 	isns_obj_t **p,
1871 	isns_tlv_t **op,
1872 	uint16_t *op_len
1873 )
1874 {
1875 	int ec = 0;
1876 
1877 	isns_tlv_t *tmp;
1878 	uint16_t tmp_len;
1879 	isns_attr_t *attr;
1880 
1881 	isns_obj_t *entity = NULL;
1882 
1883 	tmp = *op;
1884 	tmp_len = *op_len;
1885 
1886 	/* parse the entity object */
1887 	if (tmp_len >= 8 && IS_ENTITY_KEY(tmp->attr_id)) {
1888 		entity = obj_calloc(OBJ_ENTITY);
1889 		if (entity != NULL) {
1890 			do {
1891 				attr = &entity->attrs[
1892 				    ATTR_INDEX_ENTITY(tmp->attr_id)];
1893 				ec = copy_attr(attr, tmp);
1894 				NEXT_TLV(tmp, tmp_len);
1895 			} while (ec == 0 &&
1896 			    tmp_len >= 8 &&
1897 			    IS_ENTITY_ATTR(tmp->attr_id));
1898 		} else {
1899 			ec = ISNS_RSP_INTERNAL_ERROR;
1900 		}
1901 
1902 		if (ec == 0) {
1903 			/* set default registration period */
1904 			attr = &entity->attrs[
1905 			    ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)];
1906 			if (attr->tag == 0) {
1907 				attr->tag = ISNS_ENTITY_REG_PERIOD_ATTR_ID;
1908 				attr->len = 4;
1909 				attr->value.ui = get_reg_period();
1910 			}
1911 		} else if (entity != NULL) {
1912 			free(entity);
1913 			entity = NULL;
1914 		}
1915 	}
1916 
1917 	*p = entity;
1918 	*op = tmp;
1919 	*op_len = tmp_len;
1920 
1921 	return (ec);
1922 }
1923 
1924 /*
1925  * ****************************************************************************
1926  *
1927  * reg_get_iscsi:
1928  *	parse the Operating Attributes of the DevAttrReg message and
1929  *	create an iSCSI Storage Node object.
1930  *
1931  * p	- the pointer of the object for returning.
1932  * pg_key1 - the pointer of iscsi storage node name for returning.
1933  * op	- the operating attributes.
1934  * op_len - the length of the operating attributes.
1935  * return - error code.
1936  *
1937  * ****************************************************************************
1938  */
1939 static int
1940 reg_get_iscsi(
1941 	isns_obj_t **p,
1942 	isns_attr_t *pg_key1,
1943 	isns_tlv_t **op,
1944 	uint16_t *op_len
1945 )
1946 {
1947 	int ec = 0;
1948 
1949 	isns_tlv_t *tmp;
1950 	uint16_t tmp_len;
1951 	isns_attr_t *attr;
1952 
1953 	isns_obj_t *obj = NULL;
1954 
1955 	tmp = *op;
1956 	tmp_len = *op_len;
1957 
1958 	/* keep the iscsi storage node name for */
1959 	/* parsing a pg object which is immediately */
1960 	/* followed with a PGT by the iscsi storage node */
1961 	pg_key1->tag = PG_KEY1;
1962 	pg_key1->len = tmp->attr_len;
1963 	pg_key1->value.ptr = (uchar_t *)&tmp->attr_value[0];
1964 
1965 	/* parse one iscsi storage node object */
1966 	obj = obj_calloc(OBJ_ISCSI);
1967 	if (obj != NULL) {
1968 		/* parse key & non-key attributes */
1969 		do {
1970 			attr = &obj->attrs[
1971 			    ATTR_INDEX_ISCSI(tmp->attr_id)];
1972 			ec = copy_attr(attr, tmp);
1973 			NEXT_TLV(tmp, tmp_len);
1974 		} while (ec == 0 &&
1975 		    tmp_len >= 8 &&
1976 		    IS_ISCSI_ATTR(tmp->attr_id));
1977 	} else {
1978 		/* no memory */
1979 		ec = ISNS_RSP_INTERNAL_ERROR;
1980 	}
1981 
1982 	*p = obj;
1983 	*op = tmp;
1984 	*op_len = tmp_len;
1985 
1986 	return (ec);
1987 }
1988 
1989 /*
1990  * ****************************************************************************
1991  *
1992  * reg_get_portal:
1993  *	parse the Operating Attributes of the DevAttrReg message and
1994  *	create a Portal object.
1995  *
1996  * p	- the pointer of the object for returning.
1997  * pg_key1 - the pointer of portal ip addr for returning.
1998  * pg_key2 - the pointer of portal port for returning.
1999  * op	- the operating attributes.
2000  * op_len - the length of the operating attributes.
2001  * return - error code.
2002  *
2003  * ****************************************************************************
2004  */
2005 static int
2006 reg_get_portal(
2007 	isns_obj_t **p,
2008 	isns_attr_t *pg_key1,
2009 	isns_attr_t *pg_key2,
2010 	isns_tlv_t **op,
2011 	uint16_t *op_len
2012 )
2013 {
2014 	int ec = 0;
2015 
2016 	isns_tlv_t *tmp;
2017 	uint16_t tmp_len;
2018 	isns_attr_t *attr;
2019 
2020 	isns_obj_t *obj = NULL;
2021 
2022 	isns_tlv_t *ip;
2023 
2024 	tmp = *op;
2025 	tmp_len = *op_len;
2026 
2027 	/* keep the portal ip addr */
2028 	pg_key1->tag = PG_KEY2;
2029 	pg_key1->len = tmp->attr_len;
2030 	pg_key1->value.ip = (void *)&tmp->attr_value[0];
2031 	ip = tmp;
2032 
2033 	NEXT_TLV(tmp, tmp_len);
2034 	if (tmp_len > 8 &&
2035 	    tmp->attr_id == PORTAL_KEY2 &&
2036 	    tmp->attr_len == 4) {
2037 		/* keep the portal port */
2038 		pg_key2->tag = PG_KEY3;
2039 		pg_key2->len = tmp->attr_len;
2040 		pg_key2->value.ui = ntohl(*(uint32_t *)&tmp->attr_value[0]);
2041 
2042 		/* parse one portal object */
2043 		obj = obj_calloc(OBJ_PORTAL);
2044 		if (obj != NULL) {
2045 			/* copy ip addr attribute */
2046 			attr = &obj->attrs[
2047 			    ATTR_INDEX_PORTAL(ip->attr_id)];
2048 			ec = copy_attr(attr, ip);
2049 			/* copy port attribute */
2050 			if (ec == 0) {
2051 				attr = &obj->attrs[
2052 				    ATTR_INDEX_PORTAL(tmp->attr_id)];
2053 				ec = copy_attr(attr, tmp);
2054 			}
2055 			/* parse non-key attributes */
2056 			NEXT_TLV(tmp, tmp_len);
2057 			while (ec == 0 &&
2058 			    tmp_len >= 8 &&
2059 			    IS_PORTAL_ATTR(tmp->attr_id)) {
2060 				attr = &obj->attrs[
2061 				    ATTR_INDEX_PORTAL(
2062 				    tmp->attr_id)];
2063 				ec = copy_attr(attr, tmp);
2064 				NEXT_TLV(tmp, tmp_len);
2065 			}
2066 		} else {
2067 			/* no memory */
2068 			ec = ISNS_RSP_INTERNAL_ERROR;
2069 		}
2070 	} else {
2071 		/* ip address is not followed by port */
2072 		ec = ISNS_RSP_MSG_FORMAT_ERROR;
2073 	}
2074 
2075 	*p = obj;
2076 	*op = tmp;
2077 	*op_len = tmp_len;
2078 
2079 	return (ec);
2080 }
2081 
2082 /*
2083  * ****************************************************************************
2084  *
2085  * reg_get_pg:
2086  *	parse the Operating Attributes of the DevAttrReg message and
2087  *	create a Portal Group object.
2088  *
2089  * p	- the pointer of the object for returning.
2090  * op	- the operating attributes.
2091  * op_len - the length of the operating attributes.
2092  * return - error code.
2093  *
2094  * ****************************************************************************
2095  */
2096 static int
2097 reg_get_pg(
2098 	isns_obj_t **p,
2099 	isns_tlv_t **op,
2100 	uint16_t *op_len
2101 )
2102 {
2103 	int ec = 0;
2104 
2105 	isns_tlv_t *tmp;
2106 	uint16_t tmp_len;
2107 	isns_attr_t *attr;
2108 
2109 	isns_obj_t *obj = NULL;
2110 
2111 	tmp = *op;
2112 	tmp_len = *op_len;
2113 
2114 	/* parse a complete pg object */
2115 	obj = obj_calloc(OBJ_PG);
2116 	if (obj != NULL) {
2117 		/* parse attributes */
2118 		do {
2119 			attr = &obj->attrs[
2120 			    ATTR_INDEX_PG(tmp->attr_id)];
2121 			ec = copy_attr(attr, tmp);
2122 			NEXT_TLV(tmp, tmp_len);
2123 		} while (ec == 0 &&
2124 		    tmp_len >= 8 &&
2125 		    IS_PG_ATTR(tmp->attr_id));
2126 	} else {
2127 		ec = ISNS_RSP_INTERNAL_ERROR;
2128 	}
2129 
2130 	*p = obj;
2131 	*op = tmp;
2132 	*op_len = tmp_len;
2133 
2134 	return (ec);
2135 }
2136 
2137 /*
2138  * ****************************************************************************
2139  *
2140  * reg_get_pg1:
2141  *	parse the Operating Attributes of the DevAttrReg message and
2142  *	create a Portal Group object which is followed to a Portal object.
2143  *
2144  * p	- the pointer of the object for returning.
2145  * pgt	- the size-3 array of pointers which have the pg portal ip addr, port
2146  *	  and the pg tag attributes.
2147  * op	- the operating attributes.
2148  * op_len - the length of the operating attributes.
2149  * return - error code.
2150  *
2151  * ****************************************************************************
2152  */
2153 static int
2154 reg_get_pg1(
2155 	isns_obj_t **p,
2156 	isns_attr_t const *pgt,
2157 	isns_tlv_t **op,
2158 	uint16_t *op_len
2159 )
2160 {
2161 	int ec = 0;
2162 
2163 	isns_tlv_t *tmp;
2164 	uint16_t tmp_len;
2165 	isns_attr_t *attr;
2166 
2167 	isns_obj_t *obj = NULL;
2168 	int i = 0;
2169 
2170 	tmp = *op;
2171 	tmp_len = *op_len;
2172 
2173 	if (pgt[0].tag == PG_KEY2 &&
2174 	    pgt[1].tag == PG_KEY3) {
2175 		/* the pg iscsi storage node name is */
2176 		/* followed to a portal group tag */
2177 		obj = obj_calloc(OBJ_PG);
2178 		if (obj != NULL) {
2179 			/* copy pg iscsi storage node name */
2180 			attr = &obj->attrs[
2181 			    ATTR_INDEX_PG(tmp->attr_id)];
2182 			ec = copy_attr(attr, tmp);
2183 			/* copy pg ip addr, pg port & pgt */
2184 			while (ec == 0 && i < 3) {
2185 				attr = &obj->attrs[
2186 				    ATTR_INDEX_PG(pgt[i].tag)];
2187 				ec = assign_attr(attr, &pgt[i]);
2188 				i ++;
2189 			}
2190 			NEXT_TLV(tmp, tmp_len);
2191 		} else {
2192 			/* no memory */
2193 			ec = ISNS_RSP_INTERNAL_ERROR;
2194 		}
2195 	} else {
2196 		ec = ISNS_RSP_MSG_FORMAT_ERROR;
2197 	}
2198 
2199 	*p = obj;
2200 	*op = tmp;
2201 	*op_len = tmp_len;
2202 
2203 	return (ec);
2204 }
2205 
2206 /*
2207  * ****************************************************************************
2208  *
2209  * reg_get_pg2:
2210  *	parse the Operating Attributes of the DevAttrReg message and
2211  *	create a Portal Group object which is followed to a iSCSI
2212  *	Storage Node object.
2213  *
2214  * p	- the pointer of the object for returning.
2215  * pgt	- the size-3 array of pointers which have the pg iscsi storage
2216  *	  node name and the pg tag attributes.
2217  * op	- the operating attributes.
2218  * op_len - the length of the operating attributes.
2219  * return - error code.
2220  *
2221  * ****************************************************************************
2222  */
2223 static int
2224 reg_get_pg2(
2225 	isns_obj_t **p,
2226 	isns_attr_t const *pgt,
2227 	isns_tlv_t **op,
2228 	uint16_t *op_len
2229 )
2230 {
2231 	int ec = 0;
2232 
2233 	isns_tlv_t *tmp;
2234 	uint16_t tmp_len;
2235 	isns_attr_t *attr;
2236 
2237 	isns_obj_t *obj = NULL;
2238 	int i = 0;
2239 
2240 	isns_tlv_t *ip;
2241 
2242 	tmp = *op;
2243 	tmp_len = *op_len;
2244 
2245 	/* keep ip address */
2246 	ip = tmp;
2247 	NEXT_TLV(tmp, tmp_len);
2248 
2249 	if (tmp_len > 8 &&
2250 	    /* expect pg portal port */
2251 	    tmp->attr_id == PG_KEY3 &&
2252 	    tmp->attr_len == 4 &&
2253 	    /* expect pg tag */
2254 	    pgt[2].tag == PG_PGT &&
2255 	    /* expect pg iscsi storage node name only */
2256 	    pgt[1].tag == 0 &&
2257 	    pgt[0].tag == PG_KEY1) {
2258 		/* the pg portal ip addr & port is followed */
2259 		/* to a pg tag and we have the iscsi storage */
2260 		/* node parsed previously */
2261 		obj = obj_calloc(OBJ_PG);
2262 		if (obj != NULL) {
2263 			/* copy the pg ip addr */
2264 			attr = &obj->attrs[
2265 			    ATTR_INDEX_PG(ip->attr_id)];
2266 			ec = copy_attr(attr, ip);
2267 			/* copy the pg port */
2268 			if (ec == 0) {
2269 				attr = &obj->attrs[
2270 				    ATTR_INDEX_PG(tmp->attr_id)];
2271 				ec = copy_attr(attr, tmp);
2272 			}
2273 			/* copy pg iscsi storage node name & pgt */
2274 			while (ec == 0 && i < 3) {
2275 				attr = &obj->attrs[
2276 				    ATTR_INDEX_PG(pgt[i].tag)];
2277 				ec = assign_attr(attr, &pgt[i]);
2278 				i += 2;
2279 			}
2280 			NEXT_TLV(tmp, tmp_len);
2281 		} else {
2282 			ec = ISNS_RSP_INTERNAL_ERROR;
2283 		}
2284 	} else {
2285 		ec = ISNS_RSP_MSG_FORMAT_ERROR;
2286 	}
2287 
2288 	*p = obj;
2289 	*op = tmp;
2290 	*op_len = tmp_len;
2291 
2292 	return (ec);
2293 }
2294 
2295 /*
2296  * ****************************************************************************
2297  *
2298  * reg_get_obj:
2299  *	parse and create one object from the rest of Operating Attributes
2300  *	of the DevAttrReg message, the object can be iSCSI Storage Node,
2301  *	Portal or Portal Group.
2302  *
2303  * p	- the pointer of the object for returning.
2304  * pgt	- an attribute array with size 3, the elements are:
2305  *	  0: the first pg key attribute, it is either the name of an
2306  *	     iscsi storage node object or the ip addr of a portal object.
2307  *	  1: the second pg key attribute, i.e. the portal port.
2308  *	  2: the portal group tag attribute.
2309  * op	- the operating attributes.
2310  * op_len - the length of the operating attributes.
2311  * return - error code.
2312  *
2313  * ****************************************************************************
2314  */
2315 int
2316 reg_get_obj(
2317 	isns_obj_t **p,
2318 	isns_attr_t *pgt,
2319 	isns_tlv_t **op,
2320 	uint16_t *op_len
2321 )
2322 {
2323 	int ec = 0;
2324 
2325 	int derefd = 0;
2326 
2327 	uint32_t pg_tag;
2328 
2329 	if (*op_len == 0) {
2330 		*p = NULL;
2331 		return (0);
2332 	}
2333 
2334 	switch ((*op)->attr_id) {
2335 	case ISCSI_KEY:
2336 		ec = reg_get_iscsi(p, &pgt[0], op, op_len);
2337 		pgt[1].tag = 0;
2338 		pgt[2].tag = 0;
2339 		break;
2340 	case PORTAL_KEY1:
2341 		ec = reg_get_portal(p, &pgt[0], &pgt[1], op, op_len);
2342 		pgt[2].tag = 0;
2343 		break;
2344 	case PG_KEY1:
2345 		if (pgt[2].tag == PG_PGT) {
2346 			/* pg iscsi storage node name is */
2347 			/* followed to a pgt */
2348 			ec = reg_get_pg1(p, pgt, op, op_len);
2349 		} else {
2350 			/* a complete pg object */
2351 			ec = reg_get_pg(p, op, op_len);
2352 			pgt[0].tag = 0;
2353 			pgt[1].tag = 0;
2354 			pgt[2].tag = 0;
2355 		}
2356 		break;
2357 	case PG_KEY2:
2358 		/* pg portal ip addr is followed to a pgt */
2359 		ec = reg_get_pg2(p, pgt, op, op_len);
2360 		break;
2361 	case PG_PGT:
2362 		switch (pgt[0].tag) {
2363 		case 0:
2364 			/* portal group tag does not follow */
2365 			/* iscsi storage node or portal object */
2366 			*p = NULL;
2367 			ec = ISNS_RSP_MSG_FORMAT_ERROR;
2368 			break;
2369 		case PG_KEY1:
2370 		case PG_KEY2:
2371 			pgt[2].tag = PG_PGT;
2372 			pgt[2].len = (*op)->attr_len;
2373 			pg_tag = 0;
2374 			switch ((*op)->attr_len) {
2375 			case 4:
2376 				pg_tag = ntohl(*(uint32_t *)
2377 				    &(*op)->attr_value[0]);
2378 				/* FALLTHROUGH */
2379 			case 0:
2380 				pgt[2].value.ui = pg_tag;
2381 				break;
2382 			default:
2383 				*p = NULL;
2384 				ec = ISNS_RSP_MSG_FORMAT_ERROR;
2385 				break;
2386 			}
2387 			if (ec == 0) {
2388 				derefd = 1;
2389 				NEXT_TLV(*op, *op_len);
2390 				ec = reg_get_obj(p, pgt, op, op_len);
2391 			}
2392 			break;
2393 		default:
2394 			/* should never happen */
2395 			ASSERT(0);
2396 			*p = NULL;
2397 			ec = ISNS_RSP_INTERNAL_ERROR;
2398 			break;
2399 		}
2400 		break;
2401 	default:
2402 		*p = NULL;
2403 		ec = ISNS_RSP_MSG_FORMAT_ERROR;
2404 		break;
2405 	}
2406 
2407 	if (ec == 0 && derefd == 0) {
2408 		ec = update_deref_obj(*p);
2409 	}
2410 
2411 	if (ec != 0 && *p != NULL) {
2412 		free_one_object(*p);
2413 		*p = NULL;
2414 	}
2415 
2416 	return (ec);
2417 }
2418 
2419 /*
2420  * ****************************************************************************
2421  *
2422  * reg_auth_src:
2423  *	Authorize the source attribute the DevAttrReg message.
2424  *	The update can only performed by the node who has the owenership.
2425  *
2426  * p	- the pointer of the object for returning.
2427  * pgt	- an attribute array with size 3, the elements are:
2428  *	  0: the first pg key attribute, it is either the name of an
2429  *	     iscsi storage node object or the ip addr of a portal object.
2430  *	  1: the second pg key attribute, i.e. the portal port.
2431  *	  2: the portal group tag attribute.
2432  * op	- the operating attributes.
2433  * op_len - the length of the operating attributes.
2434  * return - error code.
2435  *
2436  * ****************************************************************************
2437  */
2438 int
2439 reg_auth_src(
2440 	isns_type_t type,
2441 	uint32_t uid,
2442 	uchar_t *src
2443 )
2444 {
2445 	lookup_ctrl_t lc;
2446 	uint32_t puid;
2447 
2448 	puid = is_parent_there(src);
2449 
2450 	if (TYPE_OF_PARENT[type] != 0) {
2451 		SET_UID_LCP(&lc, type, uid);
2452 		uid = cache_lookup(&lc, NULL, cb_get_parent);
2453 		type = TYPE_OF_PARENT[type];
2454 	}
2455 
2456 	if (uid != 0 && puid == 0) {
2457 		SET_UID_LCP(&lc, type, uid);
2458 		uid = cache_lookup(&lc, NULL, cb_node_child);
2459 	}
2460 
2461 	if (puid != uid) {
2462 		return (0);
2463 	}
2464 
2465 	return (1);
2466 }
2467 
2468 /*
2469  * ****************************************************************************
2470  *
2471  * is_obj_online:
2472  *	determine if the object is currently registered with the server.
2473  *
2474  * obj - the object being checked.
2475  * return - 0: not registered, otherwise registered.
2476  *
2477  * ****************************************************************************
2478  */
2479 int
2480 is_obj_online(
2481 	const isns_obj_t *obj
2482 )
2483 {
2484 	int online = 1;
2485 
2486 	switch (obj->type) {
2487 	case OBJ_ISCSI:
2488 		online = obj->attrs[ATTR_INDEX_ISCSI(
2489 		    ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui == 0 ? 0 : 1;
2490 		break;
2491 	default:
2492 		break;
2493 	}
2494 
2495 	return (online);
2496 }
2497 
2498 static int
2499 set_obj_offline(
2500 	isns_obj_t *obj
2501 )
2502 {
2503 	switch (obj->type) {
2504 	case OBJ_ISCSI:
2505 		obj->attrs[ATTR_INDEX_ISCSI(
2506 		    ISNS_ISCSI_NODE_TYPE_ATTR_ID)].value.ui = 0;
2507 		break;
2508 	default:
2509 		break;
2510 	}
2511 
2512 	return (0);
2513 }
2514 
2515 /*
2516  * ****************************************************************************
2517  *
2518  * assoc_clone:
2519  *	clone the association object.
2520  *
2521  * p - the object being cloned.
2522  * clone_flag - 0: the object is being removed;
2523  *		1: only the association is being removed.
2524  * return - the clone object.
2525  *
2526  * ****************************************************************************
2527  */
2528 void *
2529 assoc_clone(
2530 	void *p,
2531 	int clone_flag
2532 )
2533 {
2534 	isns_type_t type;
2535 	isns_obj_t *clone;
2536 	const isns_attr_t *src_attr;
2537 	isns_attr_t *dst_attr;
2538 	uint32_t id, op;
2539 	int i = 0;
2540 
2541 	const isns_obj_t *obj;
2542 	uint32_t dd_flag;
2543 	int online;
2544 
2545 	int state;
2546 
2547 	obj = (isns_obj_t *)p;
2548 
2549 	if (obj->type != OBJ_ISCSI) {
2550 		return (NULL);
2551 	}
2552 
2553 	dd_flag = (get_dd_id(get_obj_uid(obj), ISNS_DEFAULT_DD_ID) == 0) ?
2554 	    0 : 1;
2555 	online = is_obj_online(obj);
2556 
2557 	state = (clone_flag << 2) | (dd_flag  << 1) | online;
2558 
2559 	/* clone_flag	dd_flag	online	action		*/
2560 	/* 0		0	0	ASSERT(0)	*/
2561 	/* 0		0	1	NULL		*/
2562 	/* 0		1	0	itself		*/
2563 	/* 0		1	1	clone it	*/
2564 	/* 1		0	0	NULL		*/
2565 	/* 1		0	1	itself		*/
2566 	/* 1		1	0	itself		*/
2567 	/* 1		1	1	itself		*/
2568 
2569 	switch (state) {
2570 	case 0:
2571 		ASSERT(0);
2572 	case 1:
2573 	case 4:
2574 		return (NULL);
2575 	case 2:
2576 	case 5:
2577 	case 6:
2578 	case 7:
2579 		return (p);
2580 	case 3:
2581 	default:
2582 		break;
2583 	}
2584 
2585 	type = obj->type;
2586 	clone = obj_calloc(type);
2587 
2588 	if (clone != NULL) {
2589 		id = UID_ATTR_INDEX[type];
2590 		src_attr = &(obj->attrs[id]);
2591 		dst_attr = &(clone->attrs[id]);
2592 		if (assign_attr(dst_attr, src_attr) != 0) {
2593 			free_one_object(clone);
2594 			return (NULL);
2595 		}
2596 
2597 		while (i < MAX_KEY_ATTRS) {
2598 			op = KEY_ATTR_OP[type][i];
2599 			if (op != 0) {
2600 				id = KEY_ATTR_INDEX[type][i];
2601 				src_attr = &(obj->attrs[id]);
2602 				dst_attr = &(clone->attrs[id]);
2603 				if (assign_attr(dst_attr, src_attr) != 0) {
2604 					free_one_object(clone);
2605 					return (NULL);
2606 				}
2607 			} else {
2608 				break;
2609 			}
2610 			i ++;
2611 		}
2612 	}
2613 
2614 	return ((void *)clone);
2615 }
2616 
2617 /*
2618  * ****************************************************************************
2619  *
2620  * free_one_object:
2621  *	free up one object.
2622  *
2623  * obj - the object being freed.
2624  *
2625  * ****************************************************************************
2626  */
2627 void
2628 free_one_object(
2629 	isns_obj_t *obj
2630 )
2631 {
2632 	int i;
2633 	uint32_t *cuid;
2634 	if (obj == NULL) {
2635 		return;
2636 	}
2637 	for (i = 0; i < NUM_OF_ATTRS[obj->type]; i++) {
2638 		isns_attr_t *attr = &obj->attrs[i];
2639 		switch (attr->tag) {
2640 			case ISNS_EID_ATTR_ID:
2641 			case ISNS_ISCSI_NAME_ATTR_ID:
2642 			case ISNS_ISCSI_ALIAS_ATTR_ID:
2643 			case ISNS_ISCSI_AUTH_METHOD_ATTR_ID:
2644 			case ISNS_PG_ISCSI_NAME_ATTR_ID:
2645 			case ISNS_PORTAL_IP_ADDR_ATTR_ID:
2646 			case ISNS_PORTAL_NAME_ATTR_ID:
2647 			case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
2648 			case ISNS_DD_SET_NAME_ATTR_ID:
2649 			case ISNS_DD_NAME_ATTR_ID:
2650 			case ISNS_DD_ISCSI_NAME_ATTR_ID:
2651 			case ISNS_DD_FC_PORT_NAME_ATTR_ID:
2652 			case ISNS_DD_PORTAL_IP_ADDR_ATTR_ID:
2653 #ifdef DEBUG
2654 				if (verbose_mc) {
2655 					printf("memory(%d) deallocated\n",
2656 					    attr->len);
2657 				}
2658 #endif
2659 				free(attr->value.ptr);
2660 				attr->value.ptr = NULL;
2661 				break;
2662 			default:
2663 				break;
2664 		}
2665 	}
2666 
2667 	/* free child uids */
2668 	i = 0;
2669 	while (i < NUM_OF_CHILD[obj->type]) {
2670 		cuid = get_child_n(obj, i);
2671 		free(cuid);
2672 		i ++;
2673 	}
2674 
2675 	/* at last, free the object itself */
2676 #ifdef DEBUG
2677 	if (verbose_mc) {
2678 		printf("object(%d) deallocated\n", obj->type);
2679 	}
2680 #endif
2681 	free(obj);
2682 }
2683 
2684 /*
2685  * ****************************************************************************
2686  *
2687  * free_object:
2688  *	free up one object.
2689  *
2690  * obj - the object being freed.
2691  *
2692  * ****************************************************************************
2693  */
2694 void
2695 free_object(
2696 	isns_obj_t *obj
2697 )
2698 {
2699 	free_one_object(obj);
2700 }
2701 
2702 /*
2703  * ****************************************************************************
2704  *
2705  * set_parent_obj:
2706  *	set the parent object UID.
2707  *
2708  * obj - the child object.
2709  * puid- the parent object UID.
2710  * return - error code.
2711  *
2712  * ****************************************************************************
2713  */
2714 int
2715 set_parent_obj(
2716 	isns_obj_t *obj,
2717 	uint32_t puid
2718 )
2719 {
2720 	uint32_t *const p = get_parent_p(obj);
2721 	if (p != NULL) {
2722 		*p = puid;
2723 	}
2724 
2725 	return (0);
2726 }
2727 
2728 /*
2729  * ****************************************************************************
2730  *
2731  * buff_child_obj:
2732  *	add a child object UID to the child object array.
2733  *
2734  * obj - the parent object.
2735  * child_type - the type of the child object.
2736  * number  - the number of the child object.
2737  * return - the length of the child object UID array.
2738  *
2739  * ****************************************************************************
2740  */
2741 int
2742 buff_child_obj(
2743 	const isns_type_t ptype,
2744 	const isns_type_t ctype,
2745 	const void *c,
2746 	void const ***child
2747 )
2748 {
2749 	int ec = 0;
2750 
2751 	int i = 0;
2752 	void const ***pp, **p;
2753 	uint32_t num, new_num;
2754 
2755 	pp = NULL;
2756 	/* get the pointer of the array which the child belongs to */
2757 	while (i < NUM_OF_CHILD[ptype]) {
2758 		if (TYPE_OF_CHILD[ptype][i] == ctype) {
2759 			pp = &child[i];
2760 			break;
2761 		}
2762 		i ++;
2763 	}
2764 
2765 	/* the child type is not applicable */
2766 	if (pp == NULL) {
2767 		return (ec);
2768 	}
2769 
2770 	p = *pp;
2771 	/* get an empty slot from the uid array for this child */
2772 	if (p != NULL) {
2773 		num = (uint32_t)*p;
2774 		i = 0;
2775 		while (i < num) {
2776 			if (p[++i] == NULL) {
2777 				/* found it */
2778 				p[i] = c;
2779 				return (ec);
2780 			}
2781 		}
2782 		p = *pp;
2783 		new_num = num + 1;
2784 	} else {
2785 		num = 0;
2786 		new_num = 1;
2787 	}
2788 
2789 	/* the array is full, enlarge the child uid array */
2790 	p = (void const **)realloc(p, (new_num + 1) * sizeof (void *));
2791 	if (p != NULL) {
2792 		*pp = p;
2793 		*p = (void *)new_num;
2794 		p[new_num] = c;
2795 	} else {
2796 		ec = ISNS_RSP_INTERNAL_ERROR;
2797 	}
2798 
2799 	return (ec);
2800 }
2801 
2802 /*
2803  * ****************************************************************************
2804  *
2805  * update_child_object:
2806  *	update the child object of a network entity object.
2807  *
2808  * puid - the UID of the parent object, i.e. the network entity object.
2809  * child_type - the type of the child object.
2810  * child_uid  - the uid of the child object.
2811  * return - error code.
2812  *
2813  * ****************************************************************************
2814  */
2815 int
2816 update_child_obj(
2817 	const isns_type_t ptype,
2818 	const uint32_t puid,
2819 	void const ***child,
2820 	int child_flag
2821 )
2822 {
2823 	int ec = 0;
2824 
2825 	lookup_ctrl_t lc;
2826 
2827 	SET_UID_LCP(&lc, ptype, puid);
2828 
2829 	lc.data[1].ptr = (uchar_t *)child;
2830 	lc.data[2].ui = child_flag;
2831 
2832 	ec = cache_lookup(&lc, NULL, cb_add_child);
2833 
2834 	return (ec);
2835 }
2836 
2837 int
2838 update_ref_obj(
2839 	const isns_obj_t *obj
2840 )
2841 {
2842 	uint32_t uid;
2843 	lookup_ctrl_t lc;
2844 	isns_type_t t;
2845 
2846 	t = obj->type;
2847 
2848 	if (TYPE_OF_REF[t][0] != 0) {
2849 		(void) setup_ref_lcp(&lc, obj, NULL);
2850 
2851 		lc.id[2] = t;
2852 		lc.data[2].ui = get_obj_uid(obj);
2853 
2854 		uid = 0;
2855 		do {
2856 			lc.curr_uid = uid;
2857 			(void) cache_lookup(&lc, &uid, cb_set_ref);
2858 		} while (uid != 0);
2859 	}
2860 
2861 	return (0);
2862 }
2863 
2864 /*
2865  * ****************************************************************************
2866  *
2867  * verify_ref_obj:
2868  *	update the reference bit of a portal group object.
2869  *
2870  * obj - the object being ref'ed.
2871  * return - error code.
2872  *
2873  * ****************************************************************************
2874  */
2875 int
2876 verify_ref_obj(
2877 	const isns_type_t ptype,
2878 	const uint32_t puid,
2879 	void const ***child
2880 )
2881 {
2882 	int ec = 0;
2883 
2884 	lookup_ctrl_t lc;
2885 
2886 	SET_UID_LCP(&lc, ptype, puid);
2887 
2888 	lc.data[1].ptr = (uchar_t *)child;
2889 
2890 	ec = cache_lookup(&lc, NULL, cb_verify_ref);
2891 
2892 	return (ec);
2893 }
2894 
2895 int
2896 update_deref_obj(
2897 	isns_obj_t *obj
2898 )
2899 {
2900 	int ec = 0;
2901 
2902 	isns_type_t t, rt;
2903 	lookup_ctrl_t lc;
2904 	int i, ref_count;
2905 
2906 	uint32_t uid, *refp;
2907 
2908 	t = obj->type;
2909 	i = ref_count = 0;
2910 	while (i < NUM_OF_REF[t]) {
2911 		rt = TYPE_OF_REF[t][i + 1];
2912 		(void) setup_deref_lcp(&lc, obj, rt);
2913 		uid = is_obj_there(&lc);
2914 		if (uid != 0) {
2915 			refp = get_ref_p(obj, lc.type);
2916 			*refp = uid;
2917 			ref_count ++;
2918 		}
2919 		i ++;
2920 	}
2921 
2922 	if (i > 0 && ref_count == 0) {
2923 		ec = ISNS_RSP_INVALID_REGIS;
2924 	}
2925 
2926 	return (ec);
2927 }
2928 
2929 /*
2930  * ****************************************************************************
2931  *
2932  * register_object:
2933  *	add one object to the object container.
2934  *
2935  * obj	- the object being added.
2936  * uid_p- the pointer for returning object UID.
2937  * update_p- the pointer for returning flag which indicates if the object
2938  *		is newly registered or updated with an existing one.
2939  * return - error code.
2940  *
2941  * ****************************************************************************
2942  */
2943 int
2944 register_object(
2945 	isns_obj_t *obj,
2946 	uint32_t *uid_p,
2947 	int *update_p
2948 )
2949 {
2950 	return (cache_add(obj, 0, uid_p, update_p));
2951 }
2952 
2953 /*
2954  * ****************************************************************************
2955  *
2956  * register_assoc:
2957  *	add one association object to the object container, the association
2958  *	object has only the information for discovery domain membership, i.e.
2959  *	a name and UID only.
2960  *
2961  * obj	- the association object being added.
2962  * uid_p- the pointer for returning object UID.
2963  * return - error code.
2964  *
2965  * ****************************************************************************
2966  */
2967 int
2968 register_assoc(
2969 	isns_obj_t *obj,
2970 	uint32_t *uid_p
2971 )
2972 {
2973 	return (cache_add(obj, 1, uid_p, NULL));
2974 }
2975 
2976 /*
2977  * ****************************************************************************
2978  *
2979  * is_obj_there:
2980  *	check if the object is registered or not.
2981  *
2982  * lcp	- the lookup control data.
2983  * return - the object UID.
2984  *
2985  * ****************************************************************************
2986  */
2987 uint32_t
2988 is_obj_there(
2989 	lookup_ctrl_t *lcp
2990 )
2991 {
2992 	uint32_t uid;
2993 
2994 	(void) cache_lookup(lcp, &uid, NULL);
2995 
2996 	return (uid);
2997 }
2998 
2999 uint32_t
3000 is_parent_there(
3001 	uchar_t *src
3002 )
3003 {
3004 	lookup_ctrl_t lc;
3005 
3006 	lc.curr_uid = 0;
3007 	lc.type = OBJ_ISCSI;
3008 	lc.id[0] = ATTR_INDEX_ISCSI(ISNS_ISCSI_NAME_ATTR_ID);
3009 	lc.op[0] = OP_STRING;
3010 	lc.data[0].ptr = src;
3011 	lc.op[1] = 0;
3012 
3013 	return (cache_lookup(&lc, NULL, cb_get_parent));
3014 }
3015 
3016 /*
3017  * ****************************************************************************
3018  *
3019  * setup_ref_lcp:
3020  *	prepare the lookup control data for looking up a portal group
3021  *	object which references to a iscsi stroage node and/or a portal
3022  *	object.
3023  *
3024  * lcp	- the lookup control data.
3025  * iscsi- the ref'ed iscsi storage node object.
3026  * portal- the ref'ed portal object.
3027  * return - error code.
3028  *
3029  * ****************************************************************************
3030  */
3031 static int
3032 setup_ref_lcp(
3033 	lookup_ctrl_t *lcp,
3034 	const isns_obj_t *iscsi,
3035 	const isns_obj_t *portal
3036 )
3037 {
3038 	int i = 0, j = 0;
3039 
3040 	lcp->curr_uid = 0;
3041 	lcp->type = TYPE_OF_REF[iscsi->type][0];
3042 
3043 	/* extrace the matching attributes from iscsi storage node object */
3044 	while (iscsi != NULL &&
3045 	    i < MAX_REF_MATCH &&
3046 	    REF_MATCH_OPS[iscsi->type][i] > 0) {
3047 		lcp->id[i] = REF_MATCH_ID2[iscsi->type][i];
3048 		lcp->op[i] = REF_MATCH_OPS[iscsi->type][i];
3049 		lcp->data[i].ptr = iscsi->attrs[
3050 		    REF_MATCH_ID1[iscsi->type][i]].value.ptr;
3051 		i ++;
3052 	}
3053 
3054 	/* extrace the matching attributes from portal object */
3055 	while (portal != NULL &&
3056 	    i < MAX_LOOKUP_CTRL &&
3057 	    j < MAX_REF_MATCH &&
3058 	    REF_MATCH_OPS[portal->type][j] > 0) {
3059 		lcp->id[i] = REF_MATCH_ID2[portal->type][j];
3060 		lcp->op[i] = REF_MATCH_OPS[portal->type][j];
3061 		lcp->data[i].ptr = portal->attrs[
3062 		    REF_MATCH_ID1[portal->type][j]].value.ptr;
3063 		j ++;
3064 		i ++;
3065 	}
3066 
3067 	if (i < MAX_LOOKUP_CTRL) {
3068 		lcp->op[i] = 0;
3069 	}
3070 
3071 	return (0);
3072 }
3073 
3074 static int
3075 setup_deref_lcp(
3076 	lookup_ctrl_t *lcp,
3077 	const isns_obj_t *pg,
3078 	isns_type_t t
3079 )
3080 {
3081 	int i = 0;
3082 
3083 	lcp->curr_uid = 0;
3084 	lcp->type = t;
3085 
3086 	/* extrace the matching attributes from iscsi storage node object */
3087 	while (i < MAX_REF_MATCH &&
3088 	    REF_MATCH_OPS[t][i] > 0) {
3089 		lcp->id[i] = REF_MATCH_ID1[t][i];
3090 		lcp->op[i] = REF_MATCH_OPS[t][i];
3091 		lcp->data[i].ptr = pg->attrs[
3092 		    REF_MATCH_ID2[t][i]].value.ptr;
3093 		i ++;
3094 	}
3095 
3096 	if (i < MAX_LOOKUP_CTRL) {
3097 		lcp->op[i] = 0;
3098 	}
3099 
3100 	return (0);
3101 }
3102 
3103 /*
3104  * ****************************************************************************
3105  *
3106  * setup_parent_lcp:
3107  *	prepare the lookup control data for looking up parent object
3108  *	with a child object.
3109  *
3110  * lcp	- the lookup control data.
3111  * obj	- the child object.
3112  * return - parent object UID.
3113  *
3114  * ****************************************************************************
3115  */
3116 static uint32_t
3117 setup_parent_lcp(
3118 	lookup_ctrl_t *lcp,
3119 	isns_obj_t *obj
3120 )
3121 {
3122 	isns_type_t ptype;
3123 	uint32_t puid;
3124 
3125 	puid = get_parent_uid(obj);
3126 	if (puid != 0) {
3127 		ptype = TYPE_OF_PARENT[obj->type];
3128 		SET_UID_LCP(lcp, ptype, puid);
3129 		lcp->data[1].ui = obj->type;
3130 		lcp->data[2].ui = get_obj_uid(obj);
3131 	}
3132 
3133 	return (puid);
3134 }
3135 
3136 static int
3137 cb_get_parent(
3138 	void *p1,
3139 	/* LINTED E_FUNC_ARG_UNUSED */
3140 	void *p2
3141 )
3142 {
3143 	return (get_parent_uid(p1));
3144 }
3145 
3146 static int
3147 cb_node_child(
3148 	void *p1,
3149 	/* LINTED E_FUNC_ARG_UNUSED */
3150 	void *p2
3151 )
3152 {
3153 	isns_obj_t *obj = (isns_obj_t *)p1;
3154 
3155 	uint32_t num, uid;
3156 
3157 	uint32_t *cuid = get_child_t(obj, OBJ_ISCSI);
3158 
3159 	if (cuid != NULL) {
3160 		num = *cuid;
3161 	} else {
3162 		num = 0;
3163 	}
3164 
3165 	while (num > 0) {
3166 		uid = *++cuid;
3167 		if (uid != 0) {
3168 			return (uid);
3169 		}
3170 		num --;
3171 	}
3172 
3173 	return (0);
3174 }
3175 
3176 /*
3177  * ****************************************************************************
3178  *
3179  * cb_set_ref:
3180  *	callback function which sets the reference bit to 1 according to
3181  *	the type of object.
3182  *
3183  * p1	- the object.
3184  * p2	- the lcp.
3185  * return - error code.
3186  *
3187  * ****************************************************************************
3188  */
3189 static int
3190 cb_set_ref(
3191 	void *p1,
3192 	void *p2
3193 )
3194 {
3195 	isns_obj_t *obj = (isns_obj_t *)p1;
3196 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3197 
3198 	isns_type_t t;
3199 	uint32_t u;
3200 
3201 	uint32_t *refp;
3202 
3203 	t = lcp->id[2];
3204 	u = lcp->data[2].ui;
3205 	refp = get_ref_p(obj, t);
3206 	*refp = u;
3207 
3208 	/* successful */
3209 	return (0);
3210 }
3211 
3212 /*
3213  * ****************************************************************************
3214  *
3215  * cb_clear_ref:
3216  *	callback function which clears the reference bit according to
3217  *	the type of object.
3218  *
3219  * p1	- the object.
3220  * p2	- the lcp.
3221  * return - 1: the object is no longer ref'ed, 0: otherwise.
3222  *
3223  * ****************************************************************************
3224  */
3225 static int
3226 cb_clear_ref(
3227 	void *p1,
3228 	void *p2
3229 )
3230 {
3231 	isns_obj_t *obj = (isns_obj_t *)p1;
3232 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3233 
3234 	isns_type_t t;
3235 	uint32_t *refp;
3236 
3237 	int i = 0;
3238 	uint32_t ref;
3239 
3240 	t = lcp->data[2].ui;
3241 	refp = get_ref_p(obj, t);
3242 	*refp = 0;
3243 
3244 	while (i < NUM_OF_REF[obj->type]) {
3245 		ref = get_ref_n(obj, i);
3246 		if (ref != 0) {
3247 			return (0);
3248 		}
3249 		i ++;
3250 	}
3251 
3252 	return (1);
3253 }
3254 
3255 static int
3256 cb_add_child(
3257 	void *p1,
3258 	void *p2
3259 )
3260 {
3261 	isns_obj_t *obj = (isns_obj_t *)p1;
3262 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3263 
3264 	const void ***child;
3265 	const void **vpp;
3266 	uint32_t vnum;
3267 	int child_flag;
3268 
3269 	uint32_t **upp, *up;
3270 	uint32_t num;
3271 
3272 	isns_obj_t *o;
3273 
3274 	int i = 0;
3275 
3276 	child = (const void ***)lcp->data[1].ptr;
3277 	child_flag = lcp->data[2].ui;
3278 
3279 	while (i < NUM_OF_CHILD[obj->type]) {
3280 		vpp = child[i];
3281 		if (vpp != NULL &&
3282 		    (vnum = (uint32_t)*vpp) > 0 &&
3283 		    *(vpp + 1) != NULL) {
3284 			upp = get_child_np(obj, i);
3285 			if (*upp == NULL) {
3286 				if (child_flag == 0 &&
3287 				    sizeof (typeof (**upp)) ==
3288 				    sizeof (typeof (**child))) {
3289 					*upp = (uint32_t *)vpp;
3290 					vpp = NULL;
3291 					child[i] = NULL;
3292 				}
3293 				num = vnum;
3294 			} else {
3295 				num = **upp + vnum;
3296 			}
3297 			if (vpp != NULL) {
3298 				/* copy required */
3299 				up = (uint32_t *)realloc(*upp,
3300 				    (num + 1) * sizeof (uint32_t));
3301 				if (up == NULL) {
3302 					return (ISNS_RSP_INTERNAL_ERROR);
3303 				}
3304 				*upp = up;
3305 				*up = num;
3306 				up += num;
3307 				vpp += vnum;
3308 				while (vnum > 0) {
3309 					if (*vpp == NULL) {
3310 						*up = 0;
3311 					} else if (child_flag == 0) {
3312 						*up = (uint32_t)*vpp;
3313 						*vpp = NULL;
3314 					} else {
3315 						o = (isns_obj_t *)*vpp;
3316 						*up = get_obj_uid(o);
3317 						if (is_obj_online(o) == 0) {
3318 							free_object(o);
3319 						}
3320 						*vpp = NULL;
3321 					}
3322 					up --;
3323 					vpp --;
3324 					vnum --;
3325 				}
3326 			}
3327 		}
3328 		i ++;
3329 	}
3330 
3331 	return (0);
3332 }
3333 
3334 /*
3335  * ****************************************************************************
3336  *
3337  * cb_remove_child:
3338  *	callback function which removes a child object UID from the
3339  *	children objet UID array of the parent object.
3340  *
3341  * p1	- the object.
3342  * p2	- the lcp.
3343  * return - 1: no more such type of child object, 0: otherwise.
3344  *
3345  * ****************************************************************************
3346  */
3347 static int
3348 cb_remove_child(
3349 	void *p1,
3350 	void *p2
3351 )
3352 {
3353 	isns_obj_t *obj = (isns_obj_t *)p1;
3354 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3355 	uint32_t child_type = lcp->data[1].ui;
3356 	uint32_t child_uid = lcp->data[2].ui;
3357 	uint32_t *cuidp, cuid, num_of_child = 0;
3358 	int i;
3359 
3360 	/* get the children object UID array */
3361 	cuidp = get_child_t(obj, child_type);
3362 	if (cuidp != NULL) {
3363 		num_of_child = *cuidp;
3364 	}
3365 
3366 	/* remove it */
3367 	while (num_of_child > 0) {
3368 		cuid = *++cuidp;
3369 		if (cuid == child_uid) {
3370 			*cuidp = 0;
3371 			break;
3372 		}
3373 		num_of_child --;
3374 	}
3375 
3376 	/* check if all of child object UIDs are removed */
3377 	i = 0;
3378 	while (i < NUM_OF_CHILD[obj->type]) {
3379 		cuidp = get_child_n(obj, i);
3380 		if (cuidp != NULL) {
3381 			num_of_child = *cuidp;
3382 			while (num_of_child > 0) {
3383 				cuid = *++cuidp;
3384 				if (cuid != 0) {
3385 					return (0);
3386 				}
3387 				num_of_child --;
3388 			}
3389 		}
3390 		i ++;
3391 	}
3392 
3393 	return (1);
3394 }
3395 
3396 static int
3397 cb_verify_ref(
3398 	void *p1,
3399 	void *p2
3400 )
3401 {
3402 	int ec = 0;
3403 
3404 	isns_obj_t *parent = (isns_obj_t *)p1;
3405 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3406 
3407 	const void ***child;
3408 
3409 	const void **vpp;
3410 	const void *vp;
3411 	uint32_t vnum;
3412 
3413 	const void **evpp;
3414 	const void *evp;
3415 	uint32_t evnum;
3416 
3417 	isns_type_t pt; /* parent object type */
3418 	isns_type_t ct; /* child object type */
3419 	isns_type_t rt; /* ref object type */
3420 	isns_type_t et; /* peer object type */
3421 
3422 	uint32_t *up;
3423 	uint32_t u;
3424 	uint32_t unum;
3425 
3426 	lookup_ctrl_t lc;
3427 	uint8_t flag[MAX_OBJ_TYPE + 1] = { 0 };
3428 
3429 	int i, j, k;
3430 
3431 	pt = parent->type;
3432 
3433 	child = (const void ***)lcp->data[1].ptr;
3434 
3435 	for (i = 0; i < NUM_OF_CHILD[pt]; i++) {
3436 		ct = TYPE_OF_CHILD[pt][i];
3437 		rt = TYPE_OF_REF[ct][0];
3438 		if (rt == 0) {
3439 			continue;
3440 		}
3441 
3442 		et = TYPE_OF_REF[ct][1];
3443 		vpp = child[i];
3444 		if (vpp != NULL) {
3445 			vnum = (uint32_t)*vpp;
3446 			up = get_child_t(parent, et);
3447 			if (up != NULL) {
3448 				unum = *up;
3449 			} else {
3450 				unum = 0;
3451 			}
3452 		} else {
3453 			vnum = 0;
3454 		}
3455 
3456 		j = vnum;
3457 		while (j > 0) {
3458 			vp = vpp[j];
3459 			if (vp != NULL) {
3460 				(void) setup_ref_lcp(&lc, vp, NULL);
3461 				k = unum;
3462 				while (k > 0) {
3463 					u = up[k];
3464 					if (u != 0) {
3465 						ec = ref_new2old(
3466 						    &lc, et, u, vp);
3467 						if (ec != 0) {
3468 							return (ec);
3469 						}
3470 					}
3471 					k --;
3472 				} /* End of while each unum */
3473 			}
3474 			j --;
3475 		} /* End of while each vnum */
3476 
3477 		if (flag[ct] != 0) {
3478 			continue;
3479 		}
3480 
3481 		evnum = 0;
3482 		j = 0;
3483 		while (j < NUM_OF_CHILD[pt]) {
3484 			if (TYPE_OF_CHILD[pt][j] == et) {
3485 				evpp = child[j];
3486 				if (evpp != NULL) {
3487 					evnum = (uint32_t)*evpp;
3488 				}
3489 				break;
3490 			}
3491 			j ++;
3492 		}
3493 
3494 		j = vnum;
3495 		while (j > 0) {
3496 			vp = vpp[j];
3497 			k = evnum;
3498 			while (k > 0) {
3499 				evp = evpp[k];
3500 				if (vp != NULL && evp != NULL) {
3501 					(void) setup_ref_lcp(&lc, vp, evp);
3502 					ec = ref_new2new(&lc, vp, evp);
3503 					if (ec != 0) {
3504 						return (ec);
3505 					}
3506 				}
3507 				k --;
3508 			}
3509 			j --;
3510 		} /* End of while each vnum */
3511 
3512 		flag[et] = 1;
3513 	} /* End of for each type of child */
3514 
3515 	return (ec);
3516 }
3517 
3518 static int
3519 cb_ref_new2old(
3520 	void *p1,
3521 	void *p2
3522 )
3523 {
3524 	isns_obj_t *obj = (isns_obj_t *)p1;
3525 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3526 
3527 	isns_type_t et;
3528 	uint32_t uu;
3529 
3530 	uint32_t ref;
3531 
3532 	int match;
3533 
3534 	et = lcp->id[2];
3535 	uu = lcp->data[2].ui;
3536 
3537 	ref = get_ref_t(obj, et);
3538 
3539 	if (ref == uu) {
3540 		match = 1;
3541 	} else {
3542 		match = 0;
3543 	}
3544 
3545 	return (match);
3546 }
3547 
3548 static int
3549 cb_new_ref(
3550 	void *p1,
3551 	void *p2
3552 )
3553 {
3554 	int ec = 0;
3555 
3556 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
3557 	isns_obj_t *a = (isns_obj_t *)p1;
3558 	isns_obj_t *b = (isns_obj_t *)lcp->data[2].ptr;
3559 
3560 	ec = new_ref(a, b);
3561 
3562 	return (ec);
3563 }
3564 
3565 static int
3566 ref_new2old(
3567 	lookup_ctrl_t *lcp,
3568 	isns_type_t et,
3569 	uint32_t uu,
3570 	const isns_obj_t *vp
3571 )
3572 {
3573 	int ec = 0;
3574 
3575 	int match;
3576 	uint32_t uid;
3577 
3578 	lookup_ctrl_t lc;
3579 
3580 	lcp->id[2] = et;
3581 	lcp->data[2].ui = uu;
3582 
3583 	uid = 0;
3584 	do {
3585 		lcp->curr_uid = uid;
3586 		match = cache_lookup(lcp, &uid, cb_ref_new2old);
3587 	} while (match == 0 && uid != 0);
3588 
3589 	if (match == 0) {
3590 		/* no such ref, create a default one */
3591 		SET_UID_LCP(&lc, et, uu);
3592 
3593 		lc.data[2].ptr = (uchar_t *)vp;
3594 
3595 		ec = cache_lookup(&lc, NULL, cb_new_ref);
3596 	}
3597 
3598 	return (ec);
3599 }
3600 
3601 static int
3602 ref_new2new(
3603 	lookup_ctrl_t *lcp,
3604 	const isns_obj_t *p1,
3605 	const isns_obj_t *p2
3606 )
3607 {
3608 	int ec = 0;
3609 
3610 	if (is_obj_there(lcp) != 0) {
3611 		return (0);
3612 	}
3613 
3614 	ec = new_ref(p1, p2);
3615 
3616 	return (ec);
3617 }
3618 
3619 static int
3620 new_ref(
3621 	const isns_obj_t *p1,
3622 	const isns_obj_t *p2
3623 )
3624 {
3625 	int ec = 0;
3626 
3627 	isns_obj_t *obj;
3628 
3629 	obj = make_ref[p1->type](p1, p2);
3630 	if (obj != NULL) {
3631 		ec = register_object(obj, NULL, NULL);
3632 	} else {
3633 		ec = ISNS_RSP_INTERNAL_ERROR;
3634 	}
3635 
3636 	return (ec);
3637 }
3638 
3639 /*
3640  * ****************************************************************************
3641  *
3642  * do_dereg:
3643  *	Physically remove an object along with the children objects,
3644  *	the reference object and the parent object recursively.
3645  *	Apporiate SCN is triggered.
3646  *
3647  * lcp	- the lookup control for the object being removed.
3648  * parent_flag	- 1: the object being removed is the parent object;
3649  *		  0: otherwise.
3650  * child_flag	- 1: the object being removed is a child object;
3651  *		  0: otherwise.
3652  * pending	- 1: do not remove the ESI entry immediately;
3653  *		  0: remove the ESI entry without any delay.
3654  * return - error code.
3655  *
3656  * ****************************************************************************
3657  */
3658 static int
3659 do_dereg(
3660 	lookup_ctrl_t *lcp,
3661 	int parent_flag,
3662 	int child_flag,
3663 	int pending
3664 )
3665 {
3666 	int ec = 0;
3667 
3668 	isns_obj_t *obj;
3669 	uint32_t *cuidp, num;
3670 	isns_type_t type;
3671 	uint32_t uid;
3672 	int i;
3673 
3674 	/* remove the object from object container */
3675 	obj = cache_remove(lcp, 0);
3676 
3677 	if (obj == NULL) {
3678 		return (0);
3679 	}
3680 
3681 	/* trigger a scn */
3682 	if (scn_q != NULL) {
3683 		(void) make_scn(ISNS_OBJECT_REMOVED, obj);
3684 	}
3685 
3686 	/* dereg children */
3687 	i = 0;
3688 	while (ec == 0 && !parent_flag &&
3689 	    i < NUM_OF_CHILD[obj->type]) {
3690 		type = TYPE_OF_CHILD[obj->type][i];
3691 		cuidp = get_child_n(obj, i);
3692 		if (cuidp != NULL) {
3693 			num = *cuidp;
3694 		} else {
3695 			num = 0;
3696 		}
3697 		while (ec == 0 && num > 0) {
3698 			uid = cuidp[num];
3699 			if (uid != 0) {
3700 				SET_UID_LCP(lcp, type, uid);
3701 				ec = do_dereg(lcp,
3702 				    parent_flag,
3703 				    1,
3704 				    pending);
3705 			}
3706 			num --;
3707 		}
3708 		i ++;
3709 	}
3710 
3711 	/* clear the ref bit on the ref'd object */
3712 	if (ec == 0 && TYPE_OF_REF[obj->type][0] > 0) {
3713 		uid = 0;
3714 		do {
3715 			(void) setup_ref_lcp(lcp, obj, NULL);
3716 			lcp->curr_uid = uid;
3717 			lcp->data[2].ui = obj->type;
3718 			if (cache_lookup(lcp, &uid, cb_clear_ref) != 0) {
3719 				UPDATE_LCP_UID(lcp, uid);
3720 				ec = do_dereg(lcp,
3721 				    parent_flag,
3722 				    child_flag,
3723 				    pending);
3724 			}
3725 		} while (uid != 0);
3726 	}
3727 
3728 	/* remove it from the parent */
3729 	if (ec == 0 && !child_flag &&
3730 	    TYPE_OF_PARENT[obj->type] > 0 &&
3731 	    (uid = setup_parent_lcp(lcp, obj)) != 0) {
3732 		if (cache_lookup(lcp, NULL, cb_remove_child) != 0) {
3733 			UPDATE_LCP_UID(lcp, uid);
3734 			ec = do_dereg(lcp,
3735 			    1,
3736 			    child_flag,
3737 			    0);
3738 		}
3739 	}
3740 
3741 	if (ec == 0 && !child_flag) {
3742 		/* remove it from persistent data store */
3743 		if (sys_q) {
3744 			ec = write_data(DATA_DELETE, obj);
3745 		}
3746 		/* remove esi event entry */
3747 		if (ec == 0) {
3748 			(void) esi_remove_obj(obj, pending);
3749 		}
3750 
3751 		/* save the parent uid for caller */
3752 		if (TYPE_OF_PARENT[obj->type] != 0) {
3753 			lcp->curr_uid = get_parent_uid(obj);
3754 		} else {
3755 			/* it's the parent itself */
3756 			lcp->curr_uid = get_obj_uid(obj);
3757 		}
3758 	}
3759 
3760 	/* remove this portal from scn registry */
3761 	if (ec == 0 &&
3762 	    obj->type == OBJ_PORTAL) {
3763 		(void) remove_scn_portal(get_obj_uid(obj));
3764 	}
3765 
3766 	/* free the object */
3767 	(void) free_object(obj);
3768 
3769 	return (ec);
3770 }
3771 
3772 /*
3773  * ****************************************************************************
3774  *
3775  * dereg_assoc:
3776  *	Remove one association object from object container.
3777  *
3778  * lcp	- the lookup control for the object being removed.
3779  * return - error code.
3780  *
3781  * ****************************************************************************
3782  */
3783 int
3784 dereg_assoc(
3785 	lookup_ctrl_t *lcp
3786 )
3787 {
3788 	isns_obj_t *obj;
3789 
3790 	obj = cache_remove(lcp, 1);
3791 
3792 	/* free the object */
3793 	if (obj != NULL) {
3794 		free_object(obj);
3795 	}
3796 
3797 	return (0);
3798 }
3799 
3800 /*
3801  * ****************************************************************************
3802  *
3803  * dereg_object:
3804  *	Remove one object from object container.
3805  *
3806  * lcp	- the lookup control for the object being removed.
3807  * return - error code.
3808  *
3809  * ****************************************************************************
3810  */
3811 int
3812 dereg_object(
3813 	lookup_ctrl_t *lcp,
3814 	int pending
3815 )
3816 {
3817 	return (do_dereg(lcp, 0, 0, pending));
3818 }
3819 
3820 /*
3821  * ****************************************************************************
3822  *
3823  * data_sync:
3824  *	Synchronize the cache with persistent data store.
3825  *	Flush the cache data to data store if the input ec is zero,
3826  *	retreat the changes in cache and ignore data store update
3827  *	if there is an error.
3828  *
3829  * ec	- error code.
3830  * return - error code.
3831  *
3832  * ****************************************************************************
3833  */
3834 int
3835 data_sync(
3836 	int ec
3837 )
3838 {
3839 	/* cache is updated successfully, commit the data to data store */
3840 	if (IS_CACHE_UPDATED()) {
3841 		if (ec == 0) {
3842 			ec = write_data(DATA_COMMIT, NULL);
3843 		}
3844 		if (ec == 0) {
3845 			/* successful, trigger the SCN */
3846 			(void) queue_msg_set(scn_q, SCN_TRIGGER, (void *)NULL);
3847 		} else {
3848 			shutdown_server();
3849 		}
3850 	} else {
3851 		/* ignore all SCNs which have been generated */
3852 		(void) queue_msg_set(scn_q, SCN_IGNORE, (void *)NULL);
3853 
3854 		(void) write_data(DATA_RETREAT, NULL);
3855 	}
3856 
3857 	return (ec);
3858 }
3859 
3860 static pthread_mutex_t name_mtx[3] = {
3861 	PTHREAD_MUTEX_INITIALIZER,
3862 	PTHREAD_MUTEX_INITIALIZER,
3863 	PTHREAD_MUTEX_INITIALIZER
3864 };
3865 static const char *name_pattern[3] = {
3866 	"ENTITY_ID_%d",
3867 	"DD_%d",
3868 	"DD-Set_%d"
3869 };
3870 static uint32_t name_count[3] = {
3871 	0,
3872 	0,
3873 	0
3874 };
3875 
3876 /*
3877  * ****************************************************************************
3878  *
3879  * make_unique_name:
3880  *	make a default unique name for a newly registered network entity,
3881  *	discovery domain or discovery domain set object.
3882  *
3883  * len	- pointer of the length of the new name for returning.
3884  * tag	- which attribute of the new name is for.
3885  * return - the name being made.
3886  *
3887  * ****************************************************************************
3888  */
3889 static char *
3890 make_unique_name(
3891 	int *len,
3892 	uint32_t tag
3893 )
3894 {
3895 	int i;
3896 	int count;
3897 	char name[32] = { 0 };
3898 
3899 	char *p;
3900 
3901 	lookup_ctrl_t lc;
3902 
3903 	lc.curr_uid = 0;
3904 
3905 	switch (tag) {
3906 	case ISNS_EID_ATTR_ID:
3907 		i = 0;
3908 		lc.type = OBJ_ENTITY;
3909 		lc.id[0] = ATTR_INDEX_ENTITY(ISNS_EID_ATTR_ID);
3910 		break;
3911 	case ISNS_DD_NAME_ATTR_ID:
3912 		i = 1;
3913 		lc.type = OBJ_DD;
3914 		lc.id[0] = ATTR_INDEX_DD(ISNS_DD_NAME_ATTR_ID);
3915 		break;
3916 	case ISNS_DD_SET_NAME_ATTR_ID:
3917 		i = 2;
3918 		lc.type = OBJ_DDS;
3919 		lc.id[0] = ATTR_INDEX_DDS(ISNS_DD_SET_NAME_ATTR_ID);
3920 		break;
3921 	default:
3922 		ASSERT(0);
3923 		break;
3924 	}
3925 
3926 	lc.op[0] = OP_STRING;
3927 	lc.op[1] = 0;
3928 	do {
3929 		(void) pthread_mutex_lock(&name_mtx[i]);
3930 		count = ++ name_count[i];
3931 		(void) pthread_mutex_unlock(&name_mtx[i]);
3932 		/* no more space, failure */
3933 		if (count == 0) {
3934 			return (NULL);
3935 		}
3936 		(void) sprintf(name, name_pattern[i], count);
3937 		lc.data[0].ptr = (uchar_t *)name;
3938 	} while (is_obj_there(&lc) != 0);
3939 
3940 	/* 4-bytes aligned length */
3941 	*len = strlen(name);
3942 	*len = *len + (4 - *len % 4);
3943 	p = (char *)malloc(*len);
3944 	if (p != NULL) {
3945 		(void) strcpy(p, name);
3946 	}
3947 	return (p);
3948 }
3949 
3950 #ifdef DEBUG
3951 void
3952 obj_dump(
3953 	void *p
3954 )
3955 {
3956 	print_object(NULL, (isns_obj_t *)p);
3957 }
3958 #endif
3959