1131826Sharti/* 2131826Sharti * Copyright (c) 2003-2004 3131826Sharti * Hartmut Brandt 4131826Sharti * All rights reserved. 5131826Sharti * 6131826Sharti * Copyright (c) 2001-2002 7131826Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 8131826Sharti * All rights reserved. 9131826Sharti * 10131826Sharti * Author: Harti Brandt <harti@freebsd.org> 11131826Sharti * 12131826Sharti * Redistribution of this software and documentation and use in source and 13131826Sharti * binary forms, with or without modification, are permitted provided that 14131826Sharti * the following conditions are met: 15131826Sharti * 16131826Sharti * 1. Redistributions of source code or documentation must retain the above 17131826Sharti * copyright notice, this list of conditions and the following disclaimer. 18131826Sharti * 2. Redistributions in binary form must reproduce the above copyright 19131826Sharti * notice, this list of conditions and the following disclaimer in the 20131826Sharti * documentation and/or other materials provided with the distribution. 21131826Sharti * 22131826Sharti * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR 23131826Sharti * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 24131826Sharti * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 25131826Sharti * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 26131826Sharti * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27131826Sharti * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28131826Sharti * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 29131826Sharti * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30131826Sharti * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31131826Sharti * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 32131826Sharti * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33131826Sharti * 34131826Sharti * $Begemot: libunimsg/netnatm/api/cc_port.c,v 1.1 2004/07/08 08:21:53 brandt Exp $ 35131826Sharti * 36131826Sharti * ATM API as defined per af-saa-0108 37131826Sharti * 38131826Sharti * Port-global stuff (ILMI and Co.) 39131826Sharti */ 40131826Sharti#include <netnatm/unimsg.h> 41131826Sharti#include <netnatm/msg/unistruct.h> 42131826Sharti#include <netnatm/api/unisap.h> 43131826Sharti#include <netnatm/sig/unidef.h> 44131826Sharti#include <netnatm/api/atmapi.h> 45131826Sharti#include <netnatm/api/ccatm.h> 46131826Sharti#include <netnatm/api/ccpriv.h> 47131826Sharti 48131826Sharti/* 49131826Sharti * Find a port with a given number 50131826Sharti */ 51131826Shartistatic struct ccport * 52131826Shartifind_port(struct ccdata *cc, u_int portno) 53131826Sharti{ 54131826Sharti struct ccport *port; 55131826Sharti 56131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) 57131826Sharti if (port->param.port == portno) 58131826Sharti return (port); 59131826Sharti return (NULL); 60131826Sharti} 61131826Sharti 62131826Sharti/* 63131826Sharti * Create a new port structure, initialize it and link it to the node. 64131826Sharti * Returns 0 on success, an errno otherwise. 65131826Sharti */ 66131826Shartistruct ccport * 67131826Sharticc_port_create(struct ccdata *cc, void *uarg, u_int portno) 68131826Sharti{ 69131826Sharti struct ccport *port, *p1; 70131826Sharti 71131826Sharti if (portno == 0 || portno > 0xffffffff) 72131826Sharti return (NULL); 73131826Sharti 74131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) 75131826Sharti if (port->param.port == portno) 76131826Sharti return (NULL); 77131826Sharti 78131826Sharti port = CCZALLOC(sizeof(*port)); 79131826Sharti if (port == NULL) 80131826Sharti return (NULL); 81131826Sharti 82131826Sharti port->uarg = uarg; 83131826Sharti port->cc = cc; 84131826Sharti port->admin = CCPORT_STOPPED; 85131826Sharti LIST_INIT(&port->conn_list); 86131826Sharti TAILQ_INIT(&port->addr_list); 87131826Sharti port->param.port = portno; 88131826Sharti port->param.pcr = 350053; 89131826Sharti port->param.max_vpi_bits = 0; 90131826Sharti port->param.max_vci_bits = 8; 91131826Sharti port->param.max_svpc_vpi = 0; 92131826Sharti port->param.max_svcc_vpi = 0; 93131826Sharti port->param.min_svcc_vci = 32; 94131826Sharti port->param.num_addrs = 0; 95131826Sharti TAILQ_INIT(&port->cookies); 96131826Sharti 97131826Sharti TAILQ_FOREACH(p1, &cc->port_list, node_link) 98131826Sharti if (p1->param.port > portno) { 99131826Sharti TAILQ_INSERT_BEFORE(p1, port, node_link); 100131826Sharti break; 101131826Sharti } 102131826Sharti if (p1 == NULL) 103131826Sharti TAILQ_INSERT_TAIL(&cc->port_list, port, node_link); 104131826Sharti 105131826Sharti return (port); 106131826Sharti} 107131826Sharti 108131826Sharti/* 109131826Sharti * Destroy a port. This closes all connections and aborts all the users of 110131826Sharti * these connections. 111131826Sharti * This should be called only after work has returned so that no signals 112131826Sharti * are pending. 113131826Sharti */ 114131826Shartivoid 115131826Sharticc_port_destroy(struct ccport *port, int shutdown) 116131826Sharti{ 117131826Sharti struct ccaddr *addr; 118131826Sharti struct ccreq *r; 119131826Sharti 120131826Sharti TAILQ_REMOVE(&port->cc->port_list, port, node_link); 121131826Sharti 122131826Sharti while ((r = TAILQ_FIRST(&port->cookies)) != NULL) { 123131826Sharti TAILQ_REMOVE(&port->cookies, r, link); 124131826Sharti CCFREE(r); 125131826Sharti } 126131826Sharti 127131826Sharti /* 128131826Sharti * Abort all connections. 129131826Sharti */ 130131826Sharti while (!LIST_EMPTY(&port->conn_list)) 131131826Sharti cc_conn_abort(LIST_FIRST(&port->conn_list), shutdown); 132131826Sharti 133131826Sharti /* 134131826Sharti * Free addresses. 135131826Sharti */ 136131826Sharti while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 137131826Sharti TAILQ_REMOVE(&port->addr_list, addr, port_link); 138131826Sharti CCFREE(addr); 139131826Sharti } 140131826Sharti 141131826Sharti CCFREE(port); 142131826Sharti} 143131826Sharti 144131826Sharti/* 145131826Sharti * Management is given up on this node. Remove all addresses from the port. 146131826Sharti */ 147131826Shartivoid 148131826Sharticc_unmanage(struct ccdata *cc) 149131826Sharti{ 150131826Sharti struct ccport *port; 151131826Sharti struct ccaddr *addr; 152131826Sharti 153131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) { 154131826Sharti while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 155131826Sharti TAILQ_REMOVE(&port->addr_list, addr, port_link); 156131826Sharti CCFREE(addr); 157131826Sharti } 158131826Sharti } 159131826Sharti} 160131826Sharti 161131826Sharti/* 162131826Sharti * Compare two addresses 163131826Sharti */ 164131826Shartistatic __inline int 165131826Shartiaddr_eq(const struct uni_addr *a1, const struct uni_addr *a2) 166131826Sharti{ 167131826Sharti return (a1->type == a2->type && a1->plan == a2->plan && 168131826Sharti a1->len == a2->len && memcmp(a1->addr, a2->addr, a1->len) == 0); 169131826Sharti} 170131826Sharti 171131826Sharti 172131826Sharti/* 173131826Sharti * retrieve addresses 174131826Sharti */ 175131826Shartiint 176131826Sharticc_get_addrs(struct ccdata *cc, u_int portno, 177131826Sharti struct uni_addr **pa, u_int **ports, u_int *count) 178131826Sharti{ 179131826Sharti struct ccport *port = NULL; 180131826Sharti struct ccaddr *addr; 181131826Sharti struct uni_addr *buf, *ptr; 182131826Sharti u_int *pports; 183131826Sharti 184131826Sharti /* 185131826Sharti * If a port number is specified and the port does not exist, 186131826Sharti * return an error. 187131826Sharti */ 188131826Sharti if (portno != 0) 189131826Sharti if ((port = find_port(cc, portno)) == NULL) 190131826Sharti return (ENOENT); 191131826Sharti 192131826Sharti /* 193131826Sharti * Count the addresses 194131826Sharti */ 195131826Sharti *count = 0; 196131826Sharti if (portno != 0) { 197131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) 198131826Sharti (*count)++; 199131826Sharti } else { 200131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) 201131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) 202131826Sharti (*count)++; 203131826Sharti } 204131826Sharti 205131826Sharti buf = CCMALLOC(*count * sizeof(struct uni_addr)); 206131826Sharti if (buf == NULL) 207131826Sharti return (ENOMEM); 208131826Sharti ptr = buf; 209131826Sharti 210131826Sharti *ports = CCMALLOC(*count * sizeof(u_int)); 211131826Sharti if (*ports == NULL) { 212131826Sharti CCFREE(buf); 213131826Sharti return (ENOMEM); 214131826Sharti } 215131826Sharti pports = *ports; 216131826Sharti 217131826Sharti if (portno != 0) { 218131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) { 219131826Sharti *ptr++ = addr->addr; 220131826Sharti *pports++ = portno; 221131826Sharti } 222131826Sharti } else { 223131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) 224131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) { 225131826Sharti *ptr++ = addr->addr; 226131826Sharti *pports++ = port->param.port; 227131826Sharti } 228131826Sharti } 229131826Sharti 230131826Sharti *pa = buf; 231131826Sharti return (0); 232131826Sharti} 233131826Sharti 234131826Sharti/* 235131826Sharti * return port number 236131826Sharti */ 237131826Shartiu_int 238131826Sharticc_port_no(struct ccport *port) 239131826Sharti{ 240131826Sharti return (port->param.port); 241131826Sharti} 242131826Sharti 243131826Sharti/* 244131826Sharti * Address unregisterd. 245131826Sharti */ 246131826Shartiint 247131826Sharticc_addr_unregister(struct ccdata *cc, u_int portno, const struct uni_addr *arg) 248131826Sharti{ 249131826Sharti struct ccport *port; 250131826Sharti struct ccaddr *a; 251131826Sharti 252131826Sharti if ((port = find_port(cc, portno)) == NULL) 253131826Sharti return (ENOENT); 254131826Sharti 255131826Sharti /* Find the address */ 256131826Sharti TAILQ_FOREACH(a, &port->addr_list, port_link) 257131826Sharti if (addr_eq(arg, &a->addr)) { 258131826Sharti TAILQ_REMOVE(&port->addr_list, a, port_link); 259131826Sharti CCFREE(a); 260131826Sharti return (0); 261131826Sharti } 262131826Sharti 263131826Sharti return (ENOENT); 264131826Sharti} 265131826Sharti 266131826Sharti/* 267131826Sharti * Address registerd. 268131826Sharti */ 269131826Shartiint 270131826Sharticc_addr_register(struct ccdata *cc, u_int portno, const struct uni_addr *arg) 271131826Sharti{ 272131826Sharti struct ccport *port, *p1; 273131826Sharti struct ccaddr *a; 274131826Sharti 275131826Sharti if ((port = find_port(cc, portno)) == NULL) 276131826Sharti return (ENOENT); 277131826Sharti 278131826Sharti /* maybe we know it already? */ 279131826Sharti TAILQ_FOREACH(p1, &port->cc->port_list, node_link) 280131826Sharti TAILQ_FOREACH(a, &p1->addr_list, port_link) 281131826Sharti if (addr_eq(arg, &a->addr)) 282131826Sharti return (EISCONN); 283131826Sharti 284131826Sharti a = CCZALLOC(sizeof(*a)); 285131826Sharti if (a == NULL) 286131826Sharti return (ENOMEM); 287131826Sharti a->addr = *arg; 288131826Sharti 289131826Sharti TAILQ_INSERT_TAIL(&port->addr_list, a, port_link); 290131826Sharti 291131826Sharti return (0); 292131826Sharti} 293131826Sharti 294131826Sharti/* 295131826Sharti * Set/get port parameters. 296131826Sharti */ 297131826Shartiint 298131826Sharticc_port_get_param(struct ccdata *cc, u_int portno, 299131826Sharti struct atm_port_info *param) 300131826Sharti{ 301131826Sharti struct ccport *port; 302131826Sharti 303131826Sharti if ((port = find_port(cc, portno)) == NULL) 304131826Sharti return (ENOENT); 305131826Sharti 306131826Sharti *param = port->param; 307131826Sharti return (0); 308131826Sharti} 309131826Sharti 310131826Sharti/* XXX maybe allow only in stopped. */ 311131826Shartiint 312131826Sharticc_port_set_param(struct ccdata *cc, const struct atm_port_info *param) 313131826Sharti{ 314131826Sharti struct ccport *port; 315131826Sharti struct ccaddr *addr; 316131826Sharti 317131826Sharti if ((port = find_port(cc, param->port)) == NULL) 318131826Sharti return (ENOENT); 319131826Sharti 320131826Sharti port->param = *param; 321131826Sharti 322131826Sharti port->param.num_addrs = 0; 323131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) 324131826Sharti port->param.num_addrs++; 325131826Sharti 326131826Sharti return (0); 327131826Sharti} 328131826Sharti 329131826Sharti/* 330131826Sharti * get port list 331131826Sharti */ 332131826Shartiint 333131826Sharticc_port_getlist(struct ccdata *cc, u_int *cnt, u_int **ports) 334131826Sharti{ 335131826Sharti struct ccport *p; 336131826Sharti u_int n; 337131826Sharti 338131826Sharti n = 0; 339131826Sharti TAILQ_FOREACH(p, &cc->port_list, node_link) 340131826Sharti n++; 341131826Sharti 342131826Sharti *ports = CCMALLOC(n * sizeof(u_int)); 343131826Sharti if (*ports == NULL) 344131826Sharti return (ENOMEM); 345131826Sharti 346131826Sharti n = 0; 347131826Sharti TAILQ_FOREACH(p, &cc->port_list, node_link) 348131826Sharti (*ports)[n++] = p->param.port; 349131826Sharti *cnt = n; 350131826Sharti 351131826Sharti return (0); 352131826Sharti} 353131826Sharti 354131826Sharti/* 355131826Sharti * START and STOP signalling 356131826Sharti */ 357131826Shartiint 358131826Sharticc_port_start(struct ccdata *cc, u_int portno) 359131826Sharti{ 360131826Sharti struct ccport *port; 361131826Sharti 362131826Sharti if ((port = find_port(cc, portno)) == NULL) 363131826Sharti return (ENOENT); 364131826Sharti if (port->admin != CCPORT_STOPPED) 365131826Sharti return (EISCONN); 366131826Sharti 367131826Sharti cc->funcs->send_uni_glob(port, port->uarg, 368131826Sharti UNIAPI_LINK_ESTABLISH_request, 0, NULL); 369131826Sharti port->admin = CCPORT_RUNNING; 370131826Sharti 371131826Sharti return (0); 372131826Sharti} 373131826Sharti 374131826Shartiint 375131826Sharticc_port_stop(struct ccdata *cc, u_int portno) 376131826Sharti{ 377131826Sharti struct ccport *port; 378131826Sharti 379131826Sharti if ((port = find_port(cc, portno)) == NULL) 380131826Sharti return (ENOENT); 381131826Sharti if (port->admin != CCPORT_RUNNING) 382131826Sharti return (ENOTCONN); 383131826Sharti 384131826Sharti port->admin = CCPORT_STOPPED; 385131826Sharti 386131826Sharti /* 387131826Sharti * Abort all connections. 388131826Sharti */ 389131826Sharti while (!LIST_EMPTY(&port->conn_list)) 390131826Sharti cc_conn_destroy(LIST_FIRST(&port->conn_list)); 391131826Sharti 392131826Sharti return (0); 393131826Sharti} 394131826Sharti 395131826Sharti/* 396131826Sharti * is port running? 397131826Sharti */ 398131826Shartiint 399131826Sharticc_port_isrunning(struct ccdata *cc, u_int portno, int *state) 400131826Sharti{ 401131826Sharti struct ccport *port; 402131826Sharti 403131826Sharti if ((port = find_port(cc, portno)) == NULL) 404131826Sharti return (ENOENT); 405131826Sharti if (port->admin == CCPORT_RUNNING) 406131826Sharti *state = 1; 407131826Sharti else 408131826Sharti *state = 0; 409131826Sharti return (0); 410131826Sharti} 411131826Sharti 412131826Sharti/* 413131826Sharti * Clear address and prefix information from the named port. 414131826Sharti */ 415131826Shartiint 416131826Sharticc_port_clear(struct ccdata *cc, u_int portno) 417131826Sharti{ 418131826Sharti struct ccaddr *addr; 419131826Sharti struct ccport *port; 420131826Sharti 421131826Sharti if ((port = find_port(cc, portno)) == NULL) 422131826Sharti return (ENOENT); 423131826Sharti 424131826Sharti while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { 425131826Sharti TAILQ_REMOVE(&port->addr_list, addr, port_link); 426131826Sharti CCFREE(addr); 427131826Sharti } 428131826Sharti return (0); 429131826Sharti} 430131826Sharti 431131826Sharti/* 432131826Sharti * retrieve info on local ports 433131826Sharti */ 434131826Shartistruct atm_port_list * 435131826Sharticc_get_local_port_info(struct ccdata *cc, u_int portno, size_t *lenp) 436131826Sharti{ 437131826Sharti struct atm_port_list *list; 438131826Sharti struct atm_port_info *pp; 439131826Sharti struct uni_addr *aa; 440131826Sharti struct ccaddr *addr; 441131826Sharti struct ccport *port; 442131826Sharti u_int nports, naddrs; 443131826Sharti 444131826Sharti /* 445131826Sharti * Count ports and addresses. 446131826Sharti */ 447131826Sharti nports = 0; 448131826Sharti naddrs = 0; 449131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) { 450131826Sharti if (portno == 0 || port->param.port == portno) { 451131826Sharti nports++; 452131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) 453131826Sharti naddrs++; 454131826Sharti } 455131826Sharti } 456131826Sharti 457131826Sharti /* 458131826Sharti * Size and allocate message 459131826Sharti */ 460131826Sharti *lenp = sizeof(*list) + nports * sizeof(*pp) + naddrs * sizeof(*aa); 461131826Sharti 462131826Sharti list = CCZALLOC(*lenp); 463131826Sharti if (list == NULL) 464131826Sharti return (NULL); 465131826Sharti 466131826Sharti /* 467131826Sharti * Fill the message. 468131826Sharti */ 469131826Sharti list->num_ports = nports; 470131826Sharti list->num_addrs = naddrs; 471131826Sharti 472131826Sharti pp = (void *)((u_char *)list + sizeof(*list)); 473131826Sharti aa = (void *)((u_char *)list + sizeof(*list) + nports * sizeof(*pp)); 474131826Sharti 475131826Sharti TAILQ_FOREACH(port, &cc->port_list, node_link) { 476131826Sharti if (portno == 0 || port->param.port == portno) { 477131826Sharti *pp = port->param; 478131826Sharti pp->num_addrs = 0; 479131826Sharti TAILQ_FOREACH(addr, &port->addr_list, port_link) { 480131826Sharti *aa++ = addr->addr; 481131826Sharti pp->num_addrs++; 482131826Sharti } 483131826Sharti pp++; 484131826Sharti } 485131826Sharti } 486131826Sharti 487131826Sharti return (list); 488131826Sharti} 489131826Sharti 490131826Shartistatic struct ccreq * 491131826Shartifind_cookie(struct ccport *port, u_int cookie) 492131826Sharti{ 493131826Sharti struct ccreq *r; 494131826Sharti 495131826Sharti TAILQ_FOREACH(r, &port->cookies, link) 496131826Sharti if (r->cookie == cookie) 497131826Sharti return (r); 498131826Sharti return (NULL); 499131826Sharti} 500131826Sharti 501131826Sharti/* 502131826Sharti * input a response from the UNI layer to CC 503131826Sharti */ 504131826Shartiint 505131826Sharticc_uni_response(struct ccport *port, u_int cookie, u_int reason, u_int state) 506131826Sharti{ 507131826Sharti struct ccconn *conn; 508131826Sharti struct ccreq *req; 509131826Sharti 510131826Sharti if (cookie == 0) 511131826Sharti return (EINVAL); 512131826Sharti 513131826Sharti if (port->admin != CCPORT_RUNNING) 514131826Sharti return (ENOTCONN); 515131826Sharti 516131826Sharti if ((req = find_cookie(port, cookie)) == NULL) { 517131826Sharti cc_port_log(port, "UNI response for unknown cookie %u", cookie); 518131826Sharti return (EINVAL); 519131826Sharti } 520131826Sharti conn = req->conn; 521131826Sharti 522131826Sharti TAILQ_REMOVE(&port->cookies, req, link); 523131826Sharti CCFREE(req); 524131826Sharti 525131826Sharti if (reason == UNIAPI_OK) 526131826Sharti return (cc_conn_resp(conn, CONN_SIG_OK, 527131826Sharti cookie, reason, state)); 528131826Sharti else 529131826Sharti return (cc_conn_resp(conn, CONN_SIG_ERROR, 530131826Sharti cookie, reason, state)); 531131826Sharti} 532131826Sharti 533131826Shartistatic struct ccconn * 534131826Shartifind_cref(const struct ccport *port, const struct uni_cref *cref) 535131826Sharti{ 536131826Sharti struct ccconn *conn; 537131826Sharti 538131826Sharti LIST_FOREACH(conn, &port->conn_list, port_link) 539131826Sharti if (conn->cref.cref == cref->cref && 540131826Sharti conn->cref.flag == cref->flag) 541131826Sharti return (conn); 542131826Sharti return (NULL); 543131826Sharti} 544131826Sharti 545131826Sharti/* 546131826Sharti * Signal from UNI on this port 547131826Sharti */ 548131826Shartiint 549131826Sharticc_uni_signal(struct ccport *port, u_int cookie, u_int sig, struct uni_msg *msg) 550131826Sharti{ 551131826Sharti int error = 0; 552131826Sharti size_t len, ilen = 0; 553131826Sharti struct uni_cref *cref; 554131826Sharti struct ccconn *conn; 555131826Sharti 556131826Sharti if (port->admin != CCPORT_RUNNING) { 557131826Sharti error = ENOTCONN; 558131826Sharti goto out; 559131826Sharti } 560131826Sharti len = (msg != NULL) ? uni_msg_len(msg) : 0; 561131826Sharti 562131826Sharti switch ((enum uni_sig)sig) { 563131826Sharti 564131826Sharti case UNIAPI_ERROR: 565131826Sharti /* handled above */ 566131826Sharti cc_port_log(port, "bad UNIAPI_ERROR cookie=%u", cookie); 567131826Sharti error = EINVAL; 568131826Sharti break; 569131826Sharti 570131826Sharti case UNIAPI_CALL_CREATED: 571131826Sharti ilen = sizeof(struct uniapi_call_created); 572131826Sharti if (len != ilen) 573131826Sharti goto bad_len; 574131826Sharti 575131826Sharti if (cookie != 0) { 576131826Sharti /* outgoing call */ 577131826Sharti struct ccreq *req; 578131826Sharti 579131826Sharti if ((req = find_cookie(port, cookie)) == NULL) { 580131826Sharti cc_port_log(port, "bad cookie %u in CREATE", 581131826Sharti cookie); 582131826Sharti error = EINVAL; 583131826Sharti goto out; 584131826Sharti } 585131826Sharti conn = req->conn; 586131826Sharti 587131826Sharti } else { 588131826Sharti if ((conn = cc_conn_create(port->cc)) == NULL) { 589131826Sharti error = ENOMEM; 590131826Sharti goto out; 591131826Sharti } 592131826Sharti cc_conn_ins_port(conn, port); 593131826Sharti } 594131826Sharti 595131826Sharti cc_conn_sig_msg_nodef(conn, CONN_SIG_CREATED, msg); 596131826Sharti msg = NULL; 597131826Sharti goto out; 598131826Sharti 599131826Sharti case UNIAPI_CALL_DESTROYED: 600131826Sharti ilen = sizeof(struct uniapi_call_destroyed); 601131826Sharti if (len != ilen) 602131826Sharti goto bad_len; 603131826Sharti 604131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_call_destroyed *)->cref; 605131826Sharti if ((conn = find_cref(port, cref)) == NULL) 606131826Sharti goto unk_call; 607131826Sharti 608131826Sharti error = cc_conn_sig(conn, CONN_SIG_DESTROYED, NULL); 609131826Sharti goto out; 610131826Sharti 611131826Sharti case UNIAPI_LINK_ESTABLISH_confirm: 612131826Sharti goto out; 613131826Sharti 614131826Sharti case UNIAPI_LINK_RELEASE_confirm: 615131826Sharti /* Ups. If we administratively up, restart the link */ 616131826Sharti if (port->admin == CCPORT_RUNNING) 617131826Sharti port->cc->funcs->send_uni_glob(port, port->uarg, 618131826Sharti UNIAPI_LINK_ESTABLISH_request, 0, NULL); 619131826Sharti goto out; 620131826Sharti 621131826Sharti case UNIAPI_PARTY_CREATED: 622131826Sharti ilen = sizeof(struct uniapi_party_created); 623131826Sharti if (len != ilen) 624131826Sharti goto bad_len; 625131826Sharti 626131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_party_created *)->cref; 627131826Sharti 628131826Sharti if ((conn = find_cref(port, cref)) == NULL) 629131826Sharti goto unk_call; 630131826Sharti 631131826Sharti error = cc_conn_sig_msg_nodef(conn, 632131826Sharti CONN_SIG_PARTY_CREATED, msg); 633131826Sharti msg = NULL; 634131826Sharti goto out; 635131826Sharti 636131826Sharti case UNIAPI_PARTY_DESTROYED: 637131826Sharti ilen = sizeof(struct uniapi_party_destroyed); 638131826Sharti if (len != ilen) 639131826Sharti goto bad_len; 640131826Sharti 641131826Sharti cref = &uni_msg_rptr(msg, 642131826Sharti struct uniapi_party_destroyed *)->cref; 643131826Sharti 644131826Sharti if ((conn = find_cref(port, cref)) == NULL) 645131826Sharti goto unk_call; 646131826Sharti 647131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_DESTROYED, msg); 648131826Sharti msg = NULL; 649131826Sharti goto out; 650131826Sharti 651131826Sharti case UNIAPI_DROP_PARTY_ACK_indication: /* UNI -> API */ 652131826Sharti ilen = sizeof(struct uniapi_drop_party_ack_indication); 653131826Sharti if (len != ilen) 654131826Sharti goto bad_len; 655131826Sharti 656131826Sharti cref = &uni_msg_rptr(msg, 657131826Sharti struct uniapi_drop_party_ack_indication *)->drop.hdr.cref; 658131826Sharti 659131826Sharti if ((conn = find_cref(port, cref)) == NULL) 660131826Sharti goto unk_call; 661131826Sharti 662131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_ACK_IND, msg); 663131826Sharti msg = NULL; 664131826Sharti goto out; 665131826Sharti 666131826Sharti case UNIAPI_RESET_indication: /* UNI -> API */ 667131826Sharti { 668131826Sharti /* 669131826Sharti * XXX - do the right thing 670131826Sharti */ 671131826Sharti struct uniapi_reset_indication *ind = uni_msg_rptr(msg, 672131826Sharti struct uniapi_reset_indication *); 673131826Sharti struct uniapi_reset_response *resp; 674131826Sharti struct uni_msg *u; 675131826Sharti 676131826Sharti /* 677131826Sharti * Construct message to UNI. 678131826Sharti */ 679131826Sharti if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) 680131826Sharti return (ENOMEM); 681131826Sharti 682131826Sharti resp = uni_msg_wptr(u, struct uniapi_reset_response *); 683131826Sharti memset(resp, 0, sizeof(*resp)); 684131826Sharti u->b_wptr += sizeof(*resp); 685131826Sharti 686131826Sharti resp->restart = ind->restart; 687131826Sharti resp->connid = ind->connid; 688131826Sharti 689131826Sharti port->cc->funcs->send_uni_glob(port, port->uarg, 690131826Sharti UNIAPI_RESET_response, 0, u); 691131826Sharti 692131826Sharti goto out; 693131826Sharti } 694131826Sharti 695131826Sharti case UNIAPI_RELEASE_indication: /* UNI -> API */ 696131826Sharti ilen = sizeof(struct uniapi_release_indication); 697131826Sharti if (len != ilen) 698131826Sharti goto bad_len; 699131826Sharti 700131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_release_indication *) 701131826Sharti ->release.hdr.cref; 702131826Sharti 703131826Sharti if ((conn = find_cref(port, cref)) == NULL) 704131826Sharti goto unk_call; 705131826Sharti 706131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_REL_IND, msg); 707131826Sharti msg = NULL; 708131826Sharti goto out; 709131826Sharti 710131826Sharti case UNIAPI_RELEASE_confirm: /* UNI -> API */ 711131826Sharti ilen = sizeof(struct uniapi_release_confirm); 712131826Sharti if (len != ilen) 713131826Sharti goto bad_len; 714131826Sharti 715131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_release_confirm *) 716131826Sharti ->release.hdr.cref; 717131826Sharti 718131826Sharti if ((conn = find_cref(port, cref)) == NULL) 719131826Sharti goto unk_call; 720131826Sharti 721131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_REL_CONF, msg); 722131826Sharti msg = NULL; 723131826Sharti goto out; 724131826Sharti 725131826Sharti case UNIAPI_SETUP_confirm: /* UNI -> API */ 726131826Sharti ilen = sizeof(struct uniapi_setup_confirm); 727131826Sharti if (len != ilen) 728131826Sharti goto bad_len; 729131826Sharti 730131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_setup_confirm *) 731131826Sharti ->connect.hdr.cref; 732131826Sharti 733131826Sharti if ((conn = find_cref(port, cref)) == NULL) 734131826Sharti goto unk_call; 735131826Sharti 736131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_CONFIRM, msg); 737131826Sharti msg = NULL; 738131826Sharti goto out; 739131826Sharti 740131826Sharti 741131826Sharti case UNIAPI_ALERTING_indication: /* UNI -> API */ 742131826Sharti ilen = sizeof(struct uniapi_alerting_indication); 743131826Sharti if (len != ilen) 744131826Sharti goto bad_len; 745131826Sharti 746131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_alerting_indication *) 747131826Sharti ->alerting.hdr.cref; 748131826Sharti 749131826Sharti if ((conn = find_cref(port, cref)) == NULL) 750131826Sharti goto unk_call; 751131826Sharti 752131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_ALERTING_IND, msg); 753131826Sharti msg = NULL; 754131826Sharti goto out; 755131826Sharti 756131826Sharti 757131826Sharti case UNIAPI_PROCEEDING_indication: /* UNI -> API */ 758131826Sharti ilen = sizeof(struct uniapi_proceeding_indication); 759131826Sharti if (len != ilen) 760131826Sharti goto bad_len; 761131826Sharti 762131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_proceeding_indication *) 763131826Sharti ->call_proc.hdr.cref; 764131826Sharti 765131826Sharti if ((conn = find_cref(port, cref)) == NULL) 766131826Sharti goto unk_call; 767131826Sharti 768131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_PROC_IND, msg); 769131826Sharti msg = NULL; 770131826Sharti goto out; 771131826Sharti 772131826Sharti 773131826Sharti case UNIAPI_SETUP_indication: /* UNI -> API */ 774131826Sharti ilen = sizeof(struct uniapi_setup_indication); 775131826Sharti if (len != ilen) 776131826Sharti goto bad_len; 777131826Sharti 778131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_setup_indication *) 779131826Sharti ->setup.hdr.cref; 780131826Sharti 781131826Sharti if ((conn = find_cref(port, cref)) == NULL) 782131826Sharti goto unk_call; 783131826Sharti 784131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_IND, msg); 785131826Sharti msg = NULL; 786131826Sharti goto out; 787131826Sharti 788131826Sharti case UNIAPI_SETUP_COMPLETE_indication: /* UNI -> API */ 789131826Sharti ilen = sizeof(struct uniapi_setup_complete_indication); 790131826Sharti if (len != ilen) 791131826Sharti goto bad_len; 792131826Sharti 793131826Sharti cref = &uni_msg_rptr(msg, 794131826Sharti struct uniapi_setup_complete_indication *) 795131826Sharti ->connect_ack.hdr.cref; 796131826Sharti 797131826Sharti if ((conn = find_cref(port, cref)) == NULL) 798131826Sharti goto unk_call; 799131826Sharti 800131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_COMPL, msg); 801131826Sharti msg = NULL; 802131826Sharti goto out; 803131826Sharti 804131826Sharti case UNIAPI_PARTY_ALERTING_indication: /* UNI -> API */ 805131826Sharti ilen = sizeof(struct uniapi_party_alerting_indication); 806131826Sharti if (len != ilen) 807131826Sharti goto bad_len; 808131826Sharti 809131826Sharti cref = &uni_msg_rptr(msg, 810131826Sharti struct uniapi_party_alerting_indication *)->alert.hdr.cref; 811131826Sharti 812131826Sharti if ((conn = find_cref(port, cref)) == NULL) 813131826Sharti goto unk_call; 814131826Sharti 815131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ALERTING_IND, msg); 816131826Sharti msg = NULL; 817131826Sharti goto out; 818131826Sharti 819131826Sharti case UNIAPI_ADD_PARTY_ACK_indication: /* UNI -> API */ 820131826Sharti ilen = sizeof(struct uniapi_add_party_ack_indication); 821131826Sharti if (len != ilen) 822131826Sharti goto bad_len; 823131826Sharti 824131826Sharti cref = &uni_msg_rptr(msg, 825131826Sharti struct uniapi_add_party_ack_indication *)->ack.hdr.cref; 826131826Sharti 827131826Sharti if ((conn = find_cref(port, cref)) == NULL) 828131826Sharti goto unk_call; 829131826Sharti 830131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_ACK_IND, msg); 831131826Sharti msg = NULL; 832131826Sharti goto out; 833131826Sharti 834131826Sharti case UNIAPI_ADD_PARTY_REJ_indication: /* UNI -> API */ 835131826Sharti ilen = sizeof(struct uniapi_add_party_rej_indication); 836131826Sharti if (len != ilen) 837131826Sharti goto bad_len; 838131826Sharti 839131826Sharti cref = &uni_msg_rptr(msg, 840131826Sharti struct uniapi_add_party_rej_indication *)->rej.hdr.cref; 841131826Sharti 842131826Sharti if ((conn = find_cref(port, cref)) == NULL) 843131826Sharti goto unk_call; 844131826Sharti 845131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_REJ_IND, msg); 846131826Sharti msg = NULL; 847131826Sharti goto out; 848131826Sharti 849131826Sharti case UNIAPI_DROP_PARTY_indication: /* UNI -> API */ 850131826Sharti ilen = sizeof(struct uniapi_drop_party_indication); 851131826Sharti if (len != ilen) 852131826Sharti goto bad_len; 853131826Sharti 854131826Sharti cref = &uni_msg_rptr(msg, struct uniapi_drop_party_indication *) 855131826Sharti ->drop.hdr.cref; 856131826Sharti 857131826Sharti if ((conn = find_cref(port, cref)) == NULL) 858131826Sharti goto unk_call; 859131826Sharti 860131826Sharti error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_IND, msg); 861131826Sharti msg = NULL; 862131826Sharti goto out; 863131826Sharti 864131826Sharti case UNIAPI_RESET_confirm: /* UNI -> API */ 865131826Sharti case UNIAPI_RESET_ERROR_indication: /* UNI -> API */ 866131826Sharti case UNIAPI_RESET_STATUS_indication: /* UNI -> API */ 867131826Sharti /* XXX */ 868131826Sharti goto out; 869131826Sharti 870131826Sharti case UNIAPI_NOTIFY_indication: /* UNI -> API */ 871131826Sharti case UNIAPI_STATUS_indication: /* UNI -> API */ 872131826Sharti break; 873131826Sharti 874131826Sharti case UNIAPI_ADD_PARTY_indication: /* UNI -> API */ 875131826Sharti /* not supported by the API */ 876131826Sharti break; 877131826Sharti 878131826Sharti /* 879131826Sharti * All these are illegal in this direction 880131826Sharti */ 881131826Sharti case UNIAPI_LINK_ESTABLISH_request: /* API -> UNI */ 882131826Sharti case UNIAPI_LINK_RELEASE_request: /* API -> UNI */ 883131826Sharti case UNIAPI_RESET_request: /* API -> UNI */ 884131826Sharti case UNIAPI_RESET_response: /* API -> UNI */ 885131826Sharti case UNIAPI_RESET_ERROR_response: /* API -> UNI */ 886131826Sharti case UNIAPI_SETUP_request: /* API -> UNI */ 887131826Sharti case UNIAPI_SETUP_response: /* API -> UNI */ 888131826Sharti case UNIAPI_ALERTING_request: /* API -> UNI */ 889131826Sharti case UNIAPI_PROCEEDING_request: /* API -> UNI */ 890131826Sharti case UNIAPI_RELEASE_request: /* API -> UNI */ 891131826Sharti case UNIAPI_RELEASE_response: /* API -> UNI */ 892131826Sharti case UNIAPI_NOTIFY_request: /* API -> UNI */ 893131826Sharti case UNIAPI_STATUS_ENQUIRY_request: /* API -> UNI */ 894131826Sharti case UNIAPI_ADD_PARTY_request: /* API -> UNI */ 895131826Sharti case UNIAPI_PARTY_ALERTING_request: /* API -> UNI */ 896131826Sharti case UNIAPI_ADD_PARTY_ACK_request: /* API -> UNI */ 897131826Sharti case UNIAPI_ADD_PARTY_REJ_request: /* API -> UNI */ 898131826Sharti case UNIAPI_DROP_PARTY_request: /* API -> UNI */ 899131826Sharti case UNIAPI_DROP_PARTY_ACK_request: /* API -> UNI */ 900131826Sharti case UNIAPI_ABORT_CALL_request: /* API -> UNI */ 901131826Sharti case UNIAPI_SETUP_COMPLETE_request: /* API -> UNI */ 902131826Sharti case UNIAPI_MAXSIG: 903131826Sharti break; 904131826Sharti } 905131826Sharti cc_port_log(port, "bad signal %u", sig); 906131826Sharti error = EINVAL; 907131826Sharti goto out; 908131826Sharti 909131826Sharti bad_len: 910131826Sharti cc_port_log(port, "signal %u bad length: %zu, need %zu", len, ilen); 911131826Sharti error = EINVAL; 912131826Sharti goto out; 913131826Sharti 914131826Sharti unk_call: 915131826Sharti cc_port_log(port, "unknown call %u/%u", cref->cref, cref->flag); 916131826Sharti error = EINVAL; 917131826Sharti 918131826Sharti out: 919131826Sharti if (msg != NULL) 920131826Sharti uni_msg_destroy(msg); 921131826Sharti return (error); 922131826Sharti} 923131826Sharti 924