1131826Sharti/* 2131826Sharti * Copyright (c) 2003-2004 3131826Sharti * Hartmut Brandt 4131826Sharti * All rights reserved. 5131826Sharti * 6131826Sharti * Copyright (c) 2001-2002 7131826Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 8131826Sharti * All rights reserved. 9131826Sharti * 10131826Sharti * Author: Harti Brandt <harti@freebsd.org> 11131826Sharti * 12131826Sharti * Redistribution of this software and documentation and use in source and 13131826Sharti * binary forms, with or without modification, are permitted provided that 14131826Sharti * the following conditions are met: 15131826Sharti * 16131826Sharti * 1. Redistributions of source code or documentation must retain the above 17131826Sharti * copyright notice, this list of conditions and the following disclaimer. 18131826Sharti * 2. Redistributions in binary form must reproduce the above copyright 19131826Sharti * notice, this list of conditions and the following disclaimer in the 20131826Sharti * documentation and/or other materials provided with the distribution. 21131826Sharti * 22131826Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 23131826Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 24131826Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 25131826Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26131826Sharti * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27131826Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28131826Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29131826Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30131826Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31131826Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32131826Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33131826Sharti * 34133492Sharti * $Begemot: libunimsg/netnatm/api/cc_user.c,v 1.3 2004/07/16 18:46:55 brandt Exp $ 35131826Sharti * 36131826Sharti * ATM API as defined per af-saa-0108 37131826Sharti * 38131826Sharti * User side (upper half) 39131826Sharti */ 40131826Sharti 41131826Sharti#include <netnatm/unimsg.h> 42131826Sharti#include <netnatm/msg/unistruct.h> 43131826Sharti#include <netnatm/msg/unimsglib.h> 44131826Sharti#include <netnatm/api/unisap.h> 45131826Sharti#include <netnatm/sig/unidef.h> 46131826Sharti#include <netnatm/api/atmapi.h> 47131826Sharti#include <netnatm/api/ccatm.h> 48131826Sharti#include <netnatm/api/ccpriv.h> 49131826Sharti 50131826Sharti/* 51131826Sharti* This file handles messages to a USER. 52131826Sharti*/ 53131826Shartistatic const char *stab[] = { 54131826Sharti#define DEF(N) [N] = #N, 55131826Sharti USER_STATES 56131826Sharti#undef DEF 57131826Sharti}; 58131826Sharti 59131826Sharticonst char * 60131826Sharticc_user_state2str(u_int s) 61131826Sharti{ 62131826Sharti if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL) 63131826Sharti return ("?"); 64131826Sharti return (stab[s]); 65131826Sharti} 66131826Sharti 67131826Shartistatic __inline void 68131826Shartiset_state(struct ccuser *user, enum user_state ns) 69131826Sharti{ 70131826Sharti if (user->state != ns) { 71131826Sharti if (user->cc->log & CCLOG_USER_STATE) 72131826Sharti cc_user_log(user, "%s -> %s", 73131826Sharti stab[user->state], stab[ns]); 74131826Sharti user->state = ns; 75131826Sharti } 76131826Sharti} 77131826Sharti 78131826Shartistatic __inline void 79131826Sharticc_user_send(struct ccuser *user, u_int op, void *arg, size_t len) 80131826Sharti{ 81131826Sharti user->cc->funcs->send_user(user, user->uarg, op, arg, len); 82131826Sharti} 83131826Sharti 84131826Shartistatic __inline void 85131826Sharticc_user_ok(struct ccuser *user, u_int data, void *arg, size_t len) 86131826Sharti{ 87131826Sharti user->cc->funcs->respond_user(user, user->uarg, 88131826Sharti ATMERR_OK, data, arg, len); 89131826Sharti} 90131826Sharti 91131826Shartistatic __inline void 92131826Sharticc_user_err(struct ccuser *user, int err) 93131826Sharti{ 94131826Sharti user->cc->funcs->respond_user(user, user->uarg, 95131826Sharti err, ATMRESP_NONE, NULL, 0); 96131826Sharti} 97131826Sharti 98131826Sharti 99131826Sharti/********************************************************************** 100131826Sharti* 101131826Sharti* INSTANCE MANAGEMENT 102131826Sharti*/ 103131826Sharti/* 104131826Sharti* New endpoint created 105131826Sharti*/ 106131826Shartistruct ccuser * 107131826Sharticc_user_create(struct ccdata *cc, void *uarg, const char *name) 108131826Sharti{ 109131826Sharti struct ccuser *user; 110131826Sharti 111131826Sharti user = CCZALLOC(sizeof(*user)); 112131826Sharti if (user == NULL) 113131826Sharti return (NULL); 114131826Sharti 115131826Sharti user->cc = cc; 116131826Sharti user->state = USER_NULL; 117131826Sharti user->uarg = uarg; 118131826Sharti strncpy(user->name, name, sizeof(user->name)); 119131826Sharti user->name[sizeof(user->name) - 1] = '\0'; 120131826Sharti TAILQ_INIT(&user->connq); 121131826Sharti LIST_INSERT_HEAD(&cc->user_list, user, node_link); 122131826Sharti 123131826Sharti if (user->cc->log & CCLOG_USER_INST) 124131826Sharti cc_user_log(user, "created with name '%s'", name); 125131826Sharti 126131826Sharti return (user); 127131826Sharti} 128131826Sharti 129131826Sharti/* 130131826Sharti * Reset a user instance 131131826Sharti */ 132131826Shartistatic void 133131826Sharticc_user_reset(struct ccuser *user) 134131826Sharti{ 135131826Sharti 136131826Sharti CCASSERT(TAILQ_EMPTY(&user->connq), ("connq not empty")); 137131826Sharti 138131826Sharti if (user->sap != NULL) { 139131826Sharti CCFREE(user->sap); 140131826Sharti user->sap = NULL; 141131826Sharti } 142131826Sharti 143131826Sharti if (user->accepted != NULL) { 144131826Sharti user->accepted->acceptor = NULL; 145131826Sharti user->accepted = NULL; 146131826Sharti } 147131826Sharti user->config = USER_P2P; 148131826Sharti user->queue_act = 0; 149131826Sharti user->queue_max = 0; 150131826Sharti user->aborted = 0; 151131826Sharti 152131826Sharti set_state(user, USER_NULL); 153131826Sharti 154131826Sharti cc_user_sig_flush(user); 155131826Sharti} 156131826Sharti 157131826Shartistatic void 158131826Sharticc_user_abort(struct ccuser *user, const struct uni_ie_cause *cause) 159131826Sharti{ 160131826Sharti struct ccconn *conn; 161131826Sharti 162131826Sharti /* 163131826Sharti * Although the standard state that 'all connections 164131826Sharti * associated with this endpoint are aborted' we only 165131826Sharti * have to abort the head one, because in state A6 166131826Sharti * (call present) the endpoint is only associated to the 167131826Sharti * head connection - the others are 'somewhere else' and 168131826Sharti * need to be redispatched. 169131826Sharti * 170131826Sharti * First bring user into a state that the connections 171131826Sharti * are not dispatched back to it. 172131826Sharti */ 173131826Sharti set_state(user, USER_NULL); 174131826Sharti if (!user->aborted) { 175131826Sharti if ((conn = TAILQ_FIRST(&user->connq)) != NULL) { 176131826Sharti memset(conn->cause, 0, sizeof(conn->cause)); 177131826Sharti if (cause != NULL) 178131826Sharti conn->cause[0] = *cause; 179131826Sharti cc_conn_reset_acceptor(conn); 180131826Sharti cc_disconnect_from_user(conn); 181131826Sharti cc_conn_sig(conn, CONN_SIG_USER_ABORT, NULL); 182131826Sharti } 183131826Sharti } 184131826Sharti 185131826Sharti while ((conn = TAILQ_FIRST(&user->connq)) != NULL) { 186131826Sharti /* these should be in C21 */ 187131826Sharti cc_disconnect_from_user(conn); 188131826Sharti cc_conn_dispatch(conn); 189131826Sharti } 190131826Sharti 191131826Sharti cc_user_reset(user); 192131826Sharti} 193131826Sharti 194131826Sharti/* 195131826Sharti * Application has closed this endpoint. Clean up all user resources and 196131826Sharti * abort all connections. This can be called in any state. 197131826Sharti */ 198131826Shartivoid 199131826Sharticc_user_destroy(struct ccuser *user) 200131826Sharti{ 201131826Sharti 202131826Sharti if (user->cc->log & CCLOG_USER_INST) 203131826Sharti cc_user_log(user, "destroy '%s'", user->name); 204131826Sharti 205131826Sharti cc_user_abort(user, NULL); 206131826Sharti 207131826Sharti if (user->sap != NULL) 208131826Sharti CCFREE(user->sap); 209131826Sharti 210131826Sharti cc_user_sig_flush(user); 211131826Sharti 212131826Sharti LIST_REMOVE(user, node_link); 213131826Sharti CCFREE(user); 214131826Sharti} 215131826Sharti 216131826Sharti/********************************************************************** 217131826Sharti * 218131826Sharti * OUTGOING CALLS 219131826Sharti */ 220131826Sharti/* 221131826Sharti * Return true when the calling address of the connection matches the address. 222131826Sharti */ 223131826Shartistatic int 224131826Shartiaddr_matches(const struct ccaddr *addr, const struct ccconn *conn) 225131826Sharti{ 226131826Sharti 227131826Sharti if (!IE_ISPRESENT(conn->calling)) 228131826Sharti return (0); 229131826Sharti 230131826Sharti return (addr->addr.type == conn->calling.addr.type && 231131826Sharti addr->addr.plan == conn->calling.addr.plan && 232131826Sharti addr->addr.len == conn->calling.addr.len && 233131826Sharti memcmp(addr->addr.addr, conn->calling.addr.addr, 234131826Sharti addr->addr.len) == 0); 235131826Sharti} 236131826Sharti 237131826Sharti/* 238131826Sharti * Check if the user's SAP (given he is in the right state) and 239131826Sharti * the given SAP overlap 240131826Sharti */ 241131826Shartistatic int 242131826Sharticheck_overlap(struct ccuser *user, struct uni_sap *sap) 243131826Sharti{ 244131826Sharti return ((user->state == USER_IN_PREPARING || 245131826Sharti user->state == USER_IN_WAITING) && 246131826Sharti unisve_overlap_sap(user->sap, sap)); 247131826Sharti} 248131826Sharti 249131826Sharti/* 250131826Sharti * Send arrival notification to user 251131826Sharti */ 252131826Shartistatic void 253131826Shartido_arrival(struct ccuser *user) 254131826Sharti{ 255131826Sharti struct ccconn *conn; 256131826Sharti 257131826Sharti user->aborted = 0; 258131826Sharti if ((conn = TAILQ_FIRST(&user->connq)) != NULL) { 259131826Sharti set_state(user, USER_IN_ARRIVED); 260131826Sharti cc_user_send(user, ATMOP_ARRIVAL_OF_INCOMING_CALL, NULL, 0); 261131826Sharti cc_conn_sig(conn, CONN_SIG_ARRIVAL, NULL); 262131826Sharti } 263131826Sharti} 264131826Sharti 265131826Sharti/********************************************************************** 266131826Sharti * 267131826Sharti * ATTRIBUTES 268131826Sharti */ 269131826Sharti/* 270131826Sharti * Query an attribute. This is possible only in some states: preparation 271131826Sharti * of an outgoing call, after an incoming call was offered to the application 272131826Sharti * and in the three active states (P2P, P2PLeaf, P2PRoot). 273131826Sharti */ 274131826Shartistatic struct ccconn * 275131826Sharticc_query_check(struct ccuser *user) 276131826Sharti{ 277131826Sharti 278131826Sharti switch (user->state) { 279131826Sharti 280131826Sharti case USER_OUT_PREPARING: 281131826Sharti case USER_IN_ARRIVED: 282131826Sharti case USER_ACTIVE: 283131826Sharti return (TAILQ_FIRST(&user->connq)); 284131826Sharti 285131826Sharti case USER_NULL: 286131826Sharti /* if we are waiting for the SETUP_confirm, we are in 287131826Sharti * the NULL state still (we are the new endpoint), but 288131826Sharti * have a connection in 'accepted' that is in the 289131826Sharti * CONN_IN_WAIT_ACCEPT_OK state. 290131826Sharti */ 291131826Sharti if (user->accepted != NULL && 292131826Sharti user->accepted->state == CONN_IN_WAIT_ACCEPT_OK) 293131826Sharti return (user->accepted); 294131826Sharti /* FALLTHRU */ 295131826Sharti 296131826Sharti default: 297131826Sharti return (NULL); 298131826Sharti } 299131826Sharti} 300131826Sharti 301131826Sharti/* 302131826Sharti * Query attributes 303131826Sharti */ 304131826Shartistatic void 305131826Sharticc_attr_query(struct ccuser *user, struct ccconn *conn, 306131826Sharti uint32_t *attr, u_int count) 307131826Sharti{ 308131826Sharti void *val, *ptr; 309131826Sharti size_t total, len; 310131826Sharti u_int i; 311131826Sharti uint32_t *atab; 312131826Sharti 313131826Sharti /* determine the length of the total attribute buffer */ 314131826Sharti total = sizeof(uint32_t) + count * sizeof(uint32_t); 315131826Sharti for (i = 0; i < count; i++) { 316131826Sharti len = 0; 317131826Sharti switch ((enum atm_attribute)attr[i]) { 318131826Sharti 319131826Sharti case ATM_ATTR_NONE: 320131826Sharti break; 321131826Sharti 322131826Sharti case ATM_ATTR_BLLI_SELECTOR: 323131826Sharti len = sizeof(uint32_t); 324131826Sharti break; 325131826Sharti 326131826Sharti case ATM_ATTR_BLLI: 327131826Sharti len = sizeof(struct uni_ie_blli); 328131826Sharti break; 329131826Sharti 330131826Sharti case ATM_ATTR_BEARER: 331131826Sharti len = sizeof(struct uni_ie_bearer); 332131826Sharti break; 333131826Sharti 334131826Sharti case ATM_ATTR_TRAFFIC: 335131826Sharti len = sizeof(struct uni_ie_traffic); 336131826Sharti break; 337131826Sharti 338131826Sharti case ATM_ATTR_QOS: 339131826Sharti len = sizeof(struct uni_ie_qos); 340131826Sharti break; 341131826Sharti 342131826Sharti case ATM_ATTR_EXQOS: 343131826Sharti len = sizeof(struct uni_ie_exqos); 344131826Sharti break; 345131826Sharti 346131826Sharti case ATM_ATTR_CALLED: 347131826Sharti len = sizeof(struct uni_ie_called); 348131826Sharti break; 349131826Sharti 350131826Sharti case ATM_ATTR_CALLEDSUB: 351131826Sharti len = sizeof(struct uni_ie_calledsub); 352131826Sharti break; 353131826Sharti 354131826Sharti case ATM_ATTR_CALLING: 355131826Sharti len = sizeof(struct uni_ie_calling); 356131826Sharti break; 357131826Sharti 358131826Sharti case ATM_ATTR_CALLINGSUB: 359131826Sharti len = sizeof(struct uni_ie_callingsub); 360131826Sharti break; 361131826Sharti 362131826Sharti case ATM_ATTR_AAL: 363131826Sharti len = sizeof(struct uni_ie_aal); 364131826Sharti break; 365131826Sharti 366131826Sharti case ATM_ATTR_EPREF: 367131826Sharti len = sizeof(struct uni_ie_epref); 368131826Sharti break; 369131826Sharti 370131826Sharti case ATM_ATTR_CONNED: 371131826Sharti len = sizeof(struct uni_ie_conned); 372131826Sharti break; 373131826Sharti 374131826Sharti case ATM_ATTR_CONNEDSUB: 375131826Sharti len = sizeof(struct uni_ie_connedsub); 376131826Sharti break; 377131826Sharti 378131826Sharti case ATM_ATTR_EETD: 379131826Sharti len = sizeof(struct uni_ie_eetd); 380131826Sharti break; 381131826Sharti 382131826Sharti case ATM_ATTR_ABRSETUP: 383131826Sharti len = sizeof(struct uni_ie_abrsetup); 384131826Sharti break; 385131826Sharti 386131826Sharti case ATM_ATTR_ABRADD: 387131826Sharti len = sizeof(struct uni_ie_abradd); 388131826Sharti break; 389131826Sharti 390131826Sharti case ATM_ATTR_CONNID: 391131826Sharti len = sizeof(struct uni_ie_connid); 392131826Sharti break; 393131826Sharti 394131826Sharti case ATM_ATTR_MDCR: 395131826Sharti len = sizeof(struct uni_ie_mdcr); 396131826Sharti break; 397131826Sharti } 398131826Sharti if (len == 0) { 399131826Sharti cc_user_err(user, ATMERR_BAD_ATTR); 400131826Sharti return; 401131826Sharti } 402131826Sharti total += len; 403131826Sharti } 404131826Sharti 405131826Sharti /* allocate buffer */ 406131826Sharti val = CCMALLOC(total); 407131826Sharti if (val == NULL) 408131826Sharti return; 409131826Sharti 410131826Sharti atab = val; 411131826Sharti atab[0] = count; 412131826Sharti 413131826Sharti /* fill */ 414131826Sharti ptr = (u_char *)val + (sizeof(uint32_t) + count * sizeof(uint32_t)); 415131826Sharti for (i = 0; i < count; i++) { 416131826Sharti len = 0; 417131826Sharti atab[i + 1] = attr[i]; 418131826Sharti switch (attr[i]) { 419131826Sharti 420131826Sharti case ATM_ATTR_NONE: 421131826Sharti break; 422131826Sharti 423131826Sharti case ATM_ATTR_BLLI_SELECTOR: 424131826Sharti len = sizeof(uint32_t); 425131826Sharti memcpy(ptr, &conn->blli_selector, len); 426131826Sharti break; 427131826Sharti 428131826Sharti case ATM_ATTR_BLLI: 429131826Sharti /* in A6 the blli_selector may be 0 when 430131826Sharti * there was no blli in the SETUP. 431131826Sharti */ 432131826Sharti len = sizeof(struct uni_ie_blli); 433131826Sharti if (conn->blli_selector == 0) 434131826Sharti memset(ptr, 0, len); 435131826Sharti else 436131826Sharti memcpy(ptr, &conn->blli[conn->blli_selector - 437131826Sharti 1], len); 438131826Sharti break; 439131826Sharti 440131826Sharti case ATM_ATTR_BEARER: 441131826Sharti len = sizeof(struct uni_ie_bearer); 442131826Sharti memcpy(ptr, &conn->bearer, len); 443131826Sharti break; 444131826Sharti 445131826Sharti case ATM_ATTR_TRAFFIC: 446131826Sharti len = sizeof(struct uni_ie_traffic); 447131826Sharti memcpy(ptr, &conn->traffic, len); 448131826Sharti break; 449131826Sharti 450131826Sharti case ATM_ATTR_QOS: 451131826Sharti len = sizeof(struct uni_ie_qos); 452131826Sharti memcpy(ptr, &conn->qos, len); 453131826Sharti break; 454131826Sharti 455131826Sharti case ATM_ATTR_EXQOS: 456131826Sharti len = sizeof(struct uni_ie_exqos); 457131826Sharti memcpy(ptr, &conn->exqos, len); 458131826Sharti break; 459131826Sharti 460131826Sharti case ATM_ATTR_CALLED: 461131826Sharti len = sizeof(struct uni_ie_called); 462131826Sharti memcpy(ptr, &conn->called, len); 463131826Sharti break; 464131826Sharti 465131826Sharti case ATM_ATTR_CALLEDSUB: 466131826Sharti len = sizeof(struct uni_ie_calledsub); 467131826Sharti memcpy(ptr, &conn->calledsub, len); 468131826Sharti break; 469131826Sharti 470131826Sharti case ATM_ATTR_CALLING: 471131826Sharti len = sizeof(struct uni_ie_calling); 472131826Sharti memcpy(ptr, &conn->calling, len); 473131826Sharti break; 474131826Sharti 475131826Sharti case ATM_ATTR_CALLINGSUB: 476131826Sharti len = sizeof(struct uni_ie_callingsub); 477131826Sharti memcpy(ptr, &conn->callingsub, len); 478131826Sharti break; 479131826Sharti 480131826Sharti case ATM_ATTR_AAL: 481131826Sharti len = sizeof(struct uni_ie_aal); 482131826Sharti memcpy(ptr, &conn->aal, len); 483131826Sharti break; 484131826Sharti 485131826Sharti case ATM_ATTR_EPREF: 486131826Sharti len = sizeof(struct uni_ie_epref); 487131826Sharti memcpy(ptr, &conn->epref, len); 488131826Sharti break; 489131826Sharti 490131826Sharti case ATM_ATTR_CONNED: 491131826Sharti len = sizeof(struct uni_ie_conned); 492131826Sharti memcpy(ptr, &conn->conned, len); 493131826Sharti break; 494131826Sharti 495131826Sharti case ATM_ATTR_CONNEDSUB: 496131826Sharti len = sizeof(struct uni_ie_connedsub); 497131826Sharti memcpy(ptr, &conn->connedsub, len); 498131826Sharti break; 499131826Sharti 500131826Sharti case ATM_ATTR_EETD: 501131826Sharti len = sizeof(struct uni_ie_eetd); 502131826Sharti memcpy(ptr, &conn->eetd, len); 503131826Sharti break; 504131826Sharti 505131826Sharti case ATM_ATTR_ABRSETUP: 506131826Sharti len = sizeof(struct uni_ie_abrsetup); 507131826Sharti memcpy(ptr, &conn->abrsetup, len); 508131826Sharti break; 509131826Sharti 510131826Sharti case ATM_ATTR_ABRADD: 511131826Sharti len = sizeof(struct uni_ie_abradd); 512131826Sharti memcpy(ptr, &conn->abradd, len); 513131826Sharti break; 514131826Sharti 515131826Sharti case ATM_ATTR_CONNID: 516131826Sharti len = sizeof(struct uni_ie_connid); 517131826Sharti memcpy(ptr, &conn->connid, len); 518131826Sharti break; 519131826Sharti 520131826Sharti case ATM_ATTR_MDCR: 521131826Sharti len = sizeof(struct uni_ie_mdcr); 522131826Sharti memcpy(ptr, &conn->mdcr, len); 523131826Sharti break; 524131826Sharti } 525131826Sharti ptr = (u_char *)ptr + len; 526131826Sharti } 527131826Sharti 528131826Sharti cc_user_ok(user, ATMRESP_ATTRS, val, total); 529131826Sharti 530131826Sharti CCFREE(val); 531131826Sharti} 532131826Sharti 533131826Sharti/* 534131826Sharti * Check whether the state is ok and return the connection 535131826Sharti */ 536131826Shartistatic struct ccconn * 537131826Sharticc_set_check(struct ccuser *user) 538131826Sharti{ 539131826Sharti switch(user->state) { 540131826Sharti 541131826Sharti case USER_OUT_PREPARING: 542131826Sharti case USER_IN_ARRIVED: 543131826Sharti return (TAILQ_FIRST(&user->connq)); 544131826Sharti 545131826Sharti default: 546131826Sharti return (NULL); 547131826Sharti } 548131826Sharti} 549131826Sharti 550131826Sharti/* 551131826Sharti * Set connection attribute(s) 552131826Sharti */ 553131826Shartistatic void 554131826Sharticc_attr_set(struct ccuser *user, struct ccconn *conn, uint32_t *attr, 555131826Sharti u_int count, u_char *val, size_t vallen) 556131826Sharti{ 557131826Sharti size_t total, len; 558131826Sharti u_int i; 559131826Sharti u_char *ptr; 560131826Sharti 561131826Sharti /* determine the length of the total attribute buffer */ 562131826Sharti total = 0; 563131826Sharti ptr = val; 564131826Sharti for (i = 0; i < count; i++) { 565131826Sharti len = 0; 566131826Sharti switch ((enum atm_attribute)attr[i]) { 567131826Sharti 568131826Sharti case ATM_ATTR_NONE: 569131826Sharti break; 570131826Sharti 571131826Sharti case ATM_ATTR_BLLI_SELECTOR: 572131826Sharti { 573131826Sharti uint32_t sel; 574131826Sharti 575131826Sharti if (conn->state != CONN_OUT_PREPARING) 576131826Sharti goto rdonly; 577131826Sharti memcpy(&sel, ptr, sizeof(sel)); 578131826Sharti if (sel == 0 || sel > UNI_NUM_IE_BLLI) 579131826Sharti goto bad_val; 580131826Sharti len = sizeof(uint32_t); 581131826Sharti break; 582131826Sharti } 583131826Sharti 584131826Sharti case ATM_ATTR_BLLI: 585131826Sharti len = sizeof(struct uni_ie_blli); 586131826Sharti break; 587131826Sharti 588131826Sharti case ATM_ATTR_BEARER: 589131826Sharti if (conn->state != CONN_OUT_PREPARING) 590131826Sharti goto rdonly; 591131826Sharti len = sizeof(struct uni_ie_bearer); 592131826Sharti break; 593131826Sharti 594131826Sharti case ATM_ATTR_TRAFFIC: 595131826Sharti len = sizeof(struct uni_ie_traffic); 596131826Sharti break; 597131826Sharti 598131826Sharti case ATM_ATTR_QOS: 599131826Sharti if (conn->state != CONN_OUT_PREPARING) 600131826Sharti goto rdonly; 601131826Sharti len = sizeof(struct uni_ie_qos); 602131826Sharti break; 603131826Sharti 604131826Sharti case ATM_ATTR_EXQOS: 605131826Sharti len = sizeof(struct uni_ie_exqos); 606131826Sharti break; 607131826Sharti 608131826Sharti case ATM_ATTR_CALLED: 609131826Sharti goto rdonly; 610131826Sharti 611131826Sharti case ATM_ATTR_CALLEDSUB: 612131826Sharti if (conn->state != CONN_OUT_PREPARING) 613131826Sharti goto rdonly; 614131826Sharti len = sizeof(struct uni_ie_calledsub); 615131826Sharti break; 616131826Sharti 617131826Sharti case ATM_ATTR_CALLING: 618131826Sharti if (conn->state != CONN_OUT_PREPARING) 619131826Sharti goto rdonly; 620131826Sharti len = sizeof(struct uni_ie_calling); 621131826Sharti break; 622131826Sharti 623131826Sharti case ATM_ATTR_CALLINGSUB: 624131826Sharti if (conn->state != CONN_OUT_PREPARING) 625131826Sharti goto rdonly; 626131826Sharti len = sizeof(struct uni_ie_callingsub); 627131826Sharti break; 628131826Sharti 629131826Sharti case ATM_ATTR_AAL: 630131826Sharti len = sizeof(struct uni_ie_aal); 631131826Sharti break; 632131826Sharti 633131826Sharti case ATM_ATTR_EPREF: 634131826Sharti goto rdonly; 635131826Sharti 636131826Sharti case ATM_ATTR_CONNED: 637131826Sharti goto rdonly; 638131826Sharti 639131826Sharti case ATM_ATTR_CONNEDSUB: 640131826Sharti goto rdonly; 641131826Sharti 642131826Sharti case ATM_ATTR_EETD: 643131826Sharti len = sizeof(struct uni_ie_eetd); 644131826Sharti break; 645131826Sharti 646131826Sharti case ATM_ATTR_ABRSETUP: 647131826Sharti len = sizeof(struct uni_ie_abrsetup); 648131826Sharti break; 649131826Sharti 650131826Sharti case ATM_ATTR_ABRADD: 651131826Sharti len = sizeof(struct uni_ie_abradd); 652131826Sharti break; 653131826Sharti 654131826Sharti case ATM_ATTR_CONNID: 655131826Sharti len = sizeof(struct uni_ie_connid); 656131826Sharti break; 657131826Sharti 658131826Sharti case ATM_ATTR_MDCR: 659131826Sharti if (conn->state != CONN_OUT_PREPARING) 660131826Sharti goto rdonly; 661131826Sharti len = sizeof(struct uni_ie_mdcr); 662131826Sharti break; 663131826Sharti } 664131826Sharti if (len == 0) { 665131826Sharti cc_user_err(user, ATMERR_BAD_ATTR); 666131826Sharti return; 667131826Sharti } 668131826Sharti total += len; 669131826Sharti ptr += len; 670131826Sharti } 671131826Sharti 672131826Sharti /* check the length */ 673131826Sharti if (vallen != total) { 674131826Sharti cc_user_err(user, ATMERR_BAD_ARGS); 675131826Sharti return; 676131826Sharti } 677131826Sharti 678131826Sharti ptr = val; 679131826Sharti for (i = 0; i < count; i++) { 680131826Sharti len = 0; 681131826Sharti switch ((enum atm_attribute)attr[i]) { 682131826Sharti 683131826Sharti case ATM_ATTR_NONE: 684131826Sharti break; 685131826Sharti 686131826Sharti case ATM_ATTR_BLLI_SELECTOR: 687131826Sharti { 688131826Sharti uint32_t sel; 689131826Sharti 690131826Sharti memcpy(&sel, ptr, sizeof(sel)); 691131826Sharti conn->blli_selector = sel; 692131826Sharti len = sizeof(uint32_t); 693131826Sharti break; 694131826Sharti } 695131826Sharti 696131826Sharti case ATM_ATTR_BLLI: 697131826Sharti len = sizeof(struct uni_ie_blli); 698131826Sharti memcpy(&conn->blli[conn->blli_selector - 1], ptr, len); 699131826Sharti conn->dirty_attr |= CCDIRTY_BLLI; 700131826Sharti break; 701131826Sharti 702131826Sharti case ATM_ATTR_BEARER: 703131826Sharti len = sizeof(struct uni_ie_bearer); 704131826Sharti memcpy(&conn->bearer, ptr, len); 705131826Sharti break; 706131826Sharti 707131826Sharti case ATM_ATTR_TRAFFIC: 708131826Sharti len = sizeof(struct uni_ie_traffic); 709131826Sharti memcpy(&conn->traffic, ptr, len); 710131826Sharti conn->dirty_attr |= CCDIRTY_TRAFFIC; 711131826Sharti break; 712131826Sharti 713131826Sharti case ATM_ATTR_QOS: 714131826Sharti len = sizeof(struct uni_ie_qos); 715131826Sharti memcpy(&conn->qos, ptr, len); 716131826Sharti break; 717131826Sharti 718131826Sharti case ATM_ATTR_EXQOS: 719131826Sharti len = sizeof(struct uni_ie_exqos); 720131826Sharti memcpy(&conn->exqos, ptr, len); 721131826Sharti conn->dirty_attr |= CCDIRTY_EXQOS; 722131826Sharti break; 723131826Sharti 724131826Sharti case ATM_ATTR_CALLED: 725131826Sharti len = sizeof(struct uni_ie_called); 726131826Sharti break; 727131826Sharti 728131826Sharti case ATM_ATTR_CALLEDSUB: 729131826Sharti len = sizeof(struct uni_ie_calledsub); 730131826Sharti memcpy(&conn->calledsub, ptr, len); 731131826Sharti break; 732131826Sharti 733131826Sharti case ATM_ATTR_CALLING: 734131826Sharti len = sizeof(struct uni_ie_calling); 735131826Sharti memcpy(&conn->calling, ptr, len); 736131826Sharti break; 737131826Sharti 738131826Sharti case ATM_ATTR_CALLINGSUB: 739131826Sharti len = sizeof(struct uni_ie_callingsub); 740131826Sharti memcpy(&conn->callingsub, ptr, len); 741131826Sharti break; 742131826Sharti 743131826Sharti case ATM_ATTR_AAL: 744131826Sharti len = sizeof(struct uni_ie_aal); 745131826Sharti memcpy(&conn->aal, ptr, len); 746131826Sharti conn->dirty_attr |= CCDIRTY_AAL; 747131826Sharti break; 748131826Sharti 749131826Sharti case ATM_ATTR_EPREF: 750131826Sharti len = sizeof(struct uni_ie_epref); 751131826Sharti break; 752131826Sharti 753131826Sharti case ATM_ATTR_CONNED: 754131826Sharti len = sizeof(struct uni_ie_conned); 755131826Sharti break; 756131826Sharti 757131826Sharti case ATM_ATTR_CONNEDSUB: 758131826Sharti len = sizeof(struct uni_ie_connedsub); 759131826Sharti break; 760131826Sharti 761131826Sharti case ATM_ATTR_EETD: 762131826Sharti len = sizeof(struct uni_ie_eetd); 763131826Sharti memcpy(&conn->eetd, ptr, len); 764131826Sharti conn->dirty_attr |= CCDIRTY_EETD; 765131826Sharti break; 766131826Sharti 767131826Sharti case ATM_ATTR_ABRSETUP: 768131826Sharti len = sizeof(struct uni_ie_abrsetup); 769131826Sharti memcpy(&conn->abrsetup, ptr, len); 770131826Sharti conn->dirty_attr |= CCDIRTY_ABRSETUP; 771131826Sharti break; 772131826Sharti 773131826Sharti case ATM_ATTR_ABRADD: 774131826Sharti len = sizeof(struct uni_ie_abradd); 775131826Sharti memcpy(&conn->abradd, ptr, len); 776131826Sharti conn->dirty_attr |= CCDIRTY_ABRADD; 777131826Sharti break; 778131826Sharti 779131826Sharti case ATM_ATTR_CONNID: 780131826Sharti len = sizeof(struct uni_ie_connid); 781131826Sharti memcpy(&conn->connid, ptr, len); 782131826Sharti conn->dirty_attr |= CCDIRTY_CONNID; 783131826Sharti break; 784131826Sharti 785131826Sharti case ATM_ATTR_MDCR: 786131826Sharti len = sizeof(struct uni_ie_mdcr); 787131826Sharti memcpy(&conn->mdcr, ptr, len); 788131826Sharti break; 789131826Sharti } 790131826Sharti ptr += len; 791131826Sharti } 792131826Sharti 793131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 794131826Sharti return; 795131826Sharti 796131826Sharti bad_val: 797131826Sharti cc_user_err(user, ATMERR_BAD_VALUE); 798131826Sharti return; 799131826Sharti 800131826Sharti rdonly: 801131826Sharti cc_user_err(user, ATMERR_RDONLY); 802131826Sharti return; 803131826Sharti} 804131826Sharti 805131826Sharti#ifdef CCATM_DEBUG 806131826Shartistatic const char *op_names[] = { 807131826Sharti#define S(OP) [ATMOP_##OP] = #OP 808131826Sharti S(RESP), 809131826Sharti S(ABORT_CONNECTION), 810131826Sharti S(ACCEPT_INCOMING_CALL), 811131826Sharti S(ADD_PARTY), 812131826Sharti S(ADD_PARTY_REJECT), 813131826Sharti S(ADD_PARTY_SUCCESS), 814131826Sharti S(ARRIVAL_OF_INCOMING_CALL), 815131826Sharti S(CALL_RELEASE), 816131826Sharti S(CONNECT_OUTGOING_CALL), 817131826Sharti S(DROP_PARTY), 818131826Sharti S(GET_LOCAL_PORT_INFO), 819131826Sharti S(P2MP_CALL_ACTIVE), 820131826Sharti S(P2P_CALL_ACTIVE), 821131826Sharti S(PREPARE_INCOMING_CALL), 822131826Sharti S(PREPARE_OUTGOING_CALL), 823131826Sharti S(QUERY_CONNECTION_ATTRIBUTES), 824131826Sharti S(REJECT_INCOMING_CALL), 825131826Sharti S(SET_CONNECTION_ATTRIBUTES), 826131826Sharti S(WAIT_ON_INCOMING_CALL), 827131826Sharti S(SET_CONNECTION_ATTRIBUTES_X), 828131826Sharti S(QUERY_CONNECTION_ATTRIBUTES_X), 829131826Sharti S(QUERY_STATE), 830131826Sharti#undef S 831131826Sharti}; 832131826Sharti#endif 833131826Sharti 834131826Sharti/* 835131826Sharti * Signal from user - map this to our internal signals and queue 836131826Sharti * the mapped signal. 837131826Sharti */ 838131826Shartiint 839131826Sharticc_user_signal(struct ccuser *user, enum atmop sig, struct uni_msg *msg) 840131826Sharti{ 841131826Sharti size_t len = uni_msg_len(msg); 842131826Sharti int err = EINVAL; 843131826Sharti 844131826Sharti if (user->cc->log & CCLOG_USER_SIG) 845131826Sharti cc_user_log(user, "signal %s to user", op_names[sig]); 846131826Sharti 847131826Sharti if ((u_int)sig > ATMOP_QUERY_STATE) 848131826Sharti goto bad_signal; 849131826Sharti 850131826Sharti switch (sig) { 851131826Sharti 852131826Sharti case ATMOP_ABORT_CONNECTION: 853131826Sharti if (len != sizeof(struct atm_abort_connection)) 854131826Sharti goto bad_len; 855131826Sharti err = cc_user_sig_msg(user, USER_SIG_ABORT_CONNECTION, msg); 856131826Sharti break; 857131826Sharti 858131826Sharti case ATMOP_ACCEPT_INCOMING_CALL: 859131826Sharti if (len != sizeof(struct atm_accept_incoming_call)) 860131826Sharti goto bad_len; 861131826Sharti err = cc_user_sig_msg(user, USER_SIG_ACCEPT_INCOMING, msg); 862131826Sharti break; 863131826Sharti 864131826Sharti case ATMOP_ADD_PARTY: 865131826Sharti if (len != sizeof(struct atm_add_party)) 866131826Sharti goto bad_len; 867131826Sharti err = cc_user_sig_msg(user, USER_SIG_ADD_PARTY, msg); 868131826Sharti break; 869131826Sharti 870131826Sharti case ATMOP_CALL_RELEASE: 871131826Sharti if (len != sizeof(struct atm_call_release)) 872131826Sharti goto bad_len; 873131826Sharti err = cc_user_sig_msg(user, USER_SIG_CALL_RELEASE, msg); 874131826Sharti break; 875131826Sharti 876131826Sharti case ATMOP_CONNECT_OUTGOING_CALL: 877131826Sharti if (len != sizeof(struct atm_connect_outgoing_call)) 878131826Sharti goto bad_len; 879131826Sharti err = cc_user_sig_msg(user, USER_SIG_CONNECT_OUTGOING, msg); 880131826Sharti break; 881131826Sharti 882131826Sharti case ATMOP_DROP_PARTY: 883131826Sharti if (len != sizeof(struct atm_drop_party)) 884131826Sharti goto bad_len; 885131826Sharti err = cc_user_sig_msg(user, USER_SIG_DROP_PARTY, msg); 886131826Sharti break; 887131826Sharti 888131826Sharti case ATMOP_GET_LOCAL_PORT_INFO: 889131826Sharti if (len != sizeof(struct atm_get_local_port_info)) 890131826Sharti goto bad_len; 891131826Sharti err = cc_user_sig_msg(user, USER_SIG_GET_LOCAL_PORT_INFO, msg); 892131826Sharti break; 893131826Sharti 894131826Sharti case ATMOP_PREPARE_INCOMING_CALL: 895131826Sharti if (len != sizeof(struct atm_prepare_incoming_call)) 896131826Sharti goto bad_len; 897131826Sharti err = cc_user_sig_msg(user, USER_SIG_PREPARE_INCOMING, msg); 898131826Sharti break; 899131826Sharti 900131826Sharti case ATMOP_PREPARE_OUTGOING_CALL: 901131826Sharti if (len != 0) 902131826Sharti goto bad_len; 903131826Sharti uni_msg_destroy(msg); 904131826Sharti err = cc_user_sig(user, USER_SIG_PREPARE_OUTGOING, NULL, 0); 905131826Sharti break; 906131826Sharti 907131826Sharti case ATMOP_QUERY_CONNECTION_ATTRIBUTES: 908131826Sharti if (len != sizeof(struct atm_query_connection_attributes)) 909131826Sharti goto bad_len; 910131826Sharti err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR, msg); 911131826Sharti break; 912131826Sharti 913131826Sharti case ATMOP_REJECT_INCOMING_CALL: 914131826Sharti if (len != sizeof(struct atm_reject_incoming_call)) 915131826Sharti goto bad_len; 916131826Sharti err = cc_user_sig_msg(user, USER_SIG_REJECT_INCOMING, msg); 917131826Sharti break; 918131826Sharti 919131826Sharti case ATMOP_SET_CONNECTION_ATTRIBUTES: 920131826Sharti if (len < sizeof(struct atm_set_connection_attributes)) 921131826Sharti goto bad_len; 922131826Sharti err = cc_user_sig_msg(user, USER_SIG_SET_ATTR, msg); 923131826Sharti break; 924131826Sharti 925131826Sharti case ATMOP_WAIT_ON_INCOMING_CALL: 926131826Sharti if (len != 0) 927131826Sharti goto bad_len; 928131826Sharti uni_msg_destroy(msg); 929131826Sharti err = cc_user_sig(user, USER_SIG_WAIT_ON_INCOMING, NULL, 0); 930131826Sharti break; 931131826Sharti 932131826Sharti case ATMOP_QUERY_CONNECTION_ATTRIBUTES_X: 933131826Sharti if (len < sizeof(struct atm_set_connection_attributes_x) || 934131826Sharti len != offsetof(struct atm_set_connection_attributes_x, 935131826Sharti attr) + uni_msg_rptr(msg, 936131826Sharti struct atm_set_connection_attributes_x *)->count * 937131826Sharti sizeof(uint32_t)) 938131826Sharti goto bad_len; 939131826Sharti err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR_X, msg); 940131826Sharti break; 941131826Sharti 942131826Sharti case ATMOP_SET_CONNECTION_ATTRIBUTES_X: 943131826Sharti if (len < sizeof(struct atm_set_connection_attributes_x)) 944131826Sharti goto bad_len; 945131826Sharti err = cc_user_sig_msg(user, USER_SIG_SET_ATTR_X, msg); 946131826Sharti break; 947131826Sharti 948131826Sharti case ATMOP_QUERY_STATE: 949131826Sharti if (len != 0) 950131826Sharti goto bad_len; 951131826Sharti uni_msg_destroy(msg); 952131826Sharti err = cc_user_sig(user, USER_SIG_QUERY_STATE, NULL, 0); 953131826Sharti break; 954131826Sharti 955131826Sharti case ATMOP_RESP: 956131826Sharti case ATMOP_ADD_PARTY_REJECT: 957131826Sharti case ATMOP_ADD_PARTY_SUCCESS: 958131826Sharti case ATMOP_ARRIVAL_OF_INCOMING_CALL: 959131826Sharti case ATMOP_P2MP_CALL_ACTIVE: 960131826Sharti case ATMOP_P2P_CALL_ACTIVE: 961131826Sharti bad_signal: 962131826Sharti /* bad signal */ 963131826Sharti if (user->cc->log & CCLOG_USER_SIG) 964131826Sharti cc_user_log(user, "bad signal %u", sig); 965131826Sharti cc_user_err(user, ATMERR_BAD_OP); 966131826Sharti uni_msg_destroy(msg); 967131826Sharti break; 968131826Sharti } 969131826Sharti return (err); 970131826Sharti 971131826Sharti bad_len: 972131826Sharti /* bad argument length */ 973131826Sharti if (user->cc->log & CCLOG_USER_SIG) 974131826Sharti cc_user_log(user, "signal %s had bad len=%zu", 975131826Sharti op_names[sig], len); 976131826Sharti cc_user_err(user, ATMERR_BAD_ARGS); 977131826Sharti uni_msg_destroy(msg); 978131826Sharti return (EINVAL); 979131826Sharti} 980131826Sharti 981131826Sharti/* 982131826Sharti * Send active signal to user 983131826Sharti */ 984131826Shartistatic void 985131826Sharticc_user_active(struct ccuser *user) 986131826Sharti{ 987131826Sharti struct ccconn *conn = TAILQ_FIRST(&user->connq); 988131826Sharti 989131826Sharti set_state(user, USER_ACTIVE); 990131826Sharti if (conn->bearer.cfg == UNI_BEARER_P2P) { 991131826Sharti struct atm_p2p_call_active *act; 992131826Sharti 993131826Sharti user->config = USER_P2P; 994131826Sharti act = CCZALLOC(sizeof(*act)); 995131826Sharti if (act == NULL) 996131826Sharti return; 997131826Sharti act->connid = conn->connid; 998131826Sharti cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, act, sizeof(*act)); 999131826Sharti CCFREE(act); 1000131826Sharti } else { 1001131826Sharti struct atm_p2mp_call_active *act; 1002131826Sharti 1003131826Sharti user->config = USER_ROOT; 1004131826Sharti act = CCZALLOC(sizeof(*act)); 1005131826Sharti if (act == NULL) 1006131826Sharti return; 1007131826Sharti act->connid = conn->connid; 1008131826Sharti cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, act, sizeof(*act)); 1009131826Sharti CCFREE(act); 1010131826Sharti } 1011131826Sharti} 1012131826Sharti 1013131826Sharti/* 1014131826Sharti* Handle a signal to this user 1015131826Sharti*/ 1016131826Shartivoid 1017131826Sharticc_user_sig_handle(struct ccuser *user, enum user_sig sig, 1018131826Sharti void *arg, u_int arg2) 1019131826Sharti{ 1020131826Sharti 1021131826Sharti if (user->cc->log & CCLOG_USER_SIG) 1022131826Sharti cc_user_log(user, "signal %s to user state %s", 1023131826Sharti cc_user_sigtab[sig], stab[user->state]); 1024131826Sharti 1025131826Sharti switch (sig) { 1026131826Sharti 1027131826Sharti 1028131826Sharti case USER_SIG_PREPARE_OUTGOING: 1029131826Sharti { 1030131826Sharti /* 1031131826Sharti * Here we create a connection for the call we soon will make. 1032131826Sharti * We put this call on the list of orphaned connections, 1033131826Sharti * because we don't know yet, which port will get the 1034131826Sharti * connection. It is assigned, when the user issues the call 1035131826Sharti * to connect. 1036131826Sharti */ 1037131826Sharti struct ccconn *conn; 1038131826Sharti 1039131826Sharti if (user->state != USER_NULL) { 1040131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1041131826Sharti goto bad_state; 1042131826Sharti } 1043131826Sharti conn = cc_conn_create(user->cc); 1044131826Sharti if (conn == NULL) { 1045131826Sharti cc_user_err(user, ATMERR_NOMEM); 1046131826Sharti return; 1047131826Sharti } 1048131826Sharti set_state(user, USER_OUT_PREPARING); 1049131826Sharti cc_conn_set_state(conn, CONN_OUT_PREPARING); 1050131826Sharti conn->blli_selector = 1; 1051131826Sharti cc_connect_to_user(conn, user); 1052131826Sharti 1053131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1054131826Sharti return; 1055131826Sharti } 1056131826Sharti 1057131826Sharti 1058131826Sharti case USER_SIG_CONNECT_OUTGOING: 1059131826Sharti { 1060131826Sharti /* 1061131826Sharti * Request to connect that call 1062131826Sharti * 1063131826Sharti * Here we assign the connection to a port. 1064131826Sharti */ 1065131826Sharti struct uni_msg *msg = arg; 1066131826Sharti struct atm_connect_outgoing_call *req = uni_msg_rptr(msg, 1067131826Sharti struct atm_connect_outgoing_call *); 1068131826Sharti struct ccdata *priv = user->cc; 1069131826Sharti struct ccport *port; 1070131826Sharti struct ccaddr *addr; 1071131826Sharti struct ccconn *conn = TAILQ_FIRST(&user->connq); 1072131826Sharti 1073131826Sharti if (user->state != USER_OUT_PREPARING) { 1074131826Sharti uni_msg_destroy(msg); 1075131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1076131826Sharti goto bad_state; 1077131826Sharti } 1078131826Sharti if (!IE_ISPRESENT(req->called)) { 1079131826Sharti uni_msg_destroy(msg); 1080131826Sharti cc_user_err(user, ATMERR_BAD_ARGS); 1081131826Sharti return; 1082131826Sharti } 1083131826Sharti CCASSERT(conn->port == NULL, ("connection still on port")); 1084131826Sharti 1085131826Sharti if (TAILQ_EMPTY(&priv->port_list)) { 1086131826Sharti /* 1087131826Sharti * We have no ports - reject 1088131826Sharti */ 1089131826Sharti uni_msg_destroy(msg); 1090131826Sharti cc_user_err(user, ATMERR_BAD_PORT); 1091131826Sharti return; 1092131826Sharti } 1093131826Sharti 1094131826Sharti /* 1095131826Sharti * Find the correct port 1096131826Sharti * Routing of outgoing calls goes to the lowest numbered port 1097131826Sharti * with a matching address or, if no address match is found to 1098131826Sharti * the lowest numbered port. 1099131826Sharti */ 1100131826Sharti TAILQ_FOREACH(port, &priv->port_list, node_link) 1101131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) 1102131826Sharti if (addr_matches(addr, conn)) 1103131826Sharti break; 1104131826Sharti 1105131826Sharti if (port == NULL) 1106131826Sharti port = TAILQ_FIRST(&priv->port_list); 1107131826Sharti 1108131826Sharti cc_conn_ins_port(conn, port); 1109131826Sharti conn->called = req->called; 1110131826Sharti uni_msg_destroy(msg); 1111131826Sharti 1112131826Sharti /* 1113131826Sharti * Now move the state 1114131826Sharti */ 1115131826Sharti set_state(user, USER_OUT_WAIT_OK); 1116131826Sharti cc_conn_sig(conn, CONN_SIG_CONNECT_OUTGOING, NULL); 1117131826Sharti 1118131826Sharti return; 1119131826Sharti } 1120131826Sharti 1121131826Sharti 1122131826Sharti case USER_SIG_CONNECT_OUTGOING_ERR: 1123131826Sharti switch (user->state) { 1124131826Sharti 1125131826Sharti case USER_OUT_WAIT_OK: 1126131826Sharti set_state(user, USER_OUT_PREPARING); 1127131826Sharti cc_user_err(user, arg2); 1128131826Sharti break; 1129131826Sharti 1130131826Sharti case USER_REL_WAIT_CONN: 1131131826Sharti { 1132131826Sharti struct ccconn *conn; 1133131826Sharti 1134131826Sharti conn = TAILQ_FIRST(&user->connq); 1135131826Sharti if (conn != NULL) { 1136131826Sharti cc_disconnect_from_user(conn); 1137131826Sharti cc_conn_destroy(conn); 1138131826Sharti } 1139131826Sharti 1140131826Sharti cc_user_reset(user); 1141131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1142131826Sharti break; 1143131826Sharti } 1144131826Sharti 1145131826Sharti default: 1146131826Sharti goto bad_state; 1147131826Sharti } 1148131826Sharti return; 1149131826Sharti 1150131826Sharti 1151131826Sharti case USER_SIG_CONNECT_OUTGOING_OK: 1152131826Sharti switch (user->state) { 1153131826Sharti 1154131826Sharti case USER_OUT_WAIT_OK: 1155131826Sharti set_state(user, USER_OUT_WAIT_CONF); 1156131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1157131826Sharti break; 1158131826Sharti 1159131826Sharti case USER_REL_WAIT_CONN: 1160131826Sharti set_state(user, USER_REL_WAIT_SCONF); 1161131826Sharti break; 1162131826Sharti 1163131826Sharti default: 1164131826Sharti goto bad_state; 1165131826Sharti } 1166131826Sharti return; 1167131826Sharti 1168131826Sharti 1169131826Sharti case USER_SIG_SETUP_CONFIRM: 1170131826Sharti /* 1171131826Sharti * SETUP.confirm from UNI stack. 1172131826Sharti */ 1173131826Sharti switch (user->state) { 1174131826Sharti 1175131826Sharti case USER_OUT_WAIT_CONF: 1176131826Sharti cc_user_active(user); 1177131826Sharti break; 1178131826Sharti 1179131826Sharti case USER_REL_WAIT_SCONF: 1180131826Sharti /* now try to release */ 1181131826Sharti set_state(user, USER_REL_WAIT_CONF); 1182131826Sharti cc_conn_sig(TAILQ_FIRST(&user->connq), 1183131826Sharti CONN_SIG_RELEASE, NULL); 1184131826Sharti break; 1185131826Sharti 1186131826Sharti default: 1187131826Sharti goto bad_state; 1188131826Sharti } 1189131826Sharti return; 1190131826Sharti 1191131826Sharti 1192131826Sharti case USER_SIG_PREPARE_INCOMING: 1193131826Sharti { 1194131826Sharti struct uni_msg *msg = arg; 1195131826Sharti struct ccuser *ptr; 1196131826Sharti struct atm_prepare_incoming_call *prep = uni_msg_rptr(msg, 1197131826Sharti struct atm_prepare_incoming_call *); 1198131826Sharti 1199131826Sharti if (user->state != USER_NULL) { 1200131826Sharti uni_msg_destroy(msg); 1201131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1202131826Sharti goto bad_state; 1203131826Sharti } 1204131826Sharti 1205131826Sharti /* 1206131826Sharti * Check the SAP 1207131826Sharti */ 1208131826Sharti if (unisve_check_sap(&prep->sap) != UNISVE_OK) { 1209131826Sharti uni_msg_destroy(msg); 1210131826Sharti cc_user_err(user, ATMERR_BAD_SAP); 1211131826Sharti return; 1212131826Sharti } 1213131826Sharti 1214131826Sharti /* 1215131826Sharti * Loop through all incoming calls and check whether there 1216131826Sharti * is an overlap in SAP space. 1217131826Sharti */ 1218131826Sharti LIST_FOREACH(ptr, &user->cc->user_list, node_link) { 1219131826Sharti if (check_overlap(ptr, &prep->sap)) { 1220131826Sharti uni_msg_destroy(msg); 1221131826Sharti cc_user_err(user, ATMERR_OVERLAP); 1222131826Sharti return; 1223131826Sharti } 1224131826Sharti } 1225131826Sharti 1226131826Sharti /* 1227131826Sharti * Save info and set state 1228131826Sharti */ 1229131826Sharti user->sap = CCZALLOC(sizeof(struct uni_sap)); 1230131826Sharti if (user->sap == NULL) { 1231131826Sharti uni_msg_destroy(msg); 1232131826Sharti cc_user_err(user, ATMERR_NOMEM); 1233131826Sharti return; 1234131826Sharti } 1235131826Sharti *user->sap = prep->sap; 1236131826Sharti user->queue_max = prep->queue_size; 1237131826Sharti user->queue_act = 0; 1238131826Sharti uni_msg_destroy(msg); 1239131826Sharti 1240131826Sharti set_state(user, USER_IN_PREPARING); 1241131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1242131826Sharti 1243131826Sharti return; 1244131826Sharti } 1245131826Sharti 1246131826Sharti 1247131826Sharti case USER_SIG_WAIT_ON_INCOMING: 1248131826Sharti if (user->state != USER_IN_PREPARING) { 1249131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1250131826Sharti goto bad_state; 1251131826Sharti } 1252131826Sharti 1253131826Sharti set_state(user, USER_IN_WAITING); 1254131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1255131826Sharti return; 1256131826Sharti 1257131826Sharti 1258131826Sharti case USER_SIG_SETUP_IND: 1259131826Sharti /* 1260131826Sharti * New connection queued up in the queue. If this is the 1261131826Sharti * first one, inform the application of the arrival. 1262131826Sharti */ 1263131826Sharti switch (user->state) { 1264131826Sharti 1265131826Sharti case USER_IN_WAITING: 1266131826Sharti do_arrival(user); 1267131826Sharti break; 1268131826Sharti 1269131826Sharti case USER_IN_ARRIVED: 1270131826Sharti case USER_IN_WAIT_REJ: 1271131826Sharti case USER_IN_WAIT_ACC: 1272131826Sharti break; 1273131826Sharti 1274131826Sharti default: 1275131826Sharti goto bad_state; 1276131826Sharti } 1277131826Sharti return; 1278131826Sharti 1279131826Sharti 1280131826Sharti case USER_SIG_REJECT_INCOMING: 1281131826Sharti { 1282131826Sharti /* 1283131826Sharti * User rejects call. This is done on the OLD user 1284131826Sharti * (i.e. the one sending the arrival). 1285131826Sharti */ 1286131826Sharti struct uni_msg *msg = arg; 1287131826Sharti struct atm_reject_incoming_call *rej = uni_msg_rptr(msg, 1288131826Sharti struct atm_reject_incoming_call *); 1289131826Sharti struct ccconn *conn = TAILQ_FIRST(&user->connq); 1290131826Sharti 1291131826Sharti if (user->state != USER_IN_ARRIVED) { 1292131826Sharti uni_msg_destroy(msg); 1293131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1294131826Sharti goto bad_state; 1295131826Sharti } 1296131826Sharti if (user->aborted) { 1297131826Sharti /* connection has disappeared. Send an ok 1298131826Sharti * to the user and lock whether there is another 1299131826Sharti * connection at this endpoint */ 1300133492Sharti uni_msg_destroy(msg); 1301131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1302131826Sharti 1303131826Sharti set_state(user, USER_IN_WAITING); 1304131826Sharti do_arrival(user); 1305131826Sharti return; 1306131826Sharti } 1307131826Sharti conn->cause[0] = rej->cause; 1308131826Sharti memset(&conn->cause[1], 0, sizeof(conn->cause[1])); 1309131826Sharti uni_msg_destroy(msg); 1310131826Sharti 1311131826Sharti set_state(user, USER_IN_WAIT_REJ); 1312131826Sharti cc_conn_sig(conn, CONN_SIG_REJECT, NULL); 1313131826Sharti 1314131826Sharti return; 1315131826Sharti } 1316131826Sharti 1317131826Sharti 1318131826Sharti case USER_SIG_REJECT_OK: 1319131826Sharti if (user->state != USER_IN_WAIT_REJ) 1320131826Sharti goto bad_state; 1321131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1322131826Sharti 1323131826Sharti set_state(user, USER_IN_WAITING); 1324131826Sharti do_arrival(user); 1325131826Sharti return; 1326131826Sharti 1327131826Sharti 1328131826Sharti case USER_SIG_REJECT_ERR: 1329131826Sharti if (user->state != USER_IN_WAIT_REJ) 1330131826Sharti goto bad_state; 1331131826Sharti cc_user_err(user, arg2); 1332131826Sharti 1333131826Sharti if (arg == NULL) 1334131826Sharti set_state(user, USER_IN_ARRIVED); 1335131826Sharti else { 1336131826Sharti set_state(user, USER_IN_WAITING); 1337131826Sharti do_arrival(user); 1338131826Sharti } 1339131826Sharti return; 1340131826Sharti 1341131826Sharti 1342131826Sharti case USER_SIG_ACCEPT_INCOMING: 1343131826Sharti { 1344131826Sharti /* 1345131826Sharti * User accepts call. This is done on the OLD user (i.e. the one 1346131826Sharti * sending the arrival), the message contains a pointer to the 1347131826Sharti * new endpoint. 1348131826Sharti */ 1349131826Sharti struct uni_msg *msg = arg; 1350131826Sharti struct atm_accept_incoming_call *acc = 1351131826Sharti uni_msg_rptr(msg, struct atm_accept_incoming_call *); 1352131826Sharti struct ccuser *newep; 1353131826Sharti 1354131826Sharti if (user->state != USER_IN_ARRIVED) { 1355131826Sharti uni_msg_destroy(msg); 1356131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1357131826Sharti return; 1358131826Sharti } 1359131826Sharti if (user->aborted) { 1360131826Sharti /* connection has disappeared. Send an error 1361131826Sharti * to the user and lock whether there is another 1362131826Sharti * connection at this endpoint */ 1363133492Sharti uni_msg_destroy(msg); 1364131826Sharti cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1365131826Sharti 1366131826Sharti set_state(user, USER_IN_WAITING); 1367131826Sharti do_arrival(user); 1368131826Sharti return; 1369131826Sharti } 1370131826Sharti acc->newep[sizeof(acc->newep) - 1] = '\0'; 1371131826Sharti 1372131826Sharti LIST_FOREACH(newep, &user->cc->user_list, node_link) 1373131826Sharti if (strcmp(acc->newep, newep->name) == 0) 1374131826Sharti break; 1375133492Sharti uni_msg_destroy(msg); 1376131826Sharti 1377131826Sharti if (newep == NULL) { 1378131826Sharti cc_user_err(user, ATMERR_BAD_ENDPOINT); 1379131826Sharti return; 1380131826Sharti } 1381131826Sharti 1382131826Sharti if (newep->state != USER_NULL || newep->accepted != NULL) { 1383131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1384131826Sharti return; 1385131826Sharti } 1386131826Sharti 1387131826Sharti set_state(user, USER_IN_WAIT_ACC); 1388131826Sharti cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep); 1389131826Sharti 1390131826Sharti return; 1391131826Sharti } 1392131826Sharti 1393131826Sharti 1394131826Sharti case USER_SIG_ACCEPT_OK: 1395131826Sharti if (user->state != USER_IN_WAIT_ACC) 1396131826Sharti goto bad_state; 1397131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1398131826Sharti 1399131826Sharti set_state(user, USER_IN_WAITING); 1400131826Sharti do_arrival(user); 1401131826Sharti return; 1402131826Sharti 1403131826Sharti 1404131826Sharti case USER_SIG_ACCEPT_ERR: 1405131826Sharti if (user->state != USER_IN_WAIT_ACC) 1406131826Sharti goto bad_state; 1407131826Sharti cc_user_err(user, arg2); 1408131826Sharti 1409131826Sharti if (arg == NULL) { 1410131826Sharti /* arg used as flag! */ 1411131826Sharti set_state(user, USER_IN_ARRIVED); 1412131826Sharti } else { 1413131826Sharti set_state(user, USER_IN_WAITING); 1414131826Sharti do_arrival(user); 1415131826Sharti } 1416131826Sharti return; 1417131826Sharti 1418131826Sharti 1419131826Sharti case USER_SIG_ACCEPTING: 1420131826Sharti if (user->state != USER_NULL) 1421131826Sharti goto bad_state; 1422131826Sharti set_state(user, USER_IN_ACCEPTING); 1423131826Sharti return; 1424131826Sharti 1425131826Sharti 1426131826Sharti case USER_SIG_SETUP_COMPL: 1427131826Sharti { 1428131826Sharti struct ccconn *conn = TAILQ_FIRST(&user->connq); 1429131826Sharti 1430131826Sharti if (user->state != USER_IN_ACCEPTING) 1431131826Sharti goto bad_state; 1432131826Sharti 1433131826Sharti user->state = USER_ACTIVE; 1434131826Sharti if (conn->bearer.cfg == UNI_BEARER_P2P) { 1435131826Sharti struct atm_p2p_call_active *act; 1436131826Sharti 1437131826Sharti user->config = USER_P2P; 1438131826Sharti act = CCZALLOC(sizeof(*act)); 1439131826Sharti if (act == NULL) 1440131826Sharti return; 1441131826Sharti act->connid = conn->connid; 1442131826Sharti cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, 1443131826Sharti act, sizeof(*act)); 1444131826Sharti CCFREE(act); 1445131826Sharti } else { 1446131826Sharti struct atm_p2mp_call_active *act; 1447131826Sharti 1448131826Sharti user->config = USER_LEAF; 1449131826Sharti act = CCZALLOC(sizeof(*act)); 1450131826Sharti if (act == NULL) 1451131826Sharti return; 1452131826Sharti act->connid = conn->connid; 1453131826Sharti cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, 1454131826Sharti act, sizeof(*act)); 1455131826Sharti CCFREE(act); 1456131826Sharti } 1457131826Sharti return; 1458131826Sharti } 1459131826Sharti 1460131826Sharti 1461131826Sharti case USER_SIG_CALL_RELEASE: 1462131826Sharti { 1463131826Sharti struct uni_msg *msg = arg; 1464131826Sharti struct atm_call_release *api = uni_msg_rptr(msg, 1465131826Sharti struct atm_call_release *); 1466131826Sharti struct ccconn *conn; 1467131826Sharti 1468131826Sharti conn = TAILQ_FIRST(&user->connq); 1469131826Sharti switch (user->state) { 1470131826Sharti 1471131826Sharti case USER_OUT_WAIT_OK: /* U2/A3 */ 1472131826Sharti /* wait for CONN_OK first */ 1473131826Sharti conn->cause[0] = api->cause[0]; 1474131826Sharti conn->cause[1] = api->cause[1]; 1475131826Sharti set_state(user, USER_REL_WAIT_CONN); 1476131826Sharti break; 1477131826Sharti 1478131826Sharti case USER_OUT_WAIT_CONF: /* U3/A3 */ 1479131826Sharti /* wait for SETUP.confirm first */ 1480131826Sharti conn->cause[0] = api->cause[0]; 1481131826Sharti conn->cause[1] = api->cause[1]; 1482131826Sharti set_state(user, USER_REL_WAIT_SCONF); 1483131826Sharti break; 1484131826Sharti 1485131826Sharti case USER_IN_ACCEPTING: /* U11/A7 */ 1486131826Sharti conn->cause[0] = api->cause[0]; 1487131826Sharti conn->cause[1] = api->cause[1]; 1488131826Sharti set_state(user, USER_REL_WAIT_SCOMP); 1489131826Sharti cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); 1490131826Sharti break; 1491131826Sharti 1492131826Sharti case USER_ACTIVE: /* U4/A8,A9,A10 */ 1493131826Sharti conn->cause[0] = api->cause[0]; 1494131826Sharti conn->cause[1] = api->cause[1]; 1495131826Sharti set_state(user, USER_REL_WAIT); 1496131826Sharti cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); 1497131826Sharti break; 1498131826Sharti 1499131826Sharti default: 1500131826Sharti uni_msg_destroy(msg); 1501131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1502131826Sharti goto bad_state; 1503131826Sharti } 1504131826Sharti uni_msg_destroy(msg); 1505131826Sharti return; 1506131826Sharti } 1507131826Sharti 1508131826Sharti 1509131826Sharti case USER_SIG_RELEASE_CONFIRM: 1510131826Sharti { 1511131826Sharti struct atm_call_release *ind; 1512131826Sharti 1513131826Sharti switch (user->state) { 1514131826Sharti 1515131826Sharti case USER_OUT_WAIT_CONF: /* U3/A3 */ 1516131826Sharti case USER_ACTIVE: /* U4/A8,A9,A10 */ 1517131826Sharti cc_user_reset(user); 1518131826Sharti break; 1519131826Sharti 1520131826Sharti case USER_REL_WAIT: /* U5 /A8,A9,A10 */ 1521131826Sharti case USER_REL_WAIT_SCOMP: /* U12/A7 */ 1522131826Sharti case USER_REL_WAIT_SCONF: /* U13/A3 */ 1523131826Sharti case USER_REL_WAIT_CONF: /* U14/A3 */ 1524131826Sharti cc_user_reset(user); 1525131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1526131826Sharti return; 1527131826Sharti 1528131826Sharti case USER_IN_ACCEPTING: /* U11/A7 */ 1529131826Sharti cc_user_reset(user); 1530131826Sharti break; 1531131826Sharti 1532131826Sharti default: 1533131826Sharti goto bad_state; 1534131826Sharti } 1535131826Sharti 1536131826Sharti ind = CCZALLOC(sizeof(*ind)); 1537131826Sharti if (ind == NULL) 1538131826Sharti return; 1539131826Sharti memcpy(ind->cause, user->cause, sizeof(ind->cause)); 1540131826Sharti cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind)); 1541131826Sharti CCFREE(ind); 1542131826Sharti return; 1543131826Sharti } 1544131826Sharti 1545131826Sharti 1546131826Sharti case USER_SIG_RELEASE_ERR: 1547131826Sharti switch (user->state) { 1548131826Sharti 1549131826Sharti case USER_REL_WAIT: /* U5/A8,A9,A10 */ 1550131826Sharti set_state(user, USER_ACTIVE); 1551131826Sharti cc_user_err(user, ATM_MKUNIERR(arg2)); 1552131826Sharti break; 1553131826Sharti 1554131826Sharti case USER_REL_WAIT_CONF: /* U14/A3 */ 1555131826Sharti cc_user_err(user, ATM_MKUNIERR(arg2)); 1556131826Sharti cc_user_active(user); 1557131826Sharti break; 1558131826Sharti 1559131826Sharti case USER_REL_WAIT_SCOMP: /* U12/A7 */ 1560131826Sharti set_state(user, USER_IN_ACCEPTING); 1561131826Sharti cc_user_err(user, ATM_MKUNIERR(arg2)); 1562131826Sharti break; 1563131826Sharti 1564131826Sharti default: 1565131826Sharti goto bad_state; 1566131826Sharti } 1567131826Sharti return; 1568131826Sharti 1569131826Sharti 1570131826Sharti case USER_SIG_ADD_PARTY: 1571131826Sharti { 1572131826Sharti struct uni_msg *msg = arg; 1573131826Sharti struct atm_add_party *add = uni_msg_rptr(msg, 1574131826Sharti struct atm_add_party *); 1575131826Sharti struct ccconn *conn; 1576131826Sharti 1577131826Sharti if (user->state != USER_ACTIVE || user->config != USER_ROOT) { 1578131826Sharti uni_msg_destroy(msg); 1579131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1580131826Sharti return; 1581131826Sharti } 1582131826Sharti 1583131826Sharti if (add->leaf_ident == 0 || add->leaf_ident >= 32786) { 1584131826Sharti uni_msg_destroy(msg); 1585131826Sharti cc_user_err(user, ATMERR_BAD_LEAF_IDENT); 1586131826Sharti return; 1587131826Sharti } 1588131826Sharti 1589131826Sharti conn = TAILQ_FIRST(&user->connq); 1590131826Sharti conn->called = add->called; 1591131826Sharti 1592131826Sharti cc_conn_sig(conn, CONN_SIG_ADD_PARTY, 1593131826Sharti (void *)(uintptr_t)add->leaf_ident); 1594131826Sharti 1595131826Sharti uni_msg_destroy(msg); 1596131826Sharti return; 1597131826Sharti } 1598131826Sharti 1599131826Sharti 1600131826Sharti case USER_SIG_ADD_PARTY_ERR: 1601131826Sharti if (user->state != USER_ACTIVE) 1602131826Sharti goto bad_state; 1603131826Sharti cc_user_err(user, arg2); 1604131826Sharti return; 1605131826Sharti 1606131826Sharti 1607131826Sharti case USER_SIG_ADD_PARTY_OK: 1608131826Sharti if (user->state != USER_ACTIVE) 1609131826Sharti goto bad_state; 1610131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1611131826Sharti return; 1612131826Sharti 1613131826Sharti 1614131826Sharti case USER_SIG_ADD_PARTY_ACK: 1615131826Sharti { 1616131826Sharti u_int leaf_ident = arg2; 1617131826Sharti struct atm_add_party_success *succ; 1618131826Sharti 1619131826Sharti if (user->state != USER_ACTIVE) 1620131826Sharti goto bad_state; 1621131826Sharti 1622131826Sharti succ = CCZALLOC(sizeof(*succ)); 1623131826Sharti if (succ == NULL) 1624131826Sharti return; 1625131826Sharti 1626131826Sharti succ->leaf_ident = leaf_ident; 1627131826Sharti cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS, 1628131826Sharti succ, sizeof(*succ)); 1629131826Sharti 1630131826Sharti CCFREE(succ); 1631131826Sharti return; 1632131826Sharti } 1633131826Sharti 1634131826Sharti 1635131826Sharti case USER_SIG_ADD_PARTY_REJ: 1636131826Sharti { 1637131826Sharti u_int leaf_ident = arg2; 1638131826Sharti struct atm_add_party_reject *reject; 1639131826Sharti 1640131826Sharti if (user->state != USER_ACTIVE) 1641131826Sharti goto bad_state; 1642131826Sharti 1643131826Sharti reject = CCZALLOC(sizeof(*reject)); 1644131826Sharti if (reject == NULL) 1645131826Sharti return; 1646131826Sharti 1647131826Sharti reject->leaf_ident = leaf_ident; 1648131826Sharti reject->cause = user->cause[0]; 1649131826Sharti cc_user_send(user, ATMOP_ADD_PARTY_REJECT, 1650131826Sharti reject, sizeof(*reject)); 1651131826Sharti 1652131826Sharti CCFREE(reject); 1653131826Sharti return; 1654131826Sharti } 1655131826Sharti 1656131826Sharti 1657131826Sharti case USER_SIG_DROP_PARTY: 1658131826Sharti { 1659131826Sharti struct uni_msg *msg = arg; 1660131826Sharti struct atm_drop_party *drop = uni_msg_rptr(msg, 1661131826Sharti struct atm_drop_party *); 1662131826Sharti struct ccconn *conn; 1663131826Sharti 1664131826Sharti if (user->state != USER_ACTIVE || user->config != USER_ROOT) { 1665131826Sharti uni_msg_destroy(msg); 1666131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1667131826Sharti return; 1668131826Sharti } 1669131826Sharti 1670131826Sharti if (drop->leaf_ident >= 32786) { 1671131826Sharti uni_msg_destroy(msg); 1672131826Sharti cc_user_err(user, ATMERR_BAD_LEAF_IDENT); 1673131826Sharti return; 1674131826Sharti } 1675131826Sharti 1676131826Sharti conn = TAILQ_FIRST(&user->connq); 1677131826Sharti conn->cause[0] = drop->cause; 1678131826Sharti memset(&conn->cause[1], 0, sizeof(conn->cause[1])); 1679131826Sharti 1680131826Sharti cc_conn_sig(conn, CONN_SIG_DROP_PARTY, 1681131826Sharti (void *)(uintptr_t)drop->leaf_ident); 1682131826Sharti 1683131826Sharti uni_msg_destroy(msg); 1684131826Sharti return; 1685131826Sharti } 1686131826Sharti 1687131826Sharti 1688131826Sharti case USER_SIG_DROP_PARTY_ERR: 1689131826Sharti if (user->state != USER_ACTIVE) 1690131826Sharti goto bad_state; 1691131826Sharti cc_user_err(user, arg2); 1692131826Sharti return; 1693131826Sharti 1694131826Sharti 1695131826Sharti case USER_SIG_DROP_PARTY_OK: 1696131826Sharti if (user->state != USER_ACTIVE) 1697131826Sharti goto bad_state; 1698131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1699131826Sharti return; 1700131826Sharti 1701131826Sharti 1702131826Sharti case USER_SIG_DROP_PARTY_IND: 1703131826Sharti { 1704131826Sharti u_int leaf_ident = arg2; 1705131826Sharti struct atm_drop_party *drop; 1706131826Sharti 1707131826Sharti if (user->state != USER_ACTIVE) 1708131826Sharti goto bad_state; 1709131826Sharti 1710131826Sharti drop = CCZALLOC(sizeof(*drop)); 1711131826Sharti if (drop == NULL) 1712131826Sharti return; 1713131826Sharti 1714131826Sharti drop->leaf_ident = leaf_ident; 1715131826Sharti drop->cause = user->cause[0]; 1716131826Sharti cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop)); 1717131826Sharti 1718131826Sharti CCFREE(drop); 1719131826Sharti return; 1720131826Sharti } 1721131826Sharti 1722131826Sharti 1723131826Sharti case USER_SIG_QUERY_ATTR: 1724131826Sharti { 1725131826Sharti struct uni_msg *msg = arg; 1726131826Sharti struct atm_query_connection_attributes *req; 1727131826Sharti struct ccconn *conn; 1728131826Sharti 1729131826Sharti if (user->aborted) { 1730131826Sharti cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1731131826Sharti uni_msg_destroy(msg); 1732131826Sharti return; 1733131826Sharti } 1734131826Sharti conn = cc_query_check(user); 1735131826Sharti if (conn == NULL) { 1736131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1737131826Sharti uni_msg_destroy(msg); 1738131826Sharti return; 1739131826Sharti } 1740131826Sharti req = uni_msg_rptr(msg, 1741131826Sharti struct atm_query_connection_attributes *); 1742131826Sharti cc_attr_query(user, conn, &req->attr, 1); 1743131826Sharti uni_msg_destroy(msg); 1744131826Sharti return; 1745131826Sharti } 1746131826Sharti 1747131826Sharti case USER_SIG_QUERY_ATTR_X: 1748131826Sharti { 1749131826Sharti struct uni_msg *msg = arg; 1750131826Sharti struct atm_query_connection_attributes_x *req; 1751131826Sharti struct ccconn *conn; 1752131826Sharti 1753131826Sharti conn = cc_query_check(user); 1754131826Sharti if (conn == NULL) { 1755131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1756131826Sharti uni_msg_destroy(msg); 1757131826Sharti return; 1758131826Sharti } 1759131826Sharti req = uni_msg_rptr(msg, 1760131826Sharti struct atm_query_connection_attributes_x *); 1761131826Sharti cc_attr_query(user, conn, req->attr, req->count); 1762131826Sharti uni_msg_destroy(msg); 1763131826Sharti return; 1764131826Sharti } 1765131826Sharti 1766131826Sharti case USER_SIG_SET_ATTR: 1767131826Sharti { 1768131826Sharti struct uni_msg *msg = arg; 1769131826Sharti struct atm_set_connection_attributes *req; 1770131826Sharti struct ccconn *conn; 1771131826Sharti 1772131826Sharti if (user->aborted) { 1773131826Sharti cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1774131826Sharti uni_msg_destroy(msg); 1775131826Sharti return; 1776131826Sharti } 1777131826Sharti conn = cc_set_check(user); 1778131826Sharti if (conn == NULL) { 1779131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1780131826Sharti uni_msg_destroy(msg); 1781131826Sharti return; 1782131826Sharti } 1783131826Sharti req = uni_msg_rptr(msg, struct atm_set_connection_attributes *); 1784131826Sharti cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1), 1785131826Sharti uni_msg_len(msg) - sizeof(*req)); 1786131826Sharti uni_msg_destroy(msg); 1787131826Sharti return; 1788131826Sharti } 1789131826Sharti 1790131826Sharti case USER_SIG_SET_ATTR_X: 1791131826Sharti { 1792131826Sharti struct uni_msg *msg = arg; 1793131826Sharti struct atm_set_connection_attributes_x *req; 1794131826Sharti struct ccconn *conn; 1795131826Sharti 1796131826Sharti conn = cc_set_check(user); 1797131826Sharti if (conn == NULL) { 1798131826Sharti cc_user_err(user, ATMERR_BAD_STATE); 1799131826Sharti uni_msg_destroy(msg); 1800131826Sharti return; 1801131826Sharti } 1802131826Sharti req = uni_msg_rptr(msg, 1803131826Sharti struct atm_set_connection_attributes_x *); 1804131826Sharti cc_attr_set(user, conn, req->attr, req->count, 1805131826Sharti (u_char *)req->attr + req->count * sizeof(req->attr[0]), 1806131826Sharti uni_msg_len(msg) - 1807131826Sharti offsetof(struct atm_set_connection_attributes_x, attr) - 1808131826Sharti req->count * sizeof(req->attr[0])); 1809131826Sharti uni_msg_destroy(msg); 1810131826Sharti return; 1811131826Sharti } 1812131826Sharti 1813131826Sharti case USER_SIG_QUERY_STATE: 1814131826Sharti { 1815131826Sharti struct atm_epstate state; 1816131826Sharti 1817131826Sharti strcpy(state.name, user->name); 1818131826Sharti switch (user->state) { 1819131826Sharti 1820131826Sharti case USER_NULL: 1821131826Sharti if (user->accepted != NULL) 1822131826Sharti state.state = ATM_A7; 1823131826Sharti else 1824131826Sharti state.state = ATM_A1; 1825131826Sharti break; 1826131826Sharti 1827131826Sharti case USER_OUT_PREPARING: 1828131826Sharti state.state = ATM_A2; 1829131826Sharti break; 1830131826Sharti 1831131826Sharti case USER_OUT_WAIT_OK: 1832131826Sharti case USER_OUT_WAIT_CONF: 1833131826Sharti case USER_REL_WAIT_SCONF: 1834131826Sharti case USER_REL_WAIT_CONF: 1835131826Sharti case USER_REL_WAIT_CONN: 1836131826Sharti state.state = ATM_A3; 1837131826Sharti break; 1838131826Sharti 1839131826Sharti case USER_ACTIVE: 1840131826Sharti case USER_REL_WAIT: 1841131826Sharti switch (user->config) { 1842131826Sharti 1843131826Sharti case USER_P2P: 1844131826Sharti state.state = ATM_A8; 1845131826Sharti break; 1846131826Sharti 1847131826Sharti case USER_ROOT: 1848131826Sharti state.state = ATM_A9; 1849131826Sharti break; 1850131826Sharti 1851131826Sharti case USER_LEAF: 1852131826Sharti state.state = ATM_A10; 1853131826Sharti break; 1854131826Sharti } 1855131826Sharti break; 1856131826Sharti 1857131826Sharti case USER_IN_PREPARING: 1858131826Sharti state.state = ATM_A4; 1859131826Sharti break; 1860131826Sharti 1861131826Sharti case USER_IN_WAITING: 1862131826Sharti state.state = ATM_A5; 1863131826Sharti break; 1864131826Sharti 1865131826Sharti case USER_IN_ARRIVED: 1866131826Sharti case USER_IN_WAIT_REJ: 1867131826Sharti case USER_IN_WAIT_ACC: 1868131826Sharti state.state = ATM_A6; 1869131826Sharti break; 1870131826Sharti 1871131826Sharti case USER_IN_ACCEPTING: 1872131826Sharti case USER_REL_WAIT_SCOMP: 1873131826Sharti state.state = ATM_A7; 1874131826Sharti break; 1875131826Sharti } 1876131826Sharti cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state)); 1877131826Sharti return; 1878131826Sharti } 1879131826Sharti 1880131826Sharti case USER_SIG_GET_LOCAL_PORT_INFO: 1881131826Sharti { 1882131826Sharti struct uni_msg *msg = arg; 1883131826Sharti struct atm_port_list *list; 1884131826Sharti size_t list_len; 1885131826Sharti 1886131826Sharti list = cc_get_local_port_info(user->cc, 1887131826Sharti uni_msg_rptr(msg, struct atm_get_local_port_info *)->port, 1888131826Sharti &list_len); 1889131826Sharti uni_msg_destroy(msg); 1890131826Sharti if (list == NULL) { 1891131826Sharti cc_user_err(user, ATMERR_NOMEM); 1892131826Sharti return; 1893131826Sharti } 1894131826Sharti cc_user_ok(user, ATMRESP_PORTS, list, list_len); 1895131826Sharti CCFREE(list); 1896131826Sharti return; 1897131826Sharti } 1898131826Sharti 1899131826Sharti case USER_SIG_ABORT_CONNECTION: 1900131826Sharti { 1901131826Sharti struct uni_msg *msg = arg; 1902131826Sharti struct atm_abort_connection *abo = uni_msg_rptr(msg, 1903131826Sharti struct atm_abort_connection *); 1904131826Sharti 1905131826Sharti cc_user_abort(user, &abo->cause); 1906131826Sharti uni_msg_destroy(msg); 1907131826Sharti cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1908131826Sharti return; 1909131826Sharti } 1910131826Sharti 1911131826Sharti } 1912131826Sharti if (user->cc->log & CCLOG_USER_SIG) 1913131826Sharti cc_user_log(user, "bad signal=%u in state=%u", 1914131826Sharti sig, user->state); 1915131826Sharti return; 1916131826Sharti 1917131826Sharti bad_state: 1918131826Sharti if (user->cc->log & CCLOG_USER_SIG) 1919131826Sharti cc_user_log(user, "bad state=%u for signal=%u", 1920131826Sharti user->state, sig); 1921131826Sharti return; 1922131826Sharti} 1923