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