1122205Sharti/* 2122205Sharti * Copyright (c) 1996-2003 3122205Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4122205Sharti * All rights reserved. 5122205Sharti * 6131826Sharti * Author: Hartmut Brandt <harti@freebsd.org> 7131826Sharti * 8122205Sharti * Redistribution and use in source and binary forms, with or without 9122205Sharti * modification, are permitted provided that the following conditions 10122205Sharti * are met: 11122205Sharti * 1. Redistributions of source code must retain the above copyright 12122205Sharti * notice, this list of conditions and the following disclaimer. 13122205Sharti * 2. Redistributions in binary form must reproduce the above copyright 14122205Sharti * notice, this list of conditions and the following disclaimer in the 15122205Sharti * documentation and/or other materials provided with the distribution. 16122205Sharti * 17122205Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18122205Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19122205Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20122205Sharti * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21122205Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22122205Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23122205Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24122205Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25122205Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26122205Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27122205Sharti * SUCH DAMAGE. 28122205Sharti * 29133492Sharti * $Begemot: libunimsg/netnatm/sig/sig_reset.c,v 1.11 2004/08/05 07:11:03 brandt Exp $ 30122205Sharti * 31122205Sharti * Reset-start and reset-respond 32122205Sharti */ 33122205Sharti 34122205Sharti#include <netnatm/unimsg.h> 35122205Sharti#include <netnatm/saal/sscfudef.h> 36122205Sharti#include <netnatm/msg/unistruct.h> 37122205Sharti#include <netnatm/msg/unimsglib.h> 38122205Sharti#include <netnatm/sig/uni.h> 39122205Sharti 40122205Sharti#include <netnatm/sig/unipriv.h> 41122205Sharti#include <netnatm/sig/unimkmsg.h> 42122205Sharti 43122205Shartistatic void response_restart(struct uni *, struct uni_msg *, struct uni_all *); 44122205Shartistatic void response_status(struct uni *, struct uni_msg *, struct uni_all *); 45122205Sharti 46122205Shartistatic void response_t317(struct uni *); 47122205Sharti 48131826Shartistatic void response_error(struct uni *, struct uniapi_reset_error_response *, 49131826Sharti uint32_t cookie); 50131826Shartistatic void response_response(struct uni *, struct uniapi_reset_response *, 51131826Sharti uint32_t); 52122205Sharti 53131826Shartistatic void start_request(struct uni *, struct uniapi_reset_request *, 54131826Sharti uint32_t); 55122205Sharti 56122205Shartistatic void start_t316(struct uni *); 57122205Sharti 58122205Shartistatic void start_restart_ack(struct uni *, struct uni_msg *, struct uni_all *); 59122205Shartistatic void start_status(struct uni *, struct uni_msg *, struct uni_all *); 60122205Sharti 61122205Shartistatic int restart_forward(struct uni *, const struct uni_all *); 62122205Sharti 63133492Sharti#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, 64122205Shartistatic const char *const start_sigs[] = { 65122205Sharti DEF_START_SIGS 66122205Sharti}; 67122205Sharti#undef DEF_PRIV_SIG 68122205Sharti 69133492Sharti#define DEF_PRIV_SIG(NAME, FROM) [SIG##NAME] = "SIG"#NAME, 70122205Shartistatic const char *const respond_sigs[] = { 71122205Sharti DEF_RESPOND_SIGS 72122205Sharti}; 73122205Sharti#undef DEF_PRIV_SIG 74122205Sharti 75122205ShartiTIMER_FUNC_UNI(t317, t317_func) 76122205ShartiTIMER_FUNC_UNI(t316, t316_func) 77122205Sharti 78122205Sharti/* 79122205Sharti * Reset-Start process. 80122205Sharti */ 81122205Shartivoid 82131826Shartiuni_sig_start(struct uni *uni, u_int sig, uint32_t cookie, 83122205Sharti struct uni_msg *m, struct uni_all *u) 84122205Sharti{ 85122205Sharti if (sig >= SIGS_END) { 86122205Sharti VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to " 87122205Sharti "Reset-Start", sig); 88122205Sharti if (m) 89122205Sharti uni_msg_destroy(m); 90122205Sharti if (u) 91122205Sharti UNI_FREE(u); 92122205Sharti return; 93122205Sharti } 94122205Sharti 95122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, 96122205Sharti "Signal %s in state %u of Reset-Start; cookie %u", 97122205Sharti start_sigs[sig], uni->glob_start, cookie); 98122205Sharti 99122205Sharti switch (sig) { 100122205Sharti 101122205Sharti /* 102122205Sharti * User requests 103122205Sharti */ 104122205Sharti case SIGS_RESET_request: 105122205Sharti start_request(uni, 106122205Sharti uni_msg_rptr(m, struct uniapi_reset_request *), cookie); 107122205Sharti uni_msg_destroy(m); 108122205Sharti break; 109122205Sharti 110122205Sharti /* 111122205Sharti * Timers 112122205Sharti */ 113122205Sharti case SIGS_T316: 114122205Sharti start_t316(uni); 115122205Sharti break; 116122205Sharti 117122205Sharti /* 118122205Sharti * SAAL 119122205Sharti */ 120122205Sharti case SIGS_RESTART_ACK: 121122205Sharti start_restart_ack(uni, m, u); 122122205Sharti uni_msg_destroy(m); 123122205Sharti UNI_FREE(u); 124122205Sharti break; 125122205Sharti 126122205Sharti case SIGS_STATUS: 127122205Sharti start_status(uni, m, u); 128122205Sharti uni_msg_destroy(m); 129122205Sharti UNI_FREE(u); 130122205Sharti break; 131122205Sharti 132122205Sharti case SIGS_END: 133122205Sharti break; 134122205Sharti } 135122205Sharti} 136122205Sharti 137122205Sharti/* 138122205Sharti * Reset-request from USER. 139122205Sharti * 140122205Sharti * Q.2931:Reset-Start 1/2 141122205Sharti */ 142122205Shartistatic void 143131826Shartistart_request(struct uni *uni, struct uniapi_reset_request *req, uint32_t cookie) 144122205Sharti{ 145122205Sharti struct uni_all *resp; 146122205Sharti int err; 147122205Sharti 148122205Sharti if (uni->glob_start != UNI_CALLSTATE_REST0) { 149122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0); 150122205Sharti return; 151122205Sharti } 152122205Sharti 153122205Sharti if ((resp = UNI_ALLOC()) == NULL) { 154122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0); 155122205Sharti return; 156122205Sharti } 157122205Sharti 158122205Sharti MK_MSG_ORIG(resp, UNI_RESTART, 0, 0); 159122205Sharti resp->u.restart.restart = req->restart; 160122205Sharti resp->u.restart.connid = req->connid; 161122205Sharti 162122205Sharti if (restart_forward(uni, resp)) 163122205Sharti return; 164122205Sharti 165122205Sharti uni->connid_start = req->connid; 166122205Sharti uni->restart_start = req->restart; 167122205Sharti 168122205Sharti if ((err = uni_send_output(resp, uni)) != 0) 169122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0); 170122205Sharti UNI_FREE(resp); 171122205Sharti if (err) 172122205Sharti return; 173122205Sharti 174122205Sharti uni->cnt316 = 0; 175122205Sharti TIMER_START_UNI(uni, t316, uni->timer316); 176122205Sharti uni->glob_start = UNI_CALLSTATE_REST1; 177122205Sharti 178122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 1"); 179122205Sharti 180122205Sharti 181122205Sharti uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 182122205Sharti} 183122205Sharti 184122205Sharti/* 185122205Sharti * T316 timeout function 186122205Sharti */ 187122205Shartistatic void 188122205Shartit316_func(struct uni *uni) 189122205Sharti{ 190122205Sharti uni_enq_start(uni, SIGS_T316, 0, NULL, NULL); 191122205Sharti} 192122205Sharti 193122205Sharti/* 194122205Sharti * Q.2931:Reset-Start 1/2 195122205Sharti */ 196122205Shartistatic void 197122205Shartistart_t316(struct uni *uni) 198122205Sharti{ 199122205Sharti if (uni->glob_start != UNI_CALLSTATE_REST1) { 200122205Sharti VERBOSE0(uni, UNI_FAC_ERR, "T316 in state %d", 201122205Sharti uni->glob_start); 202122205Sharti return; 203122205Sharti } 204122205Sharti 205122205Sharti if (++uni->cnt316 == uni->init316) { 206122205Sharti struct uni_msg *app; 207122205Sharti struct uniapi_reset_error_indication *resp; 208122205Sharti 209122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start error"); 210122205Sharti 211122205Sharti resp = ALLOC_API(struct uniapi_reset_error_indication, app); 212122205Sharti if (resp != NULL) { 213122205Sharti resp->source = 0; 214122205Sharti resp->reason = UNIAPI_RESET_ERROR_NO_RESPONSE, 215122205Sharti 216122205Sharti uni->funcs->uni_output(uni, uni->arg, 217122205Sharti UNIAPI_RESET_ERROR_indication, 0, app); 218122205Sharti } 219122205Sharti 220122205Sharti uni->glob_start = UNI_CALLSTATE_REST0; 221122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0"); 222122205Sharti } else { 223122205Sharti struct uni_all *resp; 224122205Sharti 225122205Sharti if ((resp = UNI_ALLOC()) == NULL) 226122205Sharti return; 227122205Sharti 228122205Sharti MK_MSG_ORIG(resp, UNI_RESTART, 0, 0); 229122205Sharti resp->u.restart.restart = uni->restart_start; 230122205Sharti resp->u.restart.connid = uni->connid_start; 231122205Sharti 232122205Sharti (void)uni_send_output(resp, uni); 233122205Sharti 234122205Sharti UNI_FREE(resp); 235122205Sharti 236122205Sharti TIMER_START_UNI(uni, t316, uni->timer316); 237122205Sharti } 238122205Sharti} 239122205Sharti 240122205Sharti/* 241122205Sharti * Got RESTART_ACK. 242122205Sharti */ 243122205Shartistatic void 244122205Shartistart_restart_ack(struct uni *uni, struct uni_msg *m, struct uni_all *u) 245122205Sharti{ 246122205Sharti enum uni_callstate new_state; 247122205Sharti struct uniapi_reset_confirm *conf; 248122205Sharti struct uni_msg *app; 249122205Sharti 250122205Sharti if (uni->glob_start == UNI_CALLSTATE_REST0) { 251122205Sharti uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_start, 252122205Sharti UNI_CAUSE_MSG_INCOMP, UNI_RESTART_ACK); 253122205Sharti return; 254122205Sharti } 255122205Sharti 256122205Sharti if (uni->glob_start != UNI_CALLSTATE_REST1) { 257122205Sharti ASSERT(0, ("bad global call state in Reset-Start")); 258122205Sharti return; 259122205Sharti } 260122205Sharti 261122205Sharti /* 262122205Sharti * If body decoding fails, this is because IEs are wrong. 263122205Sharti */ 264122205Sharti (void)uni_decode_body(m, u, &uni->cx); 265122205Sharti MANDATE_IE(uni, u->u.restart_ack.restart, UNI_IE_RESTART); 266122205Sharti 267122205Sharti if (IE_ISGOOD(u->u.restart_ack.restart)) { 268122205Sharti /* 269122205Sharti * Q.2931: 5.5.2.2 270122205Sharti */ 271122205Sharti if (u->u.restart_ack.restart.rclass == UNI_RESTART_ALL && 272122205Sharti IE_ISGOOD(u->u.restart_ack.connid)) { 273213789Srpaulo (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID, 274122205Sharti u->u.restart_ack.connid.h.act, 275122205Sharti UNI_IERR_UNK); 276122205Sharti } else if ((u->u.restart_ack.restart.rclass == UNI_RESTART_PATH || 277122205Sharti u->u.restart_ack.restart.rclass == UNI_RESTART_CHANNEL)) { 278122205Sharti MANDATE_IE(uni, u->u.restart_ack.connid, UNI_IE_CONNID); 279122205Sharti } 280122205Sharti } 281122205Sharti /* 282122205Sharti * Compare the information elements now, because 283122205Sharti * we may need the new callstate for the status message 284122205Sharti * below. 285122205Sharti */ 286122205Sharti new_state = UNI_CALLSTATE_REST1; 287122205Sharti 288122205Sharti if (IE_ISGOOD(u->u.restart_ack.restart) && 289122205Sharti IE_ISGOOD(uni->restart_start) && 290122205Sharti u->u.restart_ack.restart.rclass == uni->restart_start.rclass && 291122205Sharti !IE_ISGOOD(u->u.restart_ack.connid) == !IE_ISGOOD(uni->connid_start) && 292122205Sharti (!IE_ISGOOD(uni->connid_start) || 293122205Sharti (u->u.restart_ack.connid.vpci == uni->connid_start.vpci && 294122205Sharti u->u.restart_ack.connid.vci == uni->connid_start.vci))) 295122205Sharti new_state = UNI_CALLSTATE_REST0; 296122205Sharti 297122205Sharti switch (uni_verify(uni, u->u.hdr.act)) { 298122205Sharti case VFY_RAIM: 299122205Sharti case VFY_RAI: 300122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, 301122205Sharti UNI_CALLSTATE_REST1, NULL, 0); 302122205Sharti case VFY_I: 303122205Sharti return; 304122205Sharti 305122205Sharti case VFY_CLR: 306122205Sharti uni->glob_start = UNI_CALLSTATE_REST0; 307122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, 308122205Sharti "Reset-Start state := 0"); 309122205Sharti return; 310122205Sharti 311122205Sharti case VFY_RAP: 312122205Sharti case VFY_RAPU: 313122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, 314122205Sharti new_state, NULL, 0); 315122205Sharti case VFY_OK: 316122205Sharti break; 317122205Sharti } 318122205Sharti 319122205Sharti if (new_state == UNI_CALLSTATE_REST1) 320122205Sharti /* 321122205Sharti * Q.2931: 5.5.1.2/2 322122205Sharti */ 323122205Sharti return; 324122205Sharti 325122205Sharti /* 326122205Sharti * Build restart.confirm signal for application 327122205Sharti */ 328122205Sharti if (!IE_ISGOOD(u->u.restart_ack.connid)) 329122205Sharti u->u.restart.connid.h.present = 0; 330122205Sharti 331122205Sharti 332122205Sharti if ((conf = ALLOC_API(struct uniapi_reset_confirm, app)) == NULL) 333122205Sharti return; 334122205Sharti conf->restart = u->u.restart.restart; 335122205Sharti conf->connid = u->u.restart.connid; 336122205Sharti 337122205Sharti TIMER_STOP_UNI(uni, t316); 338122205Sharti 339122205Sharti uni->funcs->uni_output(uni, uni->arg, UNIAPI_RESET_confirm, 0, app); 340122205Sharti 341122205Sharti uni->glob_start = UNI_CALLSTATE_REST0; 342122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0"); 343122205Sharti} 344122205Sharti 345122205Sharti/* 346122205Sharti * Reset-Start got a STATUS message. 347122205Sharti * 348122205Sharti * Q.2931: Reset-Start 2/2 349122205Sharti * 350122205Sharti * In Q.2931 only CALLSTATE_REST1 is allowed, this seems silly and to contradict 351122205Sharti * 5.6.12. So allow it in any state. 352122205Sharti * 353122205Sharti * The following states are considered compatible: 354122205Sharti * 355122205Sharti * Sender Receiver(we) 356122205Sharti * ------ -------- 357122205Sharti * Rest0 Rest0 this is the normal state OK! 358122205Sharti * Rest2 Rest0 this may be the result of no answer from the API 359122205Sharti * on the remote end and the us finally timing out. ERROR! 360122205Sharti * Rest2 Rest1 this is normal. OK! 361122205Sharti * Rest0 Rest1 RESTART_ACK was probably lost. OK! 362122205Sharti * 363122205Sharti * All others are wrong. 364122205Sharti */ 365122205Shartistatic void 366122205Shartistart_status(struct uni *uni, struct uni_msg *m, struct uni_all *u) 367122205Sharti{ 368122205Sharti (void)uni_decode_body(m, u, &uni->cx); 369122205Sharti MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE); 370122205Sharti MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE); 371122205Sharti switch (uni_verify(uni, u->u.hdr.act)) { 372122205Sharti case VFY_CLR: 373122205Sharti uni->glob_start = UNI_CALLSTATE_REST0; 374122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Start state := 0"); 375122205Sharti return; 376122205Sharti 377122205Sharti case VFY_RAIM: 378122205Sharti case VFY_RAI: 379122205Sharti case VFY_RAP: 380122205Sharti case VFY_RAPU: 381122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, uni->glob_start, 382122205Sharti NULL, 0); 383122205Sharti case VFY_I: 384122205Sharti case VFY_OK: 385122205Sharti break; 386122205Sharti } 387122205Sharti if (!IE_ISGOOD(u->u.status.callstate)) { 388122205Sharti /* 389122205Sharti * As a result of the strange handling above, we must 390122205Sharti * process a STATUS with an invalid or missing callstate! 391122205Sharti */ 392122205Sharti return; 393122205Sharti } 394122205Sharti if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 && 395122205Sharti uni->glob_start == UNI_CALLSTATE_REST0) || 396122205Sharti (u->u.status.callstate.state == UNI_CALLSTATE_REST0 && 397122205Sharti uni->glob_start == UNI_CALLSTATE_REST1) || 398122205Sharti (u->u.status.callstate.state == UNI_CALLSTATE_REST2 && 399122205Sharti uni->glob_start == UNI_CALLSTATE_REST1)) { 400122205Sharti /* 401122205Sharti * Implementation dependend procedure: 402122205Sharti * Inform the API 403122205Sharti */ 404122205Sharti struct uniapi_reset_status_indication *resp; 405122205Sharti struct uni_msg *app; 406122205Sharti 407122205Sharti resp = ALLOC_API(struct uniapi_reset_status_indication, app); 408122205Sharti if (resp == NULL) 409122205Sharti return; 410122205Sharti resp->cref = u->u.hdr.cref; 411122205Sharti resp->callstate = u->u.status.callstate; 412122205Sharti if (IE_ISGOOD(u->u.status.cause)) 413122205Sharti resp->cause = u->u.status.cause; 414122205Sharti 415122205Sharti uni->funcs->uni_output(uni, uni->arg, 416122205Sharti UNIAPI_RESET_STATUS_indication, 0, app); 417122205Sharti 418122205Sharti } else { 419122205Sharti struct uniapi_reset_error_indication *resp; 420122205Sharti struct uni_msg *app; 421122205Sharti 422122205Sharti resp = ALLOC_API(struct uniapi_reset_error_indication, app); 423122205Sharti if (resp != NULL) { 424122205Sharti resp->source = 0; 425122205Sharti resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE, 426122205Sharti 427122205Sharti uni->funcs->uni_output(uni, uni->arg, 428122205Sharti UNIAPI_RESET_ERROR_indication, 0, app); 429122205Sharti } 430122205Sharti } 431122205Sharti} 432122205Sharti 433122205Sharti/************************************************************/ 434122205Sharti/* 435122205Sharti * Reset-Respond process. 436122205Sharti */ 437122205Shartivoid 438131826Shartiuni_sig_respond(struct uni *uni, u_int sig, uint32_t cookie, 439122205Sharti struct uni_msg *m, struct uni_all *u) 440122205Sharti{ 441122205Sharti if (sig >= SIGR_END) { 442122205Sharti VERBOSE(uni, UNI_FAC_ERR, 1, "Signal %d outside of range to " 443122205Sharti "Reset-Respond", sig); 444122205Sharti if (m) 445122205Sharti uni_msg_destroy(m); 446122205Sharti if (u) 447122205Sharti UNI_FREE(u); 448122205Sharti return; 449122205Sharti } 450122205Sharti 451122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, 452122205Sharti "Signal %s in state %u of Reset-Respond; cookie %u", 453122205Sharti respond_sigs[sig], uni->glob_respond, cookie); 454122205Sharti 455122205Sharti switch (sig) { 456122205Sharti 457122205Sharti /* 458122205Sharti * SAAL 459122205Sharti */ 460122205Sharti case SIGR_RESTART: 461122205Sharti response_restart(uni, m, u); 462122205Sharti uni_msg_destroy(m); 463122205Sharti UNI_FREE(u); 464122205Sharti break; 465122205Sharti 466122205Sharti case SIGR_STATUS: 467122205Sharti response_status(uni, m, u); 468122205Sharti uni_msg_destroy(m); 469122205Sharti UNI_FREE(u); 470122205Sharti break; 471122205Sharti 472122205Sharti /* 473122205Sharti * User 474122205Sharti */ 475122205Sharti case SIGR_RESET_ERROR_response: 476122205Sharti response_error(uni, 477122205Sharti uni_msg_rptr(m, struct uniapi_reset_error_response *), 478122205Sharti cookie); 479122205Sharti uni_msg_destroy(m); 480122205Sharti break; 481122205Sharti 482122205Sharti case SIGR_RESET_response: 483122205Sharti response_response(uni, 484122205Sharti uni_msg_rptr(m, struct uniapi_reset_response *), cookie); 485122205Sharti uni_msg_destroy(m); 486122205Sharti break; 487122205Sharti 488122205Sharti /* 489122205Sharti * Timers 490122205Sharti */ 491122205Sharti case SIGR_T317: 492122205Sharti response_t317(uni); 493122205Sharti return; 494122205Sharti 495122205Sharti case SIGR_END: 496122205Sharti break; 497122205Sharti } 498122205Sharti} 499122205Sharti 500122205Sharti/* 501122205Sharti * Send a RELEASE_COMPLETE to all affected calls as per 502122205Sharti * F.2.3(3) 503122205Sharti */ 504122205Shartistatic int 505122205Shartirestart_forward(struct uni *uni, const struct uni_all *u) 506122205Sharti{ 507122205Sharti struct call *c; 508122205Sharti struct uni_all *resp; 509122205Sharti 510122205Sharti if ((resp = UNI_ALLOC()) == NULL) 511122205Sharti return (-1); 512122205Sharti 513122205Sharti TAILQ_FOREACH(c, &uni->calls, link) { 514122205Sharti if (u->u.restart.restart.rclass == UNI_RESTART_ALL || 515122205Sharti (IE_ISPRESENT(c->connid) && 516122205Sharti u->u.restart.connid.vpci == c->connid.vpci && 517122205Sharti (u->u.restart.restart.rclass == UNI_RESTART_PATH || 518122205Sharti u->u.restart.connid.vci == c->connid.vci))) { 519122205Sharti MK_MSG_ORIG(resp, UNI_RELEASE_COMPL, c->cref, c->mine); 520122205Sharti uni_release_compl(c, resp); 521122205Sharti } 522122205Sharti } 523122205Sharti 524122205Sharti UNI_FREE(resp); 525122205Sharti return (0); 526122205Sharti} 527122205Sharti 528122205Sharti/* 529122205Sharti * Respond process got a restart message. 530122205Sharti * Doesn't free the messages. 531122205Sharti */ 532122205Shartistatic void 533122205Shartiresponse_restart(struct uni *uni, struct uni_msg *m, struct uni_all *u) 534122205Sharti{ 535122205Sharti struct uni_msg *app; 536122205Sharti struct uniapi_reset_indication *ind; 537122205Sharti 538122205Sharti if (uni->glob_respond == UNI_CALLSTATE_REST0) { 539122205Sharti /* 540122205Sharti * If body decoding fails, this is because IEs are wrong. 541122205Sharti */ 542122205Sharti (void)uni_decode_body(m, u, &uni->cx); 543122205Sharti MANDATE_IE(uni, u->u.restart.restart, UNI_IE_RESTART); 544122205Sharti if (IE_ISGOOD(u->u.restart.restart)) { 545122205Sharti /* 546122205Sharti * Q.2931: 5.5.2.2 547122205Sharti */ 548122205Sharti if (u->u.restart.restart.rclass == UNI_RESTART_ALL && 549122205Sharti IE_ISGOOD(u->u.restart.connid)) { 550213789Srpaulo (void)UNI_SAVE_IERR(&uni->cx, UNI_IE_CONNID, 551122205Sharti u->u.restart.connid.h.act, 552122205Sharti UNI_IERR_UNK); 553122205Sharti } else if ((u->u.restart.restart.rclass == UNI_RESTART_PATH || 554122205Sharti u->u.restart.restart.rclass == UNI_RESTART_CHANNEL)) { 555122205Sharti MANDATE_IE(uni, u->u.restart.connid, UNI_IE_CONNID); 556122205Sharti } 557122205Sharti } 558122205Sharti switch (uni_verify(uni, u->u.hdr.act)) { 559122205Sharti case VFY_RAIM: 560122205Sharti case VFY_RAI: 561122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, 562122205Sharti UNI_CALLSTATE_REST0, NULL, 0); 563122205Sharti case VFY_CLR: 564122205Sharti case VFY_I: 565122205Sharti return; 566122205Sharti 567122205Sharti case VFY_RAP: 568122205Sharti case VFY_RAPU: 569122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, 570122205Sharti UNI_CALLSTATE_REST2, NULL, 0); 571122205Sharti case VFY_OK: 572122205Sharti break; 573122205Sharti } 574122205Sharti if (!IE_ISGOOD(u->u.restart.connid)) 575122205Sharti u->u.restart.connid.h.present = 0; 576122205Sharti 577122205Sharti /* 578122205Sharti * Send a RELEASE_COMPLETE to all affected calls as per 579122205Sharti * F.2.3(3) 580122205Sharti */ 581122205Sharti if (restart_forward(uni, u)) 582122205Sharti return; 583122205Sharti 584122205Sharti /* 585122205Sharti * Build restart signal for application 586122205Sharti */ 587122205Sharti if ((ind = ALLOC_API(struct uniapi_reset_indication, app)) == NULL) 588122205Sharti return; 589122205Sharti 590122205Sharti ind->restart = u->u.restart.restart; 591122205Sharti ind->connid = u->u.restart.connid; 592122205Sharti 593122205Sharti uni_enq_coord(uni, SIGO_RESET_indication, 0, app); 594122205Sharti 595122205Sharti TIMER_START_UNI(uni, t317, uni->timer317); 596122205Sharti uni->glob_respond = UNI_CALLSTATE_REST2; 597122205Sharti 598122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 2"); 599122205Sharti 600122205Sharti 601122205Sharti } else if (uni->glob_respond == UNI_CALLSTATE_REST2) { 602122205Sharti /* 603122205Sharti * No need to decode the message. It is unexpected in this 604122205Sharti * state so return a status. 605122205Sharti */ 606122205Sharti uni_respond_status_mtype(uni, &u->u.hdr.cref, uni->glob_respond, 607122205Sharti UNI_CAUSE_MSG_INCOMP, UNI_RESTART); 608122205Sharti 609122205Sharti 610122205Sharti } else 611122205Sharti ASSERT(0, ("bad global call state in responder")); 612122205Sharti} 613122205Sharti 614122205Shartistatic void 615122205Shartiresponse_t317(struct uni *uni) 616122205Sharti{ 617122205Sharti struct uniapi_reset_error_indication *resp; 618122205Sharti struct uni_msg *app; 619122205Sharti 620122205Sharti if (uni->glob_respond != UNI_CALLSTATE_REST2) { 621122205Sharti VERBOSE0(uni, UNI_FAC_ERR, "T317 in state %d", 622122205Sharti uni->glob_respond); 623122205Sharti return; 624122205Sharti } 625122205Sharti 626122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond error"); 627122205Sharti 628122205Sharti if ((resp = ALLOC_API(struct uniapi_reset_error_indication, app)) != NULL) { 629122205Sharti resp->source = 1; 630122205Sharti resp->reason = UNIAPI_RESET_ERROR_NO_CONFIRM; 631122205Sharti 632122205Sharti uni->funcs->uni_output(uni, uni->arg, 633122205Sharti UNIAPI_RESET_ERROR_indication, 0, app); 634122205Sharti } 635122205Sharti 636122205Sharti uni->glob_respond = UNI_CALLSTATE_REST0; 637122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0"); 638122205Sharti} 639122205Sharti 640122205Sharti/* 641122205Sharti * Error response from USER 642122205Sharti */ 643122205Shartistatic void 644122205Shartiresponse_error(struct uni *uni, struct uniapi_reset_error_response *c, 645131826Sharti uint32_t cookie) 646122205Sharti{ 647122205Sharti struct uni_all *resp; 648122205Sharti 649122205Sharti if (uni->glob_respond != UNI_CALLSTATE_REST2) { 650122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0); 651122205Sharti return; 652122205Sharti } 653122205Sharti 654122205Sharti if ((resp = UNI_ALLOC()) == NULL) { 655122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0); 656122205Sharti return; 657122205Sharti } 658122205Sharti 659122205Sharti MK_MSG_ORIG(resp, UNI_STATUS, 0, 1); 660122205Sharti MK_IE_CALLSTATE(resp->u.status.callstate, UNI_CALLSTATE_REST2); 661122205Sharti 662122205Sharti if (IE_ISGOOD(c->cause)) 663122205Sharti resp->u.status.cause = c->cause; 664122205Sharti else { 665122205Sharti MK_IE_CAUSE(resp->u.status.cause, UNI_CAUSE_LOC_USER, 666122205Sharti UNI_CAUSE_CHANNEL_NEX); 667122205Sharti if (IE_ISGOOD(uni->connid_respond)) 668122205Sharti ADD_CAUSE_CHANNID(resp->u.status.cause, 669122205Sharti uni->connid_respond.vpci, 670122205Sharti uni->connid_respond.vci); 671122205Sharti } 672122205Sharti 673122205Sharti if (uni_send_output(resp, uni) != 0) { 674122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0); 675122205Sharti UNI_FREE(resp); 676122205Sharti return; 677122205Sharti } 678122205Sharti 679122205Sharti uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 680122205Sharti} 681122205Sharti 682122205Sharti/* 683122205Sharti * Reset-response from user. 684122205Sharti */ 685122205Shartistatic void 686122205Shartiresponse_response(struct uni *uni, struct uniapi_reset_response *arg, 687131826Sharti uint32_t cookie) 688122205Sharti{ 689122205Sharti struct uni_all *resp; 690122205Sharti 691122205Sharti if (uni->glob_respond != UNI_CALLSTATE_REST2) { 692122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_BAD_CALLSTATE, cookie, 0); 693122205Sharti return; 694122205Sharti } 695122205Sharti 696122205Sharti if (!IE_ISGOOD(arg->restart)) { 697122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_MISSING_IE, cookie, 0); 698122205Sharti return; 699122205Sharti } 700122205Sharti 701122205Sharti if ((resp = UNI_ALLOC()) == NULL) { 702122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_NOMEM, cookie, 0); 703122205Sharti return; 704122205Sharti } 705122205Sharti 706122205Sharti TIMER_STOP_UNI(uni, t317); 707122205Sharti 708122205Sharti MK_MSG_ORIG(resp, UNI_RESTART_ACK, 0, 1); 709122205Sharti resp->u.restart.restart = arg->restart; 710122205Sharti if (IE_ISGOOD(arg->connid)) 711122205Sharti resp->u.restart.connid = arg->connid; 712122205Sharti 713122205Sharti if (uni_send_output(resp, uni) != 0) { 714122205Sharti uniapi_uni_error(uni, UNIAPI_ERROR_ENCODING, cookie, 0); 715122205Sharti UNI_FREE(resp); 716122205Sharti return; 717122205Sharti } 718122205Sharti 719122205Sharti UNI_FREE(resp); 720122205Sharti 721122205Sharti uni->glob_respond = UNI_CALLSTATE_REST0; 722122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, "Reset-Respond state := 0"); 723122205Sharti 724122205Sharti uniapi_uni_error(uni, UNIAPI_OK, cookie, 0); 725122205Sharti} 726122205Sharti 727122205Sharti/* 728122205Sharti * Reset-Response got a STATUS message. 729122205Sharti * 730122205Sharti * Q.2931: Reset-Response 2/2 731122205Sharti * 732122205Sharti * In Q.2931 only CALLSTATE_REST2 is allowed, this seems silly and to contradict 733122205Sharti * 5.6.12. So allow it in any state. 734122205Sharti * 735122205Sharti * The following states are considered compatible: 736122205Sharti * 737122205Sharti * Sender Receiver 738122205Sharti * ------ -------- 739122205Sharti * Rest0 Rest0 this is the normal state OK! 740122205Sharti * Rest0 Rest2 this may be the result of no answer from the API 741122205Sharti * and the Sender finally timing out. ERROR! 742122205Sharti * Rest1 Rest2 this is normal. OK! 743122205Sharti * Rest1 Rest0 RESTART_ACK was probably lost. OK! 744122205Sharti * 745122205Sharti * All others are wrong. 746122205Sharti */ 747122205Shartistatic void 748122205Shartiresponse_status(struct uni *uni, struct uni_msg *m, struct uni_all *u) 749122205Sharti{ 750122205Sharti (void)uni_decode_body(m, u, &uni->cx); 751122205Sharti MANDATE_IE(uni, u->u.status.callstate, UNI_IE_CALLSTATE); 752122205Sharti MANDATE_IE(uni, u->u.status.cause, UNI_IE_CAUSE); 753122205Sharti switch (uni_verify(uni, u->u.hdr.act)) { 754122205Sharti case VFY_CLR: 755122205Sharti if (uni->proto == UNIPROTO_UNI40U) { 756122205Sharti uni->glob_respond = UNI_CALLSTATE_REST0; 757122205Sharti VERBOSE(uni, UNI_FAC_RESTART, 1, 758122205Sharti "Reset-Respond state := 0"); 759122205Sharti return; 760122205Sharti } 761122205Sharti break; 762122205Sharti 763122205Sharti case VFY_RAIM: 764122205Sharti case VFY_RAI: 765122205Sharti case VFY_RAP: 766122205Sharti case VFY_RAPU: 767122205Sharti uni_respond_status_verify(uni, &u->u.hdr.cref, 768122205Sharti uni->glob_respond, NULL, 0); 769122205Sharti case VFY_I: 770122205Sharti case VFY_OK: 771122205Sharti break; 772122205Sharti } 773122205Sharti if (!IE_ISGOOD(u->u.status.callstate)) { 774122205Sharti /* 775122205Sharti * As a result of the strange handling above, we must 776122205Sharti * process a STATUS with an invalid or missing callstate! 777122205Sharti */ 778122205Sharti return; 779122205Sharti } 780122205Sharti if ((u->u.status.callstate.state == UNI_CALLSTATE_REST0 && 781122205Sharti uni->glob_respond == UNI_CALLSTATE_REST0) || 782122205Sharti (u->u.status.callstate.state == UNI_CALLSTATE_REST1 && 783122205Sharti uni->glob_respond == UNI_CALLSTATE_REST0) || 784122205Sharti (u->u.status.callstate.state == UNI_CALLSTATE_REST1 && 785122205Sharti uni->glob_respond == UNI_CALLSTATE_REST2)) { 786122205Sharti /* 787122205Sharti * Implementation dependend procedure: 788122205Sharti * Inform the API 789122205Sharti */ 790122205Sharti struct uniapi_reset_status_indication *resp; 791122205Sharti struct uni_msg *app; 792122205Sharti 793122205Sharti resp = ALLOC_API(struct uniapi_reset_status_indication, app); 794122205Sharti if (resp == NULL) 795122205Sharti return; 796122205Sharti 797122205Sharti resp->cref = u->u.hdr.cref; 798122205Sharti resp->callstate = u->u.status.callstate; 799122205Sharti if (IE_ISGOOD(u->u.status.cause)) 800122205Sharti resp->cause = u->u.status.cause; 801122205Sharti 802122205Sharti uni->funcs->uni_output(uni, uni->arg, 803122205Sharti UNIAPI_RESET_STATUS_indication, 0, app); 804122205Sharti 805122205Sharti } else { 806122205Sharti struct uniapi_reset_error_indication *resp; 807122205Sharti struct uni_msg *app; 808122205Sharti 809122205Sharti resp = ALLOC_API(struct uniapi_reset_error_indication, app); 810122205Sharti if (resp != NULL) { 811122205Sharti resp->source = 1; 812122205Sharti resp->reason = UNIAPI_RESET_ERROR_PEER_INCOMP_STATE, 813122205Sharti 814122205Sharti uni->funcs->uni_output(uni, uni->arg, 815122205Sharti UNIAPI_RESET_ERROR_indication, 0, app); 816122205Sharti } 817122205Sharti } 818122205Sharti} 819122205Sharti 820122205Sharti/* 821122205Sharti * T317 timeout function 822122205Sharti */ 823122205Shartistatic void 824122205Shartit317_func(struct uni *uni) 825122205Sharti{ 826122205Sharti uni_enq_resp(uni, SIGR_T317, 0, NULL, NULL); 827122205Sharti} 828