1 /*
2  * Copyright (c) 1996-2003
3  *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  * 	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <[email protected]>
28  *
29  * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
30  *
31  * Instance handling
32  */
33 
34 #include <netnatm/unimsg.h>
35 #include <netnatm/saal/sscopdef.h>
36 #include <netnatm/saal/sscfudef.h>
37 #include <netnatm/msg/unistruct.h>
38 #include <netnatm/msg/unimsglib.h>
39 #include <netnatm/sig/uni.h>
40 #include <netnatm/sig/unisig.h>
41 
42 #include <netnatm/sig/unipriv.h>
43 
44 #ifdef UNICORE
45 UNICORE
46 #endif
47 
48 #define STR(S) [S] = #S
49 static const char *custat_names[] = {
50 	STR(CU_STAT0),
51 	STR(CU_STAT1),
52 	STR(CU_STAT2),
53 	STR(CU_STAT3),
54 };
55 static const char *globstat_names[] = {
56 	STR(UNI_CALLSTATE_REST0),
57 	STR(UNI_CALLSTATE_REST1),
58 	STR(UNI_CALLSTATE_REST2),
59 };
60 
61 static const char *sig_names[] = {
62 	STR(UNIAPI_ERROR),
63 	STR(UNIAPI_CALL_CREATED),
64 	STR(UNIAPI_CALL_DESTROYED),
65 	STR(UNIAPI_PARTY_CREATED),
66 	STR(UNIAPI_PARTY_DESTROYED),
67 	STR(UNIAPI_LINK_ESTABLISH_request),
68 	STR(UNIAPI_LINK_ESTABLISH_confirm),
69 	STR(UNIAPI_LINK_RELEASE_request),
70 	STR(UNIAPI_LINK_RELEASE_confirm),
71 	STR(UNIAPI_RESET_request),
72 	STR(UNIAPI_RESET_confirm),
73 	STR(UNIAPI_RESET_indication),
74 	STR(UNIAPI_RESET_ERROR_indication),
75 	STR(UNIAPI_RESET_response),
76 	STR(UNIAPI_RESET_ERROR_response),
77 	STR(UNIAPI_RESET_STATUS_indication),
78 	STR(UNIAPI_SETUP_request),
79 	STR(UNIAPI_SETUP_indication),
80 	STR(UNIAPI_SETUP_response),
81 	STR(UNIAPI_SETUP_confirm),
82 	STR(UNIAPI_SETUP_COMPLETE_indication),
83 	STR(UNIAPI_SETUP_COMPLETE_request),
84 	STR(UNIAPI_ALERTING_request),
85 	STR(UNIAPI_ALERTING_indication),
86 	STR(UNIAPI_PROCEEDING_request),
87 	STR(UNIAPI_PROCEEDING_indication),
88 	STR(UNIAPI_RELEASE_request),
89 	STR(UNIAPI_RELEASE_indication),
90 	STR(UNIAPI_RELEASE_response),
91 	STR(UNIAPI_RELEASE_confirm),
92 	STR(UNIAPI_NOTIFY_request),
93 	STR(UNIAPI_NOTIFY_indication),
94 	STR(UNIAPI_STATUS_indication),
95 	STR(UNIAPI_STATUS_ENQUIRY_request),
96 	STR(UNIAPI_ADD_PARTY_request),
97 	STR(UNIAPI_ADD_PARTY_indication),
98 	STR(UNIAPI_PARTY_ALERTING_request),
99 	STR(UNIAPI_PARTY_ALERTING_indication),
100 	STR(UNIAPI_ADD_PARTY_ACK_request),
101 	STR(UNIAPI_ADD_PARTY_ACK_indication),
102 	STR(UNIAPI_ADD_PARTY_REJ_request),
103 	STR(UNIAPI_ADD_PARTY_REJ_indication),
104 	STR(UNIAPI_DROP_PARTY_request),
105 	STR(UNIAPI_DROP_PARTY_indication),
106 	STR(UNIAPI_DROP_PARTY_ACK_request),
107 	STR(UNIAPI_DROP_PARTY_ACK_indication),
108 	STR(UNIAPI_ABORT_CALL_request),
109 };
110 
111 static const char *verb_names[] = {
112 # define UNI_DEBUG_DEFINE(D) [UNI_FAC_##D] = #D,
113 	UNI_DEBUG_FACILITIES
114 # undef UNI_DEBUG_DEFINE
115 };
116 
117 const char *
uni_facname(enum uni_verb fac)118 uni_facname(enum uni_verb fac)
119 {
120 	static char buf[40];
121 
122 	if (fac >= UNI_MAXFACILITY) {
123 		sprintf(buf, "FAC%u", fac);
124 		return (buf);
125 	}
126 	return (verb_names[fac]);
127 }
128 
129 const char *
uni_signame(enum uni_sig sig)130 uni_signame(enum uni_sig sig)
131 {
132 	static char buf[40];
133 
134 	if (sig >= UNIAPI_MAXSIG) {
135 		sprintf(buf, "UNIAPI_SIG%u", sig);
136 		return (buf);
137 	}
138 	return (sig_names[sig]);
139 }
140 
141 struct unicx *
uni_context(struct uni * uni)142 uni_context(struct uni *uni)
143 {
144 	return (&uni->cx);
145 }
146 
147 static void
uni_init(struct uni * uni)148 uni_init(struct uni *uni)
149 {
150 	uni->working = 0;
151 	uni->cref_alloc = 12;
152 	uni->custat = CU_STAT0;
153 	uni->glob_start = UNI_CALLSTATE_REST0;
154 	uni->glob_respond = UNI_CALLSTATE_REST0;
155 }
156 
157 static void
uni_stop(struct uni * uni)158 uni_stop(struct uni *uni)
159 {
160 	struct call *c;
161 
162 	while ((c = TAILQ_FIRST(&uni->calls)) != NULL) {
163 		TAILQ_REMOVE(&uni->calls, c, link);
164 		uni_destroy_call(c, 1);
165 	}
166 
167 	SIGQ_CLEAR(&uni->workq);
168 	SIGQ_CLEAR(&uni->delq);
169 }
170 
171 /*
172  * INSTANCE HANDLING
173  */
174 struct uni *
uni_create(void * arg,const struct uni_funcs * funcs)175 uni_create(void *arg, const struct uni_funcs *funcs)
176 {
177 	struct uni *uni;
178 
179 	if ((uni = INS_ALLOC()) == NULL)
180 		return (NULL);
181 
182 	uni_init(uni);
183 
184 	uni->funcs = funcs;
185 	uni->arg = arg;
186 	uni->proto = UNIPROTO_UNI40U;
187 	uni->sb_tb = 0;
188 	TAILQ_INIT(&uni->workq);
189 	TAILQ_INIT(&uni->delq);
190 	TIMER_INIT_UNI(uni, t309);
191 	uni->timer309 = UNI_T309_DEFAULT;
192 	TAILQ_INIT(&uni->calls);
193 	uni_initcx(&uni->cx);
194 	TIMER_INIT_UNI(uni, t317);
195 	TIMER_INIT_UNI(uni, t316);
196 
197 	uni->timer301 = UNI_T301_DEFAULT;
198 	uni->init303 = UNI_T303_CNT_DEFAULT;
199 	uni->timer303 = UNI_T303_DEFAULT;
200 	uni->init308 = UNI_T308_CNT_DEFAULT;
201 	uni->timer308 = UNI_T308_DEFAULT;
202 	uni->timer310 = UNI_T310U_DEFAULT;
203 	uni->timer313 = UNI_T313_DEFAULT;
204 	uni->init316 = UNI_T316_CNT_DEFAULT;
205 	uni->timer316 = UNI_T316_DEFAULT;
206 	uni->timer317 = UNI_T317_DEFAULT;
207 	uni->timer322 = UNI_T322_DEFAULT;
208 	uni->init322 = UNI_T322_CNT_DEFAULT;
209 	uni->timer397 = UNI_T397_DEFAULT;
210 	uni->timer398 = UNI_T398_DEFAULT;
211 	uni->timer399 = UNI_T399U_DEFAULT;
212 
213 	return (uni);
214 }
215 
216 void
uni_destroy(struct uni * uni)217 uni_destroy(struct uni *uni)
218 {
219 	uni_stop(uni);
220 
221 	TIMER_DESTROY_UNI(uni, t309);
222 	TIMER_DESTROY_UNI(uni, t316);
223 	TIMER_DESTROY_UNI(uni, t317);
224 
225 	INS_FREE(uni);
226 }
227 
228 void
uni_reset(struct uni * uni)229 uni_reset(struct uni *uni)
230 {
231 	uni_stop(uni);
232 	uni_init(uni);
233 }
234 
235 
236 /*
237  * DISPATCH SSCOP SIGNAL
238  */
239 void
uni_saal_input(struct uni * uni,enum saal_sig sig,struct uni_msg * m)240 uni_saal_input(struct uni *uni, enum saal_sig sig, struct uni_msg *m)
241 {
242 	switch (sig) {
243 
244 	  case SAAL_ESTABLISH_indication:
245 		if (m != NULL)
246 			uni_msg_destroy(m);
247 		uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_indication, 0, NULL);
248 		break;
249 
250 	  case SAAL_ESTABLISH_confirm:
251 		if (m != NULL)
252 			uni_msg_destroy(m);
253 		uni_enq_coord(uni, SIGO_SAAL_ESTABLISH_confirm, 0, NULL);
254 		break;
255 
256 	  case SAAL_RELEASE_confirm:
257 		if (m != NULL)
258 			uni_msg_destroy(m);
259 		uni_enq_coord(uni, SIGO_SAAL_RELEASE_confirm, 0, NULL);
260 		break;
261 
262 	  case SAAL_RELEASE_indication:
263 		if (m != NULL)
264 			uni_msg_destroy(m);
265 		uni_enq_coord(uni, SIGO_SAAL_RELEASE_indication, 0, NULL);
266 		break;
267 
268 	  case SAAL_DATA_indication:
269 		uni_enq_coord(uni, SIGO_SAAL_DATA_indication, 0, m);
270 		break;
271 
272 	  case SAAL_UDATA_indication:
273 		uni_enq_coord(uni, SIGO_SAAL_UDATA_indication, 0, m);
274 		break;
275 
276 	  default:
277 		VERBOSE(uni, UNI_FAC_ERR, 1, "bogus saal signal %u", sig);
278 		if (m != NULL)
279 			uni_msg_destroy(m);
280 		break;
281 	}
282 }
283 
284 static struct {
285 	const char	*name;
286 	enum uni_sig	sig;
287 	size_t		arglen;
288 	u_int		coord_sig;
289 	u_int		proto;
290 #define UNIU	0x01
291 #define UNIN	0x02
292 #define PNNI	0x04
293 } maptab[] = {
294 	{ "LINK-ESTABLISH.request", UNIAPI_LINK_ESTABLISH_request,
295 	    0,
296 	    SIGO_LINK_ESTABLISH_request, UNIU | UNIN },
297 	{ "LINK-RELEASE.request", UNIAPI_LINK_RELEASE_request,
298 	    0,
299 	    SIGO_LINK_RELEASE_request, UNIU | UNIN },
300 
301 	{ "RESET.request", UNIAPI_RESET_request,
302 	    sizeof(struct uniapi_reset_request),
303 	    SIGO_RESET_request, UNIU | UNIN },
304 	{ "RESET-ERROR.response", UNIAPI_RESET_ERROR_response,
305 	    sizeof(struct uniapi_reset_error_response),
306 	    SIGO_RESET_ERROR_response, UNIU | UNIN },
307 	{ "RESET.response", UNIAPI_RESET_response,
308 	    sizeof(struct uniapi_reset_response),
309 	    SIGO_RESET_response, UNIU | UNIN },
310 
311 	{ "SETUP.request", UNIAPI_SETUP_request,
312 	    sizeof(struct uniapi_setup_request),
313 	    SIGO_SETUP_request, UNIU | UNIN },
314 	{ "SETUP.response", UNIAPI_SETUP_response,
315 	    sizeof(struct uniapi_setup_response),
316 	    SIGO_SETUP_response, UNIU | UNIN },
317 	{ "SETUP-COMPLETE.request", UNIAPI_SETUP_COMPLETE_request,
318 	    sizeof(struct uniapi_setup_complete_request),
319 	    SIGO_SETUP_COMPLETE_request, UNIN },
320 	{ "PROCEEDING.request", UNIAPI_PROCEEDING_request,
321 	    sizeof(struct uniapi_proceeding_request),
322 	    SIGO_PROCEEDING_request, UNIU | UNIN },
323 	{ "ALERTING.request", UNIAPI_ALERTING_request,
324 	    sizeof(struct uniapi_alerting_request),
325 	    SIGO_ALERTING_request, UNIU | UNIN },
326 	{ "RELEASE.request", UNIAPI_RELEASE_request,
327 	    sizeof(struct uniapi_release_request),
328 	    SIGO_RELEASE_request, UNIU | UNIN },
329 	{ "RELEASE.response", UNIAPI_RELEASE_response,
330 	    sizeof(struct uniapi_release_response),
331 	    SIGO_RELEASE_response, UNIU | UNIN },
332 	{ "NOTIFY.request", UNIAPI_NOTIFY_request,
333 	    sizeof(struct uniapi_notify_request),
334 	    SIGO_NOTIFY_request, UNIU | UNIN },
335 	{ "STATUS-ENQUIRY.request", UNIAPI_STATUS_ENQUIRY_request,
336 	    sizeof(struct uniapi_status_enquiry_request),
337 	    SIGO_STATUS_ENQUIRY_request, UNIU | UNIN },
338 
339 	{ "ADD-PARTY.request", UNIAPI_ADD_PARTY_request,
340 	    sizeof(struct uniapi_add_party_request),
341 	    SIGO_ADD_PARTY_request, UNIU | UNIN },
342 	{ "ADD-PARTY-ACK.request", UNIAPI_ADD_PARTY_ACK_request,
343 	    sizeof(struct uniapi_add_party_ack_request),
344 	    SIGO_ADD_PARTY_ACK_request, UNIU | UNIN },
345 	{ "ADD-PARTY-REJ.request", UNIAPI_ADD_PARTY_REJ_request,
346 	    sizeof(struct uniapi_add_party_rej_request),
347 	    SIGO_ADD_PARTY_REJ_request, UNIU | UNIN },
348 	{ "PARTY-ALERTING.request", UNIAPI_PARTY_ALERTING_request,
349 	    sizeof(struct uniapi_party_alerting_request),
350 	    SIGO_PARTY_ALERTING_request, UNIU | UNIN },
351 	{ "DROP-PARTY.request", UNIAPI_DROP_PARTY_request,
352 	    sizeof(struct uniapi_drop_party_request),
353 	    SIGO_DROP_PARTY_request, UNIU | UNIN },
354 	{ "DROP-PARTY-ACK.request", UNIAPI_DROP_PARTY_ACK_request,
355 	    sizeof(struct uniapi_drop_party_ack_request),
356 	    SIGO_DROP_PARTY_ACK_request, UNIU | UNIN },
357 
358 	{ "ABORT-CALL.request", UNIAPI_ABORT_CALL_request,
359 	    sizeof(struct uniapi_abort_call_request),
360 	    SIGO_ABORT_CALL_request, UNIU | UNIN },
361 
362 	{ NULL, 0, 0, 0, 0 }
363 };
364 
365 void
uni_uni_input(struct uni * uni,enum uni_sig sig,uint32_t cookie,struct uni_msg * m)366 uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie,
367     struct uni_msg *m)
368 {
369 	u_int i;
370 
371 	for (i = 0; maptab[i].name != NULL; i++) {
372 		if (maptab[i].sig == sig) {
373 			if (uni->proto == UNIPROTO_UNI40U) {
374 				if (!(maptab[i].proto & UNIU))
375 					uniapi_uni_error(uni,
376 					    UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
377 			} else if(uni->proto == UNIPROTO_UNI40N) {
378 				if (!(maptab[i].proto & UNIN))
379 					uniapi_uni_error(uni,
380 					    UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
381 			} else if(uni->proto == UNIPROTO_PNNI10) {
382 				if (!(maptab[i].proto & PNNI))
383 					uniapi_uni_error(uni,
384 					    UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
385 			} else {
386 				uniapi_uni_error(uni,
387 				    UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
388 			}
389 			if (uni_msg_len(m) != maptab[i].arglen) {
390 				VERBOSE(uni, UNI_FAC_ERR, 1, "bogus data in %s"
391 				    " (expecting %zu, got %zu)", maptab[i].name,
392 				    maptab[i].arglen, uni_msg_len(m));
393 				uni_msg_destroy(m);
394 				uniapi_uni_error(uni, UNIAPI_ERROR_BAD_ARG,
395 				    cookie, 0);
396 				return;
397 			}
398 			if (maptab[i].arglen == 0) {
399 				uni_msg_destroy(m);
400 				m = NULL;
401 			}
402 			VERBOSE(uni, UNI_FAC_API, 1, "got signal %s - "
403 			    "delivering to Coord", maptab[i].name);
404 			uni_enq_coord(uni, maptab[i].coord_sig, cookie, m);
405 			return;
406 		}
407 	}
408 	VERBOSE(uni, UNI_FAC_ERR, 1, "bogus uni signal %u", sig);
409 	uni_msg_destroy(m);
410 	uniapi_uni_error(uni, UNIAPI_ERROR_BAD_SIGNAL, cookie, 0);
411 }
412 #undef UNIU
413 #undef UNIN
414 #undef PNNI
415 
416 /**************************************************************/
417 
418 void
uni_work(struct uni * uni)419 uni_work(struct uni *uni)
420 {
421 	struct sig *s;
422 
423 	if (uni->working)
424 		return;
425 	uni->working = 1;
426 
427 	while ((s = TAILQ_FIRST(&uni->workq)) != NULL) {
428 		TAILQ_REMOVE(&uni->workq, s, link);
429 		switch (s->type) {
430 
431 		  case SIG_COORD:
432 			uni_sig_coord(uni, s->sig, s->cookie, s->msg);
433 			break;
434 
435 		  case SIG_RESET_START:
436 			uni_sig_start(uni, s->sig, s->cookie, s->msg, s->u);
437 			break;
438 
439 		  case SIG_RESET_RESP:
440 			uni_sig_respond(uni, s->sig, s->cookie, s->msg, s->u);
441 			break;
442 
443 		  case SIG_CALL:
444 			uni_sig_call(s->call, s->sig, s->cookie, s->msg, s->u);
445 			break;
446 
447 		  case SIG_PARTY:
448 			uni_sig_party(s->party, s->sig, s->cookie, s->msg, s->u);
449 			break;
450 
451 		  default:
452 			ASSERT(0, ("bad signal type"));
453 		}
454 		SIG_FREE(s);
455 	}
456 
457 	uni->working = 0;
458 }
459 
460 /*
461  * Enqueue a signal in the working queue
462  */
463 void
uni_enq_sig(struct uni * uni,u_int type,struct call * call,struct party * party,uint32_t sig,uint32_t cookie,struct uni_msg * msg,struct uni_all * u)464 uni_enq_sig(struct uni *uni, u_int type, struct call *call,
465     struct party *party, uint32_t sig, uint32_t cookie,
466     struct uni_msg *msg, struct uni_all *u)
467 {
468 	struct sig *s;
469 
470 	if ((s = SIG_ALLOC()) != NULL) {
471 		s->type = type;
472 		s->sig = sig;
473 		s->cookie = cookie;
474 		s->msg = msg;
475 		s->call = call;
476 		s->party = party;
477 		s->u = u;
478 		TAILQ_INSERT_TAIL(&uni->workq, s, link);
479 	}
480 }
481 
482 /*
483  * Enqueue a signal in the delayed queue
484  */
485 void
uni_delenq_sig(struct uni * uni,u_int type,struct call * call,struct party * party,uint32_t sig,uint32_t cookie,struct uni_msg * msg,struct uni_all * u)486 uni_delenq_sig(struct uni *uni, u_int type, struct call *call,
487     struct party *party, uint32_t sig, uint32_t cookie,
488     struct uni_msg *msg, struct uni_all *u)
489 {
490 	struct sig *s;
491 
492 	if ((s = SIG_ALLOC()) != NULL) {
493 		s->type = type;
494 		s->sig = sig;
495 		s->cookie = cookie;
496 		s->msg = msg;
497 		s->call = call;
498 		s->party = party;
499 		s->u = u;
500 		TAILQ_INSERT_TAIL(&uni->delq, s, link);
501 	}
502 }
503 
504 /**************************************************************/
505 
506 void
uniapi_uni_error(struct uni * uni,uint32_t reason,uint32_t cookie,uint32_t state)507 uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie,
508     uint32_t state)
509 {
510 	struct uni_msg *resp;
511 	struct uniapi_error *err;
512 
513 	if (cookie == 0)
514 		return;
515 
516 	resp = uni_msg_alloc(sizeof(struct uniapi_error));
517 	err = uni_msg_wptr(resp, struct uniapi_error *);
518 	resp->b_wptr += sizeof(struct uniapi_error);
519 
520 	err->reason = reason;
521 	err->state = state;
522 
523 	uni->funcs->uni_output(uni, uni->arg, UNIAPI_ERROR, cookie, resp);
524 }
525 
526 void
uniapi_call_error(struct call * c,uint32_t reason,uint32_t cookie)527 uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie)
528 {
529 	uniapi_uni_error(c->uni, reason, cookie, callstates[c->cstate].ext);
530 }
531 void
uniapi_party_error(struct party * p,uint32_t reason,uint32_t cookie)532 uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie)
533 {
534 	uniapi_uni_error(p->call->uni, reason, cookie,
535 	    callstates[p->call->cstate].ext);
536 }
537 
538 /**************************************************************/
539 void
uni_status(struct uni * uni,void * arg)540 uni_status(struct uni *uni, void *arg)
541 {
542 	uni->funcs->status(uni, uni->arg, arg,
543 	    "working: %s\n", uni->working ? "yes" : "no");
544 	uni->funcs->status(uni, uni->arg, arg,
545 	    "work queue: %sempty\n", TAILQ_EMPTY(&uni->workq)? "" : "not ");
546 	uni->funcs->status(uni, uni->arg, arg,
547 	    "delayed work queue: %sempty\n",
548 	    TAILQ_EMPTY(&uni->delq)? "" : "not ");
549 	uni->funcs->status(uni, uni->arg, arg,
550 	    "coordinator: %s\n", custat_names[uni->custat]);
551 	uni->funcs->status(uni, uni->arg, arg,
552 	    "reset-start: %s\n", globstat_names[uni->glob_start]);
553 	uni->funcs->status(uni, uni->arg, arg,
554 	    "reset-respond: %s\n", globstat_names[uni->glob_respond]);
555 }
556 
557 void
uni_undel(struct uni * uni,int (* filter)(struct sig *,void *),void * arg)558 uni_undel(struct uni *uni, int (*filter)(struct sig *, void *), void *arg)
559 {
560 	struct sigqueue		newq;
561 	struct sig *s, *s1;
562 
563 	if (TAILQ_EMPTY(&uni->delq))
564 		return;
565 
566 	TAILQ_INIT(&newq);
567 
568 	s = TAILQ_FIRST(&uni->delq);
569 	while (s != NULL) {
570 		s1 = TAILQ_NEXT(s, link);
571 		if ((*filter)(s, arg)) {
572 			TAILQ_REMOVE(&uni->delq, s, link);
573 			TAILQ_INSERT_TAIL(&uni->workq, s, link);
574 		}
575 		s = s1;
576 	}
577 }
578 
579 void
uni_delsig(struct uni * uni,u_int type,struct call * c,struct party * p)580 uni_delsig(struct uni *uni, u_int type, struct call *c, struct party *p)
581 {
582 	struct sig *s, *s1;
583 
584 	s = TAILQ_FIRST(&uni->workq);
585 	while (s != NULL) {
586 		s1 = TAILQ_NEXT(s, link);
587 		if ((type == SIG_CALL && s->type == SIG_CALL &&
588 		    s->call == c) ||
589 		    (type == SIG_PARTY && s->type == SIG_PARTY &&
590 		    s->call == c && s->party == p)) {
591 			TAILQ_REMOVE(&uni->workq, s, link);
592 			if (s->msg)
593 				uni_msg_destroy(s->msg);
594 			if (s->u)
595 				UNI_FREE(s->u);
596 			SIG_FREE(s);
597 		}
598 		s = s1;
599 	}
600 
601 	s = TAILQ_FIRST(&uni->delq);
602 	while (s != NULL) {
603 		s1 = TAILQ_NEXT(s, link);
604 		if ((type == SIG_CALL && s->type == SIG_CALL &&
605 		    s->call == c) ||
606 		    (type == SIG_PARTY && s->type == SIG_PARTY &&
607 		    s->call == c && s->party == p)) {
608 			TAILQ_REMOVE(&uni->delq, s, link);
609 			if (s->msg)
610 				uni_msg_destroy(s->msg);
611 			if (s->u)
612 				UNI_FREE(s->u);
613 			SIG_FREE(s);						\
614 		}
615 		s = s1;
616 	}
617 }
618 
619 /**************************************************************/
620 
621 void
uni_get_config(const struct uni * uni,struct uni_config * config)622 uni_get_config(const struct uni *uni, struct uni_config *config)
623 {
624 	config->proto = uni->proto;
625 
626 	config->popt = 0;
627 	if (uni->cx.q2932)
628 		config->popt |= UNIPROTO_GFP;
629 
630 	config->option = 0;
631 	if (uni->cx.git_hard)
632 		config->option |= UNIOPT_GIT_HARD;
633 	if (uni->cx.bearer_hard)
634 		config->option |= UNIOPT_BEARER_HARD;
635 	if (uni->cx.cause_hard)
636 		config->option |= UNIOPT_CAUSE_HARD;
637 	if (uni->sb_tb)
638 		config->popt |= UNIPROTO_SB_TB;
639 
640 	config->timer301 = uni->timer301;
641 	config->timer303 = uni->timer303;
642 	config->init303 = uni->init303;
643 	config->timer308 = uni->timer308;
644 	config->init308 = uni->init308;
645 	config->timer309 = uni->timer309;
646 	config->timer310 = uni->timer310;
647 	config->timer313 = uni->timer313;
648 	config->timer316 = uni->timer316;
649 	config->init316 = uni->init316;
650 	config->timer317 = uni->timer317;
651 	config->timer322 = uni->timer322;
652 	config->init322 = uni->init322;
653 	config->timer397 = uni->timer397;
654 	config->timer398 = uni->timer398;
655 	config->timer399 = uni->timer399;
656 }
657 
658 void
uni_set_config(struct uni * uni,const struct uni_config * config,uint32_t * mask,uint32_t * popt_mask,uint32_t * opt_mask)659 uni_set_config(struct uni *uni, const struct uni_config *config,
660     uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask)
661 {
662 	int idle;
663 
664 	idle = TAILQ_EMPTY(&uni->calls) &&
665 	    TAILQ_EMPTY(&uni->workq) &&
666 	    TAILQ_EMPTY(&uni->delq);
667 
668 	if ((*mask & UNICFG_PROTO) && idle) {
669 		switch (config->proto) {
670 
671 		  case UNIPROTO_UNI40U:
672 		  case UNIPROTO_UNI40N:
673 		  /* case UNIPROTO_PNNI10: XXX */
674 			uni->proto = config->proto;
675 			*mask &= ~UNICFG_PROTO;
676 			break;
677 		}
678 	}
679 	if (*popt_mask & UNIPROTO_GFP) {
680 		if (config->popt & UNIPROTO_GFP) {
681 			uni->cx.q2932 = 1;
682 			*popt_mask &= ~UNIPROTO_GFP;
683 		} else {
684 			if (!uni->cx.q2932 || idle) {
685 				uni->cx.q2932 = 0;
686 				*popt_mask &= ~UNIPROTO_GFP;
687 			}
688 		}
689 	}
690 	if (*popt_mask & UNIPROTO_SB_TB) {
691 		uni->sb_tb = ((config->popt & UNIPROTO_SB_TB) != 0);
692 		*popt_mask &= ~UNIPROTO_SB_TB;
693 	}
694 	if (*opt_mask & UNIOPT_GIT_HARD) {
695 		uni->cx.git_hard = ((config->option & UNIOPT_GIT_HARD) != 0);
696 		*opt_mask &= ~UNIOPT_GIT_HARD;
697 	}
698 	if (*opt_mask & UNIOPT_BEARER_HARD) {
699 		uni->cx.bearer_hard = ((config->option & UNIOPT_BEARER_HARD) != 0);
700 		*opt_mask &= ~UNIOPT_BEARER_HARD;
701 	}
702 	if (*opt_mask & UNIOPT_CAUSE_HARD) {
703 		uni->cx.cause_hard = ((config->option & UNIOPT_CAUSE_HARD) != 0);
704 		*opt_mask &= ~UNIOPT_CAUSE_HARD;
705 	}
706 
707 #define SET_TIMER(NAME,name)						\
708 	if (*mask & UNICFG_##NAME) {					\
709 		uni->name = config->name;				\
710 		*mask &= ~UNICFG_##NAME;				\
711 	}
712 
713 	SET_TIMER(TIMER301, timer301);
714 	SET_TIMER(TIMER303, timer303);
715 	SET_TIMER(INIT303,  init303);
716 	SET_TIMER(TIMER308, timer308);
717 	SET_TIMER(INIT308,  init308);
718 	SET_TIMER(TIMER309, timer309);
719 	SET_TIMER(TIMER310, timer310);
720 	SET_TIMER(TIMER313, timer313);
721 	SET_TIMER(TIMER316, timer316);
722 	SET_TIMER(INIT316,  init316);
723 	SET_TIMER(TIMER317, timer317);
724 	SET_TIMER(TIMER322, timer322);
725 	SET_TIMER(INIT322,  init322);
726 	SET_TIMER(TIMER397, timer397);
727 	SET_TIMER(TIMER398, timer398);
728 	SET_TIMER(TIMER399, timer399);
729 
730 #undef SET_TIMER
731 }
732 
733 void
uni_set_debug(struct uni * uni,enum uni_verb fac,u_int level)734 uni_set_debug(struct uni *uni, enum uni_verb fac, u_int level)
735 {
736 	uni->debug[fac] = level;
737 }
738 
739 u_int
uni_get_debug(const struct uni * uni,enum uni_verb fac)740 uni_get_debug(const struct uni *uni, enum uni_verb fac)
741 {
742 	return (uni->debug[fac]);
743 }
744 
745 u_int
uni_getcustate(const struct uni * uni)746 uni_getcustate(const struct uni *uni)
747 {
748 	return (uni->custat);
749 }
750