xref: /titanic_51/usr/src/cmd/isns/isnsd/esi.c (revision fcf3ce441efd61da9bb2884968af01cb7c1452cc)
1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte  * CDDL HEADER START
3*fcf3ce44SJohn Forte  *
4*fcf3ce44SJohn Forte  * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte  * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte  * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte  *
8*fcf3ce44SJohn Forte  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte  * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte  * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte  * and limitations under the License.
12*fcf3ce44SJohn Forte  *
13*fcf3ce44SJohn Forte  * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte  * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte  * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte  *
19*fcf3ce44SJohn Forte  * CDDL HEADER END
20*fcf3ce44SJohn Forte  */
21*fcf3ce44SJohn Forte 
22*fcf3ce44SJohn Forte /*
23*fcf3ce44SJohn Forte  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*fcf3ce44SJohn Forte  * Use is subject to license terms.
25*fcf3ce44SJohn Forte  */
26*fcf3ce44SJohn Forte 
27*fcf3ce44SJohn Forte #include <stdio.h>
28*fcf3ce44SJohn Forte #include <stdlib.h>
29*fcf3ce44SJohn Forte #include <string.h>
30*fcf3ce44SJohn Forte #include <unistd.h>
31*fcf3ce44SJohn Forte #include <sys/types.h>
32*fcf3ce44SJohn Forte #include <time.h>
33*fcf3ce44SJohn Forte #include <signal.h>
34*fcf3ce44SJohn Forte #include <poll.h>
35*fcf3ce44SJohn Forte 
36*fcf3ce44SJohn Forte #include "isns_server.h"
37*fcf3ce44SJohn Forte #include "isns_cache.h"
38*fcf3ce44SJohn Forte #include "isns_obj.h"
39*fcf3ce44SJohn Forte #include "isns_pdu.h"
40*fcf3ce44SJohn Forte #include "isns_func.h"
41*fcf3ce44SJohn Forte #include "isns_qry.h"
42*fcf3ce44SJohn Forte #include "isns_msgq.h"
43*fcf3ce44SJohn Forte #include "isns_log.h"
44*fcf3ce44SJohn Forte #include "isns_sched.h"
45*fcf3ce44SJohn Forte #include "isns_scn.h"
46*fcf3ce44SJohn Forte #include "isns_esi.h"
47*fcf3ce44SJohn Forte 
48*fcf3ce44SJohn Forte /*
49*fcf3ce44SJohn Forte  * global variables.
50*fcf3ce44SJohn Forte  */
51*fcf3ce44SJohn Forte 
52*fcf3ce44SJohn Forte /*
53*fcf3ce44SJohn Forte  * local variables.
54*fcf3ce44SJohn Forte  */
55*fcf3ce44SJohn Forte static ev_t *ev_list = NULL;
56*fcf3ce44SJohn Forte 
57*fcf3ce44SJohn Forte static uint32_t stopwatch = 0;
58*fcf3ce44SJohn Forte static pthread_mutex_t stw_mtx = PTHREAD_MUTEX_INITIALIZER;
59*fcf3ce44SJohn Forte 
60*fcf3ce44SJohn Forte static int wakeup = 0;
61*fcf3ce44SJohn Forte static pthread_mutex_t idl_mtx = PTHREAD_MUTEX_INITIALIZER;
62*fcf3ce44SJohn Forte static pthread_cond_t idl_cond = PTHREAD_COND_INITIALIZER;
63*fcf3ce44SJohn Forte 
64*fcf3ce44SJohn Forte /*
65*fcf3ce44SJohn Forte  * external variables.
66*fcf3ce44SJohn Forte  */
67*fcf3ce44SJohn Forte extern const int UID_ATTR_INDEX[MAX_OBJ_TYPE_FOR_SIZE];
68*fcf3ce44SJohn Forte 
69*fcf3ce44SJohn Forte extern boolean_t time_to_exit;
70*fcf3ce44SJohn Forte 
71*fcf3ce44SJohn Forte extern msg_queue_t *sys_q;
72*fcf3ce44SJohn Forte 
73*fcf3ce44SJohn Forte extern uint64_t esi_threshold;
74*fcf3ce44SJohn Forte 
75*fcf3ce44SJohn Forte #ifdef DEBUG
76*fcf3ce44SJohn Forte extern void dump_pdu1(isns_pdu_t *);
77*fcf3ce44SJohn Forte #endif
78*fcf3ce44SJohn Forte 
79*fcf3ce44SJohn Forte /*
80*fcf3ce44SJohn Forte  * local functions.
81*fcf3ce44SJohn Forte  */
82*fcf3ce44SJohn Forte static void *esi_monitor(void *);
83*fcf3ce44SJohn Forte 
84*fcf3ce44SJohn Forte /*
85*fcf3ce44SJohn Forte  * ****************************************************************************
86*fcf3ce44SJohn Forte  *
87*fcf3ce44SJohn Forte  * new_esi_portal:
88*fcf3ce44SJohn Forte  *	Make a new portal for ESI event.
89*fcf3ce44SJohn Forte  *
90*fcf3ce44SJohn Forte  * uid	- the portal object UID.
91*fcf3ce44SJohn Forte  * ip6	- the portal IPv6 format IP address.
92*fcf3ce44SJohn Forte  * port	- the portal port.
93*fcf3ce44SJohn Forte  * esip	- the ESI port.
94*fcf3ce44SJohn Forte  * return - the new ESI portal.
95*fcf3ce44SJohn Forte  *
96*fcf3ce44SJohn Forte  * ****************************************************************************
97*fcf3ce44SJohn Forte  */
98*fcf3ce44SJohn Forte static esi_portal_t *
99*fcf3ce44SJohn Forte new_esi_portal(
100*fcf3ce44SJohn Forte 	uint32_t uid,
101*fcf3ce44SJohn Forte 	in6_addr_t *ip6,
102*fcf3ce44SJohn Forte 	uint32_t port,
103*fcf3ce44SJohn Forte 	uint32_t esip
104*fcf3ce44SJohn Forte )
105*fcf3ce44SJohn Forte {
106*fcf3ce44SJohn Forte 	esi_portal_t *p;
107*fcf3ce44SJohn Forte 
108*fcf3ce44SJohn Forte 	p = (esi_portal_t *)malloc(sizeof (esi_portal_t));
109*fcf3ce44SJohn Forte 	if (p != NULL) {
110*fcf3ce44SJohn Forte 		if (((int *)ip6)[0] == 0x00 &&
111*fcf3ce44SJohn Forte 		    ((int *)ip6)[1] == 0x00 &&
112*fcf3ce44SJohn Forte 		    ((uchar_t *)ip6)[8] == 0x00 &&
113*fcf3ce44SJohn Forte 		    ((uchar_t *)ip6)[9] == 0x00 &&
114*fcf3ce44SJohn Forte 		    ((uchar_t *)ip6)[10] == 0xFF &&
115*fcf3ce44SJohn Forte 		    ((uchar_t *)ip6)[11] == 0xFF) {
116*fcf3ce44SJohn Forte 			p->sz = sizeof (in_addr_t);
117*fcf3ce44SJohn Forte 			p->ip4 = ((uint32_t *)ip6)[3];
118*fcf3ce44SJohn Forte 		} else {
119*fcf3ce44SJohn Forte 			p->sz = sizeof (in6_addr_t);
120*fcf3ce44SJohn Forte 		}
121*fcf3ce44SJohn Forte 		p->ip6 = ip6;
122*fcf3ce44SJohn Forte 		p->port = port;
123*fcf3ce44SJohn Forte 		p->esip = esip;
124*fcf3ce44SJohn Forte 		p->ref = uid;
125*fcf3ce44SJohn Forte 		p->so = 0;
126*fcf3ce44SJohn Forte 		p->next = NULL;
127*fcf3ce44SJohn Forte 	}
128*fcf3ce44SJohn Forte 
129*fcf3ce44SJohn Forte 	return (p);
130*fcf3ce44SJohn Forte }
131*fcf3ce44SJohn Forte 
132*fcf3ce44SJohn Forte /*
133*fcf3ce44SJohn Forte  * ****************************************************************************
134*fcf3ce44SJohn Forte  *
135*fcf3ce44SJohn Forte  * free_esi_portal:
136*fcf3ce44SJohn Forte  *	Free a list of portal of one ESI event.
137*fcf3ce44SJohn Forte  *
138*fcf3ce44SJohn Forte  * p	- the ESI portal.
139*fcf3ce44SJohn Forte  *
140*fcf3ce44SJohn Forte  * ****************************************************************************
141*fcf3ce44SJohn Forte  */
142*fcf3ce44SJohn Forte static void
143*fcf3ce44SJohn Forte free_esi_portal(
144*fcf3ce44SJohn Forte 	esi_portal_t *p
145*fcf3ce44SJohn Forte )
146*fcf3ce44SJohn Forte {
147*fcf3ce44SJohn Forte 	esi_portal_t *n;
148*fcf3ce44SJohn Forte 
149*fcf3ce44SJohn Forte 	while (p != NULL) {
150*fcf3ce44SJohn Forte 		n = p->next;
151*fcf3ce44SJohn Forte 		free(p->ip6);
152*fcf3ce44SJohn Forte 		free(p);
153*fcf3ce44SJohn Forte 		p = n;
154*fcf3ce44SJohn Forte 	}
155*fcf3ce44SJohn Forte }
156*fcf3ce44SJohn Forte 
157*fcf3ce44SJohn Forte /*
158*fcf3ce44SJohn Forte  * ****************************************************************************
159*fcf3ce44SJohn Forte  *
160*fcf3ce44SJohn Forte  * ev_new:
161*fcf3ce44SJohn Forte  *	Make a new ESI event.
162*fcf3ce44SJohn Forte  *
163*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
164*fcf3ce44SJohn Forte  * eid	- the Entity object name.
165*fcf3ce44SJohn Forte  * len	- the length of the name.
166*fcf3ce44SJohn Forte  * return - the ESI event.
167*fcf3ce44SJohn Forte  *
168*fcf3ce44SJohn Forte  * ****************************************************************************
169*fcf3ce44SJohn Forte  */
170*fcf3ce44SJohn Forte static ev_t *
171*fcf3ce44SJohn Forte ev_new(
172*fcf3ce44SJohn Forte 	uint32_t uid,
173*fcf3ce44SJohn Forte 	uchar_t *eid,
174*fcf3ce44SJohn Forte 	uint32_t len
175*fcf3ce44SJohn Forte )
176*fcf3ce44SJohn Forte {
177*fcf3ce44SJohn Forte 	ev_t *ev;
178*fcf3ce44SJohn Forte 
179*fcf3ce44SJohn Forte 	ev = (ev_t *)malloc(sizeof (ev_t));
180*fcf3ce44SJohn Forte 	if (ev != NULL) {
181*fcf3ce44SJohn Forte 		if (pthread_mutex_init(&ev->mtx, NULL) != 0 ||
182*fcf3ce44SJohn Forte 		    (ev->eid = (uchar_t *)malloc(len)) == NULL) {
183*fcf3ce44SJohn Forte 			free(ev);
184*fcf3ce44SJohn Forte 			return (NULL);
185*fcf3ce44SJohn Forte 		}
186*fcf3ce44SJohn Forte 		ev->uid = uid;
187*fcf3ce44SJohn Forte 		(void) strcpy((char *)ev->eid, (char *)eid);
188*fcf3ce44SJohn Forte 		ev->eid_len = len;
189*fcf3ce44SJohn Forte 		/* initialization time */
190*fcf3ce44SJohn Forte 		ev->flags = EV_FLAG_INIT;
191*fcf3ce44SJohn Forte 	}
192*fcf3ce44SJohn Forte 
193*fcf3ce44SJohn Forte 	return (ev);
194*fcf3ce44SJohn Forte }
195*fcf3ce44SJohn Forte 
196*fcf3ce44SJohn Forte /*
197*fcf3ce44SJohn Forte  * ****************************************************************************
198*fcf3ce44SJohn Forte  *
199*fcf3ce44SJohn Forte  * cb_portal_uids:
200*fcf3ce44SJohn Forte  *	Callback function which makes a copy of the portal child object
201*fcf3ce44SJohn Forte  *	UIDs from a Network Entity object.
202*fcf3ce44SJohn Forte  *
203*fcf3ce44SJohn Forte  * p1	- the Network Entity object.
204*fcf3ce44SJohn Forte  * p2	- the lookup control data.
205*fcf3ce44SJohn Forte  * return - the number of portal object UIDs.
206*fcf3ce44SJohn Forte  *
207*fcf3ce44SJohn Forte  * ****************************************************************************
208*fcf3ce44SJohn Forte  */
209*fcf3ce44SJohn Forte static int
210*fcf3ce44SJohn Forte cb_portal_uids(
211*fcf3ce44SJohn Forte 	void *p1,
212*fcf3ce44SJohn Forte 	void *p2
213*fcf3ce44SJohn Forte )
214*fcf3ce44SJohn Forte {
215*fcf3ce44SJohn Forte 	isns_obj_t *obj = (isns_obj_t *)p1;
216*fcf3ce44SJohn Forte 	lookup_ctrl_t *lcp = (lookup_ctrl_t *)p2;
217*fcf3ce44SJohn Forte 
218*fcf3ce44SJohn Forte 	isns_attr_t *attr;
219*fcf3ce44SJohn Forte 
220*fcf3ce44SJohn Forte 	uint32_t *cuidp;
221*fcf3ce44SJohn Forte 
222*fcf3ce44SJohn Forte 	uint32_t num = 0;
223*fcf3ce44SJohn Forte 	uint32_t *p = NULL;
224*fcf3ce44SJohn Forte 
225*fcf3ce44SJohn Forte 	cuidp = get_child_t(obj, OBJ_PORTAL);
226*fcf3ce44SJohn Forte 	if (cuidp != NULL) {
227*fcf3ce44SJohn Forte 		p = (uint32_t *)malloc(*cuidp * sizeof (*p));
228*fcf3ce44SJohn Forte 		if (p != NULL) {
229*fcf3ce44SJohn Forte 			num = *cuidp ++;
230*fcf3ce44SJohn Forte 			(void) memcpy(p, cuidp, num * sizeof (*p));
231*fcf3ce44SJohn Forte 			lcp->data[1].ptr = (uchar_t *)p;
232*fcf3ce44SJohn Forte 		}
233*fcf3ce44SJohn Forte 	}
234*fcf3ce44SJohn Forte 
235*fcf3ce44SJohn Forte 	attr = &obj->attrs[ATTR_INDEX_ENTITY(ISNS_ENTITY_REG_PERIOD_ATTR_ID)];
236*fcf3ce44SJohn Forte 	if (attr->tag != 0 && attr->value.ui != 0) {
237*fcf3ce44SJohn Forte 		lcp->data[2].ui = attr->value.ui;
238*fcf3ce44SJohn Forte 	} else {
239*fcf3ce44SJohn Forte 		/* just one second before the end of the world */
240*fcf3ce44SJohn Forte 		lcp->data[2].ui = INFINITY - 1;
241*fcf3ce44SJohn Forte 	}
242*fcf3ce44SJohn Forte 
243*fcf3ce44SJohn Forte 	return (num);
244*fcf3ce44SJohn Forte }
245*fcf3ce44SJohn Forte 
246*fcf3ce44SJohn Forte /*
247*fcf3ce44SJohn Forte  * ****************************************************************************
248*fcf3ce44SJohn Forte  *
249*fcf3ce44SJohn Forte  * cb_esi_portal:
250*fcf3ce44SJohn Forte  *	Callback function which gets ESI port number and ESI interval
251*fcf3ce44SJohn Forte  *	from a portal object.
252*fcf3ce44SJohn Forte  *
253*fcf3ce44SJohn Forte  * p1	- the Portal object.
254*fcf3ce44SJohn Forte  * p2	- the lookup control data.
255*fcf3ce44SJohn Forte  * return - the ESI interval.
256*fcf3ce44SJohn Forte  *
257*fcf3ce44SJohn Forte  * ****************************************************************************
258*fcf3ce44SJohn Forte  */
259*fcf3ce44SJohn Forte static int
260*fcf3ce44SJohn Forte cb_esi_portal(
261*fcf3ce44SJohn Forte 	void *p1,
262*fcf3ce44SJohn Forte 	void *p2
263*fcf3ce44SJohn Forte )
264*fcf3ce44SJohn Forte {
265*fcf3ce44SJohn Forte 	uint32_t intval = 0;
266*fcf3ce44SJohn Forte 
267*fcf3ce44SJohn Forte 	isns_obj_t *obj;
268*fcf3ce44SJohn Forte 	lookup_ctrl_t *lcp;
269*fcf3ce44SJohn Forte 
270*fcf3ce44SJohn Forte 	in6_addr_t *ip;
271*fcf3ce44SJohn Forte 	uint32_t esip;
272*fcf3ce44SJohn Forte 
273*fcf3ce44SJohn Forte 	isns_attr_t *attr;
274*fcf3ce44SJohn Forte 
275*fcf3ce44SJohn Forte 	if (cb_clone_attrs(p1, p2) == 0) {
276*fcf3ce44SJohn Forte 		obj = (isns_obj_t *)p1;
277*fcf3ce44SJohn Forte 		lcp = (lookup_ctrl_t *)p2;
278*fcf3ce44SJohn Forte 		ip = lcp->data[1].ip;
279*fcf3ce44SJohn Forte 		esip = lcp->data[2].ui;
280*fcf3ce44SJohn Forte 		if (esip != 0) {
281*fcf3ce44SJohn Forte 			attr = &obj->attrs[ATTR_INDEX_PORTAL(
282*fcf3ce44SJohn Forte 			    ISNS_PORTAL_PORT_ATTR_ID)];
283*fcf3ce44SJohn Forte 			lcp->data[0].ui = attr->value.ui;
284*fcf3ce44SJohn Forte 			attr = &obj->attrs[ATTR_INDEX_PORTAL(
285*fcf3ce44SJohn Forte 			    ISNS_ESI_INTERVAL_ATTR_ID)];
286*fcf3ce44SJohn Forte 			if (attr->tag != 0 && attr->value.ui != 0) {
287*fcf3ce44SJohn Forte 				intval = attr->value.ui;
288*fcf3ce44SJohn Forte 			} else {
289*fcf3ce44SJohn Forte 				intval = DEFAULT_ESI_INTVAL;
290*fcf3ce44SJohn Forte 			}
291*fcf3ce44SJohn Forte 		} else {
292*fcf3ce44SJohn Forte 			free(ip);
293*fcf3ce44SJohn Forte 		}
294*fcf3ce44SJohn Forte 	}
295*fcf3ce44SJohn Forte 
296*fcf3ce44SJohn Forte 	return ((int)intval);
297*fcf3ce44SJohn Forte }
298*fcf3ce44SJohn Forte 
299*fcf3ce44SJohn Forte /*
300*fcf3ce44SJohn Forte  * ****************************************************************************
301*fcf3ce44SJohn Forte  *
302*fcf3ce44SJohn Forte  * extract_esi_portal:
303*fcf3ce44SJohn Forte  *	Extract a list of portal which have an ESI port for an Entity.
304*fcf3ce44SJohn Forte  *
305*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
306*fcf3ce44SJohn Forte  * intval - the ESI interval for returnning.
307*fcf3ce44SJohn Forte  * return - the list of portals.
308*fcf3ce44SJohn Forte  *
309*fcf3ce44SJohn Forte  * ****************************************************************************
310*fcf3ce44SJohn Forte  */
311*fcf3ce44SJohn Forte static esi_portal_t *
312*fcf3ce44SJohn Forte extract_esi_portal(
313*fcf3ce44SJohn Forte 	uint32_t uid,
314*fcf3ce44SJohn Forte 	uint32_t *intval
315*fcf3ce44SJohn Forte )
316*fcf3ce44SJohn Forte {
317*fcf3ce44SJohn Forte 	esi_portal_t *list = NULL;
318*fcf3ce44SJohn Forte 	esi_portal_t *p;
319*fcf3ce44SJohn Forte 
320*fcf3ce44SJohn Forte 	lookup_ctrl_t lc;
321*fcf3ce44SJohn Forte 
322*fcf3ce44SJohn Forte 	uint32_t num_of_portal;
323*fcf3ce44SJohn Forte 	uint32_t *portal_uids;
324*fcf3ce44SJohn Forte 
325*fcf3ce44SJohn Forte 	uint32_t intv;
326*fcf3ce44SJohn Forte 
327*fcf3ce44SJohn Forte 	/* prepare for looking up entity object */
328*fcf3ce44SJohn Forte 	SET_UID_LCP(&lc, OBJ_ENTITY, uid);
329*fcf3ce44SJohn Forte 	lc.data[1].ptr = NULL;
330*fcf3ce44SJohn Forte 	lc.data[2].ui = INFINITY - 1;
331*fcf3ce44SJohn Forte 
332*fcf3ce44SJohn Forte 	/* get the array of the portal uid(s) */
333*fcf3ce44SJohn Forte 	num_of_portal = (uint32_t)cache_lookup(&lc, NULL, cb_portal_uids);
334*fcf3ce44SJohn Forte 	portal_uids = (uint32_t *)lc.data[1].ptr;
335*fcf3ce44SJohn Forte 	*intval = lc.data[2].ui;
336*fcf3ce44SJohn Forte 
337*fcf3ce44SJohn Forte 	/* prepare for looking up portal object(s) */
338*fcf3ce44SJohn Forte 	SET_UID_LCP(&lc, OBJ_PORTAL, 0);
339*fcf3ce44SJohn Forte 	lc.id[1] = ISNS_PORTAL_IP_ADDR_ATTR_ID;
340*fcf3ce44SJohn Forte 	lc.id[2] = ISNS_ESI_PORT_ATTR_ID;
341*fcf3ce44SJohn Forte 	FOR_EACH_OBJS(portal_uids, num_of_portal, uid, {
342*fcf3ce44SJohn Forte 		if (uid != 0) {
343*fcf3ce44SJohn Forte 			lc.data[0].ui = uid;
344*fcf3ce44SJohn Forte 			intv = cache_lookup(&lc, NULL, cb_esi_portal);
345*fcf3ce44SJohn Forte 			if (intv != 0) {
346*fcf3ce44SJohn Forte 				p = new_esi_portal(uid,
347*fcf3ce44SJohn Forte 				    (in6_addr_t *)lc.data[1].ip,
348*fcf3ce44SJohn Forte 				    lc.data[0].ui, lc.data[2].ui);
349*fcf3ce44SJohn Forte 				if (p != NULL) {
350*fcf3ce44SJohn Forte 					p->next = list;
351*fcf3ce44SJohn Forte 					list = p;
352*fcf3ce44SJohn Forte 					if (*intval > intv) {
353*fcf3ce44SJohn Forte 						*intval = intv;
354*fcf3ce44SJohn Forte 					}
355*fcf3ce44SJohn Forte 				}
356*fcf3ce44SJohn Forte 			}
357*fcf3ce44SJohn Forte 		}
358*fcf3ce44SJohn Forte 	});
359*fcf3ce44SJohn Forte 
360*fcf3ce44SJohn Forte 	/* free up the portal uid array */
361*fcf3ce44SJohn Forte 	free(portal_uids);
362*fcf3ce44SJohn Forte 
363*fcf3ce44SJohn Forte 	return (list);
364*fcf3ce44SJohn Forte }
365*fcf3ce44SJohn Forte 
366*fcf3ce44SJohn Forte /*
367*fcf3ce44SJohn Forte  * ****************************************************************************
368*fcf3ce44SJohn Forte  *
369*fcf3ce44SJohn Forte  * ev_add:
370*fcf3ce44SJohn Forte  *	Add an ESI event.
371*fcf3ce44SJohn Forte  *
372*fcf3ce44SJohn Forte  * ev	- the ESI event.
373*fcf3ce44SJohn Forte  * init	- 0: initialization time, otherwise not.
374*fcf3ce44SJohn Forte  * return - error code.
375*fcf3ce44SJohn Forte  *
376*fcf3ce44SJohn Forte  * ****************************************************************************
377*fcf3ce44SJohn Forte  */
378*fcf3ce44SJohn Forte static int
379*fcf3ce44SJohn Forte ev_add(
380*fcf3ce44SJohn Forte 	ev_t *ev,
381*fcf3ce44SJohn Forte 	int init
382*fcf3ce44SJohn Forte )
383*fcf3ce44SJohn Forte {
384*fcf3ce44SJohn Forte 	uint32_t intval;
385*fcf3ce44SJohn Forte 	esi_portal_t *p;
386*fcf3ce44SJohn Forte 
387*fcf3ce44SJohn Forte 	double rnd;
388*fcf3ce44SJohn Forte 	uint32_t t = 0;
389*fcf3ce44SJohn Forte 
390*fcf3ce44SJohn Forte 	/* get the portal(s) which are registered for ESI monitoring */
391*fcf3ce44SJohn Forte 	/* and the second interval for ESI or registration expiration */
392*fcf3ce44SJohn Forte 	p = extract_esi_portal(ev->uid, &intval);
393*fcf3ce44SJohn Forte 	ev->intval = intval;
394*fcf3ce44SJohn Forte 	if (p != NULL) {
395*fcf3ce44SJohn Forte 		ev->type = EV_ESI;
396*fcf3ce44SJohn Forte 		ev->portal = p;
397*fcf3ce44SJohn Forte 		/* avoid running everything at the same time */
398*fcf3ce44SJohn Forte 		if (init != 0) {
399*fcf3ce44SJohn Forte 			/* generate random number within range (0, 1] */
400*fcf3ce44SJohn Forte 			rnd = (rand() + 1) / (double)(RAND_MAX + 1);
401*fcf3ce44SJohn Forte 			t = (uint32_t)(intval * rnd);
402*fcf3ce44SJohn Forte 		}
403*fcf3ce44SJohn Forte 	} else {
404*fcf3ce44SJohn Forte 		/* no portal is registered for ESI monitoring, make */
405*fcf3ce44SJohn Forte 		/* an entry for entity registration expiration */
406*fcf3ce44SJohn Forte 		ev->type = EV_REG_EXP;
407*fcf3ce44SJohn Forte 		ev->portal = NULL;
408*fcf3ce44SJohn Forte 		if (init != 0) {
409*fcf3ce44SJohn Forte 			t = intval;
410*fcf3ce44SJohn Forte 		}
411*fcf3ce44SJohn Forte 	}
412*fcf3ce44SJohn Forte 
413*fcf3ce44SJohn Forte 	/* schedule the event */
414*fcf3ce44SJohn Forte 	return (el_add(ev, t, NULL));
415*fcf3ce44SJohn Forte }
416*fcf3ce44SJohn Forte 
417*fcf3ce44SJohn Forte /*
418*fcf3ce44SJohn Forte  * global functions.
419*fcf3ce44SJohn Forte  */
420*fcf3ce44SJohn Forte 
421*fcf3ce44SJohn Forte /*
422*fcf3ce44SJohn Forte  * ****************************************************************************
423*fcf3ce44SJohn Forte  *
424*fcf3ce44SJohn Forte  * sigalrm:
425*fcf3ce44SJohn Forte  *	The signal handler for SIGALRM, the ESI proc uses the SIGALRM
426*fcf3ce44SJohn Forte  *	for waking up to perform the client status inquery.
427*fcf3ce44SJohn Forte  *
428*fcf3ce44SJohn Forte  * sig	- the signal.
429*fcf3ce44SJohn Forte  *
430*fcf3ce44SJohn Forte  * ****************************************************************************
431*fcf3ce44SJohn Forte  */
432*fcf3ce44SJohn Forte /*ARGSUSED*/
433*fcf3ce44SJohn Forte void
434*fcf3ce44SJohn Forte sigalrm(
435*fcf3ce44SJohn Forte 	int sig
436*fcf3ce44SJohn Forte )
437*fcf3ce44SJohn Forte {
438*fcf3ce44SJohn Forte 	/* wake up the idle */
439*fcf3ce44SJohn Forte 	(void) pthread_mutex_lock(&idl_mtx);
440*fcf3ce44SJohn Forte 	wakeup = 1; /* wake up naturally */
441*fcf3ce44SJohn Forte 	(void) pthread_cond_signal(&idl_cond);
442*fcf3ce44SJohn Forte 	(void) pthread_mutex_unlock(&idl_mtx);
443*fcf3ce44SJohn Forte }
444*fcf3ce44SJohn Forte 
445*fcf3ce44SJohn Forte /*
446*fcf3ce44SJohn Forte  * ****************************************************************************
447*fcf3ce44SJohn Forte  *
448*fcf3ce44SJohn Forte  * esi_load:
449*fcf3ce44SJohn Forte  *	Load an ESI event from data store.
450*fcf3ce44SJohn Forte  *
451*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
452*fcf3ce44SJohn Forte  * eid	- the Entity object name.
453*fcf3ce44SJohn Forte  * len	- the length of the name.
454*fcf3ce44SJohn Forte  * return - error code.
455*fcf3ce44SJohn Forte  *
456*fcf3ce44SJohn Forte  * ****************************************************************************
457*fcf3ce44SJohn Forte  */
458*fcf3ce44SJohn Forte int
459*fcf3ce44SJohn Forte esi_load(
460*fcf3ce44SJohn Forte 	uint32_t uid,
461*fcf3ce44SJohn Forte 	uchar_t *eid,
462*fcf3ce44SJohn Forte 	uint32_t len
463*fcf3ce44SJohn Forte )
464*fcf3ce44SJohn Forte {
465*fcf3ce44SJohn Forte 	int ec = 0;
466*fcf3ce44SJohn Forte 
467*fcf3ce44SJohn Forte 	/* make a new event */
468*fcf3ce44SJohn Forte 	ev_t *ev = ev_new(uid, eid, len);
469*fcf3ce44SJohn Forte 
470*fcf3ce44SJohn Forte 	/* put the new event to the list */
471*fcf3ce44SJohn Forte 	if (ev != NULL) {
472*fcf3ce44SJohn Forte 		ev->next = ev_list;
473*fcf3ce44SJohn Forte 		ev_list = ev;
474*fcf3ce44SJohn Forte 	} else {
475*fcf3ce44SJohn Forte 		ec = ISNS_RSP_INTERNAL_ERROR;
476*fcf3ce44SJohn Forte 	}
477*fcf3ce44SJohn Forte 
478*fcf3ce44SJohn Forte 	return (ec);
479*fcf3ce44SJohn Forte }
480*fcf3ce44SJohn Forte 
481*fcf3ce44SJohn Forte /*
482*fcf3ce44SJohn Forte  * ****************************************************************************
483*fcf3ce44SJohn Forte  *
484*fcf3ce44SJohn Forte  * verify_esi_portal:
485*fcf3ce44SJohn Forte  *	Verify ESI port and add the ESI entries after the ESI are loaded.
486*fcf3ce44SJohn Forte  *
487*fcf3ce44SJohn Forte  * return - error code.
488*fcf3ce44SJohn Forte  *
489*fcf3ce44SJohn Forte  * ****************************************************************************
490*fcf3ce44SJohn Forte  */
491*fcf3ce44SJohn Forte int
492*fcf3ce44SJohn Forte verify_esi_portal(
493*fcf3ce44SJohn Forte )
494*fcf3ce44SJohn Forte {
495*fcf3ce44SJohn Forte 	int ec = 0;
496*fcf3ce44SJohn Forte 
497*fcf3ce44SJohn Forte 	ev_t *ev;
498*fcf3ce44SJohn Forte 
499*fcf3ce44SJohn Forte 	/* add each event from the list */
500*fcf3ce44SJohn Forte 	while (ev_list != NULL && ec == 0) {
501*fcf3ce44SJohn Forte 		ev = ev_list;
502*fcf3ce44SJohn Forte 		ev_list = ev->next;
503*fcf3ce44SJohn Forte 		ev->next = NULL;
504*fcf3ce44SJohn Forte 		ec = ev_add(ev, 1);
505*fcf3ce44SJohn Forte 	}
506*fcf3ce44SJohn Forte 
507*fcf3ce44SJohn Forte 	return (ec);
508*fcf3ce44SJohn Forte }
509*fcf3ce44SJohn Forte 
510*fcf3ce44SJohn Forte /*
511*fcf3ce44SJohn Forte  * ****************************************************************************
512*fcf3ce44SJohn Forte  *
513*fcf3ce44SJohn Forte  * esi_add:
514*fcf3ce44SJohn Forte  *	Add a new ESI event when a new Entity is registered.
515*fcf3ce44SJohn Forte  *
516*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
517*fcf3ce44SJohn Forte  * eid	- the Entity object name.
518*fcf3ce44SJohn Forte  * len	- the length of the name.
519*fcf3ce44SJohn Forte  * return - error code.
520*fcf3ce44SJohn Forte  *
521*fcf3ce44SJohn Forte  * ****************************************************************************
522*fcf3ce44SJohn Forte  */
523*fcf3ce44SJohn Forte int
524*fcf3ce44SJohn Forte esi_add(
525*fcf3ce44SJohn Forte 	uint32_t uid,
526*fcf3ce44SJohn Forte 	uchar_t *eid,
527*fcf3ce44SJohn Forte 	uint32_t len
528*fcf3ce44SJohn Forte )
529*fcf3ce44SJohn Forte {
530*fcf3ce44SJohn Forte 	int ec = 0;
531*fcf3ce44SJohn Forte 
532*fcf3ce44SJohn Forte 	/* make a new event */
533*fcf3ce44SJohn Forte 	ev_t *ev = ev_new(uid, eid, len);
534*fcf3ce44SJohn Forte 
535*fcf3ce44SJohn Forte 	if (ev != NULL) {
536*fcf3ce44SJohn Forte 		/* interrupt idle */
537*fcf3ce44SJohn Forte 		ev->flags |= EV_FLAG_WAKEUP;
538*fcf3ce44SJohn Forte 		ec = ev_add(ev, 0);
539*fcf3ce44SJohn Forte 	} else {
540*fcf3ce44SJohn Forte 		ec = ISNS_RSP_INTERNAL_ERROR;
541*fcf3ce44SJohn Forte 	}
542*fcf3ce44SJohn Forte 
543*fcf3ce44SJohn Forte 	return (ec);
544*fcf3ce44SJohn Forte }
545*fcf3ce44SJohn Forte 
546*fcf3ce44SJohn Forte /*
547*fcf3ce44SJohn Forte  * ****************************************************************************
548*fcf3ce44SJohn Forte  *
549*fcf3ce44SJohn Forte  * esi_remove:
550*fcf3ce44SJohn Forte  *	Remove an ESI event immediately.
551*fcf3ce44SJohn Forte  *
552*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
553*fcf3ce44SJohn Forte  * return - always successful.
554*fcf3ce44SJohn Forte  *
555*fcf3ce44SJohn Forte  * ****************************************************************************
556*fcf3ce44SJohn Forte  */
557*fcf3ce44SJohn Forte int
558*fcf3ce44SJohn Forte esi_remove(
559*fcf3ce44SJohn Forte 	uint32_t uid
560*fcf3ce44SJohn Forte )
561*fcf3ce44SJohn Forte {
562*fcf3ce44SJohn Forte 	(void) el_remove(uid, 0, 0);
563*fcf3ce44SJohn Forte 
564*fcf3ce44SJohn Forte 	return (0);
565*fcf3ce44SJohn Forte }
566*fcf3ce44SJohn Forte 
567*fcf3ce44SJohn Forte /*
568*fcf3ce44SJohn Forte  * ****************************************************************************
569*fcf3ce44SJohn Forte  *
570*fcf3ce44SJohn Forte  * esi_remove_obj:
571*fcf3ce44SJohn Forte  *	Update an ESI event when a Entity object or a Portal object is
572*fcf3ce44SJohn Forte  *	removed from server. If the object is being removed because of
573*fcf3ce44SJohn Forte  *	ESI failure, the ESI event will be removed with a pending time,
574*fcf3ce44SJohn Forte  *	otherwise, the ESI will be removed immediately.
575*fcf3ce44SJohn Forte  *
576*fcf3ce44SJohn Forte  * obj	- the object being removed.
577*fcf3ce44SJohn Forte  * pending - the pending flag.
578*fcf3ce44SJohn Forte  * return - always successful.
579*fcf3ce44SJohn Forte  *
580*fcf3ce44SJohn Forte  * ****************************************************************************
581*fcf3ce44SJohn Forte  */
582*fcf3ce44SJohn Forte int
583*fcf3ce44SJohn Forte esi_remove_obj(
584*fcf3ce44SJohn Forte 	const isns_obj_t *obj,
585*fcf3ce44SJohn Forte 	int pending
586*fcf3ce44SJohn Forte )
587*fcf3ce44SJohn Forte {
588*fcf3ce44SJohn Forte 	uint32_t puid, uid;
589*fcf3ce44SJohn Forte 
590*fcf3ce44SJohn Forte 	switch (obj->type) {
591*fcf3ce44SJohn Forte 	case OBJ_PORTAL:
592*fcf3ce44SJohn Forte 		puid = get_parent_uid(obj);
593*fcf3ce44SJohn Forte 		uid = get_obj_uid(obj);
594*fcf3ce44SJohn Forte 		break;
595*fcf3ce44SJohn Forte 	case OBJ_ENTITY:
596*fcf3ce44SJohn Forte 		puid = get_obj_uid(obj);
597*fcf3ce44SJohn Forte 		uid = 0;
598*fcf3ce44SJohn Forte 		break;
599*fcf3ce44SJohn Forte 	default:
600*fcf3ce44SJohn Forte 		puid = 0;
601*fcf3ce44SJohn Forte 		break;
602*fcf3ce44SJohn Forte 	}
603*fcf3ce44SJohn Forte 
604*fcf3ce44SJohn Forte 	if (puid != 0) {
605*fcf3ce44SJohn Forte 		(void) el_remove(puid, uid, pending);
606*fcf3ce44SJohn Forte 	}
607*fcf3ce44SJohn Forte 
608*fcf3ce44SJohn Forte 	return (0);
609*fcf3ce44SJohn Forte }
610*fcf3ce44SJohn Forte 
611*fcf3ce44SJohn Forte /*
612*fcf3ce44SJohn Forte  * ****************************************************************************
613*fcf3ce44SJohn Forte  *
614*fcf3ce44SJohn Forte  * get_stopwatch:
615*fcf3ce44SJohn Forte  *	Get the stopwatch. It might need to signal the condition to
616*fcf3ce44SJohn Forte  *	wake up the idle so the stopwatch gets updated.
617*fcf3ce44SJohn Forte  *
618*fcf3ce44SJohn Forte  * flag	- wake up flag.
619*fcf3ce44SJohn Forte  * return - the stopwatch.
620*fcf3ce44SJohn Forte  *
621*fcf3ce44SJohn Forte  * ****************************************************************************
622*fcf3ce44SJohn Forte  */
623*fcf3ce44SJohn Forte uint32_t
624*fcf3ce44SJohn Forte get_stopwatch(
625*fcf3ce44SJohn Forte 	int flag
626*fcf3ce44SJohn Forte )
627*fcf3ce44SJohn Forte {
628*fcf3ce44SJohn Forte 	uint32_t t;
629*fcf3ce44SJohn Forte 
630*fcf3ce44SJohn Forte 	/* not re-schedule, wake up idle */
631*fcf3ce44SJohn Forte 	(void) pthread_mutex_lock(&idl_mtx);
632*fcf3ce44SJohn Forte 	if (flag != 0) {
633*fcf3ce44SJohn Forte 		wakeup = 2; /* wake up manually */
634*fcf3ce44SJohn Forte 		(void) pthread_cond_signal(&idl_cond);
635*fcf3ce44SJohn Forte 	} else {
636*fcf3ce44SJohn Forte 		wakeup = 0; /* clear previous interruption */
637*fcf3ce44SJohn Forte 	}
638*fcf3ce44SJohn Forte 	(void) pthread_mutex_unlock(&idl_mtx);
639*fcf3ce44SJohn Forte 
640*fcf3ce44SJohn Forte 	/* get most current time */
641*fcf3ce44SJohn Forte 	(void) pthread_mutex_lock(&stw_mtx);
642*fcf3ce44SJohn Forte 	t = stopwatch;
643*fcf3ce44SJohn Forte 	(void) pthread_mutex_unlock(&stw_mtx);
644*fcf3ce44SJohn Forte 
645*fcf3ce44SJohn Forte 	return (t);
646*fcf3ce44SJohn Forte }
647*fcf3ce44SJohn Forte 
648*fcf3ce44SJohn Forte /*
649*fcf3ce44SJohn Forte  * ****************************************************************************
650*fcf3ce44SJohn Forte  *
651*fcf3ce44SJohn Forte  * ev_intval:
652*fcf3ce44SJohn Forte  *	Get the time interval of an ESI event.
653*fcf3ce44SJohn Forte  *
654*fcf3ce44SJohn Forte  * p	- the ESI event.
655*fcf3ce44SJohn Forte  * return - the time interval.
656*fcf3ce44SJohn Forte  *
657*fcf3ce44SJohn Forte  * ****************************************************************************
658*fcf3ce44SJohn Forte  */
659*fcf3ce44SJohn Forte uint32_t
660*fcf3ce44SJohn Forte ev_intval(
661*fcf3ce44SJohn Forte 	void *p
662*fcf3ce44SJohn Forte )
663*fcf3ce44SJohn Forte {
664*fcf3ce44SJohn Forte 	return (((ev_t *)p)->intval);
665*fcf3ce44SJohn Forte }
666*fcf3ce44SJohn Forte 
667*fcf3ce44SJohn Forte /*
668*fcf3ce44SJohn Forte  * ****************************************************************************
669*fcf3ce44SJohn Forte  *
670*fcf3ce44SJohn Forte  * ev_match:
671*fcf3ce44SJohn Forte  *	Check the ESI event maching an Entity object.
672*fcf3ce44SJohn Forte  *
673*fcf3ce44SJohn Forte  * p	- the ESI event.
674*fcf3ce44SJohn Forte  * uid	- the Entity object UID.
675*fcf3ce44SJohn Forte  * return - 1: match, otherwise not.
676*fcf3ce44SJohn Forte  *
677*fcf3ce44SJohn Forte  * ****************************************************************************
678*fcf3ce44SJohn Forte  */
679*fcf3ce44SJohn Forte int
680*fcf3ce44SJohn Forte ev_match(
681*fcf3ce44SJohn Forte 	void *p,
682*fcf3ce44SJohn Forte 	uint32_t uid
683*fcf3ce44SJohn Forte )
684*fcf3ce44SJohn Forte {
685*fcf3ce44SJohn Forte 	if (((ev_t *)p)->uid == uid) {
686*fcf3ce44SJohn Forte 		return (1);
687*fcf3ce44SJohn Forte 	} else {
688*fcf3ce44SJohn Forte 		return (0);
689*fcf3ce44SJohn Forte 	}
690*fcf3ce44SJohn Forte }
691*fcf3ce44SJohn Forte 
692*fcf3ce44SJohn Forte /*
693*fcf3ce44SJohn Forte  * ****************************************************************************
694*fcf3ce44SJohn Forte  *
695*fcf3ce44SJohn Forte  * ev_remove:
696*fcf3ce44SJohn Forte  *	Remove a portal or an ESI event. If all of ESI portal has been
697*fcf3ce44SJohn Forte  *	removed, the ESI event will be marked as removal pending, which
698*fcf3ce44SJohn Forte  *	will result in removing the Entity object after the pending time.
699*fcf3ce44SJohn Forte  *
700*fcf3ce44SJohn Forte  * p	- the ESI event.
701*fcf3ce44SJohn Forte  * portal_uid	- the Portal object UID.
702*fcf3ce44SJohn Forte  * flag	- 0: the ESI is currently in use, otherwise it is scheduled.
703*fcf3ce44SJohn Forte  * pending	- flag for the ESI removal pending.
704*fcf3ce44SJohn Forte  * return - 0: the ESI is physically removed, otherwise not.
705*fcf3ce44SJohn Forte  *
706*fcf3ce44SJohn Forte  * ****************************************************************************
707*fcf3ce44SJohn Forte  */
708*fcf3ce44SJohn Forte int
709*fcf3ce44SJohn Forte ev_remove(
710*fcf3ce44SJohn Forte 	void *p,
711*fcf3ce44SJohn Forte 	uint32_t portal_uid,
712*fcf3ce44SJohn Forte 	int flag,
713*fcf3ce44SJohn Forte 	int pending
714*fcf3ce44SJohn Forte )
715*fcf3ce44SJohn Forte {
716*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)p;
717*fcf3ce44SJohn Forte 	esi_portal_t **pp, *portal;
718*fcf3ce44SJohn Forte 
719*fcf3ce44SJohn Forte 	int has_portal = 0;
720*fcf3ce44SJohn Forte 	int state;
721*fcf3ce44SJohn Forte 
722*fcf3ce44SJohn Forte 	/* remove one portal only */
723*fcf3ce44SJohn Forte 	if (portal_uid != 0) {
724*fcf3ce44SJohn Forte 		pp = &ev->portal;
725*fcf3ce44SJohn Forte 		portal = *pp;
726*fcf3ce44SJohn Forte 		while (portal != NULL) {
727*fcf3ce44SJohn Forte 			/* found the match portal */
728*fcf3ce44SJohn Forte 			if (portal->ref == portal_uid) {
729*fcf3ce44SJohn Forte 				/* mark it as removed */
730*fcf3ce44SJohn Forte 				portal->ref = 0;
731*fcf3ce44SJohn Forte 				if (flag != 0) {
732*fcf3ce44SJohn Forte 					/* not in use, remove it physically */
733*fcf3ce44SJohn Forte 					*pp = portal->next;
734*fcf3ce44SJohn Forte 					portal->next = NULL;
735*fcf3ce44SJohn Forte 					free_esi_portal(portal);
736*fcf3ce44SJohn Forte 				} else {
737*fcf3ce44SJohn Forte 					pp = &portal->next;
738*fcf3ce44SJohn Forte 				}
739*fcf3ce44SJohn Forte 			} else {
740*fcf3ce44SJohn Forte 				/* one or more esi portals are available */
741*fcf3ce44SJohn Forte 				if (portal->ref != 0) {
742*fcf3ce44SJohn Forte 					has_portal = 1;
743*fcf3ce44SJohn Forte 				}
744*fcf3ce44SJohn Forte 				pp = &portal->next;
745*fcf3ce44SJohn Forte 			}
746*fcf3ce44SJohn Forte 			portal = *pp;
747*fcf3ce44SJohn Forte 		}
748*fcf3ce44SJohn Forte 	}
749*fcf3ce44SJohn Forte 
750*fcf3ce44SJohn Forte 	/* no portal available */
751*fcf3ce44SJohn Forte 	if (has_portal == 0) {
752*fcf3ce44SJohn Forte 		state = (pending << 1) | flag;
753*fcf3ce44SJohn Forte 		switch (state) {
754*fcf3ce44SJohn Forte 		case 0x0:
755*fcf3ce44SJohn Forte 			/* mark the event as removed */
756*fcf3ce44SJohn Forte 			ev->flags |= EV_FLAG_REMOVE;
757*fcf3ce44SJohn Forte 			isnslog(LOG_DEBUG, "ev_remove",
758*fcf3ce44SJohn Forte 			    "%s [%d] is marked as removed.",
759*fcf3ce44SJohn Forte 			    ev->type == EV_ESI ? "ESI" : "REG_EXP",
760*fcf3ce44SJohn Forte 			    ev->uid);
761*fcf3ce44SJohn Forte 			break;
762*fcf3ce44SJohn Forte 		case 0x1:
763*fcf3ce44SJohn Forte 			/* physically remove the event */
764*fcf3ce44SJohn Forte 			ev_free(ev);
765*fcf3ce44SJohn Forte 			break;
766*fcf3ce44SJohn Forte 		case 0x2:
767*fcf3ce44SJohn Forte 		case 0x3:
768*fcf3ce44SJohn Forte 			/* mark the event as removal pending */
769*fcf3ce44SJohn Forte 			isnslog(LOG_DEBUG, "ev_remove",
770*fcf3ce44SJohn Forte 			    "%s [%d] is marked as removal pending.",
771*fcf3ce44SJohn Forte 			    ev->type == EV_ESI ? "ESI" : "REG_EXP",
772*fcf3ce44SJohn Forte 			    ev->uid);
773*fcf3ce44SJohn Forte 			ev->flags |= EV_FLAG_REM_P1;
774*fcf3ce44SJohn Forte 			has_portal = 1;
775*fcf3ce44SJohn Forte 			break;
776*fcf3ce44SJohn Forte 		default:
777*fcf3ce44SJohn Forte 			break;
778*fcf3ce44SJohn Forte 		}
779*fcf3ce44SJohn Forte 	} else {
780*fcf3ce44SJohn Forte 		isnslog(LOG_DEBUG, "ev_remove", "%s [%d] removed portal %d.",
781*fcf3ce44SJohn Forte 		    ev->type == EV_ESI ? "ESI" : "REG_EXP",
782*fcf3ce44SJohn Forte 		    ev->uid, portal_uid);
783*fcf3ce44SJohn Forte 	}
784*fcf3ce44SJohn Forte 
785*fcf3ce44SJohn Forte 	return (has_portal);
786*fcf3ce44SJohn Forte }
787*fcf3ce44SJohn Forte 
788*fcf3ce44SJohn Forte /*
789*fcf3ce44SJohn Forte  * ****************************************************************************
790*fcf3ce44SJohn Forte  *
791*fcf3ce44SJohn Forte  * ev_free:
792*fcf3ce44SJohn Forte  *	Free an ESI event.
793*fcf3ce44SJohn Forte  *
794*fcf3ce44SJohn Forte  * p	- the ESI event.
795*fcf3ce44SJohn Forte  *
796*fcf3ce44SJohn Forte  * ****************************************************************************
797*fcf3ce44SJohn Forte  */
798*fcf3ce44SJohn Forte void
799*fcf3ce44SJohn Forte ev_free(
800*fcf3ce44SJohn Forte 	void *p
801*fcf3ce44SJohn Forte )
802*fcf3ce44SJohn Forte {
803*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)p;
804*fcf3ce44SJohn Forte 
805*fcf3ce44SJohn Forte 	/* free up all of portals */
806*fcf3ce44SJohn Forte 	free_esi_portal(ev->portal);
807*fcf3ce44SJohn Forte 
808*fcf3ce44SJohn Forte 	isnslog(LOG_DEBUG, "ev_free",
809*fcf3ce44SJohn Forte 	    "%s [%d] is physically removed.",
810*fcf3ce44SJohn Forte 	    ev->type == EV_ESI ? "ESI" : "REG_EXP",
811*fcf3ce44SJohn Forte 	    ev->uid);
812*fcf3ce44SJohn Forte 
813*fcf3ce44SJohn Forte 	free(ev->eid);
814*fcf3ce44SJohn Forte 
815*fcf3ce44SJohn Forte 	/* free the event */
816*fcf3ce44SJohn Forte 	free(ev);
817*fcf3ce44SJohn Forte }
818*fcf3ce44SJohn Forte 
819*fcf3ce44SJohn Forte /*
820*fcf3ce44SJohn Forte  * ****************************************************************************
821*fcf3ce44SJohn Forte  *
822*fcf3ce44SJohn Forte  * evf_init:
823*fcf3ce44SJohn Forte  *	Check the initial flag of an ESI event.
824*fcf3ce44SJohn Forte  *
825*fcf3ce44SJohn Forte  * p	- the ESI event.
826*fcf3ce44SJohn Forte  * return - 0: not initial, otherwise yes.
827*fcf3ce44SJohn Forte  *
828*fcf3ce44SJohn Forte  * ****************************************************************************
829*fcf3ce44SJohn Forte  */
830*fcf3ce44SJohn Forte int
831*fcf3ce44SJohn Forte evf_init(
832*fcf3ce44SJohn Forte 	void *p
833*fcf3ce44SJohn Forte )
834*fcf3ce44SJohn Forte {
835*fcf3ce44SJohn Forte 	return (((ev_t *)p)->flags & EV_FLAG_INIT);
836*fcf3ce44SJohn Forte }
837*fcf3ce44SJohn Forte 
838*fcf3ce44SJohn Forte /*
839*fcf3ce44SJohn Forte  * ****************************************************************************
840*fcf3ce44SJohn Forte  *
841*fcf3ce44SJohn Forte  * evf_again:
842*fcf3ce44SJohn Forte  *	Check the again flag of an ESI event.
843*fcf3ce44SJohn Forte  *	(this flag might be eliminated and use the init flag.)
844*fcf3ce44SJohn Forte  *
845*fcf3ce44SJohn Forte  * p	- the ESI event.
846*fcf3ce44SJohn Forte  * return - 0: not again, otherwise yes.
847*fcf3ce44SJohn Forte  *
848*fcf3ce44SJohn Forte  * ****************************************************************************
849*fcf3ce44SJohn Forte  */
850*fcf3ce44SJohn Forte int
851*fcf3ce44SJohn Forte evf_again(
852*fcf3ce44SJohn Forte 	void *p
853*fcf3ce44SJohn Forte )
854*fcf3ce44SJohn Forte {
855*fcf3ce44SJohn Forte 	return (((ev_t *)p)->flags & EV_FLAG_AGAIN);
856*fcf3ce44SJohn Forte }
857*fcf3ce44SJohn Forte 
858*fcf3ce44SJohn Forte /*
859*fcf3ce44SJohn Forte  * ****************************************************************************
860*fcf3ce44SJohn Forte  *
861*fcf3ce44SJohn Forte  * evf_wakeup:
862*fcf3ce44SJohn Forte  *	Check the wakeup flag of an ESI event. The idle might need to
863*fcf3ce44SJohn Forte  *	wake up before the event is scheduled.
864*fcf3ce44SJohn Forte  *
865*fcf3ce44SJohn Forte  * p	- the ESI event.
866*fcf3ce44SJohn Forte  * return - 0: no wakeup, otherwise yes.
867*fcf3ce44SJohn Forte  *
868*fcf3ce44SJohn Forte  * ****************************************************************************
869*fcf3ce44SJohn Forte  */
870*fcf3ce44SJohn Forte int
871*fcf3ce44SJohn Forte evf_wakeup(
872*fcf3ce44SJohn Forte 	void *p
873*fcf3ce44SJohn Forte )
874*fcf3ce44SJohn Forte {
875*fcf3ce44SJohn Forte 	return (((ev_t *)p)->flags & EV_FLAG_WAKEUP);
876*fcf3ce44SJohn Forte }
877*fcf3ce44SJohn Forte 
878*fcf3ce44SJohn Forte /*
879*fcf3ce44SJohn Forte  * ****************************************************************************
880*fcf3ce44SJohn Forte  *
881*fcf3ce44SJohn Forte  * evf_rem:
882*fcf3ce44SJohn Forte  *	Check the removal flag of an ESI event. The ESI entry might be
883*fcf3ce44SJohn Forte  *	marked as removal.
884*fcf3ce44SJohn Forte  *
885*fcf3ce44SJohn Forte  * p	- the ESI event.
886*fcf3ce44SJohn Forte  * return - 0: not removed, otherwise yes.
887*fcf3ce44SJohn Forte  *
888*fcf3ce44SJohn Forte  * ****************************************************************************
889*fcf3ce44SJohn Forte  */
890*fcf3ce44SJohn Forte int
891*fcf3ce44SJohn Forte evf_rem(
892*fcf3ce44SJohn Forte 	void *p
893*fcf3ce44SJohn Forte )
894*fcf3ce44SJohn Forte {
895*fcf3ce44SJohn Forte 	return (((ev_t *)p)->flags & EV_FLAG_REMOVE);
896*fcf3ce44SJohn Forte }
897*fcf3ce44SJohn Forte 
898*fcf3ce44SJohn Forte /*
899*fcf3ce44SJohn Forte  * ****************************************************************************
900*fcf3ce44SJohn Forte  *
901*fcf3ce44SJohn Forte  * evf_rem_pending:
902*fcf3ce44SJohn Forte  *	Check the removal pending flag of an ESI event. The ESI entry
903*fcf3ce44SJohn Forte  *	might be marked as removal pending. If it is, we will switch the
904*fcf3ce44SJohn Forte  *	event type and change the time interval.
905*fcf3ce44SJohn Forte  *
906*fcf3ce44SJohn Forte  * p	- the ESI event.
907*fcf3ce44SJohn Forte  * return - 0: not removal pending, otherwise yes.
908*fcf3ce44SJohn Forte  *
909*fcf3ce44SJohn Forte  * ****************************************************************************
910*fcf3ce44SJohn Forte  */
911*fcf3ce44SJohn Forte int
912*fcf3ce44SJohn Forte evf_rem_pending(
913*fcf3ce44SJohn Forte 	void *p
914*fcf3ce44SJohn Forte )
915*fcf3ce44SJohn Forte {
916*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)p;
917*fcf3ce44SJohn Forte 	if ((ev->flags & EV_FLAG_REM_P) != 0) {
918*fcf3ce44SJohn Forte 		if (ev->type != EV_REG_EXP) {
919*fcf3ce44SJohn Forte 			isnslog(LOG_DEBUG, "ev_rem_pending",
920*fcf3ce44SJohn Forte 			    "%s [%d] is changed to REG_EXP.",
921*fcf3ce44SJohn Forte 			    ev->type == EV_ESI ? "ESI" : "REG_EXP",
922*fcf3ce44SJohn Forte 			    ev->uid);
923*fcf3ce44SJohn Forte 			ev->type = EV_REG_EXP;
924*fcf3ce44SJohn Forte 			ev->intval *= 2; /* after 2 ESI interval */
925*fcf3ce44SJohn Forte 		}
926*fcf3ce44SJohn Forte 		return (1);
927*fcf3ce44SJohn Forte 	}
928*fcf3ce44SJohn Forte 
929*fcf3ce44SJohn Forte 	return (0);
930*fcf3ce44SJohn Forte }
931*fcf3ce44SJohn Forte 
932*fcf3ce44SJohn Forte /*
933*fcf3ce44SJohn Forte  * ****************************************************************************
934*fcf3ce44SJohn Forte  *
935*fcf3ce44SJohn Forte  * evf_zero:
936*fcf3ce44SJohn Forte  *	Reset the event flag.
937*fcf3ce44SJohn Forte  *
938*fcf3ce44SJohn Forte  * p	- the ESI event.
939*fcf3ce44SJohn Forte  *
940*fcf3ce44SJohn Forte  * ****************************************************************************
941*fcf3ce44SJohn Forte  */
942*fcf3ce44SJohn Forte void
943*fcf3ce44SJohn Forte evf_zero(
944*fcf3ce44SJohn Forte 	void *p
945*fcf3ce44SJohn Forte )
946*fcf3ce44SJohn Forte {
947*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)p;
948*fcf3ce44SJohn Forte 
949*fcf3ce44SJohn Forte 	/* not acutally clear it, need to set again flag */
950*fcf3ce44SJohn Forte 	/* and keep the removal pending flag */
951*fcf3ce44SJohn Forte 	ev->flags = EV_FLAG_AGAIN | (ev->flags & EV_FLAG_REM_P);
952*fcf3ce44SJohn Forte }
953*fcf3ce44SJohn Forte 
954*fcf3ce44SJohn Forte /*
955*fcf3ce44SJohn Forte  * ****************************************************************************
956*fcf3ce44SJohn Forte  *
957*fcf3ce44SJohn Forte  * evl_append:
958*fcf3ce44SJohn Forte  *	Append an ESI event to the list, the list contains all of
959*fcf3ce44SJohn Forte  *	ESI events which are being processed at present.
960*fcf3ce44SJohn Forte  *
961*fcf3ce44SJohn Forte  * p	- the ESI event.
962*fcf3ce44SJohn Forte  *
963*fcf3ce44SJohn Forte  * ****************************************************************************
964*fcf3ce44SJohn Forte  */
965*fcf3ce44SJohn Forte void
966*fcf3ce44SJohn Forte evl_append(
967*fcf3ce44SJohn Forte 	void *p
968*fcf3ce44SJohn Forte )
969*fcf3ce44SJohn Forte {
970*fcf3ce44SJohn Forte 	ev_t *ev;
971*fcf3ce44SJohn Forte 
972*fcf3ce44SJohn Forte 	ev = (ev_t *)p;
973*fcf3ce44SJohn Forte 	ev->next = ev_list;
974*fcf3ce44SJohn Forte 	ev_list = ev;
975*fcf3ce44SJohn Forte }
976*fcf3ce44SJohn Forte 
977*fcf3ce44SJohn Forte /*
978*fcf3ce44SJohn Forte  * ****************************************************************************
979*fcf3ce44SJohn Forte  *
980*fcf3ce44SJohn Forte  * evl_strip:
981*fcf3ce44SJohn Forte  *	Strip off an ESI event from the list after the event is being
982*fcf3ce44SJohn Forte  *	processed, it will be scheduled in the scheduler.
983*fcf3ce44SJohn Forte  *
984*fcf3ce44SJohn Forte  * p	- the ESI event.
985*fcf3ce44SJohn Forte  *
986*fcf3ce44SJohn Forte  * ****************************************************************************
987*fcf3ce44SJohn Forte  */
988*fcf3ce44SJohn Forte void
989*fcf3ce44SJohn Forte evl_strip(
990*fcf3ce44SJohn Forte 	void *p
991*fcf3ce44SJohn Forte )
992*fcf3ce44SJohn Forte {
993*fcf3ce44SJohn Forte 	ev_t **evp = &ev_list;
994*fcf3ce44SJohn Forte 	ev_t *ev = *evp;
995*fcf3ce44SJohn Forte 
996*fcf3ce44SJohn Forte 	while (ev != NULL) {
997*fcf3ce44SJohn Forte 		if (ev == p) {
998*fcf3ce44SJohn Forte 			*evp = ev->next;
999*fcf3ce44SJohn Forte 			break;
1000*fcf3ce44SJohn Forte 		}
1001*fcf3ce44SJohn Forte 		evp = &ev->next;
1002*fcf3ce44SJohn Forte 		ev = *evp;
1003*fcf3ce44SJohn Forte 	}
1004*fcf3ce44SJohn Forte }
1005*fcf3ce44SJohn Forte 
1006*fcf3ce44SJohn Forte /*
1007*fcf3ce44SJohn Forte  * ****************************************************************************
1008*fcf3ce44SJohn Forte  *
1009*fcf3ce44SJohn Forte  * evl_remove:
1010*fcf3ce44SJohn Forte  *	Remove an ESI event or a portal of an ESI event from the event list.
1011*fcf3ce44SJohn Forte  *
1012*fcf3ce44SJohn Forte  * id1	- the Entity object UID.
1013*fcf3ce44SJohn Forte  * id2	- the Portal object UID.
1014*fcf3ce44SJohn Forte  * pending - the pending flag.
1015*fcf3ce44SJohn Forte  * return - 1: found a match event, otherwise not.
1016*fcf3ce44SJohn Forte  *
1017*fcf3ce44SJohn Forte  * ****************************************************************************
1018*fcf3ce44SJohn Forte  */
1019*fcf3ce44SJohn Forte int
1020*fcf3ce44SJohn Forte evl_remove(
1021*fcf3ce44SJohn Forte 	uint32_t id1,
1022*fcf3ce44SJohn Forte 	uint32_t id2,
1023*fcf3ce44SJohn Forte 	int pending
1024*fcf3ce44SJohn Forte )
1025*fcf3ce44SJohn Forte {
1026*fcf3ce44SJohn Forte 	ev_t *ev = ev_list;
1027*fcf3ce44SJohn Forte 
1028*fcf3ce44SJohn Forte 	while (ev != NULL) {
1029*fcf3ce44SJohn Forte 		/* found it */
1030*fcf3ce44SJohn Forte 		if (ev_match(ev, id1) != 0) {
1031*fcf3ce44SJohn Forte 			/* lock the event */
1032*fcf3ce44SJohn Forte 			(void) pthread_mutex_lock(&ev->mtx);
1033*fcf3ce44SJohn Forte 			/* mark it as removed */
1034*fcf3ce44SJohn Forte 			(void) ev_remove(ev, id2, 0, pending);
1035*fcf3ce44SJohn Forte 			/* unlock the event */
1036*fcf3ce44SJohn Forte 			(void) pthread_mutex_unlock(&ev->mtx);
1037*fcf3ce44SJohn Forte 			/* tell caller removal is done */
1038*fcf3ce44SJohn Forte 			return (1);
1039*fcf3ce44SJohn Forte 		}
1040*fcf3ce44SJohn Forte 		ev = ev->next;
1041*fcf3ce44SJohn Forte 	}
1042*fcf3ce44SJohn Forte 
1043*fcf3ce44SJohn Forte 	/* not found it */
1044*fcf3ce44SJohn Forte 	return (0);
1045*fcf3ce44SJohn Forte }
1046*fcf3ce44SJohn Forte 
1047*fcf3ce44SJohn Forte #define	ALARM_MAX	(21427200)
1048*fcf3ce44SJohn Forte 
1049*fcf3ce44SJohn Forte /*
1050*fcf3ce44SJohn Forte  * ****************************************************************************
1051*fcf3ce44SJohn Forte  *
1052*fcf3ce44SJohn Forte  * idle:
1053*fcf3ce44SJohn Forte  *	Idle for certain amount of time or a wakeup signal is recieved.
1054*fcf3ce44SJohn Forte  *
1055*fcf3ce44SJohn Forte  * t	- the idle time.
1056*fcf3ce44SJohn Forte  * return - the time that idle left.
1057*fcf3ce44SJohn Forte  *
1058*fcf3ce44SJohn Forte  * ****************************************************************************
1059*fcf3ce44SJohn Forte  */
1060*fcf3ce44SJohn Forte static int
1061*fcf3ce44SJohn Forte idle(
1062*fcf3ce44SJohn Forte 	uint32_t t
1063*fcf3ce44SJohn Forte )
1064*fcf3ce44SJohn Forte {
1065*fcf3ce44SJohn Forte 	uint32_t t1, t2, t3 = 0;
1066*fcf3ce44SJohn Forte 	int idl_int = 0;
1067*fcf3ce44SJohn Forte 
1068*fcf3ce44SJohn Forte 	/* hold the mutex for stopwatch update */
1069*fcf3ce44SJohn Forte 	(void) pthread_mutex_lock(&stw_mtx);
1070*fcf3ce44SJohn Forte 
1071*fcf3ce44SJohn Forte 	do {
1072*fcf3ce44SJohn Forte 		if (t > ALARM_MAX) {
1073*fcf3ce44SJohn Forte 			t1 = ALARM_MAX;
1074*fcf3ce44SJohn Forte 		} else {
1075*fcf3ce44SJohn Forte 			t1 = t;
1076*fcf3ce44SJohn Forte 		}
1077*fcf3ce44SJohn Forte 
1078*fcf3ce44SJohn Forte 		/* start alarm */
1079*fcf3ce44SJohn Forte 		(void) alarm(t1);
1080*fcf3ce44SJohn Forte 
1081*fcf3ce44SJohn Forte 		/* hold the mutex for idle condition */
1082*fcf3ce44SJohn Forte 		(void) pthread_mutex_lock(&idl_mtx);
1083*fcf3ce44SJohn Forte 
1084*fcf3ce44SJohn Forte 		/* wait on condition variable to wake up idle */
1085*fcf3ce44SJohn Forte 		while (wakeup == 0) {
1086*fcf3ce44SJohn Forte 			(void) pthread_cond_wait(&idl_cond, &idl_mtx);
1087*fcf3ce44SJohn Forte 		}
1088*fcf3ce44SJohn Forte 		if (wakeup == 2) {
1089*fcf3ce44SJohn Forte 			idl_int = 1;
1090*fcf3ce44SJohn Forte 		}
1091*fcf3ce44SJohn Forte 		/* clean wakeup flag */
1092*fcf3ce44SJohn Forte 		wakeup = 0;
1093*fcf3ce44SJohn Forte 
1094*fcf3ce44SJohn Forte 		/* release the mutex for idle condition */
1095*fcf3ce44SJohn Forte 		(void) pthread_mutex_unlock(&idl_mtx);
1096*fcf3ce44SJohn Forte 
1097*fcf3ce44SJohn Forte 		/* stop alarm */
1098*fcf3ce44SJohn Forte 		t2 = alarm(0);
1099*fcf3ce44SJohn Forte 
1100*fcf3ce44SJohn Forte 		/* seconds actually slept */
1101*fcf3ce44SJohn Forte 		t3 += t1 - t2;
1102*fcf3ce44SJohn Forte 		t -= t3;
1103*fcf3ce44SJohn Forte 	} while (t > 0 && idl_int == 0);
1104*fcf3ce44SJohn Forte 
1105*fcf3ce44SJohn Forte 	/* increate the stopwatch by the actually slept time */
1106*fcf3ce44SJohn Forte 	stopwatch += t3;
1107*fcf3ce44SJohn Forte 
1108*fcf3ce44SJohn Forte 	/* release the mutex after stopwatch is updated */
1109*fcf3ce44SJohn Forte 	(void) pthread_mutex_unlock(&stw_mtx);
1110*fcf3ce44SJohn Forte 
1111*fcf3ce44SJohn Forte 	/* return the amount of time which is not slept */
1112*fcf3ce44SJohn Forte 	return (t);
1113*fcf3ce44SJohn Forte }
1114*fcf3ce44SJohn Forte 
1115*fcf3ce44SJohn Forte /*
1116*fcf3ce44SJohn Forte  * ****************************************************************************
1117*fcf3ce44SJohn Forte  *
1118*fcf3ce44SJohn Forte  * ev_ex:
1119*fcf3ce44SJohn Forte  *	Execute an event. To inquiry the client status or
1120*fcf3ce44SJohn Forte  *	perform registration expiration.
1121*fcf3ce44SJohn Forte  *
1122*fcf3ce44SJohn Forte  * ev	- the event.
1123*fcf3ce44SJohn Forte  *
1124*fcf3ce44SJohn Forte  * ****************************************************************************
1125*fcf3ce44SJohn Forte  */
1126*fcf3ce44SJohn Forte static void
1127*fcf3ce44SJohn Forte ev_ex(
1128*fcf3ce44SJohn Forte 	ev_t *ev
1129*fcf3ce44SJohn Forte )
1130*fcf3ce44SJohn Forte {
1131*fcf3ce44SJohn Forte 	pthread_t tid;
1132*fcf3ce44SJohn Forte 
1133*fcf3ce44SJohn Forte 	switch (ev->type) {
1134*fcf3ce44SJohn Forte 	case EV_ESI:
1135*fcf3ce44SJohn Forte 		if (pthread_create(&tid, NULL,
1136*fcf3ce44SJohn Forte 		    esi_monitor, (void *)ev) != 0) {
1137*fcf3ce44SJohn Forte 			isnslog(LOG_DEBUG, "ev_ex", "pthread_create() failed.");
1138*fcf3ce44SJohn Forte 			/* reschedule for next occurence */
1139*fcf3ce44SJohn Forte 			(void) el_add(ev, 0, NULL);
1140*fcf3ce44SJohn Forte 		} else {
1141*fcf3ce44SJohn Forte 			/* increase the thread ref count */
1142*fcf3ce44SJohn Forte 			inc_thr_count();
1143*fcf3ce44SJohn Forte 		}
1144*fcf3ce44SJohn Forte 		break;
1145*fcf3ce44SJohn Forte 	case EV_REG_EXP:
1146*fcf3ce44SJohn Forte 		(void) queue_msg_set(sys_q, REG_EXP, (void *)ev);
1147*fcf3ce44SJohn Forte 		break;
1148*fcf3ce44SJohn Forte 	default:
1149*fcf3ce44SJohn Forte 		break;
1150*fcf3ce44SJohn Forte 	}
1151*fcf3ce44SJohn Forte }
1152*fcf3ce44SJohn Forte 
1153*fcf3ce44SJohn Forte /*
1154*fcf3ce44SJohn Forte  * ****************************************************************************
1155*fcf3ce44SJohn Forte  *
1156*fcf3ce44SJohn Forte  * esi_proc:
1157*fcf3ce44SJohn Forte  *	ESI thread entry, which:
1158*fcf3ce44SJohn Forte  *	1: fetch an event from schedule,
1159*fcf3ce44SJohn Forte  *	2: idle for some time,
1160*fcf3ce44SJohn Forte  *	3: execute the event or re-schedule it,
1161*fcf3ce44SJohn Forte  *	4: repeat from step 1 before server is being shutdown.
1162*fcf3ce44SJohn Forte  *
1163*fcf3ce44SJohn Forte  * arg	- the thread argument.
1164*fcf3ce44SJohn Forte  *
1165*fcf3ce44SJohn Forte  * ****************************************************************************
1166*fcf3ce44SJohn Forte  */
1167*fcf3ce44SJohn Forte /*ARGSUSED*/
1168*fcf3ce44SJohn Forte void *
1169*fcf3ce44SJohn Forte esi_proc(
1170*fcf3ce44SJohn Forte 	void *arg
1171*fcf3ce44SJohn Forte )
1172*fcf3ce44SJohn Forte {
1173*fcf3ce44SJohn Forte 	uint32_t t, t1, pt;
1174*fcf3ce44SJohn Forte 	ev_t *ev;
1175*fcf3ce44SJohn Forte 
1176*fcf3ce44SJohn Forte 	void *evp;
1177*fcf3ce44SJohn Forte 
1178*fcf3ce44SJohn Forte 	while (time_to_exit == B_FALSE) {
1179*fcf3ce44SJohn Forte 		ev = (ev_t *)el_first(&pt);
1180*fcf3ce44SJohn Forte 
1181*fcf3ce44SJohn Forte 		/* caculate the idle time */
1182*fcf3ce44SJohn Forte 		if (ev != NULL) {
1183*fcf3ce44SJohn Forte 			if (pt > stopwatch) {
1184*fcf3ce44SJohn Forte 				t = pt - stopwatch;
1185*fcf3ce44SJohn Forte 			} else {
1186*fcf3ce44SJohn Forte 				t = 0;
1187*fcf3ce44SJohn Forte 			}
1188*fcf3ce44SJohn Forte 		} else {
1189*fcf3ce44SJohn Forte 			t = INFINITY;
1190*fcf3ce44SJohn Forte 		}
1191*fcf3ce44SJohn Forte 
1192*fcf3ce44SJohn Forte 		do {
1193*fcf3ce44SJohn Forte 			/* block for a certain amount of time */
1194*fcf3ce44SJohn Forte 			if (t > 0) {
1195*fcf3ce44SJohn Forte 				isnslog(LOG_DEBUG, "esi_proc",
1196*fcf3ce44SJohn Forte 				    "idle for %d seconds.", t);
1197*fcf3ce44SJohn Forte 				t1 = idle(t);
1198*fcf3ce44SJohn Forte 			} else {
1199*fcf3ce44SJohn Forte 				t1 = 0;
1200*fcf3ce44SJohn Forte 			}
1201*fcf3ce44SJohn Forte 			if (t1 > 0) {
1202*fcf3ce44SJohn Forte 				isnslog(LOG_DEBUG, "esi_proc",
1203*fcf3ce44SJohn Forte 				    "idle interrupted after idle for "
1204*fcf3ce44SJohn Forte 				    "%d seconds.", t - t1);
1205*fcf3ce44SJohn Forte 			}
1206*fcf3ce44SJohn Forte 			if (time_to_exit != B_FALSE) {
1207*fcf3ce44SJohn Forte 				ev = NULL; /* force break */
1208*fcf3ce44SJohn Forte 			} else if (ev != NULL) {
1209*fcf3ce44SJohn Forte 				if (t1 > 0) {
1210*fcf3ce44SJohn Forte 					/* not naturally waken up */
1211*fcf3ce44SJohn Forte 					/* reschedule current event */
1212*fcf3ce44SJohn Forte 					evp = NULL;
1213*fcf3ce44SJohn Forte 					(void) el_add(ev, pt, &evp);
1214*fcf3ce44SJohn Forte 					ev = (ev_t *)evp;
1215*fcf3ce44SJohn Forte 					t = t1;
1216*fcf3ce44SJohn Forte 				} else {
1217*fcf3ce44SJohn Forte 					/* excute */
1218*fcf3ce44SJohn Forte 					isnslog(LOG_DEBUG, "esi_proc",
1219*fcf3ce44SJohn Forte 					    "excute the cron job[%d].",
1220*fcf3ce44SJohn Forte 					    ev->uid);
1221*fcf3ce44SJohn Forte 					ev_ex(ev);
1222*fcf3ce44SJohn Forte 					ev = NULL;
1223*fcf3ce44SJohn Forte 				}
1224*fcf3ce44SJohn Forte 			}
1225*fcf3ce44SJohn Forte 		} while (ev != NULL);
1226*fcf3ce44SJohn Forte 	}
1227*fcf3ce44SJohn Forte 
1228*fcf3ce44SJohn Forte 	return (NULL);
1229*fcf3ce44SJohn Forte }
1230*fcf3ce44SJohn Forte 
1231*fcf3ce44SJohn Forte /*
1232*fcf3ce44SJohn Forte  * ****************************************************************************
1233*fcf3ce44SJohn Forte  *
1234*fcf3ce44SJohn Forte  * esi_ping:
1235*fcf3ce44SJohn Forte  *	Ping the client with the ESI retry threshold for status inquiry.
1236*fcf3ce44SJohn Forte  *
1237*fcf3ce44SJohn Forte  * so	- the socket descriptor.
1238*fcf3ce44SJohn Forte  * pdu	- the ESI packet.
1239*fcf3ce44SJohn Forte  * pl	- the length of packet.
1240*fcf3ce44SJohn Forte  * return - 1: status inquired, otherwise not.
1241*fcf3ce44SJohn Forte  *
1242*fcf3ce44SJohn Forte  * ****************************************************************************
1243*fcf3ce44SJohn Forte  */
1244*fcf3ce44SJohn Forte static int
1245*fcf3ce44SJohn Forte esi_ping(
1246*fcf3ce44SJohn Forte 	int so,
1247*fcf3ce44SJohn Forte 	isns_pdu_t *pdu,
1248*fcf3ce44SJohn Forte 	size_t pl
1249*fcf3ce44SJohn Forte )
1250*fcf3ce44SJohn Forte {
1251*fcf3ce44SJohn Forte 	int try_cnt = 0;
1252*fcf3ce44SJohn Forte 	isns_pdu_t *rsp = NULL;
1253*fcf3ce44SJohn Forte 	size_t rsp_sz;
1254*fcf3ce44SJohn Forte 
1255*fcf3ce44SJohn Forte 	int alive = 0;
1256*fcf3ce44SJohn Forte 
1257*fcf3ce44SJohn Forte 	do {
1258*fcf3ce44SJohn Forte 		if (isns_send_pdu(so, pdu, pl) == 0) {
1259*fcf3ce44SJohn Forte 			if (isns_rcv_pdu(so, &rsp, &rsp_sz,
1260*fcf3ce44SJohn Forte 			    ISNS_RCV_SHORT_TIMEOUT) > 0) {
1261*fcf3ce44SJohn Forte #ifdef DEBUG
1262*fcf3ce44SJohn Forte 				dump_pdu1(rsp);
1263*fcf3ce44SJohn Forte #endif
1264*fcf3ce44SJohn Forte 				alive = 1;
1265*fcf3ce44SJohn Forte 				break;
1266*fcf3ce44SJohn Forte 			}
1267*fcf3ce44SJohn Forte 		} else {
1268*fcf3ce44SJohn Forte 			/* retry after 1 second */
1269*fcf3ce44SJohn Forte 			(void) sleep(1);
1270*fcf3ce44SJohn Forte 		}
1271*fcf3ce44SJohn Forte 		try_cnt ++;
1272*fcf3ce44SJohn Forte 	} while (try_cnt < esi_threshold);
1273*fcf3ce44SJohn Forte 
1274*fcf3ce44SJohn Forte 	if (rsp != NULL) {
1275*fcf3ce44SJohn Forte 		free(rsp);
1276*fcf3ce44SJohn Forte 	}
1277*fcf3ce44SJohn Forte 
1278*fcf3ce44SJohn Forte 	return (alive);
1279*fcf3ce44SJohn Forte }
1280*fcf3ce44SJohn Forte 
1281*fcf3ce44SJohn Forte /*
1282*fcf3ce44SJohn Forte  * ****************************************************************************
1283*fcf3ce44SJohn Forte  *
1284*fcf3ce44SJohn Forte  * esi_monitor:
1285*fcf3ce44SJohn Forte  *	Child thread for client status mornitoring.
1286*fcf3ce44SJohn Forte  *
1287*fcf3ce44SJohn Forte  * arg	- the ESI event.
1288*fcf3ce44SJohn Forte  *
1289*fcf3ce44SJohn Forte  * ****************************************************************************
1290*fcf3ce44SJohn Forte  */
1291*fcf3ce44SJohn Forte static void *
1292*fcf3ce44SJohn Forte esi_monitor(
1293*fcf3ce44SJohn Forte 	void *arg
1294*fcf3ce44SJohn Forte )
1295*fcf3ce44SJohn Forte {
1296*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)arg;
1297*fcf3ce44SJohn Forte 
1298*fcf3ce44SJohn Forte 	esi_portal_t *p;
1299*fcf3ce44SJohn Forte 	int so;
1300*fcf3ce44SJohn Forte 
1301*fcf3ce44SJohn Forte 	isns_pdu_t *pdu = NULL;
1302*fcf3ce44SJohn Forte 	size_t sz;
1303*fcf3ce44SJohn Forte 	size_t pl;
1304*fcf3ce44SJohn Forte 	size_t half;
1305*fcf3ce44SJohn Forte 
1306*fcf3ce44SJohn Forte 	time_t t;
1307*fcf3ce44SJohn Forte 
1308*fcf3ce44SJohn Forte 	int feedback;
1309*fcf3ce44SJohn Forte 
1310*fcf3ce44SJohn Forte 	/* lock the event for esi monitoring */
1311*fcf3ce44SJohn Forte 	(void) pthread_mutex_lock(&ev->mtx);
1312*fcf3ce44SJohn Forte 
1313*fcf3ce44SJohn Forte 	if (evf_rem(ev) != 0) {
1314*fcf3ce44SJohn Forte 		goto mon_done;
1315*fcf3ce44SJohn Forte 	} else if (evf_rem_pending(ev) != 0) {
1316*fcf3ce44SJohn Forte 		goto mon_done;
1317*fcf3ce44SJohn Forte 	}
1318*fcf3ce44SJohn Forte 
1319*fcf3ce44SJohn Forte 	/* timestamp */
1320*fcf3ce44SJohn Forte 	t = time(NULL);
1321*fcf3ce44SJohn Forte 
1322*fcf3ce44SJohn Forte 	/* allocate ESI PDU */
1323*fcf3ce44SJohn Forte 	if (pdu_reset_esi(&pdu, &pl, &sz) != 0 ||
1324*fcf3ce44SJohn Forte 	    pdu_add_tlv(&pdu, &pl, &sz,
1325*fcf3ce44SJohn Forte 	    ISNS_TIMESTAMP_ATTR_ID, 8, (void *)&t, 1) != 0 ||
1326*fcf3ce44SJohn Forte 	    pdu_add_tlv(&pdu, &pl, &sz,
1327*fcf3ce44SJohn Forte 	    ISNS_EID_ATTR_ID, ev->eid_len, (void *)ev->eid, 0) != 0) {
1328*fcf3ce44SJohn Forte 		/* no memory, will retry later */
1329*fcf3ce44SJohn Forte 		goto mon_done;
1330*fcf3ce44SJohn Forte 	}
1331*fcf3ce44SJohn Forte 
1332*fcf3ce44SJohn Forte 	/* set pdu head */
1333*fcf3ce44SJohn Forte 	pdu->version = htons((uint16_t)ISNSP_VERSION);
1334*fcf3ce44SJohn Forte 	pdu->func_id = htons((uint16_t)ISNS_ESI);
1335*fcf3ce44SJohn Forte 	pdu->xid = htons(get_server_xid());
1336*fcf3ce44SJohn Forte 
1337*fcf3ce44SJohn Forte 	/* keep the current lenght of the playload */
1338*fcf3ce44SJohn Forte 	half = pl;
1339*fcf3ce44SJohn Forte 
1340*fcf3ce44SJohn Forte 	p = ev->portal;
1341*fcf3ce44SJohn Forte 	while (p != NULL) {
1342*fcf3ce44SJohn Forte 		if (p->ref != 0 &&
1343*fcf3ce44SJohn Forte 		    /* skip IPv6 portal */
1344*fcf3ce44SJohn Forte 		    p->sz != sizeof (in6_addr_t) &&
1345*fcf3ce44SJohn Forte 		    pdu_add_tlv(&pdu, &pl, &sz,
1346*fcf3ce44SJohn Forte 		    ISNS_PORTAL_IP_ADDR_ATTR_ID,
1347*fcf3ce44SJohn Forte 		    sizeof (in6_addr_t), (void *)p->ip6, 0) == 0 &&
1348*fcf3ce44SJohn Forte 		    pdu_add_tlv(&pdu, &pl, &sz,
1349*fcf3ce44SJohn Forte 		    ISNS_PORTAL_PORT_ATTR_ID,
1350*fcf3ce44SJohn Forte 		    4, (void *)p->port, 0) == 0) {
1351*fcf3ce44SJohn Forte 			/* connect once */
1352*fcf3ce44SJohn Forte 			so = connect_to(p->sz, p->ip4, p->ip6, p->esip);
1353*fcf3ce44SJohn Forte 			if (so != -1) {
1354*fcf3ce44SJohn Forte 				feedback = esi_ping(so, pdu, pl);
1355*fcf3ce44SJohn Forte 				(void) close(so);
1356*fcf3ce44SJohn Forte 				/* p->so = so; */
1357*fcf3ce44SJohn Forte 			} else {
1358*fcf3ce44SJohn Forte 				/* cannot connect, portal is dead */
1359*fcf3ce44SJohn Forte 				feedback = 0;
1360*fcf3ce44SJohn Forte 			}
1361*fcf3ce44SJohn Forte 			if (feedback == 0) {
1362*fcf3ce44SJohn Forte 				isnslog(LOG_DEBUG, "esi_monitor",
1363*fcf3ce44SJohn Forte 				    "ESI ping failed.");
1364*fcf3ce44SJohn Forte 				(void) queue_msg_set(sys_q, DEAD_PORTAL,
1365*fcf3ce44SJohn Forte 				    (void *)p->ref);
1366*fcf3ce44SJohn Forte 			} else {
1367*fcf3ce44SJohn Forte 				goto mon_done;
1368*fcf3ce44SJohn Forte 			}
1369*fcf3ce44SJohn Forte 		}
1370*fcf3ce44SJohn Forte 		pl = half;
1371*fcf3ce44SJohn Forte 		p = p->next;
1372*fcf3ce44SJohn Forte 	}
1373*fcf3ce44SJohn Forte 
1374*fcf3ce44SJohn Forte mon_done:
1375*fcf3ce44SJohn Forte 	/* unlock the event after esi monitoring is done */
1376*fcf3ce44SJohn Forte 	(void) pthread_mutex_unlock(&ev->mtx);
1377*fcf3ce44SJohn Forte 
1378*fcf3ce44SJohn Forte 	/* clean up pdu */
1379*fcf3ce44SJohn Forte 	if (pdu != NULL) {
1380*fcf3ce44SJohn Forte 		free(pdu);
1381*fcf3ce44SJohn Forte 	}
1382*fcf3ce44SJohn Forte 
1383*fcf3ce44SJohn Forte 	/* set reschedule flags */
1384*fcf3ce44SJohn Forte 	ev->flags |= EV_FLAG_WAKEUP;
1385*fcf3ce44SJohn Forte 
1386*fcf3ce44SJohn Forte 	/* reschedule for next occurence */
1387*fcf3ce44SJohn Forte 	(void) el_add(ev, 0, NULL);
1388*fcf3ce44SJohn Forte 
1389*fcf3ce44SJohn Forte 	/* decrease the thread ref count */
1390*fcf3ce44SJohn Forte 	dec_thr_count();
1391*fcf3ce44SJohn Forte 
1392*fcf3ce44SJohn Forte 	return (NULL);
1393*fcf3ce44SJohn Forte }
1394*fcf3ce44SJohn Forte 
1395*fcf3ce44SJohn Forte /*
1396*fcf3ce44SJohn Forte  * ****************************************************************************
1397*fcf3ce44SJohn Forte  *
1398*fcf3ce44SJohn Forte  * portal_dies:
1399*fcf3ce44SJohn Forte  *	Handles the dead portal that ESI detected.
1400*fcf3ce44SJohn Forte  *
1401*fcf3ce44SJohn Forte  * uid	- the Portal object UID.
1402*fcf3ce44SJohn Forte  *
1403*fcf3ce44SJohn Forte  * ****************************************************************************
1404*fcf3ce44SJohn Forte  */
1405*fcf3ce44SJohn Forte void
1406*fcf3ce44SJohn Forte portal_dies(
1407*fcf3ce44SJohn Forte 	uint32_t uid
1408*fcf3ce44SJohn Forte )
1409*fcf3ce44SJohn Forte {
1410*fcf3ce44SJohn Forte 	int ec = 0;
1411*fcf3ce44SJohn Forte 
1412*fcf3ce44SJohn Forte 	lookup_ctrl_t lc;
1413*fcf3ce44SJohn Forte 
1414*fcf3ce44SJohn Forte 	/* prepare the lookup control for deregistration */
1415*fcf3ce44SJohn Forte 	SET_UID_LCP(&lc, OBJ_PORTAL, uid);
1416*fcf3ce44SJohn Forte 
1417*fcf3ce44SJohn Forte 	/* lock the cache for object deregistration */
1418*fcf3ce44SJohn Forte 	(void) cache_lock_write();
1419*fcf3ce44SJohn Forte 
1420*fcf3ce44SJohn Forte 	/* deregister the portal */
1421*fcf3ce44SJohn Forte 	ec = dereg_object(&lc, 1);
1422*fcf3ce44SJohn Forte 
1423*fcf3ce44SJohn Forte 	/* unlock cache and sync with data store */
1424*fcf3ce44SJohn Forte 	(void) cache_unlock_sync(ec);
1425*fcf3ce44SJohn Forte }
1426*fcf3ce44SJohn Forte 
1427*fcf3ce44SJohn Forte /*
1428*fcf3ce44SJohn Forte  * ****************************************************************************
1429*fcf3ce44SJohn Forte  *
1430*fcf3ce44SJohn Forte  * portal_dies:
1431*fcf3ce44SJohn Forte  *	Handles the Entity registration expiration.
1432*fcf3ce44SJohn Forte  *
1433*fcf3ce44SJohn Forte  * p	- the ESI event.
1434*fcf3ce44SJohn Forte  *
1435*fcf3ce44SJohn Forte  * ****************************************************************************
1436*fcf3ce44SJohn Forte  */
1437*fcf3ce44SJohn Forte void
1438*fcf3ce44SJohn Forte reg_expiring(
1439*fcf3ce44SJohn Forte 	void *p
1440*fcf3ce44SJohn Forte )
1441*fcf3ce44SJohn Forte {
1442*fcf3ce44SJohn Forte 	int ec = 0;
1443*fcf3ce44SJohn Forte 	ev_t *ev = (ev_t *)p;
1444*fcf3ce44SJohn Forte 	lookup_ctrl_t lc;
1445*fcf3ce44SJohn Forte 
1446*fcf3ce44SJohn Forte 	/* prepare the lookup control for deregistration */
1447*fcf3ce44SJohn Forte 	SET_UID_LCP(&lc, OBJ_ENTITY, ev->uid);
1448*fcf3ce44SJohn Forte 
1449*fcf3ce44SJohn Forte 	/* lock the cache for object deregistration */
1450*fcf3ce44SJohn Forte 	(void) cache_lock_write();
1451*fcf3ce44SJohn Forte 
1452*fcf3ce44SJohn Forte 	if (evf_rem(ev) == 0) {
1453*fcf3ce44SJohn Forte 		/* deregister the entity */
1454*fcf3ce44SJohn Forte 		ec = dereg_object(&lc, 0);
1455*fcf3ce44SJohn Forte 
1456*fcf3ce44SJohn Forte 		/* unlock cache and sync with data store */
1457*fcf3ce44SJohn Forte 		ec = cache_unlock_sync(ec);
1458*fcf3ce44SJohn Forte 
1459*fcf3ce44SJohn Forte 		if (ec == 0) {
1460*fcf3ce44SJohn Forte 			/* successfuk, mark ev as removed */
1461*fcf3ce44SJohn Forte 			ev->flags |= EV_FLAG_REMOVE;
1462*fcf3ce44SJohn Forte 		} else {
1463*fcf3ce44SJohn Forte 			/* failed, retry after 3 mintues */
1464*fcf3ce44SJohn Forte 			ev->intval = 3 * 60;
1465*fcf3ce44SJohn Forte 			isnslog(LOG_DEBUG, "reg_expiring",
1466*fcf3ce44SJohn Forte 			    "dereg failed, retry after 3 mintues.");
1467*fcf3ce44SJohn Forte 		}
1468*fcf3ce44SJohn Forte 	} else {
1469*fcf3ce44SJohn Forte 		/* ev is marked as removed, no need to dereg */
1470*fcf3ce44SJohn Forte 		(void) cache_unlock_nosync();
1471*fcf3ce44SJohn Forte 	}
1472*fcf3ce44SJohn Forte 
1473*fcf3ce44SJohn Forte 	/* reschedule it for next occurence */
1474*fcf3ce44SJohn Forte 	(void) el_add(ev, 0, NULL);
1475*fcf3ce44SJohn Forte }
1476