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