1/*
2 * Copyright (c) 2003-2007
3 *	Hartmut Brandt
4 *	All rights reserved.
5 *
6 * Copyright (c) 2001-2002
7 *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
8 *	All rights reserved.
9 *
10 * Author: Harti Brandt <harti@freebsd.org>
11 *
12 * Redistribution of this software and documentation and use in source and
13 * binary forms, with or without modification, are permitted provided that
14 * the following conditions are met:
15 *
16 * 1. Redistributions of source code or documentation must retain the above
17 *    copyright notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 *    notice, this list of conditions and the following disclaimer in the
20 *    documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR
23 * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
25 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
26 * THE AUTHOR OR ITS CONTRIBUTORS  BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
29 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 *
34 * $Id: cc_conn.c 1291 2007-07-10 10:35:38Z brandt_h $
35 *
36 * ATM API as defined per af-saa-0108
37 *
38 * Lower half - connection handling
39 */
40#include <netnatm/unimsg.h>
41#include <netnatm/msg/unistruct.h>
42#include <netnatm/msg/unimsglib.h>
43#include <netnatm/api/unisap.h>
44#include <netnatm/sig/unidef.h>
45#include <netnatm/api/atmapi.h>
46#include <netnatm/api/ccatm.h>
47#include <netnatm/api/ccpriv.h>
48
49static const char *stab[] = {
50#define DEF(N) [N] = #N,
51	CONN_STATES
52#undef DEF
53};
54
55static const char *ptab[] = {
56#define DEF(N) [PARTY_##N] = #N,
57	PARTY_STATES
58#undef DEF
59};
60
61const char *
62cc_conn_state2str(u_int s)
63{
64	if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL)
65		return ("?");
66	return (stab[s]);
67}
68
69void
70cc_conn_set_state(struct ccconn *conn, enum conn_state ns)
71{
72	if (conn->state != ns) {
73		if (conn->cc->log & CCLOG_CONN_STATE)
74			cc_conn_log(conn, "%s -> %s",
75			    stab[conn->state], stab[ns]);
76		conn->state = ns;
77	}
78}
79
80const char *
81cc_party_state2str(u_int s)
82{
83	if (s >= sizeof(ptab) / sizeof(ptab[0]) || ptab[s] == NULL)
84		return ("?");
85	return (ptab[s]);
86}
87
88void
89cc_party_set_state(struct ccparty *party, enum party_state ns)
90{
91
92	if (party->state != ns) {
93		if (party->conn->cc->log & CCLOG_PARTY_STATE)
94			cc_party_log(party, "%s -> %s",
95			    ptab[party->state], ptab[ns]);
96		party->state = ns;
97	}
98}
99
100/*
101 * Remove connection from its user's queue
102 */
103void
104cc_disconnect_from_user(struct ccconn *conn)
105{
106
107	if (conn->user == NULL)
108		cc_conn_log(conn, "no %s", "user");
109	else {
110		TAILQ_REMOVE(&conn->user->connq, conn, connq_link);
111		conn->user->queue_act--;
112		conn->user = NULL;
113	}
114}
115
116/*
117 * Put connection on user queue
118 */
119void
120cc_connect_to_user(struct ccconn *conn, struct ccuser *user)
121{
122
123	if (conn->user != NULL)
124		cc_conn_log(conn, "still connected to %p", conn->user);
125	conn->user = user;
126	TAILQ_INSERT_TAIL(&user->connq, conn, connq_link);
127	conn->user->queue_act++;
128}
129
130/*
131 * Send a signal to the UNI stack for this connection
132 */
133static void
134cc_send_uni(struct ccconn *conn, u_int op, struct uni_msg *msg)
135{
136	struct ccreq *r;
137
138	r = CCZALLOC(sizeof(*r));
139	if (r == NULL) {
140		if (msg != NULL)
141			uni_msg_destroy(msg);
142		cc_conn_log(conn, "no memory for cookie op=%u", op);
143		return;
144	}
145
146	if ((r->cookie = ++conn->port->cc->cookie) == 0)
147		r->cookie = ++conn->port->cc->cookie;
148	r->req = op;
149	r->conn = conn;
150
151	TAILQ_INSERT_TAIL(&conn->port->cookies, r, link);
152
153	conn->port->cc->funcs->send_uni(conn, conn->port->uarg, op,
154	    r->cookie, msg);
155}
156
157/*
158 * Send a RELEASE.request for this connection.
159 */
160static void
161do_release_request(struct ccconn *conn, const struct uni_ie_cause cause[2])
162{
163	struct uni_msg *u;
164	struct uniapi_release_request *req;
165
166	if ((u = uni_msg_alloc(sizeof(*req))) == NULL)
167		return;
168	req = uni_msg_wptr(u, struct uniapi_release_request *);
169	memset(req, 0, sizeof(*req));
170	u->b_wptr += sizeof(struct uniapi_release_request);
171
172	req->release.hdr.cref = conn->cref;
173	req->release.hdr.act = UNI_MSGACT_DEFAULT;
174
175	if (cause == NULL) {
176		IE_SETPRESENT(req->release.cause[0]);
177		req->release.cause[0].h.act = UNI_IEACT_DEFAULT;
178		req->release.cause[0].loc = UNI_CAUSE_LOC_USER;
179		req->release.cause[0].cause = UNI_CAUSE_UNSPEC;
180	} else {
181		req->release.cause[0] = cause[0];
182		req->release.cause[1] = cause[1];
183	}
184
185	cc_send_uni(conn, UNIAPI_RELEASE_request, u);
186}
187
188/*
189 * Make a RELEASE.response for this connection
190 */
191static void
192do_release_response(struct ccconn *conn, uint8_t cause, struct uni_ie_cause *ie)
193{
194	struct uni_msg *u;
195	struct uniapi_release_response *resp;
196
197	if ((u = uni_msg_alloc(sizeof(*resp))) == NULL)
198		return;
199	resp = uni_msg_wptr(u, struct uniapi_release_response *);
200	memset(resp, 0, sizeof(*resp));
201	u->b_wptr += sizeof(struct uniapi_release_response);
202
203	resp->release_compl.hdr.cref = conn->cref;
204	resp->release_compl.hdr.act = UNI_MSGACT_DEFAULT;
205
206	if (ie != NULL)
207		resp->release_compl.cause[0] = *ie;
208
209	if (cause != 0) {
210		IE_SETPRESENT(resp->release_compl.cause[0]);
211		resp->release_compl.cause[0].h.act = UNI_IEACT_DEFAULT;
212		resp->release_compl.cause[0].loc = UNI_CAUSE_LOC_USER;
213		resp->release_compl.cause[0].cause = cause;
214	}
215
216	cc_send_uni(conn, UNIAPI_RELEASE_response, u);
217}
218
219/**********************************************************************
220 *
221 * INSTANCE handling
222 */
223struct ccconn *
224cc_conn_create(struct ccdata *cc)
225{
226	struct ccconn *conn;
227
228	conn = CCZALLOC(sizeof(*conn));
229	if (conn == NULL)
230		return (NULL);
231
232	conn->state = CONN_NULL;
233	conn->port = NULL;
234	conn->cc = cc;
235	LIST_INIT(&conn->parties);
236
237	LIST_INSERT_HEAD(&cc->orphaned_conns, conn, port_link);
238
239	if (conn->cc->log & CCLOG_CONN_INST)
240		cc_conn_log(conn, "created %s", "orphaned");
241
242	return (conn);
243}
244
245/*
246 * assign to port
247 */
248void
249cc_conn_ins_port(struct ccconn *conn, struct ccport *port)
250{
251
252	if (conn->port != NULL) {
253		cc_conn_log(conn, "conn is already on port %u",
254		    conn->port->param.port);
255		cc_conn_rem_port(conn);
256	}
257	LIST_REMOVE(conn, port_link);
258
259	conn->port = port;
260	LIST_INSERT_HEAD(&port->conn_list, conn, port_link);
261
262}
263
264/*
265 * remove from port
266 */
267void
268cc_conn_rem_port(struct ccconn *conn)
269{
270
271	if (conn->port == NULL) {
272		cc_conn_log(conn, "conn not on any %s", "port");
273		return;
274	}
275	LIST_REMOVE(conn, port_link);
276	conn->port = NULL;
277	LIST_INSERT_HEAD(&conn->cc->orphaned_conns, conn, port_link);
278}
279
280static void
281cc_conn_flush_cookies(struct ccconn *conn)
282{
283	struct ccreq *r, *r1;
284
285	if (conn->port == NULL)
286		return;
287	TAILQ_FOREACH_SAFE(r, &conn->port->cookies, link, r1) {
288		if (r->conn == conn) {
289			TAILQ_REMOVE(&conn->port->cookies, r, link);
290			CCFREE(r);
291		}
292	}
293}
294
295void
296cc_conn_reset_acceptor(struct ccconn *conn)
297{
298	if (conn->acceptor != NULL) {
299		conn->acceptor->accepted = NULL;
300		conn->acceptor = NULL;
301	}
302}
303
304/*
305 * Destroy a connection
306 */
307void
308cc_conn_destroy(struct ccconn *conn)
309{
310	struct ccparty *p;
311
312	if (conn->cc->log & CCLOG_CONN_INST)
313		cc_conn_log(conn, "destroy%s", "");
314
315	if (conn->user != NULL) {
316		cc_conn_log(conn, "still connected to user %p\n", conn->user);
317		conn->user->queue_act--;
318		TAILQ_REMOVE(&conn->user->connq, conn, connq_link);
319	}
320
321	if (conn->acceptor != NULL)
322		conn->acceptor->accepted = NULL;
323
324	cc_conn_flush_cookies(conn);
325	cc_conn_sig_flush(conn);
326
327	LIST_REMOVE(conn, port_link);
328	while ((p = LIST_FIRST(&conn->parties)) != NULL) {
329		LIST_REMOVE(p, link);
330		CCFREE(p);
331	}
332
333	CCFREE(conn);
334}
335
336struct ccparty *
337cc_party_create(struct ccconn *conn, u_int ident, u_int flag)
338{
339	struct ccparty *party;
340
341	party = CCZALLOC(sizeof(*party));
342	if (party == NULL)
343		return (NULL);
344
345	party->conn = conn;
346	party->state = PARTY_NULL;
347	IE_SETPRESENT(party->epref);
348	party->epref.flag = flag;
349	party->epref.epref = ident;
350	LIST_INSERT_HEAD(&conn->parties, party, link);
351
352	if (party->conn->cc->log & CCLOG_PARTY_INST)
353		cc_party_log(party, "created %u.%u", flag, ident);
354
355	return (party);
356}
357
358static void
359cc_party_destroy(struct ccparty *party)
360{
361
362	if (party->conn->cc->log & CCLOG_PARTY_INST)
363		cc_party_log(party, "destroyed %u.%u", party->epref.flag,
364		    party->epref.epref);
365
366	LIST_REMOVE(party, link);
367	CCFREE(party);
368}
369
370static struct ccparty *
371cc_party_find(struct ccconn *conn, u_int ident)
372{
373	struct ccparty *party;
374
375	LIST_FOREACH(party, &conn->parties, link)
376		if (party->epref.epref == ident)
377			return (party);
378	return (NULL);
379}
380/*
381 * Abort connection from down stream (because of the UNI hook beeing
382 * disconnected). This is called from two places:
383 *  1) the shutdown code.
384 *	In this case the connections should be already dissociated from
385 *	users and be only in states waiting for the UNI stack.
386 *  2) from the disconnect code.
387 */
388void
389cc_conn_abort(struct ccconn *conn, int shutdown)
390{
391	struct ccuser *u = conn->user;
392	struct ccparty *p, *p1;
393
394	if (shutdown) {
395		CCASSERT(u == NULL, ("still in use"));
396		CCASSERT(conn->acceptor == NULL, ("still in use"));
397		cc_conn_destroy(conn);
398		return;
399	}
400
401	/*
402	 * Look whether any parties are blocked waiting for a response
403	 * from the stack. We don't use extra party states to handle
404	 * user aborts, so check that there is a user before using it.
405	 */
406	if (u == NULL) {
407		while ((p = LIST_FIRST(&conn->parties)) != NULL)
408			cc_party_destroy(p);
409	} else {
410		LIST_FOREACH_SAFE(p, &conn->parties, link, p1) {
411			switch (p->state) {
412
413			  case PARTY_NULL:		/* P0 */
414				/* should not happen */
415				goto dpty;
416
417			  case PARTY_ACTIVE:		/* P1 */
418				/* don't send a drop - user'll get a rel */
419				goto dpty;
420
421			  case PARTY_ADD_WAIT_CREATE:	/* P2 */
422			  case PARTY_ADD_WAIT_OK:	/* P3 */
423				/* we're adding - synthesise an error */
424				cc_user_sig(u, USER_SIG_ADD_PARTY_ERR,
425				    NULL, ATMERR_BAD_PORT);
426				goto dpty;
427
428			  case PARTY_ADD_WAIT_ACK:	/* P4 */
429				/* don't send a drop - user'll get a rel */
430				goto dpty;
431
432			  case PARTY_DROP_WAIT_OK:	/* P5 */
433			  case PARTY_DROP_WAIT_ACK:	/* P6 */
434			  case PARTY_ADD_DROP_WAIT_OK:	/* P11 */
435				/* we're dropping - synthesis an ok */
436				cc_user_sig(u, USER_SIG_DROP_PARTY_OK,
437				    NULL, p->epref.epref);
438				goto dpty;
439
440			  case PARTY_WAIT_DESTROY:	/* P7 */
441				goto dpty;
442
443			  case PARTY_WAIT_SETUP_COMPL:	/* P8 */
444			  case PARTY_WAIT_SETUP_CONF:	/* P10 */
445				/* first party - nothing to do */
446				goto dpty;
447
448			  case PARTY_WAIT_DROP_ACK_OK:	/* P9 */
449			  case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
450				/* we're dropping - nothing to do */
451				goto dpty;
452			}
453			cc_party_log(p, "bad uabort for party in state %s",
454			    ptab[p->state]);
455    dpty:
456			cc_party_destroy(p);
457		}
458	}
459
460	/*
461	 * Now do what the connection needs
462	 */
463	switch (conn->state) {
464
465	  case CONN_NULL:		/* 0 */
466	  case CONN_OUT_PREPARING: 	/* 1 */
467		/* may not happen because we're not associated with
468		 * aport yet */
469		break;
470
471	  case CONN_OUT_WAIT_CREATE: 	/* 2 */
472	  case CONN_OUT_WAIT_OK:	/* 3 */
473	  case CONN_OUT_WAIT_DESTROY:	/* 37 */
474		/* return an error to the user, go back to C1/U1
475		 * reset cref (for C37, C3) and cookie */
476		conn->cref.flag = 0;
477		conn->cref.cref = 0;
478		cc_conn_flush_cookies(conn);
479		cc_conn_set_state(conn, CONN_OUT_PREPARING);
480		cc_conn_rem_port(conn);
481		cc_user_sig(u, USER_SIG_CONNECT_OUTGOING_ERR,
482		    NULL, ATMERR_BAD_PORT);
483		return;
484
485	  case CONN_OUT_WAIT_CONF:	/* 4 */
486	  case CONN_ACTIVE:		/* 5 */
487	  case CONN_IN_WAIT_COMPL:	/* 13 */
488		/* emulate a RELEASE.confirm */
489		memset(&u->cause, 0, sizeof(u->cause));
490		cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0);
491		cc_disconnect_from_user(conn);
492		cc_conn_destroy(conn);
493		return;
494
495	  case CONN_IN_PREPARING:	/* 10 */
496	  case CONN_AB_WAIT_REQ_OK:	/* 33 */
497	  case CONN_AB_WAIT_RESP_OK:	/* 34 */
498	  case CONN_AB_FLUSH_IND:	/* 35 */
499		/* no user - destroy */
500		cc_conn_destroy(conn);
501		return;
502
503	  case CONN_IN_ARRIVED:		/* 11 */
504		u->aborted = 1;
505		cc_disconnect_from_user(conn);
506		cc_conn_destroy(conn);
507		return;
508
509	  case CONN_IN_WAIT_ACCEPT_OK:	/* 12 */
510		/* return ACCEPT error */
511		cc_disconnect_from_user(conn);
512		cc_conn_reset_acceptor(conn);
513		cc_user_sig(u, USER_SIG_ACCEPT_ERR,
514		    u, ATMERR_PREVIOUSLY_ABORTED);
515		cc_conn_destroy(conn);
516		return;
517
518	  case CONN_REJ_WAIT_OK:	/* 14 */
519		/* return REJECT ok */
520		cc_disconnect_from_user(conn);
521		cc_conn_destroy(conn);
522		cc_user_sig(u, USER_SIG_REJECT_OK, NULL, 0);
523		return;
524
525	  case CONN_REL_IN_WAIT_OK:	/* 15 */
526	  case CONN_REL_WAIT_OK:	/* 20 */
527		/* confirm destroy */
528		if (u != NULL) {
529			/* connection not aborted */
530			memset(&u->cause, 0, sizeof(u->cause));
531			cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0);
532			cc_disconnect_from_user(conn);
533		}
534		cc_conn_destroy(conn);
535		return;
536
537	  case CONN_IN_WAITING:		/* 21 */
538		/* user has not seen the connection - destroy */
539		cc_disconnect_from_user(conn);
540		cc_conn_destroy(conn);
541		return;
542	}
543	cc_conn_log(conn, "bad state %s", stab[conn->state]);
544}
545
546#ifdef DEBUG_MATCH
547static void
548print_sap(const struct uni_sap *sap)
549{
550	static const char *const tags[] = {
551		[UNISVE_ABSENT] "absent",
552		[UNISVE_PRESENT]"present",
553		[UNISVE_ANY]	"any",
554	};
555	u_int i;
556
557	printf("addr={%s", tags[sap->addr.tag]);
558	if (sap->addr.tag == UNISVE_PRESENT) {
559		printf(",%d-%d", sap->addr.type, sap->addr.plan);
560		for (i = 0; i < sap->addr.len; i++)
561			printf("%c%02x", ",:"[i!=0], sap->addr.addr[i]);
562	}
563	printf("}\n");
564
565	printf("selector={%s", tags[sap->selector.tag]);
566	if (sap->selector.tag == UNISVE_PRESENT)
567		printf(",%02x", sap->selector.selector);
568	printf("}\n");
569
570	printf("blli_id2={%s", tags[sap->blli_id2.tag]);
571	if (sap->blli_id2.tag == UNISVE_PRESENT)
572		printf(",%02x,%02x", sap->blli_id2.proto, sap->blli_id2.user);
573	printf("}\n");
574
575	printf("blli_id3={%s", tags[sap->blli_id3.tag]);
576	if (sap->blli_id3.tag == UNISVE_PRESENT)
577		printf(",%02x,%02x,%02x,%06x,%04x,%d",
578		    sap->blli_id3.proto, sap->blli_id3.user,
579		    sap->blli_id3.ipi, sap->blli_id3.oui,
580		    sap->blli_id3.pid, sap->blli_id3.noipi);
581	printf("}\n");
582
583	printf("bhli={%s", tags[sap->bhli.tag]);
584	if (sap->bhli.tag == UNISVE_PRESENT) {
585		printf(",%d", sap->bhli.type);
586		for (i = 0; i < sap->bhli.len; i++)
587			printf("%c%02x", ",:"[i!=0], sap->bhli.info[i]);
588	}
589	printf("}\n");
590}
591#endif
592
593/*********************************************************************
594 *
595 * DISPATCH incoming call
596 */
597void
598cc_conn_dispatch(struct ccconn *conn)
599{
600	struct ccdata *priv = conn->port->cc;
601	struct ccuser *user;
602	u_int blli_index;
603
604#ifdef DEBUG_MATCH
605	static char buf[1000];
606	static struct unicx cx;
607	static int init = 1;
608
609	if (init) {
610		uni_initcx(&cx);
611		init = 0;
612	}
613#endif
614
615	/*
616	 * Do call dispatching according to 4.6
617	 */
618#ifdef DEBUG_MATCH
619	printf("+++++ DISPATCH++++++\n");
620#endif
621	for (blli_index = 0; blli_index < UNI_NUM_IE_BLLI; blli_index++) {
622		if (blli_index > 0 && !IE_ISGOOD(conn->blli[blli_index]))
623			break;
624#ifdef DEBUG_MATCH
625		if (IE_ISPRESENT(conn->called)) {
626			uni_print_ie(buf, sizeof(buf), UNI_IE_CALLED,
627			    (union uni_ieall *)&conn->called, &cx);
628			printf("called=%s\n", buf);
629		}
630		if (IE_ISPRESENT(conn->bhli)) {
631			uni_print_ie(buf, sizeof(buf), UNI_IE_BHLI,
632			    (union uni_ieall *)&conn->bhli, &cx);
633			printf("bhli=%s\n", buf);
634		}
635		if (IE_ISPRESENT(conn->blli[blli_index])) {
636			uni_print_ie(buf, sizeof(buf), UNI_IE_BLLI,
637			    (union uni_ieall *)&conn->blli[blli_index], &cx);
638			printf("%s\n", buf);
639		}
640#endif
641		LIST_FOREACH(user, &priv->user_list, node_link) {
642			if ((user->state == USER_IN_WAITING ||
643			    user->state == USER_IN_ARRIVED ||
644			    user->state == USER_IN_WAIT_ACC ||
645			    user->state == USER_IN_WAIT_REJ) &&
646			    !unisve_is_catchall(user->sap)) {
647#ifdef DEBUG_MATCH
648				printf("TRYING user=%p\n", user);
649				print_sap(user->sap);
650#endif
651				if (unisve_match(user->sap, &conn->called,
652				    &conn->blli[blli_index], &conn->bhli))
653					goto found;
654			}
655		}
656	}
657#ifdef DEBUG_MATCH
658	printf("TRYING CATCHALL\n");
659#endif
660	blli_index = 0;
661	LIST_FOREACH(user, &priv->user_list, node_link) {
662		if ((user->state == USER_IN_WAITING ||
663		    user->state == USER_IN_ARRIVED ||
664		    user->state == USER_IN_WAIT_ACC ||
665		    user->state == USER_IN_WAIT_REJ) &&
666		    unisve_is_catchall(user->sap))
667			goto found;
668	}
669#ifdef DEBUG_MATCH
670	printf("SORRY\n");
671#endif
672
673	/*
674	 * No application found - reject call.
675	 */
676	do_release_response(conn, UNI_CAUSE_INCOMP, NULL);
677	cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
678	return;
679
680  found:
681#ifdef DEBUG_MATCH
682	printf("MATCH\n");
683#endif
684	if (user->queue_max == user->queue_act) {
685		do_release_response(conn, UNI_CAUSE_BUSY, NULL);
686		cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
687		return;
688	}
689
690	if (blli_index == 0 && !IE_ISGOOD(conn->blli[blli_index]))
691		conn->blli_selector = 0;
692	else
693		conn->blli_selector = blli_index + 1;
694
695	cc_conn_set_state(conn, CONN_IN_WAITING);
696	cc_connect_to_user(conn, user);
697
698	cc_user_sig(user, USER_SIG_SETUP_IND, NULL, 0);
699}
700
701static void
702cc_party_setup_conf(struct ccconn *conn)
703{
704	struct ccparty *party;
705
706	party = cc_party_find(conn, conn->epref.epref);
707	if (party == NULL) {
708		cc_party_log(party, "no party for %s",
709		    cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]);
710		return;
711	}
712	if (party->state != PARTY_WAIT_SETUP_CONF) {
713		cc_party_log(party, "bad state=%s for signal=%s",
714		    ptab[party->state], cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]);
715		return;
716	}
717	cc_party_set_state(party, PARTY_ACTIVE);
718}
719
720static void
721cc_party_add_ack_ind(struct ccconn *conn, const struct uni_ie_epref *epref)
722{
723	struct ccparty *party;
724
725	party = cc_party_find(conn, epref->epref);
726	if (party == NULL) {
727		cc_party_log(party, "no party for %s",
728		    cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]);
729	}
730	if (party->state != PARTY_ADD_WAIT_ACK) {
731		cc_party_log(party, "bad state=%s for signal=%s",
732		    ptab[party->state],
733		    cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]);
734		return;
735	}
736	cc_party_set_state(party, PARTY_ACTIVE);
737	cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ACK,
738	    NULL, epref->epref);
739}
740
741static void
742cc_party_add_rej_ind(struct ccconn *conn, const struct uni_ie_epref *epref)
743{
744	struct ccparty *party;
745
746	party = cc_party_find(conn, epref->epref);
747	if (party == NULL) {
748		cc_party_log(party, "no party for %s",
749		    cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]);
750		return;
751	}
752	if (party->state != PARTY_ADD_WAIT_ACK) {
753		cc_party_log(party, "bad state=%s for signal=%s",
754		    ptab[party->state],
755		    cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]);
756		return;
757	}
758	cc_party_set_state(party, PARTY_WAIT_DESTROY);
759	cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, NULL, epref->epref);
760}
761
762static void
763cc_party_drop_ack_ind(struct ccconn *conn,
764    const struct uni_drop_party *drop)
765{
766	struct ccparty *party;
767
768	party = cc_party_find(conn, drop->epref.epref);
769	if (party == NULL) {
770		cc_party_log(party, "no party for %s",
771		    cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]);
772		return;
773	}
774	switch (party->state) {
775
776	  case PARTY_ACTIVE:			/* P1 */
777		memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
778		conn->user->cause[0] = drop->cause;
779		cc_party_set_state(party, PARTY_WAIT_DESTROY);
780		cc_user_sig(conn->user, USER_SIG_DROP_PARTY_IND,
781		    NULL, party->epref.epref);
782		break;
783
784	  case PARTY_ADD_WAIT_ACK:		/* P4 */
785		memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
786		conn->user->cause[0] = drop->cause;
787		cc_party_set_state(party, PARTY_WAIT_DESTROY);
788		cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ,
789		    NULL, party->epref.epref);
790		break;
791
792	  case PARTY_DROP_WAIT_ACK:		/* P6 */
793		cc_party_set_state(party, PARTY_WAIT_DESTROY);
794		cc_user_sig(conn->user, USER_SIG_DROP_PARTY_OK, NULL, 0);
795		break;
796
797	  case PARTY_WAIT_SETUP_COMPL:		/* P8 */
798	  case PARTY_WAIT_SETUP_CONF:		/* P10 */
799		cc_party_set_state(party, PARTY_WAIT_DESTROY);
800		break;
801
802	  default:
803		cc_party_log(party, "bad state=%s for signal=%s",
804		    ptab[party->state],
805		    cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]);
806		break;
807	}
808}
809
810/*
811 * Handle a signal to this connection
812 */
813void
814cc_conn_sig_handle(struct ccconn *conn, enum conn_sig sig,
815    void *arg, u_int iarg)
816{
817	struct ccparty *party;
818
819	if (conn->cc->log & CCLOG_CONN_SIG)
820		cc_conn_log(conn, "signal %s in state %s", cc_conn_sigtab[sig],
821		    stab[conn->state]);
822
823	switch (sig) {
824
825	  case CONN_SIG_CONNECT_OUTGOING:
826		/* Do SETUP */
827	    {
828		struct uni_msg *u;
829		struct uniapi_setup_request *setup;
830
831		if (conn->state != CONN_OUT_PREPARING)
832			goto bad_state;
833
834		if (IE_ISGOOD(conn->bearer) &&
835		    conn->bearer.cfg == UNI_BEARER_MP) {
836			IE_SETPRESENT(conn->epref);
837			conn->epref.flag = 0;
838			conn->epref.epref = 0;
839		}
840
841		/*
842		 * Construct message to UNI.
843		 */
844		u = uni_msg_alloc(sizeof(struct uniapi_setup_request));
845		if (u == NULL) {
846			cc_user_sig(conn->user, USER_SIG_CONNECT_OUTGOING_ERR,
847			    NULL, ATMERR_NOMEM);
848			return;
849		}
850		setup = uni_msg_wptr(u, struct uniapi_setup_request *);
851		memset(setup, 0, sizeof(*setup));
852		u->b_wptr += sizeof(struct uniapi_setup_request);
853
854		setup->setup.hdr.act = UNI_MSGACT_DEFAULT;
855		memcpy(setup->setup.blli, conn->blli, sizeof(conn->blli));
856		setup->setup.bearer = conn->bearer;
857		setup->setup.traffic = conn->traffic;
858		setup->setup.qos = conn->qos;
859		setup->setup.exqos = conn->exqos;
860		setup->setup.called = conn->called;
861		setup->setup.calledsub[0] = conn->calledsub;
862		setup->setup.aal = conn->aal;
863		setup->setup.epref = conn->epref;
864		setup->setup.eetd = conn->eetd;
865		setup->setup.abrsetup = conn->abrsetup;
866		setup->setup.abradd = conn->abradd;
867		setup->setup.calling = conn->calling;
868		setup->setup.callingsub[0] = conn->callingsub;
869		setup->setup.connid = conn->connid;
870		memcpy(setup->setup.tns, conn->tns, sizeof(conn->tns));
871		setup->setup.atraffic = conn->atraffic;
872		setup->setup.mintraffic = conn->mintraffic;
873		setup->setup.cscope = conn->cscope;
874		setup->setup.bhli = conn->bhli;
875		setup->setup.mdcr = conn->mdcr;
876
877		cc_conn_set_state(conn, CONN_OUT_WAIT_CREATE);
878		cc_send_uni(conn, UNIAPI_SETUP_request, u);
879
880		break;
881	    }
882
883
884	  case CONN_SIG_ARRIVAL:
885		/* user informed of arrival of this call */
886		if (conn->state != CONN_IN_WAITING)
887			goto bad_state;
888		cc_conn_set_state(conn, CONN_IN_ARRIVED);
889		break;
890
891
892	  case CONN_SIG_RELEASE:
893	    {
894		/* Release this call */
895		struct uni_msg *u;
896		struct uniapi_release_request *req;
897
898		if (conn->state != CONN_ACTIVE &&
899		    conn->state != CONN_IN_WAIT_COMPL)
900			goto bad_state;
901
902		if ((u = uni_msg_alloc(sizeof(*req))) == NULL)
903			return;
904
905		req = uni_msg_wptr(u, struct uniapi_release_request *);
906		memset(req, 0, sizeof(*req));
907		u->b_wptr += sizeof(struct uniapi_release_request);
908
909		req->release.hdr.cref = conn->cref;
910		req->release.hdr.act = UNI_MSGACT_DEFAULT;
911
912		req->release.cause[0] = conn->cause[0];
913		req->release.cause[1] = conn->cause[1];
914
915		if (conn->state == CONN_ACTIVE)
916			cc_conn_set_state(conn, CONN_REL_WAIT_OK);
917		else
918			cc_conn_set_state(conn, CONN_REL_IN_WAIT_OK);
919
920		cc_send_uni(conn, UNIAPI_RELEASE_request, u);
921		break;
922	    }
923
924	  case CONN_SIG_REJECT:
925	    {
926		/* reject from user */
927		struct ccuser *user = conn->user;
928
929		if (conn->state != CONN_IN_ARRIVED) {
930			cc_user_sig(user, USER_SIG_REJECT_ERR,
931			    NULL, ATMERR_BAD_STATE);
932			break;
933		}
934		cc_conn_set_state(conn, CONN_REJ_WAIT_OK);
935		do_release_response(conn, 0, conn->cause);
936		break;
937	    }
938
939
940	  case CONN_SIG_ACCEPT:
941	    {
942		 /* User accepts. */
943    		struct ccuser *newep = arg;
944		struct uni_msg *u;
945		struct uniapi_setup_response *resp;
946		struct ccuser *user = conn->user;
947
948		if (conn->state != CONN_IN_ARRIVED) {
949			cc_user_sig(user, USER_SIG_ACCEPT_ERR,
950			    NULL, ATMERR_PREVIOUSLY_ABORTED);
951			break;
952		}
953
954		u = uni_msg_alloc(sizeof(struct uniapi_setup_response));
955		if (u == NULL) {
956			cc_user_sig(user, USER_SIG_ACCEPT_ERR,
957			    NULL, ATMERR_NOMEM);
958			return;
959		}
960
961		/*
962		 * Link to the new endpoint
963		 */
964		conn->acceptor = newep;
965		newep->accepted = conn;
966
967		/*
968		 * Construct connect message
969		 */
970		resp = uni_msg_wptr(u, struct uniapi_setup_response *);
971		memset(resp, 0, sizeof(*resp));
972		u->b_wptr += sizeof(*resp);
973
974		resp->connect.hdr.act = UNI_MSGACT_DEFAULT;
975		resp->connect.hdr.cref = conn->cref;
976
977		/*
978		 * attributes
979		 */
980		if (conn->dirty_attr & CCDIRTY_AAL)
981			resp->connect.aal = conn->aal;
982		if (conn->dirty_attr & CCDIRTY_BLLI)
983			resp->connect.blli =
984			    conn->blli[conn->blli_selector - 1];
985		if (conn->dirty_attr & CCDIRTY_CONNID)
986			resp->connect.connid = conn->connid;
987		/* XXX NOTIFY */
988		if (conn->dirty_attr & CCDIRTY_EETD)
989			resp->connect.eetd = conn->eetd;
990		/* XXX GIT */
991		/* XXX UU */
992		if (conn->dirty_attr & CCDIRTY_TRAFFIC)
993			resp->connect.traffic = conn->traffic;
994		if (conn->dirty_attr & CCDIRTY_EXQOS)
995			resp->connect.exqos = conn->exqos;
996		if (conn->dirty_attr & CCDIRTY_ABRSETUP)
997			resp->connect.abrsetup = conn->abrsetup;
998		if (conn->dirty_attr & CCDIRTY_ABRADD)
999			resp->connect.abradd = conn->abradd;
1000
1001		/*
1002		 * If the SETUP had an endpoint reference - echo it back
1003		 */
1004		if (IE_ISPRESENT(conn->epref)) {
1005			resp->connect.epref = conn->epref;
1006			resp->connect.epref.flag = !resp->connect.epref.flag;
1007		}
1008
1009		cc_conn_set_state(conn, CONN_IN_WAIT_ACCEPT_OK);
1010		cc_send_uni(conn, UNIAPI_SETUP_response, u);
1011		break;
1012	    }
1013
1014
1015	  case CONN_SIG_ADD_PARTY:
1016	    {
1017		/* request to add party from user */
1018		struct uni_msg *u;
1019		struct uniapi_add_party_request *req;
1020
1021		if (conn->state != CONN_ACTIVE)
1022			goto bad_state;
1023
1024		/* create the party */
1025		party = cc_party_create(conn, (u_int)(uintptr_t)arg, 0);
1026		if (party == NULL) {
1027			cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR,
1028			    NULL, ATMERR_NOMEM);
1029			return;
1030		}
1031		party->called = conn->called;
1032
1033		/* Construct message to UNI. */
1034		u = uni_msg_alloc(sizeof(struct uniapi_setup_request));
1035		if (u == NULL) {
1036			cc_party_destroy(party);
1037			cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR,
1038			    NULL, ATMERR_NOMEM);
1039			return;
1040		}
1041
1042		req = uni_msg_wptr(u, struct uniapi_add_party_request *);
1043		memset(req, 0, sizeof(*req));
1044		u->b_wptr += sizeof(struct uniapi_add_party_request);
1045
1046		req->add.hdr.act = UNI_MSGACT_DEFAULT;
1047		req->add.hdr.cref = conn->cref;
1048		req->add.epref = party->epref;
1049		req->add.called = party->called;
1050
1051		cc_party_set_state(party, PARTY_ADD_WAIT_CREATE);
1052		cc_send_uni(conn, UNIAPI_ADD_PARTY_request, u);
1053		break;
1054	    }
1055
1056
1057	  case CONN_SIG_DROP_PARTY:
1058	    {
1059		/* user request to drop a party */
1060		struct uni_msg *u;
1061		struct uniapi_drop_party_request *req;
1062
1063		if (conn->state != CONN_ACTIVE)
1064			goto bad_state;
1065
1066		party = cc_party_find(conn, (u_int)(uintptr_t)arg);
1067		if (party == NULL) {
1068			cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR,
1069			    NULL, ATMERR_BAD_PARTY);
1070			return;
1071		}
1072
1073		switch (party->state) {
1074
1075		  case PARTY_ACTIVE:
1076		  case PARTY_ADD_WAIT_ACK:
1077			break;
1078
1079		  default:
1080			cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR,
1081			    NULL, ATMERR_BAD_STATE);
1082			return;
1083
1084		}
1085		/*
1086		 * Construct message to UNI.
1087		 */
1088		u = uni_msg_alloc(sizeof(*req));
1089		if (u == NULL) {
1090			cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR,
1091			    NULL, ATMERR_NOMEM);
1092			return;
1093		}
1094
1095		req = uni_msg_wptr(u, struct uniapi_drop_party_request *);
1096		memset(req, 0, sizeof(*req));
1097		u->b_wptr += sizeof(struct uniapi_drop_party_request);
1098
1099		req->drop.hdr.act = UNI_MSGACT_DEFAULT;
1100		req->drop.hdr.cref = conn->cref;
1101		req->drop.epref = party->epref;
1102		req->drop.cause = conn->cause[0];
1103
1104		if (party->state == PARTY_ACTIVE)
1105			cc_party_set_state(party, PARTY_DROP_WAIT_OK);
1106		else
1107			cc_party_set_state(party, PARTY_ADD_DROP_WAIT_OK);
1108		cc_send_uni(conn, UNIAPI_DROP_PARTY_request, u);
1109		break;
1110	    }
1111
1112	  case CONN_SIG_DROP_PARTY_ACK_IND:
1113	    {
1114		struct uni_msg *msg = arg;
1115		struct uniapi_drop_party_ack_indication *ind = uni_msg_rptr(msg,
1116		    struct uniapi_drop_party_ack_indication *);
1117
1118		cc_party_drop_ack_ind(conn, &ind->drop);
1119		break;
1120	    }
1121
1122
1123	  case CONN_SIG_USER_ABORT:
1124		/*
1125		 * Aborting a connection. This is callable in all states.
1126		 * The connection is already disconnected from the user.
1127		 * The cause is in cause[].
1128		 */
1129		switch (conn->state) {
1130
1131		  case CONN_NULL:		/* C0 */
1132		  case CONN_OUT_PREPARING:	/* C1 */
1133			cc_conn_destroy(conn);
1134			break;
1135
1136		  case CONN_OUT_WAIT_CONF:	/* C4 */
1137		  case CONN_ACTIVE:		/* C5 */
1138			do_release_request(conn, conn->cause);
1139			cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK);
1140			break;
1141
1142		  case CONN_IN_WAITING:		/* C21 */
1143			/* that should not happen */
1144			goto bad_state;
1145			break;
1146
1147		  case CONN_IN_ARRIVED:		/* C11 */
1148			/*
1149			 * This is called only for the first connection
1150			 * of the user - the others are re-dispatched.
1151			 */
1152			do_release_response(conn, 0, conn->cause);
1153			cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1154			break;
1155
1156		  case CONN_IN_WAIT_COMPL:	/* C13 */
1157			do_release_request(conn, conn->cause);
1158			cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK);
1159			break;
1160
1161		  case CONN_OUT_WAIT_DESTROY:	/* C20 */
1162			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1163			break;
1164
1165		  case CONN_IN_WAIT_ACCEPT_OK:	/* C12 */
1166		  case CONN_AB_WAIT_REQ_OK:	/* C33 */
1167		  case CONN_AB_WAIT_RESP_OK:	/* C34 */
1168		  case CONN_AB_FLUSH_IND:	/* C35 */
1169			/* just ignore */
1170			break;
1171
1172		/*
1173		 * The following states may not happen, because
1174		 * we're waiting for a response from the UNI stack.
1175		 * As soon as the response comes the ABORT is undefered
1176		 * and will hit us (but in another state).
1177		 */
1178		  case CONN_OUT_WAIT_CREATE:	/* C2 */
1179		  case CONN_OUT_WAIT_OK:	/* C3 */
1180		  case CONN_IN_PREPARING:	/* C10 */
1181		  case CONN_REJ_WAIT_OK:	/* C14 */
1182		  case CONN_REL_IN_WAIT_OK:	/* C15 */
1183		  case CONN_REL_WAIT_OK:	/* C20 */
1184			goto bad_state;
1185		}
1186		break;
1187
1188
1189	  case CONN_SIG_CREATED:
1190	    {
1191		/*
1192		 * CALL_CREATED message from UNI. This can happen for either
1193		 * incoming or outgoing connections.
1194		 */
1195		struct uni_msg *msg = arg;
1196		struct uniapi_call_created *cr = uni_msg_rptr(msg,
1197		    struct uniapi_call_created *);
1198
1199		switch (conn->state) {
1200
1201		  case CONN_OUT_WAIT_CREATE:
1202			conn->cref = cr->cref;
1203			cc_conn_set_state(conn, CONN_OUT_WAIT_OK);
1204			break;
1205
1206		  case CONN_NULL:
1207			conn->cref = cr->cref;
1208			cc_conn_set_state(conn, CONN_IN_PREPARING);
1209			break;
1210
1211		  default:
1212			goto bad_state;
1213		}
1214		break;
1215	    }
1216
1217	  case CONN_SIG_DESTROYED:
1218		/*
1219		 * CALL_DESTROYED message from UNI.
1220		 */
1221		switch (conn->state) {
1222
1223		  case CONN_OUT_WAIT_DESTROY:
1224			cc_conn_rem_port(conn);
1225			cc_conn_set_state(conn, CONN_OUT_PREPARING);
1226			if (conn->user != NULL)
1227				cc_user_sig(conn->user,
1228				    USER_SIG_CONNECT_OUTGOING_ERR,
1229				    NULL, ATM_MKUNIERR(conn->reason));
1230			break;
1231
1232		  case CONN_AB_FLUSH_IND:
1233			cc_conn_destroy(conn);
1234			break;
1235
1236		  case CONN_IN_PREPARING:
1237			cc_conn_destroy(conn);
1238			break;
1239
1240		  default:
1241			goto bad_state;
1242		}
1243		break;
1244
1245
1246	  case CONN_SIG_SETUP_CONFIRM:
1247		/* Setup confirm from the UNI. */
1248	    {
1249		struct uni_msg *msg = arg;
1250		struct uniapi_setup_confirm *conf = uni_msg_rptr(msg,
1251		    struct uniapi_setup_confirm *);
1252
1253		switch (conn->state) {
1254
1255		  case CONN_OUT_WAIT_CONF:
1256			/*
1257			 * Shuffle attributes and inform the user.
1258			 * Negotiable attributes are condititionally shuffled,
1259			 * because not returning it means accepting it
1260			 * (in case of blli the first instance of it).
1261			 * All others are shuffled unconditionally.
1262			 * Here we should also open the VCI in the driver. (XXX)
1263			 */
1264#define SHUFFLE(ATTR)	conn->ATTR = conf->connect.ATTR
1265#define COND_SHUFFLE(ATTR) if (IE_ISPRESENT(conf->connect.ATTR)) SHUFFLE(ATTR)
1266
1267			COND_SHUFFLE(aal);
1268			(void)memset(conn->blli + 1, 0,
1269			    sizeof(conn->blli) - sizeof(conn->blli[0]));
1270			if (IE_ISPRESENT(conf->connect.blli))
1271				conn->blli[0] = conf->connect.blli;
1272			conn->blli_selector = 1;
1273			COND_SHUFFLE(epref);
1274			SHUFFLE(conned);
1275			SHUFFLE(connedsub);
1276			SHUFFLE(eetd);
1277			COND_SHUFFLE(traffic);
1278			COND_SHUFFLE(exqos);
1279			COND_SHUFFLE(abrsetup);
1280			COND_SHUFFLE(abradd);
1281			COND_SHUFFLE(connid);
1282#undef SHUFFLE
1283#undef COND_SHUFFLE
1284			if (IE_ISGOOD(conn->epref))
1285				cc_party_setup_conf(conn);
1286
1287			cc_conn_set_state(conn, CONN_ACTIVE);
1288			cc_user_sig(conn->user, USER_SIG_SETUP_CONFIRM,
1289			    NULL, 0);
1290			break;
1291
1292		  case CONN_AB_FLUSH_IND:
1293		  case CONN_AB_WAIT_RESP_OK:
1294			break;
1295
1296		  default:
1297			goto bad_state;
1298		}
1299		break;
1300	    }
1301
1302	  case CONN_SIG_SETUP_IND:
1303	    {
1304		/* SETUP indication */
1305		struct uni_msg *msg = arg;
1306		struct uniapi_setup_indication *ind = uni_msg_rptr(msg,
1307		    struct uniapi_setup_indication *);
1308		u_int i;
1309
1310		if (conn->state != CONN_IN_PREPARING)
1311			goto bad_state;
1312
1313		/*
1314		 * Shuffle information elements.
1315		 */
1316		for (i = 0; i < UNI_NUM_IE_BLLI; i++)
1317			conn->blli[i] = ind->setup.blli[i];
1318		conn->bearer = ind->setup.bearer;
1319		conn->traffic = ind->setup.traffic;
1320		conn->qos = ind->setup.qos;
1321		conn->exqos = ind->setup.exqos;
1322		conn->called = ind->setup.called;
1323		conn->calledsub = ind->setup.calledsub[0];
1324		conn->aal = ind->setup.aal;
1325		conn->epref = ind->setup.epref;
1326		conn->eetd = ind->setup.eetd;
1327		conn->abrsetup = ind->setup.abrsetup;
1328		conn->abradd = ind->setup.abradd;
1329		conn->calling = ind->setup.calling;
1330		conn->callingsub = ind->setup.callingsub[0];
1331		conn->connid = ind->setup.connid;
1332		for (i = 0; i < UNI_NUM_IE_TNS; i++)
1333			conn->tns[i] = ind->setup.tns[i];
1334		conn->atraffic = ind->setup.atraffic;
1335		conn->mintraffic = ind->setup.mintraffic;
1336		conn->cscope = ind->setup.cscope;
1337		conn->bhli = ind->setup.bhli;
1338		conn->mdcr = ind->setup.mdcr;
1339
1340		cc_conn_dispatch(conn);
1341		break;
1342	    }
1343
1344
1345	  case CONN_SIG_SETUP_COMPL:
1346	    {
1347		struct uni_msg *msg = arg;
1348		struct uniapi_setup_indication *ind __unused =
1349		    uni_msg_rptr(msg, struct uniapi_setup_indication *);
1350
1351		/* SETUP_COMPLETE.indication from UNI */
1352		if (conn->state == CONN_AB_FLUSH_IND ||
1353		    conn->state == CONN_AB_WAIT_RESP_OK)
1354			break;
1355
1356		if (conn->state != CONN_IN_WAIT_COMPL)
1357			goto bad_state;
1358
1359		cc_conn_set_state(conn, CONN_ACTIVE);
1360
1361		LIST_FOREACH(party, &conn->parties, link) {
1362			if (party->state == PARTY_WAIT_SETUP_COMPL)
1363				cc_party_set_state(party, PARTY_ACTIVE);
1364			else
1365				cc_party_log(party, "bad state=%s for sig=%s",
1366				    ptab[party->state],
1367				    cc_conn_sigtab[CONN_SIG_SETUP_COMPL]);
1368		}
1369
1370		cc_user_sig(conn->user, USER_SIG_SETUP_COMPL, NULL, 0);
1371		break;
1372	    }
1373
1374
1375	  case CONN_SIG_PROC_IND:
1376	    {
1377		/*
1378		 * ALERTING.indication and PROCEEDING.indication are entirly
1379		 * ignored by the specification. We need to at least save the
1380		 * connid information element.
1381		 */
1382		struct uni_msg *msg = arg;
1383		struct uniapi_proceeding_indication *ind = uni_msg_rptr(msg,
1384		    struct uniapi_proceeding_indication *);
1385
1386		switch (conn->state) {
1387
1388		  case CONN_OUT_WAIT_CONF:
1389			if (IE_ISGOOD(ind->call_proc.connid))
1390				conn->connid = ind->call_proc.connid;
1391			break;
1392
1393		  case CONN_AB_FLUSH_IND:
1394		  case CONN_AB_WAIT_RESP_OK:
1395			break;
1396
1397		  default:
1398			goto bad_state;
1399		}
1400		break;
1401	    }
1402
1403	  case CONN_SIG_ALERTING_IND:
1404	    {
1405		struct uni_msg *msg = arg;
1406		struct uniapi_alerting_indication *ind = uni_msg_rptr(msg,
1407		    struct uniapi_alerting_indication *);
1408
1409		switch (conn->state) {
1410
1411		  case CONN_OUT_WAIT_CONF:
1412			if (IE_ISGOOD(ind->alerting.connid))
1413				conn->connid = ind->alerting.connid;
1414			break;
1415
1416		  case CONN_AB_FLUSH_IND:
1417		  case CONN_AB_WAIT_RESP_OK:
1418			break;
1419
1420		  default:
1421			goto bad_state;
1422		}
1423		break;
1424	  }
1425
1426	  case CONN_SIG_REL_CONF:
1427	    {
1428		/* RELEASE.confirm from UNI */
1429		struct uni_msg *msg = arg;
1430		struct uniapi_release_confirm *conf = uni_msg_rptr(msg,
1431		    struct uniapi_release_confirm *);
1432
1433		switch (conn->state) {
1434
1435		  case CONN_OUT_WAIT_CONF:
1436		  case CONN_ACTIVE:
1437			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1438			memcpy(conn->user->cause, conf->release.cause,
1439			    sizeof(conn->user->cause));
1440			/*
1441			 * If any party is in P6, ok the user
1442			 */
1443			LIST_FOREACH(party, &conn->parties, link) {
1444				if (party->state == PARTY_DROP_WAIT_ACK) {
1445					cc_party_set_state(party,
1446					    PARTY_WAIT_DESTROY);
1447					cc_user_sig(conn->user,
1448					    USER_SIG_DROP_PARTY_OK,
1449					    NULL, party->epref.epref);
1450				}
1451			}
1452			cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1453			    NULL, 0);
1454			cc_disconnect_from_user(conn);
1455			break;
1456
1457		  case CONN_AB_FLUSH_IND:
1458		  case CONN_AB_WAIT_RESP_OK:
1459			break;
1460
1461		  case CONN_IN_WAITING:
1462			cc_disconnect_from_user(conn);
1463			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1464			break;
1465
1466		  case CONN_IN_ARRIVED:
1467			conn->user->aborted = 1;
1468			memcpy(conn->user->cause, conf->release.cause,
1469			    sizeof(conn->user->cause));
1470			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1471			cc_disconnect_from_user(conn);
1472			break;
1473
1474		  case CONN_IN_WAIT_COMPL:
1475			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1476			memcpy(conn->user->cause, conf->release.cause,
1477			    sizeof(conn->user->cause));
1478			cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1479			    NULL, 0);
1480			cc_disconnect_from_user(conn);
1481			break;
1482
1483		  default:
1484			goto bad_state;
1485		}
1486		break;
1487	    }
1488
1489	  case CONN_SIG_REL_IND:
1490	    {
1491		/* RELEASE.ind from UNI */
1492		struct uni_msg *msg = arg;
1493		struct uniapi_release_indication *conf = uni_msg_rptr(msg,
1494		    struct uniapi_release_indication *);
1495
1496		switch (conn->state) {
1497
1498		  case CONN_OUT_WAIT_CONF:
1499		  case CONN_ACTIVE:
1500			do_release_response(conn, 0, NULL);
1501			cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1502			memcpy(conn->user->cause, conf->release.cause,
1503			    sizeof(conn->user->cause));
1504			/*
1505			 * If any party is in P6, ok the user
1506			 */
1507			LIST_FOREACH(party, &conn->parties, link) {
1508				if (party->state == PARTY_DROP_WAIT_ACK) {
1509					cc_party_set_state(party,
1510					    PARTY_WAIT_DESTROY);
1511					cc_user_sig(conn->user,
1512					    USER_SIG_DROP_PARTY_OK,
1513					    NULL, party->epref.epref);
1514				}
1515			}
1516			cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1517			    NULL, 0);
1518			cc_disconnect_from_user(conn);
1519			break;
1520
1521		  case CONN_AB_FLUSH_IND:
1522		  case CONN_AB_WAIT_RESP_OK:
1523			break;
1524
1525		  case CONN_IN_WAITING:
1526			cc_disconnect_from_user(conn);
1527			do_release_response(conn, 0, NULL);
1528			cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1529			break;
1530
1531		  case CONN_IN_ARRIVED:
1532			conn->user->aborted = 1;
1533			cc_disconnect_from_user(conn);
1534			do_release_response(conn, 0, NULL);
1535			cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1536			break;
1537
1538		  case CONN_IN_WAIT_COMPL:
1539			do_release_response(conn, 0, NULL);
1540			cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1541			memcpy(conn->user->cause, conf->release.cause,
1542			    sizeof(conn->user->cause));
1543			cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM,
1544			    NULL, 0);
1545			cc_disconnect_from_user(conn);
1546			break;
1547		  default:
1548			goto bad_state;
1549			break;
1550		}
1551		break;
1552	    }
1553
1554	  case CONN_SIG_PARTY_ALERTING_IND:
1555		/* party alerting from UNI */
1556		if (conn->state == CONN_AB_FLUSH_IND)
1557			break;
1558		if (conn->state != CONN_ACTIVE)
1559			goto bad_state;
1560		/* ignore */
1561		break;
1562
1563	  case CONN_SIG_PARTY_ADD_ACK_IND:
1564	    {
1565		/* ADD PARTY ACKNOWLEDGE from UNI */
1566		struct uni_msg *msg = arg;
1567		struct uniapi_add_party_ack_indication *ind = uni_msg_rptr(msg,
1568		    struct uniapi_add_party_ack_indication *);
1569
1570		if (conn->state == CONN_AB_FLUSH_IND)
1571			break;
1572		if (conn->state != CONN_ACTIVE)
1573			goto bad_state;
1574
1575		cc_party_add_ack_ind(conn, &ind->ack.epref);
1576		break;
1577	    }
1578
1579
1580	 case CONN_SIG_PARTY_ADD_REJ_IND:
1581	    {
1582		/* ADD PARTY REJECT indication */
1583		struct uni_msg *msg = arg;
1584		struct uniapi_add_party_rej_indication *ind = uni_msg_rptr(msg,
1585		    struct uniapi_add_party_rej_indication *);
1586
1587		if (conn->state == CONN_AB_FLUSH_IND)
1588			break;
1589		if (conn->state != CONN_ACTIVE)
1590			goto bad_state;
1591
1592		memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
1593		conn->user->cause[0] = ind->rej.cause;
1594
1595		cc_party_add_rej_ind(conn, &ind->rej.epref);
1596		break;
1597	    }
1598
1599
1600	  case CONN_SIG_DROP_PARTY_IND:
1601	    {
1602		/* DROP_PARTY.indication from UNI */
1603		struct uni_msg *msg = arg;
1604		struct uniapi_drop_party_indication *ind = uni_msg_rptr(msg,
1605		    struct uniapi_drop_party_indication *);
1606		struct uniapi_drop_party_ack_request *req;
1607		struct uni_msg *u;
1608
1609		if (conn->state == CONN_AB_FLUSH_IND)
1610			break;
1611		if (conn->state != CONN_ACTIVE)
1612			goto bad_state;
1613
1614		party = cc_party_find(conn, ind->drop.epref.epref);
1615		if (party == NULL) {
1616			cc_party_log(party, "no party for %s",
1617			    cc_conn_sigtab[sig]);
1618			break;
1619		}
1620
1621		u = uni_msg_alloc(sizeof(*req));
1622		if (u == NULL)
1623			return;
1624
1625		memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1]));
1626		conn->user->cause[0] = ind->drop.cause;
1627
1628		switch (party->state) {
1629
1630		  default:
1631			cc_party_log(party, "bad state %s for DROP.ind",
1632			    ptab[party->state]);
1633			/* FALLTHRU */
1634
1635		  case PARTY_ACTIVE:		/* P1 -> P9 */
1636			cc_party_set_state(party, PARTY_WAIT_DROP_ACK_OK);
1637			break;
1638
1639		  case PARTY_ADD_WAIT_ACK:	/* P4 -> P12 */
1640			cc_party_set_state(party, PARTY_ADD_DROPACK_WAIT_OK);
1641			break;
1642		}
1643
1644		/*
1645		 * Construct message to UNI.
1646		 */
1647		req = uni_msg_wptr(u, struct uniapi_drop_party_ack_request *);
1648		memset(req, 0, sizeof(*req));
1649		u->b_wptr += sizeof(*req);
1650
1651		IE_SETPRESENT(req->ack.epref);
1652		req->ack.hdr.act = UNI_MSGACT_DEFAULT;
1653		req->ack.hdr.cref = conn->cref;
1654
1655		req->ack.epref.flag = 0;
1656		req->ack.epref.epref = ind->drop.epref.epref;
1657
1658		cc_send_uni(conn, UNIAPI_DROP_PARTY_ACK_request, u);
1659		break;
1660	    }
1661
1662	  case CONN_SIG_OK:
1663	    {
1664 		/* OK response from UNI */
1665		struct ccuser *user = conn->user;
1666
1667		switch (conn->state) {
1668
1669		  case CONN_OUT_WAIT_OK:		/* C3 */
1670			cc_conn_set_state(conn, CONN_OUT_WAIT_CONF);
1671			if (conn->user != NULL)
1672				cc_user_sig(conn->user,
1673				    USER_SIG_CONNECT_OUTGOING_OK, NULL, 0);
1674			break;
1675
1676		  case CONN_AB_WAIT_RESP_OK:		/* C33 */
1677		  case CONN_AB_WAIT_REQ_OK:		/* C34 */
1678			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1679			break;
1680
1681		  case CONN_REL_WAIT_OK:		/* C20 */
1682		  case CONN_REL_IN_WAIT_OK:		/* C15 */
1683			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1684			if (conn->user != NULL) {
1685				/* connection has not been aborted */
1686				memset(&conn->user->cause, 0,
1687				    sizeof(conn->user->cause));
1688				cc_user_sig(conn->user,
1689				    USER_SIG_RELEASE_CONFIRM, NULL, 0);
1690				cc_disconnect_from_user(conn);
1691			}
1692			break;
1693
1694		  case CONN_IN_WAIT_ACCEPT_OK:		/* C12 */
1695			if (user == NULL) {
1696				/* has been aborted */
1697				do_release_request(conn, NULL);
1698				cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK);
1699				break;
1700			}
1701			cc_conn_set_state(conn, CONN_IN_WAIT_COMPL);
1702			cc_disconnect_from_user(conn);
1703			cc_user_sig(user, USER_SIG_ACCEPT_OK, NULL, 0);
1704			if (conn->acceptor == NULL) {
1705				do_release_request(conn, NULL);
1706				cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK);
1707				break;
1708			}
1709			cc_connect_to_user(conn, conn->acceptor);
1710			cc_conn_reset_acceptor(conn);
1711			cc_user_sig(conn->user, USER_SIG_ACCEPTING, NULL, 0);
1712			break;
1713
1714		  case CONN_REJ_WAIT_OK:		/* C14 */
1715			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1716			if (user != NULL) {
1717				cc_disconnect_from_user(conn);
1718				cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0);
1719			}
1720			break;
1721
1722		  default:
1723			/* maybe it's for a party */
1724			LIST_FOREACH(party, &conn->parties, link) {
1725				switch (party->state) {
1726
1727				  case PARTY_ADD_WAIT_OK:	/* P3 */
1728					if (user != NULL)
1729						cc_user_sig(user,
1730						    USER_SIG_ADD_PARTY_OK,
1731						    NULL, 0);
1732					cc_party_set_state(party,
1733					    PARTY_ADD_WAIT_ACK);
1734					goto ex_party_ok;
1735
1736				  case PARTY_DROP_WAIT_OK:	/* P5 */
1737					cc_party_set_state(party,
1738					    PARTY_DROP_WAIT_ACK);
1739					goto ex_party_ok;
1740
1741				  case PARTY_WAIT_DROP_ACK_OK:	/* P9 */
1742				  case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
1743				     {
1744					struct ccparty *p1;
1745
1746					cc_party_set_state(party,
1747					    PARTY_WAIT_DESTROY);
1748					/* signal to user only if there are any other parties */
1749					LIST_FOREACH(p1, &conn->parties, link)
1750						if (p1 != party)
1751							break;
1752					if (p1 != NULL && user != NULL)
1753						cc_user_sig(user,
1754						    USER_SIG_DROP_PARTY_IND,
1755						    NULL,
1756						    party->epref.epref);
1757
1758					goto ex_party_ok;
1759				    }
1760
1761				  case PARTY_ADD_DROP_WAIT_OK:	/* P11 */
1762					cc_party_set_state(party,
1763					    PARTY_DROP_WAIT_ACK);
1764					goto ex_party_ok;
1765
1766				  default:
1767					break;
1768				}
1769			}
1770			goto bad_state;
1771		    ex_party_ok:
1772			break;
1773		}
1774		break;
1775	    }
1776
1777	  case CONN_SIG_ERROR:
1778	    {
1779		/* error response from UNI */
1780		u_int reason = (iarg >> 16) & 0xffff;
1781		u_int state = iarg & 0xffff;
1782		struct ccuser *user = conn->user;
1783
1784		switch (conn->state) {
1785
1786		  case CONN_OUT_WAIT_CREATE:		/* C2 */
1787			cc_conn_rem_port(conn);
1788			cc_conn_set_state(conn, CONN_OUT_PREPARING);
1789			if (conn->user != NULL)
1790				cc_user_sig(conn->user,
1791				    USER_SIG_CONNECT_OUTGOING_ERR,
1792				    NULL, ATM_MKUNIERR(reason));
1793			break;
1794
1795		  case CONN_OUT_WAIT_OK:		/* C3 */
1796			cc_conn_set_state(conn, CONN_OUT_WAIT_DESTROY);
1797			conn->reason = reason;
1798			break;
1799
1800		  case CONN_AB_WAIT_REQ_OK:		/* C33 */
1801			if (state == UNI_CALLSTATE_U12) {
1802				do_release_response(conn, 0, conn->cause);
1803				cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1804				break;
1805			}
1806			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1807			break;
1808
1809		  case CONN_AB_WAIT_RESP_OK:		/* C34 */
1810			cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1811			break;
1812
1813		  case CONN_REL_WAIT_OK:		/* C20 */
1814			if (user == NULL) {
1815				/* connection has been aborted. */
1816				if (state == UNI_CALLSTATE_U10) {
1817					/* do what we can */
1818					do_release_request(conn, conn->cause);
1819					cc_conn_set_state(conn,
1820					    CONN_AB_WAIT_REQ_OK);
1821				} else if (state == UNI_CALLSTATE_U12) {
1822					do_release_response(conn, 0, NULL);
1823					cc_conn_set_state(conn,
1824					    CONN_AB_WAIT_RESP_OK);
1825				} else {
1826					cc_conn_set_state(conn,
1827					    CONN_AB_FLUSH_IND);
1828				}
1829				break;
1830			}
1831			if (state == UNI_CALLSTATE_U10) {
1832				cc_conn_set_state(conn, CONN_ACTIVE);
1833				cc_user_sig(conn->user, USER_SIG_RELEASE_ERR,
1834				    NULL, reason);
1835			} else if (state == UNI_CALLSTATE_U12) {
1836				do_release_response(conn, 0, NULL);
1837				cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1838				memset(&conn->user->cause, 0,
1839				    sizeof(conn->user->cause));
1840				cc_user_sig(conn->user,
1841				    USER_SIG_RELEASE_CONFIRM, NULL, 0);
1842				cc_disconnect_from_user(conn);
1843			} else {
1844				cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1845				memset(&conn->user->cause, 0,
1846				    sizeof(conn->user->cause));
1847				cc_user_sig(conn->user,
1848				    USER_SIG_RELEASE_CONFIRM, NULL, 0);
1849				cc_disconnect_from_user(conn);
1850			}
1851			break;
1852
1853		  case CONN_IN_WAIT_ACCEPT_OK:		/* C12 */
1854			if (user == NULL) {
1855				/* connection was aborted */
1856				if (state == UNI_CALLSTATE_U6 ||
1857				    state == UNI_CALLSTATE_U7 ||
1858				    state == UNI_CALLSTATE_U9 ||
1859				    state == UNI_CALLSTATE_U12) {
1860					do_release_response(conn, 0, NULL);
1861					cc_conn_set_state(conn,
1862					    CONN_AB_WAIT_RESP_OK);
1863				} else {
1864					cc_conn_set_state(conn,
1865					    CONN_AB_FLUSH_IND);
1866				}
1867				break;
1868			}
1869			cc_conn_reset_acceptor(conn);
1870			if (state == UNI_CALLSTATE_U6 ||
1871			    state == UNI_CALLSTATE_U9 ||
1872			    state == UNI_CALLSTATE_U7) {
1873				cc_user_sig(user, USER_SIG_ACCEPT_ERR,
1874				    NULL, ATM_MKUNIERR(reason));
1875				cc_conn_set_state(conn, CONN_IN_ARRIVED);
1876			} else if (state == UNI_CALLSTATE_U12) {
1877				do_release_response(conn, 0, NULL);
1878				cc_disconnect_from_user(conn);
1879				cc_user_sig(user, USER_SIG_ACCEPT_ERR,
1880				    user, ATMERR_PREVIOUSLY_ABORTED);
1881				cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1882			} else {
1883				cc_disconnect_from_user(conn);
1884				cc_user_sig(user, USER_SIG_ACCEPT_ERR,
1885				    user, ATMERR_PREVIOUSLY_ABORTED);
1886				cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1887			}
1888			break;
1889
1890		  case CONN_REJ_WAIT_OK:		/* C14 */
1891			if (user == NULL) {
1892				/* connection has been aborted. */
1893				if (state == UNI_CALLSTATE_U6 ||
1894				    state == UNI_CALLSTATE_U7 ||
1895				    state == UNI_CALLSTATE_U9 ||
1896				    state == UNI_CALLSTATE_U12) {
1897					/* do what we can */
1898					do_release_response(conn, 0, NULL);
1899					cc_conn_set_state(conn,
1900					    CONN_AB_WAIT_RESP_OK);
1901				} else {
1902					cc_conn_set_state(conn,
1903					    CONN_AB_FLUSH_IND);
1904				}
1905				break;
1906			}
1907			if (state == UNI_CALLSTATE_U6 ||
1908			    state == UNI_CALLSTATE_U9 ||
1909			    state == UNI_CALLSTATE_U7) {
1910				cc_user_sig(user, USER_SIG_REJECT_ERR,
1911				    NULL, ATM_MKUNIERR(reason));
1912				cc_conn_set_state(conn, CONN_IN_ARRIVED);
1913			} else {
1914				cc_disconnect_from_user(conn);
1915				cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0);
1916				cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1917			}
1918			break;
1919
1920		  case CONN_REL_IN_WAIT_OK:		/* C15 */
1921			if (user == NULL) {
1922				/* connection has been aborted. */
1923				if (state == UNI_CALLSTATE_U8) {
1924					/* do what we can */
1925					do_release_request(conn, conn->cause);
1926					cc_conn_set_state(conn,
1927					    CONN_AB_WAIT_REQ_OK);
1928				} else if (state == UNI_CALLSTATE_U12) {
1929					do_release_response(conn, 0, NULL);
1930					cc_conn_set_state(conn,
1931					    CONN_AB_WAIT_RESP_OK);
1932				} else {
1933					cc_conn_set_state(conn,
1934					    CONN_AB_FLUSH_IND);
1935				}
1936				break;
1937			}
1938			if (state == UNI_CALLSTATE_U8) {
1939				cc_conn_set_state(conn, CONN_IN_WAIT_COMPL);
1940				cc_user_sig(conn->user, USER_SIG_RELEASE_ERR,
1941				    NULL, reason);
1942			} else if (state == UNI_CALLSTATE_U12) {
1943				do_release_response(conn, 0, NULL);
1944				cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK);
1945				memset(&conn->user->cause, 0,
1946				    sizeof(conn->user->cause));
1947				cc_user_sig(conn->user,
1948				    USER_SIG_RELEASE_CONFIRM, NULL, 0);
1949				cc_disconnect_from_user(conn);
1950			} else {
1951				cc_conn_set_state(conn, CONN_AB_FLUSH_IND);
1952				memset(&conn->user->cause, 0,
1953				    sizeof(conn->user->cause));
1954				cc_user_sig(conn->user,
1955				    USER_SIG_RELEASE_CONFIRM, NULL, 0);
1956				cc_disconnect_from_user(conn);
1957			}
1958			break;
1959
1960		  default:
1961			/* maybe it's for a party */
1962			LIST_FOREACH(party, &conn->parties, link) {
1963				switch (party->state) {
1964
1965				  case PARTY_ADD_WAIT_CREATE:	/* P2 */
1966					cc_party_destroy(party);
1967					if (user != NULL)
1968						cc_user_sig(user,
1969						    USER_SIG_ADD_PARTY_ERR,
1970						    NULL, ATM_MKUNIERR(reason));
1971					goto ex_party_err;
1972
1973				  case PARTY_ADD_WAIT_OK:	/* P3 */
1974					cc_party_set_state(party,
1975					    PARTY_WAIT_DESTROY);
1976					if (user != NULL)
1977						cc_user_sig(user,
1978						    USER_SIG_ADD_PARTY_ERR,
1979						    NULL, ATM_MKUNIERR(reason));
1980					goto ex_party_err;
1981
1982				  case PARTY_DROP_WAIT_OK:	/* P5 */
1983					cc_party_set_state(party,
1984					    PARTY_ACTIVE);
1985					if (user != NULL)
1986						cc_user_sig(user,
1987						    USER_SIG_DROP_PARTY_ERR,
1988						    NULL, ATM_MKUNIERR(reason));
1989					goto ex_party_err;
1990
1991				  case PARTY_WAIT_DROP_ACK_OK:	/* P9 */
1992					cc_party_set_state(party,
1993					    PARTY_ACTIVE);
1994					goto ex_party_err;
1995
1996				  case PARTY_ADD_DROP_WAIT_OK:	/* P11 */
1997					cc_party_set_state(party,
1998					    PARTY_ADD_WAIT_ACK);
1999					if (user != NULL)
2000						cc_user_sig(user,
2001						    USER_SIG_DROP_PARTY_ERR,
2002						    NULL, ATM_MKUNIERR(reason));
2003					goto ex_party_err;
2004
2005				  case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */
2006					cc_party_set_state(party,
2007					    PARTY_ADD_WAIT_ACK);
2008					goto ex_party_err;
2009
2010				  default:
2011					break;
2012				}
2013			}
2014			cc_conn_log(conn, "unexpected reason=%u ustate=%u "
2015			    "state=%s\n", reason, state, stab[conn->state]);
2016		  ex_party_err:
2017			break;
2018		}
2019		break;
2020	    }
2021
2022	  case CONN_SIG_PARTY_CREATED:
2023	    {
2024		struct uni_msg *msg = arg;
2025		struct uniapi_party_created *pcr = uni_msg_rptr(msg,
2026		    struct uniapi_party_created *);
2027
2028		party = cc_party_find(conn, pcr->epref.epref);
2029		if (party == NULL) {
2030			/* for incoming connections we see the party-created
2031			 * immediately after the call-create so that we
2032			 * must be in C10 */
2033			switch (conn->state) {
2034
2035			  case CONN_IN_PREPARING:
2036				party = cc_party_create(conn,
2037				    pcr->epref.epref, 1);
2038				if (party == NULL)
2039					break;
2040				cc_party_set_state(party,
2041				    PARTY_WAIT_SETUP_COMPL);
2042				break;
2043
2044			  case CONN_OUT_WAIT_OK:
2045				party = cc_party_create(conn,
2046				    pcr->epref.epref, 0);
2047				if (party == NULL)
2048					break;
2049				cc_party_set_state(party,
2050				    PARTY_WAIT_SETUP_CONF);
2051				break;
2052
2053			  default:
2054				goto bad_state;
2055			}
2056			break;
2057		}
2058		/* this is for an ADD-PARTY */
2059		if (conn->state != CONN_ACTIVE)
2060			goto bad_state;
2061		if (party->state != PARTY_ADD_WAIT_CREATE)
2062			goto bad_party_state;
2063		cc_party_set_state(party, PARTY_ADD_WAIT_OK);
2064		break;
2065	    }
2066
2067	  case CONN_SIG_PARTY_DESTROYED:
2068	    {
2069		struct uni_msg *msg = arg;
2070		struct uniapi_party_destroyed *pcr = uni_msg_rptr(msg,
2071		    struct uniapi_party_destroyed *);
2072
2073		party = cc_party_find(conn, pcr->epref.epref);
2074		if (party == NULL) {
2075			cc_conn_log(conn, "no party to destroy %u/%u",
2076			    pcr->epref.flag, pcr->epref.epref);
2077			break;
2078		}
2079		cc_party_destroy(party);
2080		break;
2081	    }
2082
2083	}
2084
2085	return;
2086
2087  bad_state:
2088	cc_conn_log(conn, "bad state=%s for signal=%s",
2089	    stab[conn->state], cc_conn_sigtab[sig]);
2090	return;
2091
2092  bad_party_state:
2093	cc_conn_log(conn, "bad party state=%s for signal=%s",
2094	    ptab[party->state], cc_conn_sigtab[sig]);
2095	return;
2096}
2097