diff options
Diffstat (limited to 'sys/contrib/ngatm/netnatm/api/cc_port.c')
-rw-r--r-- | sys/contrib/ngatm/netnatm/api/cc_port.c | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/sys/contrib/ngatm/netnatm/api/cc_port.c b/sys/contrib/ngatm/netnatm/api/cc_port.c new file mode 100644 index 0000000..f01a723 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_port.c @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2003-2004 + * Hartmut Brandt + * All rights reserved. + * + * Copyright (c) 2001-2002 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Harti Brandt <harti@freebsd.org> + * + * Redistribution of this software and documentation and use in source and + * binary forms, with or without modification, are permitted provided that + * the following conditions are met: + * + * 1. Redistributions of source code or documentation must retain the above + * copyright notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE AND DOCUMENTATION IS PROVIDED BY THE AUTHOR + * AND ITS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Begemot: libunimsg/netnatm/api/cc_port.c,v 1.1 2004/07/08 08:21:53 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + * + * Port-global stuff (ILMI and Co.) + */ +#include <netnatm/unimsg.h> +#include <netnatm/msg/unistruct.h> +#include <netnatm/api/unisap.h> +#include <netnatm/sig/unidef.h> +#include <netnatm/api/atmapi.h> +#include <netnatm/api/ccatm.h> +#include <netnatm/api/ccpriv.h> + +/* + * Find a port with a given number + */ +static struct ccport * +find_port(struct ccdata *cc, u_int portno) +{ + struct ccport *port; + + TAILQ_FOREACH(port, &cc->port_list, node_link) + if (port->param.port == portno) + return (port); + return (NULL); +} + +/* + * Create a new port structure, initialize it and link it to the node. + * Returns 0 on success, an errno otherwise. + */ +struct ccport * +cc_port_create(struct ccdata *cc, void *uarg, u_int portno) +{ + struct ccport *port, *p1; + + if (portno == 0 || portno > 0xffffffff) + return (NULL); + + TAILQ_FOREACH(port, &cc->port_list, node_link) + if (port->param.port == portno) + return (NULL); + + port = CCZALLOC(sizeof(*port)); + if (port == NULL) + return (NULL); + + port->uarg = uarg; + port->cc = cc; + port->admin = CCPORT_STOPPED; + LIST_INIT(&port->conn_list); + TAILQ_INIT(&port->addr_list); + port->param.port = portno; + port->param.pcr = 350053; + port->param.max_vpi_bits = 0; + port->param.max_vci_bits = 8; + port->param.max_svpc_vpi = 0; + port->param.max_svcc_vpi = 0; + port->param.min_svcc_vci = 32; + port->param.num_addrs = 0; + TAILQ_INIT(&port->cookies); + + TAILQ_FOREACH(p1, &cc->port_list, node_link) + if (p1->param.port > portno) { + TAILQ_INSERT_BEFORE(p1, port, node_link); + break; + } + if (p1 == NULL) + TAILQ_INSERT_TAIL(&cc->port_list, port, node_link); + + return (port); +} + +/* + * Destroy a port. This closes all connections and aborts all the users of + * these connections. + * This should be called only after work has returned so that no signals + * are pending. + */ +void +cc_port_destroy(struct ccport *port, int shutdown) +{ + struct ccaddr *addr; + struct ccreq *r; + + TAILQ_REMOVE(&port->cc->port_list, port, node_link); + + while ((r = TAILQ_FIRST(&port->cookies)) != NULL) { + TAILQ_REMOVE(&port->cookies, r, link); + CCFREE(r); + } + + /* + * Abort all connections. + */ + while (!LIST_EMPTY(&port->conn_list)) + cc_conn_abort(LIST_FIRST(&port->conn_list), shutdown); + + /* + * Free addresses. + */ + while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { + TAILQ_REMOVE(&port->addr_list, addr, port_link); + CCFREE(addr); + } + + CCFREE(port); +} + +/* + * Management is given up on this node. Remove all addresses from the port. + */ +void +cc_unmanage(struct ccdata *cc) +{ + struct ccport *port; + struct ccaddr *addr; + + TAILQ_FOREACH(port, &cc->port_list, node_link) { + while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { + TAILQ_REMOVE(&port->addr_list, addr, port_link); + CCFREE(addr); + } + } +} + +/* + * Compare two addresses + */ +static __inline int +addr_eq(const struct uni_addr *a1, const struct uni_addr *a2) +{ + return (a1->type == a2->type && a1->plan == a2->plan && + a1->len == a2->len && memcmp(a1->addr, a2->addr, a1->len) == 0); +} + + +/* + * retrieve addresses + */ +int +cc_get_addrs(struct ccdata *cc, u_int portno, + struct uni_addr **pa, u_int **ports, u_int *count) +{ + struct ccport *port = NULL; + struct ccaddr *addr; + struct uni_addr *buf, *ptr; + u_int *pports; + + /* + * If a port number is specified and the port does not exist, + * return an error. + */ + if (portno != 0) + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + + /* + * Count the addresses + */ + *count = 0; + if (portno != 0) { + TAILQ_FOREACH(addr, &port->addr_list, port_link) + (*count)++; + } else { + TAILQ_FOREACH(port, &cc->port_list, node_link) + TAILQ_FOREACH(addr, &port->addr_list, port_link) + (*count)++; + } + + buf = CCMALLOC(*count * sizeof(struct uni_addr)); + if (buf == NULL) + return (ENOMEM); + ptr = buf; + + *ports = CCMALLOC(*count * sizeof(u_int)); + if (*ports == NULL) { + CCFREE(buf); + return (ENOMEM); + } + pports = *ports; + + if (portno != 0) { + TAILQ_FOREACH(addr, &port->addr_list, port_link) { + *ptr++ = addr->addr; + *pports++ = portno; + } + } else { + TAILQ_FOREACH(port, &cc->port_list, node_link) + TAILQ_FOREACH(addr, &port->addr_list, port_link) { + *ptr++ = addr->addr; + *pports++ = port->param.port; + } + } + + *pa = buf; + return (0); +} + +/* + * return port number + */ +u_int +cc_port_no(struct ccport *port) +{ + return (port->param.port); +} + +/* + * Address unregisterd. + */ +int +cc_addr_unregister(struct ccdata *cc, u_int portno, const struct uni_addr *arg) +{ + struct ccport *port; + struct ccaddr *a; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + + /* Find the address */ + TAILQ_FOREACH(a, &port->addr_list, port_link) + if (addr_eq(arg, &a->addr)) { + TAILQ_REMOVE(&port->addr_list, a, port_link); + CCFREE(a); + return (0); + } + + return (ENOENT); +} + +/* + * Address registerd. + */ +int +cc_addr_register(struct ccdata *cc, u_int portno, const struct uni_addr *arg) +{ + struct ccport *port, *p1; + struct ccaddr *a; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + + /* maybe we know it already? */ + TAILQ_FOREACH(p1, &port->cc->port_list, node_link) + TAILQ_FOREACH(a, &p1->addr_list, port_link) + if (addr_eq(arg, &a->addr)) + return (EISCONN); + + a = CCZALLOC(sizeof(*a)); + if (a == NULL) + return (ENOMEM); + a->addr = *arg; + + TAILQ_INSERT_TAIL(&port->addr_list, a, port_link); + + return (0); +} + +/* + * Set/get port parameters. + */ +int +cc_port_get_param(struct ccdata *cc, u_int portno, + struct atm_port_info *param) +{ + struct ccport *port; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + + *param = port->param; + return (0); +} + +/* XXX maybe allow only in stopped. */ +int +cc_port_set_param(struct ccdata *cc, const struct atm_port_info *param) +{ + struct ccport *port; + struct ccaddr *addr; + + if ((port = find_port(cc, param->port)) == NULL) + return (ENOENT); + + port->param = *param; + + port->param.num_addrs = 0; + TAILQ_FOREACH(addr, &port->addr_list, port_link) + port->param.num_addrs++; + + return (0); +} + +/* + * get port list + */ +int +cc_port_getlist(struct ccdata *cc, u_int *cnt, u_int **ports) +{ + struct ccport *p; + u_int n; + + n = 0; + TAILQ_FOREACH(p, &cc->port_list, node_link) + n++; + + *ports = CCMALLOC(n * sizeof(u_int)); + if (*ports == NULL) + return (ENOMEM); + + n = 0; + TAILQ_FOREACH(p, &cc->port_list, node_link) + (*ports)[n++] = p->param.port; + *cnt = n; + + return (0); +} + +/* + * START and STOP signalling + */ +int +cc_port_start(struct ccdata *cc, u_int portno) +{ + struct ccport *port; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + if (port->admin != CCPORT_STOPPED) + return (EISCONN); + + cc->funcs->send_uni_glob(port, port->uarg, + UNIAPI_LINK_ESTABLISH_request, 0, NULL); + port->admin = CCPORT_RUNNING; + + return (0); +} + +int +cc_port_stop(struct ccdata *cc, u_int portno) +{ + struct ccport *port; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + if (port->admin != CCPORT_RUNNING) + return (ENOTCONN); + + port->admin = CCPORT_STOPPED; + + /* + * Abort all connections. + */ + while (!LIST_EMPTY(&port->conn_list)) + cc_conn_destroy(LIST_FIRST(&port->conn_list)); + + return (0); +} + +/* + * is port running? + */ +int +cc_port_isrunning(struct ccdata *cc, u_int portno, int *state) +{ + struct ccport *port; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + if (port->admin == CCPORT_RUNNING) + *state = 1; + else + *state = 0; + return (0); +} + +/* + * Clear address and prefix information from the named port. + */ +int +cc_port_clear(struct ccdata *cc, u_int portno) +{ + struct ccaddr *addr; + struct ccport *port; + + if ((port = find_port(cc, portno)) == NULL) + return (ENOENT); + + while ((addr = TAILQ_FIRST(&port->addr_list)) != NULL) { + TAILQ_REMOVE(&port->addr_list, addr, port_link); + CCFREE(addr); + } + return (0); +} + +/* + * retrieve info on local ports + */ +struct atm_port_list * +cc_get_local_port_info(struct ccdata *cc, u_int portno, size_t *lenp) +{ + struct atm_port_list *list; + struct atm_port_info *pp; + struct uni_addr *aa; + struct ccaddr *addr; + struct ccport *port; + u_int nports, naddrs; + + /* + * Count ports and addresses. + */ + nports = 0; + naddrs = 0; + TAILQ_FOREACH(port, &cc->port_list, node_link) { + if (portno == 0 || port->param.port == portno) { + nports++; + TAILQ_FOREACH(addr, &port->addr_list, port_link) + naddrs++; + } + } + + /* + * Size and allocate message + */ + *lenp = sizeof(*list) + nports * sizeof(*pp) + naddrs * sizeof(*aa); + + list = CCZALLOC(*lenp); + if (list == NULL) + return (NULL); + + /* + * Fill the message. + */ + list->num_ports = nports; + list->num_addrs = naddrs; + + pp = (void *)((u_char *)list + sizeof(*list)); + aa = (void *)((u_char *)list + sizeof(*list) + nports * sizeof(*pp)); + + TAILQ_FOREACH(port, &cc->port_list, node_link) { + if (portno == 0 || port->param.port == portno) { + *pp = port->param; + pp->num_addrs = 0; + TAILQ_FOREACH(addr, &port->addr_list, port_link) { + *aa++ = addr->addr; + pp->num_addrs++; + } + pp++; + } + } + + return (list); +} + +static struct ccreq * +find_cookie(struct ccport *port, u_int cookie) +{ + struct ccreq *r; + + TAILQ_FOREACH(r, &port->cookies, link) + if (r->cookie == cookie) + return (r); + return (NULL); +} + +/* + * input a response from the UNI layer to CC + */ +int +cc_uni_response(struct ccport *port, u_int cookie, u_int reason, u_int state) +{ + struct ccconn *conn; + struct ccreq *req; + + if (cookie == 0) + return (EINVAL); + + if (port->admin != CCPORT_RUNNING) + return (ENOTCONN); + + if ((req = find_cookie(port, cookie)) == NULL) { + cc_port_log(port, "UNI response for unknown cookie %u", cookie); + return (EINVAL); + } + conn = req->conn; + + TAILQ_REMOVE(&port->cookies, req, link); + CCFREE(req); + + if (reason == UNIAPI_OK) + return (cc_conn_resp(conn, CONN_SIG_OK, + cookie, reason, state)); + else + return (cc_conn_resp(conn, CONN_SIG_ERROR, + cookie, reason, state)); +} + +static struct ccconn * +find_cref(const struct ccport *port, const struct uni_cref *cref) +{ + struct ccconn *conn; + + LIST_FOREACH(conn, &port->conn_list, port_link) + if (conn->cref.cref == cref->cref && + conn->cref.flag == cref->flag) + return (conn); + return (NULL); +} + +/* + * Signal from UNI on this port + */ +int +cc_uni_signal(struct ccport *port, u_int cookie, u_int sig, struct uni_msg *msg) +{ + int error = 0; + size_t len, ilen = 0; + struct uni_cref *cref; + struct ccconn *conn; + + if (port->admin != CCPORT_RUNNING) { + error = ENOTCONN; + goto out; + } + len = (msg != NULL) ? uni_msg_len(msg) : 0; + + switch ((enum uni_sig)sig) { + + case UNIAPI_ERROR: + /* handled above */ + cc_port_log(port, "bad UNIAPI_ERROR cookie=%u", cookie); + error = EINVAL; + break; + + case UNIAPI_CALL_CREATED: + ilen = sizeof(struct uniapi_call_created); + if (len != ilen) + goto bad_len; + + if (cookie != 0) { + /* outgoing call */ + struct ccreq *req; + + if ((req = find_cookie(port, cookie)) == NULL) { + cc_port_log(port, "bad cookie %u in CREATE", + cookie); + error = EINVAL; + goto out; + } + conn = req->conn; + + } else { + if ((conn = cc_conn_create(port->cc)) == NULL) { + error = ENOMEM; + goto out; + } + cc_conn_ins_port(conn, port); + } + + cc_conn_sig_msg_nodef(conn, CONN_SIG_CREATED, msg); + msg = NULL; + goto out; + + case UNIAPI_CALL_DESTROYED: + ilen = sizeof(struct uniapi_call_destroyed); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_call_destroyed *)->cref; + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig(conn, CONN_SIG_DESTROYED, NULL); + goto out; + + case UNIAPI_LINK_ESTABLISH_confirm: + goto out; + + case UNIAPI_LINK_RELEASE_confirm: + /* Ups. If we administratively up, restart the link */ + if (port->admin == CCPORT_RUNNING) + port->cc->funcs->send_uni_glob(port, port->uarg, + UNIAPI_LINK_ESTABLISH_request, 0, NULL); + goto out; + + case UNIAPI_PARTY_CREATED: + ilen = sizeof(struct uniapi_party_created); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_party_created *)->cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg_nodef(conn, + CONN_SIG_PARTY_CREATED, msg); + msg = NULL; + goto out; + + case UNIAPI_PARTY_DESTROYED: + ilen = sizeof(struct uniapi_party_destroyed); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_party_destroyed *)->cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_DESTROYED, msg); + msg = NULL; + goto out; + + case UNIAPI_DROP_PARTY_ACK_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_drop_party_ack_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_drop_party_ack_indication *)->drop.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_ACK_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_RESET_indication: /* UNI -> API */ + { + /* + * XXX - do the right thing + */ + struct uniapi_reset_indication *ind = uni_msg_rptr(msg, + struct uniapi_reset_indication *); + struct uniapi_reset_response *resp; + struct uni_msg *u; + + /* + * Construct message to UNI. + */ + if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) + return (ENOMEM); + + resp = uni_msg_wptr(u, struct uniapi_reset_response *); + memset(resp, 0, sizeof(*resp)); + u->b_wptr += sizeof(*resp); + + resp->restart = ind->restart; + resp->connid = ind->connid; + + port->cc->funcs->send_uni_glob(port, port->uarg, + UNIAPI_RESET_response, 0, u); + + goto out; + } + + case UNIAPI_RELEASE_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_release_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_release_indication *) + ->release.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_REL_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_RELEASE_confirm: /* UNI -> API */ + ilen = sizeof(struct uniapi_release_confirm); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_release_confirm *) + ->release.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_REL_CONF, msg); + msg = NULL; + goto out; + + case UNIAPI_SETUP_confirm: /* UNI -> API */ + ilen = sizeof(struct uniapi_setup_confirm); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_setup_confirm *) + ->connect.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_CONFIRM, msg); + msg = NULL; + goto out; + + + case UNIAPI_ALERTING_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_alerting_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_alerting_indication *) + ->alerting.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_ALERTING_IND, msg); + msg = NULL; + goto out; + + + case UNIAPI_PROCEEDING_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_proceeding_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_proceeding_indication *) + ->call_proc.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_PROC_IND, msg); + msg = NULL; + goto out; + + + case UNIAPI_SETUP_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_setup_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_setup_indication *) + ->setup.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_SETUP_COMPLETE_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_setup_complete_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_setup_complete_indication *) + ->connect_ack.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_SETUP_COMPL, msg); + msg = NULL; + goto out; + + case UNIAPI_PARTY_ALERTING_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_party_alerting_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_party_alerting_indication *)->alert.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ALERTING_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_ADD_PARTY_ACK_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_add_party_ack_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_add_party_ack_indication *)->ack.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_ACK_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_ADD_PARTY_REJ_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_add_party_rej_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, + struct uniapi_add_party_rej_indication *)->rej.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_PARTY_ADD_REJ_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_DROP_PARTY_indication: /* UNI -> API */ + ilen = sizeof(struct uniapi_drop_party_indication); + if (len != ilen) + goto bad_len; + + cref = &uni_msg_rptr(msg, struct uniapi_drop_party_indication *) + ->drop.hdr.cref; + + if ((conn = find_cref(port, cref)) == NULL) + goto unk_call; + + error = cc_conn_sig_msg(conn, CONN_SIG_DROP_PARTY_IND, msg); + msg = NULL; + goto out; + + case UNIAPI_RESET_confirm: /* UNI -> API */ + case UNIAPI_RESET_ERROR_indication: /* UNI -> API */ + case UNIAPI_RESET_STATUS_indication: /* UNI -> API */ + /* XXX */ + goto out; + + case UNIAPI_NOTIFY_indication: /* UNI -> API */ + case UNIAPI_STATUS_indication: /* UNI -> API */ + break; + + case UNIAPI_ADD_PARTY_indication: /* UNI -> API */ + /* not supported by the API */ + break; + + /* + * All these are illegal in this direction + */ + case UNIAPI_LINK_ESTABLISH_request: /* API -> UNI */ + case UNIAPI_LINK_RELEASE_request: /* API -> UNI */ + case UNIAPI_RESET_request: /* API -> UNI */ + case UNIAPI_RESET_response: /* API -> UNI */ + case UNIAPI_RESET_ERROR_response: /* API -> UNI */ + case UNIAPI_SETUP_request: /* API -> UNI */ + case UNIAPI_SETUP_response: /* API -> UNI */ + case UNIAPI_ALERTING_request: /* API -> UNI */ + case UNIAPI_PROCEEDING_request: /* API -> UNI */ + case UNIAPI_RELEASE_request: /* API -> UNI */ + case UNIAPI_RELEASE_response: /* API -> UNI */ + case UNIAPI_NOTIFY_request: /* API -> UNI */ + case UNIAPI_STATUS_ENQUIRY_request: /* API -> UNI */ + case UNIAPI_ADD_PARTY_request: /* API -> UNI */ + case UNIAPI_PARTY_ALERTING_request: /* API -> UNI */ + case UNIAPI_ADD_PARTY_ACK_request: /* API -> UNI */ + case UNIAPI_ADD_PARTY_REJ_request: /* API -> UNI */ + case UNIAPI_DROP_PARTY_request: /* API -> UNI */ + case UNIAPI_DROP_PARTY_ACK_request: /* API -> UNI */ + case UNIAPI_ABORT_CALL_request: /* API -> UNI */ + case UNIAPI_SETUP_COMPLETE_request: /* API -> UNI */ + case UNIAPI_MAXSIG: + break; + } + cc_port_log(port, "bad signal %u", sig); + error = EINVAL; + goto out; + + bad_len: + cc_port_log(port, "signal %u bad length: %zu, need %zu", len, ilen); + error = EINVAL; + goto out; + + unk_call: + cc_port_log(port, "unknown call %u/%u", cref->cref, cref->flag); + error = EINVAL; + + out: + if (msg != NULL) + uni_msg_destroy(msg); + return (error); +} + |