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_user.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-2004
    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  * $Begemot: libunimsg/netnatm/api/cc_user.c,v 1.3 2004/07/16 18:46:55 brandt Exp $
   35  *
   36  * ATM API as defined per af-saa-0108
   37  *
   38  * User side (upper half)
   39  */
   40 
   41 #include <netnatm/unimsg.h>
   42 #include <netnatm/msg/unistruct.h>
   43 #include <netnatm/msg/unimsglib.h>
   44 #include <netnatm/api/unisap.h>
   45 #include <netnatm/sig/unidef.h>
   46 #include <netnatm/api/atmapi.h>
   47 #include <netnatm/api/ccatm.h>
   48 #include <netnatm/api/ccpriv.h>
   49 
   50 /*
   51 * This file handles messages to a USER.
   52 */
   53 static const char *stab[] = {
   54 #define DEF(N) [N] = #N,
   55         USER_STATES
   56 #undef DEF
   57 };
   58 
   59 const char *
   60 cc_user_state2str(u_int s)
   61 {
   62         if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL)
   63                 return ("?");
   64         return (stab[s]);
   65 }
   66 
   67 static __inline void
   68 set_state(struct ccuser *user, enum user_state ns)
   69 {
   70         if (user->state != ns) {
   71                 if (user->cc->log & CCLOG_USER_STATE)
   72                         cc_user_log(user, "%s -> %s",
   73                             stab[user->state], stab[ns]);
   74                 user->state = ns;
   75         }
   76 }
   77 
   78 static __inline void
   79 cc_user_send(struct ccuser *user, u_int op, void *arg, size_t len)
   80 {
   81         user->cc->funcs->send_user(user, user->uarg, op, arg, len);
   82 }
   83 
   84 static __inline void
   85 cc_user_ok(struct ccuser *user, u_int data, void *arg, size_t len)
   86 {
   87         user->cc->funcs->respond_user(user, user->uarg,
   88             ATMERR_OK, data, arg, len);
   89 }
   90 
   91 static __inline void
   92 cc_user_err(struct ccuser *user, int err)
   93 {
   94         user->cc->funcs->respond_user(user, user->uarg,
   95             err, ATMRESP_NONE, NULL, 0);
   96 }
   97 
   98 
   99 /**********************************************************************
  100 *
  101 * INSTANCE MANAGEMENT
  102 */
  103 /*
  104 * New endpoint created
  105 */
  106 struct ccuser *
  107 cc_user_create(struct ccdata *cc, void *uarg, const char *name)
  108 {
  109         struct ccuser *user;
  110 
  111         user = CCZALLOC(sizeof(*user));
  112         if (user == NULL)
  113                 return (NULL);
  114 
  115         user->cc = cc;
  116         user->state = USER_NULL;
  117         user->uarg = uarg;
  118         strncpy(user->name, name, sizeof(user->name));
  119         user->name[sizeof(user->name) - 1] = '\0';
  120         TAILQ_INIT(&user->connq);
  121         LIST_INSERT_HEAD(&cc->user_list, user, node_link);
  122 
  123         if (user->cc->log & CCLOG_USER_INST)
  124                 cc_user_log(user, "created with name '%s'", name);
  125 
  126         return (user);
  127 }
  128 
  129 /*
  130  * Reset a user instance
  131  */
  132 static void
  133 cc_user_reset(struct ccuser *user)
  134 {
  135 
  136         CCASSERT(TAILQ_EMPTY(&user->connq), ("connq not empty"));
  137 
  138         if (user->sap != NULL) {
  139                 CCFREE(user->sap);
  140                 user->sap = NULL;
  141         }
  142 
  143         if (user->accepted != NULL) {
  144                 user->accepted->acceptor = NULL;
  145                 user->accepted = NULL;
  146         }
  147         user->config = USER_P2P;
  148         user->queue_act = 0;
  149         user->queue_max = 0;
  150         user->aborted = 0;
  151 
  152         set_state(user, USER_NULL);
  153 
  154         cc_user_sig_flush(user);
  155 }
  156 
  157 static void
  158 cc_user_abort(struct ccuser *user, const struct uni_ie_cause *cause)
  159 {
  160         struct ccconn *conn;
  161 
  162         /*
  163          * Although the standard state that 'all connections
  164          * associated with this endpoint are aborted' we only
  165          * have to abort the head one, because in state A6
  166          * (call present) the endpoint is only associated to the
  167          * head connection - the others are 'somewhere else' and
  168          * need to be redispatched.
  169          *
  170          * First bring user into a state that the connections
  171          * are not dispatched back to it.
  172          */
  173         set_state(user, USER_NULL);
  174         if (!user->aborted) {
  175                 if ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
  176                         memset(conn->cause, 0, sizeof(conn->cause));
  177                         if (cause != NULL)
  178                                 conn->cause[0] = *cause;
  179                         cc_conn_reset_acceptor(conn);
  180                         cc_disconnect_from_user(conn);
  181                         cc_conn_sig(conn, CONN_SIG_USER_ABORT, NULL);
  182                 }
  183         }
  184 
  185         while ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
  186                 /* these should be in C21 */
  187                 cc_disconnect_from_user(conn);
  188                 cc_conn_dispatch(conn);
  189         }
  190 
  191         cc_user_reset(user);
  192 }
  193 
  194 /*
  195  * Application has closed this endpoint. Clean up all user resources and
  196  * abort all connections. This can be called in any state.
  197  */
  198 void
  199 cc_user_destroy(struct ccuser *user)
  200 {
  201 
  202         if (user->cc->log & CCLOG_USER_INST)
  203                 cc_user_log(user, "destroy '%s'", user->name);
  204 
  205         cc_user_abort(user, NULL);
  206 
  207         if (user->sap != NULL)
  208                 CCFREE(user->sap);
  209 
  210         cc_user_sig_flush(user);
  211 
  212         LIST_REMOVE(user, node_link);
  213         CCFREE(user);
  214 }
  215 
  216 /**********************************************************************
  217  *
  218  * OUTGOING CALLS
  219  */
  220 /*
  221  * Return true when the calling address of the connection matches the address.
  222  */
  223 static int
  224 addr_matches(const struct ccaddr *addr, const struct ccconn *conn)
  225 {
  226 
  227         if (!IE_ISPRESENT(conn->calling))
  228                 return (0);
  229 
  230         return (addr->addr.type == conn->calling.addr.type &&
  231             addr->addr.plan == conn->calling.addr.plan &&
  232             addr->addr.len == conn->calling.addr.len &&
  233             memcmp(addr->addr.addr, conn->calling.addr.addr,
  234             addr->addr.len) == 0);
  235 }
  236 
  237 /*
  238  * Check if the user's SAP (given he is in the right state) and
  239  * the given SAP overlap
  240  */
  241 static int
  242 check_overlap(struct ccuser *user, struct uni_sap *sap)
  243 {
  244         return ((user->state == USER_IN_PREPARING ||
  245             user->state == USER_IN_WAITING) &&
  246             unisve_overlap_sap(user->sap, sap));
  247 }
  248 
  249 /*
  250  * Send arrival notification to user
  251  */
  252 static void
  253 do_arrival(struct ccuser *user)
  254 {
  255         struct ccconn *conn;
  256 
  257         user->aborted = 0;
  258         if ((conn = TAILQ_FIRST(&user->connq)) != NULL) {
  259                 set_state(user, USER_IN_ARRIVED);
  260                 cc_user_send(user, ATMOP_ARRIVAL_OF_INCOMING_CALL, NULL, 0);
  261                 cc_conn_sig(conn, CONN_SIG_ARRIVAL, NULL);
  262         }
  263 }
  264 
  265 /**********************************************************************
  266  *
  267  * ATTRIBUTES
  268  */
  269 /*
  270  * Query an attribute. This is possible only in some states: preparation
  271  * of an outgoing call, after an incoming call was offered to the application
  272  * and in the three active states (P2P, P2PLeaf, P2PRoot).
  273  */
  274 static struct ccconn *
  275 cc_query_check(struct ccuser *user)
  276 {
  277 
  278         switch (user->state) {
  279 
  280           case USER_OUT_PREPARING:
  281           case USER_IN_ARRIVED:
  282           case USER_ACTIVE:
  283                 return (TAILQ_FIRST(&user->connq));
  284 
  285           case USER_NULL:
  286                 /* if we are waiting for the SETUP_confirm, we are in
  287                  * the NULL state still (we are the new endpoint), but
  288                  * have a connection in 'accepted' that is in the
  289                  * CONN_IN_WAIT_ACCEPT_OK state.
  290                  */
  291                 if (user->accepted != NULL &&
  292                     user->accepted->state == CONN_IN_WAIT_ACCEPT_OK)
  293                         return (user->accepted);
  294                 /* FALLTHRU */
  295 
  296           default:
  297                 return (NULL);
  298         }
  299 }
  300 
  301 /*
  302  * Query attributes
  303  */
  304 static void
  305 cc_attr_query(struct ccuser *user, struct ccconn *conn,
  306     uint32_t *attr, u_int count)
  307 {
  308         void *val, *ptr;
  309         size_t total, len;
  310         u_int i;
  311         uint32_t *atab;
  312 
  313         /* determine the length of the total attribute buffer */
  314         total = sizeof(uint32_t) + count * sizeof(uint32_t);
  315         for (i = 0; i < count; i++) {
  316                 len = 0;
  317                 switch ((enum atm_attribute)attr[i]) {
  318 
  319                   case ATM_ATTR_NONE:
  320                         break;
  321 
  322                   case ATM_ATTR_BLLI_SELECTOR:
  323                         len = sizeof(uint32_t);
  324                         break;
  325 
  326                   case ATM_ATTR_BLLI:
  327                         len = sizeof(struct uni_ie_blli);
  328                         break;
  329 
  330                   case ATM_ATTR_BEARER:
  331                         len = sizeof(struct uni_ie_bearer);
  332                         break;
  333 
  334                   case ATM_ATTR_TRAFFIC:
  335                         len = sizeof(struct uni_ie_traffic);
  336                         break;
  337 
  338                   case ATM_ATTR_QOS:
  339                         len = sizeof(struct uni_ie_qos);
  340                         break;
  341 
  342                   case ATM_ATTR_EXQOS:
  343                         len = sizeof(struct uni_ie_exqos);
  344                         break;
  345 
  346                   case ATM_ATTR_CALLED:
  347                         len = sizeof(struct uni_ie_called);
  348                         break;
  349 
  350                   case ATM_ATTR_CALLEDSUB:
  351                         len = sizeof(struct uni_ie_calledsub);
  352                         break;
  353 
  354                   case ATM_ATTR_CALLING:
  355                         len = sizeof(struct uni_ie_calling);
  356                         break;
  357 
  358                   case ATM_ATTR_CALLINGSUB:
  359                         len = sizeof(struct uni_ie_callingsub);
  360                         break;
  361 
  362                   case ATM_ATTR_AAL:
  363                         len = sizeof(struct uni_ie_aal);
  364                         break;
  365 
  366                   case ATM_ATTR_EPREF:
  367                         len = sizeof(struct uni_ie_epref);
  368                         break;
  369 
  370                   case ATM_ATTR_CONNED:
  371                         len = sizeof(struct uni_ie_conned);
  372                         break;
  373 
  374                   case ATM_ATTR_CONNEDSUB:
  375                         len = sizeof(struct uni_ie_connedsub);
  376                         break;
  377 
  378                   case ATM_ATTR_EETD:
  379                         len = sizeof(struct uni_ie_eetd);
  380                         break;
  381 
  382                   case ATM_ATTR_ABRSETUP:
  383                         len = sizeof(struct uni_ie_abrsetup);
  384                         break;
  385 
  386                   case ATM_ATTR_ABRADD:
  387                         len = sizeof(struct uni_ie_abradd);
  388                         break;
  389 
  390                   case ATM_ATTR_CONNID:
  391                         len = sizeof(struct uni_ie_connid);
  392                         break;
  393 
  394                   case ATM_ATTR_MDCR:
  395                         len = sizeof(struct uni_ie_mdcr);
  396                         break;
  397                 }
  398                 if (len == 0) {
  399                         cc_user_err(user, ATMERR_BAD_ATTR);
  400                         return;
  401                 }
  402                 total += len;
  403         }
  404 
  405         /* allocate buffer */
  406         val = CCMALLOC(total);
  407         if (val == NULL)
  408                 return;
  409 
  410         atab = val;
  411         atab[0] = count;
  412 
  413         /* fill */
  414         ptr = (u_char *)val + (sizeof(uint32_t) + count * sizeof(uint32_t));
  415         for (i = 0; i < count; i++) {
  416                 len = 0;
  417                 atab[i + 1] = attr[i];
  418                 switch (attr[i]) {
  419 
  420                   case ATM_ATTR_NONE:
  421                         break;
  422 
  423                   case ATM_ATTR_BLLI_SELECTOR:
  424                         len = sizeof(uint32_t);
  425                         memcpy(ptr, &conn->blli_selector, len);
  426                         break;
  427 
  428                   case ATM_ATTR_BLLI:
  429                         /* in A6 the blli_selector may be 0 when
  430                          * there was no blli in the SETUP.
  431                          */
  432                         len = sizeof(struct uni_ie_blli);
  433                         if (conn->blli_selector == 0)
  434                                 memset(ptr, 0, len);
  435                         else
  436                                 memcpy(ptr, &conn->blli[conn->blli_selector -
  437                                     1], len);
  438                         break;
  439 
  440                   case ATM_ATTR_BEARER:
  441                         len = sizeof(struct uni_ie_bearer);
  442                         memcpy(ptr, &conn->bearer, len);
  443                         break;
  444 
  445                   case ATM_ATTR_TRAFFIC:
  446                         len = sizeof(struct uni_ie_traffic);
  447                         memcpy(ptr, &conn->traffic, len);
  448                         break;
  449 
  450                   case ATM_ATTR_QOS:
  451                         len = sizeof(struct uni_ie_qos);
  452                         memcpy(ptr, &conn->qos, len);
  453                         break;
  454 
  455                   case ATM_ATTR_EXQOS:
  456                         len = sizeof(struct uni_ie_exqos);
  457                         memcpy(ptr, &conn->exqos, len);
  458                         break;
  459 
  460                   case ATM_ATTR_CALLED:
  461                         len = sizeof(struct uni_ie_called);
  462                         memcpy(ptr, &conn->called, len);
  463                         break;
  464 
  465                   case ATM_ATTR_CALLEDSUB:
  466                         len = sizeof(struct uni_ie_calledsub);
  467                         memcpy(ptr, &conn->calledsub, len);
  468                         break;
  469 
  470                   case ATM_ATTR_CALLING:
  471                         len = sizeof(struct uni_ie_calling);
  472                         memcpy(ptr, &conn->calling, len);
  473                         break;
  474 
  475                   case ATM_ATTR_CALLINGSUB:
  476                         len = sizeof(struct uni_ie_callingsub);
  477                         memcpy(ptr, &conn->callingsub, len);
  478                         break;
  479 
  480                   case ATM_ATTR_AAL:
  481                         len = sizeof(struct uni_ie_aal);
  482                         memcpy(ptr, &conn->aal, len);
  483                         break;
  484 
  485                   case ATM_ATTR_EPREF:
  486                         len = sizeof(struct uni_ie_epref);
  487                         memcpy(ptr, &conn->epref, len);
  488                         break;
  489 
  490                   case ATM_ATTR_CONNED:
  491                         len = sizeof(struct uni_ie_conned);
  492                         memcpy(ptr, &conn->conned, len);
  493                         break;
  494 
  495                   case ATM_ATTR_CONNEDSUB:
  496                         len = sizeof(struct uni_ie_connedsub);
  497                         memcpy(ptr, &conn->connedsub, len);
  498                         break;
  499 
  500                   case ATM_ATTR_EETD:
  501                         len = sizeof(struct uni_ie_eetd);
  502                         memcpy(ptr, &conn->eetd, len);
  503                         break;
  504 
  505                   case ATM_ATTR_ABRSETUP:
  506                         len = sizeof(struct uni_ie_abrsetup);
  507                         memcpy(ptr, &conn->abrsetup, len);
  508                         break;
  509 
  510                   case ATM_ATTR_ABRADD:
  511                         len = sizeof(struct uni_ie_abradd);
  512                         memcpy(ptr, &conn->abradd, len);
  513                         break;
  514 
  515                   case ATM_ATTR_CONNID:
  516                         len = sizeof(struct uni_ie_connid);
  517                         memcpy(ptr, &conn->connid, len);
  518                         break;
  519 
  520                   case ATM_ATTR_MDCR:
  521                         len = sizeof(struct uni_ie_mdcr);
  522                         memcpy(ptr, &conn->mdcr, len);
  523                         break;
  524                 }
  525                 ptr = (u_char *)ptr + len;
  526         }
  527 
  528         cc_user_ok(user, ATMRESP_ATTRS, val, total);
  529 
  530         CCFREE(val);
  531 }
  532 
  533 /*
  534  * Check whether the state is ok and return the connection
  535  */
  536 static struct ccconn *
  537 cc_set_check(struct ccuser *user)
  538 {
  539         switch(user->state) {
  540 
  541           case USER_OUT_PREPARING:
  542           case USER_IN_ARRIVED:
  543                 return (TAILQ_FIRST(&user->connq));
  544 
  545           default:
  546                 return (NULL);
  547         }
  548 }
  549 
  550 /*
  551  * Set connection attribute(s)
  552  */
  553 static void
  554 cc_attr_set(struct ccuser *user, struct ccconn *conn, uint32_t *attr,
  555     u_int count, u_char *val, size_t vallen)
  556 {
  557         size_t total, len;
  558         u_int i;
  559         u_char *ptr;
  560 
  561         /* determine the length of the total attribute buffer */
  562         total = 0;
  563         ptr = val;
  564         for (i = 0; i < count; i++) {
  565                 len = 0;
  566                 switch ((enum atm_attribute)attr[i]) {
  567 
  568                   case ATM_ATTR_NONE:
  569                         break;
  570 
  571                   case ATM_ATTR_BLLI_SELECTOR:
  572                     {
  573                         uint32_t sel;
  574 
  575                         if (conn->state != CONN_OUT_PREPARING)
  576                                 goto rdonly;
  577                         memcpy(&sel, ptr, sizeof(sel));
  578                         if (sel == 0 || sel > UNI_NUM_IE_BLLI)
  579                                 goto bad_val;
  580                         len = sizeof(uint32_t);
  581                         break;
  582                     }
  583 
  584                   case ATM_ATTR_BLLI:
  585                         len = sizeof(struct uni_ie_blli);
  586                         break;
  587 
  588                   case ATM_ATTR_BEARER:
  589                         if (conn->state != CONN_OUT_PREPARING)
  590                                 goto rdonly;
  591                         len = sizeof(struct uni_ie_bearer);
  592                         break;
  593 
  594                   case ATM_ATTR_TRAFFIC:
  595                         len = sizeof(struct uni_ie_traffic);
  596                         break;
  597 
  598                   case ATM_ATTR_QOS:
  599                         if (conn->state != CONN_OUT_PREPARING)
  600                                 goto rdonly;
  601                         len = sizeof(struct uni_ie_qos);
  602                         break;
  603 
  604                   case ATM_ATTR_EXQOS:
  605                         len = sizeof(struct uni_ie_exqos);
  606                         break;
  607 
  608                   case ATM_ATTR_CALLED:
  609                         goto rdonly;
  610 
  611                   case ATM_ATTR_CALLEDSUB:
  612                         if (conn->state != CONN_OUT_PREPARING)
  613                                 goto rdonly;
  614                         len = sizeof(struct uni_ie_calledsub);
  615                         break;
  616 
  617                   case ATM_ATTR_CALLING:
  618                         if (conn->state != CONN_OUT_PREPARING)
  619                                 goto rdonly;
  620                         len = sizeof(struct uni_ie_calling);
  621                         break;
  622 
  623                   case ATM_ATTR_CALLINGSUB:
  624                         if (conn->state != CONN_OUT_PREPARING)
  625                                 goto rdonly;
  626                         len = sizeof(struct uni_ie_callingsub);
  627                         break;
  628 
  629                   case ATM_ATTR_AAL:
  630                         len = sizeof(struct uni_ie_aal);
  631                         break;
  632 
  633                   case ATM_ATTR_EPREF:
  634                         goto rdonly;
  635 
  636                   case ATM_ATTR_CONNED:
  637                         goto rdonly;
  638 
  639                   case ATM_ATTR_CONNEDSUB:
  640                         goto rdonly;
  641 
  642                   case ATM_ATTR_EETD:
  643                         len = sizeof(struct uni_ie_eetd);
  644                         break;
  645 
  646                   case ATM_ATTR_ABRSETUP:
  647                         len = sizeof(struct uni_ie_abrsetup);
  648                         break;
  649 
  650                   case ATM_ATTR_ABRADD:
  651                         len = sizeof(struct uni_ie_abradd);
  652                         break;
  653 
  654                   case ATM_ATTR_CONNID:
  655                         len = sizeof(struct uni_ie_connid);
  656                         break;
  657 
  658                   case ATM_ATTR_MDCR:
  659                         if (conn->state != CONN_OUT_PREPARING)
  660                                 goto rdonly;
  661                         len = sizeof(struct uni_ie_mdcr);
  662                         break;
  663                 }
  664                 if (len == 0) {
  665                         cc_user_err(user, ATMERR_BAD_ATTR);
  666                         return;
  667                 }
  668                 total += len;
  669                 ptr += len;
  670         }
  671 
  672         /* check the length */
  673         if (vallen != total) {
  674                 cc_user_err(user, ATMERR_BAD_ARGS);
  675                 return;
  676         }
  677 
  678         ptr = val;
  679         for (i = 0; i < count; i++) {
  680                 len = 0;
  681                 switch ((enum atm_attribute)attr[i]) {
  682 
  683                   case ATM_ATTR_NONE:
  684                         break;
  685 
  686                   case ATM_ATTR_BLLI_SELECTOR:
  687                     {
  688                         uint32_t sel;
  689 
  690                         memcpy(&sel, ptr, sizeof(sel));
  691                         conn->blli_selector = sel;
  692                         len = sizeof(uint32_t);
  693                         break;
  694                     }
  695 
  696                   case ATM_ATTR_BLLI:
  697                         len = sizeof(struct uni_ie_blli);
  698                         memcpy(&conn->blli[conn->blli_selector - 1], ptr, len);
  699                         conn->dirty_attr |= CCDIRTY_BLLI;
  700                         break;
  701 
  702                   case ATM_ATTR_BEARER:
  703                         len = sizeof(struct uni_ie_bearer);
  704                         memcpy(&conn->bearer, ptr, len);
  705                         break;
  706 
  707                   case ATM_ATTR_TRAFFIC:
  708                         len = sizeof(struct uni_ie_traffic);
  709                         memcpy(&conn->traffic, ptr, len);
  710                         conn->dirty_attr |= CCDIRTY_TRAFFIC;
  711                         break;
  712 
  713                   case ATM_ATTR_QOS:
  714                         len = sizeof(struct uni_ie_qos);
  715                         memcpy(&conn->qos, ptr, len);
  716                         break;
  717 
  718                   case ATM_ATTR_EXQOS:
  719                         len = sizeof(struct uni_ie_exqos);
  720                         memcpy(&conn->exqos, ptr, len);
  721                         conn->dirty_attr |= CCDIRTY_EXQOS;
  722                         break;
  723 
  724                   case ATM_ATTR_CALLED:
  725                         len = sizeof(struct uni_ie_called);
  726                         break;
  727 
  728                   case ATM_ATTR_CALLEDSUB:
  729                         len = sizeof(struct uni_ie_calledsub);
  730                         memcpy(&conn->calledsub, ptr, len);
  731                         break;
  732 
  733                   case ATM_ATTR_CALLING:
  734                         len = sizeof(struct uni_ie_calling);
  735                         memcpy(&conn->calling, ptr, len);
  736                         break;
  737 
  738                   case ATM_ATTR_CALLINGSUB:
  739                         len = sizeof(struct uni_ie_callingsub);
  740                         memcpy(&conn->callingsub, ptr, len);
  741                         break;
  742 
  743                   case ATM_ATTR_AAL:
  744                         len = sizeof(struct uni_ie_aal);
  745                         memcpy(&conn->aal, ptr, len);
  746                         conn->dirty_attr |= CCDIRTY_AAL;
  747                         break;
  748 
  749                   case ATM_ATTR_EPREF:
  750                         len = sizeof(struct uni_ie_epref);
  751                         break;
  752 
  753                   case ATM_ATTR_CONNED:
  754                         len = sizeof(struct uni_ie_conned);
  755                         break;
  756 
  757                   case ATM_ATTR_CONNEDSUB:
  758                         len = sizeof(struct uni_ie_connedsub);
  759                         break;
  760 
  761                   case ATM_ATTR_EETD:
  762                         len = sizeof(struct uni_ie_eetd);
  763                         memcpy(&conn->eetd, ptr, len);
  764                         conn->dirty_attr |= CCDIRTY_EETD;
  765                         break;
  766 
  767                   case ATM_ATTR_ABRSETUP:
  768                         len = sizeof(struct uni_ie_abrsetup);
  769                         memcpy(&conn->abrsetup, ptr, len);
  770                         conn->dirty_attr |= CCDIRTY_ABRSETUP;
  771                         break;
  772 
  773                   case ATM_ATTR_ABRADD:
  774                         len = sizeof(struct uni_ie_abradd);
  775                         memcpy(&conn->abradd, ptr, len);
  776                         conn->dirty_attr |= CCDIRTY_ABRADD;
  777                         break;
  778 
  779                   case ATM_ATTR_CONNID:
  780                         len = sizeof(struct uni_ie_connid);
  781                         memcpy(&conn->connid, ptr, len);
  782                         conn->dirty_attr |= CCDIRTY_CONNID;
  783                         break;
  784 
  785                   case ATM_ATTR_MDCR:
  786                         len = sizeof(struct uni_ie_mdcr);
  787                         memcpy(&conn->mdcr, ptr, len);
  788                         break;
  789                 }
  790                 ptr += len;
  791         }
  792 
  793         cc_user_ok(user, ATMRESP_NONE, NULL, 0);
  794         return;
  795 
  796   bad_val:
  797         cc_user_err(user, ATMERR_BAD_VALUE);
  798         return;
  799 
  800   rdonly:
  801         cc_user_err(user, ATMERR_RDONLY);
  802         return;
  803 }
  804 
  805 #ifdef CCATM_DEBUG
  806 static const char *op_names[] = {
  807 #define S(OP)   [ATMOP_##OP] = #OP
  808         S(RESP),
  809         S(ABORT_CONNECTION),
  810         S(ACCEPT_INCOMING_CALL),
  811         S(ADD_PARTY),
  812         S(ADD_PARTY_REJECT),
  813         S(ADD_PARTY_SUCCESS),
  814         S(ARRIVAL_OF_INCOMING_CALL),
  815         S(CALL_RELEASE),
  816         S(CONNECT_OUTGOING_CALL),
  817         S(DROP_PARTY),
  818         S(GET_LOCAL_PORT_INFO),
  819         S(P2MP_CALL_ACTIVE),
  820         S(P2P_CALL_ACTIVE),
  821         S(PREPARE_INCOMING_CALL),
  822         S(PREPARE_OUTGOING_CALL),
  823         S(QUERY_CONNECTION_ATTRIBUTES),
  824         S(REJECT_INCOMING_CALL),
  825         S(SET_CONNECTION_ATTRIBUTES),
  826         S(WAIT_ON_INCOMING_CALL),
  827         S(SET_CONNECTION_ATTRIBUTES_X),
  828         S(QUERY_CONNECTION_ATTRIBUTES_X),
  829         S(QUERY_STATE),
  830 #undef S
  831 };
  832 #endif
  833 
  834 /*
  835  * Signal from user - map this to our internal signals and queue
  836  * the mapped signal.
  837  */
  838 int
  839 cc_user_signal(struct ccuser *user, enum atmop sig, struct uni_msg *msg)
  840 {
  841         size_t len = uni_msg_len(msg);
  842         int err = EINVAL;
  843 
  844         if (user->cc->log & CCLOG_USER_SIG)
  845                 cc_user_log(user, "signal %s to user", op_names[sig]);
  846 
  847         if ((u_int)sig > ATMOP_QUERY_STATE)
  848                 goto bad_signal;
  849 
  850         switch (sig) {
  851 
  852           case ATMOP_ABORT_CONNECTION:
  853                 if (len != sizeof(struct atm_abort_connection))
  854                         goto bad_len;
  855                 err = cc_user_sig_msg(user, USER_SIG_ABORT_CONNECTION, msg);
  856                 break;
  857 
  858           case ATMOP_ACCEPT_INCOMING_CALL:
  859                 if (len != sizeof(struct atm_accept_incoming_call))
  860                         goto bad_len;
  861                 err = cc_user_sig_msg(user, USER_SIG_ACCEPT_INCOMING, msg);
  862                 break;
  863 
  864           case ATMOP_ADD_PARTY:
  865                 if (len != sizeof(struct atm_add_party))
  866                         goto bad_len;
  867                 err = cc_user_sig_msg(user, USER_SIG_ADD_PARTY, msg);
  868                 break;
  869 
  870           case ATMOP_CALL_RELEASE:
  871                 if (len != sizeof(struct atm_call_release))
  872                         goto bad_len;
  873                 err = cc_user_sig_msg(user, USER_SIG_CALL_RELEASE, msg);
  874                 break;
  875 
  876           case ATMOP_CONNECT_OUTGOING_CALL:
  877                 if (len != sizeof(struct atm_connect_outgoing_call))
  878                         goto bad_len;
  879                 err = cc_user_sig_msg(user, USER_SIG_CONNECT_OUTGOING, msg);
  880                 break;
  881 
  882           case ATMOP_DROP_PARTY:
  883                 if (len != sizeof(struct atm_drop_party))
  884                         goto bad_len;
  885                 err = cc_user_sig_msg(user, USER_SIG_DROP_PARTY, msg);
  886                 break;
  887 
  888           case ATMOP_GET_LOCAL_PORT_INFO:
  889                 if (len != sizeof(struct atm_get_local_port_info))
  890                         goto bad_len;
  891                 err = cc_user_sig_msg(user, USER_SIG_GET_LOCAL_PORT_INFO, msg);
  892                 break;
  893 
  894           case ATMOP_PREPARE_INCOMING_CALL:
  895                 if (len != sizeof(struct atm_prepare_incoming_call))
  896                         goto bad_len;
  897                 err = cc_user_sig_msg(user, USER_SIG_PREPARE_INCOMING, msg);
  898                 break;
  899 
  900           case ATMOP_PREPARE_OUTGOING_CALL:
  901                 if (len != 0)
  902                         goto bad_len;
  903                 uni_msg_destroy(msg);
  904                 err = cc_user_sig(user, USER_SIG_PREPARE_OUTGOING, NULL, 0);
  905                 break;
  906 
  907           case ATMOP_QUERY_CONNECTION_ATTRIBUTES:
  908                 if (len != sizeof(struct atm_query_connection_attributes))
  909                         goto bad_len;
  910                 err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR, msg);
  911                 break;
  912 
  913           case ATMOP_REJECT_INCOMING_CALL:
  914                 if (len != sizeof(struct atm_reject_incoming_call))
  915                         goto bad_len;
  916                 err = cc_user_sig_msg(user, USER_SIG_REJECT_INCOMING, msg);
  917                 break;
  918 
  919           case ATMOP_SET_CONNECTION_ATTRIBUTES:
  920                 if (len < sizeof(struct atm_set_connection_attributes))
  921                         goto bad_len;
  922                 err = cc_user_sig_msg(user, USER_SIG_SET_ATTR, msg);
  923                 break;
  924 
  925           case ATMOP_WAIT_ON_INCOMING_CALL:
  926                 if (len != 0)
  927                         goto bad_len;
  928                 uni_msg_destroy(msg);
  929                 err = cc_user_sig(user, USER_SIG_WAIT_ON_INCOMING, NULL, 0);
  930                 break;
  931 
  932           case ATMOP_QUERY_CONNECTION_ATTRIBUTES_X:
  933                 if (len < sizeof(struct atm_set_connection_attributes_x) ||
  934                     len != offsetof(struct atm_set_connection_attributes_x,
  935                     attr) + uni_msg_rptr(msg,
  936                     struct atm_set_connection_attributes_x *)->count *
  937                     sizeof(uint32_t))
  938                         goto bad_len;
  939                 err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR_X, msg);
  940                 break;
  941 
  942           case ATMOP_SET_CONNECTION_ATTRIBUTES_X:
  943                 if (len < sizeof(struct atm_set_connection_attributes_x))
  944                         goto bad_len;
  945                 err = cc_user_sig_msg(user, USER_SIG_SET_ATTR_X, msg);
  946                 break;
  947 
  948           case ATMOP_QUERY_STATE:
  949                 if (len != 0)
  950                         goto bad_len;
  951                 uni_msg_destroy(msg);
  952                 err = cc_user_sig(user, USER_SIG_QUERY_STATE, NULL, 0);
  953                 break;
  954 
  955           case ATMOP_RESP:
  956           case ATMOP_ADD_PARTY_REJECT:
  957           case ATMOP_ADD_PARTY_SUCCESS:
  958           case ATMOP_ARRIVAL_OF_INCOMING_CALL:
  959           case ATMOP_P2MP_CALL_ACTIVE:
  960           case ATMOP_P2P_CALL_ACTIVE:
  961           bad_signal:
  962                 /* bad signal */
  963                 if (user->cc->log & CCLOG_USER_SIG)
  964                         cc_user_log(user, "bad signal %u", sig);
  965                 cc_user_err(user, ATMERR_BAD_OP);
  966                 uni_msg_destroy(msg);
  967                 break;
  968         }
  969         return (err);
  970 
  971   bad_len:
  972         /* bad argument length */
  973         if (user->cc->log & CCLOG_USER_SIG)
  974                 cc_user_log(user, "signal %s had bad len=%zu",
  975                     op_names[sig], len);
  976         cc_user_err(user, ATMERR_BAD_ARGS);
  977         uni_msg_destroy(msg);
  978         return (EINVAL);
  979 }
  980 
  981 /*
  982  * Send active signal to user
  983  */
  984 static void
  985 cc_user_active(struct ccuser *user)
  986 {
  987         struct ccconn *conn = TAILQ_FIRST(&user->connq);
  988 
  989         set_state(user, USER_ACTIVE);
  990         if (conn->bearer.cfg == UNI_BEARER_P2P) {
  991                 struct atm_p2p_call_active *act;
  992 
  993                 user->config = USER_P2P;
  994                 act = CCZALLOC(sizeof(*act));
  995                 if (act == NULL)
  996                         return;
  997                 act->connid = conn->connid;
  998                 cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, act, sizeof(*act));
  999                 CCFREE(act);
 1000         } else {
 1001                 struct atm_p2mp_call_active *act;
 1002 
 1003                 user->config = USER_ROOT;
 1004                 act = CCZALLOC(sizeof(*act));
 1005                 if (act == NULL)
 1006                         return;
 1007                 act->connid = conn->connid;
 1008                 cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, act, sizeof(*act));
 1009                 CCFREE(act);
 1010         }
 1011 }
 1012 
 1013 /*
 1014 * Handle a signal to this user
 1015 */
 1016 void
 1017 cc_user_sig_handle(struct ccuser *user, enum user_sig sig,
 1018     void *arg, u_int arg2)
 1019 {
 1020 
 1021         if (user->cc->log & CCLOG_USER_SIG)
 1022                 cc_user_log(user, "signal %s to user state %s",
 1023                     cc_user_sigtab[sig], stab[user->state]);
 1024 
 1025         switch (sig) {
 1026 
 1027 
 1028           case USER_SIG_PREPARE_OUTGOING:
 1029             {
 1030                 /*
 1031                  * Here we create a connection for the call we soon will make.
 1032                  * We put this call on the list of orphaned connections,
 1033                  * because we don't know yet, which port will get the
 1034                  * connection. It is assigned, when the user issues the call
 1035                  * to connect.
 1036                  */
 1037                 struct ccconn *conn;
 1038 
 1039                 if (user->state != USER_NULL) {
 1040                         cc_user_err(user, ATMERR_BAD_STATE);
 1041                         goto bad_state;
 1042                 }
 1043                 conn = cc_conn_create(user->cc);
 1044                 if (conn == NULL) {
 1045                         cc_user_err(user, ATMERR_NOMEM);
 1046                         return;
 1047                 }
 1048                 set_state(user, USER_OUT_PREPARING);
 1049                 cc_conn_set_state(conn, CONN_OUT_PREPARING);
 1050                 conn->blli_selector = 1;
 1051                 cc_connect_to_user(conn, user);
 1052 
 1053                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1054                 return;
 1055             }
 1056 
 1057 
 1058           case USER_SIG_CONNECT_OUTGOING:
 1059             {
 1060                 /*
 1061                  * Request to connect that call
 1062                  *
 1063                  * Here we assign the connection to a port.
 1064                  */
 1065                 struct uni_msg *msg = arg;
 1066                 struct atm_connect_outgoing_call *req = uni_msg_rptr(msg,
 1067                     struct atm_connect_outgoing_call *);
 1068                 struct ccdata *priv = user->cc;
 1069                 struct ccport *port;
 1070                 struct ccaddr *addr;
 1071                 struct ccconn *conn = TAILQ_FIRST(&user->connq);
 1072 
 1073                 if (user->state != USER_OUT_PREPARING) {
 1074                         uni_msg_destroy(msg);
 1075                         cc_user_err(user, ATMERR_BAD_STATE);
 1076                         goto bad_state;
 1077                 }
 1078                 if (!IE_ISPRESENT(req->called)) {
 1079                         uni_msg_destroy(msg);
 1080                         cc_user_err(user, ATMERR_BAD_ARGS);
 1081                         return;
 1082                 }
 1083                 CCASSERT(conn->port == NULL, ("connection still on port"));
 1084 
 1085                 if (TAILQ_EMPTY(&priv->port_list)) {
 1086                         /*
 1087                          * We have no ports - reject
 1088                          */
 1089                         uni_msg_destroy(msg);
 1090                         cc_user_err(user, ATMERR_BAD_PORT);
 1091                         return;
 1092                 }
 1093 
 1094                 /*
 1095                  * Find the correct port
 1096                  * Routing of outgoing calls goes to the lowest numbered port
 1097                  * with a matching address or, if no address match is found to
 1098                  * the lowest numbered port.
 1099                  */
 1100                 TAILQ_FOREACH(port, &priv->port_list, node_link)
 1101                         TAILQ_FOREACH(addr, &port->addr_list, port_link)
 1102                                 if (addr_matches(addr, conn))
 1103                                         break;
 1104 
 1105                 if (port == NULL)
 1106                         port = TAILQ_FIRST(&priv->port_list);
 1107 
 1108                 cc_conn_ins_port(conn, port);
 1109                 conn->called = req->called;
 1110                 uni_msg_destroy(msg);
 1111 
 1112                 /*
 1113                  * Now move the state
 1114                  */
 1115                 set_state(user, USER_OUT_WAIT_OK);
 1116                 cc_conn_sig(conn, CONN_SIG_CONNECT_OUTGOING, NULL);
 1117 
 1118                 return;
 1119             }
 1120 
 1121 
 1122           case USER_SIG_CONNECT_OUTGOING_ERR:
 1123                 switch (user->state) {
 1124 
 1125                   case USER_OUT_WAIT_OK:
 1126                         set_state(user, USER_OUT_PREPARING);
 1127                         cc_user_err(user, arg2);
 1128                         break;
 1129 
 1130                   case USER_REL_WAIT_CONN:
 1131                     {
 1132                         struct ccconn *conn;
 1133 
 1134                         conn = TAILQ_FIRST(&user->connq);
 1135                         if (conn != NULL) {
 1136                                 cc_disconnect_from_user(conn);
 1137                                 cc_conn_destroy(conn);
 1138                         }
 1139 
 1140                         cc_user_reset(user);
 1141                         cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1142                         break;
 1143                     }
 1144 
 1145                   default:
 1146                         goto bad_state;
 1147                 }
 1148                 return;
 1149 
 1150 
 1151           case USER_SIG_CONNECT_OUTGOING_OK:
 1152                 switch (user->state) {
 1153 
 1154                   case USER_OUT_WAIT_OK:
 1155                         set_state(user, USER_OUT_WAIT_CONF);
 1156                         cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1157                         break;
 1158 
 1159                   case USER_REL_WAIT_CONN:
 1160                         set_state(user, USER_REL_WAIT_SCONF);
 1161                         break;
 1162 
 1163                   default:
 1164                         goto bad_state;
 1165                 }
 1166                 return;
 1167 
 1168 
 1169           case USER_SIG_SETUP_CONFIRM:
 1170                 /*
 1171                  * SETUP.confirm from UNI stack.
 1172                  */
 1173                 switch (user->state) {
 1174 
 1175                   case USER_OUT_WAIT_CONF:
 1176                         cc_user_active(user);
 1177                         break;
 1178 
 1179                   case USER_REL_WAIT_SCONF:
 1180                         /* now try to release */
 1181                         set_state(user, USER_REL_WAIT_CONF);
 1182                         cc_conn_sig(TAILQ_FIRST(&user->connq),
 1183                             CONN_SIG_RELEASE, NULL);
 1184                         break;
 1185 
 1186                   default:
 1187                         goto bad_state;
 1188                 }
 1189                 return;
 1190 
 1191 
 1192           case USER_SIG_PREPARE_INCOMING:
 1193             {
 1194                 struct uni_msg *msg = arg;
 1195                 struct ccuser *ptr;
 1196                 struct atm_prepare_incoming_call *prep = uni_msg_rptr(msg,
 1197                     struct atm_prepare_incoming_call *);
 1198 
 1199                 if (user->state != USER_NULL) {
 1200                         uni_msg_destroy(msg);
 1201                         cc_user_err(user, ATMERR_BAD_STATE);
 1202                         goto bad_state;
 1203                 }
 1204 
 1205                 /*
 1206                  * Check the SAP
 1207                  */
 1208                 if (unisve_check_sap(&prep->sap) != UNISVE_OK) {
 1209                         uni_msg_destroy(msg);
 1210                         cc_user_err(user, ATMERR_BAD_SAP);
 1211                         return;
 1212                 }
 1213 
 1214                 /*
 1215                  * Loop through all incoming calls and check whether there
 1216                  * is an overlap in SAP space.
 1217                  */
 1218                 LIST_FOREACH(ptr, &user->cc->user_list, node_link) {
 1219                         if (check_overlap(ptr, &prep->sap)) {
 1220                                 uni_msg_destroy(msg);
 1221                                 cc_user_err(user, ATMERR_OVERLAP);
 1222                                 return;
 1223                         }
 1224                 }
 1225 
 1226                 /*
 1227                  * Save info and set state
 1228                  */
 1229                 user->sap = CCZALLOC(sizeof(struct uni_sap));
 1230                 if (user->sap == NULL) {
 1231                         uni_msg_destroy(msg);
 1232                         cc_user_err(user, ATMERR_NOMEM);
 1233                         return;
 1234                 }
 1235                 *user->sap = prep->sap;
 1236                 user->queue_max = prep->queue_size;
 1237                 user->queue_act = 0;
 1238                 uni_msg_destroy(msg);
 1239 
 1240                 set_state(user, USER_IN_PREPARING);
 1241                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1242 
 1243                 return;
 1244             }
 1245 
 1246 
 1247           case USER_SIG_WAIT_ON_INCOMING:
 1248                 if (user->state != USER_IN_PREPARING) {
 1249                         cc_user_err(user, ATMERR_BAD_STATE);
 1250                         goto bad_state;
 1251                 }
 1252 
 1253                 set_state(user, USER_IN_WAITING);
 1254                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1255                 return;
 1256 
 1257 
 1258           case USER_SIG_SETUP_IND:
 1259                 /*
 1260                  * New connection queued up in the queue. If this is the
 1261                  * first one, inform the application of the arrival.
 1262                  */
 1263                 switch (user->state) {
 1264 
 1265                   case USER_IN_WAITING:
 1266                         do_arrival(user);
 1267                         break;
 1268 
 1269                   case USER_IN_ARRIVED:
 1270                   case USER_IN_WAIT_REJ:
 1271                   case USER_IN_WAIT_ACC:
 1272                         break;
 1273 
 1274                   default:
 1275                         goto bad_state;
 1276                 }
 1277                 return;
 1278 
 1279 
 1280           case USER_SIG_REJECT_INCOMING:
 1281              {
 1282                 /*
 1283                  * User rejects call. This is done on the OLD user
 1284                  * (i.e. the one sending the arrival).
 1285                  */
 1286                 struct uni_msg *msg = arg;
 1287                 struct atm_reject_incoming_call *rej = uni_msg_rptr(msg,
 1288                     struct atm_reject_incoming_call *);
 1289                 struct ccconn *conn = TAILQ_FIRST(&user->connq);
 1290 
 1291                 if (user->state != USER_IN_ARRIVED) {
 1292                         uni_msg_destroy(msg);
 1293                         cc_user_err(user, ATMERR_BAD_STATE);
 1294                         goto bad_state;
 1295                 }
 1296                 if (user->aborted) {
 1297                         /* connection has disappeared. Send an ok
 1298                          * to the user and lock whether there is another
 1299                          * connection at this endpoint */
 1300                         uni_msg_destroy(msg);
 1301                         cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1302 
 1303                         set_state(user, USER_IN_WAITING);
 1304                         do_arrival(user);
 1305                         return;
 1306                 }
 1307                 conn->cause[0] = rej->cause;
 1308                 memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
 1309                 uni_msg_destroy(msg);
 1310 
 1311                 set_state(user, USER_IN_WAIT_REJ);
 1312                 cc_conn_sig(conn, CONN_SIG_REJECT, NULL);
 1313 
 1314                 return;
 1315             }
 1316 
 1317 
 1318           case USER_SIG_REJECT_OK:
 1319                 if (user->state != USER_IN_WAIT_REJ)
 1320                         goto bad_state;
 1321                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1322 
 1323                 set_state(user, USER_IN_WAITING);
 1324                 do_arrival(user);
 1325                 return;
 1326 
 1327 
 1328           case USER_SIG_REJECT_ERR:
 1329                 if (user->state != USER_IN_WAIT_REJ)
 1330                         goto bad_state;
 1331                 cc_user_err(user, arg2);
 1332 
 1333                 if (arg == NULL)
 1334                         set_state(user, USER_IN_ARRIVED);
 1335                 else {
 1336                         set_state(user, USER_IN_WAITING);
 1337                         do_arrival(user);
 1338                 }
 1339                 return;
 1340 
 1341 
 1342           case USER_SIG_ACCEPT_INCOMING:
 1343             {
 1344                 /*
 1345                  * User accepts call. This is done on the OLD user (i.e. the one
 1346                  * sending the arrival), the message contains a pointer to the
 1347                  * new endpoint.
 1348                  */
 1349                 struct uni_msg *msg = arg;
 1350                 struct atm_accept_incoming_call *acc =
 1351                     uni_msg_rptr(msg, struct atm_accept_incoming_call *);
 1352                 struct ccuser *newep;
 1353 
 1354                 if (user->state != USER_IN_ARRIVED) {
 1355                         uni_msg_destroy(msg);
 1356                         cc_user_err(user, ATMERR_BAD_STATE);
 1357                         return;
 1358                 }
 1359                 if (user->aborted) {
 1360                         /* connection has disappeared. Send an error
 1361                          * to the user and lock whether there is another
 1362                          * connection at this endpoint */
 1363                         uni_msg_destroy(msg);
 1364                         cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
 1365 
 1366                         set_state(user, USER_IN_WAITING);
 1367                         do_arrival(user);
 1368                         return;
 1369                 }
 1370                 acc->newep[sizeof(acc->newep) - 1] = '\0';
 1371 
 1372                 LIST_FOREACH(newep, &user->cc->user_list, node_link)
 1373                         if (strcmp(acc->newep, newep->name) == 0)
 1374                                 break;
 1375                 uni_msg_destroy(msg);
 1376 
 1377                 if (newep == NULL) {
 1378                         cc_user_err(user, ATMERR_BAD_ENDPOINT);
 1379                         return;
 1380                 }
 1381 
 1382                 if (newep->state != USER_NULL || newep->accepted != NULL) {
 1383                         cc_user_err(user, ATMERR_BAD_STATE);
 1384                         return;
 1385                 }
 1386 
 1387                 set_state(user, USER_IN_WAIT_ACC);
 1388                 cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep);
 1389 
 1390                 return;
 1391             }
 1392 
 1393 
 1394           case USER_SIG_ACCEPT_OK:
 1395                 if (user->state != USER_IN_WAIT_ACC)
 1396                         goto bad_state;
 1397                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1398 
 1399                 set_state(user, USER_IN_WAITING);
 1400                 do_arrival(user);
 1401                 return;
 1402 
 1403 
 1404           case USER_SIG_ACCEPT_ERR:
 1405                 if (user->state != USER_IN_WAIT_ACC)
 1406                         goto bad_state;
 1407                 cc_user_err(user, arg2);
 1408 
 1409                 if (arg == NULL) {
 1410                         /* arg used as flag! */
 1411                         set_state(user, USER_IN_ARRIVED);
 1412                 } else {
 1413                         set_state(user, USER_IN_WAITING);
 1414                         do_arrival(user);
 1415                 }
 1416                 return;
 1417 
 1418 
 1419           case USER_SIG_ACCEPTING:
 1420                 if (user->state != USER_NULL)
 1421                         goto bad_state;
 1422                 set_state(user, USER_IN_ACCEPTING);
 1423                 return;
 1424 
 1425 
 1426           case USER_SIG_SETUP_COMPL:
 1427             {
 1428                 struct ccconn *conn = TAILQ_FIRST(&user->connq);
 1429 
 1430                 if (user->state != USER_IN_ACCEPTING)
 1431                         goto bad_state;
 1432 
 1433                 user->state = USER_ACTIVE;
 1434                 if (conn->bearer.cfg == UNI_BEARER_P2P) {
 1435                         struct atm_p2p_call_active *act;
 1436 
 1437                         user->config = USER_P2P;
 1438                         act = CCZALLOC(sizeof(*act));
 1439                         if (act == NULL)
 1440                                 return;
 1441                         act->connid = conn->connid;
 1442                         cc_user_send(user, ATMOP_P2P_CALL_ACTIVE,
 1443                             act, sizeof(*act));
 1444                         CCFREE(act);
 1445                 } else {
 1446                         struct atm_p2mp_call_active *act;
 1447 
 1448                         user->config = USER_LEAF;
 1449                         act = CCZALLOC(sizeof(*act));
 1450                         if (act == NULL)
 1451                                 return;
 1452                         act->connid = conn->connid;
 1453                         cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE,
 1454                             act, sizeof(*act));
 1455                         CCFREE(act);
 1456                 }
 1457                 return;
 1458             }
 1459 
 1460 
 1461           case USER_SIG_CALL_RELEASE:
 1462             {
 1463                 struct uni_msg *msg = arg;
 1464                 struct atm_call_release *api = uni_msg_rptr(msg,
 1465                     struct atm_call_release *);
 1466                 struct ccconn *conn;
 1467 
 1468                 conn = TAILQ_FIRST(&user->connq);
 1469                 switch (user->state) {
 1470 
 1471                   case USER_OUT_WAIT_OK:        /* U2/A3 */
 1472                         /* wait for CONN_OK first */
 1473                         conn->cause[0] = api->cause[0];
 1474                         conn->cause[1] = api->cause[1];
 1475                         set_state(user, USER_REL_WAIT_CONN);
 1476                         break;
 1477 
 1478                   case USER_OUT_WAIT_CONF:      /* U3/A3 */
 1479                         /* wait for SETUP.confirm first */
 1480                         conn->cause[0] = api->cause[0];
 1481                         conn->cause[1] = api->cause[1];
 1482                         set_state(user, USER_REL_WAIT_SCONF);
 1483                         break;
 1484 
 1485                   case USER_IN_ACCEPTING:       /* U11/A7 */
 1486                         conn->cause[0] = api->cause[0];
 1487                         conn->cause[1] = api->cause[1];
 1488                         set_state(user, USER_REL_WAIT_SCOMP);
 1489                         cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
 1490                         break;
 1491 
 1492                   case USER_ACTIVE:             /* U4/A8,A9,A10 */
 1493                         conn->cause[0] = api->cause[0];
 1494                         conn->cause[1] = api->cause[1];
 1495                         set_state(user, USER_REL_WAIT);
 1496                         cc_conn_sig(conn, CONN_SIG_RELEASE, NULL);
 1497                         break;
 1498 
 1499                   default:
 1500                         uni_msg_destroy(msg);
 1501                         cc_user_err(user, ATMERR_BAD_STATE);
 1502                         goto bad_state;
 1503                 }
 1504                 uni_msg_destroy(msg);
 1505                 return;
 1506             }
 1507 
 1508 
 1509           case USER_SIG_RELEASE_CONFIRM:
 1510             {
 1511                 struct atm_call_release *ind;
 1512 
 1513                 switch (user->state) {
 1514 
 1515                   case USER_OUT_WAIT_CONF:      /* U3/A3 */
 1516                   case USER_ACTIVE:             /* U4/A8,A9,A10 */
 1517                         cc_user_reset(user);
 1518                         break;
 1519 
 1520                   case USER_REL_WAIT:           /* U5 /A8,A9,A10 */
 1521                   case USER_REL_WAIT_SCOMP:     /* U12/A7 */
 1522                   case USER_REL_WAIT_SCONF:     /* U13/A3 */
 1523                   case USER_REL_WAIT_CONF:      /* U14/A3 */
 1524                         cc_user_reset(user);
 1525                         cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1526                         return;
 1527 
 1528                   case USER_IN_ACCEPTING:       /* U11/A7 */
 1529                         cc_user_reset(user);
 1530                         break;
 1531 
 1532                   default:
 1533                         goto bad_state;
 1534                 }
 1535 
 1536                 ind = CCZALLOC(sizeof(*ind));
 1537                 if (ind == NULL)
 1538                         return;
 1539                 memcpy(ind->cause, user->cause, sizeof(ind->cause));
 1540                 cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind));
 1541                 CCFREE(ind);
 1542                 return;
 1543             }
 1544 
 1545 
 1546           case USER_SIG_RELEASE_ERR:
 1547                 switch (user->state) {
 1548 
 1549                   case USER_REL_WAIT:           /* U5/A8,A9,A10 */
 1550                         set_state(user, USER_ACTIVE);
 1551                         cc_user_err(user, ATM_MKUNIERR(arg2));
 1552                         break;
 1553 
 1554                   case USER_REL_WAIT_CONF:      /* U14/A3 */
 1555                         cc_user_err(user, ATM_MKUNIERR(arg2));
 1556                         cc_user_active(user);
 1557                         break;
 1558 
 1559                   case USER_REL_WAIT_SCOMP:     /* U12/A7 */
 1560                         set_state(user, USER_IN_ACCEPTING);
 1561                         cc_user_err(user, ATM_MKUNIERR(arg2));
 1562                         break;
 1563 
 1564                   default:
 1565                         goto bad_state;
 1566                 }
 1567                 return;
 1568 
 1569 
 1570           case USER_SIG_ADD_PARTY:
 1571             {
 1572                 struct uni_msg *msg = arg;
 1573                 struct atm_add_party *add = uni_msg_rptr(msg,
 1574                     struct atm_add_party *);
 1575                 struct ccconn *conn;
 1576 
 1577                 if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
 1578                         uni_msg_destroy(msg);
 1579                         cc_user_err(user, ATMERR_BAD_STATE);
 1580                         return;
 1581                 }
 1582 
 1583                 if (add->leaf_ident == 0 || add->leaf_ident >= 32786) {
 1584                         uni_msg_destroy(msg);
 1585                         cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
 1586                         return;
 1587                 }
 1588 
 1589                 conn = TAILQ_FIRST(&user->connq);
 1590                 conn->called = add->called;
 1591 
 1592                 cc_conn_sig(conn, CONN_SIG_ADD_PARTY,
 1593                     (void *)(uintptr_t)add->leaf_ident);
 1594 
 1595                 uni_msg_destroy(msg);
 1596                 return;
 1597             }
 1598 
 1599 
 1600           case USER_SIG_ADD_PARTY_ERR:
 1601                 if (user->state != USER_ACTIVE)
 1602                         goto bad_state;
 1603                 cc_user_err(user, arg2);
 1604                 return;
 1605 
 1606 
 1607           case USER_SIG_ADD_PARTY_OK:
 1608                 if (user->state != USER_ACTIVE)
 1609                         goto bad_state;
 1610                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1611                 return;
 1612 
 1613 
 1614           case USER_SIG_ADD_PARTY_ACK:
 1615             {
 1616                 u_int leaf_ident = arg2;
 1617                 struct atm_add_party_success *succ;
 1618 
 1619                 if (user->state != USER_ACTIVE)
 1620                         goto bad_state;
 1621 
 1622                 succ = CCZALLOC(sizeof(*succ));
 1623                 if (succ == NULL)
 1624                         return;
 1625 
 1626                 succ->leaf_ident = leaf_ident;
 1627                 cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS,
 1628                     succ, sizeof(*succ));
 1629 
 1630                 CCFREE(succ);
 1631                 return;
 1632             }
 1633 
 1634 
 1635           case USER_SIG_ADD_PARTY_REJ:
 1636             {
 1637                 u_int leaf_ident = arg2;
 1638                 struct atm_add_party_reject *reject;
 1639 
 1640                 if (user->state != USER_ACTIVE)
 1641                         goto bad_state;
 1642 
 1643                 reject = CCZALLOC(sizeof(*reject));
 1644                 if (reject == NULL)
 1645                         return;
 1646 
 1647                 reject->leaf_ident = leaf_ident;
 1648                 reject->cause = user->cause[0];
 1649                 cc_user_send(user, ATMOP_ADD_PARTY_REJECT,
 1650                     reject, sizeof(*reject));
 1651 
 1652                 CCFREE(reject);
 1653                 return;
 1654             }
 1655 
 1656 
 1657           case USER_SIG_DROP_PARTY:
 1658             {
 1659                 struct uni_msg *msg = arg;
 1660                 struct atm_drop_party *drop = uni_msg_rptr(msg,
 1661                     struct atm_drop_party *);
 1662                 struct ccconn *conn;
 1663 
 1664                 if (user->state != USER_ACTIVE || user->config != USER_ROOT) {
 1665                         uni_msg_destroy(msg);
 1666                         cc_user_err(user, ATMERR_BAD_STATE);
 1667                         return;
 1668                 }
 1669 
 1670                 if (drop->leaf_ident >= 32786) {
 1671                         uni_msg_destroy(msg);
 1672                         cc_user_err(user, ATMERR_BAD_LEAF_IDENT);
 1673                         return;
 1674                 }
 1675 
 1676                 conn = TAILQ_FIRST(&user->connq);
 1677                 conn->cause[0] = drop->cause;
 1678                 memset(&conn->cause[1], 0, sizeof(conn->cause[1]));
 1679 
 1680                 cc_conn_sig(conn, CONN_SIG_DROP_PARTY,
 1681                     (void *)(uintptr_t)drop->leaf_ident);
 1682 
 1683                 uni_msg_destroy(msg);
 1684                 return;
 1685             }
 1686 
 1687 
 1688           case USER_SIG_DROP_PARTY_ERR:
 1689                 if (user->state != USER_ACTIVE)
 1690                         goto bad_state;
 1691                 cc_user_err(user, arg2);
 1692                 return;
 1693 
 1694 
 1695           case USER_SIG_DROP_PARTY_OK:
 1696                 if (user->state != USER_ACTIVE)
 1697                         goto bad_state;
 1698                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1699                 return;
 1700 
 1701 
 1702           case USER_SIG_DROP_PARTY_IND:
 1703             {
 1704                 u_int leaf_ident = arg2;
 1705                 struct atm_drop_party *drop;
 1706 
 1707                 if (user->state != USER_ACTIVE)
 1708                         goto bad_state;
 1709 
 1710                 drop = CCZALLOC(sizeof(*drop));
 1711                 if (drop == NULL)
 1712                         return;
 1713 
 1714                 drop->leaf_ident = leaf_ident;
 1715                 drop->cause = user->cause[0];
 1716                 cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop));
 1717 
 1718                 CCFREE(drop);
 1719                 return;
 1720             }
 1721 
 1722 
 1723           case USER_SIG_QUERY_ATTR:
 1724             {
 1725                 struct uni_msg *msg = arg;
 1726                 struct atm_query_connection_attributes *req;
 1727                 struct ccconn *conn;
 1728 
 1729                 if (user->aborted) {
 1730                         cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
 1731                         uni_msg_destroy(msg);
 1732                         return;
 1733                 }
 1734                 conn = cc_query_check(user);
 1735                 if (conn == NULL) {
 1736                         cc_user_err(user, ATMERR_BAD_STATE);
 1737                         uni_msg_destroy(msg);
 1738                         return;
 1739                 }
 1740                 req = uni_msg_rptr(msg,
 1741                     struct atm_query_connection_attributes *);
 1742                 cc_attr_query(user, conn, &req->attr, 1);
 1743                 uni_msg_destroy(msg);
 1744                 return;
 1745             }
 1746 
 1747           case USER_SIG_QUERY_ATTR_X:
 1748             {
 1749                 struct uni_msg *msg = arg;
 1750                 struct atm_query_connection_attributes_x *req;
 1751                 struct ccconn *conn;
 1752 
 1753                 conn = cc_query_check(user);
 1754                 if (conn == NULL) {
 1755                         cc_user_err(user, ATMERR_BAD_STATE);
 1756                         uni_msg_destroy(msg);
 1757                         return;
 1758                 }
 1759                 req = uni_msg_rptr(msg,
 1760                     struct atm_query_connection_attributes_x *);
 1761                 cc_attr_query(user, conn, req->attr, req->count);
 1762                 uni_msg_destroy(msg);
 1763                 return;
 1764             }
 1765 
 1766           case USER_SIG_SET_ATTR:
 1767             {
 1768                 struct uni_msg *msg = arg;
 1769                 struct atm_set_connection_attributes *req;
 1770                 struct ccconn *conn;
 1771 
 1772                 if (user->aborted) {
 1773                         cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED);
 1774                         uni_msg_destroy(msg);
 1775                         return;
 1776                 }
 1777                 conn = cc_set_check(user);
 1778                 if (conn == NULL) {
 1779                         cc_user_err(user, ATMERR_BAD_STATE);
 1780                         uni_msg_destroy(msg);
 1781                         return;
 1782                 }
 1783                 req = uni_msg_rptr(msg, struct atm_set_connection_attributes *);
 1784                 cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1),
 1785                     uni_msg_len(msg) - sizeof(*req));
 1786                 uni_msg_destroy(msg);
 1787                 return;
 1788             }
 1789 
 1790           case USER_SIG_SET_ATTR_X:
 1791             {
 1792                 struct uni_msg *msg = arg;
 1793                 struct atm_set_connection_attributes_x *req;
 1794                 struct ccconn *conn;
 1795 
 1796                 conn = cc_set_check(user);
 1797                 if (conn == NULL) {
 1798                         cc_user_err(user, ATMERR_BAD_STATE);
 1799                         uni_msg_destroy(msg);
 1800                         return;
 1801                 }
 1802                 req = uni_msg_rptr(msg,
 1803                     struct atm_set_connection_attributes_x *);
 1804                 cc_attr_set(user, conn, req->attr, req->count,
 1805                     (u_char *)req->attr + req->count * sizeof(req->attr[0]),
 1806                     uni_msg_len(msg) -
 1807                     offsetof(struct atm_set_connection_attributes_x, attr) -
 1808                     req->count * sizeof(req->attr[0]));
 1809                 uni_msg_destroy(msg);
 1810                 return;
 1811             }
 1812 
 1813           case USER_SIG_QUERY_STATE:
 1814             {
 1815                 struct atm_epstate state;
 1816 
 1817                 strcpy(state.name, user->name);
 1818                 switch (user->state) {
 1819 
 1820                   case USER_NULL:
 1821                         if (user->accepted != NULL)
 1822                                 state.state = ATM_A7;
 1823                         else
 1824                                 state.state = ATM_A1;
 1825                         break;
 1826 
 1827                   case USER_OUT_PREPARING:
 1828                         state.state = ATM_A2;
 1829                         break;
 1830 
 1831                   case USER_OUT_WAIT_OK:
 1832                   case USER_OUT_WAIT_CONF:
 1833                   case USER_REL_WAIT_SCONF:
 1834                   case USER_REL_WAIT_CONF:
 1835                   case USER_REL_WAIT_CONN:
 1836                         state.state = ATM_A3;
 1837                         break;
 1838 
 1839                   case USER_ACTIVE:
 1840                   case USER_REL_WAIT:
 1841                         switch (user->config) {
 1842 
 1843                           case USER_P2P:
 1844                                 state.state = ATM_A8;
 1845                                 break;
 1846 
 1847                           case USER_ROOT:
 1848                                 state.state = ATM_A9;
 1849                                 break;
 1850 
 1851                           case USER_LEAF:
 1852                                 state.state = ATM_A10;
 1853                                 break;
 1854                         }
 1855                         break;
 1856 
 1857                   case USER_IN_PREPARING:
 1858                         state.state = ATM_A4;
 1859                         break;
 1860 
 1861                   case USER_IN_WAITING:
 1862                         state.state = ATM_A5;
 1863                         break;
 1864 
 1865                   case USER_IN_ARRIVED:
 1866                   case USER_IN_WAIT_REJ:
 1867                   case USER_IN_WAIT_ACC:
 1868                         state.state = ATM_A6;
 1869                         break;
 1870 
 1871                   case USER_IN_ACCEPTING:
 1872                   case USER_REL_WAIT_SCOMP:
 1873                         state.state = ATM_A7;
 1874                         break;
 1875                 }
 1876                 cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state));
 1877                 return;
 1878             }
 1879 
 1880           case USER_SIG_GET_LOCAL_PORT_INFO:
 1881             {
 1882                 struct uni_msg *msg = arg;
 1883                 struct atm_port_list *list;
 1884                 size_t list_len;
 1885 
 1886                 list = cc_get_local_port_info(user->cc,
 1887                     uni_msg_rptr(msg, struct atm_get_local_port_info *)->port,
 1888                     &list_len);
 1889                 uni_msg_destroy(msg);
 1890                 if (list == NULL) {
 1891                         cc_user_err(user, ATMERR_NOMEM);
 1892                         return;
 1893                 }
 1894                 cc_user_ok(user, ATMRESP_PORTS, list, list_len);
 1895                 CCFREE(list);
 1896                 return;
 1897             }
 1898 
 1899           case USER_SIG_ABORT_CONNECTION:
 1900             {
 1901                 struct uni_msg *msg = arg;
 1902                 struct atm_abort_connection *abo = uni_msg_rptr(msg,
 1903                     struct atm_abort_connection *);
 1904 
 1905                 cc_user_abort(user, &abo->cause);
 1906                 uni_msg_destroy(msg);
 1907                 cc_user_ok(user, ATMRESP_NONE, NULL, 0);
 1908                 return;
 1909             }
 1910 
 1911         }
 1912         if (user->cc->log & CCLOG_USER_SIG)
 1913                 cc_user_log(user, "bad signal=%u in state=%u",
 1914                     sig, user->state);
 1915         return;
 1916 
 1917   bad_state:
 1918         if (user->cc->log & CCLOG_USER_SIG)
 1919                 cc_user_log(user, "bad state=%u for signal=%u",
 1920                     user->state, sig);
 1921         return;
 1922 }

Cache object: dc128a21da45be4f1ae1cbfb3469ff83


[ 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.