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