1122205Sharti/*
2122205Sharti * Copyright (c) 1996-2003
3122205Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4122205Sharti * 	All rights reserved.
5122205Sharti *
6122205Sharti * Redistribution and use in source and binary forms, with or without
7122205Sharti * modification, are permitted provided that the following conditions
8122205Sharti * are met:
9122205Sharti * 1. Redistributions of source code must retain the above copyright
10122205Sharti *    notice, this list of conditions and the following disclaimer.
11122205Sharti * 2. Redistributions in binary form must reproduce the above copyright
12122205Sharti *    notice, this list of conditions and the following disclaimer in the
13122205Sharti *    documentation and/or other materials provided with the distribution.
14122205Sharti *
15122205Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16122205Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17122205Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18122205Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19122205Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20122205Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21122205Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22122205Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23122205Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24122205Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25122205Sharti * SUCH DAMAGE.
26122205Sharti *
27122205Sharti * Author: Hartmut Brandt <harti@freebsd.org>
28122205Sharti *
29133492Sharti * $Begemot: libunimsg/netnatm/sig/sig_coord.c,v 1.12 2004/08/05 07:11:01 brandt Exp $
30122205Sharti *
31122205Sharti * Coordinator
32122205Sharti */
33122205Sharti
34122205Sharti#include <netnatm/unimsg.h>
35122205Sharti#include <netnatm/saal/sscfudef.h>
36122205Sharti#include <netnatm/msg/unistruct.h>
37122205Sharti#include <netnatm/msg/unimsglib.h>
38122205Sharti#include <netnatm/sig/uni.h>
39122205Sharti
40122205Sharti#include <netnatm/sig/unipriv.h>
41122205Sharti#include <netnatm/sig/unimkmsg.h>
42122205Sharti
43133492Sharti#define STR(S) [S] = #S
44122205Shartistatic const char *const cunames[] = {
45122205Sharti	STR(CU_STAT0),
46122205Sharti	STR(CU_STAT1),
47122205Sharti	STR(CU_STAT2),
48122205Sharti	STR(CU_STAT3),
49122205Sharti};
50122205Sharti
51133492Sharti#define DEF_PRIV_SIG(NAME, FROM)	[SIG##NAME] =	"SIG"#NAME,
52122205Shartistatic const char *const coord_sigs[] = {
53122205Sharti	DEF_COORD_SIGS
54122205Sharti};
55122205Sharti#undef DEF_PRIV_SIG
56122205Sharti
57122205Shartistatic void sig_all_calls(struct uni *, u_int sig);
58122205Shartistatic void set_custat(struct uni *, enum cu_stat);
59122205Sharti
60122205Shartistatic void input_dummy(struct uni *uni, struct uni_msg *m, struct uni_all *u);
61122205Shartistatic void input_global(struct uni *uni, struct uni_msg *m, struct uni_all *u);
62122205Shartistatic void input_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u);
63122205Shartistatic void input_cobi(struct call *c, struct uni_msg *m, struct uni_all *u);
64122205Shartistatic void input_call(struct call *c, struct uni_msg *m, struct uni_all *u);
65122205Sharti
66122205ShartiTIMER_FUNC_UNI(t309, t309_func)
67122205Sharti
68122205Sharti/*
69122205Sharti * All those 'bogus signal' printouts are not specified in the SDLs.
70122205Sharti */
71122205Sharti
72122205Sharti
73122205Sharti/*
74122205Sharti * SAAL-ESTABLISH.indication
75122205Sharti *
76122205Sharti * This means either a resynchronisation or error-recovery or
77122205Sharti * an incoming SSCOP connection.
78122205Sharti */
79122205Shartistatic void
80122205Sharticoord_saal_establish_indication(struct uni *uni)
81122205Sharti{
82122205Sharti	switch (uni->custat) {
83122205Sharti
84122205Sharti	  case CU_STAT0:	/* Q.2931:Coord-U 4/10 */
85122205Sharti	  case CU_STAT3:	/* Q.2931:Coord-U 5/10 */
86122205Sharti		sig_all_calls(uni, SIGC_LINK_ESTABLISH_indication);
87122205Sharti		set_custat(uni, CU_STAT3);
88122205Sharti		break;
89122205Sharti
90122205Sharti	  case CU_STAT1:
91122205Sharti	  case CU_STAT2:
92122205Sharti		VERBOSE0(uni, UNI_FAC_COORD,
93122205Sharti		    "signal saal_establish.indication in CU%u", uni->custat);
94122205Sharti		break;
95122205Sharti
96122205Sharti	  default:
97122205Sharti		ASSERT(0, ("CU_STAT*"));
98122205Sharti	}
99122205Sharti}
100122205Sharti
101122205Sharti/*
102122205Sharti * SAAL-ESTABLISH.confirm
103122205Sharti */
104122205Shartistatic void
105122205Sharticoord_saal_establish_confirm(struct uni *uni)
106122205Sharti{
107122205Sharti	switch (uni->custat) {
108122205Sharti
109122205Sharti	  case CU_STAT0:
110122205Sharti	  case CU_STAT2:
111122205Sharti		VERBOSE0(uni, UNI_FAC_COORD,
112122205Sharti		    "signal saal_establish.confirm in CU%u", uni->custat);
113122205Sharti		break;
114122205Sharti
115122205Sharti	  case CU_STAT1:
116122205Sharti		/*
117122205Sharti		 * Q.2931:Co-ord-U 4/10
118122205Sharti		 */
119122205Sharti		TIMER_STOP_UNI(uni, t309);
120122205Sharti		sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
121122205Sharti		uni->funcs->uni_output(uni, uni->arg,
122122205Sharti		    UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
123122205Sharti		set_custat(uni, CU_STAT3);
124122205Sharti		break;
125122205Sharti
126122205Sharti	  case CU_STAT3:
127122205Sharti		/*
128122205Sharti		 * Q.2931:Coord-U 5/10
129122205Sharti		 */
130122205Sharti		sig_all_calls(uni, SIGC_LINK_ESTABLISH_confirm);
131122205Sharti		uni->funcs->uni_output(uni, uni->arg,
132122205Sharti		    UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
133122205Sharti		break;
134122205Sharti
135122205Sharti	  default:
136122205Sharti		ASSERT(0, ("CU_STAT*"));
137122205Sharti	}
138122205Sharti}
139122205Sharti
140122205Sharti/*
141122205Sharti * SAAL-RELEASE.confirm
142122205Sharti */
143122205Shartistatic void
144122205Sharticoord_saal_release_confirm(struct uni *uni)
145122205Sharti{
146122205Sharti	switch (uni->custat) {
147122205Sharti
148122205Sharti	  case CU_STAT0:
149122205Sharti	  case CU_STAT1:
150122205Sharti	  case CU_STAT3:
151122205Sharti		VERBOSE0(uni, UNI_FAC_COORD,
152122205Sharti		    "signal saal_release.confirm in CU%u", uni->custat);
153122205Sharti		break;
154122205Sharti
155122205Sharti	  case CU_STAT2:
156122205Sharti		/*
157122205Sharti		 * Q.2931:Coord-U 5/10
158122205Sharti		 */
159122205Sharti		uni->funcs->uni_output(uni, uni->arg,
160122205Sharti		    UNIAPI_LINK_RELEASE_confirm, 0, NULL);
161122205Sharti		set_custat(uni, CU_STAT0);
162122205Sharti		break;
163122205Sharti
164122205Sharti	  default:
165122205Sharti		ASSERT(0, ("CU_STAT*"));
166122205Sharti	}
167122205Sharti}
168122205Sharti
169122205Sharti/*
170122205Sharti * SAAL failure.
171122205Sharti */
172122205Shartistatic void
173122205Sharticoord_saal_release_indication(struct uni *uni)
174122205Sharti{
175122205Sharti	switch (uni->custat) {
176122205Sharti
177122205Sharti	  case CU_STAT0:
178122205Sharti	  case CU_STAT2:
179122205Sharti		VERBOSE0(uni, UNI_FAC_COORD,
180122205Sharti		    "signal saal_release.indication in CU%u", uni->custat);
181122205Sharti		break;
182122205Sharti
183122205Sharti	  case CU_STAT1:
184122205Sharti	  case CU_STAT3:
185122205Sharti		/*
186122205Sharti		 * Q.2931:Coord-U 4/10
187122205Sharti		 * Q.2931:Coord-U 5/10
188122205Sharti		 */
189122205Sharti		sig_all_calls(uni, SIGC_LINK_RELEASE_indication);
190122205Sharti		set_custat(uni, CU_STAT0);
191122205Sharti		break;
192122205Sharti
193122205Sharti	  default:
194122205Sharti		ASSERT(0, ("CU_STAT*"));
195122205Sharti	}
196122205Sharti}
197122205Sharti
198122205Sharti/*
199122205Sharti * Link-establish.request from USER. This can also come from
200122205Sharti * a call instance. In this case 'cookie' is zero.
201122205Sharti */
202122205Shartistatic void
203131826Sharticoord_link_establish_request(struct uni *uni, uint32_t cookie)
204122205Sharti{
205122205Sharti	switch (uni->custat) {
206122205Sharti
207122205Sharti	  case CU_STAT0:
208122205Sharti		/*
209122205Sharti		 * Q.2931:Coord-U 4/10
210122205Sharti		 */
211122205Sharti		uni->funcs->saal_output(uni, uni->arg,
212122205Sharti		    SAAL_ESTABLISH_request, NULL);
213122205Sharti		if (!TIMER_ISACT(uni, t309))
214122205Sharti			TIMER_START_UNI(uni, t309, uni->timer309);
215122205Sharti		set_custat(uni, CU_STAT1);
216122205Sharti		if (cookie)
217122205Sharti			uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
218122205Sharti		break;
219122205Sharti
220122205Sharti	  case CU_STAT1:
221122205Sharti		/*
222122205Sharti		 * Q.2931:Coord-U 4/10
223122205Sharti		 * This is probably missing from the delay field.
224122205Sharti		 */
225122205Sharti		uni_delenq_coord(uni, SIGO_LINK_ESTABLISH_request,
226122205Sharti		    cookie, NULL);
227122205Sharti		break;
228122205Sharti
229122205Sharti	  case CU_STAT2:
230122205Sharti		uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
231122205Sharti		if (cookie == 0)
232122205Sharti			VERBOSE0(uni, UNI_FAC_COORD,
233122205Sharti			    "signal link-establish.request in CU%u",
234122205Sharti			    uni->custat);
235122205Sharti		break;
236122205Sharti
237122205Sharti	  case CU_STAT3:
238122205Sharti		/*
239122205Sharti		 * Q.2931:Coord-U 5/10
240122205Sharti		 */
241122205Sharti		uni->funcs->uni_output(uni, uni->arg,
242122205Sharti		    UNIAPI_LINK_ESTABLISH_confirm, 0, NULL);
243122205Sharti		uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
244122205Sharti		break;
245122205Sharti
246122205Sharti	  default:
247122205Sharti		ASSERT(0, ("CU_STAT*"));
248122205Sharti	}
249122205Sharti}
250122205Sharti
251122205Sharti/*
252122205Sharti * Link-release.request from user
253122205Sharti */
254122205Shartistatic void
255122205Sharticoord_link_release_request(struct uni *uni, u_int cookie)
256122205Sharti{
257122205Sharti	switch (uni->custat) {
258122205Sharti
259122205Sharti	  case CU_STAT0:
260122205Sharti	  case CU_STAT1:
261122205Sharti	  case CU_STAT2:
262122205Sharti		uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
263122205Sharti		break;
264122205Sharti
265122205Sharti	  case CU_STAT3:
266122205Sharti		/*
267122205Sharti		 * Q.2931:Coord-U 5/10
268122205Sharti		 */
269122205Sharti		uni->funcs->saal_output(uni, uni->arg,
270122205Sharti		    SAAL_RELEASE_request, NULL);
271122205Sharti		set_custat(uni, CU_STAT2);
272122205Sharti		uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
273122205Sharti		break;
274122205Sharti
275122205Sharti	  default:
276122205Sharti		ASSERT(0, ("CU_STAT*"));
277122205Sharti	}
278122205Sharti}
279122205Sharti
280122205Sharti/*
281122205Sharti * T309 timeout signal
282122205Sharti */
283122205Shartistatic void
284122205Sharticoord_t309(struct uni *uni)
285122205Sharti{
286122205Sharti	switch (uni->custat) {
287122205Sharti
288122205Sharti	  case CU_STAT0:
289122205Sharti	  case CU_STAT1:
290122205Sharti		/*
291122205Sharti		 * Q.2931:Coord-U 4/10
292122205Sharti		 */
293122205Sharti		sig_all_calls(uni, SIGC_LINK_ESTABLISH_ERROR_indication);
294122205Sharti		set_custat(uni, CU_STAT0);
295122205Sharti		/* this is not in the SDLs, but how will the call control
296122205Sharti		 * know, that starting the LINK has failed otherwise? */
297122205Sharti		uni->funcs->uni_output(uni, uni->arg,
298122205Sharti		    UNIAPI_LINK_RELEASE_confirm, 0, NULL);
299122205Sharti		break;
300122205Sharti
301122205Sharti	  case CU_STAT2:
302122205Sharti	  case CU_STAT3:
303122205Sharti		VERBOSE0(uni, UNI_FAC_COORD,
304122205Sharti		    "signal T309 in CU%u", uni->custat);
305122205Sharti		break;
306122205Sharti
307122205Sharti	  default:
308122205Sharti		ASSERT(0, ("CU_STAT*"));
309122205Sharti	}
310122205Sharti}
311122205Sharti
312122205Sharti/*
313122205Sharti * Message from SAAL
314122205Sharti */
315122205Shartistatic void
316122205Sharticoord_saal_data_indication(struct uni *uni, struct uni_msg *m)
317122205Sharti{
318122205Sharti	struct uni_all *u;
319122205Sharti	struct call *c;
320122205Sharti
321122205Sharti	memset(&uni->cause, 0, sizeof(uni->cause));
322122205Sharti	if ((u = UNI_ALLOC()) == NULL) {
323122205Sharti		uni_msg_destroy(m);
324122205Sharti		return;
325122205Sharti	}
326122205Sharti	if (uni_decode_head(m, u, &uni->cx)) {
327122205Sharti		VERBOSE(uni, UNI_FAC_COORD, 2, "bogus message - ignored");
328122205Sharti		uni_msg_destroy(m);
329122205Sharti		UNI_FREE(u);
330122205Sharti		return;
331122205Sharti	}
332122205Sharti	if (u->u.hdr.cref.cref == CREF_DUMMY) {
333122205Sharti		if (uni->cx.q2932) {
334122205Sharti			input_dummy(uni, m, u);
335122205Sharti		} else {
336122205Sharti			VERBOSE(uni, UNI_FAC_COORD, 2, "dummy cref - ignored");
337122205Sharti			UNI_FREE(u);
338122205Sharti			uni_msg_destroy(m);
339122205Sharti		}
340122205Sharti		return;
341122205Sharti	}
342122205Sharti
343122205Sharti	if (u->u.hdr.cref.cref == CREF_GLOBAL)
344122205Sharti		input_global(uni, m, u);
345122205Sharti	else if ((c = uni_find_call(uni, &u->u.hdr.cref)) == NULL)
346122205Sharti		input_unknown(uni, m, u);
347122205Sharti	else if (c->type == CALL_COBI)
348122205Sharti		input_cobi(c, m, u);
349122205Sharti	else
350122205Sharti		input_call(c, m, u);
351122205Sharti}
352122205Sharti
353122205Sharti/*
354122205Sharti * Message with global call reference
355122205Sharti *
356122205Sharti * Q.2931:Coord-U (X) 7/10
357122205Sharti */
358122205Shartistatic void
359122205Shartiinput_global(struct uni *uni, struct uni_msg *m, struct uni_all *u)
360122205Sharti{
361122205Sharti	VERBOSE(uni, UNI_FAC_COORD, 2, "GLOB MTYPE = %x", u->mtype);
362122205Sharti
363122205Sharti	switch (u->mtype) {
364122205Sharti
365122205Sharti	  default:
366122205Sharti		/*
367122205Sharti		 * Q.2931:Coord-U 7/10
368122205Sharti		 * Q.2931: 5.6.3.2e
369122205Sharti		 * Amd4:   29e
370122205Sharti		 */
371122205Sharti		uni_respond_status(uni, &u->u.hdr.cref,
372122205Sharti		    u->u.hdr.cref.flag ? uni->glob_start : uni->glob_respond,
373122205Sharti		    UNI_CAUSE_CREF_INV);
374122205Sharti		break;
375122205Sharti
376122205Sharti	  case UNI_RESTART:
377122205Sharti		if (u->u.hdr.cref.flag) {
378122205Sharti			/*
379122205Sharti			 * Q.2931:Coord-U 7/10 (5.6.3.2h)
380122205Sharti			 */
381122205Sharti			uni_respond_status(uni, &u->u.hdr.cref,
382122205Sharti			    uni->glob_start, UNI_CAUSE_CREF_INV);
383122205Sharti			break;
384122205Sharti		}
385122205Sharti		uni_enq_resp(uni, SIGR_RESTART, 0, m, u);
386122205Sharti		return;
387122205Sharti
388122205Sharti	  case UNI_RESTART_ACK:
389122205Sharti		if (!u->u.hdr.cref.flag) {
390122205Sharti			/*
391122205Sharti			 * Q.2931:Coord-U 7/10 (5.6.3.2h)
392122205Sharti			 * Note, that the SDL diagram contains an error.
393122205Sharti			 * The error with the 'YES' label should go to the
394122205Sharti			 * box below 'OTHER'.
395122205Sharti			 */
396122205Sharti			uni_respond_status(uni, &u->u.hdr.cref,
397122205Sharti			    uni->glob_respond, UNI_CAUSE_CREF_INV);
398122205Sharti			break;
399122205Sharti		}
400122205Sharti		uni_enq_start(uni, SIGS_RESTART_ACK, 0, m, u);
401122205Sharti		return;
402122205Sharti
403122205Sharti	  case UNI_STATUS:
404122205Sharti		if (u->u.hdr.cref.flag)
405122205Sharti			uni_enq_start(uni, SIGS_STATUS, 0, m, u);
406122205Sharti		else
407122205Sharti			uni_enq_resp(uni, SIGR_STATUS, 0, m, u);
408122205Sharti		return;
409122205Sharti	}
410122205Sharti	uni_msg_destroy(m);
411122205Sharti	UNI_FREE(u);
412122205Sharti}
413122205Sharti
414122205Sharti/*
415122205Sharti * Q.2931:Coord-U 8/10
416122205Sharti *
417122205Sharti * Message for an unknown call reference
418122205Sharti */
419122205Shartistatic void
420122205Shartiinput_unknown(struct uni *uni, struct uni_msg *m, struct uni_all *u)
421122205Sharti{
422122205Sharti	struct uni_all *resp;
423122205Sharti	struct call *c;
424122205Sharti	u_int cause = UNI_CAUSE_CREF_INV;
425122205Sharti
426122205Sharti	VERBOSE(uni, UNI_FAC_COORD, 2, "UNKNOWN MTYPE = %x", u->mtype);
427122205Sharti
428122205Sharti	switch (u->mtype) {
429122205Sharti
430122205Sharti	  default:
431122205Sharti		/*
432122205Sharti		 * This message type is entirly unknown
433122205Sharti		 *
434122205Sharti		 * 5.6.4 and 5.7.1 are only when the call is not in the
435122205Sharti		 * NULL state. This means, 5.6.3.2a takes over.
436122205Sharti		 */
437122205Sharti		break;
438122205Sharti
439122205Sharti	  case UNI_SETUP:
440122205Sharti		if (u->u.hdr.cref.flag)
441122205Sharti			/*
442122205Sharti			 * 5.6.3.2c
443122205Sharti			 */
444122205Sharti			goto drop;
445122205Sharti		if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
446122205Sharti			uni_enq_call(c, SIGC_SETUP, 0, m, u);
447122205Sharti			return;
448122205Sharti		}
449122205Sharti		goto drop;
450122205Sharti
451122205Sharti	  case UNI_RELEASE_COMPL:
452122205Sharti		/*
453122205Sharti		 * 5.6.3.2c
454122205Sharti		 */
455122205Sharti		goto drop;
456122205Sharti
457122205Sharti	  case UNI_STATUS:
458122205Sharti		/*
459122205Sharti		 * 5.6.12
460122205Sharti		 *
461122205Sharti		 * The SDLs don't use the verify procedure and don't
462122205Sharti		 * handle the case of an invalid callstate - we
463122205Sharti		 * ignore the message, if the callstate is not good.
464122205Sharti		 */
465122205Sharti		(void)uni_decode_body(m, u, &uni->cx);
466122205Sharti		if (!IE_ISGOOD(u->u.status.callstate))
467122205Sharti			goto drop;
468122205Sharti		if (u->u.status.callstate.state == UNI_CALLSTATE_U0)
469122205Sharti			goto drop;
470122205Sharti		cause = UNI_CAUSE_MSG_INCOMP;
471122205Sharti		break;
472122205Sharti
473122205Sharti	  case UNI_STATUS_ENQ:
474122205Sharti		if ((resp = UNI_ALLOC()) == NULL)
475122205Sharti			goto drop;
476122205Sharti
477122205Sharti		(void)uni_decode_body(m, u, &uni->cx);
478122205Sharti		MK_MSG_RESP(resp, UNI_STATUS, &u->u.hdr.cref);
479122205Sharti		MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_U0);
480122205Sharti		MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER,
481122205Sharti		    UNI_CAUSE_STATUS);
482122205Sharti
483122205Sharti		if (IE_ISGOOD(u->u.status_enq.epref)) {
484122205Sharti			/* reflect epref as required by L3MU_PO */
485122205Sharti			resp->u.status.epref = u->u.status_enq.epref;
486122205Sharti			MK_IE_EPREF(resp->u.status.epref,
487122205Sharti			    u->u.status_enq.epref.epref,
488122205Sharti			    !u->u.status_enq.epref.flag);
489122205Sharti			MK_IE_EPSTATE(resp->u.status.epstate, UNI_EPSTATE_NULL);
490122205Sharti		}
491122205Sharti
492122205Sharti		(void)uni_send_output(resp, uni);
493122205Sharti
494122205Sharti		UNI_FREE(resp);
495122205Sharti		goto drop;
496122205Sharti
497122205Sharti	  case UNI_COBISETUP:
498122205Sharti		if (u->u.hdr.cref.flag)
499122205Sharti			/*
500122205Sharti			 * 5.6.3.2c (probably)
501122205Sharti			 */
502122205Sharti			goto drop;
503122205Sharti		if ((c = uni_create_call(uni, u->u.hdr.cref.cref, 0, 0)) != NULL) {
504122205Sharti			uni_enq_call(c, SIGC_COBISETUP, 0, m, u);
505122205Sharti			return;
506122205Sharti		}
507122205Sharti		goto drop;
508122205Sharti	}
509122205Sharti
510122205Sharti	/*
511122205Sharti	 * 5.6.3.2a)
512122205Sharti	 *
513122205Sharti	 * Respond with a RELEASE COMPLETE
514122205Sharti	 */
515122205Sharti	if ((resp = UNI_ALLOC()) == NULL)
516122205Sharti		goto drop;
517122205Sharti
518122205Sharti	MK_MSG_RESP(resp, UNI_RELEASE_COMPL, &u->u.hdr.cref);
519122205Sharti	MK_IE_CAUSE(resp->u.release_compl.cause[0], UNI_CAUSE_LOC_USER, cause);
520122205Sharti	if (uni_diag(cause, UNI_CODING_ITU) == UNI_DIAG_MTYPE)
521122205Sharti		ADD_CAUSE_MTYPE(resp->u.release_compl.cause[0], u->mtype);
522122205Sharti
523122205Sharti	(void)uni_send_output(resp, uni);
524122205Sharti
525122205Sharti	UNI_FREE(resp);
526122205Sharti
527122205Sharti  drop:
528122205Sharti	UNI_FREE(u);
529122205Sharti	uni_msg_destroy(m);
530122205Sharti}
531122205Sharti
532122205Shartistatic void
533122205Shartiinput_cobi(struct call *c __unused, struct uni_msg *m, struct uni_all *u)
534122205Sharti{
535122205Sharti	/* XXX */
536122205Sharti	UNI_FREE(u);
537122205Sharti	uni_msg_destroy(m);
538122205Sharti}
539122205Sharti
540122205Shartistatic void
541122205Shartiinput_dummy(struct uni *uni __unused, struct uni_msg *m, struct uni_all *u)
542122205Sharti{
543122205Sharti	/* XXX */
544122205Sharti	UNI_FREE(u);
545122205Sharti	uni_msg_destroy(m);
546122205Sharti}
547122205Sharti
548122205Shartistatic void
549122205Shartiinput_call(struct call *c, struct uni_msg *m, struct uni_all *u)
550122205Sharti{
551122205Sharti	VERBOSE(c->uni, UNI_FAC_COORD, 2, "CALL MTYPE = %x %d/%s",
552122205Sharti		u->mtype, c->cref, c->mine ? "mine":"his");
553122205Sharti
554122205Sharti	switch (u->mtype) {
555122205Sharti
556122205Sharti	  case UNI_SETUP:
557122205Sharti		/*
558122205Sharti		 * Ignored
559122205Sharti		 */
560122205Sharti		break;
561122205Sharti
562122205Sharti	  case UNI_CALL_PROC:
563122205Sharti		uni_enq_call(c, SIGC_CALL_PROC, 0, m, u);
564122205Sharti		return;
565122205Sharti
566122205Sharti	  case UNI_ALERTING:
567122205Sharti		uni_enq_call(c, SIGC_ALERTING, 0, m, u);
568122205Sharti		return;
569122205Sharti
570122205Sharti	  case UNI_RELEASE:
571122205Sharti		uni_enq_call(c, SIGC_RELEASE, 0, m, u);
572122205Sharti		return;
573122205Sharti
574122205Sharti	  case UNI_RELEASE_COMPL:
575122205Sharti		uni_enq_call(c, SIGC_RELEASE_COMPL, 0, m, u);
576122205Sharti		return;
577122205Sharti
578122205Sharti	  case UNI_CONNECT:
579122205Sharti		uni_enq_call(c, SIGC_CONNECT, 0, m, u);
580122205Sharti		return;
581122205Sharti
582122205Sharti	  case UNI_CONNECT_ACK:
583122205Sharti		uni_enq_call(c, SIGC_CONNECT_ACK, 0, m, u);
584122205Sharti		return;
585122205Sharti
586122205Sharti	  case UNI_NOTIFY:
587122205Sharti		uni_enq_call(c, SIGC_NOTIFY, 0, m, u);
588122205Sharti		return;
589122205Sharti
590122205Sharti	  case UNI_STATUS:
591122205Sharti		uni_enq_call(c, SIGC_STATUS, 0, m, u);
592122205Sharti		return;
593122205Sharti
594122205Sharti	  case UNI_STATUS_ENQ:
595122205Sharti		uni_enq_call(c, SIGC_STATUS_ENQ, 0, m, u);
596122205Sharti		return;
597122205Sharti
598122205Sharti	  case UNI_ADD_PARTY:
599122205Sharti		uni_enq_call(c, SIGC_ADD_PARTY, 0, m, u);
600122205Sharti		return;
601122205Sharti
602122205Sharti	  case UNI_PARTY_ALERTING:
603122205Sharti		uni_enq_call(c, SIGC_PARTY_ALERTING, 0, m, u);
604122205Sharti		return;
605122205Sharti
606122205Sharti	  case UNI_ADD_PARTY_ACK:
607122205Sharti		uni_enq_call(c, SIGC_ADD_PARTY_ACK, 0, m, u);
608122205Sharti		return;
609122205Sharti
610122205Sharti	  case UNI_ADD_PARTY_REJ:
611122205Sharti		uni_enq_call(c, SIGC_ADD_PARTY_REJ, 0, m, u);
612122205Sharti		return;
613122205Sharti
614122205Sharti	  case UNI_DROP_PARTY:
615122205Sharti		uni_enq_call(c, SIGC_DROP_PARTY, 0, m, u);
616122205Sharti		return;
617122205Sharti
618122205Sharti	  case UNI_DROP_PARTY_ACK:
619122205Sharti		uni_enq_call(c, SIGC_DROP_PARTY_ACK, 0, m, u);
620122205Sharti		return;
621122205Sharti
622122205Sharti	  default:
623122205Sharti		uni_enq_call(c, SIGC_UNKNOWN, 0, m, u);
624122205Sharti		return;
625122205Sharti	}
626122205Sharti	UNI_FREE(u);
627122205Sharti	uni_msg_destroy(m);
628122205Sharti}
629122205Sharti
630122205Sharti
631122205Sharti/*
632122205Sharti * This macro tries to implement the delaying behaviour for
633122205Sharti * message from the API when we are in the Awaiting-Establish state.
634122205Sharti * In this state, the message is delayed. If we drop back to CU 0,
635122205Sharti * everything gets unqueued and errors are returned for all that stuff.
636122205Sharti * If we progess to CUSTAT2 we process the requests.
637122205Sharti */
638122205Sharti#define COMMON_DELAY(SIG, COOKIE)					\
639122205Sharti		if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2) {\
640122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BADCU,	\
641122205Sharti			    COOKIE, 0);					\
642122205Sharti			break;						\
643122205Sharti		}							\
644122205Sharti		if (uni->custat == CU_STAT1) {				\
645122205Sharti			uni_delenq_coord(uni, SIG, COOKIE, msg);	\
646122205Sharti			break;						\
647122205Sharti		}
648122205Sharti
649122205Sharti/*
650122205Sharti * Signal handler of the coordinator
651122205Sharti */
652122205Shartivoid
653131826Shartiuni_sig_coord(struct uni *uni, enum coord_sig sig, uint32_t cookie,
654122205Sharti    struct uni_msg *msg)
655122205Sharti{
656122205Sharti	struct call *c;
657122205Sharti
658122205Sharti	if (sig >= SIGO_END) {
659122205Sharti		VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
660122205Sharti		    "Coord", sig);
661122205Sharti		if (msg)
662122205Sharti			uni_msg_destroy(msg);
663122205Sharti		return;
664122205Sharti	}
665122205Sharti
666122205Sharti	VERBOSE(uni, UNI_FAC_COORD, 1, "Signal %s in state %s",
667122205Sharti	    coord_sigs[sig], cunames[uni->custat]);
668122205Sharti
669122205Sharti	switch (sig) {
670122205Sharti
671122205Sharti	  case SIGO_END:
672122205Sharti		break;
673122205Sharti
674122205Sharti	  case SIGO_DATA:	/* delayed output */
675122205Sharti		if (uni->custat == CU_STAT0 || uni->custat == CU_STAT1)
676122205Sharti			break;	/* drop */
677122205Sharti		if (uni->custat == CU_STAT1)
678122205Sharti			uni_delenq_coord(uni, SIGO_DATA, cookie, msg);/* ??? */
679122205Sharti		else
680122205Sharti			uni->funcs->saal_output(uni, uni->arg,
681122205Sharti			    SAAL_DATA_request, msg);
682122205Sharti		msg = NULL;
683122205Sharti		break;
684122205Sharti
685122205Sharti	  /*
686122205Sharti	   * SAAL signals
687122205Sharti	   */
688122205Sharti	  case SIGO_SAAL_ESTABLISH_indication:
689122205Sharti		coord_saal_establish_indication(uni);
690122205Sharti		break;
691122205Sharti
692122205Sharti	  case SIGO_SAAL_ESTABLISH_confirm:
693122205Sharti		coord_saal_establish_confirm(uni);
694122205Sharti		break;
695122205Sharti
696122205Sharti	  case SIGO_SAAL_RELEASE_confirm:
697122205Sharti		coord_saal_release_confirm(uni);
698122205Sharti		break;
699122205Sharti
700122205Sharti	  case SIGO_SAAL_RELEASE_indication:
701122205Sharti		coord_saal_release_indication(uni);
702122205Sharti		break;
703122205Sharti
704122205Sharti	  case SIGO_SAAL_DATA_indication:
705122205Sharti		coord_saal_data_indication(uni, msg);
706122205Sharti		msg = NULL;
707122205Sharti		break;
708122205Sharti
709122205Sharti	  case SIGO_SAAL_UDATA_indication:
710122205Sharti		VERBOSE0(uni, UNI_FAC_ERR, "SAAL_UDATA_indication");
711122205Sharti		break;
712122205Sharti
713122205Sharti	  /*
714122205Sharti	   * Signals from USER
715122205Sharti	   */
716122205Sharti	  case SIGO_LINK_ESTABLISH_request:
717122205Sharti		coord_link_establish_request(uni, cookie);
718122205Sharti		break;
719122205Sharti
720122205Sharti	  case SIGO_LINK_RELEASE_request:
721122205Sharti		coord_link_release_request(uni, cookie);
722122205Sharti		break;
723122205Sharti
724122205Sharti	  case SIGO_RESET_request:
725122205Sharti		uni_enq_start(uni, SIGS_RESET_request, cookie, msg, NULL);
726122205Sharti		msg = NULL;
727122205Sharti		if (uni->custat == CU_STAT0) {
728122205Sharti			uni->funcs->saal_output(uni, uni->arg,
729122205Sharti			    SAAL_ESTABLISH_request, NULL);
730122205Sharti			if (!TIMER_ISACT(uni, t309))
731122205Sharti				TIMER_START_UNI(uni, t309, uni->timer309);
732122205Sharti			set_custat(uni, CU_STAT1);
733122205Sharti		}
734122205Sharti		break;
735122205Sharti
736122205Sharti	  case SIGO_RESET_ERROR_response:
737122205Sharti		COMMON_DELAY(SIGO_RESET_ERROR_response, cookie);
738122205Sharti		uni_enq_resp(uni, SIGR_RESET_ERROR_response, cookie, msg, NULL);
739122205Sharti		msg = NULL;
740122205Sharti		break;
741122205Sharti
742122205Sharti	  case SIGO_RESET_response:
743122205Sharti		COMMON_DELAY(SIGO_RESET_response, cookie);
744122205Sharti		uni_enq_resp(uni, SIGR_RESET_response, cookie, msg, NULL);
745122205Sharti		msg = NULL;
746122205Sharti		break;
747122205Sharti
748122205Sharti	  case SIGO_SETUP_request:
749122205Sharti		if ((c = uni_create_new_call(uni, cookie)) != NULL) {
750122205Sharti			uni_enq_call(c, SIGC_SETUP_request, cookie, msg, NULL);
751122205Sharti			msg = NULL;
752122205Sharti			if (uni->custat == CU_STAT0) {
753122205Sharti				uni->funcs->saal_output(uni, uni->arg,
754122205Sharti				    SAAL_ESTABLISH_request, NULL);
755122205Sharti				if (!TIMER_ISACT(uni, t309))
756122205Sharti					TIMER_START_UNI(uni, t309, uni->timer309);
757122205Sharti				set_custat(uni, CU_STAT1);
758122205Sharti			}
759122205Sharti		} else {
760122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie,
761122205Sharti			    UNI_CALLSTATE_U0);
762122205Sharti		}
763122205Sharti		break;
764122205Sharti
765122205Sharti	  case SIGO_PROCEEDING_request:
766122205Sharti	    {
767122205Sharti		struct uniapi_proceeding_request *arg =
768122205Sharti		    uni_msg_rptr(msg, struct uniapi_proceeding_request *);
769122205Sharti
770122205Sharti		COMMON_DELAY(SIGO_PROCEEDING_request, cookie);
771122205Sharti		if ((c = uni_find_call(uni, &arg->call_proc.hdr.cref)) != NULL) {
772122205Sharti			uni_enq_call(c, SIGC_PROCEEDING_request, cookie, msg, NULL);
773122205Sharti			msg = NULL;
774122205Sharti		} else {
775122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
776122205Sharti			    UNI_CALLSTATE_U0);
777122205Sharti		}
778122205Sharti		break;
779122205Sharti	    }
780122205Sharti
781122205Sharti	  case SIGO_ALERTING_request:
782122205Sharti	    {
783122205Sharti		struct uniapi_alerting_request *arg =
784122205Sharti		    uni_msg_rptr(msg, struct uniapi_alerting_request *);
785122205Sharti
786122205Sharti		COMMON_DELAY(SIGO_ALERTING_request, cookie);
787122205Sharti		if ((c = uni_find_call(uni, &arg->alerting.hdr.cref)) != NULL) {
788122205Sharti			uni_enq_call(c, SIGC_ALERTING_request, cookie, msg, NULL);
789122205Sharti			msg = NULL;
790122205Sharti		} else {
791122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
792122205Sharti			    UNI_CALLSTATE_U0);
793122205Sharti		}
794122205Sharti		break;
795122205Sharti	    }
796122205Sharti
797122205Sharti	  case SIGO_SETUP_response:
798122205Sharti	    {
799122205Sharti		struct uniapi_setup_response *arg =
800122205Sharti		    uni_msg_rptr(msg, struct uniapi_setup_response *);
801122205Sharti
802122205Sharti		COMMON_DELAY(SIGO_SETUP_response, cookie);
803122205Sharti		if ((c = uni_find_call(uni, &arg->connect.hdr.cref)) != NULL) {
804122205Sharti			uni_enq_call(c, SIGC_SETUP_response, cookie, msg, NULL);
805122205Sharti			msg = NULL;
806122205Sharti		} else {
807122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
808122205Sharti			    UNI_CALLSTATE_U0);
809122205Sharti		}
810122205Sharti		break;
811122205Sharti	    }
812122205Sharti
813122205Sharti	  case SIGO_SETUP_COMPLETE_request:
814122205Sharti	    {
815122205Sharti		struct uniapi_setup_complete_request *arg =
816122205Sharti		    uni_msg_rptr(msg, struct uniapi_setup_complete_request *);
817122205Sharti
818122205Sharti		COMMON_DELAY(SIGO_SETUP_COMPLETE_request, cookie);
819122205Sharti		if ((c = uni_find_call(uni, &arg->connect_ack.hdr.cref)) != NULL) {
820122205Sharti			uni_enq_call(c, SIGC_SETUP_COMPLETE_request,
821122205Sharti			    cookie, msg, NULL);
822122205Sharti			msg = NULL;
823122205Sharti		} else {
824122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
825122205Sharti			    UNI_CALLSTATE_U0);
826122205Sharti		}
827122205Sharti		break;
828122205Sharti	    }
829122205Sharti
830122205Sharti	  case SIGO_RELEASE_request:
831122205Sharti	    {
832122205Sharti		struct uniapi_release_request *arg =
833122205Sharti		    uni_msg_rptr(msg, struct uniapi_release_request *);
834122205Sharti
835122205Sharti		COMMON_DELAY(SIGO_RELEASE_request, cookie);
836122205Sharti		if ((c = uni_find_call(uni, &arg->release.hdr.cref)) != NULL) {
837122205Sharti			uni_enq_call(c, SIGC_RELEASE_request, cookie, msg, NULL);
838122205Sharti			msg = NULL;
839122205Sharti		} else {
840122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
841122205Sharti			    UNI_CALLSTATE_U0);
842122205Sharti		}
843122205Sharti		break;
844122205Sharti	    }
845122205Sharti
846122205Sharti	  case SIGO_RELEASE_response:
847122205Sharti	    {
848122205Sharti		struct uniapi_release_response *arg =
849122205Sharti		    uni_msg_rptr(msg, struct uniapi_release_response *);
850122205Sharti
851122205Sharti		COMMON_DELAY(SIGO_RELEASE_response, cookie);
852122205Sharti		if ((c = uni_find_call(uni, &arg->release_compl.hdr.cref)) != NULL) {
853122205Sharti			uni_enq_call(c, SIGC_RELEASE_response, cookie, msg, NULL);
854122205Sharti			msg = NULL;
855122205Sharti		} else {
856122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
857122205Sharti			    UNI_CALLSTATE_U0);
858122205Sharti		}
859122205Sharti		break;
860122205Sharti	    }
861122205Sharti
862122205Sharti	  case SIGO_NOTIFY_request:
863122205Sharti	    {
864122205Sharti		struct uniapi_notify_request *arg =
865122205Sharti		    uni_msg_rptr(msg, struct uniapi_notify_request *);
866122205Sharti
867122205Sharti		COMMON_DELAY(SIGO_NOTIFY_request, cookie);
868122205Sharti		if ((c = uni_find_call(uni, &arg->notify.hdr.cref)) != NULL) {
869122205Sharti			uni_enq_call(c, SIGC_NOTIFY_request, cookie, msg, NULL);
870122205Sharti			msg = NULL;
871122205Sharti		} else {
872122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
873122205Sharti			    UNI_CALLSTATE_U0);
874122205Sharti		}
875122205Sharti		break;
876122205Sharti	    }
877122205Sharti
878122205Sharti	  case SIGO_STATUS_ENQUIRY_request:
879122205Sharti	    {
880122205Sharti		struct uniapi_status_enquiry_request *arg =
881122205Sharti		    uni_msg_rptr(msg, struct uniapi_status_enquiry_request *);
882122205Sharti
883122205Sharti		COMMON_DELAY(SIGO_STATUS_ENQUIRY_request, cookie);
884122205Sharti		if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
885122205Sharti			uni_enq_call(c, SIGC_STATUS_ENQUIRY_request, cookie, msg, NULL);
886122205Sharti			msg = NULL;
887122205Sharti		} else {
888122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
889122205Sharti			    UNI_CALLSTATE_U0);
890122205Sharti		}
891122205Sharti		break;
892122205Sharti	    }
893122205Sharti
894122205Sharti	  case SIGO_ADD_PARTY_request:
895122205Sharti	    {
896122205Sharti		struct uniapi_add_party_request *arg =
897122205Sharti		    uni_msg_rptr(msg, struct uniapi_add_party_request *);
898122205Sharti
899122205Sharti		COMMON_DELAY(SIGO_ADD_PARTY_request, cookie);
900122205Sharti		if ((c = uni_find_call(uni, &arg->add.hdr.cref)) != NULL) {
901122205Sharti			if (c->type != CALL_ROOT) {
902122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
903122205Sharti				    cookie);
904122205Sharti				break;
905122205Sharti			}
906122205Sharti			uni_enq_call(c, SIGC_ADD_PARTY_request, cookie, msg, NULL);
907122205Sharti			msg = NULL;
908122205Sharti		} else {
909122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
910122205Sharti			    UNI_CALLSTATE_U0);
911122205Sharti		}
912122205Sharti		break;
913122205Sharti	    }
914122205Sharti
915122205Sharti	  case SIGO_PARTY_ALERTING_request:
916122205Sharti	    {
917122205Sharti		struct uniapi_party_alerting_request *arg =
918122205Sharti		    uni_msg_rptr(msg, struct uniapi_party_alerting_request *);
919122205Sharti
920122205Sharti		COMMON_DELAY(SIGO_PARTY_ALERTING_request, cookie);
921122205Sharti		if ((c = uni_find_call(uni, &arg->alert.hdr.cref)) != NULL) {
922122205Sharti			if (c->type != CALL_LEAF) {
923122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
924122205Sharti				    cookie);
925122205Sharti				break;
926122205Sharti			}
927122205Sharti			uni_enq_call(c, SIGC_PARTY_ALERTING_request, cookie, msg, NULL);
928122205Sharti			msg = NULL;
929122205Sharti		} else {
930122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
931122205Sharti			    UNI_CALLSTATE_U0);
932122205Sharti		}
933122205Sharti		break;
934122205Sharti	    }
935122205Sharti
936122205Sharti	  case SIGO_ADD_PARTY_ACK_request:
937122205Sharti	    {
938122205Sharti		struct uniapi_add_party_ack_request *arg =
939122205Sharti		    uni_msg_rptr(msg, struct uniapi_add_party_ack_request *);
940122205Sharti
941122205Sharti		COMMON_DELAY(SIGO_ADD_PARTY_ACK_request, cookie);
942122205Sharti		if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
943122205Sharti			if (c->type != CALL_LEAF) {
944122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
945122205Sharti				    cookie);
946122205Sharti				break;
947122205Sharti			}
948122205Sharti			uni_enq_call(c, SIGC_ADD_PARTY_ACK_request, cookie, msg, NULL);
949122205Sharti			msg = NULL;
950122205Sharti		} else {
951122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
952122205Sharti			    UNI_CALLSTATE_U0);
953122205Sharti		}
954122205Sharti		break;
955122205Sharti	    }
956122205Sharti
957122205Sharti	  case SIGO_ADD_PARTY_REJ_request:
958122205Sharti	    {
959122205Sharti		struct uniapi_add_party_rej_request *arg =
960122205Sharti		    uni_msg_rptr(msg, struct uniapi_add_party_rej_request *);
961122205Sharti
962122205Sharti		COMMON_DELAY(SIGO_ADD_PARTY_REJ_request, cookie);
963122205Sharti		if ((c = uni_find_call(uni, &arg->rej.hdr.cref)) != NULL) {
964122205Sharti			if (c->type != CALL_LEAF) {
965122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
966122205Sharti				    cookie);
967122205Sharti				break;
968122205Sharti			}
969122205Sharti			uni_enq_call(c, SIGC_ADD_PARTY_REJ_request, cookie, msg, NULL);
970122205Sharti			msg = NULL;
971122205Sharti		} else {
972122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
973122205Sharti			    UNI_CALLSTATE_U0);
974122205Sharti		}
975122205Sharti		break;
976122205Sharti	    }
977122205Sharti
978122205Sharti	  case SIGO_DROP_PARTY_request:
979122205Sharti	    {
980122205Sharti		struct uniapi_drop_party_request *arg =
981122205Sharti		    uni_msg_rptr(msg, struct uniapi_drop_party_request *);
982122205Sharti
983122205Sharti		COMMON_DELAY(SIGO_DROP_PARTY_request, cookie);
984122205Sharti		if ((c = uni_find_call(uni, &arg->drop.hdr.cref)) != NULL) {
985122205Sharti			if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
986122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
987122205Sharti				    cookie);
988122205Sharti				break;
989122205Sharti			}
990122205Sharti			uni_enq_call(c, SIGC_DROP_PARTY_request, cookie, msg, NULL);
991122205Sharti			msg = NULL;
992122205Sharti		} else {
993122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
994122205Sharti			    UNI_CALLSTATE_U0);
995122205Sharti		}
996122205Sharti		break;
997122205Sharti	    }
998122205Sharti
999122205Sharti	  case SIGO_DROP_PARTY_ACK_request:
1000122205Sharti	    {
1001122205Sharti		struct uniapi_drop_party_ack_request *arg =
1002122205Sharti		    uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *);
1003122205Sharti
1004122205Sharti		COMMON_DELAY(SIGO_DROP_PARTY_ACK_request, cookie);
1005122205Sharti		if ((c = uni_find_call(uni, &arg->ack.hdr.cref)) != NULL) {
1006122205Sharti			if (c->type != CALL_ROOT && c->type != CALL_LEAF) {
1007122205Sharti				uniapi_call_error(c, UNIAPI_ERROR_BAD_CTYPE,
1008122205Sharti				    cookie);
1009122205Sharti				break;
1010122205Sharti			}
1011122205Sharti			uni_enq_call(c, SIGC_DROP_PARTY_ACK_request, cookie, msg, NULL);
1012122205Sharti			msg = NULL;
1013122205Sharti		} else {
1014122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
1015122205Sharti			    UNI_CALLSTATE_U0);
1016122205Sharti		}
1017122205Sharti		break;
1018122205Sharti	    }
1019122205Sharti
1020122205Sharti	  case SIGO_ABORT_CALL_request:
1021122205Sharti	    {
1022122205Sharti		struct uniapi_abort_call_request *arg =
1023122205Sharti		    uni_msg_rptr(msg, struct uniapi_abort_call_request *);
1024122205Sharti
1025122205Sharti		if ((c = uni_find_call(uni, &arg->cref)) != NULL) {
1026122205Sharti			uni_enq_call(c, SIGC_ABORT_CALL_request, cookie, NULL, NULL);
1027122205Sharti		} else {
1028122205Sharti			uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALL, cookie,
1029122205Sharti			    UNI_CALLSTATE_U0);
1030122205Sharti		}
1031122205Sharti		break;
1032122205Sharti	    }
1033122205Sharti
1034122205Sharti	  /*
1035122205Sharti	   * Call-Control
1036122205Sharti	   */
1037122205Sharti	  case SIGO_CALL_DESTROYED:
1038122205Sharti		uni->funcs->uni_output(uni, uni->arg,
1039122205Sharti		    UNIAPI_CALL_DESTROYED, 0, msg);
1040122205Sharti		msg = NULL;
1041122205Sharti		break;
1042122205Sharti
1043122205Sharti	  /*
1044122205Sharti	   * ResetRespond
1045122205Sharti	   */
1046122205Sharti	  case SIGO_RESET_indication:
1047122205Sharti		uni->funcs->uni_output(uni, uni->arg,
1048122205Sharti		    UNIAPI_RESET_indication, 0, msg);
1049122205Sharti		msg = NULL;
1050122205Sharti		break;
1051122205Sharti
1052122205Sharti	  /*
1053122205Sharti	   * Timeouts
1054122205Sharti	   */
1055122205Sharti	  case SIGO_T309:
1056122205Sharti		coord_t309(uni);
1057122205Sharti		break;
1058122205Sharti
1059122205Sharti	}
1060122205Sharti	if (msg != NULL)
1061122205Sharti		uni_msg_destroy(msg);
1062122205Sharti}
1063122205Sharti
1064122205Sharti/*
1065122205Sharti * Send a signal to all call instances
1066122205Sharti */
1067122205Shartistatic void
1068122205Shartisig_all_calls(struct uni *uni, u_int sig)
1069122205Sharti{
1070122205Sharti	struct call *call;
1071122205Sharti
1072122205Sharti	TAILQ_FOREACH(call, &uni->calls, link)
1073122205Sharti		uni_enq_call(call, sig, 0, NULL, NULL);
1074122205Sharti}
1075122205Sharti
1076122205Sharti/*
1077122205Sharti * Set a new coordinator state - this moves all delayed coordinator
1078122205Sharti * signals from the delayed queue to the signal queue.
1079122205Sharti */
1080122205Shartistatic int
1081122205Sharticufilt(struct sig *s, void *arg __unused)
1082122205Sharti{
1083122205Sharti	return (s->type == SIG_COORD);
1084122205Sharti}
1085122205Sharti
1086122205Shartistatic void
1087122205Shartiset_custat(struct uni *uni, enum cu_stat nstate)
1088122205Sharti{
1089122205Sharti	if (uni->custat != nstate) {
1090122205Sharti		uni->custat = nstate;
1091122205Sharti		uni_undel(uni, cufilt, NULL);
1092122205Sharti	}
1093122205Sharti}
1094122205Sharti
1095122205Sharti/*
1096122205Sharti * T309 timeout function
1097122205Sharti */
1098122205Shartistatic void
1099122205Shartit309_func(struct uni *uni)
1100122205Sharti{
1101122205Sharti	uni_enq_coord(uni, SIGO_T309, 0, NULL);
1102122205Sharti}
1103122205Sharti
1104122205Sharti/*
1105122205Sharti * Respond with a status message
1106122205Sharti */
1107122205Shartivoid
1108122205Shartiuni_respond_status(struct uni *uni, struct uni_cref *cref,
1109122205Sharti    enum uni_callstate cs, enum uni_cause c1)
1110122205Sharti{
1111122205Sharti	struct uni_all *resp;
1112122205Sharti
1113122205Sharti	if ((resp = UNI_ALLOC()) == NULL)
1114122205Sharti		return;
1115122205Sharti
1116122205Sharti	MK_MSG_RESP(resp, UNI_STATUS, cref);
1117122205Sharti	MK_IE_CALLSTATE(resp->u.status.callstate, cs);
1118122205Sharti	MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
1119122205Sharti
1120122205Sharti	(void)uni_send_output(resp, uni);
1121122205Sharti
1122122205Sharti	UNI_FREE(resp);
1123122205Sharti}
1124122205Sharti
1125122205Sharti/*
1126122205Sharti * Respond with a status message
1127122205Sharti */
1128122205Shartivoid
1129122205Shartiuni_respond_status_mtype(struct uni *uni, struct uni_cref *cref,
1130122205Sharti    enum uni_callstate cs, enum uni_cause c1, u_int mtype)
1131122205Sharti{
1132122205Sharti	struct uni_all *resp;
1133122205Sharti
1134122205Sharti	if((resp = UNI_ALLOC()) == NULL)
1135122205Sharti		return;
1136122205Sharti
1137122205Sharti	MK_MSG_RESP(resp, UNI_STATUS, cref);
1138122205Sharti	MK_IE_CALLSTATE(resp->u.status.callstate, cs);
1139122205Sharti	MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, c1);
1140122205Sharti	ADD_CAUSE_MTYPE(resp->u.status.cause, mtype);
1141122205Sharti
1142122205Sharti	(void)uni_send_output(resp, uni);
1143122205Sharti
1144122205Sharti	UNI_FREE(resp);
1145122205Sharti}
1146122205Sharti
1147122205Sharti/*
1148122205Sharti * Send a message. If we are in CUSTAT1, delay the message if we
1149122205Sharti * are in CUSTAT3 send it, else drop it.
1150122205Sharti */
1151122205Shartiint
1152122205Shartiuni_send_output(struct uni_all *u, struct uni *uni)
1153122205Sharti{
1154122205Sharti	struct uni_msg *m;
1155122205Sharti	int err;
1156122205Sharti
1157122205Sharti	if (uni->custat == CU_STAT0 || uni->custat == CU_STAT2)
1158122205Sharti		return (0);
1159122205Sharti
1160122205Sharti	m = uni_msg_alloc(1024);
1161122205Sharti	if ((err = uni_encode(m, u, &uni->cx)) != 0) {
1162122205Sharti		VERBOSE0(uni, UNI_FAC_ERR, "uni_encode failed: %08x", err);
1163122205Sharti		uni_msg_destroy(m);
1164122205Sharti		return (-1);
1165122205Sharti	}
1166122205Sharti	if (uni->custat == CU_STAT1)
1167122205Sharti		uni_delenq_coord(uni, SIGO_DATA, 0, m);
1168122205Sharti	else
1169122205Sharti		uni->funcs->saal_output(uni, uni->arg, SAAL_DATA_request, m);
1170122205Sharti	return (0);
1171122205Sharti}
1172