cc_user.c revision 131826
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.2 2004/07/08 09:17:18 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 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1301 1302 set_state(user, USER_IN_WAITING); 1303 do_arrival(user); 1304 return; 1305 } 1306 conn->cause[0] = rej->cause; 1307 memset(&conn->cause[1], 0, sizeof(conn->cause[1])); 1308 uni_msg_destroy(msg); 1309 1310 set_state(user, USER_IN_WAIT_REJ); 1311 cc_conn_sig(conn, CONN_SIG_REJECT, NULL); 1312 1313 return; 1314 } 1315 1316 1317 case USER_SIG_REJECT_OK: 1318 if (user->state != USER_IN_WAIT_REJ) 1319 goto bad_state; 1320 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1321 1322 set_state(user, USER_IN_WAITING); 1323 do_arrival(user); 1324 return; 1325 1326 1327 case USER_SIG_REJECT_ERR: 1328 if (user->state != USER_IN_WAIT_REJ) 1329 goto bad_state; 1330 cc_user_err(user, arg2); 1331 1332 if (arg == NULL) 1333 set_state(user, USER_IN_ARRIVED); 1334 else { 1335 set_state(user, USER_IN_WAITING); 1336 do_arrival(user); 1337 } 1338 return; 1339 1340 1341 case USER_SIG_ACCEPT_INCOMING: 1342 { 1343 /* 1344 * User accepts call. This is done on the OLD user (i.e. the one 1345 * sending the arrival), the message contains a pointer to the 1346 * new endpoint. 1347 */ 1348 struct uni_msg *msg = arg; 1349 struct atm_accept_incoming_call *acc = 1350 uni_msg_rptr(msg, struct atm_accept_incoming_call *); 1351 struct ccuser *newep; 1352 1353 if (user->state != USER_IN_ARRIVED) { 1354 uni_msg_destroy(msg); 1355 cc_user_err(user, ATMERR_BAD_STATE); 1356 return; 1357 } 1358 if (user->aborted) { 1359 /* connection has disappeared. Send an error 1360 * to the user and lock whether there is another 1361 * connection at this endpoint */ 1362 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1363 1364 set_state(user, USER_IN_WAITING); 1365 do_arrival(user); 1366 return; 1367 } 1368 acc->newep[sizeof(acc->newep) - 1] = '\0'; 1369 1370 LIST_FOREACH(newep, &user->cc->user_list, node_link) 1371 if (strcmp(acc->newep, newep->name) == 0) 1372 break; 1373 1374 if (newep == NULL) { 1375 uni_msg_destroy(msg); 1376 cc_user_err(user, ATMERR_BAD_ENDPOINT); 1377 return; 1378 } 1379 1380 if (newep->state != USER_NULL || newep->accepted != NULL) { 1381 uni_msg_destroy(msg); 1382 cc_user_err(user, ATMERR_BAD_STATE); 1383 return; 1384 } 1385 1386 set_state(user, USER_IN_WAIT_ACC); 1387 cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep); 1388 1389 return; 1390 } 1391 1392 1393 case USER_SIG_ACCEPT_OK: 1394 if (user->state != USER_IN_WAIT_ACC) 1395 goto bad_state; 1396 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1397 1398 set_state(user, USER_IN_WAITING); 1399 do_arrival(user); 1400 return; 1401 1402 1403 case USER_SIG_ACCEPT_ERR: 1404 if (user->state != USER_IN_WAIT_ACC) 1405 goto bad_state; 1406 cc_user_err(user, arg2); 1407 1408 if (arg == NULL) { 1409 /* arg used as flag! */ 1410 set_state(user, USER_IN_ARRIVED); 1411 } else { 1412 set_state(user, USER_IN_WAITING); 1413 do_arrival(user); 1414 } 1415 return; 1416 1417 1418 case USER_SIG_ACCEPTING: 1419 if (user->state != USER_NULL) 1420 goto bad_state; 1421 set_state(user, USER_IN_ACCEPTING); 1422 return; 1423 1424 1425 case USER_SIG_SETUP_COMPL: 1426 { 1427 struct ccconn *conn = TAILQ_FIRST(&user->connq); 1428 1429 if (user->state != USER_IN_ACCEPTING) 1430 goto bad_state; 1431 1432 user->state = USER_ACTIVE; 1433 if (conn->bearer.cfg == UNI_BEARER_P2P) { 1434 struct atm_p2p_call_active *act; 1435 1436 user->config = USER_P2P; 1437 act = CCZALLOC(sizeof(*act)); 1438 if (act == NULL) 1439 return; 1440 act->connid = conn->connid; 1441 cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, 1442 act, sizeof(*act)); 1443 CCFREE(act); 1444 } else { 1445 struct atm_p2mp_call_active *act; 1446 1447 user->config = USER_LEAF; 1448 act = CCZALLOC(sizeof(*act)); 1449 if (act == NULL) 1450 return; 1451 act->connid = conn->connid; 1452 cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, 1453 act, sizeof(*act)); 1454 CCFREE(act); 1455 } 1456 return; 1457 } 1458 1459 1460 case USER_SIG_CALL_RELEASE: 1461 { 1462 struct uni_msg *msg = arg; 1463 struct atm_call_release *api = uni_msg_rptr(msg, 1464 struct atm_call_release *); 1465 struct ccconn *conn; 1466 1467 conn = TAILQ_FIRST(&user->connq); 1468 switch (user->state) { 1469 1470 case USER_OUT_WAIT_OK: /* U2/A3 */ 1471 /* wait for CONN_OK first */ 1472 conn->cause[0] = api->cause[0]; 1473 conn->cause[1] = api->cause[1]; 1474 set_state(user, USER_REL_WAIT_CONN); 1475 break; 1476 1477 case USER_OUT_WAIT_CONF: /* U3/A3 */ 1478 /* wait for SETUP.confirm first */ 1479 conn->cause[0] = api->cause[0]; 1480 conn->cause[1] = api->cause[1]; 1481 set_state(user, USER_REL_WAIT_SCONF); 1482 break; 1483 1484 case USER_IN_ACCEPTING: /* U11/A7 */ 1485 conn->cause[0] = api->cause[0]; 1486 conn->cause[1] = api->cause[1]; 1487 set_state(user, USER_REL_WAIT_SCOMP); 1488 cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); 1489 break; 1490 1491 case USER_ACTIVE: /* U4/A8,A9,A10 */ 1492 conn->cause[0] = api->cause[0]; 1493 conn->cause[1] = api->cause[1]; 1494 set_state(user, USER_REL_WAIT); 1495 cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); 1496 break; 1497 1498 default: 1499 uni_msg_destroy(msg); 1500 cc_user_err(user, ATMERR_BAD_STATE); 1501 goto bad_state; 1502 } 1503 uni_msg_destroy(msg); 1504 return; 1505 } 1506 1507 1508 case USER_SIG_RELEASE_CONFIRM: 1509 { 1510 struct atm_call_release *ind; 1511 1512 switch (user->state) { 1513 1514 case USER_OUT_WAIT_CONF: /* U3/A3 */ 1515 case USER_ACTIVE: /* U4/A8,A9,A10 */ 1516 cc_user_reset(user); 1517 break; 1518 1519 case USER_REL_WAIT: /* U5 /A8,A9,A10 */ 1520 case USER_REL_WAIT_SCOMP: /* U12/A7 */ 1521 case USER_REL_WAIT_SCONF: /* U13/A3 */ 1522 case USER_REL_WAIT_CONF: /* U14/A3 */ 1523 cc_user_reset(user); 1524 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1525 return; 1526 1527 case USER_IN_ACCEPTING: /* U11/A7 */ 1528 cc_user_reset(user); 1529 break; 1530 1531 default: 1532 goto bad_state; 1533 } 1534 1535 ind = CCZALLOC(sizeof(*ind)); 1536 if (ind == NULL) 1537 return; 1538 memcpy(ind->cause, user->cause, sizeof(ind->cause)); 1539 cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind)); 1540 CCFREE(ind); 1541 return; 1542 } 1543 1544 1545 case USER_SIG_RELEASE_ERR: 1546 switch (user->state) { 1547 1548 case USER_REL_WAIT: /* U5/A8,A9,A10 */ 1549 set_state(user, USER_ACTIVE); 1550 cc_user_err(user, ATM_MKUNIERR(arg2)); 1551 break; 1552 1553 case USER_REL_WAIT_CONF: /* U14/A3 */ 1554 cc_user_err(user, ATM_MKUNIERR(arg2)); 1555 cc_user_active(user); 1556 break; 1557 1558 case USER_REL_WAIT_SCOMP: /* U12/A7 */ 1559 set_state(user, USER_IN_ACCEPTING); 1560 cc_user_err(user, ATM_MKUNIERR(arg2)); 1561 break; 1562 1563 default: 1564 goto bad_state; 1565 } 1566 return; 1567 1568 1569 case USER_SIG_ADD_PARTY: 1570 { 1571 struct uni_msg *msg = arg; 1572 struct atm_add_party *add = uni_msg_rptr(msg, 1573 struct atm_add_party *); 1574 struct ccconn *conn; 1575 1576 if (user->state != USER_ACTIVE || user->config != USER_ROOT) { 1577 uni_msg_destroy(msg); 1578 cc_user_err(user, ATMERR_BAD_STATE); 1579 return; 1580 } 1581 1582 if (add->leaf_ident == 0 || add->leaf_ident >= 32786) { 1583 uni_msg_destroy(msg); 1584 cc_user_err(user, ATMERR_BAD_LEAF_IDENT); 1585 return; 1586 } 1587 1588 conn = TAILQ_FIRST(&user->connq); 1589 conn->called = add->called; 1590 1591 cc_conn_sig(conn, CONN_SIG_ADD_PARTY, 1592 (void *)(uintptr_t)add->leaf_ident); 1593 1594 uni_msg_destroy(msg); 1595 return; 1596 } 1597 1598 1599 case USER_SIG_ADD_PARTY_ERR: 1600 if (user->state != USER_ACTIVE) 1601 goto bad_state; 1602 cc_user_err(user, arg2); 1603 return; 1604 1605 1606 case USER_SIG_ADD_PARTY_OK: 1607 if (user->state != USER_ACTIVE) 1608 goto bad_state; 1609 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1610 return; 1611 1612 1613 case USER_SIG_ADD_PARTY_ACK: 1614 { 1615 u_int leaf_ident = arg2; 1616 struct atm_add_party_success *succ; 1617 1618 if (user->state != USER_ACTIVE) 1619 goto bad_state; 1620 1621 succ = CCZALLOC(sizeof(*succ)); 1622 if (succ == NULL) 1623 return; 1624 1625 succ->leaf_ident = leaf_ident; 1626 cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS, 1627 succ, sizeof(*succ)); 1628 1629 CCFREE(succ); 1630 return; 1631 } 1632 1633 1634 case USER_SIG_ADD_PARTY_REJ: 1635 { 1636 u_int leaf_ident = arg2; 1637 struct atm_add_party_reject *reject; 1638 1639 if (user->state != USER_ACTIVE) 1640 goto bad_state; 1641 1642 reject = CCZALLOC(sizeof(*reject)); 1643 if (reject == NULL) 1644 return; 1645 1646 reject->leaf_ident = leaf_ident; 1647 reject->cause = user->cause[0]; 1648 cc_user_send(user, ATMOP_ADD_PARTY_REJECT, 1649 reject, sizeof(*reject)); 1650 1651 CCFREE(reject); 1652 return; 1653 } 1654 1655 1656 case USER_SIG_DROP_PARTY: 1657 { 1658 struct uni_msg *msg = arg; 1659 struct atm_drop_party *drop = uni_msg_rptr(msg, 1660 struct atm_drop_party *); 1661 struct ccconn *conn; 1662 1663 if (user->state != USER_ACTIVE || user->config != USER_ROOT) { 1664 uni_msg_destroy(msg); 1665 cc_user_err(user, ATMERR_BAD_STATE); 1666 return; 1667 } 1668 1669 if (drop->leaf_ident >= 32786) { 1670 uni_msg_destroy(msg); 1671 cc_user_err(user, ATMERR_BAD_LEAF_IDENT); 1672 return; 1673 } 1674 1675 conn = TAILQ_FIRST(&user->connq); 1676 conn->cause[0] = drop->cause; 1677 memset(&conn->cause[1], 0, sizeof(conn->cause[1])); 1678 1679 cc_conn_sig(conn, CONN_SIG_DROP_PARTY, 1680 (void *)(uintptr_t)drop->leaf_ident); 1681 1682 uni_msg_destroy(msg); 1683 return; 1684 } 1685 1686 1687 case USER_SIG_DROP_PARTY_ERR: 1688 if (user->state != USER_ACTIVE) 1689 goto bad_state; 1690 cc_user_err(user, arg2); 1691 return; 1692 1693 1694 case USER_SIG_DROP_PARTY_OK: 1695 if (user->state != USER_ACTIVE) 1696 goto bad_state; 1697 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1698 return; 1699 1700 1701 case USER_SIG_DROP_PARTY_IND: 1702 { 1703 u_int leaf_ident = arg2; 1704 struct atm_drop_party *drop; 1705 1706 if (user->state != USER_ACTIVE) 1707 goto bad_state; 1708 1709 drop = CCZALLOC(sizeof(*drop)); 1710 if (drop == NULL) 1711 return; 1712 1713 drop->leaf_ident = leaf_ident; 1714 drop->cause = user->cause[0]; 1715 cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop)); 1716 1717 CCFREE(drop); 1718 return; 1719 } 1720 1721 1722 case USER_SIG_QUERY_ATTR: 1723 { 1724 struct uni_msg *msg = arg; 1725 struct atm_query_connection_attributes *req; 1726 struct ccconn *conn; 1727 1728 if (user->aborted) { 1729 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1730 uni_msg_destroy(msg); 1731 return; 1732 } 1733 conn = cc_query_check(user); 1734 if (conn == NULL) { 1735 cc_user_err(user, ATMERR_BAD_STATE); 1736 uni_msg_destroy(msg); 1737 return; 1738 } 1739 req = uni_msg_rptr(msg, 1740 struct atm_query_connection_attributes *); 1741 cc_attr_query(user, conn, &req->attr, 1); 1742 uni_msg_destroy(msg); 1743 return; 1744 } 1745 1746 case USER_SIG_QUERY_ATTR_X: 1747 { 1748 struct uni_msg *msg = arg; 1749 struct atm_query_connection_attributes_x *req; 1750 struct ccconn *conn; 1751 1752 conn = cc_query_check(user); 1753 if (conn == NULL) { 1754 cc_user_err(user, ATMERR_BAD_STATE); 1755 uni_msg_destroy(msg); 1756 return; 1757 } 1758 req = uni_msg_rptr(msg, 1759 struct atm_query_connection_attributes_x *); 1760 cc_attr_query(user, conn, req->attr, req->count); 1761 uni_msg_destroy(msg); 1762 return; 1763 } 1764 1765 case USER_SIG_SET_ATTR: 1766 { 1767 struct uni_msg *msg = arg; 1768 struct atm_set_connection_attributes *req; 1769 struct ccconn *conn; 1770 1771 if (user->aborted) { 1772 cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); 1773 uni_msg_destroy(msg); 1774 return; 1775 } 1776 conn = cc_set_check(user); 1777 if (conn == NULL) { 1778 cc_user_err(user, ATMERR_BAD_STATE); 1779 uni_msg_destroy(msg); 1780 return; 1781 } 1782 req = uni_msg_rptr(msg, struct atm_set_connection_attributes *); 1783 cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1), 1784 uni_msg_len(msg) - sizeof(*req)); 1785 uni_msg_destroy(msg); 1786 return; 1787 } 1788 1789 case USER_SIG_SET_ATTR_X: 1790 { 1791 struct uni_msg *msg = arg; 1792 struct atm_set_connection_attributes_x *req; 1793 struct ccconn *conn; 1794 1795 conn = cc_set_check(user); 1796 if (conn == NULL) { 1797 cc_user_err(user, ATMERR_BAD_STATE); 1798 uni_msg_destroy(msg); 1799 return; 1800 } 1801 req = uni_msg_rptr(msg, 1802 struct atm_set_connection_attributes_x *); 1803 cc_attr_set(user, conn, req->attr, req->count, 1804 (u_char *)req->attr + req->count * sizeof(req->attr[0]), 1805 uni_msg_len(msg) - 1806 offsetof(struct atm_set_connection_attributes_x, attr) - 1807 req->count * sizeof(req->attr[0])); 1808 uni_msg_destroy(msg); 1809 return; 1810 } 1811 1812 case USER_SIG_QUERY_STATE: 1813 { 1814 struct atm_epstate state; 1815 1816 strcpy(state.name, user->name); 1817 switch (user->state) { 1818 1819 case USER_NULL: 1820 if (user->accepted != NULL) 1821 state.state = ATM_A7; 1822 else 1823 state.state = ATM_A1; 1824 break; 1825 1826 case USER_OUT_PREPARING: 1827 state.state = ATM_A2; 1828 break; 1829 1830 case USER_OUT_WAIT_OK: 1831 case USER_OUT_WAIT_CONF: 1832 case USER_REL_WAIT_SCONF: 1833 case USER_REL_WAIT_CONF: 1834 case USER_REL_WAIT_CONN: 1835 state.state = ATM_A3; 1836 break; 1837 1838 case USER_ACTIVE: 1839 case USER_REL_WAIT: 1840 switch (user->config) { 1841 1842 case USER_P2P: 1843 state.state = ATM_A8; 1844 break; 1845 1846 case USER_ROOT: 1847 state.state = ATM_A9; 1848 break; 1849 1850 case USER_LEAF: 1851 state.state = ATM_A10; 1852 break; 1853 } 1854 break; 1855 1856 case USER_IN_PREPARING: 1857 state.state = ATM_A4; 1858 break; 1859 1860 case USER_IN_WAITING: 1861 state.state = ATM_A5; 1862 break; 1863 1864 case USER_IN_ARRIVED: 1865 case USER_IN_WAIT_REJ: 1866 case USER_IN_WAIT_ACC: 1867 state.state = ATM_A6; 1868 break; 1869 1870 case USER_IN_ACCEPTING: 1871 case USER_REL_WAIT_SCOMP: 1872 state.state = ATM_A7; 1873 break; 1874 } 1875 cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state)); 1876 return; 1877 } 1878 1879 case USER_SIG_GET_LOCAL_PORT_INFO: 1880 { 1881 struct uni_msg *msg = arg; 1882 struct atm_port_list *list; 1883 size_t list_len; 1884 1885 list = cc_get_local_port_info(user->cc, 1886 uni_msg_rptr(msg, struct atm_get_local_port_info *)->port, 1887 &list_len); 1888 uni_msg_destroy(msg); 1889 if (list == NULL) { 1890 cc_user_err(user, ATMERR_NOMEM); 1891 return; 1892 } 1893 cc_user_ok(user, ATMRESP_PORTS, list, list_len); 1894 CCFREE(list); 1895 return; 1896 } 1897 1898 case USER_SIG_ABORT_CONNECTION: 1899 { 1900 struct uni_msg *msg = arg; 1901 struct atm_abort_connection *abo = uni_msg_rptr(msg, 1902 struct atm_abort_connection *); 1903 1904 cc_user_abort(user, &abo->cause); 1905 uni_msg_destroy(msg); 1906 cc_user_ok(user, ATMRESP_NONE, NULL, 0); 1907 return; 1908 } 1909 1910 } 1911 if (user->cc->log & CCLOG_USER_SIG) 1912 cc_user_log(user, "bad signal=%u in state=%u", 1913 sig, user->state); 1914 return; 1915 1916 bad_state: 1917 if (user->cc->log & CCLOG_USER_SIG) 1918 cc_user_log(user, "bad state=%u for signal=%u", 1919 user->state, sig); 1920 return; 1921} 1922