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/sig/sig_reset.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) 1996-2003
    3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
    4  *      All rights reserved.
    5  *
    6  * Author: Hartmut Brandt <harti@freebsd.org>
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $Begemot: libunimsg/netnatm/sig/sig_reset.c,v 1.11 2004/08/05 07:11:03 brandt Exp $
   30  *
   31  * Reset-start and reset-respond
   32  */
   33 
   34 #include <netnatm/unimsg.h>
   35 #include <netnatm/saal/sscfudef.h>
   36 #include <netnatm/msg/unistruct.h>
   37 #include <netnatm/msg/unimsglib.h>
   38 #include <netnatm/sig/uni.h>
   39 
   40 #include <netnatm/sig/unipriv.h>
   41 #include <netnatm/sig/unimkmsg.h>
   42 
   43 static void response_restart(struct uni *, struct uni_msg *, struct uni_all *);
   44 static void response_status(struct uni *, struct uni_msg *, struct uni_all *);
   45 
   46 static void response_t317(struct uni *);
   47 
   48 static void response_error(struct uni *, struct uniapi_reset_error_response *,
   49     uint32_t cookie);
   50 static void response_response(struct uni *, struct uniapi_reset_response *,
   51     uint32_t);
   52 
   53 static void start_request(struct uni *, struct uniapi_reset_request *,
   54     uint32_t);
   55 
   56 static void start_t316(struct uni *);
   57 
   58 static void start_restart_ack(struct uni *, struct uni_msg *, struct uni_all *);
   59 static void start_status(struct uni *, struct uni_msg *, struct uni_all *);
   60 
   61 static int restart_forward(struct uni *, const struct uni_all *);
   62 
   63 #define DEF_PRIV_SIG(NAME, FROM)        [SIG##NAME] =   "SIG"#NAME,
   64 static const char *const start_sigs[] = {
   65         DEF_START_SIGS
   66 };
   67 #undef DEF_PRIV_SIG
   68 
   69 #define DEF_PRIV_SIG(NAME, FROM)        [SIG##NAME] =   "SIG"#NAME,
   70 static const char *const respond_sigs[] = {
   71         DEF_RESPOND_SIGS
   72 };
   73 #undef DEF_PRIV_SIG
   74 
   75 TIMER_FUNC_UNI(t317, t317_func)
   76 TIMER_FUNC_UNI(t316, t316_func)
   77 
   78 /*
   79  * Reset-Start process.
   80  */
   81 void
   82 uni_sig_start(struct uni *uni, u_int sig, uint32_t cookie,
   83     struct uni_msg *m, struct uni_all *u)
   84 {
   85         if (sig >= SIGS_END) {
   86                 VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
   87                     "Reset-Start", sig);
   88                 if (m)
   89                         uni_msg_destroy(m);
   90                 if (u)
   91                         UNI_FREE(u);
   92                 return;
   93         }
   94 
   95         VERBOSE(uni, UNI_FAC_RESTART, 1,
   96             "Signal %s in state %u of Reset-Start; cookie %u",
   97             start_sigs[sig], uni->glob_start, cookie);
   98 
   99         switch (sig) {
  100 
  101         /*
  102          * User requests
  103          */
  104           case SIGS_RESET_request:
  105                 start_request(uni,
  106                     uni_msg_rptr(m, struct uniapi_reset_request *), cookie);
  107                 uni_msg_destroy(m);
  108                 break;
  109 
  110         /*
  111          * Timers
  112          */
  113           case SIGS_T316:
  114                 start_t316(uni);
  115                 break;
  116 
  117         /*
  118          * SAAL
  119          */
  120           case SIGS_RESTART_ACK:
  121                 start_restart_ack(uni, m, u);
  122                 uni_msg_destroy(m);
  123                 UNI_FREE(u);
  124                 break;
  125 
  126           case SIGS_STATUS:
  127                 start_status(uni, m, u);
  128                 uni_msg_destroy(m);
  129                 UNI_FREE(u);
  130                 break;
  131 
  132           case SIGS_END:
  133                 break;
  134         }
  135 }
  136 
  137 /*
  138  * Reset-request from USER.
  139  *
  140  * Q.2931:Reset-Start 1/2
  141  */
  142 static void
  143 start_request(struct uni *uni, struct uniapi_reset_request *req, uint32_t cookie)
  144 {
  145         struct uni_all *resp;
  146         int err;
  147 
  148         if (uni->glob_start != UNI_CALLSTATE_REST0) {
  149                 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
  150                 return;
  151         }
  152 
  153         if ((resp = UNI_ALLOC()) == NULL) {
  154                 uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
  155                 return;
  156         }
  157 
  158         MK_MSG_ORIG(resp, UNI_RESTART, 0, 0);
  159         resp->u.restart.restart = req->restart;
  160         resp->u.restart.connid = req->connid;
  161 
  162         if (restart_forward(uni, resp))
  163                 return;
  164 
  165         uni->connid_start = req->connid;
  166         uni->restart_start = req->restart;
  167 
  168         if ((err = uni_send_output(resp, uni)) != 0)
  169                 uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
  170         UNI_FREE(resp);
  171         if (err)
  172                 return;
  173 
  174         uni->cnt316 = 0;
  175         TIMER_START_UNI(uni, t316, uni->timer316);
  176         uni->glob_start = UNI_CALLSTATE_REST1;
  177 
  178         VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 1");
  179 
  180 
  181         uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
  182 }
  183 
  184 /*
  185  * T316 timeout function
  186  */
  187 static void
  188 t316_func(struct uni *uni)
  189 {
  190         uni_enq_start(uni, SIGS_T316, 0, NULL, NULL);
  191 }
  192 
  193 /*
  194  * Q.2931:Reset-Start 1/2
  195  */
  196 static void
  197 start_t316(struct uni *uni)
  198 {
  199         if (uni->glob_start != UNI_CALLSTATE_REST1) {
  200                 VERBOSE0(uni, UNI_FAC_ERR, "T316 in state %d",
  201                     uni->glob_start);
  202                 return;
  203         }
  204 
  205         if (++uni->cnt316 == uni->init316) {
  206                 struct uni_msg *app;
  207                 struct uniapi_reset_error_indication *resp;
  208 
  209                 VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start error");
  210 
  211                 resp = ALLOC_API(struct uniapi_reset_error_indication, app);
  212                 if (resp != NULL) {
  213                         resp->source = 0;
  214                         resp->reason = UNIAPI_RESET_ERROR_NO_RESPONSE,
  215 
  216                         uni->funcs->uni_output(uni, uni->arg,
  217                             UNIAPI_RESET_ERROR_indication, 0, app);
  218                 }
  219 
  220                 uni->glob_start = UNI_CALLSTATE_REST0;
  221                 VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
  222         } else {
  223                 struct uni_all *resp;
  224 
  225                 if ((resp = UNI_ALLOC()) == NULL)
  226                         return;
  227 
  228                 MK_MSG_ORIG(resp, UNI_RESTART, 0, 0);
  229                 resp->u.restart.restart = uni->restart_start;
  230                 resp->u.restart.connid = uni->connid_start;
  231 
  232                 (void)uni_send_output(resp, uni);
  233 
  234                 UNI_FREE(resp);
  235 
  236                 TIMER_START_UNI(uni, t316, uni->timer316);
  237         }
  238 }
  239 
  240 /*
  241  * Got RESTART_ACK.
  242  */
  243 static void
  244 start_restart_ack(struct uni *uni, struct uni_msg *m, struct uni_all *u)
  245 {
  246         enum uni_callstate new_state;
  247         struct uniapi_reset_confirm *conf;
  248         struct uni_msg *app;
  249 
  250         if (uni->glob_start == UNI_CALLSTATE_REST0) {
  251                 uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_start,
  252                     UNI_CAUSE_MSG_INCOMP, UNI_RESTART_ACK);
  253                 return;
  254         }
  255 
  256         if (uni->glob_start != UNI_CALLSTATE_REST1) {
  257                 ASSERT(0, ("bad global call state in Reset-Start"));
  258                 return;
  259         }
  260 
  261         /*
  262          * If body decoding fails, this is because IEs are wrong.
  263          */
  264         (void)uni_decode_body(m, u, &uni->cx);
  265         MANDATE_IE(uni, u->u.restart_ack.restart, UNI_IE_RESTART);
  266 
  267         if (IE_ISGOOD(u->u.restart_ack.restart)) {
  268                 /*
  269                  * Q.2931: 5.5.2.2
  270                  */
  271                 if (u->u.restart_ack.restart.rclass == UNI_RESTART_ALL &&
  272                     IE_ISGOOD(u->u.restart_ack.connid)) {
  273                         (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID,
  274                             u->u.restart_ack.connid.h.act,
  275                             UNI_IERR_UNK);
  276                 } else if ((u->u.restart_ack.restart.rclass == UNI_RESTART_PATH ||
  277                             u->u.restart_ack.restart.rclass == UNI_RESTART_CHANNEL)) {
  278                         MANDATE_IE(uni, u->u.restart_ack.connid, UNI_IE_CONNID);
  279                 }
  280         }
  281         /*
  282          * Compare the information elements now, because
  283          * we may need the new callstate for the status message
  284          * below.
  285          */
  286         new_state = UNI_CALLSTATE_REST1;
  287 
  288         if (IE_ISGOOD(u->u.restart_ack.restart) &&
  289             IE_ISGOOD(uni->restart_start) &&
  290             u->u.restart_ack.restart.rclass == uni->restart_start.rclass &&
  291             !IE_ISGOOD(u->u.restart_ack.connid) == !IE_ISGOOD(uni->connid_start) &&
  292             (!IE_ISGOOD(uni->connid_start) ||
  293                (u->u.restart_ack.connid.vpci == uni->connid_start.vpci &&
  294                 u->u.restart_ack.connid.vci == uni->connid_start.vci)))
  295                 new_state = UNI_CALLSTATE_REST0;
  296 
  297         switch (uni_verify(uni, u->u.hdr.act)) {
  298           case VFY_RAIM:
  299           case VFY_RAI:
  300                 uni_respond_status_verify(uni, &u->u.hdr.cref,
  301                     UNI_CALLSTATE_REST1, NULL, 0);
  302           case VFY_I:
  303                 return;
  304 
  305           case VFY_CLR:
  306                 uni->glob_start = UNI_CALLSTATE_REST0;
  307                 VERBOSE(uni, UNI_FAC_RESTART, 1,
  308                     "Reset-Start state := 0");
  309                 return;
  310 
  311           case VFY_RAP:
  312           case VFY_RAPU:
  313                 uni_respond_status_verify(uni, &u->u.hdr.cref,
  314                     new_state, NULL, 0);
  315           case VFY_OK:
  316                 break;
  317         }
  318 
  319         if (new_state == UNI_CALLSTATE_REST1)
  320                 /*
  321                  * Q.2931: 5.5.1.2/2
  322                  */
  323                 return;
  324 
  325         /*
  326          * Build restart.confirm signal for application
  327          */
  328         if (!IE_ISGOOD(u->u.restart_ack.connid))
  329                 u->u.restart.connid.h.present = 0;
  330 
  331 
  332         if ((conf = ALLOC_API(struct uniapi_reset_confirm, app)) == NULL)
  333                 return;
  334         conf->restart = u->u.restart.restart;
  335         conf->connid = u->u.restart.connid;
  336 
  337         TIMER_STOP_UNI(uni, t316);
  338 
  339         uni->funcs->uni_output(uni, uni->arg, UNIAPI_RESET_confirm, 0, app);
  340 
  341         uni->glob_start = UNI_CALLSTATE_REST0;
  342         VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
  343 }
  344 
  345 /*
  346  * Reset-Start got a STATUS message.
  347  *
  348  * Q.2931: Reset-Start 2/2
  349  *
  350  * In Q.2931 only CALLSTATE_REST1 is allowed, this seems silly and to contradict
  351  * 5.6.12. So allow it in any state.
  352  *
  353  * The following states are considered compatible:
  354  *
  355  *  Sender   Receiver(we)
  356  *  ------   --------
  357  *  Rest0     Rest0     this is the normal state OK!
  358  *  Rest2     Rest0     this may be the result of no answer from the API
  359  *                      on the remote end and the us finally timing out. ERROR!
  360  *  Rest2     Rest1     this is normal. OK!
  361  *  Rest0     Rest1     RESTART_ACK was probably lost. OK!
  362  *
  363  * All others are wrong.
  364  */
  365 static void
  366 start_status(struct uni *uni, struct uni_msg *m, struct uni_all *u)
  367 {
  368         (void)uni_decode_body(m, u, &uni->cx);
  369         MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE);
  370         MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE);
  371         switch (uni_verify(uni, u->u.hdr.act)) {
  372           case VFY_CLR:
  373                 uni->glob_start = UNI_CALLSTATE_REST0;
  374                 VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0");
  375                 return;
  376 
  377           case VFY_RAIM:
  378           case VFY_RAI:
  379           case VFY_RAP:
  380           case VFY_RAPU:
  381                 uni_respond_status_verify(uni, &u->u.hdr.cref, uni->glob_start,
  382                     NULL, 0);
  383           case VFY_I:
  384           case VFY_OK:
  385                 break;
  386         }
  387         if (!IE_ISGOOD(u->u.status.callstate)) {
  388                 /*
  389                  * As a result of the strange handling above, we must
  390                  * process a STATUS with an invalid or missing callstate!
  391                  */
  392                 return;
  393         }
  394         if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
  395              uni->glob_start == UNI_CALLSTATE_REST0) ||
  396             (u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
  397              uni->glob_start == UNI_CALLSTATE_REST1) ||
  398             (u->u.status.callstate.state == UNI_CALLSTATE_REST2 &&
  399              uni->glob_start == UNI_CALLSTATE_REST1)) {
  400                 /*
  401                  * Implementation dependend procedure:
  402                  * Inform the API
  403                  */
  404                 struct uniapi_reset_status_indication *resp;
  405                 struct uni_msg *app;
  406 
  407                 resp = ALLOC_API(struct uniapi_reset_status_indication, app);
  408                 if (resp == NULL)
  409                         return;
  410                 resp->cref = u->u.hdr.cref;
  411                 resp->callstate = u->u.status.callstate;
  412                 if (IE_ISGOOD(u->u.status.cause))
  413                         resp->cause = u->u.status.cause;
  414 
  415                 uni->funcs->uni_output(uni, uni->arg,
  416                     UNIAPI_RESET_STATUS_indication, 0, app);
  417                 
  418         } else {
  419                 struct uniapi_reset_error_indication *resp;
  420                 struct uni_msg *app;
  421 
  422                 resp = ALLOC_API(struct uniapi_reset_error_indication, app);
  423                 if (resp != NULL) {
  424                         resp->source = 0;
  425                         resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE,
  426 
  427                         uni->funcs->uni_output(uni, uni->arg,
  428                             UNIAPI_RESET_ERROR_indication, 0, app);
  429                 }
  430         }
  431 }
  432 
  433 /************************************************************/
  434 /*
  435  * Reset-Respond process.
  436  */
  437 void
  438 uni_sig_respond(struct uni *uni, u_int sig, uint32_t cookie,
  439     struct uni_msg *m, struct uni_all *u)
  440 {
  441         if (sig >= SIGR_END) {
  442                 VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to "
  443                     "Reset-Respond", sig);
  444                 if (m)
  445                         uni_msg_destroy(m);
  446                 if (u)
  447                         UNI_FREE(u);
  448                 return;
  449         }
  450 
  451         VERBOSE(uni, UNI_FAC_RESTART, 1,
  452             "Signal %s in state %u of Reset-Respond; cookie %u",
  453             respond_sigs[sig], uni->glob_respond, cookie);
  454 
  455         switch (sig) {
  456 
  457         /*
  458          * SAAL
  459          */
  460           case SIGR_RESTART:
  461                 response_restart(uni, m, u);
  462                 uni_msg_destroy(m);
  463                 UNI_FREE(u);
  464                 break;
  465 
  466           case SIGR_STATUS:
  467                 response_status(uni, m, u);
  468                 uni_msg_destroy(m);
  469                 UNI_FREE(u);
  470                 break;
  471 
  472         /*
  473          * User
  474          */
  475           case SIGR_RESET_ERROR_response:
  476                 response_error(uni,
  477                     uni_msg_rptr(m, struct uniapi_reset_error_response *),
  478                     cookie);
  479                 uni_msg_destroy(m);
  480                 break;
  481 
  482           case SIGR_RESET_response:
  483                 response_response(uni,
  484                     uni_msg_rptr(m, struct uniapi_reset_response *), cookie);
  485                 uni_msg_destroy(m);
  486                 break;
  487 
  488         /*
  489          * Timers
  490          */
  491           case SIGR_T317:
  492                 response_t317(uni);
  493                 return;
  494 
  495           case SIGR_END:
  496                 break;
  497         }
  498 }
  499 
  500 /*
  501  * Send a RELEASE_COMPLETE to all affected calls as per
  502  * F.2.3(3)
  503  */
  504 static int
  505 restart_forward(struct uni *uni, const struct uni_all *u)
  506 {
  507         struct call *c;
  508         struct uni_all *resp;
  509 
  510         if ((resp = UNI_ALLOC()) == NULL)
  511                 return (-1);
  512 
  513         TAILQ_FOREACH(c, &uni->calls, link) {
  514                 if (u->u.restart.restart.rclass == UNI_RESTART_ALL ||
  515                     (IE_ISPRESENT(c->connid) &&
  516                     u->u.restart.connid.vpci == c->connid.vpci &&
  517                     (u->u.restart.restart.rclass == UNI_RESTART_PATH ||
  518                     u->u.restart.connid.vci == c->connid.vci))) {
  519                         MK_MSG_ORIG(resp, UNI_RELEASE_COMPL, c->cref, c->mine);
  520                         uni_release_compl(c, resp);
  521                 }
  522         }
  523 
  524         UNI_FREE(resp);
  525         return (0);
  526 }
  527 
  528 /*
  529  * Respond process got a restart message.
  530  * Doesn't free the messages.
  531  */
  532 static void
  533 response_restart(struct uni *uni, struct uni_msg *m, struct uni_all *u)
  534 {
  535         struct uni_msg *app;
  536         struct uniapi_reset_indication *ind;
  537 
  538         if (uni->glob_respond == UNI_CALLSTATE_REST0) {
  539                 /*
  540                  * If body decoding fails, this is because IEs are wrong.
  541                  */
  542                 (void)uni_decode_body(m, u, &uni->cx);
  543                 MANDATE_IE(uni, u->u.restart.restart, UNI_IE_RESTART);
  544                 if (IE_ISGOOD(u->u.restart.restart)) {
  545                         /*
  546                          * Q.2931: 5.5.2.2
  547                          */
  548                         if (u->u.restart.restart.rclass == UNI_RESTART_ALL &&
  549                            IE_ISGOOD(u->u.restart.connid)) {
  550                                 (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID,
  551                                     u->u.restart.connid.h.act,
  552                                     UNI_IERR_UNK);
  553                         } else if ((u->u.restart.restart.rclass == UNI_RESTART_PATH ||
  554                                    u->u.restart.restart.rclass == UNI_RESTART_CHANNEL)) {
  555                                 MANDATE_IE(uni, u->u.restart.connid, UNI_IE_CONNID);
  556                         }
  557                 }
  558                 switch (uni_verify(uni, u->u.hdr.act)) {
  559                   case VFY_RAIM:
  560                   case VFY_RAI:
  561                         uni_respond_status_verify(uni, &u->u.hdr.cref,
  562                             UNI_CALLSTATE_REST0, NULL, 0);
  563                   case VFY_CLR:
  564                   case VFY_I:
  565                         return;
  566 
  567                   case VFY_RAP:
  568                   case VFY_RAPU:
  569                         uni_respond_status_verify(uni, &u->u.hdr.cref,
  570                             UNI_CALLSTATE_REST2, NULL, 0);
  571                   case VFY_OK:
  572                         break;
  573                 }
  574                 if (!IE_ISGOOD(u->u.restart.connid))
  575                         u->u.restart.connid.h.present = 0;
  576 
  577                 /*
  578                  * Send a RELEASE_COMPLETE to all affected calls as per
  579                  * F.2.3(3)
  580                  */
  581                 if (restart_forward(uni, u))
  582                         return;
  583 
  584                 /*
  585                  * Build restart signal for application
  586                  */
  587                 if ((ind = ALLOC_API(struct uniapi_reset_indication, app)) == NULL)
  588                         return;
  589 
  590                 ind->restart = u->u.restart.restart;
  591                 ind->connid = u->u.restart.connid;
  592 
  593                 uni_enq_coord(uni, SIGO_RESET_indication, 0, app);
  594 
  595                 TIMER_START_UNI(uni, t317, uni->timer317);
  596                 uni->glob_respond = UNI_CALLSTATE_REST2;
  597 
  598                 VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 2");
  599 
  600 
  601         } else if (uni->glob_respond == UNI_CALLSTATE_REST2) {
  602                 /*
  603                  * No need to decode the message. It is unexpected in this
  604                  * state so return a status.
  605                  */
  606                 uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_respond,
  607                     UNI_CAUSE_MSG_INCOMP, UNI_RESTART);
  608 
  609 
  610         } else
  611                 ASSERT(0, ("bad global call state in responder"));
  612 }
  613 
  614 static void
  615 response_t317(struct uni *uni)
  616 {
  617         struct uniapi_reset_error_indication *resp;
  618         struct uni_msg *app;
  619 
  620         if (uni->glob_respond != UNI_CALLSTATE_REST2) {
  621                 VERBOSE0(uni, UNI_FAC_ERR, "T317 in state %d",
  622                     uni->glob_respond);
  623                 return;
  624         }
  625 
  626         VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond error");
  627 
  628         if ((resp = ALLOC_API(struct uniapi_reset_error_indication, app)) != NULL) {
  629                 resp->source = 1;
  630                 resp->reason = UNIAPI_RESET_ERROR_NO_CONFIRM;
  631 
  632                 uni->funcs->uni_output(uni, uni->arg,
  633                     UNIAPI_RESET_ERROR_indication, 0, app);
  634         }
  635 
  636         uni->glob_respond = UNI_CALLSTATE_REST0;
  637         VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0");
  638 }
  639 
  640 /*
  641  * Error response from USER
  642  */
  643 static void
  644 response_error(struct uni *uni, struct uniapi_reset_error_response *c,
  645     uint32_t cookie)
  646 {
  647         struct uni_all *resp;
  648 
  649         if (uni->glob_respond != UNI_CALLSTATE_REST2) {
  650                 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
  651                 return;
  652         }
  653 
  654         if ((resp = UNI_ALLOC()) == NULL) {
  655                 uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
  656                 return;
  657         }
  658 
  659         MK_MSG_ORIG(resp, UNI_STATUS, 0, 1);
  660         MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_REST2);
  661 
  662         if (IE_ISGOOD(c->cause))
  663                 resp->u.status.cause = c->cause;
  664         else {
  665                 MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER,
  666                     UNI_CAUSE_CHANNEL_NEX);
  667                 if (IE_ISGOOD(uni->connid_respond))
  668                         ADD_CAUSE_CHANNID(resp->u.status.cause,
  669                             uni->connid_respond.vpci,
  670                             uni->connid_respond.vci);
  671         }
  672 
  673         if (uni_send_output(resp, uni) != 0) {
  674                 uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
  675                 UNI_FREE(resp);
  676                 return;
  677         }
  678 
  679         uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
  680 }
  681 
  682 /*
  683  * Reset-response from user.
  684  */
  685 static void
  686 response_response(struct uni *uni, struct uniapi_reset_response *arg,
  687     uint32_t cookie)
  688 {
  689         struct uni_all *resp;
  690 
  691         if (uni->glob_respond != UNI_CALLSTATE_REST2) {
  692                 uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0);
  693                 return;
  694         }
  695 
  696         if (!IE_ISGOOD(arg->restart)) {
  697                 uniapi_uni_error(uni, UNIAPI_ERROR_MISSING_IE, cookie, 0);
  698                 return;
  699         }
  700 
  701         if ((resp = UNI_ALLOC()) == NULL) {
  702                 uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0);
  703                 return;
  704         }
  705 
  706         TIMER_STOP_UNI(uni, t317);
  707 
  708         MK_MSG_ORIG(resp, UNI_RESTART_ACK, 0, 1);
  709         resp->u.restart.restart = arg->restart;
  710         if (IE_ISGOOD(arg->connid))
  711                 resp->u.restart.connid = arg->connid;
  712 
  713         if (uni_send_output(resp, uni) != 0) {
  714                 uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0);
  715                 UNI_FREE(resp);
  716                 return;
  717         }
  718 
  719         UNI_FREE(resp);
  720 
  721         uni->glob_respond = UNI_CALLSTATE_REST0;
  722         VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0");
  723 
  724         uniapi_uni_error(uni, UNIAPI_OK, cookie, 0);
  725 }
  726 
  727 /*
  728  * Reset-Response got a STATUS message.
  729  *
  730  * Q.2931: Reset-Response 2/2
  731  *
  732  * In Q.2931 only CALLSTATE_REST2 is allowed, this seems silly and to contradict
  733  * 5.6.12. So allow it in any state.
  734  *
  735  * The following states are considered compatible:
  736  *
  737  *  Sender   Receiver
  738  *  ------   --------
  739  *  Rest0     Rest0     this is the normal state OK!
  740  *  Rest0     Rest2     this may be the result of no answer from the API
  741  *                      and the Sender finally timing out. ERROR!
  742  *  Rest1     Rest2     this is normal. OK!
  743  *  Rest1     Rest0     RESTART_ACK was probably lost. OK!
  744  *
  745  * All others are wrong.
  746  */
  747 static void
  748 response_status(struct uni *uni, struct uni_msg *m, struct uni_all *u)
  749 {
  750         (void)uni_decode_body(m, u, &uni->cx);
  751         MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE);
  752         MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE);
  753         switch (uni_verify(uni, u->u.hdr.act)) {
  754           case VFY_CLR:
  755                 if (uni->proto == UNIPROTO_UNI40U) {
  756                         uni->glob_respond = UNI_CALLSTATE_REST0;
  757                         VERBOSE(uni, UNI_FAC_RESTART, 1,
  758                             "Reset-Respond state := 0");
  759                         return;
  760                 }
  761                 break;
  762 
  763           case VFY_RAIM:
  764           case VFY_RAI:
  765           case VFY_RAP:
  766           case VFY_RAPU:
  767                 uni_respond_status_verify(uni, &u->u.hdr.cref,
  768                     uni->glob_respond, NULL, 0);
  769           case VFY_I:
  770           case VFY_OK:
  771                 break;
  772         }
  773         if (!IE_ISGOOD(u->u.status.callstate)) {
  774                 /*
  775                  * As a result of the strange handling above, we must
  776                  * process a STATUS with an invalid or missing callstate!
  777                  */
  778                 return;
  779         }
  780         if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 &&
  781              uni->glob_respond == UNI_CALLSTATE_REST0) ||
  782             (u->u.status.callstate.state == UNI_CALLSTATE_REST1 &&
  783              uni->glob_respond == UNI_CALLSTATE_REST0) ||
  784             (u->u.status.callstate.state == UNI_CALLSTATE_REST1 &&
  785              uni->glob_respond == UNI_CALLSTATE_REST2)) {
  786                 /*
  787                  * Implementation dependend procedure:
  788                  * Inform the API
  789                  */
  790                 struct uniapi_reset_status_indication *resp;
  791                 struct uni_msg *app;
  792 
  793                 resp = ALLOC_API(struct uniapi_reset_status_indication, app);
  794                 if (resp == NULL)
  795                         return;
  796 
  797                 resp->cref = u->u.hdr.cref;
  798                 resp->callstate = u->u.status.callstate;
  799                 if (IE_ISGOOD(u->u.status.cause))
  800                         resp->cause = u->u.status.cause;
  801 
  802                 uni->funcs->uni_output(uni, uni->arg,
  803                     UNIAPI_RESET_STATUS_indication, 0, app);
  804                 
  805         } else {
  806                 struct uniapi_reset_error_indication *resp;
  807                 struct uni_msg *app;
  808 
  809                 resp = ALLOC_API(struct uniapi_reset_error_indication, app);
  810                 if (resp != NULL) {
  811                         resp->source = 1;
  812                         resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE,
  813 
  814                         uni->funcs->uni_output(uni, uni->arg,
  815                             UNIAPI_RESET_ERROR_indication, 0, app);
  816                 }
  817         }
  818 }
  819 
  820 /*
  821  * T317 timeout function
  822  */
  823 static void
  824 t317_func(struct uni *uni)
  825 {
  826         uni_enq_resp(uni, SIGR_T317, 0, NULL, NULL);
  827 }

Cache object: 6e6bcb35bcfdc933be9560149f6a4d0f


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