The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/ngatm/netnatm/api/cc_conn.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 22a4908eb84e650ed5dc92f1511019e4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.