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_port.c,v 1.1 2004/07/08 08:21:53 brandt Exp $ 35 * 36 * ATM API as defined per af-saa-0108 37 * 38 * Port-global stuff (ILMI and Co.) 39 */ 40#include <netnatm/unimsg.h> 41#include <netnatm/msg/unistruct.h> 42#include <netnatm/api/unisap.h> 43#include <netnatm/sig/unidef.h> 44#include <netnatm/api/atmapi.h> 45#include <netnatm/api/ccatm.h> 46#include <netnatm/api/ccpriv.h> 47 48/* 49 * Find a port with a given number 50 */ 51static struct ccport * 52find_port(struct ccdata *cc, u_int portno) 53{ 54 struct ccport *port; 55 56 TAILQ_FOREACH(port, &cc->port_list, node_link) 57 if (port->param.port == portno) 58 return (port); 59 return (NULL); 60} 61 62/* 63 * Create a new port structure, initialize it and link it to the node. 64 * Returns 0 on success, an errno otherwise. 65 */ 66struct ccport * 67cc_port_create(struct ccdata *cc, void *uarg, u_int portno) 68{ 69 struct ccport *port, *p1; 70 71 if (portno == 0 || portno > 0xffffffff) 72 return (NULL); 73 74 TAILQ_FOREACH(port, &cc->port_list, node_link) 75 if (port->param.port == portno) 76 return (NULL); 77 78 port = CCZALLOC(sizeof(*port)); 79 if (port == NULL) 80 return (NULL); 81 82 port->uarg = uarg; 83 port->cc = cc; 84 port->admin = CCPORT_STOPPED; 85 LIST_INIT(&port->conn_list); 86 TAILQ_INIT(&port->addr_list); 87 port->param.port = portno; 88 port->param.pcr = 350053; 89 port->param.max_vpi_bits = 0; 90 port->param.max_vci_bits = 8; 91 port->param.max_svpc_vpi = 0; 92 port->param.max_svcc_vpi = 0; 93 port->param.min_svcc_vci = 32; 94 port->param.num_addrs = 0; 95 TAILQ_INIT(&port->cookies); 96 97 TAILQ_FOREACH(p1, &cc->port_list, node_link) 98 if (p1->param.port > portno) { 99 TAILQ_INSERT_BEFORE(p1, port, node_link); 100 break; 101 } 102 if (p1 == NULL) 103 TAILQ_INSERT_TAIL(&cc->port_list, port, node_link); 104 105 return (port); 106} 107 108/* 109 * Destroy a port. This closes all connections and aborts all the users of 110 * these connections. 111 * This should be called only after work has returned so that no signals 112 * are pending. 113 */ 114void 115cc_port_destroy(struct ccport *port, int shutdown) 116{ 117 struct ccaddr *addr; 118 struct ccreq *r; 119 120 TAILQ_REMOVE(&port->cc->port_list, port, node_link); 121 122 while ((r = TAILQ_FIRST(&port->cookies)) != NULL) { 123 TAILQ_REMOVE(&port->cookies, r, link); 124 CCFREE(r); 125 } 126 127 /* 128 * Abort all connections. 129 */ 130 while (!LIST_EMPTY(&port->conn_list)) 131 cc_conn_abort(LIST_FIRST(&port->conn_list), shutdown); 132 133 /* 134 * Free addresses. 135 */ 136 while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 137 TAILQ_REMOVE(&port->addr_list, addr, port_link); 138 CCFREE(addr); 139 } 140 141 CCFREE(port); 142} 143 144/* 145 * Management is given up on this node. Remove all addresses from the port. 146 */ 147void 148cc_unmanage(struct ccdata *cc) 149{ 150 struct ccport *port; 151 struct ccaddr *addr; 152 153 TAILQ_FOREACH(port, &cc->port_list, node_link) { 154 while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 155 TAILQ_REMOVE(&port->addr_list, addr, port_link); 156 CCFREE(addr); 157 } 158 } 159} 160 161/* 162 * Compare two addresses 163 */ 164static __inline int 165addr_eq(const struct uni_addr *a1, const struct uni_addr *a2) 166{ 167 return (a1->type == a2->type && a1->plan == a2->plan && 168 a1->len == a2->len && memcmp(a1->addr, a2->addr, a1->len) == 0); 169} 170 171 172/* 173 * retrieve addresses 174 */ 175int 176cc_get_addrs(struct ccdata *cc, u_int portno, 177 struct uni_addr **pa, u_int **ports, u_int *count) 178{ 179 struct ccport *port = NULL; 180 struct ccaddr *addr; 181 struct uni_addr *buf, *ptr; 182 u_int *pports; 183 184 /* 185 * If a port number is specified and the port does not exist, 186 * return an error. 187 */ 188 if (portno != 0) 189 if ((port = find_port(cc, portno)) == NULL) 190 return (ENOENT); 191 192 /* 193 * Count the addresses 194 */ 195 *count = 0; 196 if (portno != 0) { 197 TAILQ_FOREACH(addr, &port->addr_list, port_link) 198 (*count)++; 199 } else { 200 TAILQ_FOREACH(port, &cc->port_list, node_link) 201 TAILQ_FOREACH(addr, &port->addr_list, port_link) 202 (*count)++; 203 } 204 205 buf = CCMALLOC(*count * sizeof(struct uni_addr)); 206 if (buf == NULL) 207 return (ENOMEM); 208 ptr = buf; 209 210 *ports = CCMALLOC(*count * sizeof(u_int)); 211 if (*ports == NULL) { 212 CCFREE(buf); 213 return (ENOMEM); 214 } 215 pports = *ports; 216 217 if (portno != 0) { 218 TAILQ_FOREACH(addr, &port->addr_list, port_link) { 219 *ptr++ = addr->addr; 220 *pports++ = portno; 221 } 222 } else { 223 TAILQ_FOREACH(port, &cc->port_list, node_link) 224 TAILQ_FOREACH(addr, &port->addr_list, port_link) { 225 *ptr++ = addr->addr; 226 *pports++ = port->param.port; 227 } 228 } 229 230 *pa = buf; 231 return (0); 232} 233 234/* 235 * return port number 236 */ 237u_int 238cc_port_no(struct ccport *port) 239{ 240 return (port->param.port); 241} 242 243/* 244 * Address unregisterd. 245 */ 246int 247cc_addr_unregister(struct ccdata *cc, u_int portno, const struct uni_addr *arg) 248{ 249 struct ccport *port; 250 struct ccaddr *a; 251 252 if ((port = find_port(cc, portno)) == NULL) 253 return (ENOENT); 254 255 /* Find the address */ 256 TAILQ_FOREACH(a, &port->addr_list, port_link) 257 if (addr_eq(arg, &a->addr)) { 258 TAILQ_REMOVE(&port->addr_list, a, port_link); 259 CCFREE(a); 260 return (0); 261 } 262 263 return (ENOENT); 264} 265 266/* 267 * Address registerd. 268 */ 269int 270cc_addr_register(struct ccdata *cc, u_int portno, const struct uni_addr *arg) 271{ 272 struct ccport *port, *p1; 273 struct ccaddr *a; 274 275 if ((port = find_port(cc, portno)) == NULL) 276 return (ENOENT); 277 278 /* maybe we know it already? */ 279 TAILQ_FOREACH(p1, &port->cc->port_list, node_link) 280 TAILQ_FOREACH(a, &p1->addr_list, port_link) 281 if (addr_eq(arg, &a->addr)) 282 return (EISCONN); 283 284 a = CCZALLOC(sizeof(*a)); 285 if (a == NULL) 286 return (ENOMEM); 287 a->addr = *arg; 288 289 TAILQ_INSERT_TAIL(&port->addr_list, a, port_link); 290 291 return (0); 292} 293 294/* 295 * Set/get port parameters. 296 */ 297int 298cc_port_get_param(struct ccdata *cc, u_int portno, 299 struct atm_port_info *param) 300{ 301 struct ccport *port; 302 303 if ((port = find_port(cc, portno)) == NULL) 304 return (ENOENT); 305 306 *param = port->param; 307 return (0); 308} 309 310/* XXX maybe allow only in stopped. */ 311int 312cc_port_set_param(struct ccdata *cc, const struct atm_port_info *param) 313{ 314 struct ccport *port; 315 struct ccaddr *addr; 316 317 if ((port = find_port(cc, param->port)) == NULL) 318 return (ENOENT); 319 320 port->param = *param; 321 322 port->param.num_addrs = 0; 323 TAILQ_FOREACH(addr, &port->addr_list, port_link) 324 port->param.num_addrs++; 325 326 return (0); 327} 328 329/* 330 * get port list 331 */ 332int 333cc_port_getlist(struct ccdata *cc, u_int *cnt, u_int **ports) 334{ 335 struct ccport *p; 336 u_int n; 337 338 n = 0; 339 TAILQ_FOREACH(p, &cc->port_list, node_link) 340 n++; 341 342 *ports = CCMALLOC(n * sizeof(u_int)); 343 if (*ports == NULL) 344 return (ENOMEM); 345 346 n = 0; 347 TAILQ_FOREACH(p, &cc->port_list, node_link) 348 (*ports)[n++] = p->param.port; 349 *cnt = n; 350 351 return (0); 352} 353 354/* 355 * START and STOP signalling 356 */ 357int 358cc_port_start(struct ccdata *cc, u_int portno) 359{ 360 struct ccport *port; 361 362 if ((port = find_port(cc, portno)) == NULL) 363 return (ENOENT); 364 if (port->admin != CCPORT_STOPPED) 365 return (EISCONN); 366 367 cc->funcs->send_uni_glob(port, port->uarg, 368 UNIAPI_LINK_ESTABLISH_request, 0, NULL); 369 port->admin = CCPORT_RUNNING; 370 371 return (0); 372} 373 374int 375cc_port_stop(struct ccdata *cc, u_int portno) 376{ 377 struct ccport *port; 378 379 if ((port = find_port(cc, portno)) == NULL) 380 return (ENOENT); 381 if (port->admin != CCPORT_RUNNING) 382 return (ENOTCONN); 383 384 port->admin = CCPORT_STOPPED; 385 386 /* 387 * Abort all connections. 388 */ 389 while (!LIST_EMPTY(&port->conn_list)) 390 cc_conn_destroy(LIST_FIRST(&port->conn_list)); 391 392 return (0); 393} 394 395/* 396 * is port running? 397 */ 398int 399cc_port_isrunning(struct ccdata *cc, u_int portno, int *state) 400{ 401 struct ccport *port; 402 403 if ((port = find_port(cc, portno)) == NULL) 404 return (ENOENT); 405 if (port->admin == CCPORT_RUNNING) 406 *state = 1; 407 else 408 *state = 0; 409 return (0); 410} 411 412/* 413 * Clear address and prefix information from the named port. 414 */ 415int 416cc_port_clear(struct ccdata *cc, u_int portno) 417{ 418 struct ccaddr *addr; 419 struct ccport *port; 420 421 if ((port = find_port(cc, portno)) == NULL) 422 return (ENOENT); 423 424 while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 425 TAILQ_REMOVE(&port->addr_list, addr, port_link); 426 CCFREE(addr); 427 } 428 return (0); 429} 430 431/* 432 * retrieve info on local ports 433 */ 434struct atm_port_list * 435cc_get_local_port_info(struct ccdata *cc, u_int portno, size_t *lenp) 436{ 437 struct atm_port_list *list; 438 struct atm_port_info *pp; 439 struct uni_addr *aa; 440 struct ccaddr *addr; 441 struct ccport *port; 442 u_int nports, naddrs; 443 444 /* 445 * Count ports and addresses. 446 */ 447 nports = 0; 448 naddrs = 0; 449 TAILQ_FOREACH(port, &cc->port_list, node_link) { 450 if (portno == 0 || port->param.port == portno) { 451 nports++; 452 TAILQ_FOREACH(addr, &port->addr_list, port_link) 453 naddrs++; 454 } 455 } 456 457 /* 458 * Size and allocate message 459 */ 460 *lenp = sizeof(*list) + nports * sizeof(*pp) + naddrs * sizeof(*aa); 461 462 list = CCZALLOC(*lenp); 463 if (list == NULL) 464 return (NULL); 465 466 /* 467 * Fill the message. 468 */ 469 list->num_ports = nports; 470 list->num_addrs = naddrs; 471 472 pp = (void *)((u_char *)list + sizeof(*list)); 473 aa = (void *)((u_char *)list + sizeof(*list) + nports * sizeof(*pp)); 474 475 TAILQ_FOREACH(port, &cc->port_list, node_link) { 476 if (portno == 0 || port->param.port == portno) { 477 *pp = port->param; 478 pp->num_addrs = 0; 479 TAILQ_FOREACH(addr, &port->addr_list, port_link) { 480 *aa++ = addr->addr; 481 pp->num_addrs++; 482 } 483 pp++; 484 } 485 } 486 487 return (list); 488} 489 490static struct ccreq * 491find_cookie(struct ccport *port, u_int cookie) 492{ 493 struct ccreq *r; 494 495 TAILQ_FOREACH(r, &port->cookies, link) 496 if (r->cookie == cookie) 497 return (r); 498 return (NULL); 499} 500 501/* 502 * input a response from the UNI layer to CC 503 */ 504int 505cc_uni_response(struct ccport *port, u_int cookie, u_int reason, u_int state) 506{ 507 struct ccconn *conn; 508 struct ccreq *req; 509 510 if (cookie == 0) 511 return (EINVAL); 512 513 if (port->admin != CCPORT_RUNNING) 514 return (ENOTCONN); 515 516 if ((req = find_cookie(port, cookie)) == NULL) { 517 cc_port_log(port, "UNI response for unknown cookie %u", cookie); 518 return (EINVAL); 519 } 520 conn = req->conn; 521 522 TAILQ_REMOVE(&port->cookies, req, link); 523 CCFREE(req); 524 525 if (reason == UNIAPI_OK) 526 return (cc_conn_resp(conn, CONN_SIG_OK, 527 cookie, reason, state)); 528 else 529 return (cc_conn_resp(conn, CONN_SIG_ERROR, 530 cookie, reason, state)); 531} 532 533static struct ccconn * 534find_cref(const struct ccport *port, const struct uni_cref *cref) 535{ 536 struct ccconn *conn; 537 538 LIST_FOREACH(conn, &port->conn_list, port_link) 539 if (conn->cref.cref == cref->cref && 540 conn->cref.flag == cref->flag) 541 return (conn); 542 return (NULL); 543} 544 545/* 546 * Signal from UNI on this port 547 */ 548int 549cc_uni_signal(struct ccport *port, u_int cookie, u_int sig, struct uni_msg *msg) 550{ 551 int error = 0; 552 size_t len, ilen = 0; 553 struct uni_cref *cref; 554 struct ccconn *conn; 555 556 if (port->admin != CCPORT_RUNNING) { 557 error = ENOTCONN; 558 goto out; 559 } 560 len = (msg != NULL) ? uni_msg_len(msg) : 0; 561 562 switch ((enum uni_sig)sig) { 563 564 case UNIAPI_ERROR: 565 /* handled above */ 566 cc_port_log(port, "bad UNIAPI_ERROR cookie=%u", cookie); 567 error = EINVAL; 568 break; 569 570 case UNIAPI_CALL_CREATED: 571 ilen = sizeof(struct uniapi_call_created); 572 if (len != ilen) 573 goto bad_len; 574 575 if (cookie != 0) { 576 /* outgoing call */ 577 struct ccreq *req; 578 579 if ((req = find_cookie(port, cookie)) == NULL) { 580 cc_port_log(port, "bad cookie %u in CREATE", 581 cookie); 582 error = EINVAL; 583 goto out; 584 } 585 conn = req->conn; 586 587 } else { 588 if ((conn = cc_conn_create(port->cc)) == NULL) { 589 error = ENOMEM; 590 goto out; 591 } 592 cc_conn_ins_port(conn, port); 593 } 594 595 cc_conn_sig_msg_nodef(conn, CONN_SIG_CREATED, msg); 596 msg = NULL; 597 goto out; 598 599 case UNIAPI_CALL_DESTROYED: 600 ilen = sizeof(struct uniapi_call_destroyed); 601 if (len != ilen) 602 goto bad_len; 603 604 cref = &uni_msg_rptr(msg, struct uniapi_call_destroyed *)->cref; 605 if ((conn = find_cref(port, cref)) == NULL) 606 goto unk_call; 607 608 error = cc_conn_sig(conn, CONN_SIG_DESTROYED, NULL); 609 goto out; 610 611 case UNIAPI_LINK_ESTABLISH_confirm: 612 goto out; 613 614 case UNIAPI_LINK_RELEASE_confirm: 615 /* Ups. If we administratively up, restart the link */ 616 if (port->admin == CCPORT_RUNNING) 617 port->cc->funcs->send_uni_glob(port, port->uarg, 618 UNIAPI_LINK_ESTABLISH_request, 0, NULL); 619 goto out; 620 621 case UNIAPI_PARTY_CREATED: 622 ilen = sizeof(struct uniapi_party_created); 623 if (len != ilen) 624 goto bad_len; 625 626 cref = &uni_msg_rptr(msg, struct uniapi_party_created *)->cref; 627 628 if ((conn = find_cref(port, cref)) == NULL) 629 goto unk_call; 630 631 error = cc_conn_sig_msg_nodef(conn, 632 CONN_SIG_PARTY_CREATED, msg); 633 msg = NULL; 634 goto out; 635 636 case UNIAPI_PARTY_DESTROYED: 637 ilen = sizeof(struct uniapi_party_destroyed); 638 if (len != ilen) 639 goto bad_len; 640 641 cref = &uni_msg_rptr(msg, 642 struct uniapi_party_destroyed *)->cref; 643 644 if ((conn = find_cref(port, cref)) == NULL) 645 goto unk_call; 646 647 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_DESTROYED, msg); 648 msg = NULL; 649 goto out; 650 651 case UNIAPI_DROP_PARTY_ACK_indication: /* UNI -> API */ 652 ilen = sizeof(struct uniapi_drop_party_ack_indication); 653 if (len != ilen) 654 goto bad_len; 655 656 cref = &uni_msg_rptr(msg, 657 struct uniapi_drop_party_ack_indication *)->drop.hdr.cref; 658 659 if ((conn = find_cref(port, cref)) == NULL) 660 goto unk_call; 661 662 error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_ACK_IND, msg); 663 msg = NULL; 664 goto out; 665 666 case UNIAPI_RESET_indication: /* UNI -> API */ 667 { 668 /* 669 * XXX - do the right thing 670 */ 671 struct uniapi_reset_indication *ind = uni_msg_rptr(msg, 672 struct uniapi_reset_indication *); 673 struct uniapi_reset_response *resp; 674 struct uni_msg *u; 675 676 /* 677 * Construct message to UNI. 678 */ 679 if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) 680 return (ENOMEM); 681 682 resp = uni_msg_wptr(u, struct uniapi_reset_response *); 683 memset(resp, 0, sizeof(*resp)); 684 u->b_wptr += sizeof(*resp); 685 686 resp->restart = ind->restart; 687 resp->connid = ind->connid; 688 689 port->cc->funcs->send_uni_glob(port, port->uarg, 690 UNIAPI_RESET_response, 0, u); 691 692 goto out; 693 } 694 695 case UNIAPI_RELEASE_indication: /* UNI -> API */ 696 ilen = sizeof(struct uniapi_release_indication); 697 if (len != ilen) 698 goto bad_len; 699 700 cref = &uni_msg_rptr(msg, struct uniapi_release_indication *) 701 ->release.hdr.cref; 702 703 if ((conn = find_cref(port, cref)) == NULL) 704 goto unk_call; 705 706 error = cc_conn_sig_msg(conn, CONN_SIG_REL_IND, msg); 707 msg = NULL; 708 goto out; 709 710 case UNIAPI_RELEASE_confirm: /* UNI -> API */ 711 ilen = sizeof(struct uniapi_release_confirm); 712 if (len != ilen) 713 goto bad_len; 714 715 cref = &uni_msg_rptr(msg, struct uniapi_release_confirm *) 716 ->release.hdr.cref; 717 718 if ((conn = find_cref(port, cref)) == NULL) 719 goto unk_call; 720 721 error = cc_conn_sig_msg(conn, CONN_SIG_REL_CONF, msg); 722 msg = NULL; 723 goto out; 724 725 case UNIAPI_SETUP_confirm: /* UNI -> API */ 726 ilen = sizeof(struct uniapi_setup_confirm); 727 if (len != ilen) 728 goto bad_len; 729 730 cref = &uni_msg_rptr(msg, struct uniapi_setup_confirm *) 731 ->connect.hdr.cref; 732 733 if ((conn = find_cref(port, cref)) == NULL) 734 goto unk_call; 735 736 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_CONFIRM, msg); 737 msg = NULL; 738 goto out; 739 740 741 case UNIAPI_ALERTING_indication: /* UNI -> API */ 742 ilen = sizeof(struct uniapi_alerting_indication); 743 if (len != ilen) 744 goto bad_len; 745 746 cref = &uni_msg_rptr(msg, struct uniapi_alerting_indication *) 747 ->alerting.hdr.cref; 748 749 if ((conn = find_cref(port, cref)) == NULL) 750 goto unk_call; 751 752 error = cc_conn_sig_msg(conn, CONN_SIG_ALERTING_IND, msg); 753 msg = NULL; 754 goto out; 755 756 757 case UNIAPI_PROCEEDING_indication: /* UNI -> API */ 758 ilen = sizeof(struct uniapi_proceeding_indication); 759 if (len != ilen) 760 goto bad_len; 761 762 cref = &uni_msg_rptr(msg, struct uniapi_proceeding_indication *) 763 ->call_proc.hdr.cref; 764 765 if ((conn = find_cref(port, cref)) == NULL) 766 goto unk_call; 767 768 error = cc_conn_sig_msg(conn, CONN_SIG_PROC_IND, msg); 769 msg = NULL; 770 goto out; 771 772 773 case UNIAPI_SETUP_indication: /* UNI -> API */ 774 ilen = sizeof(struct uniapi_setup_indication); 775 if (len != ilen) 776 goto bad_len; 777 778 cref = &uni_msg_rptr(msg, struct uniapi_setup_indication *) 779 ->setup.hdr.cref; 780 781 if ((conn = find_cref(port, cref)) == NULL) 782 goto unk_call; 783 784 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_IND, msg); 785 msg = NULL; 786 goto out; 787 788 case UNIAPI_SETUP_COMPLETE_indication: /* UNI -> API */ 789 ilen = sizeof(struct uniapi_setup_complete_indication); 790 if (len != ilen) 791 goto bad_len; 792 793 cref = &uni_msg_rptr(msg, 794 struct uniapi_setup_complete_indication *) 795 ->connect_ack.hdr.cref; 796 797 if ((conn = find_cref(port, cref)) == NULL) 798 goto unk_call; 799 800 error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_COMPL, msg); 801 msg = NULL; 802 goto out; 803 804 case UNIAPI_PARTY_ALERTING_indication: /* UNI -> API */ 805 ilen = sizeof(struct uniapi_party_alerting_indication); 806 if (len != ilen) 807 goto bad_len; 808 809 cref = &uni_msg_rptr(msg, 810 struct uniapi_party_alerting_indication *)->alert.hdr.cref; 811 812 if ((conn = find_cref(port, cref)) == NULL) 813 goto unk_call; 814 815 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ALERTING_IND, msg); 816 msg = NULL; 817 goto out; 818 819 case UNIAPI_ADD_PARTY_ACK_indication: /* UNI -> API */ 820 ilen = sizeof(struct uniapi_add_party_ack_indication); 821 if (len != ilen) 822 goto bad_len; 823 824 cref = &uni_msg_rptr(msg, 825 struct uniapi_add_party_ack_indication *)->ack.hdr.cref; 826 827 if ((conn = find_cref(port, cref)) == NULL) 828 goto unk_call; 829 830 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_ACK_IND, msg); 831 msg = NULL; 832 goto out; 833 834 case UNIAPI_ADD_PARTY_REJ_indication: /* UNI -> API */ 835 ilen = sizeof(struct uniapi_add_party_rej_indication); 836 if (len != ilen) 837 goto bad_len; 838 839 cref = &uni_msg_rptr(msg, 840 struct uniapi_add_party_rej_indication *)->rej.hdr.cref; 841 842 if ((conn = find_cref(port, cref)) == NULL) 843 goto unk_call; 844 845 error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_REJ_IND, msg); 846 msg = NULL; 847 goto out; 848 849 case UNIAPI_DROP_PARTY_indication: /* UNI -> API */ 850 ilen = sizeof(struct uniapi_drop_party_indication); 851 if (len != ilen) 852 goto bad_len; 853 854 cref = &uni_msg_rptr(msg, struct uniapi_drop_party_indication *) 855 ->drop.hdr.cref; 856 857 if ((conn = find_cref(port, cref)) == NULL) 858 goto unk_call; 859 860 error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_IND, msg); 861 msg = NULL; 862 goto out; 863 864 case UNIAPI_RESET_confirm: /* UNI -> API */ 865 case UNIAPI_RESET_ERROR_indication: /* UNI -> API */ 866 case UNIAPI_RESET_STATUS_indication: /* UNI -> API */ 867 /* XXX */ 868 goto out; 869 870 case UNIAPI_NOTIFY_indication: /* UNI -> API */ 871 case UNIAPI_STATUS_indication: /* UNI -> API */ 872 break; 873 874 case UNIAPI_ADD_PARTY_indication: /* UNI -> API */ 875 /* not supported by the API */ 876 break; 877 878 /* 879 * All these are illegal in this direction 880 */ 881 case UNIAPI_LINK_ESTABLISH_request: /* API -> UNI */ 882 case UNIAPI_LINK_RELEASE_request: /* API -> UNI */ 883 case UNIAPI_RESET_request: /* API -> UNI */ 884 case UNIAPI_RESET_response: /* API -> UNI */ 885 case UNIAPI_RESET_ERROR_response: /* API -> UNI */ 886 case UNIAPI_SETUP_request: /* API -> UNI */ 887 case UNIAPI_SETUP_response: /* API -> UNI */ 888 case UNIAPI_ALERTING_request: /* API -> UNI */ 889 case UNIAPI_PROCEEDING_request: /* API -> UNI */ 890 case UNIAPI_RELEASE_request: /* API -> UNI */ 891 case UNIAPI_RELEASE_response: /* API -> UNI */ 892 case UNIAPI_NOTIFY_request: /* API -> UNI */ 893 case UNIAPI_STATUS_ENQUIRY_request: /* API -> UNI */ 894 case UNIAPI_ADD_PARTY_request: /* API -> UNI */ 895 case UNIAPI_PARTY_ALERTING_request: /* API -> UNI */ 896 case UNIAPI_ADD_PARTY_ACK_request: /* API -> UNI */ 897 case UNIAPI_ADD_PARTY_REJ_request: /* API -> UNI */ 898 case UNIAPI_DROP_PARTY_request: /* API -> UNI */ 899 case UNIAPI_DROP_PARTY_ACK_request: /* API -> UNI */ 900 case UNIAPI_ABORT_CALL_request: /* API -> UNI */ 901 case UNIAPI_SETUP_COMPLETE_request: /* API -> UNI */ 902 case UNIAPI_MAXSIG: 903 break; 904 } 905 cc_port_log(port, "bad signal %u", sig); 906 error = EINVAL; 907 goto out; 908 909 bad_len: 910 cc_port_log(port, "signal %u bad length: %zu, need %zu", len, ilen); 911 error = EINVAL; 912 goto out; 913 914 unk_call: 915 cc_port_log(port, "unknown call %u/%u", cref->cref, cref->flag); 916 error = EINVAL; 917 918 out: 919 if (msg != NULL) 920 uni_msg_destroy(msg); 921 return (error); 922} 923 924