diff --git a/sys/contrib/ngatm/netnatm/addr.h b/sys/contrib/ngatm/netnatm/addr.h index 9064d10241c2..c1ba20eb1c3d 100644 --- a/sys/contrib/ngatm/netnatm/addr.h +++ b/sys/contrib/ngatm/netnatm/addr.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/addr.h,v 1.2 2003/09/19 13:10:35 hbb Exp $ + * $Begemot: libunimsg/netnatm/addr.h,v 1.3 2004/07/08 08:21:45 brandt Exp $ */ #ifndef _NETNATM_ADDR_H_ #define _NETNATM_ADDR_H_ diff --git a/sys/contrib/ngatm/netnatm/api/atmapi.h b/sys/contrib/ngatm/netnatm/api/atmapi.h new file mode 100644 index 000000000000..887f548598ed --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/atmapi.h @@ -0,0 +1,291 @@ +/* + * 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 + * + * 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 AUTHORS + * 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 AUTHORS 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/atmapi.h,v 1.1 2004/07/08 08:21:48 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + */ +#ifndef _NETNATM_API_ATMAPI_H_ +#define _NETNATM_API_ATMAPI_H_ + +#include + +/* size of an endpointlen including trailing \0 */ +#define ATM_EPNAMSIZ 65 + +enum atmstate { + ATM_A0, /* non existent */ + ATM_A1, /* initial */ + ATM_A2, /* outgoing call preparation */ + ATM_A3, /* outgoing call requested */ + ATM_A4, /* incoming call preparation */ + ATM_A5, /* wait incoming call */ + ATM_A6, /* incoming call present */ + ATM_A7, /* incoming call requested */ + ATM_A8, /* p2p data transfer */ + ATM_A9, /* p2mp root data transfer */ + ATM_A10, /* p2mp leaf data transfer */ + ATM_A11, /* terminated */ +}; + +enum atmop { + ATMOP_RESP, /* 0 */ + ATMOP_ABORT_CONNECTION, + ATMOP_ACCEPT_INCOMING_CALL, + ATMOP_ADD_PARTY, + ATMOP_ADD_PARTY_REJECT, + ATMOP_ADD_PARTY_SUCCESS, /* 5 */ + ATMOP_ARRIVAL_OF_INCOMING_CALL, + ATMOP_CALL_RELEASE, + ATMOP_CONNECT_OUTGOING_CALL, + ATMOP_DROP_PARTY, + ATMOP_GET_LOCAL_PORT_INFO, /* 10 */ + ATMOP_P2MP_CALL_ACTIVE, + ATMOP_P2P_CALL_ACTIVE, + ATMOP_PREPARE_INCOMING_CALL, + ATMOP_PREPARE_OUTGOING_CALL, + ATMOP_QUERY_CONNECTION_ATTRIBUTES, /* 15 */ + ATMOP_REJECT_INCOMING_CALL, + ATMOP_SET_CONNECTION_ATTRIBUTES, + ATMOP_WAIT_ON_INCOMING_CALL, + ATMOP_SET_CONNECTION_ATTRIBUTES_X, + ATMOP_QUERY_CONNECTION_ATTRIBUTES_X, /* 20 */ + ATMOP_QUERY_STATE, +}; + +#define ATM_DEFINE_ERRORS \ + DEF(ATMERR_OK, 0, "OK") \ + DEF(ATMERR_SYS, -1, "syscall error") \ + DEF(ATMERR_BAD_OP, -2, "bad operation") \ + DEF(ATMERR_BAD_ARGS, -3, "bad arguments for operation") \ + DEF(ATMERR_BAD_STATE, -4, "operation in bad state") \ + DEF(ATMERR_BAD_ATTR, -5, "unknown attribute") \ + DEF(ATMERR_BAD_VALUE, -6, "bad attribute value") \ + DEF(ATMERR_BUSY, -7, "busy") \ + DEF(ATMERR_RDONLY, -8, "read-only attribute") \ + DEF(ATMERR_BAD_SAP, -9, "bad SAP") \ + DEF(ATMERR_OVERLAP, -10,"overlaping SAP") \ + DEF(ATMERR_BAD_ENDPOINT, -11,"bad ATM endpoint") \ + DEF(ATMERR_PREVIOUSLY_ABORTED,-12,"previously aborted") \ + DEF(ATMERR_NO_CALL, -13,"no incoming call") \ + DEF(ATMERR_BAD_LEAF_IDENT, -14,"bad leaf identifier") \ + DEF(ATMERR_BAD_PORT, -15,"unknown port") \ + DEF(ATMERR_BAD_SIGNAL, -29-UNIAPI_ERROR_BAD_SIGNAL, "bad signal")\ + DEF(ATMERR_BADCU, -29-UNIAPI_ERROR_BADCU, "bad coordinator state")\ + DEF(ATMERR_BAD_CALLSTATE, -29-UNIAPI_ERROR_BAD_CALLSTATE, "bad call state")\ + DEF(ATMERR_BAD_EPSTATE, -29-UNIAPI_ERROR_BAD_EPSTATE, "bad party state")\ + DEF(ATMERR_BAD_UNIARG, -29-UNIAPI_ERROR_BAD_ARG, "bad uni argument")\ + DEF(ATMERR_BAD_CALL, -29-UNIAPI_ERROR_BAD_CALL, "unknown call")\ + DEF(ATMERR_BAD_PARTY, -29-UNIAPI_ERROR_BAD_PARTY, "unknown party")\ + DEF(ATMERR_BAD_CTYPE, -29-UNIAPI_ERROR_BAD_CTYPE, "wrong call type")\ + DEF(ATMERR_BAD_IE, -29-UNIAPI_ERROR_BAD_IE, "bad information element")\ + DEF(ATMERR_EPREF_INUSE, -29-UNIAPI_ERROR_EPREF_INUSE, "endpoint reference in use")\ + DEF(ATMERR_MISSING_IE, -29-UNIAPI_ERROR_MISSING_IE, "missing information element")\ + DEF(ATMERR_ENCODING, -29-UNIAPI_ERROR_ENCODING, "encoding error")\ + DEF(ATMERR_NOMEM, -29-UNIAPI_ERROR_NOMEM, "no memory")\ + DEF(ATMERR_UNIBUSY, -29-UNIAPI_ERROR_BUSY, "uni process busy") + +#define ATM_MKUNIERR(E) (-29 - (E)) + +enum atm_error { +#define DEF(NAME,VAL,STR) NAME = (VAL), +ATM_DEFINE_ERRORS +#undef DEF +}; + +enum atm_attribute { + ATM_ATTR_NONE = 0, + ATM_ATTR_BLLI_SELECTOR, + ATM_ATTR_BLLI, + ATM_ATTR_BEARER, + ATM_ATTR_TRAFFIC, + ATM_ATTR_QOS, + ATM_ATTR_EXQOS, + ATM_ATTR_CALLED, + ATM_ATTR_CALLEDSUB, + ATM_ATTR_CALLING, + ATM_ATTR_CALLINGSUB, + ATM_ATTR_AAL, + ATM_ATTR_EPREF, + ATM_ATTR_CONNED, + ATM_ATTR_CONNEDSUB, + ATM_ATTR_EETD, + ATM_ATTR_ABRSETUP, + ATM_ATTR_ABRADD, + ATM_ATTR_CONNID, + ATM_ATTR_MDCR, +}; + +struct atm_resp { + int32_t resp; + uint32_t data; /* type of attached data */ +}; +enum { + ATMRESP_NONE, /* no data */ + ATMRESP_ATTRS, /* attribute(s) */ + ATMRESP_PORTS, /* port info */ + ATMRESP_STATE, /* endpoint state */ + ATMRESP_EXSTAT, /* extended status */ +}; + +struct atm_abort_connection { + struct uni_ie_cause cause; +}; + +struct atm_query_connection_attributes { + uint32_t attr; +}; +struct atm_set_connection_attributes { + uint32_t attr; +}; +struct atm_query_connection_attributes_x { + uint32_t count; +#if defined(__GNUC__) && __GNUC__ < 3 + uint32_t attr[0]; +#else + uint32_t attr[]; +#endif +}; +struct atm_set_connection_attributes_x { + uint32_t count; +#if defined(__GNUC__) && __GNUC__ < 3 + uint32_t attr[0]; +#else + uint32_t attr[]; +#endif +}; +struct atm_prepare_incoming_call { + struct uni_sap sap; + uint32_t queue_size; +}; +struct atm_connect_outgoing_call { + struct uni_ie_called called; +}; +struct atm_call_release { + struct uni_ie_cause cause[2]; +}; +struct atm_p2p_call_active { + struct uni_ie_connid connid; +}; +struct atm_p2mp_call_active { + struct uni_ie_connid connid; +}; +struct atm_accept_incoming_call { + char newep[ATM_EPNAMSIZ]; +}; +struct atm_reject_incoming_call { + struct uni_ie_cause cause; +}; +struct atm_add_party { + uint16_t leaf_ident; + struct uni_ie_called called; +}; +struct atm_add_party_success { + uint16_t leaf_ident; +}; +struct atm_add_party_reject { + uint16_t leaf_ident; + struct uni_ie_cause cause; +}; +struct atm_drop_party { + uint16_t leaf_ident; + struct uni_ie_cause cause; +}; + +/* + * Get local port info. If port is 0, information on all ports is returned, + * otherwise only on the named port. + * The response consists of a header with two counters, a list of ports + * (struct atm_port_info) and a list of addresses (struct uni_addr). + * The port to which an address belongs is implicit in the num_addrs field + * of the port. + */ +struct atm_get_local_port_info { + uint32_t port; +}; + +struct atm_port_list { + uint32_t num_ports; /* number of ports */ + uint32_t num_addrs; /* total number of addresses */ +}; + +struct atm_port_info { + uint32_t port; + uint32_t pcr; + uint32_t max_vpi_bits; + uint32_t max_vci_bits; + uint32_t max_svpc_vpi; + uint32_t max_svcc_vpi; + uint32_t min_svcc_vci; + u_char esi[6]; + uint32_t num_addrs; /* number of addresses on this port */ +}; + +/* + * Endpoint state info + */ +struct atm_epstate { + char name[ATM_EPNAMSIZ]; + uint8_t state; +}; + +/* + * Extended status information. + */ +struct atm_exstatus { + uint32_t neps; /* endpoints */ + uint32_t nports; /* ports */ + uint32_t nconns; /* connections */ + uint32_t nparties; /* number of parties */ +}; +struct atm_exstatus_ep { + char name[ATM_EPNAMSIZ]; + uint8_t state; /* Ux */ +}; +struct atm_exstatus_port { + uint32_t portno; + uint8_t state; +}; +struct atm_exstatus_conn { + uint32_t id; + uint32_t cref; /* (flag << 23) | cref */ + uint32_t port; + char ep[ATM_EPNAMSIZ]; /* \0 - none */ + uint8_t state; /* Cx */ +}; +struct atm_exstatus_party { + uint32_t connid; + uint16_t epref; + uint8_t state; /* Px */ +}; +#endif diff --git a/sys/contrib/ngatm/netnatm/api/cc_conn.c b/sys/contrib/ngatm/netnatm/api/cc_conn.c new file mode 100644 index 000000000000..c67716fe650d --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_conn.c @@ -0,0 +1,2096 @@ +/* + * 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 + * + * 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_conn.c,v 1.1 2004/07/08 08:21:49 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + * + * Lower half - connection handling + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *stab[] = { +#define DEF(N) [N] = #N, + CONN_STATES +#undef DEF +}; + +static const char *ptab[] = { +#define DEF(N) [PARTY_##N] = #N, + PARTY_STATES +#undef DEF +}; + +const char * +cc_conn_state2str(u_int s) +{ + if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL) + return ("?"); + return (stab[s]); +} + +__inline void +cc_conn_set_state(struct ccconn *conn, enum conn_state ns) +{ + if (conn->state != ns) { + if (conn->cc->log & CCLOG_CONN_STATE) + cc_conn_log(conn, "%s -> %s", + stab[conn->state], stab[ns]); + conn->state = ns; + } +} + +const char * +cc_party_state2str(u_int s) +{ + if (s >= sizeof(ptab) / sizeof(ptab[0]) || ptab[s] == NULL) + return ("?"); + return (ptab[s]); +} + +__inline void +cc_party_set_state(struct ccparty *party, enum party_state ns) +{ + + if (party->state != ns) { + if (party->conn->cc->log & CCLOG_PARTY_STATE) + cc_party_log(party, "%s -> %s", + ptab[party->state], ptab[ns]); + party->state = ns; + } +} + +/* + * Remove connection from its user's queue + */ +__inline void +cc_disconnect_from_user(struct ccconn *conn) +{ + + if (conn->user == NULL) + cc_conn_log(conn, "no %s", "user"); + else { + TAILQ_REMOVE(&conn->user->connq, conn, connq_link); + conn->user->queue_act--; + conn->user = NULL; + } +} + +/* + * Put connection on user queue + */ +__inline void +cc_connect_to_user(struct ccconn *conn, struct ccuser *user) +{ + + if (conn->user != NULL) + cc_conn_log(conn, "still connected to %p", conn->user); + conn->user = user; + TAILQ_INSERT_TAIL(&user->connq, conn, connq_link); + conn->user->queue_act++; +} + +/* + * Send a signal to the UNI stack for this connection + */ +static void +cc_send_uni(struct ccconn *conn, u_int op, struct uni_msg *msg) +{ + struct ccreq *r; + + r = CCZALLOC(sizeof(*r)); + if (r == NULL) { + if (msg != NULL) + uni_msg_destroy(msg); + cc_conn_log(conn, "no memory for cookie"); + return; + } + + if ((r->cookie = ++conn->port->cc->cookie) == 0) + r->cookie = ++conn->port->cc->cookie; + r->req = op; + r->conn = conn; + + TAILQ_INSERT_TAIL(&conn->port->cookies, r, link); + + conn->port->cc->funcs->send_uni(conn, conn->port->uarg, op, + r->cookie, msg); +} + +/* + * Send a RELEASE.request for this connection. + */ +static void +do_release_request(struct ccconn *conn, const struct uni_ie_cause cause[2]) +{ + struct uni_msg *u; + struct uniapi_release_request *req; + + if ((u = uni_msg_alloc(sizeof(*req))) == NULL) + return; + req = uni_msg_wptr(u, struct uniapi_release_request *); + memset(req, 0, sizeof(*req)); + u->b_wptr += sizeof(struct uniapi_release_request); + + req->release.hdr.cref = conn->cref; + req->release.hdr.act = UNI_MSGACT_DEFAULT; + + if (cause == NULL) { + IE_SETPRESENT(req->release.cause[0]); + req->release.cause[0].h.act = UNI_IEACT_DEFAULT; + req->release.cause[0].loc = UNI_CAUSE_LOC_USER; + req->release.cause[0].cause = UNI_CAUSE_UNSPEC; + } else { + req->release.cause[0] = cause[0]; + req->release.cause[1] = cause[1]; + } + + cc_send_uni(conn, UNIAPI_RELEASE_request, u); +} + +/* + * Make a RELEASE.response for this connection + */ +static void +do_release_response(struct ccconn *conn, uint8_t cause, struct uni_ie_cause *ie) +{ + struct uni_msg *u; + struct uniapi_release_response *resp; + + if ((u = uni_msg_alloc(sizeof(*resp))) == NULL) + return; + resp = uni_msg_wptr(u, struct uniapi_release_response *); + memset(resp, 0, sizeof(*resp)); + u->b_wptr += sizeof(struct uniapi_release_response); + + resp->release_compl.hdr.cref = conn->cref; + resp->release_compl.hdr.act = UNI_MSGACT_DEFAULT; + + if (ie != NULL) + resp->release_compl.cause[0] = *ie; + + if (cause != 0) { + IE_SETPRESENT(resp->release_compl.cause[0]); + resp->release_compl.cause[0].h.act = UNI_IEACT_DEFAULT; + resp->release_compl.cause[0].loc = UNI_CAUSE_LOC_USER; + resp->release_compl.cause[0].cause = cause; + } + + cc_send_uni(conn, UNIAPI_RELEASE_response, u); +} + +/********************************************************************** + * + * INSTANCE handling + */ +struct ccconn * +cc_conn_create(struct ccdata *cc) +{ + struct ccconn *conn; + + conn = CCZALLOC(sizeof(*conn)); + if (conn == NULL) + return (NULL); + + conn->state = CONN_NULL; + conn->port = NULL; + conn->cc = cc; + LIST_INIT(&conn->parties); + + LIST_INSERT_HEAD(&cc->orphaned_conns, conn, port_link); + + if (conn->cc->log & CCLOG_CONN_INST) + cc_conn_log(conn, "created %s", "orphaned"); + + return (conn); +} + +/* + * assign to port + */ +void +cc_conn_ins_port(struct ccconn *conn, struct ccport *port) +{ + + if (conn->port != NULL) { + cc_conn_log(conn, "conn is already on port %u", + conn->port->param.port); + cc_conn_rem_port(conn); + } + LIST_REMOVE(conn, port_link); + + conn->port = port; + LIST_INSERT_HEAD(&port->conn_list, conn, port_link); + +} + +/* + * remove from port + */ +void +cc_conn_rem_port(struct ccconn *conn) +{ + + if (conn->port == NULL) { + cc_conn_log(conn, "conn not on any %s", "port"); + return; + } + LIST_REMOVE(conn, port_link); + conn->port = NULL; + LIST_INSERT_HEAD(&conn->cc->orphaned_conns, conn, port_link); +} + +static void +cc_conn_flush_cookies(struct ccconn *conn) +{ + struct ccreq *r, *r1; + + if (conn->port == NULL) + return; + TAILQ_FOREACH_SAFE(r, &conn->port->cookies, link, r1) { + if (r->conn == conn) { + TAILQ_REMOVE(&conn->port->cookies, r, link); + CCFREE(r); + } + } +} + +__inline void +cc_conn_reset_acceptor(struct ccconn *conn) +{ + if (conn->acceptor != NULL) { + conn->acceptor->accepted = NULL; + conn->acceptor = NULL; + } +} + +/* + * Destroy a connection + */ +void +cc_conn_destroy(struct ccconn *conn) +{ + struct ccparty *p; + + if (conn->cc->log & CCLOG_CONN_INST) + cc_conn_log(conn, "destroy%s", ""); + + if (conn->user != NULL) { + cc_conn_log(conn, "still connected to user %p\n", conn->user); + conn->user->queue_act--; + TAILQ_REMOVE(&conn->user->connq, conn, connq_link); + } + + if (conn->acceptor != NULL) + conn->acceptor->accepted = NULL; + + cc_conn_flush_cookies(conn); + cc_conn_sig_flush(conn); + + LIST_REMOVE(conn, port_link); + while ((p = LIST_FIRST(&conn->parties)) != NULL) { + LIST_REMOVE(p, link); + CCFREE(p); + } + + CCFREE(conn); +} + +struct ccparty * +cc_party_create(struct ccconn *conn, u_int ident, u_int flag) +{ + struct ccparty *party; + + party = CCZALLOC(sizeof(*party)); + if (party == NULL) + return (NULL); + + party->conn = conn; + party->state = PARTY_NULL; + IE_SETPRESENT(party->epref); + party->epref.flag = flag; + party->epref.epref = ident; + LIST_INSERT_HEAD(&conn->parties, party, link); + + if (party->conn->cc->log & CCLOG_PARTY_INST) + cc_party_log(party, "created %u.%u", flag, ident); + + return (party); +} + +static void +cc_party_destroy(struct ccparty *party) +{ + + if (party->conn->cc->log & CCLOG_PARTY_INST) + cc_party_log(party, "destroyed %u.%u", party->epref.flag, + party->epref.epref); + + LIST_REMOVE(party, link); + CCFREE(party); +} + +static struct ccparty * +cc_party_find(struct ccconn *conn, u_int ident) +{ + struct ccparty *party; + + LIST_FOREACH(party, &conn->parties, link) + if (party->epref.epref == ident) + return (party); + return (NULL); +} +/* + * Abort connection from down stream (because of the UNI hook beeing + * disconnected). This is called from two places: + * 1) the shutdown code. + * In this case the connections should be already dissociated from + * users and be only in states waiting for the UNI stack. + * 2) from the disconnect code. + */ +void +cc_conn_abort(struct ccconn *conn, int shutdown) +{ + struct ccuser *u = conn->user; + struct ccparty *p, *p1; + + if (shutdown) { + CCASSERT(u == NULL, ("still in use")); + CCASSERT(conn->acceptor == NULL, ("still in use")); + cc_conn_destroy(conn); + return; + } + + /* + * Look whether any parties are blocked waiting for a response + * from the stack. We don't use extra party states to handle + * user aborts, so check that there is a user before using it. + */ + if (u == NULL) { + while ((p = LIST_FIRST(&conn->parties)) != NULL) + cc_party_destroy(p); + } else { + LIST_FOREACH_SAFE(p, &conn->parties, link, p1) { + switch (p->state) { + + case PARTY_NULL: /* P0 */ + /* should not happen */ + goto dpty; + + case PARTY_ACTIVE: /* P1 */ + /* don't send a drop - user'll get a rel */ + goto dpty; + + case PARTY_ADD_WAIT_CREATE: /* P2 */ + case PARTY_ADD_WAIT_OK: /* P3 */ + /* we're adding - synthesise an error */ + cc_user_sig(u, USER_SIG_ADD_PARTY_ERR, + NULL, ATMERR_BAD_PORT); + goto dpty; + + case PARTY_ADD_WAIT_ACK: /* P4 */ + /* don't send a drop - user'll get a rel */ + goto dpty; + + case PARTY_DROP_WAIT_OK: /* P5 */ + case PARTY_DROP_WAIT_ACK: /* P6 */ + case PARTY_ADD_DROP_WAIT_OK: /* P11 */ + /* we're dropping - synthesis an ok */ + cc_user_sig(u, USER_SIG_DROP_PARTY_OK, + NULL, p->epref.epref); + goto dpty; + + case PARTY_WAIT_DESTROY: /* P7 */ + goto dpty; + + case PARTY_WAIT_SETUP_COMPL: /* P8 */ + case PARTY_WAIT_SETUP_CONF: /* P10 */ + /* first party - nothing to do */ + goto dpty; + + case PARTY_WAIT_DROP_ACK_OK: /* P9 */ + case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ + /* we're dropping - nothing to do */ + goto dpty; + } + cc_party_log(p, "bad uabort for party in state %s", + ptab[p->state]); + dpty: + cc_party_destroy(p); + } + } + + /* + * Now do what the connection needs + */ + switch (conn->state) { + + case CONN_NULL: /* 0 */ + case CONN_OUT_PREPARING: /* 1 */ + /* may not happen because we're not associated with + * aport yet */ + break; + + case CONN_OUT_WAIT_CREATE: /* 2 */ + case CONN_OUT_WAIT_OK: /* 3 */ + case CONN_OUT_WAIT_DESTROY: /* 37 */ + /* return an error to the user, go back to C1/U1 + * reset cref (for C37, C3) and cookie */ + conn->cref.flag = 0; + conn->cref.cref = 0; + cc_conn_flush_cookies(conn); + cc_conn_set_state(conn, CONN_OUT_PREPARING); + cc_conn_rem_port(conn); + cc_user_sig(u, USER_SIG_CONNECT_OUTGOING_ERR, + NULL, ATMERR_BAD_PORT); + return; + + case CONN_OUT_WAIT_CONF: /* 4 */ + case CONN_ACTIVE: /* 5 */ + case CONN_IN_WAIT_COMPL: /* 13 */ + /* emulate a RELEASE.confirm */ + memset(&u->cause, 0, sizeof(u->cause)); + cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + cc_conn_destroy(conn); + return; + + case CONN_IN_PREPARING: /* 10 */ + case CONN_AB_WAIT_REQ_OK: /* 33 */ + case CONN_AB_WAIT_RESP_OK: /* 34 */ + case CONN_AB_FLUSH_IND: /* 35 */ + /* no user - destroy */ + cc_conn_destroy(conn); + return; + + case CONN_IN_ARRIVED: /* 11 */ + u->aborted = 1; + cc_disconnect_from_user(conn); + cc_conn_destroy(conn); + return; + + case CONN_IN_WAIT_ACCEPT_OK: /* 12 */ + /* return ACCEPT error */ + cc_disconnect_from_user(conn); + cc_conn_reset_acceptor(conn); + cc_user_sig(u, USER_SIG_ACCEPT_ERR, + u, ATMERR_PREVIOUSLY_ABORTED); + cc_conn_destroy(conn); + return; + + case CONN_REJ_WAIT_OK: /* 14 */ + /* return REJECT ok */ + cc_disconnect_from_user(conn); + cc_conn_destroy(conn); + cc_user_sig(u, USER_SIG_REJECT_OK, NULL, 0); + return; + + case CONN_REL_IN_WAIT_OK: /* 15 */ + case CONN_REL_WAIT_OK: /* 20 */ + /* confirm destroy */ + if (u != NULL) { + /* connection not aborted */ + memset(&u->cause, 0, sizeof(u->cause)); + cc_user_sig(u, USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } + cc_conn_destroy(conn); + return; + + case CONN_IN_WAITING: /* 21 */ + /* user has not seen the connection - destroy */ + cc_disconnect_from_user(conn); + cc_conn_destroy(conn); + return; + } + cc_conn_log(conn, "bad state %s", stab[conn->state]); +} + +#ifdef DEBUG_MATCH +static void +print_sap(const struct uni_sap *sap) +{ + static const char *const tags[] = { + [UNISVE_ABSENT] "absent", + [UNISVE_PRESENT]"present", + [UNISVE_ANY] "any", + }; + u_int i; + + printf("addr={%s", tags[sap->addr.tag]); + if (sap->addr.tag == UNISVE_PRESENT) { + printf(",%d-%d", sap->addr.type, sap->addr.plan); + for (i = 0; i < sap->addr.len; i++) + printf("%c%02x", ",:"[i!=0], sap->addr.addr[i]); + } + printf("}\n"); + + printf("selector={%s", tags[sap->selector.tag]); + if (sap->selector.tag == UNISVE_PRESENT) + printf(",%02x", sap->selector.selector); + printf("}\n"); + + printf("blli_id2={%s", tags[sap->blli_id2.tag]); + if (sap->blli_id2.tag == UNISVE_PRESENT) + printf(",%02x,%02x", sap->blli_id2.proto, sap->blli_id2.user); + printf("}\n"); + + printf("blli_id3={%s", tags[sap->blli_id3.tag]); + if (sap->blli_id3.tag == UNISVE_PRESENT) + printf(",%02x,%02x,%02x,%06x,%04x,%d", + sap->blli_id3.proto, sap->blli_id3.user, + sap->blli_id3.ipi, sap->blli_id3.oui, + sap->blli_id3.pid, sap->blli_id3.noipi); + printf("}\n"); + + printf("bhli={%s", tags[sap->bhli.tag]); + if (sap->bhli.tag == UNISVE_PRESENT) { + printf(",%d", sap->bhli.type); + for (i = 0; i < sap->bhli.len; i++) + printf("%c%02x", ",:"[i!=0], sap->bhli.info[i]); + } + printf("}\n"); +} +#endif + +/********************************************************************* + * + * DISPATCH incoming call + */ +void +cc_conn_dispatch(struct ccconn *conn) +{ + struct ccdata *priv = conn->port->cc; + struct ccuser *user; + u_int blli_index; + +#ifdef DEBUG_MATCH + static char buf[1000]; + static struct unicx cx; + static int init = 1; + + if (init) { + uni_initcx(&cx); + init = 0; + } +#endif + + /* + * Do call dispatching according to 4.6 + */ +#ifdef DEBUG_MATCH + printf("+++++ DISPATCH++++++\n"); +#endif + for (blli_index = 0; blli_index < UNI_NUM_IE_BLLI; blli_index++) { + if (blli_index > 0 && !IE_ISGOOD(conn->blli[blli_index])) + break; +#ifdef DEBUG_MATCH + if (IE_ISPRESENT(conn->called)) { + uni_print_ie(buf, sizeof(buf), UNI_IE_CALLED, + (union uni_ieall *)&conn->called, &cx); + printf("called=%s\n", buf); + } + if (IE_ISPRESENT(conn->bhli)) { + uni_print_ie(buf, sizeof(buf), UNI_IE_BHLI, + (union uni_ieall *)&conn->bhli, &cx); + printf("bhli=%s\n", buf); + } + if (IE_ISPRESENT(conn->blli[blli_index])) { + uni_print_ie(buf, sizeof(buf), UNI_IE_BLLI, + (union uni_ieall *)&conn->blli[blli_index], &cx); + printf("%s\n", buf); + } +#endif + LIST_FOREACH(user, &priv->user_list, node_link) { + if ((user->state == USER_IN_WAITING || + user->state == USER_IN_ARRIVED || + user->state == USER_IN_WAIT_ACC || + user->state == USER_IN_WAIT_REJ) && + !unisve_is_catchall(user->sap)) { +#ifdef DEBUG_MATCH + printf("TRYING user=%p\n", user); + print_sap(user->sap); +#endif + if (unisve_match(user->sap, &conn->called, + &conn->blli[blli_index], &conn->bhli)) + goto found; + } + } + } +#ifdef DEBUG_MATCH + printf("TRYING CATCHALL\n"); +#endif + blli_index = 0; + LIST_FOREACH(user, &priv->user_list, node_link) { + if ((user->state == USER_IN_WAITING || + user->state == USER_IN_ARRIVED || + user->state == USER_IN_WAIT_ACC || + user->state == USER_IN_WAIT_REJ) && + unisve_is_catchall(user->sap)) + goto found; + } +#ifdef DEBUG_MATCH + printf("SORRY\n"); +#endif + + /* + * No application found - reject call. + */ + do_release_response(conn, UNI_CAUSE_INCOMP, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + return; + + found: +#ifdef DEBUG_MATCH + printf("MATCH\n"); +#endif + if (user->queue_max == user->queue_act) { + do_release_response(conn, UNI_CAUSE_BUSY, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + return; + } + + if (blli_index == 0 && !IE_ISGOOD(conn->blli[blli_index])) + conn->blli_selector = 0; + else + conn->blli_selector = blli_index + 1; + + cc_conn_set_state(conn, CONN_IN_WAITING); + cc_connect_to_user(conn, user); + + cc_user_sig(user, USER_SIG_SETUP_IND, NULL, 0); +} + +static void +cc_party_setup_conf(struct ccconn *conn) +{ + struct ccparty *party; + + party = cc_party_find(conn, conn->epref.epref); + if (party == NULL) { + cc_party_log(party, "no party for %s", + cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); + return; + } + if (party->state != PARTY_WAIT_SETUP_CONF) { + cc_party_log(party, "bad state=%s for signal=%s", + ptab[party->state], cc_conn_sigtab[CONN_SIG_SETUP_CONFIRM]); + return; + } + cc_party_set_state(party, PARTY_ACTIVE); +} + +static void +cc_party_add_ack_ind(struct ccconn *conn, const struct uni_ie_epref *epref) +{ + struct ccparty *party; + + party = cc_party_find(conn, epref->epref); + if (party == NULL) { + cc_party_log(party, "no party for %s", + cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); + } + if (party->state != PARTY_ADD_WAIT_ACK) { + cc_party_log(party, "bad state=%s for signal=%s", + ptab[party->state], + cc_conn_sigtab[CONN_SIG_PARTY_ADD_ACK_IND]); + return; + } + cc_party_set_state(party, PARTY_ACTIVE); + cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ACK, + NULL, epref->epref); +} + +static void +cc_party_add_rej_ind(struct ccconn *conn, const struct uni_ie_epref *epref) +{ + struct ccparty *party; + + party = cc_party_find(conn, epref->epref); + if (party == NULL) { + cc_party_log(party, "no party for %s", + cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); + return; + } + if (party->state != PARTY_ADD_WAIT_ACK) { + cc_party_log(party, "bad state=%s for signal=%s", + ptab[party->state], + cc_conn_sigtab[CONN_SIG_PARTY_ADD_REJ_IND]); + return; + } + cc_party_set_state(party, PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, NULL, epref->epref); +} + +static void +cc_party_drop_ack_ind(struct ccconn *conn, + const struct uni_drop_party *drop) +{ + struct ccparty *party; + + party = cc_party_find(conn, drop->epref.epref); + if (party == NULL) { + cc_party_log(party, "no party for %s", + ptab[CONN_SIG_DROP_PARTY_ACK_IND]); + return; + } + switch (party->state) { + + case PARTY_ACTIVE: /* P1 */ + memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); + conn->user->cause[0] = drop->cause; + cc_party_set_state(party, PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, USER_SIG_DROP_PARTY_IND, + NULL, party->epref.epref); + break; + + case PARTY_ADD_WAIT_ACK: /* P4 */ + memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); + conn->user->cause[0] = drop->cause; + cc_party_set_state(party, PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, USER_SIG_ADD_PARTY_REJ, + NULL, party->epref.epref); + break; + + case PARTY_DROP_WAIT_ACK: /* P6 */ + cc_party_set_state(party, PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, USER_SIG_DROP_PARTY_OK, NULL, 0); + break; + + case PARTY_WAIT_SETUP_COMPL: /* P8 */ + case PARTY_WAIT_SETUP_CONF: /* P10 */ + cc_party_set_state(party, PARTY_WAIT_DESTROY); + break; + + default: + cc_party_log(party, "bad state=%s for signal=%s", + ptab[party->state], + cc_conn_sigtab[CONN_SIG_DROP_PARTY_ACK_IND]); + break; + } +} + +/* + * Handle a signal to this connection + */ +void +cc_conn_sig_handle(struct ccconn *conn, enum conn_sig sig, + void *arg, u_int iarg) +{ + struct ccparty *party; + + if (conn->cc->log & CCLOG_CONN_SIG) + cc_conn_log(conn, "signal %s in state %s", cc_conn_sigtab[sig], + stab[conn->state]); + + switch (sig) { + + case CONN_SIG_CONNECT_OUTGOING: + /* Do SETUP */ + { + struct uni_msg *u; + struct uniapi_setup_request *setup; + + if (conn->state != CONN_OUT_PREPARING) + goto bad_state; + + if (IE_ISGOOD(conn->bearer) && + conn->bearer.cfg == UNI_BEARER_MP) { + IE_SETPRESENT(conn->epref); + conn->epref.flag = 0; + conn->epref.epref = 0; + } + + /* + * Construct message to UNI. + */ + u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); + if (u == NULL) { + cc_user_sig(conn->user, USER_SIG_CONNECT_OUTGOING_ERR, + NULL, ATMERR_NOMEM); + return; + } + setup = uni_msg_wptr(u, struct uniapi_setup_request *); + memset(setup, 0, sizeof(*setup)); + u->b_wptr += sizeof(struct uniapi_setup_request); + + setup->setup.hdr.act = UNI_MSGACT_DEFAULT; + memcpy(setup->setup.blli, conn->blli, sizeof(conn->blli)); + setup->setup.bearer = conn->bearer; + setup->setup.traffic = conn->traffic; + setup->setup.qos = conn->qos; + setup->setup.exqos = conn->exqos; + setup->setup.called = conn->called; + setup->setup.calledsub[0] = conn->calledsub; + setup->setup.aal = conn->aal; + setup->setup.epref = conn->epref; + setup->setup.eetd = conn->eetd; + setup->setup.abrsetup = conn->abrsetup; + setup->setup.abradd = conn->abradd; + setup->setup.calling = conn->calling; + setup->setup.callingsub[0] = conn->callingsub; + setup->setup.connid = conn->connid; + memcpy(setup->setup.tns, conn->tns, sizeof(conn->tns)); + setup->setup.atraffic = conn->atraffic; + setup->setup.mintraffic = conn->mintraffic; + setup->setup.cscope = conn->cscope; + setup->setup.bhli = conn->bhli; + setup->setup.mdcr = conn->mdcr; + + cc_conn_set_state(conn, CONN_OUT_WAIT_CREATE); + cc_send_uni(conn, UNIAPI_SETUP_request, u); + + break; + } + + + case CONN_SIG_ARRIVAL: + /* user informed of arrival of this call */ + if (conn->state != CONN_IN_WAITING) + goto bad_state; + cc_conn_set_state(conn, CONN_IN_ARRIVED); + break; + + + case CONN_SIG_RELEASE: + { + /* Release this call */ + struct uni_msg *u; + struct uniapi_release_request *req; + + if (conn->state != CONN_ACTIVE && + conn->state != CONN_IN_WAIT_COMPL) + goto bad_state; + + if ((u = uni_msg_alloc(sizeof(*req))) == NULL) + return; + + req = uni_msg_wptr(u, struct uniapi_release_request *); + memset(req, 0, sizeof(*req)); + u->b_wptr += sizeof(struct uniapi_release_request); + + req->release.hdr.cref = conn->cref; + req->release.hdr.act = UNI_MSGACT_DEFAULT; + + req->release.cause[0] = conn->cause[0]; + req->release.cause[1] = conn->cause[1]; + + if (conn->state == CONN_ACTIVE) + cc_conn_set_state(conn, CONN_REL_WAIT_OK); + else + cc_conn_set_state(conn, CONN_REL_IN_WAIT_OK); + + cc_send_uni(conn, UNIAPI_RELEASE_request, u); + break; + } + + case CONN_SIG_REJECT: + { + /* reject from user */ + struct ccuser *user = conn->user; + + if (conn->state != CONN_IN_ARRIVED) { + cc_user_sig(user, USER_SIG_REJECT_ERR, + NULL, ATMERR_BAD_STATE); + break; + } + cc_conn_set_state(conn, CONN_REJ_WAIT_OK); + do_release_response(conn, 0, conn->cause); + break; + } + + + case CONN_SIG_ACCEPT: + { + /* User accepts. */ + struct ccuser *newep = arg; + struct uni_msg *u; + struct uniapi_setup_response *resp; + struct ccuser *user = conn->user; + + if (conn->state != CONN_IN_ARRIVED) { + cc_user_sig(user, USER_SIG_ACCEPT_ERR, + NULL, ATMERR_PREVIOUSLY_ABORTED); + break; + } + + u = uni_msg_alloc(sizeof(struct uniapi_setup_response)); + if (u == NULL) { + cc_user_sig(user, USER_SIG_ACCEPT_ERR, + NULL, ATMERR_NOMEM); + return; + } + + /* + * Link to the new endpoint + */ + conn->acceptor = newep; + newep->accepted = conn; + + /* + * Construct connect message + */ + resp = uni_msg_wptr(u, struct uniapi_setup_response *); + memset(resp, 0, sizeof(*resp)); + u->b_wptr += sizeof(*resp); + + resp->connect.hdr.act = UNI_MSGACT_DEFAULT; + resp->connect.hdr.cref = conn->cref; + + /* + * attributes + */ + if (conn->dirty_attr && CCDIRTY_AAL) + resp->connect.aal = conn->aal; + if (conn->dirty_attr && CCDIRTY_BLLI) + resp->connect.blli = + conn->blli[conn->blli_selector - 1]; + if (conn->dirty_attr && CCDIRTY_CONNID) + resp->connect.connid = conn->connid; + /* XXX NOTIFY */ + if (conn->dirty_attr && CCDIRTY_EETD) + resp->connect.eetd = conn->eetd; + /* XXX GIT */ + /* XXX UU */ + if (conn->dirty_attr && CCDIRTY_TRAFFIC) + resp->connect.traffic = conn->traffic; + if (conn->dirty_attr && CCDIRTY_EXQOS) + resp->connect.exqos = conn->exqos; + if (conn->dirty_attr && CCDIRTY_ABRSETUP) + resp->connect.abrsetup = conn->abrsetup; + if (conn->dirty_attr && CCDIRTY_ABRADD) + resp->connect.abradd = conn->abradd; + + /* + * If the SETUP had an endpoint reference - echo it back + */ + if (IE_ISPRESENT(conn->epref)) { + resp->connect.epref = conn->epref; + resp->connect.epref.flag = !resp->connect.epref.flag; + } + + cc_conn_set_state(conn, CONN_IN_WAIT_ACCEPT_OK); + cc_send_uni(conn, UNIAPI_SETUP_response, u); + break; + } + + + case CONN_SIG_ADD_PARTY: + { + /* request to add party from user */ + struct uni_msg *u; + struct uniapi_add_party_request *req; + + if (conn->state != CONN_ACTIVE) + goto bad_state; + + /* create the party */ + party = cc_party_create(conn, (u_int)(uintptr_t)arg, 0); + if (party == NULL) { + cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, + NULL, ATMERR_NOMEM); + return; + } + party->called = conn->called; + + /* Construct message to UNI. */ + u = uni_msg_alloc(sizeof(struct uniapi_setup_request)); + if (u == NULL) { + cc_party_destroy(party); + cc_user_sig(conn->user, USER_SIG_ADD_PARTY_ERR, + NULL, ATMERR_NOMEM); + return; + } + + req = uni_msg_wptr(u, struct uniapi_add_party_request *); + memset(req, 0, sizeof(*req)); + u->b_wptr += sizeof(struct uniapi_add_party_request); + + req->add.hdr.act = UNI_MSGACT_DEFAULT; + req->add.hdr.cref = conn->cref; + req->add.epref = party->epref; + req->add.called = party->called; + + cc_party_set_state(party, PARTY_ADD_WAIT_CREATE); + cc_send_uni(conn, UNIAPI_ADD_PARTY_request, u); + break; + } + + + case CONN_SIG_DROP_PARTY: + { + /* user request to drop a party */ + struct uni_msg *u; + struct uniapi_drop_party_request *req; + + if (conn->state != CONN_ACTIVE) + goto bad_state; + + party = cc_party_find(conn, (u_int)(uintptr_t)arg); + if (party == NULL) { + cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, + NULL, ATMERR_BAD_PARTY); + return; + } + + switch (party->state) { + + case PARTY_ACTIVE: + case PARTY_ADD_WAIT_ACK: + break; + + default: + cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, + NULL, ATMERR_BAD_STATE); + return; + + } + /* + * Construct message to UNI. + */ + u = uni_msg_alloc(sizeof(*req)); + if (u == NULL) { + cc_user_sig(conn->user, USER_SIG_DROP_PARTY_ERR, + NULL, ATMERR_NOMEM); + return; + } + + req = uni_msg_wptr(u, struct uniapi_drop_party_request *); + memset(req, 0, sizeof(*req)); + u->b_wptr += sizeof(struct uniapi_drop_party_request); + + req->drop.hdr.act = UNI_MSGACT_DEFAULT; + req->drop.hdr.cref = conn->cref; + req->drop.epref = party->epref; + req->drop.cause = conn->cause[0]; + + if (party->state == PARTY_ACTIVE) + cc_party_set_state(party, PARTY_DROP_WAIT_OK); + else + cc_party_set_state(party, PARTY_ADD_DROP_WAIT_OK); + cc_send_uni(conn, UNIAPI_DROP_PARTY_request, u); + break; + } + + case CONN_SIG_DROP_PARTY_ACK_IND: + { + struct uni_msg *msg = arg; + struct uniapi_drop_party_ack_indication *ind = uni_msg_rptr(msg, + struct uniapi_drop_party_ack_indication *); + + cc_party_drop_ack_ind(conn, &ind->drop); + break; + } + + + case CONN_SIG_USER_ABORT: + /* + * Aborting a connection. This is callable in all states. + * The connection is already disconnected from the user. + * The cause is in cause[]. + */ + switch (conn->state) { + + case CONN_NULL: /* C0 */ + case CONN_OUT_PREPARING: /* C1 */ + cc_conn_destroy(conn); + break; + + case CONN_OUT_WAIT_CONF: /* C4 */ + case CONN_ACTIVE: /* C5 */ + do_release_request(conn, conn->cause); + cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); + break; + + case CONN_IN_WAITING: /* C21 */ + /* that should not happen */ + goto bad_state; + break; + + case CONN_IN_ARRIVED: /* C11 */ + /* + * This is called only for the first connection + * of the user - the others are re-dispatched. + */ + do_release_response(conn, 0, conn->cause); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + break; + + case CONN_IN_WAIT_COMPL: /* C13 */ + do_release_request(conn, conn->cause); + cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); + break; + + case CONN_OUT_WAIT_DESTROY: /* C20 */ + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + break; + + case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ + case CONN_AB_WAIT_REQ_OK: /* C33 */ + case CONN_AB_WAIT_RESP_OK: /* C34 */ + case CONN_AB_FLUSH_IND: /* C35 */ + /* just ignore */ + break; + + /* + * The following states may not happen, because + * we're waiting for a response from the UNI stack. + * As soon as the response comes the ABORT is undefered + * and will hit us (but in another state). + */ + case CONN_OUT_WAIT_CREATE: /* C2 */ + case CONN_OUT_WAIT_OK: /* C3 */ + case CONN_IN_PREPARING: /* C10 */ + case CONN_REJ_WAIT_OK: /* C14 */ + case CONN_REL_IN_WAIT_OK: /* C15 */ + case CONN_REL_WAIT_OK: /* C20 */ + goto bad_state; + } + break; + + + case CONN_SIG_CREATED: + { + /* + * CALL_CREATED message from UNI. This can happen for either + * incoming or outgoing connections. + */ + struct uni_msg *msg = arg; + struct uniapi_call_created *cr = uni_msg_rptr(msg, + struct uniapi_call_created *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CREATE: + conn->cref = cr->cref; + cc_conn_set_state(conn, CONN_OUT_WAIT_OK); + break; + + case CONN_NULL: + conn->cref = cr->cref; + cc_conn_set_state(conn, CONN_IN_PREPARING); + break; + + default: + goto bad_state; + } + break; + } + + case CONN_SIG_DESTROYED: + /* + * CALL_DESTROYED message from UNI. + */ + switch (conn->state) { + + case CONN_OUT_WAIT_DESTROY: + cc_conn_rem_port(conn); + cc_conn_set_state(conn, CONN_OUT_PREPARING); + if (conn->user != NULL) + cc_user_sig(conn->user, + USER_SIG_CONNECT_OUTGOING_ERR, + NULL, ATM_MKUNIERR(conn->reason)); + break; + + case CONN_AB_FLUSH_IND: + cc_conn_destroy(conn); + break; + + case CONN_IN_PREPARING: + cc_conn_destroy(conn); + break; + + default: + goto bad_state; + } + break; + + + case CONN_SIG_SETUP_CONFIRM: + /* Setup confirm from the UNI. */ + { + struct uni_msg *msg = arg; + struct uniapi_setup_confirm *conf = uni_msg_rptr(msg, + struct uniapi_setup_confirm *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CONF: + /* + * Shuffle attributes and inform the user. + * Negotiable attributes are condititionally shuffled, + * because not returning it means accepting it + * (in case of blli the first instance of it). + * All others are shuffled unconditionally. + * Here we should also open the VCI in the driver. (XXX) + */ +#define SHUFFLE(ATTR) conn->ATTR = conf->connect.ATTR +#define COND_SHUFFLE(ATTR) if (IE_ISPRESENT(conf->connect.ATTR)) SHUFFLE(ATTR) + + COND_SHUFFLE(aal); + (void)memset(conn->blli + 1, 0, + sizeof(conn->blli) - sizeof(conn->blli[0])); + if (IE_ISPRESENT(conf->connect.blli)) + conn->blli[0] = conf->connect.blli; + conn->blli_selector = 1; + COND_SHUFFLE(epref); + SHUFFLE(conned); + SHUFFLE(connedsub); + SHUFFLE(eetd); + COND_SHUFFLE(traffic); + COND_SHUFFLE(exqos); + COND_SHUFFLE(abrsetup); + COND_SHUFFLE(abradd); + COND_SHUFFLE(connid); +#undef SHUFFLE +#undef COND_SHUFFLE + if (IE_ISGOOD(conn->epref)) + cc_party_setup_conf(conn); + + cc_conn_set_state(conn, CONN_ACTIVE); + cc_user_sig(conn->user, USER_SIG_SETUP_CONFIRM, + NULL, 0); + break; + + case CONN_AB_FLUSH_IND: + case CONN_AB_WAIT_RESP_OK: + break; + + default: + goto bad_state; + } + break; + } + + case CONN_SIG_SETUP_IND: + { + /* SETUP indication */ + struct uni_msg *msg = arg; + struct uniapi_setup_indication *ind = uni_msg_rptr(msg, + struct uniapi_setup_indication *); + u_int i; + + if (conn->state != CONN_IN_PREPARING) + goto bad_state; + + /* + * Shuffle information elements. + */ + for (i = 0; i < UNI_NUM_IE_BLLI; i++) + conn->blli[i] = ind->setup.blli[i]; + conn->bearer = ind->setup.bearer; + conn->traffic = ind->setup.traffic; + conn->qos = ind->setup.qos; + conn->exqos = ind->setup.exqos; + conn->called = ind->setup.called; + conn->calledsub = ind->setup.calledsub[0]; + conn->aal = ind->setup.aal; + conn->epref = ind->setup.epref; + conn->eetd = ind->setup.eetd; + conn->abrsetup = ind->setup.abrsetup; + conn->abradd = ind->setup.abradd; + conn->calling = ind->setup.calling; + conn->callingsub = ind->setup.callingsub[0]; + conn->connid = ind->setup.connid; + for (i = 0; i < UNI_NUM_IE_TNS; i++) + conn->tns[i] = ind->setup.tns[i]; + conn->atraffic = ind->setup.atraffic; + conn->mintraffic = ind->setup.mintraffic; + conn->cscope = ind->setup.cscope; + conn->bhli = ind->setup.bhli; + conn->mdcr = ind->setup.mdcr; + + cc_conn_dispatch(conn); + break; + } + + + case CONN_SIG_SETUP_COMPL: + { + struct uni_msg *msg = arg; + struct uniapi_setup_indication *ind __unused = + uni_msg_rptr(msg, struct uniapi_setup_indication *); + + /* SETUP_COMPLETE.indication from UNI */ + if (conn->state == CONN_AB_FLUSH_IND || + conn->state == CONN_AB_WAIT_RESP_OK) + break; + + if (conn->state != CONN_IN_WAIT_COMPL) + goto bad_state; + + cc_conn_set_state(conn, CONN_ACTIVE); + + LIST_FOREACH(party, &conn->parties, link) { + if (party->state == PARTY_WAIT_SETUP_COMPL) + cc_party_set_state(party, PARTY_ACTIVE); + else + cc_party_log(party, "bad state=%s for sig=%s", + ptab[party->state], + cc_conn_sigtab[CONN_SIG_SETUP_COMPL]); + } + + cc_user_sig(conn->user, USER_SIG_SETUP_COMPL, NULL, 0); + break; + } + + + case CONN_SIG_PROC_IND: + { + /* + * ALERTING.indication and PROCEEDING.indication are entirly + * ignored by the specification. We need to at least save the + * connid information element. + */ + struct uni_msg *msg = arg; + struct uniapi_proceeding_indication *ind = uni_msg_rptr(msg, + struct uniapi_proceeding_indication *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CONF: + if (IE_ISGOOD(ind->call_proc.connid)) + conn->connid = ind->call_proc.connid; + break; + + case CONN_AB_FLUSH_IND: + case CONN_AB_WAIT_RESP_OK: + break; + + default: + goto bad_state; + } + break; + } + + case CONN_SIG_ALERTING_IND: + { + struct uni_msg *msg = arg; + struct uniapi_alerting_indication *ind = uni_msg_rptr(msg, + struct uniapi_alerting_indication *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CONF: + if (IE_ISGOOD(ind->alerting.connid)) + conn->connid = ind->alerting.connid; + break; + + case CONN_AB_FLUSH_IND: + case CONN_AB_WAIT_RESP_OK: + break; + + default: + goto bad_state; + } + break; + } + + case CONN_SIG_REL_CONF: + { + /* RELEASE.confirm from UNI */ + struct uni_msg *msg = arg; + struct uniapi_release_confirm *conf = uni_msg_rptr(msg, + struct uniapi_release_confirm *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CONF: + case CONN_ACTIVE: + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + memcpy(conn->user->cause, conf->release.cause, + sizeof(conn->user->cause)); + /* + * If any party is in P6, ok the user + */ + LIST_FOREACH(party, &conn->parties, link) { + if (party->state == PARTY_DROP_WAIT_ACK) { + cc_party_set_state(party, + PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, + USER_SIG_DROP_PARTY_OK, + NULL, party->epref.epref); + } + } + cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, + NULL, 0); + cc_disconnect_from_user(conn); + break; + + case CONN_AB_FLUSH_IND: + case CONN_AB_WAIT_RESP_OK: + break; + + case CONN_IN_WAITING: + cc_disconnect_from_user(conn); + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + break; + + case CONN_IN_ARRIVED: + conn->user->aborted = 1; + memcpy(conn->user->cause, conf->release.cause, + sizeof(conn->user->cause)); + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + cc_disconnect_from_user(conn); + break; + + case CONN_IN_WAIT_COMPL: + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + memcpy(conn->user->cause, conf->release.cause, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, + NULL, 0); + cc_disconnect_from_user(conn); + break; + + default: + goto bad_state; + } + break; + } + + case CONN_SIG_REL_IND: + { + /* RELEASE.ind from UNI */ + struct uni_msg *msg = arg; + struct uniapi_release_indication *conf = uni_msg_rptr(msg, + struct uniapi_release_indication *); + + switch (conn->state) { + + case CONN_OUT_WAIT_CONF: + case CONN_ACTIVE: + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + memcpy(conn->user->cause, conf->release.cause, + sizeof(conn->user->cause)); + /* + * If any party is in P6, ok the user + */ + LIST_FOREACH(party, &conn->parties, link) { + if (party->state == PARTY_DROP_WAIT_ACK) { + cc_party_set_state(party, + PARTY_WAIT_DESTROY); + cc_user_sig(conn->user, + USER_SIG_DROP_PARTY_OK, + NULL, party->epref.epref); + } + } + cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, + NULL, 0); + cc_disconnect_from_user(conn); + break; + + case CONN_AB_FLUSH_IND: + case CONN_AB_WAIT_RESP_OK: + break; + + case CONN_IN_WAITING: + cc_disconnect_from_user(conn); + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + break; + + case CONN_IN_ARRIVED: + conn->user->aborted = 1; + cc_disconnect_from_user(conn); + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + break; + + case CONN_IN_WAIT_COMPL: + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + memcpy(conn->user->cause, conf->release.cause, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, USER_SIG_RELEASE_CONFIRM, + NULL, 0); + cc_disconnect_from_user(conn); + break; + default: + goto bad_state; + break; + } + break; + } + + case CONN_SIG_PARTY_ALERTING_IND: + /* party alerting from UNI */ + if (conn->state == CONN_AB_FLUSH_IND) + break; + if (conn->state != CONN_ACTIVE) + goto bad_state; + /* ignore */ + break; + + case CONN_SIG_PARTY_ADD_ACK_IND: + { + /* ADD PARTY ACKNOWLEDGE from UNI */ + struct uni_msg *msg = arg; + struct uniapi_add_party_ack_indication *ind = uni_msg_rptr(msg, + struct uniapi_add_party_ack_indication *); + + if (conn->state == CONN_AB_FLUSH_IND) + break; + if (conn->state != CONN_ACTIVE) + goto bad_state; + + cc_party_add_ack_ind(conn, &ind->ack.epref); + break; + } + + + case CONN_SIG_PARTY_ADD_REJ_IND: + { + /* ADD PARTY REJECT indication */ + struct uni_msg *msg = arg; + struct uniapi_add_party_rej_indication *ind = uni_msg_rptr(msg, + struct uniapi_add_party_rej_indication *); + + if (conn->state == CONN_AB_FLUSH_IND) + break; + if (conn->state != CONN_ACTIVE) + goto bad_state; + + memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); + conn->user->cause[0] = ind->rej.cause; + + cc_party_add_rej_ind(conn, &ind->rej.epref); + break; + } + + + case CONN_SIG_DROP_PARTY_IND: + { + /* DROP_PARTY.indication from UNI */ + struct uni_msg *msg = arg; + struct uniapi_drop_party_indication *ind = uni_msg_rptr(msg, + struct uniapi_drop_party_indication *); + struct uniapi_drop_party_ack_request *req; + struct uni_msg *u; + + if (conn->state == CONN_AB_FLUSH_IND) + break; + if (conn->state != CONN_ACTIVE) + goto bad_state; + + party = cc_party_find(conn, ind->drop.epref.epref); + if (party == NULL) { + cc_party_log(party, "no party for %s", + cc_conn_sigtab[sig]); + break; + } + + u = uni_msg_alloc(sizeof(*req)); + if (u == NULL) + return; + + memset(&conn->user->cause[1], 0, sizeof(conn->user->cause[1])); + conn->user->cause[0] = ind->drop.cause; + + switch (party->state) { + + default: + cc_party_log(party, "bad state %s for DROP.ind", + ptab[party->state]); + /* FALLTHRU */ + + case PARTY_ACTIVE: /* P1 -> P9 */ + cc_party_set_state(party, PARTY_WAIT_DROP_ACK_OK); + break; + + case PARTY_ADD_WAIT_ACK: /* P4 -> P12 */ + cc_party_set_state(party, PARTY_ADD_DROPACK_WAIT_OK); + break; + } + + /* + * Construct message to UNI. + */ + req = uni_msg_wptr(u, struct uniapi_drop_party_ack_request *); + memset(req, 0, sizeof(*req)); + u->b_wptr += sizeof(*req); + + IE_SETPRESENT(req->ack.epref); + req->ack.hdr.act = UNI_MSGACT_DEFAULT; + req->ack.hdr.cref = conn->cref; + + req->ack.epref.flag = 0; + req->ack.epref.epref = ind->drop.epref.epref; + + cc_send_uni(conn, UNIAPI_DROP_PARTY_ACK_request, u); + break; + } + + case CONN_SIG_OK: + { + /* OK response from UNI */ + struct ccuser *user = conn->user; + + switch (conn->state) { + + case CONN_OUT_WAIT_OK: /* C3 */ + cc_conn_set_state(conn, CONN_OUT_WAIT_CONF); + if (conn->user != NULL) + cc_user_sig(conn->user, + USER_SIG_CONNECT_OUTGOING_OK, NULL, 0); + break; + + case CONN_AB_WAIT_RESP_OK: /* C33 */ + case CONN_AB_WAIT_REQ_OK: /* C34 */ + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + break; + + case CONN_REL_WAIT_OK: /* C20 */ + case CONN_REL_IN_WAIT_OK: /* C15 */ + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + if (conn->user != NULL) { + /* connection has not been aborted */ + memset(&conn->user->cause, 0, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, + USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } + break; + + case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ + if (user == NULL) { + /* has been aborted */ + do_release_request(conn, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); + break; + } + cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); + cc_disconnect_from_user(conn); + cc_user_sig(user, USER_SIG_ACCEPT_OK, NULL, 0); + if (conn->acceptor == NULL) { + do_release_request(conn, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_REQ_OK); + break; + } + cc_connect_to_user(conn, conn->acceptor); + cc_conn_reset_acceptor(conn); + cc_user_sig(conn->user, USER_SIG_ACCEPTING, NULL, 0); + break; + + case CONN_REJ_WAIT_OK: /* C14 */ + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + if (user != NULL) { + cc_disconnect_from_user(conn); + cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); + } + break; + + default: + /* maybe it's for a party */ + LIST_FOREACH(party, &conn->parties, link) { + switch (party->state) { + + case PARTY_ADD_WAIT_OK: /* P3 */ + if (user != NULL) + cc_user_sig(user, + USER_SIG_ADD_PARTY_OK, + NULL, 0); + cc_party_set_state(party, + PARTY_ADD_WAIT_ACK); + goto ex_party_ok; + + case PARTY_DROP_WAIT_OK: /* P5 */ + cc_party_set_state(party, + PARTY_DROP_WAIT_ACK); + goto ex_party_ok; + + case PARTY_WAIT_DROP_ACK_OK: /* P9 */ + case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ + { + struct ccparty *p1; + + cc_party_set_state(party, + PARTY_WAIT_DESTROY); + /* signal to user only if there are any other parties */ + LIST_FOREACH(p1, &conn->parties, link) + if (p1 != party) + break; + if (p1 != NULL && user != NULL) + cc_user_sig(user, + USER_SIG_DROP_PARTY_IND, + NULL, + party->epref.epref); + + goto ex_party_ok; + } + + case PARTY_ADD_DROP_WAIT_OK: /* P11 */ + cc_party_set_state(party, + PARTY_DROP_WAIT_ACK); + goto ex_party_ok; + + default: + break; + } + } + goto bad_state; + ex_party_ok: + break; + } + break; + } + + case CONN_SIG_ERROR: + { + /* error response from UNI */ + u_int reason = (iarg >> 16) & 0xffff; + u_int state = iarg & 0xffff; + struct ccuser *user = conn->user; + + switch (conn->state) { + + case CONN_OUT_WAIT_CREATE: /* C2 */ + cc_conn_rem_port(conn); + cc_conn_set_state(conn, CONN_OUT_PREPARING); + if (conn->user != NULL) + cc_user_sig(conn->user, + USER_SIG_CONNECT_OUTGOING_ERR, + NULL, ATM_MKUNIERR(reason)); + break; + + case CONN_OUT_WAIT_OK: /* C3 */ + cc_conn_set_state(conn, CONN_OUT_WAIT_DESTROY); + conn->reason = reason; + break; + + case CONN_AB_WAIT_REQ_OK: /* C33 */ + if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, conn->cause); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + break; + } + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + break; + + case CONN_AB_WAIT_RESP_OK: /* C34 */ + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + break; + + case CONN_REL_WAIT_OK: /* C20 */ + if (user == NULL) { + /* connection has been aborted. */ + if (state == UNI_CALLSTATE_U10) { + /* do what we can */ + do_release_request(conn, conn->cause); + cc_conn_set_state(conn, + CONN_AB_WAIT_REQ_OK); + } else if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, + CONN_AB_WAIT_RESP_OK); + } else { + cc_conn_set_state(conn, + CONN_AB_FLUSH_IND); + } + break; + } + if (state == UNI_CALLSTATE_U10) { + cc_conn_set_state(conn, CONN_ACTIVE); + cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, + NULL, reason); + } else if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + memset(&conn->user->cause, 0, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, + USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } else { + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + memset(&conn->user->cause, 0, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, + USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } + break; + + case CONN_IN_WAIT_ACCEPT_OK: /* C12 */ + if (user == NULL) { + /* connection was aborted */ + if (state == UNI_CALLSTATE_U6 || + state == UNI_CALLSTATE_U7 || + state == UNI_CALLSTATE_U9 || + state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, + CONN_AB_WAIT_RESP_OK); + } else { + cc_conn_set_state(conn, + CONN_AB_FLUSH_IND); + } + break; + } + cc_conn_reset_acceptor(conn); + if (state == UNI_CALLSTATE_U6 || + state == UNI_CALLSTATE_U9 || + state == UNI_CALLSTATE_U7) { + cc_user_sig(user, USER_SIG_ACCEPT_ERR, + NULL, ATM_MKUNIERR(reason)); + cc_conn_set_state(conn, CONN_IN_ARRIVED); + } else if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_disconnect_from_user(conn); + cc_user_sig(user, USER_SIG_ACCEPT_ERR, + user, ATMERR_PREVIOUSLY_ABORTED); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + } else { + cc_disconnect_from_user(conn); + cc_user_sig(user, USER_SIG_ACCEPT_ERR, + user, ATMERR_PREVIOUSLY_ABORTED); + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + } + break; + + case CONN_REJ_WAIT_OK: /* C14 */ + if (user == NULL) { + /* connection has been aborted. */ + if (state == UNI_CALLSTATE_U6 || + state == UNI_CALLSTATE_U7 || + state == UNI_CALLSTATE_U9 || + state == UNI_CALLSTATE_U12) { + /* do what we can */ + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, + CONN_AB_WAIT_RESP_OK); + } else { + cc_conn_set_state(conn, + CONN_AB_FLUSH_IND); + } + break; + } + if (state == UNI_CALLSTATE_U6 || + state == UNI_CALLSTATE_U9 || + state == UNI_CALLSTATE_U7) { + cc_user_sig(user, USER_SIG_REJECT_ERR, + NULL, ATM_MKUNIERR(reason)); + cc_conn_set_state(conn, CONN_IN_ARRIVED); + } else { + cc_disconnect_from_user(conn); + cc_user_sig(user, USER_SIG_REJECT_OK, NULL, 0); + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + } + break; + + case CONN_REL_IN_WAIT_OK: /* C15 */ + if (user == NULL) { + /* connection has been aborted. */ + if (state == UNI_CALLSTATE_U8) { + /* do what we can */ + do_release_request(conn, conn->cause); + cc_conn_set_state(conn, + CONN_AB_WAIT_REQ_OK); + } else if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, + CONN_AB_WAIT_RESP_OK); + } else { + cc_conn_set_state(conn, + CONN_AB_FLUSH_IND); + } + break; + } + if (state == UNI_CALLSTATE_U8) { + cc_conn_set_state(conn, CONN_IN_WAIT_COMPL); + cc_user_sig(conn->user, USER_SIG_RELEASE_ERR, + NULL, reason); + } else if (state == UNI_CALLSTATE_U12) { + do_release_response(conn, 0, NULL); + cc_conn_set_state(conn, CONN_AB_WAIT_RESP_OK); + memset(&conn->user->cause, 0, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, + USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } else { + cc_conn_set_state(conn, CONN_AB_FLUSH_IND); + memset(&conn->user->cause, 0, + sizeof(conn->user->cause)); + cc_user_sig(conn->user, + USER_SIG_RELEASE_CONFIRM, NULL, 0); + cc_disconnect_from_user(conn); + } + break; + + default: + /* maybe it's for a party */ + LIST_FOREACH(party, &conn->parties, link) { + switch (party->state) { + + case PARTY_ADD_WAIT_CREATE: /* P2 */ + cc_party_destroy(party); + if (user != NULL) + cc_user_sig(user, + USER_SIG_ADD_PARTY_ERR, + NULL, ATM_MKUNIERR(reason)); + goto ex_party_err; + + case PARTY_ADD_WAIT_OK: /* P3 */ + cc_party_set_state(party, + PARTY_WAIT_DESTROY); + if (user != NULL) + cc_user_sig(user, + USER_SIG_ADD_PARTY_ERR, + NULL, ATM_MKUNIERR(reason)); + goto ex_party_err; + + case PARTY_DROP_WAIT_OK: /* P5 */ + cc_party_set_state(party, + PARTY_ACTIVE); + if (user != NULL) + cc_user_sig(user, + USER_SIG_DROP_PARTY_ERR, + NULL, ATM_MKUNIERR(reason)); + goto ex_party_err; + + case PARTY_WAIT_DROP_ACK_OK: /* P9 */ + cc_party_set_state(party, + PARTY_ACTIVE); + goto ex_party_err; + + case PARTY_ADD_DROP_WAIT_OK: /* P11 */ + cc_party_set_state(party, + PARTY_ADD_WAIT_ACK); + if (user != NULL) + cc_user_sig(user, + USER_SIG_DROP_PARTY_ERR, + NULL, ATM_MKUNIERR(reason)); + goto ex_party_err; + + case PARTY_ADD_DROPACK_WAIT_OK:/* P12 */ + cc_party_set_state(party, + PARTY_ADD_WAIT_ACK); + goto ex_party_err; + + default: + break; + } + } + cc_conn_log(conn, "unexpected reason=%u ustate=%u " + "state=%s\n", reason, state, stab[conn->state]); + ex_party_err: + break; + } + break; + } + + case CONN_SIG_PARTY_CREATED: + { + struct uni_msg *msg = arg; + struct uniapi_party_created *pcr = uni_msg_rptr(msg, + struct uniapi_party_created *); + + party = cc_party_find(conn, pcr->epref.epref); + if (party == NULL) { + /* for incoming connections we see the party-created + * immediately after the call-create so that we + * must be in C10 */ + switch (conn->state) { + + case CONN_IN_PREPARING: + party = cc_party_create(conn, + pcr->epref.epref, 1); + if (party == NULL) + break; + cc_party_set_state(party, + PARTY_WAIT_SETUP_COMPL); + break; + + case CONN_OUT_WAIT_OK: + party = cc_party_create(conn, + pcr->epref.epref, 0); + if (party == NULL) + break; + cc_party_set_state(party, + PARTY_WAIT_SETUP_CONF); + break; + + default: + goto bad_state; + } + break; + } + /* this is for an ADD-PARTY */ + if (conn->state != CONN_ACTIVE) + goto bad_state; + if (party->state != PARTY_ADD_WAIT_CREATE) + goto bad_party_state; + cc_party_set_state(party, PARTY_ADD_WAIT_OK); + break; + } + + case CONN_SIG_PARTY_DESTROYED: + { + struct uni_msg *msg = arg; + struct uniapi_party_destroyed *pcr = uni_msg_rptr(msg, + struct uniapi_party_destroyed *); + + party = cc_party_find(conn, pcr->epref.epref); + if (party == NULL) { + cc_conn_log(conn, "no party to destroy %u/%u", + pcr->epref.flag, pcr->epref.epref); + break; + } + cc_party_destroy(party); + break; + } + + } + + return; + + bad_state: + cc_conn_log(conn, "bad state=%s for signal=%s", + stab[conn->state], cc_conn_sigtab[sig]); + return; + + bad_party_state: + cc_conn_log(conn, "bad party state=%s for signal=%s", + ptab[party->state], cc_conn_sigtab[sig]); + return; +} diff --git a/sys/contrib/ngatm/netnatm/api/cc_data.c b/sys/contrib/ngatm/netnatm/api/cc_data.c new file mode 100644 index 000000000000..bf607de1e45b --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_data.c @@ -0,0 +1,226 @@ +/* +* Copyright (c) 2004 +* Hartmut Brandt +* All rights reserved. +* +* Author: Harti Brandt +* +* 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_data.c,v 1.1 2004/07/08 08:21:50 brandt Exp $ +* +* ATM API as defined per af-saa-0108 +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Create a new call control instance + */ +struct ccdata * +cc_create(const struct cc_funcs *vtab) +{ + struct ccdata *cc; + + cc = CCMALLOC(sizeof(*cc)); + if (cc == NULL) + return (NULL); + + LIST_INIT(&cc->user_list); + TAILQ_INIT(&cc->port_list); + LIST_INIT(&cc->orphaned_conns); + TAILQ_INIT(&cc->sigs); + TAILQ_INIT(&cc->def_sigs); + TAILQ_INIT(&cc->free_sigs); + cc->funcs = vtab; + cc->cookie = 0; + + return (cc); +} + +/* + * Reset everything the hard way by just freeing the data + */ +void +cc_reset(struct ccdata *cc) +{ + + while (!LIST_EMPTY(&cc->user_list)) + cc_user_destroy(LIST_FIRST(&cc->user_list)); + + while (!TAILQ_EMPTY(&cc->port_list)) + cc_port_destroy(TAILQ_FIRST(&cc->port_list), 1); + + while (!LIST_EMPTY(&cc->orphaned_conns)) + cc_conn_destroy(LIST_FIRST(&cc->orphaned_conns)); + + CCASSERT(LIST_EMPTY(&cc->user_list), + ("user list not empty")); + CCASSERT(LIST_EMPTY(&cc->orphaned_conns), + ("still orphaned conns")); + + cc_sig_flush_all(cc); + + cc->cookie = 0; +} + +/* + * Destroy a call control instance and free all data + */ +void +cc_destroy(struct ccdata *cc) +{ + + cc_reset(cc); + CCFREE(cc); +} + +/* + * set/get logging flags + */ +void +cc_set_log(struct ccdata *cc, u_int flags) +{ + cc->log = flags; +} +u_int +cc_get_log(const struct ccdata *cc) +{ + return (cc->log); +} + +/* get extended status */ +int +cc_get_extended_status(const struct ccdata *cc, struct atm_exstatus *status, + struct atm_exstatus_ep **pep, struct atm_exstatus_port **pport, + struct atm_exstatus_conn **pconn, struct atm_exstatus_party **pparty) +{ + const struct ccuser *user; + const struct ccport *port; + const struct ccconn *conn; + const struct ccparty *party; + struct atm_exstatus_ep *eep; + struct atm_exstatus_port *eport; + struct atm_exstatus_conn *econn; + struct atm_exstatus_party *eparty; + + /* count and allocate */ + status->neps = 0; + LIST_FOREACH(user, &cc->user_list, node_link) + status->neps++; + + status->nports = 0; + status->nconns = 0; + status->nparties = 0; + LIST_FOREACH(conn, &cc->orphaned_conns, port_link) { + status->nconns++; + LIST_FOREACH(party, &conn->parties, link) + status->nparties++; + } + TAILQ_FOREACH(port, &cc->port_list, node_link) { + status->nports++; + LIST_FOREACH(conn, &port->conn_list, port_link) { + status->nconns++; + LIST_FOREACH(party, &conn->parties, link) + status->nparties++; + } + } + + *pep = CCMALLOC(sizeof(**pep) * status->neps); + *pport = CCMALLOC(sizeof(**pport) * status->nports); + *pconn = CCMALLOC(sizeof(**pconn) * status->nconns); + *pparty = CCMALLOC(sizeof(**pparty) * status->nparties); + + if (*pep == NULL || *pport == NULL || + *pconn == NULL || *pparty == NULL) { + CCFREE(*pep); + CCFREE(*pport); + CCFREE(*pconn); + CCFREE(*pparty); + return (ENOMEM); + } + + eep = *pep; + eport = *pport; + econn = *pconn; + eparty = *pparty; + + /* collect information */ + LIST_FOREACH(user, &cc->user_list, node_link) { + strcpy(eep->name, user->name); + eep->state = user->state; + eep++; + } + + LIST_FOREACH(conn, &cc->orphaned_conns, port_link) { + econn->id = econn - *pconn; + econn->port = 0; + if (conn->user != NULL) + strcpy(econn->ep, conn->user->name); + else + econn->ep[0] = '\0'; + econn->state = conn->state; + econn->cref = conn->cref.cref; + if (conn->cref.flag) + econn->cref |= (1 << 23); + LIST_FOREACH(party, &conn->parties, link) { + eparty->connid = econn - *pconn; + eparty->epref = party->epref.epref; + eparty->state = party->state; + eparty++; + } + econn++; + } + + TAILQ_FOREACH(port, &cc->port_list, node_link) { + eport->portno = port->param.port; + eport->state = port->admin; + LIST_FOREACH(conn, &port->conn_list, port_link) { + econn->id = econn - *pconn; + econn->port = port->param.port; + if (conn->user != NULL) + strcpy(econn->ep, conn->user->name); + else + econn->ep[0] = '\0'; + econn->state = conn->state; + econn->cref = conn->cref.cref; + if (conn->cref.flag) + econn->cref |= (1 << 23); + LIST_FOREACH(party, &conn->parties, link) { + eparty->connid = econn - *pconn; + eparty->epref = party->epref.epref; + eparty->state = party->state; + eparty++; + } + econn++; + } + eport++; + } + return (0); +} diff --git a/sys/contrib/ngatm/netnatm/api/cc_dump.c b/sys/contrib/ngatm/netnatm/api/cc_dump.c new file mode 100644 index 000000000000..d3b0c5819133 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_dump.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2003-2004 + * Hartmut Brandt + * All rights reserved. + * + * Author: Harti Brandt + * + * 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_dump.c,v 1.1 2004/07/08 08:21:51 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _KERNEL +#ifdef __FreeBSD__ +#include +#endif +#else /* !_KERNEL */ +#include +#endif + +/* + * local structure to reduce number of arguments to functions + */ +struct dump { + struct ccdata *cc; /* what to dump */ + size_t maxsiz; /* size of user buffer */ + cc_dump_f func; /* user function */ + void *uarg; /* user supplied argument */ + char *buf; /* user buffer */ + size_t len; /* current string length */ + int ret; /* return code */ +}; + +static void cc_dumpf(struct dump *, const char *, ...) __printflike(2, 3); + +static void +cc_dumpf(struct dump *d, const char *fmt, ...) +{ + va_list ap; + int n; + + if (d->ret != 0) + return; + if (d->len >= d->maxsiz - 1) { + d->ret = d->func(d->cc, d->uarg, d->buf); + if (d->ret != 0) + return; + d->buf[0] = '\0'; + d->len = 0; + } + va_start(ap, fmt); + n = vsnprintf(d->buf + d->len, d->maxsiz - d->len, fmt, ap); + va_end(ap); + + if (n < 0) { + d->ret = errno; + return; + } + if ((size_t)n < d->maxsiz - d->len) { + d->len += n; + return; + } + + /* undo the vsnprintf() and flush */ + d->buf[d->len] = '\0'; + d->ret = d->func(d->cc, d->uarg, d->buf); + if (d->ret != 0) + return; + d->buf[0] = '\0'; + d->len = 0; + + va_start(ap, fmt); + n = vsnprintf(d->buf, d->maxsiz, fmt, ap); + va_end(ap); + + if (n < 0) { + d->ret = errno; + return; + } + if ((size_t)n >= d->maxsiz) { + /* ok, truncate */ + d->len = d->maxsiz - 1; + return; + } + d->len = n; +} + +/* + * Dump a SAP + */ +static void +cc_dump_sap(struct dump *d, const struct uni_sap *sap) +{ + static const char *const tagtab[] = { + [UNISVE_ABSENT] "absent", + [UNISVE_ANY] "any", + [UNISVE_PRESENT]"present" + }; + static const char *const plantab[] = { + [UNI_ADDR_E164] "E164", + [UNI_ADDR_ATME] "ATME", + }; + static const char *const hlitab[] = { + [UNI_BHLI_ISO] "ISO", + [UNI_BHLI_VENDOR] "VENDOR", + [UNI_BHLI_USER] "USER" + }; + u_int i; + + cc_dumpf(d, " sap(%p):\n", sap); + cc_dumpf(d, " addr=%s", tagtab[sap->addr.tag]); + if (sap->addr.tag == UNISVE_PRESENT) { + cc_dumpf(d, " %s %u ", plantab[sap->addr.plan], sap->addr.len); + if (sap->addr.plan == UNI_ADDR_E164) + for (i = 0; i < sap->addr.len; i++) + cc_dumpf(d, "%c", sap->addr.addr[i]); + else + for (i = 0; i < sap->addr.len; i++) + cc_dumpf(d, "%02x", sap->addr.addr[i]); + } + cc_dumpf(d, "\n"); + + cc_dumpf(d, " selector=%s", tagtab[sap->selector.tag]); + if (sap->selector.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x", sap->selector.selector); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " blli_id2=%s", tagtab[sap->blli_id2.tag]); + if (sap->blli_id2.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x %02x", sap->blli_id2.proto, + sap->blli_id2.user); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " blli_id3=%s", tagtab[sap->blli_id3.tag]); + if (sap->blli_id3.tag == UNISVE_PRESENT) + cc_dumpf(d, " %02x,%02x, %02x(%d),%03x,%02x", + sap->blli_id3.proto, sap->blli_id3.user, + sap->blli_id3.ipi, sap->blli_id3.noipi, + sap->blli_id3.oui, sap->blli_id3.pid); + cc_dumpf(d, "\n"); + + cc_dumpf(d, " bhli=%s", tagtab[sap->bhli.tag]); + if (sap->bhli.tag == UNISVE_PRESENT) { + cc_dumpf(d, " %s ", hlitab[sap->bhli.type]); + for (i = 0; i < sap->bhli.len; i++) + cc_dumpf(d, "%02x", sap->bhli.info[i]); + } + cc_dumpf(d, "\n"); +} + +/* + * Dump a user. + */ +static void +cc_dump_user(struct dump *d, const struct ccuser *user) +{ + struct ccconn *conn; + + cc_dumpf(d, "user(%p): %s '%s' %s\n", user, + cc_user_state2str(user->state), user->name, + (user->config == USER_P2P) ? "p2p" : + (user->config == USER_ROOT) ? "root" : + (user->config == USER_LEAF) ? "leaf" : "?"); + if (user->sap) + cc_dump_sap(d, user->sap); + + cc_dumpf(d, " queue=%u/%u accepted=%p aborted=%u\n", user->queue_max, + user->queue_act, user->accepted, user->aborted); + + cc_dumpf(d, " connq:"); + TAILQ_FOREACH(conn, &user->connq, connq_link) + cc_dumpf(d, "%p", conn); + cc_dumpf(d, "\n"); +} + +/* + * Dump a party + */ +static void +cc_dump_party(struct dump *d, const struct ccparty *party, const char *pfx) +{ + + cc_dumpf(d, "%s party(%p): %u.%u %s\n", pfx, party, + party->epref.flag, party->epref.epref, + cc_party_state2str(party->state)); +} + +/* + * Dump a connection + */ +static void +cc_dump_conn(struct dump *d, const struct ccconn *conn, const char *pfx) +{ + const struct ccparty *party; + + cc_dumpf(d, "%sconn(%p): %s\n", pfx, conn, + cc_conn_state2str(conn->state)); + cc_dumpf(d, "%s user=%p cref=%u.%u acceptor=%p\n", pfx, + conn->user, conn->cref.cref, conn->cref.flag, + conn->acceptor); + + cc_dumpf(d, "%s blli_sel=%u\n", pfx, conn->blli_selector); + + LIST_FOREACH(party, &conn->parties, link) + cc_dump_party(d, party, pfx); +} + +/* + * Dump a port + */ +static void +cc_dump_port(struct dump *d, const struct ccport *p) +{ + u_int i; + const struct ccaddr *a; + const struct ccconn *c; + const struct ccreq *r; + + static const char *const ttab[] = { + [UNI_ADDR_UNKNOWN] = "unknown", + [UNI_ADDR_INTERNATIONAL] = "international", + [UNI_ADDR_NATIONAL] = "national", + [UNI_ADDR_NETWORK] = "network", + [UNI_ADDR_SUBSCR] = "subscr", + [UNI_ADDR_ABBR] = "abbr", + }; + static const char *const ptab[] = { + [UNI_ADDR_UNKNOWN] = "unknown", + [UNI_ADDR_E164] = "e164", + [UNI_ADDR_ATME] = "atme", + [UNI_ADDR_DATA] = "data", + [UNI_ADDR_PRIVATE] = "private", + }; + + cc_dumpf(d, "port(%p) %u: %s\n", p, p->param.port, + (p->admin == CCPORT_STOPPED) ? "STOPPED" : + (p->admin == CCPORT_RUNNING) ? "RUNNING" : "????"); + cc_dumpf(d, " pcr=%u bits=%u.%u ids=%u/%u/%u esi=%02x:%02x:" + "%02x:%02x:%02x:%02x naddrs=%u\n", p->param.pcr, + p->param.max_vpi_bits, p->param.max_vci_bits, p->param.max_svpc_vpi, + p->param.max_svcc_vpi, p->param.min_svcc_vci, p->param.esi[0], + p->param.esi[1], p->param.esi[2], p->param.esi[3], p->param.esi[4], + p->param.esi[5], p->param.num_addrs); + + cc_dumpf(d, " cookies:"); + TAILQ_FOREACH(r, &p->cookies, link) + cc_dumpf(d, " %u(%p,%u)", r->cookie, r->conn, r->req); + cc_dumpf(d, "\n"); + + TAILQ_FOREACH(a, &p->addr_list, port_link) { + cc_dumpf(d, " addr(%p): %s %s %u ", a, + (a->addr.type < sizeof(ttab) / sizeof(ttab[0]) && + ttab[a->addr.type] != NULL) ? ttab[a->addr.type] : "?", + (a->addr.plan < sizeof(ptab) / sizeof(ptab[0]) && + ptab[a->addr.plan] != NULL) ? ptab[a->addr.plan] : "?", + a->addr.len); + for (i = 0; i < a->addr.len; i++) + cc_dumpf(d, "%02x", a->addr.addr[i]); + cc_dumpf(d, "\n"); + } + LIST_FOREACH(c, &p->conn_list, port_link) + cc_dump_conn(d, c, " "); +} + +/* + * Produce a textual dump of the state + */ +int +cc_dump(struct ccdata *cc, size_t maxsiz, cc_dump_f func, void *uarg) +{ + struct dump d; + struct ccuser *user; + struct ccconn *conn; + struct ccport *port; + + d.ret = 0; + d.uarg = uarg; + d.maxsiz = maxsiz; + d.cc = cc; + d.func = func; + d.buf = CCMALLOC(maxsiz); + if (d.buf == NULL) + return (ENOMEM); + d.len = 0; + + cc_dumpf(&d, "dump of node %p\n", cc); + + TAILQ_FOREACH(port, &cc->port_list, node_link) + cc_dump_port(&d, port); + + LIST_FOREACH(user, &cc->user_list, node_link) + cc_dump_user(&d, user); + + cc_dumpf(&d, "orphaned conns:\n"); + LIST_FOREACH(conn, &cc->orphaned_conns, port_link) + cc_dump_conn(&d, conn, ""); + + if (d.len > 0 && d.ret == 0) + d.ret = d.func(d.cc, d.uarg, d.buf); + + CCFREE(d.buf); + return (d.ret); +} 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 000000000000..f01a723260b2 --- /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 + * + * 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 +#include +#include +#include +#include +#include +#include + +/* + * 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); +} + diff --git a/sys/contrib/ngatm/netnatm/api/cc_sig.c b/sys/contrib/ngatm/netnatm/api/cc_sig.c new file mode 100644 index 000000000000..ae6fcce51229 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_sig.c @@ -0,0 +1,350 @@ +/* +* Copyright (c) 2004 +* Hartmut Brandt +* All rights reserved. +* +* Author: Harti Brandt +* +* 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_sig.c,v 1.1 2004/07/08 08:21:54 brandt Exp $ +* +* ATM API as defined per af-saa-0108 +* +* Generic signal handling +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +enum { + SIG_USER, + SIG_CONN, +}; + +struct ccsig { + u_char type; /* type of target */ + u_char has_msg; /* arg1 is a message */ + void *target; /* target instance */ + u_int sig; /* signal */ + void *arg1; /* argument */ + u_int arg2; /* argument */ + TAILQ_ENTRY(ccsig) link; +}; + +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_sig_log(CC, FMT, ARGS...) do { \ + if ((CC)->log & CCLOG_SIGS) \ + (CC)->funcs->log("%s: " FMT, __FUNCTION__ , ## ARGS); \ + } while (0) +#else +#define cc_sig_log(CC, FMT, ...) do { \ + if ((CC)->log & CCLOG_SIGS) \ + (CC)->funcs->log("%s: " FMT, __func__, __VA_ARGS__); \ + } while (0) +#endif + + +const char *const cc_user_sigtab[] = { +#define DEF(N) [USER_SIG_##N] = #N, +USER_SIGS +#undef DEF +}; + +const char *const cc_conn_sigtab[] = { +#define DEF(N) [CONN_SIG_##N] = #N, +CONN_SIGS +#undef DEF +}; + + +/* + * Allocate and populate a signal + */ +static /* __inline */ struct ccsig * +sig_alloc(struct ccdata *cc, u_int type, void *target, u_int has_msg, + u_int sig, void *arg1, u_int arg2) +{ + struct ccsig *s; + + if ((s = TAILQ_FIRST(&cc->free_sigs)) == NULL) { + s = CCZALLOC(sizeof(struct ccsig)); + if (s == NULL) { + cc_log(cc, "signal %u/%u lost - ENOMEM", type, sig); + return (NULL); + } + } else + TAILQ_REMOVE(&cc->free_sigs, s, link); + + s->type = type; + s->has_msg = has_msg; + s->target = target; + s->sig = sig; + s->arg1 = arg1; + s->arg2 = arg2; + + return (s); +} + +/* + * Queue a signal to this user + */ +int +cc_user_sig(struct ccuser *user, enum user_sig sig, void *arg1, u_int arg2) +{ + struct ccsig *s; + + s = sig_alloc(user->cc, SIG_USER, user, 0, sig, arg1, arg2); + if (s == NULL) + return (ENOMEM); + TAILQ_INSERT_TAIL(&user->cc->sigs, s, link); + cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig], + user); + return (0); +} + +/* Queue a signal with message to this user */ +int +cc_user_sig_msg(struct ccuser *user, enum user_sig sig, struct uni_msg *msg) +{ + struct ccsig *s; + + s = sig_alloc(user->cc, SIG_USER, user, msg != NULL, sig, msg, 0); + if (s == NULL) + return (ENOMEM); + TAILQ_INSERT_TAIL(&user->cc->sigs, s, link); + cc_sig_log(user->cc, "queuing sig %s to user %p", cc_user_sigtab[sig], + user); + return (0); +} + +/* + * Signal to connection + */ +static int +sig_conn(struct ccconn *conn, enum conn_sig sig, u_int has_msg, void *arg) +{ + struct ccsig *s; + const struct ccreq *r = NULL; + + s = sig_alloc(conn->cc, SIG_CONN, conn, has_msg, sig, arg, 0); + if (s == NULL) + return (ENOMEM); + + if (conn->port != NULL) { + /* argh */ + TAILQ_FOREACH(r, &conn->port->cookies, link) + if (r->conn == conn) + break; + } + if (r == NULL) { + TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); + cc_sig_log(conn->cc, "queuing sig %s to conn %p", + cc_conn_sigtab[sig], conn); + } else { + TAILQ_INSERT_TAIL(&conn->cc->def_sigs, s, link); + cc_sig_log(conn->cc, "queuing defered sig %s to conn %p", + cc_conn_sigtab[sig], conn); + } + return (0); +} + +/* + * Queue a signal to a connection. + */ +int +cc_conn_sig(struct ccconn *conn, enum conn_sig sig, void *arg1) +{ + + return (sig_conn(conn, sig, 0, arg1)); +} + +/* + * signal with message to connection + */ +int +cc_conn_sig_msg(struct ccconn *conn, enum conn_sig sig, struct uni_msg *msg) +{ + + return (sig_conn(conn, sig, (msg != NULL), msg)); +} +int +cc_conn_sig_msg_nodef(struct ccconn *conn, enum conn_sig sig, + struct uni_msg *msg) +{ + struct ccsig *s; + + s = sig_alloc(conn->cc, SIG_CONN, conn, (msg != NULL), sig, msg, 0); + if (s == NULL) + return (ENOMEM); + + TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); + cc_sig_log(conn->cc, "queuing sig %s to conn %p", + cc_conn_sigtab[sig], conn); + + return (0); +} + +/* + * Queue a response signal to a connection. + */ +int +cc_conn_resp(struct ccconn *conn, enum conn_sig sig, u_int cookie __unused, + u_int reason, u_int state) +{ + struct ccsig *s, *s1, *s2; + + s = sig_alloc(conn->cc, SIG_CONN, conn, 0, sig, NULL, + ((reason & 0xffff) << 16) | (state & 0xffff)); + if (s == NULL) + return (ENOMEM); + + TAILQ_INSERT_TAIL(&conn->cc->sigs, s, link); + + cc_sig_log(conn->cc, "queuing response %s to conn %p", + cc_conn_sigtab[sig], conn); + + s1 = TAILQ_FIRST(&conn->cc->def_sigs); + while (s1 != NULL) { + s2 = TAILQ_NEXT(s1, link); + if (s1->type == SIG_CONN && s1->target == conn) { + TAILQ_REMOVE(&conn->cc->def_sigs, s1, link); + TAILQ_INSERT_AFTER(&conn->cc->sigs, s, s1, link); + cc_sig_log(conn->cc, "undefering sig %s to conn %p", + cc_conn_sigtab[s1->sig], conn); + s = s1; + } + s1 = s2; + } + + return (0); +} + +/* + * Flush all signals to a given target from both queues + */ +static /* __inline */ void +sig_flush(struct ccdata *cc, u_int type, void *target) +{ + struct ccsig *s, *s1; + + s = TAILQ_FIRST(&cc->sigs); + while (s != NULL) { + s1 = TAILQ_NEXT(s, link); + if (s->type == type && s->target == target) { + if (s->has_msg) + uni_msg_destroy((struct uni_msg *)s->arg1); + TAILQ_REMOVE(&cc->sigs, s, link); + TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); + } + s = s1; + } + + s = TAILQ_FIRST(&cc->def_sigs); + while (s != NULL) { + s1 = TAILQ_NEXT(s, link); + if (s->type == type && s->target == target) { + if (s->has_msg) + uni_msg_destroy((struct uni_msg *)s->arg1); + TAILQ_REMOVE(&cc->def_sigs, s, link); + TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); + } + s = s1; + } +} + +/* + * Flush all signals to this user + */ +void +cc_user_sig_flush(struct ccuser *user) +{ + + cc_sig_log(user->cc, "flushing signals to user %p", user); + sig_flush(user->cc, SIG_USER, user); +} + +/* + * Flush all signals to this connection + */ +void +cc_conn_sig_flush(struct ccconn *conn) +{ + + cc_sig_log(conn->cc, "flushing signals to conn %p", conn); + sig_flush(conn->cc, SIG_CONN, conn); +} + +/* + * Do the work + */ +void +cc_work(struct ccdata *cc) +{ + struct ccsig *s; + + cc_sig_log(cc, "start %s", "work"); + while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) { + TAILQ_REMOVE(&cc->sigs, s, link); + if (s->type == SIG_USER) + cc_user_sig_handle(s->target, s->sig, s->arg1, s->arg2); + else { + cc_conn_sig_handle(s->target, s->sig, s->arg1, s->arg2); + if (s->has_msg) + uni_msg_destroy(s->arg1); + } + TAILQ_INSERT_HEAD(&cc->free_sigs, s, link); + } + cc_sig_log(cc, "end %s", "work"); +} + +/* + * flush all signals + */ +void +cc_sig_flush_all(struct ccdata *cc) +{ + struct ccsig *s; + + while ((s = TAILQ_FIRST(&cc->sigs)) != NULL) { + if (s->has_msg) + uni_msg_destroy((struct uni_msg *)s->arg1); + TAILQ_REMOVE(&cc->sigs, s, link); + CCFREE(s); + } + while ((s = TAILQ_FIRST(&cc->def_sigs)) != NULL) { + if (s->has_msg) + uni_msg_destroy((struct uni_msg *)s->arg1); + TAILQ_REMOVE(&cc->def_sigs, s, link); + CCFREE(s); + } + while ((s = TAILQ_FIRST(&cc->free_sigs)) != NULL) { + TAILQ_REMOVE(&cc->free_sigs, s, link); + CCFREE(s); + } +} diff --git a/sys/contrib/ngatm/netnatm/api/cc_user.c b/sys/contrib/ngatm/netnatm/api/cc_user.c new file mode 100644 index 000000000000..a4d5c76ffdd5 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/cc_user.c @@ -0,0 +1,1921 @@ +/* + * 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 + * + * 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_user.c,v 1.2 2004/07/08 09:17:18 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + * + * User side (upper half) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* This file handles messages to a USER. +*/ +static const char *stab[] = { +#define DEF(N) [N] = #N, + USER_STATES +#undef DEF +}; + +const char * +cc_user_state2str(u_int s) +{ + if (s >= sizeof(stab) / sizeof(stab[0]) || stab[s] == NULL) + return ("?"); + return (stab[s]); +} + +static __inline void +set_state(struct ccuser *user, enum user_state ns) +{ + if (user->state != ns) { + if (user->cc->log & CCLOG_USER_STATE) + cc_user_log(user, "%s -> %s", + stab[user->state], stab[ns]); + user->state = ns; + } +} + +static __inline void +cc_user_send(struct ccuser *user, u_int op, void *arg, size_t len) +{ + user->cc->funcs->send_user(user, user->uarg, op, arg, len); +} + +static __inline void +cc_user_ok(struct ccuser *user, u_int data, void *arg, size_t len) +{ + user->cc->funcs->respond_user(user, user->uarg, + ATMERR_OK, data, arg, len); +} + +static __inline void +cc_user_err(struct ccuser *user, int err) +{ + user->cc->funcs->respond_user(user, user->uarg, + err, ATMRESP_NONE, NULL, 0); +} + + +/********************************************************************** +* +* INSTANCE MANAGEMENT +*/ +/* +* New endpoint created +*/ +struct ccuser * +cc_user_create(struct ccdata *cc, void *uarg, const char *name) +{ + struct ccuser *user; + + user = CCZALLOC(sizeof(*user)); + if (user == NULL) + return (NULL); + + user->cc = cc; + user->state = USER_NULL; + user->uarg = uarg; + strncpy(user->name, name, sizeof(user->name)); + user->name[sizeof(user->name) - 1] = '\0'; + TAILQ_INIT(&user->connq); + LIST_INSERT_HEAD(&cc->user_list, user, node_link); + + if (user->cc->log & CCLOG_USER_INST) + cc_user_log(user, "created with name '%s'", name); + + return (user); +} + +/* + * Reset a user instance + */ +static void +cc_user_reset(struct ccuser *user) +{ + + CCASSERT(TAILQ_EMPTY(&user->connq), ("connq not empty")); + + if (user->sap != NULL) { + CCFREE(user->sap); + user->sap = NULL; + } + + if (user->accepted != NULL) { + user->accepted->acceptor = NULL; + user->accepted = NULL; + } + user->config = USER_P2P; + user->queue_act = 0; + user->queue_max = 0; + user->aborted = 0; + + set_state(user, USER_NULL); + + cc_user_sig_flush(user); +} + +static void +cc_user_abort(struct ccuser *user, const struct uni_ie_cause *cause) +{ + struct ccconn *conn; + + /* + * Although the standard state that 'all connections + * associated with this endpoint are aborted' we only + * have to abort the head one, because in state A6 + * (call present) the endpoint is only associated to the + * head connection - the others are 'somewhere else' and + * need to be redispatched. + * + * First bring user into a state that the connections + * are not dispatched back to it. + */ + set_state(user, USER_NULL); + if (!user->aborted) { + if ((conn = TAILQ_FIRST(&user->connq)) != NULL) { + memset(conn->cause, 0, sizeof(conn->cause)); + if (cause != NULL) + conn->cause[0] = *cause; + cc_conn_reset_acceptor(conn); + cc_disconnect_from_user(conn); + cc_conn_sig(conn, CONN_SIG_USER_ABORT, NULL); + } + } + + while ((conn = TAILQ_FIRST(&user->connq)) != NULL) { + /* these should be in C21 */ + cc_disconnect_from_user(conn); + cc_conn_dispatch(conn); + } + + cc_user_reset(user); +} + +/* + * Application has closed this endpoint. Clean up all user resources and + * abort all connections. This can be called in any state. + */ +void +cc_user_destroy(struct ccuser *user) +{ + + if (user->cc->log & CCLOG_USER_INST) + cc_user_log(user, "destroy '%s'", user->name); + + cc_user_abort(user, NULL); + + if (user->sap != NULL) + CCFREE(user->sap); + + cc_user_sig_flush(user); + + LIST_REMOVE(user, node_link); + CCFREE(user); +} + +/********************************************************************** + * + * OUTGOING CALLS + */ +/* + * Return true when the calling address of the connection matches the address. + */ +static int +addr_matches(const struct ccaddr *addr, const struct ccconn *conn) +{ + + if (!IE_ISPRESENT(conn->calling)) + return (0); + + return (addr->addr.type == conn->calling.addr.type && + addr->addr.plan == conn->calling.addr.plan && + addr->addr.len == conn->calling.addr.len && + memcmp(addr->addr.addr, conn->calling.addr.addr, + addr->addr.len) == 0); +} + +/* + * Check if the user's SAP (given he is in the right state) and + * the given SAP overlap + */ +static int +check_overlap(struct ccuser *user, struct uni_sap *sap) +{ + return ((user->state == USER_IN_PREPARING || + user->state == USER_IN_WAITING) && + unisve_overlap_sap(user->sap, sap)); +} + +/* + * Send arrival notification to user + */ +static void +do_arrival(struct ccuser *user) +{ + struct ccconn *conn; + + user->aborted = 0; + if ((conn = TAILQ_FIRST(&user->connq)) != NULL) { + set_state(user, USER_IN_ARRIVED); + cc_user_send(user, ATMOP_ARRIVAL_OF_INCOMING_CALL, NULL, 0); + cc_conn_sig(conn, CONN_SIG_ARRIVAL, NULL); + } +} + +/********************************************************************** + * + * ATTRIBUTES + */ +/* + * Query an attribute. This is possible only in some states: preparation + * of an outgoing call, after an incoming call was offered to the application + * and in the three active states (P2P, P2PLeaf, P2PRoot). + */ +static struct ccconn * +cc_query_check(struct ccuser *user) +{ + + switch (user->state) { + + case USER_OUT_PREPARING: + case USER_IN_ARRIVED: + case USER_ACTIVE: + return (TAILQ_FIRST(&user->connq)); + + case USER_NULL: + /* if we are waiting for the SETUP_confirm, we are in + * the NULL state still (we are the new endpoint), but + * have a connection in 'accepted' that is in the + * CONN_IN_WAIT_ACCEPT_OK state. + */ + if (user->accepted != NULL && + user->accepted->state == CONN_IN_WAIT_ACCEPT_OK) + return (user->accepted); + /* FALLTHRU */ + + default: + return (NULL); + } +} + +/* + * Query attributes + */ +static void +cc_attr_query(struct ccuser *user, struct ccconn *conn, + uint32_t *attr, u_int count) +{ + void *val, *ptr; + size_t total, len; + u_int i; + uint32_t *atab; + + /* determine the length of the total attribute buffer */ + total = sizeof(uint32_t) + count * sizeof(uint32_t); + for (i = 0; i < count; i++) { + len = 0; + switch ((enum atm_attribute)attr[i]) { + + case ATM_ATTR_NONE: + break; + + case ATM_ATTR_BLLI_SELECTOR: + len = sizeof(uint32_t); + break; + + case ATM_ATTR_BLLI: + len = sizeof(struct uni_ie_blli); + break; + + case ATM_ATTR_BEARER: + len = sizeof(struct uni_ie_bearer); + break; + + case ATM_ATTR_TRAFFIC: + len = sizeof(struct uni_ie_traffic); + break; + + case ATM_ATTR_QOS: + len = sizeof(struct uni_ie_qos); + break; + + case ATM_ATTR_EXQOS: + len = sizeof(struct uni_ie_exqos); + break; + + case ATM_ATTR_CALLED: + len = sizeof(struct uni_ie_called); + break; + + case ATM_ATTR_CALLEDSUB: + len = sizeof(struct uni_ie_calledsub); + break; + + case ATM_ATTR_CALLING: + len = sizeof(struct uni_ie_calling); + break; + + case ATM_ATTR_CALLINGSUB: + len = sizeof(struct uni_ie_callingsub); + break; + + case ATM_ATTR_AAL: + len = sizeof(struct uni_ie_aal); + break; + + case ATM_ATTR_EPREF: + len = sizeof(struct uni_ie_epref); + break; + + case ATM_ATTR_CONNED: + len = sizeof(struct uni_ie_conned); + break; + + case ATM_ATTR_CONNEDSUB: + len = sizeof(struct uni_ie_connedsub); + break; + + case ATM_ATTR_EETD: + len = sizeof(struct uni_ie_eetd); + break; + + case ATM_ATTR_ABRSETUP: + len = sizeof(struct uni_ie_abrsetup); + break; + + case ATM_ATTR_ABRADD: + len = sizeof(struct uni_ie_abradd); + break; + + case ATM_ATTR_CONNID: + len = sizeof(struct uni_ie_connid); + break; + + case ATM_ATTR_MDCR: + len = sizeof(struct uni_ie_mdcr); + break; + } + if (len == 0) { + cc_user_err(user, ATMERR_BAD_ATTR); + return; + } + total += len; + } + + /* allocate buffer */ + val = CCMALLOC(total); + if (val == NULL) + return; + + atab = val; + atab[0] = count; + + /* fill */ + ptr = (u_char *)val + (sizeof(uint32_t) + count * sizeof(uint32_t)); + for (i = 0; i < count; i++) { + len = 0; + atab[i + 1] = attr[i]; + switch (attr[i]) { + + case ATM_ATTR_NONE: + break; + + case ATM_ATTR_BLLI_SELECTOR: + len = sizeof(uint32_t); + memcpy(ptr, &conn->blli_selector, len); + break; + + case ATM_ATTR_BLLI: + /* in A6 the blli_selector may be 0 when + * there was no blli in the SETUP. + */ + len = sizeof(struct uni_ie_blli); + if (conn->blli_selector == 0) + memset(ptr, 0, len); + else + memcpy(ptr, &conn->blli[conn->blli_selector - + 1], len); + break; + + case ATM_ATTR_BEARER: + len = sizeof(struct uni_ie_bearer); + memcpy(ptr, &conn->bearer, len); + break; + + case ATM_ATTR_TRAFFIC: + len = sizeof(struct uni_ie_traffic); + memcpy(ptr, &conn->traffic, len); + break; + + case ATM_ATTR_QOS: + len = sizeof(struct uni_ie_qos); + memcpy(ptr, &conn->qos, len); + break; + + case ATM_ATTR_EXQOS: + len = sizeof(struct uni_ie_exqos); + memcpy(ptr, &conn->exqos, len); + break; + + case ATM_ATTR_CALLED: + len = sizeof(struct uni_ie_called); + memcpy(ptr, &conn->called, len); + break; + + case ATM_ATTR_CALLEDSUB: + len = sizeof(struct uni_ie_calledsub); + memcpy(ptr, &conn->calledsub, len); + break; + + case ATM_ATTR_CALLING: + len = sizeof(struct uni_ie_calling); + memcpy(ptr, &conn->calling, len); + break; + + case ATM_ATTR_CALLINGSUB: + len = sizeof(struct uni_ie_callingsub); + memcpy(ptr, &conn->callingsub, len); + break; + + case ATM_ATTR_AAL: + len = sizeof(struct uni_ie_aal); + memcpy(ptr, &conn->aal, len); + break; + + case ATM_ATTR_EPREF: + len = sizeof(struct uni_ie_epref); + memcpy(ptr, &conn->epref, len); + break; + + case ATM_ATTR_CONNED: + len = sizeof(struct uni_ie_conned); + memcpy(ptr, &conn->conned, len); + break; + + case ATM_ATTR_CONNEDSUB: + len = sizeof(struct uni_ie_connedsub); + memcpy(ptr, &conn->connedsub, len); + break; + + case ATM_ATTR_EETD: + len = sizeof(struct uni_ie_eetd); + memcpy(ptr, &conn->eetd, len); + break; + + case ATM_ATTR_ABRSETUP: + len = sizeof(struct uni_ie_abrsetup); + memcpy(ptr, &conn->abrsetup, len); + break; + + case ATM_ATTR_ABRADD: + len = sizeof(struct uni_ie_abradd); + memcpy(ptr, &conn->abradd, len); + break; + + case ATM_ATTR_CONNID: + len = sizeof(struct uni_ie_connid); + memcpy(ptr, &conn->connid, len); + break; + + case ATM_ATTR_MDCR: + len = sizeof(struct uni_ie_mdcr); + memcpy(ptr, &conn->mdcr, len); + break; + } + ptr = (u_char *)ptr + len; + } + + cc_user_ok(user, ATMRESP_ATTRS, val, total); + + CCFREE(val); +} + +/* + * Check whether the state is ok and return the connection + */ +static struct ccconn * +cc_set_check(struct ccuser *user) +{ + switch(user->state) { + + case USER_OUT_PREPARING: + case USER_IN_ARRIVED: + return (TAILQ_FIRST(&user->connq)); + + default: + return (NULL); + } +} + +/* + * Set connection attribute(s) + */ +static void +cc_attr_set(struct ccuser *user, struct ccconn *conn, uint32_t *attr, + u_int count, u_char *val, size_t vallen) +{ + size_t total, len; + u_int i; + u_char *ptr; + + /* determine the length of the total attribute buffer */ + total = 0; + ptr = val; + for (i = 0; i < count; i++) { + len = 0; + switch ((enum atm_attribute)attr[i]) { + + case ATM_ATTR_NONE: + break; + + case ATM_ATTR_BLLI_SELECTOR: + { + uint32_t sel; + + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + memcpy(&sel, ptr, sizeof(sel)); + if (sel == 0 || sel > UNI_NUM_IE_BLLI) + goto bad_val; + len = sizeof(uint32_t); + break; + } + + case ATM_ATTR_BLLI: + len = sizeof(struct uni_ie_blli); + break; + + case ATM_ATTR_BEARER: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_bearer); + break; + + case ATM_ATTR_TRAFFIC: + len = sizeof(struct uni_ie_traffic); + break; + + case ATM_ATTR_QOS: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_qos); + break; + + case ATM_ATTR_EXQOS: + len = sizeof(struct uni_ie_exqos); + break; + + case ATM_ATTR_CALLED: + goto rdonly; + + case ATM_ATTR_CALLEDSUB: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_calledsub); + break; + + case ATM_ATTR_CALLING: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_calling); + break; + + case ATM_ATTR_CALLINGSUB: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_callingsub); + break; + + case ATM_ATTR_AAL: + len = sizeof(struct uni_ie_aal); + break; + + case ATM_ATTR_EPREF: + goto rdonly; + + case ATM_ATTR_CONNED: + goto rdonly; + + case ATM_ATTR_CONNEDSUB: + goto rdonly; + + case ATM_ATTR_EETD: + len = sizeof(struct uni_ie_eetd); + break; + + case ATM_ATTR_ABRSETUP: + len = sizeof(struct uni_ie_abrsetup); + break; + + case ATM_ATTR_ABRADD: + len = sizeof(struct uni_ie_abradd); + break; + + case ATM_ATTR_CONNID: + len = sizeof(struct uni_ie_connid); + break; + + case ATM_ATTR_MDCR: + if (conn->state != CONN_OUT_PREPARING) + goto rdonly; + len = sizeof(struct uni_ie_mdcr); + break; + } + if (len == 0) { + cc_user_err(user, ATMERR_BAD_ATTR); + return; + } + total += len; + ptr += len; + } + + /* check the length */ + if (vallen != total) { + cc_user_err(user, ATMERR_BAD_ARGS); + return; + } + + ptr = val; + for (i = 0; i < count; i++) { + len = 0; + switch ((enum atm_attribute)attr[i]) { + + case ATM_ATTR_NONE: + break; + + case ATM_ATTR_BLLI_SELECTOR: + { + uint32_t sel; + + memcpy(&sel, ptr, sizeof(sel)); + conn->blli_selector = sel; + len = sizeof(uint32_t); + break; + } + + case ATM_ATTR_BLLI: + len = sizeof(struct uni_ie_blli); + memcpy(&conn->blli[conn->blli_selector - 1], ptr, len); + conn->dirty_attr |= CCDIRTY_BLLI; + break; + + case ATM_ATTR_BEARER: + len = sizeof(struct uni_ie_bearer); + memcpy(&conn->bearer, ptr, len); + break; + + case ATM_ATTR_TRAFFIC: + len = sizeof(struct uni_ie_traffic); + memcpy(&conn->traffic, ptr, len); + conn->dirty_attr |= CCDIRTY_TRAFFIC; + break; + + case ATM_ATTR_QOS: + len = sizeof(struct uni_ie_qos); + memcpy(&conn->qos, ptr, len); + break; + + case ATM_ATTR_EXQOS: + len = sizeof(struct uni_ie_exqos); + memcpy(&conn->exqos, ptr, len); + conn->dirty_attr |= CCDIRTY_EXQOS; + break; + + case ATM_ATTR_CALLED: + len = sizeof(struct uni_ie_called); + break; + + case ATM_ATTR_CALLEDSUB: + len = sizeof(struct uni_ie_calledsub); + memcpy(&conn->calledsub, ptr, len); + break; + + case ATM_ATTR_CALLING: + len = sizeof(struct uni_ie_calling); + memcpy(&conn->calling, ptr, len); + break; + + case ATM_ATTR_CALLINGSUB: + len = sizeof(struct uni_ie_callingsub); + memcpy(&conn->callingsub, ptr, len); + break; + + case ATM_ATTR_AAL: + len = sizeof(struct uni_ie_aal); + memcpy(&conn->aal, ptr, len); + conn->dirty_attr |= CCDIRTY_AAL; + break; + + case ATM_ATTR_EPREF: + len = sizeof(struct uni_ie_epref); + break; + + case ATM_ATTR_CONNED: + len = sizeof(struct uni_ie_conned); + break; + + case ATM_ATTR_CONNEDSUB: + len = sizeof(struct uni_ie_connedsub); + break; + + case ATM_ATTR_EETD: + len = sizeof(struct uni_ie_eetd); + memcpy(&conn->eetd, ptr, len); + conn->dirty_attr |= CCDIRTY_EETD; + break; + + case ATM_ATTR_ABRSETUP: + len = sizeof(struct uni_ie_abrsetup); + memcpy(&conn->abrsetup, ptr, len); + conn->dirty_attr |= CCDIRTY_ABRSETUP; + break; + + case ATM_ATTR_ABRADD: + len = sizeof(struct uni_ie_abradd); + memcpy(&conn->abradd, ptr, len); + conn->dirty_attr |= CCDIRTY_ABRADD; + break; + + case ATM_ATTR_CONNID: + len = sizeof(struct uni_ie_connid); + memcpy(&conn->connid, ptr, len); + conn->dirty_attr |= CCDIRTY_CONNID; + break; + + case ATM_ATTR_MDCR: + len = sizeof(struct uni_ie_mdcr); + memcpy(&conn->mdcr, ptr, len); + break; + } + ptr += len; + } + + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + + bad_val: + cc_user_err(user, ATMERR_BAD_VALUE); + return; + + rdonly: + cc_user_err(user, ATMERR_RDONLY); + return; +} + +#ifdef CCATM_DEBUG +static const char *op_names[] = { +#define S(OP) [ATMOP_##OP] = #OP + S(RESP), + S(ABORT_CONNECTION), + S(ACCEPT_INCOMING_CALL), + S(ADD_PARTY), + S(ADD_PARTY_REJECT), + S(ADD_PARTY_SUCCESS), + S(ARRIVAL_OF_INCOMING_CALL), + S(CALL_RELEASE), + S(CONNECT_OUTGOING_CALL), + S(DROP_PARTY), + S(GET_LOCAL_PORT_INFO), + S(P2MP_CALL_ACTIVE), + S(P2P_CALL_ACTIVE), + S(PREPARE_INCOMING_CALL), + S(PREPARE_OUTGOING_CALL), + S(QUERY_CONNECTION_ATTRIBUTES), + S(REJECT_INCOMING_CALL), + S(SET_CONNECTION_ATTRIBUTES), + S(WAIT_ON_INCOMING_CALL), + S(SET_CONNECTION_ATTRIBUTES_X), + S(QUERY_CONNECTION_ATTRIBUTES_X), + S(QUERY_STATE), +#undef S +}; +#endif + +/* + * Signal from user - map this to our internal signals and queue + * the mapped signal. + */ +int +cc_user_signal(struct ccuser *user, enum atmop sig, struct uni_msg *msg) +{ + size_t len = uni_msg_len(msg); + int err = EINVAL; + + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "signal %s to user", op_names[sig]); + + if ((u_int)sig > ATMOP_QUERY_STATE) + goto bad_signal; + + switch (sig) { + + case ATMOP_ABORT_CONNECTION: + if (len != sizeof(struct atm_abort_connection)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_ABORT_CONNECTION, msg); + break; + + case ATMOP_ACCEPT_INCOMING_CALL: + if (len != sizeof(struct atm_accept_incoming_call)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_ACCEPT_INCOMING, msg); + break; + + case ATMOP_ADD_PARTY: + if (len != sizeof(struct atm_add_party)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_ADD_PARTY, msg); + break; + + case ATMOP_CALL_RELEASE: + if (len != sizeof(struct atm_call_release)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_CALL_RELEASE, msg); + break; + + case ATMOP_CONNECT_OUTGOING_CALL: + if (len != sizeof(struct atm_connect_outgoing_call)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_CONNECT_OUTGOING, msg); + break; + + case ATMOP_DROP_PARTY: + if (len != sizeof(struct atm_drop_party)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_DROP_PARTY, msg); + break; + + case ATMOP_GET_LOCAL_PORT_INFO: + if (len != sizeof(struct atm_get_local_port_info)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_GET_LOCAL_PORT_INFO, msg); + break; + + case ATMOP_PREPARE_INCOMING_CALL: + if (len != sizeof(struct atm_prepare_incoming_call)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_PREPARE_INCOMING, msg); + break; + + case ATMOP_PREPARE_OUTGOING_CALL: + if (len != 0) + goto bad_len; + uni_msg_destroy(msg); + err = cc_user_sig(user, USER_SIG_PREPARE_OUTGOING, NULL, 0); + break; + + case ATMOP_QUERY_CONNECTION_ATTRIBUTES: + if (len != sizeof(struct atm_query_connection_attributes)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR, msg); + break; + + case ATMOP_REJECT_INCOMING_CALL: + if (len != sizeof(struct atm_reject_incoming_call)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_REJECT_INCOMING, msg); + break; + + case ATMOP_SET_CONNECTION_ATTRIBUTES: + if (len < sizeof(struct atm_set_connection_attributes)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_SET_ATTR, msg); + break; + + case ATMOP_WAIT_ON_INCOMING_CALL: + if (len != 0) + goto bad_len; + uni_msg_destroy(msg); + err = cc_user_sig(user, USER_SIG_WAIT_ON_INCOMING, NULL, 0); + break; + + case ATMOP_QUERY_CONNECTION_ATTRIBUTES_X: + if (len < sizeof(struct atm_set_connection_attributes_x) || + len != offsetof(struct atm_set_connection_attributes_x, + attr) + uni_msg_rptr(msg, + struct atm_set_connection_attributes_x *)->count * + sizeof(uint32_t)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_QUERY_ATTR_X, msg); + break; + + case ATMOP_SET_CONNECTION_ATTRIBUTES_X: + if (len < sizeof(struct atm_set_connection_attributes_x)) + goto bad_len; + err = cc_user_sig_msg(user, USER_SIG_SET_ATTR_X, msg); + break; + + case ATMOP_QUERY_STATE: + if (len != 0) + goto bad_len; + uni_msg_destroy(msg); + err = cc_user_sig(user, USER_SIG_QUERY_STATE, NULL, 0); + break; + + case ATMOP_RESP: + case ATMOP_ADD_PARTY_REJECT: + case ATMOP_ADD_PARTY_SUCCESS: + case ATMOP_ARRIVAL_OF_INCOMING_CALL: + case ATMOP_P2MP_CALL_ACTIVE: + case ATMOP_P2P_CALL_ACTIVE: + bad_signal: + /* bad signal */ + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "bad signal %u", sig); + cc_user_err(user, ATMERR_BAD_OP); + uni_msg_destroy(msg); + break; + } + return (err); + + bad_len: + /* bad argument length */ + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "signal %s had bad len=%zu", + op_names[sig], len); + cc_user_err(user, ATMERR_BAD_ARGS); + uni_msg_destroy(msg); + return (EINVAL); +} + +/* + * Send active signal to user + */ +static void +cc_user_active(struct ccuser *user) +{ + struct ccconn *conn = TAILQ_FIRST(&user->connq); + + set_state(user, USER_ACTIVE); + if (conn->bearer.cfg == UNI_BEARER_P2P) { + struct atm_p2p_call_active *act; + + user->config = USER_P2P; + act = CCZALLOC(sizeof(*act)); + if (act == NULL) + return; + act->connid = conn->connid; + cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, act, sizeof(*act)); + CCFREE(act); + } else { + struct atm_p2mp_call_active *act; + + user->config = USER_ROOT; + act = CCZALLOC(sizeof(*act)); + if (act == NULL) + return; + act->connid = conn->connid; + cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, act, sizeof(*act)); + CCFREE(act); + } +} + +/* +* Handle a signal to this user +*/ +void +cc_user_sig_handle(struct ccuser *user, enum user_sig sig, + void *arg, u_int arg2) +{ + + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "signal %s to user state %s", + cc_user_sigtab[sig], stab[user->state]); + + switch (sig) { + + + case USER_SIG_PREPARE_OUTGOING: + { + /* + * Here we create a connection for the call we soon will make. + * We put this call on the list of orphaned connections, + * because we don't know yet, which port will get the + * connection. It is assigned, when the user issues the call + * to connect. + */ + struct ccconn *conn; + + if (user->state != USER_NULL) { + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + conn = cc_conn_create(user->cc); + if (conn == NULL) { + cc_user_err(user, ATMERR_NOMEM); + return; + } + set_state(user, USER_OUT_PREPARING); + cc_conn_set_state(conn, CONN_OUT_PREPARING); + conn->blli_selector = 1; + cc_connect_to_user(conn, user); + + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + } + + + case USER_SIG_CONNECT_OUTGOING: + { + /* + * Request to connect that call + * + * Here we assign the connection to a port. + */ + struct uni_msg *msg = arg; + struct atm_connect_outgoing_call *req = uni_msg_rptr(msg, + struct atm_connect_outgoing_call *); + struct ccdata *priv = user->cc; + struct ccport *port; + struct ccaddr *addr; + struct ccconn *conn = TAILQ_FIRST(&user->connq); + + if (user->state != USER_OUT_PREPARING) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + if (!IE_ISPRESENT(req->called)) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_ARGS); + return; + } + CCASSERT(conn->port == NULL, ("connection still on port")); + + if (TAILQ_EMPTY(&priv->port_list)) { + /* + * We have no ports - reject + */ + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_PORT); + return; + } + + /* + * Find the correct port + * Routing of outgoing calls goes to the lowest numbered port + * with a matching address or, if no address match is found to + * the lowest numbered port. + */ + TAILQ_FOREACH(port, &priv->port_list, node_link) + TAILQ_FOREACH(addr, &port->addr_list, port_link) + if (addr_matches(addr, conn)) + break; + + if (port == NULL) + port = TAILQ_FIRST(&priv->port_list); + + cc_conn_ins_port(conn, port); + conn->called = req->called; + uni_msg_destroy(msg); + + /* + * Now move the state + */ + set_state(user, USER_OUT_WAIT_OK); + cc_conn_sig(conn, CONN_SIG_CONNECT_OUTGOING, NULL); + + return; + } + + + case USER_SIG_CONNECT_OUTGOING_ERR: + switch (user->state) { + + case USER_OUT_WAIT_OK: + set_state(user, USER_OUT_PREPARING); + cc_user_err(user, arg2); + break; + + case USER_REL_WAIT_CONN: + { + struct ccconn *conn; + + conn = TAILQ_FIRST(&user->connq); + if (conn != NULL) { + cc_disconnect_from_user(conn); + cc_conn_destroy(conn); + } + + cc_user_reset(user); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + break; + } + + default: + goto bad_state; + } + return; + + + case USER_SIG_CONNECT_OUTGOING_OK: + switch (user->state) { + + case USER_OUT_WAIT_OK: + set_state(user, USER_OUT_WAIT_CONF); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + break; + + case USER_REL_WAIT_CONN: + set_state(user, USER_REL_WAIT_SCONF); + break; + + default: + goto bad_state; + } + return; + + + case USER_SIG_SETUP_CONFIRM: + /* + * SETUP.confirm from UNI stack. + */ + switch (user->state) { + + case USER_OUT_WAIT_CONF: + cc_user_active(user); + break; + + case USER_REL_WAIT_SCONF: + /* now try to release */ + set_state(user, USER_REL_WAIT_CONF); + cc_conn_sig(TAILQ_FIRST(&user->connq), + CONN_SIG_RELEASE, NULL); + break; + + default: + goto bad_state; + } + return; + + + case USER_SIG_PREPARE_INCOMING: + { + struct uni_msg *msg = arg; + struct ccuser *ptr; + struct atm_prepare_incoming_call *prep = uni_msg_rptr(msg, + struct atm_prepare_incoming_call *); + + if (user->state != USER_NULL) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + + /* + * Check the SAP + */ + if (unisve_check_sap(&prep->sap) != UNISVE_OK) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_SAP); + return; + } + + /* + * Loop through all incoming calls and check whether there + * is an overlap in SAP space. + */ + LIST_FOREACH(ptr, &user->cc->user_list, node_link) { + if (check_overlap(ptr, &prep->sap)) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_OVERLAP); + return; + } + } + + /* + * Save info and set state + */ + user->sap = CCZALLOC(sizeof(struct uni_sap)); + if (user->sap == NULL) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_NOMEM); + return; + } + *user->sap = prep->sap; + user->queue_max = prep->queue_size; + user->queue_act = 0; + uni_msg_destroy(msg); + + set_state(user, USER_IN_PREPARING); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + + return; + } + + + case USER_SIG_WAIT_ON_INCOMING: + if (user->state != USER_IN_PREPARING) { + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + + set_state(user, USER_IN_WAITING); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + + + case USER_SIG_SETUP_IND: + /* + * New connection queued up in the queue. If this is the + * first one, inform the application of the arrival. + */ + switch (user->state) { + + case USER_IN_WAITING: + do_arrival(user); + break; + + case USER_IN_ARRIVED: + case USER_IN_WAIT_REJ: + case USER_IN_WAIT_ACC: + break; + + default: + goto bad_state; + } + return; + + + case USER_SIG_REJECT_INCOMING: + { + /* + * User rejects call. This is done on the OLD user + * (i.e. the one sending the arrival). + */ + struct uni_msg *msg = arg; + struct atm_reject_incoming_call *rej = uni_msg_rptr(msg, + struct atm_reject_incoming_call *); + struct ccconn *conn = TAILQ_FIRST(&user->connq); + + if (user->state != USER_IN_ARRIVED) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + if (user->aborted) { + /* connection has disappeared. Send an ok + * to the user and lock whether there is another + * connection at this endpoint */ + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + + set_state(user, USER_IN_WAITING); + do_arrival(user); + return; + } + conn->cause[0] = rej->cause; + memset(&conn->cause[1], 0, sizeof(conn->cause[1])); + uni_msg_destroy(msg); + + set_state(user, USER_IN_WAIT_REJ); + cc_conn_sig(conn, CONN_SIG_REJECT, NULL); + + return; + } + + + case USER_SIG_REJECT_OK: + if (user->state != USER_IN_WAIT_REJ) + goto bad_state; + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + + set_state(user, USER_IN_WAITING); + do_arrival(user); + return; + + + case USER_SIG_REJECT_ERR: + if (user->state != USER_IN_WAIT_REJ) + goto bad_state; + cc_user_err(user, arg2); + + if (arg == NULL) + set_state(user, USER_IN_ARRIVED); + else { + set_state(user, USER_IN_WAITING); + do_arrival(user); + } + return; + + + case USER_SIG_ACCEPT_INCOMING: + { + /* + * User accepts call. This is done on the OLD user (i.e. the one + * sending the arrival), the message contains a pointer to the + * new endpoint. + */ + struct uni_msg *msg = arg; + struct atm_accept_incoming_call *acc = + uni_msg_rptr(msg, struct atm_accept_incoming_call *); + struct ccuser *newep; + + if (user->state != USER_IN_ARRIVED) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + return; + } + if (user->aborted) { + /* connection has disappeared. Send an error + * to the user and lock whether there is another + * connection at this endpoint */ + cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); + + set_state(user, USER_IN_WAITING); + do_arrival(user); + return; + } + acc->newep[sizeof(acc->newep) - 1] = '\0'; + + LIST_FOREACH(newep, &user->cc->user_list, node_link) + if (strcmp(acc->newep, newep->name) == 0) + break; + + if (newep == NULL) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_ENDPOINT); + return; + } + + if (newep->state != USER_NULL || newep->accepted != NULL) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + return; + } + + set_state(user, USER_IN_WAIT_ACC); + cc_conn_sig(TAILQ_FIRST(&user->connq), CONN_SIG_ACCEPT, newep); + + return; + } + + + case USER_SIG_ACCEPT_OK: + if (user->state != USER_IN_WAIT_ACC) + goto bad_state; + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + + set_state(user, USER_IN_WAITING); + do_arrival(user); + return; + + + case USER_SIG_ACCEPT_ERR: + if (user->state != USER_IN_WAIT_ACC) + goto bad_state; + cc_user_err(user, arg2); + + if (arg == NULL) { + /* arg used as flag! */ + set_state(user, USER_IN_ARRIVED); + } else { + set_state(user, USER_IN_WAITING); + do_arrival(user); + } + return; + + + case USER_SIG_ACCEPTING: + if (user->state != USER_NULL) + goto bad_state; + set_state(user, USER_IN_ACCEPTING); + return; + + + case USER_SIG_SETUP_COMPL: + { + struct ccconn *conn = TAILQ_FIRST(&user->connq); + + if (user->state != USER_IN_ACCEPTING) + goto bad_state; + + user->state = USER_ACTIVE; + if (conn->bearer.cfg == UNI_BEARER_P2P) { + struct atm_p2p_call_active *act; + + user->config = USER_P2P; + act = CCZALLOC(sizeof(*act)); + if (act == NULL) + return; + act->connid = conn->connid; + cc_user_send(user, ATMOP_P2P_CALL_ACTIVE, + act, sizeof(*act)); + CCFREE(act); + } else { + struct atm_p2mp_call_active *act; + + user->config = USER_LEAF; + act = CCZALLOC(sizeof(*act)); + if (act == NULL) + return; + act->connid = conn->connid; + cc_user_send(user, ATMOP_P2MP_CALL_ACTIVE, + act, sizeof(*act)); + CCFREE(act); + } + return; + } + + + case USER_SIG_CALL_RELEASE: + { + struct uni_msg *msg = arg; + struct atm_call_release *api = uni_msg_rptr(msg, + struct atm_call_release *); + struct ccconn *conn; + + conn = TAILQ_FIRST(&user->connq); + switch (user->state) { + + case USER_OUT_WAIT_OK: /* U2/A3 */ + /* wait for CONN_OK first */ + conn->cause[0] = api->cause[0]; + conn->cause[1] = api->cause[1]; + set_state(user, USER_REL_WAIT_CONN); + break; + + case USER_OUT_WAIT_CONF: /* U3/A3 */ + /* wait for SETUP.confirm first */ + conn->cause[0] = api->cause[0]; + conn->cause[1] = api->cause[1]; + set_state(user, USER_REL_WAIT_SCONF); + break; + + case USER_IN_ACCEPTING: /* U11/A7 */ + conn->cause[0] = api->cause[0]; + conn->cause[1] = api->cause[1]; + set_state(user, USER_REL_WAIT_SCOMP); + cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); + break; + + case USER_ACTIVE: /* U4/A8,A9,A10 */ + conn->cause[0] = api->cause[0]; + conn->cause[1] = api->cause[1]; + set_state(user, USER_REL_WAIT); + cc_conn_sig(conn, CONN_SIG_RELEASE, NULL); + break; + + default: + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + goto bad_state; + } + uni_msg_destroy(msg); + return; + } + + + case USER_SIG_RELEASE_CONFIRM: + { + struct atm_call_release *ind; + + switch (user->state) { + + case USER_OUT_WAIT_CONF: /* U3/A3 */ + case USER_ACTIVE: /* U4/A8,A9,A10 */ + cc_user_reset(user); + break; + + case USER_REL_WAIT: /* U5 /A8,A9,A10 */ + case USER_REL_WAIT_SCOMP: /* U12/A7 */ + case USER_REL_WAIT_SCONF: /* U13/A3 */ + case USER_REL_WAIT_CONF: /* U14/A3 */ + cc_user_reset(user); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + + case USER_IN_ACCEPTING: /* U11/A7 */ + cc_user_reset(user); + break; + + default: + goto bad_state; + } + + ind = CCZALLOC(sizeof(*ind)); + if (ind == NULL) + return; + memcpy(ind->cause, user->cause, sizeof(ind->cause)); + cc_user_send(user, ATMOP_CALL_RELEASE, ind, sizeof(*ind)); + CCFREE(ind); + return; + } + + + case USER_SIG_RELEASE_ERR: + switch (user->state) { + + case USER_REL_WAIT: /* U5/A8,A9,A10 */ + set_state(user, USER_ACTIVE); + cc_user_err(user, ATM_MKUNIERR(arg2)); + break; + + case USER_REL_WAIT_CONF: /* U14/A3 */ + cc_user_err(user, ATM_MKUNIERR(arg2)); + cc_user_active(user); + break; + + case USER_REL_WAIT_SCOMP: /* U12/A7 */ + set_state(user, USER_IN_ACCEPTING); + cc_user_err(user, ATM_MKUNIERR(arg2)); + break; + + default: + goto bad_state; + } + return; + + + case USER_SIG_ADD_PARTY: + { + struct uni_msg *msg = arg; + struct atm_add_party *add = uni_msg_rptr(msg, + struct atm_add_party *); + struct ccconn *conn; + + if (user->state != USER_ACTIVE || user->config != USER_ROOT) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + return; + } + + if (add->leaf_ident == 0 || add->leaf_ident >= 32786) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_LEAF_IDENT); + return; + } + + conn = TAILQ_FIRST(&user->connq); + conn->called = add->called; + + cc_conn_sig(conn, CONN_SIG_ADD_PARTY, + (void *)(uintptr_t)add->leaf_ident); + + uni_msg_destroy(msg); + return; + } + + + case USER_SIG_ADD_PARTY_ERR: + if (user->state != USER_ACTIVE) + goto bad_state; + cc_user_err(user, arg2); + return; + + + case USER_SIG_ADD_PARTY_OK: + if (user->state != USER_ACTIVE) + goto bad_state; + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + + + case USER_SIG_ADD_PARTY_ACK: + { + u_int leaf_ident = arg2; + struct atm_add_party_success *succ; + + if (user->state != USER_ACTIVE) + goto bad_state; + + succ = CCZALLOC(sizeof(*succ)); + if (succ == NULL) + return; + + succ->leaf_ident = leaf_ident; + cc_user_send(user, ATMOP_ADD_PARTY_SUCCESS, + succ, sizeof(*succ)); + + CCFREE(succ); + return; + } + + + case USER_SIG_ADD_PARTY_REJ: + { + u_int leaf_ident = arg2; + struct atm_add_party_reject *reject; + + if (user->state != USER_ACTIVE) + goto bad_state; + + reject = CCZALLOC(sizeof(*reject)); + if (reject == NULL) + return; + + reject->leaf_ident = leaf_ident; + reject->cause = user->cause[0]; + cc_user_send(user, ATMOP_ADD_PARTY_REJECT, + reject, sizeof(*reject)); + + CCFREE(reject); + return; + } + + + case USER_SIG_DROP_PARTY: + { + struct uni_msg *msg = arg; + struct atm_drop_party *drop = uni_msg_rptr(msg, + struct atm_drop_party *); + struct ccconn *conn; + + if (user->state != USER_ACTIVE || user->config != USER_ROOT) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_STATE); + return; + } + + if (drop->leaf_ident >= 32786) { + uni_msg_destroy(msg); + cc_user_err(user, ATMERR_BAD_LEAF_IDENT); + return; + } + + conn = TAILQ_FIRST(&user->connq); + conn->cause[0] = drop->cause; + memset(&conn->cause[1], 0, sizeof(conn->cause[1])); + + cc_conn_sig(conn, CONN_SIG_DROP_PARTY, + (void *)(uintptr_t)drop->leaf_ident); + + uni_msg_destroy(msg); + return; + } + + + case USER_SIG_DROP_PARTY_ERR: + if (user->state != USER_ACTIVE) + goto bad_state; + cc_user_err(user, arg2); + return; + + + case USER_SIG_DROP_PARTY_OK: + if (user->state != USER_ACTIVE) + goto bad_state; + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + + + case USER_SIG_DROP_PARTY_IND: + { + u_int leaf_ident = arg2; + struct atm_drop_party *drop; + + if (user->state != USER_ACTIVE) + goto bad_state; + + drop = CCZALLOC(sizeof(*drop)); + if (drop == NULL) + return; + + drop->leaf_ident = leaf_ident; + drop->cause = user->cause[0]; + cc_user_send(user, ATMOP_DROP_PARTY, drop, sizeof(*drop)); + + CCFREE(drop); + return; + } + + + case USER_SIG_QUERY_ATTR: + { + struct uni_msg *msg = arg; + struct atm_query_connection_attributes *req; + struct ccconn *conn; + + if (user->aborted) { + cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); + uni_msg_destroy(msg); + return; + } + conn = cc_query_check(user); + if (conn == NULL) { + cc_user_err(user, ATMERR_BAD_STATE); + uni_msg_destroy(msg); + return; + } + req = uni_msg_rptr(msg, + struct atm_query_connection_attributes *); + cc_attr_query(user, conn, &req->attr, 1); + uni_msg_destroy(msg); + return; + } + + case USER_SIG_QUERY_ATTR_X: + { + struct uni_msg *msg = arg; + struct atm_query_connection_attributes_x *req; + struct ccconn *conn; + + conn = cc_query_check(user); + if (conn == NULL) { + cc_user_err(user, ATMERR_BAD_STATE); + uni_msg_destroy(msg); + return; + } + req = uni_msg_rptr(msg, + struct atm_query_connection_attributes_x *); + cc_attr_query(user, conn, req->attr, req->count); + uni_msg_destroy(msg); + return; + } + + case USER_SIG_SET_ATTR: + { + struct uni_msg *msg = arg; + struct atm_set_connection_attributes *req; + struct ccconn *conn; + + if (user->aborted) { + cc_user_err(user, ATMERR_PREVIOUSLY_ABORTED); + uni_msg_destroy(msg); + return; + } + conn = cc_set_check(user); + if (conn == NULL) { + cc_user_err(user, ATMERR_BAD_STATE); + uni_msg_destroy(msg); + return; + } + req = uni_msg_rptr(msg, struct atm_set_connection_attributes *); + cc_attr_set(user, conn, &req->attr, 1, (u_char *)(req + 1), + uni_msg_len(msg) - sizeof(*req)); + uni_msg_destroy(msg); + return; + } + + case USER_SIG_SET_ATTR_X: + { + struct uni_msg *msg = arg; + struct atm_set_connection_attributes_x *req; + struct ccconn *conn; + + conn = cc_set_check(user); + if (conn == NULL) { + cc_user_err(user, ATMERR_BAD_STATE); + uni_msg_destroy(msg); + return; + } + req = uni_msg_rptr(msg, + struct atm_set_connection_attributes_x *); + cc_attr_set(user, conn, req->attr, req->count, + (u_char *)req->attr + req->count * sizeof(req->attr[0]), + uni_msg_len(msg) - + offsetof(struct atm_set_connection_attributes_x, attr) - + req->count * sizeof(req->attr[0])); + uni_msg_destroy(msg); + return; + } + + case USER_SIG_QUERY_STATE: + { + struct atm_epstate state; + + strcpy(state.name, user->name); + switch (user->state) { + + case USER_NULL: + if (user->accepted != NULL) + state.state = ATM_A7; + else + state.state = ATM_A1; + break; + + case USER_OUT_PREPARING: + state.state = ATM_A2; + break; + + case USER_OUT_WAIT_OK: + case USER_OUT_WAIT_CONF: + case USER_REL_WAIT_SCONF: + case USER_REL_WAIT_CONF: + case USER_REL_WAIT_CONN: + state.state = ATM_A3; + break; + + case USER_ACTIVE: + case USER_REL_WAIT: + switch (user->config) { + + case USER_P2P: + state.state = ATM_A8; + break; + + case USER_ROOT: + state.state = ATM_A9; + break; + + case USER_LEAF: + state.state = ATM_A10; + break; + } + break; + + case USER_IN_PREPARING: + state.state = ATM_A4; + break; + + case USER_IN_WAITING: + state.state = ATM_A5; + break; + + case USER_IN_ARRIVED: + case USER_IN_WAIT_REJ: + case USER_IN_WAIT_ACC: + state.state = ATM_A6; + break; + + case USER_IN_ACCEPTING: + case USER_REL_WAIT_SCOMP: + state.state = ATM_A7; + break; + } + cc_user_ok(user, ATMRESP_STATE, &state, sizeof(state)); + return; + } + + case USER_SIG_GET_LOCAL_PORT_INFO: + { + struct uni_msg *msg = arg; + struct atm_port_list *list; + size_t list_len; + + list = cc_get_local_port_info(user->cc, + uni_msg_rptr(msg, struct atm_get_local_port_info *)->port, + &list_len); + uni_msg_destroy(msg); + if (list == NULL) { + cc_user_err(user, ATMERR_NOMEM); + return; + } + cc_user_ok(user, ATMRESP_PORTS, list, list_len); + CCFREE(list); + return; + } + + case USER_SIG_ABORT_CONNECTION: + { + struct uni_msg *msg = arg; + struct atm_abort_connection *abo = uni_msg_rptr(msg, + struct atm_abort_connection *); + + cc_user_abort(user, &abo->cause); + uni_msg_destroy(msg); + cc_user_ok(user, ATMRESP_NONE, NULL, 0); + return; + } + + } + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "bad signal=%u in state=%u", + sig, user->state); + return; + + bad_state: + if (user->cc->log & CCLOG_USER_SIG) + cc_user_log(user, "bad state=%u for signal=%u", + user->state, sig); + return; +} diff --git a/sys/contrib/ngatm/netnatm/api/ccatm.h b/sys/contrib/ngatm/netnatm/api/ccatm.h new file mode 100644 index 000000000000..1b4a179a3348 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/ccatm.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2003-2004 + * Hartmut Brandt + * All rights reserved. + * + * Author: Harti Brandt + * + * 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/ccatm.h,v 1.1 2004/07/08 08:21:58 brandt Exp $ + * + * ATM API as defined per af-saa-0108 + * + * Interface to the supporting code. + */ + +#ifndef _API_CCATM_H_ +#define _API_CCATM_H_ + +struct ccuser; +struct ccconn; +struct ccport; +struct ccdata; + +struct cc_funcs { + /* send signal to API user */ + void (*send_user)(struct ccuser *, void *, u_int, void *, size_t); + + /* respond API user */ + void (*respond_user)(struct ccuser *, void *, int, u_int, + void *, size_t); + + /* send signal to uni for connection */ + void (*send_uni)(struct ccconn *, void *, u_int, u_int, + struct uni_msg *); + + /* send global signal to uni */ + void (*send_uni_glob)(struct ccport *, void *, u_int, u_int, + struct uni_msg *); + + /* log a message */ + void (*log)(const char *, ...); +}; + +enum { + CCLOG_USER_STATE = 0x00000001, + CCLOG_USER_INST = 0x00000002, + CCLOG_USER_SIG = 0x00000004, + CCLOG_CONN_STATE = 0x00000010, + CCLOG_CONN_INST = 0x00000020, + CCLOG_CONN_SIG = 0x00000040, + CCLOG_PARTY_STATE = 0x00000100, + CCLOG_PARTY_INST = 0x00000200, + CCLOG_PARTY_SIG = 0x00000400, + CCLOG_SIGS = 0x00001000, +}; + +/* instance handling */ +struct ccdata *cc_create(const struct cc_funcs *); +void cc_destroy(struct ccdata *); +void cc_reset(struct ccdata *); + +/* input a response from the UNI layer to CC */ +int cc_uni_response(struct ccport *, u_int cookie, u_int reason, u_int state); + +/* Signal from UNI on this port */ +int cc_uni_signal(struct ccport *, u_int cookie, u_int sig, struct uni_msg *); + +/* retrieve addresses */ +int cc_get_addrs(struct ccdata *, u_int, struct uni_addr **, u_int **, u_int *); + +/* dump state */ +typedef int (*cc_dump_f)(struct ccdata *, void *, const char *); +int cc_dump(struct ccdata *, size_t, cc_dump_f, void *); + +/* start/stop port */ +int cc_port_stop(struct ccdata *, u_int); +int cc_port_start(struct ccdata *, u_int); + +/* is port running? */ +int cc_port_isrunning(struct ccdata *, u_int, int *); + +/* return port number */ +u_int cc_port_no(struct ccport *); + +/* Clear address and prefix information from the named port. */ +int cc_port_clear(struct ccdata *, u_int); + +/* Address registered. */ +int cc_addr_register(struct ccdata *, u_int, const struct uni_addr *); + +/* Address unregistered. */ +int cc_addr_unregister(struct ccdata *, u_int, const struct uni_addr *); + +/* get port info */ +int cc_port_get_param(struct ccdata *, u_int, struct atm_port_info *); + +/* set port info */ +int cc_port_set_param(struct ccdata *, const struct atm_port_info *); + +/* get port list */ +int cc_port_getlist(struct ccdata *, u_int *, u_int **); + +/* create a port */ +struct ccport *cc_port_create(struct ccdata *, void *, u_int); + +/* destroy a port */ +void cc_port_destroy(struct ccport *, int); + +/* New endpoint created */ +struct ccuser *cc_user_create(struct ccdata *, void *, const char *); + +/* destroy user endpoint */ +void cc_user_destroy(struct ccuser *); + +/* signal from user */ +int cc_user_signal(struct ccuser *, u_int, struct uni_msg *); + +/* Management is given up on this node. */ +void cc_unmanage(struct ccdata *); + +/* handle all queued signals */ +void cc_work(struct ccdata *); + +/* set/get logging flags */ +void cc_set_log(struct ccdata *, u_int); +u_int cc_get_log(const struct ccdata *); + +/* get extended status */ +int cc_get_extended_status(const struct ccdata *, struct atm_exstatus *, + struct atm_exstatus_ep **, struct atm_exstatus_port **, + struct atm_exstatus_conn **, struct atm_exstatus_party **); + +#endif diff --git a/sys/contrib/ngatm/netnatm/api/ccpriv.h b/sys/contrib/ngatm/netnatm/api/ccpriv.h new file mode 100644 index 000000000000..85bf9b769e37 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/ccpriv.h @@ -0,0 +1,562 @@ +/* + * Copyright (c) 2003-2004 + * Hartmut Brandt + * All rights reserved. + * + * Author: Harti Brandt + * + * 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. + * + * $FreeBSD$ + * + * ATM API as defined per af-saa-0108 + * + * Private declarations. + */ +#ifdef _KERNEL +#ifdef __FreeBSD__ +#include +#endif +#else /* !_KERNEL */ +#include "cccust.h" +#endif + +struct ccuser; +struct ccconn; +struct ccaddr; +struct ccport; +struct ccdata; +struct ccsig; +struct ccparty; + +LIST_HEAD(ccuser_list, ccuser); +LIST_HEAD(ccconn_list, ccconn); +TAILQ_HEAD(ccaddr_list, ccaddr); +TAILQ_HEAD(ccport_list, ccport); +TAILQ_HEAD(ccsig_list, ccsig); +LIST_HEAD(ccparty_list, ccparty); + +/* + * Private node data. + */ +struct ccdata { + struct ccuser_list user_list; /* instance list */ + struct ccport_list port_list; /* list of ports */ + struct ccconn_list orphaned_conns; /* list of connections */ + struct ccsig_list sigs; /* current signals */ + struct ccsig_list def_sigs; /* deferred signals */ + struct ccsig_list free_sigs; /* free signals */ + + const struct cc_funcs *funcs; + uint32_t cookie; /* cookie generator */ + u_int log; /* logging flags */ +}; + +/* retrieve info on local ports */ +struct atm_port_list *cc_get_local_port_info(struct ccdata *, + u_int, size_t *); + +/* log */ +#ifdef CCATM_DEBUG +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_log(CC, FMT, ARGS...) do { \ + (CC)->funcs->log("%s (data=%p): " FMT, __FUNCTION__, \ + (CC) , ## ARGS); \ + } while (0) +#else +#define cc_log(CC, FMT, ...) do { \ + (CC)->funcs->log("%s (data=%p): " FMT, __func__, \ + (CC), __VA_ARGS__); \ + } while (0) +#endif +#else +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_log(CC, FMT, ARGS...) do { } while (0) +#else +#define cc_log(CC, FMT, ...) do { } while (0) +#endif +#endif + +/* + * structure to remember cookies for outstanding requests + * we also remember the request itself but don't use it. + */ +struct ccreq { + TAILQ_ENTRY(ccreq) link; + uint32_t cookie; + uint32_t req; + struct ccconn *conn; +}; +TAILQ_HEAD(ccreq_list, ccreq); + +/* + * Port data. Each port has one UNI stack below. + * The port number is in param.port. The number is assigned when the + * hook to the uni is connected. This hook has the name 'uni'. + */ +struct ccport { + void *uarg; /* hook to UNI protocol */ + struct ccdata *cc; /* back pointer to node */ + enum { + CCPORT_STOPPED, /* halted */ + CCPORT_RUNNING, /* ok */ + } admin; /* admin status */ + struct ccconn_list conn_list; /* list of connections */ + struct ccaddr_list addr_list; /* list of network addresses */ + struct atm_port_info param; /* parameters */ + + /* list of outstanding requests */ + struct ccreq_list cookies; + + TAILQ_ENTRY(ccport) node_link; +}; + +#ifdef CCATM_DEBUG +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_port_log(P, FMT, ARGS...) do { \ + (P)->cc->funcs->log("%s (port=%p/%u): " FMT, __FUNCTION__, \ + (P), (P)->param.port , ## ARGS); \ + } while (0) +#else +#define cc_port_log(P, FMT, ...) do { \ + (P)->cc->funcs->log("%s (port=%p/%u): " FMT, __func__, \ + (P), (P)->param.port, __VA_ARGS__); \ + } while (0) +#endif +#else +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_port_log(P, FMT, ARGS...) do { } while (0) +#else +#define cc_port_log(P, FMT, ...) do { } while (0) +#endif +#endif + +#define CONN_STATES \ + DEF(CONN_NULL) /* C0 */ \ + DEF(CONN_OUT_PREPARING) /* C1 */ \ + DEF(CONN_OUT_WAIT_CREATE) /* C2 */ \ + DEF(CONN_OUT_WAIT_OK) /* C3 */ \ + DEF(CONN_OUT_WAIT_CONF) /* C4 */ \ + \ + DEF(CONN_ACTIVE) /* C5 */ \ + \ + DEF(CONN_IN_PREPARING) /* C10 */ \ + DEF(CONN_IN_WAITING) /* C21 */ \ + DEF(CONN_IN_ARRIVED) /* C11 */ \ + DEF(CONN_IN_WAIT_ACCEPT_OK) /* C12 */ \ + DEF(CONN_IN_WAIT_COMPL) /* C13 */ \ + \ + DEF(CONN_REJ_WAIT_OK) /* C14 */ \ + DEF(CONN_REL_IN_WAIT_OK) /* C15 */ \ + DEF(CONN_REL_WAIT_OK) /* C20 */ \ + \ + DEF(CONN_AB_WAIT_REQ_OK) /* C33 */ \ + DEF(CONN_AB_WAIT_RESP_OK) /* C34 */ \ + DEF(CONN_AB_FLUSH_IND) /* C35 */ \ + DEF(CONN_OUT_WAIT_DESTROY) /* C37 */ + +enum conn_state { +#define DEF(N) N, + CONN_STATES +#undef DEF +}; + +#define CONN_SIGS \ + DEF(CONNECT_OUTGOING) /* U */ \ + DEF(ARRIVAL) /* U */ \ + DEF(RELEASE) /* U */ \ + DEF(REJECT) /* U */ \ + DEF(ACCEPT) /* U newuser */ \ + DEF(ADD_PARTY) /* U ident */ \ + DEF(DROP_PARTY) /* U ident */ \ + DEF(USER_ABORT) /* U */ \ + \ + DEF(CREATED) /* P msg */ \ + DEF(DESTROYED) /* P */ \ + DEF(SETUP_CONFIRM) /* P msg */ \ + DEF(SETUP_IND) /* P msg */ \ + DEF(SETUP_COMPL) /* P msg */ \ + DEF(PROC_IND) /* P msg */ \ + DEF(ALERTING_IND) /* P msg */ \ + DEF(REL_CONF) /* P msg */ \ + DEF(REL_IND) /* P msg */ \ + DEF(PARTY_CREATED) /* P msg */ \ + DEF(PARTY_DESTROYED) /* P msg */ \ + DEF(PARTY_ALERTING_IND) /* P msg */ \ + DEF(PARTY_ADD_ACK_IND) /* P msg */ \ + DEF(PARTY_ADD_REJ_IND) /* P msg */ \ + DEF(DROP_PARTY_IND) /* P msg */ \ + DEF(DROP_PARTY_ACK_IND) /* P msg */ \ + \ + DEF(OK) /* P msg */ \ + DEF(ERROR) /* P msg */ + +enum conn_sig { +#define DEF(NAME) CONN_SIG_##NAME, +CONN_SIGS +#undef DEF +}; +extern const char *const cc_conn_sigtab[]; + +/* + * This describes a connection and must be in sync with the UNI + * stack. + */ +struct ccconn { + enum conn_state state; /* API state of the connection */ + struct ccdata *cc; /* owner node */ + struct ccport *port; /* the port we belong to */ + struct ccuser *user; /* user instance we belong to */ + TAILQ_ENTRY(ccconn) connq_link; /* queue of the owner */ + LIST_ENTRY(ccconn) port_link; /* link in list of port */ + struct uni_cref cref; + uint8_t reason; + struct ccuser *acceptor; + + /* attributes */ + uint32_t blli_selector; + struct uni_ie_blli blli[UNI_NUM_IE_BLLI]; + + struct uni_ie_bearer bearer; + struct uni_ie_traffic traffic; + struct uni_ie_qos qos; + struct uni_ie_exqos exqos; + struct uni_ie_called called; + struct uni_ie_calledsub calledsub; + struct uni_ie_aal aal; + struct uni_ie_epref epref; + struct uni_ie_conned conned; + struct uni_ie_connedsub connedsub; + struct uni_ie_eetd eetd; + struct uni_ie_abrsetup abrsetup; + struct uni_ie_abradd abradd; + struct uni_ie_mdcr mdcr; + + struct uni_ie_calling calling; + struct uni_ie_callingsub callingsub; + struct uni_ie_connid connid; + struct uni_ie_tns tns[UNI_NUM_IE_TNS]; + struct uni_ie_atraffic atraffic; + struct uni_ie_mintraffic mintraffic; + struct uni_ie_cscope cscope; + struct uni_ie_bhli bhli; + + /* bit mask of written attributes in A6 */ + u_int dirty_attr; + + struct uni_ie_cause cause[2]; + + struct ccparty_list parties; +}; + +/* dirty attribute mask values */ +enum { + CCDIRTY_AAL = 0x0001, + CCDIRTY_BLLI = 0x0002, + CCDIRTY_CONNID = 0x0004, + CCDIRTY_NOTIFY = 0x0008, /* XXX */ + CCDIRTY_EETD = 0x0010, + CCDIRTY_GIT = 0x0020, /* XXX */ + CCDIRTY_UU = 0x0040, /* XXX */ + CCDIRTY_TRAFFIC = 0x0080, + CCDIRTY_EXQOS = 0x0100, + CCDIRTY_ABRSETUP = 0x0200, + CCDIRTY_ABRADD = 0x0400, +}; + +/* set conn to new state */ +void cc_conn_set_state(struct ccconn *, enum conn_state); + +/* return string for state */ +const char *cc_conn_state2str(u_int); + +/* connect connection to user */ +void cc_connect_to_user(struct ccconn *, struct ccuser *); + +/* disconnect from the user */ +void cc_disconnect_from_user(struct ccconn *); + +/* abort the connection */ +void cc_conn_abort(struct ccconn *, int); + +/* destroy a connection */ +void cc_conn_destroy(struct ccconn *); + +/* create a connection */ +struct ccconn *cc_conn_create(struct ccdata *); + +/* assign to port */ +void cc_conn_ins_port(struct ccconn *, struct ccport *); + +/* remove from port */ +void cc_conn_rem_port(struct ccconn *); + +/* dispatch a connection to a user or reject it */ +void cc_conn_dispatch(struct ccconn *); + +/* disconnect from acceptor */ +void cc_conn_reset_acceptor(struct ccconn *); + +/* log on a connection */ +#ifdef CCATM_DEBUG +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_conn_log(C, FMT, ARGS...) do { \ + (C)->cc->funcs->log("%s (conn=%p): " FMT, __FUNCTION__, \ + (C) , ## ARGS); \ + } while (0) +#else +#define cc_conn_log(C, FMT, ...) do { \ + (C)->cc->funcs->log("%s (conn=%p): " FMT, __func__, \ + (C), __VA_ARGS__); \ + } while (0) +#endif +#else +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_conn_log(C, FMT, ARGS...) do { } while (0) +#else +#define cc_conn_log(C, FMT, ...) do { } while (0) +#endif +#endif + +/* handle signal to connection */ +void cc_conn_sig_handle(struct ccconn *, enum conn_sig, void *arg, u_int iarg); + +/* + * Mp connection parties + */ +#define PARTY_STATES \ + DEF(NULL) /* 0 created */ \ + DEF(ACTIVE) /* 1 active */ \ + DEF(ADD_WAIT_CREATE) /* 2 wait for PARTY_CREATE */ \ + DEF(ADD_WAIT_OK) /* 3 wait for OK for ADD.request */ \ + DEF(ADD_WAIT_ACK) /* 4 wait for ADD.ack/rej */ \ + DEF(DROP_WAIT_OK) /* 5 wait for OK for DROP.request */ \ + DEF(DROP_WAIT_ACK) /* 6 wait for DROP.ack */ \ + DEF(WAIT_DESTROY) /* 7 wait for destroy */ \ + DEF(WAIT_SETUP_COMPL) /* 8 wait for setup.complete */ \ + DEF(WAIT_DROP_ACK_OK) /* 9 wait for OK for DROP_ACK.request */\ + DEF(WAIT_SETUP_CONF) /* 10 wait for setup.confirm */ \ + DEF(ADD_DROP_WAIT_OK) /* 11 wait for ok to DROP.request */ \ + DEF(ADD_DROPACK_WAIT_OK)/* 12 wait for ok to DROP_ACK.req */ + +enum party_state { +#define DEF(N) PARTY_##N, +PARTY_STATES +#undef DEF +}; + +struct ccparty { + struct ccconn *conn; /* owner */ + LIST_ENTRY(ccparty) link; + enum party_state state; + struct uni_ie_called called; + struct uni_ie_epref epref; +}; + +/* set party to new state */ +void cc_party_set_state(struct ccparty *, enum party_state); + +/* return string for state */ +const char *cc_party_state2str(u_int); + +/* create new party */ +struct ccparty *cc_party_create(struct ccconn *, u_int ident, u_int flag); + +/* log on a party */ +#ifdef CCATM_DEBUG +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_party_log(P, FMT, ARGS...) do { \ + (P)->conn->cc->funcs->log("%s (conn=%p, party=%p): " FMT, \ + __FUNCTION__, (P)->conn, (P) , ## ARGS); \ + } while (0) +#else +#define cc_party_log(P, FMT, ...) do { \ + (P)->conn->cc->funcs->log("%s (conn=%p, party=%p): " FMT, \ + __func__, (P)->conn, (P), __VA_ARGS__); \ + } while (0) +#endif +#else +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_party_log(P, FMT, ARGS...) do { } while (0) +#else +#define cc_party_log(P, FMT, ...) do { } while (0) +#endif +#endif + +/* + * This is kind of a user socket, i.e. the entity managed towards the + * upper layer. + */ +#define USER_STATES \ + DEF(USER_NULL) /* U0 none */ \ + DEF(USER_OUT_PREPARING) /* U1 process set/query requests */ \ + DEF(USER_OUT_WAIT_OK) /* U2 wait for OK to setup */ \ + DEF(USER_OUT_WAIT_CONF) /* U3 wait for SETUP.confirm */ \ + DEF(USER_ACTIVE) /* U4 A8-9-10/U10 */ \ + DEF(USER_REL_WAIT) /* U5 wait for release to compl */ \ + DEF(USER_IN_PREPARING) /* U6 set SAP */ \ + DEF(USER_IN_WAITING) /* U7 wait and dispatch */ \ + DEF(USER_IN_ARRIVED) /* U8 waiting for rej/acc */ \ + DEF(USER_IN_WAIT_REJ) /* U9 wait for rejecting */ \ + DEF(USER_IN_WAIT_ACC) /* U10 wait for accepting */ \ + DEF(USER_IN_ACCEPTING) /* U11 wait for SETUP_complete */ \ + DEF(USER_REL_WAIT_SCOMP)/* U12 wait for SETUP_complete */ \ + DEF(USER_REL_WAIT_SCONF)/* U13 wait for SETUP.confirm */ \ + DEF(USER_REL_WAIT_CONF) /* U14 wait for confirm */ \ + DEF(USER_REL_WAIT_CONN) /* U15 wait for CONN_OK */ + +enum user_state { +#define DEF(N) N, +USER_STATES +#undef DEF +}; + +#define USER_SIGS \ + DEF(PREPARE_OUTGOING) /* U */ \ + DEF(CONNECT_OUTGOING) /* U msg */ \ + DEF(PREPARE_INCOMING) /* U msg */ \ + DEF(WAIT_ON_INCOMING) /* U msg */ \ + DEF(REJECT_INCOMING) /* U msg */ \ + DEF(ACCEPT_INCOMING) /* U msg */ \ + DEF(CALL_RELEASE) /* U msg */ \ + DEF(ADD_PARTY) /* U msg */ \ + DEF(DROP_PARTY) /* U msg */ \ + DEF(QUERY_ATTR) /* U msg */ \ + DEF(QUERY_ATTR_X) /* U msg */ \ + DEF(SET_ATTR) /* U msg */ \ + DEF(SET_ATTR_X) /* U msg */ \ + DEF(QUERY_STATE) /* U */ \ + DEF(GET_LOCAL_PORT_INFO) /* U msg */ \ + DEF(ABORT_CONNECTION) /* U msg */ \ + \ + DEF(CONNECT_OUTGOING_OK) /* */ \ + DEF(CONNECT_OUTGOING_ERR) /* reason */ \ + DEF(SETUP_CONFIRM) /* */ \ + DEF(SETUP_IND) /* */ \ + DEF(REJECT_OK) /* */ \ + DEF(REJECT_ERR) /* reason */ \ + DEF(ACCEPT_OK) /* */ \ + DEF(ACCEPT_ERR) /* reason */ \ + DEF(ACCEPTING) /* */ \ + DEF(SETUP_COMPL) /* */ \ + DEF(RELEASE_CONFIRM) /* */ \ + DEF(RELEASE_ERR) /* reason */ \ + DEF(ADD_PARTY_ERR) /* reason */ \ + DEF(ADD_PARTY_OK) /* */ \ + DEF(ADD_PARTY_ACK) /* leaf-ident */ \ + DEF(ADD_PARTY_REJ) /* leaf-ident */ \ + DEF(DROP_PARTY_ERR) /* reason */ \ + DEF(DROP_PARTY_OK) /* */ \ + DEF(DROP_PARTY_IND) /* leaf-ident */ \ + + +enum user_sig { +#define DEF(NAME) USER_SIG_##NAME, +USER_SIGS +#undef DEF +}; +extern const char *const cc_user_sigtab[]; + +struct ccuser { + LIST_ENTRY(ccuser) node_link; /* link in list of node */ + enum user_state state; /* type of this instance */ + struct ccdata *cc; /* the node */ + void *uarg; /* the hook (if any) */ + char name[ATM_EPNAMSIZ]; + enum { + USER_P2P, + USER_ROOT, + USER_LEAF + } config; /* configuration */ + + struct uni_sap *sap; /* listening SAP */ + u_int queue_max; /* maximum queue size */ + u_int queue_act; /* actual queue size */ + TAILQ_HEAD(,ccconn) connq; /* pending connections */ + struct ccconn *accepted; + struct uni_ie_cause cause[2]; /* cause from connection */ + u_int aborted; +}; + +/* set user to new state */ +void cc_user_set_state(struct ccuser *, enum user_state); + +/* return string for state */ +const char *cc_user_state2str(u_int); + +/* log on a user */ +#ifdef CCATM_DEBUG +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_user_log(U, FMT, ARGS...) do { \ + (U)->cc->funcs->log("%s (user=%p): " FMT, __FUNCTION__, \ + (U) , ## ARGS); \ + } while (0) +#else +#define cc_user_log(U, FMT, ...) do { \ + (U)->cc->funcs->log("%s (user=%p): " FMT, __func__, \ + (U), __VA_ARGS__); \ + } while (0) +#endif +#else +#if defined(__GNUC__) && __GNUC__ < 3 +#define cc_user_log(U, FMT, ARGS...) do { } while (0) +#else +#define cc_user_log(U, FMT, ...) do { } while (0) +#endif +#endif + +/* Handle a signal to this user */ +void cc_user_sig_handle(struct ccuser *, enum user_sig, void *, u_int); + +/* + * Addresses + */ +struct ccaddr { + TAILQ_ENTRY(ccaddr) port_link; + struct uni_addr addr; +}; + +/* signal to connection */ +int cc_conn_sig(struct ccconn *, enum conn_sig, void *arg); + +/* signal with message to connection */ +int cc_conn_sig_msg(struct ccconn *, enum conn_sig, struct uni_msg *); +int cc_conn_sig_msg_nodef(struct ccconn *, enum conn_sig, struct uni_msg *); + +/* response signal to connection */ +int cc_conn_resp(struct ccconn *, enum conn_sig, u_int, u_int, u_int); + +/* flush all signals to a given connection */ +void cc_conn_sig_flush(struct ccconn *); + +/* Queue a signal to this user */ +int cc_user_sig(struct ccuser *, enum user_sig, void *, u_int); + +/* Queue a signal with message to this user */ +int cc_user_sig_msg(struct ccuser *, enum user_sig, struct uni_msg *); + +/* Flush all signals to a given user */ +void cc_user_sig_flush(struct ccuser *); + +/* flush all signals */ +void cc_sig_flush_all(struct ccdata *); diff --git a/sys/contrib/ngatm/netnatm/api/unisap.c b/sys/contrib/ngatm/netnatm/api/unisap.c new file mode 100644 index 000000000000..d96f39ec1b1c --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/unisap.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * Copyright (c) 2004 + * Hartmut Brandt + * + * Author: Hartmut Brandt + * + * Redistribution 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 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 IS PROVIDED BY THE AUTHOR AND 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 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/unisap.c,v 1.4 2004/07/08 08:22:01 brandt Exp $ + */ + +#include +#ifdef _KERNEL +#include +#include +#else +#include +#include +#endif +#include +#include + +int +unisve_check_addr(const struct unisve_addr *sve) +{ + if (sve->tag == UNISVE_ABSENT) + return (UNISVE_OK); + if (sve->tag == UNISVE_ANY) + return (UNISVE_OK); + if (sve->tag != UNISVE_PRESENT) + return (UNISVE_ERROR_BAD_TAG); + + if (sve->type == UNI_ADDR_INTERNATIONAL) { + if (sve->plan != UNI_ADDR_E164) + return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); + if (sve->len == 0 || sve->len > 15) + return (UNISVE_ERROR_ADDR_LEN); + + } else if (sve->type == UNI_ADDR_UNKNOWN) { + if (sve->plan != UNI_ADDR_ATME) + return (UNISVE_ERROR_TYPE_PLAN_CONFLICT); + if (sve->len != 19) + return (UNISVE_ERROR_ADDR_LEN); + } else + return (UNISVE_ERROR_BAD_ADDR_TYPE); + + return (UNISVE_OK); +} + +int +unisve_check_selector(const struct unisve_selector *sve) +{ + if (sve->tag != UNISVE_PRESENT && + sve->tag != UNISVE_ABSENT && + sve->tag != UNISVE_ANY) + return (UNISVE_ERROR_BAD_TAG); + return (UNISVE_OK); +} + +/* + * We don't want to check the protocol values here. + */ +int +unisve_check_blli_id2(const struct unisve_blli_id2 *sve) +{ + if (sve->tag != UNISVE_PRESENT && + sve->tag != UNISVE_ABSENT && + sve->tag != UNISVE_ANY) + return (UNISVE_ERROR_BAD_TAG); + return (UNISVE_OK); +} + +/* + * We don't want to check the protocol values here. + */ +int +unisve_check_blli_id3(const struct unisve_blli_id3 *sve) +{ + if (sve->tag != UNISVE_PRESENT && + sve->tag != UNISVE_ABSENT && + sve->tag != UNISVE_ANY) + return (UNISVE_ERROR_BAD_TAG); + return (UNISVE_OK); +} + +int +unisve_check_bhli(const struct unisve_bhli *sve) +{ + if (sve->tag == UNISVE_ABSENT) + return (UNISVE_OK); + if (sve->tag == UNISVE_ANY) + return (UNISVE_OK); + + if (sve->tag != UNISVE_PRESENT) + return (UNISVE_ERROR_BAD_TAG); + + if (sve->type != UNI_BHLI_ISO && + sve->type != UNI_BHLI_USER && + sve->type != UNI_BHLI_VENDOR) + return (UNISVE_ERROR_BAD_BHLI_TYPE); + + if (sve->len > sizeof(sve->info)) + return (UNISVE_ERROR_BAD_BHLI_LEN); + + return (UNISVE_OK); +} + +int +unisve_check_sap(const struct uni_sap *sap) +{ + int err; + + if ((err = unisve_check_addr(&sap->addr)) != 0 || + (err = unisve_check_selector(&sap->selector)) != 0 || + (err = unisve_check_blli_id2(&sap->blli_id2)) != 0 || + (err = unisve_check_blli_id3(&sap->blli_id3)) != 0 || + (err = unisve_check_bhli(&sap->bhli)) != 0) + return (err); + + if (sap->addr.plan == UNI_ADDR_E164) { + if (sap->selector.tag == UNISVE_PRESENT) + return (UNISVE_ERROR_ADDR_SEL_CONFLICT); + } else if (sap->addr.plan == UNI_ADDR_ATME) { + if (sap->selector.tag == UNISVE_ABSENT) + return (UNISVE_ERROR_ADDR_SEL_CONFLICT); + } + return (0); +} + +#define COMMON_OVERLAP(A1,A2) \ + if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_ABSENT) || \ + A1->tag == UNISVE_ANY || A2->tag == UNISVE_ANY) \ + return (1); \ + if ((A1->tag == UNISVE_ABSENT && A2->tag == UNISVE_PRESENT) || \ + (A2->tag == UNISVE_ABSENT && A1->tag == UNISVE_PRESENT)) \ + return (0); + +int +unisve_overlap_addr(const struct unisve_addr *s1, const struct unisve_addr *s2) +{ + COMMON_OVERLAP(s1, s2); + + return (s1->type == s2->type && s1->plan == s2->plan && + s1->len == s2->len && memcmp(s1->addr, s2->addr, s1->len) == 0); +} + +int +unisve_overlap_selector(const struct unisve_selector *s1, + const struct unisve_selector *s2) +{ + COMMON_OVERLAP(s1, s2); + + return (s1->selector == s2->selector); +} + +int +unisve_overlap_blli_id2(const struct unisve_blli_id2 *s1, + const struct unisve_blli_id2 *s2) +{ + COMMON_OVERLAP(s1, s2); + + return (s1->proto == s2->proto && + (s1->proto != UNI_BLLI_L2_USER || s1->user == s2->user)); +} + +int +unisve_overlap_blli_id3(const struct unisve_blli_id3 *s1, + const struct unisve_blli_id3 *s2) +{ + COMMON_OVERLAP(s1, s2); + + if (s1->proto != s2->proto) + return (0); + if (s1->proto == UNI_BLLI_L3_USER) + return (s1->user == s2->user); + if (s1->proto == UNI_BLLI_L3_TR9577) { + if (s1->noipi && s2->noipi) + return (1); + if (!s1->noipi && !s2->noipi) { + if (s1->ipi == s2->ipi) { + if (s1->ipi != UNI_BLLI_L3_SNAP) + return (1); + if (s1->oui == s2->oui && s1->pid == s2->pid) + return (1); + } + } + return (0); + } + return (1); +} + +int +unisve_overlap_bhli(const struct unisve_bhli *s1, const struct unisve_bhli *s2) +{ + COMMON_OVERLAP(s1, s2); + + return (s1->type == s2->type && s1->len == s2->len && + memcmp(s1->info, s2->info, s1->len) == 0); +} + +int +unisve_overlap_sap(const struct uni_sap *s1, const struct uni_sap *s2) +{ + int any1, any2; + + /* + * Two catch-all's SAP's are not allowed. A catch-all does never + * overlap with a non-catch all SAP. + */ + any1 = unisve_is_catchall(s1); + any2 = unisve_is_catchall(s2); + + if (any1 && any2) + return (1); + if(any1 || any2) + return (0); + + return (unisve_overlap_addr(&s1->addr, &s2->addr) && + unisve_overlap_selector(&s1->selector, &s2->selector) && + unisve_overlap_blli_id2(&s1->blli_id2, &s2->blli_id2) && + unisve_overlap_blli_id3(&s1->blli_id3, &s2->blli_id3) && + unisve_overlap_bhli(&s1->bhli, &s2->bhli)); +} + +int +unisve_is_catchall(const struct uni_sap *sap) +{ + return (sap->addr.tag == UNISVE_ANY && + sap->selector.tag == UNISVE_ANY && + sap->blli_id2.tag == UNISVE_ANY && + sap->blli_id3.tag == UNISVE_ANY && + sap->bhli.tag == UNISVE_ANY); +} + +int +unisve_match(const struct uni_sap *sap, const struct uni_ie_called *called, + const struct uni_ie_blli *blli, const struct uni_ie_bhli *bhli) +{ + switch (sap->addr.tag) { + case UNISVE_ABSENT: + if (IE_ISGOOD(*called)) + return (0); + break; + + case UNISVE_ANY: + break; + + case UNISVE_PRESENT: + if (!IE_ISGOOD(*called)) + return (0); + if (called->addr.type != sap->addr.type || + called->addr.plan != sap->addr.plan) + return (0); + if (called->addr.plan == UNI_ADDR_E164) { + if (called->addr.len != sap->addr.len || + memcmp(called->addr.addr, sap->addr.addr, + called->addr.len) != 0) + return (0); + } else if (called->addr.plan == UNI_ADDR_ATME) { + if (called->addr.len != 20 || + memcmp(called->addr.addr, sap->addr.addr, 19) != 0) + return (0); + } + break; + + default: + return (0); + } + + switch (sap->selector.tag) { + + case UNISVE_ABSENT: + if (IE_ISGOOD(*called) && called->addr.plan == UNI_ADDR_ATME) + return (0); + break; + + case UNISVE_ANY: + break; + + case UNISVE_PRESENT: + if (!IE_ISGOOD(*called)) + return (0); + if (called->addr.plan != UNI_ADDR_ATME) + return (0); + if (called->addr.addr[19] != sap->selector.selector) + return (0); + break; + + default: + return (0); + } + + switch (sap->blli_id2.tag) { + + case UNISVE_ABSENT: + if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L2_P)) + return (0); + break; + + case UNISVE_ANY: + break; + + case UNISVE_PRESENT: + if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L2_P) == 0) + return (0); + if (blli->l2 != sap->blli_id2.proto) + return (0); + if (blli->l2 == UNI_BLLI_L2_USER) { + if ((blli->h.present & UNI_BLLI_L2_USER_P) == 0) + return (0); + if (blli->l2_user != sap->blli_id2.user) + return (0); + } + break; + + default: + return (0); + } + + switch (sap->blli_id3.tag) { + + case UNISVE_ABSENT: + if (IE_ISGOOD(*blli) && (blli->h.present & UNI_BLLI_L3_P)) + return (0); + break; + + case UNISVE_ANY: + break; + + case UNISVE_PRESENT: + if (!IE_ISGOOD(*blli) || (blli->h.present & UNI_BLLI_L3_P) == 0) + return (0); + if (blli->l3 != sap->blli_id3.proto) + return (0); + if (blli->l3 == UNI_BLLI_L3_USER) { + if ((blli->h.present & UNI_BLLI_L3_USER_P) == 0) + return (0); + if (blli->l3_user != sap->blli_id3.user) + return (0); + break; + } + if (blli->l3 == UNI_BLLI_L3_TR9577) { + if (sap->blli_id3.noipi) { + if (blli->h.present & UNI_BLLI_L3_IPI_P) + return (0); + } else { + if (!(blli->h.present & UNI_BLLI_L3_IPI_P)) + return (0); + if (blli->l3_ipi != sap->blli_id3.ipi) + return (0); + if (blli->l3_ipi == UNI_BLLI_L3_SNAP) { + if (!(blli->h.present & + UNI_BLLI_L3_SNAP_P)) + return (0); + if (blli->oui != sap->blli_id3.oui || + blli->pid != sap->blli_id3.pid) + return (0); + } + } + } + break; + + default: + return (0); + } + + switch (sap->bhli.tag) { + + case UNISVE_ABSENT: + if (IE_ISGOOD(*bhli)) + return (0); + break; + + case UNISVE_ANY: + break; + + case UNISVE_PRESENT: + if (!IE_ISGOOD(*bhli)) + return (0); + if (sap->bhli.type != bhli->type) + return (0); + if (sap->bhli.len != bhli->len) + return (0); + if (memcmp(sap->bhli.info, bhli->info, bhli->len) != 0) + return (0); + break; + + default: + return (0); + } + /* Uff */ + return (1); +} diff --git a/sys/contrib/ngatm/netnatm/api/unisap.h b/sys/contrib/ngatm/netnatm/api/unisap.h new file mode 100644 index 000000000000..004feb77eb93 --- /dev/null +++ b/sys/contrib/ngatm/netnatm/api/unisap.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2001-2003 + * Fraunhofer Institute for Open Communication Systems (FhG Fokus). + * All rights reserved. + * + * Author: Hartmut Brandt + * + * Redistribution 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 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 IS PROVIDED BY THE AUTHOR AND 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 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/unisap.h,v 1.5 2004/07/08 08:22:01 brandt Exp $ + * $FreeBSD$ + */ +#ifndef _NETNATM_API_UNISAP_H_ +#define _NETNATM_API_UNISAP_H_ + +#include + +enum unisve_tag { + UNISVE_ABSENT, /* Element is absent */ + UNISVE_PRESENT, /* Element is present with specific value */ + UNISVE_ANY /* Any values is acceptable */ +}; + +struct unisve_addr { + enum unisve_tag tag; + enum uni_addr_type type; /* type of address */ + enum uni_addr_plan plan; /* addressing plan */ + uint32_t len; /* length of address */ + u_char addr[UNI_ADDR_MAXLEN]; +}; + +struct unisve_selector { + enum unisve_tag tag; + uint8_t selector; +}; + +struct unisve_blli_id2 { + enum unisve_tag tag; + u_int proto:5; /* the protocol */ + u_int user:7; /* user specific protocol */ +}; + +struct unisve_blli_id3 { + enum unisve_tag tag; + u_int proto:5; /* L3 protocol */ + u_int user:7; /* user specific protocol */ + u_int ipi:8; /* ISO/IEC TR 9557 IPI */ + u_int oui:24; /* IEEE 802.1 OUI */ + u_int pid:16; /* IEEE 802.1 PID */ + uint32_t noipi; /* ISO/IEC TR 9557 per frame */ +}; + +struct unisve_bhli { + enum unisve_tag tag; + enum uni_bhli type; /* type of info */ + uint32_t len; /* length of info */ + uint8_t info[8]; /* info itself */ +}; + +struct uni_sap { + struct unisve_addr addr; + struct unisve_selector selector; + struct unisve_blli_id2 blli_id2; + struct unisve_blli_id3 blli_id3; + struct unisve_bhli bhli; +}; + +int unisve_check_addr(const struct unisve_addr *); +int unisve_check_selector(const struct unisve_selector *); +int unisve_check_blli_id2(const struct unisve_blli_id2 *); +int unisve_check_blli_id3(const struct unisve_blli_id3 *); +int unisve_check_bhli(const struct unisve_bhli *); + +int unisve_check_sap(const struct uni_sap *); + +int unisve_overlap_addr(const struct unisve_addr *, const struct unisve_addr *); +int unisve_overlap_selector(const struct unisve_selector *, + const struct unisve_selector *); +int unisve_overlap_blli_id2(const struct unisve_blli_id2 *, + const struct unisve_blli_id2 *); +int unisve_overlap_blli_id3(const struct unisve_blli_id3 *, + const struct unisve_blli_id3 *); +int unisve_overlap_bhli(const struct unisve_bhli *, + const struct unisve_bhli *); +int unisve_overlap_sap(const struct uni_sap *, const struct uni_sap *); + +int unisve_is_catchall(const struct uni_sap *); +int unisve_match(const struct uni_sap *, const struct uni_ie_called *, + const struct uni_ie_blli *, const struct uni_ie_bhli *); + +enum { + UNISVE_OK = 0, + UNISVE_ERROR_BAD_TAG, + UNISVE_ERROR_TYPE_PLAN_CONFLICT, + UNISVE_ERROR_ADDR_SEL_CONFLICT, + UNISVE_ERROR_ADDR_LEN, + UNISVE_ERROR_BAD_ADDR_TYPE, + UNISVE_ERROR_BAD_BHLI_TYPE, + UNISVE_ERROR_BAD_BHLI_LEN, +}; + +#define UNISVE_ERRSTR \ + "no error", \ + "bad SVE tag", \ + "bad address type/plan combination", \ + "bad address plan/selector tag combination", \ + "bad address length in SVE", \ + "unknown address type in SVE", \ + "bad BHLI type in SVE", \ + "BHLI info too long in SVE", + +#endif diff --git a/sys/contrib/ngatm/netnatm/genfiles b/sys/contrib/ngatm/netnatm/genfiles index a51e921e2b92..70fb5e880463 100644 --- a/sys/contrib/ngatm/netnatm/genfiles +++ b/sys/contrib/ngatm/netnatm/genfiles @@ -3,10 +3,10 @@ # Fraunhofer Institute for Open Communication Systems (FhG Fokus). # All rights reserved. # -# $Begemot: libunimsg/atm/genfiles,v 1.3 2003/09/19 11:51:57 hbb Exp $ -# # Author: Harti Brandt # +# $Begemot: libunimsg/netnatm/genfiles,v 1.4 2004/07/08 08:21:45 brandt Exp $ +# awk -f ${SRC}msg/parseie.awk -f ${SRC}msg/geniec.awk ${SRC}msg/ie.def >${DST}msg/uni_ietab.h awk -f ${SRC}msg/parseie.awk -f ${SRC}msg/genieh.awk ${SRC}msg/ie.def >${DST}msg/uni_ie.h awk -f ${SRC}msg/parsemsg.awk -f ${SRC}msg/genmsgc.awk ${SRC}msg/msg.def >${DST}msg/uni_msg.c diff --git a/sys/contrib/ngatm/netnatm/misc/straddr.c b/sys/contrib/ngatm/netnatm/misc/straddr.c index 78207aa009f6..7d21b8f74206 100644 --- a/sys/contrib/ngatm/netnatm/misc/straddr.c +++ b/sys/contrib/ngatm/netnatm/misc/straddr.c @@ -3,6 +3,8 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * + * Author: Hartmut Brandt + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,9 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Author: Hartmut Brandt - * - * $Begemot: libunimsg/atm/misc/straddr.c,v 1.3 2003/09/19 12:05:45 hbb Exp $ + * $Begemot: libunimsg/netnatm/misc/straddr.c,v 1.4 2004/07/08 08:22:02 brandt Exp $ */ #include diff --git a/sys/contrib/ngatm/netnatm/misc/unimsg_common.c b/sys/contrib/ngatm/netnatm/misc/unimsg_common.c index 5d216a58d142..033213aef781 100644 --- a/sys/contrib/ngatm/netnatm/misc/unimsg_common.c +++ b/sys/contrib/ngatm/netnatm/misc/unimsg_common.c @@ -3,6 +3,8 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * + * Author: Hartmut Brandt + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,9 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Author: Hartmut Brandt - * - * $Begemot: libunimsg/atm/misc/unimsg_common.c,v 1.2 2003/09/19 12:05:45 hbb Exp $ + * $Begemot: libunimsg/netnatm/misc/unimsg_common.c,v 1.3 2004/07/08 08:22:03 brandt Exp $ */ #include diff --git a/sys/contrib/ngatm/netnatm/msg/geniec.awk b/sys/contrib/ngatm/netnatm/msg/geniec.awk index 8030c5939ce9..d0620825178f 100644 --- a/sys/contrib/ngatm/netnatm/msg/geniec.awk +++ b/sys/contrib/ngatm/netnatm/msg/geniec.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/geniec.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/geniec.awk,v 1.4 2003/10/10 14:50:05 hbb Exp $ # # Generate table for IE parsing. # diff --git a/sys/contrib/ngatm/netnatm/msg/genieh.awk b/sys/contrib/ngatm/netnatm/msg/genieh.awk index 8119b1dd02d9..7120d7b9a020 100644 --- a/sys/contrib/ngatm/netnatm/msg/genieh.awk +++ b/sys/contrib/ngatm/netnatm/msg/genieh.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/genieh.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/genieh.awk,v 1.4 2004/07/08 08:22:03 brandt Exp $ # # Generate IE header file # diff --git a/sys/contrib/ngatm/netnatm/msg/genmsgc.awk b/sys/contrib/ngatm/netnatm/msg/genmsgc.awk index d3f196eacfa7..ffd69ac5fc69 100644 --- a/sys/contrib/ngatm/netnatm/msg/genmsgc.awk +++ b/sys/contrib/ngatm/netnatm/msg/genmsgc.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/genmsgc.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/genmsgc.awk,v 1.6 2004/07/08 08:22:04 brandt Exp $ # # Generate message functions. # diff --git a/sys/contrib/ngatm/netnatm/msg/genmsgh.awk b/sys/contrib/ngatm/netnatm/msg/genmsgh.awk index a98fa98f754c..8705b31e1e30 100644 --- a/sys/contrib/ngatm/netnatm/msg/genmsgh.awk +++ b/sys/contrib/ngatm/netnatm/msg/genmsgh.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/genmsgh.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/genmsgh.awk,v 1.4 2004/07/08 08:22:04 brandt Exp $ # # Generate message header # diff --git a/sys/contrib/ngatm/netnatm/msg/ie.def b/sys/contrib/ngatm/netnatm/msg/ie.def index 61c0ccfabb00..fbeabe87a84c 100644 --- a/sys/contrib/ngatm/netnatm/msg/ie.def +++ b/sys/contrib/ngatm/netnatm/msg/ie.def @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/ie.def,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/ie.def,v 1.4 2003/09/29 10:47:18 hbb Exp $ # # Define information elements --- no content definition # diff --git a/sys/contrib/ngatm/netnatm/msg/msg.def b/sys/contrib/ngatm/netnatm/msg/msg.def index 40099a474c58..41453ec6a5c4 100644 --- a/sys/contrib/ngatm/netnatm/msg/msg.def +++ b/sys/contrib/ngatm/netnatm/msg/msg.def @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/msg.def,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/msg.def,v 1.4 2003/09/29 10:47:18 hbb Exp $ # # Define message contents # diff --git a/sys/contrib/ngatm/netnatm/msg/parseie.awk b/sys/contrib/ngatm/netnatm/msg/parseie.awk index a505951f6e48..14bd0f876978 100644 --- a/sys/contrib/ngatm/netnatm/msg/parseie.awk +++ b/sys/contrib/ngatm/netnatm/msg/parseie.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/parseie.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/parseie.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ # # Parse the IE definition file # diff --git a/sys/contrib/ngatm/netnatm/msg/parsemsg.awk b/sys/contrib/ngatm/netnatm/msg/parsemsg.awk index 241400321f23..ff13874d4509 100644 --- a/sys/contrib/ngatm/netnatm/msg/parsemsg.awk +++ b/sys/contrib/ngatm/netnatm/msg/parsemsg.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/msg/parsemsg.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ +# $Begemot: libunimsg/netnatm/msg/parsemsg.awk,v 1.3 2003/09/19 11:58:15 hbb Exp $ # # Parse the message definition file # diff --git a/sys/contrib/ngatm/netnatm/msg/priv.h b/sys/contrib/ngatm/netnatm/msg/priv.h index 48943904273b..aa13fc467d46 100644 --- a/sys/contrib/ngatm/netnatm/msg/priv.h +++ b/sys/contrib/ngatm/netnatm/msg/priv.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/priv.h,v 1.3 2003/09/19 11:58:15 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/priv.h,v 1.4 2003/10/10 14:50:05 hbb Exp $ * * Private definitions for the IE code file. */ diff --git a/sys/contrib/ngatm/netnatm/msg/privmsg.c b/sys/contrib/ngatm/netnatm/msg/privmsg.c index 3a3051a3d30d..3540efdb8ce2 100644 --- a/sys/contrib/ngatm/netnatm/msg/privmsg.c +++ b/sys/contrib/ngatm/netnatm/msg/privmsg.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/privmsg.c,v 1.3 2003/09/19 11:58:15 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/privmsg.c,v 1.8 2003/10/10 14:50:05 hbb Exp $ * * Private definitions for the MSG code file. * diff --git a/sys/contrib/ngatm/netnatm/msg/traffic.c b/sys/contrib/ngatm/netnatm/msg/traffic.c index f941dedb01b2..acaffdbbe7d4 100644 --- a/sys/contrib/ngatm/netnatm/msg/traffic.c +++ b/sys/contrib/ngatm/netnatm/msg/traffic.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/traffic.c,v 1.3 2003/09/19 11:58:15 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/traffic.c,v 1.4 2004/07/08 08:22:05 brandt Exp $ * * Traffic classification */ diff --git a/sys/contrib/ngatm/netnatm/msg/uni_config.h b/sys/contrib/ngatm/netnatm/msg/uni_config.h index 2a16152027b9..e53f59b8395c 100644 --- a/sys/contrib/ngatm/netnatm/msg/uni_config.h +++ b/sys/contrib/ngatm/netnatm/msg/uni_config.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/uni_config.h,v 1.3 2003/09/19 11:58:15 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/uni_config.h,v 1.3 2003/09/19 11:58:15 hbb Exp $ */ #ifndef _uni_uni_config_h_ #define _uni_uni_config_h_ diff --git a/sys/contrib/ngatm/netnatm/msg/uni_hdr.h b/sys/contrib/ngatm/netnatm/msg/uni_hdr.h index 0447de6ecc51..c9a30f12be5d 100644 --- a/sys/contrib/ngatm/netnatm/msg/uni_hdr.h +++ b/sys/contrib/ngatm/netnatm/msg/uni_hdr.h @@ -26,12 +26,17 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/uni_hdr.h,v 1.3 2003/09/19 11:58:15 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/uni_hdr.h,v 1.6 2004/07/08 08:22:05 brandt Exp $ */ #ifndef _NETNATM_MSG_UNI_HDR_H_ #define _NETNATM_MSG_UNI_HDR_H_ #include +#ifdef _KERNEL +#include +#else +#include +#endif #include diff --git a/sys/contrib/ngatm/netnatm/msg/uni_ie.c b/sys/contrib/ngatm/netnatm/msg/uni_ie.c index b6a2b78b6858..a9d5eca33b3d 100644 --- a/sys/contrib/ngatm/netnatm/msg/uni_ie.c +++ b/sys/contrib/ngatm/netnatm/msg/uni_ie.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/uni_ie.c,v 1.12 2003/10/14 15:02:22 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/uni_ie.c,v 1.14 2004/07/08 08:22:06 brandt Exp $ * * Private definitions for the IE code file. * diff --git a/sys/contrib/ngatm/netnatm/msg/unimsglib.h b/sys/contrib/ngatm/netnatm/msg/unimsglib.h index e98d58033cc2..f8489dbffc0c 100644 --- a/sys/contrib/ngatm/netnatm/msg/unimsglib.h +++ b/sys/contrib/ngatm/netnatm/msg/unimsglib.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/unimsglib.h,v 1.3 2003/09/19 11:58:16 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/unimsglib.h,v 1.6 2004/07/08 08:22:07 brandt Exp $ */ #ifndef _NETNATM_MSG_UNIMSGLIB_H_ #define _NETNATM_MSG_UNIMSGLIB_H_ diff --git a/sys/contrib/ngatm/netnatm/msg/uniprint.h b/sys/contrib/ngatm/netnatm/msg/uniprint.h index c16f6b1b1760..239fa2dd4076 100644 --- a/sys/contrib/ngatm/netnatm/msg/uniprint.h +++ b/sys/contrib/ngatm/netnatm/msg/uniprint.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/msg/uniprint.h,v 1.3 2003/09/19 11:58:16 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/uniprint.h,v 1.4 2004/07/08 08:22:08 brandt Exp $ * * Print utility functions. These are only needed if you want to hook to * the format of the uni printing routines. diff --git a/sys/contrib/ngatm/netnatm/msg/unistruct.h b/sys/contrib/ngatm/netnatm/msg/unistruct.h index fd57cf935cf6..819f2753dc3c 100644 --- a/sys/contrib/ngatm/netnatm/msg/unistruct.h +++ b/sys/contrib/ngatm/netnatm/msg/unistruct.h @@ -3,6 +3,8 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * + * Author: Hartmut Brandt + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,9 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Author: Hartmut Brandt - * - * $Begemot: libunimsg/atm/msg/unistruct.h,v 1.4 2003/09/19 11:58:16 hbb Exp $ + * $Begemot: libunimsg/netnatm/msg/unistruct.h,v 1.6 2004/07/08 08:22:08 brandt Exp $ * * This file defines all structures that are used by * API users. diff --git a/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c b/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c index a385b700f685..80140ba03d49 100644 --- a/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c +++ b/sys/contrib/ngatm/netnatm/saal/saal_sscfu.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/saal_sscfu.c,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/saal_sscfu.c,v 1.4 2004/07/08 08:22:10 brandt Exp $ * * SSCF on the UNI */ diff --git a/sys/contrib/ngatm/netnatm/saal/saal_sscop.c b/sys/contrib/ngatm/netnatm/saal/saal_sscop.c index 7a62505c2b51..75ce17db89fa 100644 --- a/sys/contrib/ngatm/netnatm/saal/saal_sscop.c +++ b/sys/contrib/ngatm/netnatm/saal/saal_sscop.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/saal_sscop.c,v 1.10 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/saal_sscop.c,v 1.11 2004/07/08 08:22:13 brandt Exp $ * * Core SSCOP code (ITU-T Q.2110) */ diff --git a/sys/contrib/ngatm/netnatm/saal/sscfu.h b/sys/contrib/ngatm/netnatm/saal/sscfu.h index f62e90851bc2..3aaa9270d3ff 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscfu.h +++ b/sys/contrib/ngatm/netnatm/saal/sscfu.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscfu.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscfu.h,v 1.4 2004/07/08 08:22:15 brandt Exp $ * * Public include file for UNI SSCF */ diff --git a/sys/contrib/ngatm/netnatm/saal/sscfudef.h b/sys/contrib/ngatm/netnatm/saal/sscfudef.h index 866e43e66475..08882f2a9bc2 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscfudef.h +++ b/sys/contrib/ngatm/netnatm/saal/sscfudef.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscfudef.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscfudef.h,v 1.4 2004/07/08 08:22:16 brandt Exp $ * * Definitions of UNI SSCF constants. */ diff --git a/sys/contrib/ngatm/netnatm/saal/sscfupriv.h b/sys/contrib/ngatm/netnatm/saal/sscfupriv.h index b807b4fbf729..b4a1299ac108 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscfupriv.h +++ b/sys/contrib/ngatm/netnatm/saal/sscfupriv.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscfupriv.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscfupriv.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ * * Private SSCF-UNI definitions. */ diff --git a/sys/contrib/ngatm/netnatm/saal/sscop.h b/sys/contrib/ngatm/netnatm/saal/sscop.h index 65965f54bb4c..8574a1581791 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscop.h +++ b/sys/contrib/ngatm/netnatm/saal/sscop.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscop.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscop.h,v 1.4 2004/07/08 08:22:16 brandt Exp $ * * External interface to sscop. */ diff --git a/sys/contrib/ngatm/netnatm/saal/sscopdef.h b/sys/contrib/ngatm/netnatm/saal/sscopdef.h index 09bd65ce1596..ec6716461c34 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscopdef.h +++ b/sys/contrib/ngatm/netnatm/saal/sscopdef.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscopdef.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscopdef.h,v 1.4 2004/07/08 08:22:17 brandt Exp $ * * Definitions of SSCOP constants and parameter blocks. This is seen by * the outside world. @@ -35,6 +35,11 @@ #define _NETNATM_SAAL_SSCOPDEF_H_ #include +#ifdef _KERNEL +#include +#else +#include +#endif /* * AA-interface signals diff --git a/sys/contrib/ngatm/netnatm/saal/sscoppriv.h b/sys/contrib/ngatm/netnatm/saal/sscoppriv.h index 950cd593e29c..e2b055530b1f 100644 --- a/sys/contrib/ngatm/netnatm/saal/sscoppriv.h +++ b/sys/contrib/ngatm/netnatm/saal/sscoppriv.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/saal/sscoppriv.h,v 1.3 2003/09/19 12:02:03 hbb Exp $ + * $Begemot: libunimsg/netnatm/saal/sscoppriv.h,v 1.4 2004/07/08 08:22:17 brandt Exp $ * * Private SSCOP definitions. * @@ -39,6 +39,16 @@ #include "sscopcust.h" #endif +/* Argh. BSDi */ +#ifndef _BYTE_ORDER +#ifndef BYTE_ORDER +#error "_BYTE_ORDER not defined" +#endif +#define _BYTE_ORDER BYTE_ORDER +#define _LITTLE_ENDIAN LITTLE_ENDIAN +#define _BIG_ENDIAN BIG_ENDIAN +#endif + /* * PDU trailer */ diff --git a/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk b/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk index ca347acfb934..be61925c977a 100644 --- a/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk +++ b/sys/contrib/ngatm/netnatm/sig/genmsgcpyc.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/sig/genmsgcpyc.awk,v 1.3 2003/09/19 12:03:33 hbb Exp $ +# $Begemot: libunimsg/netnatm/sig/genmsgcpyc.awk,v 1.4 2004/07/08 08:22:18 brandt Exp $ # # Generate copy functions for messages # diff --git a/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk b/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk index 0b50688c60cf..f9b44f2b168d 100644 --- a/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk +++ b/sys/contrib/ngatm/netnatm/sig/genmsgcpyh.awk @@ -26,7 +26,7 @@ # # Author: Hartmut Brandt # -# $Begemot: libunimsg/atm/sig/genmsgcpyh.awk,v 1.3 2003/09/19 12:03:33 hbb Exp $ +# $Begemot: libunimsg/netnatm/sig/genmsgcpyh.awk,v 1.4 2004/07/08 08:22:19 brandt Exp $ # # Generate copy functions for messages # diff --git a/sys/contrib/ngatm/netnatm/sig/sig_call.c b/sys/contrib/ngatm/netnatm/sig/sig_call.c index e11c52f3113f..c6a754b4c2a4 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_call.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_call.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/sig_call.c,v 1.61 2003/10/16 13:35:44 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_call.c,v 1.64 2004/07/08 08:22:19 brandt Exp $ * * Call instance handling * @@ -144,7 +144,7 @@ uni_find_callx(struct uni *uni, u_int cref, u_int mine) * Create a new call instance. The type must be set by the caller. */ struct call * -uni_create_call(struct uni *uni, u_int cref, u_int mine, u_int32_t cookie) +uni_create_call(struct uni *uni, u_int cref, u_int mine, uint32_t cookie) { struct call *c; struct uniapi_call_created *ind; @@ -185,10 +185,10 @@ uni_create_call(struct uni *uni, u_int cref, u_int mine, u_int32_t cookie) } struct call * -uni_create_new_call(struct uni *uni, u_int32_t cookie) +uni_create_new_call(struct uni *uni, uint32_t cookie) { struct call *c; - u_int32_t old = uni->cref_alloc++; + uint32_t old = uni->cref_alloc++; again: if (uni->cref_alloc == (1 << 23)) @@ -254,7 +254,7 @@ static void allocate_epref(struct call *c, struct uni_ie_epref *epref) { struct party *p; - u_int32_t old = c->epref_alloc++; + uint32_t old = c->epref_alloc++; again: if (c->epref_alloc == (1 << 15)) @@ -466,7 +466,7 @@ un0_setup(struct call *c, struct uni_msg *m, struct uni_all *u, * Q.2971:Call-Control-N 4/39 (N0) */ static void -un0_setup_request(struct call *c, struct uni_msg *m, u_int32_t cookie, +un0_setup_request(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uniapi_setup_request *arg = @@ -829,7 +829,7 @@ unx_alerting(struct call *c, struct uni_msg *m, struct uni_all *u, * Q.2971:Call-Control-N 6/39 (N1) */ static void -u6n1_proceeding_request(struct call *c, struct uni_msg *m, u_int32_t cookie, +u6n1_proceeding_request(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uni_all *msg; @@ -866,7 +866,7 @@ u6n1_proceeding_request(struct call *c, struct uni_msg *m, u_int32_t cookie, * Q.2971:Call-Control-N 7/39 (N3) */ static void -unx_alerting_request(struct call *c, struct uni_msg *m, u_int32_t cookie, +unx_alerting_request(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uni_all *msg; @@ -915,7 +915,7 @@ unx_alerting_request(struct call *c, struct uni_msg *m, u_int32_t cookie, * Q.2971:Call-Control-N 8/39 (N4) */ static void -unx_setup_response(struct call *c, struct uni_msg *m, u_int32_t cookie, +unx_setup_response(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uni_all *msg; @@ -947,6 +947,7 @@ unx_setup_response(struct call *c, struct uni_msg *m, u_int32_t cookie, p->flags |= PARTY_CONNECT; } else if (c->type == CALL_LEAF) { + /* XXX don't mandate if only one party */ uniapi_call_error(c, UNIAPI_ERROR_BAD_PARTY, cookie); UNI_FREE(msg); uni_msg_destroy(m); @@ -979,7 +980,7 @@ unx_setup_response(struct call *c, struct uni_msg *m, u_int32_t cookie, * Q.2971:Call-Control-N 15/39 (N8) */ static void -n8_setup_compl_request(struct call *c, struct uni_msg *m, u_int32_t cookie, +n8_setup_compl_request(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uni_all *msg; @@ -1289,7 +1290,7 @@ n10_connect_ack(struct call *c, struct uni_msg *m, struct uni_all *u) * Q.2971:Call-Control-N 29/39 (N11) */ static void -unx_release_response(struct call *c, struct uni_msg *m, u_int32_t cookie) +unx_release_response(struct call *c, struct uni_msg *m, uint32_t cookie) { struct party *p; struct uni_all *msg; @@ -1544,7 +1545,7 @@ unx_notify(struct call *c, struct uni_msg *m, struct uni_all *u) * Q.2971:Call-Control-N 19/39 */ static void -unx_notify_request(struct call *c, struct uni_msg *m, u_int32_t cookie) +unx_notify_request(struct call *c, struct uni_msg *m, uint32_t cookie) { struct uni_all *msg; struct uniapi_notify_request *arg = @@ -1575,7 +1576,7 @@ unx_notify_request(struct call *c, struct uni_msg *m, u_int32_t cookie) * Q.2971:Call-Control-N 28/39 */ static void -unx_release_request(struct call *c, struct uni_msg *m, u_int32_t cookie, +unx_release_request(struct call *c, struct uni_msg *m, uint32_t cookie, enum call_state new_state) { struct uni_all *msg; @@ -1942,7 +1943,7 @@ unx_status(struct call *c, struct uni_msg *m, struct uni_all *u) * Q.2971:Call-Control-N 32/39 */ static void -unx_status_enquiry_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +unx_status_enquiry_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_status_enquiry_request *arg = uni_msg_rptr(msg, struct uniapi_status_enquiry_request *); @@ -2457,7 +2458,7 @@ nx_add_party_rej_indication(struct call *c, struct uni_msg *api) * Q.2971:Call-Control-N 22/39 (N10) */ static void -unx_add_party_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +unx_add_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_add_party_request *add = uni_msg_rptr(msg, struct uniapi_add_party_request *); @@ -2503,7 +2504,7 @@ unx_add_party_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) * Q.2971:Call-Control-N 22/39 */ static void -un10_add_party_ack_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +un10_add_party_ack_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_add_party_ack_request *ack = uni_msg_rptr(msg, struct uniapi_add_party_ack_request *); @@ -2538,7 +2539,7 @@ un10_add_party_ack_request(struct call *c, struct uni_msg *msg, u_int32_t cookie * Q.2971:Call-Control-N 22/39 N10 */ static void -unx_party_alerting_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +unx_party_alerting_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_party_alerting_request *alert = uni_msg_rptr(msg, struct uniapi_party_alerting_request *); @@ -2573,7 +2574,7 @@ unx_party_alerting_request(struct call *c, struct uni_msg *msg, u_int32_t cookie * Q.2971:Call-Control-N 22/39 N10 */ static void -unx_add_party_rej_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +unx_add_party_rej_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_add_party_rej_request *rej = uni_msg_rptr(msg, struct uniapi_add_party_rej_request *); @@ -2607,7 +2608,7 @@ unx_add_party_rej_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) * Q.2971:Call-Control-N 27/39 N1-N9 */ static void -unx_drop_party_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) +unx_drop_party_request(struct call *c, struct uni_msg *msg, uint32_t cookie) { struct uniapi_drop_party_request *drop = uni_msg_rptr(msg, struct uniapi_drop_party_request *); @@ -2637,7 +2638,7 @@ unx_drop_party_request(struct call *c, struct uni_msg *msg, u_int32_t cookie) */ static void unx_drop_party_ack_request(struct call *c, struct uni_msg *msg, - u_int32_t cookie) + uint32_t cookie) { struct uniapi_drop_party_ack_request *ack = uni_msg_rptr(msg, struct uniapi_drop_party_ack_request *); @@ -2667,6 +2668,7 @@ unx_drop_party_ack_request(struct call *c, struct uni_msg *msg, * Q.2971:Call-Control-N 21/39 N10 * * Body already decoded + * XXX check EPREF flag */ static void unx_add_party(struct call *c, struct uni_msg *m, struct uni_all *u, @@ -2751,6 +2753,14 @@ unx_add_party(struct call *c, struct uni_msg *m, struct uni_all *u, &u->u.add_party.epref, -1); return; } + + if (IE_ISGOOD(u->u.add_party.epref) && p == NULL && + u->u.add_party.epref.flag) { + IE_SETERROR(u->u.add_party.epref); + UNI_SAVE_IERR(&c->uni->cx, UNI_IE_EPREF, + u->u.add_party.epref.h.act, UNI_IERR_BAD); + } + if (!IE_ISGOOD(u->u.add_party.epref)) { /* 9.5.3.2.2 */ if (vfy == VFY_OK) { @@ -3321,7 +3331,7 @@ unx_unknown(struct call *c, struct uni_msg *m, struct uni_all *u) /**********************************************************************/ void -uni_sig_call(struct call *c, enum call_sig sig, u_int32_t cookie, +uni_sig_call(struct call *c, enum call_sig sig, uint32_t cookie, struct uni_msg *msg, struct uni_all *u) { if (sig >= SIGC_END) { @@ -3859,7 +3869,7 @@ uni_sig_call(struct call *c, enum call_sig sig, u_int32_t cookie, unx_alerting_request(c, msg, cookie, CALLST_U7); break; } - if (c->cstate == CALLST_N1 || c->cstate == CALLST_N1) { + if (c->cstate == CALLST_N1 || c->cstate == CALLST_N3) { /* Q.2971:Call-Control-N 38/39 (N1) */ /* Q.2971:Call-Control-N 7/39 (N3) */ unx_alerting_request(c, msg, cookie, CALLST_N4); diff --git a/sys/contrib/ngatm/netnatm/sig/sig_coord.c b/sys/contrib/ngatm/netnatm/sig/sig_coord.c index bbdd72341451..474974fb6547 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_coord.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_coord.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/sig_coord.c,v 1.6 2003/09/24 10:27:50 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_coord.c,v 1.11 2004/07/08 08:22:20 brandt Exp $ * * Coordinator */ @@ -200,7 +200,7 @@ coord_saal_release_indication(struct uni *uni) * a call instance. In this case 'cookie' is zero. */ static void -coord_link_establish_request(struct uni *uni, u_int32_t cookie) +coord_link_establish_request(struct uni *uni, uint32_t cookie) { switch (uni->custat) { @@ -650,7 +650,7 @@ input_call(struct call *c, struct uni_msg *m, struct uni_all *u) * Signal handler of the coordinator */ void -uni_sig_coord(struct uni *uni, enum coord_sig sig, u_int32_t cookie, +uni_sig_coord(struct uni *uni, enum coord_sig sig, uint32_t cookie, struct uni_msg *msg) { struct call *c; diff --git a/sys/contrib/ngatm/netnatm/sig/sig_party.c b/sys/contrib/ngatm/netnatm/sig/sig_party.c index c8c92b0907b9..e09482d20df2 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_party.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_party.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/sig_party.c,v 1.12 2003/10/10 14:37:28 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_party.c,v 1.17 2004/07/08 08:22:21 brandt Exp $ * * Party instance handling */ @@ -71,7 +71,7 @@ set_party_state(struct party *p, enum uni_epstate state) * No check is done, that a party with this epref does not alreay exist. */ struct party * -uni_create_partyx(struct call *c, u_int epref, u_int mine, u_int32_t cookie) +uni_create_partyx(struct call *c, u_int epref, u_int mine, uint32_t cookie) { struct party *p; struct uni_msg *api; @@ -232,7 +232,7 @@ stop_all_party_timers(struct party *p) * Q.2971:Party-control-N 3 (PN0) */ static void -pun0_add_party_request(struct party *p, struct uni_msg *api, u_int32_t cookie) +pun0_add_party_request(struct party *p, struct uni_msg *api, uint32_t cookie) { struct uni_all *add; struct uniapi_add_party_request *req = @@ -266,7 +266,7 @@ pun0_add_party_request(struct party *p, struct uni_msg *api, u_int32_t cookie) * Q.2971:Party-Control-N 7 PN3 */ static void -punx_add_party_ack_request(struct party *p, struct uni_msg *m, u_int32_t cookie) +punx_add_party_ack_request(struct party *p, struct uni_msg *m, uint32_t cookie) { struct uni_all *ack; struct uniapi_add_party_ack_request *req = @@ -295,7 +295,7 @@ punx_add_party_ack_request(struct party *p, struct uni_msg *m, u_int32_t cookie) * Q.2971:Party-Control-N 6 PN2 */ static void -pun2_add_party_rej_request(struct party *p, struct uni_msg *m, u_int32_t cookie) +pun2_add_party_rej_request(struct party *p, struct uni_msg *m, uint32_t cookie) { struct uni_all *rej; struct uniapi_add_party_rej_request *req = @@ -352,7 +352,7 @@ pun0_add_party(struct party *p, struct uni_msg *m, struct uni_all *u) */ static void pun2_party_alerting_request(struct party *p, struct uni_msg *api, - u_int32_t cookie) + uint32_t cookie) { struct uni_all *alert; struct uniapi_party_alerting_request *req = @@ -751,7 +751,7 @@ drop_partyE(struct party *p) * Q.2971:Party-Control-N 8 */ static void -punx_drop_party_request(struct party *p, struct uni_msg *api, u_int32_t cookie) +punx_drop_party_request(struct party *p, struct uni_msg *api, uint32_t cookie) { struct uniapi_drop_party_request *req = uni_msg_rptr(api, struct uniapi_drop_party_request *); @@ -784,7 +784,7 @@ punx_drop_party_request(struct party *p, struct uni_msg *api, u_int32_t cookie) * Q.2971:Party-Control-N 9 */ static void -pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, u_int32_t cookie) +pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, uint32_t cookie) { struct uniapi_drop_party_ack_request *req = uni_msg_rptr(api, struct uniapi_drop_party_ack_request *); @@ -814,7 +814,7 @@ pun6_drop_party_ack_request(struct party *p, struct uni_msg *api, u_int32_t cook * Q.2971:Party-Control-N 12 */ static void -punx_status_enquiry_request(struct party *p, u_int32_t cookie) +punx_status_enquiry_request(struct party *p, uint32_t cookie) { struct uni_all *enq; @@ -911,7 +911,7 @@ pun5_status(struct party *p, struct uni_msg *m, struct uni_all *u) /************************************************************/ void -uni_sig_party(struct party *p, enum party_sig sig, u_int32_t cookie, +uni_sig_party(struct party *p, enum party_sig sig, uint32_t cookie, struct uni_msg *msg, struct uni_all *u) { if (sig >= SIGP_END) { diff --git a/sys/contrib/ngatm/netnatm/sig/sig_print.c b/sys/contrib/ngatm/netnatm/sig/sig_print.c index 56bb9cec2e95..252ba07d96eb 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_print.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_print.c @@ -27,7 +27,7 @@ * Author: Hartmut Brandt * Kendy Kutzner * - * $Begemot: libunimsg/atm/sig/sig_print.c,v 1.4 2003/09/19 12:03:34 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_print.c,v 1.5 2004/07/08 08:22:22 brandt Exp $ */ #include diff --git a/sys/contrib/ngatm/netnatm/sig/sig_reset.c b/sys/contrib/ngatm/netnatm/sig/sig_reset.c index b5b4a5e38fcf..d57d9214d183 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_reset.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_reset.c @@ -3,6 +3,8 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * + * Author: Hartmut Brandt + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,9 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Author: Hartmut Brandt - * - * $Begemot: libunimsg/atm/sig/sig_reset.c,v 1.5 2003/09/24 10:27:50 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_reset.c,v 1.10 2004/07/08 08:22:22 brandt Exp $ * * Reset-start and reset-respond */ @@ -45,10 +45,13 @@ static void response_status(struct uni *, struct uni_msg *, struct uni_all *); static void response_t317(struct uni *); -static void response_error(struct uni *, struct uniapi_reset_error_response *, u_int32_t cookie); -static void response_response(struct uni *, struct uniapi_reset_response *, u_int32_t); +static void response_error(struct uni *, struct uniapi_reset_error_response *, + uint32_t cookie); +static void response_response(struct uni *, struct uniapi_reset_response *, + uint32_t); -static void start_request(struct uni *, struct uniapi_reset_request *, u_int32_t); +static void start_request(struct uni *, struct uniapi_reset_request *, + uint32_t); static void start_t316(struct uni *); @@ -76,7 +79,7 @@ TIMER_FUNC_UNI(t316, t316_func) * Reset-Start process. */ void -uni_sig_start(struct uni *uni, u_int sig, u_int32_t cookie, +uni_sig_start(struct uni *uni, u_int sig, uint32_t cookie, struct uni_msg *m, struct uni_all *u) { if (sig >= SIGS_END) { @@ -137,7 +140,7 @@ uni_sig_start(struct uni *uni, u_int sig, u_int32_t cookie, * Q.2931:Reset-Start 1/2 */ static void -start_request(struct uni *uni, struct uniapi_reset_request *req, u_int32_t cookie) +start_request(struct uni *uni, struct uniapi_reset_request *req, uint32_t cookie) { struct uni_all *resp; int err; @@ -432,7 +435,7 @@ start_status(struct uni *uni, struct uni_msg *m, struct uni_all *u) * Reset-Respond process. */ void -uni_sig_respond(struct uni *uni, u_int sig, u_int32_t cookie, +uni_sig_respond(struct uni *uni, u_int sig, uint32_t cookie, struct uni_msg *m, struct uni_all *u) { if (sig >= SIGR_END) { @@ -639,7 +642,7 @@ response_t317(struct uni *uni) */ static void response_error(struct uni *uni, struct uniapi_reset_error_response *c, - u_int32_t cookie) + uint32_t cookie) { struct uni_all *resp; @@ -681,7 +684,7 @@ response_error(struct uni *uni, struct uniapi_reset_error_response *c, */ static void response_response(struct uni *uni, struct uniapi_reset_response *arg, - u_int32_t cookie) + uint32_t cookie) { struct uni_all *resp; diff --git a/sys/contrib/ngatm/netnatm/sig/sig_uni.c b/sys/contrib/ngatm/netnatm/sig/sig_uni.c index 3755881a62e0..78db20ef08fe 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_uni.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_uni.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/sig_uni.c,v 1.4 2003/09/24 10:27:50 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_uni.c,v 1.10 2004/07/08 08:22:23 brandt Exp $ * * Instance handling */ @@ -363,7 +363,7 @@ static struct { }; void -uni_uni_input(struct uni *uni, enum uni_sig sig, u_int32_t cookie, +uni_uni_input(struct uni *uni, enum uni_sig sig, uint32_t cookie, struct uni_msg *m) { u_int i; @@ -462,7 +462,7 @@ uni_work(struct uni *uni) */ void uni_enq_sig(struct uni *uni, u_int type, struct call *call, - struct party *party, u_int32_t sig, u_int32_t cookie, + struct party *party, uint32_t sig, uint32_t cookie, struct uni_msg *msg, struct uni_all *u) { struct sig *s; @@ -484,7 +484,7 @@ uni_enq_sig(struct uni *uni, u_int type, struct call *call, */ void uni_delenq_sig(struct uni *uni, u_int type, struct call *call, - struct party *party, u_int32_t sig, u_int32_t cookie, + struct party *party, uint32_t sig, uint32_t cookie, struct uni_msg *msg, struct uni_all *u) { struct sig *s; @@ -504,8 +504,8 @@ uni_delenq_sig(struct uni *uni, u_int type, struct call *call, /**************************************************************/ void -uniapi_uni_error(struct uni *uni, u_int32_t reason, u_int32_t cookie, - u_int32_t state) +uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie, + uint32_t state) { struct uni_msg *resp; struct uniapi_error *err; @@ -524,12 +524,12 @@ uniapi_uni_error(struct uni *uni, u_int32_t reason, u_int32_t cookie, } void -uniapi_call_error(struct call *c, u_int32_t reason, u_int32_t cookie) +uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie) { uniapi_uni_error(c->uni, reason, cookie, callstates[c->cstate].ext); } void -uniapi_party_error(struct party *p, u_int32_t reason, u_int32_t cookie) +uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie) { uniapi_uni_error(p->call->uni, reason, cookie, callstates[p->call->cstate].ext); @@ -657,7 +657,7 @@ uni_get_config(const struct uni *uni, struct uni_config *config) void uni_set_config(struct uni *uni, const struct uni_config *config, - u_int32_t *mask, u_int32_t *popt_mask, u_int32_t *opt_mask) + uint32_t *mask, uint32_t *popt_mask, uint32_t *opt_mask) { int idle; diff --git a/sys/contrib/ngatm/netnatm/sig/sig_verify.c b/sys/contrib/ngatm/netnatm/sig/sig_verify.c index fe9561b8a545..ae78ed8eb50f 100644 --- a/sys/contrib/ngatm/netnatm/sig/sig_verify.c +++ b/sys/contrib/ngatm/netnatm/sig/sig_verify.c @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/sig_verify.c,v 1.16 2003/10/10 14:37:28 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/sig_verify.c,v 1.19 2004/07/08 08:22:23 brandt Exp $ * * Message verification with explicit action indicators. */ diff --git a/sys/contrib/ngatm/netnatm/sig/uni.h b/sys/contrib/ngatm/netnatm/sig/uni.h index 9fa194333c65..5af6c445d187 100644 --- a/sys/contrib/ngatm/netnatm/sig/uni.h +++ b/sys/contrib/ngatm/netnatm/sig/uni.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/uni.h,v 1.3 2003/09/19 12:03:34 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/uni.h,v 1.5 2004/07/08 08:22:24 brandt Exp $ * * Public UNI interface */ @@ -41,7 +41,7 @@ struct uni; struct uni_funcs { /* output to the upper layer */ void (*uni_output)(struct uni *, void *, enum uni_sig, - u_int32_t, struct uni_msg *); + uint32_t, struct uni_msg *); /* output to the SAAL */ void (*saal_output)(struct uni *, void *, enum saal_sig, @@ -79,13 +79,13 @@ void uni_get_config(const struct uni *, struct uni_config *); /* set new instance configuration */ void uni_set_config(struct uni *, const struct uni_config *, - u_int32_t *, u_int32_t *, u_int32_t *); + uint32_t *, uint32_t *, uint32_t *); /* input from the SAAL to the instance */ void uni_saal_input(struct uni *, enum saal_sig, struct uni_msg *); /* input from the upper layer to the instance */ -void uni_uni_input(struct uni *, enum uni_sig, u_int32_t, struct uni_msg *); +void uni_uni_input(struct uni *, enum uni_sig, uint32_t, struct uni_msg *); /* do work on pending signals */ void uni_work(struct uni *); diff --git a/sys/contrib/ngatm/netnatm/sig/unidef.h b/sys/contrib/ngatm/netnatm/sig/unidef.h index a92bd18d69c3..7278db8b91cb 100644 --- a/sys/contrib/ngatm/netnatm/sig/unidef.h +++ b/sys/contrib/ngatm/netnatm/sig/unidef.h @@ -26,13 +26,19 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/unidef.h,v 1.6 2003/09/19 12:03:34 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/unidef.h,v 1.9 2004/07/08 08:22:24 brandt Exp $ * * UNI public definitions. */ #ifndef _ATM_SIG_UNIDEF_H_ #define _ATM_SIG_UNIDEF_H_ +#ifdef _KERNEL +#include +#else +#include +#endif + /* * Debug facilities */ @@ -109,25 +115,25 @@ enum uni_option { * UNI configuration */ struct uni_config { - u_int32_t proto; /* which protocol */ - u_int32_t popt; /* protocol option */ - u_int32_t option; /* other options */ - u_int32_t timer301; /* T301 */ - u_int32_t timer303; /* T303 */ - u_int32_t init303; /* T303 retransmission count */ - u_int32_t timer308; /* T308 */ - u_int32_t init308; /* T308 retransmission count */ - u_int32_t timer309; /* T309 */ - u_int32_t timer310; /* T310 */ - u_int32_t timer313; /* T313 */ - u_int32_t timer316; /* T316 */ - u_int32_t init316; /* T316 retransmission count */ - u_int32_t timer317; /* T317 */ - u_int32_t timer322; /* T322 */ - u_int32_t init322; /* T322 retransmission count */ - u_int32_t timer397; /* T397 */ - u_int32_t timer398; /* T398 */ - u_int32_t timer399; /* T399 */ + uint32_t proto; /* which protocol */ + uint32_t popt; /* protocol option */ + uint32_t option; /* other options */ + uint32_t timer301; /* T301 */ + uint32_t timer303; /* T303 */ + uint32_t init303; /* T303 retransmission count */ + uint32_t timer308; /* T308 */ + uint32_t init308; /* T308 retransmission count */ + uint32_t timer309; /* T309 */ + uint32_t timer310; /* T310 */ + uint32_t timer313; /* T313 */ + uint32_t timer316; /* T316 */ + uint32_t init316; /* T316 retransmission count */ + uint32_t timer317; /* T317 */ + uint32_t timer322; /* T322 */ + uint32_t init322; /* T322 retransmission count */ + uint32_t timer397; /* T397 */ + uint32_t timer398; /* T398 */ + uint32_t timer399; /* T399 */ }; enum uni_config_mask { UNICFG_PROTO = 0x00000001, @@ -213,8 +219,8 @@ enum uni_sig { }; struct uniapi_error { - u_int32_t reason; - u_int32_t state; + uint32_t reason; + uint32_t state; }; /* keep this in sync with atmapi.h:enum atmerr */ @@ -275,8 +281,8 @@ struct uniapi_reset_indication { }; struct uniapi_reset_error_indication { - u_int32_t source; /* 0 - start, 1 - response */ - u_int32_t reason; + uint32_t source; /* 0 - start, 1 - response */ + uint32_t reason; }; #define UNIAPI_DEF_RESET_ERRORS(MACRO) \ diff --git a/sys/contrib/ngatm/netnatm/sig/unimkmsg.h b/sys/contrib/ngatm/netnatm/sig/unimkmsg.h index 852382512107..80264e143b1c 100644 --- a/sys/contrib/ngatm/netnatm/sig/unimkmsg.h +++ b/sys/contrib/ngatm/netnatm/sig/unimkmsg.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/unimkmsg.h,v 1.4 2003/09/19 12:03:34 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/unimkmsg.h,v 1.4 2003/09/19 12:03:34 hbb Exp $ * * Macros to make messages. */ diff --git a/sys/contrib/ngatm/netnatm/sig/unipriv.h b/sys/contrib/ngatm/netnatm/sig/unipriv.h index 7b4a0d77eab2..35dc408b9fde 100644 --- a/sys/contrib/ngatm/netnatm/sig/unipriv.h +++ b/sys/contrib/ngatm/netnatm/sig/unipriv.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/unipriv.h,v 1.5 2003/09/24 10:27:50 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/unipriv.h,v 1.17 2004/07/08 08:22:25 brandt Exp $ * * Private UNI stuff. */ @@ -229,8 +229,8 @@ struct sig { u_int type; /* one of the above */ struct call *call; /* call to send to */ struct party *party; /* party to send to */ - u_int32_t sig; /* the signal */ - u_int32_t cookie; /* user cookie */ + uint32_t sig; /* the signal */ + uint32_t cookie; /* user cookie */ struct uni_msg *msg; /* attached message */ struct uni_all *u; /* dito */ }; @@ -248,15 +248,15 @@ TAILQ_HEAD(sigqueue, sig); } \ } while(0) -void uni_sig_party(struct party *, enum party_sig, u_int32_t cookie, +void uni_sig_party(struct party *, enum party_sig, uint32_t cookie, struct uni_msg *, struct uni_all *); -void uni_sig_call(struct call *, enum call_sig, u_int32_t cookie, +void uni_sig_call(struct call *, enum call_sig, uint32_t cookie, struct uni_msg *, struct uni_all *); -void uni_sig_coord(struct uni *, enum coord_sig, u_int32_t cookie, +void uni_sig_coord(struct uni *, enum coord_sig, uint32_t cookie, struct uni_msg *); -void uni_sig_start(struct uni *, enum start_sig, u_int32_t cookie, +void uni_sig_start(struct uni *, enum start_sig, uint32_t cookie, struct uni_msg *, struct uni_all *); -void uni_sig_respond(struct uni *, enum respond_sig, u_int32_t cookie, +void uni_sig_respond(struct uni *, enum respond_sig, uint32_t cookie, struct uni_msg *, struct uni_all *); /************************************************************* @@ -283,7 +283,8 @@ void uni_destroy_party(struct party *, int); struct party *uni_find_party(struct call *, struct uni_ie_epref *); struct party *uni_find_partyx(struct call *, u_int epref, u_int mine); struct party *uni_create_party(struct call *, struct uni_ie_epref *); -struct party *uni_create_partyx(struct call *, u_int epref, u_int mine, u_int32_t cookie); +struct party *uni_create_partyx(struct call *, u_int epref, u_int mine, + uint32_t cookie); u_int uni_party_act_count(struct call *, int); enum call_type { @@ -336,8 +337,8 @@ TAILQ_HEAD(callqueue, call); struct call *uni_find_call(struct uni *, struct uni_cref *); struct call *uni_find_callx(struct uni *, u_int cref, u_int mine); struct call *uni_create_call(struct uni *, u_int cref, u_int mine, - u_int32_t cookie); -struct call *uni_create_new_call(struct uni *, u_int32_t cookie); + uint32_t cookie); +struct call *uni_create_new_call(struct uni *, uint32_t cookie); void uni_destroy_call(struct call *, int); void uni_bad_message(struct call *, struct uni_all *, u_int, @@ -364,7 +365,7 @@ struct uni { struct sigqueue delq; /* delayed signal queue */ int working; - u_int32_t cref_alloc; + uint32_t cref_alloc; enum cu_stat custat; /* coordinator state */ struct uni_timer t309; @@ -403,10 +404,10 @@ struct uni { u_int debug[UNI_MAXFACILITY]; }; -void uniapi_uni_error(struct uni *uni, u_int32_t reason, u_int32_t cookie, - u_int32_t state); -void uniapi_call_error(struct call *c, u_int32_t reason, u_int32_t cookie); -void uniapi_party_error(struct party *p, u_int32_t reason, u_int32_t cookie); +void uniapi_uni_error(struct uni *uni, uint32_t reason, uint32_t cookie, + uint32_t state); +void uniapi_call_error(struct call *c, uint32_t reason, uint32_t cookie); +void uniapi_party_error(struct party *p, uint32_t reason, uint32_t cookie); /************************************************************* * @@ -513,18 +514,36 @@ void uni_respond_status_mtype(struct uni *uni, struct uni_cref *cref, _tmp; \ }) -#define VERBOSE(UNI, FAC, LEVEL, FMT, ARGS...) do { \ +#if defined(__GNUC__) && __GNUC__ < 3 + +#define VERBOSE(UNI, FAC, LEVEL, ARGS...) do { \ if ((UNI)->debug[(FAC)] >= (LEVEL)) { \ - (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), \ - FMT , ## ARGS); \ + (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC) ,\ + ## ARGS); \ } \ } while(0) -#define VERBOSE0(UNI, FAC, FMT, ARGS...) do { \ - (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), FMT , \ +#define VERBOSE0(UNI, FAC, ARGS...) do { \ + (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC) , \ ## ARGS); \ } while(0) +#else + +#define VERBOSE(UNI, FAC, LEVEL, ...) do { \ + if ((UNI)->debug[(FAC)] >= (LEVEL)) { \ + (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), \ + __VA_ARGS__); \ + } \ + } while(0) + +#define VERBOSE0(UNI, FAC, ...) do { \ + (UNI)->funcs->verbose((UNI), (UNI)->arg, (FAC), \ + __VA_ARGS__); \ + } while(0) + +#endif + #define TIMER_INIT_UNI(U,T) _TIMER_INIT(U,T) #define TIMER_INIT_CALL(C,T) _TIMER_INIT(C,T) #define TIMER_INIT_PARTY(P,T) _TIMER_INIT(P,T) diff --git a/sys/contrib/ngatm/netnatm/sig/unisig.h b/sys/contrib/ngatm/netnatm/sig/unisig.h index 2f845f998a1d..22ff671d2922 100644 --- a/sys/contrib/ngatm/netnatm/sig/unisig.h +++ b/sys/contrib/ngatm/netnatm/sig/unisig.h @@ -26,7 +26,7 @@ * * Author: Hartmut Brandt * - * $Begemot: libunimsg/atm/sig/unisig.h,v 1.3 2003/09/19 12:03:34 hbb Exp $ + * $Begemot: libunimsg/netnatm/sig/unisig.h,v 1.4 2004/07/08 08:22:26 brandt Exp $ * * Utility functions for signalling stuff */ diff --git a/sys/contrib/ngatm/netnatm/unimsg.h b/sys/contrib/ngatm/netnatm/unimsg.h index d5b390c14679..efc91c57a81f 100644 --- a/sys/contrib/ngatm/netnatm/unimsg.h +++ b/sys/contrib/ngatm/netnatm/unimsg.h @@ -3,6 +3,8 @@ * Fraunhofer Institute for Open Communication Systems (FhG Fokus). * All rights reserved. * + * Author: Hartmut Brandt + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -24,9 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * Author: Hartmut Brandt - * - * $Begemot: libunimsg/atm/unimsg.h,v 1.3 2003/09/19 11:52:40 hbb Exp $ + * $Begemot: libunimsg/netnatm/unimsg.h,v 1.4 2004/07/08 08:21:46 brandt Exp $ * * This defines the structure of messages as handled by this library. */ @@ -38,8 +38,10 @@ #ifdef __FreeBSD__ #include #endif +#include #else #include +#include #endif struct uni_msg {