/*
* 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);
}