1131826Sharti/* 2171364Sharti * Copyright (c) 2003-2007 3131826Sharti * Hartmut Brandt 4131826Sharti * All rights reserved. 5131826Sharti * 6131826Sharti * Copyright (c) 2001-2002 7131826Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 8131826Sharti * All rights reserved. 9131826Sharti * 10131826Sharti * Author: Harti Brandt <harti@freebsd.org> 11131826Sharti * 12131826Sharti * Redistribution of this software and documentation and use in source and 13131826Sharti * binary forms, with or without modification, are permitted provided that 14131826Sharti * the following conditions are met: 15131826Sharti * 16131826Sharti * 1. Redistributions of source code or documentation must retain the above 17131826Sharti * copyright notice, this list of conditions and the following disclaimer. 18131826Sharti * 2. Redistributions in binary form must reproduce the above copyright 19131826Sharti * notice, this list of conditions and the following disclaimer in the 20131826Sharti * documentation and/or other materials provided with the distribution. 21131826Sharti * 22131826Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 23131826Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 24131826Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 25131826Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26131826Sharti * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27131826Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28131826Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29131826Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30131826Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31131826Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32131826Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33131826Sharti * 34171364Sharti * $Id: cc_conn.c 1291 2007-07-10 10:35:38Z brandt_h $ 35131826Sharti * 36131826Sharti * ATM API as defined per af-saa-0108 37131826Sharti * 38131826Sharti * Lower half - connection handling 39131826Sharti */ 40131826Sharti#include <netnatm/unimsg.h> 41131826Sharti#include <netnatm/msg/unistruct.h> 42131826Sharti#include <netnatm/msg/unimsglib.h> 43131826Sharti#include <netnatm/api/unisap.h> 44131826Sharti#include <netnatm/sig/unidef.h> 45131826Sharti#include <netnatm/api/atmapi.h> 46131826Sharti#include <netnatm/api/ccatm.h> 47131826Sharti#include <netnatm/api/ccpriv.h> 48131826Sharti 49131826Shartistatic const char *stab[] = { 50131826Sharti#define DEF(N) [N] = #N, 51131826Sharti CONN_STATES 52131826Sharti#undef DEF 53131826Sharti}; 54131826Sharti 55131826Shartistatic const char *ptab[] = { 56131826Sharti#define DEF(N) [PARTY_##N] = #N, 57131826Sharti PARTY_STATES 58131826Sharti#undef DEF 59131826Sharti}; 60131826Sharti 61131826Sharticonst char * 62131826Sharticc_conn_state2str(u_int s) 63131826Sharti{ 64131826Sharti if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL) 65131826Sharti return ("?"); 66131826Sharti return (stab[s]); 67131826Sharti} 68131826Sharti 69171364Shartivoid 70131826Sharticc_conn_set_state(struct ccconn *conn, enum conn_state ns) 71131826Sharti{ 72131826Sharti if (conn->state != ns) { 73131826Sharti if (conn->cc->log & CCLOG_CONN_STATE) 74131826Sharti cc_conn_log(conn, "%s -> %s", 75131826Sharti stab[conn->state], stab[ns]); 76131826Sharti conn->state = ns; 77131826Sharti } 78131826Sharti} 79131826Sharti 80131826Sharticonst char * 81131826Sharticc_party_state2str(u_int s) 82131826Sharti{ 83131826Sharti if (s >= sizeof(ptab) / sizeof(ptab[0]) || ptab[s] == NULL) 84131826Sharti return ("?"); 85131826Sharti return (ptab[s]); 86131826Sharti} 87131826Sharti 88171364Shartivoid 89131826Sharticc_party_set_state(struct ccparty *party, enum party_state ns) 90131826Sharti{ 91131826Sharti 92131826Sharti if (party->state != ns) { 93131826Sharti if (party->conn->cc->log & CCLOG_PARTY_STATE) 94131826Sharti cc_party_log(party, "%s -> %s", 95131826Sharti ptab[party->state], ptab[ns]); 96131826Sharti party->state = ns; 97131826Sharti } 98131826Sharti} 99131826Sharti 100131826Sharti/* 101131826Sharti * Remove connection from its user's queue 102131826Sharti */ 103171364Shartivoid 104131826Sharticc_disconnect_from_user(struct ccconn *conn) 105131826Sharti{ 106131826Sharti 107131826Sharti if (conn->user == NULL) 108131826Sharti cc_conn_log(conn, "no %s", "user"); 109131826Sharti else { 110131826Sharti TAILQ_REMOVE(&conn->user->connq, conn, connq_link); 111131826Sharti conn->user->queue_act--; 112131826Sharti conn->user = NULL; 113131826Sharti } 114131826Sharti} 115131826Sharti 116131826Sharti/* 117131826Sharti * Put connection on user queue 118131826Sharti */ 119171364Shartivoid 120131826Sharticc_connect_to_user(struct ccconn *conn, struct ccuser *user) 121131826Sharti{ 122131826Sharti 123131826Sharti if (conn->user != NULL) 124131826Sharti cc_conn_log(conn, "still connected to %p", conn->user); 125131826Sharti conn->user = user; 126131826Sharti TAILQ_INSERT_TAIL(&user->connq, conn, connq_link); 127131826Sharti conn->user->queue_act++; 128131826Sharti} 129131826Sharti 130131826Sharti/* 131131826Sharti * Send a signal to the UNI stack for this connection 132131826Sharti */ 133131826Shartistatic void 134131826Sharticc_send_uni(struct ccconn *conn, u_int op, struct uni_msg *msg) 135131826Sharti{ 136131826Sharti struct ccreq *r; 137131826Sharti 138131826Sharti r = CCZALLOC(sizeof(*r)); 139131826Sharti if (r == NULL) { 140131826Sharti if (msg != NULL) 141131826Sharti uni_msg_destroy(msg); 142133492Sharti cc_conn_log(conn, "no memory for cookie op=%u", op); 143131826Sharti return; 144131826Sharti } 145131826Sharti 146131826Sharti if ((r->cookie = ++conn->port->cc->cookie) == 0) 147131826Sharti r->cookie = ++conn->port->cc->cookie; 148131826Sharti r->req = op; 149131826Sharti r->conn = conn; 150131826Sharti 151131826Sharti TAILQ_INSERT_TAIL(&conn->port->cookies, r, link); 152131826Sharti 153131826Sharti conn->port->cc->funcs->send_uni(conn, conn->port->uarg, op, 154131826Sharti r->cookie, msg); 155131826Sharti} 156131826Sharti 157131826Sharti/* 158131826Sharti * Send a RELEASE.request for this connection. 159131826Sharti */ 160131826Shartistatic void 161131826Shartido_release_request(struct ccconn *conn, const struct uni_ie_cause cause[2]) 162131826Sharti{ 163131826Sharti struct uni_msg *u; 164131826Sharti struct uniapi_release_request *req; 165131826Sharti 166131826Sharti if ((u = uni_msg_alloc(sizeof(*req))) == NULL) 167131826Sharti return; 168131826Sharti req = uni_msg_wptr(u, struct uniapi_release_request *); 169131826Sharti memset(req, 0, sizeof(*req)); 170131826Sharti u->b_wptr += sizeof(struct uniapi_release_request); 171131826Sharti 172131826Sharti req->release.hdr.cref = conn->cref; 173131826Sharti req->release.hdr.act = UNI_MSGACT_DEFAULT; 174131826Sharti 175131826Sharti if (cause == NULL) { 176131826Sharti IE_SETPRESENT(req->release.cause[0]); 177131826Sharti req->release.cause[0].h.act = UNI_IEACT_DEFAULT; 178131826Sharti req->release.cause[0].loc = UNI_CAUSE_LOC_USER; 179131826Sharti req->release.cause[0].cause = UNI_CAUSE_UNSPEC; 180131826Sharti } else { 181131826Sharti req->release.cause[0] = cause[0]; 182131826Sharti req->release.cause[1] = cause[1]; 183131826Sharti } 184131826Sharti 185131826Sharti cc_send_uni(conn, UNIAPI_RELEASE_request, u); 186131826Sharti} 187131826Sharti 188131826Sharti/* 189131826Sharti * Make a RELEASE.response for this connection 190131826Sharti */ 191131826Shartistatic void 192131826Shartido_release_response(struct ccconn *conn, uint8_t cause, struct uni_ie_cause *ie) 193131826Sharti{ 194131826Sharti struct uni_msg *u; 195131826Sharti struct uniapi_release_response *resp; 196131826Sharti 197131826Sharti if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) 198131826Sharti return; 199131826Sharti resp = uni_msg_wptr(u, struct uniapi_release_response *); 200131826Sharti memset(resp, 0, sizeof(*resp)); 201131826Sharti u->b_wptr += sizeof(struct uniapi_release_response); 202131826Sharti 203131826Sharti resp->release_compl.hdr.cref = conn->cref; 204131826Sharti resp->release_compl.hdr.act = UNI_MSGACT_DEFAULT; 205131826Sharti 206131826Sharti if (ie != NULL) 207131826Sharti resp->release_compl.cause[0] = *ie; 208131826Sharti 209131826Sharti if (cause != 0) { 210131826Sharti IE_SETPRESENT(resp->release_compl.cause[0]); 211131826Sharti resp->release_compl.cause[0].h.act = UNI_IEACT_DEFAULT; 212131826Sharti resp->release_compl.cause[0].loc = UNI_CAUSE_LOC_USER; 213131826Sharti resp->release_compl.cause[0].cause = cause; 214131826Sharti } 215131826Sharti 216131826Sharti cc_send_uni(conn, UNIAPI_RELEASE_response, u); 217131826Sharti} 218131826Sharti 219131826Sharti/********************************************************************** 220131826Sharti * 221131826Sharti * INSTANCE handling 222131826Sharti */ 223131826Shartistruct ccconn * 224131826Sharticc_conn_create(struct ccdata *cc) 225131826Sharti{ 226131826Sharti struct ccconn *conn; 227131826Sharti 228131826Sharti conn = CCZALLOC(sizeof(*conn)); 229131826Sharti if (conn == NULL) 230131826Sharti return (NULL); 231131826Sharti 232131826Sharti conn->state = CONN_NULL; 233131826Sharti conn->port = NULL; 234131826Sharti conn->cc = cc; 235131826Sharti LIST_INIT(&conn->parties); 236131826Sharti 237131826Sharti LIST_INSERT_HEAD(&cc->orphaned_conns, conn, port_link); 238131826Sharti 239131826Sharti if (conn->cc->log & CCLOG_CONN_INST) 240131826Sharti cc_conn_log(conn, "created %s", "orphaned"); 241131826Sharti 242131826Sharti return (conn); 243131826Sharti} 244131826Sharti 245131826Sharti/* 246131826Sharti * assign to port 247131826Sharti */ 248131826Shartivoid 249131826Sharticc_conn_ins_port(struct ccconn *conn, struct ccport *port) 250131826Sharti{ 251131826Sharti 252131826Sharti if (conn->port != NULL) { 253131826Sharti cc_conn_log(conn, "conn is already on port %u", 254131826Sharti conn->port->param.port); 255131826Sharti cc_conn_rem_port(conn); 256131826Sharti } 257131826Sharti LIST_REMOVE(conn, port_link); 258131826Sharti 259131826Sharti conn->port = port; 260131826Sharti LIST_INSERT_HEAD(&port->conn_list, conn, port_link); 261131826Sharti 262131826Sharti} 263131826Sharti 264131826Sharti/* 265131826Sharti * remove from port 266131826Sharti */ 267131826Shartivoid 268131826Sharticc_conn_rem_port(struct ccconn *conn) 269131826Sharti{ 270131826Sharti 271131826Sharti if (conn->port == NULL) { 272131826Sharti cc_conn_log(conn, "conn not on any %s", "port"); 273131826Sharti return; 274131826Sharti } 275131826Sharti LIST_REMOVE(conn, port_link); 276131826Sharti conn->port = NULL; 277131826Sharti LIST_INSERT_HEAD(&conn->cc->orphaned_conns, conn, port_link); 278131826Sharti} 279131826Sharti 280131826Shartistatic void 281131826Sharticc_conn_flush_cookies(struct ccconn *conn) 282131826Sharti{ 283131826Sharti struct ccreq *r, *r1; 284131826Sharti 285131826Sharti if (conn->port == NULL) 286131826Sharti return; 287131826Sharti TAILQ_FOREACH_SAFE(r, &conn->port->cookies, link, r1) { 288131826Sharti if (r->conn == conn) { 289131826Sharti TAILQ_REMOVE(&conn->port->cookies, r, link); 290131826Sharti CCFREE(r); 291131826Sharti } 292131826Sharti } 293131826Sharti} 294131826Sharti 295171364Shartivoid 296131826Sharticc_conn_reset_acceptor(struct ccconn *conn) 297131826Sharti{ 298131826Sharti if (conn->acceptor != NULL) { 299131826Sharti conn->acceptor->accepted = NULL; 300131826Sharti conn->acceptor = NULL; 301131826Sharti } 302131826Sharti} 303131826Sharti 304131826Sharti/* 305131826Sharti * Destroy a connection 306131826Sharti */ 307131826Shartivoid 308131826Sharticc_conn_destroy(struct ccconn *conn) 309131826Sharti{ 310131826Sharti struct ccparty *p; 311131826Sharti 312131826Sharti if (conn->cc->log & CCLOG_CONN_INST) 313131826Sharti cc_conn_log(conn, "destroy%s", ""); 314131826Sharti 315131826Sharti if (conn->user != NULL) { 316131826Sharti cc_conn_log(conn, "still connected to user %p\n", conn->user); 317131826Sharti conn->user->queue_act--; 318131826Sharti TAILQ_REMOVE(&conn->user->connq, conn, connq_link); 319131826Sharti } 320131826Sharti 321131826Sharti if (conn->acceptor != NULL) 322131826Sharti conn->acceptor->accepted = NULL; 323131826Sharti 324131826Sharti cc_conn_flush_cookies(conn); 325131826Sharti cc_conn_sig_flush(conn); 326131826Sharti 327131826Sharti LIST_REMOVE(conn, port_link); 328131826Sharti while ((p = LIST_FIRST(&conn->parties)) != NULL) { 329131826Sharti LIST_REMOVE(p, link); 330131826Sharti CCFREE(p); 331131826Sharti } 332131826Sharti 333131826Sharti CCFREE(conn); 334131826Sharti} 335131826Sharti 336131826Shartistruct ccparty * 337131826Sharticc_party_create(struct ccconn *conn, u_int ident, u_int flag) 338131826Sharti{ 339131826Sharti struct ccparty *party; 340131826Sharti 341131826Sharti party = CCZALLOC(sizeof(*party)); 342131826Sharti if (party == NULL) 343131826Sharti return (NULL); 344131826Sharti 345131826Sharti party->conn = conn; 346131826Sharti party->state = PARTY_NULL; 347131826Sharti IE_SETPRESENT(party->epref); 348131826Sharti party->epref.flag = flag; 349131826Sharti party->epref.epref = ident; 350131826Sharti LIST_INSERT_HEAD(&conn->parties, party, link); 351131826Sharti 352131826Sharti if (party->conn->cc->log & CCLOG_PARTY_INST) 353131826Sharti cc_party_log(party, "created %u.%u", flag, ident); 354131826Sharti 355131826Sharti return (party); 356131826Sharti} 357131826Sharti 358131826Shartistatic void 359131826Sharticc_party_destroy(struct ccparty *party) 360131826Sharti{ 361131826Sharti 362131826Sharti if (party->conn->cc->log & CCLOG_PARTY_INST) 363131826Sharti cc_party_log(party, "destroyed %u.%u", party->epref.flag, 364131826Sharti party->epref.epref); 365131826Sharti 366131826Sharti LIST_REMOVE(party, link); 367131826Sharti CCFREE(party); 368131826Sharti} 369131826Sharti 370131826Shartistatic struct ccparty * 371131826Sharticc_party_find(struct ccconn *conn, u_int ident) 372131826Sharti{ 373131826Sharti struct ccparty *party; 374131826Sharti 375131826Sharti LIST_FOREACH(party, &conn->parties, link) 376131826Sharti if (party->epref.epref == ident) 377131826Sharti return (party); 378131826Sharti return (NULL); 379131826Sharti} 380131826Sharti/* 381131826Sharti * Abort connection from down stream (because of the UNI hook beeing 382131826Sharti * disconnected). This is called from two places: 383131826Sharti * 1) the shutdown code. 384131826Sharti * In this case the connections should be already dissociated from 385131826Sharti * users and be only in states waiting for the UNI stack. 386131826Sharti * 2) from the disconnect code. 387131826Sharti */ 388131826Shartivoid 389131826Sharticc_conn_abort(struct ccconn *conn, int shutdown) 390131826Sharti{ 391131826Sharti struct ccuser *u = conn->user; 392131826Sharti struct ccparty *p, *p1; 393131826Sharti 394131826Sharti if (shutdown) { 395131826Sharti CCASSERT(u == NULL, ("still in use")); 396131826Sharti CCASSERT(conn->acceptor == NULL, ("still in use")); 397131826Sharti cc_conn_destroy(conn); 398131826Sharti return; 399131826Sharti } 400131826Sharti 401131826Sharti /* 402131826Sharti * Look whether any parties are blocked waiting for a response 403131826Sharti * from the stack. We don't use extra party states to handle 404131826Sharti * user aborts, so check that there is a user before using it. 405131826Sharti */ 406131826Sharti if (u == NULL) { 407131826Sharti while ((p = LIST_FIRST(&conn->parties)) != NULL) 408131826Sharti cc_party_destroy(p); 409131826Sharti } else { 410131826Sharti LIST_FOREACH_SAFE(p, &conn->parties, link, p1) { 411131826Sharti switch (p->state) { 412131826Sharti 413131826Sharti case PARTY_NULL: /* P0 */ 414131826Sharti /* should not happen */ 415131826Sharti goto dpty; 416131826Sharti 417131826Sharti case PARTY_ACTIVE: /* P1 */ 418131826Sharti /* don't send a drop - user'll get a rel */ 419131826Sharti goto dpty; 420131826Sharti 421131826Sharti case PARTY_ADD_WAIT_CREATE: /* P2 */ 422131826Sharti case PARTY_ADD_WAIT_OK: /* P3 */ 423131826Sharti /* we're adding - synthesise an error */ 424131826Sharti cc_user_sig(u, USER_SIG_ADD_PARTY_ERR, 425131826Sharti NULL, ATMERR_BAD_PORT); 426131826Sharti goto dpty; 427131826Sharti 428131826Sharti case PARTY_ADD_WAIT_ACK: /* P4 */ 429131826Sharti /* don't send a drop - user'll get a rel */ 430131826Sharti goto dpty; 431131826Sharti 432131826Sharti case PARTY_DROP_WAIT_OK: /* P5 */ 433131826Sharti case PARTY_DROP_WAIT_ACK: /* P6 */ 434131826Sharti case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 435131826Sharti /* we're dropping - synthesis an ok */ 436131826Sharti cc_user_sig(u, USER_SIG_DROP_PARTY_OK, 437131826Sharti NULL, p->epref.epref); 438131826Sharti goto dpty; 439131826Sharti 440131826Sharti case PARTY_WAIT_DESTROY: /* P7 */ 441131826Sharti goto dpty; 442131826Sharti 443131826Sharti case PARTY_WAIT_SETUP_COMPL: /* P8 */ 444131826Sharti case PARTY_WAIT_SETUP_CONF: /* P10 */ 445131826Sharti /* first party - nothing to do */ 446131826Sharti goto dpty; 447131826Sharti 448131826Sharti case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 449131826Sharti case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 450131826Sharti /* we're dropping - nothing to do */ 451131826Sharti goto dpty; 452131826Sharti } 453131826Sharti cc_party_log(p, "bad uabort for party in state %s", 454131826Sharti ptab[p->state]); 455131826Sharti dpty: 456131826Sharti cc_party_destroy(p); 457131826Sharti } 458131826Sharti } 459131826Sharti 460131826Sharti /* 461131826Sharti * Now do what the connection needs 462131826Sharti */ 463131826Sharti switch (conn->state) { 464131826Sharti 465131826Sharti case CONN_NULL: /* 0 */ 466131826Sharti case CONN_OUT_PREPARING: /* 1 */ 467131826Sharti /* may not happen because we're not associated with 468131826Sharti * aport yet */ 469131826Sharti break; 470131826Sharti 471131826Sharti case CONN_OUT_WAIT_CREATE: /* 2 */ 472131826Sharti case CONN_OUT_WAIT_OK: /* 3 */ 473131826Sharti case CONN_OUT_WAIT_DESTROY: /* 37 */ 474131826Sharti /* return an error to the user, go back to C1/U1 475131826Sharti * reset cref (for C37, C3) and cookie */ 476131826Sharti conn->cref.flag = 0; 477131826Sharti conn->cref.cref = 0; 478131826Sharti cc_conn_flush_cookies(conn); 479131826Sharti cc_conn_set_state(conn, CONN_OUT_PREPARING); 480131826Sharti cc_conn_rem_port(conn); 481131826Sharti cc_user_sig(u, USER_SIG_CONNECT_OUTGOING_ERR, 482131826Sharti NULL, ATMERR_BAD_PORT); 483131826Sharti return; 484131826Sharti 485131826Sharti case CONN_OUT_WAIT_CONF: /* 4 */ 486131826Sharti case CONN_ACTIVE: /* 5 */ 487131826Sharti case CONN_IN_WAIT_COMPL: /* 13 */ 488131826Sharti /* emulate a RELEASE.confirm */ 489131826Sharti memset(&u->cause, 0, sizeof(u->cause)); 490131826Sharti cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); 491131826Sharti cc_disconnect_from_user(conn); 492131826Sharti cc_conn_destroy(conn); 493131826Sharti return; 494131826Sharti 495131826Sharti case CONN_IN_PREPARING: /* 10 */ 496131826Sharti case CONN_AB_WAIT_REQ_OK: /* 33 */ 497131826Sharti case CONN_AB_WAIT_RESP_OK: /* 34 */ 498131826Sharti case CONN_AB_FLUSH_IND: /* 35 */ 499131826Sharti /* no user - destroy */ 500131826Sharti cc_conn_destroy(conn); 501131826Sharti return; 502131826Sharti 503131826Sharti case CONN_IN_ARRIVED: /* 11 */ 504131826Sharti u->aborted = 1; 505131826Sharti cc_disconnect_from_user(conn); 506131826Sharti cc_conn_destroy(conn); 507131826Sharti return; 508131826Sharti 509131826Sharti case CONN_IN_WAIT_ACCEPT_OK: /* 12 */ 510131826Sharti /* return ACCEPT error */ 511131826Sharti cc_disconnect_from_user(conn); 512131826Sharti cc_conn_reset_acceptor(conn); 513131826Sharti cc_user_sig(u, USER_SIG_ACCEPT_ERR, 514131826Sharti u, ATMERR_PREVIOUSLY_ABORTED); 515131826Sharti cc_conn_destroy(conn); 516131826Sharti return; 517131826Sharti 518131826Sharti case CONN_REJ_WAIT_OK: /* 14 */ 519131826Sharti /* return REJECT ok */ 520131826Sharti cc_disconnect_from_user(conn); 521131826Sharti cc_conn_destroy(conn); 522131826Sharti cc_user_sig(u, USER_SIG_REJECT_OK, NULL, 0); 523131826Sharti return; 524131826Sharti 525131826Sharti case CONN_REL_IN_WAIT_OK: /* 15 */ 526131826Sharti case CONN_REL_WAIT_OK: /* 20 */ 527131826Sharti /* confirm destroy */ 528131826Sharti if (u != NULL) { 529131826Sharti /* connection not aborted */ 530131826Sharti memset(&u->cause, 0, sizeof(u->cause)); 531131826Sharti cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); 532131826Sharti cc_disconnect_from_user(conn); 533131826Sharti } 534131826Sharti cc_conn_destroy(conn); 535131826Sharti return; 536131826Sharti 537131826Sharti case CONN_IN_WAITING: /* 21 */ 538131826Sharti /* user has not seen the connection - destroy */ 539131826Sharti cc_disconnect_from_user(conn); 540131826Sharti cc_conn_destroy(conn); 541131826Sharti return; 542131826Sharti } 543131826Sharti cc_conn_log(conn, "bad state %s", stab[conn->state]); 544131826Sharti} 545131826Sharti 546131826Sharti#ifdef DEBUG_MATCH 547131826Shartistatic void 548131826Shartiprint_sap(const struct uni_sap *sap) 549131826Sharti{ 550131826Sharti static const char *const tags[] = { 551131826Sharti [UNISVE_ABSENT] "absent", 552131826Sharti [UNISVE_PRESENT]"present", 553131826Sharti [UNISVE_ANY] "any", 554131826Sharti }; 555131826Sharti u_int i; 556131826Sharti 557131826Sharti printf("addr={%s", tags[sap->addr.tag]); 558131826Sharti if (sap->addr.tag == UNISVE_PRESENT) { 559131826Sharti printf(",%d-%d", sap->addr.type, sap->addr.plan); 560131826Sharti for (i = 0; i < sap->addr.len; i++) 561131826Sharti printf("%c%02x", ",:"[i!=0], sap->addr.addr[i]); 562131826Sharti } 563131826Sharti printf("}\n"); 564131826Sharti 565131826Sharti printf("selector={%s", tags[sap->selector.tag]); 566131826Sharti if (sap->selector.tag == UNISVE_PRESENT) 567131826Sharti printf(",%02x", sap->selector.selector); 568131826Sharti printf("}\n"); 569131826Sharti 570131826Sharti printf("blli_id2={%s", tags[sap->blli_id2.tag]); 571131826Sharti if (sap->blli_id2.tag == UNISVE_PRESENT) 572131826Sharti printf(",%02x,%02x", sap->blli_id2.proto, sap->blli_id2.user); 573131826Sharti printf("}\n"); 574131826Sharti 575131826Sharti printf("blli_id3={%s", tags[sap->blli_id3.tag]); 576131826Sharti if (sap->blli_id3.tag == UNISVE_PRESENT) 577131826Sharti printf(",%02x,%02x,%02x,%06x,%04x,%d", 578131826Sharti sap->blli_id3.proto, sap->blli_id3.user, 579131826Sharti sap->blli_id3.ipi, sap->blli_id3.oui, 580131826Sharti sap->blli_id3.pid, sap->blli_id3.noipi); 581131826Sharti printf("}\n"); 582131826Sharti 583131826Sharti printf("bhli={%s", tags[sap->bhli.tag]); 584131826Sharti if (sap->bhli.tag == UNISVE_PRESENT) { 585131826Sharti printf(",%d", sap->bhli.type); 586131826Sharti for (i = 0; i < sap->bhli.len; i++) 587131826Sharti printf("%c%02x", ",:"[i!=0], sap->bhli.info[i]); 588131826Sharti } 589131826Sharti printf("}\n"); 590131826Sharti} 591131826Sharti#endif 592131826Sharti 593131826Sharti/********************************************************************* 594131826Sharti * 595131826Sharti * DISPATCH incoming call 596131826Sharti */ 597131826Shartivoid 598131826Sharticc_conn_dispatch(struct ccconn *conn) 599131826Sharti{ 600131826Sharti struct ccdata *priv = conn->port->cc; 601131826Sharti struct ccuser *user; 602131826Sharti u_int blli_index; 603131826Sharti 604131826Sharti#ifdef DEBUG_MATCH 605131826Sharti static char buf[1000]; 606131826Sharti static struct unicx cx; 607131826Sharti static int init = 1; 608131826Sharti 609131826Sharti if (init) { 610131826Sharti uni_initcx(&cx); 611131826Sharti init = 0; 612131826Sharti } 613131826Sharti#endif 614131826Sharti 615131826Sharti /* 616131826Sharti * Do call dispatching according to 4.6 617131826Sharti */ 618131826Sharti#ifdef DEBUG_MATCH 619131826Sharti printf("+++++ DISPATCH++++++\n"); 620131826Sharti#endif 621131826Sharti for (blli_index = 0; blli_index < UNI_NUM_IE_BLLI; blli_index++) { 622131826Sharti if (blli_index > 0 && !IE_ISGOOD(conn->blli[blli_index])) 623131826Sharti break; 624131826Sharti#ifdef DEBUG_MATCH 625131826Sharti if (IE_ISPRESENT(conn->called)) { 626131826Sharti uni_print_ie(buf, sizeof(buf), UNI_IE_CALLED, 627131826Sharti (union uni_ieall *)&conn->called, &cx); 628131826Sharti printf("called=%s\n", buf); 629131826Sharti } 630131826Sharti if (IE_ISPRESENT(conn->bhli)) { 631131826Sharti uni_print_ie(buf, sizeof(buf), UNI_IE_BHLI, 632131826Sharti (union uni_ieall *)&conn->bhli, &cx); 633131826Sharti printf("bhli=%s\n", buf); 634131826Sharti } 635131826Sharti if (IE_ISPRESENT(conn->blli[blli_index])) { 636131826Sharti uni_print_ie(buf, sizeof(buf), UNI_IE_BLLI, 637131826Sharti (union uni_ieall *)&conn->blli[blli_index], &cx); 638131826Sharti printf("%s\n", buf); 639131826Sharti } 640131826Sharti#endif 641131826Sharti LIST_FOREACH(user, &priv->user_list, node_link) { 642131826Sharti if ((user->state == USER_IN_WAITING || 643131826Sharti user->state == USER_IN_ARRIVED || 644131826Sharti user->state == USER_IN_WAIT_ACC || 645131826Sharti user->state == USER_IN_WAIT_REJ) && 646131826Sharti !unisve_is_catchall(user->sap)) { 647131826Sharti#ifdef DEBUG_MATCH 648131826Sharti printf("TRYING user=%p\n", user); 649131826Sharti print_sap(user->sap); 650131826Sharti#endif 651131826Sharti if (unisve_match(user->sap, &conn->called, 652131826Sharti &conn->blli[blli_index], &conn->bhli)) 653131826Sharti goto found; 654131826Sharti } 655131826Sharti } 656131826Sharti } 657131826Sharti#ifdef DEBUG_MATCH 658131826Sharti printf("TRYING CATCHALL\n"); 659131826Sharti#endif 660131826Sharti blli_index = 0; 661131826Sharti LIST_FOREACH(user, &priv->user_list, node_link) { 662131826Sharti if ((user->state == USER_IN_WAITING || 663131826Sharti user->state == USER_IN_ARRIVED || 664131826Sharti user->state == USER_IN_WAIT_ACC || 665131826Sharti user->state == USER_IN_WAIT_REJ) && 666131826Sharti unisve_is_catchall(user->sap)) 667131826Sharti goto found; 668131826Sharti } 669131826Sharti#ifdef DEBUG_MATCH 670131826Sharti printf("SORRY\n"); 671131826Sharti#endif 672131826Sharti 673131826Sharti /* 674131826Sharti * No application found - reject call. 675131826Sharti */ 676131826Sharti do_release_response(conn, UNI_CAUSE_INCOMP, NULL); 677131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 678131826Sharti return; 679131826Sharti 680131826Sharti found: 681131826Sharti#ifdef DEBUG_MATCH 682131826Sharti printf("MATCH\n"); 683131826Sharti#endif 684131826Sharti if (user->queue_max == user->queue_act) { 685131826Sharti do_release_response(conn, UNI_CAUSE_BUSY, NULL); 686131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 687131826Sharti return; 688131826Sharti } 689131826Sharti 690131826Sharti if (blli_index == 0 && !IE_ISGOOD(conn->blli[blli_index])) 691131826Sharti conn->blli_selector = 0; 692131826Sharti else 693131826Sharti conn->blli_selector = blli_index + 1; 694131826Sharti 695131826Sharti cc_conn_set_state(conn, CONN_IN_WAITING); 696131826Sharti cc_connect_to_user(conn, user); 697131826Sharti 698131826Sharti cc_user_sig(user, USER_SIG_SETUP_IND, NULL, 0); 699131826Sharti} 700131826Sharti 701131826Shartistatic void 702131826Sharticc_party_setup_conf(struct ccconn *conn) 703131826Sharti{ 704131826Sharti struct ccparty *party; 705131826Sharti 706131826Sharti party = cc_party_find(conn, conn->epref.epref); 707131826Sharti if (party == NULL) { 708131826Sharti cc_party_log(party, "no party for %s", 709131826Sharti cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); 710131826Sharti return; 711131826Sharti } 712131826Sharti if (party->state != PARTY_WAIT_SETUP_CONF) { 713131826Sharti cc_party_log(party, "bad state=%s for signal=%s", 714131826Sharti ptab[party->state], cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); 715131826Sharti return; 716131826Sharti } 717131826Sharti cc_party_set_state(party, PARTY_ACTIVE); 718131826Sharti} 719131826Sharti 720131826Shartistatic void 721131826Sharticc_party_add_ack_ind(struct ccconn *conn, const struct uni_ie_epref *epref) 722131826Sharti{ 723131826Sharti struct ccparty *party; 724131826Sharti 725131826Sharti party = cc_party_find(conn, epref->epref); 726131826Sharti if (party == NULL) { 727131826Sharti cc_party_log(party, "no party for %s", 728131826Sharti cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); 729131826Sharti } 730131826Sharti if (party->state != PARTY_ADD_WAIT_ACK) { 731131826Sharti cc_party_log(party, "bad state=%s for signal=%s", 732131826Sharti ptab[party->state], 733131826Sharti cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); 734131826Sharti return; 735131826Sharti } 736131826Sharti cc_party_set_state(party, PARTY_ACTIVE); 737131826Sharti cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ACK, 738131826Sharti NULL, epref->epref); 739131826Sharti} 740131826Sharti 741131826Shartistatic void 742131826Sharticc_party_add_rej_ind(struct ccconn *conn, const struct uni_ie_epref *epref) 743131826Sharti{ 744131826Sharti struct ccparty *party; 745131826Sharti 746131826Sharti party = cc_party_find(conn, epref->epref); 747131826Sharti if (party == NULL) { 748131826Sharti cc_party_log(party, "no party for %s", 749131826Sharti cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); 750131826Sharti return; 751131826Sharti } 752131826Sharti if (party->state != PARTY_ADD_WAIT_ACK) { 753131826Sharti cc_party_log(party, "bad state=%s for signal=%s", 754131826Sharti ptab[party->state], 755131826Sharti cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); 756131826Sharti return; 757131826Sharti } 758131826Sharti cc_party_set_state(party, PARTY_WAIT_DESTROY); 759131826Sharti cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, NULL, epref->epref); 760131826Sharti} 761131826Sharti 762131826Shartistatic void 763131826Sharticc_party_drop_ack_ind(struct ccconn *conn, 764131826Sharti const struct uni_drop_party *drop) 765131826Sharti{ 766131826Sharti struct ccparty *party; 767131826Sharti 768131826Sharti party = cc_party_find(conn, drop->epref.epref); 769131826Sharti if (party == NULL) { 770131826Sharti cc_party_log(party, "no party for %s", 771201818Strasz cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]); 772131826Sharti return; 773131826Sharti } 774131826Sharti switch (party->state) { 775131826Sharti 776131826Sharti case PARTY_ACTIVE: /* P1 */ 777131826Sharti memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 778131826Sharti conn->user->cause[0] = drop->cause; 779131826Sharti cc_party_set_state(party, PARTY_WAIT_DESTROY); 780131826Sharti cc_user_sig(conn->user, USER_SIG_DROP_PARTY_IND, 781131826Sharti NULL, party->epref.epref); 782131826Sharti break; 783131826Sharti 784131826Sharti case PARTY_ADD_WAIT_ACK: /* P4 */ 785131826Sharti memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 786131826Sharti conn->user->cause[0] = drop->cause; 787131826Sharti cc_party_set_state(party, PARTY_WAIT_DESTROY); 788131826Sharti cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, 789131826Sharti NULL, party->epref.epref); 790131826Sharti break; 791131826Sharti 792131826Sharti case PARTY_DROP_WAIT_ACK: /* P6 */ 793131826Sharti cc_party_set_state(party, PARTY_WAIT_DESTROY); 794131826Sharti cc_user_sig(conn->user, USER_SIG_DROP_PARTY_OK, NULL, 0); 795131826Sharti break; 796131826Sharti 797131826Sharti case PARTY_WAIT_SETUP_COMPL: /* P8 */ 798131826Sharti case PARTY_WAIT_SETUP_CONF: /* P10 */ 799131826Sharti cc_party_set_state(party, PARTY_WAIT_DESTROY); 800131826Sharti break; 801131826Sharti 802131826Sharti default: 803131826Sharti cc_party_log(party, "bad state=%s for signal=%s", 804131826Sharti ptab[party->state], 805131826Sharti cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]); 806131826Sharti break; 807131826Sharti } 808131826Sharti} 809131826Sharti 810131826Sharti/* 811131826Sharti * Handle a signal to this connection 812131826Sharti */ 813131826Shartivoid 814131826Sharticc_conn_sig_handle(struct ccconn *conn, enum conn_sig sig, 815131826Sharti void *arg, u_int iarg) 816131826Sharti{ 817131826Sharti struct ccparty *party; 818131826Sharti 819131826Sharti if (conn->cc->log & CCLOG_CONN_SIG) 820131826Sharti cc_conn_log(conn, "signal %s in state %s", cc_conn_sigtab[sig], 821131826Sharti stab[conn->state]); 822131826Sharti 823131826Sharti switch (sig) { 824131826Sharti 825131826Sharti case CONN_SIG_CONNECT_OUTGOING: 826131826Sharti /* Do SETUP */ 827131826Sharti { 828131826Sharti struct uni_msg *u; 829131826Sharti struct uniapi_setup_request *setup; 830131826Sharti 831131826Sharti if (conn->state != CONN_OUT_PREPARING) 832131826Sharti goto bad_state; 833131826Sharti 834131826Sharti if (IE_ISGOOD(conn->bearer) && 835131826Sharti conn->bearer.cfg == UNI_BEARER_MP) { 836131826Sharti IE_SETPRESENT(conn->epref); 837131826Sharti conn->epref.flag = 0; 838131826Sharti conn->epref.epref = 0; 839131826Sharti } 840131826Sharti 841131826Sharti /* 842131826Sharti * Construct message to UNI. 843131826Sharti */ 844131826Sharti u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); 845131826Sharti if (u == NULL) { 846131826Sharti cc_user_sig(conn->user, USER_SIG_CONNECT_OUTGOING_ERR, 847131826Sharti NULL, ATMERR_NOMEM); 848131826Sharti return; 849131826Sharti } 850131826Sharti setup = uni_msg_wptr(u, struct uniapi_setup_request *); 851131826Sharti memset(setup, 0, sizeof(*setup)); 852131826Sharti u->b_wptr += sizeof(struct uniapi_setup_request); 853131826Sharti 854131826Sharti setup->setup.hdr.act = UNI_MSGACT_DEFAULT; 855131826Sharti memcpy(setup->setup.blli, conn->blli, sizeof(conn->blli)); 856131826Sharti setup->setup.bearer = conn->bearer; 857131826Sharti setup->setup.traffic = conn->traffic; 858131826Sharti setup->setup.qos = conn->qos; 859131826Sharti setup->setup.exqos = conn->exqos; 860131826Sharti setup->setup.called = conn->called; 861131826Sharti setup->setup.calledsub[0] = conn->calledsub; 862131826Sharti setup->setup.aal = conn->aal; 863131826Sharti setup->setup.epref = conn->epref; 864131826Sharti setup->setup.eetd = conn->eetd; 865131826Sharti setup->setup.abrsetup = conn->abrsetup; 866131826Sharti setup->setup.abradd = conn->abradd; 867131826Sharti setup->setup.calling = conn->calling; 868131826Sharti setup->setup.callingsub[0] = conn->callingsub; 869131826Sharti setup->setup.connid = conn->connid; 870131826Sharti memcpy(setup->setup.tns, conn->tns, sizeof(conn->tns)); 871131826Sharti setup->setup.atraffic = conn->atraffic; 872131826Sharti setup->setup.mintraffic = conn->mintraffic; 873131826Sharti setup->setup.cscope = conn->cscope; 874131826Sharti setup->setup.bhli = conn->bhli; 875131826Sharti setup->setup.mdcr = conn->mdcr; 876131826Sharti 877131826Sharti cc_conn_set_state(conn, CONN_OUT_WAIT_CREATE); 878131826Sharti cc_send_uni(conn, UNIAPI_SETUP_request, u); 879131826Sharti 880131826Sharti break; 881131826Sharti } 882131826Sharti 883131826Sharti 884131826Sharti case CONN_SIG_ARRIVAL: 885131826Sharti /* user informed of arrival of this call */ 886131826Sharti if (conn->state != CONN_IN_WAITING) 887131826Sharti goto bad_state; 888131826Sharti cc_conn_set_state(conn, CONN_IN_ARRIVED); 889131826Sharti break; 890131826Sharti 891131826Sharti 892131826Sharti case CONN_SIG_RELEASE: 893131826Sharti { 894131826Sharti /* Release this call */ 895131826Sharti struct uni_msg *u; 896131826Sharti struct uniapi_release_request *req; 897131826Sharti 898131826Sharti if (conn->state != CONN_ACTIVE && 899131826Sharti conn->state != CONN_IN_WAIT_COMPL) 900131826Sharti goto bad_state; 901131826Sharti 902131826Sharti if ((u = uni_msg_alloc(sizeof(*req))) == NULL) 903131826Sharti return; 904131826Sharti 905131826Sharti req = uni_msg_wptr(u, struct uniapi_release_request *); 906131826Sharti memset(req, 0, sizeof(*req)); 907131826Sharti u->b_wptr += sizeof(struct uniapi_release_request); 908131826Sharti 909131826Sharti req->release.hdr.cref = conn->cref; 910131826Sharti req->release.hdr.act = UNI_MSGACT_DEFAULT; 911131826Sharti 912131826Sharti req->release.cause[0] = conn->cause[0]; 913131826Sharti req->release.cause[1] = conn->cause[1]; 914131826Sharti 915131826Sharti if (conn->state == CONN_ACTIVE) 916131826Sharti cc_conn_set_state(conn, CONN_REL_WAIT_OK); 917131826Sharti else 918131826Sharti cc_conn_set_state(conn, CONN_REL_IN_WAIT_OK); 919131826Sharti 920131826Sharti cc_send_uni(conn, UNIAPI_RELEASE_request, u); 921131826Sharti break; 922131826Sharti } 923131826Sharti 924131826Sharti case CONN_SIG_REJECT: 925131826Sharti { 926131826Sharti /* reject from user */ 927131826Sharti struct ccuser *user = conn->user; 928131826Sharti 929131826Sharti if (conn->state != CONN_IN_ARRIVED) { 930131826Sharti cc_user_sig(user, USER_SIG_REJECT_ERR, 931131826Sharti NULL, ATMERR_BAD_STATE); 932131826Sharti break; 933131826Sharti } 934131826Sharti cc_conn_set_state(conn, CONN_REJ_WAIT_OK); 935131826Sharti do_release_response(conn, 0, conn->cause); 936131826Sharti break; 937131826Sharti } 938131826Sharti 939131826Sharti 940131826Sharti case CONN_SIG_ACCEPT: 941131826Sharti { 942131826Sharti /* User accepts. */ 943131826Sharti struct ccuser *newep = arg; 944131826Sharti struct uni_msg *u; 945131826Sharti struct uniapi_setup_response *resp; 946131826Sharti struct ccuser *user = conn->user; 947131826Sharti 948131826Sharti if (conn->state != CONN_IN_ARRIVED) { 949131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_ERR, 950131826Sharti NULL, ATMERR_PREVIOUSLY_ABORTED); 951131826Sharti break; 952131826Sharti } 953131826Sharti 954131826Sharti u = uni_msg_alloc(sizeof(struct uniapi_setup_response)); 955131826Sharti if (u == NULL) { 956131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_ERR, 957131826Sharti NULL, ATMERR_NOMEM); 958131826Sharti return; 959131826Sharti } 960131826Sharti 961131826Sharti /* 962131826Sharti * Link to the new endpoint 963131826Sharti */ 964131826Sharti conn->acceptor = newep; 965131826Sharti newep->accepted = conn; 966131826Sharti 967131826Sharti /* 968131826Sharti * Construct connect message 969131826Sharti */ 970131826Sharti resp = uni_msg_wptr(u, struct uniapi_setup_response *); 971131826Sharti memset(resp, 0, sizeof(*resp)); 972131826Sharti u->b_wptr += sizeof(*resp); 973131826Sharti 974131826Sharti resp->connect.hdr.act = UNI_MSGACT_DEFAULT; 975131826Sharti resp->connect.hdr.cref = conn->cref; 976131826Sharti 977131826Sharti /* 978131826Sharti * attributes 979131826Sharti */ 980213788Srpaulo if (conn->dirty_attr & CCDIRTY_AAL) 981131826Sharti resp->connect.aal = conn->aal; 982213788Srpaulo if (conn->dirty_attr & CCDIRTY_BLLI) 983131826Sharti resp->connect.blli = 984131826Sharti conn->blli[conn->blli_selector - 1]; 985213788Srpaulo if (conn->dirty_attr & CCDIRTY_CONNID) 986131826Sharti resp->connect.connid = conn->connid; 987131826Sharti /* XXX NOTIFY */ 988213788Srpaulo if (conn->dirty_attr & CCDIRTY_EETD) 989131826Sharti resp->connect.eetd = conn->eetd; 990131826Sharti /* XXX GIT */ 991131826Sharti /* XXX UU */ 992213788Srpaulo if (conn->dirty_attr & CCDIRTY_TRAFFIC) 993131826Sharti resp->connect.traffic = conn->traffic; 994213788Srpaulo if (conn->dirty_attr & CCDIRTY_EXQOS) 995131826Sharti resp->connect.exqos = conn->exqos; 996213788Srpaulo if (conn->dirty_attr & CCDIRTY_ABRSETUP) 997131826Sharti resp->connect.abrsetup = conn->abrsetup; 998213788Srpaulo if (conn->dirty_attr & CCDIRTY_ABRADD) 999131826Sharti resp->connect.abradd = conn->abradd; 1000131826Sharti 1001131826Sharti /* 1002131826Sharti * If the SETUP had an endpoint reference - echo it back 1003131826Sharti */ 1004131826Sharti if (IE_ISPRESENT(conn->epref)) { 1005131826Sharti resp->connect.epref = conn->epref; 1006131826Sharti resp->connect.epref.flag = !resp->connect.epref.flag; 1007131826Sharti } 1008131826Sharti 1009131826Sharti cc_conn_set_state(conn, CONN_IN_WAIT_ACCEPT_OK); 1010131826Sharti cc_send_uni(conn, UNIAPI_SETUP_response, u); 1011131826Sharti break; 1012131826Sharti } 1013131826Sharti 1014131826Sharti 1015131826Sharti case CONN_SIG_ADD_PARTY: 1016131826Sharti { 1017131826Sharti /* request to add party from user */ 1018131826Sharti struct uni_msg *u; 1019131826Sharti struct uniapi_add_party_request *req; 1020131826Sharti 1021131826Sharti if (conn->state != CONN_ACTIVE) 1022131826Sharti goto bad_state; 1023131826Sharti 1024131826Sharti /* create the party */ 1025131826Sharti party = cc_party_create(conn, (u_int)(uintptr_t)arg, 0); 1026131826Sharti if (party == NULL) { 1027131826Sharti cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, 1028131826Sharti NULL, ATMERR_NOMEM); 1029131826Sharti return; 1030131826Sharti } 1031131826Sharti party->called = conn->called; 1032131826Sharti 1033131826Sharti /* Construct message to UNI. */ 1034131826Sharti u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); 1035131826Sharti if (u == NULL) { 1036131826Sharti cc_party_destroy(party); 1037131826Sharti cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, 1038131826Sharti NULL, ATMERR_NOMEM); 1039131826Sharti return; 1040131826Sharti } 1041131826Sharti 1042131826Sharti req = uni_msg_wptr(u, struct uniapi_add_party_request *); 1043131826Sharti memset(req, 0, sizeof(*req)); 1044131826Sharti u->b_wptr += sizeof(struct uniapi_add_party_request); 1045131826Sharti 1046131826Sharti req->add.hdr.act = UNI_MSGACT_DEFAULT; 1047131826Sharti req->add.hdr.cref = conn->cref; 1048131826Sharti req->add.epref = party->epref; 1049131826Sharti req->add.called = party->called; 1050131826Sharti 1051131826Sharti cc_party_set_state(party, PARTY_ADD_WAIT_CREATE); 1052131826Sharti cc_send_uni(conn, UNIAPI_ADD_PARTY_request, u); 1053131826Sharti break; 1054131826Sharti } 1055131826Sharti 1056131826Sharti 1057131826Sharti case CONN_SIG_DROP_PARTY: 1058131826Sharti { 1059131826Sharti /* user request to drop a party */ 1060131826Sharti struct uni_msg *u; 1061131826Sharti struct uniapi_drop_party_request *req; 1062131826Sharti 1063131826Sharti if (conn->state != CONN_ACTIVE) 1064131826Sharti goto bad_state; 1065131826Sharti 1066131826Sharti party = cc_party_find(conn, (u_int)(uintptr_t)arg); 1067131826Sharti if (party == NULL) { 1068131826Sharti cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1069131826Sharti NULL, ATMERR_BAD_PARTY); 1070131826Sharti return; 1071131826Sharti } 1072131826Sharti 1073131826Sharti switch (party->state) { 1074131826Sharti 1075131826Sharti case PARTY_ACTIVE: 1076131826Sharti case PARTY_ADD_WAIT_ACK: 1077131826Sharti break; 1078131826Sharti 1079131826Sharti default: 1080131826Sharti cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1081131826Sharti NULL, ATMERR_BAD_STATE); 1082131826Sharti return; 1083131826Sharti 1084131826Sharti } 1085131826Sharti /* 1086131826Sharti * Construct message to UNI. 1087131826Sharti */ 1088131826Sharti u = uni_msg_alloc(sizeof(*req)); 1089131826Sharti if (u == NULL) { 1090131826Sharti cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, 1091131826Sharti NULL, ATMERR_NOMEM); 1092131826Sharti return; 1093131826Sharti } 1094131826Sharti 1095131826Sharti req = uni_msg_wptr(u, struct uniapi_drop_party_request *); 1096131826Sharti memset(req, 0, sizeof(*req)); 1097131826Sharti u->b_wptr += sizeof(struct uniapi_drop_party_request); 1098131826Sharti 1099131826Sharti req->drop.hdr.act = UNI_MSGACT_DEFAULT; 1100131826Sharti req->drop.hdr.cref = conn->cref; 1101131826Sharti req->drop.epref = party->epref; 1102131826Sharti req->drop.cause = conn->cause[0]; 1103131826Sharti 1104131826Sharti if (party->state == PARTY_ACTIVE) 1105131826Sharti cc_party_set_state(party, PARTY_DROP_WAIT_OK); 1106131826Sharti else 1107131826Sharti cc_party_set_state(party, PARTY_ADD_DROP_WAIT_OK); 1108131826Sharti cc_send_uni(conn, UNIAPI_DROP_PARTY_request, u); 1109131826Sharti break; 1110131826Sharti } 1111131826Sharti 1112131826Sharti case CONN_SIG_DROP_PARTY_ACK_IND: 1113131826Sharti { 1114131826Sharti struct uni_msg *msg = arg; 1115131826Sharti struct uniapi_drop_party_ack_indication *ind = uni_msg_rptr(msg, 1116131826Sharti struct uniapi_drop_party_ack_indication *); 1117131826Sharti 1118131826Sharti cc_party_drop_ack_ind(conn, &ind->drop); 1119131826Sharti break; 1120131826Sharti } 1121131826Sharti 1122131826Sharti 1123131826Sharti case CONN_SIG_USER_ABORT: 1124131826Sharti /* 1125131826Sharti * Aborting a connection. This is callable in all states. 1126131826Sharti * The connection is already disconnected from the user. 1127131826Sharti * The cause is in cause[]. 1128131826Sharti */ 1129131826Sharti switch (conn->state) { 1130131826Sharti 1131131826Sharti case CONN_NULL: /* C0 */ 1132131826Sharti case CONN_OUT_PREPARING: /* C1 */ 1133131826Sharti cc_conn_destroy(conn); 1134131826Sharti break; 1135131826Sharti 1136131826Sharti case CONN_OUT_WAIT_CONF: /* C4 */ 1137131826Sharti case CONN_ACTIVE: /* C5 */ 1138131826Sharti do_release_request(conn, conn->cause); 1139131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1140131826Sharti break; 1141131826Sharti 1142131826Sharti case CONN_IN_WAITING: /* C21 */ 1143131826Sharti /* that should not happen */ 1144131826Sharti goto bad_state; 1145131826Sharti break; 1146131826Sharti 1147131826Sharti case CONN_IN_ARRIVED: /* C11 */ 1148131826Sharti /* 1149131826Sharti * This is called only for the first connection 1150131826Sharti * of the user - the others are re-dispatched. 1151131826Sharti */ 1152131826Sharti do_release_response(conn, 0, conn->cause); 1153131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1154131826Sharti break; 1155131826Sharti 1156131826Sharti case CONN_IN_WAIT_COMPL: /* C13 */ 1157131826Sharti do_release_request(conn, conn->cause); 1158131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1159131826Sharti break; 1160131826Sharti 1161131826Sharti case CONN_OUT_WAIT_DESTROY: /* C20 */ 1162131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1163131826Sharti break; 1164131826Sharti 1165131826Sharti case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1166131826Sharti case CONN_AB_WAIT_REQ_OK: /* C33 */ 1167131826Sharti case CONN_AB_WAIT_RESP_OK: /* C34 */ 1168131826Sharti case CONN_AB_FLUSH_IND: /* C35 */ 1169131826Sharti /* just ignore */ 1170131826Sharti break; 1171131826Sharti 1172131826Sharti /* 1173131826Sharti * The following states may not happen, because 1174131826Sharti * we're waiting for a response from the UNI stack. 1175131826Sharti * As soon as the response comes the ABORT is undefered 1176131826Sharti * and will hit us (but in another state). 1177131826Sharti */ 1178131826Sharti case CONN_OUT_WAIT_CREATE: /* C2 */ 1179131826Sharti case CONN_OUT_WAIT_OK: /* C3 */ 1180131826Sharti case CONN_IN_PREPARING: /* C10 */ 1181131826Sharti case CONN_REJ_WAIT_OK: /* C14 */ 1182131826Sharti case CONN_REL_IN_WAIT_OK: /* C15 */ 1183131826Sharti case CONN_REL_WAIT_OK: /* C20 */ 1184131826Sharti goto bad_state; 1185131826Sharti } 1186131826Sharti break; 1187131826Sharti 1188131826Sharti 1189131826Sharti case CONN_SIG_CREATED: 1190131826Sharti { 1191131826Sharti /* 1192131826Sharti * CALL_CREATED message from UNI. This can happen for either 1193131826Sharti * incoming or outgoing connections. 1194131826Sharti */ 1195131826Sharti struct uni_msg *msg = arg; 1196131826Sharti struct uniapi_call_created *cr = uni_msg_rptr(msg, 1197131826Sharti struct uniapi_call_created *); 1198131826Sharti 1199131826Sharti switch (conn->state) { 1200131826Sharti 1201131826Sharti case CONN_OUT_WAIT_CREATE: 1202131826Sharti conn->cref = cr->cref; 1203131826Sharti cc_conn_set_state(conn, CONN_OUT_WAIT_OK); 1204131826Sharti break; 1205131826Sharti 1206131826Sharti case CONN_NULL: 1207131826Sharti conn->cref = cr->cref; 1208131826Sharti cc_conn_set_state(conn, CONN_IN_PREPARING); 1209131826Sharti break; 1210131826Sharti 1211131826Sharti default: 1212131826Sharti goto bad_state; 1213131826Sharti } 1214131826Sharti break; 1215131826Sharti } 1216131826Sharti 1217131826Sharti case CONN_SIG_DESTROYED: 1218131826Sharti /* 1219131826Sharti * CALL_DESTROYED message from UNI. 1220131826Sharti */ 1221131826Sharti switch (conn->state) { 1222131826Sharti 1223131826Sharti case CONN_OUT_WAIT_DESTROY: 1224131826Sharti cc_conn_rem_port(conn); 1225131826Sharti cc_conn_set_state(conn, CONN_OUT_PREPARING); 1226131826Sharti if (conn->user != NULL) 1227131826Sharti cc_user_sig(conn->user, 1228131826Sharti USER_SIG_CONNECT_OUTGOING_ERR, 1229131826Sharti NULL, ATM_MKUNIERR(conn->reason)); 1230131826Sharti break; 1231131826Sharti 1232131826Sharti case CONN_AB_FLUSH_IND: 1233131826Sharti cc_conn_destroy(conn); 1234131826Sharti break; 1235131826Sharti 1236131826Sharti case CONN_IN_PREPARING: 1237131826Sharti cc_conn_destroy(conn); 1238131826Sharti break; 1239131826Sharti 1240131826Sharti default: 1241131826Sharti goto bad_state; 1242131826Sharti } 1243131826Sharti break; 1244131826Sharti 1245131826Sharti 1246131826Sharti case CONN_SIG_SETUP_CONFIRM: 1247131826Sharti /* Setup confirm from the UNI. */ 1248131826Sharti { 1249131826Sharti struct uni_msg *msg = arg; 1250131826Sharti struct uniapi_setup_confirm *conf = uni_msg_rptr(msg, 1251131826Sharti struct uniapi_setup_confirm *); 1252131826Sharti 1253131826Sharti switch (conn->state) { 1254131826Sharti 1255131826Sharti case CONN_OUT_WAIT_CONF: 1256131826Sharti /* 1257131826Sharti * Shuffle attributes and inform the user. 1258131826Sharti * Negotiable attributes are condititionally shuffled, 1259131826Sharti * because not returning it means accepting it 1260131826Sharti * (in case of blli the first instance of it). 1261131826Sharti * All others are shuffled unconditionally. 1262131826Sharti * Here we should also open the VCI in the driver. (XXX) 1263131826Sharti */ 1264131826Sharti#define SHUFFLE(ATTR) conn->ATTR = conf->connect.ATTR 1265131826Sharti#define COND_SHUFFLE(ATTR) if (IE_ISPRESENT(conf->connect.ATTR)) SHUFFLE(ATTR) 1266131826Sharti 1267131826Sharti COND_SHUFFLE(aal); 1268131826Sharti (void)memset(conn->blli + 1, 0, 1269131826Sharti sizeof(conn->blli) - sizeof(conn->blli[0])); 1270131826Sharti if (IE_ISPRESENT(conf->connect.blli)) 1271131826Sharti conn->blli[0] = conf->connect.blli; 1272131826Sharti conn->blli_selector = 1; 1273131826Sharti COND_SHUFFLE(epref); 1274131826Sharti SHUFFLE(conned); 1275131826Sharti SHUFFLE(connedsub); 1276131826Sharti SHUFFLE(eetd); 1277131826Sharti COND_SHUFFLE(traffic); 1278131826Sharti COND_SHUFFLE(exqos); 1279131826Sharti COND_SHUFFLE(abrsetup); 1280131826Sharti COND_SHUFFLE(abradd); 1281131826Sharti COND_SHUFFLE(connid); 1282131826Sharti#undef SHUFFLE 1283131826Sharti#undef COND_SHUFFLE 1284131826Sharti if (IE_ISGOOD(conn->epref)) 1285131826Sharti cc_party_setup_conf(conn); 1286131826Sharti 1287131826Sharti cc_conn_set_state(conn, CONN_ACTIVE); 1288131826Sharti cc_user_sig(conn->user, USER_SIG_SETUP_CONFIRM, 1289131826Sharti NULL, 0); 1290131826Sharti break; 1291131826Sharti 1292131826Sharti case CONN_AB_FLUSH_IND: 1293131826Sharti case CONN_AB_WAIT_RESP_OK: 1294131826Sharti break; 1295131826Sharti 1296131826Sharti default: 1297131826Sharti goto bad_state; 1298131826Sharti } 1299131826Sharti break; 1300131826Sharti } 1301131826Sharti 1302131826Sharti case CONN_SIG_SETUP_IND: 1303131826Sharti { 1304131826Sharti /* SETUP indication */ 1305131826Sharti struct uni_msg *msg = arg; 1306131826Sharti struct uniapi_setup_indication *ind = uni_msg_rptr(msg, 1307131826Sharti struct uniapi_setup_indication *); 1308131826Sharti u_int i; 1309131826Sharti 1310131826Sharti if (conn->state != CONN_IN_PREPARING) 1311131826Sharti goto bad_state; 1312131826Sharti 1313131826Sharti /* 1314131826Sharti * Shuffle information elements. 1315131826Sharti */ 1316131826Sharti for (i = 0; i < UNI_NUM_IE_BLLI; i++) 1317131826Sharti conn->blli[i] = ind->setup.blli[i]; 1318131826Sharti conn->bearer = ind->setup.bearer; 1319131826Sharti conn->traffic = ind->setup.traffic; 1320131826Sharti conn->qos = ind->setup.qos; 1321131826Sharti conn->exqos = ind->setup.exqos; 1322131826Sharti conn->called = ind->setup.called; 1323131826Sharti conn->calledsub = ind->setup.calledsub[0]; 1324131826Sharti conn->aal = ind->setup.aal; 1325131826Sharti conn->epref = ind->setup.epref; 1326131826Sharti conn->eetd = ind->setup.eetd; 1327131826Sharti conn->abrsetup = ind->setup.abrsetup; 1328131826Sharti conn->abradd = ind->setup.abradd; 1329131826Sharti conn->calling = ind->setup.calling; 1330131826Sharti conn->callingsub = ind->setup.callingsub[0]; 1331131826Sharti conn->connid = ind->setup.connid; 1332131826Sharti for (i = 0; i < UNI_NUM_IE_TNS; i++) 1333131826Sharti conn->tns[i] = ind->setup.tns[i]; 1334131826Sharti conn->atraffic = ind->setup.atraffic; 1335131826Sharti conn->mintraffic = ind->setup.mintraffic; 1336131826Sharti conn->cscope = ind->setup.cscope; 1337131826Sharti conn->bhli = ind->setup.bhli; 1338131826Sharti conn->mdcr = ind->setup.mdcr; 1339131826Sharti 1340131826Sharti cc_conn_dispatch(conn); 1341131826Sharti break; 1342131826Sharti } 1343131826Sharti 1344131826Sharti 1345131826Sharti case CONN_SIG_SETUP_COMPL: 1346131826Sharti { 1347131826Sharti struct uni_msg *msg = arg; 1348131826Sharti struct uniapi_setup_indication *ind __unused = 1349131826Sharti uni_msg_rptr(msg, struct uniapi_setup_indication *); 1350131826Sharti 1351131826Sharti /* SETUP_COMPLETE.indication from UNI */ 1352131826Sharti if (conn->state == CONN_AB_FLUSH_IND || 1353131826Sharti conn->state == CONN_AB_WAIT_RESP_OK) 1354131826Sharti break; 1355131826Sharti 1356131826Sharti if (conn->state != CONN_IN_WAIT_COMPL) 1357131826Sharti goto bad_state; 1358131826Sharti 1359131826Sharti cc_conn_set_state(conn, CONN_ACTIVE); 1360131826Sharti 1361131826Sharti LIST_FOREACH(party, &conn->parties, link) { 1362131826Sharti if (party->state == PARTY_WAIT_SETUP_COMPL) 1363131826Sharti cc_party_set_state(party, PARTY_ACTIVE); 1364131826Sharti else 1365131826Sharti cc_party_log(party, "bad state=%s for sig=%s", 1366131826Sharti ptab[party->state], 1367131826Sharti cc_conn_sigtab[CONN_SIG_SETUP_COMPL]); 1368131826Sharti } 1369131826Sharti 1370131826Sharti cc_user_sig(conn->user, USER_SIG_SETUP_COMPL, NULL, 0); 1371131826Sharti break; 1372131826Sharti } 1373131826Sharti 1374131826Sharti 1375131826Sharti case CONN_SIG_PROC_IND: 1376131826Sharti { 1377131826Sharti /* 1378131826Sharti * ALERTING.indication and PROCEEDING.indication are entirly 1379131826Sharti * ignored by the specification. We need to at least save the 1380131826Sharti * connid information element. 1381131826Sharti */ 1382131826Sharti struct uni_msg *msg = arg; 1383131826Sharti struct uniapi_proceeding_indication *ind = uni_msg_rptr(msg, 1384131826Sharti struct uniapi_proceeding_indication *); 1385131826Sharti 1386131826Sharti switch (conn->state) { 1387131826Sharti 1388131826Sharti case CONN_OUT_WAIT_CONF: 1389131826Sharti if (IE_ISGOOD(ind->call_proc.connid)) 1390131826Sharti conn->connid = ind->call_proc.connid; 1391131826Sharti break; 1392131826Sharti 1393131826Sharti case CONN_AB_FLUSH_IND: 1394131826Sharti case CONN_AB_WAIT_RESP_OK: 1395131826Sharti break; 1396131826Sharti 1397131826Sharti default: 1398131826Sharti goto bad_state; 1399131826Sharti } 1400131826Sharti break; 1401131826Sharti } 1402131826Sharti 1403131826Sharti case CONN_SIG_ALERTING_IND: 1404131826Sharti { 1405131826Sharti struct uni_msg *msg = arg; 1406131826Sharti struct uniapi_alerting_indication *ind = uni_msg_rptr(msg, 1407131826Sharti struct uniapi_alerting_indication *); 1408131826Sharti 1409131826Sharti switch (conn->state) { 1410131826Sharti 1411131826Sharti case CONN_OUT_WAIT_CONF: 1412131826Sharti if (IE_ISGOOD(ind->alerting.connid)) 1413131826Sharti conn->connid = ind->alerting.connid; 1414131826Sharti break; 1415131826Sharti 1416131826Sharti case CONN_AB_FLUSH_IND: 1417131826Sharti case CONN_AB_WAIT_RESP_OK: 1418131826Sharti break; 1419131826Sharti 1420131826Sharti default: 1421131826Sharti goto bad_state; 1422131826Sharti } 1423131826Sharti break; 1424131826Sharti } 1425131826Sharti 1426131826Sharti case CONN_SIG_REL_CONF: 1427131826Sharti { 1428131826Sharti /* RELEASE.confirm from UNI */ 1429131826Sharti struct uni_msg *msg = arg; 1430131826Sharti struct uniapi_release_confirm *conf = uni_msg_rptr(msg, 1431131826Sharti struct uniapi_release_confirm *); 1432131826Sharti 1433131826Sharti switch (conn->state) { 1434131826Sharti 1435131826Sharti case CONN_OUT_WAIT_CONF: 1436131826Sharti case CONN_ACTIVE: 1437131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1438131826Sharti memcpy(conn->user->cause, conf->release.cause, 1439131826Sharti sizeof(conn->user->cause)); 1440131826Sharti /* 1441131826Sharti * If any party is in P6, ok the user 1442131826Sharti */ 1443131826Sharti LIST_FOREACH(party, &conn->parties, link) { 1444131826Sharti if (party->state == PARTY_DROP_WAIT_ACK) { 1445131826Sharti cc_party_set_state(party, 1446131826Sharti PARTY_WAIT_DESTROY); 1447131826Sharti cc_user_sig(conn->user, 1448131826Sharti USER_SIG_DROP_PARTY_OK, 1449131826Sharti NULL, party->epref.epref); 1450131826Sharti } 1451131826Sharti } 1452131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1453131826Sharti NULL, 0); 1454131826Sharti cc_disconnect_from_user(conn); 1455131826Sharti break; 1456131826Sharti 1457131826Sharti case CONN_AB_FLUSH_IND: 1458131826Sharti case CONN_AB_WAIT_RESP_OK: 1459131826Sharti break; 1460131826Sharti 1461131826Sharti case CONN_IN_WAITING: 1462131826Sharti cc_disconnect_from_user(conn); 1463131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1464131826Sharti break; 1465131826Sharti 1466131826Sharti case CONN_IN_ARRIVED: 1467131826Sharti conn->user->aborted = 1; 1468131826Sharti memcpy(conn->user->cause, conf->release.cause, 1469131826Sharti sizeof(conn->user->cause)); 1470131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1471131826Sharti cc_disconnect_from_user(conn); 1472131826Sharti break; 1473131826Sharti 1474131826Sharti case CONN_IN_WAIT_COMPL: 1475131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1476131826Sharti memcpy(conn->user->cause, conf->release.cause, 1477131826Sharti sizeof(conn->user->cause)); 1478131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1479131826Sharti NULL, 0); 1480131826Sharti cc_disconnect_from_user(conn); 1481131826Sharti break; 1482131826Sharti 1483131826Sharti default: 1484131826Sharti goto bad_state; 1485131826Sharti } 1486131826Sharti break; 1487131826Sharti } 1488131826Sharti 1489131826Sharti case CONN_SIG_REL_IND: 1490131826Sharti { 1491131826Sharti /* RELEASE.ind from UNI */ 1492131826Sharti struct uni_msg *msg = arg; 1493131826Sharti struct uniapi_release_indication *conf = uni_msg_rptr(msg, 1494131826Sharti struct uniapi_release_indication *); 1495131826Sharti 1496131826Sharti switch (conn->state) { 1497131826Sharti 1498131826Sharti case CONN_OUT_WAIT_CONF: 1499131826Sharti case CONN_ACTIVE: 1500131826Sharti do_release_response(conn, 0, NULL); 1501131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1502131826Sharti memcpy(conn->user->cause, conf->release.cause, 1503131826Sharti sizeof(conn->user->cause)); 1504131826Sharti /* 1505131826Sharti * If any party is in P6, ok the user 1506131826Sharti */ 1507131826Sharti LIST_FOREACH(party, &conn->parties, link) { 1508131826Sharti if (party->state == PARTY_DROP_WAIT_ACK) { 1509131826Sharti cc_party_set_state(party, 1510131826Sharti PARTY_WAIT_DESTROY); 1511131826Sharti cc_user_sig(conn->user, 1512131826Sharti USER_SIG_DROP_PARTY_OK, 1513131826Sharti NULL, party->epref.epref); 1514131826Sharti } 1515131826Sharti } 1516131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1517131826Sharti NULL, 0); 1518131826Sharti cc_disconnect_from_user(conn); 1519131826Sharti break; 1520131826Sharti 1521131826Sharti case CONN_AB_FLUSH_IND: 1522131826Sharti case CONN_AB_WAIT_RESP_OK: 1523131826Sharti break; 1524131826Sharti 1525131826Sharti case CONN_IN_WAITING: 1526131826Sharti cc_disconnect_from_user(conn); 1527131826Sharti do_release_response(conn, 0, NULL); 1528131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1529131826Sharti break; 1530131826Sharti 1531131826Sharti case CONN_IN_ARRIVED: 1532131826Sharti conn->user->aborted = 1; 1533131826Sharti cc_disconnect_from_user(conn); 1534131826Sharti do_release_response(conn, 0, NULL); 1535131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1536131826Sharti break; 1537131826Sharti 1538131826Sharti case CONN_IN_WAIT_COMPL: 1539131826Sharti do_release_response(conn, 0, NULL); 1540131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1541131826Sharti memcpy(conn->user->cause, conf->release.cause, 1542131826Sharti sizeof(conn->user->cause)); 1543131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, 1544131826Sharti NULL, 0); 1545131826Sharti cc_disconnect_from_user(conn); 1546131826Sharti break; 1547131826Sharti default: 1548131826Sharti goto bad_state; 1549131826Sharti break; 1550131826Sharti } 1551131826Sharti break; 1552131826Sharti } 1553131826Sharti 1554131826Sharti case CONN_SIG_PARTY_ALERTING_IND: 1555131826Sharti /* party alerting from UNI */ 1556131826Sharti if (conn->state == CONN_AB_FLUSH_IND) 1557131826Sharti break; 1558131826Sharti if (conn->state != CONN_ACTIVE) 1559131826Sharti goto bad_state; 1560131826Sharti /* ignore */ 1561131826Sharti break; 1562131826Sharti 1563131826Sharti case CONN_SIG_PARTY_ADD_ACK_IND: 1564131826Sharti { 1565131826Sharti /* ADD PARTY ACKNOWLEDGE from UNI */ 1566131826Sharti struct uni_msg *msg = arg; 1567131826Sharti struct uniapi_add_party_ack_indication *ind = uni_msg_rptr(msg, 1568131826Sharti struct uniapi_add_party_ack_indication *); 1569131826Sharti 1570131826Sharti if (conn->state == CONN_AB_FLUSH_IND) 1571131826Sharti break; 1572131826Sharti if (conn->state != CONN_ACTIVE) 1573131826Sharti goto bad_state; 1574131826Sharti 1575131826Sharti cc_party_add_ack_ind(conn, &ind->ack.epref); 1576131826Sharti break; 1577131826Sharti } 1578131826Sharti 1579131826Sharti 1580131826Sharti case CONN_SIG_PARTY_ADD_REJ_IND: 1581131826Sharti { 1582131826Sharti /* ADD PARTY REJECT indication */ 1583131826Sharti struct uni_msg *msg = arg; 1584131826Sharti struct uniapi_add_party_rej_indication *ind = uni_msg_rptr(msg, 1585131826Sharti struct uniapi_add_party_rej_indication *); 1586131826Sharti 1587131826Sharti if (conn->state == CONN_AB_FLUSH_IND) 1588131826Sharti break; 1589131826Sharti if (conn->state != CONN_ACTIVE) 1590131826Sharti goto bad_state; 1591131826Sharti 1592131826Sharti memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 1593131826Sharti conn->user->cause[0] = ind->rej.cause; 1594131826Sharti 1595131826Sharti cc_party_add_rej_ind(conn, &ind->rej.epref); 1596131826Sharti break; 1597131826Sharti } 1598131826Sharti 1599131826Sharti 1600131826Sharti case CONN_SIG_DROP_PARTY_IND: 1601131826Sharti { 1602131826Sharti /* DROP_PARTY.indication from UNI */ 1603131826Sharti struct uni_msg *msg = arg; 1604131826Sharti struct uniapi_drop_party_indication *ind = uni_msg_rptr(msg, 1605131826Sharti struct uniapi_drop_party_indication *); 1606131826Sharti struct uniapi_drop_party_ack_request *req; 1607131826Sharti struct uni_msg *u; 1608131826Sharti 1609131826Sharti if (conn->state == CONN_AB_FLUSH_IND) 1610131826Sharti break; 1611131826Sharti if (conn->state != CONN_ACTIVE) 1612131826Sharti goto bad_state; 1613131826Sharti 1614131826Sharti party = cc_party_find(conn, ind->drop.epref.epref); 1615131826Sharti if (party == NULL) { 1616131826Sharti cc_party_log(party, "no party for %s", 1617131826Sharti cc_conn_sigtab[sig]); 1618131826Sharti break; 1619131826Sharti } 1620131826Sharti 1621131826Sharti u = uni_msg_alloc(sizeof(*req)); 1622131826Sharti if (u == NULL) 1623131826Sharti return; 1624131826Sharti 1625131826Sharti memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); 1626131826Sharti conn->user->cause[0] = ind->drop.cause; 1627131826Sharti 1628131826Sharti switch (party->state) { 1629131826Sharti 1630131826Sharti default: 1631131826Sharti cc_party_log(party, "bad state %s for DROP.ind", 1632131826Sharti ptab[party->state]); 1633131826Sharti /* FALLTHRU */ 1634131826Sharti 1635131826Sharti case PARTY_ACTIVE: /* P1 -> P9 */ 1636131826Sharti cc_party_set_state(party, PARTY_WAIT_DROP_ACK_OK); 1637131826Sharti break; 1638131826Sharti 1639131826Sharti case PARTY_ADD_WAIT_ACK: /* P4 -> P12 */ 1640131826Sharti cc_party_set_state(party, PARTY_ADD_DROPACK_WAIT_OK); 1641131826Sharti break; 1642131826Sharti } 1643131826Sharti 1644131826Sharti /* 1645131826Sharti * Construct message to UNI. 1646131826Sharti */ 1647131826Sharti req = uni_msg_wptr(u, struct uniapi_drop_party_ack_request *); 1648131826Sharti memset(req, 0, sizeof(*req)); 1649131826Sharti u->b_wptr += sizeof(*req); 1650131826Sharti 1651131826Sharti IE_SETPRESENT(req->ack.epref); 1652131826Sharti req->ack.hdr.act = UNI_MSGACT_DEFAULT; 1653131826Sharti req->ack.hdr.cref = conn->cref; 1654131826Sharti 1655131826Sharti req->ack.epref.flag = 0; 1656131826Sharti req->ack.epref.epref = ind->drop.epref.epref; 1657131826Sharti 1658131826Sharti cc_send_uni(conn, UNIAPI_DROP_PARTY_ACK_request, u); 1659131826Sharti break; 1660131826Sharti } 1661131826Sharti 1662131826Sharti case CONN_SIG_OK: 1663131826Sharti { 1664131826Sharti /* OK response from UNI */ 1665131826Sharti struct ccuser *user = conn->user; 1666131826Sharti 1667131826Sharti switch (conn->state) { 1668131826Sharti 1669131826Sharti case CONN_OUT_WAIT_OK: /* C3 */ 1670131826Sharti cc_conn_set_state(conn, CONN_OUT_WAIT_CONF); 1671131826Sharti if (conn->user != NULL) 1672131826Sharti cc_user_sig(conn->user, 1673131826Sharti USER_SIG_CONNECT_OUTGOING_OK, NULL, 0); 1674131826Sharti break; 1675131826Sharti 1676131826Sharti case CONN_AB_WAIT_RESP_OK: /* C33 */ 1677131826Sharti case CONN_AB_WAIT_REQ_OK: /* C34 */ 1678131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1679131826Sharti break; 1680131826Sharti 1681131826Sharti case CONN_REL_WAIT_OK: /* C20 */ 1682131826Sharti case CONN_REL_IN_WAIT_OK: /* C15 */ 1683131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1684131826Sharti if (conn->user != NULL) { 1685131826Sharti /* connection has not been aborted */ 1686131826Sharti memset(&conn->user->cause, 0, 1687131826Sharti sizeof(conn->user->cause)); 1688131826Sharti cc_user_sig(conn->user, 1689131826Sharti USER_SIG_RELEASE_CONFIRM, NULL, 0); 1690131826Sharti cc_disconnect_from_user(conn); 1691131826Sharti } 1692131826Sharti break; 1693131826Sharti 1694131826Sharti case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1695131826Sharti if (user == NULL) { 1696131826Sharti /* has been aborted */ 1697131826Sharti do_release_request(conn, NULL); 1698131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1699131826Sharti break; 1700131826Sharti } 1701131826Sharti cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); 1702131826Sharti cc_disconnect_from_user(conn); 1703131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_OK, NULL, 0); 1704131826Sharti if (conn->acceptor == NULL) { 1705131826Sharti do_release_request(conn, NULL); 1706131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); 1707131826Sharti break; 1708131826Sharti } 1709131826Sharti cc_connect_to_user(conn, conn->acceptor); 1710131826Sharti cc_conn_reset_acceptor(conn); 1711131826Sharti cc_user_sig(conn->user, USER_SIG_ACCEPTING, NULL, 0); 1712131826Sharti break; 1713131826Sharti 1714131826Sharti case CONN_REJ_WAIT_OK: /* C14 */ 1715131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1716131826Sharti if (user != NULL) { 1717131826Sharti cc_disconnect_from_user(conn); 1718131826Sharti cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); 1719131826Sharti } 1720131826Sharti break; 1721131826Sharti 1722131826Sharti default: 1723131826Sharti /* maybe it's for a party */ 1724131826Sharti LIST_FOREACH(party, &conn->parties, link) { 1725131826Sharti switch (party->state) { 1726131826Sharti 1727131826Sharti case PARTY_ADD_WAIT_OK: /* P3 */ 1728131826Sharti if (user != NULL) 1729131826Sharti cc_user_sig(user, 1730131826Sharti USER_SIG_ADD_PARTY_OK, 1731131826Sharti NULL, 0); 1732131826Sharti cc_party_set_state(party, 1733131826Sharti PARTY_ADD_WAIT_ACK); 1734131826Sharti goto ex_party_ok; 1735131826Sharti 1736131826Sharti case PARTY_DROP_WAIT_OK: /* P5 */ 1737131826Sharti cc_party_set_state(party, 1738131826Sharti PARTY_DROP_WAIT_ACK); 1739131826Sharti goto ex_party_ok; 1740131826Sharti 1741131826Sharti case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 1742131826Sharti case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 1743131826Sharti { 1744131826Sharti struct ccparty *p1; 1745131826Sharti 1746131826Sharti cc_party_set_state(party, 1747131826Sharti PARTY_WAIT_DESTROY); 1748131826Sharti /* signal to user only if there are any other parties */ 1749131826Sharti LIST_FOREACH(p1, &conn->parties, link) 1750131826Sharti if (p1 != party) 1751131826Sharti break; 1752131826Sharti if (p1 != NULL && user != NULL) 1753131826Sharti cc_user_sig(user, 1754131826Sharti USER_SIG_DROP_PARTY_IND, 1755131826Sharti NULL, 1756131826Sharti party->epref.epref); 1757131826Sharti 1758131826Sharti goto ex_party_ok; 1759131826Sharti } 1760131826Sharti 1761131826Sharti case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 1762131826Sharti cc_party_set_state(party, 1763131826Sharti PARTY_DROP_WAIT_ACK); 1764131826Sharti goto ex_party_ok; 1765131826Sharti 1766131826Sharti default: 1767131826Sharti break; 1768131826Sharti } 1769131826Sharti } 1770131826Sharti goto bad_state; 1771131826Sharti ex_party_ok: 1772131826Sharti break; 1773131826Sharti } 1774131826Sharti break; 1775131826Sharti } 1776131826Sharti 1777131826Sharti case CONN_SIG_ERROR: 1778131826Sharti { 1779131826Sharti /* error response from UNI */ 1780131826Sharti u_int reason = (iarg >> 16) & 0xffff; 1781131826Sharti u_int state = iarg & 0xffff; 1782131826Sharti struct ccuser *user = conn->user; 1783131826Sharti 1784131826Sharti switch (conn->state) { 1785131826Sharti 1786131826Sharti case CONN_OUT_WAIT_CREATE: /* C2 */ 1787131826Sharti cc_conn_rem_port(conn); 1788131826Sharti cc_conn_set_state(conn, CONN_OUT_PREPARING); 1789131826Sharti if (conn->user != NULL) 1790131826Sharti cc_user_sig(conn->user, 1791131826Sharti USER_SIG_CONNECT_OUTGOING_ERR, 1792131826Sharti NULL, ATM_MKUNIERR(reason)); 1793131826Sharti break; 1794131826Sharti 1795131826Sharti case CONN_OUT_WAIT_OK: /* C3 */ 1796131826Sharti cc_conn_set_state(conn, CONN_OUT_WAIT_DESTROY); 1797131826Sharti conn->reason = reason; 1798131826Sharti break; 1799131826Sharti 1800131826Sharti case CONN_AB_WAIT_REQ_OK: /* C33 */ 1801131826Sharti if (state == UNI_CALLSTATE_U12) { 1802131826Sharti do_release_response(conn, 0, conn->cause); 1803131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1804131826Sharti break; 1805131826Sharti } 1806131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1807131826Sharti break; 1808131826Sharti 1809131826Sharti case CONN_AB_WAIT_RESP_OK: /* C34 */ 1810131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1811131826Sharti break; 1812131826Sharti 1813131826Sharti case CONN_REL_WAIT_OK: /* C20 */ 1814131826Sharti if (user == NULL) { 1815131826Sharti /* connection has been aborted. */ 1816131826Sharti if (state == UNI_CALLSTATE_U10) { 1817131826Sharti /* do what we can */ 1818131826Sharti do_release_request(conn, conn->cause); 1819131826Sharti cc_conn_set_state(conn, 1820131826Sharti CONN_AB_WAIT_REQ_OK); 1821131826Sharti } else if (state == UNI_CALLSTATE_U12) { 1822131826Sharti do_release_response(conn, 0, NULL); 1823131826Sharti cc_conn_set_state(conn, 1824131826Sharti CONN_AB_WAIT_RESP_OK); 1825131826Sharti } else { 1826131826Sharti cc_conn_set_state(conn, 1827131826Sharti CONN_AB_FLUSH_IND); 1828131826Sharti } 1829131826Sharti break; 1830131826Sharti } 1831131826Sharti if (state == UNI_CALLSTATE_U10) { 1832131826Sharti cc_conn_set_state(conn, CONN_ACTIVE); 1833131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, 1834131826Sharti NULL, reason); 1835131826Sharti } else if (state == UNI_CALLSTATE_U12) { 1836131826Sharti do_release_response(conn, 0, NULL); 1837131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1838131826Sharti memset(&conn->user->cause, 0, 1839131826Sharti sizeof(conn->user->cause)); 1840131826Sharti cc_user_sig(conn->user, 1841131826Sharti USER_SIG_RELEASE_CONFIRM, NULL, 0); 1842131826Sharti cc_disconnect_from_user(conn); 1843131826Sharti } else { 1844131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1845131826Sharti memset(&conn->user->cause, 0, 1846131826Sharti sizeof(conn->user->cause)); 1847131826Sharti cc_user_sig(conn->user, 1848131826Sharti USER_SIG_RELEASE_CONFIRM, NULL, 0); 1849131826Sharti cc_disconnect_from_user(conn); 1850131826Sharti } 1851131826Sharti break; 1852131826Sharti 1853131826Sharti case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ 1854131826Sharti if (user == NULL) { 1855131826Sharti /* connection was aborted */ 1856131826Sharti if (state == UNI_CALLSTATE_U6 || 1857131826Sharti state == UNI_CALLSTATE_U7 || 1858131826Sharti state == UNI_CALLSTATE_U9 || 1859131826Sharti state == UNI_CALLSTATE_U12) { 1860131826Sharti do_release_response(conn, 0, NULL); 1861131826Sharti cc_conn_set_state(conn, 1862131826Sharti CONN_AB_WAIT_RESP_OK); 1863131826Sharti } else { 1864131826Sharti cc_conn_set_state(conn, 1865131826Sharti CONN_AB_FLUSH_IND); 1866131826Sharti } 1867131826Sharti break; 1868131826Sharti } 1869131826Sharti cc_conn_reset_acceptor(conn); 1870131826Sharti if (state == UNI_CALLSTATE_U6 || 1871131826Sharti state == UNI_CALLSTATE_U9 || 1872131826Sharti state == UNI_CALLSTATE_U7) { 1873131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1874131826Sharti NULL, ATM_MKUNIERR(reason)); 1875131826Sharti cc_conn_set_state(conn, CONN_IN_ARRIVED); 1876131826Sharti } else if (state == UNI_CALLSTATE_U12) { 1877131826Sharti do_release_response(conn, 0, NULL); 1878131826Sharti cc_disconnect_from_user(conn); 1879131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1880131826Sharti user, ATMERR_PREVIOUSLY_ABORTED); 1881131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1882131826Sharti } else { 1883131826Sharti cc_disconnect_from_user(conn); 1884131826Sharti cc_user_sig(user, USER_SIG_ACCEPT_ERR, 1885131826Sharti user, ATMERR_PREVIOUSLY_ABORTED); 1886131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1887131826Sharti } 1888131826Sharti break; 1889131826Sharti 1890131826Sharti case CONN_REJ_WAIT_OK: /* C14 */ 1891131826Sharti if (user == NULL) { 1892131826Sharti /* connection has been aborted. */ 1893131826Sharti if (state == UNI_CALLSTATE_U6 || 1894131826Sharti state == UNI_CALLSTATE_U7 || 1895131826Sharti state == UNI_CALLSTATE_U9 || 1896131826Sharti state == UNI_CALLSTATE_U12) { 1897131826Sharti /* do what we can */ 1898131826Sharti do_release_response(conn, 0, NULL); 1899131826Sharti cc_conn_set_state(conn, 1900131826Sharti CONN_AB_WAIT_RESP_OK); 1901131826Sharti } else { 1902131826Sharti cc_conn_set_state(conn, 1903131826Sharti CONN_AB_FLUSH_IND); 1904131826Sharti } 1905131826Sharti break; 1906131826Sharti } 1907131826Sharti if (state == UNI_CALLSTATE_U6 || 1908131826Sharti state == UNI_CALLSTATE_U9 || 1909131826Sharti state == UNI_CALLSTATE_U7) { 1910131826Sharti cc_user_sig(user, USER_SIG_REJECT_ERR, 1911131826Sharti NULL, ATM_MKUNIERR(reason)); 1912131826Sharti cc_conn_set_state(conn, CONN_IN_ARRIVED); 1913131826Sharti } else { 1914131826Sharti cc_disconnect_from_user(conn); 1915131826Sharti cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); 1916131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1917131826Sharti } 1918131826Sharti break; 1919131826Sharti 1920131826Sharti case CONN_REL_IN_WAIT_OK: /* C15 */ 1921131826Sharti if (user == NULL) { 1922131826Sharti /* connection has been aborted. */ 1923131826Sharti if (state == UNI_CALLSTATE_U8) { 1924131826Sharti /* do what we can */ 1925131826Sharti do_release_request(conn, conn->cause); 1926131826Sharti cc_conn_set_state(conn, 1927131826Sharti CONN_AB_WAIT_REQ_OK); 1928131826Sharti } else if (state == UNI_CALLSTATE_U12) { 1929131826Sharti do_release_response(conn, 0, NULL); 1930131826Sharti cc_conn_set_state(conn, 1931131826Sharti CONN_AB_WAIT_RESP_OK); 1932131826Sharti } else { 1933131826Sharti cc_conn_set_state(conn, 1934131826Sharti CONN_AB_FLUSH_IND); 1935131826Sharti } 1936131826Sharti break; 1937131826Sharti } 1938131826Sharti if (state == UNI_CALLSTATE_U8) { 1939131826Sharti cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); 1940131826Sharti cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, 1941131826Sharti NULL, reason); 1942131826Sharti } else if (state == UNI_CALLSTATE_U12) { 1943131826Sharti do_release_response(conn, 0, NULL); 1944131826Sharti cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); 1945131826Sharti memset(&conn->user->cause, 0, 1946131826Sharti sizeof(conn->user->cause)); 1947131826Sharti cc_user_sig(conn->user, 1948131826Sharti USER_SIG_RELEASE_CONFIRM, NULL, 0); 1949131826Sharti cc_disconnect_from_user(conn); 1950131826Sharti } else { 1951131826Sharti cc_conn_set_state(conn, CONN_AB_FLUSH_IND); 1952131826Sharti memset(&conn->user->cause, 0, 1953131826Sharti sizeof(conn->user->cause)); 1954131826Sharti cc_user_sig(conn->user, 1955131826Sharti USER_SIG_RELEASE_CONFIRM, NULL, 0); 1956131826Sharti cc_disconnect_from_user(conn); 1957131826Sharti } 1958131826Sharti break; 1959131826Sharti 1960131826Sharti default: 1961131826Sharti /* maybe it's for a party */ 1962131826Sharti LIST_FOREACH(party, &conn->parties, link) { 1963131826Sharti switch (party->state) { 1964131826Sharti 1965131826Sharti case PARTY_ADD_WAIT_CREATE: /* P2 */ 1966131826Sharti cc_party_destroy(party); 1967131826Sharti if (user != NULL) 1968131826Sharti cc_user_sig(user, 1969131826Sharti USER_SIG_ADD_PARTY_ERR, 1970131826Sharti NULL, ATM_MKUNIERR(reason)); 1971131826Sharti goto ex_party_err; 1972131826Sharti 1973131826Sharti case PARTY_ADD_WAIT_OK: /* P3 */ 1974131826Sharti cc_party_set_state(party, 1975131826Sharti PARTY_WAIT_DESTROY); 1976131826Sharti if (user != NULL) 1977131826Sharti cc_user_sig(user, 1978131826Sharti USER_SIG_ADD_PARTY_ERR, 1979131826Sharti NULL, ATM_MKUNIERR(reason)); 1980131826Sharti goto ex_party_err; 1981131826Sharti 1982131826Sharti case PARTY_DROP_WAIT_OK: /* P5 */ 1983131826Sharti cc_party_set_state(party, 1984131826Sharti PARTY_ACTIVE); 1985131826Sharti if (user != NULL) 1986131826Sharti cc_user_sig(user, 1987131826Sharti USER_SIG_DROP_PARTY_ERR, 1988131826Sharti NULL, ATM_MKUNIERR(reason)); 1989131826Sharti goto ex_party_err; 1990131826Sharti 1991131826Sharti case PARTY_WAIT_DROP_ACK_OK: /* P9 */ 1992131826Sharti cc_party_set_state(party, 1993131826Sharti PARTY_ACTIVE); 1994131826Sharti goto ex_party_err; 1995131826Sharti 1996131826Sharti case PARTY_ADD_DROP_WAIT_OK: /* P11 */ 1997131826Sharti cc_party_set_state(party, 1998131826Sharti PARTY_ADD_WAIT_ACK); 1999131826Sharti if (user != NULL) 2000131826Sharti cc_user_sig(user, 2001131826Sharti USER_SIG_DROP_PARTY_ERR, 2002131826Sharti NULL, ATM_MKUNIERR(reason)); 2003131826Sharti goto ex_party_err; 2004131826Sharti 2005131826Sharti case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ 2006131826Sharti cc_party_set_state(party, 2007131826Sharti PARTY_ADD_WAIT_ACK); 2008131826Sharti goto ex_party_err; 2009131826Sharti 2010131826Sharti default: 2011131826Sharti break; 2012131826Sharti } 2013131826Sharti } 2014131826Sharti cc_conn_log(conn, "unexpected reason=%u ustate=%u " 2015131826Sharti "state=%s\n", reason, state, stab[conn->state]); 2016131826Sharti ex_party_err: 2017131826Sharti break; 2018131826Sharti } 2019131826Sharti break; 2020131826Sharti } 2021131826Sharti 2022131826Sharti case CONN_SIG_PARTY_CREATED: 2023131826Sharti { 2024131826Sharti struct uni_msg *msg = arg; 2025131826Sharti struct uniapi_party_created *pcr = uni_msg_rptr(msg, 2026131826Sharti struct uniapi_party_created *); 2027131826Sharti 2028131826Sharti party = cc_party_find(conn, pcr->epref.epref); 2029131826Sharti if (party == NULL) { 2030131826Sharti /* for incoming connections we see the party-created 2031131826Sharti * immediately after the call-create so that we 2032131826Sharti * must be in C10 */ 2033131826Sharti switch (conn->state) { 2034131826Sharti 2035131826Sharti case CONN_IN_PREPARING: 2036131826Sharti party = cc_party_create(conn, 2037131826Sharti pcr->epref.epref, 1); 2038131826Sharti if (party == NULL) 2039131826Sharti break; 2040131826Sharti cc_party_set_state(party, 2041131826Sharti PARTY_WAIT_SETUP_COMPL); 2042131826Sharti break; 2043131826Sharti 2044131826Sharti case CONN_OUT_WAIT_OK: 2045131826Sharti party = cc_party_create(conn, 2046131826Sharti pcr->epref.epref, 0); 2047131826Sharti if (party == NULL) 2048131826Sharti break; 2049131826Sharti cc_party_set_state(party, 2050131826Sharti PARTY_WAIT_SETUP_CONF); 2051131826Sharti break; 2052131826Sharti 2053131826Sharti default: 2054131826Sharti goto bad_state; 2055131826Sharti } 2056131826Sharti break; 2057131826Sharti } 2058131826Sharti /* this is for an ADD-PARTY */ 2059131826Sharti if (conn->state != CONN_ACTIVE) 2060131826Sharti goto bad_state; 2061131826Sharti if (party->state != PARTY_ADD_WAIT_CREATE) 2062131826Sharti goto bad_party_state; 2063131826Sharti cc_party_set_state(party, PARTY_ADD_WAIT_OK); 2064131826Sharti break; 2065131826Sharti } 2066131826Sharti 2067131826Sharti case CONN_SIG_PARTY_DESTROYED: 2068131826Sharti { 2069131826Sharti struct uni_msg *msg = arg; 2070131826Sharti struct uniapi_party_destroyed *pcr = uni_msg_rptr(msg, 2071131826Sharti struct uniapi_party_destroyed *); 2072131826Sharti 2073131826Sharti party = cc_party_find(conn, pcr->epref.epref); 2074131826Sharti if (party == NULL) { 2075131826Sharti cc_conn_log(conn, "no party to destroy %u/%u", 2076131826Sharti pcr->epref.flag, pcr->epref.epref); 2077131826Sharti break; 2078131826Sharti } 2079131826Sharti cc_party_destroy(party); 2080131826Sharti break; 2081131826Sharti } 2082131826Sharti 2083131826Sharti } 2084131826Sharti 2085131826Sharti return; 2086131826Sharti 2087131826Sharti bad_state: 2088131826Sharti cc_conn_log(conn, "bad state=%s for signal=%s", 2089131826Sharti stab[conn->state], cc_conn_sigtab[sig]); 2090131826Sharti return; 2091131826Sharti 2092131826Sharti bad_party_state: 2093131826Sharti cc_conn_log(conn, "bad party state=%s for signal=%s", 2094131826Sharti ptab[party->state], cc_conn_sigtab[sig]); 2095131826Sharti return; 2096131826Sharti} 2097