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 <[email protected]>
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 
49 static const char *stab[] = {
50 #define DEF(N) [N] = #N,
51 	CONN_STATES
52 #undef DEF
53 };
54 
55 static const char *ptab[] = {
56 #define DEF(N) [PARTY_##N] = #N,
57 	PARTY_STATES
58 #undef DEF
59 };
60 
61 const char *
cc_conn_state2str(u_int s)62 cc_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 
69 void
cc_conn_set_state(struct ccconn * conn,enum conn_state ns)70 cc_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 
80 const char *
cc_party_state2str(u_int s)81 cc_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 
88 void
cc_party_set_state(struct ccparty * party,enum party_state ns)89 cc_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  */
103 void
cc_disconnect_from_user(struct ccconn * conn)104 cc_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  */
119 void
cc_connect_to_user(struct ccconn * conn,struct ccuser * user)120 cc_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  */
133 static void
cc_send_uni(struct ccconn * conn,u_int op,struct uni_msg * msg)134 cc_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  */
160 static void
do_release_request(struct ccconn * conn,const struct uni_ie_cause cause[2])161 do_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  */
191 static void
do_release_response(struct ccconn * conn,uint8_t cause,struct uni_ie_cause * ie)192 do_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  */
223 struct ccconn *
cc_conn_create(struct ccdata * cc)224 cc_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  */
248 void
cc_conn_ins_port(struct ccconn * conn,struct ccport * port)249 cc_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  */
267 void
cc_conn_rem_port(struct ccconn * conn)268 cc_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 
280 static void
cc_conn_flush_cookies(struct ccconn * conn)281 cc_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 
295 void
cc_conn_reset_acceptor(struct ccconn * conn)296 cc_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  */
307 void
cc_conn_destroy(struct ccconn * conn)308 cc_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 
336 struct ccparty *
cc_party_create(struct ccconn * conn,u_int ident,u_int flag)337 cc_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 
358 static void
cc_party_destroy(struct ccparty * party)359 cc_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 
370 static struct ccparty *
cc_party_find(struct ccconn * conn,u_int ident)371 cc_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  */
388 void
cc_conn_abort(struct ccconn * conn,int shutdown)389 cc_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
547 static void
print_sap(const struct uni_sap * sap)548 print_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  */
597 void
cc_conn_dispatch(struct ccconn * conn)598 cc_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 
701 static void
cc_party_setup_conf(struct ccconn * conn)702 cc_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 
720 static void
cc_party_add_ack_ind(struct ccconn * conn,const struct uni_ie_epref * epref)721 cc_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 
741 static void
cc_party_add_rej_ind(struct ccconn * conn,const struct uni_ie_epref * epref)742 cc_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 
762 static void
cc_party_drop_ack_ind(struct ccconn * conn,const struct uni_drop_party * drop)763 cc_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  */
813 void
cc_conn_sig_handle(struct ccconn * conn,enum conn_sig sig,void * arg,u_int iarg)814 cc_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