]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/ngatm/netnatm/api/cc_conn.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / ngatm / netnatm / api / cc_conn.c
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
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 *
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
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 *
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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
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 *
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
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
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
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
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
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
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
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
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 }